ui: use task list component from widget toolkit
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
73b77d4787
commit
c7d032fc17
|
@ -78,7 +78,6 @@ JSSRC= \
|
||||||
dashboard/LongestTasks.js \
|
dashboard/LongestTasks.js \
|
||||||
dashboard/RunningTasks.js \
|
dashboard/RunningTasks.js \
|
||||||
dashboard/TaskSummary.js \
|
dashboard/TaskSummary.js \
|
||||||
panel/Tasks.js \
|
|
||||||
panel/XtermJsConsole.js \
|
panel/XtermJsConsole.js \
|
||||||
panel/AccessControl.js \
|
panel/AccessControl.js \
|
||||||
panel/StorageAndDisks.js \
|
panel/StorageAndDisks.js \
|
||||||
|
|
|
@ -61,12 +61,21 @@ Ext.define('PBS.ServerAdministration', {
|
||||||
url: "/api2/extjs/nodes/localhost/journal",
|
url: "/api2/extjs/nodes/localhost/journal",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'pbsNodeTasks',
|
xtype: 'proxmoxNodeTasks',
|
||||||
itemId: 'tasks',
|
itemId: 'tasks',
|
||||||
iconCls: 'fa fa-list-alt',
|
iconCls: 'fa fa-list-alt',
|
||||||
title: gettext('Tasks'),
|
title: gettext('Tasks'),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
nodename: 'localhost',
|
nodename: 'localhost',
|
||||||
|
extraFilter: [
|
||||||
|
{
|
||||||
|
xtype: 'pbsDataStoreSelector',
|
||||||
|
fieldLabel: gettext('Datastore'),
|
||||||
|
emptyText: gettext('All'),
|
||||||
|
name: 'store',
|
||||||
|
allowBlank: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,10 +14,6 @@
|
||||||
background-color: #3892d4;
|
background-color: #3892d4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-blue {
|
|
||||||
color: #3892d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make the upper window end visible */
|
/* make the upper window end visible */
|
||||||
.x-css-shadow {
|
.x-css-shadow {
|
||||||
box-shadow: rgb(136,136,136) 0px -1px 15px !important;
|
box-shadow: rgb(136,136,136) 0px -1px 15px !important;
|
||||||
|
|
|
@ -1,379 +0,0 @@
|
||||||
Ext.define('PBS.node.Tasks', {
|
|
||||||
extend: 'Ext.grid.GridPanel',
|
|
||||||
|
|
||||||
alias: 'widget.pbsNodeTasks',
|
|
||||||
|
|
||||||
stateful: true,
|
|
||||||
stateId: 'pbs-grid-node-tasks',
|
|
||||||
|
|
||||||
loadMask: true,
|
|
||||||
sortableColumns: false,
|
|
||||||
|
|
||||||
controller: {
|
|
||||||
xclass: 'Ext.app.ViewController',
|
|
||||||
|
|
||||||
showTaskLog: function() {
|
|
||||||
let me = this;
|
|
||||||
let selection = me.getView().getSelection();
|
|
||||||
if (selection.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let rec = selection[0];
|
|
||||||
|
|
||||||
Ext.create('Proxmox.window.TaskViewer', {
|
|
||||||
upid: rec.data.upid,
|
|
||||||
endtime: rec.data.endtime,
|
|
||||||
}).show();
|
|
||||||
},
|
|
||||||
|
|
||||||
updateLayout: function() {
|
|
||||||
let me = this;
|
|
||||||
// we want to update the scrollbar on every store load
|
|
||||||
// since the total count might be different
|
|
||||||
// the buffered grid plugin does this only on scrolling itself
|
|
||||||
// and even reduces the scrollheight again when scrolling up
|
|
||||||
me.getView().updateLayout();
|
|
||||||
},
|
|
||||||
|
|
||||||
sinceChange: function(field, newval) {
|
|
||||||
let me = this;
|
|
||||||
let vm = me.getViewModel();
|
|
||||||
|
|
||||||
vm.set('since', newval);
|
|
||||||
},
|
|
||||||
|
|
||||||
untilChange: function(field, newval, oldval) {
|
|
||||||
let me = this;
|
|
||||||
let vm = me.getViewModel();
|
|
||||||
|
|
||||||
vm.set('until', newval);
|
|
||||||
},
|
|
||||||
|
|
||||||
reload: function() {
|
|
||||||
let me = this;
|
|
||||||
let view = me.getView();
|
|
||||||
view.getStore().load();
|
|
||||||
},
|
|
||||||
|
|
||||||
showFilter: function(btn, pressed) {
|
|
||||||
let me = this;
|
|
||||||
let vm = me.getViewModel();
|
|
||||||
vm.set('showFilter', pressed);
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function(view) {
|
|
||||||
let me = this;
|
|
||||||
Proxmox.Utils.monStoreErrors(view, view.getStore(), true);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
listeners: {
|
|
||||||
itemdblclick: 'showTaskLog',
|
|
||||||
},
|
|
||||||
|
|
||||||
viewModel: {
|
|
||||||
data: {
|
|
||||||
typefilter: '',
|
|
||||||
statusfilter: '',
|
|
||||||
datastore: '',
|
|
||||||
showFilter: false,
|
|
||||||
since: null,
|
|
||||||
until: null,
|
|
||||||
},
|
|
||||||
|
|
||||||
formulas: {
|
|
||||||
filterIcon: (get) => 'fa fa-filter' + (get('showFilter') ? ' info-blue' : ''),
|
|
||||||
extraParams: function(get) {
|
|
||||||
let me = this;
|
|
||||||
let params = {};
|
|
||||||
if (get('typefilter')) {
|
|
||||||
params.typefilter = get('typefilter');
|
|
||||||
}
|
|
||||||
if (get('statusfilter')) {
|
|
||||||
params.statusfilter = get('statusfilter');
|
|
||||||
}
|
|
||||||
if (get('datastore')) {
|
|
||||||
params.store = get('datastore');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get('since')) {
|
|
||||||
params.since = get('since').valueOf()/1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get('until')) {
|
|
||||||
let until = new Date(get('until').getTime()); // copy object
|
|
||||||
until.setDate(until.getDate() + 1); // end of the day
|
|
||||||
params.until = until.valueOf()/1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
me.getView().getStore().load();
|
|
||||||
|
|
||||||
return params;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
stores: {
|
|
||||||
bufferedstore: {
|
|
||||||
type: 'buffered',
|
|
||||||
pageSize: 500,
|
|
||||||
autoLoad: true,
|
|
||||||
remoteFilter: true,
|
|
||||||
model: 'proxmox-tasks',
|
|
||||||
proxy: {
|
|
||||||
type: 'proxmox',
|
|
||||||
startParam: 'start',
|
|
||||||
limitParam: 'limit',
|
|
||||||
extraParams: '{extraParams}',
|
|
||||||
url: "/api2/json/nodes/localhost/tasks",
|
|
||||||
},
|
|
||||||
listeners: {
|
|
||||||
prefetch: 'updateLayout',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
bind: {
|
|
||||||
store: '{bufferedstore}',
|
|
||||||
},
|
|
||||||
|
|
||||||
dockedItems: [
|
|
||||||
{
|
|
||||||
xtype: 'toolbar',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'proxmoxButton',
|
|
||||||
text: gettext('View'),
|
|
||||||
iconCls: 'fa fa-window-restore',
|
|
||||||
disabled: true,
|
|
||||||
handler: 'showTaskLog',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'button',
|
|
||||||
text: gettext('Reload'),
|
|
||||||
iconCls: 'fa fa-refresh',
|
|
||||||
handler: 'reload',
|
|
||||||
},
|
|
||||||
'->',
|
|
||||||
{
|
|
||||||
xtype: 'button',
|
|
||||||
enableToggle: true,
|
|
||||||
bind: {
|
|
||||||
iconCls: '{filterIcon}',
|
|
||||||
},
|
|
||||||
text: gettext('Filter'),
|
|
||||||
stateful: true,
|
|
||||||
stateId: 'task-showfilter',
|
|
||||||
stateEvents: ['toggle'],
|
|
||||||
applyState: function(state) {
|
|
||||||
if (state.pressed !== undefined) {
|
|
||||||
this.setPressed(state.pressed);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getState: function() {
|
|
||||||
return {
|
|
||||||
pressed: this.pressed,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
listeners: {
|
|
||||||
toggle: 'showFilter',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'toolbar',
|
|
||||||
dock: 'top',
|
|
||||||
layout: {
|
|
||||||
type: 'hbox',
|
|
||||||
align: 'top',
|
|
||||||
},
|
|
||||||
bind: {
|
|
||||||
hidden: '{!showFilter}',
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'container',
|
|
||||||
padding: 10,
|
|
||||||
layout: {
|
|
||||||
type: 'vbox',
|
|
||||||
align: 'stretch',
|
|
||||||
},
|
|
||||||
defaults: {
|
|
||||||
labelWidth: 80,
|
|
||||||
},
|
|
||||||
// cannot bind the values directly, as it then changes also
|
|
||||||
// on blur, causing wrong reloads of the store
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'datefield',
|
|
||||||
fieldLabel: gettext('Since'),
|
|
||||||
format: 'Y-m-d',
|
|
||||||
bind: {
|
|
||||||
maxValue: '{until}',
|
|
||||||
},
|
|
||||||
listeners: {
|
|
||||||
change: 'sinceChange',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'datefield',
|
|
||||||
fieldLabel: gettext('Until'),
|
|
||||||
format: 'Y-m-d',
|
|
||||||
bind: {
|
|
||||||
minValue: '{since}',
|
|
||||||
},
|
|
||||||
listeners: {
|
|
||||||
change: 'untilChange',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'container',
|
|
||||||
padding: 10,
|
|
||||||
layout: {
|
|
||||||
type: 'vbox',
|
|
||||||
align: 'stretch',
|
|
||||||
},
|
|
||||||
defaults: {
|
|
||||||
labelWidth: 80,
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'pmxTaskTypeSelector',
|
|
||||||
fieldLabel: gettext('Task Type'),
|
|
||||||
emptyText: gettext('All'),
|
|
||||||
bind: {
|
|
||||||
value: '{typefilter}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'combobox',
|
|
||||||
fieldLabel: gettext('Task Result'),
|
|
||||||
emptyText: gettext('All'),
|
|
||||||
multiSelect: true,
|
|
||||||
store: [
|
|
||||||
['ok', gettext('OK')],
|
|
||||||
['unknown', Proxmox.Utils.unknownText],
|
|
||||||
['warning', gettext('Warnings')],
|
|
||||||
['error', gettext('Errors')],
|
|
||||||
],
|
|
||||||
bind: {
|
|
||||||
value: '{statusfilter}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
xtype: 'container',
|
|
||||||
padding: 10,
|
|
||||||
layout: {
|
|
||||||
type: 'vbox',
|
|
||||||
align: 'stretch',
|
|
||||||
},
|
|
||||||
defaults: {
|
|
||||||
labelWidth: 80,
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'pbsDataStoreSelector',
|
|
||||||
fieldLabel: gettext('Datastore'),
|
|
||||||
emptyText: gettext('All'),
|
|
||||||
bind: {
|
|
||||||
value: '{datastore}',
|
|
||||||
},
|
|
||||||
allowBlank: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
viewConfig: {
|
|
||||||
trackOver: false,
|
|
||||||
stripeRows: false, // does not work with getRowClass()
|
|
||||||
emptyText: gettext('No Tasks found'),
|
|
||||||
|
|
||||||
getRowClass: function(record, index) {
|
|
||||||
let status = record.get('status');
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
let parsed = Proxmox.Utils.parse_task_status(status);
|
|
||||||
if (parsed === 'error') {
|
|
||||||
return "proxmox-invalid-row";
|
|
||||||
} else if (parsed === 'warning') {
|
|
||||||
return "proxmox-warning-row";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
header: gettext("Start Time"),
|
|
||||||
dataIndex: 'starttime',
|
|
||||||
width: 130,
|
|
||||||
renderer: function(value) {
|
|
||||||
return Ext.Date.format(value, "M d H:i:s");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext("End Time"),
|
|
||||||
dataIndex: 'endtime',
|
|
||||||
width: 130,
|
|
||||||
renderer: function(value, metaData, record) {
|
|
||||||
if (!value) {
|
|
||||||
metaData.tdCls = "x-grid-row-loading";
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return Ext.Date.format(value, "M d H:i:s");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext("Duration"),
|
|
||||||
hidden: true,
|
|
||||||
width: 80,
|
|
||||||
renderer: function(value, metaData, record) {
|
|
||||||
let start = record.data.starttime;
|
|
||||||
if (start) {
|
|
||||||
let end = record.data.endtime || Date.now();
|
|
||||||
let duration = end - start;
|
|
||||||
if (duration > 0) {
|
|
||||||
duration /= 1000;
|
|
||||||
}
|
|
||||||
return Proxmox.Utils.format_duration_human(duration);
|
|
||||||
}
|
|
||||||
return Proxmox.Utils.unknownText;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext("User name"),
|
|
||||||
dataIndex: 'user',
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext("Description"),
|
|
||||||
dataIndex: 'upid',
|
|
||||||
flex: 1,
|
|
||||||
renderer: Proxmox.Utils.render_upid,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext("Status"),
|
|
||||||
dataIndex: 'status',
|
|
||||||
width: 200,
|
|
||||||
renderer: function(value, metaData, record) {
|
|
||||||
if (value === undefined && !record.data.endtime) {
|
|
||||||
metaData.tdCls = "x-grid-row-loading";
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return Proxmox.Utils.format_task_status(value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
Loading…
Reference in New Issue