Ext.namespace('Zarafa.settings');
/**
* @class Zarafa.settings.SettingsContext
* @extends Zarafa.core.Context
*/
Zarafa.settings.SettingsContext = Ext.extend(Zarafa.core.Context, {
/**
* @constructor
* @param {Object} config Configuration object
*/
constructor : function(config)
{
config = config || {};
Ext.applyIf(config, {
stateful : false
});
Zarafa.settings.SettingsContext.superclass.constructor.call(this, config);
// Register the settings tab in the MainTabBar
this.registerInsertionPoint('main.maintabbar.right', this.createSettingsMainTab, this);
// Register some default categories for the settings
this.registerInsertionPoint('context.settings.categories', this.createSettingCategories, this);
this.addEvents(
/**
* Fires when the user press a button in required reload message box.
* @param {String} button The button which user pressed from
* required reload message box
*/
'afterrequiredreload'
);
},
/**
* @return {Zarafa.settings.SettingsContextModel} the settings context model
*/
getModel : function()
{
if (!Ext.isDefined(this.model)) {
this.model = new Zarafa.settings.SettingsContextModel();
}
return this.model;
},
/**
* Switch the currently active view inside the {@link Zarafa.core.Context context}.
* This will fire the {@link #viewchange} event.
*
* Before switching the view, this function will first check if there are
* any pending changes.
*
* @param {Mixed} viewId The view identification
*/
setView : function(viewId)
{
if (this.current_view != viewId) {
var model = this.getModel();
if (model.hasChanges()) {
Ext.MessageBox.show({
title: _('Kopano WebApp'),
msg : _('Do you wish to apply the changes?'),
icon: Ext.MessageBox.QUESTION,
fn: this.applyChanges.createDelegate(this, [ viewId ], 1),
buttons: Ext.MessageBox.YESNOCANCEL
});
} else {
Zarafa.settings.SettingsContext.superclass.setView.call(this, viewId);
}
}
},
/**
* Sets the current view mode from the available view modes.
*
* Compared to the {@link Zarafa.core.Context superclass} this function
* will always fire the viewmode change event regardless if the same value
* has been provided or not.
*
* Fires the {@link #viewmodechange} event.
* @param {Number} mode view mode (context should define modes and its numeric values).
*/
setViewMode : function(mode)
{
var oldMode = this.current_view_mode;
this.current_view_mode = mode;
this.fireEvent('viewmodechange', this, this.current_view_mode, oldMode);
},
/**
* Event handler for {@link #setView}. This will check if the user
* wishes to cancel the {@link #setView} action, or wishes to either
* {@link Zarafa.settings.SettingsContextModel#applyChanges apply} or
* {@link Zarafa.settings.SettingsContextModel#discardChanges discard}
* all changes.
* @param {String} btn The button which the user pressed
* @param {Mixed} viewId the viewId argument from {@link #setView}.
* @private
*/
applyChanges : function(btn, viewId)
{
// The user cancels the switch to a different category
if (btn === 'cancel') {
return;
}
// Check if the user wishes to save or discard all changes
var model = this.getModel();
if (btn === 'yes') {
model.applyChanges();
} else {
model.discardChanges();
}
Zarafa.settings.SettingsContext.superclass.setView.call(this, viewId);
},
/**
* Called before the context is switched in.
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder MAPI folder to show.
* @param {Boolean} suspended True to enable the ContextModel {@link Zarafa.core.ContextModel#suspendLoading suspended}
*/
enable : function(folder, suspended)
{
Zarafa.settings.SettingsContext.superclass.enable.apply(this, arguments);
container.on('beforecontextswitch', this.onBeforeContextSwitch, this);
this.getModel().getRealSettingsModel().on('save', this.onSaveSettings, this);
container.getNavigationBar().collapse();
},
/**
* Called before the context is switched out.
*/
disable : function()
{
container.getNavigationBar().expand();
container.un('beforecontextswitch', this.onBeforeContextSwitch, this);
Zarafa.settings.SettingsContext.superclass.disable.apply(this, arguments);
},
/**
* Event handler which shows the warning {@link Zarafa.common.dialogs.MessageBox.addCustomButtons messageBox}
* if updated settings required the webapp to reload.
* @param {Zarafa.settings.SettingsModel} model The model which fired the event.
* @param {Object} param The key-value object containing the action and the corresponding
* settings which were saved to the server.
*/
onSaveSettings : function(model, param)
{
if(param.requiresReload) {
var message = _('In order for the changes to take effect, please reload WebApp.') +'<br>'+ _('NOTE: Any unsaved changes will be lost.');
Zarafa.common.dialogs.MessageBox.addCustomButtons({
title: _('Kopano WebApp'),
msg : message,
icon : Ext.MessageBox.QUESTION,
fn : this.reloadWebapp,
customButton : [{
text : _('Reload'),
name : 'reload'
}, {
text : _('Cancel'),
name : 'cancel'
}],
scope : this
});
}
},
/**
* Event handler for {@link #onSaveSettings}. This will check if the user
* wishes to reload the webapp or not.
* @param {String} button The button which the user pressed
* @private
*/
reloadWebapp : function(button)
{
if(button === 'reload') {
this.getModel().getRealSettingsModel().un('save', this.onSaveSettings, this);
Zarafa.core.Util.reloadWebapp();
}
this.fireEvent('afterrequiredreload', this, button);
},
/**
* Bid for the type of shared component and the given record.
* @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
* @param {Ext.data.Record} record Optionally passed record.
* @return {Number} The bid for the shared component
*/
bidSharedComponent: function(type, record)
{
var bid = -1;
if (Array.isArray(record)) {
record = record[0];
}
switch (type) {
case Zarafa.core.data.SharedComponentType['common.contextmenu']:
if (record instanceof Zarafa.settings.ui.SettingsTreeNode) {
bid = 1;
}
break;
}
return bid;
},
/**
* Will return the reference to the shared component.
* Based on the type of component requested a component is returned.
* @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
* @param {Ext.data.Record} record Optionally passed record.
* @return {Ext.Component} Component
*/
getSharedComponent: function(type, record)
{
var component;
switch (type) {
case Zarafa.core.data.SharedComponentType['common.contextmenu']:
if (record instanceof Zarafa.settings.ui.SettingsTreeNode) {
component = Zarafa.settings.ui.SettingsContextMenu;
}
break;
}
return component;
},
/**
* Obtain the {@link Zarafa.settings.ui.SettingsMainPanel SettingsMainPanel} object
*
* @return {Zarafa.settings.ui.SetingsMainPanel} The main panel which should
* be used within the {@link Zarafa.core.Context context}
*/
createContentPanel : function()
{
return {
xtype : 'zarafa.settingsmainpanel',
id: 'zarafa-mainpanel-contentpanel-settings',
title : this.getDisplayName(),
context: this
};
},
/**
* Adds a button to the top tab bar for the settings.
* @return {Object} The button for the top tabbar
* @private
*/
createSettingsMainTab: function()
{
return {
text: this.getDisplayName(),
tabOrderIndex: 1,
context: this.getName(),
id: 'mainmenu-button-settings'
};
},
/**
* Create the 3 default {@link Zarafa.settings.ui.SettingsCategory Settings Categories}
* to the {@link Zarafa.settings.SettingsContext}. This will create new
* {@link Zarafa.settings.ui.SettingsCategoryTab tabs} for the
* {@link Zarafa.settings.ui.SettingsGeneralCategory General},
* {@link Zarafa.settings.ui.SettingsPluginsCategory Plugins},
* {@link Zarafa.settings.ui.SettingsAdvancedCategory Advanced setings} and
* {@link Zarafa.settings.ui.SettingsCopyrightCategory Copyright notice}
* in the {@link Zarafa.settings.ui.SettingsCategoryWidgetPanel Widget Panel}.
* @return {Array} configuration object for the categories to register
* @private
*/
createSettingCategories: function()
{
var categories = [{
xtype : 'zarafa.settingsgeneralcategory',
settingsContext : this
}];
// disable plugin settings if sysadmin wants it
if (container.getServerConfig().isPluginsEnabled()) {
categories.push({
xtype : 'zarafa.settingspluginscategory',
settingsContext : this
});
}
// disable advanced settings if sysadmin wants it
if (container.getServerConfig().isAdvancedSettingsEnabled()) {
categories.push({
xtype : 'zarafa.settingsadvancedcategory',
settingsContext : this
});
}
categories = categories.concat([
{
xtype : 'zarafa.settingskeyshortcutcategory',
settingsContext : this
},{
xtype : 'zarafa.settingscopyrightcategory',
settingsContext : this
}]);
return categories;
},
/**
* Event handler which is fired just before the {@link Zarafa.core.Container container}
* {@link Zarafa.core.Container#beforecontextswitch switches the context}. This will
* check if there are any pending changes which the user might wish to apply or discard.
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder folder that is loaded for the new context
* @param {Zarafa.core.Context} oldContext context being switched out
* @param {Zarafa.core.Context} newContext new context being switched in
* @return {Boolean} False to prevent the context from being switched
* @private
*/
onBeforeContextSwitch : function(folder, oldContext, newContext)
{
if (this.getModel().hasChanges()) {
Ext.MessageBox.show({
title: _('Kopano WebApp'),
msg : _('Do you wish to apply the changes?'),
icon: Ext.MessageBox.QUESTION,
fn: this.applyChangesContext.createDelegate(this, [ folder, newContext ], 1),
buttons: Ext.MessageBox.YESNOCANCEL
});
// Always return false, we will manually switch context again
// in the event handler for the message box.
return false;
}
},
/**
* Event handler for {@link #onBeforeContextSwitch}. This will check if the user
* wishes to cancel the {@link #setView} action, or wishes to either
* {@link Zarafa.settings.SettingsContextModel#applyChanges apply} or
* {@link Zarafa.settings.SettingsContextModel#discardChanges discard}
* all changes.
* @param {String} btn The button which the user pressed
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder The folder to which to
* switch when the user is wishes to switch context.
* @param {Zarafa.core.Context} newContext The context to which to switch
* @private
*/
applyChangesContext : function(btn, folder, newContext)
{
// The user cancels the switch to a different category
if (btn === 'cancel') {
return;
}
// Check if the user wishes to save or discard all changes
var model = this.getModel();
if (btn === 'yes') {
model.applyChanges();
} else {
model.discardChanges();
}
/*
* if requiresReload config was true then don't directly switch the context
* register the afterrequiredreload event and then switch the context based on the
* button pressed by the user from required reload message box.
*/
if(model.getRealSettingsModel().requiresReload) {
this.on('afterrequiredreload', this.onAfterRequiredReload.createDelegate(this, [ folder, newContext ],1), this, {single : true});
} else {
container.switchContext(newContext, folder);
}
},
/**
* Function is used to switch the context if cancel button was pressed from
* required reload message box.
*
* @param {Zarafa.core.Context} currentContext The current context.
* @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder The folder to which to
* switch when the user is wishes to switch context.
* @param {Zarafa.core.Context} newContext The context to which to switch
* @param {String} button The button which the user pressed from required reload message box
* @private
*/
onAfterRequiredReload : function(currentContext, newContextFolder, newContext, button)
{
if(button === 'cancel') {
container.switchContext(newContext, newContextFolder);
}
}
});
Zarafa.onReady(function() {
container.registerContext(new Zarafa.core.ContextMetaData({
name : 'settings',
displayName : _('Settings'),
allowUserVisible : false,
pluginConstructor : Zarafa.settings.SettingsContext
}));
});