/*
* Copyright 2022 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 list of temporary users, awaiting for subscription's finalization.
*/
Ext.define('Ametys.plugins.web.tempusers.TempUsersTool', {
extend: 'Ametys.plugins.cms.search.AbstractSearchTool',
constructor: function(config)
{
this.callParent(arguments);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onTempUserDeleted, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onTempUserCreatedOrModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onTempUserCreatedOrModified, this);
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
createStore: function()
{
var storeCfg = Ext.applyIf(this._getStoreCfg(), {
autoDestroy: true,
pageSize: Ametys.plugins.cms.search.AbstractSearchTool.PAGE_SIZE
});
return Ext.create('Ext.data.Store', storeCfg);
},
_getStoreCfg: function()
{
return {
model: 'Ametys.plugins.web.tempusers.TempUsersTool.TempUser',
proxy: {
type: 'ametys',
methodName: 'searchTempUsers',
methodArguments: ['siteName', 'searchParameters', 'start', 'limit', 'sorters'],
role: 'org.ametys.web.usermanagement.UserSignupManager',
reader: {
type: 'json',
rootProperty: 'users'
},
extraParams: {
siteName: Ametys.getAppParameter('siteName')
}
},
sorters: [{property: 'email', direction:'ASC'}],
remoteSort: true,
sortOnLoad: true,
listeners: {
'beforeload': {fn: this._onBeforeLoad, scope: this},
'load': Ext.bind(this._onLoad, this)
}
}
},
// Overriden to enable multi selection
_getResultGridCfg: function(store)
{
var dockedItems = [];
if (this.enablePagination)
{
dockedItems.push(this._getPaginationToolbarCfg(store));
}
return {
store: store,
region: 'center',
split: true,
border: false,
stateful: true,
stateId: this.getId() + "$grid",
columns: [], // columns will be set later
selModel : {
mode: 'MULTI'
},
features: [{
ftype: 'grouping',
groupHeaderTpl: [
'{columnName}: {name:this.formatName}',
{
formatName: function(name) {
return Ext.String.trim(name.toString());
}
}
]
}],
viewConfig: {
loadingText: "{{i18n plugin.cms:UITOOL_SEARCH_WAITING_MESSAGE}}"
},
dockedItems: dockedItems,
listeners: {
'selectionchange': Ext.bind(this._onSelectionChanged, this)
}
};
},
/**
* Function called 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)
{
if (this.grid && !this._updatingModel && (!(this.form instanceof Ametys.form.ConfigurableFormPanel) || this.form.isFormReady()))
{
this.grid.getView().unmask();
if (!this.form.isValid())
{
this._stopSearch();
return false;
}
var sorters = [];
this.store.getSorters().each (function (sorter) {
var sortProperty = sorter.getProperty();
var direction = sorter.getDirection();
if (sortProperty == 'expiration_date')
{
sortProperty = "subscription_date";
}
else if (sortProperty == 'expired')
{
sortProperty = "subscription_date";
direction = direction == 'ASC' ? 'DESC' : 'ASC';
}
sorters.push({property: sortProperty, direction: direction})
});
var values = this.form.getJsonValues();
if (values.population && values.population == '#all')
{
values.population = null;
}
operation.setParams( Ext.apply(operation.getParams() || {}, {
'searchParameters': values,
'sorters': sorters
}));
this._error = null;
}
else
{
// avoid use less requests at startup (applyState...)
return false;
}
},
/**
* Function called after loading results
* @param {Ext.data.Store} store The store
* @param {Ext.data.Model[]} records An array of records
* @param {Boolean} successful True if the operation was successful.
* @param {Ext.data.operation.Operation} operation Operation performed by the proxy
* @protected
*/
_onLoad: function (store, records, successful, operation)
{
if (operation.aborted)
{
// Load has been canceled. Do nothing.
return;
}
// Hack to process groups locally even if remoteSort is enabled.
store.getData().setAutoGroup(true);
this._setGridDisabled(false);
if (records.length == 0)
{
this.grid.getView().mask("{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_NO_RESULT}}", 'ametys-mask-unloading');
}
this.sendCurrentSelection();
},
_onSelectionChanged: function(sm, selected)
{
this.sendCurrentSelection();
},
sendCurrentSelection : function()
{
var targets = [];
var store = this.grid.getStore();
var emails = [];
var selection = this.grid.getSelectionModel().getSelection();
for (var i=0; i < selection.length; i++)
{
emails.push(selection[i].data.email);
}
Ext.create("Ametys.message.Message", {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: {
id: Ametys.message.MessageTarget.TEMP_USER,
parameters: { emails: emails }
}
});
},
refresh: function()
{
Ametys.plugins.web.tempusers.TempUsersDAO.invalidateCache();
this.callParent(arguments);
},
_retrieveCriteriaAndColumns: function(force)
{
var toolParams = this.getParams().toolParams || {};
var criteria = this._getSearchCriteria();
this._configureSearchForm(criteria);
var columns = this._getColumns();
this.grid.reconfigure(this.store, columns);
this._initSearchForm(toolParams);
this._updatingModel = false;
// Launch search
this.refresh();
},
/**
* @protected
* Get the search criteria configuration
* @return the search criteria
*/
_getSearchCriteria: function()
{
return {
"criteria": {
role: 'fieldset',
elements: {
"pattern": this._getTextfieldCfg(),
"population": this._getPopulationComboboxCfg(),
"origin": this._getOriginComboboxCfg()
}
}
}
},
/**
* @protected
* Get the columns configuration
* @return The array of columns
*/
_getColumns: function()
{
return [
{stateId: 'grid-email', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EMAIL}}", flex: 1, minWidth : 160, sortable: true, dataIndex: 'email'},
{stateId: 'grid-firstname', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_FIRSTNAME}}", width : 180, sortable: true, dataIndex: 'firstname'},
{stateId: 'grid-lastname', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_LASTNAME}}", width : 180, sortable: true, dataIndex: 'lastname'},
{stateId: 'grid-population', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_POPULATION}}", width : 200, sortable: true, dataIndex: 'population', renderer: this._renderPopulation},
{stateId: 'grid-userDirectory', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_USER_DIRECTORY}}", width : 180, sortable: true, hidden: true, dataIndex: 'userDirectory', renderer: this._renderUserDirectory},
{stateId: 'grid-subscriptionDate', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_SUBSCRIPTION_DATE}}", width : 160, sortable: true, dataIndex: 'subscription_date', renderer: Ext.util.Format.dateRenderer('d F Y')},
{stateId: 'grid-expirationDate', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EXPIRATION_DATE}}", width : 160, sortable: true, dataIndex: 'expiration_date', renderer: Ext.util.Format.dateRenderer('d F Y')},
{stateId: 'grid-origin', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN}}", width : 160, sortable: true, dataIndex: 'origin', renderer: Ext.bind(this._renderOrigin, this)},
{stateId: 'grid-status', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EXPIRED_STATUS}}", width : 140, hidden: false, sortable: true, dataIndex: 'expired', renderer: Ext.bind(this._renderExpired, this)}
];
},
/**
* @private
*/
_getOriginComboboxCfg: function()
{
return {
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN}}",
widget: 'edition.combobox',
type: "boolean",
enumeration: [
{
value: null,
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_ALL}}"
},
{
value: 'INVITATION',
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_FROM_INVITATION}}"
},
{
value: 'USER_REQUEST',
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_FROM_USER_REQUEST}}"
}
]
}
},
/**
* @private
*/
_getTextfieldCfg: function()
{
return {
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_TEXTFIELD}}",
type: "string",
'widget-params': {
emptyText: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_TEXTFIELD_EMPTY_TEXT}}"
}
}
},
/**
* @private
*/
_getPopulationComboboxCfg: function()
{
return {
widget: 'edition.combobox',
label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_POPULATION}}",
type: "string",
'widget-params': {
valueField: 'id',
displayField: 'label',
forceSelection: true,
triggerAction: 'all',
defaultValue: '#all',
proxyStore: {
type: 'ametys',
plugin: 'core-ui',
url: 'populations.json',
reader: {
type: 'json',
rootProperty: 'userPopulations'
},
extraParams: {
contexts: Ametys.getAppParameter('populationContexts'),
modifiable: true // only modifiable
}
},
storeListeners: {
'load': {fn: this._onLoadPopulations, scope: this}
}
}
};
},
/**
* @private
* Listener invoked after loading populations
* @param {Ext.data.Store} store The store
* @param {Ext.data.Model[]} records The records of the store
*/
_onLoadPopulations: function(store, records)
{
// Add an option in the populations combobox for searching over all the populations
store.add({
id: '#all',
label: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_TOOL_USERS_POPULATION_FIELD_OPTION_ALL}}"
});
},
/**
* @private
* Render the expired column of the grid
* @param {String} value the value of 'expired'
*/
_renderExpired: function (value)
{
if (value)
{
return '<span class="a-grid-glyph ametysicon-sign-raw-cross"></span>' + " {{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_STATUS_EXPIRED}}";
}
return '<span class="a-grid-glyph ametysicon-datetime-clock"></span>' + " {{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_STATUS_ACTIVE}}";
},
/**
* @private
* Render the signup request origin
* @param {String} value the value of 'origin'
*/
_renderOrigin: function(value)
{
if (value == 'INVITATION')
{
return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_FROM_INVITATION}}";
}
else if (value == 'USER_REQUEST')
{
return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_FROM_USER_REQUEST}}";
}
else
{
return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_UNKNOWN}}";
}
},
/**
* @private
* Render the population
* @param {String} value the id of population
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
*/
_renderPopulation: function(value, metaData, record)
{
return record.get("populationLabel") || value;
},
/**
* @private
* Render the user directory
* @param {String} value the id of user directory
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
*/
_renderUserDirectory: function(value, metaData, record)
{
return record.get("userDirectoryLabel") || value;
},
/**
* @private
* Listener upon reception of a creation message
* @param {Ametys.message.Message} message the creation message
*/
_onTempUserCreatedOrModified: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.TEMP_USER);
if (targets.length > 0)
{
this.showOutOfDate(true);
}
},
/**
* @private
* Listener upon reception of a deletion message
* @param {Ametys.message.Message} message the deletion message
*/
_onTempUserDeleted: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.TEMP_USER);
if (targets.length > 0)
{
var store = this.grid.getStore();
Ext.Array.forEach(targets, function(target) {
var email = target.getParameters().email;
var index = store.find("email", email);
if (index != -1)
{
store.removeAt(index);
}
});
}
}
});