/*
* Copyright 2013 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 tool displays the elements of a cart
* @private
*/
Ext.define('Ametys.plugins.cart.tool.CartTool', {
extend: "Ametys.tool.Tool",
statics: {
/**
* @property {Number} PAGE_SIZE
* @readonly
* @static
* The number of records to display by 'page'
*/
PAGE_SIZE: 10,
renderURL: function(value, metaData, record)
{
return value ? `<a href="${value}">${value}</a>` : '';
}
},
/**
* @property {Ext.grid.Panel} grid The grid panel displaying the carts
* @private
*/
/**
* @property {String} _cartId The id of the cart
* @private
*/
/**
* @property {Ext.data.Store} store The store for cart's elements
* @private
*/
constructor: function(config)
{
this.callParent(arguments);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onDeleted, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onCartModified, this);
},
setParams: function(params)
{
this.callParent(arguments);
this._cartId = params['id'];
this.refresh();
// Register the tool on the history tool
var toolId = this.getFactory().getId();
var toolParams = this.getParams();
Ametys.navhistory.HistoryDAO.addEntry({
id: this.getId(),
label: this.getTitle(),
description: this.getDescription(),
iconSmall: this.getSmallIcon(),
iconMedium: this.getMediumIcon(),
iconLarge: this.getLargeIcon(),
type: Ametys.navhistory.HistoryDAO.TOOL_TYPE,
action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, [toolId, toolParams], false)
});
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
/**
* Create the carts grid. Grouped by type.
*/
createPanel: function()
{
this.store = this.createStore();
this.grid = Ext.create("Ext.grid.Panel", {
store: this.store,
stateful: true,
stateId: this.self.getName() + "$grid",
scrollable: true,
columns: [
{stateId: 'grid-column-title', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_TITLE}}", flex: 1, sortable: true, dataIndex: 'title', renderer: Ametys.grid.GridColumnHelper.renderTextWithIcon},
{stateId: 'grid-column-description', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_DESCRIPTION}}", flex: 1, sortable: true, hidden: true, dataIndex: 'description'},
{stateId: 'grid-column-creator', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_CREATOR}}", hidden: false, width: 140, sortable: true, dataIndex: 'creator', renderer: Ametys.grid.GridColumnHelper.renderUser},
{stateId: 'grid-column-creation', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_CREATION}}", hidden: false, width: 140, sortable: true, dataIndex: 'creation', renderer: Ametys.grid.GridColumnHelper.renderDateTime},
{stateId: 'grid-column-contributor', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_LASTCONTRIBUTOR}}", hidden: false, width: 140, sortable: true, dataIndex: 'lastContributor', renderer: Ametys.grid.GridColumnHelper.renderUser},
{stateId: 'grid-column-lastmodified', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_LASTMODIFICATION}}", hidden: false, width: 140, sortable: true, dataIndex: 'lastModification', renderer: Ametys.grid.GridColumnHelper.renderDateTime},
{stateId: 'grid-column-workflow', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_WORKFLOWSTEP}}", hidden: false, width: 120, sortable: true, dataIndex: 'workflowStep', renderer: Ametys.plugins.cms.search.SearchGridHelper.renderWorkflowStep},
{stateId: 'grid-column-queryType', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_QUERY_TYPE}}", width: 120, sortable: true, dataIndex: 'queryType', renderer: Ametys.plugins.queriesdirectory.tree.QueriesTree.renderType},
{stateId: 'grid-column-documentation', header: "{{i18n PLUGINS_CART_UITOOL_CART_COLUMN_DOCUMENTATION}}", width: 120, sortable: true, dataIndex: 'documentation', renderer: Ametys.plugins.cart.tool.CartTool.renderURL},
],
selModel : {
mode: 'MULTI'
},
features: [{
ftype:'grouping',
groupHeaderTpl: '{name} ({rows.length})',
enableGroupingMenu: false
}],
viewConfig: {
plugins: [{
ptype: 'ametysgridviewdragdrop',
dragTextField: 'title',
setAmetysDragInfos: Ext.bind(this.getDragInfo, this),
setAmetysDropZoneInfos: Ext.bind(this.getDropInfo, this)
}]
},
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
items: ['->', {
xtype: 'tbtext',
text: '',
tpl: Ext.create('Ext.XTemplate',
"<tpl if='nb == 0'>",
"{{i18n PLUGINS_CART_UITOOL_CART_TPL_NO_ELEMENT}}",
"</tpl>",
"<tpl if='nb == 1'>",
"{{i18n PLUGINS_CART_UITOOL_CART_TPL_ONE_ELEMENT}}",
"</tpl>",
"<tpl if='nb != 1 && nb != 0'>",
"{{i18n PLUGINS_CART_UITOOL_CART_TPL_NB_ELEMENTS_1}} {nb} {{i18n PLUGINS_CART_UITOOL_CART_TPL_NB_ELEMENTS_2}}",
"</tpl>"
)
}]
}
],
listeners: {
'selectionchange': Ext.bind(this.sendCurrentSelection, this)
}
});
this.grid.on('itemdblclick', Ext.bind(this._openCartElement, this));
return this.grid;
},
/**
* @private
* This event is thrown by the getDragData to add the 'source' of the drag.
* @param {Object} item The default drag data that will be transmitted. You have to add a 'source' item in it:
* @param {Object} item.source The source (in the relation way) of the drag operation. A Ametys.relation.RelationPoint config.
*/
getDragInfo: function(item)
{
var targets = this._getSelectedTargets();
if (targets && targets.length > 0)
{
item.source = {
relationTypes: [Ametys.relation.Relation.REFERENCE],
targets: targets
};
}
},
/**
* @private
* This event is thrown before the beforeDrop event and create the target of the drop operation relation.
* @param {Ext.data.Model[]} targetRecords The target records of the drop operation.
* @param {Object} item The default drag data that will be transmitted. You have to add a 'target' item in it:
* @param {Object} item.target The target (in the relation way) of the drop operation. A Ametys.relation.RelationPoint config.
*/
getDropInfo: function(targetRecords, item)
{
var targets = this._getTargets(targetRecords);
if (targets.length > 0)
{
item.target = {
relationTypes: [Ametys.relation.Relation.REFERENCE],
targets: targets
};
}
else
{
item.target = {
relationTypes: [Ametys.relation.Relation.REFERENCE],
targets: {
id: 'cart',
parameters: {
id: this._cartId
}
}
};
}
},
/**
* Returns the CartElement store
* @return {Ext.data.Store} The cart element store
*/
createStore: function()
{
return Ext.create('Ext.data.Store', {
model: 'Ametys.plugins.cart.tool.CartTool.CartElementEntry',
sorters: [{property: 'title', direction:'ASC'}],
proxy: {
type: 'ametys',
plugin: 'cart',
url: 'cart/elements.json',
reader: {
type: 'json',
rootProperty: 'cartElements',
totalProperty: 'total'
}
},
autoLoad: false,
pageSize: this.self.PAGE_SIZE,
groupField: 'group',
listeners: {
'beforeload': {fn: this._onBeforeLoad, scope: this},
'load': {fn: this._onLoad, scope: this}
}
});
},
/**
* Function before loading the store.
* @param {Ext.data.Store} store The store
* @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
* @private
*/
_onBeforeLoad: function (store, operation)
{
operation.setParams(operation.getParams() || {});
//Adding the cartId as a HTTP parameter for the store's proxy
operation.setParams({
cartId: this._cartId
});
},
/**
* Function called after loading the store.
* @param {Ext.data.Store} store The store
* @param {Ext.data.Model[]} records The loaded records
* @param {boolean} success Is the load a success
* @private
*/
_onLoad: function (store, records, success)
{
if (success)
{
var tbtext = this.grid.getDockedItems('toolbar[dock="bottom"]')[0].down('tbtext');
tbtext.update({nb: records.length});
}
},
/**
* @private
* Convert records to targets
* @param {Ext.data.Model[]} records The record to convert
* @return {Object[]} An array of Ametys.message.MessageTarget configurations.
*/
_getTargets: function(records)
{
var elmtTargets = [];
Ext.each (records, function (record) {
var type = record.get('type');
if (type === 'content')
{
elmtTargets.push({
id: type,
parameters: {
ids: [record.get('elmtId')]
}
});
}
else if (type === 'resource')
{
elmtTargets.push({
id: type,
parameters: {
ids: [record.get('elmtId')]
}
});
}
});
return elmtTargets;
},
/**
* @private
* Get the current selected elements as message target configuration
* @return {Object[]} An array of Ametys.message.MessageTarget configurations.
*/
_getSelectedTargets: function()
{
return this._getTargets(this.grid.getSelectionModel().getSelection());
},
sendCurrentSelection: function()
{
var subtargets = this._getSubtargetsByType();
/*Ext.each (this.grid.getSelectionModel().getSelection(), function (record) {
elmtTargets.push({
type: 'cartElement',
parameters: {
id: record.get('elmtId'),
cartElementType: record.get('type')
}
});
});*/
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: {
id: Ametys.message.MessageTarget.CART,
parameters: {
id: this._cartId
},
subtargets: subtargets
}
});
},
/**
* @private
* Get the subtargets configuration to create a message bus, based upon current grid selection
* @return {Object} The configuration to create a subtarget bus message. With 'type' and 'parameters' properties.
*/
_getSubtargetsByType: function ()
{
var types = {};
Ext.each (this.grid.getSelectionModel().getSelection(), function (record) {
var type = record.get('type');
if (!types[type])
{
types[type] = [];
}
types[type].push(record.get('elmtId'));
});
var subtargets = [];
for (var type in types)
{
if (type == 'cartQuery' || type == 'cartQueryFromDirectory')
{
var queries = types[type];
for (var i=0; i < queries.length; i++)
{
subtargets.push({
id: type,
parameters: {
id: queries[i]
}
});
}
}
else
{
subtargets.push({
id: type,
parameters: {
ids: types[type]
}
});
}
}
return subtargets;
},
/**
* Reload the store on refresh
*/
refresh: function()
{
this.callParent(arguments);
this.grid.store.load({callback: Ext.bind(this._updateInfos, this)});
},
/**
* Update tool information
* @private
*/
_updateInfos: function (records, operation, success)
{
var result = Ext.JSON.decode(Ext.dom.Query.selectValue("", operation.getResponse()));
if (result['unknown-cart'])
{
var details = '';
var params = this.getParams();
for (var name in params)
{
details += name + " : " + params[name] + '\n';
}
Ametys.log.ErrorDialog.display({
title: "{{i18n PLUGINS_CART_UITOOL_CART_NOT_FOUND}}",
text: "{{i18n PLUGINS_CART_UITOOL_CART_NOT_FOUND_ERROR}}",
details: details,
category: this.self.getName()
});
this.close();
return;
}
this.setTitle(result.label);
this.setDescription(result.description);
this.showUpToDate();
// Save in navigation history
var toolId = this.getFactory().getId();
var toolParams = this.getParams();
Ametys.navhistory.HistoryDAO.addEntry({
id: this.getId(),
objectId: this._cartId,
label: this.getTitle(),
description: this.getDescription(),
iconSmall: this.getSmallIcon(),
iconMedium: this.getMediumIcon(),
iconLarge: this.getLargeIcon(),
type: Ametys.navhistory.HistoryDAO.TOOL_TYPE,
action: function () {Ametys.tool.ToolsManager.openTool(toolId, toolParams)}
});
},
/**
* Manage CartElement doubleclick
* @param {Ext.view.View} view The view
* @param {Ext.data.Model} record The record that belongs to the item
* @param {HTMLElement} item The item's element
* @param {Number} index The item's index
*/
_openCartElement: function(view, record, item, index)
{
var type = record.get('type');
if (type === 'resource')
{
// Download resource file
Ametys.explorer.resources.actions.File.download(record.get('elmtId'));
}
else if (type === 'content')
{
// Open content tool
Ametys.tool.ToolsManager.openTool('uitool-content', {'id': record.get('elmtId')});
}
else if (type === 'cartQuery' || type === 'cartQueryFromDirectory')
{
// Open search tool
var query = Ext.JSON.decode(record.get('queryContent'));
var toolId = query.toolId;
var toolParams = query.toolParams || {};
toolParams.solrSearchToolId = record.get('elmtId');
toolParams.scriptToolId = record.get('elmtId');
if (type === 'cartQueryFromDirectory')
{
toolParams.queryId = record.get('elmtId');
}
Ametys.tool.ToolsManager.openTool(toolId, toolParams);
}
},
/**
* Listener when cart has been modified.
* Will set the tool in "out of date" mode.
* @param {Ametys.message.Message} message The modified message.
* @private
*/
_onCartModified: function(message)
{
var me = this;
var targets = message.getTargets(function (target) {return 'cart' == target.getId() && target.getParameters().id === me._cartId;});
if (targets && targets.length > 0)
{
this.showOutOfDate();
return;
}
var elementTargets = message.getTargets(function (target) {
return me._isSupportedTarget(target);
});
if (elementTargets.length > 0)
{
for (var i=0; i < elementTargets.length; i++)
{
var elementId = elementTargets[i].getParameters().id;
if (this.store.findExact('elmtId', elementId) != -1)
{
this.showOutOfDate();
return;
}
}
}
},
/**
* Listener when cart or cart'elements has been deleted.
* Will close the tool or remove the records if present
* @param {Ametys.message.Message} message The deletion message.
* @private
*/
_onDeleted: function(message)
{
var me = this;
var targets = message.getTargets(function (target) {return 'cart' == target.getId() && target.getParameters().id === me._cartId;});
if (targets && targets.length > 0)
{
this.close();
return;
}
targets = message.getTargets(function (target) {
return ('cartElement' == target.getId() && target.getParameters().cartId === me._cartId) || me._isSupportedTarget(target);
});
if (targets && targets.length > 0)
{
var records = [];
for (var i=0; i < targets.length; i++)
{
var record = this.store.findExact('elmtId', targets[i].getParameters().id);
if (record != null)
{
records.push(record);
}
}
if (records.length > 0)
{
this.store.remove(records);
var tbtext = this.grid.getDockedItems('toolbar[dock="bottom"]')[0].down('tbtext');
tbtext.update({nb: this.store.getCount()});
}
}
},
/**
* True if the target is supported
* @param {Object} target The target.
* @private
*/
_isSupportedTarget(target)
{
return 'content' == target.getId()
|| 'resource' == target.getId()
|| 'query' == target.getId();
}
});