6 * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
7 * @author Cornelius Weiss <c.weiss@metaways.de>
8 * @copyright Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
10 * TODO allow to add user defined part to Tine.title
13 /*global Ext, Tine, google, OpenLayers, Locale, */
15 /** ------------------------- Ext.ux Initialisation ------------------------ **/
17 Ext.ux.Printer.BaseRenderer.prototype.stylesheetPath = 'Tinebase/js/ux/Printer/print.css';
20 /** ------------------------ Tine 2.0 Initialisation ----------------------- **/
26 Ext.namespace('Tine', 'Tine.Tinebase', 'Tine.Calendar');
29 * version of Tine 2.0 javascript client version, gets set a build / release time <br>
30 * <b>Supported Properties:</b>
32 * <tr><td><b>buildType</b></td><td> type of build</td></tr>
33 * <tr><td><b>buildDate</b></td><td> date of build</td></tr>
34 * <tr><td><b>buildRevision</b></td><td> revision of build</td></tr>
35 * <tr><td><b>codeName</b></td><td> codename of release</td></tr>
36 * <tr><td><b>packageString</b></td><td> packageString of release</td></tr>
37 * <tr><td><b>releaseTime</b></td><td> releaseTime of release</td></tr>
41 Tine.clientVersion = {};
42 Tine.clientVersion.buildType = 'none';
43 Tine.clientVersion.buildDate = 'none';
44 Tine.clientVersion.buildRevision = 'none';
45 Tine.clientVersion.codeName = 'none';
46 Tine.clientVersion.packageString = 'none';
47 Tine.clientVersion.releaseTime = 'none';
50 * title of app (gets set at build time)
54 Tine.logo = 'images/tine_logo.png';
56 Tine.title = 'Tine 2.0';
57 Tine.weburl = 'http://www.tine20.com/1/welcome-community/';
58 Tine.helpUrl = 'https://wiki.tine20.org/Main_Page';
59 Tine.bugreportUrl = 'https://api.tine20.net/bugreport.php';
62 * quiet logging in release mode
64 Ext.LOGLEVEL = Tine.clientVersion.buildType === 'RELEASE' ? 0 : 7;
65 Tine.log = Ext.ux.log;
67 Ext.namespace('Tine.Tinebase');
70 * @class Tine.Tinebase.tineInit
71 * @namespace Tine.Tinebase
73 * static tine init functions
75 Tine.Tinebase.tineInit = {
77 * @cfg {String} getAllRegistryDataMethod
79 getAllRegistryDataMethod: 'Tinebase.getAllRegistryData',
82 * @cfg {Boolean} stateful
87 * @cfg {String} jsonKeyCookieId
89 jsonKeyCookieId: 'TINE20JSONKEY',
92 * @cfg {String} requestUrl
94 requestUrl: 'index.php',
97 * prefix for localStorage keys
100 lsPrefix: Tine.Tinebase.common.getUrl('path') + 'Tine',
102 onPreferenceChangeRegistered: false,
104 initWindow: function () {
105 Ext.getBody().on('keydown', function (e) {
106 if (e.ctrlKey && e.getKey() === e.A && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
107 // disable the native 'select all'
109 } else if (e.getKey() === e.BACKSPACE && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
110 // disable the native 'history back'
112 } else if (!window.isMainWindow && e.ctrlKey && e.getKey() === e.T) {
113 // disable the native 'new tab' if in popup window
115 } else if (window.isMainWindow && e.ctrlKey && e.getKey() === e.L) {
117 Tine.Tinebase.common.reload({
123 // disable generic drops
124 Ext.getBody().on('dragover', function (e) {
127 e.browserEvent.dataTransfer.dropEffect = 'none';
131 checkWebpack: function() {
132 if (! window.postal) {
133 var wikiurl = 'https://wiki.tine20.org/Developers/Getting_Started/Working_with_GIT#Install_webpack';
134 Ext.Msg.alert('Webpack-dev-server missing?',
135 'You need to install and run webpack-dev-server! <a target="_blank" href="' + wikiurl + '">Installation instructions in the Wiki</a>.', function() {
136 Tine.Tinebase.common.reload();
141 initPostal: function () {
142 if (! window.postal) return;
144 var config = postal.fedx.transports.xwindow.configure();
145 postal.fedx.transports.xwindow.configure( {
146 localStoragePrefix: Tine.Tinebase.tineInit.lsPrefix + '.' + config.localStoragePrefix
148 postal.instanceId('xwindow-' + _.random(0,1000));
149 postal.configuration.promise.createDeferred = function() {
150 return Promise.defer();
152 postal.configuration.promise.getPromise = function(dfd) {
155 postal.fedx.addFilter( [
156 { channel: 'thirdparty', topic: '#', direction: 'both' },
157 //{ channel: 'postal.request-response', topic: '#', direction: 'both' }
159 postal.fedx.signalReady();
161 postal.addWireTap( function( d, e ) {
162 Tine.log.debug( "ID: " + postal.instanceId() + " " + JSON.stringify( e, null, 4 ) );
166 initDebugConsole: function () {
167 var map = new Ext.KeyMap(Ext.getDoc(), [{
170 fn: Tine.Tinebase.common.showDebugConsole
175 * Each window has exactly one viewport containing a card layout in its lifetime
176 * The default card is a splash screen.
178 * defautl wait panel (picture only no string!)
180 initBootSplash: function () {
184 id: 'tine-viewport-waitcycle',
189 // the content elements come from the initial html so they are displayed fastly
190 contentEl: Ext.select('div[class^=tine-viewport-]')
193 Tine.Tinebase.viewport = new Ext.Viewport({
198 id: 'tine-viewport-maincardpanel',
199 ref: 'tineViewportMaincardpanel',
200 isWindowMainCardPanel: true,
209 initLoginPanel: function() {
210 if (window.isMainWindow && ! Tine.loginPanel) {
211 var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
212 Tine.loginPanel = new Tine.Tinebase.LoginPanel({
213 defaultUsername: Tine.Tinebase.registry.get('defaultUsername'),
214 defaultPassword: Tine.Tinebase.registry.get('defaultPassword')
216 mainCardPanel.add(Tine.loginPanel);
219 // event firing is unpredictable in IE9/10/11, you'll never know when it comes ...
221 Tine.Tinebase.registry.on('replace', function(key, oldValue, newValue) {
222 if (oldValue && !newValue) {
223 Tine.log.info('tineInit::initLoginPanel - handle logout in other window');
224 if (window.isMainWindow) {
225 Tine.Tinebase.common.reload();
227 Ext.ux.PopupWindow.close(window);
230 }, this, 'currentAccount');
234 showLoginBox: function(cb, scope) {
235 var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel,
236 activeItem = mainCardPanel.layout.activeItem;
238 mainCardPanel.layout.setActiveItem(Tine.loginPanel.id);
239 Tine.loginPanel.doLayout();
240 Tine.loginPanel.onLogin = function(response) {
241 mainCardPanel.layout.setActiveItem(activeItem);
242 cb.call(scope||window, response);
245 // //listen for other windows login?
246 // Tine.Tinebase.registry.on('replace', function() {
247 // mainCardPanel.layout.setActiveItem(activeItem);
248 // }, this, 'currentAccount');
252 renderWindow: function () {
253 Tine.log.info('renderWindow::start');
255 var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
257 // check if user is already logged in
258 if (! Tine.Tinebase.registry.get('currentAccount')) {
259 Tine.Tinebase.tineInit.showLoginBox(function(response){
260 Tine.log.info('tineInit::renderWindow -fetch users registry');
261 Tine.Tinebase.tineInit.initRegistry(true, function() {
262 Tine.log.info('tineInit::renderWindow - registry fetched, render main window');
263 Ext.MessageBox.hide();
264 Tine.Tinebase.tineInit.initWindowMgr();
265 Tine.Tinebase.tineInit.renderWindow();
272 // experimental deep link
273 if (window.location.hash) {
274 var hash = window.location.hash.replace(/^#+/, ''),
277 if (hash.match(/\//)) {
278 var args = hash.split('/'),
279 app = Tine.Tinebase.appMgr.get(args.shift()),
280 method = args.shift();
282 config = app.dispatchRoute(method, args);
285 //http://tine.example.com/#{"name":"TimesheetEditWindow_0","contentPanelConstructor":"Tine.Timetracker.TimesheetEditDialog","recordId":0}
286 config = Ext.decode(hash);
289 if (window.history && window.history.replaceState) {
290 window.history.replaceState({}, document.title, Tine.Tinebase.common.getUrl());
293 // what about plugins?
294 Ext.applyIf(config, {
299 window.name = config.name;
301 // disable mainWindows per hash for the moment. MainWindow concept needs to be rethought
302 // in the context of window manager rewrite
303 window.isMainWindow = false;
305 Ext.ux.PopupWindowMgr.register(new Ext.ux.PopupWindow(config));
309 * register MainWindow
311 else if (window.isMainWindow) {
312 Ext.ux.PopupWindowMgr.register({
315 contentPanelConstructor: 'Tine.Tinebase.MainScreenPanel'
320 Tine.log.info('renderWindow::before get window');
322 // fetch window config from WindowMgr
323 var c = Ext.ux.PopupWindowMgr.get(window) || {};
326 window.document.title = Ext.util.Format.stripTags(c.title ? c.title : window.document.title);
328 Tine.log.info('renderWindow::getCenterPanel');
330 // finally render the window contents in a new card
331 var card = Tine.WindowFactory.getCenterPanel(c);
332 mainCardPanel.add(card);
333 mainCardPanel.layout.setActiveItem(card.id);
336 window.initializationComplete = true;
339 initAjax: function () {
340 Ext.Ajax.url = Tine.Tinebase.tineInit.requestUrl;
341 Ext.Ajax.method = 'POST';
343 Ext.Ajax.defaultHeaders = {
344 'X-Tine20-Request-Type' : 'JSON'
347 Ext.Ajax.transactions = {};
349 Tine.Tinebase.tineInit.jsonKeyCookieProvider = new Ext.ux.util.Cookie();
352 * inspect all requests done via the ajax singleton
354 * - send custom headers
356 * - implicitly transform non jsonrpc requests
358 * NOTE: implicitly transformed reqeusts get their callback fn's proxied
359 * through generic response inspectors as defined below
361 Ext.Ajax.on('beforerequest', function (connection, options) {
363 var jsonKey = Tine.Tinebase.registry && Tine.Tinebase.registry.get ? Tine.Tinebase.registry.get('jsonKey') : '';
364 if (Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId)) {
365 var cookieJsonKey = Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId);
366 Tine.Tinebase.tineInit.jsonKeyCookieProvider.clear(this.jsonKeyCookieId);
367 // NOTE cookie reset is not always working in IE, so we need to check jsonKey again
368 if (cookieJsonKey && cookieJsonKey != "null") {
369 jsonKey = cookieJsonKey;
370 Tine.Tinebase.registry.set('jsonKey', jsonKey);
374 options.headers = options.headers || {};
375 options.headers['X-Tine20-JsonKey'] = jsonKey;
376 options.headers['X-Tine20-TransactionId'] = Tine.Tinebase.data.Record.generateUID();
378 options.url = Ext.urlAppend((options.url ? options.url : Tine.Tinebase.tineInit.requestUrl), 'transactionid=' + options.headers['X-Tine20-TransactionId']);
380 // convert non Ext.Direct request to jsonrpc
382 // - convert error handling
383 if (options.params && !options.isUpload) {
386 var def = Tine.Tinebase.registry.get('serviceMap') ? Tine.Tinebase.registry.get('serviceMap').services[options.params.method] : false;
388 // sort parms according to def
389 for (var i = 0, p; i < def.parameters.length; i += 1) {
390 p = def.parameters[i].name;
391 params[p] = options.params[p];
394 for (var param in options.params) {
395 if (options.params.hasOwnProperty(param) && param !== 'method') {
396 params[param] = options.params[param];
401 options.jsonData = Ext.encode({
403 method: options.params.method,
409 options.cbs.success = options.success || null;
410 options.cbs.failure = options.failure || null;
411 options.cbs.callback = options.callback || null;
413 options.isImplicitJsonRpc = true;
414 delete options.params;
415 delete options.success;
416 delete options.failure;
417 delete options.callback;
420 Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']] = {
422 json: options.jsonData
429 * inspect completed responses => staus code == 200
431 * - detect resoponse errors (e.g. html from xdebug) and convert to exceptional states
432 * - implicitly transform requests from JSONRPC
434 * NOTE: All programatically catchable exceptions lead to successfull requests
435 * with the jsonprc protocol. For implicitly converted jsonprc requests we
436 * transform error states here and route them to the error methods defined
437 * in the request options
439 * NOTE: Illegal json data responses are mapped to error code 530
440 * Empty resonses (Ext.Decode can't deal with them) are maped to 540
441 * Memory exhausted to 550
443 Ext.Ajax.on('requestcomplete', function (connection, response, options) {
444 delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
446 // detect resoponse errors (e.g. html from xdebug) and convert into error response
447 if (! options.isUpload && ! response.responseText.match(/^([{\[])|(<\?xml)+/)) {
449 code: response.responseText !== "" ? 530 : 540,
450 message: response.responseText !== "" ? 'illegal json data in response' : 'empty response',
451 traceHTML: response.responseText,
452 request: options.jsonData,
453 response: response.responseText
456 // Fatal error: Allowed memory size of n bytes exhausted (tried to allocate m bytes)
457 if (response.responseText.match(/^Fatal error: Allowed memory size of /m)) {
458 Ext.apply(exception, {
460 message: response.responseText
464 // encapsulate as jsonrpc response
465 var requestOptions = Ext.decode(options.jsonData);
466 response.responseText = Ext.encode({
467 jsonrpc: requestOptions.jsonrpc,
468 id: requestOptions.id,
471 message: exception.message,
477 // strip jsonrpc fragments for non Ext.Direct requests
478 if (options.isImplicitJsonRpc) {
479 var jsonrpc = Ext.decode(response.responseText);
480 if (jsonrpc.result) {
481 response.responseText = Ext.encode(jsonrpc.result);
483 if (options.cbs.success) {
484 options.cbs.success.call(options.scope, response, options);
486 if (options.cbs.callback) {
487 options.cbs.callback.call(options.scope, options, true, response);
491 response.responseText = Ext.encode(jsonrpc.error);
493 if (options.cbs.failure) {
494 options.cbs.failure.call(options.scope, response, options);
495 } else if (options.cbs.callback) {
496 options.cbs.callback.call(options.scope, options, false, response);
498 var responseData = Ext.decode(response.responseText);
500 exception = responseData.data ? responseData.data : responseData;
501 exception.request = options.jsonData;
502 exception.response = response.responseText;
504 Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
511 * inspect request exceptions
512 * - convert to jsonrpc compatiple exceptional states
513 * - call generic exception handler if no handler is defined in request options
515 * NOTE: Request exceptions are exceptional state from web-server:
516 * -> status codes != 200 : This kind of exceptions are not part of the jsonrpc protocol
517 * -> timeouts: status code 520
519 Ext.Ajax.on('requestexception', function (connection, response, options) {
520 delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
521 // map connection errors to errorcode 510 and timeouts to 520
522 var errorCode = response.status > 0 ? response.status :
523 (response.status === 0 ? 510 : 520);
525 // convert into error response
526 if (! options.isUpload) {
529 message: 'request exception: ' + response.statusText,
530 traceHTML: response.responseText,
531 request: options.jsonData,
532 requestHeaders: options.headers,
533 openTransactions: Ext.Ajax.transactions,
534 response: response.responseText
537 // encapsulate as jsonrpc response
538 var requestOptions = Ext.decode(options.jsonData);
539 response.responseText = Ext.encode({
540 jsonrpc: requestOptions.jsonrpc,
541 id: requestOptions.id,
544 message: exception.message,
550 // NOTE: Tine.data.RecordProxy is implicitRPC atm.
551 if (options.isImplicitJsonRpc) {
552 var jsonrpc = Ext.decode(response.responseText);
554 response.responseText = Ext.encode(jsonrpc.error);
556 if (options.cbs.failure) {
557 options.cbs.failure.call(options.scope, response, options);
558 } else if (options.cbs.callback) {
559 options.cbs.callback.call(options.scope, options, false, response);
561 var responseData = Ext.decode(response.responseText);
563 exception = responseData.data ? responseData.data : responseData;
565 Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
568 } else if (! options.failure && ! options.callback) {
569 Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
577 * @param {Boolean} forceReload
578 * @param {Function} cb
579 * @param {Object} scope
581 initRegistry: function (forceReload, cb, scope) {
582 Tine.Tinebase.registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + 'Tinebase.registry');
584 var version = Tine.Tinebase.registry.get('version'),
585 userApplications = Tine.Tinebase.registry.get('userApplications') || [];
590 || userApplications.length < 2;
592 if (forceReload || reloadNeeded) {
593 Tine.Tinebase.tineInit.clearRegistry();
596 timeout: 120000, // 2 minutes
598 method: Tine.Tinebase.tineInit.getAllRegistryDataMethod
600 failure: function () {
601 // if registry could not be loaded, this is mostly due to missconfiguaration
602 // don't send error reports for that!
603 Tine.Tinebase.ExceptionHandler.handleRequestException({
607 success: function (response, request) {
608 var registryData = Ext.util.JSON.decode(response.responseText);
609 for (var app in registryData) {
610 if (registryData.hasOwnProperty(app)) {
611 var appData = registryData[app];
612 Ext.ns('Tine.' + app);
613 Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
615 for (var key in appData) {
616 if (appData.hasOwnProperty(key)) {
617 if (key === 'preferences') {
618 Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
619 for (var pref in appData[key]) {
620 if (appData[key].hasOwnProperty(pref)) {
621 Tine[app].preferences.set(pref, appData[key][pref]);
626 Tine[app].registry.set(key, appData[key]);
633 Tine.Tinebase.tineInit.onRegistryLoad();
639 for (var app,i=0;i<userApplications.length;i++) {
640 app = userApplications[i].name;
641 Ext.ns('Tine.' + app);
642 Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
643 Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
646 Tine.Tinebase.tineInit.onRegistryLoad();
654 * apply registry data
656 onRegistryLoad: function() {
657 if (! Tine.Tinebase.tineInit.onPreferenceChangeRegistered
658 && Tine.Tinebase.registry.get('preferences')
659 && Tine.Tinebase.registry.get('currentAccount')
662 Tine.log.info('tineInit::onRegistryLoad - register onPreferenceChange handler');
663 Tine.Tinebase.preferences.on('replace', Tine.Tinebase.tineInit.onPreferenceChange);
664 Tine.Tinebase.tineInit.onPreferenceChangeRegistered = true;
667 Tine.helpUrl = Tine.Tinebase.registry.get('helpUrl') || Tine.helpUrl;
668 //Do we have a custom weburl for branding?
669 Tine.weburl = Tine.Tinebase.registry.get('brandingWeburl') ? Tine.Tinebase.registry.get('brandingWeburl') : Tine.weburl;
670 //DO we have a custom title for branding?
671 Tine.title = Tine.Tinebase.registry.get('brandingTitle') ? Tine.Tinebase.registry.get('brandingTitle') : Tine.title;
672 Tine.logo = Tine.Tinebase.registry.get('brandingLogo') ? Tine.Tinebase.registry.get('brandingLogo') : Tine.logo;
673 Tine.favicon = Tine.Tinebase.registry.get('brandingFavicon') ? Tine.Tinebase.registry.get('brandingFavicon') : Tine.favicon;
675 Ext.override(Ext.ux.file.Upload, {
676 maxFileUploadSize: Tine.Tinebase.registry.get('maxFileUploadSize'),
677 maxPostSize: Tine.Tinebase.registry.get('maxPostSize')
680 Tine.Tinebase.tineInit.initExtDirect();
682 Tine.Tinebase.tineInit.initState();
684 if (Tine.Tinebase.registry.get('currentAccount')) {
685 Tine.Tinebase.tineInit.initAppMgr();
688 Tine.Tinebase.tineInit.initUploadMgr();
690 Tine.Tinebase.tineInit.initLoginPanel();
694 * remove all registry data
696 clearRegistry: function() {
697 Tine.log.info('tineInit::clearRegistry');
698 if (Ext.isFunction(store.namespace)) {
699 store.namespace(Tine.Tinebase.tineInit.lsPrefix).clearAll();
704 * executed when a value in Tinebase registry/preferences changed
706 * @param {string} key
707 * @param {value} oldValue
708 * @param {value} newValue
710 onPreferenceChange: function (key, oldValue, newValue) {
711 if (Tine.Tinebase.tineInit.isReloading) {
717 case 'confirmLogout':
720 Tine.log.info('tineInit::onPreferenceChange - reload mainscreen');
721 Tine.Tinebase.common.reload({
722 clearCache: key == 'locale'
730 * initialise window and windowMgr (only popup atm.)
732 initWindowMgr: function () {
734 * initialise window types
736 var windowType = 'Browser';
737 Ext.ux.PopupWindow.prototype.url = 'index.php';
739 if (Tine.Tinebase.registry && Tine.Tinebase.registry.get('preferences')) {
740 // update window factory window type (required after login)
741 windowType = Tine.Tinebase.registry.get('preferences').get('windowtype');
743 windowType = 'Browser';
747 Tine.WindowFactory = new Ext.ux.WindowFactory({
748 windowType: windowType
751 // init ApplicationStarter on Ext window once
752 if (windowType == 'Ext') {
753 Tine.Tinebase.ApplicationStarter.init();
757 * initialise state provider
759 initState: function () {
760 if (Tine.Tinebase.tineInit.stateful === true) {
761 if (window.isMainWindow || Ext.isIE) {
762 // NOTE: IE is as always pain in the ass! cross window issues prohibit serialisation of state objects
763 Ext.state.Manager.setProvider(new Tine.Tinebase.StateProvider());
765 var mainWindow = Ext.ux.PopupWindowMgr.getMainWindow();
766 Ext.state.Manager = mainWindow.Ext.state.Manager;
772 * add provider to Ext.Direct based on Tine servicemap
774 initExtDirect: function () {
775 var sam = Tine.Tinebase.registry.get('serviceMap');
777 Ext.Direct.addProvider(Ext.apply(sam, {
778 'type' : 'jsonrpcprovider',
785 * init external libraries
787 initLibs: function () {
789 // fix OpenLayers script location to find images/themes/...
790 OpenLayers._getScriptLocation = function () {
791 return 'library/OpenLayers/';
797 * initialise application manager
799 initAppMgr: function () {
800 if (! Ext.isIE9 && ! Ext.isIE && ! window.isMainWindow) {
801 // return app from main window for non-IE browsers
802 Tine.Tinebase.appMgr = Ext.ux.PopupWindowMgr.getMainWindow().Tine.Tinebase.appMgr;
804 Tine.Tinebase.appMgr = new Tine.Tinebase.AppManager();
809 * initialise upload manager
811 initUploadMgr: function () {
812 Tine.Tinebase.uploadManager = new Ext.ux.file.UploadManager();
818 initLocale: function () {
819 //Locale.setlocale(Locale.LC_ALL, '');
820 window.i18n = new Locale.Gettext();
821 window.i18n.textdomain('Tinebase');
823 window._ = function (msgid) {
824 Tine.log.warn('_() is deprecated, please use i18n._ instead' + new Error().stack);
825 return window.i18n.dgettext('Tinebase', msgid);
828 Tine.Tinebase.prototypeTranslation();
832 Ext.onReady(function () {
833 Tine.Tinebase.tineInit.initWindow();
834 Tine.Tinebase.tineInit.checkWebpack();
835 Tine.Tinebase.tineInit.initPostal();
836 Tine.Tinebase.tineInit.initDebugConsole();
837 Tine.Tinebase.tineInit.initBootSplash();
838 Tine.Tinebase.tineInit.initLocale();
839 Tine.Tinebase.tineInit.initAjax();
840 Tine.Tinebase.tineInit.initLibs();
842 Tine.Tinebase.tineInit.initRegistry(false, function() {
843 Tine.Tinebase.tineInit.initWindowMgr();
844 Tine.Tinebase.tineInit.renderWindow();