]> 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
Implement Preferences
[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 : "org.argeo.slc.ria/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 "org.argeo.ria.components.PersistentTreeFolder" :
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 : "org.argeo.slc.ria/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 * {org.argeo.ria.components.PersistentTreeFolder} 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(nodes[i], "@uuid");
187 var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
188 if(agents[uuid]){
189 newAgents[uuid] = host;
190 continue;
191 }
192 agents[uuid] = host;
193 if(newAgents) newAgents[uuid] = host;
194 var agentFolder = new org.argeo.ria.components.DynamicTreeFolder(
195 host + ' (' + uuid + ')', modulesLoader,
196 "Loading Modules...", folder.getDragData());
197 agentFolder.setUserData("agentUuid", uuid);
198 agentFolder.setIcon("org.argeo.slc.ria/mime-xsl-22.png");
199 folder.add(agentFolder);
200 }
201 if(newAgents){
202 // Make sure some agents should not be removed
203 for(var agentKey in agents){
204 if(!newAgents[agentKey]){
205 var node = org.argeo.slc.ria.FlowsSelectorView.findAgentNodeById(folder, agentKey);
206 if(node) folder.remove(node);
207 delete agents[agentKey];
208 var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();
209 if(batchView) batchView.clearBatchForAgentId(agentKey);
210 }
211 }
212 }
213 folder.setUserData("agentsMap", agents);
214 folder.setLoaded(true);
215 folder.getTree().fireEvent("changeSelection");
216 });
217 req.addListener("failed", function(response) {
218 folder.setLoaded(true);
219 });
220 req.send();
221
222 },
223
224 /**
225 * Loader for the "modules" level : takes any tree folder, currently the
226 * root folder.
227 *
228 * @param folder
229 * {org.argeo.ria.components.PersistentTreeFolder} The root folder
230 */
231 modulesLoader : function(folder) {
232 var agentId = folder.getUserData("agentUuid");
233 var req = org.argeo.slc.ria.SlcApi.getListModulesService(agentId);
234 req.addListener("completed", function(response) {
235 var descriptors = org.argeo.ria.util.Element.selectNodes(
236 response.getContent(),
237 "slc:object-list/slc:execution-module-descriptor");
238 var mods = {};
239 for (var i = 0; i < descriptors.length; i++) {
240 var name = org.argeo.ria.util.Element.getSingleNodeText(
241 descriptors[i], "slc:name");
242 var version = org.argeo.ria.util.Element.getSingleNodeText(
243 descriptors[i], "slc:version");
244 if (!mods[name])
245 mods[name] = [];
246 mods[name].push(version);
247 }
248 var flowLoader = org.argeo.slc.ria.FlowsSelectorView.flowLoader;
249 for (var key in mods) {
250 for (var i = 0; i < mods[key].length; i++) {
251 var versionFolder = new org.argeo.ria.components.DynamicTreeFolder(
252 key + ' (' + mods[key][i] + ')', flowLoader,
253 "Loading Flows", folder.getDragData());
254 versionFolder.setUserData("moduleData", {
255 name : key,
256 version : mods[key][i]
257 });
258 versionFolder.setUserData("agentUuid", agentId);
259 // Warning, we must add it AFTER setting the user data,
260 // because of the persistent loading mechanism.
261 folder.add(versionFolder);
262 }
263 }
264 folder.setLoaded(true);
265 folder.getTree().fireEvent("changeSelection");
266 });
267 req.addListener("failed", function(response) {
268 folder.setLoaded(true);
269 });
270 req.send();
271 },
272
273 /**
274 * Loader for the "flow" level : takes a folder containing "moduleData"
275 * and create its children.
276 *
277 * @param folder
278 * {org.argeo.ria.components.PersistentTreeFolder} A Tree folder containing in the
279 * key "moduleData" of its user data a map containing the
280 * keys {name,version}
281 */
282 flowLoader : function(folder) {
283 var moduleData = folder.getUserData("moduleData");
284 var agentUuid = folder.getUserData("agentUuid");
285
286 var req = org.argeo.slc.ria.SlcApi
287 .getLoadExecutionDescriptorService(agentUuid,
288 moduleData.name, moduleData.version);
289 req.addListener("completed", function(response) {
290 var executionModule = new org.argeo.slc.ria.execution.Module();
291 try {
292 executionModule.setXmlNode(response.getContent());
293 } catch (e) {
294 this.error(e);
295 }
296 var execFlows = executionModule.getExecutionFlows();
297 for (var key in execFlows) {
298 var file = new qx.ui.tree.TreeFile(key);
299 var path = execFlows[key].getPath();
300 file.setUserData("executionModule", executionModule);
301 file.setUserData("executionFlow", execFlows[key]);
302 file.setUserData("agentUuid", agentUuid);
303 org.argeo.slc.ria.FlowsSelectorView.attachNodeByPath(folder, path, file, {
304 agentUuid : folder.getUserData("agentUuid")
305 });
306 folder.appendDragData(file);
307 }
308 folder.setLoaded(true);
309 folder.getTree().fireEvent("changeSelection");
310 });
311 req.addListener("failed", function(response) {
312 folder.setLoaded(true);
313 });
314 req.send();
315 },
316
317 /**
318 * Parse a string path and search if there is a root node.
319 *
320 * @param rootNode
321 * {org.argeo.ria.components.DynamicTreeFolder} The parent
322 * node (containing data model)
323 * @param path
324 * {String} The path of the node to attach.
325 * @param childNode
326 * {qx.ui.tree.TreeFile} The leaf node
327 * @param userData
328 * {Map} User data to attach at all levels.
329 */
330 attachNodeByPath : function(rootNode, path, childNode, userData) {
331 if (!path || path == "" || path == "/") {
332 rootNode.add(childNode);
333 return;
334 }
335 var model = rootNode.getUserData("dataModel");
336 if (!model) {
337 model = {};
338 rootNode.setUserData("dataModel", model);
339 }
340 var parts = path.split("/");
341 var keys = qx.lang.Object.getKeys(model);
342 var crtPath = "";
343 var crtFolder = rootNode;
344 for (var i = 0; i < parts.length; i++) {
345 if (parts[i] == "")
346 continue;
347 crtPath += "/" + parts[i];
348 if (!model[crtPath]) {
349 var virtualFolder = new org.argeo.ria.components.PersistentTreeFolder(parts[i]);
350 if (userData && qx.lang.Object.getLength(userData)) {
351 for (var key in userData) {
352 virtualFolder.setUserData(key, userData[key]);
353 }
354 }
355 rootNode.appendDragData(virtualFolder);
356 model[crtPath] = virtualFolder;
357 crtFolder.add(virtualFolder);
358 crtFolder = virtualFolder;
359 } else {
360 crtFolder = model[crtPath];
361 }
362 }
363 crtFolder.add(childNode);
364 },
365
366 findAgentNodeById : function(node, agentId){
367 var nodeAgents = node.getItems();
368 for(var i=0;i<nodeAgents.length;i++){
369 if(nodeAgents[i].getUserData("agentUuid") == agentId){
370 return nodeAgents[i];
371 }
372 }
373 }
374 },
375
376 members : {
377 /**
378 * Called at applet creation. Just registers viewPane.
379 *
380 * @param viewPane
381 * {org.argeo.ria.components.ViewPane} The viewPane.
382 */
383 init : function(viewPane) {
384 this.setView(viewPane);
385 this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));
386 this.remoteNotifier = new org.argeo.ria.remote.RemoteNotifier(
387 "/org.argeo.slc.webapp/", "pollEvent.service",
388 "addEventListener.service", "removeEventListener.service");
389 this.remoteNotifier.setEventParamName("slc_eventType");
390 this.remoteNotifier.setEventXPath("/slc:slc-event");
391 this.remoteNotifier
392 .setEventTypeXPath('slc:headers/slc:header[@name="slc_eventType"]');
393 this.remoteNotifier
394 .setEventDataXPath('slc:headers/slc:header[@name="slc_agentId"]');
395 this.remoteNotifier.setAnswerStatusXPath("slc:execution-answer/slc:status");
396 this.remoteNotifier.startPolling();
397 this.UIBus = org.argeo.ria.event.UIBus.getInstance();
398 this.UIBus.registerNotifier(this.remoteNotifier);
399 },
400
401 /**
402 *
403 */
404 load : function() {
405 this._createLayout();
406 this.getView().setViewTitle("Available Scripts");
407 this.UIBus.addListener("agentRegistered", this._addAgentHandler, this);
408 this.UIBus.addListener("agentUnregistered", this._removeAgentHandler, this);
409 },
410
411 _addAgentHandler : function(agentId){
412 this.rootNode.load();
413 },
414
415 _removeAgentHandler : function(agentId){
416 var treeNode = this.self(arguments).findAgentNodeById(this.rootNode, agentId);
417 if(treeNode){
418 this.rootNode.remove(treeNode);
419 }
420 var agentsMap = this.getAgentsMap();
421 if(agentsMap[agentId]){
422 delete agentsMap[agentId];
423 }
424 var batchView = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById("batch").getContent();
425 if(batchView){
426 batchView.clearBatchForAgentId(agentId);
427 }
428 },
429
430 addScroll : function() {
431 return false;
432 },
433
434 close : function() {
435 this.UIBus.removeListener("agentRegistered", this._addAgentHandler, this);
436 this.UIBus.removeListener("agentUnregistered", this._removeAgentHandler, this);
437 this.remoteNotifier.stopPolling();
438 },
439
440 /**
441 * Creates the main applet layout.
442 */
443 _createLayout : function() {
444
445 this.tree = new qx.ui.tree.Tree();
446 this.tree.setDecorator(null);
447 this.tree.setSelectionMode("multi");
448 var dragData = {
449 "file" : {
450 "type" : ["items"],
451 "action" : ["move"]
452 },
453 "folder" : {
454 "type" : ["items"],
455 "action" : ["move"]
456 }
457 };
458
459 this.rootNode = new org.argeo.ria.components.DynamicTreeFolder(
460 "Tests", this.self(arguments).agentLoader,
461 "Loading Agents", dragData);
462 this.tree.setRoot(this.rootNode);
463 this.rootNode.setOpen(true);
464 this.tree.setContextMenu(org.argeo.ria.event.CommandsManager
465 .getInstance().createMenuFromIds(["addtobatch",
466 "reloadtree"]));
467
468 this.tree.addListener("changeSelection", function(e) {
469 var viewSelection = this.getViewSelection();
470 viewSelection.setViewId("form:tree");
471 viewSelection.clear();
472 var sel = this.tree.getSortedSelection();
473 for (var i = 0; i < sel.length; i++) {
474 viewSelection.addNode(sel[i]);
475 }
476 }, this);
477
478
479 this.add(this.tree);
480 },
481
482 getAgentsMap : function(){
483 return this.rootNode.getUserData("agentsMap");
484 }
485 }
486 });