]> git.argeo.org Git - gpl/argeo-slc.git/blob - server/org.argeo.slc.ria/src/argeo-ria-lib/slc/class/org/argeo/slc/ria/BatchView.js
Update API
[gpl/argeo-slc.git] / server / org.argeo.slc.ria / src / argeo-ria-lib / slc / class / org / argeo / slc / ria / BatchView.js
1 /**
2 * Applet for the batch manager
3 */
4 qx.Class.define("org.argeo.slc.ria.BatchView",
5 {
6 extend : qx.ui.container.Composite,
7 implement : [org.argeo.ria.components.IView],
8 include : [org.argeo.ria.session.MPrefHolder],
9 statics : {
10 riaPreferences : {
11 "slc.batch.delete.confirm" : {
12 label : "Confirm on batch deletion",
13 type : "boolean",
14 defaultValue : true
15 },
16 "slc.batch.autoclear" : {
17 label : "Autoclear batch on execution",
18 type : "boolean",
19 defaultValue : false
20 }
21 }
22 },
23 properties :
24 {
25 /**
26 * The commands definition Map that will be automatically added and wired to the menubar and toolbar.
27 * See {@link org.argeo.ria.event.CommandsManager#definitions} for the keys to use for defining commands.
28 */
29 commands : {
30 init : {
31 "submitform" : {
32 label : "Execute Batch",
33 icon : "org.argeo.slc.ria/media-playback-start.png",
34 shortcut : null,
35 enabled : false,
36 menu : "Launcher",
37 toolbar : "batch",
38 callback : function(e) {
39 var batchAgentId = this.getBatchAgentId();
40 if (!batchAgentId) {
41 return;
42 }
43 var prefName = "slc.batch.autoclear";
44 var prefValue = this.getRiaPreferenceValue(prefName);
45 if(prefValue !== null){
46 this.executeBatchOnAgent(batchAgentId, prefValue);
47 return;
48 }
49 var modal = new org.argeo.ria.components.Modal("Clear?", null);
50 modal.addYesNoReminder("Do you want to clear the batch automatically after execution?", prefName);
51 modal.addListener("cancel", function(e){
52 this.executeBatchOnAgent(batchAgentId, false);
53 }, this);
54 modal.addListener("ok", function(e){
55 this.executeBatchOnAgent(batchAgentId, true);
56 }, this);
57 modal.attachAndShow();
58 },
59 command : null
60 },
61 /*
62 "toggleopenonadd" : {
63 label : "Auto edit on Add",
64 icon : "org.argeo.slc.ria/document-open.png",
65 shortcut : null,
66 enabled : true,
67 toggle : true,
68 toggleInitialState : true,
69 menu : "Launcher",
70 toolbar : "launcher",
71 callback : function(event) {
72 var state = event.getTarget().getUserData("slc.command.toggleState");
73 this.setAutoOpen(state);
74 },
75 command : null
76 },
77 "editexecutionspecs" : {
78 label : "Edit Execution Specs",
79 icon : "org.argeo.slc.ria/document-open.png",
80 shortcut : null,
81 enabled : false,
82 menu : "Launcher",
83 toolbar : "batch",
84 callback : function(e) {
85 var sel = this.list.getSortedSelection();
86 var spec = sel[0].getUserData("batchEntrySpec");
87 if (spec.hasEditableValues()) {
88 var specEditor = new org.argeo.slc.ria.execution.SpecEditor(spec);
89 specEditor.attachAndShow();
90 }
91 },
92 selectionChange : function(viewId, selection) {
93 if (viewId != "batch:list")
94 return;
95 this.setEnabled(false);
96 if ((selection && selection.length == 1)) {
97 var selectedItemSpec = selection[0].getUserData("batchEntrySpec");
98 if (selectedItemSpec.hasEditableValues()) {
99 this.setEnabled(true);
100 }
101 }
102 },
103 command : null
104 },
105 */
106 "removefrombatch" : {
107 label : "Remove from batch",
108 icon : "org.argeo.slc.ria/edit-delete.png",
109 shortcut : null,
110 enabled : false,
111 menu : "Launcher",
112 toolbar : "batch",
113 callback : function(e) {
114 var sel = this.list.getSortedSelection();
115 var confirmPref = this.getRiaPreferenceValue("slc.batch.delete.confirm");
116 var execution = function() {
117 for (var i = 0; i < sel.length; i++) {
118 this.list.remove(sel[i]);
119 }
120 if (!this.list.hasChildren()) {
121 this.setBatchAgentId(null);
122 }
123 }
124 if(confirmPref){
125 var modal = new org.argeo.ria.components.Modal("Confirm", null);
126 modal.addConfirm("Are you sure you want to remove<br> the selected test"
127 + (sel.length > 1 ? "s" : "")
128 + " from the Batch?");
129 modal.addListener("ok", execution, this);
130 modal.attachAndShow();
131 }else{
132 execution = qx.lang.Function.bind(execution, this);
133 execution();
134 }
135 },
136 selectionChange : function(viewId, selection) {
137 if (viewId != "batch:list")
138 return;
139 this.setEnabled(false);
140 if ((selection && selection.length > 0))
141 this.setEnabled(true);
142 },
143 command : null
144 },
145 "clearbatch" : {
146 label : "Clear batch",
147 icon : "org.argeo.slc.ria/user-trash-full.png",
148 shortcut : null,
149 enabled : true,
150 menu : "Launcher",
151 toolbar : "batch",
152 callback : function(e) {
153 if(!this.list.hasChildren()) return;
154 this.list.selectAll();
155 this.getCommands()["removefrombatch"].command.execute();
156 },
157 selectionChange : function(viewId, selection) {
158 },
159 command : null
160 }
161 }
162 },
163 view : {
164 init : null
165 },
166 viewSelection : {
167 nullable:false,
168 check:"org.argeo.ria.components.ViewSelection"
169 },
170 instanceId : {init:""},
171 instanceLabel : {init:""},
172 /**
173 * A boolean registering whether the SpecEditor must autoOpen or not
174 * when a spec is added to the Batch.
175 */
176 autoOpen : {
177 init : true,
178 check : "Boolean"
179 },
180 batchAgentId : {
181 init : null,
182 nullable : true,
183 check : "String",
184 event : "changeBatchAgentId"
185 }
186 },
187
188 construct : function(){
189 this.base(arguments);
190 this.setLayout(new qx.ui.layout.Dock());
191 },
192
193 members : {
194 /**
195 * The implementation should contain the GUI initialisation.
196 * This is the role of the manager to actually add the graphical component to the pane,
197 * so it's not necessary to do it here.
198 * @param viewPane {org.argeo.ria.components.ViewPane} The pane manager
199 * @param data {Mixed} Any object or data passed by the initiator of the view
200 * @return {Boolean}
201 */
202 init : function(viewPane, data){
203 this.setView(viewPane);
204 this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));
205 this._emptyAgentString = "Empty Batch (Drop scripts here)";
206 this._crtAgentString = "Batch Execution on Agent ";
207
208 },
209 /**
210 * The implementation should contain the real data loading (i.o. query...)
211 * @return {Boolean}
212 */
213 load : function(){
214 this._createLayout();
215 this.getView().setViewTitle(this._emptyAgentString);
216 //this.getView().setViewTitle("");
217 },
218
219 /**
220 * Creates the main applet layout.
221 */
222 _createLayout : function() {
223 this.listPane = new qx.ui.container.Composite(new qx.ui.layout.Dock());
224 this.addListener("changeBatchAgentId", function(event) {
225 var value = event.getData();
226 if (value == null) {
227 this.getView().setViewTitle(this._emptyAgentString);
228 } else {
229 var selectorView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("selector").getContent();
230 if(selectorView){
231 var agentsMap = selectorView.getAgentsMap();
232 this.getView().setViewTitle(this._crtAgentString + "'" + agentsMap[value] + "'");
233 }
234 }
235 }, this);
236
237 var indicator = new qx.ui.core.Widget();
238 indicator.setDecorator(new qx.ui.decoration.Single().set({
239 top : [1, "solid", "#33508D"]
240 }));
241 indicator.setHeight(0);
242 indicator.setOpacity(0.5);
243 indicator.setZIndex(100);
244 indicator.setLayoutProperties({
245 left : -1000,
246 top : -1000
247 });
248 org.argeo.ria.Application.INSTANCE.getRoot().add(indicator);
249
250 this.list = new qx.ui.form.List();
251 this.list.setDecorator(null);
252 this.list.setSelectionMode("multi");
253 this.list.setDroppable(true);
254 this.list.setDraggable(true);
255 this.list.setContextMenu(org.argeo.ria.event.CommandsManager
256 .getInstance().createMenuFromIds(["removefrombatch"]));
257
258 this.list.addListener("dragstart", function(e) {
259 e.addType(["items"]);
260 e.addAction(["move"]);
261 }, this);
262 this.list.addListener("dragend", function(e) {
263 indicator.setDomPosition(-1000, -1000);
264 });
265 this.list.addListener("dragover", function(e) {
266 var orig = e.getOriginalTarget();
267 var origCoords = orig.getContainerLocation();
268 indicator.setWidth(orig.getBounds().width);
269 indicator.setDomPosition(origCoords.left,
270 origCoords.bottom);
271 });
272 this.list.addListener("drag", function(e) {
273 var orig = e.getOriginalTarget();
274 var origCoords = orig.getContainerLocation();
275 indicator.setWidth(orig.getBounds().width);
276 indicator.setDomPosition(origCoords.left,
277 origCoords.bottom);
278 });
279
280 this.list.addListener("drop", function(e) {
281 var target = e.getRelatedTarget();
282 var afterItem = e.getOriginalTarget();
283 indicator.setDomPosition(-1000, -1000);
284 if (afterItem.classname != "qx.ui.form.ListItem")
285 afterItem = null;
286 if (!target) {
287 target = this.list.getSortedSelection()[0];
288 this.addFlowToBatch(target, afterItem);
289 } else {
290 org.argeo.ria.event.CommandsManager.getInstance().executeCommand("addtobatch");
291 }
292 }, this);
293 this.listPane.add(this.list, {
294 edge : "center"
295 });
296
297 this.list.addListener("changeSelection", function(e) {
298 var viewSelection = this.getViewSelection();
299 viewSelection.setViewId("batch:list");
300 viewSelection.clear();
301 var listSel = this.list.getSortedSelection();
302 for (var i = 0; i < listSel.length; i++) {
303 viewSelection.addNode(listSel[i]);
304 }
305 }, this);
306
307 this.dropDecorator = new qx.ui.decoration.Background();
308 this.dropDecorator.set({
309 backgroundImage : "org.argeo.slc.ria/drophere.gif",
310 backgroundRepeat : "no-repeat"
311 });
312
313
314 listChangeListener = function() {
315 var command = org.argeo.ria.event.CommandsManager.getInstance()
316 .getCommandById("submitform");
317 command.setEnabled(this.list.hasChildren());
318 var command2 = org.argeo.ria.event.CommandsManager.getInstance()
319 .getCommandById("clearbatch");
320 command2.setEnabled(this.list.hasChildren());
321 this.list.setDecorator((this.list.hasChildren()?null:this.dropDecorator));
322 };
323 this.list.addListener("addItem", listChangeListener, this);
324 this.list.addListener("removeItem", listChangeListener, this);
325
326 this.list.setDecorator(this.dropDecorator);
327
328 this.add(this.listPane);
329 },
330
331
332 /**
333 * Adds a given ExecutionFlow to the batch
334 *
335 * @param target
336 * {mixed} The dropped target, can be a TreeFile (add) or a
337 * ListItem (reorder).
338 * @param after
339 * {qx.ui.form.ListItem} Optional list item : if set, the
340 * flow will be added as a new list item positionned after
341 * this one.
342 * @param skipAutoOpen
343 * {boolean} Whether the formular should open or not.
344 */
345 addFlowToBatch : function(target, after, skipAutoOpen) {
346 if (target && target.classname == "qx.ui.form.ListItem") {
347 if (!after)
348 return;
349 if (after == "first")
350 this.list.addAt(target, 0);
351 else
352 this.list.addAfter(target, after);
353 return;
354 }
355
356 // Folder case
357 if (qx.Class.isSubClassOf(qx.Class.getByName(target.classname),
358 qx.ui.tree.TreeFolder)) {
359 var allChildren = target.getItems(true);
360 for (var i = 0; i < allChildren.length; i++) {
361 if (allChildren[i].getUserData("executionFlow")) {
362 try{
363 this.addFlowToBatch(allChildren[i], null, true);
364 }catch(e){
365 return;
366 }
367 }
368 }
369 return;
370 }
371
372 // Check agent Uuid against current batch agent Id.
373 var agentUuid = target.getUserData("agentUuid");
374 if (!this.getBatchAgentId()) {
375 this.setBatchAgentId(agentUuid);
376 } else if (this.getBatchAgentId() != agentUuid) {
377 this.error("Batch can contain tests only of the same agent!");
378 throw new Error("Batch can contain tests only of the same agent!");
379 }
380
381 var executionModule = target.getUserData("executionModule");
382 var executionFlow = target.getUserData("executionFlow");
383 var batchEntry = new org.argeo.slc.ria.execution.BatchEntrySpec(
384 executionModule, executionFlow);
385
386 this.appendBatchEntrySpec(batchEntry, target.getIcon(), after);
387 },
388
389 appendBatchEntrySpec: function(batchEntrySpec, icon, after){
390
391 var item = new qx.ui.form.ListItem(batchEntrySpec.getLabel(), icon || "org.argeo.slc.ria/system.png");
392 item.setUserData("batchEntrySpec", batchEntrySpec);
393 item.setPaddingTop(1);
394 item.setPaddingBottom(2);
395 if (after) {
396 if (after == "first")
397 this.list.addAt(item, 0);
398 else
399 this.list.addAfter(item, after);
400 } else {
401 this.list.add(item);
402 }
403 this.list.select(item);
404
405 },
406
407 /**
408 * Called at execution
409 *
410 * @param agentUuid
411 * {String} The id of the target agent
412 */
413 executeBatchOnAgent : function(agentUuid, clearBatch) {
414 var selection = this.list.getChildren();
415 if (!selection.length)
416 return;
417 var slcExecMessage = new org.argeo.slc.ria.execution.Message();
418 for (var i = 0; i < selection.length; i++) {
419 var batchEntrySpec = selection[i].getUserData("batchEntrySpec");
420 slcExecMessage.addBatchEntrySpec(batchEntrySpec);
421 }
422 try{
423 var xmlMessage = slcExecMessage.toXml();
424 if(!window.xmlExecStub){
425 window.xmlExecStub = {};
426 }
427 window.xmlExecStub[slcExecMessage.getUuid()] = qx.xml.Document.fromString(xmlMessage);
428 var req = org.argeo.slc.ria.SlcApi.getNewSlcExecutionService(
429 agentUuid, xmlMessage);
430 req.send();
431 // Force logs refresh right now!
432 qx.event.Timer.once(function() {
433 var command = org.argeo.ria.event.CommandsManager
434 .getInstance().getCommandById("reloadlogs");
435 if (command) {
436 command.execute();
437 }
438 }, this, 2000);
439 if(clearBatch){
440 req.addListener("completed", function(e){
441 this.list.removeAll();
442 this.setBatchAgentId(null);
443 }, this);
444 }
445 }catch(e){
446 this.error(e);
447 }
448 },
449
450 clearBatchForAgentId : function(agentId){
451 if(this.getBatchAgentId() == agentId){
452 this.list.removeAll();
453 this.setBatchAgentId(null);
454 }
455 },
456
457 /**
458 * Whether this component is already contained in a scroller (return false) or not (return true).
459 * @return {Boolean}
460 */
461 addScroll : function(){return false;},
462 /**
463 * Called at destruction time
464 * Perform all the clean operations (stopping polling queries, etc.)
465 */
466 close : function(){return true;}
467 }
468
469
470 });