1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * Creates the portal application.
 26  * @class
 27  * This class represents the portal application.
 28  * 
 29  * @param	{DwtControl}	container		the container
 30  * @param	{ZmPortalController}	parentController		the controller
 31  * 
 32  * @extends		ZmApp
 33  */
 34 ZmPortalApp = function(container, parentController) {
 35 	ZmApp.call(this, ZmApp.PORTAL, container, parentController);
 36 }
 37 
 38 ZmPortalApp.prototype = new ZmApp;
 39 ZmPortalApp.prototype.constructor = ZmPortalApp;
 40 
 41 /**
 42  * Returns a string representation of the object.
 43  * 
 44  * @return		{String}		a string representation of the object
 45  */
 46 ZmPortalApp.prototype.toString = function() {
 47 	return "ZmPortalApp";
 48 };
 49 
 50 // Construction
 51 
 52 ZmPortalApp.prototype._registerApp = function() {
 53     ZmApp.registerApp(ZmApp.PORTAL, {
 54         nameKey: "portal",
 55         icon: "Globe",
 56         chooserTooltipKey:	"goToPortal",
 57         button: ZmAppChooser.B_PORTAL,
 58         chooserSort: 1,
 59         defaultSort: 1
 60 	});
 61 };
 62 
 63 //
 64 // Constants
 65 //
 66 
 67 /**
 68  * Defines the "portal" application.
 69  */
 70 ZmApp.PORTAL                    = ZmId.APP_PORTAL;
 71 ZmApp.CLASS[ZmApp.PORTAL]		= "ZmPortalApp";
 72 ZmApp.SETTING[ZmApp.PORTAL]		= ZmSetting.PORTAL_ENABLED;
 73 ZmApp.LOAD_SORT[ZmApp.PORTAL]	= 1;
 74 ZmApp.QS_ARG[ZmApp.PORTAL]		= "home";
 75 
 76 ZmEvent.S_PORTLET   = "PORTLET";
 77 ZmItem.PORTLET      = ZmEvent.S_PORTLET;
 78 
 79 ZmPortalApp.__PORTLET_ID = 0;
 80 
 81 //
 82 // Public methods
 83 //
 84 
 85 /**
 86  * Refreshes the portlets.
 87  * 
 88  */
 89 ZmPortalApp.prototype.refreshPortlets = function() {
 90     var mgr = this.getPortletMgr();
 91     var portlets = mgr.getPortlets();
 92     for (var id in portlets) {
 93         portlets[id].refresh();
 94     }
 95 };
 96 
 97 ZmPortalApp.prototype.launch =
 98 function(params, callback) {
 99     var loadCallback = new AjxCallback(this, this._handleLoadLaunch, [params, callback]);
100 	AjxDispatcher.require("Portal", true, loadCallback, null, true);
101 };
102 
103 ZmPortalApp.prototype._handleLoadLaunch = function(params, callback) {
104 	var controller = this.getPortalController();
105 	controller.show();
106     ZmApp.prototype.launch.call(this, params, callback);
107 };
108 
109 ZmPortalApp.prototype.activate = function(active) {
110 	var controller = this.getPortalController();
111 	controller.setPaused(!active);
112 	ZmApp.prototype.activate.call(this, active);
113 };
114 
115 /**
116  * Gets the portal manifest.
117  * 
118  * @param	{AjxCallback}		callback		the callback to call after the manifest is loaded
119  * @return	{Object}		the manifest
120  */
121 ZmPortalApp.prototype.getManifest = function(callback) {
122     if (!this._manifest) {
123         // load the portal manifest
124         var portalName = appCtxt.get(ZmSetting.PORTAL_NAME);
125         if (portalName) {
126             var timestamp = new Date().getTime(); 
127             var params = {
128                 url: [ window.appContextPath,"/portals/",portalName,"/manifest.xml?v=",timestamp ].join(""),
129                 callback: callback ? new AjxCallback(this, this._handleLoadManifest, [callback]) : null
130             };
131             var req = AjxLoader.load(params);
132             if (!callback) {
133                 this._handleLoadManifest(callback, req);
134             }
135         }
136     }
137 	else if (callback) {
138 		callback.run(this._manifest);
139 	}
140 	return this._manifest;
141 };
142 
143 ZmPortalApp.prototype._handleLoadManifest = function(callback, req) {
144     var e;
145     if (req.status == 200 && req.responseXML) {
146         try {
147             // serialize manifest into JSON and evaluate
148             var json = new AjxJsonSerializer(true).serialize(req.responseXML);
149 			this._manifest = JSON.parse(json);
150 
151             // further minimize the object structure
152             var portalDef = this._manifest.portal ;
153             var portletsDef = portalDef && portalDef.portlets;
154             if (portletsDef && !(portletsDef.portlet instanceof Array)) {
155                 portletsDef.portlet = [ portletsDef.portlet ];
156             }
157             portalDef.portlets = portletsDef.portlet;
158 
159             if (portalDef.portlets) {
160                 for (var i = 0; i < portalDef.portlets.length; i++) {
161                     var portletDef = portalDef.portlets[i];
162                     var propertyDef = portletDef.property;
163                     if (propertyDef && !(propertyDef instanceof Array)) {
164                         propertyDef = [ propertyDef ];
165                     }
166                     portletDef.properties = propertyDef;
167                     delete portletDef.property;
168                 }
169             }
170         }
171         catch (e) {
172             DBG.println(e);
173         }
174     }
175     else {
176         e = ""
177     }
178 
179     if (!this._manifest) {
180         this._manifest = { error: e };
181     }
182     
183     // callback
184     if (callback) {
185         callback.run(this._manifest);
186     }
187 };
188 
189 /**
190  * Gets the portal controller.
191  * 
192  * @return	{ZmPortalController}	the controller
193  */
194 ZmPortalApp.prototype.getPortalController = function() {
195 	AjxDispatcher.require("Portal");
196 	if (!this._portalController) {
197 		this._portalController = new ZmPortalController(this._container, this);
198 	}
199 	return this._portalController;
200 };
201 
202 /**
203  * Gets the portlet manager.
204  * 
205  * @return	{ZmPortletMgr}		the portlet manager
206  */
207 ZmPortalApp.prototype.getPortletMgr = function() {
208 	AjxDispatcher.require("Portal");
209     if (!this._portletMgr) {
210         this._portletMgr = new ZmPortletMgr();
211     }
212     return this._portletMgr;
213 };
214 
215 //
216 // Protected functions
217 //
218 
219 ZmPortalApp.prototype._getOverviewTrees =
220 function() {
221 	return this._getOverviewApp()._getOverviewTrees();
222 };
223 
224 //ZmPortalApp.prototype.getAccordionController =
225 //function() {
226 //	return this._getOverviewApp().getAccordionController();
227 //};
228 
229 ZmPortalApp.prototype._getOverviewApp =
230 function() {
231 	if (!this._overviewApp) {
232 		var apps = [];
233 		for (var name in ZmApp.CHOOSER_SORT) {
234 			apps.push({ name: name, sort: ZmApp.CHOOSER_SORT[name] });
235 		}
236 		apps.sort(ZmPortalApp.__BY_SORT);
237 
238 		var appName = null;
239 		for (var i = 0; i < apps.length; i++) {
240 			var app = apps[i];
241 			if (app.name == this._name) { continue; }
242 			if (appCtxt.getApp(app.name).isIframe) { continue; }
243 
244 			appName = app.name;
245 			break;
246 		}
247 		this._overviewApp = appCtxt.getApp(appName);
248 	}
249 	return this._overviewApp;
250 };
251 
252 //
253 // Private functions
254 //
255 
256 ZmPortalApp.__BY_SORT = function(a, b) {
257 	return a.sort - b.sort;
258 };
259