Name

sn_outlook_addin.OfficeAddInManifestGenerator

Description

No description available

Script

var OfficeAddInManifestGenerator = Class.create();
OfficeAddInManifestGenerator.prototype = {
  initialize: function(manifestId) {
  	var defaultManifestId = gs.getProperty('sn_outlook_addin.defaultManifestId', 'f2d445ff5390330048e5ddeeff7b1273');
  	this.supportedLanguages=[];
  	//maps SNC language ID to Microsoft Outlook locale
  	this.languageMap = {
  		'pb':'pt-br',
  		'zh':'zh-cn',
  		'cs':'cs-cz',
  		'nl':'nl-nl',
  		'et':'et-ee',
  		'fi':'fi-fi',
  		'fr':'fr-fr',
  		'de':'de-de',
  		'he':'he-il',
  		'hu':'hu-hu',
  		'it':'it-it',
  		'ja':'ja-jp',
  		'ko':'ko-kr',
  		'pl':'pl-pl',
  		'pt':'pt-pt',
  		'ru':'ru-ru',
  		'es':'es-es',
  		'th':'th-th',
  		'zt':'zh-tw',
  		'tr':'tr-tr'
  	};
  	this.digest = new GlideDigest();
  	this.baseUrl = gs.getProperty('glide.servlet.uri');
  	this.manifestXml = new XMLDocument2();
  	this.providerName = 'ServiceNow';
  	this.defaultLocale = 'en-US';
  
  	this.grManifest = this._getmanifestRecord(manifestId || defaultManifestId);
  	var applicationMetaMap = {
  		outlook: {
  			host: 'Mailbox',
  			hostType: 'MailHost',
  			appType: 'MailApp'
  		},
  		word: {
  			host: 'Document',
  			hostType: 'Document',
  			appType: 'TaskPaneApp'
  		},
  		powerpoint: {
  			host: 'Presentation',
  			hostType: 'Presentation',
  			appType: 'TaskPaneApp'
  		}

  	};
  	this.app = applicationMetaMap[this.grManifest.office_host || 'outlook'];
  	this._populateSupportedLanguages();
  },		
  generate: function() {
  	if(!this.grManifest) {
  		throw "NOT_FOUND";
  	}
  	
      var appType = this.app.appType;
  	var root = this.manifestXml.createElement("OfficeApp");
  	root.setAttribute("xmlns", "http://schemas.microsoft.com/office/appforoffice/1.1");
  	root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
  	root.setAttribute("xmlns:bt", "http://schemas.microsoft.com/office/officeappbasictypes/1.0");

  	if(appType === 'MailApp')
  		root.setAttribute("xmlns:mailappor", "http://schemas.microsoft.com/office/mailappversionoverrides/1.0");
  	else if(appType === 'TaskPaneApp')
  		root.setAttribute("xmlns:ov",'http://schemas.microsoft.com/office/taskpaneappversionoverrides');
  	root.setAttribute("xsi:type", appType);

  	this._populateManifestRootElements();
  	this._populateAppDomains();
  	this._populateHosts();

  	if (appType === 'MailApp') {
  		this._populateRequirements();
  		this._populateFormSettings();
          this._populateRules();
      } else if(appType === 'TaskPaneApp') {
          this._populateDefaultSettings();
      }
      this._populateVersionOverrides();
  	return this.manifestXml.toString();
  },
  _getmanifestRecord: function(manifestId) {
  	var gr=new GlideRecord('sn_office_manifest');
  	gr.addActiveQuery();
  	gr.addQuery("sys_id", manifestId);
  	gr.query();
  	if(gr.next()) {
  		return gr;
  	}
  	
  	return null;
  },
  
  _getResourceId: function(sysId, attr) {
  	return this.digest.getMD5Hex(sysId+attr);
  },
  
  _populateManifestRootElements: function(){
  	var appType = this.app.appType;
  	var root, curNode, xmlDoc = this.manifestXml;
  	root = xmlDoc.getNode('/OfficeApp');
  	xmlDoc.setCurrentElement(root);
  	xmlDoc.createElementWithTextValue("Id",this.grManifest.plugin_id.toString());
  	xmlDoc.createElementWithTextValue("Version",this.grManifest.version.toString());
  	xmlDoc.createElementWithTextValue("ProviderName",this.providerName);
  	xmlDoc.createElementWithTextValue("DefaultLocale",this.defaultLocale);
  	xmlDoc.createElement("DisplayName").setAttribute("DefaultValue",this.grManifest.getValue("addin_name"));
  	this._addlocalizedElement(root, "Description", "Override", "", this.grManifest.getValue("description"));
  	xmlDoc.createElement("IconUrl").setAttribute("DefaultValue",this._getImageUrl(this.grManifest.getValue("icon")));
  	xmlDoc.createElement("HighResolutionIconUrl").setAttribute("DefaultValue",this._getImageUrl("/images/outlook-addin/now.png"));
  	xmlDoc.createElement("SupportUrl").setAttribute("DefaultValue","https://hi.service-now.com/hisp");
  	xmlDoc.createElement("AppDomains");
  	xmlDoc.createElement("Hosts");
  	
      var permission = this.grManifest.getValue("permission");
  	if(appType === 'MailApp'){
  		xmlDoc.createElement("Requirements");
  		xmlDoc.createElement("FormSettings");
  	} else if(appType === 'TaskPaneApp') {
  		xmlDoc.createElement("DefaultSettings");
  		permission = permission.replace('Item','Document');
  	}
  	xmlDoc.createElementWithTextValue("Permissions",  permission);
  	
  	if(appType === 'MailApp'){
  		curNode = xmlDoc.createElement("Rule");
  		curNode.setAttribute("xsi:type", "RuleCollection");
  		curNode.setAttribute("Mode", "Or");
  		xmlDoc.createElementWithTextValue("DisableEntityHighlighting", "false");
  	}
  	curNode = xmlDoc.createElement("VersionOverrides");
  	if(appType === 'MailApp'){
  		curNode.setAttribute("xmlns","http://schemas.microsoft.com/office/mailappversionoverrides");
  	} else if(appType === 'TaskPaneApp'){
  		curNode.setAttribute("xmlns","http://schemas.microsoft.com/office/taskpaneappversionoverrides");
  	}
  	curNode.setAttribute("xsi:type","VersionOverridesV1_0");
  },
  _populateAppDomains: function() {
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/AppDomains");
  	xmlDoc.setCurrentElement(node);
  	xmlDoc.createElementWithTextValue("AppDomain",this.baseUrl);
  },
  _populateHosts: function() {
      var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/Hosts");
  	xmlDoc.setCurrentElement(node);
  	xmlDoc.createElement("Host").setAttribute("Name",this.app.host);
  },

  _populateRequirements: function() {
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/Requirements");
  	xmlDoc.setCurrentElement(node);
  	var sets = xmlDoc.createElement("Sets");
  	xmlDoc.setCurrentElement(sets);
  	var set = xmlDoc.createElement("Set");
  	set.setAttribute("Name",this.app.host);
  	set.setAttribute("MinVersion", this.grManifest.getValue("min_version"));
  },
  
  _populateDefaultSettings: function(){
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/DefaultSettings");
  	xmlDoc.setCurrentElement(node);
  	xmlDoc.createElement("SourceLocation").setAttribute("DefaultValue", this.baseUrl);
  },

  _populateFormSettings: function () {
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/FormSettings");
  	xmlDoc.setCurrentElement(node);
  	var form = xmlDoc.createElement("Form");
  	form.setAttribute("xsi:type","ItemRead");
  	xmlDoc.setCurrentElement(form);
  	var desktopSettings = xmlDoc.createElement("DesktopSettings");
  	xmlDoc.setCurrentElement(desktopSettings);
  	xmlDoc.createElement("SourceLocation").setAttribute("DefaultValue", this.baseUrl);
  	xmlDoc.createElementWithTextValue("RequestedHeight","250");
  },

  _populateRules: function() {
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/Rule");
  	xmlDoc.setCurrentElement(node);
  	var childRuleNode = xmlDoc.createElement("Rule");
  	childRuleNode.setAttribute("xsi:type", "ItemIs");
  	childRuleNode.setAttribute("ItemType", "Message");
  	childRuleNode.setAttribute("FormType", "Read");
  },

  _populateVersionOverrides: function() {
  	var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/VersionOverrides");
  	xmlDoc.setCurrentElement(node);
  	//add hosts node and default mailhost
  	var hostsNode = xmlDoc.createElement("Hosts");
  	xmlDoc.setCurrentElement(hostsNode);
  	var mailHostNode = xmlDoc.createElement("Host");
  	mailHostNode.setAttribute("xsi:type", this.app.hostType);
  	//add resources hierarchy
  	xmlDoc.setCurrentElement(node);
  	xmlDoc.setCurrentElement(xmlDoc.createElement("Resources"));
  	var imagesNode = xmlDoc.createElement("bt:Images");
  	var urlsNode = xmlDoc.createElement("bt:Urls");
  	var shortStringsNode = xmlDoc.createElement("bt:ShortStrings");
  	var longStringsNode = xmlDoc.createElement("bt:LongStrings");
  	this._populateDesktopFormFactor();
  },

  _populateDesktopFormFactor: function() {
      var appType = this.app.appType;
      var xmlDoc = this.manifestXml, node = xmlDoc.getNode("/OfficeApp/VersionOverrides/Hosts/Host");
  	var extPtType = 'MessageReadCommandSurface';
  	var grpId = 'msgReadGroup';
  	var tab = 'TabDefault';
  	
      if(appType === 'TaskPaneApp') {
          extPtType = 'PrimaryCommandSurface';
          grpId = 'CommandsGroup';
  		tab = "TabHome";
      }
  	xmlDoc.setCurrentElement(node);
  	var desktopFormFactorNode = xmlDoc.createElement("DesktopFormFactor");
  	xmlDoc.setCurrentElement(desktopFormFactorNode);
  	var extensionPointNode = xmlDoc.createElement("ExtensionPoint");
  	extensionPointNode.setAttribute("xsi:type", extPtType);
  	xmlDoc.setCurrentElement(extensionPointNode);
  	var officeTabNode = xmlDoc.createElement("OfficeTab");
  	officeTabNode.setAttribute("id", tab);
  	xmlDoc.setCurrentElement(officeTabNode);
  	var groupNode = xmlDoc.createElement("Group");
  	groupNode.setAttribute("id", grpId);
  	xmlDoc.setCurrentElement(groupNode);
  	xmlDoc.createElement("Label").setAttribute("resid", this._getResourceId(this.grManifest.sys_id.toString(), "label"));
  	
  	if(appType === 'MailApp') {
  		xmlDoc.createElement("Tooltip").setAttribute("resid", this._getResourceId(this.grManifest.sys_id.toString(), "tooltip"));
  		this._addResource("LongStrings", this._getResourceId(this.grManifest.sys_id.toString(), "tooltip"), this.grManifest.getValue("description"));
  	}
  	this._addResource("ShortStrings", this._getResourceId(this.grManifest.sys_id.toString(), "label"), this.grManifest.getValue("addin_name"));
  	this._populateControlsAndResources(groupNode);
  },

  _populateControlsAndResources: function(groupNode) {
      var appType = this.app.appType;
  	var xmlDoc = this.manifestXml, grControl = new GlideRecord('sn_office_control'), controlNode, itemsNode;
  	grControl.addQuery('manifest', this.grManifest.sys_id.toString());
  	var qc = grControl.addQuery("type", "Button");
  	qc.addOrCondition("type", "Menu");
  	grControl.addNullQuery('parent_control');
  	grControl.addActiveQuery();
  	grControl.orderBy('order');
      grControl.query();
  	
      var addedIconInGroup = false;
  	while(grControl.next()) {
          if(!addedIconInGroup && appType === 'TaskPaneApp'){
              xmlDoc.setCurrentElement(groupNode);
              var iconNode = xmlDoc.createElement("Icon");
              xmlDoc.setCurrentElement(iconNode);
              imgNode = xmlDoc.createElement("bt:Image");
              imgNode.setAttribute("size", "16");
              imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon16"));

              imgNode = xmlDoc.createElement("bt:Image");
              imgNode.setAttribute("size", "32");
              imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon32"));
              imgNode = xmlDoc.createElement("bt:Image");
              imgNode.setAttribute("size", "80");
              imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon80"));
              addedIconInGroup = true;
          }
  		xmlDoc.setCurrentElement(groupNode);
  		controlNode = xmlDoc.createElement("Control");
  		controlNode.setAttribute("xsi:type", grControl.getValue("type"));
  		controlNode.setAttribute("id", grControl.sys_id.toString());
  		xmlDoc.setCurrentElement(controlNode);						
  		//populate all the attributes for the control
  		this._populateControlNode(controlNode, grControl);
  		if(grControl.type.toString() === 'Menu') {
  			xmlDoc.setCurrentElement(controlNode);
  			itemsNode = xmlDoc.createElement("Items");
  			this._populateMenuItems(itemsNode, grControl.sys_id.toString());
  		}			
  	}
  },

  _populateMenuItems: function(itemsNode, parentId) {
  	var xmlDoc = this.manifestXml, grControl = new GlideRecord('sn_office_control'), ItemNode;
  	grControl.addQuery("type", "MenuItem");
  	grControl.addQuery("parent_control", parentId);
  	grControl.addActiveQuery();
  	grControl.orderBy('order');
  	grControl.query();
  	while(grControl.next()) {
  		xmlDoc.setCurrentElement(itemsNode);
  		itemNode = xmlDoc.createElement("Item");
  		itemNode.setAttribute("id", grControl.sys_id.toString());
  		this._populateControlNode(itemNode, grControl);
  	}
  },

  //populates the button, menu or menuItem nodes in the manifest
  _populateControlNode: function(controlNode, grControl) {
  	var xmlDoc = this.manifestXml, addTooltip = false;
  	xmlDoc.setCurrentElement(controlNode);
  	xmlDoc.createElement("Label").setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "label"));
  	//tooltips are only available for control elements
  	if((grControl.getValue("type") === 'Menu' || grControl.getValue("type") === 'Button') && this.app.appType === 'MailApp') {
  		addTooltip= true;
  		xmlDoc.createElement("Tooltip").setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "tooltip"));
  	}
  	//add supertip and Icon parents
  	superTipNode = xmlDoc.createElement("Supertip");
  	iconNode = xmlDoc.createElement("Icon");
  	//add supertip elements
  	xmlDoc.setCurrentElement(superTipNode);
  	xmlDoc.createElement("Title").setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "label"));
  	xmlDoc.createElement("Description").setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "description"));
  	//add images to icons
  	xmlDoc.setCurrentElement(iconNode);
  	imgNode = xmlDoc.createElement("bt:Image");
  	imgNode.setAttribute("size", "16");
  	imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon16"));

  	imgNode = xmlDoc.createElement("bt:Image");
  	imgNode.setAttribute("size", "32");
  	imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon32"));
  	imgNode = xmlDoc.createElement("bt:Image");
  	imgNode.setAttribute("size", "80");
  	imgNode.setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "icon80"));


  	//addResource resets teh currentElement
  	//always resetCurrentElement post invocation of addResource
  	this._addResource("ShortStrings", this._getResourceId(grControl.sys_id.toString(), "label"), grControl.getValue("label"));
  	this._addResource("LongStrings", this._getResourceId(grControl.sys_id.toString(), "description"), grControl.getValue("description"));
  	this._addResource("Images", this._getResourceId(grControl.sys_id.toString(), "icon16"), this._getImageUrl(grControl.getValue('icon16')));
  	this._addResource("Images", this._getResourceId(grControl.sys_id.toString(), "icon32"), this._getImageUrl(grControl.getValue('icon32')));
  	this._addResource("Images", this._getResourceId(grControl.sys_id.toString(), "icon80"), this._getImageUrl(grControl.getValue('icon80')));
  	
  	if(addTooltip) {
  		this._addResource("LongStrings", this._getResourceId(grControl.sys_id.toString(), "tooltip"), grControl.getValue("description"));
  	}

  	if(grControl.type.toString() === 'Button' || grControl.type.toString() === 'MenuItem') {
  		xmlDoc.setCurrentElement(controlNode);
  		actionNode = xmlDoc.createElement("Action");
  		actionNode.setAttribute("xsi:type", "ShowTaskpane");
  		xmlDoc.setCurrentElement(actionNode);
  		if(this.app.appType === 'TaskPaneApp' && this.grManifest.autoshow_taskpane)
  			xmlDoc.createElementWithTextValue('TaskpaneId','Office.AutoShowTaskpaneWithDocument');
  		xmlDoc.createElement("SourceLocation").setAttribute("resid", this._getResourceId(grControl.sys_id.toString(), "url"));
  		this._addResource("Urls", this._getResourceId(grControl.sys_id.toString(), "url"), this._getPageUrl(grControl.getValue('relative_url')));
  	}
  },
  _getImageUrl: function(value) {
  	if(value && value.startsWith("/")) {
  		return this.baseUrl + value.substring(1);
  	} else if(value && value.startsWith("https")) {
  		return value;
  	} else {
  		return this.baseUrl + "/images/outlook-addin/now80.png";
  	}
  },

  //adds resource to the right resource node
  _addResource: function(type, id, value) {
  	var xmlDoc = this.manifestXml, resourceNode, curNode;
  	if(type === 'ShortStrings') {
  		resourceNode = xmlDoc.getNode('/OfficeApp/VersionOverrides/Resources/bt:ShortStrings');
  		this._addlocalizedElement(resourceNode, "bt:String", "bt:Override", id, value);
  	} else if(type === 'LongStrings') {
  		resourceNode = xmlDoc.getNode('/OfficeApp/VersionOverrides/Resources/bt:LongStrings');
  		this._addlocalizedElement(resourceNode, "bt:String", "bt:Override", id, value);
  	} else if(type === 'Urls') {
  		resourceNode = xmlDoc.getNode('/OfficeApp/VersionOverrides/Resources/bt:Urls');
  		xmlDoc.setCurrentElement(resourceNode);
  		curNode = xmlDoc.createElement('bt:Url');
  		curNode.setAttribute("id", id);
  		curNode.setAttribute("DefaultValue", value);
  	} else if(type === 'Images') {
  		resourceNode = xmlDoc.getNode('/OfficeApp/VersionOverrides/Resources/bt:Images');
  		xmlDoc.setCurrentElement(resourceNode);
  		curNode = xmlDoc.createElement('bt:Image');
  		curNode.setAttribute("id", id);
  		curNode.setAttribute("DefaultValue", value);
  	}
  },
  _populateSupportedLanguages: function() {
  	var gr = new GlideRecord('sys_language');
  	if(!gr.isValid()) {
  		return;
  	}

  	gr.addActiveQuery();
  	gr.query();
  	while(gr.next()) {
  		this.supportedLanguages.push(gr.id.toString());
  	}
  },
  _getPageUrl: function(relativeUrl) {
  	if (this.grManifest.login_not_required)
  		return this.baseUrl + (relativeUrl.startsWith('/') ? relativeUrl.substring(1): relativeUrl);
  	var encodedUrl = encodeURIComponent(relativeUrl);
  	return this.baseUrl+'sn_outlook_addin_OutlookLogin.do?page='+encodedUrl;
  },
  _addlocalizedElement: function(parentNode, tag, overrideTag, id, defaultValue) {
  	var i, node, key, curChild, xmlDoc = this.manifestXml;
  	xmlDoc.setCurrentElement(parentNode);
  	node = xmlDoc.createElement(tag);
  	if(id) {
  		node.setAttribute("id",id);
  	}
  	node.setAttribute("DefaultValue",gs.getMessageLang(defaultValue, 'en'));
  	xmlDoc.setCurrentElement(node);
  	for(i in this.supportedLanguages) {
  		key = this.supportedLanguages[i];
  		if(this.languageMap[key]) {
  			curChild = xmlDoc.createElement(overrideTag);
  			curChild.setAttribute('Locale', this.languageMap[key]);
  			curChild.setAttribute('Value', gs.getMessageLang(defaultValue, key));
  		}
  	}
  	xmlDoc.setCurrentElement(parentNode);
  },
  type: 'OfficeAddInManifestGenerator'
};

Sys ID

ada53689ff70230048e505f6793bf1c6

Offical Documentation

Official Docs: