]>
git.argeo.org Git - gpl/argeo-slc.git/blob - server/org.argeo.slc.ria/src/argeo-ria-lib/slc/class/org/argeo/slc/ria/NewLauncherApplet.js
383b1d0bff88422cbec029f64324407e8077d578
2 * A simple Hello World applet for documentation purpose.
3 * The only associated command is the "Close" command.
5 qx
.Class
.define("org.argeo.slc.ria.NewLauncherApplet",
7 extend
: qx
.ui
.container
.Composite
,
8 implement
: [org
.argeo
.ria
.components
.IView
],
10 construct : function(){
12 this.setLayout(new qx
.ui
.layout
.Dock());
18 * The viewPane inside which this applet is added.
25 check
:"org.argeo.ria.components.ViewSelection"
27 instanceId
: {init
:""},
28 instanceLabel
: {init
:""},
30 * A boolean registering whether the SpecEditor must autoOpen or not when a spec is added to the Batch.
40 event
: "changeBatchAgentId"
43 * Commands definition, see {@link org.argeo.ria.event.CommandsManager#definitions}
48 label
: "Execute Batch",
49 icon
: "resource/slc/media-playback-start.png",
54 callback : function(e
){
55 if(this.getBatchAgentId()){
56 this.executeBatchOnAgent(this.getBatchAgentId());
62 label
: "Add to batch",
63 icon
: "resource/slc/list-add.png",
68 callback : function(e
){
69 this._addFlowToBatch();
71 selectionChange : function(viewId
, selection
){
72 if(viewId
!= "form:tree") return;
73 if(!selection
|| selection
.length
!= 1) return;
74 var item
= selection
[0];
75 this.setEnabled(false);
76 switch(item
.classname
){
77 case "qx.ui.tree.TreeFile" :
78 this.setEnabled(true);
80 case "qx.ui.tree.TreeFolder" :
81 if(item
.getTree().getRoot() == item
) break;
82 this.setEnabled(true);
84 case "org.argeo.ria.components.DynamicTreeFolder":
85 if(item
.getTree().getRoot() == item
) break;
86 if(item
.getState() == "loaded") this.setEnabled(true);
94 icon
: "resource/slc/document-open.png",
98 toggleInitialState
: true,
100 toolbar
: "launcher",
101 callback : function(event
){
102 var state
= event
.getTarget().getUserData("slc.command.toggleState");
103 this.setAutoOpen(state
);
107 "editexecutionspecs" : {
108 label
: "Edit Execution Specs",
109 icon
: "resource/slc/document-open.png",
114 callback : function(e
){
115 var sel
= this.list
.getSortedSelection();
116 var spec
= sel
[0].getUserData("batchEntrySpec");
117 if(spec
.hasEditableValues()){
118 var specEditor
= new org
.argeo
.slc
.ria
.execution
.SpecEditor(spec
);
119 specEditor
.attachAndShow();
122 selectionChange : function(viewId
, selection
){
123 if(viewId
!= "form:list") return;
124 this.setEnabled(false);
125 if((selection
&& selection
.length
== 1)) {
126 var selectedItemSpec
= selection
[0].getUserData("batchEntrySpec");
127 if(selectedItemSpec
.hasEditableValues()){
128 this.setEnabled(true);
134 "removefrombatch" : {
135 label
: "Remove from batch",
136 icon
: "resource/slc/edit-delete.png",
141 callback : function(e
){
142 var sel
= this.list
.getSortedSelection();
143 var modal
= new org
.argeo
.ria
.components
.Modal("Confirm", null);
144 modal
.addConfirm("Are you sure you want to remove<br> the selected test" + (sel
.length
>1?"s":"") + " from the Batch?");
145 modal
.addListener("ok", function(){
146 for(var i
=0;i
<sel
.length
;i
++){
147 this.list
.remove(sel
[i
]);
149 if(!this.list
.hasChildren()){
150 this.setBatchAgentId(null);
153 modal
.attachAndShow();
155 selectionChange : function(viewId
, selection
){
156 if(viewId
!= "form:list") return;
157 this.setEnabled(false);
158 if((selection
&& selection
.length
> 0)) this.setEnabled(true);
164 icon
: "resource/slc/view-refresh.png",
165 shortcut
: "Control+m",
168 toolbar
: "launcher",
169 callback : function(e
){
170 var selected
= this.tree
.getSelection()[0];
171 if(selected
.classname
== "org.argeo.ria.components.DynamicTreeFolder"){
172 if(selected
.getUserData("moduleData")){
173 // It's a "module" node, first trigger the reloadBundle.service
174 selected
.setUserData("dataModel", {});
175 selected
.setEnabled(false);
176 selected
.setOpen(false);
177 var moduleData
= selected
.getUserData("moduleData");
178 var bundleService
= org
.argeo
.slc
.ria
.SlcApi
.getReloadBundleService(moduleData
.name
, moduleData
.version
);
179 bundleService
.addListener("completed", function(response
){
180 selected
.setEnabled(true);
181 selected
.setOpen(true);
184 //bundleService.send();
185 //Do not send, not implemented yet, false timer instead.
186 qx
.event
.Timer
.once(function(response
){
187 selected
.setEnabled(true);
188 selected
.setOpen(true);
196 selectionChange : function(viewId
, selection
){
197 if(viewId
!= "form:tree") return;
198 if(!selection
) return;
199 if(selection
.length
> 1){
200 this.setEnabled(false);
203 var item
= selection
[0];
204 if(!qx
.Class
.isSubClassOf(qx
.Class
.getByName(item
.classname
), qx
.ui
.tree
.AbstractTreeItem
)) return;
205 this.setEnabled(false);
206 if(qx
.Class
.isSubClassOf(qx
.Class
.getByName(item
.classname
), org
.argeo
.ria
.components
.DynamicTreeFolder
)){
207 this.setEnabled(true);
218 * Static loader for the "agent" level (first level)
219 * @param folder {qx.ui.tree.TreeFolder} The root Tree Folder.
221 agentLoader : function(folder
){
223 var req
= org
.argeo
.slc
.ria
.SlcApi
.getListAgentsService("agents");
225 req
.addListener("completed", function(response
){
226 var xmlDoc
= response
.getContent();
227 var nodes
= org
.argeo
.ria
.util
.Element
.selectNodes(xmlDoc
, "//slc:slc-agent-descriptor");
228 //var newTopics = {};
229 var modulesLoader
= org
.argeo
.slc
.ria
.NewLauncherApplet
.modulesLoader
;
230 for(var i
=0;i
<nodes
.length
;i
++){
231 var uuid
= org
.argeo
.ria
.util
.Element
.getSingleNodeText(nodes
[i
], "@uuid");
232 var host
= org
.argeo
.ria
.util
.Element
.getSingleNodeText(nodes
[i
], "slc:host");
234 var agentFolder
= new org
.argeo
.ria
.components
.DynamicTreeFolder(
235 host
+ ' ('+uuid
+')',
237 "Loading Modules...",
240 agentFolder
.setUserData("agentUuid", uuid
);
241 agentFolder
.setIcon("resource/slc/mime-xsl-22.png");
242 folder
.add(agentFolder
);
244 folder
.setUserData("agentsMap", agents
);
245 folder
.setLoaded(true);
247 req
.addListener("failed", function(response
){folder
.setLoaded(true);});
253 * Loader for the "modules" level : takes any tree folder, currently the root folder.
254 * @param folder {qx.ui.tree.TreeFolder} The root folder
256 modulesLoader : function(folder
){
257 var agentId
= folder
.getUserData("agentUuid");
258 var req
= org
.argeo
.slc
.ria
.SlcApi
.getListModulesService(agentId
);
259 req
.addListener("completed", function(response
){
260 var descriptors
= org
.argeo
.ria
.util
.Element
.selectNodes(response
.getContent(), "slc:object-list/slc:execution-module-descriptor");
262 for(var i
=0;i
<descriptors
.length
; i
++){
263 var name
= org
.argeo
.ria
.util
.Element
.getSingleNodeText(descriptors
[i
], "slc:name");
264 var version
= org
.argeo
.ria
.util
.Element
.getSingleNodeText(descriptors
[i
], "slc:version");
265 if(!mods
[name
]) mods
[name
] = [];
266 mods
[name
].push(version
);
268 var flowLoader
= org
.argeo
.slc
.ria
.NewLauncherApplet
.flowLoader
;
269 for(var key
in mods
){
270 for(var i
=0;i
<mods
[key
].length
;i
++){
271 var versionFolder
= new org
.argeo
.ria
.components
.DynamicTreeFolder(
272 key
+ ' ('+mods
[key
][i
]+')',
277 folder
.add(versionFolder
);
278 versionFolder
.setUserData("moduleData", {name
:key
, version
:mods
[key
][i
]});
279 versionFolder
.setUserData("agentUuid", agentId
);
281 folder
.setLoaded(true);
284 req
.addListener("failed", function(response
){folder
.setLoaded(true);});
289 * Loader for the "flow" level : takes a folder containing "moduleData" and create its children.
290 * @param folder {qx.ui.tree.TreeFolder} A Tree folder containing in the key "moduleData" of its user data a map containing the keys {name,version}
292 flowLoader : function(folder
){
293 var moduleData
= folder
.getUserData("moduleData");
294 var agentUuid
= folder
.getUserData("agentUuid");
295 //var pathStub = ["", "/test/toto/zobi", "loop"];
298 var req
= org
.argeo
.slc
.ria
.SlcApi
.getLoadExecutionDescriptorService(agentUuid
,moduleData
.name
, moduleData
.version
);
299 req
.addListener("completed", function(response
){
300 var executionModule
= new org
.argeo
.slc
.ria
.execution
.Module();
302 executionModule
.setXmlNode(response
.getContent());
306 var execFlows
= executionModule
.getExecutionFlows();
307 for(var key
in execFlows
){
308 var file
= new qx
.ui
.tree
.TreeFile(key
);
309 var path
= execFlows
[key
].getPath();
310 //path = pathStub[indexStub];
312 file
.setUserData("executionModule", executionModule
);
313 file
.setUserData("executionFlow", execFlows
[key
]);
314 file
.setUserData("agentUuid", agentUuid
);
315 org
.argeo
.slc
.ria
.NewLauncherApplet
.attachNodeByPath(
319 {agentUuid
:folder
.getUserData("agentUuid")}
321 folder
.appendDragData(file
);
323 folder
.setLoaded(true);
325 req
.addListener("failed", function(response
){folder
.setLoaded(true);});
330 * Parse a string path and search if there is a root node.
331 * @param rootNode {org.argeo.ria.components.DynamicTreeFolder} The parent node (containing data model)
332 * @param path {String} The path of the node to attach.
333 * @param childNode {qx.ui.tree.TreeFile} The leaf node
334 * @param userData {Map} User data to attach at all levels.
336 attachNodeByPath : function(rootNode
, path
, childNode
, userData
){
337 if(!path
|| path
=="" || path
== "/" ){
338 rootNode
.add(childNode
);
341 var model
= rootNode
.getUserData("dataModel");
344 rootNode
.setUserData("dataModel", model
);
346 var parts
= path
.split("/");
347 var keys
= qx
.lang
.Object
.getKeys(model
);
349 var crtFolder
= rootNode
;
350 for(var i
=0;i
<parts
.length
;i
++){
351 if(parts
[i
] == "") continue;
353 if(!model
[parts
[i
]]) {
354 var virtualFolder
= new qx
.ui
.tree
.TreeFolder(parts
[i
]);
355 if(userData
&& qx
.lang
.Object
.getLength(userData
)){
356 for(var key
in userData
){ virtualFolder
.setUserData(key
, userData
[key
]); }
358 rootNode
.appendDragData(virtualFolder
);
359 model
[parts
[i
]] = virtualFolder
;
360 crtFolder
.add(virtualFolder
);
361 crtFolder
= virtualFolder
;
363 crtFolder
= model
[parts
[i
]];
366 crtFolder
.add(childNode
);
373 * Called at applet creation. Just registers viewPane.
374 * @param viewPane {org.argeo.ria.components.ViewPane} The viewPane.
376 init : function(viewPane
){
377 this.setView(viewPane
);
378 this.setViewSelection(new org
.argeo
.ria
.components
.ViewSelection(viewPane
.getViewId()));
379 this.remoteNotifier
= new org
.argeo
.ria
.remote
.RemoteNotifier(
380 "/org.argeo.slc.webapp/",
382 "addEventListener.service",
383 "removeEventListener.service"
385 this.remoteNotifier
.setEventParamName("slc_eventType");
386 this.remoteNotifier
.setEventXPath("/slc:slc-event");
387 this.remoteNotifier
.setEventTypeXPath('slc:headers/slc:header[@name="slc_eventType"]');
388 this.remoteNotifier
.setEventDataXPath('slc:headers/slc:header[@name="slc_agentId"]');
389 this.remoteNotifier
.startPolling();
390 this.UIBus
= org
.argeo
.ria
.event
.UIBus
.getInstance();
391 this.UIBus
.registerNotifier(this.remoteNotifier
);
393 this._emptyAgentString
= "Empty Batch";
394 this._crtAgentString
= "Target Agent : ";
401 this._createLayout();
402 this.getView().setViewTitle("Execution Launcher");
403 this.reloadHandler = function(message
){
404 this.rootNode
.reload();
406 this.UIBus
.addListener("agentRegistered", this.reloadHandler
, this);
407 this.UIBus
.addListener("agentUnregistered", this.reloadHandler
, this);
410 addScroll : function(){
415 this.UIBus
.removeListener("agentRegistered", this.reloadHandler
, this);
416 this.UIBus
.removeListener("agentUnregistered", this.reloadHandler
, this);
417 this.remoteNotifier
.stopPolling();
421 * Creates the main applet layout.
423 _createLayout : function(){
425 var splitPane
= new qx
.ui
.splitpane
.Pane("vertical");
426 splitPane
.setDecorator(null);
429 this.formPane
= new qx
.ui
.container
.Composite(new qx
.ui
.layout
.VBox(5));
430 this.scroll
= new qx
.ui
.container
.Scroll(this.formPane
);
431 this.formPane
.setPadding(10);
433 this.tree
= new qx
.ui
.tree
.Tree();
434 this.tree
.setDecorator(null);
435 this.tree
.setSelectionMode("multi");
447 this.rootNode
= new org
.argeo
.ria
.components
.DynamicTreeFolder(
449 this.self(arguments
).agentLoader
,
453 this.tree
.setRoot(this.rootNode
);
454 this.rootNode
.setOpen(true);
455 this.tree
.setContextMenu(org
.argeo
.ria
.event
.CommandsManager
.getInstance().createMenuFromIds(["addtobatch", "reloadtree"]));
457 this.tree
.addListener("changeSelection", function(e
){
458 var viewSelection
= this.getViewSelection();
459 viewSelection
.setViewId("form:tree");
460 viewSelection
.clear();
461 var sel
= this.tree
.getSortedSelection();
462 for(var i
=0;i
<sel
.length
;i
++){
463 viewSelection
.addNode(sel
[i
]);
467 this.listPane
= new qx
.ui
.container
.Composite(new qx
.ui
.layout
.Dock());
468 var listToolBar
= new qx
.ui
.toolbar
.ToolBar();
469 var toolGroup
= new qx
.ui
.toolbar
.Part();
470 listToolBar
.add(toolGroup
);
472 this.batchLabel
= new qx
.ui
.basic
.Atom(this._emptyAgentString
, "resource/slc/mime-xsl-22.png");
473 this.batchLabel
.setPadding(6);
474 toolGroup
.add(this.batchLabel
);
475 this.addListener("changeBatchAgentId", function(event
){
476 var value
= event
.getData();
478 this.batchLabel
.setLabel(this._emptyAgentString
);
480 var agentsList
= this.rootNode
.getUserData("agentsMap");
481 this.batchLabel
.setLabel(this._crtAgentString
+ agentsList
[value
]);
485 listToolBar
.addSpacer();
486 listToolBar
.setPaddingRight(4);
487 var execButton
= this.getCommands()["submitform"].command
.getToolbarButton();
488 var delButton
= this.getCommands()["removefrombatch"].command
.getToolbarButton();
489 var formButton
= this.getCommands()["editexecutionspecs"].command
.getToolbarButton();
490 execButton
.setShow("icon");
491 delButton
.setShow("icon");
492 formButton
.setShow("icon");
493 listToolBar
.add(execButton
);
494 listToolBar
.add(new qx
.ui
.toolbar
.Separator());
495 listToolBar
.add(formButton
);
496 listToolBar
.add(delButton
);
498 this.listPane
.add(listToolBar
, {edge
:"north"});
500 var indicator
= new qx
.ui
.core
.Widget();
501 indicator
.setDecorator(new qx
.ui
.decoration
.Single().set({top
:[1,"solid","#33508D"]}));
502 indicator
.setHeight(0);
503 indicator
.setOpacity(0.5);
504 indicator
.setZIndex(100);
505 indicator
.setLayoutProperties({left
:-1000,top
:-1000});
506 org
.argeo
.ria
.Application
.INSTANCE
.getRoot().add(indicator
);
509 this.list
= new qx
.ui
.form
.List();
510 this.list
.setDecorator(null);
511 this.list
.setSelectionMode("multi");
512 this.list
.setDroppable(true);
513 this.list
.setDraggable(true);
514 this.list
.setContextMenu(org
.argeo
.ria
.event
.CommandsManager
.getInstance().createMenuFromIds(["editexecutionspecs", "removefrombatch"]));
517 this.list
.addListener("dragstart", function(e
){
518 e
.addType(["items"]);
519 e
.addAction(["move"]);
521 this.list
.addListener("dragend", function(e
){
522 indicator
.setDomPosition(-1000,-1000);
524 this.list
.addListener("dragover", function(e
){
525 var orig
= e
.getOriginalTarget();
526 var origCoords
= orig
.getContainerLocation();
527 indicator
.setWidth(orig
.getBounds().width
);
528 indicator
.setDomPosition(origCoords
.left
, origCoords
.bottom
);
530 this.list
.addListener("drag", function(e
){
531 var orig
= e
.getOriginalTarget();
532 var origCoords
= orig
.getContainerLocation();
533 indicator
.setWidth(orig
.getBounds().width
);
534 indicator
.setDomPosition(origCoords
.left
, origCoords
.bottom
);
537 this.list
.addListener("drop", function(e
){
538 var target
= e
.getRelatedTarget();
539 var afterItem
= e
.getOriginalTarget();
540 indicator
.setDomPosition(-1000,-1000);
541 if(afterItem
.classname
!= "qx.ui.form.ListItem") afterItem
= null;
543 target
= this.list
.getSortedSelection()[0];
544 this._addFlowToBatch(target
, afterItem
);
546 this._addFlowToBatch(null, afterItem
);
549 this.listPane
.add(this.list
, {edge
:"center"});
551 this.list
.addListener("changeSelection", function(e
){
552 var viewSelection
= this.getViewSelection();
553 viewSelection
.setViewId("form:list");
554 viewSelection
.clear();
555 var listSel
= this.list
.getSortedSelection();
556 for(var i
=0;i
<listSel
.length
;i
++){
557 viewSelection
.addNode(listSel
[i
]);
561 listChangeListener = function(){
562 var command
= org
.argeo
.ria
.event
.CommandsManager
.getInstance().getCommandById("submitform");
563 command
.setEnabled(this.list
.hasChildren());
565 this.list
.addListener("addItem", listChangeListener
, this);
566 this.list
.addListener("removeItem", listChangeListener
, this);
568 splitPane
.add(this.tree
, 0);
569 splitPane
.add(this.listPane
, 1);
573 * Adds a given ExecutionFlow to the batch
574 * @param target {mixed} The dropped target, can be a TreeFile (add) or a ListItem (reorder).
575 * @param after {qx.ui.form.ListItem} Optional list item : if set, the flow will be added as a new list item positionned after this one.
577 _addFlowToBatch : function(target
, after
, skipAutoOpen
){
578 if(target
&& target
.classname
== "qx.ui.form.ListItem"){
580 if(after
== "first") this.list
.addAt(target
, 0);
581 else this.list
.addAfter(target
, after
);
585 if(this.tree
.isSelectionEmpty()){
588 selection
= this.tree
.getSelection();
589 if(selection
.length
> 1){
590 for(var i
=0;i
<selection
.length
;i
++){
591 this._addFlowToBatch(selection
[i
], null, true);
595 target
= selection
[0];
600 if(qx
.Class
.isSubClassOf(qx
.Class
.getByName(target
.classname
), qx
.ui
.tree
.TreeFolder
)){
601 var allChildren
= target
.getItems(true);
602 for(var i
=0;i
<allChildren
.length
;i
++){
603 if(allChildren
[i
].getUserData("executionFlow")){
604 this._addFlowToBatch(allChildren
[i
], null, true);
610 // Check agent Uuid against current batch agent Id.
611 var agentUuid
= target
.getUserData("agentUuid");
612 if(!this.getBatchAgentId()){
613 this.setBatchAgentId(agentUuid
);
614 }else if(this.getBatchAgentId() != agentUuid
){
615 var modal
= new org
.argeo
.ria
.components
.Modal("Wrong Agent!", null, "Batch can contain tests only of the same agent!");
616 modal
.attachAndShow();
620 var executionModule
= target
.getUserData("executionModule");
621 var executionFlow
= target
.getUserData("executionFlow");
622 var batchEntry
= new org
.argeo
.slc
.ria
.execution
.BatchEntrySpec(executionModule
, executionFlow
);
623 var label
= batchEntry
.getLabel();
624 var icon
= target
.getIcon() || "resource/slc/office-document.png";
625 var item
= new qx
.ui
.form
.ListItem(label
, icon
);
626 item
.addListener("dblclick", function(e
){
627 this.getCommands()["editexecutionspecs"].command
.execute();
629 item
.setUserData("batchEntrySpec", batchEntry
);
630 item
.setPaddingTop(1);
631 item
.setPaddingBottom(2);
633 if(after
== "first") this.list
.addAt(item
, 0);
634 else this.list
.addAfter(item
, after
);
638 this.list
.select(item
);
639 if(this.getAutoOpen() && !skipAutoOpen
){
640 this.getCommands()["editexecutionspecs"].command
.execute();
645 * Called at execution
646 * @param agentUuid {String} The id of the target agent
648 executeBatchOnAgent : function(agentUuid
){
649 var selection
= this.list
.getChildren();
650 if(!selection
.length
) return;
651 var slcExecMessage
= new org
.argeo
.slc
.ria
.execution
.Message();
652 for(var i
=0;i
<selection
.length
;i
++){
653 var batchEntrySpec
= selection
[i
].getUserData("batchEntrySpec");
654 slcExecMessage
.addBatchEntrySpec(batchEntrySpec
);
656 var req
= org
.argeo
.slc
.ria
.SlcApi
.getNewSlcExecutionService(agentUuid
, slcExecMessage
.toXml());
658 // Force logs refresh right now!
659 qx
.event
.Timer
.once(function(){
660 var command
= org
.argeo
.ria
.event
.CommandsManager
.getInstance().getCommandById("reloadlogs");