/*
* Copyright 2010 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.
*/
/**
* JCR tree panel.
* @private
*/
Ext.define('Ametys.repository.tree.JcrTreePanel',
{
extend: 'Ext.tree.Panel',
animate: true,
constructor: function (config) {
Ext.applyIf (config, {
defaultWorkspaceName: 'default',
store: this._getStore(),
viewConfig: {
toggleOnDblClick: false
}
});
config.dockedItems = this._getDockedItems();
this.callParent(arguments);
},
/**
* @protected
* Create the tree store
* @return {Ext.data.TreeStore} the store
*/
_getStore: function ()
{
return Ametys.repository.RepositoryDao.getNodeStore();
},
/**
* @protected
* Get the docked items
* @return {Object} the docked items configuration object
*/
_getDockedItems: function ()
{
return [{
dock: 'top',
xtype: 'toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
defaultType: 'button',
items: [
// Workspace selection
Ext.apply(this._getWorkspacesComboBoxConfig(), {flex: 1}),
{
xtype: 'tbspacer',
flex: 0.0001
},
{
// Refresh node
tooltip: "{{i18n PLUGINS_REPOSITORYAPP_REFRESH_NODE_BTN}}",
handler: Ext.bind (this.refreshNode, this, [], false),
iconCls: 'a-btn-glyph ametysicon-arrow123 size-16',
cls: 'a-btn-light'
}
]
}]
},
/**
* @private
* Get configuration for workspaces combo box
* @return {Object} the configuration object
*/
_getWorkspacesComboBoxConfig: function ()
{
return {
xtype: 'combobox',
itemId: 'workspaces-combo',
cls: 'ametys',
maxWidth: 400,
forceSelection: true,
editable: false,
triggerAction: 'all',
queryMode: 'local',
fieldLabel: "{{i18n PLUGINS_REPOSITORYAPP_WORKSPACE_NAME}}",
store: {
fields: ['name'],
data: []
},
name: 'workspaceName',
valueField: 'name',
displayField: 'name',
style: {
marginRight: '0px'
},
listeners: {
render: {fn: this._onWorkspaceComboRender, scope: this},
select: {fn: this._onWorkspaceChange, scope: this}
}
}
},
/**
* Load workspaces when the corresponding combobox is rendered.
* @param {Ext.Component} combo the workspace combobox.
* @param {Object} eOpts Options added to the addListener
* @private
*/
_onWorkspaceComboRender: function(combo, eOpts)
{
// Get the workspaces from the server, in order to fill the workspace combobox.
Ametys.data.ServerComm.callMethod({
role: 'org.ametys.workspaces.repository.jcr.RepositoryDao',
methodName: 'getWorkspaces',
callback: {
handler: this._loadWorkspacesCb,
scope: this
},
priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
errorMessage: "{{i18n PLUGINS_REPOSITORYAPP_WORKSPACE_NAME}}"
});
},
/**
* Get the name of current workspace
* @return {String} the current workspace's name
*/
getCurrentWorkspaceName: function ()
{
var workspaceCombo = this.down("combobox[itemId='workspaces-combo']");
return workspaceCombo.getValue();
},
/**
* This function reload the given node
* @param {String} [id] The id of the node to reload. If null the tree current selection will be used.
*/
refreshNode: function (id)
{
var node;
if (id == null)
{
var selection = this.getSelectionModel().getSelection();
node = selection.length > 0 ? selection[0] : null;
// Workaround - Refresh selection in case node is not existing anymore
this.getSelectionModel().deselect(node, true);
this.getSelectionModel().select(node);
}
else
{
node = this.getStore().getNodeById(id);
}
if (node != null)
{
// Set leaf to false, to allow children to be added during the load. Leaf will be set to true again if needed after the load.
node.set('leaf', false);
var me = this;
this.getStore().load({
node: node,
callback: function(records, operation, success) {
if (success)
{
this.getSelectionModel().select([node]);
// FIXME In case the node is not already expanded, we have to force it or the expand sprite will disappear.
node.expand();
}
},
scope: this
});
}
},
/**
* Callback effectively filling the workspace combobox.
* @param {String[]} workspaces The workspaces names
* @param {Array} args The callback arguments.
* @private
*/
_loadWorkspacesCb: function(workspaces, args)
{
var workspaceCombo = this.down("combobox[itemId='workspaces-combo']");
var store = workspaceCombo.getStore();
var wspData = [];
for (var i = 0; i < workspaces.length; i++)
{
wspData.push({
name: workspaces[i]
});
}
store.loadData(wspData, false);
// Initialize with default value
workspaceCombo.setValue(this.defaultWorkspaceName);
Ametys.repository.RepositoryApp.setCurrentWorkspace(this.defaultWorkspaceName);
},
/**
* Listens for workspace change.
* @param {Ext.form.field.ComboBox} combo The workspace combobox.
* @param {Ext.data.Model} record The selected record.
* @param {Object} eOpts Options added to the addListener
* @private
*/
_onWorkspaceChange: function(combo, record, eOpts)
{
// Single selection.
var selectedWorkspace = record.get('name');
// The workspace wasn't changed: do nothing.
if (Ametys.repository.RepositoryApp.getCurrentWorkspace() == selectedWorkspace)
{
return;
}
Ametys.repository.RepositoryApp.setCurrentWorkspace(selectedWorkspace);
// Reload and keep the selection.
this.reload(true);
},
/**
* Get a node in the store by its path.
* @param {String} path The node path (without groups).
* @return {Ametys.repository.data.RepositoryNode} The node if found, `null` otherwise.
*/
getNodeByPath: function(path)
{
var nodes = this.getStore().query('path', path, false, false, true);
if (nodes.length > 0)
{
return nodes.getAt(0);
}
return null;
},
/**
* Select a node in the tree from its JCR path (without node groups).
* @param {String} path The full repository node path, with or without leading slash.
*/
selectNodeByJcrPath: function(path)
{
var nodes = this.getSelectionModel().getSelection();
if (nodes.length > 0 && nodes[0].get('path') == path)
{
// The node is already selected: return.
return;
}
var nodeColl = this.getStore().query('path', path, false, false, true);
if (nodeColl.length > 0)
{
// The node model is cached in the store: select it.
this.getSelectionModel().select(nodeColl.getAt(0));
return;
}
// If not, query the tree path from the server.
var relPath = path.charAt(0) == '/' ? path.substring(1) : path;
Ametys.data.ServerComm.callMethod({
role: 'org.ametys.workspaces.repository.jcr.RepositoryDao',
methodName: 'getNodeByPath',
parameters: [relPath, Ametys.repository.RepositoryApp.getCurrentWorkspace()],
callback: {
handler: this._selectNodeByJcrPathCb,
scope: this
}
});
},
/**
* Callback for selectNodeByJcrPath.
* @param {XMLElement} result The XML document.
* @param {Array} args The callback arguments.
* @private
*/
_selectNodeByJcrPathCb: function(result, args)
{
if (result != null)
{
this.selectNodeByPath(result.pathWithGroups);
}
},
/**
* Select a node in the tree. The full tree path (with node groups) is required.
* @param {String} path the full tree node path, with groups if applicable.
*/
selectNodeByPath: function(path)
{
var rootText = this.getRootNode().get('text');
var fullPath = '/' + rootText + path;
this.selectPath(fullPath, 'text');
},
/**
* Reload the whole tree and optionally re-select the same node after loading.
* @param {Boolean} [keepSelection=false] true to re-select the same node after loading.
*/
reload: function(keepSelection)
{
var selections = this.getSelectionModel().getSelection();
this.getStore().load({
callback: function(records, operation, success) {
if (success && keepSelection && selections != null && selections.length > 0)
{
this.selectNodeByPath(selections[0].get('path'));
}
},
scope: this
});
},
/**
* Reload a given node and optionally select it after loading.
* @param {Ext.data.TreeModel} node The node to reload.
* @param {Boolean} [select=true] true to select the node after loading it, false otherwise.
*/
reloadAndSelect: function(node, select)
{
this.getStore().load({
node: node,
callback: function(records, operation, success) {
if (success)
{
// FIXME In case the node is not already expanded, we have to force it or the expand sprite will disappear.
node.expand();
if (select)
{
this.getSelectionModel().select([node]);
}
}
},
scope: this
});
}
});