/*
* Copyright 2015 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This UI helper provides a dialog to select one or more sites
* See {@link #open} method.
*
* Ametys.web.helper.ChooseSite.open({
* multiple: false,
* callback: Ext.bind(this._chooseSiteCb, this)
* });
*/
Ext.define('Ametys.web.helper.ChooseSite', {
singleton: true,
/**
* @property {Boolean} [multiple=false] True to allow multiple selections. Defaults to false.
*/
/**
* @property {String/String[]} values The name of the selected sites.
*/
/**
* @property {Function} _cbFn The call back function to call after choosing the sites
* @private
*/
/**
* @property _box {Ametys.window.DialogBox} The dialog box
* @private
*/
/**
* @property _tree {Ext.data.TreeStore} The sites tree panel
* @private
*/
/**
* @property {Boolean} _initialized Internal property reflecting the state of the dialogbox.
* @private
*/
/**
* Configure and open the dialog box
* @param {Object} config The configuration options :
* @param {String} [config.icon] The full path to icon (16x16 pixels) for the dialog box.
* @param {String} [config.iconCls] The CSS class for icon of the dialog box
* @param {String} [config.title] The title of the dialog box.
* @param {String} [config.helpMessage] The help message to display on top of dialog box.
* @param {String/String[]} [config.values] the selected site names
* @param {Boolean} [config.readAccessOnly=false] true to list sites on read access only. Defaults to false.
* @param {Boolean} [config.sharedSitesOnly=false] true to list sites with shared contents only. Defaults to false.
* @param {Boolean} [config.multiple=false] `true` to allow selecting multiple sites.
* @param {Function} config.callback The callback function invoked when sites are selected. The callback function will receive the following parameters:
* @param {String/String[]} config.callback.names The names of the selected sites. In simple mode, the value is a string, in multiple mode it is an array.
*/
open: function (config)
{
config = config || {};
this.multiple = config.multiple == true;
this.values = Ext.Array.from(config.values);
this.readAccessOnly = config.readAccessOnly == true; // false by default;
this.sharedSitesOnly = config.sharedSitesOnly == true; // false by default;
this._cbFn = config.callback || Ext.emptyFn;
this._initialized = false;
this._createDialogBox(config.icon, config.iconCls, config.title, config.helpMessage);
this._box.show();
},
/**
* Creates the dialog box if it is not already created
* @param {String} icon The full path to icon (16x16 pixels) for the dialog box
* @param {String} iconCls A css classname to set the icon of the dialog box
* @param {String} title The title of the dialog box.
* @param {String} helpMessage The help message to display on top of dialog box.
* @private
*/
_createDialogBox: function (icon, iconCls, title, helpMessage)
{
this._tree = Ext.create('Ametys.web.site.SitesTree', {
border: true,
flex: 1,
checkMode: this.multiple,
readAccessOnly: this.readAccessOnly,
sharedSitesOnly: this.sharedSitesOnly,
listeners : {
selectionchange: Ext.bind(this._onSelectSite, this),
load: {fn: this._onLoad, scope: this},
itemappend: {fn: this._onItemAppend, scope: this}
}
});
var defaultTitle = this.multiple ? "{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_MULTIPLE_SELECT_TITLE}}" : "{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_SIMPLE_SELECT_TITLE}}";
var defaultHelpMessage = this.multiple ? "{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_MULTIPLE_SELECT_DESCRIPTION}}" : "{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_SIMPLE_SELECT_DESCRIPTION}}";
this._box = Ext.create('Ametys.window.DialogBox', {
title: title || defaultTitle,
icon: icon,
iconCls: icon ? null : iconCls || 'ametysicon-world91',
width: 420,
height: 500,
scrollable: false,
bodyStyle: {
padding: 0
},
cls: 'ametys-dialogbox',
layout: {
type: 'vbox',
align : 'stretch',
pack : 'start'
},
items: [{
xtype: 'component',
cls: 'a-text',
html: helpMessage || defaultHelpMessage
},
this._tree
],
closeAction: 'destroy',
referenceHolder: true,
defaultButton: 'validate',
buttons : [{
reference: 'validate',
itemId: 'ok-btn',
disabled: true,
text :"{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_OKBUTTON}}",
handler : Ext.bind(this._validate, this)
}, {
text :"{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_CANCELBUTTON}}",
handler: Ext.bind(function() {this._box.close();}, this)
}
]
});
},
/**
* This method update the dialog box depending on the current selection
* @private
*/
_onSelectSite: function(sm, nodes)
{
var isValidSelection = this._isSelectionValid(nodes);
this._box.down("button[itemId='ok-btn']").setDisabled(!isValidSelection);
},
/**
* Select the site according to the input values
* @param {Ext.data.TreeStore} store The tree store
* @param {Ext.data.TreeModel[]} records The records
* @param {Boolean} successful True if the operation was successful
* @private
*/
_onLoad: function(store, records, successful)
{
if (!this._initialized)
{
this._selectValues();
this._initialized = true;
}
},
/**
* @private
* Select the site according to the 'values' property during the initialization
*/
_selectValues: function()
{
if (this.values.length > 0)
{
Ametys.data.ServerComm.callMethod({
role: 'org.ametys.web.repository.site.SiteDAO',
methodName: 'getSitesInfos',
parameters: [this.values],
callback: {
scope: this,
handler: this._getSitesInfosCb
},
errorMessage: {
category: this.self.getName(),
msg: "{{i18n PLUGINS_WEB_HELPER_CHOOSESITE_ERROR}}"
}
});
}
if (this.values.length == 0 || this.multiple)
{
var rootNode = this._tree.getRootNode();
this._tree.getSelectionModel().select(this._tree.getRootNode());
this._tree.getView().focusNode(rootNode);
}
},
/**
* @private
* Callback after retrieving sites' properties. Select site in tree.
* @param {Object} response The server response
*/
_getSitesInfosCb: function(response)
{
Ext.Array.forEach(response.sites, function(site) {
this._tree.expandNodeByPath(site.path, function(successful, node) {
if (successful)
{
if (this.multiple)
{
node.set('checked', true);
}
else
{
this._tree.getSelectionModel().select(node);
this._tree.getView().focusNode(node);
}
}
}, this);
}, this);
},
/**
* Check if selection is valid according to the configuration parameters
* @param {Ext.data.TreeModel[]} nodes The selected nodes.
* @return {boolean} true if the selection is valid
* @private
*/
_isSelectionValid : function(nodes)
{
if (nodes.length == 0)
{
return false;
}
for (var i=0; i < nodes.length; i++)
{
if (nodes[i].isRoot())
{
return false;
}
}
return true;
},
/**
* @private
* Listener to the itemappend event of the tree.
* Initialize the checkable status of each node
*/
_onItemAppend: function(parenNode, node, index)
{
if (this.multiple && node && !node.isRoot())
{
node.set('checked', false); // add an empty checkbox
}
},
/**
* Retrieve the current tree values, and call the callback function from the initial configuration sent to #open
* @private
*/
_validate: function ()
{
var selection = this.multiple === false ? this._tree.getSelectionModel().getSelection() : this._tree.getChecked(),
names;
names = Ext.Array.map(selection, function(record) {
return record.get('name');
});
this._box.close();
if (this._cbFn)
{
if (this.multiple)
{
this._cbFn.call(this, names);
}
else
{
this._cbFn.call(this, names[0]);
}
}
}
});