init : true,
check : "Boolean"
},
+ batchAgentId : {
+ init : null,
+ nullable : true,
+ check : "String",
+ event : "changeBatchAgentId"
+ },
/**
* Commands definition, see {@link org.argeo.ria.event.CommandsManager#definitions}
*/
commands : {
init : {
"submitform" : {
- label : "Execute Batch On...",
+ label : "Execute Batch",
icon : "resource/slc/media-playback-start.png",
shortcut : null,
- enabled : true,
+ enabled : false,
menu : "Launcher",
- toolbar : null,
- callback : function(e){},
- submenu : [],
- submenuCallback : function(commandId){
- //alert("Execute Batch on Agent "+commandId);
- this.executeBatchOnAgent(commandId);
+ toolbar : "launcher",
+ callback : function(e){
+ if(this.getBatchAgentId()){
+ this.executeBatchOnAgent(this.getBatchAgentId());
+ }
},
command : null
},
if(!selection || selection.length != 1) return;
var item = selection[0];
this.setEnabled(false);
- if(qx.Class.isSubClassOf(qx.Class.getByName(item.classname), qx.ui.tree.TreeFile)){
- this.setEnabled(true);
+ switch(item.classname){
+ case "qx.ui.tree.TreeFile" :
+ this.setEnabled(true);
+ break;
+ case "qx.ui.tree.TreeFolder" :
+ if(item.getTree().getRoot() == item) break;
+ this.setEnabled(true);
+ break;
+ case "org.argeo.ria.components.DynamicTreeFolder":
+ if(item.getTree().getRoot() == item) break;
+ if(item.getState() == "loaded") this.setEnabled(true);
+ break;
}
-
},
command : null
},
toolbar : null,
callback : function(e){
var sel = this.list.getSortedSelection();
- var item = sel[0];
- var specEditor = new org.argeo.slc.ria.execution.SpecEditor(item.getUserData("batchEntrySpec"));
- specEditor.attachAndShow();
+ var spec = sel[0].getUserData("batchEntrySpec");
+ if(spec.hasEditableValues()){
+ var specEditor = new org.argeo.slc.ria.execution.SpecEditor(spec);
+ specEditor.attachAndShow();
+ }
},
selectionChange : function(viewId, selection){
if(viewId != "form:list") return;
this.setEnabled(false);
- if((selection && selection.length == 1)) this.setEnabled(true);
+ if((selection && selection.length == 1)) {
+ var selectedItemSpec = selection[0].getUserData("batchEntrySpec");
+ if(selectedItemSpec.hasEditableValues()){
+ this.setEnabled(true);
+ }
+ }
},
command : null
},
for(var i=0;i<sel.length;i++){
this.list.remove(sel[i]);
}
+ if(!this.list.hasChildren()){
+ this.setBatchAgentId(null);
+ }
}, this);
modal.attachAndShow();
},
},
command : null
},
- "reloadagents" : {
- label : "Reload Agents",
- icon : "resource/slc/view-refresh.png",
- shortcut : "Control+r",
- enabled : true,
- menu : "Launcher",
- toolbar : "launcher",
- callback : function(e){
- var req = org.argeo.slc.ria.SlcApi.getListAgentsService("agents");
- req.send();
- },
- command : null
- },
"reloadtree" : {
label : "Reload",
icon : "resource/slc/view-refresh.png",
menu : "Launcher",
toolbar : "launcher",
callback : function(e){
- var selected = this.tree.getSelectedItem();
+ var selected = this.tree.getSelection()[0];
if(selected.classname == "org.argeo.ria.components.DynamicTreeFolder"){
if(selected.getUserData("moduleData")){
// It's a "module" node, first trigger the reloadBundle.service
},
selectionChange : function(viewId, selection){
if(viewId != "form:tree") return;
- if(!selection || selection.length != 1) return;
+ if(!selection) return;
+ if(selection.length > 1){
+ this.setEnabled(false);
+ return;
+ }
var item = selection[0];
if(!qx.Class.isSubClassOf(qx.Class.getByName(item.classname), qx.ui.tree.AbstractTreeItem)) return;
this.setEnabled(false);
command : null
}
}
- },
- /**
- * A map containing all currently registered agents.
- */
- registeredTopics : {
- init : {},
- check : "Map",
- event : "changeRegisteredTopics"
}
},
statics : {
/**
- * Loader for the "flow" level : takes a folder containing "moduleData" and create its children.
- * @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}
+ * Static loader for the "agent" level (first level)
+ * @param folder {qx.ui.tree.TreeFolder} The root Tree Folder.
*/
- flowLoader : function(folder){
- var moduleData = folder.getUserData("moduleData");
- //var pathStub = ["", "/test/toto/zobi", "loop"];
- //var indexStub = 0;
-
- var req = org.argeo.slc.ria.SlcApi.getLoadExecutionDescriptorService(moduleData.name, moduleData.version);
+ agentLoader : function(folder){
+
+ var req = org.argeo.slc.ria.SlcApi.getListAgentsService("agents");
+ var agents = {};
req.addListener("completed", function(response){
- var executionModule = new org.argeo.slc.ria.execution.Module();
- executionModule.setXmlNode(response.getContent());
- var execFlows = executionModule.getExecutionFlows();
- for(var key in execFlows){
- var file = new qx.ui.tree.TreeFile(key);
- var path = execFlows[key].getPath();
- //path = pathStub[indexStub];
- //indexStub ++;
- file.setUserData("executionModule", executionModule);
- file.setUserData("executionFlow", execFlows[key]);
- org.argeo.slc.ria.NewLauncherApplet.attachNodeByPath(folder, path, file);
- folder.appendDragData(file);
- }
- folder.setLoaded(true);
+ var xmlDoc = response.getContent();
+ var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc, "//slc:slc-agent-descriptor");
+ //var newTopics = {};
+ var modulesLoader = org.argeo.slc.ria.NewLauncherApplet.modulesLoader;
+ for(var i=0;i<nodes.length;i++){
+ var uuid = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "@uuid");
+ var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
+ agents[uuid] = host;
+ var agentFolder = new org.argeo.ria.components.DynamicTreeFolder(
+ host + ' ('+uuid+')',
+ modulesLoader,
+ "Loading Modules...",
+ folder.getDragData()
+ );
+ agentFolder.setUserData("agentUuid", uuid);
+ agentFolder.setIcon("resource/slc/mime-xsl-22.png");
+ folder.add(agentFolder);
+ }
+ folder.setUserData("agentsMap", agents);
+ folder.setLoaded(true);
});
- req.send();
- },
-
+ req.addListener("failed", function(response){folder.setLoaded(true);});
+ req.send();
+
+ },
+
/**
* Loader for the "modules" level : takes any tree folder, currently the root folder.
* @param folder {qx.ui.tree.TreeFolder} The root folder
*/
modulesLoader : function(folder){
- var req = org.argeo.slc.ria.SlcApi.getListModulesService();
+ var agentId = folder.getUserData("agentUuid");
+ var req = org.argeo.slc.ria.SlcApi.getListModulesService(agentId);
req.addListener("completed", function(response){
var descriptors = org.argeo.ria.util.Element.selectNodes(response.getContent(), "slc:object-list/slc:execution-module-descriptor");
var mods = {};
);
folder.add(versionFolder);
versionFolder.setUserData("moduleData", {name:key, version:mods[key][i]});
+ versionFolder.setUserData("agentUuid", agentId);
}
folder.setLoaded(true);
}
});
+ req.addListener("failed", function(response){folder.setLoaded(true);});
req.send();
},
+ /**
+ * Loader for the "flow" level : takes a folder containing "moduleData" and create its children.
+ * @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}
+ */
+ flowLoader : function(folder){
+ var moduleData = folder.getUserData("moduleData");
+ var agentUuid = folder.getUserData("agentUuid");
+ //var pathStub = ["", "/test/toto/zobi", "loop"];
+ //var indexStub = 0;
+
+ var req = org.argeo.slc.ria.SlcApi.getLoadExecutionDescriptorService(agentUuid,moduleData.name, moduleData.version);
+ req.addListener("completed", function(response){
+ var executionModule = new org.argeo.slc.ria.execution.Module();
+ try{
+ executionModule.setXmlNode(response.getContent());
+ }catch(e){
+ this.error(e);
+ }
+ var execFlows = executionModule.getExecutionFlows();
+ for(var key in execFlows){
+ var file = new qx.ui.tree.TreeFile(key);
+ var path = execFlows[key].getPath();
+ //path = pathStub[indexStub];
+ //indexStub ++;
+ file.setUserData("executionModule", executionModule);
+ file.setUserData("executionFlow", execFlows[key]);
+ file.setUserData("agentUuid", agentUuid);
+ org.argeo.slc.ria.NewLauncherApplet.attachNodeByPath(
+ folder,
+ path,
+ file,
+ {agentUuid:folder.getUserData("agentUuid")}
+ );
+ folder.appendDragData(file);
+ }
+ folder.setLoaded(true);
+ });
+ req.addListener("failed", function(response){folder.setLoaded(true);});
+ req.send();
+ },
+
/**
* Parse a string path and search if there is a root node.
- * @param rootNode {qx.ui.tree.AbstractTreeItem} The parent node (containing data model)
+ * @param rootNode {org.argeo.ria.components.DynamicTreeFolder} The parent node (containing data model)
* @param path {String} The path of the node to attach.
+ * @param childNode {qx.ui.tree.TreeFile} The leaf node
+ * @param userData {Map} User data to attach at all levels.
*/
- attachNodeByPath : function(rootNode, path, childNode){
+ attachNodeByPath : function(rootNode, path, childNode, userData){
if(!path || path=="" || path == "/" ){
rootNode.add(childNode);
return;
crtPath += parts[i];
if(!model[parts[i]]) {
var virtualFolder = new qx.ui.tree.TreeFolder(parts[i]);
+ if(userData && qx.lang.Object.getLength(userData)){
+ for(var key in userData){ virtualFolder.setUserData(key, userData[key]); }
+ }
+ rootNode.appendDragData(virtualFolder);
model[parts[i]] = virtualFolder;
crtFolder.add(virtualFolder);
crtFolder = virtualFolder;
init : function(viewPane){
this.setView(viewPane);
this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));
- this._amqClient = org.argeo.ria.remote.JmsClient.getInstance();
- this._amqClient.uri = "/org.argeo.slc.webapp/amq";
- this._amqClient.startPolling();
+ this.remoteNotifier = new org.argeo.ria.remote.RemoteNotifier(
+ "/org.argeo.slc.webapp/",
+ "pollEvent.service",
+ "addEventListener.service",
+ "removeEventListener.service"
+ );
+ this.remoteNotifier.setEventParamName("slc_eventType");
+ this.remoteNotifier.setEventXPath("/slc:slc-event");
+ this.remoteNotifier.setEventTypeXPath('slc:headers/slc:header[@name="slc_eventType"]');
+ this.remoteNotifier.setEventDataXPath('slc:headers/slc:header[@name="slc_agentId"]');
+ this.remoteNotifier.startPolling();
+ this.UIBus = org.argeo.ria.event.UIBus.getInstance();
+ this.UIBus.registerNotifier(this.remoteNotifier);
+
+ this._emptyAgentString = "Empty Batch";
+ this._crtAgentString = "Target Agent : ";
},
/**
load : function(){
this._createLayout();
this.getView().setViewTitle("Execution Launcher");
- org.argeo.ria.remote.RequestManager.getInstance().addListener("reload", function(reloadEvent){
- if(reloadEvent.getDataType()!= "agents") return ;
- var xmlDoc = reloadEvent.getContent();
- var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc, "//slc:slc-agent-descriptor");
- var newTopics = {};
- for(var i=0;i<nodes.length;i++){
- var uuid = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "@uuid");
- var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
- newTopics[uuid] = host+" ("+uuid+")";
- }
- this.setRegisteredTopics(newTopics);
- }, this);
- this.addListener("changeRegisteredTopics", function(event){
- //this._refreshTopicsSubscriptions(event);
- this._feedSelector(event);
- }, this);
- var reloadHandler = function(message){
- // Delay reload to be sure the jms was first integrated by the db, then ask the db.
- qx.event.Timer.once(function(){
- org.argeo.ria.event.CommandsManager.getInstance().getCommandById("reloadagents").execute();
- }, this, 1000);
+ this.reloadHandler = function(message){
+ this.rootNode.reload();
}
- this._amqClient.addListener("agentregister", "topic://agent.register", reloadHandler, this);
- this._amqClient.addListener("agentunregister", "topic://agent.unregister", reloadHandler, this);
- reloadHandler();
+ this.UIBus.addListener("agentRegistered", this.reloadHandler, this);
+ this.UIBus.addListener("agentUnregistered", this.reloadHandler, this);
},
addScroll : function(){
},
close : function(){
- this._amqClient.removeListener("agentregister", "topic://agent.register");
- this._amqClient.removeListener("agentunregister", "topic://agent.unregister");
- this._amqClient.removeListener("modulesResponse", "topic://modulesManager.response");
- this.setRegisteredTopics({});
- this._amqClient.stopPolling();
+ this.UIBus.removeListener("agentRegistered", this.reloadHandler, this);
+ this.UIBus.removeListener("agentUnregistered", this.reloadHandler, this);
+ this.remoteNotifier.stopPolling();
},
/**
this.tree = new qx.ui.tree.Tree();
this.tree.setDecorator(null);
+ this.tree.setSelectionMode("multi");
var dragData = {
"file" : {
"type" : ["items"],
"action":["move"]
- }
+ },
+ "folder" : {
+ "type" : ["items"],
+ "action":["move"]
+ }
};
- var root = new org.argeo.ria.components.DynamicTreeFolder(
- "All Tests",
- this.self(arguments).modulesLoader,
- "Loading Modules",
+ this.rootNode = new org.argeo.ria.components.DynamicTreeFolder(
+ "Tests",
+ this.self(arguments).agentLoader,
+ "Loading Agents",
dragData
);
- this.tree.setRoot(root);
- root.setOpen(true);
+ this.tree.setRoot(this.rootNode);
+ this.rootNode.setOpen(true);
this.tree.setContextMenu(org.argeo.ria.event.CommandsManager.getInstance().createMenuFromIds(["addtobatch", "reloadtree"]));
this.tree.addListener("changeSelection", function(e){
var toolGroup = new qx.ui.toolbar.Part();
listToolBar.add(toolGroup);
- var execButton = this.getCommands()["submitform"].command.getToolbarButton();
- toolGroup.add(execButton);
-
+ this.batchLabel = new qx.ui.basic.Atom(this._emptyAgentString, "resource/slc/mime-xsl-22.png");
+ this.batchLabel.setPadding(6);
+ toolGroup.add(this.batchLabel);
+ this.addListener("changeBatchAgentId", function(event){
+ var value = event.getData();
+ if(value == null){
+ this.batchLabel.setLabel(this._emptyAgentString);
+ }else{
+ var agentsList = this.rootNode.getUserData("agentsMap");
+ this.batchLabel.setLabel(this._crtAgentString + agentsList[value]);
+ }
+ }, this);
+
listToolBar.addSpacer();
listToolBar.setPaddingRight(4);
+ var execButton = this.getCommands()["submitform"].command.getToolbarButton();
var delButton = this.getCommands()["removefrombatch"].command.getToolbarButton();
var formButton = this.getCommands()["editexecutionspecs"].command.getToolbarButton();
+ execButton.setShow("icon");
delButton.setShow("icon");
formButton.setShow("icon");
+ listToolBar.add(execButton);
+ listToolBar.add(new qx.ui.toolbar.Separator());
listToolBar.add(formButton);
listToolBar.add(delButton);
if(afterItem.classname != "qx.ui.form.ListItem") afterItem = null;
if(!target){
target = this.list.getSortedSelection()[0];
+ this._addFlowToBatch(target, afterItem);
+ }else{
+ this._addFlowToBatch(null, afterItem);
}
- this._addFlowToBatch(target, afterItem);
}, this);
this.listPane.add(this.list, {edge:"center"});
}
}, this);
+ listChangeListener = function(){
+ var command = org.argeo.ria.event.CommandsManager.getInstance().getCommandById("submitform");
+ command.setEnabled(this.list.hasChildren());
+ };
+ this.list.addListener("addItem", listChangeListener, this);
+ this.list.addListener("removeItem", listChangeListener, this);
+
splitPane.add(this.tree, 0);
splitPane.add(this.listPane, 1);
},
* @param target {mixed} The dropped target, can be a TreeFile (add) or a ListItem (reorder).
* @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.
*/
- _addFlowToBatch : function(target, after){
- //this.debug(target);
- if(!target){
- target = this.tree.getSelectedItem();
- if(!target) return;
- }else if(target.classname == "qx.ui.form.ListItem"){
+ _addFlowToBatch : function(target, after, skipAutoOpen){
+ if(target && target.classname == "qx.ui.form.ListItem"){
if(!after) return;
if(after == "first") this.list.addAt(target, 0);
else this.list.addAfter(target, after);
return;
}
+ if(!target){
+ if(this.tree.isSelectionEmpty()){
+ return;
+ }
+ selection = this.tree.getSelection();
+ if(selection.length > 1){
+ for(var i=0;i<selection.length;i++){
+ this._addFlowToBatch(selection[i], null, true);
+ }
+ return;
+ }else{
+ target = selection[0];
+ }
+ }
+
+ // Folder case
+ if(qx.Class.isSubClassOf(qx.Class.getByName(target.classname), qx.ui.tree.TreeFolder)){
+ var allChildren = target.getItems(true);
+ for(var i=0;i<allChildren.length;i++){
+ if(allChildren[i].getUserData("executionFlow")){
+ this._addFlowToBatch(allChildren[i], null, true);
+ }
+ }
+ return;
+ }
+
+ // Check agent Uuid against current batch agent Id.
+ var agentUuid = target.getUserData("agentUuid");
+ if(!this.getBatchAgentId()){
+ this.setBatchAgentId(agentUuid);
+ }else if(this.getBatchAgentId() != agentUuid){
+ var modal = new org.argeo.ria.components.Modal("Wrong Agent!", null, "Batch can contain tests only of the same agent!");
+ modal.attachAndShow();
+ return;
+ }
+
var executionModule = target.getUserData("executionModule");
var executionFlow = target.getUserData("executionFlow");
var batchEntry = new org.argeo.slc.ria.execution.BatchEntrySpec(executionModule, executionFlow);
var label = batchEntry.getLabel();
- var icon = target.getIcon();
+ var icon = target.getIcon() || "resource/slc/office-document.png";
var item = new qx.ui.form.ListItem(label, icon);
item.addListener("dblclick", function(e){
this.getCommands()["editexecutionspecs"].command.execute();
this.list.add(item);
}
this.list.select(item);
- if(this.getAutoOpen()){
+ if(this.getAutoOpen() && !skipAutoOpen){
this.getCommands()["editexecutionspecs"].command.execute();
}
},
-
- /**
- * Refresh the selector when the topics are updated.
- * @param changeTopicsEvent {qx.event.type.DataEvent} The reload event.
- */
- _feedSelector : function(changeTopicsEvent){
- var topics = changeTopicsEvent.getData();
- var command = this.getCommands()["submitform"].command;
- command.setEnabled(false);
- var menu = [];
- for(var key in topics){
- var submenu = {"label":topics[key],"icon":"resource/slc/mime-xsl.png", "commandId":key};
- menu.push(submenu);
- }
- // FAKE!!
- if(!menu.length){
- menu.push({"label":"Fake Agent", "icon":"resource/slc/mime-xsl.png", "commandId":"fake_agent_uuid"});
- }
- command.clearMenus();
- command.setMenu(menu);
- if(menu.length) command.setEnabled(true);
- },
-
-
+
/**
* Called at execution
* @param agentUuid {String} The id of the target agent
for(var i=0;i<selection.length;i++){
var batchEntrySpec = selection[i].getUserData("batchEntrySpec");
slcExecMessage.addBatchEntrySpec(batchEntrySpec);
- }
- this._amqClient.sendMessage(
- "topic://agent.newExecution",
- slcExecMessage.toXml(),
- {"slc-agentId":agentUuid}
- );
+ }
+ var req = org.argeo.slc.ria.SlcApi.getNewSlcExecutionService(agentUuid, slcExecMessage.toXml());
+ req.send();
// Force logs refresh right now!
qx.event.Timer.once(function(){
var command = org.argeo.ria.event.CommandsManager.getInstance().getCommandById("reloadlogs");