/*
* 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.
*/
/**
* Tool for displaying the scheduled tasks (the 'Runnables') of the application.
* @private
*/
Ext.define('Ametys.plugins.coreui.schedule.ScheduledTasksTool', {
extend: "Ametys.tool.Tool",
/**
* @cfg {Number} [refreshTimer=5000] The wait time between refreshes of the tool, in milliseconds.
* The tool also waits for the previous request to resolve before launching a new timer, which can result in a few additional seconds between refreshes if there are a lot of data to process or if the server lags.
*/
/**
* @property {Ext.data.ArrayStore} _store The store with the tasks
* @private
*/
/**
* @property {Ext.grid.Panel} _grid The grid panel displaying the tasks
* @private
*/
/**
* @property {Boolean} _isRunning True if the timer is running.
*/
/**
* @property {Boolean} _filterComplete True if the filter on complete tasks is active
* @private
*/
/**
* @property {String} _filterValue The value of search filter
* @private
*/
statics: {
/**
* @private
* @readonly
* @property {Number} __PROGRESSION_MAXCHILD Number max of displayed children before truncating
*/
__PROGRESSION_MAXCHILDREN: 10
},
constructor: function(config)
{
this.callParent(arguments);
// Add the schedulables in the store of the filter
Ametys.plugins.core.schedule.Scheduler.getSchedulables([], function(schedulables) {
this._grid.down('#grid-schedulable-id').filter.store.loadData(schedulables);
}, {scope: this});
Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onMessageCreated, this);
Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onMessageModified, this);
Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
},
/**
* Gets the grid of the tool
* @return {Ext.grid.Panel} the grid of the tool
*/
getGrid: function()
{
return this._grid;
},
createPanel: function()
{
this._store = this._createStore();
// staful button to show/hide complete task
var me = this;
this._filterCompleteBtn = Ext.create("Ext.Button", {
tooltip: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_FILTER_HIDE_COMPLETE}}",
iconCls: 'a-btn-glyph ametysicon-sign-check decorator-ametysicon-body-part-eye-no size-16',
cls: 'a-btn-light',
stateful: true,
stateId: this.self.getName() + "$complete",
enableToggle: true,
toggleHandler: function(btn, state) {
// The starting applyState triggers this function... too soon
if (me._filterCompleteBtn)
{
me._activeCompleteFilter(btn, state);
btn.saveState();
}
},
applyState: function(state) {
this.setPressed(state && state.pressed);
},
getState: function() {
return {
pressed: this.pressed
};
}
});
this._grid = Ext.create("Ext.grid.Panel", {
store: this._store,
stateful: true,
stateId: this.self.getName() + "$grid",
cls: 'ametys-scheduled-tasks',
selModel: {
mode: 'MULTI'
},
// Grouping by state
features: [
{
ftype: 'grouping',
enableGroupingMenu: false,
groupHeaderTpl: [
'{name:this.formatState}',
{
formatState: function(group) {
switch (group) {
case "0":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_GROUP_RUNNING_LABEL}}";
case "1":
default:
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_GROUP_COMPLETED_LABEL}}";
case "2":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_GROUP_ENABLED_LABEL}}";
case "3":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_GROUP_DISABLED_LABEL}}";
}
}
}
]
}
],
viewConfig : {
loadMask: false,
},
plugins: 'gridfilters',
columns: [
{stateId: 'grid-state', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_STATE}}", width: 50, dataIndex: 'state', renderer: this._renderState},
{stateId: 'grid-title', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_TITLE}}", flex: 1, minWidth: 100, sortable: true, dataIndex: 'label'},
{stateId: 'grid-description', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_DESCRIPTION}}", flex: 2, dataIndex: 'description', hidden: true},
{stateId: 'grid-id', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_ID}}", width: 120, dataIndex: 'id', hidden: true},
{stateId: 'grid-cron', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_CRON}}", width: 170, dataIndex: 'cronExpression'},
{
itemId: 'grid-schedulable-id',
stateId: 'grid-schedulable-id',
header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_SCHEDULABLE_LABEL}}",
flex: 1,
dataIndex: 'schedulableId',
renderer: this._renderSchedulableId,
filter: {
type: 'list',
store: Ext.create('Ext.data.Store', {
fields: ['id','text'],
sorters: 'text',
data: []
})
}
},
{stateId: 'grid-schedulable-description', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_SCHEDULABLE_DESCRIPTION}}", flex: 2, dataIndex: 'schedulableDescription', hidden: true},
{stateId: 'grid-schedulable-parameters', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_SCHEDULABLE_PARAMETERS}}", flex: 2, dataIndex: 'schedulableParameters', renderer: this._renderSchedulableParameters, hidden: true},
{stateId: 'grid-system-task', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_TYPE}}", width: 100, dataIndex: 'private', renderer: this._renderTaskType},
{stateId: 'grid-launch-user', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_LAUNCH_USER}}", width: 100, dataIndex: 'launchUser', renderer: this._renderUser},
{stateId: 'grid-next-fire', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_NEXT_FIRE}}", width: 200, dataIndex: 'nextFireTime', renderer: Ametys.grid.GridColumnHelper.renderDateTime},
{stateId: 'grid-previous-fire', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_PREVIOUS_FIRE}}", width: 200, dataIndex: 'previousFireTime', renderer: this._renderPreviousFireTime, scope: this},
{stateId: 'grid-last-duration', header: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_LAST_DURATION}}", width: 140, dataIndex: 'lastDuration', renderer: Ext.bind(this._renderDuration, this)}
],
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
layout: {
type: 'hbox',
align: 'stretch'
},
border: false,
defaults : {
cls: 'ametys',
labelWidth: 55,
labelSeparator: ''
},
items: [
{
// Filter input
xtype: 'textfield',
itemId: 'search-filter-input',
cls: 'ametys',
flex: 1,
maxWidth: 300,
emptyText: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_FILTER_EMPTY_TEXT}}",
enableKeyEvents: true,
msgTarget: 'qtip',
listeners: {change: Ext.Function.createBuffered(this._filterTasks, 300, this)}
}, {
// Clear filter
tooltip: "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_FILTER_CLEAR}}",
handler: Ext.bind (this._clearSearchFilter, this),
iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
cls: 'a-btn-light'
},
// Filter button for complete tasks
this._filterCompleteBtn
]
}],
listeners: {'selectionchange': Ext.bind(this.sendCurrentSelection, this)}
});
return this._grid;
},
/**
* @private
* Create the store for tasks.
* @return {Ext.data.Store} The store
*/
_createStore: function()
{
return Ext.create('Ext.data.Store', {
autoDestroy: true,
model: 'Ametys.plugins.coreui.schedule.ScheduledTasksTool.TaskEntry',
proxy: {
type: 'ametys',
plugin: 'core-ui',
url: 'scheduledTasks.json',
reader: {
type: 'json',
rootProperty: 'tasks'
}
},
statefulFilters: false, // do not save filters in state
groupField: 'group',
sortOnLoad: true,
sorters: [{property: 'previousFireTime', direction:'DESC'}]
});
},
getMBSelectionInteraction: function()
{
return Ametys.tool.Tool.MB_TYPE_ACTIVE;
},
setParams: function(params)
{
if (this._timer)
{
clearTimeout(this._timer);
}
this.callParent(arguments);
this._refreshTimer = params.refreshTimer || 10000;
this._isRunning = true;
this.showOutOfDate();
},
refresh: function(manual)
{
if (manual)
{
this.showRefreshing();
}
else
{
this.showUpToDate();
}
this.updateSchedulables(true);
},
updateSchedulables(force)
{
if (!this._isRunning && !force)
{
return;
}
// Load the store of the grid
this._store.load({scope: this, callback: this._updateSchedulablesCb});
},
/**
* Callback after refreshing the tool.
* @private
*/
_updateSchedulablesCb()
{
if (!this.isNotDestroyed())
{
return;
}
if (this._isRunning)
{
if (this._timer)
{
clearTimeout(this._timer);
}
this._timer = setTimeout(Ext.bind(this.showOutOfDate, this), this._refreshTimer);
}
// Apply active filters
this._filterTasks();
this.showRefreshed();
},
/**
* True if the tool is fetching live update, false if the log rotation has been paused.
*/
isRunning: function()
{
return this._isRunning;
},
onClose: function()
{
if (this._isRunning)
{
this._isRunning = false;
clearTimeout(this._timer);
this._timer = null;
}
this.callParent(arguments);
},
sendCurrentSelection: function()
{
var selection = this._grid.getSelection();
var tasks = [];
Ext.Array.forEach(selection, function(task) {
tasks.push(
Ext.create('Ametys.plugins.coreui.schedule.Task', {
id: task.get('id'),
schedulable: task.get('schedulable').id,
modifiable: task.get('modifiable'),
removable: task.get('removable'),
deactivatable: task.get('deactivatable'),
state: task.get('state')
})
);
}, this);
Ext.create('Ametys.message.Message', {
type: Ametys.message.Message.SELECTION_CHANGED,
targets: {
id: Ametys.message.MessageTarget.TASK,
parameters: {
tasks: tasks
}
}
});
},
/**
* @private
* Schedulable renderer
* @param {Object} value The data value
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderSchedulableId: function(value, metaData, record)
{
var label = record.get('schedulableLabel'),
iconGlyph = record.get('iconGlyph'),
iconSmall = record.get('iconSmall');
if (!Ext.isEmpty(iconGlyph))
{
return '<span class="' + iconGlyph + '"></span> ' + label;
}
else
{
return '<img src="' + Ametys.getPluginResourcesPrefix('core-ui') + '/' + iconSmall + '"></img> ' + label;
}
},
/**
* @private
* Renders the parameters of the parameters
* @param {Object} value The data value
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderSchedulableParameters: function(value, metaData, record)
{
var result = "";
Ext.Object.each(value, function(paramId, details) {
result += details.label + ", ";
}, this);
return result.replace(/, $/, "");
},
/**
* @private
* Renders the value of the "system" column.
* @param {Boolean} value The data value for the current cell.
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderTaskType: function(value, metaData, record)
{
var isTrue = Ext.isBoolean(value) ? value : value == 'true';
if (isTrue)
{
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_TYPE_SYSTEM}}";
}
else
{
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_COLUMN_TYPE_USER}}";
}
},
/**
* @private
* Renders the value of the "running" column.
* @param {Boolean} value The data value for the current cell.
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderState: function(value, metaData, record)
{
if (record.get('group') == '0') // running
{
if (record.get('success'))
{
return '<span class="a-grid-glyph ametysicon-play124 task-running decorator-task-success decorator-ametysicon-checked34" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_RUNNING}}"/>';
}
else if (record.get('previousFireTime'))
{
return '<span class="a-grid-glyph ametysicon-play124 task-running decorator-task-failure decorator-ametysicon-cross-1" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_RUNNING}}"/>';
}
else
{
return '<span class="a-grid-glyph ametysicon-play124 task-running" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_RUNNING}}"/>';
}
}
else if (record.get('group') == '1') // completed
{
if (value == 'success')
{
return '<span class="a-grid-glyph ametysicon-checked34 task-success" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_SUCCESS}}"/>';
}
else if (value == 'failure')
{
return '<span class="a-grid-glyph ametysicon-cross-1 task-failure" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_FAILURE}}"/>';
}
}
else if (record.get('group') == '2') // active
{
if (record.get('success'))
{
return '<span class="a-grid-glyph ametysicon-datetime-clock decorator-ametysicon-checked34 decorator-task-success" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_SUCCESS}}"/>';
}
else if (record.get('previousFireTime'))
{
return '<span class="a-grid-glyph ametysicon-datetime-clock decorator-ametysicon-cross-1 decorator-task-failure" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_FAILURE}}"/>';
}
else
{
return '<span class="a-grid-glyph ametysicon-datetime-clock" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_AWAITING}}"/>';
}
}
else // awaiting 3
{
if (record.get('success'))
{
return '<span class="a-grid-glyph ametysicon-datetime-clock decorator-ametysicon-checked34 decorator-task-success task-disabled" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_SUCCESS}}"/>';
}
else if (record.get('previousFireTime'))
{
return '<span class="a-grid-glyph ametysicon-datetime-clock decorator-ametysicon-cross-1 decorator-task-failure task-disabled" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_FAILURE}}"/>';
}
else
{
return '<span class="a-grid-glyph ametysicon-datetime-clock task-disabled" title="{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STATE_DISABLED}}"/>';
}
}
},
/**
* @private
* Renders the value of the "running" column.
* @param {Boolean} value The data value for the current cell.
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderRunning: function(value, metaData, record)
{
var isTrue = Ext.isBoolean(value) ? value : value == 'true';
if (isTrue)
{
return '<span class="a-grid-glyph ametysicon-play124"/>';
}
else
{
return '';
}
},
/**
* @private
* Renders the value of the "success" column.
* @param {Boolean} value The data value for the current cell.
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderSuccess: function(value, metaData, record)
{
if (value == null)
{
// The task did not run yet or is currently running, display nothing
return '';
}
else if (value)
{
return '<span class="a-grid-glyph ametysicon-check34"/>';
}
else
{
return '<span class="a-grid-glyph ametysicon-delete30"/>';
}
},
/**
* @private
* User renderer
* @param {Object} value The data value
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderUser: function(value, metaData, record)
{
if (Ext.Object.isEmpty(value))
{
return "";
}
return Ametys.helper.Users.renderUser(value.login, value.populationLabel, value.sortablename);
},
/**
* @private
* Specific date renderer for previous fire time (add some information if the task is running)
* @param {Object} value The data value
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
* @return {String} The html representation
*/
_renderPreviousFireTime: function(value, metaData, record)
{
if (record.get('running'))
{
if (value)
{
// Add a message saying the task is running and so the displayed fire time is the time the currently running job was triggered
return Ametys.grid.GridColumnHelper.renderDateTime(value, metaData, record) + " {{i18n PLUGINS_CORE_UI_TASKS_TOOL_PREVIOUS_FIRE_TIME_PREVIOUS}}<br/>"
+ Ametys.grid.GridColumnHelper.renderDateTime(record.data.fireTime, metaData, record) + " {{i18n PLUGINS_CORE_UI_TASKS_TOOL_RUNNING}}";
}
else
{
return Ametys.grid.GridColumnHelper.renderDateTime(record.data.fireTime, metaData, record) + " {{i18n PLUGINS_CORE_UI_TASKS_TOOL_RUNNING}}";
}
}
else
{
return Ametys.grid.GridColumnHelper.renderDateTime(value, metaData, record);
}
},
/**
* @private
* Duration renderer
* @param {Object} value The data value
* @param {Object} metaData A collection of metadata about the current cell
* @param {Ext.data.Model} record The record
*/
_renderDuration: function(value, metaData, record)
{
if (record.get('running'))
{
let data = record.data;
return this._renderDurationForProgressiveTask(value, data);
}
else
{
return !value ? '-' : Ext.util.Format.duration(value);
}
},
/**
* @private
* Round a percentage to the greater int, except if it is greater or equals to 99% tip renderer
* @param {Object} percentage The percentage
* @param {Boolean} fortooltip is for tooltip rendering
*/
_roundPercentage: function(percentage, fortooltip)
{
var round = fortooltip ? 1 : 100;
if (percentage >= 99)
{
return (Math.floor(percentage * round) / round);
}
else
{
return (Math.round(percentage * round) / round);
}
},
/**
* @private
* Duration progressive task tool tip renderer
* @param {Object} progressionTracker A progressionTracker
*/
_createProgressiveToolTipMessageForStep: function(progressionTracker)
{
let label = progressionTracker.label;
let messageToolTip = "";
if (label)
{
messageToolTip += "<li>";
let progressionAndLabel = "<span class='percent'>" + this._roundPercentage(progressionTracker.progression, true) + " %</span> - " + label;
let size = progressionTracker.size;
let hasSteps = progressionTracker.hasOwnProperty("steps");
if (progressionTracker.running)
{
if (size > 0 && !hasSteps)
{
progressionAndLabel += " " + progressionTracker.index + " / " + size;
}
messageToolTip += "<strong>" + progressionAndLabel + "</strong>" ;
if (hasSteps)
{
messageToolTip += "<ol>";
messageToolTip += this._handleSubStepsMessageToolTip(progressionTracker.steps);
messageToolTip += "</ol>";
}
}
else
{
messageToolTip += progressionAndLabel;
}
messageToolTip += "</li>";
}
else if (progressionTracker.running && progressionTracker.hasOwnProperty("steps"))
{
messageToolTip += this._handleSubStepsMessageToolTip(progressionTracker.steps);
}
return messageToolTip;
},
_handleSubStepsMessageToolTip: function(steps)
{
let messageToolTip = "";
if (steps.length <= Ametys.plugins.coreui.schedule.ScheduledTasksTool.__PROGRESSION_MAXCHILDREN)
{
for (let step of steps)
{
messageToolTip += this._createProgressiveToolTipMessageForStep(step);
}
}
else
{
var countBefore = 0;
for (let step of steps)
{
if (step.running)
{
if (countBefore == 1)
{
messageToolTip += this._createProgressiveToolTipMessageForStep(steps[0]);
}
else if (countBefore > 1)
{
// display the .. before
messageToolTip += "<li><span class='percent'>100 %</span> - [1... " + countBefore + "]</li>"
}
messageToolTip += this._createProgressiveToolTipMessageForStep(step);
countAfter = steps.length - countBefore - 1;
if (countAfter == 1)
{
messageToolTip += this._createProgressiveToolTipMessageForStep(steps[steps.length - 1]);
}
if (countAfter > 1)
{
// display the .. after
messageToolTip += "<li><span class='percent'>0 %</span> - [" + (countBefore + 2) + "..." + steps.length + "]</li>"
}
break;
}
else
{
countBefore++;
}
}
}
return messageToolTip;
},
/**
* @private
* Render duration for progressive task
* @param {Object} data The data
*/
_renderDurationForProgressiveTask: function(value, data)
{
let result = "<div>";
let progressionTracker = data.progressionTracker;
let steps = [];
if (progressionTracker.hasOwnProperty("steps"))
{
steps = progressionTracker.steps;
}
let progression = this._roundPercentage(progressionTracker.progression);
let duration = " - ";
if (data.duration)
{
duration = Ext.util.Format.duration(data.duration);
}
let progressionLabel = "";
if (!steps || steps.length == 0)
{
progressionLabel = duration + " {{i18n PLUGINS_CORE_UI_TASKS_TOOL_RUNNING}}";
}
else
{
progressionLabel = Ext.String.format("{{i18n PLUGINS_CORE_UI_TASKS_TOOL_PREVIOUS_FIRE_TIME_AND_RUNNING_PROGRESSIVE}}",
duration,
progression);
let messageToolTip = "<ol class='schedule-tip'>";
messageToolTip += this._handleSubStepsMessageToolTip(steps);
messageToolTip += "</ol>";
result = "<div data-qtip=\"" + messageToolTip + "\">";
if (progressionTracker.size > 1)
{
progressionLabel += " " + Ext.String.format("{{i18n PLUGINS_CORE_UI_TASKS_TOOL_PREVIOUS_FIRE_TIME_AND_RUNNING_PROGRESSIVE_STEP}}",
progressionTracker.index,
progressionTracker.size);
}
}
let progressionMessage = "";
if (value)
{
progressionMessage += Ext.util.Format.duration(value) + " {{i18n PLUGINS_CORE_UI_TASKS_TOOL_PREVIOUS_FIRE_TIME_PREVIOUS}}<br/>";
}
progressionMessage += progressionLabel;
result += progressionMessage + "</div>";
return result;
},
/**
* @private
*/
_isFilterOnCompleteTaskActive: function()
{
return this._filterCompleteBtn.pressed;
},
/**
* @private
*/
_activeCompleteFilter: function(btn, state)
{
if (state)
{
btn.setTooltip("{{i18n PLUGINS_CORE_UI_TASKS_TOOL_FILTER_SHOW_COMPLETE}}")
}
else
{
btn.setTooltip("{{i18n PLUGINS_CORE_UI_TASKS_TOOL_FILTER_HIDE_COMPLETE}}");
}
this._filterTasks();
},
/**
* @private
* Clear the current filter
*/
_clearSearchFilter: function()
{
this._grid.down("#search-filter-input").reset();
this._filterValue = null;
this._filterTasks();
},
/**
* @private
* Filters tasks by active filters (search input field and toggle filter button)
*/
_filterTasks: function()
{
var value = Ext.String.trim(this._grid.down("#search-filter-input").getValue());
var hideComplete = this._isFilterOnCompleteTaskActive();
if (this._filterValue == value && hideComplete == this._filterComplete)
{
// Do nothing (filters didn't change)
return;
}
this._filterComplete = hideComplete;
this._filterValue = value;
if (this._filterValue == null && !this._filterComplete)
{
this._store.clearFilter();
return;
}
var regexFilter = this._filterValue ? new RegExp(this._filterValue, 'i') : null;
this._store.clearFilter();
this._store.filterBy(function(record){
return (regexFilter == null
|| regexFilter.test(record.data.label)
|| regexFilter.test(record.data.description)
|| regexFilter.test(record.data.schedulableLabel)
|| regexFilter.test(record.data.schedulableDescription))
&& (!hideComplete || !record.data.completed);
});
var currentSelection = this._grid.getSelection();
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]);
}
})
}
},
/**
* Listener on creation message.
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onMessageCreated: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.TASK);
if (targets.length > 0)
{
this.showOutOfDate();
}
},
/**
* Listener on edition message.
* @param {Ametys.message.Message} message The edition message.
* @private
*/
_onMessageModified: function(message)
{
var targets = message.getTargets(Ametys.message.MessageTarget.TASK);
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.TASK);
let records = targets.map(target => this._store.getById(target.getParameters().id));
this._grid.getSelectionModel().deselect(records);
this._store.remove(records);
}
});
/**
* This class is the model for entries in the grid of the scheduled tasks
* @private
*/
Ext.define("Ametys.plugins.coreui.schedule.ScheduledTasksTool.TaskEntry", {
extend: 'Ext.data.Model',
fields: [
{name: 'id'},
{name: 'label', type: 'string'},
{name: 'description'},
{name: 'cronExpression', convert: function(v, rec) {
switch (rec.get('fireProcess')) {
case "NEVER":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NEVER_TASK}}";
case "STARTUP":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_STARTUP_TASK}}";
case "NOW":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NOW_TASK}}";
case "CRON":
default:
return v || "-";
}
}},
{name: 'enabled', defaultValue: false},
{name: 'completed', defaultValue: false},
{
name: 'group',
calculate: function(data) {
return data.running ? "0" : (data.completed ? "1" : (data.enabled ? "2" : "3"));
}
},
{name: 'modifiable'},
{name: 'removable'},
{name: 'deactivatable'},
{name: 'schedulableId', mapping: function(data) {return data.schedulable.id;}},
{name: 'schedulableLabel', mapping: function(data) {return data.schedulable.label;}},
{name: 'schedulableDescription', mapping: function(data) {return data.schedulable.description;}},
{name: 'schedulableParameters', mapping: function(data) {return data.schedulable.parameters;}},
{name: 'iconGlyph', mapping: function(data) {return data.schedulable.iconGlyph;}},
{name: 'iconSmall', mapping: function(data) {return data.schedulable.iconSmall;}},
{name: 'private', mapping: function(data) {return data.schedulable['private'];}},
{name: 'launchUser'},
{name: 'nextFireTime', convert: function(v, rec) {
if (rec.get('completed'))
{
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NO_NEXT_EXECUTION}}";
}
switch (rec.get('fireProcess')) {
case "STARTUP":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NEXT_STARTUP_TASK}}";
case "NOW":
return "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NO_NEXT_EXECUTION}}";
case "CRON":
default:
return v || "{{i18n PLUGINS_CORE_UI_TASKS_TOOL_NO_NEXT_EXECUTION}}";
}
}},
{name: 'previousFireTime'},
{name: 'lastDuration'},
{name: 'success'},
{name: 'running'},
{name: 'fireProcess'},
{name: 'state'}
]
});