# PBX Manager Plugin

The PBX Manager is a PBX App, which is used for configuration tasks. An App Service can provide a plugin, which shows up in the PBX Manager and can configuration tasks for the App Service. Typical task would be creating PBX objects, configuring the App Instance, establish connections to other App Instances.

This documentation describes the following procedures used for these Plugings

Publish A PBX Manager plugin
  An App Service may publish a PBX Manager Plugin, so that it shows up in the PBX Manager App.
Plugin Javascript
  The PBX Manager loads a Javascript Object which has to conform to some definitions
Plugin Context
  When the plugin is loaded, some other Javascript libraries are already loaded and some API functions are available from the PBX Manager
Plugin Templates
  Some template files, which can be used to start a new plugin

## Publish a PBX Manager plugin

To publish a PBX Manager Plugin the App Service adds a class AppInstancePlugin to the AppService pluginList by overwriting the virtual function AppInstancePlugins:

    void <your AppService Class>::AppInstancePlugins(istd::list<AppInstancePlugin> * pluginList)
    {
        pluginList->push_back(new AppInstancePlugin(<Javascript filename>, <Icon file>, <Language file>, <multiple domains>));
    }

Javascript filename
  The file name of the Javascript file, which shall be loaded as plugin without the .js extension.
Icon file
  File for the Icon to be displayed in the PBX Manager App. Typically a 50x50px .png file is used
Language file
  This is a file containing localized texts so that the title of the plugin can be displayed in the language of the user. It should contain a Javascript object with the same name as the filename, with properties for each supported language, which should contain the property "pluginTitle" as title
multiple Domain
  If argument is true, the plugin is announced to all PBX Managers, regardless of the domain. If false the Plugin is only announced if the domain of the instance matches the domain of the PBX Manager.

A plugin typically consists of three files: The Javascript code of the plugin, the texts file for the localized texts and a css. It is recommended to use the following naming conventions for these files:

Javascript code
  <company id>.<App name>Manager.js
Texsts file
  <company id>.<App name>ManagerTexts.js
CSS file
  <company id>.<App name>Manager.css

## Plugin Javascript

The PBX Manager loads the Javascript file and expects a constructor function

    plugin.<filename>

to exist, which is the called to allocate a Plugin object.

"plugin" is used as a namespace to avoid a conflict with other Javascritpt objects.

It is recommended to use the company id as object name inside plugin to avoid conflicts with any other plugin from other vendors.

The PBX Manager expects that a object which uses the innovaphone.ui1.nodePrototype as prototype to be created by this constructor function. A Node "div" with a class "item-node" should be created.

The constructor function has the following arguments

start
  The innovaphone.lib1 start object, which can be used to access other myApps APIs
item
  An object with informatio about the plugin

      {
          ap: string,
          apDn: string,
          uri: string,
          png: string
      }

  ap
    sip name of the AP object of the AP of this instance
  apDn
    Display name of the AP Object of the AP
  uri
    URI of the instance relative to the AP
  png
    The icon file
app
  This is the innovaphone.appwebsocket.Connection object which is connected to the PBX so it can be used to access PBX APIs like "PbxAdminApi". In addition to the standard AppWebsocket connection object, it has a property "domain" which is set to the PBX domain.

### Connect to the App instance

The plugin can establish a AppWebsocket connection to the App instance. For authentication the GetInstanceLogin message from the com.innovaphone.manager API can be used.

        var managerApi = start.consumeApi("com.innovaphone.manager");
        instance = new innovaphone.appwebsocket.Connection("ws" + item.uri.slice(4), "-", null, app.domain, instanceConnected, instanceMessage, null, null, instanceLogin);

        function instanceLogin(app, challenge) {
            managerApi.sendSrc({ mt: "GetInstanceLogin", path: item.uri.slice(item.uri.indexOf("/", 8) + 1, item.uri.lastIndexOf("/")), app: app, challenge: challenge }, item.ap, function (obj) {
                instance.login(obj.msg);
            });
        }

### Set the instance password

When the Manager plugin configures the first App object for an instance, it should reset the instance password with a new randowm password. Use the function innovaphone.Manager.randomPwd(16) to generate such a random password. The com.innovaphone.manager SetInstancePassword can be used for this purpose

        var pwd = innovaphone.Manager.randomPwd(16);
        managerApi.sendSrc({ mt: "SetInstancePassword", path: item.uri.slice(item.uri.indexOf("/", 8) + 1, item.uri.lastIndexOf("/")), pwd: pwd }, item.ap, function (obj) {
            ...
        });

If an additional App object shall be configured, the password stored in this App object can be copied from an existing App object, which can be referenced with copyPwd in the UpdateObject message.

    src.send({ mt: "UpdateObject", api: "PbxAdminApi", copyPwd: copyPwd, cn: obj.title, guid: obj.guid, h323: obj.sip, pseudo: { type: "app", ... }, ... });

## Plugin Context

The following Javascript libries are loaded when the plugin is loaded:

- innovaphone.lib1.js
- innovaphone.ui1.lib.js
- innovaphone.ui1.svg.js
- innovaphone.ui1.scrolling.js
- innovaphone.appwebsocket.Connection.js

## Plugin Templates

In the template files replace <company id> by your company in all lower case, <app name> by your App name, starting with a capital letter and <app id> with your App name with all lower case.

<company id>.Manager<app name>.js

The main plugin javascript

    /// <reference path="~/web1/lib1/innovaphone.lib1.js" />
    /// <reference path="~/web1/ui1.lib/innovaphone.ui1.lib.js" />

    var plugin = plugin || {};
    plugin.innovaphone = plugin.innovaphone || {};
    plugin.<company id>.Manager<app name> = <company id>.Manager<app name> || function (start, item, app) {
        this.createNode("div", null, null, "item-node");
        innovaphone.lib1.loadCss(item.uri + ".css");

        var colorSchemes = {
            dark: {
                "--<company id>-<app id>-c1": "#efefef",
            },
            light: {
                "--<company id>-<app id>-c1": "#444444",
            }
        };

        var schemes = new innovaphone.ui1.CssVariables(colorSchemes, start.scheme);
        start.onschemechanged.attach(function () { schemes.activate(start.scheme) });

        var texts;
        var panel = this.add(new innovaphone.ui1.Div(null, "== plugin ==", "<company id>-<app id>-panel"));

        innovaphone.lib1.loadObjectScript(item.uri + "Texts", function () {
            texts = new innovaphone.lib1.Languages(<company id>.Manager<app name>Texts, start.lang);
            init();
        });

        function init() {

        }
    }
    plugin.innovaphone.Manager<app name>.prototype = innovaphone.ui1.nodePrototype;

<company id>.Manager<app name>Texts.js

The texts file

    innovaphone.Manager<app name>Texts = {
        en: {
            pluginTitle: "<app name>",
        },
        de: {
            pluginTitle: "<app name>",
        }
    }

<company id>.Manager<app name>.css

The CSS

    div.<company id>-<app id>-panel {
        position:absolute;
        left:0px;
        right:0px;
        top:0px;
        bottom:0px;
        color:var(--<company id>-<app id>-c1);
        font-size:14px;
    }