more meaningful debug message when app init fails
[tine20] / tine20 / Tinebase / js / AppManager.js
1 /*
2  * Tine 2.0
3  * 
4  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
5  * @author      Cornelius Weiss <c.weiss@metaways.de>
6  * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
7  */
8 Ext.ns('Tine.Tinebase');
9
10 /**
11  * Tine 2.0 main application manager
12  * 
13  * @namespace   Tine.Tinebase
14  * @class       Tine.Tinebase.AppManager
15  * @extends     Ext.util.Observable
16  * @consturctor
17  * @author      Cornelius Weiss <c.weiss@metaways.de>
18  */
19 Tine.Tinebase.AppManager = function() {
20     /**
21      * @property apps
22      * @type Ext.util.MixedCollection
23      * 
24      * enabled apps
25      */
26     this.apps = new Ext.util.MixedCollection({});
27     
28     this.addEvents(
29         /**
30          * @event beforeactivate
31          * fired before an application gets activated. Retrun false to stop activation
32          * @param {Tine.Aplication} app about to activate
33          */
34         'beforeactivate',
35         /**
36          * @event activate
37          * fired when an application gets activated
38          * @param {Tine.Aplication} activated app
39          */
40         'activate',
41         /**
42          * @event beforedeactivate
43          * fired before an application gets deactivated. Retrun false to stop deactivation
44          * @param {Tine.Aplication} app about to deactivate
45          */
46         'beforedeactivate',
47         /**
48          * @event deactivate
49          * fired when an application gets deactivated
50          * @param {Tine.Aplication} deactivated app
51          */
52         'deactivate',
53         /**
54          * @event windowopenexception
55          * windowopenexceptionated 
56          * @param {} Exception
57          */
58         'windowopenexception'
59     );
60     
61     
62     // fill this.apps with registry data 
63     // do it the other way round because add() always adds records at the beginning of the MixedCollection
64     var enabledApps = Tine.Tinebase.registry.get('userApplications'),
65         app;
66         
67     Tine.log.debug('Tine.Tinebase.AppManager - enabled Apps: ');
68     Tine.log.debug(enabledApps);
69     
70     for (var i = (enabledApps.length - 1); i >= 0; i--) {
71         app = enabledApps[i];
72         
73         // if the app is not in the namespace, we don't initialise it
74         // we don't have a Tinebase 'Application'
75         if (Tine[app.name] && ! app.name.match(/(Tinebase)/)) {
76             app.appName = app.name;
77             app.isInitialised = false;
78             this.apps.add(app.appName, app);
79         }
80     }
81 };
82
83 Ext.extend(Tine.Tinebase.AppManager, Ext.util.Observable, {
84     /**
85      * @cfg {Tine.Application}
86      */
87     defaultApp: null,
88     
89     /**
90      * @property activeApp
91      * @type Tine.Application
92      * 
93      * currently active app
94      */
95     activeApp: null,
96     
97     /**
98      * activate application
99      * 
100      * @param {Tine.Application} app
101      * @return {Boolean}
102      * 
103      * TODO think about adding a fallback app if app mainscreen could not be fetched 
104      */
105     activate: function(app) {
106         if (app || (app = this.getDefault()) ) {
107             if (app == this.getActive()) {
108                 // app is already active, nothing to do
109                 return true;
110             }
111             
112             if (this.activeApp) {
113                 if ((this.fireEvent('beforedeactivate', this.activeApp) === false || this.activeApp.onBeforeDeActivate() === false)) {
114                     return false;
115                 }
116                 
117                 this.activeApp.onDeActivate();
118                 this.fireEvent('deactivate', this.activeApp);
119                 this.activeApp = null;
120             }
121             
122             if (this.fireEvent('beforeactivate', app) === false || app.onBeforeActivate() === false) {
123                 return false;
124             }
125             
126             var mainscreen = app.getMainScreen();
127             if (mainscreen) {
128                 mainscreen.show();
129             } else {
130                 // app has no mainscreen / perhaps it has been disabled
131                 return false;
132             }
133             
134             this.activeApp = app;
135             app.onActivate();
136             this.fireEvent('activate', app);
137         }
138     },
139     
140     /**
141      * returns an appObject
142      * 
143      * @param {String} appName
144      * @return {Tine.Application}
145      */
146     get: function(appName) {
147         if (Ext.isObject(appName) && appName.hasOwnProperty('appName')) {
148             appName = appName.appName;
149         }
150         if (! this.isEnabled(appName)) {
151             return false;
152         }
153         
154         var app = this.apps.get(appName);
155         if (! app.isInitialised) {
156             var appObj = this.getAppObj(app);
157             appObj.isInitialised = true;
158             Ext.applyIf(appObj, app);
159             this.apps.replace(appName, appObj);
160         }
161         
162         return this.apps.get(appName);
163     },
164     
165     /**
166      * returns appObject
167      * 
168      * @param {String} applicationId
169      * @return {Tine.Application}
170      */
171     getById: function(applicationId) {
172         var appObj = null;
173         Ext.each(Tine.Tinebase.registry.get('userApplications'), function(rawApp) {
174             if (rawApp.id === applicationId) {
175                 appObj = this.get(rawApp.appName);
176                 return false;
177             }
178         }, this);
179         
180         return appObj;
181     },
182     
183     /**
184      * returns currently activated app
185      * @return {Tine.Application}
186      */
187     getActive: function() {
188         return this.activeApp;
189     },
190     
191     /**
192      * returns appObject of default app
193      * 
194      * @return {Tine.Application}
195      */
196     getDefault: function() {
197         if (! this.defaultApp) {
198             var defaultAppName = (Tine.Tinebase.registry.get('preferences') && Tine.Tinebase.registry.get('preferences').get('defaultapp')) 
199                 ? Tine.Tinebase.registry.get('preferences').get('defaultapp') 
200                 : this.defaultAppName;
201                 
202             this.defaultApp = this.get(defaultAppName) || this.apps.find(function(app) {return app.hasMainScreen});
203             
204             if (! this.defaultApp) {
205                 // no global exception concept yet...
206                 //throw Ext.Error('no apps enabled', 620);
207                 Ext.MessageBox.show({
208                     title: _('Missing Applications'), 
209                     msg: _('There are no applications enabled for you. Please contact your administrator.'),
210                     buttons: Ext.Msg.OK,
211                     icon: Ext.MessageBox.WARNING
212                 });
213             }
214         }
215         
216         return this.defaultApp;
217     },
218     
219     /**
220      * set default app for this session
221      * 
222      * @param {Tine.Application/String} app
223      */
224     setDefault: function(app) {
225         if (Ext.isString(app)) {
226             app = this.get(app);
227         }
228         
229         if (app) {
230             this.defaultApp = app;
231         }
232     },
233     
234     /**
235      * returns a list of all apps for current user
236      */
237     getAll: function() {
238         this.initAll();
239         return this.apps;
240     },
241     
242     /**
243      * checks wether a given app is enabled for current user or not
244      */
245     isEnabled: function(appName) {
246         var app = this.apps.get(appName);
247         return app ? app.status == 'enabled' : false;
248     },
249     
250     /**
251      * initialises all enabled apps
252      * @private
253      */
254     initAll: function() {
255         this.apps.each(function(app) {
256             this.get(app.appName);
257         }, this);
258     },
259     
260     /**
261      * @private
262      */
263     getAppObj: function(app) {
264        try{
265             // legacy
266             if (typeof(Tine[app.appName].getPanel) == 'function') {
267                 // make a legacy Tine.Application
268                 return this.getLegacyApp(app);
269             }
270
271             return typeof(Tine[app.appName].Application) == 'function' ? new Tine[app.appName].Application(app) : new Tine.Tinebase.Application(app);
272             
273         } catch(e) {
274             console.error('Initialising of Application "' + app.appName + '" failed with the following message:' + e);
275             console.error(e.stack);
276             return false;
277         }
278     },
279     
280     /**
281      * @private
282      */
283     getLegacyApp: function(app) {
284         var appPanel = Tine[app.appName].getPanel();
285         var appObj =  new Tine.Tinebase.Application(app);
286         var mainScreen = new Tine.widgets.MainScreen({app: appObj});
287         
288         Ext.apply(mainScreen, {
289             appPanel: appPanel,
290             getContainerTreePanel: function() {
291                 return this.appPanel;
292             },
293             getWestPanel: function() {
294                 return this.appPanel;
295             },
296             show: function() {
297                 // remove favorite toolbar for legacy modules
298                 var westPanelToolbar = Ext.getCmp('west').getTopToolbar();
299                 westPanelToolbar.removeAll();
300                 westPanelToolbar.hide();
301                 westPanelToolbar.doLayout();
302
303                 Tine.Tinebase.MainScreen.setActiveTreePanel(appPanel, true);
304                 appPanel.fireEvent('beforeexpand', appPanel);
305             }
306         });
307         Ext.apply(appObj, {
308             mainScreen: mainScreen
309         });
310         appPanel.on('render', function(p) {
311             p.header.remove();
312             // additionally to removing the DOM node, we also need to reset the 
313             // header class variable, as IE evals "if (this.header)" to true otherwise 
314             p.header = false;
315             p.doLayout();
316         });
317         
318         return appObj;
319     }
320 });