]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/node/Tasks.js
task viewer: show task endtime and duration in status
[proxmox-widget-toolkit.git] / src / node / Tasks.js
1 Ext.define('Proxmox.node.Tasks', {
2 extend: 'Ext.grid.GridPanel',
3
4 alias: ['widget.proxmoxNodeTasks'],
5 stateful: true,
6 stateId: 'grid-node-tasks',
7 loadMask: true,
8 sortableColumns: false,
9 vmidFilter: 0,
10
11 initComponent: function() {
12 let me = this;
13
14 if (!me.nodename) {
15 throw "no node name specified";
16 }
17
18 let store = Ext.create('Ext.data.BufferedStore', {
19 pageSize: 500,
20 autoLoad: true,
21 remoteFilter: true,
22 model: 'proxmox-tasks',
23 proxy: {
24 type: 'proxmox',
25 startParam: 'start',
26 limitParam: 'limit',
27 url: "/api2/json/nodes/" + me.nodename + "/tasks",
28 },
29 });
30
31 let userfilter = '';
32 let filter_errors = 0;
33
34 let updateProxyParams = function() {
35 let params = {
36 errors: filter_errors,
37 };
38 if (userfilter) {
39 params.userfilter = userfilter;
40 }
41 if (me.vmidFilter) {
42 params.vmid = me.vmidFilter;
43 }
44 store.proxy.extraParams = params;
45 };
46
47 updateProxyParams();
48
49 let reload_task = Ext.create('Ext.util.DelayedTask', function() {
50 updateProxyParams();
51 store.reload();
52 });
53
54 let run_task_viewer = function() {
55 let sm = me.getSelectionModel();
56 let rec = sm.getSelection()[0];
57 if (!rec) {
58 return;
59 }
60
61 let win = Ext.create('Proxmox.window.TaskViewer', {
62 upid: rec.data.upid,
63 endtime: rec.data.endtime,
64 });
65 win.show();
66 };
67
68 let view_btn = new Ext.Button({
69 text: gettext('View'),
70 disabled: true,
71 handler: run_task_viewer,
72 });
73
74 Proxmox.Utils.monStoreErrors(me, store, true);
75
76 Ext.apply(me, {
77 store: store,
78 viewConfig: {
79 trackOver: false,
80 stripeRows: false, // does not work with getRowClass()
81
82 getRowClass: function(record, index) {
83 let status = record.get('status');
84
85 if (status) {
86 let parsed = Proxmox.Utils.parse_task_status(status);
87 if (parsed === 'error') {
88 return "proxmox-invalid-row";
89 } else if (parsed === 'warning') {
90 return "proxmox-warning-row";
91 }
92 }
93 return '';
94 },
95 },
96 tbar: [
97 view_btn,
98 {
99 text: gettext('Refresh'), // FIXME: smart-auto-refresh store
100 handler: () => store.reload(),
101 },
102 '->',
103 gettext('User name') +':',
104 ' ',
105 {
106 xtype: 'textfield',
107 width: 200,
108 value: userfilter,
109 enableKeyEvents: true,
110 listeners: {
111 keyup: function(field, e) {
112 userfilter = field.getValue();
113 reload_task.delay(500);
114 },
115 },
116 }, ' ', gettext('Only Errors') + ':', ' ',
117 {
118 xtype: 'checkbox',
119 hideLabel: true,
120 checked: filter_errors,
121 listeners: {
122 change: function(field, checked) {
123 filter_errors = checked ? 1 : 0;
124 reload_task.delay(10);
125 },
126 },
127 }, ' ',
128 ],
129 columns: [
130 {
131 header: gettext("Start Time"),
132 dataIndex: 'starttime',
133 width: 130,
134 renderer: function(value) {
135 return Ext.Date.format(value, "M d H:i:s");
136 },
137 },
138 {
139 header: gettext("End Time"),
140 dataIndex: 'endtime',
141 width: 130,
142 renderer: function(value, metaData, record) {
143 if (!value) {
144 metaData.tdCls = "x-grid-row-loading";
145 return '';
146 }
147 return Ext.Date.format(value, "M d H:i:s");
148 },
149 },
150 {
151 header: gettext("Node"),
152 dataIndex: 'node',
153 width: 120,
154 },
155 {
156 header: gettext("User name"),
157 dataIndex: 'user',
158 width: 150,
159 },
160 {
161 header: gettext("Description"),
162 dataIndex: 'upid',
163 flex: 1,
164 renderer: Proxmox.Utils.render_upid,
165 },
166 {
167 header: gettext("Status"),
168 dataIndex: 'status',
169 width: 200,
170 renderer: function(value, metaData, record) {
171 if (value === undefined && !record.data.endtime) {
172 metaData.tdCls = "x-grid-row-loading";
173 return '';
174 }
175
176 let parsed = Proxmox.Utils.parse_task_status(value);
177 switch (parsed) {
178 case 'unknown': return Proxmox.Utils.unknownText;
179 case 'error': return Proxmox.Utils.errorText + ': ' + value;
180 case 'ok': // fall-through
181 case 'warning': // fall-through
182 default: return value;
183 }
184 },
185 },
186 ],
187 listeners: {
188 itemdblclick: run_task_viewer,
189 selectionchange: function(v, selections) {
190 view_btn.setDisabled(!(selections && selections[0]));
191 },
192 show: function() { reload_task.delay(10); },
193 destroy: function() { reload_task.cancel(); },
194 },
195 });
196
197 me.callParent();
198 },
199 });