/*
* Copyright 2016 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.
*/
/**
* Content context for profile assignments.
*/
Ext.define('Ametys.plugins.cms.profiles.ContentRightAssignmentContext', {
extend: 'Ametys.plugins.coreui.profiles.AbstractRightAssignmentContext',
/**
* @property {String} DEFAULT_MODEL_ID The default id of the search model
* @readonly
*/
DEFAULT_MODEL_ID: "search-ui.right-assignment",
/**
* @cfg {String} [modelId] The id of the search model. If not provided, {@link #DEFAULT_MODEL_ID} will be used.
*/
/**
* @private
* @property {String} _modelId The id of the search model
*/
/**
* @private
* @property {Ext.container.Container} _container The component of this right assignment context
*/
/**
* @private
* @property {Ametys.form.ConfigurableFormPanel} _form The form of the search criteria
*/
/**
* @private
* @property {Ext.grid.Panel} _grid The result grid
*/
/**
* @private
* @property {Ext.data.Store} _gridStore The store of the grid
*/
/**
* @private
* @property {Boolean} _initialized true if the criteria and the result grid are initialized
*/
_initialized: false,
/**
* @private
* @property {String} _contentsRootContext The context holding the contents
*/
_contentsRootContext: null,
/**
* @cfg {String} [radio-option-all-label] The label to display in the option for assign on all contents
*/
/**
* @private
* @property {String} _radioOptionAllLabel The label to display in the option for assign on all contents
*/
/**
* @cfg {String} [hint-all-contents] The hint to display when the option 'radio-content-all' is selected
*/
/**
* @private
* @property {String} _hintAllContents The hint to display when the option 'radio-content-all' is selected
*/
/**
* @cfg {String} [result-grid-mask-message] The message of the mask in the result grid when the option 'radio-content-all' is selected
*/
/**
* @private
* @property {String} _resultGridMaskMessage The message of the mask in the result grid when the option 'radio-content-all' is selected
*/
constructor: function(config)
{
this.callParent(arguments);
this._modelId = config.modelId || this.DEFAULT_MODEL_ID;
this._radioOptionAllLabel = config['radio-option-all-label'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_RADIO_OPTION_ALL}}";
this._hintAllContents = config['hint-all-contents'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_HINT_ALL}}";
this._resultGridMaskMessage = config['result-grid-mask-message'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_MASK_MESSAGE}}";
this._contentsRootContext = config['root-context'];
},
getComponent: function()
{
var items = this._getRadioFields();
// Form containing the search criteria
this._form = this._createForm();
// The result grid
this._grid = this._createSearchGrid();
items.push({
xtype: 'container',
itemId: 'search-container',
flex: 1,
layout: {
type: "vbox",
align: "stretch"
},
items: [this._form, this._grid]
});
this._container = Ext.create('Ext.container.Container', {
layout: {
type: "vbox",
align: "stretch"
},
items: items,
listeners: {
destroy: Ext.bind(function(ct) {
this._initialized = false;
}, this)
}
});
return this._container;
},
/**
* @private
* Get the radio fields items
* @return The radio fields
*/
_getRadioFields: function()
{
return [{
xtype: 'radiofield',
boxLabel : this._radioOptionAllLabel,
name : 'radio-content',
itemId: 'radio-content-all',
checked: true,
inputValue: 'all',
style: {
marginLeft: '5px'
}
}, {
xtype: 'radiofield',
boxLabel : "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_RADIO_OPTION_SEARCH}}",
name : 'radio-content',
inputValue: 'search',
itemId: 'radio-content-search',
handler: this._onSelectSearch,
scope: this,
style: {
marginLeft: '5px'
}
}];
},
/**
* @private
* Create a form
* @return The form
*/
_createForm: function()
{
// Form containing the search criteria
return Ext.create('Ametys.form.ConfigurableFormPanel', {
defaultFieldConfig: {
labelWidth: 110
}
});
},
/**
* @private
* Create the search result grid
* @return The grid
*/
_createSearchGrid: function ()
{
// The store of the result grid
this._gridStore = Ext.create('Ext.data.Store', {
remoteSort: true,
autoLoad: false,
sortOnLoad: true,
listeners: {
'beforeload': {fn: this._onBeforeLoadGrid, scope: this},
'load': {fn: this._onLoadGrid, scope: this}
}
});
return Ext.create('Ext.grid.Panel', {
store: this._gridStore,
scrollable: true,
width: '100%',
flex: 1,
listeners: {
'selectionchange': Ext.bind(this._onSelectionChanged, this)
},
selModel : {
mode: 'MULTI'
},
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
border: true,
items: [{
itemId: 'search',
text: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH}}",
iconCls: 'ametysicon-magnifier12',
handler: this._search,
scope: this,
tooltip: {
title: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH}}",
text: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH_DESC}}",
glyphIcon: 'ametysicon-magnifier12',
inribbon: false
}
}]
}, {
dock: 'bottom',
xtype: 'pagingtoolbar',
store: this._gridStore,
displayInfo: true,
displayMsg: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_1}}{0}{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_2}}{1}{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_3}}{2}",
emptyMsg: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_NO_RESULT}}",
scrollable: true
}]
});
},
/**
* @private
* Handler when the search radio button is checked or unchecked
*/
_onSelectSearch: function (checkbox, checked)
{
if (checked)
{
// Enable search
this._switchToSearchMode();
}
else
{
// Disable search
this._switchToAllContentsMode();
}
},
initialize: function()
{
if (!this._initialized)
{
// Retrieve the search model
Ametys.data.ServerComm.callMethod({
role: "org.ametys.cms.search.model.SearchModelHelper",
methodName: "getSearchModelConfiguration",
parameters: [this._modelId, this._getContextualParameters()],
callback: {
handler: this._getSearchModelCb,
scope: this
},
errorMessage: {
msg: "{{i18n UITOOL_SEARCH_ERROR}}",
category: Ext.getClassName(this)
},
waitMessage: {
msg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE}}",
target: this._container
}
});
}
else
{
this._switchToAllContentsMode();
}
},
/**
* @private
* Switch to the "all contents" mode
*/
_switchToAllContentsMode: function()
{
this._container.down('#radio-content-all').setValue(true);
this._changeObjectContext(this._contentsRootContext, "<b>" + this._hintAllContents + "</b>", false, true);
// Disable search result grid
this._grid.getSelectionModel().deselectAll();
var searchContainer = this._container.down('#search-container');
searchContainer.mask(this._resultGridMaskMessage, 'ametys-mask-unloading');
},
/**
* @private
* Switch to search mode
*/
_switchToSearchMode: function ()
{
var searchContainer = this._container.down('#search-container');
searchContainer.unmask();
this._initSearchGrid(this._grid);
},
/**
* @private
* Initialize a search grid
* @param {Ext.grid.Panel} grid the grid
*/
_initSearchGrid: function(grid)
{
if (grid.getStore().getData().length > 0)
{
var firstRecord = grid.getStore().getData().getAt(0);
grid.getSelectionModel().select(firstRecord);
}
else
{
this._changeObjectContext(null, null, false, true);
}
},
/**
* @protected
* Get the contextual parameters used to get search model and search results.
* @return {Object} the contextual parameters
*/
_getContextualParameters: function()
{
return {
language: this._getCurrentLanguage()
};
},
/**
* @private
* Provides the current language to be used.
* @return {String} The current language
*/
_getCurrentLanguage: function()
{
return Ametys.cms.language.LanguageDAO.getCurrentLanguage();
},
/**
* @protected
* Get the default values to put in the search model
* @return {Object} The values
*/
_getDefaultSearchValues: function()
{
return {};
},
/**
* @private
* After retrieving the search model, configure the form and the result columns
* @param {Object} result The server result
*/
_getSearchModelCb: function(result)
{
// Configure the search form
this._form.configure(result['simple-criteria']);
this._form.setValues(this._getDefaultSearchValues());
// Reconfigure the result grid
var fields = Ametys.plugins.cms.search.SearchGridHelper.getFieldsFromJson(result.columns);
Ametys.plugins.cms.search.ContentSearchTool.addDefaultContentFields(fields);
var columns = Ametys.plugins.cms.search.SearchGridHelper.getColumnsFromJson(result.columns, false);
var sorters = Ametys.plugins.cms.search.SearchGridHelper.getSortersFromJson(columns, this._grid);
this._gridStore.setProxy({
type: 'ametys',
plugin: result.searchUrlPlugin,
url: result.searchUrl,
reader: {
type: 'json',
rootProperty: 'contents'
}
});
if (result.pageSize != null && result.pageSize > 0)
{
this._gridStore.setPageSize(result.pageSize);
}
// Update model
this._gridStore.model.replaceFields(fields, true);
this._grid.reconfigure(columns);
this._gridStore.setSorters(sorters); // Will fire a load event
this._switchToAllContentsMode();
this._initialized = true;
},
/**
* @private
* Function called before loading the grid store
* @param {Ext.data.Store} store The grid store
* @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
*/
_onBeforeLoadGrid: function(store, operation)
{
if (!this._initialized)
{
return false;
}
operation.setParams(Ext.apply(operation.getParams() || {}, {
values: Ext.clone(this._form.getJsonValues()),
excludeSubContents: false,
model: this._modelId,
contextualParameters: this._getContextualParameters()
}));
},
/**
* @private
* Function called when loading the grid store
* @param {Ext.data.Store} store The grid store
* @param {Ext.data.Model[]} records The loaded records
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
*/
_onLoadGrid: function(store, records, successful, operation)
{
if (successful && !operation.aborted && records.length > 0)
{
this._grid.getSelectionModel().select(records[0]);
this._grid.getView().focusRow(0);
}
},
/**
* @private
* Listener when the selection in the tree has changed
* @param {Ext.selection.Model} model The selection model
* @param {Ext.data.Model[]} selected The selected records
*/
_onSelectionChanged: function(model, selected)
{
if (selected.length > 0)
{
if (selected.length == 1)
{
var object = selected[0].get('id'),
title = selected[0].get('title');
this._changeObjectContext(object, "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_HINT_CONTENT}} <b>" + Ext.String.escapeHtml(title) + "</b>");
}
else
{
var objects = selected.map(function (item) {
return item.get('id');
})
this._changeObjectContext(objects, null);
}
}
else if (!this._container.down('#radio-content-all').getValue())
{
this._changeObjectContext(null, null, false, true);
}
},
/**
* @private
* Launches the search
* @param {Ext.button.Button} button The button
*/
_search: function(button)
{
if (!this._form.isValid())
{
return;
}
this._gridStore.loadPage(1);
}
});