--- /dev/null
+/**\r
+ * Applet for the batch manager\r
+ */\r
+qx.Class.define("org.argeo.slc.ria.BatchView",\r
+{\r
+ extend : qx.ui.container.Composite,\r
+ implement : [org.argeo.ria.components.IView], \r
+\r
+ properties : \r
+ {\r
+ /**\r
+ * The commands definition Map that will be automatically added and wired to the menubar and toolbar.\r
+ * See {@link org.argeo.ria.event.CommandsManager#definitions} for the keys to use for defining commands.\r
+ */\r
+ commands : {\r
+ init : {\r
+ "submitform" : {\r
+ label : "Execute Batch",\r
+ icon : "resource/slc/media-playback-start.png",\r
+ shortcut : null,\r
+ enabled : false,\r
+ menu : "Launcher",\r
+ toolbar : "batch",\r
+ callback : function(e) {\r
+ if (this.getBatchAgentId()) {\r
+ this.executeBatchOnAgent(this.getBatchAgentId());\r
+ }\r
+ },\r
+ command : null\r
+ },\r
+ "toggleopenonadd" : {\r
+ label : "Auto edit on Add",\r
+ icon : "resource/slc/document-open.png",\r
+ shortcut : null,\r
+ enabled : true,\r
+ toggle : true,\r
+ toggleInitialState : true,\r
+ menu : "Launcher",\r
+ toolbar : "launcher",\r
+ callback : function(event) {\r
+ var state = event.getTarget().getUserData("slc.command.toggleState");\r
+ this.setAutoOpen(state);\r
+ },\r
+ command : null\r
+ },\r
+ "editexecutionspecs" : {\r
+ label : "Edit Execution Specs",\r
+ icon : "resource/slc/document-open.png",\r
+ shortcut : null,\r
+ enabled : false,\r
+ menu : "Launcher",\r
+ toolbar : "batch",\r
+ callback : function(e) {\r
+ var sel = this.list.getSortedSelection();\r
+ var spec = sel[0].getUserData("batchEntrySpec");\r
+ if (spec.hasEditableValues()) {\r
+ var specEditor = new org.argeo.slc.ria.execution.SpecEditor(spec);\r
+ specEditor.attachAndShow();\r
+ }\r
+ },\r
+ selectionChange : function(viewId, selection) {\r
+ if (viewId != "form:list")\r
+ return;\r
+ this.setEnabled(false);\r
+ if ((selection && selection.length == 1)) {\r
+ var selectedItemSpec = selection[0].getUserData("batchEntrySpec");\r
+ if (selectedItemSpec.hasEditableValues()) {\r
+ this.setEnabled(true);\r
+ }\r
+ }\r
+ },\r
+ command : null\r
+ },\r
+ "removefrombatch" : {\r
+ label : "Remove from batch",\r
+ icon : "resource/slc/edit-delete.png",\r
+ shortcut : null,\r
+ enabled : false,\r
+ menu : "Launcher",\r
+ toolbar : "batch",\r
+ callback : function(e) {\r
+ var sel = this.list.getSortedSelection();\r
+ var modal = new org.argeo.ria.components.Modal("Confirm", null);\r
+ modal.addConfirm("Are you sure you want to remove<br> the selected test"\r
+ + (sel.length > 1 ? "s" : "")\r
+ + " from the Batch?");\r
+ modal.addListener("ok", function() {\r
+ for (var i = 0; i < sel.length; i++) {\r
+ this.list.remove(sel[i]);\r
+ }\r
+ if (!this.list.hasChildren()) {\r
+ this.setBatchAgentId(null);\r
+ }\r
+ }, this);\r
+ modal.attachAndShow();\r
+ },\r
+ selectionChange : function(viewId, selection) {\r
+ if (viewId != "form:list")\r
+ return;\r
+ this.setEnabled(false);\r
+ if ((selection && selection.length > 0))\r
+ this.setEnabled(true);\r
+ },\r
+ command : null\r
+ } \r
+ }\r
+ },\r
+ view : {\r
+ init : null\r
+ }, \r
+ viewSelection : {\r
+ nullable:false, \r
+ check:"org.argeo.ria.components.ViewSelection"\r
+ },\r
+ instanceId : {init:""},\r
+ instanceLabel : {init:""},\r
+ /**\r
+ * A boolean registering whether the SpecEditor must autoOpen or not\r
+ * when a spec is added to the Batch.\r
+ */\r
+ autoOpen : {\r
+ init : true,\r
+ check : "Boolean"\r
+ },\r
+ batchAgentId : {\r
+ init : null,\r
+ nullable : true,\r
+ check : "String",\r
+ event : "changeBatchAgentId"\r
+ } \r
+ },\r
+ \r
+ construct : function(){\r
+ this.base(arguments);\r
+ this.setLayout(new qx.ui.layout.Dock()); \r
+ },\r
+ \r
+ members : {\r
+ /**\r
+ * The implementation should contain the GUI initialisation.\r
+ * This is the role of the manager to actually add the graphical component to the pane, \r
+ * so it's not necessary to do it here. \r
+ * @param viewPane {org.argeo.ria.components.ViewPane} The pane manager\r
+ * @param data {Mixed} Any object or data passed by the initiator of the view\r
+ * @return {Boolean}\r
+ */\r
+ init : function(viewPane, data){\r
+ this.setView(viewPane); \r
+ this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId())); \r
+ this._emptyAgentString = "Empty Batch (Drop scripts here)";\r
+ this._crtAgentString = "Batch Execution on Agent ";\r
+ \r
+ },\r
+ /**\r
+ * The implementation should contain the real data loading (i.o. query...)\r
+ * @return {Boolean}\r
+ */\r
+ load : function(){\r
+ this._createLayout();\r
+ this.getView().setViewTitle(this._emptyAgentString);\r
+ //this.getView().setViewTitle("");\r
+ },\r
+ \r
+ /**\r
+ * Creates the main applet layout.\r
+ */\r
+ _createLayout : function() {\r
+ this.listPane = new qx.ui.container.Composite(new qx.ui.layout.Dock());\r
+ this.addListener("changeBatchAgentId", function(event) {\r
+ var value = event.getData();\r
+ if (value == null) {\r
+ this.getView().setViewTitle(this._emptyAgentString);\r
+ } else {\r
+ var selectorView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("selector").getContent();\r
+ if(selectorView){\r
+ var agentsMap = selectorView.getAgentsMap();\r
+ this.getView().setViewTitle(this._crtAgentString + "'" + agentsMap[value] + "'");\r
+ }\r
+ }\r
+ }, this);\r
+ \r
+ var indicator = new qx.ui.core.Widget();\r
+ indicator.setDecorator(new qx.ui.decoration.Single().set({\r
+ top : [1, "solid", "#33508D"]\r
+ }));\r
+ indicator.setHeight(0);\r
+ indicator.setOpacity(0.5);\r
+ indicator.setZIndex(100);\r
+ indicator.setLayoutProperties({\r
+ left : -1000,\r
+ top : -1000\r
+ });\r
+ org.argeo.ria.Application.INSTANCE.getRoot().add(indicator);\r
+\r
+ this.list = new qx.ui.form.List();\r
+ this.list.setDecorator(null);\r
+ this.list.setSelectionMode("multi");\r
+ this.list.setDroppable(true);\r
+ this.list.setDraggable(true);\r
+ this.list.setContextMenu(org.argeo.ria.event.CommandsManager\r
+ .getInstance().createMenuFromIds(["editexecutionspecs",\r
+ "removefrombatch"]));\r
+\r
+ this.list.addListener("dragstart", function(e) {\r
+ e.addType(["items"]);\r
+ e.addAction(["move"]);\r
+ }, this);\r
+ this.list.addListener("dragend", function(e) {\r
+ indicator.setDomPosition(-1000, -1000);\r
+ });\r
+ this.list.addListener("dragover", function(e) {\r
+ var orig = e.getOriginalTarget();\r
+ var origCoords = orig.getContainerLocation();\r
+ indicator.setWidth(orig.getBounds().width);\r
+ indicator.setDomPosition(origCoords.left,\r
+ origCoords.bottom);\r
+ });\r
+ this.list.addListener("drag", function(e) {\r
+ var orig = e.getOriginalTarget();\r
+ var origCoords = orig.getContainerLocation();\r
+ indicator.setWidth(orig.getBounds().width);\r
+ indicator.setDomPosition(origCoords.left,\r
+ origCoords.bottom);\r
+ });\r
+\r
+ this.list.addListener("drop", function(e) {\r
+ var target = e.getRelatedTarget();\r
+ var afterItem = e.getOriginalTarget();\r
+ indicator.setDomPosition(-1000, -1000);\r
+ if (afterItem.classname != "qx.ui.form.ListItem")\r
+ afterItem = null;\r
+ if (!target) {\r
+ target = this.list.getSortedSelection()[0];\r
+ this.addFlowToBatch(target, afterItem);\r
+ } else {\r
+ org.argeo.ria.event.CommandsManager.getInstance().executeCommand("addtobatch");\r
+ }\r
+ }, this);\r
+ this.listPane.add(this.list, {\r
+ edge : "center"\r
+ });\r
+\r
+ this.list.addListener("changeSelection", function(e) {\r
+ var viewSelection = this.getViewSelection();\r
+ viewSelection.setViewId("form:list");\r
+ viewSelection.clear();\r
+ var listSel = this.list.getSortedSelection();\r
+ for (var i = 0; i < listSel.length; i++) {\r
+ viewSelection.addNode(listSel[i]);\r
+ }\r
+ }, this);\r
+\r
+ listChangeListener = function() {\r
+ var command = org.argeo.ria.event.CommandsManager.getInstance()\r
+ .getCommandById("submitform");\r
+ command.setEnabled(this.list.hasChildren());\r
+ };\r
+ this.list.addListener("addItem", listChangeListener, this);\r
+ this.list.addListener("removeItem", listChangeListener, this);\r
+\r
+ \r
+ this.add(this.listPane);\r
+ }, \r
+ \r
+ \r
+ /**\r
+ * Adds a given ExecutionFlow to the batch\r
+ * \r
+ * @param target\r
+ * {mixed} The dropped target, can be a TreeFile (add) or a\r
+ * ListItem (reorder).\r
+ * @param after\r
+ * {qx.ui.form.ListItem} Optional list item : if set, the\r
+ * flow will be added as a new list item positionned after\r
+ * this one.\r
+ * @param skipAutoOpen\r
+ * {boolean} Whether the formular should open or not.\r
+ */\r
+ addFlowToBatch : function(target, after, skipAutoOpen) {\r
+ if (target && target.classname == "qx.ui.form.ListItem") {\r
+ if (!after)\r
+ return;\r
+ if (after == "first")\r
+ this.list.addAt(target, 0);\r
+ else\r
+ this.list.addAfter(target, after);\r
+ return;\r
+ }\r
+\r
+ // Folder case\r
+ if (qx.Class.isSubClassOf(qx.Class.getByName(target.classname),\r
+ qx.ui.tree.TreeFolder)) {\r
+ var allChildren = target.getItems(true);\r
+ for (var i = 0; i < allChildren.length; i++) {\r
+ if (allChildren[i].getUserData("executionFlow")) {\r
+ try{\r
+ this.addFlowToBatch(allChildren[i], null, true);\r
+ }catch(e){\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ return;\r
+ }\r
+\r
+ // Check agent Uuid against current batch agent Id.\r
+ var agentUuid = target.getUserData("agentUuid");\r
+ if (!this.getBatchAgentId()) {\r
+ this.setBatchAgentId(agentUuid);\r
+ } else if (this.getBatchAgentId() != agentUuid) {\r
+ this.error("Batch can contain tests only of the same agent!"); \r
+ throw new Error("Batch can contain tests only of the same agent!");\r
+ }\r
+\r
+ var executionModule = target.getUserData("executionModule");\r
+ var executionFlow = target.getUserData("executionFlow");\r
+ var batchEntry = new org.argeo.slc.ria.execution.BatchEntrySpec(\r
+ executionModule, executionFlow);\r
+ var label = batchEntry.getLabel();\r
+ var icon = target.getIcon() || "resource/slc/office-document.png";\r
+ var item = new qx.ui.form.ListItem(label, icon);\r
+ item.addListener("dblclick", function(e) {\r
+ this.getCommands()["editexecutionspecs"].command\r
+ .execute();\r
+ }, this);\r
+ item.setUserData("batchEntrySpec", batchEntry);\r
+ item.setPaddingTop(1);\r
+ item.setPaddingBottom(2);\r
+ if (after) {\r
+ if (after == "first")\r
+ this.list.addAt(item, 0);\r
+ else\r
+ this.list.addAfter(item, after);\r
+ } else {\r
+ this.list.add(item);\r
+ }\r
+ this.list.select(item);\r
+ if (this.getAutoOpen() && !skipAutoOpen) {\r
+ this.getCommands()["editexecutionspecs"].command.execute();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Called at execution\r
+ * \r
+ * @param agentUuid\r
+ * {String} The id of the target agent\r
+ */\r
+ executeBatchOnAgent : function(agentUuid) {\r
+ var selection = this.list.getChildren();\r
+ if (!selection.length)\r
+ return;\r
+ var slcExecMessage = new org.argeo.slc.ria.execution.Message();\r
+ for (var i = 0; i < selection.length; i++) {\r
+ var batchEntrySpec = selection[i].getUserData("batchEntrySpec");\r
+ slcExecMessage.addBatchEntrySpec(batchEntrySpec);\r
+ }\r
+ var req = org.argeo.slc.ria.SlcApi.getNewSlcExecutionService(\r
+ agentUuid, slcExecMessage.toXml());\r
+ req.send();\r
+ // Force logs refresh right now!\r
+ qx.event.Timer.once(function() {\r
+ var command = org.argeo.ria.event.CommandsManager\r
+ .getInstance().getCommandById("reloadlogs");\r
+ if (command) {\r
+ command.execute();\r
+ }\r
+ }, this, 2000);\r
+ },\r
+ \r
+ clearBatchForAgentId : function(agentId){\r
+ if(this.getBatchAgentId() == agentId){\r
+ this.list.removeAll(); \r
+ this.setBatchAgentId(null);\r
+ }\r
+ },\r
+ \r
+ /**\r
+ * Whether this component is already contained in a scroller (return false) or not (return true).\r
+ * @return {Boolean}\r
+ */\r
+ addScroll : function(){return false;},\r
+ /**\r
+ * Called at destruction time\r
+ * Perform all the clean operations (stopping polling queries, etc.) \r
+ */\r
+ close : function(){return true;}\r
+ }\r
+ \r
+\r
+});
\ No newline at end of file
--- /dev/null
+/**\r
+ * The selector view\r
+ * \r
+ */\r
+qx.Class.define("org.argeo.slc.ria.FlowsSelectorView", {\r
+ extend : qx.ui.container.Composite,\r
+ implement : [org.argeo.ria.components.IView],\r
+\r
+ construct : function() {\r
+ this.base(arguments);\r
+ this.setLayout(new qx.ui.layout.Dock());\r
+ },\r
+\r
+ properties : {\r
+ /**\r
+ * The viewPane inside which this applet is added.\r
+ */\r
+ view : {\r
+ init : null\r
+ },\r
+ viewSelection : {\r
+ nullable : false,\r
+ check : "org.argeo.ria.components.ViewSelection"\r
+ },\r
+ instanceId : {\r
+ init : ""\r
+ },\r
+ instanceLabel : {\r
+ init : ""\r
+ },\r
+ /**\r
+ * Commands definition, see\r
+ * {@link org.argeo.ria.event.CommandsManager#definitions}\r
+ */\r
+ commands : {\r
+ init : {\r
+ "addtobatch" : {\r
+ label : "Add to batch",\r
+ icon : "resource/slc/list-add.png",\r
+ shortcut : null,\r
+ enabled : true,\r
+ menu : null,\r
+ toolbar : null,\r
+ callback : function(e) {\r
+ if (this.tree.isSelectionEmpty()) {\r
+ return;\r
+ }\r
+ var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();\r
+ if(!batchView) return;\r
+ selection = this.tree.getSelection();\r
+ if (selection.length > 1) {\r
+ for (var i = 0; i < selection.length; i++) {\r
+ try{\r
+ batchView.addFlowToBatch(selection[i], null, true);\r
+ }catch(e){\r
+ return;\r
+ }\r
+ }\r
+ return;\r
+ } else {\r
+ try{\r
+ batchView.addFlowToBatch(selection[0], null);\r
+ }catch(e){\r
+ return;\r
+ }\r
+ }\r
+ },\r
+ selectionChange : function(viewId, selection) {\r
+ if (viewId != "form:tree")\r
+ return;\r
+ if (!selection || selection.length != 1)\r
+ return;\r
+ var item = selection[0];\r
+ this.setEnabled(false);\r
+ switch (item.classname) {\r
+ case "qx.ui.tree.TreeFile" :\r
+ this.setEnabled(true);\r
+ break;\r
+ case "qx.ui.tree.TreeFolder" :\r
+ if (item.getTree().getRoot() == item)\r
+ break;\r
+ this.setEnabled(true);\r
+ break;\r
+ case "org.argeo.ria.components.DynamicTreeFolder" :\r
+ if (item.getTree().getRoot() == item)\r
+ break; \r
+ if (item.getState() == "loaded")\r
+ this.setEnabled(true);\r
+ break;\r
+ }\r
+ },\r
+ command : null\r
+ },\r
+ "reloadtree" : {\r
+ label : "Reload",\r
+ icon : "resource/slc/view-refresh.png",\r
+ shortcut : "Control+m",\r
+ enabled : false,\r
+ menu : "Launcher",\r
+ toolbar : "launcher",\r
+ callback : function(e) {\r
+ if (this.tree.isSelectionEmpty()) { return; } \r
+ var selected = this.tree.getSelection()[0];\r
+ if (selected.classname == "org.argeo.ria.components.DynamicTreeFolder") {\r
+ if (selected.getUserData("moduleData")) {\r
+ // It's a "module" node, first trigger the\r
+ // reloadBundle.service\r
+ selected.setUserData("dataModel", {});\r
+ selected.setEnabled(false);\r
+ selected.setOpen(false);\r
+ var moduleData = selected\r
+ .getUserData("moduleData");\r
+ var bundleService = org.argeo.slc.ria.SlcApi\r
+ .getReloadBundleService(\r
+ moduleData.name,\r
+ moduleData.version);\r
+ bundleService.addListener("completed",\r
+ function(response) {\r
+ selected.setEnabled(true);\r
+ selected.setOpen(true);\r
+ selected.reload();\r
+ }, this);\r
+ // bundleService.send();\r
+ // Do not send, not implemented yet, false timer\r
+ // instead.\r
+ qx.event.Timer.once(function(response) {\r
+ selected.setEnabled(true);\r
+ selected.setOpen(true);\r
+ selected.reload();\r
+ }, this, 2000);\r
+ } else {\r
+ selected.reload();\r
+ }\r
+ }\r
+ },\r
+ selectionChange : function(viewId, selection) {\r
+ if (viewId != "form:tree")\r
+ return;\r
+ if (!selection)\r
+ return;\r
+ if (selection.length > 1) {\r
+ this.setEnabled(false);\r
+ return;\r
+ }\r
+ var item = selection[0];\r
+ if (!qx.Class.isSubClassOf(qx.Class\r
+ .getByName(item.classname),\r
+ qx.ui.tree.AbstractTreeItem))\r
+ return;\r
+ this.setEnabled(false);\r
+ if (qx.Class.isSubClassOf(qx.Class\r
+ .getByName(item.classname),\r
+ org.argeo.ria.components.DynamicTreeFolder)) {\r
+ this.setEnabled(true);\r
+ }\r
+ },\r
+ command : null\r
+ }\r
+ }\r
+ }\r
+ },\r
+\r
+ statics : {\r
+ /**\r
+ * Static loader for the "agent" level (first level)\r
+ * \r
+ * @param folder\r
+ * {qx.ui.tree.TreeFolder} The root Tree Folder.\r
+ */\r
+ agentLoader : function(folder) {\r
+\r
+ var req = org.argeo.slc.ria.SlcApi.getListAgentsService("agents"); \r
+ var agents = {};\r
+ if(folder.getState() == "loaded" && folder.getUserData("agentsMap")){\r
+ // Diff loading, just add new nodes.\r
+ agents = folder.getUserData("agentsMap");\r
+ var newAgents = {};\r
+ }\r
+ req.addListener("completed", function(response) {\r
+ var xmlDoc = response.getContent();\r
+ var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc,\r
+ "//slc:slc-agent-descriptor");\r
+ var modulesLoader = org.argeo.slc.ria.FlowsSelectorView.modulesLoader;\r
+ \r
+ for (var i = 0; i < nodes.length; i++) {\r
+ var uuid = org.argeo.ria.util.Element.getSingleNodeText(\r
+ nodes[i], "@uuid");\r
+ if(agents[uuid]){\r
+ newAgents[uuid] = host;\r
+ continue;\r
+ }\r
+ var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");\r
+ agents[uuid] = host;\r
+ if(newAgents) newAgents[uuid] = host;\r
+ var agentFolder = new org.argeo.ria.components.DynamicTreeFolder(\r
+ host + ' (' + uuid + ')', modulesLoader,\r
+ "Loading Modules...", folder.getDragData());\r
+ agentFolder.setUserData("agentUuid", uuid);\r
+ agentFolder.setIcon("resource/slc/mime-xsl-22.png");\r
+ folder.add(agentFolder);\r
+ }\r
+ if(newAgents){\r
+ // Make sure some agents should not be removed\r
+ for(var agentKey in agents){\r
+ if(!newAgents[agentKey]){\r
+ var node = org.argeo.slc.ria.FlowsSelectorView.findAgentNodeById(folder, agentKey);\r
+ if(node) folder.remove(node);\r
+ delete agents[agentKey];\r
+ var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();\r
+ if(batchView) batchView.clearBatchForAgentId(agentKey);\r
+ }\r
+ }\r
+ }\r
+ folder.setUserData("agentsMap", agents);\r
+ folder.setLoaded(true);\r
+ folder.getTree().fireEvent("changeSelection"); \r
+ });\r
+ req.addListener("failed", function(response) {\r
+ folder.setLoaded(true);\r
+ });\r
+ req.send();\r
+\r
+ },\r
+\r
+ /**\r
+ * Loader for the "modules" level : takes any tree folder, currently the\r
+ * root folder.\r
+ * \r
+ * @param folder\r
+ * {qx.ui.tree.TreeFolder} The root folder\r
+ */\r
+ modulesLoader : function(folder) {\r
+ var agentId = folder.getUserData("agentUuid");\r
+ var req = org.argeo.slc.ria.SlcApi.getListModulesService(agentId);\r
+ req.addListener("completed", function(response) {\r
+ var descriptors = org.argeo.ria.util.Element.selectNodes(\r
+ response.getContent(),\r
+ "slc:object-list/slc:execution-module-descriptor");\r
+ var mods = {};\r
+ for (var i = 0; i < descriptors.length; i++) {\r
+ var name = org.argeo.ria.util.Element.getSingleNodeText(\r
+ descriptors[i], "slc:name");\r
+ var version = org.argeo.ria.util.Element.getSingleNodeText(\r
+ descriptors[i], "slc:version");\r
+ if (!mods[name])\r
+ mods[name] = [];\r
+ mods[name].push(version);\r
+ }\r
+ var flowLoader = org.argeo.slc.ria.FlowsSelectorView.flowLoader;\r
+ for (var key in mods) {\r
+ for (var i = 0; i < mods[key].length; i++) {\r
+ var versionFolder = new org.argeo.ria.components.DynamicTreeFolder(\r
+ key + ' (' + mods[key][i] + ')', flowLoader,\r
+ "Loading Flows", folder.getDragData());\r
+ folder.add(versionFolder);\r
+ versionFolder.setUserData("moduleData", {\r
+ name : key,\r
+ version : mods[key][i]\r
+ });\r
+ versionFolder.setUserData("agentUuid", agentId);\r
+ }\r
+ }\r
+ folder.setLoaded(true);\r
+ folder.getTree().fireEvent("changeSelection");\r
+ });\r
+ req.addListener("failed", function(response) {\r
+ folder.setLoaded(true);\r
+ });\r
+ req.send();\r
+ },\r
+\r
+ /**\r
+ * Loader for the "flow" level : takes a folder containing "moduleData"\r
+ * and create its children.\r
+ * \r
+ * @param folder\r
+ * {qx.ui.tree.TreeFolder} A Tree folder containing in the\r
+ * key "moduleData" of its user data a map containing the\r
+ * keys {name,version}\r
+ */\r
+ flowLoader : function(folder) {\r
+ var moduleData = folder.getUserData("moduleData");\r
+ var agentUuid = folder.getUserData("agentUuid");\r
+\r
+ var req = org.argeo.slc.ria.SlcApi\r
+ .getLoadExecutionDescriptorService(agentUuid,\r
+ moduleData.name, moduleData.version);\r
+ req.addListener("completed", function(response) {\r
+ var executionModule = new org.argeo.slc.ria.execution.Module();\r
+ try {\r
+ executionModule.setXmlNode(response.getContent());\r
+ } catch (e) {\r
+ this.error(e);\r
+ }\r
+ var execFlows = executionModule.getExecutionFlows();\r
+ for (var key in execFlows) {\r
+ var file = new qx.ui.tree.TreeFile(key);\r
+ var path = execFlows[key].getPath();\r
+ file.setUserData("executionModule", executionModule);\r
+ file.setUserData("executionFlow", execFlows[key]);\r
+ file.setUserData("agentUuid", agentUuid);\r
+ org.argeo.slc.ria.FlowsSelectorView.attachNodeByPath(folder, path, file, {\r
+ agentUuid : folder.getUserData("agentUuid")\r
+ });\r
+ folder.appendDragData(file);\r
+ }\r
+ folder.setLoaded(true);\r
+ folder.getTree().fireEvent("changeSelection");\r
+ });\r
+ req.addListener("failed", function(response) {\r
+ folder.setLoaded(true);\r
+ });\r
+ req.send();\r
+ },\r
+\r
+ /**\r
+ * Parse a string path and search if there is a root node.\r
+ * \r
+ * @param rootNode\r
+ * {org.argeo.ria.components.DynamicTreeFolder} The parent\r
+ * node (containing data model)\r
+ * @param path\r
+ * {String} The path of the node to attach.\r
+ * @param childNode\r
+ * {qx.ui.tree.TreeFile} The leaf node\r
+ * @param userData\r
+ * {Map} User data to attach at all levels.\r
+ */\r
+ attachNodeByPath : function(rootNode, path, childNode, userData) {\r
+ if (!path || path == "" || path == "/") {\r
+ rootNode.add(childNode);\r
+ return;\r
+ }\r
+ var model = rootNode.getUserData("dataModel");\r
+ if (!model) {\r
+ model = {};\r
+ rootNode.setUserData("dataModel", model);\r
+ }\r
+ var parts = path.split("/");\r
+ var keys = qx.lang.Object.getKeys(model);\r
+ var crtPath = "";\r
+ var crtFolder = rootNode; \r
+ for (var i = 0; i < parts.length; i++) {\r
+ if (parts[i] == "")\r
+ continue;\r
+ crtPath += "/" + parts[i]; \r
+ if (!model[crtPath]) {\r
+ var virtualFolder = new qx.ui.tree.TreeFolder(parts[i]);\r
+ if (userData && qx.lang.Object.getLength(userData)) {\r
+ for (var key in userData) {\r
+ virtualFolder.setUserData(key, userData[key]);\r
+ }\r
+ }\r
+ rootNode.appendDragData(virtualFolder);\r
+ model[crtPath] = virtualFolder;\r
+ crtFolder.add(virtualFolder);\r
+ crtFolder = virtualFolder;\r
+ } else {\r
+ crtFolder = model[crtPath];\r
+ }\r
+ }\r
+ crtFolder.add(childNode);\r
+ },\r
+ \r
+ findAgentNodeById : function(node, agentId){\r
+ var nodeAgents = node.getItems();\r
+ for(var i=0;i<nodeAgents.length;i++){\r
+ if(nodeAgents[i].getUserData("agentUuid") == agentId){\r
+ return nodeAgents[i];\r
+ }\r
+ }\r
+ } \r
+ },\r
+\r
+ members : {\r
+ /**\r
+ * Called at applet creation. Just registers viewPane.\r
+ * \r
+ * @param viewPane\r
+ * {org.argeo.ria.components.ViewPane} The viewPane.\r
+ */\r
+ init : function(viewPane) {\r
+ this.setView(viewPane);\r
+ this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));\r
+ this.remoteNotifier = new org.argeo.ria.remote.RemoteNotifier(\r
+ "/org.argeo.slc.webapp/", "pollEvent.service",\r
+ "addEventListener.service", "removeEventListener.service");\r
+ this.remoteNotifier.setEventParamName("slc_eventType");\r
+ this.remoteNotifier.setEventXPath("/slc:slc-event");\r
+ this.remoteNotifier\r
+ .setEventTypeXPath('slc:headers/slc:header[@name="slc_eventType"]');\r
+ this.remoteNotifier\r
+ .setEventDataXPath('slc:headers/slc:header[@name="slc_agentId"]');\r
+ this.remoteNotifier.startPolling();\r
+ this.UIBus = org.argeo.ria.event.UIBus.getInstance();\r
+ this.UIBus.registerNotifier(this.remoteNotifier);\r
+ },\r
+\r
+ /**\r
+ * \r
+ */\r
+ load : function() {\r
+ this._createLayout();\r
+ this.getView().setViewTitle("Available Scripts");\r
+ this.UIBus.addListener("agentRegistered", this._addAgentHandler, this);\r
+ this.UIBus.addListener("agentUnregistered", this._removeAgentHandler, this);\r
+ },\r
+\r
+ _addAgentHandler : function(agentId){\r
+ this.rootNode.load();\r
+ },\r
+ \r
+ _removeAgentHandler : function(agentId){\r
+ var treeNode = this.self(arguments).findAgentNodeById(this.rootNode, agentId);\r
+ if(treeNode){\r
+ this.rootNode.remove(treeNode);\r
+ }\r
+ var agentsMap = this.getAgentsMap();\r
+ if(agentsMap[agentId]){ \r
+ delete agentsMap[agentId];\r
+ }\r
+ var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();\r
+ if(batchView){\r
+ batchView.clearBatchForAgentId(agentId);\r
+ }\r
+ },\r
+ \r
+ addScroll : function() {\r
+ return false;\r
+ },\r
+\r
+ close : function() {\r
+ this.UIBus.removeListener("agentRegistered", this._addAgentHandler, this);\r
+ this.UIBus.removeListener("agentUnregistered", this._removeAgentHandler, this);\r
+ this.remoteNotifier.stopPolling();\r
+ },\r
+\r
+ /**\r
+ * Creates the main applet layout.\r
+ */\r
+ _createLayout : function() {\r
+\r
+ this.tree = new qx.ui.tree.Tree();\r
+ this.tree.setDecorator(null);\r
+ this.tree.setSelectionMode("multi");\r
+ var dragData = {\r
+ "file" : {\r
+ "type" : ["items"],\r
+ "action" : ["move"]\r
+ },\r
+ "folder" : {\r
+ "type" : ["items"],\r
+ "action" : ["move"]\r
+ }\r
+ };\r
+\r
+ this.rootNode = new org.argeo.ria.components.DynamicTreeFolder(\r
+ "Tests", this.self(arguments).agentLoader,\r
+ "Loading Agents", dragData);\r
+ this.tree.setRoot(this.rootNode);\r
+ this.rootNode.setOpen(true);\r
+ this.tree.setContextMenu(org.argeo.ria.event.CommandsManager\r
+ .getInstance().createMenuFromIds(["addtobatch",\r
+ "reloadtree"]));\r
+\r
+ this.tree.addListener("changeSelection", function(e) {\r
+ var viewSelection = this.getViewSelection();\r
+ viewSelection.setViewId("form:tree");\r
+ viewSelection.clear();\r
+ var sel = this.tree.getSortedSelection();\r
+ for (var i = 0; i < sel.length; i++) {\r
+ viewSelection.addNode(sel[i]);\r
+ }\r
+ }, this);\r
+\r
+\r
+ this.add(this.tree);\r
+ },\r
+ \r
+ getAgentsMap : function(){\r
+ return this.rootNode.getUserData("agentsMap");\r
+ } \r
+ }\r
+});
\ No newline at end of file