/*
* 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.
*/
/**
* Tool that display the list of projects and their statistics
* @private
*/
Ext.define('Ametys.plugins.workspaces.project.tool.StatisticsTool', {
extend: 'Ametys.tool.Tool',
constructor: function(config)
{
this.callParent(arguments);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageCreatedOrModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onMessageCreatedOrModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
createPanel: function()
{
Ametys.data.ServerComm.callMethod({
role: "org.ametys.plugins.workspaces.project.ProjectManager",
methodName: "getProjectsStatisticsColumnsModel",
parameters: [],
callback: {
scope: this,
handler: this._getStatisticHeadersCb
},
errorMessage: {
category: this.self.getName(),
msg: "{{i18n PLUGINS_WORKSPACES_DAOS_PROJECT_ERROR}}"
}
});
this._panel = Ext.create('Ext.container.Container', {
layout: 'fit',
items: {
xtype: "component",
html: "{{i18n PLUGINS_WORKSPACES_PROJECT_STATISTICS_TOOL_LOADING}}"
}
})
return this._panel;
},
/**
* @private
* Create fields from data
* @param {Object} data The data
*/
_getFieldsFromJson: function (data)
{
let fields = [];
data.forEach(function (column) {
if (column.subColumns)
{
let subFields = this._getFieldsFromJson(column.subColumns);
fields = fields.concat(subFields);
}
else
{
field = { name: column.id, type: column.type };
if (column.type == "date" || column.type == "datetime")
{
field.dateFormat = Ext.Date.patterns.ISO8601DateTime;
field.type = "date";
}
if (column.type == "long")
{
field.type = "int";
}
fields.push(field);
}
}, this);
return fields;
},
/**
* @private
* Callback function called after #getStatisticHeaders is processed
* @param {Object} data The project properties
* @param {Array} args The callback arguments.
*/
_getStatisticHeadersCb: function (data)
{
fields = this._getFieldsFromJson(data);
//used for project renderer
fields.push({ name: 'valid', type: 'boolean', defaultValue: true })
let modelName = "Ametys.plugins.workspaces.project.tool.StatisticsTool.StatisticsEntry";
if (!Ext.data.schema.Schema.get('default').hasEntity(modelName))
{
Ext.define(modelName, {
extend: 'Ext.data.Model',
schema: 'default',
fields: fields
});
}
this._store = Ext.create('Ext.data.Store', {
model: modelName,
proxy: {
type: 'ametys',
role: 'org.ametys.plugins.workspaces.project.ProjectManager',
methodName: 'getProjectsStatisticsForClientSide',
methodArguments: [],
reader: {
type: 'json'
}
},
autoLoad: true,
sorters: [{property: 'title', direction: 'ASC'}]
});
var columns = Ametys.plugins.cms.search.SearchGridHelper.getColumnsFromJson(data, true);
this._grid = Ext.create('Ext.grid.Panel', {
stateful: true,
stateId: this.self.getName() + "$grid",
plugins: ['gridfilters'],
// Languages combo box
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
border: false,
defaults : {
cls: 'ametys',
labelWidth: 55,
labelSeparator: ''
},
items: [{
// Search input
xtype: 'textfield',
itemId: 'search-filter-input',
cls: 'ametys',
flex: 1,
maxWidth: 300,
emptyText: "{{i18n PLUGINS_WORKSPACES_PROJECT_LIST_TOOL_FILTER_EMPTY_TEXT}}",
enableKeyEvents: true,
minLength: 3,
minLengthText: "{{i18n PLUGINS_WORKSPACES_PROJECT_LIST_TOOL_FILTER_MIN_LENGTH_INVALID}}",
msgTarget: 'qtip',
listeners: {change: Ext.Function.createBuffered(this._filterByTitle, 300, this)}
}, {
// Clear filter
tooltip: "{{i18n PLUGINS_WORKSPACES_PROJECT_LIST_TOOL_FILTER_CLEAR}}",
handler: Ext.bind (this._clearFilter, this),
iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
cls: 'a-btn-light'
}]
}],
store: this._store,
selModel: {
mode: 'SINGLE'
},
columns: columns
});
this._panel.removeAll();
this._panel.add(this._grid);
},
/**
* @private
* Filters queries by input field value.
* @param {Ext.form.Field} field The field
*/
_filterByTitle: function (field)
{
var value = Ext.String.trim(field.getValue());
if (this._filterValue == value)
{
// Do nothing
return;
}
this._filterValue = value;
var regexFilter = new RegExp(value, 'i');
if (value.length > 2)
{
var currentSelection = this._grid.getSelection();
this._store.clearFilter();
this._store.filterBy(function(record){
return regexFilter.test(record.data.title) || regexFilter.test(record.data.name);
});
if (currentSelection.length > 0)
{
var me = this;
Ext.Array.each(currentSelection, function (sel) {
if (me._store.findExact(me._store.getModel().idProperty, sel.getId()) == -1)
{
// The current selection is not visible, clear the selection
me._grid.getSelectionModel().deselect([sel]);
}
})
}
}
else
{
// We do not call _clearFilter that will also empty the filter and prevent from typing
this._filterValue = null;
this._store.clearFilter();
}
},
/**
* Clear the current filter
*/
_clearFilter: function()
{
this._grid.down("#search-filter-input").reset();
this._filterValue = null;
this._store.clearFilter();
},
setParams: function (params)
{
this.callParent(arguments);
this.refresh();
},
/**
* Refreshes the tool
*/
refresh: function ()
{
// On the first launch, the store is not created yet. It will be loaded after creation.
if(this._store)
{
this._store.load();
}
},
/**
* Listener on creation or edition message.
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onMessageCreatedOrModified: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.WORKSPACES_PROJECT);
if (targets.length > 0)
{
this.showOutOfDate();
}
},
/**
* Listener on deletion message.
* @param {Ametys.message.Message} message The deletion message.
* @private
*/
_onMessageDeleted: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.WORKSPACES_PROJECT);
for (var i = 0; i < targets.length; i++)
{
var record = this._store.getById(targets[i].getParameters().id);
this._store.remove(record);
}
},
sendCurrentSelection: function()
{
}
});