]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/TaskViewer.js
bump version to 4.2.3
[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');
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({ text: gettext('running...') });
83 },
84 });
85
86 Ext.define('Proxmox.window.TaskViewer', {
87 extend: 'Ext.window.Window',
88 alias: 'widget.proxmoxTaskViewer',
89
90 extraTitle: '', // string to prepend after the generic task title
91
92 taskDone: Ext.emptyFn,
93
94 initComponent: function() {
95 let me = this;
96
97 if (!me.upid) {
98 throw "no task specified";
99 }
100
101 let task = Proxmox.Utils.parse_task_upid(me.upid);
102
103 let statgrid;
104
105 let rows = {
106 status: {
107 header: gettext('Status'),
108 defaultValue: 'unknown',
109 renderer: function(value) {
110 if (value !== 'stopped') {
111 return value;
112 }
113 let es = statgrid.getObjectValue('exitstatus');
114 if (es) {
115 return value + ': ' + es;
116 }
117 return 'unknown';
118 },
119 },
120 exitstatus: {
121 visible: false,
122 },
123 type: {
124 header: gettext('Task type'),
125 required: true,
126 },
127 user: {
128 header: gettext('User name'),
129 renderer: function(value) {
130 let user = value;
131 let tokenid = statgrid.getObjectValue('tokenid');
132 if (tokenid) {
133 user += `!${tokenid} (API Token)`;
134 }
135 return Ext.String.htmlEncode(user);
136 },
137 required: true,
138 },
139 tokenid: {
140 header: gettext('API Token'),
141 renderer: Ext.String.htmlEncode,
142 visible: false,
143 },
144 node: {
145 header: gettext('Node'),
146 required: true,
147 },
148 pid: {
149 header: gettext('Process ID'),
150 required: true,
151 },
152 task_id: {
153 header: gettext('Task ID'),
154 },
155 starttime: {
156 header: gettext('Start Time'),
157 required: true,
158 renderer: Proxmox.Utils.render_timestamp,
159 },
160 upid: {
161 header: gettext('Unique task ID'),
162 renderer: Ext.String.htmlEncode,
163 },
164 };
165
166 if (me.endtime) {
167 if (typeof me.endtime === 'object') {
168 // convert to epoch
169 me.endtime = parseInt(me.endtime.getTime()/1000, 10);
170 }
171 rows.endtime = {
172 header: gettext('End Time'),
173 required: true,
174 renderer: function() {
175 return Proxmox.Utils.render_timestamp(me.endtime);
176 },
177 };
178 }
179
180 rows.duration = {
181 header: gettext('Duration'),
182 required: true,
183 renderer: function() {
184 let starttime = statgrid.getObjectValue('starttime');
185 let endtime = me.endtime || Date.now()/1000;
186 let duration = endtime - starttime;
187 return Proxmox.Utils.format_duration_human(duration);
188 },
189 };
190
191 let statstore = Ext.create('Proxmox.data.ObjectStore', {
192 url: `/api2/json/nodes/${task.node}/tasks/${encodeURIComponent(me.upid)}/status`,
193 interval: 1000,
194 rows: rows,
195 });
196
197 me.on('destroy', statstore.stopUpdate);
198
199 let stop_task = function() {
200 Proxmox.Utils.API2Request({
201 url: `/nodes/${task.node}/tasks/${encodeURIComponent(me.upid)}`,
202 waitMsgTarget: me,
203 method: 'DELETE',
204 failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
205 });
206 };
207
208 let stop_btn1 = new Ext.Button({
209 text: gettext('Stop'),
210 disabled: true,
211 handler: stop_task,
212 });
213
214 let stop_btn2 = new Ext.Button({
215 text: gettext('Stop'),
216 disabled: true,
217 handler: stop_task,
218 });
219
220 statgrid = Ext.create('Proxmox.grid.ObjectGrid', {
221 title: gettext('Status'),
222 layout: 'fit',
223 tbar: [stop_btn1],
224 rstore: statstore,
225 rows: rows,
226 border: false,
227 });
228
229 let downloadBtn = new Ext.Button({
230 text: gettext('Download'),
231 iconCls: 'fa fa-download',
232 handler: () => Proxmox.Utils.downloadAsFile(
233 `/api2/json/nodes/${task.node}/tasks/${encodeURIComponent(me.upid)}/log?download=1`),
234 });
235
236
237 let logView = Ext.create('Proxmox.panel.LogView', {
238 title: gettext('Output'),
239 tbar: [stop_btn2, '->', downloadBtn],
240 border: false,
241 url: `/api2/extjs/nodes/${task.node}/tasks/${encodeURIComponent(me.upid)}/log`,
242 });
243
244 me.mon(statstore, 'load', function() {
245 let status = statgrid.getObjectValue('status');
246
247 if (status === 'stopped') {
248 logView.scrollToEnd = false;
249 logView.requestUpdate();
250 statstore.stopUpdate();
251 me.taskDone(statgrid.getObjectValue('exitstatus') === 'OK');
252 }
253
254 stop_btn1.setDisabled(status !== 'running');
255 stop_btn2.setDisabled(status !== 'running');
256 downloadBtn.setDisabled(status === 'running');
257 });
258
259 statstore.startUpdate();
260
261 Ext.apply(me, {
262 title: "Task viewer: " + task.desc + me.extraTitle,
263 width: 800,
264 height: 500,
265 layout: 'fit',
266 modal: true,
267 items: [{
268 xtype: 'tabpanel',
269 region: 'center',
270 items: [logView, statgrid],
271 }],
272 });
273
274 me.callParent();
275
276 logView.fireEvent('show', logView);
277 },
278 });
279