Jelle van der Waa bio photo

Jelle van der Waa

I'm a software developer at Kopano and an Arch Linux Developer...

Email Twitter Google+ LinkedIn Github Steam

This is a short tutorial on how to write a simple WebApp plugin, the plugin will add a widget to the WebApp’s mail settings tab. The widget will allow a user to remove email addresses and domains from the safesenders list in the users WebApp settings.

manifest.xml

We start of looking at the manifest.xml file, the file contains the following information for your plugin:

  • version
  • name
  • title
  • author
  • authorURL
  • description
<?xml version="1.0"?>
<!DOCTYPE plugin SYSTEM "manifest.dtd">
<plugin version="2">
	<info>
		<version>1.1</version>
		<name>myplugin</name>
		<title>My plugins title</title>
		<author>Jelle van der Waa</author>
		<authorURL>http://www.vdwaa.nl</authorURL>
		<description>What this plugin does!</description>
	</info>

Apart from this information it also tells the WebApp which JavaScript and CSS files it should load. We start looking at the defining which JavaScript files to load, the JavaScript files can be loaded in three different modes, source, debug, release. Source is used when you develop the plugin, release is the file which is loaded when you have issued an ant deploy and ant deploy-plugins. Usually these deploy commands are run when building an webapp package for your distro.

<components>
	<component>
		<files>
			<client>
				<clientfile load="release">js/safesenders.js</clientfile>
				<clientfile load="debug">js/safesenders-debug.js</clientfile>
				<clientfile load="source">js/SafeSenders.js</clientfile>
			</client>
		</files>
	</component>
</components>

CSS files are defined as following.

<components>
	<component>
		<files>
			<client>
			</client>
			<resources>
				<resourcefile load="release">resources/css/myplugin.css</resourcefile>
				<resourcefile load="source">resources/css/myplugin-styles.css</resourcefile>
			</resources>
		</files>
	</component>
</components>

We will not discuss loading PHP files, since this plugin only requires JavaScript functionality.

build.xml

The build.xml file should be copied from another plugin directory. This file is required by ant to build and deploy the plugin.

JavaScript files

Now that we discussed the manifest and build file we need to create a js directory and create the file js/SafeSenders.js, since the other files are generated by ant. In the js/SafeSenders.js file we will copy paste the following code.

Ext.namespace('Zarafa.plugins.safesenders');

/**
 * @class Zarafa.plugins.safesenders.SafeSenders
 * @extends Zarafa.core.Plugin
 *
 * Plugin makes it possible to remove recipients and domains from your safesender list
 */
Zarafa.plugins.safesenders.SafeSenders = Ext.extend(Zarafa.core.Plugin, {

	/**
	 * @protected
	 */
	initPlugin : function()
	{
		Zarafa.plugins.safesenders.SafeSenders.superclass.initPlugin.apply(this, arguments);
	}
});

Zarafa.onReady(function() {
	container.registerPlugin(new Zarafa.core.PluginMetaData({
		name : 'safesenders',
		displayName : _('Safesender settingswidget Plugin'),
		pluginConstructor : Zarafa.plugins.safesenders.SafeSenders
	}));
});

The code above, does the following things. It declares a namespace for the plugin, creates the plugin class (SafeSenders) and when the WebApp “is ready” it registers the plugin so that it appears in Settings -> Plugins. According to the documentation Zarafa.onReady() is described as: Adds a listener to be notified when Zarafa is ready. This will be somewhere during Ext.onReady, when Zarafa has initialized the bare essentials. When the event is fired, the Zarafa.core.Container will be available, and plugins are allowed to register.

Now that the plugin is registered, we can make use of insertion points in the WebApp to extend the WebApp’s functionality. Insertion points are described in the WebApp Developers Manual, basically you can insert your own functionalitiy, buttons, widgets in the WebApp. Note that you can enable the ‘developer plugin’ to view all the insertion points in the WebApp.

