]> git.argeo.org Git - gpl/argeo-slc.git/blob - server/org.argeo.slc.ria/src/argeo-ria-lib/slc/class/org/argeo/slc/ria/FlowsSelectorView.js
Fix various things in the launcher perspective, better layout.
[gpl/argeo-slc.git] / server / org.argeo.slc.ria / src / argeo-ria-lib / slc / class / org / argeo / slc / ria / FlowsSelectorView.js
1 /**
2 * The selector view
3 *
4 */
5 qx.Class.define("org.argeo.slc.ria.FlowsSelectorView", {
6 extend : qx.ui.container.Composite,
7 implement : [org.argeo.ria.components.IView],
8
9 construct : function() {
10 this.base(arguments);
11 this.setLayout(new qx.ui.layout.Dock());
12 },
13
14 properties : {
15 /**
16 * The viewPane inside which this applet is added.
17 */
18 view : {
19 init : null
20 },
21 viewSelection : {
22 nullable : false,
23 check : "org.argeo.ria.components.ViewSelection"
24 },
25 instanceId : {
26 init : ""
27 },
28 instanceLabel : {
29 init : ""
30 },
31 /**
32 * Commands definition, see
33 * {@link org.argeo.ria.event.CommandsManager#definitions}
34 */
35 commands : {
36 init : {
37 "addtobatch" : {
38 label : "Add to batch",
39 icon : "resource/slc/list-add.png",
40 shortcut : null,
41 enabled : true,
42 menu : null,
43 toolbar : null,
44 callback : function(e) {
45 if (this.tree.isSelectionEmpty()) {
46 return;
47 }
48 var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();
49 if(!batchView) return;
50 selection = this.tree.getSelection();
51 if (selection.length > 1) {
52 for (var i = 0; i < selection.length; i++) {
53 try{
54 batchView.addFlowToBatch(selection[i], null, true);
55 }catch(e){
56 return;
57 }
58 }
59 return;
60 } else {
61 try{
62 batchView.addFlowToBatch(selection[0], null);
63 }catch(e){
64 return;
65 }
66 }
67 },
68 selectionChange : function(viewId, selection) {
69 if (viewId != "form:tree")
70 return;
71 if (!selection || selection.length != 1)
72 return;
73 var item = selection[0];
74 this.setEnabled(false);
75 switch (item.classname) {
76 case "qx.ui.tree.TreeFile" :
77 this.setEnabled(true);
78 break;
79 case "qx.ui.tree.TreeFolder" :
80 if (item.getTree().getRoot() == item)
81 break;
82 this.setEnabled(true);
83 break;
84 case "org.argeo.ria.components.DynamicTreeFolder" :
85 if (item.getTree().getRoot() == item)
86 break;
87 if (item.getState() == "loaded")
88 this.setEnabled(true);
89 break;
90 }
91 },
92 command : null
93 },
94 "reloadtree" : {
95 label : "Reload",
96 icon : "resource/slc/view-refresh.png",
97 shortcut : "Control+m",
98 enabled : false,
99 menu : "Launcher",
100 toolbar : "launcher",
101 callback : function(e) {
102 if (this.tree.isSelectionEmpty()) { return; }
103 var selected = this.tree.getSelection()[0];
104 if (selected.classname == "org.argeo.ria.components.DynamicTreeFolder") {
105 if (selected.getUserData("moduleData")) {
106 // It's a "module" node, first trigger the
107 // reloadBundle.service
108 selected.setUserData("dataModel", {});
109 selected.setEnabled(false);
110 selected.setOpen(false);
111 var moduleData = selected
112 .getUserData("moduleData");
113 var bundleService = org.argeo.slc.ria.SlcApi
114 .getReloadBundleService(
115 moduleData.name,
116 moduleData.version);
117 bundleService.addListener("completed",
118 function(response) {
119 selected.setEnabled(true);
120 selected.setOpen(true);
121 selected.reload();
122 }, this);
123 // bundleService.send();
124 // Do not send, not implemented yet, false timer
125 // instead.
126 qx.event.Timer.once(function(response) {
127 selected.setEnabled(true);
128 selected.setOpen(true);
129 selected.reload();
130 }, this, 2000);
131 } else {
132 selected.reload();
133 }
134 }
135 },
136 selectionChange : function(viewId, selection) {
137 if (viewId != "form:tree")
138 return;
139 if (!selection)
140 return;
141 if (selection.length > 1) {
142 this.setEnabled(false);
143 return;
144 }
145 var item = selection[0];
146 if (!qx.Class.isSubClassOf(qx.Class
147 .getByName(item.classname),
148 qx.ui.tree.AbstractTreeItem))
149 return;
150 this.setEnabled(false);
151 if (qx.Class.isSubClassOf(qx.Class
152 .getByName(item.classname),
153 org.argeo.ria.components.DynamicTreeFolder)) {
154 this.setEnabled(true);
155 }
156 },
157 command : null
158 }
159 }
160 }
161 },
162
163 statics : {
164 /**
165 * Static loader for the "agent" level (first level)
166 *
167 * @param folder
168 * {qx.ui.tree.TreeFolder} The root Tree Folder.
169 */
170 agentLoader : function(folder) {
171
172 var req = org.argeo.slc.ria.SlcApi.getListAgentsService("agents");
173 var agents = {};
174 if(folder.getState() == "loaded" && folder.getUserData("agentsMap")){
175 // Diff loading, just add new nodes.
176 agents = folder.getUserData("agentsMap");
177 var newAgents = {};
178 }
179 req.addListener("completed", function(response) {
180 var xmlDoc = response.getContent();
181 var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc,
182 "//slc:slc-agent-descriptor");
183 var modulesLoader = org.argeo.slc.ria.FlowsSelectorView.modulesLoader;
184
185 for (var i = 0; i < nodes.length; i++) {
186 var uuid = org.argeo.ria.util.Element.getSingleNodeText(
187 nodes[i], "@uuid");
188 if(agents[uuid]){
189 newAgents[uuid] = host;
190 continue;
191 }
192 var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
193 agents[uuid] = host;
194 if(newAgents) newAgents[uuid] = host;
195 var agentFolder = new org.argeo.ria.components.DynamicTreeFolder(
196 host + ' (' + uuid + ')', modulesLoader,
197 "Loading Modules...", folder.getDragData());
198 agentFolder.setUserData("agentUuid", uuid);
199 agentFolder.setIcon("resource/slc/mime-xsl-22.png");
200 folder.add(agentFolder);
201 }
202 if(newAgents){
203 // Make sure some agents should not be removed
204 for(var agentKey in agents){
205 if(!newAgents[agentKey]){
206 var node = org.argeo.slc.ria.FlowsSelectorView.findAgentNodeById(folder, agentKey);
207 if(node) folder.remove(node);
208 delete agents[agentKey];
209 var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();
210 if(batchView) batchView.clearBatchForAgentId(agentKey);
211 }
212 }
213 }
214 folder.setUserData("agentsMap", agents);
215 folder.setLoaded(true);
216 folder.getTree().fireEvent("changeSelection");
217 });
218 req.addListener("failed", function(response) {
219 folder.setLoaded(true);
220 });
221 req.send();
222
223 },
224
225 /**
226 * Loader for the "modules" level : takes any tree folder, currently the
227 * root folder.
228 *
229 * @param folder
230 * {qx.ui.tree.TreeFolder} The root folder
231 */
232 modulesLoader : function(folder) {
233 var agentId = folder.getUserData("agentUuid");
234 var req = org.argeo.slc.ria.SlcApi.getListModulesService(agentId);
235 req.addListener("completed", function(response) {
236 var descriptors = org.argeo.ria.util.Element.selectNodes(
237 response.getContent(),
238 "slc:object-list/slc:execution-module-descriptor");
239 var mods = {};
240 for (var i = 0; i < descriptors.length; i++) {
241 var name = org.argeo.ria.util.Element.getSingleNodeText(
242 descriptors[i], "slc:name");
243 var version = org.argeo.ria.util.Element.getSingleNodeText(
244 descriptors[i], "slc:version");
245 if (!mods[name])
246 mods[name] = [];
247 mods[name].push(version);
248 }
249 var flowLoader = org.argeo.slc.ria.FlowsSelectorView.flowLoader;
250 for (var key in mods) {
251 for (var i = 0; i < mods[key].length; i++) {
252 var versionFolder = new org.argeo.ria.components.DynamicTreeFolder(
253 key + ' (' + mods[key][i] + ')', flowLoader,
254 "Loading Flows", folder.getDragData());
255 folder.add(versionFolder);
256 versionFolder.setUserData("moduleData", {
257 name : key,
258 version : mods[key][i]
259 });
260 versionFolder.setUserData("agentUuid", agentId);
261 }
262 }
263 folder.setLoaded(true);
264 folder.getTree().fireEvent("changeSelection");
265 });
266 req.addListener("failed", function(response) {
267 folder.setLoaded(true);
268 });
269 req.send();
270 },
271
272 /**
273 * Loader for the "flow" level : takes a folder containing "moduleData"
274 * and create its children.
275 *
276 * @param folder
277 * {qx.ui.tree.TreeFolder} A Tree folder containing in the
278 * key "moduleData" of its user data a map containing the
279 * keys {name,version}
280 */
281 flowLoader : function(folder) {
282 var moduleData = folder.getUserData("moduleData");
283 var agentUuid = folder.getUserData("agentUuid");
284
285 var req = org.argeo.slc.ria.SlcApi
286 .getLoadExecutionDescriptorService(agentUuid,
287 moduleData.name, moduleData.version);
288 req.addListener("completed", function(response) {
289 var executionModule = new org.argeo.slc.ria.execution.Module();
290 try {
291 executionModule.setXmlNode(response.getContent());
292 } catch (e) {
293 this.error(e);
294 }
295 var execFlows = executionModule.getExecutionFlows();
296 for (var key in execFlows) {
297 var file = new qx.ui.tree.TreeFile(key);
298 var path = execFlows[key].getPath();
299 file.setUserData("executionModule", executionModule);
300 file.setUserData("executionFlow", execFlows[key]);
301 file.setUserData("agentUuid", agentUuid);
302 org.argeo.slc.ria.FlowsSelectorView.attachNodeByPath(folder, path, file, {
303 agentUuid : folder.getUserData("agentUuid")
304 });
305 folder.appendDragData(file);
306 }
307 folder.setLoaded(true);
308 folder.getTree().fireEvent("changeSelection");
309 });
310 req.addListener("failed", function(response) {
311 folder.setLoaded(true);
312 });
313 req.send();
314 },
315
316 /**
317 * Parse a string path and search if there is a root node.
318 *
319 * @param rootNode
320 * {org.argeo.ria.components.DynamicTreeFolder} The parent
321 * node (containing data model)
322 * @param path
323 * {String} The path of the node to attach.
324 * @param childNode
325 * {qx.ui.tree.TreeFile} The leaf node
326 * @param userData
327 * {Map} User data to attach at all levels.
328 */
329 attachNodeByPath : function(rootNode, path, childNode, userData) {
330 if (!path || path == "" || path == "/") {
331 rootNode.add(childNode);
332 return;
333 }
334 var model = rootNode.getUserData("dataModel");
335 if (!model) {
336 model = {};
337 rootNode.setUserData("dataModel", model);
338 }
339 var parts = path.split("/");
340 var keys = qx.lang.Object.getKeys(model);
341 var crtPath = "";
342 var crtFolder = rootNode;
343 for (var i = 0; i < parts.length; i++) {
344 if (parts[i] == "")
345 continue;
346 crtPath += "/" + parts[i];
347 if (!model[crtPath]) {
348 var virtualFolder = new qx.ui.tree.TreeFolder(parts[i]);
349 if (userData && qx.lang.Object.getLength(userData)) {
350 for (var key in userData) {
351 virtualFolder.setUserData(key, userData[key]);
352 }
353 }
354 rootNode.appendDragData(virtualFolder);
355 model[crtPath] = virtualFolder;
356 crtFolder.add(virtualFolder);
357 crtFolder = virtualFolder;
358 } else {
359 crtFolder = model[crtPath];
360 }
361 }
362 crtFolder.add(childNode);
363 },
364
365 findAgentNodeById : function(node, agentId){
366 var nodeAgents = node.getItems();
367 for(var i=0;i<nodeAgents.length;i++){
368 if(nodeAgents[i].getUserData("agentUuid") == agentId){
369 return nodeAgents[i];
370 }
371 }
372 }
373 },
374
375 members : {
376 /**
377 * Called at applet creation. Just registers viewPane.
378 *
379 * @param viewPane
380 * {org.argeo.ria.components.ViewPane} The viewPane.
381 */
382 init : function(viewPane) {
383 this.setView(viewPane);
384 this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));
385 this.remoteNotifier = new org.argeo.ria.remote.RemoteNotifier(
386 "/org.argeo.slc.webapp/", "pollEvent.service",
387 "addEventListener.service", "removeEventListener.service");
388 this.remoteNotifier.setEventParamName("slc_eventType");
389 this.remoteNotifier.setEventXPath("/slc:slc-event");
390 this.remoteNotifier
391 .setEventTypeXPath('slc:headers/slc:header[@name="slc_eventType"]');
392 this.remoteNotifier
393 .setEventDataXPath('slc:headers/slc:header[@name="slc_agentId"]');
394 this.remoteNotifier.startPolling();
395 this.UIBus = org.argeo.ria.event.UIBus.getInstance();
396 this.UIBus.registerNotifier(this.remoteNotifier);
397 },
398
399 /**
400 *
401 */
402 load : function() {
403 this._createLayout();
404 this.getView().setViewTitle("Available Scripts");
405 this.UIBus.addListener("agentRegistered", this._addAgentHandler, this);
406 this.UIBus.addListener("agentUnregistered", this._removeAgentHandler, this);
407 },
408
409 _addAgentHandler : function(agentId){
410 this.rootNode.load();
411 },
412
413 _removeAgentHandler : function(agentId){
414 var treeNode = this.self(arguments).findAgentNodeById(this.rootNode, agentId);
415 if(treeNode){
416 this.rootNode.remove(treeNode);
417 }
418 var agentsMap = this.getAgentsMap();
419 if(agentsMap[agentId]){
420 delete agentsMap[agentId];
421 }
422 var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();
423 if(batchView){
424 batchView.clearBatchForAgentId(agentId);
425 }
426 },
427
428 addScroll : function() {
429 return false;
430 },
431
432 close : function() {
433 this.UIBus.removeListener("agentRegistered", this._addAgentHandler, this);
434 this.UIBus.removeListener("agentUnregistered", this._removeAgentHandler, this);
435 this.remoteNotifier.stopPolling();
436 },
437
438 /**
439 * Creates the main applet layout.
440 */
441 _createLayout : function() {
442
443 this.tree = new qx.ui.tree.Tree();
444 this.tree.setDecorator(null);
445 this.tree.setSelectionMode("multi");
446 var dragData = {
447 "file" : {
448 "type" : ["items"],
449 "action" : ["move"]
450 },
451 "folder" : {
452 "type" : ["items"],
453 "action" : ["move"]
454 }
455 };
456
457 this.rootNode = new org.argeo.ria.components.DynamicTreeFolder(
458 "Tests", this.self(arguments).agentLoader,
459 "Loading Agents", dragData);
460 this.tree.setRoot(this.rootNode);
461 this.rootNode.setOpen(true);
462 this.tree.setContextMenu(org.argeo.ria.event.CommandsManager
463 .getInstance().createMenuFromIds(["addtobatch",
464 "reloadtree"]));
465
466 this.tree.addListener("changeSelection", function(e) {
467 var viewSelection = this.getViewSelection();
468 viewSelection.setViewId("form:tree");
469 viewSelection.clear();
470 var sel = this.tree.getSortedSelection();
471 for (var i = 0; i < sel.length; i++) {
472 viewSelection.addNode(sel[i]);
473 }
474 }, this);
475
476
477 this.add(this.tree);
478 },
479
480 getAgentsMap : function(){
481 return this.rootNode.getUserData("agentsMap");
482 }
483 }
484 });