Difference between revisions of "Extending Admin UI"

Line 74: Line 74:
  
 
----
 
----
 
+
  /** you can take a look at files ZaDomainXFormView.js, ZaAccountXFormView.js, GlobalConfigXFormView.js etc, to see how each  
  { /* you can take a look at files ZaDomainXFormView.js, ZaAccountXFormView.js, GlobalConfigXFormView.js etc, to see how each xFormObject looks for each view. You will want to look at myXFormModifier methods in each of these classes */
+
* xFormObject looks for each view. You will want to look at myXFormModifier methods in each of these classes  
 +
**/
 +
{
 
   tableCssStyle:"width:100%;overflow:auto",
 
   tableCssStyle:"width:100%;overflow:auto",
 
   items:[
 
   items:[

Revision as of 02:55, 25 February 2006

The API for extending Admin UI is similar to Zimlets. Unlike Zimlets, this API was not originally meant to be published. However people have asked about it, so I decided to document it. The intended audience is developers, who want to add custom modules to Zimra Admin UI, for example, people have asked about integrating Zimbra with samba. If you want to use this API, you need to have at least basic programming skills and be familiar with JavaScript. The easiest way to understand how to create extensions for Admin UI is by example. So, lets create a sample "Hello World" extension. The example will one tab to the Accounts view. The tab will be called "Hello World" and it will have some text.

The extension will consist of two files: helloworld.xml - XML definition of the extention helloworld.js - JavaScript code of the extension helloworld.xml:


   <zimlet name="helloworld" version="1.0" description="Sample Extension for Admin UI" extension="true">
   <include>helloworld.js</include>
   </zimlet>

That's it. It is that short. It defines the name of the extension, description and included JS files. Note, that unlike Zimlet definition files it has a parameter extension="true". This is what tells zimlet utility that this is not a regular Zimlet, but an extension for Admin UI. So, moving forward. helloworld.js


 function HelloWorldExtension() {}
HelloWorldExtension.AccountXFormModifier = function (xFormObject) {
   //find _TAB_BAR_ element
   var cnt = xFormObject.items.length;
   for(i = 0; i <cnt; i++) {
      if(xFormObject.items[i].type=="tab_bar") 
        break;
   }
   //get a tab index
   var myTabIndex = ++ZaAccountXFormView.TAB_INDEX;
   //add a tab
   xFormObject.items[i].choices.push({value:myTabIndex, label:"Hello World"});
   //define a form for my new tab. This ahs to be a _CASE_ element
   
  var myTab = {type:_CASE_, relevant: ("instance[ZaModel.currentTab] == " + myTabIndex), items: [{type:_OUTPUT_, label:null, value:"Hello World!"}]};
 
   //find SWITCH element
   for(i = 0; i <cnt; i++) {
     if(xFormObject.items[i].type=="switch") 
       break;
   }
   //add my tab to the form
   xFormObject.items[i].items.push(myTab);
}
ZaTabView.XFormModifiers["ZaAccountXFormView"].push(HelloWorldExtension.AccountXFormModifier);

Now you zip helloworld.xml and helloworld.js into helloworld.zip file and run zmzimletctl deploy helloworld.zip Done!

Some more background: There are two types of views int Admin UI. List views and XForms views.

- List views are ones that show you lists of Zimbra objects. When you click on Accounts node in the navigation tree, you open Accounts List View, when you click on Servers, you open Servers List View, etc
- XForms views are views that show/edit/create a single Zimbra object. When you double click on an account in Accounts List view, you open an Account XForms view, when you click on Classes Of Service->default node, you open a COS XForms View.

Admin extensions allow you to modify anything on an XForms view, including toobar buttons. However, You cannot modify how the lists are shown in List views, in the List views you can only add new toolbar buttons and pop-up menues to List views. From the helloworld you can learn that in order to add anything to an XForms view you need to define your "modifier" method:

HelloWorldExtension.AccountXFormModifier

Then you need to add this method to the map (ZaTabView.XFormModifiers):

ZaTabView.XFormModifiers["ZaAccountXFormView"].push(HelloWorldExtension.AccountXFormModifier);

This statement adds your method to the list of methods that are called when "ZaAccountXFormView" is created. The map ZaTabView.XFormModifiers has the following arrays of methods:

ZaTabView.XFormModifiers["ZaAccountXFormView"] - modifiers for Account view
ZaTabView.XFormModifiers["ZaCosXFormView"] - modifiers for Class of Service view
ZaTabView.XFormModifiers["ZaDLXFormView"] - modifiers for Distribution List view (this is not a list view, its an XForms view for a distributino list)
ZaTabView.XFormModifiers["ZaDomainXFormView"] - modifiers for Domain view
ZaTabView.XFormModifiers["GlobalConfigXFormView"] - modifiers for Global Settings view
ZaTabView.XFormModifiers["ZaServerXFormView"] - modifiers for Server view

xFormObject argument which is passed to your modifier function (HelloWorldExtension.AccountXFormModifier in the example) will normally look like this:


/** you can take a look at files ZaDomainXFormView.js, ZaAccountXFormView.js, GlobalConfigXFormView.js etc, to see how each 
* xFormObject looks for each view. You will want to look at myXFormModifier methods in each of these classes 
**/
{
 tableCssStyle:"width:100%;overflow:auto",
 items:[
    {type:_GROUP_, cssClass:"ZmSelectedHeaderBg", colSpan:"*", /* this defines the top element of the form, a header */
        items: [
            {type:_GROUP_, numCols:4, colSizes:["32px","350px","100px","250px"],
                 items: [
                    {type:_AJX_IMAGE_, src:"Domain_32", label:null},
                    {type:_OUTPUT_, ref:ZaDomain.A_domainName, label:null,cssClass:"AdminTitle", rowSpan:2},			
                    {type:_OUTPUT_, ref:ZaItem.A_zimbraId, label:ZaMsg.NAD_ZimbraID}
                 ]
        ]
    },
    {type:_TAB_BAR_,  ref:ZaModel.currentTab, /* this defines the tab bar */
         choices:[ /* this array defines the buttons in the tab bar */
             {value:1, label:ZaMsg.Domain_Tab_General}, /* each button in the tab bar is defined as an object that has "value" and "label" */
             {value:2, label:ZaMsg.Domain_Tab_GAL},
             {value:3, label:ZaMsg.Domain_Tab_Authentication}
        ],cssClass:"ZaTabBar"
    },
    {type:_SWITCH_, /* this object contains all the "tabs" */
       items:[
          {type:_CASE_, relevant:"instance[ZaModel.currentTab] == 1", /* _CASE_ object defines a single tab */
              items:[ /* form elements for the first tab ar defined here */
          },
          {type:_CASE_, relevant:"instance[ZaModel.currentTab] == 2", 
              items:[ /* form elements for the second tab ar defined here */
          }
       ]
    }
 ]
}

"helloworld" was very simple, however totally disfunctional :) In real life you will probably want your extension to take some input from users, communicate to server and display meaningful data. So,

Jump to: navigation, search