]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/TaskViewer.js
window: task viewer: code refactoring
[proxmox-widget-toolkit.git] / src / window / TaskViewer.js
1 Ext.define('Proxmox.window.TaskProgress', {
2 extend: 'Ext.window.Window',
3 alias: 'widget.proxmoxTaskProgress',
4
5 taskDone: Ext.emptyFn,
6
7 width: 300,
8 layout: 'auto',
9 modal: true,
10 bodyPadding: 5,
11
12 initComponent: function() {
13 let me = this;
14
15 if (!me.upid) {
16 throw "no task specified";
17 }
18
19 let task = Proxmox.Utils.parse_task_upid(me.upid);
20
21 let statstore = Ext.create('Proxmox.data.ObjectStore', {
22 url: `/api2/json/nodes/${task.node}/tasks/${encodeURIComponent(me.upid)}/status`,
23 interval: 1000,
24 rows: {
25 status: { defaultValue: 'unknown' },
26 exitstatus: { defaultValue: 'unknown' },
27 },
28 });
29
30 me.on('destroy', statstore.stopUpdate);
31
32 let getObjectValue = function(key, defaultValue) {
33 let rec = statstore.getById(key);
34 if (rec) {
35 return rec.data.value;
36 }
37 return defaultValue;
38 };
39
40 let pbar = Ext.create('Ext.ProgressBar', { text: 'running...' });
41
42 me.mon(statstore, 'load', function() {
43 let status = getObjectValue('status');
44 if (status === 'stopped') {
45 let exitstatus = getObjectValue('exitstatus');
46 if (exitstatus === 'OK') {
47 pbar.reset();
48 pbar.updateText("Done!");
49 Ext.Function.defer(me.close, 1000, me);
50 } else {
51 me.close();
52 Ext.Msg.alert('Task failed', exitstatus);
53 }
54 me.taskDone(exitstatus === 'OK');
55 }
56 });
57
58 let descr = Proxmox.Utils.format_task_description(task.type, task.id);
59
60 Ext.apply(me, {
61 title: gettext('Task') + ': ' + descr,
62 items: pbar,
63 buttons: [
64 {
65 text: gettext('Details'),
66 handler: function() {
67 Ext.create('Proxmox.window.TaskViewer', {
68 autoShow: true,
69 taskDone: me.taskDone,
70 upid: me.upid,
71 });
72 me.close();
73 },
74 },
75 ],
76 });
77
78 me.callParent();
79
80 statstore.startUpdate();
81
82 pbar.wait();
83 },
84 });
85
86 // fixme: how can we avoid those lint errors?
87
88 Ext.define('Proxmox.window.TaskViewer', {
89 extend: 'Ext.window.Window',
90 alias: 'widget.proxmoxTaskViewer',
91
92 extraTitle: '', // string to prepend after the generic task title
93
94 taskDone: Ext.emptyFn,
95
96 initComponent: function() {
97 let me = this;
98
99 if (!me.upid) {
100 throw "no task specified";
101 }
102
103 let task = Proxmox.Utils.parse_task_upid(me.upid);
104
105 let statgrid;
106
107 let rows = {
108 status: {
109 header: gettext('Status'),
110 defaultValue: 'unknown',
111 renderer: function(value) {
112 if (value !== 'stopped') {
113 return value;
114 }
115 let es = statgrid.getObjectValue('exitstatus');
116 if (es) {
117 return value + ': ' + es;
118 }
119 return 'unknown';
120 },
121 },
122 exitstatus: {
123 visible: false,
124 },
125 type: {
126 header: gettext('Task type'),
127 required: true,
128 },
129 user: {
130 header: gettext('User name'),
131 renderer: function(value) {
132 let user = value;
133 let tokenid = statgrid.getObjectValue('tokenid');
134 if (tokenid) {
135 user += `!${tokenid} (API Token)`;
136 }
137 return Ext.String.htmlEncode(user);
138 },
139 required: true,
140 },
141 tokenid: {
142 header: gettext('API Token'),
143 renderer: Ext.String.htmlEncode,
144 visible: false,
145 },
146 node: {
147 header: gettext('Node'),
148 required: true,
149 },
150 pid: {
151 header: gettext('Process ID'),
152 required: true,
153 },
154 task_id: {
155 header: gettext('Task ID'),
156 },
157 starttime: {
158 header: gettext('Start Time'),
159 required: true,
160 renderer: Proxmox.Utils.render_timestamp,
161 },
162 upid: {
163 header: gettext('Unique task ID'),
164 renderer: Ext.String.htmlEncode,
165 },
166 };
167
168 if (me.endtime) {
169 if (typeof me.endtime === 'object') {
170 // convert to epoch
171 me.endtime = parseInt(me.endtime.getTime()/1000, 10);
172 }
173 rows.endtime = {
174 header: gettext('End Time'),
175 required: true,
176 renderer: function() {
177 return Proxmox.Utils.render_timestamp(me.endtime);
178 },
179 };
180 }
181
182 rows.duration = {
183 header: gettext('Duration'),
184 required: true,
185 renderer: function() {
186 let starttime = statgrid.getObjectValue('starttime');
187 let endtime = me.endtime || Date.now()/1000;
188 let duration = endtime - starttime;
189 return Proxmox.Utils.format_duration_human(duration);
190 },
191 };
192
193 let statstore = Ext.create('Proxmox.data.ObjectStore', {
194 url: "/api2/json/nodes/" + task.node + "/tasks/" + encodeURIComponent(me.upid) + "/status",
195 interval: 1000,
196 rows: rows,
197 });
198
199 me.on('destroy', statstore.stopUpdate);
200
201 let stop_task = function() {
202 Proxmox.Utils.API2Request({
203 url: "/nodes/" + task.node + "/tasks/" + encodeURIComponent(me.upid),
204 waitMsgTarget: me,
205 method: 'DELETE',
206 failure: function(response, opts) {
207 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
208 },
209 });
210 };
211
212 let stop_btn1 = new Ext.Button({
213 text: gettext('Stop'),
214 disabled: true,
215 handler: stop_task,
216 });
217
218 let stop_btn2 = new Ext.Button({
219 text: gettext('Stop'),
220 disabled: true,
221 handler: stop_task,
222 });
223
224 statgrid = Ext.create('Proxmox.grid.ObjectGrid', {
225 title: gettext('Status'),
226 layout: 'fit',
227 tbar: [stop_btn1],
228 rstore: statstore,
229 rows: rows,
230 border: false,
231 });
232
233 let logView = Ext.create('Proxmox.panel.LogView', {
234 title: gettext('Output'),
235 tbar: [stop_btn2],
236 border: false,
237 url: "/api2/extjs/nodes/" + task.node + "/tasks/" + encodeURIComponent(me.upid) + "/log",
238 });
239
240 me.mon(statstore, 'load', function() {
241 let status = statgrid.getObjectValue('status');
242
243 if (status === 'stopped') {
244 logView.scrollToEnd = false;
245 logView.requestUpdate();
246 statstore.stopUpdate();
247 me.taskDone(statgrid.getObjectValue('exitstatus') === 'OK');
248 }
249
250 stop_btn1.setDisabled(status !== 'running');
251 stop_btn2.setDisabled(status !== 'running');
252 });
253
254 statstore.startUpdate();
255
256 Ext.apply(me, {
257 title: "Task viewer: " + task.desc + me.extraTitle,
258 width: 800,
259 height: 500,
260 layout: 'fit',
261 modal: true,
262 items: [{
263 xtype: 'tabpanel',
264 region: 'center',
265 items: [logView, statgrid],
266 }],
267 });
268
269 me.callParent();
270
271 logView.fireEvent('show', logView);
272 },
273 });
274