For this plugin we want to add a widget to the mail settings tab. There is an insertion point called ‘context.settings.category.mail’ which allows us to add a widget. If we take a look at the class Zarafa.mail.settings.SettingsMailCategory, it allows us to add a new widget. The widget should extend the same class as for example Zarafa.mail.settings.SettingsComposeWidget.

		Ext.applyIf(config, {
			title : _('Mail'),
			categoryIndex : 1,
			iconCls : 'zarafa-settings-category-mail',
			items : [{
				xtype : 'zarafa.settingsmailwidget'
			},{
				xtype : 'zarafa.settingscomposewidget'
			},{
				xtype : 'zarafa.settingsincomingmailwidget'
			},{
				xtype : 'zarafa.settingssignatureswidget'
			},
			container.populateInsertionPoint('context.settings.category.mail', this)
			]
		});

We now create the directory js/settings and create the file js/settings/SettingsSafeSendersWidget.js.

Ext.namespace('Zarafa.plugins.safesenders');
/**
 * @class Zarafa.plugins.safesenders.SettingsSafeSendersWidget
 * @extends Zarafa.settings.ui.SettingsWidget
 * @xtype safesenders.settingssafesenderswidget
 *
 * The {@link Zarafa.settings.ui.SettingsWidget widget} for configuring
 * safesenders in the {@link Zarafa.mail.settings.SettingsMailCategory mail category}
 */
Zarafa.plugins.safesenders.SettingsSafesendersWidget = Ext.extend(Zarafa.settings.ui.SettingsWidget, {

	/**
	 * @constructor
	 * @param {Object} config Configuration object
	 */
	constructor : function(config)
	{
		config = config || {};

		Ext.applyIf(config, {
			height : 400,
			title : _('Safe senders'),
			xtype : 'safesenders.settingssafesenderswidget',
			layout : 'column',
			items : []
		});

		Zarafa.plugins.safesenders.SettingsSafesendersWidget.superclass.constructor.call(this, config);
	},

	/**
	 * Called by the {@link Zarafa.settings.ui.SettingsCategory Category} when
	 * it has been called with {@link zarafa.settings.ui.SettingsCategory#update}.
	 * This is used to load the latest version of the settings from the
	 * {@link Zarafa.settings.SettingsModel} into the UI of this category.
	 * @param {Zarafa.settings.SettingsModel} settingsModel The settings to load
	 */
	update : function(settingsModel)
	{
		this.model = settingsModel;
	},

	/**
	 * Called by the {@link Zarafa.settings.ui.SettingsCategory Category} when
	 * it has been called with {@link zarafa.settings.ui.SettingsCategory#updateSettings}.
	 * This is used to update the settings from the UI into the {@link Zarafa.settings.SettingsModel settings model}.
	 * @param {Zarafa.settings.SettingsModel} settingsModel The settings to update
	 */
	updateSettings : function(settingsModel)
	{
		settingsModel.beginEdit();
		settingsModel.endEdit();
	}
});
Ext.reg('safesenders.settingssafesenderswidget', Zarafa.plugins.safesenders.SettingsSafesendersWidget);

This file will implement the widget which will remove an “email address or domain” from the safe senders list, which we will not handle in this post. The last thing we will add is registering the SettingsSafesendersWidget in the insertion point in js/SafeSenders.js by adding the following code in initPlugin after the Zarafa.plugins.safesenders.SafeSenders.superclass.initPlugin.apply.

this.registerInsertionPoint('context.settings.category.mail', this.safeSendersWidget, this);

And adding the function safeSendersWidget in js/SafeSenders.js:

/**
 * Insert safesenders widget into the mail category
 * @return {settingssafesenderswidget} 
 */
safeSendersWidget: function() 
{
	return [{
		xtype : 'safesenders.settingssafesenderswidget'
	}];
}

We have now implemented a bare widget in the WebApp’s mail settings, which doesn’t do anything yet. I won’t discuss the rest of the implementation, but you can find the full source here.

More advanced information can be found in the Webapp Developer manual and WebApp API Overview.