]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.webapp/src/main/webapp/argeo-ria-lib/slc/class/org/argeo/slc/ria/NewLauncherApplet.js
929c2664debce396084191371fd38daac01cec4b
[gpl/argeo-slc.git] / org.argeo.slc.webapp / src / main / webapp / argeo-ria-lib / slc / class / org / argeo / slc / ria / NewLauncherApplet.js
1 /**
2 * A simple Hello World applet for documentation purpose.
3 * The only associated command is the "Close" command.
4 */
5 qx.Class.define("org.argeo.slc.ria.NewLauncherApplet",
6 {
7 extend : qx.ui.container.Composite,
8 implement : [org.argeo.ria.components.IView],
9
10 construct : function(){
11 this.base(arguments);
12 this.setLayout(new qx.ui.layout.Dock());
13
14 this.COMMON_FORM_HEADER_LABEL = "Choose Agent";
15 this.CHOOSE_AGENT_LABEL = "Agent Uuid";
16 this.CHOOSE_FORM_PART_LABEL = "Test Type";
17 },
18
19 properties :
20 {
21 /**
22 * The viewPane inside which this applet is added.
23 */
24 view : {
25 init : null
26 },
27 viewSelection : {
28 nullable:false,
29 check:"org.argeo.ria.components.ViewSelection"
30 },
31 instanceId : {init:""},
32 instanceLabel : {init:""},
33 /**
34 * Commands definition, see {@link org.argeo.ria.event.CommandsManager#definitions}
35 */
36 commands : {
37 init : {
38 "submitform" : {
39 label : "Execute Batch On...",
40 icon : "resource/slc/media-playback-start.png",
41 shortcut : null,
42 enabled : true,
43 menu : "Launcher",
44 toolbar : null,
45 callback : function(e){},
46 submenu : [],
47 submenuCallback : function(commandId){
48 alert("Execute Batch on Agent "+commandId);
49 },
50 command : null
51 },
52 "editexecutionspecs" : {
53 label : "Edit Execution Specs",
54 icon : "resource/slc/document-open.png",
55 shortcut : null,
56 enabled : false,
57 menu : "Launcher",
58 toolbar : null,
59 callback : function(e){
60 var sel = this.list.getSortedSelection();
61 var item = sel[0];
62 alert('Edit Specs for : ' + item.getLabel());
63 },
64 selectionChange : function(viewId, selection){
65 if(viewId != "form") return;
66 this.setEnabled(false);
67 if((selection && selection.length == 1)) this.setEnabled(true);
68 },
69 command : null
70 },
71 "removefrombatch" : {
72 label : "Remove from batch",
73 icon : "resource/slc/edit-delete.png",
74 shortcut : null,
75 enabled : false,
76 menu : "Launcher",
77 toolbar : null,
78 callback : function(e){
79 var sel = this.list.getSortedSelection();
80 alert('Remove '+ sel.length+ ' elements from batch');
81 },
82 selectionChange : function(viewId, selection){
83 if(viewId != "form") return;
84 this.setEnabled(false);
85 if((selection && selection.length > 0)) this.setEnabled(true);
86 },
87 command : null
88 },
89 "reloadagents" : {
90 label : "Reload Agents",
91 icon : "resource/slc/view-refresh.png",
92 shortcut : "Control+r",
93 enabled : true,
94 menu : "Launcher",
95 toolbar : "launcher",
96 callback : function(e){
97 var req = org.argeo.slc.ria.SlcApi.getListAgentsService("agents");
98 req.send();
99 },
100 command : null
101 },
102 "reloadtree" : {
103 label : "Reload Node",
104 icon : "resource/slc/view-refresh.png",
105 shortcut : "Control+m",
106 enabled : true,
107 menu : "Launcher",
108 toolbar : "launcher",
109 callback : function(e){
110 var selected = this.tree.getSelectedItem();
111 if(selected.classname == "org.argeo.ria.components.DynamicTreeFolder"){
112 selected.reload();
113 }
114 },
115 command : null
116 }
117 }
118 },
119 /**
120 * A map containing all currently registered agents.
121 */
122 registeredTopics : {
123 init : {},
124 check : "Map",
125 event : "changeRegisteredTopics"
126 }
127 },
128
129 statics : {
130 flowLoader : function(folder){
131 var moduleData = folder.getUserData("executionModule");
132 var req = org.argeo.ria.remote.RequestManager.getInstance().getRequest("stub.xml", "GET", "application/xml");
133 req.addListener("completed", function(response){
134 var executionModule = new org.argeo.slc.ria.execution.Module();
135 executionModule.setXmlNode(response.getContent());
136 var execFlows = executionModule.getExecutionFlows();
137 for(var key in execFlows){
138 var file = new qx.ui.tree.TreeFile(key);
139 file.setUserData("executionFlow", execFlows);
140 folder.add(file);
141 }
142 folder.setLoaded(true);
143 });
144 req.send();
145 },
146
147 modulesLoader : function(folder){
148 // Call service, and parse
149 var mods = {
150 "Module 1":["ver1.1", "ver1.2", "ver1.3"],
151 "Module 2":["ver2.1", "ver2.2", "ver2.3", "ver2.4"],
152 "Module 3":["ver3.1", "ver3.2"]
153 };
154 var flowLoader = org.argeo.slc.ria.NewLauncherApplet.flowLoader;
155 for(var key in mods){
156 var moduleFolder = new qx.ui.tree.TreeFolder(key);
157 folder.add(moduleFolder);
158 for(var i=0;i<mods[key].length;i++){
159 var versionFolder = new org.argeo.ria.components.DynamicTreeFolder(
160 mods[key][i],
161 flowLoader,
162 "Loading Flows",
163 folder.getDragData()
164 );
165 moduleFolder.add(versionFolder);
166 //versionFolder.setUserData("executionModule", "object");
167 }
168 folder.setLoaded(true);
169 }
170 }
171 },
172
173 members :
174 {
175 /**
176 * Called at applet creation. Just registers viewPane.
177 * @param viewPane {org.argeo.ria.components.ViewPane} The viewPane.
178 */
179 init : function(viewPane){
180 this.setView(viewPane);
181 this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId()));
182 //this._createForm();
183 this._amqClient = org.argeo.ria.remote.JmsClient.getInstance();
184 this._amqClient.startPolling();
185 },
186
187 /**
188 *
189 */
190 load : function(){
191 this._createLayout();
192 this.getView().setViewTitle("Execution Launcher");
193 org.argeo.ria.remote.RequestManager.getInstance().addListener("reload", function(reloadEvent){
194 if(reloadEvent.getDataType()!= "agents") return ;
195 var xmlDoc = reloadEvent.getContent();
196 var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc, "//slc:slc-agent-descriptor");
197 var newTopics = {};
198 for(var i=0;i<nodes.length;i++){
199 var uuid = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "@uuid");
200 var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
201 newTopics[uuid] = host+" ("+uuid+")";
202 }
203 this.setRegisteredTopics(newTopics);
204 }, this);
205 this.addListener("changeRegisteredTopics", function(event){
206 //this._refreshTopicsSubscriptions(event);
207 this._feedSelector(event);
208 }, this);
209 var reloadHandler = function(message){
210 // Delay reload to be sure the jms was first integrated by the db, then ask the db.
211 qx.event.Timer.once(function(){
212 org.argeo.ria.event.CommandsManager.getInstance().getCommandById("reloadagents").execute();
213 }, this, 1000);
214 }
215 this._amqClient.addListener("agentregister", "topic://agent.register", reloadHandler, this);
216 this._amqClient.addListener("agentunregister", "topic://agent.unregister", reloadHandler, this);
217 reloadHandler();
218
219 this._amqClient.addListener("modulesResponse", "modulesManager.response", function(message){
220 this.info(message);
221 }, this);
222 },
223
224 addScroll : function(){
225 return false;
226 },
227
228 close : function(){
229 this._amqClient.removeListener("agentregister", "topic://agent.register");
230 this._amqClient.removeListener("agentunregister", "topic://agent.unregister");
231 this._amqClient.removeListener("modulesResponse", "topic://modulesManager.response");
232 this.setRegisteredTopics({});
233 this._amqClient.stopPolling();
234 },
235
236 /**
237 * Creates the main applet layout.
238 */
239 _createLayout : function(){
240
241 var splitPane = new qx.ui.splitpane.Pane("vertical");
242 splitPane.setDecorator(null);
243 this.add(splitPane);
244
245 this.formPane = new qx.ui.container.Composite(new qx.ui.layout.VBox(5));
246 this.scroll = new qx.ui.container.Scroll(this.formPane);
247 this.formPane.setPadding(10);
248
249 this.tree = new qx.ui.tree.Tree();
250 this.tree.setDecorator(null);
251 var dragData = {
252 "file" : {
253 "type" : ["items"],
254 "action":["move"]
255 }
256 };
257
258 var root = new org.argeo.ria.components.DynamicTreeFolder(
259 "All Tests",
260 this.self(arguments).modulesLoader,
261 "Loading Modules",
262 dragData
263 );
264 this.tree.setRoot(root);
265 root.setOpen(true);
266
267 this.listPane = new qx.ui.container.Composite(new qx.ui.layout.Dock());
268 var listToolBar = new qx.ui.toolbar.ToolBar();
269 var toolGroup = new qx.ui.toolbar.Part();
270 listToolBar.add(toolGroup);
271
272 var execButton = this.getCommands()["submitform"].command.getToolbarButton();
273 toolGroup.add(execButton);
274
275 listToolBar.addSpacer();
276 listToolBar.setPaddingRight(4);
277 var delButton = this.getCommands()["removefrombatch"].command.getToolbarButton();
278 var formButton = this.getCommands()["editexecutionspecs"].command.getToolbarButton();
279 delButton.setShow("icon");
280 formButton.setShow("icon");
281 listToolBar.add(formButton);
282 listToolBar.add(delButton);
283
284 this.listPane.add(listToolBar, {edge:"north"});
285
286 this.list = new qx.ui.form.List();
287 this.list.setDecorator(null);
288 this.list.setSelectionMode("multi");
289 this.list.setDroppable(true);
290 this.list.addListener("drop", function(e){
291 var label = e.getRelatedTarget().getLabel();
292 var li = new qx.ui.container.Composite(new qx.ui.layout.HBox(5));
293 li.add(new qx.ui.basic.Label(label));
294 var item = new qx.ui.form.ListItem(label, e.getRelatedTarget().getIcon());
295 item.setPaddingTop(1);
296 item.setPaddingBottom(2);
297 this.list.add(item);
298 this.list.select(item);
299 this.getCommands()["editexecutionspecs"].command.execute();
300 }, this);
301 this.listPane.add(this.list, {edge:"center"});
302
303 this.list.addListener("changeSelection", function(e){
304 var viewSelection = this.getViewSelection();
305 viewSelection.clear();
306 var listSel = this.list.getSortedSelection();
307 for(var i=0;i<listSel.length;i++){
308 viewSelection.addNode(listSel[i]);
309 }
310 }, this);
311
312 splitPane.add(this.tree, 0);
313 splitPane.add(this.listPane, 1);
314 //this.add(this.scroll, {edge:'center'});
315
316 },
317
318 /**
319 * Creates the form.
320 */
321 _createForm : function(){
322 this.fields = {};
323 this.hiddenFields = {};
324 this.freeFields = [];
325
326 var execButtonPane = new qx.ui.container.Composite(new qx.ui.layout.Dock());
327 var execButton = new qx.ui.form.Button(
328 "Execute",
329 "resource/slc/media-playback-start-32.png"
330 )
331 execButton.addListener("click", function(){
332 this.submitForm();
333 }, this);
334 execButtonPane.setPadding(10, 80);
335 execButtonPane.add(execButton, {edge:"center"});
336 this.formPane.add(execButtonPane);
337
338 this.agentSelector = new qx.ui.form.SelectBox();
339 var serviceManager = org.argeo.ria.remote.RequestManager.getInstance();
340 serviceManager.addListener("reload", function(reloadEvent){
341 if(reloadEvent.getDataType()!= "agents") return ;
342 var xmlDoc = reloadEvent.getContent();
343 var nodes = org.argeo.ria.util.Element.selectNodes(xmlDoc, "//slc:slc-agent-descriptor");
344 var newTopics = {};
345 for(var i=0;i<nodes.length;i++){
346 var uuid = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "@uuid");
347 var host = org.argeo.ria.util.Element.getSingleNodeText(nodes[i], "slc:host");
348 newTopics[uuid] = host+" ("+uuid+")";
349 }
350 this.setRegisteredTopics(newTopics);
351 }, this);
352
353 var commonForm = {pane:this.formPane};
354 this._addFormHeader(commonForm, this.COMMON_FORM_HEADER_LABEL);
355 this._addFormEntry(commonForm, new qx.ui.basic.Label(this.CHOOSE_AGENT_LABEL), this.agentSelector);
356 this._createFormVariableParts();
357 if(!this.parts) return;
358 if(qx.lang.Object.getLength(this.parts) > 1){
359 // Add chooser
360 this.partChooser = new qx.ui.form.SelectBox();
361 for(var key in this.parts){
362 this.partChooser.add(new qx.ui.form.ListItem(this.parts[key].label, null, key));
363 }
364 this._addFormEntry(commonForm, new qx.ui.basic.Label(this.CHOOSE_FORM_PART_LABEL), this.partChooser);
365 this.partChooser.addListener("changeValue", function(ev){
366 this._showSelectedPart(ev.getData());
367 }, this);
368 }
369 this._showSelectedPart(qx.lang.Object.getKeys(this.parts)[0]);
370 },
371
372 /**
373 * Show a form part given its id.
374 * @param partId {String} The part id
375 */
376 _showSelectedPart : function(partId){
377 if(!this.parts) return;
378 if(!this.partsContainer){
379 this.partsContainer = new qx.ui.container.Composite(new qx.ui.layout.Canvas());
380 this.formPane.add(this.partsContainer);
381 }
382 for(var i in this.parts){
383 var formObject = this.parts[i];
384 if(!formObject.added){
385 this.partsContainer.add(formObject.pane, {top:0, left:0});
386 formObject.added = true;
387 }
388 formObject.pane.hide();
389 }
390 if(this.parts[partId]){
391 this.parts[partId].pane.show();
392 }
393 },
394
395 /**
396 * Init a form part : creates a pane, a set of fields, etc.
397 * @param formId {String} A unique ID
398 * @param label {String} A label
399 * @return {Map} The form part.
400 */
401 _initFormPart : function(formId, label){
402 if(!this.parts) this.parts = {};
403 var formObject = {};
404 formObject.hiddenFields = {};
405 formObject.freeFields = [];
406 formObject.fields = {};
407 formObject.id = formId;
408 formObject.label = label;
409 this.parts[formId] = formObject;
410 formObject.pane = new qx.ui.container.Composite(new qx.ui.layout.VBox(5));
411 return formObject;
412 },
413
414 /**
415 * To be overriden by this class children.
416 */
417 _createFormVariableParts : function(){
418 var standard = this._initFormPart("standard", "Canonical");
419 this._createStandardForm(standard);
420 var simple = this._initFormPart("simple", "SLC Sample");
421 this._createSimpleForm(simple);
422 },
423
424 /**
425 * Creates a form for SLC demo
426 * @param formObject {Map} The form part
427 */
428 _createSimpleForm : function(formObject){
429
430 this._addFormInputText(formObject, "ant.file", "File", "Category1/SubCategory2/build.xml");
431 var moreButton = new qx.ui.basic.Image("resource/slc/list-add.png");
432 moreButton.setToolTip(new qx.ui.tooltip.ToolTip("Add a parameter"));
433 moreButton.setCursor("pointer");
434 moreButton.addListener("click", function(){
435 this._addFormInputText(formObject);
436 }, this);
437 this._addFormHeader(formObject, "Add optionnal parameters", moreButton);
438 this._addFormInputText(formObject);
439 this._addFormInputText(formObject);
440
441 },
442
443 /**
444 * Create a canonical form.
445 * @param formObject {Map} The form part
446 */
447 _createStandardForm : function(formObject){
448
449 this._addFormHeader(formObject, "Set Execution Parameters");
450 this._addFormInputText(formObject, "status", "Status", "STARTED");
451 this._addFormInputText(formObject, "host", "Host", "localhost");
452 this._addFormInputText(formObject, "user", "User", "user");
453
454 var moreButton = new qx.ui.basic.Image("resource/slc/list-add.png");
455 moreButton.setToolTip(new qx.ui.tooltip.ToolTip("Add a parameter"));
456 moreButton.setCursor("pointer");
457 moreButton.addListener("click", function(){
458 this._addFormInputText(formObject);
459 }, this);
460 this._addFormHeader(formObject, "Add optionnal parameters", moreButton);
461 this._addFormInputText(formObject);
462 this._addFormInputText(formObject);
463 },
464
465 /**
466 * Add an hidden field to the form
467 * @param formObject {Map} The form part
468 * @param fieldName {String} Name
469 * @param fieldValue {String} Value
470 */
471 _addFormHiddenField : function(formObject, fieldName, fieldValue){
472 formObject.hiddenFields[fieldName] = fieldValue;
473 },
474
475 /**
476 * Creates a simple label/input form entry.
477 * @param formObject {Map} The form part
478 * @param fieldName {String} Name
479 * @param fieldLabel {String} Label of the field
480 * @param defaultValue {String} The default value
481 * @param choiceValues {Map} An map of values
482 */
483 _addFormInputText : function(formObject, fieldName, fieldLabel, defaultValue, choiceValues){
484 var labelElement;
485 if(choiceValues){
486 var fieldElement = new qx.ui.form.SelectBox();
487 for(var key in choiceValues){
488 fieldElement.add(new qx.ui.form.ListItem(choiceValues[key], null, key));
489 }
490 }else{
491 var fieldElement = new qx.ui.form.TextField();
492 }
493 if(defaultValue){
494 fieldElement.setValue(defaultValue);
495 }
496 if(fieldName && fieldLabel){
497 labelElement = new qx.ui.basic.Label(fieldLabel);
498 formObject.fields[fieldName] = fieldElement;
499 }else{
500 labelElement = new qx.ui.form.TextField();
501 formObject.freeFields.push({
502 labelEl:labelElement,
503 valueEl:fieldElement
504 });
505 }
506 this._addFormEntry(formObject, labelElement, fieldElement);
507 },
508
509 /**
510 * Add an header
511 * @param formObject {Map} The form part
512 * @param content {Mixed} Content to add.
513 * @param additionnalButton {Mixed} Any widget to add on the east.
514 */
515 _addFormHeader : function(formObject, content, additionnalButton){
516 var header = new qx.ui.basic.Label('<b>'+content+'</b>');
517 header.setRich(true);
518 if(!additionnalButton){
519 header.setPaddingTop(10);
520 formObject.pane.add(header);
521 }else{
522 var pane = new qx.ui.container.Composite(new qx.ui.layout.Dock());
523 pane.setPaddingTop(10);
524 pane.setPaddingRight(10);
525 pane.add(header, {edge:'center'});
526 pane.add(additionnalButton, {edge:'east'});
527 formObject.pane.add(pane);
528 }
529 },
530
531 /**
532 * Adds a label/input like entry in the form.
533 * @param formObject {Map} The form part
534 * @param labelElement {Object} Either a label or an input
535 * @param fieldElement {Object} Any form input.
536 */
537 _addFormEntry : function(formObject, labelElement, fieldElement){
538 var entryPane = new qx.ui.container.Composite(new qx.ui.layout.HBox(5));
539 labelElement.setWidth(100);
540 labelElement.setTextAlign("right");
541 entryPane.add(labelElement);
542 entryPane.add(new qx.ui.basic.Label(':'));
543 fieldElement.setWidth(150);
544 entryPane.add(fieldElement);
545 formObject.pane.add(entryPane);
546 },
547
548 /*
549 _refreshTopicsSubscriptions : function(changeTopicsEvent){
550 var oldTopics = changeTopicsEvent.getOldData() || {};
551 var newTopics = changeTopicsEvent.getData();
552 var removed = [];
553 var added = [];
554 for(var key in oldTopics){
555 if(!newTopics[key]) {
556 //this._removeAmqListener(key);
557 }
558 }
559 for(var key in newTopics){
560 if(!oldTopics[key]) {
561 //this._addAmqListener(key);
562 }
563 }
564 },
565 */
566
567 /**
568 * Refresh the selector when the topics are updated.
569 * @param changeTopicsEvent {qx.event.type.DataEvent} The reload event.
570 */
571 _feedSelector : function(changeTopicsEvent){
572 var topics = changeTopicsEvent.getData();
573 var command = this.getCommands()["submitform"].command;
574 command.setEnabled(false);
575 var menu = [];
576 for(var key in topics){
577 var submenu = {"label":topics[key],"icon":"resource/slc/mime-xsl.png", "commandId":key};
578 menu.push(submenu);
579 }
580 command.clearMenus();
581 command.setMenu(menu);
582 if(menu.length) command.setEnabled(true);
583 },
584
585 /*
586 _addAmqListener: function(uuid){
587 this._amqClient.addListener("slcExec", "topic://agent."+uuid+".newExecution", function(response){
588 var message = org.argeo.ria.util.Element.selectSingleNode(response, "slc:slc-execution");
589 var slcExec = new org.argeo.slc.ria.SlcExecutionMessage(message.getAttribute("uuid"));
590 slcExec.fromXml(message);
591 this.logModel.addRows([
592 [new Date().toString(), slcExec.getHost()+' ('+slcExec.getUuid()+')', slcExec.getStatus()]
593 ]);
594 }, this);
595 },
596
597 _removeAmqListener : function(uuid){
598 this._amqClient.removeListener("slcExec", "topic://agent."+uuid+".newExecution");
599 },
600 */
601
602 /**
603 * Make an SlcExecutionMessage from the currently displayed form.
604 * @param crtPartId {String} The form part currently displayed
605 * @param slcExec {org.argeo.slc.ria.SlcExecutionMessage} The message to fill.
606 * @param fields {Map} The fields of the form
607 * @param hiddenFields {Map} The hidden ones
608 * @param freeFields {Array} The free fields.
609 */
610 _prepareSlcExecutionMessage : function(crtPartId, slcExec, fields, hiddenFields, freeFields){
611 if(crtPartId == "standard"){
612 slcExec.setStatus(fields.status.getValue());
613 slcExec.setHost(fields.host.getValue());
614 slcExec.setUser(fields.user.getValue());
615 }else{
616 slcExec.addAttribute("ant.file", fields["ant.file"].getValue());
617 }
618 for(var i=0;i<freeFields.length;i++){
619 var fF = freeFields[i];
620 if(fF.labelEl.getValue() != "" && fF.valueEl.getValue() != ""){
621 slcExec.addAttribute(fF.labelEl.getValue(), fF.valueEl.getValue());
622 }
623 }
624 },
625
626 /**
627 * Called when the user clicks the "Execute" button.
628 */
629 submitForm : function(){
630 var currentUuid = this.agentSelector.getValue();
631 if(!currentUuid) return;
632 var slcExec = new org.argeo.slc.ria.SlcExecutionMessage();
633
634 var fields = {};
635 var hiddenFields = {};
636 var freeFields = {};
637 var crtPartId = "";
638 if(this.parts){
639 if(this.partChooser){
640 crtPartId = this.partChooser.getValue();
641 }else{
642 crtPartId = qx.lang.Object.getKeys(this.parts)[0];
643 }
644 var crtPart = this.parts[crtPartId];
645 fields = crtPart.fields;
646 hiddenFields = crtPart.hiddenFields;
647 freeFields = crtPart.freeFields;
648 }
649
650 this._prepareSlcExecutionMessage(crtPartId, slcExec, fields, hiddenFields, freeFields);
651
652 this._amqClient.sendMessage(
653 "topic://agent.newExecution",
654 slcExec.toXml(),
655 {"slc-agentId":currentUuid}
656 );
657 // Force logs refresh right now!
658 qx.event.Timer.once(function(){
659 var command = org.argeo.ria.event.CommandsManager.getInstance().getCommandById("reloadlogs");
660 if(command){
661 command.execute();
662 }
663 }, this, 2000);
664 }
665
666 }
667 });