/*
* 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.
*/
/**
* @private
* This tool displays the list of users
*/
Ext.define('Ametys.plugins.coreui.profiles.ProfilesTool', {
extend: 'Ametys.tool.Tool',
/**
* @private
* @property {Ext.grid.Panel} _profilesGrid the profiles' grid panel
*/
/**
* @private
* @property {Ext.panel.Panel} _rightsPanel the rights' panel
*/
/**
* @private
* @property {Object} _rightsByCategory the right records sorted by category name
*/
/**
* @private
* @property {Ametys.plugins.coreui.profiles.ProfilesTool.Profile[]} _currentProfiles the current selected profiles
*/
/**
* @private
* @property {String[]} _rights the list of rights before the tool gets dirty
*/
statics: {
/**
* Save the rights for the selected profile
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
save: function(controller)
{
var profileTool = Ametys.tool.ToolsManager.getFocusedTool();
profileTool.saveCurrentChanges();
},
/**
* Discard the pending changes on the selected profile
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
discardChanges: function(controller)
{
var profileTool = Ametys.tool.ToolsManager.getFocusedTool();
profileTool._updateCardPanels(profileTool._rights);
profileTool.setDirty(false);
profileTool.sendCurrentSelection();
},
/**
* Switch mode
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
switchMode: function (controller)
{
var profileTool = Ametys.tool.ToolsManager.getFocusedTool();
profileTool.switchMode (controller.isPressed() ? 'view': 'edit');
},
/**
* Select all rights
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
selectAll: function (controller)
{
var profileTool = Ametys.tool.ToolsManager.getFocusedTool();
profileTool.selectAll();
},
/**
* Unselect all rights
* @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
*/
unselectAll: function (controller)
{
var profileTool = Ametys.tool.ToolsManager.getFocusedTool();
profileTool.unselectAll();
}
},
constructor: function(config)
{
this.callParent(arguments);
// Listening to some bus messages.
Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onMessageCreated, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageEdited, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
setParams: function (params)
{
this.callParent(arguments);
this._initialSelectedProfiles = params.selectedProfiles || [];
this._currentProfiles = [];
this.showOutOfDate();
},
refresh: function()
{
this._profileStore.load();
this._rightsStore.load();
this.showUpToDate();
},
/**
* @private
* Get the features for the grid
* @return {Object[]} The features or null
*/
_getGridFeatures: function()
{
return [];
},
createPanel: function()
{
this._profileStore = this._createProfileStore();
this._rightsStore = this._createRightsStore();
this._profilesGrid = Ext.create('Ext.grid.Panel', {
scrollable: true,
selModel : {
mode: 'MULTI'
},
stateful: true,
stateId: this.self.getName() + "$grid",
style: {
borderRightStyle: 'solid',
borderRightWidth: '1px'
},
minWidth: 100,
maxWidth: 400,
flex: 0.3,
store: this._profileStore,
columns: [
{flex: 1, header: "{{i18n PLUGINS_CORE_UI_TOOL_PROFILES_LABEL}}", dataIndex: 'label', hideable: false},
{width: 100, hidden: true, header: "{{i18n PLUGINS_CORE_UI_TOOL_PROFILES_IDENTIFIER}}", dataIndex: 'id'}
],
features: this._getGridFeatures(),
listeners: {
beforeselect: {fn: this._onBeforeSelectProfile, scope: this},
selectionchange: {fn: this._onSelectProfile, scope: this}
}
});
this._rightsPanel = Ext.create('Ext.container.Container', {
ui: 'panel',
flex: 1,
minWidth: 350,
border: '0 0 0 1',
split: true,
layout: 'card',
activeItem: 0,
items: [
{
xtype: 'component',
cls: 'a-panel-text-empty',
itemId: 'no-selection',
scrollable: true,
border: false,
html: "{{i18n PLUGINS_CORE_UI_PROFILES_UNSELECTED}}"
},
{
xtype: 'panel',
ui: 'panel',
cls: 'profile-view',
itemId: 'card-view',
scrollable: true,
border: false,
items: [{
xtype: 'component',
cls: 'a-panel-text-empty',
itemId: 'empty-selection',
html: "{{i18n PLUGINS_CORE_UI_PROFILES_EMPTY}}"
},
{
xtype: 'component',
itemId: 'view-empty-filtering',
hidden: true,
html: "{{i18n PLUGINS_CORE_UI_PROFILES_EMPTYFILTER}}"
}],
dockedItems: this._getDockedItems("view")
},
{
xtype: 'panel',
ui: 'panel',
itemId: 'card-edit',
scrollable: true,
border: false,
items: [{
xtype: 'component',
itemId: 'edit-empty-filtering',
hidden: true,
html: "{{i18n PLUGINS_CORE_UI_PROFILES_EMPTYFILTER}}"
}],
dockedItems: this._getDockedItems("edit")
},
{
xtype: 'component',
cls: 'a-panel-text-empty',
itemId: 'too-many-selection',
scrollable: true,
border: false,
html: "{{i18n PLUGINS_CORE_UI_PROFILES_TOO_MANY_SELECTED}}"
},
]
});
return Ext.create('Ext.container.Container', {
layout: {
type: 'hbox',
pack: 'start',
align: 'stretch'
},
cls: ["uitool-profiles"],
scrollable: 'horizontal',
items: [this._profilesGrid, this._rightsPanel]
});
},
/**
* @private
* Get the toolbar as docked items
* @param {String} mode The mode: 'view' or 'edit'
*/
_getDockedItems: function(mode)
{
var toolBarItems = [{
xtype: 'textfield',
itemId: mode + '-search-filter-input',
flex: 1,
maxWidth: 300,
emptyText: "{{i18n PLUGINS_CORE_UI_PROFILES_FILTER_EMPTYTEXT}}",
enableKeyEvents: true,
msgTarget: 'qtip',
listeners: {change: Ext.Function.createBuffered(this._filter, 300, this)}
}, {
// Clear filter
itemId: mode + '-erase-filter-input',
tooltip: "{{i18n PLUGINS_CORE_UI_PROFILES_FILTER_CLEAR}}",
handler: Ext.bind (this._clearFilter, this),
iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
cls: 'a-btn-light'
}];
if (mode == "edit")
{
toolBarItems.push(' ', {
tooltip: "{{i18n PLUGINS_CORE_UI_PROFILES_FILTERUNCHECKED}}",
iconCls: 'a-btn-glyph ametysicon-code-html-input-checkbox-off size-16 decorator-ametysicon-body-part-eye',
itemId: 'search-filter-unchecked',
cls: 'a-btn-light',
enableToggle: true,
listeners: {toggle: Ext.Function.createBuffered(this._filter, 300, this)}
});
}
return [{
xtype: 'toolbar',
itemId: mode + '-search-filter-bar',
dock: 'top',
layout: {
type: 'hbox',
align: 'stretch'
},
border: false,
defaults : {
cls: 'ametys',
labelWidth: 55,
labelSeparator: ''
},
items: toolBarItems
}]
},
/**
* @private
* Filters rights by input fields values.
*/
_filter: function ()
{
function comparableValue(v)
{
return Ext.String.deemphasize(v.trim().toLowerCase())
}
Ext.suspendLayouts();
var mode = this.getMode();
var cardPanelName = mode == 'edit' ? 'card-edit' : 'card-view';
let searchFilterBar = mode + '-search-filter-bar';
let textField = this._rightsPanel.getComponent(cardPanelName).dockedItems.getByKey(searchFilterBar).getComponent(mode + '-search-filter-input');
let seeUncheckedField = this._rightsPanel.getComponent(cardPanelName).dockedItems.getByKey(searchFilterBar).getComponent('search-filter-unchecked');
try
{
let filterValue = comparableValue(textField.getValue());
var oneVisible = false;
var cardPanel = this._rightsPanel.getComponent(cardPanelName);
// Loop on all rights per categories
Ext.Object.each(this._rightsByCategory, function(categoryId) {
cardPanel.getComponent(categoryId).setVisible(false);
var rights = this._rightsByCategory[categoryId];
var categoryEditPanel = cardPanel.getComponent(categoryId);
var allCategoryMatch = comparableValue(categoryEditPanel.title).includes(filterValue);
Ext.Array.each(rights, function (right)
{
var rightId = right.get('id');
var profileRights = this._currentProfiles[0].get("rights") || [];
var hasRight = Ext.Array.contains(profileRights, rightId);
// Update edition screen without triggering a change event
var editRightContainer = categoryEditPanel.getComponent(rightId + '-' + mode);
var isVisible = (allCategoryMatch
|| comparableValue(rightId).includes(filterValue)
|| comparableValue(editRightContainer.boxLabel).includes(filterValue)
|| comparableValue(editRightContainer.ametysDescription).includes(filterValue))
&& (mode == 'edit' && (!seeUncheckedField.pressed || !editRightContainer.checked)
|| (mode == 'view' && hasRight));
editRightContainer.setVisible(isVisible);
oneVisible = oneVisible || isVisible;
// Update categories
if (isVisible)
{
cardPanel.getComponent(categoryId).setVisible(true);
}
}, this);
}, this);
cardPanel.getComponent(mode + '-empty-filtering').setVisible(filterValue != '' && !oneVisible);
}
finally
{
Ext.resumeLayouts(true);
}
},
/**
* Clear the current filter
* @param {Ext.Button} button The button
*/
_clearFilter: function(button)
{
button.prev().reset();
},
sendCurrentSelection: function()
{
var targets = [];
var gridSelection = this._profilesGrid.getSelection();
if (gridSelection.length)
{
var subtargets = [];
if (this.getMode() == 'edit')
{
subtargets.push({
id: Ametys.message.MessageTarget.FORM,
parameters: {
isDirty: this.isDirty()
}
});
}
for (const profileRecord of gridSelection)
{
targets.push ({
id: Ametys.message.MessageTarget.PROFILE,
parameters: {
id: profileRecord.getId(),
name: profileRecord.get('label'),
context: profileRecord.get('context'),
modifiable: this.config.canEditAnyContext === "true" // Admin
|| (profileRecord.get('context') == this._getProfilesContext())
},
subtargets: subtargets
});
}
}
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: targets
});
},
close: function(manual)
{
if (this.isDirty())
{
var me = this;
var callback = function (doSave)
{
if (doSave == null)
{
return;
}
else
{
if (doSave)
{
me.saveCurrentChanges(function() {Ametys.plugins.coreui.profiles.ProfilesTool.superclass.close.call(me, [manual])});
}
else
{
Ametys.plugins.coreui.profiles.ProfilesTool.superclass.close.call(me, [manual]);
}
}
}
Ametys.form.SaveHelper.promptBeforeQuit(null, "{{i18n PLUGINS_CORE_UI_PROFILES_RIGHTS_CONFIRM_DESCRIPTION}}", null, callback);
return;
}
this.callParent(arguments);
},
/**
* @private
* Create the profiles' store
* @return {Ext.data.Store} The profiles' store
*/
_createProfileStore: function ()
{
var storeConfig = Ext.merge({
remoteSort: false,
groupField: 'context',
model: 'Ametys.plugins.coreui.profiles.ProfilesTool.Profile',
proxy: {
type: 'ametys',
reader: {
type: 'json',
rootProperty: 'profiles'
}
},
sortOnLoad: true,
sorters: [{property: 'label', direction:'ASC'}]
}, this.getProfileStoreConfig());
return Ext.create('Ext.data.Store', storeConfig);
},
/**
* @private
* Listener invoked when the profiles store is loaded
* @param {Ext.data.Store} store the profiles store
* @param {Ext.data.Record[]} records the records of the store
*/
_onProfileStoreLoaded: function(store, records)
{
if (this._initialSelectedProfiles.length > 0)
{
var records = [];
var sm = this._profilesGrid.getSelectionModel();
var store = this._profilesGrid.getStore();
Ext.Array.each (this._initialSelectedProfiles, function (id) {
var index = store.find("id", id);
if (index != -1)
{
records.push(store.getAt(index));
}
});
sm.select(records);
this._initialSelectedProfiles = []; // reset
}
},
/**
* @private
* Create the rights' store
* @return {Ext.data.Store} the rights' store
*/
_createRightsStore: function()
{
var storeConfig = Ext.merge({
model: 'Ametys.plugins.coreui.profiles.ProfilesTool.Right',
proxy: {
type: 'ametys',
reader: {
type: 'json',
rootProperty: 'rights'
}
},
remoteSort: false,
sortOnLoad: true,
sorters: [{property: 'category', direction:'ASC'}, {property: 'label', direction: 'ASC'}]
}, this.getRightsStoreConfig());
return Ext.create('Ext.data.Store', storeConfig);
},
/**
* Returns the elements of configuration of profiles store to be overridden.
* Override this function if you want to override the profiles store configuration.
* @return {Object} The elements of store configuration to be overridden
*/
getProfileStoreConfig: function()
{
return {
proxy: {
plugin: 'core',
url: 'rights/profiles.json',
extraParams: {
limit: null, // No pagination
context: this._getProfilesContext()
}
},
listeners: {
load: {fn: this._onProfileStoreLoaded, scope: this}
}
};
},
/**
* @protected
* Get the context to display profiles (additionnaly to null context)
* @returns {String} the context to display or empty
*/
_getProfilesContext: function()
{
return "";
},
/**
* Returns the elements of configuration of rights store to be overridden.
* Override this function if you want to override the rights store configuration.
* @return {Object} The elements of store configuration to be overridden
*/
getRightsStoreConfig: function()
{
return {
proxy: {
plugin: 'core',
url: 'rights/rights.json'
},
listeners: {
load: {fn: this._onRightsStoreLoaded, scope: this}
}
};
},
/**
* @private
* Function invoked before a profile is selected. Update the rights' panel
* @param {Ext.selection.Model} model The selection model
* @param {Ext.data.Model} selection The selected record
*/
_onBeforeSelectProfile: function(model, selection)
{
if (this._currentProfiles.length == 1 && this.isDirty())
{
var me = this;
var callback = function (doSave)
{
if (doSave != null)
{
if (doSave)
{
me.saveCurrentChanges(function () {
me._profilesGrid.setSelection(this._currentProfiles);
})
}
else
{
me.setDirty(false);
me._profilesGrid.setSelection(this._currentProfiles);
}
}
}
Ametys.form.SaveHelper.promptBeforeQuit(null, "{{i18n PLUGINS_CORE_UI_PROFILES_RIGHTS_CONFIRM_DESCRIPTION}}", null, callback);
// Cancel the selection, it will be done after the user answered the dialog
return false;
}
},
/**
* @private
* Listener when the selection has changed
* @param {Ext.selection.Model} model The selection model
* @param {Ext.data.Model[]} selection The selected record
*/
_onSelectProfile: function(model, selection)
{
this._currentProfiles = selection;
this.sendCurrentSelection();
var activeItemIndex;
if (!selection || selection.length == 0)
{
activeItemIndex = 0;
}
else if (selection.length > 1)
{
activeItemIndex = 3;
}
else if (this.getMode() == 'view' || (selection[0].get('context') != this._getProfilesContext() && this.config.canEditAnyContext !== "true"))
{
this._updateCardPanels(selection[0].get('rights') || []);
activeItemIndex = 1;
}
else
{
this._updateCardPanels(selection[0].get('rights') || []);
activeItemIndex = 2;
}
this._rightsPanel.getLayout().setActiveItem(activeItemIndex);
},
/**
* @private
* Listener invoked when the rights store is loaded
* @param {Ext.data.Store} store the rights store
* @param {Ext.data.Record[]} records the records of the store
*/
_onRightsStoreLoaded: function(store, records)
{
this._rightsByCategory = {};
// Categorize the rights
// We generate the id 'categoryId' that will be used later in order to avoid adding it in the server method right2Json
// Indeed, we can't use the category name directly because some of their characters may not be accepted within an itemId
var categoriesIds = {};
var categoryId = null;
for (var i = 0; i < store.getTotalCount(); i++)
{
// work on store data instead of the records because the records are not sorted
var record = store.getAt(i);
var categoryName = record.get('category');
categoryId = categoriesIds[categoryName];
if (categoryId == null)
{
// Create a new identifier every time we encounter an unregistered category name
categoryId = Ext.id();
categoriesIds[categoryName] = categoryId;
this._rightsByCategory[categoryId] = [];
}
this._rightsByCategory[categoryId].push(record);
}
this._drawCardPanels();
},
/**
* @private
* Draw items inside both of the panels of the card panel of the tool and hide them
*/
_drawCardPanels: function()
{
var me = this;
var cardViewPanel = this._rightsPanel.getComponent('card-view');
var cardEditPanel = this._rightsPanel.getComponent('card-edit');
Ext.suspendLayouts();
cardEditPanel.items.each(function(item, index) {
if (item.items)
{
cardEditPanel.remove(item);
}
});
cardViewPanel.items.each(function(item, index) {
if (item.items)
{
cardViewPanel.remove(item);
}
});
Ext.Object.each(this._rightsByCategory, function(categoryId) {
var categoryRights = this._rightsByCategory[categoryId];
// Common configuration
var categoryPanelCfg = {
itemId: categoryId,
title : categoryRights[0].get('category'),
layout: {
type: 'column',
calculateItems: function(ownerContext, containerSize) {
if (containerSize.gotWidth === false)
{
return Ext.layout.container.Column.prototype.calculateItems.apply(this, arguments);
}
else
{
let columnWidth = 1 / Math.max(1, Math.floor(containerSize.width / 250));
ownerContext.target.query("checkbox").forEach(function(elt) {
elt.columnWidth = columnWidth;
});
return Ext.layout.container.Column.prototype.calculateItems.apply(this, arguments);
}
}
},
ui: 'light',
cls: 'a-panel-spacing',
collapsible: true,
titleCollapse: true,
header: {
titlePosition: 1
},
border: false
};
var categoryViewPanel = Ext.create('Ext.panel.Panel', categoryPanelCfg);
var categoryEditPanel = Ext.create('Ext.panel.Panel', Ext.applyIf(
{
tools: [
{
xtype: 'button',
cls: 'a-btn-light ametysicon-check51',
padding: '0 14px 0 2px',
itemId: 'category-select-all',
width: 16,
height: 16,
tooltip: '{{i18n PLUGINS_CORE_UI_TOOL_PROFILES_CATEGORY_SELECT_ALL}}',
border: false,
handler: function() {me.selectAll(categoryId)},
listeners:
{
click:
{
fn: function(header, event)
{
// Prevent panel collapsing mechanism
event.stopPropagation();
}
}
}
},
{
xtype: 'button',
cls: 'a-btn-light ametysicon-blank32',
margin: '0 15px 0 6px', // left to separate buttons, right to avoid to be half hiddent under the vertical scrollbar
padding: '0 14px 0 2px',
width: 16,
height: 16,
itemId: 'category-unselect-all',
tooltip: '{{i18n PLUGINS_CORE_UI_TOOL_PROFILES_CATEGORY_UNSELECT_ALL}}',
border: false,
handler: function() {me.unselectAll(categoryId)},
listeners:
{
click:
{
fn: function(header, event)
{
// Prevent panel collapsing mechanism
event.stopPropagation();
}
}
}
}
]
}, categoryPanelCfg));
Ext.Array.each(categoryRights, function(right) {
var rightId = right.get('id'),
rightLabel = right.get('label'),
rightDescription = right.get('description') + "<br/><br/><em><strong>{{i18n PLUGINS_CORE_UI_TOOL_PROFILES_DESCRIPTION_ID}}</strong><br/>" + right.get('id') + "</em>";
// View container for a right
var viewRightContainer = Ext.create('Ext.form.field.Checkbox', {
itemId: rightId + '-view',
columnWidth: 0.33,
boxLabel: rightLabel, // text for the component that will be created
readOnly : true,
ametysDescription: rightDescription,
ametysDescriptionWidth: "auto" // right ids can be long and does not support line break => autosize for the tooltip
});
// Edition container for a right
var editRightContainer = Ext.create('Ext.form.field.Checkbox', {
itemId: rightId + '-edit',
columnWidth: 0.33,
boxLabel: rightLabel, // text for the component that will be created
ametysDescription: rightDescription ,
ametysDescriptionWidth: "auto", // right ids can be long and does not support line break => autosize for the tooltip
listeners: {
change: Ext.bind(me._onEditRightFieldChange, me)
}
});
categoryViewPanel.add(viewRightContainer);
categoryEditPanel.add(editRightContainer);
});
cardViewPanel.add(categoryViewPanel);
cardEditPanel.add(categoryEditPanel);
}, this);
var selection = this._profilesGrid.getSelection()[0];
if (selection)
{
this._updateCardPanels(selection.get('rights') || []);
}
Ext.resumeLayouts(true);
},
/**
* @private
* Handler function invoked when an right edition field has changed
* @param {Ext.form.field.Checkbox} box the checkbox
* @param {Object} newValue the value of the field after it has changed
* @param {Object} oldValue the value of the field before it has changed
*/
_onEditRightFieldChange: function(box, newValue, oldValue)
{
if (!this.isDirty())
{
this.setDirty(true);
this.sendCurrentSelection();
}
},
/**
* @private
* Update the card panels according to the selected profile's right ids
* @param {String[]} profileRightsIds the ids of the rights for the selected profile
*/
_updateCardPanels: function(profileRightsIds)
{
Ext.suspendLayouts();
// Keep a copy of the rights before the tool is dirty
var categoriesToShow = [];
var cardViewPanel = this._rightsPanel.getComponent('card-view');
var cardEditPanel = this._rightsPanel.getComponent('card-edit');
Ext.Object.each(this._rightsByCategory, function(categoryId) {
var rights = this._rightsByCategory[categoryId];
var categoryViewPanel = cardViewPanel.getComponent(categoryId);
var categoryEditPanel = cardEditPanel.getComponent(categoryId);
Ext.Array.each(rights, function (right)
{
var rightId = right.get('id');
var hasRight = Ext.Array.contains(profileRightsIds, rightId);
// Update edition screen without triggering a change event
var editRightContainer = categoryEditPanel.getComponent(rightId + '-edit');
editRightContainer.suspendEvents(false);
editRightContainer.setValue(hasRight);
editRightContainer.enable();
editRightContainer.resumeEvents();
// Update view screen
var viewRightContainer = categoryViewPanel.getComponent(rightId + '-view');
viewRightContainer.setVisible(hasRight);
// Update categories
if (Ext.Array.contains(profileRightsIds, rightId) && !Ext.Array.contains(categoriesToShow, categoryId))
{
categoriesToShow.push(categoryId);
}
}, this);
}, this);
// Update category panels for visualization mode
var oneVisible = false;
Ext.Object.each(this._rightsByCategory, function(categoryId) {
var thisOneVisible = Ext.Array.contains(categoriesToShow, categoryId);
oneVisible = oneVisible || thisOneVisible;
cardViewPanel.getComponent(categoryId).setVisible(thisOneVisible);
}, this);
cardViewPanel.getComponent('empty-selection').setVisible(!oneVisible);
this._rights = this._getRights();
this._filter();
Ext.resumeLayouts(true);
},
/**
* Switch mode
* @param {String} mode The mode: 'view' or 'edit'
*/
switchMode: function (mode)
{
var editTextField = this._rightsPanel.getComponent('card-edit').dockedItems.getByKey('edit-search-filter-bar').getComponent('edit-search-filter-input');
var viewTextField = this._rightsPanel.getComponent('card-view').dockedItems.getByKey('view-search-filter-bar').getComponent('view-search-filter-input');
if (mode == 'edit')
{
// Go to edition mode
this._rightsPanel.getLayout().setActiveItem(2);
//synchronize filter
editTextField.setValue(viewTextField.getValue())
this.sendCurrentSelection();
}
else
{
//synchronize filter
viewTextField.setValue(editTextField.getValue())
if (this.isDirty())
{
var me = this;
var rights = this._getRights();
var callback = function(doSave)
{
if (doSave == null)
{
return;
}
else
{
if (doSave)
{
me.saveCurrentChanges(function() {
me._rightsPanel.getLayout().setActiveItem(1);
me.sendCurrentSelection();
});
}
else
{
me.setDirty(false);
me._updateCardPanels(me._rights);
me._rightsPanel.getLayout().setActiveItem(1);
this._filter();
me.sendCurrentSelection();
}
}
}
Ametys.form.SaveHelper.promptBeforeQuit(null, "{{i18n PLUGINS_CORE_UI_PROFILES_RIGHTS_CONFIRM_DESCRIPTION}}", null, callback);
}
else
{
// Go to view mode
this._rightsPanel.getLayout().setActiveItem(1);
this._filter();
this.sendCurrentSelection();
}
}
},
/**
* @private
* Get the selected rights
*/
_getRights: function()
{
var rights = [];
// Gather the selected rights
var cardEditPanel = this._rightsPanel.getComponent('card-edit');
Ext.Object.each(this._rightsByCategory, function(categoryId)
{
var categoryEditPanel = cardEditPanel.getComponent(categoryId);
var categoryRights = this._rightsByCategory[categoryId];
Ext.Array.each(categoryRights, function (right)
{
var rightId = right.get('id');
var editRightContainer = categoryEditPanel.getComponent(rightId + '-edit');
if (editRightContainer.getValue())
{
rights.push(rightId);
}
}, this);
}, this);
return rights;
},
/**
* Save the current changes done on selected profile
* @param {Function} callback the callback function
*/
saveCurrentChanges: function(callback)
{
if (this._currentProfiles.length == 1)
{
var rights = this._getRights();
Ametys.plugins.core.profiles.ProfilesDAO.editProfileRights([this._currentProfiles[0].getId(), rights], this._saveCb, {scope: this, arguments: {callback: callback}});
}
},
/**
* @private
* The method call by #saveCurrentChanges
* @param {Object} profile The profile's properties
* @param {Object} args The arguments transmitted
* @param {Function} args.callback The callback to call if it exits
* @param {Object[]} params The params transmitted by client side
*/
_saveCb: function (profile, args, params)
{
// Reset the dirty state of the tool
this.setDirty(false);
this._updateCardPanels(params[1]);
if (Ext.isFunction(args.callback))
{
args.callback ();
}
},
/**
* Select all rights
* @param {String} categoryId The item id of the html element surrounding the elements to check. Can be null to check all.
* @param {Boolean} [value=true] The value to set to all rights: true means rights are set and false unset.
*/
selectAll: function(categoryId, value)
{
var cardEditPanel = this._rightsPanel.getComponent('card-edit');
value = value == null ? true : value;
if (categoryId != null)
{
var categoryEditPanel = cardEditPanel.getComponent(categoryId);
categoryEditPanel.items.each (function (item, index) {
if (item.isVisible())
{
item.setValue(value)
}
});
}
else
{
cardEditPanel.items.each(function(item, index) {
if (item.items)
{
item.items.each(function(item, index) {
if (item.isVisible())
{
item.setValue(value)
}
});
}
});
}
},
/**
* Unselect all rights
* @param {String} categoryId The item id of the html element surrounding the elements to uncheck. Can be null to uncheck all.
*/
unselectAll: function(categoryId)
{
this.selectAll(categoryId, false);
},
/**
* Get the current mode
* @return the mode
*/
getMode: function ()
{
return this._rightsPanel.getLayout().getActiveItem().getItemId() == 'card-edit' ? 'edit' : 'view';
},
/**
* @private
* Listener when a Ametys.message.Message#CREATED message was received
* @param {Ametys.message.Message} message The received message
*/
_onMessageCreated: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.PROFILE);
if (targets.length)
{
for (let target of targets)
{
var id = target.getParameters().id;
var profile = this._profilesGrid.getStore().getById(id);
if (profile)
{
Ametys.plugins.core.profiles.ProfilesDAO.getProfile([id], this._updateProfile, {scope: this});
}
else
{
Ametys.plugins.core.profiles.ProfilesDAO.getProfile([id, true], this._addProfile, {scope: this});
}
}
}
var rightTarget = message.getTarget(Ametys.message.MessageTarget.RIGHT);
if (rightTarget)
{
this.showOutOfDate();
}
},
/**
* @private
* Listener when a Ametys.message.Message#EDITED message was received
* @param {Ametys.message.Message} message The received message
*/
_onMessageEdited: function(message)
{
var target = message.getTarget(Ametys.message.MessageTarget.PROFILE);
if (target != null)
{
var id = target.getParameters().id;
// recompute the rights only if the modification is major
var major = message.getParameters().major || false;
Ametys.plugins.core.profiles.ProfilesDAO.getProfile([id, major], this._updateProfile, {scope: this});
}
},
/**
* @private
* Listener when a Ametys.message.Message#DELETED message was received
* @param {Ametys.message.Message} message The received message
*/
_onMessageDeleted: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.PROFILE);
var store = this._profilesGrid.getStore();
Ext.Array.forEach(targets, function(target) {
var profile = store.getById(target.getParameters().id);
if (profile)
{
store.remove(profile);
}
}, this);
// no current profile selected anymore + no dirty state
this._currentProfiles = [];
this.setDirty(false);
var rightTarget = message.getTarget(Ametys.message.MessageTarget.RIGHT);
if (rightTarget)
{
this.showOutOfDate();
}
},
/**
* @private
* Add a profile record
* @param {Object} profile The profile's properties
*/
_addProfile: function (profile)
{
if (profile && profile.id)
{
var record = Ext.create('Ametys.plugins.coreui.profiles.ProfilesTool.Profile', profile);
this._profilesGrid.getStore().addSorted(record);
this._profilesGrid.getSelectionModel().select([record]);
}
},
/**
* @private
* Update a profile record
* @param {Object} profile The profile's properties
*/
_updateProfile: function (profile)
{
if (profile && profile.id)
{
var store = this._profilesGrid.getStore();
var record = store.getById(profile.id);
record.beginEdit();
record.set('label', profile.label);
// update rights if they were computed
if (profile.rights)
{
record.set('rights', profile.rights);
// update the right panel if the modified profile is the current selection
var selections = this._profilesGrid.getSelection();
if (selections.length == 1 && selections[0].get('id') == profile.id)
{
this._updateCardPanels(profile.rights)
}
}
record.endEdit();
// commit changes (record is not marked as dirty anymore)
record.commit();
// re-sort
store.sort();
this._profilesGrid.getSelectionModel().select([record]);
}
}
});