Commit 2ac8da6ca9b6e28203831fcbaddfc16c7609ce78

Authored by Elena.Budnik
2 parents fc8f3d9d 4fe5bccf

Merge branch 'master' of https://gitlab.irap.omp.eu/CDPP/AMDA_IHM

js/.eslintrc.yml
... ... @@ -10,6 +10,11 @@ rules:
10 10 semi: [error, always]
11 11 max-len: [error, code: 120]
12 12 max-lines: [warn, 600]
  13 + max-params: [warn, 3]
  14 + complexity: [warn, 20]
  15 + no-ternary: off
  16 + no-plusplus: off
  17 + multiline-ternary: off
13 18 linebreak-style: [error, unix]
14 19 quotes: [error, single]
15 20 strict: [error, global]
... ... @@ -26,6 +31,9 @@ rules:
26 31 id-length: off
27 32 no-magic-numbers: off
28 33 no-invalid-this: off
  34 + no-extra-parens: [error, all, nestedBinaryExpressions: false]
  35 + camelcase: warn
  36 + max-depth: warn
29 37  
30 38 # ES3/5 compatibility:
31 39 prefer-template: off
... ... @@ -33,3 +41,4 @@ rules:
33 41 prefer-arrow-callback: off
34 42 object-shorthand: off
35 43 prefer-rest-params: off
  44 + prefer-destructuring: off
... ...
js/app/models/AmdaNode.js
... ... @@ -25,7 +25,7 @@ Ext.define('amdaModel.AmdaNode', {
25 25 ],
26 26  
27 27 statics : {
28   - NEW_DIR_NAME : 'new Folder',
  28 + NEW_DIR_NAME : 'new_folder',
29 29 MULTI_PREFIX : 'mult'
30 30 },
31 31  
... ...
js/app/models/InteractiveNode.js
1   -/**
  1 +/**
2 2 * Project : AMDA-NG4
3 3 * Name : InteractiveNode.js
4 4 * @class amdaModel.InteractiveNode
... ... @@ -8,760 +8,881 @@
8 8 * @version $Id: InteractiveNode.js 2683 2014-12-02 10:58:53Z elena $
9 9 */
10 10  
  11 +/* global amdaUI, AmdaAction, myDesktopApp, amdaPlotObj, amdaModel*/
  12 +
11 13 Ext.define('amdaModel.InteractiveNode', {
12   - extend: 'amdaModel.AmdaNode',
13   -
14   - requires: [
15   - 'amdaPlotObj.PlotRequestObject'
16   - ],
17   -
18   - fields: [
19   - {name: 'contextNode', type: 'amdaModel.AmdaNode', persist: false},
20   - {name: 'objectDataModel', type: 'string', persist: false},
21   - {name: 'object', type: 'object', persist: false},
22   - {name: 'moduleId', type: 'string', persist: false},
23   - {name: 'filtered', type: 'boolean', defaultValue: false, persist: false},
24   - {name: 'disable', type: 'boolean', defaultValue: false, persist: false}
25   - ],
26   -
27   - statics: {
28   - preloadNodes : function(node,onready)
29   - {
30   - var me = this;
31   -
32   - var nodesToLoad = new Array();
33   - nodesToLoad.push(node);
34   - this.preloadTreeNode(node, nodesToLoad, function (node)
35   - {
36   - var isFinish = true;
37   - nodesToLoad.forEach(function (element, index, array)
38   - {
39   - if (!element.isLoaded())
40   - isFinish = false;
41   - });
42   - if (isFinish && onready)
43   - onready.call();
44   - });
45   - },
46   -
47   - preloadTreeNode : function(node, nodesToLoad, onloaded)
48   - {
49   - var me = this;
50   -
51   - if (node.isLoaded())
52   - {
53   - node.eachChild(function(n)
54   - {
55   - if (!n.isLoaded() && !n.isLeaf())
56   - {
57   - nodesToLoad.push(n);
58   - me.preloadTreeNode(n,nodesToLoad,onloaded);
59   - }
60   - });
61   -
62   - if (onloaded)
63   - onloaded.call(me,node);
64   - return;
65   - }
66   -
67   - node.store.load({
68   - node : node,
69   - callback : function(records, operation, successful)
70   - {
71   - records.forEach(function (record)
72   - {
73   - if (!record.isLoaded() && !record.isLeaf())
74   - {
75   - nodesToLoad.push(record);
76   - me.preloadTreeNode(record,nodesToLoad,onloaded);
77   - }
78   - });
79   - if (onloaded)
80   - onloaded.call(me,node);
81   - }
82   - });
83   - }
84   - },
85   -
86   - onReady : null,
87   -
88   - constructor : function(config)
89   - {
90   - this.callParent(arguments);
91   - this.set('nodeType',this.self.nodeType);
92   - this.set('ownerTreeId',amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
93   - if (this.get('id')) { // TODO why sometimes (delete in remote interoper tree) this.get('id') = undefined ?
94   - // if id of this node have root category suffix
95   - if (Ext.util.Format.substr(this.get('id'), -(amdaUI.ExplorerUI.CAT_SUFFIX.length), this.get('id').length) === amdaUI.ExplorerUI.CAT_SUFFIX)
96   - {
97   - // set the expanded property to true
98   - this.set('expanded',true);
99   - }
100   - }
101   - },
102   -
103   -/**
104   -* this method is overriden into ExecutableNode to return true
105   -*/
106   - isExecutable: function()
107   - {
108   - return false;
109   - },
  14 + extend: 'amdaModel.AmdaNode',
110 15  
111   -/**
112   -* open Module with THIS NODE
113   -*/
114   - editInModule : function (contextNode, onReady)
115   - {
116   - // set the contextNode of this node
117   - this.set('contextNode',contextNode);
118   - // parameter module
119   - var me = this;
120   - myDesktopApp.getLoadedModule(this.get('moduleId'),true, function (module) {
121   - // If the node to edit is not already linked to this module
122   - if (module.getLinkedNode() != me)
123   - {
124   - // set relative node into parameter Module
125   - module.setLinkedNode(me);
126   - if (contextNode==null)
127   - {
128   - // set the root node as contextNode
129   - contextNode = me.getRootNode();
130   - }
131   - module.setContextNode(contextNode);
132   -
133   - } else if (module.getLinkedNode() != null){
134   - //TODO the node to edit is already edited
135   - // myDesktopApp.warningMsg('This object is being edited');
136   - //Sol1: msg alert: "warning this node is already edited! If you want to get the original, please press the 'reset' button"->'OK'
137   - //Sol2: msg with user choice: "warning this node is already edited! Would you confirm this action and lost your modification?"->'Confirm','Cancel'
138   - }
139   - // Opening parameter window
140   - module.createWindow(onReady);
141   - });
142   - },
  16 + requires: ['amdaPlotObj.PlotRequestObject'],
  17 +
  18 + fields: [
  19 + {
  20 + name: 'contextNode',
  21 + type: 'amdaModel.AmdaNode',
  22 + persist: false
  23 + },
  24 + {
  25 + name: 'objectDataModel',
  26 + type: 'string',
  27 + persist: false
  28 + },
  29 + {
  30 + name: 'object',
  31 + type: 'object',
  32 + persist: false
  33 + },
  34 + {
  35 + name: 'moduleId',
  36 + type: 'string',
  37 + persist: false
  38 + },
  39 + {
  40 + name: 'filtered',
  41 + type: 'boolean',
  42 + defaultValue: false,
  43 + persist: false
  44 + },
  45 + {
  46 + name: 'disable',
  47 + type: 'boolean',
  48 + defaultValue: false,
  49 + persist: false
  50 + }
  51 + ],
143 52  
144   -/**
145   -* Method to rename the workspace node
146   -*/
147   - rename: function(value,callBackFn)
148   - {
149   - var dataToSend = {id : this.get('id'), old_name: this.modified.text, name: value, parent : this.parentNode.get('id'), leaf: this.isLeaf(), nodeType: this.get('nodeType')};
150   - AmdaAction.renameObject(dataToSend, callBackFn);
151   - },
152   -
153   -/**
154   -* Method to rename the workspace node when D&D
155   -*/
156   - renameDD: function(parentId, callBackFn)
157   - {
158   - var dataToSend = {id : this.get('id'), old_name: this.get('name'), name: this.get('name'), parent : parentId, leaf: this.isLeaf(), nodeType: this.get('nodeType')};
159   - AmdaAction.renameObject(dataToSend, callBackFn);
160   - },
161   -
162   -/**
163   -* validation method on name (used in module forms)
164   -* @param name the name to validate
165   -* @returns
166   -*/
167   - isValidName : function(name, callBackFn)
168   - {
169   - var dataToSend = {name: name, nodeType: this.get('nodeType'), leaf: this.isLeaf()};
170   - AmdaAction.validNameObject(dataToSend, callBackFn);
171   - },
  53 + statics: {
  54 + preloadNodes: function (node, onready) {
  55 + var nodesToLoad;
172 56  
173   -/**
174   -* Method to persist modifications of an AmdaObject by Server side and update the workspace
175   -* node linked to a Module
176   -*/
177   - update : function(opt)
178   - {
179   - AmdaAction.modifyObject(this.get('object').getJsonValues(true), function(res,e){
180   -
181   - if(e.status) {
182   - if (res.id) {
183   - if (!this.get('contextNode')) {
184   - // set the root node of 'Derived Parameters' tree as contextNode
185   - this.set('contextNode',this.getRootNode());
186   - }
187   - this.get('contextNode').expand(false,false);
188   - this.myGetOwnerTree().getSelectionModel().select(this);
189   -
190   - if (opt)
191   - {
192   - var scope = opt.scope ? opt.scope : this;
193   - if (opt.callback)
194   - opt.callback.call(scope,'update');
195   - }
196   -
197   - Ext.Msg.alert('Complete', 'Object '+this.get('object').get('name')+' has been modified');
198   - // fix the modifications for object
199   - this.get('object').commit();
200   -
201   - if (res.info) {
202   - this.set('info',res.info);
203   - }
204   -
205   - // myDataParam special update
206   - this.specialUpdate(res, false);
207   -
208   - // reload object into the view of corresponding Module
209   - var me = this;
210   - myDesktopApp.getLoadedModule(this.get('moduleId'), true, function (module) {
211   - module.getUiContent().setObject(me.get('object'));
212   - });
213   - }
214   - else {
215   - //TODO proper error message handling
216   - // error code from server; but e.status==true
217   - // revert all modifications since last load or commit
218   - this.get('object').reject();
219   - myDesktopApp.errorMsg(res.error);
220   - }
221   - }
222   - else {
223   - // revert all modifications since last load or commit
224   - this.get('object').reject();
225   - myDesktopApp.errorMsg(e.message);
226   - }
227   - },this);
228   - },
  57 + nodesToLoad = [];
  58 + nodesToLoad.push(node);
  59 + this.preloadTreeNode(node, nodesToLoad, function () {
  60 + var isFinish = true;
  61 + nodesToLoad.forEach(function (element) {
  62 + if (!element.isLoaded()) {
  63 + isFinish = false;
  64 + }
  65 + });
  66 + if (isFinish && onready) {
  67 + onready.call();
  68 + }
  69 + });
  70 + },
229 71  
230   -/**
231   -* Method to create a new AmdaObject by server side and create the workspace node linked to a Module
232   -* under its contextNode or the root node corresponding to this nodeType category
233   -*/
234   - create : function(opt)
235   - {
236   - if (!this.get('contextNode') || (this.get('contextNode').data.id == 'sharedtimeTable-treeRootNode') || (this.get('contextNode').data.id == 'sharedcatalog-treeRootNode')) {
237   - // set the root node of 'Derived Parameters' tree as contextNode
238   - this.set('contextNode',this.getRootNode());
239   - }
240   - // call the Ext.Direct method to create parameter
241   - AmdaAction.createObject(this.get('object').getJsonValues(false), this.get('contextNode').get('id'), function(res,e){
242   - //success
243   - if(e.status)
244   - {
245   - // if correct response received
246   - if (res.id) { //if (res.id || res.error == 'NAME_EXISTS') {
247   - // 'save as' case ; delete old node if it exists
248   - if (this.toRename)
249   - {
250   - this.toRename = false;
251   - var myRoot = this.getRootNode();
252   - // search the same named node to override
253   - var updateNode = myRoot.findChild('text',this.get('object').get('name'),true);
254   - // destroy the overrided node
255   - updateNode.parentNode.removeChild(updateNode);//TODO ??if destroy==true => too many recursions....
256   - updateNode.destroy();
257   - }
258   - // set text of this node
259   - this.set('text',this.get('object').get('name'));
260   - //set id of this node
261   - this.set('id',res.id);
262   - this.internalId = res.id;
263   - // set id of node's object
264   - this.get('object').set('id',res.id);
265   -
266   - if (res.created){
267   - // set the created date
268   - this.get('object').set('created',res.created);
269   - }
270   -
271   - if (res.info){
272   - // set the tooltip
273   - this.set('info',res.info);
274   - }
275   - //set globalStart & global Stop to be used for time selection
276   - this.specialUpdate(res, true);
277   -
278   - //TODO do we need this commission ???
279   - // fix the modifications for object
280   - this.get('object').commit();
281   - // if ownerTree panel is not active
282   - if (this.myGetOwnerTree().ownerCt.getActiveTab()!==this.myGetOwnerTree())
283   - {
284   - // set ownerTree panel as the active tab - to enable selection of this node his ownerTree must have a view
285   - this.myGetOwnerTree().ownerCt.setActiveTab(this.myGetOwnerTree());
286   - }
287   -
288   - Ext.Msg.alert('Complete', 'New object '+this.get('object').get('name')+' has been created');
289   - // expand the contextNode
290   - this.get('contextNode').expand(false, function()
291   - {
292   - if (!this.get('contextNode').findChild('text',this.get('text'))) {
293   - // create node in tree as child of contextNode
294   - this.get('contextNode').appendChild(this);
295   - }
296   - // select the new node
297   - this.myGetOwnerTree().getSelectionModel().select(this);
298   - if (opt)
299   - {
300   - var scope = opt.scope ? opt.scope : this;
301   - if (opt.callback)
302   - opt.callback.call(scope,'create');
303   - }
304   - }, this);
305   - }
306   - // error code from server; but e.status==true
307   - else {
308   - myDesktopApp.errorMsg(res.error);
309   - // revert all modifications since last load or commit
310   - this.get('object').reject();
311   - }
312   - }
313   - // failure: e.status == false
314   - else {
315   - // revert all modifications since last load or commit
316   - this.get('object').reject();
317   - //TODO: this.destroy();
318   - myDesktopApp.errorMsg(e.message);
319   - }
320   - },this);
321   - },
322   -
323   - specialUpdate : function() {},
324   -/**
325   -* Generic part of Context Menu
326   -*
327   -*/
328   - allMenuItems : function() {
329   - var src = this.self.objectName;
330   - var menuItems =
331   - [ {
332   - fnId : 'root-createLeaf',
333   - text : 'Create '+ src
334   - }, {
335   - fnId : 'root-createDir',
336   - text : 'Create Folder'
337   - }, {
338   - fnId : 'dire-createLeaf',
339   - text : 'Create ' + src
340   - }, {
341   - fnId : 'dire-createDir',
342   - text : 'Create Folder'
343   - }, {
344   - fnId : 'dire-renameNode',
345   - text : 'Rename Folder'
346   - }, {
347   - fnId : 'dire-deleteNode',
348   - text : 'Delete Folder'
349   - }, {
350   - fnId : 'leaf-editLeaf',
351   - text : 'Edit ' + src
352   - }, {
353   - fnId : 'leaf-renameNode',
354   - text : 'Rename ' + src
355   - }, {
356   - fnId : 'leaf-deleteNode',
357   - text : 'Delete '+ src
358   - } ];
359   - return menuItems;
360   - },
361   -
362   - allMenuMultiItems : function() {
363   - var menuMulti = [
364   - {
365   - fnId : 'mult-deleteMulti',
366   - text : 'Delete selected ' + this.self.objectName + 's'
367   - }
368   - ];
369   - return menuMulti;
370   - },
371   -
372   - getAllContextMenuItems: function(){
373   - return this.allMenuItems();
374   - },
375   -
376   - getMultiContextMenuItems: function(){
377   - return this.allMenuMultiItems();
378   - },
379   -
380   -/**
381   -* default implementation
382   -* no menu display if there's no override of this function
383   -*/
384   - getMultiContextMenuItems: function(){
385   - return null;
386   - },
387   -
388   -/**
389   -* Context Menu Actions
390   -*
391   -*/
392   - onMenuItemClick : function(menu,item,event) {
393   - // fnId parsing :
394   - var fnId = Ext.util.Format.substr(item.fnId, 5, item.fnId.length);
395   -
396   - switch (fnId) {
397   - case 'deleteNode':
398   - this.deleteNode();
399   - break;
400   - case 'createDir':
401   - this.createDir();
402   - break;
403   - case 'createLeaf':
404   - this.createLeaf(this);
405   - break;
406   - case 'renameNode':
407   - this.renameNode();
408   - break;
409   - case 'editLeaf':
410   - this.editLeaf();
411   - break;
412   - case 'deleteMulti':
413   - this.deleteMulti();
414   - break;
415   - case 'plotParam':
416   - this.createPlot(this);
417   - break;
418   - case 'downParam':
419   - this.createDownload(this);
420   - break;
421   - default:
422   - break;
423   - } // switch end
424   - },
425   -
426   - getTimeFromNode: function(node) {
427   - var startString = new String(node.get('globalStart'));
428   - var stopString = new String(node.get('globalStop'));
429   -
430   - var startDate = new Date(startString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
431   - var stopDate = new Date(stopString.replace(/\-/g,'\/').replace(/[T|Z]/g,' '));
432   -
433   - if (stopDate - startDate > 86400000 ) {
434   - var startTime = Ext.Date.add(stopDate, Ext.Date.DAY, -1);
435   - // var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d H:i:s'), stop: Ext.Date.format(stopDate, 'Y/m/d H:i:s')};
436   - var timeObj = {start: Ext.Date.format(startTime, 'Y/m/d'), stop: Ext.Date.format(stopDate, 'Y/m/d')};
437   - }
438   - else {
439   - var timeObj = {start: node.get('globalStart'), stop: node.get('globalStop')};
440   - }
441   - return timeObj;
442   - },
443   -
444   - createPlot: function(node)
445   - {
446   - if (node.get('disable')) return;
447   - myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.plot.id, true, function (module) {
448   - if (!myDesktopApp.desktop.getWindow(myDesktopApp.dynamicModules.plot.id)) {
449   - var request = Ext.create(amdaPlotObj.PlotRequestObject.$className);
450   - var newNode = Ext.create(amdaModel.PlotNode.$className, { object : request });
451   - // edit newNode into Plot Module with node as contextNode
452   - newNode.editInModule();
453   - if((node.get('globalStart') != null) && (node.get('globalStop') != null) && node.get('globalStart') != 'depending on mission' && node.get('isParameter')) {
454   - module.getUiContent().setTimeFromData(node.getTimeFromNode(node));
455   - }
456   - }
457   - module.getUiContent().addParameter(node);
458   - });
459   - },
460   -
461   - createDownload: function(node)
462   - {
463   - if (node.get('disable')) return;
464   -
465   - if (node.get('notyet')) {
466   - myDesktopApp.warningMsg('Sorry! access to this parameter is restricted.');
467   - return;
468   - }
469   -
470   - myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.download.id, true, function (module) {
471   - if (!myDesktopApp.desktop.getWindow(myDesktopApp.dynamicModules.download.id)) {
472   - var request = Ext.create(amdaModel.Download.$className);
473   - amdaModel.DownloadNode.set('object',request);
474   - // singleton!
475   - amdaModel.DownloadNode.editInModule();
476   - if ((node.get('globalStart') != null) && (node.get('globalStop') != null) && node.get('globalStart') != 'depending on mission' && node.get('isParameter')) {
477   - module.getUiContent().setTimeFromData(node.getTimeFromNode(node));
478   - }
479   - }
480   - var paramName;
481   - var components = null;
482   - switch (node.$className) {
483   - case 'amdaModel.AliasNode' :
484   - paramName = "#"+node.get('text');
485   - break;
486   - case 'amdaModel.DerivedParamNode' :
487   - paramName = "ws_"+node.get('text');
488   - break;
489   - case 'amdaModel.MyDataParamNode' :
490   - paramName = 'wsd_'+node.get('text');
491   - break;
492   - default :
493   - if (node.get('alias')!= "" )
494   - paramName = "#"+node.get('alias');
495   - else
496   - paramName = node.get('id');
497   - }
498   -// var component_info = node.get('component_info');
499   -// if (component_info && component_info.parentId) {
500   -// //It's a component
501   -// paramName = component_info.parentId;
502   -// components = [];
503   -// if (component_info.index1)
504   -// components['index1'] = component_info.index1;
505   -// if (component_info.index2)
506   -// components['index2'] = component_info.index2;
507   -// }
508   - module.addParam(paramName,true,node.get('needsArgs'),components);
509   - });
510   - },
511   -
512   - deleteNode: function() {
513   - // if the target is a directory
514   - if (!this.isLeaf()) {
515   - // determine if this directory is empty before launching the delete confirmation method
516   - this.isNotEmptyDir(this.confirmDirectoryDeletion);
517   - // else (the target is a leaf)
518   - } else {
519   - // no confirmation prompt for leaves
520   - this.confirmDirectoryDeletion(false);
521   - }
522   - },
523   -
524   -/**
525   -* this method return if node has Childs even if it was not already loaded
526   -*/
527   - isNotEmptyDir : function(callbackFn) {
528   - var hasChilds;
529   - // if node not already loaded
530   - if (!this.isLoaded()){
531   - // call directFunction to load this node
532   - AmdaAction.getTree({node:this.get('id'),nodeType:this.get('nodeType')},function(res,e){
533   - callbackFn.call(this,res.length>0?true:false);
534   - },this);
535   - }
536   - else {
537   - callbackFn.call(this,this.hasChildNodes());
538   - }
539   - },
540   -
541   -/**
542   -* this method is used to display a confirmation message
543   -*/
544   - confirmDirectoryDeletion : function(isNotEmptyDir)
545   - {
546   - // if this is a non-empty directory
547   - if (isNotEmptyDir) {
548   - // Prompt to the user if he also wants to delete its content
549   - Ext.Msg.confirm('non-empty directory', 'The target is a non-empty directory!<br>Do you want to continue and also delete its content?', function(btn, text){
550   - if (btn == 'yes'){
551   - // do delete
552   - this.realDelete();
553   - }
554   - },this);
555   - }
556   - else {
557   - this.realDelete();
558   - }
559   - },
560   -
561   -/*
562   -* Call the extDirect method to delete parameter
563   -* Callback method needed to execute node deletion in tree if id in result or to show error msg
564   -*/
565   - realDelete : function()
566   - {
567   - AmdaAction.deleteObject({id: this.get('id'), leaf: this.isLeaf(), nodeType: this.get('nodeType')}, function(res,e){
568   - //TODO proper errors handling
569   - // node deletion in tree
570   - if (res) { // if success
571   - if (res.id) {
572   - //Ext.Msg.show({title:'Warning', msg: 'Requests with parameter '+node.data.text+' are deleted', icon: Ext.MessageBox.ERROR, buttons: Ext.Msg.OK});
573   - if (this.parentNode) {
574   - if (this.isLeaf()){
575   - var moduleId = this.get('moduleId');
576   - // if really interactive node
577   - if (moduleId) {
578   - var me = this;
579   - myDesktopApp.getLoadedModule(moduleId, true, function (module) {
580   - var editedNode = module.getLinkedNode();
581   - // file node is not linked directly to the module
582   - var isThisFile = false;
583   -
584   - if (editedNode && editedNode.$className == 'amdaModel.MyDataParamNode')
585   - if (editedNode.get('fileObject').get('fileName') == me.get('text'))
586   - isThisFile = true;
587   -
588   - if (me.$className == 'amdaModel.DerivedParamNode')
589   - {
590   - var obj = {
591   - paramId : 'ws_'+me.get('text')
592   - };
593   - AmdaAction.compilParamDelete(obj);
594   - }
595   -
596   - if (editedNode === me || isThisFile){
597   - var newNode = Ext.ModelManager.create({leaf : true}, me.$className);
598   - // several tabs could be connected to one node
599   - if (moduleId === myDesktopApp.dynamicModules.plot.id) {
600   - var linkedNodes = module.linkedNodes;
601   -
602   - if (linkedNodes) {
603   - linkedNodes.each(function(key, value){
604   - if (value === me) {
605   - linkedNodes.replace(key,newNode);
606   - var tabPanel = module.getUiContent().tabPanel.items.getByKey(key);
607   - tabPanel.setObject(Ext.create(amdaModel.Plot.$className, {}));
608   - }
609   - }, me);
610   - }
611   - }
612   - newNode.editInModule();
613   - }
614   - });
615   - }
616   - }
617   - //update mask info in myData
618   - if (res.maskDesc && !res.maskDeleted) {
619   - this.parentNode.set('info', res.maskDesc);
620   - this.updateMyDataParam(res.mask, res.maskDesc);
621   - }
622   - this.remove();
623   - }
624   - //TODO Several special node-dependent actions - to move to node functions..
625   - // nodes of another nodeType to be deleted as they depend on deleted node
626   - if (res.params) {
627   - this.deleteDependence(res.params);
628   - //TODO reset
629   - }
630   - // mask was deleted or updated - to update mydata tree
631   - if (res.maskDeleted) {
632   - this.updateMyData();
633   - }
634   - }
635   - else {
636   - myDesktopApp.warningMsg(res.error);
637   - }
638   - }
639   - else {
640   - myDesktopApp.errorMsg(e.message);
641   - }
642   - }, this);
643   - },
644   -
645   -/*
646   -* Delete musti selection
647   -*/
648   - deleteMulti: function()
649   - {
650   - var selection = this.myGetOwnerTree().getSelectionModel().selected.items;
651   - alert(selection.length +' to delete!');
652   - Ext.Array.each(selection,function(item,index,allItems){
653   - item.deleteNode();
654   - })
655   - },
656   -
657   -/*
658   -* Create Folder
659   -*/
660   - createDir: function() {
661   - var me = this;
662   - amdaModel.InteractiveNode.preloadNodes(this.getRootNode(),
663   - function()
664   - {
665   - var newNode = Ext.create(me.$className,
666   - {
667   - leaf : false, nodeType : me.get('nodeType'),
668   - text : amdaModel.AmdaNode.NEW_DIR_NAME,
669   - children : []
670   - });
671   -
672   - // insert the new node as a child of node
673   - newNode = me.insertChild(0, newNode);
674   - // start text edition on this new directory node
675   - me.expand(false);
676   - newNode.expand(false);
677   -
678   - // select the new node
679   - me.myGetOwnerTree().getSelectionModel().select(newNode);
680   - // call the renameNode method for this new node
681   - newNode.renameNode();
682   - });
683   - },
684   -
685   -/*
686   -*
687   -*/
688   - createLeaf: function(contextNode) {
689   - // create new node with the same type than the contextNode
690   - var newNode = Ext.create(contextNode.$className, {leaf : true});
691   -
692   - // load the rootNode and recursively all its child nodes
693   - amdaModel.InteractiveNode.preloadNodes(contextNode.getRootNode(),
694   - function()
695   - {
696   - // edit newNode into Parameter Module with node as contextNode
697   - newNode.editInModule(contextNode);
698   - });
699   - },
700   -
701   - renameNode: function()
702   - {
703   - if (this.myGetOwnerTree())
704   - {
705   - // load the rootNode and recursively all its child nodes if not already loaded
706   - var me = this;
707   - amdaModel.InteractiveNode.preloadNodes(this.getRootNode(),
708   - function()
709   - {
710   - // fire the edition event on tree
711   - me.myGetOwnerTree().fireEvent('edition',me.myGetOwnerTree().view, me.myGetOwnerTree().getSelectionModel().selected.items[0]);
712   - });
713   - }
714   - else
715   - {
716   - myDesktopApp.errorMsg('tree is undefined');
717   - }
718   - },
719   -
720   -/*
721   -* load the rootNode and recursively all its child nodes
722   -* to know all names of DerivedParameters
723   -*/
724   - editLeaf: function(onReady)
725   - {
726   - var me = this;
727   - amdaModel.InteractiveNode.preloadNodes(this.getRootNode(),
728   - function()
729   - {
730   - if (me.get('object'))
731   - {
732   - // launch edition of parameter into parameter module
733   - me.editInModule(null, onReady);
734   - }
735   - else
736   - {
737   - // call the ext method to get the details of parameter
738   - // the edition of real parameter is done into callback method getObjectCallback
739   - if (onReady)
740   - me.onReady = onReady;
741   -
742   - AmdaAction.getObject(me.get('id'), me.get('nodeType'), me.getObjectCallback, me);
743   - }
744   - });
745   - },
746   -
747   -/*
748   -*
749   -*/
750   - getObjectCallback : function(result,remoteEvent)
751   - {
752   - var t = remoteEvent.getTransaction();
753   -
754   - if (result) {
755   - var paramObj = Ext.create(this.get('objectDataModel'), result);
756   - // set parameter into node
757   - this.set('object',paramObj);
758   - // Edition of parameter into parameter Module
759   - this.editInModule(null, this.onReady);
760   - }
761   - else {
762   - // EXCEPTION : parameter not found !?
763   - myDesktopApp.errorMsg(t.action + "." + t.method + " : No parameter '"
764   - + this.get('name') + "' found!");
765   - }
766   - }
  72 + preloadTreeNode: function (node, nodesToLoad, onloaded) {
  73 + var me = this;
  74 +
  75 + if (node.isLoaded()) {
  76 + node.eachChild(function (n) {
  77 + if (!n.isLoaded() && !n.isLeaf()) {
  78 + nodesToLoad.push(n);
  79 + me.preloadTreeNode(n, nodesToLoad, onloaded);
  80 + }
  81 + });
  82 +
  83 + if (onloaded) {
  84 + onloaded.call(me, node);
  85 + }
  86 + return;
  87 + }
  88 +
  89 + node.store.load({
  90 + node: node,
  91 + callback: function (records) {
  92 + records.forEach(function (record) {
  93 + if (!record.isLoaded() && !record.isLeaf()) {
  94 + nodesToLoad.push(record);
  95 + me.preloadTreeNode(record, nodesToLoad, onloaded);
  96 + }
  97 + });
  98 + if (onloaded) {
  99 + onloaded.call(me, node);
  100 + }
  101 + }
  102 + });
  103 + }
  104 + },
  105 +
  106 + onReady: null,
  107 +
  108 + constructor: function (config) {
  109 + var suffix;
  110 + this.callParent(arguments);
  111 + this.set('nodeType', this.self.nodeType);
  112 + this.set('ownerTreeId', amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
  113 + // TODO why sometimes (delete in remote interoper tree) this.get('id') = undefined ?
  114 + if (this.get('id')) {
  115 + // If id of this node have root category suffix
  116 + suffix = amdaUI.ExplorerUI.CAT_SUFFIX;
  117 + if (Ext.util.Format.substr(this.get('id'), -suffix.length, this.get('id').length) === suffix) {
  118 + // Set the expanded property to true
  119 + this.set('expanded', true);
  120 + }
  121 + }
  122 + },
  123 +
  124 + /**
  125 + * This method is overriden into ExecutableNode to return true
  126 + * @returns {boolean} true if node is executable
  127 + */
  128 + isExecutable: function () {
  129 + return false;
  130 + },
  131 +
  132 + /**
  133 + * Open Module with THIS NODE
  134 + * @param {object} contextNode Context node
  135 + * @param {function} onReady onRady callback function
  136 + * @returns {void}
  137 + */
  138 + editInModule: function (contextNode, onReady) {
  139 + var me = this;
  140 + // Set the contextNode of this node
  141 + this.set('contextNode', contextNode);
  142 + // Parameter module
  143 + myDesktopApp.getLoadedModule(this.get('moduleId'), true, function (module) {
  144 + // If the node to edit is not already linked to this module
  145 + if (module.getLinkedNode() != me) {
  146 + // Set relative node into parameter Module
  147 + module.setLinkedNode(me);
  148 + if (contextNode == null) {
  149 + // Set the root node as contextNode
  150 + contextNode = me.getRootNode();
  151 + }
  152 + module.setContextNode(contextNode);
  153 +
  154 + } else if (module.getLinkedNode() != null) {
  155 +
  156 + /*
  157 + * TODO the node to edit is already edited
  158 + * myDesktopApp.warningMsg('This object is being edited');
  159 + * Sol1: msg alert: "warning this node is already edited! If you want to get the original,
  160 + * please press the 'reset' button"->'OK'
  161 + * Sol2: msg with user choice: "warning this node is already edited! Would you confirm this action and lost your
  162 + * modification?"->'Confirm','Cancel'
  163 + */
  164 + }
  165 + // Opening parameter window
  166 + module.createWindow(onReady);
  167 + });
  168 + },
  169 +
  170 + /**
  171 + * Method to rename the workspace node
  172 + * @param {string} value The new name
  173 + * @param {function} callBackFn Callback function
  174 + * @returns {void}
  175 + */
  176 + rename: function (value, callBackFn) {
  177 + var dataToSend = {
  178 + id: this.get('id'),
  179 + old_name: this.modified.text,
  180 + name: value,
  181 + parent: this.data.parentId,
  182 + leaf: this.isLeaf(),
  183 + nodeType: this.get('nodeType')
  184 + };
  185 + AmdaAction.renameObject(dataToSend, callBackFn);
  186 + },
  187 +
  188 + /**
  189 + * Method to rename the workspace node when D&D
  190 + * @param {string} parentId The parent ID
  191 + * @param {function} callBackFn callback function
  192 + * @returns {void}
  193 + */
  194 + renameDD: function (parentId, callBackFn) {
  195 + var dataToSend = {
  196 + id: this.get('id'),
  197 + old_name: this.get('name'),
  198 + name: this.get('name'),
  199 + parent: parentId,
  200 + leaf: this.isLeaf(),
  201 + nodeType: this.get('nodeType')
  202 + };
  203 + AmdaAction.renameObject(dataToSend, callBackFn);
  204 + },
  205 +
  206 + /**
  207 + * Validation method on name (used in module forms)
  208 + * @param {string} name the name to validate
  209 + * @param {function} callBackFn Callback function
  210 + * @returns {void}
  211 + */
  212 + isValidName: function (name, callBackFn) {
  213 + var dataToSend = {
  214 + name: name,
  215 + nodeType: this.get('nodeType'),
  216 + leaf: this.isLeaf()
  217 + };
  218 + AmdaAction.validNameObject(dataToSend, callBackFn);
  219 + },
  220 +
  221 + /**
  222 + * Method to persist modifications of an AmdaObject by Server side and update the workspace node linked to a Module
  223 + * @param {object} opt ...
  224 + * @returns {void}
  225 + */
  226 + update: function (opt) {
  227 + AmdaAction.modifyObject(this.get('object').getJsonValues(true), function (res, e) {
  228 +
  229 + if (e.status) {
  230 + if (res.id) {
  231 + if (!this.get('contextNode')) {
  232 + // Set the root node of 'Derived Parameters' tree as contextNode
  233 + this.set('contextNode', this.getRootNode());
  234 + }
  235 + this.get('contextNode').expand(false, false);
  236 + this.myGetOwnerTree().getSelectionModel().select(this);
  237 +
  238 + if (opt && opt.callback) {
  239 + opt.callback.call(opt.scope ? opt.scope : this, 'update');
  240 + }
  241 +
  242 + Ext.Msg.alert('Complete', 'Object ' + this.get('object').get('name') + ' has been modified');
  243 + // Fix the modifications for object
  244 + this.get('object').commit();
  245 +
  246 + if (res.info) {
  247 + this.set('info', res.info);
  248 + }
  249 +
  250 + if (this.get('nodeType') == 'myDataParam') {
  251 + if (res.isSpectra) {
  252 + this.set('iconCls', 'icon-spectra');
  253 + } else if (res.size > 1) {
  254 + this.set('iconCls', 'icon-unknowntype');
  255 + }
  256 + }
  257 +
  258 + // Update my data on possibble mask change
  259 + if (res.updateMyData) {
  260 + this.updateMyData();
  261 + this.updateMask(res.mask);
  262 + }
  263 + // Reload object into the view of corresponding Module
  264 + var me = this;
  265 + myDesktopApp.getLoadedModule(this.get('moduleId'), true, function (module) {
  266 + module.getUiContent().setObject(me.get('object'));
  267 + });
  268 + } else {
  269 +
  270 + /*
  271 + *TODO proper error message handling
  272 + * error code from server; but e.status==true
  273 + * revert all modifications since last load or commit
  274 + */
  275 + this.get('object').reject();
  276 + myDesktopApp.errorMsg(res.error);
  277 + }
  278 + } else {
  279 + // Revert all modifications since last load or commit
  280 + this.get('object').reject();
  281 + myDesktopApp.errorMsg(e.message);
  282 + }
  283 + }, this);
  284 + },
  285 +
  286 + /**
  287 + * Method to create a new AmdaObject by server side and create the workspace node linked to a Module under its
  288 + * contextNode or the root node corresponding to this nodeType category.
  289 + * @param {object} opt ...
  290 + * @returns {void}
  291 + */
  292 + create: function (opt) {
  293 + var contextId;
  294 + if (!this.get('contextNode') || this.get('contextNode').data.id == 'sharedtimeTable-treeRootNode' ||
  295 + this.get('contextNode').data.id == 'sharedcatalog-treeRootNode') {
  296 + // Set the root node of 'Derived Parameters' tree as contextNode
  297 + this.set('contextNode', this.getRootNode());
  298 + }
  299 + // Call the Ext.Direct method to create parameter
  300 + contextId = this.get('contextNode').get('id');
  301 + AmdaAction.createObject(this.get('object').getJsonValues(false), contextId, function (res, e) {
  302 + var myRoot, updateNode;
  303 + // Success
  304 + if (e.status) {
  305 + // If correct response received
  306 + if (res.id) {
  307 + // If (res.id || res.error == 'NAME_EXISTS') {
  308 + if (this.toRename) {
  309 + // 'save as' case ; delete old node if it exists
  310 + this.toRename = false;
  311 + myRoot = this.getRootNode();
  312 + // Search the same named node to override
  313 + updateNode = myRoot.findChild('text', this.get('object').get('name'), true);
  314 + // Destroy the overrided node
  315 + updateNode.parentNode.removeChild(updateNode);
  316 + // TODO ??if destroy==true => too many recursions....
  317 + updateNode.destroy();
  318 + }
  319 + // Set text of this node
  320 + this.set('text', this.get('object').get('name'));
  321 + // Set id of this node
  322 + this.set('id', res.id);
  323 + this.internalId = res.id;
  324 + // Set id of node's object
  325 + this.get('object').set('id', res.id);
  326 +
  327 + if (res.created) {
  328 + // Set the created date
  329 + this.get('object').set('created', res.created);
  330 + }
  331 +
  332 + if (res.info) {
  333 + // Set the tooltip
  334 + this.set('info', res.info);
  335 + // Set globalStart & global Stop to be used for time selection
  336 + if (this.get('nodeType') == 'myDataParam') {
  337 + var startStop = res.info.split('<br/>');
  338 + this.set('globalStart', startStop[1].substr(0, 19));
  339 + this.set('globalStop', startStop[1].substr(20));
  340 +
  341 + if (res.mask) {
  342 + this.set('linkedMask', res.mask);
  343 + }
  344 + if (res.size) {
  345 + this.set('size', res.size);
  346 + }
  347 +
  348 + if (res.isSpectra) {
  349 + this.set('iconCls', 'icon-spectra');
  350 + } else if (res.size > 1) {
  351 + this.set('iconCls', 'icon-unknowntype');
  352 + }
  353 + }
  354 + }
  355 +
  356 + /*
  357 + *TODO do we need this commission ???
  358 + * fix the modifications for object
  359 + */
  360 + this.get('object').commit();
  361 + // If ownerTree panel is not active
  362 + if (this.myGetOwnerTree().ownerCt.getActiveTab() !== this.myGetOwnerTree()) {
  363 + // Set ownerTree panel as the active tab - to enable selection of this node his ownerTree must have a view
  364 + this.myGetOwnerTree().ownerCt.setActiveTab(this.myGetOwnerTree());
  365 + }
  366 +
  367 + Ext.Msg.alert('Complete', 'New object ' + this.get('object').get('name') + ' has been created');
  368 + // Expand the contextNode
  369 + this.get('contextNode').expand(false, function () {
  370 + if (!this.get('contextNode').findChild('text', this.get('text'))) {
  371 + // Create node in tree as child of contextNode
  372 + this.get('contextNode').appendChild(this);
  373 + }
  374 + // Select the new node
  375 + this.myGetOwnerTree().getSelectionModel().select(this);
  376 + if (opt && opt.callback) {
  377 + opt.callback.call(opt.scope ? opt.scope : this, 'create');
  378 + }
  379 + }, this);
  380 +
  381 + /*
  382 + * MyDataParamNode - update MyData subtree
  383 + *TODO put this in mydataparamnode
  384 + */
  385 + if (res.updateMyData) {
  386 + this.updateMyData();
  387 + this.updateMask(res.mask);
  388 + }
  389 +
  390 + }
  391 + // Error code from server; but e.status==true
  392 + else {
  393 + myDesktopApp.errorMsg(res.error);
  394 + // Revert all modifications since last load or commit
  395 + this.get('object').reject();
  396 + }
  397 + }
  398 + // Failure: e.status == false
  399 + else {
  400 + // Revert all modifications since last load or commit
  401 + this.get('object').reject();
  402 + // TODO: this.destroy();
  403 + myDesktopApp.errorMsg(e.message);
  404 + }
  405 + }, this);
  406 + },
  407 +
  408 + /**
  409 + * Generic part of Context Menu
  410 + * @returns {*[]|*} Menu items
  411 + */
  412 + allMenuItems: function () {
  413 + var menuItems, src;
  414 +
  415 + src = this.self.objectName;
  416 + menuItems = [
  417 + {
  418 + fnId: 'root-createLeaf',
  419 + text: 'Create ' + src
  420 + },
  421 + {
  422 + fnId: 'root-createDir',
  423 + text: 'Create Folder'
  424 + },
  425 + {
  426 + fnId: 'dire-createLeaf',
  427 + text: 'Create ' + src
  428 + },
  429 + {
  430 + fnId: 'dire-createDir',
  431 + text: 'Create Folder'
  432 + },
  433 + {
  434 + fnId: 'dire-renameNode',
  435 + text: 'Rename Folder'
  436 + },
  437 + {
  438 + fnId: 'dire-deleteNode',
  439 + text: 'Delete Folder'
  440 + },
  441 + {
  442 + fnId: 'leaf-editLeaf',
  443 + text: 'Edit ' + src
  444 + },
  445 + {
  446 + fnId: 'leaf-renameNode',
  447 + text: 'Rename ' + src
  448 + },
  449 + {
  450 + fnId: 'leaf-deleteNode',
  451 + text: 'Delete ' + src
  452 + }
  453 + ];
  454 + return menuItems;
  455 + },
  456 +
  457 + allMenuMultiItems: function () {
  458 + return [
  459 + {
  460 + fnId: 'mult-deleteMulti',
  461 + text: 'Delete selected ' + this.self.objectName + 's'
  462 + }
  463 + ];
  464 + },
  465 +
  466 + getAllContextMenuItems: function () {
  467 + return this.allMenuItems();
  468 + },
  469 +
  470 + getMultiContextMenuItems: function () {
  471 + return this.allMenuMultiItems();
  472 + },
  473 +
  474 + // FIXME: duplicate declaration โ†“ โ†‘
  475 +
  476 + /**
  477 + * Default implementation: no menu display if there's no override of this function
  478 + * @returns {null} Items
  479 + */
  480 + getMultiContextMenuItems: function () {
  481 + return null;
  482 + },
  483 +
  484 + /**
  485 + * Context Menu Actions
  486 + * @param {object} menu The menu
  487 + * @param {object} item the item
  488 + * @returns {void}
  489 + */
  490 + onMenuItemClick: function (menu, item) {
  491 + // FnId parsing :
  492 + var fnId = Ext.util.Format.substr(item.fnId, 5, item.fnId.length);
  493 +
  494 + switch (fnId) {
  495 + case 'deleteNode':
  496 + this.deleteNode();
  497 + break;
  498 + case 'createDir':
  499 + this.createDir();
  500 + break;
  501 + case 'createLeaf':
  502 + this.createLeaf(this);
  503 + break;
  504 + case 'renameNode':
  505 + this.renameNode(false);
  506 + break;
  507 + case 'editLeaf':
  508 + this.editLeaf();
  509 + break;
  510 + case 'deleteMulti':
  511 + this.deleteMulti();
  512 + break;
  513 + case 'plotParam':
  514 + this.createPlot(this);
  515 + break;
  516 + case 'downParam':
  517 + this.createDownload(this);
  518 + break;
  519 + default:
  520 + break;
  521 + }
  522 + },
  523 +
  524 + getTimeFromNode: function (node) {
  525 + var startDate, stopDate, timeObj;
  526 + startDate = new Date(String(node.get('globalStart')).replace(/-/g, '/').replace(/[T|Z]/g, ' '));
  527 + stopDate = new Date(String(node.get('globalStop')).replace(/-/g, '/').replace(/[T|Z]/g, ' '));
  528 +
  529 + if (stopDate - startDate > 86400000) {
  530 + // 'timeObj = {start: Ext.Date.format(startTime, 'Y/m/d H:i:s'), stop: Ext.Date.format(stopDate, 'Y/m/d H:i:s')};
  531 + timeObj = {
  532 + start: Ext.Date.format(Ext.Date.add(stopDate, Ext.Date.DAY, -1), 'Y/m/d'),
  533 + stop: Ext.Date.format(stopDate, 'Y/m/d')
  534 + };
  535 + } else {
  536 + timeObj = {
  537 + start: node.get('globalStart'),
  538 + stop: node.get('globalStop')
  539 + };
  540 + }
  541 + return timeObj;
  542 + },
  543 +
  544 + createPlot: function (node) {
  545 + if (node.get('disable')) {
  546 + return;
  547 + }
  548 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.plot.id, true, function (module) {
  549 + if (!myDesktopApp.desktop.getWindow(myDesktopApp.dynamicModules.plot.id)) {
  550 + var request = Ext.create(amdaPlotObj.PlotRequestObject.$className);
  551 + var newNode = Ext.create(amdaModel.PlotNode.$className, {object: request});
  552 + // Edit newNode into Plot Module with node as contextNode
  553 + newNode.editInModule();
  554 + if (node.get('globalStart') != null && node.get('globalStop') != null &&
  555 + node.get('globalStart') != 'depending on mission' && node.get('isParameter')) {
  556 + module.getUiContent().setTimeFromData(node.getTimeFromNode(node));
  557 + }
  558 + }
  559 + module.getUiContent().addParameter(node);
  560 + });
  561 + },
  562 +
  563 + createDownload: function (node) {
  564 + if (node.get('disable')) {
  565 + return;
  566 + }
  567 +
  568 + if (node.get('notyet')) {
  569 + myDesktopApp.warningMsg('Sorry! access to this parameter is restricted.');
  570 + return;
  571 + }
  572 +
  573 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.download.id, true, function (module) {
  574 + var paramName, request;
  575 + if (!myDesktopApp.desktop.getWindow(myDesktopApp.dynamicModules.download.id)) {
  576 + request = Ext.create(amdaModel.Download.$className);
  577 + amdaModel.DownloadNode.set('object', request);
  578 + // Singleton!
  579 + amdaModel.DownloadNode.editInModule();
  580 + if (node.get('globalStart') != null && node.get('globalStop') != null &&
  581 + node.get('globalStart') != 'depending on mission' && node.get('isParameter')) {
  582 + module.getUiContent().setTimeFromData(node.getTimeFromNode(node));
  583 + }
  584 + }
  585 + switch (node.$className) {
  586 + case 'amdaModel.AliasNode':
  587 + paramName = '#' + node.get('text');
  588 + break;
  589 + case 'amdaModel.DerivedParamNode':
  590 + paramName = 'ws_' + node.get('text');
  591 + break;
  592 + case 'amdaModel.MyDataParamNode':
  593 + paramName = 'wsd_' + node.get('text');
  594 + break;
  595 + default:
  596 + if (node.get('alias') != '') {
  597 + paramName = '#' + node.get('alias');
  598 + } else {
  599 + paramName = node.get('id');
  600 + }
  601 + }
  602 +
  603 + /*
  604 + * Var component_info = node.get('component_info');
  605 + * If (component_info && component_info.parentId) {
  606 + * // It's a component
  607 + * ParamName = component_info.parentId;
  608 + * Components = [];
  609 + * If (component_info.index1)
  610 + * Components['index1'] = component_info.index1;
  611 + * If (component_info.index2)
  612 + * Components['index2'] = component_info.index2;
  613 + * }
  614 + */
  615 + module.addParam(paramName, true, node.get('needsArgs'), null);
  616 + });
  617 + },
  618 +
  619 + deleteNode: function () {
  620 + // If the target is a directory
  621 + if (this.isLeaf()) {
  622 + // No confirmation prompt for leaves
  623 + this.confirmDirectoryDeletion(false);
  624 + } else {
  625 + // Determine if this directory is empty before launching the delete confirmation method
  626 + this.isNotEmptyDir(this.confirmDirectoryDeletion);
  627 + // Else (the target is a leaf)
  628 + }
  629 + },
  630 +
  631 + /**
  632 + * This method return if node has Childs even if it was not already loaded
  633 + * @param {function} callbackFn Callback function
  634 + * @returns {void}
  635 + */
  636 + isNotEmptyDir: function (callbackFn) {
  637 + // If node not already loaded
  638 + if (this.isLoaded()) {
  639 + callbackFn.call(this, this.hasChildNodes());
  640 + } else {
  641 + // Call directFunction to load this node
  642 + AmdaAction.getTree({
  643 + node: this.get('id'),
  644 + nodeType: this.get('nodeType')
  645 + }, function (res) {
  646 + callbackFn.call(this, res.length > 0);
  647 + }, this);
  648 + }
  649 + },
  650 +
  651 + /**
  652 + * This method is used to display a confirmation message
  653 + * @param {boolean} isNotEmptyDir true if the directory is not empty.
  654 + * @returns {void}
  655 + */
  656 + confirmDirectoryDeletion: function (isNotEmptyDir) {
  657 + var ConfirmMsg = 'The target is a non-empty directory!<br>Do you want to continue and also delete its content?';
  658 + // If this is a non-empty directory
  659 + if (isNotEmptyDir) {
  660 + // Prompt to the user if he also wants to delete its content
  661 + Ext.Msg.confirm('non-empty directory', ConfirmMsg, function (btn, text) {
  662 + if (btn == 'yes') {
  663 + // Do delete
  664 + this.realDelete();
  665 + }
  666 + }, this);
  667 + } else {
  668 + this.realDelete();
  669 + }
  670 + },
  671 +
  672 + /*
  673 + * Call the extDirect method to delete parameter
  674 + * Callback method needed to execute node deletion in tree if id in result or to show error msg
  675 + */
  676 + realDelete: function () {
  677 + AmdaAction.deleteObject({
  678 + id: this.get('id'),
  679 + leaf: this.isLeaf(),
  680 + nodeType: this.get('nodeType')
  681 + }, function (res, e) {
  682 + var me, moduleId;
  683 + me = this;
  684 +
  685 + // Node deletion in tree - TODO proper errors handling
  686 +
  687 + // If success
  688 + if (res) {
  689 + if (res.id) {
  690 +
  691 + /*
  692 + * Ext.Msg.show({
  693 + * title:'Warning',
  694 + * msg: 'Requests with parameter '+node.data.text+' are deleted',
  695 + * icon: Ext.MessageBox.ERROR,
  696 + * buttons: Ext.Msg.OK
  697 + * });
  698 + */
  699 + if (this.parentNode) {
  700 + if (this.isLeaf()) {
  701 + moduleId = this.get('moduleId');
  702 + // If really interactive node
  703 + if (moduleId) {
  704 + myDesktopApp.getLoadedModule(moduleId, true, function (module) {
  705 + var editedNode, isThisFile, linkedNodes, newNode, tabPanel;
  706 + editedNode = module.getLinkedNode();
  707 + // File node is not linked directly to the module
  708 + isThisFile = false;
  709 +
  710 + if (editedNode && editedNode.$className == 'amdaModel.MyDataParamNode') {
  711 + if (editedNode.get('fileObject').get('fileName') == me.get('text')) {
  712 + isThisFile = true;
  713 + }
  714 + }
  715 +
  716 + if (me.$className == 'amdaModel.DerivedParamNode') {
  717 + AmdaAction.compilParamDelete({paramId: 'ws_' + me.get('text')});
  718 + }
  719 +
  720 + if (editedNode === me || isThisFile) {
  721 + newNode = Ext.ModelManager.create({leaf: true}, me.$className);
  722 + // Several tabs could be connected to one node
  723 + if (moduleId === myDesktopApp.dynamicModules.plot.id) {
  724 + linkedNodes = module.linkedNodes;
  725 +
  726 + if (linkedNodes) {
  727 + linkedNodes.each(function (key, value) {
  728 + if (value === me) {
  729 + linkedNodes.replace(key, newNode);
  730 + tabPanel = module.getUiContent().tabPanel.items.getByKey(key);
  731 + tabPanel.setObject(Ext.create(amdaModel.Plot.$className, {}));
  732 + }
  733 + }, me);
  734 + }
  735 + }
  736 + newNode.editInModule();
  737 + }
  738 + });
  739 + }
  740 + }
  741 + // Update mask info in myData
  742 + if (res.maskDesc && !res.maskDeleted) {
  743 + this.parentNode.set('info', res.maskDesc);
  744 + this.updateMyDataParam(res.mask, res.maskDesc);
  745 + }
  746 + this.remove();
  747 + }
  748 +
  749 + /*
  750 + *TODO Several special node-dependent actions - to move to node functions..
  751 + * nodes of another nodeType to be deleted as they depend on deleted node
  752 + */
  753 + if (res.params) {
  754 + this.deleteDependence(res.params);
  755 + // TODO reset
  756 + }
  757 + // Mask was deleted or updated - to update mydata tree
  758 + if (res.maskDeleted) {
  759 + this.updateMyData();
  760 + }
  761 + } else {
  762 + myDesktopApp.warningMsg(res.error);
  763 + }
  764 + } else {
  765 + myDesktopApp.errorMsg(e.message);
  766 + }
  767 + }, this);
  768 + },
  769 +
  770 + /**
  771 + * Delete multi selection
  772 + * @returns {void}
  773 + */
  774 + deleteMulti: function () {
  775 + var selection = this.myGetOwnerTree().getSelectionModel().selected.items;
  776 + Ext.alert(selection.length + ' to delete!');
  777 + Ext.Array.each(selection, function (item, index, allItems) {
  778 + item.deleteNode();
  779 + });
  780 + },
  781 +
  782 + /**
  783 + * Create Folder
  784 + * @returns {void}
  785 + */
  786 + createDir: function () {
  787 + var me = this;
  788 + amdaModel.InteractiveNode.preloadNodes(this.getRootNode(), function () {
  789 + var newNode = Ext.create(me.$className,
  790 + {
  791 + leaf: false,
  792 + nodeType: me.get('nodeType'),
  793 + text: amdaModel.AmdaNode.NEW_DIR_NAME,
  794 + children: [],
  795 + parentId: me.get('id')
  796 + });
  797 +
  798 + // Insert the new node as a child of node
  799 + me.insertChild(0, newNode);
  800 + // Start text edition on this new directory node
  801 + me.expand(false);
  802 + newNode.expand(false);
  803 +
  804 + // Select the new node
  805 + me.myGetOwnerTree().getSelectionModel().select(newNode);
  806 + // Call the renameNode method for this new node
  807 + newNode.renameNode(true);
  808 + });
  809 + },
  810 +
  811 + /*
  812 + *
  813 + */
  814 + createLeaf: function (contextNode) {
  815 + // Create new node with the same type than the contextNode
  816 + var newNode = Ext.create(contextNode.$className, {leaf: true});
  817 +
  818 + // Load the rootNode and recursively all its child nodes
  819 + amdaModel.InteractiveNode.preloadNodes(contextNode.getRootNode(), function () {
  820 + // Edit newNode into Parameter Module with node as contextNode
  821 + newNode.editInModule(contextNode);
  822 + });
  823 + },
  824 +
  825 + renameNode: function (deleteOnFailure) {
  826 + var item, me;
  827 + me = this;
  828 + if (this.myGetOwnerTree()) {
  829 + // Load the rootNode and recursively all its child nodes if not already loaded
  830 + amdaModel.InteractiveNode.preloadNodes(this.getRootNode(), function () {
  831 + // Fire the edition event on tree
  832 + item = me.myGetOwnerTree().getSelectionModel().selected.items[0];
  833 + item.deleteOnFailure = deleteOnFailure;
  834 + me.myGetOwnerTree().fireEvent('edition', me.myGetOwnerTree().view, item);
  835 + });
  836 + } else {
  837 + myDesktopApp.errorMsg('tree is undefined');
  838 + }
  839 + },
  840 +
  841 + /**
  842 + * Load the rootNode and recursively all its child nodes to know all names of DerivedParameters
  843 + * @param {function} onReady On ready callback function
  844 + * @returns {void}
  845 + */
  846 + editLeaf: function (onReady) {
  847 + var me = this;
  848 + amdaModel.InteractiveNode.preloadNodes(this.getRootNode(), function () {
  849 + if (me.get('object')) {
  850 + // Launch edition of parameter into parameter module
  851 + me.editInModule(null, onReady);
  852 + } else {
  853 +
  854 + /*
  855 + * Call the ext method to get the details of parameter
  856 + * the edition of real parameter is done into callback method getObjectCallback
  857 + */
  858 + if (onReady) {
  859 + me.onReady = onReady;
  860 + }
  861 +
  862 + AmdaAction.getObject(me.get('id'), me.get('nodeType'), me.getObjectCallback, me);
  863 + }
  864 + });
  865 + },
  866 +
  867 + /**
  868 + * Get object callback
  869 + * @param {object} result The result
  870 + * @param {object} remoteEvent ...
  871 + * @returns {void}
  872 + */
  873 + getObjectCallback: function (result, remoteEvent) {
  874 + var t = remoteEvent.getTransaction();
  875 +
  876 + if (result) {
  877 + var paramObj = Ext.create(this.get('objectDataModel'), result);
  878 + // Set parameter into node
  879 + this.set('object', paramObj);
  880 + // Edition of parameter into parameter Module
  881 + this.editInModule(null, this.onReady);
  882 + } else {
  883 + // EXCEPTION : parameter not found !?
  884 + myDesktopApp.errorMsg(t.action + '.' + t.method + ' : No parameter \'' +
  885 + this.get('name') + '\' found!');
  886 + }
  887 + }
767 888 });
... ...
js/app/views/ExplorerUI.js
1 1 /**
2 2 * Project  : AMDA-NG4
3 3 * Name : ExplorerUI.js
4   - * @class amdaUI.ExplorerUI
  4 + * @class amdaUI.ExplorerUI
5 5 * @extends Ext.tab.Panel
6 6 * @class amdaUI.TreeToolColumn
7 7 * @extends Ext.tree.Column
... ... @@ -11,1085 +11,1049 @@
11 11 * @author CDA
12 12 */
13 13  
  14 +/* global AmdaAction, amdaModel, myDesktopApp, amdaUI, MyTreeEditor */
  15 +
14 16 Ext.define('amdaUI.TreeToolColumn', {
15   - extend: 'Ext.tree.Column',
16   - alias: 'widget.treetoolcolumn',
17   -
18   - /**
19   - * Add more tools here. These will be on the prototype for all TreeToolColumns
20   - */
21   - tools: {
22   - 'info': 'js/resources/images/16x16/info_mini.png'
23   - },
24   -
25   - initComponent: function()
26   - {
27   - var me = this;
28   - me.addEvents('toolclick');
29   - me.callParent();
30   - me.on('toolclick', me.toolHandler, me);
31   - },
32   -
33   - renderer: function(value, metaData, record, rowIdx, colIdx, store, view)
34   - {
35   - var toolCol = view.getHeaderAtIndex(colIdx);
36   -
37   - if (!toolCol.toolIsVisible(record)) return value;
38   -
39   - var toolId = 'tool-' + rowIdx + '-' + colIdx,
40   - toolImg = toolCol.tools[toolCol.tool],
41   - imgHtml = Ext.DomHelper.markup({
42   - id : toolId,
43   - tag : 'img',
44   - tooltype: toolCol.tool,
45   - src : toolImg,
46   - style : 'cursor:hand;'
47   - });
48   -
49   - return value + ' ' + imgHtml;
50   - },
51   -
52   - processEvent: function(type, view, cell, recordIndex, cellIndex, e)
53   - {
54   - if(type === "click" && e.target.tagName === "IMG")
55   - {
56   - var tooltype = e.target.getAttribute("tooltype");
57   - if(tooltype)
58   - return this.fireEvent("toolclick", view, cell, recordIndex, cellIndex, e);
59   - }
60   - return this.fireEvent.apply(this, arguments);
61   - },
62   -
63   - /**
64   - * Override this when you add columns to the tree... see example below
65   - */
66   -// toolHandler: function() {
67   -// alert("override this");
68   -// },
69   -
70   - toolIsVisible : function(record) {
71   - return false;
72   - }
  17 + extend: 'Ext.tree.Column',
  18 + alias: 'widget.treetoolcolumn',
  19 +
  20 + /**
  21 + * Add more tools here. These will be on the prototype for all TreeToolColumns
  22 + */
  23 + tools: {info: 'js/resources/images/16x16/info_mini.png'},
  24 +
  25 + initComponent: function () {
  26 + var me = this;
  27 +
  28 + me.addEvents('toolclick');
  29 + me.callParent();
  30 + me.on('toolclick', me.toolHandler, me);
  31 + },
  32 +
  33 + renderer: function (value, metaData, record, rowIdx, colIdx, store, view) {
  34 + var imgHtml,
  35 + toolCol = view.getHeaderAtIndex(colIdx);
  36 +
  37 + if (!toolCol.toolIsVisible(record)) {
  38 + return value;
  39 + }
  40 +
  41 + imgHtml = Ext.DomHelper.markup({
  42 + id: 'tool-' + rowIdx + '-' + colIdx,
  43 + tag: 'img',
  44 + tooltype: toolCol.tool,
  45 + src: toolCol.tools[toolCol.tool],
  46 + style: 'cursor:hand;'
  47 + });
  48 +
  49 + return value + ' ' + imgHtml;
  50 + },
  51 +
  52 + processEvent: function (type, view, cell, recordIndex, cellIndex, e) {
  53 + var toolType;
  54 +
  55 + if (type === 'click' && e.target.tagName === 'IMG') {
  56 + toolType = e.target.getAttribute('tooltype');
  57 + if (toolType) {
  58 + return this.fireEvent('toolclick', view, cell, recordIndex, cellIndex, e);
  59 + }
  60 + }
  61 + return this.fireEvent.apply(this, arguments);
  62 + },
  63 +
  64 + /**
  65 + * Override this when you add columns to the tree... see example below:
  66 + *
  67 + * ToolHandler: function() {
  68 + * Alert("override this");
  69 + * }
  70 + *
  71 + * @returns {boolean} False
  72 + */
  73 + toolIsVisible: function () {
  74 + return false;
  75 + }
73 76 });
74 77  
75 78  
76 79 // ExplorerUI
77 80 Ext.define('amdaUI.ExplorerUI', {
78   - extend: 'Ext.tab.Panel',
79   - alias : 'widget.panelExplorer',
80   -
81   - statics:
82   - {
83   - RESRC_TAB : {
84   - TREE_ID:'resourcesTree',
85   - TREE_TYPE:'resources'
86   - },
87   - OPE_TAB : {
88   - TREE_ID:'operationsTree',
89   - TREE_TYPE:'operations'
90   - },
91   - JOB_TAB : {
92   - TREE_ID:'jobsTree',
93   - TREE_TYPE:'jobs'
94   - },
95   -
96   - CAT_SUFFIX: '-treeBase',
97   - ROOT_SUFFIX: '-treeRootNode',
98   - SUB_ROOT_SUFFIX : 'RootNode',
99   -
100   - ITEM_KIND_BASE : 'base',
101   - ITEM_KIND_ROOT : 'root',
102   - ITEM_KIND_LEAF : 'leaf',
103   - ITEM_KIND_DIRE : 'dire',
104   - ITEM_KIND_PARA : 'para',
105   - ITEM_KIND_MISS : 'miss'
106   - },
107   -
108   - initComponent : function (config)
109   - {
110   - var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
111   -
112   - var myConf = {
113   - split : true,
114   - width : '100%',
115   - height : '100%',
116   - autoScroll : true,
117   - border : true,
118   - header : false,
119   - defaults : {
120   - // applied to each contained panel
121   - containerScroll : true
122   - },
123   - stateful: true,
124   - //stateId: 'tp1',
125   - stateEvents: ['tabchange'],
126   - getState: function() {
127   - return {
128   - activeTab: this.items.findIndex('id',this.getActiveTab().id)
129   - };
130   - },
131   - applyState: function(s) {
132   - this.setActiveTab(s.activeTab);
133   - },
134   - items: [
135   - this.initTree(amdaUI.ExplorerUI.RESRC_TAB.TREE_TYPE),
136   - this.initTree(amdaUI.ExplorerUI.OPE_TAB.TREE_TYPE),
137   - this.initTree(amdaUI.ExplorerUI.JOB_TAB.TREE_TYPE)
138   - ],
139   - tbar : [
140   - {
141   - xtype : 'combo',
142   - fieldLabel: 'Filter',
143   - labelWidth: 25,
144   - width: 140,
145   - store: explorerModule.filtersStore,
146   - queryMode: 'local',
147   - displayField: 'name',
148   - valueField: 'id',
149   - listeners : {
150   - scope : this,
151   - select: function(combo, records) {
152   - AmdaAction.setCrtFilterId({id : records[0].get('id')},
153   - function (result, e)
154   - {
155   - var t = e.getTransaction();
156   - if (e.status)
157   - {
158   - if (result)
159   - {
160   - var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
161   - if (explorerModule)
162   - explorerModule.setCrtFilter();
163   - }
164   - else
165   - Ext.Msg.show( {
166   - title : 'Filter',
167   - msg : 'Cannot apply filter',
168   - modal : true,
169   - icon : Ext.Msg.ERROR,
170   - buttons : Ext.Msg.OK
171   - });
172   - }
173   - else
174   - {
175   - // FAILURE
176   - Ext.Msg.show({title:'Error System', msg: e.message, icon: Ext.MessageBox.ERROR, buttons: Ext.Msg.OK});
177   - }
178   - },this);
179   - }
180   - }
181   - },
182   - {
183   - text: '',
184   - iconCls : 'icon-parameters',
185   - tooltip: { text: 'Edit Filter', align: 'bl-tl' },
186   - handler: function(t){
187   - myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.filters.id, true, function (module) {
188   - module.createWindow();
189   - });
190   - }
191   - },
192   - {
193   - text: '',
194   - iconCls : 'icon-remover',
195   - tooltip: { text: 'Reset Filter', align: 'bl-tl' },
196   - handler: function(t){
197   - var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
198   - explorerModule.resetFilter();
199   - }
200   - }, '-',
201   - {
202   - xtype: 'displayfield',
203   - fieldLabel: 'SortBy',
204   - width: 40
205   - },
206   - {
207   - text: 'Name',
208   - scope : this,
209   - tooltip: { text: 'Sort out AMDA DataBase Data by Mission Name', align: 'bl-tl' },
210   - pressed: true,
211   - enableToggle : true,
212   - toggleGroup: 'sorting',
213   - handler: function(){
214   - var tree = Ext.getCmp(amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
215   - tree.getStore().sort([
216   - { sorterFn: function(o1, o2){
217   - if (o1.get('nodeType') !== 'localParam')
218   - return;
219   -
220   - return o1.get('text').toUpperCase() < o2.get('text').toUpperCase() ? -1 : 1;
221   - }
222   - }]);
223   - this.updateFilter();
224   - }
225   - },
226   - {
227   - text: 'Target',
228   - scope : this,
229   - tooltip: {text: 'Sort out AMDA DataBase Data by Mission Main Target', align: 'bl-tl'},
230   - enableToggle : true,
231   - toggleGroup: 'sorting',
232   - handler: function(){
233   - var tree = Ext.getCmp(amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
234   - tree.getStore().sort([{ property : 'rank' }]);
235   - this.updateFilter();
236   - }
237   - }]
238   - };
239   - Ext.apply (this , Ext.apply (arguments, myConf));
240   - this.callParent(arguments);
241   - },
242   -
243   - initTree : function(treeType)
244   - {
245   - switch (treeType)
246   - {
247   - case amdaUI.ExplorerUI.RESRC_TAB.TREE_TYPE:
248   - treeId = amdaUI.ExplorerUI.RESRC_TAB.TREE_ID;
249   - break;
250   - case amdaUI.ExplorerUI.OPE_TAB.TREE_TYPE:
251   - treeId = amdaUI.ExplorerUI.OPE_TAB.TREE_ID;
252   - break;
253   - case amdaUI.ExplorerUI.JOB_TAB.TREE_TYPE:
254   - treeId = amdaUI.ExplorerUI.JOB_TAB.TREE_ID;
255   - break;
256   - default:
257   - treeId = amdaUI.ExplorerUI.RESRC_TAB.TREE_ID;
258   - break;
259   - }
260   -
261   - var store = Ext.create('Ext.data.TreeStore', {
262   - root: {
263   - expanded: true,
264   - nodeType : treeType
265   - },
266   - model: 'amdaModel.AmdaNode',
267   - sorters:[{ direction: 'ASC' ,
268   - sorterFn: function(o1, o2){
269   -
270   - if (o1.get('nodeType') == 'localParam' || o1.get('nodeType') == 'myData') {
271   - return o1.get('text').toUpperCase() < o2.get('text').toUpperCase() ? -1 : 1;
272   - }
273   -
274   - return;
275   - }
276   - }],
277   - listeners: {
278   - beforeload: function(store, operation){
279   - store.proxy.extraParams = {
280   - nodeType: operation.node.get('nodeType')
281   - };
282   - }
283   - }
284   - });
285   -
286   - var menu = new Ext.menu.Menu();
287   -
288   - var tree = Ext.create('Ext.tree.Panel', {
289   - id : treeId,
290   - title: treeType,
291   - store: store,
292   - rootVisible: false,
293   - animate: false,
294   - hideHeaders : true,
295   - selModel: Ext.create('Ext.selection.TreeModel', {
296   - // ignoreRightMouseSelection: true,
297   - mode: 'MULTI'
298   - }),
299   - viewConfig:
300   - {
301   - plugins:
302   - {
303   - ptype: 'treeviewdragdrop',
304   - enableDrag:true,
305   - enableDrop:true,
306   - //TODO - BRE - Wait a fix for drag&drop issue
307   - ddGroup:'explorerTree',
308   - pluginId : 'ddplugin',
309   -
310   - isValidDropPoint : function (node, position, dragZone, e, data)
311   - {
312   - if (!node || !data.item) {
313   - return false;
314   - }
315   - var view = this.view,
316   - targetNode = view.getRecord(node),
317   - draggedRecords = data.records,
318   - dataLength = draggedRecords.length,
319   - ln = draggedRecords.length,
320   - i, record;
321   -
322   - // No drop position, or dragged records: invalid drop point
323   - if (!(targetNode && position && dataLength)) {
324   - return false;
325   - }
326   - // If the targetNode is within the folder we are dragging
327   - for (i = 0; i < ln; i++) {
328   - record = draggedRecords[i];
329   - if (record.isNode && record.contains(targetNode)) {
330   - return false;
331   - }
332   - }
333   - // Respect the allowDrop field on Tree nodes
334   - if (position === 'append' && targetNode.get('allowDrop') === false) {
335   - return false;
336   - }
337   - else if (position != 'append' && targetNode.parentNode.get('allowDrop') === false) {
338   - return false;
339   - }
340   - // If the target record is in the dragged dataset, then invalid drop
341   - if (Ext.Array.contains(draggedRecords, targetNode)) {
342   - return false;
343   - }
344   - //
345   - if (dataLength > 1)
346   - return false;
347   -
348   - var draggedRecord = draggedRecords[0];
349   - //
350   - switch (targetNode.data.nodeType)
351   - {
352   - case 'localParam' :
353   - case 'remoteParam' :
354   - case 'remoteSimuParam' :
355   - case 'myData' :
356   - return false;
357   - default :
358   - if (draggedRecord.data.id == targetNode.data.nodeType+'-treeRootNode')
359   - return false;
360   - if ((position == 'before') && (targetNode.data.id == targetNode.data.nodeType+'-treeRootNode'))
361   - return false;
362   - return (draggedRecord.data.nodeType == targetNode.data.nodeType);
363   - }
364   - return false;
365   - },
366   - onViewRender : function(view)
367   - {
368   - var me = this;
369   -
370   - view.on('itemupdate', function(record,index,node,opts)
371   - {
372   - var forceHide = false;
373   - var crtRec = record.parentNode;
374   - while (crtRec && !forceHide)
375   - {
376   - if (crtRec.get('filtered'))
377   - forceHide = crtRec.get('filtered');
378   - crtRec = crtRec.parentNode;
379   - }
380   - tree.setNodesVisibility(record,forceHide);
381   - tree.applyDisableToNode(record);
382   - });
383   -
384   - view.on('itemadd', function(records,index,node,opts)
385   - {
386   - Ext.each(records,function (rec)
387   - {
388   - tree.applyFilterToNode(rec);
389   - tree.applyDisableToNode(rec);
390   - });
391   - });
392   -
393   - view.on('afteritemexpand', function(record,index,node,opts)
394   - {
395   - var forceHide = false;
396   - var crtRec = record.parentNode;
397   - while (crtRec && !forceHide)
398   - {
399   - if (crtRec.get('filtered'))
400   - forceHide = crtRec.get('filtered');
401   - crtRec = crtRec.parentNode;
402   -
403   - }
404   - tree.setNodesVisibility(record,forceHide);
405   - tree.applyDisableToNode(record);
406   - });
407   -
408   - if (me.enableDrag)
409   - {
410   - me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
411   - view: view,
412   - ddGroup: me.dragGroup || me.ddGroup,
413   - dragText: me.dragText,
414   - repairHighlightColor: me.nodeHighlightColor,
415   - repairHighlight: me.nodeHighlightOnRepair
416   - });
417   - }
418   -
419   - if (me.enableDrop)
420   - {
421   - me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
422   - view: view,
423   - ddGroup: me.dropGroup || me.ddGroup,
424   - allowContainerDrops: me.allowContainerDrops,
425   - appendOnly: me.appendOnly,
426   - allowParentInserts: me.allowParentInserts,
427   - expandDelay: me.expandDelay,
428   - dropHighlightColor: me.nodeHighlightColor,
429   - dropHighlight: me.nodeHighlightOnDrop,
430   - isValidDropPoint : me.isValidDropPoint
431   - });
432   - }
433   - }
434   - },
435   - listeners :
436   - {
437   - beforedrop : function(node, data, overModel, dropPosition)
438   - {
439   - var parentId;
440   - switch(dropPosition)
441   - {
442   - case 'append' :
443   - if (overModel.isLeaf())
444   - parentId = overModel.parentNode.get('id');
445   - else
446   - parentId = overModel.get('id');
447   -
448   - if(!overModel.isExpanded() && overModel.isExpandable()) {
449   - myDesktopApp.warningMsg('Please open the folder before node adding');
450   - return false;
451   - }
452   - break;
453   - case 'before' :
454   - case 'after' :
455   - parentId = overModel.parentNode.get('id');
456   - break;
457   - }
458   -
459   - Ext.each(data.records, function(rec)
460   - {
461   - rec.renameDD(parentId,function(result)
462   - {
463   - if (result)
464   - {
465   - if (!result.id)
466   - {
467   - Ext.Msg.show({
468   - title : 'Drop is impossible',
469   - msg : result.error,
470   - buttons : Ext.Msg.OK,
471   - icon : Ext.MessageBox.WARNING
472   - });
473   -
474   - return false;
475   - }
476   - }
477   - else
478   - {
479   - Ext.Msg.show({
480   - title : 'Drop is impossible',
481   - msg : 'Cannot connect to the server',
482   - buttons : Ext.Msg.OK,
483   - icon : Ext.MessageBox.WARNING
484   - });
485   -
486   - return false;
487   - }
488   -
489   - return true;
490   - });
491   - });
492   - }
493   - }
494   - },
495   - listeners:
496   - {
497   - itemmouseenter: function(view, record, item){
498   - if(record.get('isParameter')){
499   - var el = Ext.get(item),
500   - td = el.down('td > div');
501   - td.setStyle('cursor', 'crosshair');
502   - }
503   - else
504   - {
505   - var el = Ext.get(item),
506   - td = el.down('td > div');
507   - td.setStyle('cursor', 'pointer');
508   - }
509   - },
510   -
511   - itemcontextmenu: function(view, rec, item, index, e){
512   - // Add record to selection model
513   - view.ownerCt.getSelectionModel().select(rec);
514   -
515   - // block other events
516   - e.stopEvent();
517   -
518   - // clear menu items
519   - menu.removeAll();
520   - var menuItems;
521   -
522   - // if it's a single selection
523   - if (view.ownerCt.getSelectionModel().selected.length === 1) {
524   - // get items menu corresponding to right clicked record
525   - menuItems = rec.getContextMenuItems(this);
526   -
527   - } else if (view.ownerCt.getSelectionModel().selected.length > 1) {
528   - // get items menu corresponding to right clicked record
529   - menuItems = rec.getContextMenuMultiItems(this);
530   - }
531   - // if there's at least one item menu
532   - if (menuItems && menuItems.length){
533   - // add the items
534   - menu.add(menuItems);
535   - // add listener on right clicked record
536   - var onRecordClick = function (menu, item, e, eOpts)
537   - {
538   - if (this.myGetOwnerTree().getSelectionModel().isSelected(this)) {
539   - //Dispatch click event to the record
540   - this.onMenuItemClick(menu,item,e);
541   - }
542   - //Remove old click listener
543   - menu.removeListener('click',onRecordClick,this);
544   - };
545   -
546   - menu.addListener('click',onRecordClick,rec);
547   - // then show menu
548   - menu.showAt(e.getXY());
549   - }
550   - },
551   -
552   - itemdblclick: function(view, record, item, index, event){
553   - event.stopEvent();
554   - // first check if it is for SAVE-START-STOP plugin...
555   - if (Ext.PluginManager.getCount() > 0 &&
556   - record.get('nodeType') == amdaModel.TimeTableNode.nodeType && record.isLeaf()) {
557   - var zmgr = myDesktopApp.desktop.getDesktopZIndexManager();
558   - var winActive = zmgr.getActive();
559   - var winId = winActive.getId();
560   - if (winId == 'explorer-win') {
561   - zmgr.eachTopDown(function(win) {
562   - var id = win.getId();
563   - if (id !== 'explorer-win') {
564   - winId = id;
565   - return false;
566   - }
567   - });
568   - }
569   - }
570   -
571   - if (record.get('nodeType') == 'remoteParam' && !record.isLeaf()
572   - && !record.get('isParameter')) {
573   - myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.interop.id, true, function (module) {
574   - module.createWindow(record.getBaseId());
575   - });
576   - }
577   -
578   - if (record.isLeaf() || record.data.isParameter)
579   - switch (record.get('nodeType'))
580   - {
581   - case 'myData' :
582   - case 'myDataParam' :
583   - case 'derivedParam' :
584   - case 'timeTable' :
585   - case 'sharedtimeTable' :
586   - case 'sharedcatalog' :
587   - case 'catalog' :
588   - case 'request' :
589   - case 'condition' :
590   - record.editLeaf();
591   - break;
592   - case 'localParam' :
593   - case 'remoteParam':
594   - case 'remoteSimuParam':
595   - record.createAlias(record);
596   - break;
597   - case 'bkgWorks' :
598   - if (!record.get('object')) {
599   - AmdaAction.getObject(record.get('id'), record.get('nodeType'), record.getObjectCallback, record);
600   - }
601   - else {
602   - if (record.get('status') == 'done') {
603   - var isInteractive = false;
604   - var isNewTab = true;
605   - record.editNode(isNewTab, isInteractive);
606   - }
607   - else {
608   - myDesktopApp.infoMsg('Job Status: ' + record.get('status'));
609   - }
610   - }
611   - break;
612   - }
613   - },
614   -
615   - beforeselect: function(view,node,index,options){
616   - // if there's at least one node already selected
617   - if(view.selected.length
618   - //AND (the node which is beeing selected has a different nodeType than the first selected node OR the first selected node isn't a leaf
619   - && ( node.get('nodeType')!== view.selected.items[0].get('nodeType') || !view.selected.items[0].isLeaf())
620   - // OR the node which is beeing selected has no nodeType OR it isn't a leaf OR
621   - || !node.get('nodeType') || !node.isLeaf()
622   - ){
623   - // clear old selection
624   - view.deselectAll();
625   - }
626   - },
627   -
628   - afterrender: function(comp){
629   - var view = comp.getView();
630   - view.tip = Ext.create('Ext.tip.ToolTip', {
631   - // The overall target element.
632   - target: view.el,
633   - // Each grid row causes its own seperate show and hide.
634   - delegate: view.itemSelector,
635   - dismissDelay : 0,
636   - // showDelay: 100,
637   - // anchor: 'left',
638   - // Moving within the row should not hide the tip.
639   - trackMouse: true,
640   - autoRender: true,
641   - listeners: {
642   - // Change content dynamically depending on which element triggered the show.
643   - beforeshow: function updateTipBody(tip) {
644   - if (view.getRecord(tip.triggerElement)) {
645   - var info = view.getRecord(tip.triggerElement).get('info');
646   - if (!info || info == '') {
647   - tip.addCls('hide');
648   - }
649   - else {
650   - tip.removeCls('hide');
651   - tip.update(info);
652   - }
653   - }
654   - }
655   - }
656   - });
657   - },
658   - // if remote base is empty - open interoperability module
659   - itemexpand: function(node) {
660   - if ( node.get('nodeType') == amdaModel.RemoteParamNode.nodeType
661   - && node.getDepth() == 3 && !node.hasChildNodes()) {
662   - node.addData();
663   - }
664   - },
665   - scope: this
666   - },
667   -
668   - hideHeaders: true,
669   - // must define a column with a field to enable editor
670   - columns: [{
671   - xtype : 'treetoolcolumn',
672   - text : 'Name',
673   - flex : 1,
674   - dataIndex: 'text',
675   - tool: 'info', // this references the "tools" object on the prototype
676   - toolHandler: function(view, cell, recordIndex, cellIndex, e) {
677   - var tooltype = e.target.getAttribute("tooltype");
678   - var record = view.store.getAt(recordIndex);
679   - switch (tooltype)
680   - {
681   - case 'info' :
682   - myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.info.id, true, function (module) {
683   - module.createWindow(record.get('help'), record.get('text'));
684   - });
685   - break;
686   - }
687   - },
688   - toolIsVisible : function(record) {
689   -
690   - switch (record.get('nodeType'))
691   - {
692   - case 'localParam' :
693   - case 'remoteParam' :
694   - case 'remoteSimuParam' :
695   -
696   - return record.get('help') != '';
697   - }
698   - return false;
699   - },
700   - field: {
701   - validFlag: false,
702   - validator : function(value) {
703   - // get explorerModule
704   - var explModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
705   - var explUI = explModule.getUiContent();
706   - var activeTreePanel = explUI.getActiveTab();
707   -
708   - var editedNode = activeTreePanel.getSelectionModel().selected.items[0];
709   - if (editedNode) {
710   - if (!editedNode.get('id') && value === amdaModel.AmdaNode.NEW_DIR_NAME){
711   - return false;
712   - } else {
713   - return this.validFlag;
714   - }
715   - } else {
716   - return true;
717   - }
718   - },
719   - listeners: {
720   - change : function( field, newValue, oldValue, eOpts )
721   - {
722   - var explModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
723   - var explUI = explModule.getUiContent();
724   - var activeTreePanel = explUI.getActiveTab();
725   -
726   - var editedNode = activeTreePanel.getSelectionModel().selected.items[0];
727   - if (editedNode) {
728   - editedNode.isValidName(newValue, function (res) {
729   - if (!res)
730   - {
731   - field.validFlag = 'Error during object validation';
732   - field.validate();
733   - return;
734   - }
735   - if (!res.valid)
736   - {
737   - if (res.error)
738   - {
739   - field.validFlag = res.error;
740   - field.validate();
741   - return;
742   - }
743   - else
744   - {
745   - field.validFlag = 'Invalid object name';
746   - field.validate();
747   - return;
748   - }
749   - }
750   -
751   - field.validFlag = true;
752   - field.validate();
753   - });
754   - }
755   - }
756   - },
757   - scope: this
758   - }
759   - }],
760   - //add our custom editor plugin
761   - plugins: [ new MyTreeEditor({
762   - pluginId: 'treeEditor',
763   - listeners: {
764   - 'canceledit' : function(editor, context) {
765   - if (editor && editor.startValue===amdaModel.AmdaNode.NEW_DIR_NAME) {
766   - context.record.remove(true);
767   - }
768   - }
769   - }
770   - })],
771   -
772   - setNodesVisibility : function(node,forceHide)
773   - {
774   - var isFiltered = node.get('filtered');
775   -
776   - for (var i = 0; i < node.childNodes.length; i++)
777   - this.setNodesVisibility(node.childNodes[i],forceHide || isFiltered);
778   -
779   - this.setNodeVisibility(node,!(forceHide || isFiltered));
780   - },
781   -
782   - setNodeVisibility : function(node,isVisible)
783   - {
784   - var record = store.getNodeById(node.internalId);
785   - var viewNode = Ext.fly(tree.getView().getNode(record));
786   - if (viewNode)
787   - {
788   - viewNode.setVisibilityMode(Ext.Element.DISPLAY);
789   - if (isVisible)
790   - {
791   - viewNode.show();
792   - this.applyDisableToNode(record);
793   - }
794   - else
795   - viewNode.hide();
796   - }
797   - },
798   -
799   - applyFilterToNode : function(node)
800   - {
801   - if (!node)
802   - return;
803   -
804   - var filter = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id).filter;
805   -
806   - switch (node.get('nodeType'))
807   - {
808   - case 'localParam' :
809   - if (!filter || !filter['param'])
810   - {
811   - //no filter applied
812   - node.set('filtered',false);
813   - return;
814   - }
815   - var pos = node.get('depth') - 3; //depth from local param root node
816   - if (pos < 0 || pos > 2)
817   - {
818   - node.set('filtered',false);
819   - return;
820   - }
821   - var isFiltered = true;
822   - for (var i = 0; i < filter['param'].length; i++)
823   - {
824   - s = filter['param'][i].split(';');
825   - if (node.get('id') == s[pos])
826   - {
827   - isFiltered = false;
828   - break;
829   - }
830   - }
831   - node.set('filtered',isFiltered);
832   - break;
833   -
834   - case 'remoteSimuParam' :
835   - if (!filter || !filter['simu'] )
836   - {
837   - //no filter applied
838   - node.set('filtered',false);
839   - return;
840   - }
841   - var pos = node.get('depth') - 3; //depth from remote param root node
842   -
843   - if (pos < 0 || pos > 5)
844   - {
845   - node.set('filtered',false);
846   - return;
847   - }
848   - var isFiltered = true;
849   -
850   - for (var i = 0; i < filter['simu'].length; i++)
851   - {
852   - s = filter['simu'][i].split(';');
853   -
854   - if (node.get('id') == s[pos])
855   - {
856   - isFiltered = false;
857   - break;
858   - }
859   - }
860   - node.set('filtered',isFiltered);
861   - break;
862   - /*case 'alias' :
863   - if (!this.localParamFilter.result || this.localParamFilter.id == "" ||
864   - !node.isLeaf())
865   - {
866   - //no filter applied
867   - node.set('filtered',false);
868   - return;
869   - }
870   - var crtParam = node.get('id');
871   - crtParam = crtParam.replace('alias_','');
872   - crtParam = crtParam.replace(/_/g,':');
873   - var isFiltered = true;
874   - for (var i = 0; i < this.localParamFilter.result.length; i++)
875   - {
876   - s = this.localParamFilter.result[i].split(';');
877   - console.log(s[2]);
878   - if (crtParam == s[2])
879   - {
880   - isFiltered = false;
881   - break;
882   - }
883   - }
884   - node.set('filtered',isFiltered);
885   - break;*/
886   - default :
887   - return;
888   - }
889   - },
890   -
891   - applyFilterToNodes : function(node)
892   - {
893   - node.eachChild(function (child){
894   - tree.applyFilterToNodes(child);
895   - });
896   - tree.applyFilterToNode(node);
897   - },
898   -
899   - applyDisableToNode : function(node)
900   - {
901   - var crtNode = node;
902   - var disable = false;
903   -
904   - do
905   - {
906   - if (crtNode.get('disable'))
907   - {
908   - disable = true;
909   - break;
910   - }
911   - crtNode = crtNode.parentNode;
912   - } while (crtNode);
913   -
914   -
915   - var viewNode = Ext.fly(tree.getView().getNode(node));
916   - if (disable)
917   - {
918   - node.set('disable',true);
919   - viewNode.setStyle('opacity',0.5);
920   - }
921   - }
922   - });
923   -
924   - tree.addEvents('edition');
925   -
926   - return tree;
927   - },
928   -
929   - updateFilter : function()
930   - {
931   - var filter = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id).filter;
932   -
933   - var keys = [];
934   - for (var f in filter) {
935   - if (hasOwnProperty.call(filter, f))
936   - keys.push(f);
937   - }
938   -
939   - var tree = this.query('#'+amdaUI.ExplorerUI.RESRC_TAB.TREE_ID)[0];
940   - tree.getView().refresh();
941   -
942   - for (var i = 0; i < keys.length; i++)
943   - {
944   - if (keys[i] == "_empty_")
945   - continue;
946   -
947   - switch (keys[i])
948   - {
949   - case 'param' :
950   - //apply filter to local datasets
951   - var localNode = tree.getRootNode().findChild('id','myLocalData-treeRootNode',true);
952   - tree.applyFilterToNodes(localNode);
953   - tree.setNodesVisibility(localNode,false);
954   - tree.applyDisableToNode(localNode);
955   -
956   - //apply filter to aliases
957   - var aliasNode = tree.getRootNode().findChild('id','alias-treeRootNode',true);
958   - tree.applyFilterToNodes(aliasNode);
959   - tree.setNodesVisibility(aliasNode,false);
960   - tree.applyDisableToNode(aliasNode);
961   - break;
962   -
963   - case 'simu' :
964   - //apply filter to simulation datasets (in remote data)
965   - var remoteNode = tree.getRootNode().findChild('id','myRemoteSimuData-treeRootNode',true);
966   - tree.applyFilterToNodes(remoteNode);
967   - tree.setNodesVisibility(remoteNode,false);
968   - tree.applyDisableToNode(remoteNode);
969   - break;
970   - }
971   - }
972   -
973   - this.dockedItems.getAt(1).items.items[0].select(filter['name']);
974   - }
  81 +
  82 + extend: 'Ext.tab.Panel',
  83 + alias: 'widget.panelExplorer',
  84 +
  85 + statics: {
  86 + RESRC_TAB: {
  87 + TREE_ID: 'resourcesTree',
  88 + TREE_TYPE: 'resources'
  89 + },
  90 + OPE_TAB: {
  91 + TREE_ID: 'operationsTree',
  92 + TREE_TYPE: 'operations'
  93 + },
  94 + JOB_TAB: {
  95 + TREE_ID: 'jobsTree',
  96 + TREE_TYPE: 'jobs'
  97 + },
  98 +
  99 + CAT_SUFFIX: '-treeBase',
  100 + ROOT_SUFFIX: '-treeRootNode',
  101 + SUB_ROOT_SUFFIX: 'RootNode',
  102 +
  103 + ITEM_KIND_BASE: 'base',
  104 + ITEM_KIND_ROOT: 'root',
  105 + ITEM_KIND_LEAF: 'leaf',
  106 + ITEM_KIND_DIRE: 'dire',
  107 + ITEM_KIND_PARA: 'para',
  108 + ITEM_KIND_MISS: 'miss'
  109 + },
  110 +
  111 + initComponent: function (config) {
  112 + var explorerModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id),
  113 + myConf;
  114 +
  115 + myConf = {
  116 + split: true,
  117 + width: '100%',
  118 + height: '100%',
  119 + autoScroll: true,
  120 + border: true,
  121 + header: false,
  122 + defaults: {
  123 + // Applied to each contained panel
  124 + containerScroll: true
  125 + },
  126 + stateful: true,
  127 + // StateId: 'tp1',
  128 + stateEvents: ['tabchange'],
  129 + getState: function () {
  130 + return {activeTab: this.items.findIndex('id', this.getActiveTab().id)};
  131 + },
  132 + applyState: function (s) {
  133 + this.setActiveTab(s.activeTab);
  134 + },
  135 + items: [
  136 + this.initTree(amdaUI.ExplorerUI.RESRC_TAB.TREE_TYPE),
  137 + this.initTree(amdaUI.ExplorerUI.OPE_TAB.TREE_TYPE),
  138 + this.initTree(amdaUI.ExplorerUI.JOB_TAB.TREE_TYPE)
  139 + ],
  140 + tbar: [
  141 + {
  142 + xtype: 'combo',
  143 + fieldLabel: 'Filter',
  144 + labelWidth: 25,
  145 + width: 140,
  146 + store: explorerModule.filtersStore,
  147 + queryMode: 'local',
  148 + displayField: 'name',
  149 + valueField: 'id',
  150 + listeners: {
  151 + scope: this,
  152 + select: function (combo, records) {
  153 + AmdaAction.setCrtFilterId({id: records[0].get('id')}, function (result, e) {
  154 + if (e.status) {
  155 + if (result && explorerModule) {
  156 + explorerModule.setCrtFilter();
  157 + } else {
  158 + Ext.Msg.show({
  159 + title: 'Filter',
  160 + msg: 'Cannot apply filter',
  161 + modal: true,
  162 + icon: Ext.Msg.ERROR,
  163 + buttons: Ext.Msg.OK
  164 + });
  165 + }
  166 + } else {
  167 + // FAILURE
  168 + Ext.Msg.show({
  169 + title: 'Error System',
  170 + msg: e.message,
  171 + icon: Ext.MessageBox.ERROR,
  172 + buttons: Ext.Msg.OK
  173 + });
  174 + }
  175 + }, this);
  176 + }
  177 + }
  178 + },
  179 + {
  180 + text: '',
  181 + iconCls: 'icon-parameters',
  182 + tooltip: {
  183 + text: 'Edit Filter',
  184 + align: 'bl-tl'
  185 + },
  186 + handler: function () {
  187 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.filters.id, true, function (module) {
  188 + module.createWindow();
  189 + });
  190 + }
  191 + },
  192 + {
  193 + text: '',
  194 + iconCls: 'icon-remover',
  195 + tooltip: {
  196 + text: 'Reset Filter',
  197 + align: 'bl-tl'
  198 + },
  199 + handler: function () {
  200 + explorerModule.resetFilter();
  201 + }
  202 + },
  203 + '-',
  204 + {
  205 + xtype: 'displayfield',
  206 + fieldLabel: 'SortBy',
  207 + width: 40
  208 + },
  209 + {
  210 + text: 'Name',
  211 + scope: this,
  212 + tooltip: {
  213 + text: 'Sort out AMDA DataBase Data by Mission Name',
  214 + align: 'bl-tl'
  215 + },
  216 + pressed: true,
  217 + enableToggle: true,
  218 + toggleGroup: 'sorting',
  219 + handler: function () {
  220 + var tree = Ext.getCmp(amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
  221 + tree.getStore().sort([
  222 + {
  223 + sorterFn: function (o1, o2) {
  224 + if (o1.get('nodeType') !== 'localParam') {
  225 + return;
  226 + }
  227 +
  228 + return o1.get('text').toUpperCase() < o2.get('text').toUpperCase() ? -1 : 1;
  229 + }
  230 + }
  231 + ]);
  232 + this.updateFilter();
  233 + }
  234 + },
  235 + {
  236 + text: 'Target',
  237 + scope: this,
  238 + tooltip: {
  239 + text: 'Sort out AMDA DataBase Data by Mission Main Target',
  240 + align: 'bl-tl'
  241 + },
  242 + enableToggle: true,
  243 + toggleGroup: 'sorting',
  244 + handler: function () {
  245 + var tree = Ext.getCmp(amdaUI.ExplorerUI.RESRC_TAB.TREE_ID);
  246 + tree.getStore().sort([{property: 'rank'}]);
  247 + this.updateFilter();
  248 + }
  249 + }
  250 + ]
  251 + };
  252 + Ext.apply(this, Ext.apply(arguments, myConf));
  253 + this.callParent(arguments);
  254 + },
  255 +
  256 + initTree: function (treeType) {
  257 + var menu, store, tree, treeId;
  258 + switch (treeType) {
  259 + case amdaUI.ExplorerUI.RESRC_TAB.TREE_TYPE:
  260 + treeId = amdaUI.ExplorerUI.RESRC_TAB.TREE_ID;
  261 + break;
  262 + case amdaUI.ExplorerUI.OPE_TAB.TREE_TYPE:
  263 + treeId = amdaUI.ExplorerUI.OPE_TAB.TREE_ID;
  264 + break;
  265 + case amdaUI.ExplorerUI.JOB_TAB.TREE_TYPE:
  266 + treeId = amdaUI.ExplorerUI.JOB_TAB.TREE_ID;
  267 + break;
  268 + default:
  269 + treeId = amdaUI.ExplorerUI.RESRC_TAB.TREE_ID;
  270 + break;
  271 + }
  272 +
  273 + store = Ext.create('Ext.data.TreeStore', {
  274 + root: {
  275 + expanded: true,
  276 + nodeType: treeType
  277 + },
  278 + model: 'amdaModel.AmdaNode',
  279 + sorters: [
  280 + {
  281 + direction: 'ASC',
  282 + sorterFn: function (o1, o2) {
  283 + if (o1.get('nodeType') !== 'localParam') {
  284 + return;
  285 + }
  286 +
  287 + return o1.get('text').toUpperCase() < o2.get('text').toUpperCase() ? -1 : 1;
  288 + }
  289 + }
  290 + ],
  291 + listeners: {
  292 + beforeload: function (_store, operation) {
  293 + _store.proxy.extraParams = {nodeType: operation.node.get('nodeType')};
  294 + }
  295 + }
  296 + });
  297 +
  298 + menu = new Ext.menu.Menu();
  299 +
  300 + tree = Ext.create('Ext.tree.Panel', {
  301 + id: treeId,
  302 + title: treeType,
  303 + store: store,
  304 + rootVisible: false,
  305 + animate: false,
  306 + hideHeaders: true,
  307 + selModel: Ext.create('Ext.selection.TreeModel', {
  308 + // IgnoreRightMouseSelection: true,
  309 + mode: 'MULTI'
  310 + }),
  311 + viewConfig: {
  312 + plugins: {
  313 + ptype: 'treeviewdragdrop',
  314 + enableDrag: true,
  315 + enableDrop: true,
  316 + // TODO - BRE - Wait a fix for drag&drop issue
  317 + ddGroup: 'explorerTree',
  318 + pluginId: 'ddplugin',
  319 +
  320 + isValidDropPoint: function (node, position, dragZone, e, data) {
  321 + if (!node || !data.item) {
  322 + return false;
  323 + }
  324 + var view = this.view,
  325 + targetNode = view.getRecord(node),
  326 + draggedRecords = data.records,
  327 + dataLength = draggedRecords.length,
  328 + ln = draggedRecords.length,
  329 + i, record;
  330 +
  331 + // No drop position, or dragged records: invalid drop point
  332 + if (!(targetNode && position && dataLength)) {
  333 + return false;
  334 + }
  335 + // If the targetNode is within the folder we are dragging
  336 + for (i = 0; i < ln; i++) {
  337 + record = draggedRecords[i];
  338 + if (record.isNode && record.contains(targetNode)) {
  339 + return false;
  340 + }
  341 + }
  342 + // Respect the allowDrop field on Tree nodes
  343 + if (position === 'append' && targetNode.get('allowDrop') === false) {
  344 + return false;
  345 + } else if (position != 'append' && targetNode.parentNode.get('allowDrop') === false) {
  346 + return false;
  347 + }
  348 + // If the target record is in the dragged dataset, then invalid drop
  349 + if (Ext.Array.contains(draggedRecords, targetNode)) {
  350 + return false;
  351 + }
  352 + //
  353 + if (dataLength > 1) {
  354 + return false;
  355 + }
  356 +
  357 + var draggedRecord = draggedRecords[0];
  358 + //
  359 + switch (targetNode.data.nodeType) {
  360 + case 'localParam':
  361 + case 'remoteParam':
  362 + case 'remoteSimuParam':
  363 + case 'myData':
  364 + return false;
  365 + default:
  366 + if (draggedRecord.data.id == targetNode.data.nodeType + '-treeRootNode') {
  367 + return false;
  368 + }
  369 + if (position == 'before' && targetNode.data.id == targetNode.data.nodeType + '-treeRootNode') {
  370 + return false;
  371 + }
  372 + return draggedRecord.data.nodeType == targetNode.data.nodeType;
  373 + }
  374 + return false;
  375 + },
  376 + onViewRender: function (view) {
  377 + var me = this;
  378 +
  379 + view.on('itemupdate', function (record) {
  380 + var forceHide = false,
  381 + crtRec = record.parentNode;
  382 +
  383 + while (crtRec && !forceHide) {
  384 + if (crtRec.get('filtered')) {
  385 + forceHide = crtRec.get('filtered');
  386 + }
  387 + crtRec = crtRec.parentNode;
  388 + }
  389 + tree.setNodesVisibility(record, forceHide);
  390 + tree.applyDisableToNode(record);
  391 + });
  392 +
  393 + view.on('itemadd', function (records) {
  394 + Ext.each(records, function (rec) {
  395 + tree.applyFilterToNode(rec);
  396 + tree.applyDisableToNode(rec);
  397 + });
  398 + });
  399 +
  400 + view.on('afteritemexpand', function (record) {
  401 + var crtRec, forceHide;
  402 + forceHide = false;
  403 + crtRec = record.parentNode;
  404 + while (crtRec && !forceHide) {
  405 + if (crtRec.get('filtered')) {
  406 + forceHide = crtRec.get('filtered');
  407 + }
  408 + crtRec = crtRec.parentNode;
  409 +
  410 + }
  411 + tree.setNodesVisibility(record, forceHide);
  412 + tree.applyDisableToNode(record);
  413 + });
  414 +
  415 + if (me.enableDrag) {
  416 + me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
  417 + view: view,
  418 + ddGroup: me.dragGroup || me.ddGroup,
  419 + dragText: me.dragText,
  420 + repairHighlightColor: me.nodeHighlightColor,
  421 + repairHighlight: me.nodeHighlightOnRepair
  422 + });
  423 + }
  424 +
  425 + if (me.enableDrop) {
  426 + me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
  427 + view: view,
  428 + ddGroup: me.dropGroup || me.ddGroup,
  429 + allowContainerDrops: me.allowContainerDrops,
  430 + appendOnly: me.appendOnly,
  431 + allowParentInserts: me.allowParentInserts,
  432 + expandDelay: me.expandDelay,
  433 + dropHighlightColor: me.nodeHighlightColor,
  434 + dropHighlight: me.nodeHighlightOnDrop,
  435 + isValidDropPoint: me.isValidDropPoint
  436 + });
  437 + }
  438 + }
  439 + },
  440 + listeners: {
  441 + beforedrop: function (node, data, overModel, dropPosition) {
  442 + var parentId;
  443 + switch (dropPosition) {
  444 + case 'append':
  445 + if (overModel.isLeaf()) {
  446 + parentId = overModel.parentNode.get('id');
  447 + } else {
  448 + parentId = overModel.get('id');
  449 + }
  450 +
  451 + if (!overModel.isExpanded() && overModel.isExpandable()) {
  452 + myDesktopApp.warningMsg('Please open the folder before node adding');
  453 + return false;
  454 + }
  455 + break;
  456 + case 'before':
  457 + case 'after':
  458 + parentId = overModel.parentNode.get('id');
  459 + break;
  460 + default:
  461 + break;
  462 + }
  463 +
  464 + Ext.each(data.records, function (rec) {
  465 + rec.renameDD(parentId, function (result) {
  466 + if (result) {
  467 + if (!result.id) {
  468 + Ext.Msg.show({
  469 + title: 'Drop is impossible',
  470 + msg: result.error,
  471 + buttons: Ext.Msg.OK,
  472 + icon: Ext.MessageBox.WARNING
  473 + });
  474 +
  475 + return false;
  476 + }
  477 + } else {
  478 + Ext.Msg.show({
  479 + title: 'Drop is impossible',
  480 + msg: 'Cannot connect to the server',
  481 + buttons: Ext.Msg.OK,
  482 + icon: Ext.MessageBox.WARNING
  483 + });
  484 +
  485 + return false;
  486 + }
  487 +
  488 + return true;
  489 + });
  490 + });
  491 + }
  492 + }
  493 + },
  494 + listeners: {
  495 + itemmouseenter: function (view, record, item) {
  496 + Ext.get(item).down('td > div').setStyle('cursor', record.get('isParameter') ? 'pointer' : 'crosshair');
  497 + },
  498 +
  499 + itemcontextmenu: function (view, rec, item, index, e) {
  500 + var menuItems;
  501 +
  502 + // Add record to selection model
  503 + view.ownerCt.getSelectionModel().select(rec);
  504 +
  505 + // Block other events
  506 + e.stopEvent();
  507 +
  508 + // Clear menu items
  509 + menu.removeAll();
  510 +
  511 + // If it's a single selection
  512 + if (view.ownerCt.getSelectionModel().selected.length === 1) {
  513 + // Get items menu corresponding to right clicked record
  514 + menuItems = rec.getContextMenuItems(this);
  515 +
  516 + } else if (view.ownerCt.getSelectionModel().selected.length > 1) {
  517 + // Get items menu corresponding to right clicked record
  518 + menuItems = rec.getContextMenuMultiItems(this);
  519 + }
  520 + // If there's at least one item menu
  521 + if (menuItems && menuItems.length) {
  522 + // Add the items
  523 + menu.add(menuItems);
  524 +
  525 + // Add listener on right clicked record
  526 + var onRecordClick = function (menu, item, e) {
  527 + if (this.myGetOwnerTree().getSelectionModel().isSelected(this)) {
  528 + // Dispatch click event to the record
  529 + this.onMenuItemClick(menu, item, e);
  530 + }
  531 + // Remove old click listener
  532 + menu.removeListener('click', onRecordClick, this);
  533 + };
  534 +
  535 + menu.addListener('click', onRecordClick, rec);
  536 + // Then show menu
  537 + menu.showAt(e.getXY());
  538 + }
  539 + },
  540 +
  541 + itemdblclick: function (view, record, item, index, event) {
  542 + var zmgr, winId;
  543 +
  544 + event.stopEvent();
  545 + // First check if it is for SAVE-START-STOP plugin...
  546 + if (Ext.PluginManager.getCount() > 0 &&
  547 + record.get('nodeType') == amdaModel.TimeTableNode.nodeType && record.isLeaf()) {
  548 + zmgr = myDesktopApp.desktop.getDesktopZIndexManager();
  549 + winId = zmgr.getActive().getId();
  550 + if (winId == 'explorer-win') {
  551 + zmgr.eachTopDown(function (win) {
  552 + var id = win.getId();
  553 + if (id !== 'explorer-win') {
  554 + winId = id;
  555 + return false;
  556 + }
  557 + });
  558 + }
  559 + }
  560 +
  561 + if (record.get('nodeType') == 'remoteParam' && !record.isLeaf() &&
  562 + !record.get('isParameter')) {
  563 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.interop.id, true, function (module) {
  564 + module.createWindow(record.getBaseId());
  565 + });
  566 + }
  567 +
  568 + if (record.isLeaf() || record.data.isParameter) {
  569 + switch (record.get('nodeType')) {
  570 + case 'myData':
  571 + case 'myDataParam':
  572 + case 'derivedParam':
  573 + case 'timeTable':
  574 + case 'sharedtimeTable':
  575 + case 'sharedcatalog':
  576 + case 'catalog':
  577 + case 'request':
  578 + case 'condition':
  579 + record.editLeaf();
  580 + break;
  581 + case 'localParam':
  582 + case 'remoteParam':
  583 + case 'remoteSimuParam':
  584 + record.createAlias(record);
  585 + break;
  586 + case 'bkgWorks':
  587 + if (!record.get('object')) {
  588 + AmdaAction.getObject(record.get('id'), record.get('nodeType'), record.getObjectCallback, record);
  589 + } else if (record.get('status') == 'done') {
  590 + // IsInteractive = true, isNewTab = false
  591 + record.editNode(true, false);
  592 + } else {
  593 + myDesktopApp.infoMsg('Job Status: ' + record.get('status'));
  594 + }
  595 + break;
  596 + default:
  597 + break;
  598 + }
  599 + }
  600 + },
  601 +
  602 + beforeselect: function (view, node) {
  603 + // If there's at least one node already selected
  604 + if (view.selected.length &&
  605 + // AND (the node which is beeing selected has a different nodeType than the first selected node OR the first selected node isn't a leaf
  606 + (node.get('nodeType') !== view.selected.items[0].get('nodeType') || !view.selected.items[0].isLeaf()) ||
  607 + // OR the node which is beeing selected has no nodeType OR it isn't a leaf OR
  608 + !node.get('nodeType') || !node.isLeaf()
  609 + ) {
  610 + // Clear old selection
  611 + view.deselectAll();
  612 + }
  613 + },
  614 +
  615 + afterrender: function (comp) {
  616 + var view = comp.getView();
  617 + view.tip = Ext.create('Ext.tip.ToolTip', {
  618 + // The overall target element.
  619 + target: view.el,
  620 + // Each grid row causes its own seperate show and hide.
  621 + delegate: view.itemSelector,
  622 + dismissDelay: 0,
  623 +
  624 + /*
  625 + * ShowDelay: 100,
  626 + * anchor: 'left',
  627 + * Moving within the row should not hide the tip.
  628 + */
  629 + trackMouse: true,
  630 + autoRender: true,
  631 + listeners: {
  632 + // Change content dynamically depending on which element triggered the show.
  633 + beforeshow: function updateTipBody (tip) {
  634 + var info;
  635 + if (view.getRecord(tip.triggerElement)) {
  636 + info = view.getRecord(tip.triggerElement).get('info');
  637 + if (!info || info == '') {
  638 + tip.addCls('hide');
  639 + } else {
  640 + tip.removeCls('hide');
  641 + tip.update(info);
  642 + }
  643 + }
  644 + }
  645 + }
  646 + });
  647 + },
  648 + // If remote base is empty - open interoperability module
  649 + itemexpand: function (node) {
  650 + if (node.get('nodeType') == amdaModel.RemoteParamNode.nodeType &&
  651 + node.getDepth() == 3 && !node.hasChildNodes()) {
  652 + node.addData();
  653 + }
  654 + },
  655 + scope: this
  656 + },
  657 +
  658 + // Must define a column with a field to enable editor
  659 + columns: [
  660 + {
  661 + xtype: 'treetoolcolumn',
  662 + text: 'Name',
  663 + flex: 1,
  664 + dataIndex: 'text',
  665 + // This references the "tools" object on the prototype
  666 + tool: 'info',
  667 + toolHandler: function (view, cell, recordIndex, cellIndex, e) {
  668 + var record = view.store.getAt(recordIndex);
  669 + switch (e.target.getAttribute('tooltype')) {
  670 + case 'info':
  671 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.info.id, true, function (module) {
  672 + module.createWindow(record.get('help'), record.get('text'));
  673 + });
  674 + break;
  675 + default:
  676 + break;
  677 + }
  678 + },
  679 + toolIsVisible: function (record) {
  680 +
  681 + switch (record.get('nodeType')) {
  682 + case 'localParam':
  683 + case 'remoteParam':
  684 + case 'remoteSimuParam':
  685 + return record.get('help') != '';
  686 + default:
  687 + break;
  688 + }
  689 + return false;
  690 + },
  691 + field: {
  692 + validFlag: true,
  693 + listeners: {
  694 + change: function (field, newValue) {
  695 + var editedNode, explModule;
  696 +
  697 + explModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id);
  698 + editedNode = explModule.getUiContent().getActiveTab().getSelectionModel().selected.items[0];
  699 +
  700 + if (editedNode) {
  701 + editedNode.isValidName(newValue, function (res) {
  702 + var validFlag = true;
  703 + if (newValue === amdaModel.AmdaNode.NEW_DIR_NAME) {
  704 + validFlag = 'Field is not modified';
  705 + } else if (!res) {
  706 + validFlag = 'Error during object validation';
  707 + } else if (!res.valid) {
  708 + if (res.error) {
  709 + validFlag = res.error;
  710 + } else {
  711 + validFlag = 'Invalid object name';
  712 + }
  713 + }
  714 + if (validFlag !== true) {
  715 + field.markInvalid(validFlag);
  716 + }
  717 + field.validFlag = validFlag;
  718 + });
  719 + }
  720 + }
  721 + },
  722 + scope: this
  723 + }
  724 + }
  725 + ],
  726 + // Add our custom editor plugin
  727 + plugins: [
  728 + new MyTreeEditor({
  729 + pluginId: 'treeEditor',
  730 + listeners: {
  731 + beforeedit: function (editor, e) {
  732 + e.column.field.fireEvent('change', e.column.field, e.value, '');
  733 + },
  734 + validateedit: function (editor, e) {
  735 + if (e.column.field.validFlag !== true) {
  736 + if (e.record.deleteOnFailure) {
  737 + e.record.remove(true);
  738 + } else {
  739 + return false;
  740 + }
  741 + }
  742 + return true;
  743 + }
  744 + },
  745 + scope: this
  746 + })
  747 + ],
  748 +
  749 + setNodesVisibility: function (node, forceHide) {
  750 + var isFiltered = node.get('filtered');
  751 +
  752 + for (var i = 0; i < node.childNodes.length; i++) {
  753 + this.setNodesVisibility(node.childNodes[i], forceHide || isFiltered);
  754 + }
  755 +
  756 + this.setNodeVisibility(node, !(forceHide || isFiltered));
  757 + },
  758 +
  759 + setNodeVisibility: function (node, isVisible) {
  760 + var record = store.getNodeById(node.internalId);
  761 + var viewNode = Ext.fly(tree.getView().getNode(record));
  762 + if (viewNode) {
  763 + viewNode.setVisibilityMode(Ext.Element.DISPLAY);
  764 + if (isVisible) {
  765 + viewNode.show();
  766 + this.applyDisableToNode(record);
  767 + } else {
  768 + viewNode.hide();
  769 + }
  770 + }
  771 + },
  772 +
  773 + applyFilterToNode: function (node) {
  774 + var filter, isFiltered, pos;
  775 +
  776 + if (!node) {
  777 + return;
  778 + }
  779 +
  780 + filter = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id).filter;
  781 +
  782 + switch (node.get('nodeType')) {
  783 + case 'localParam':
  784 + if (!filter || !filter.param) {
  785 + // No filter applied
  786 + node.set('filtered', false);
  787 + return;
  788 + }
  789 + // Depth from local param root node
  790 + pos = node.get('depth') - 3;
  791 + if (pos < 0 || pos > 2) {
  792 + node.set('filtered', false);
  793 + return;
  794 + }
  795 + isFiltered = true;
  796 + for (var i = 0; i < filter.param.length; i++) {
  797 + if (node.get('id') == filter.param[i].split(';')[pos]) {
  798 + isFiltered = false;
  799 + break;
  800 + }
  801 + }
  802 + node.set('filtered', isFiltered);
  803 + break;
  804 +
  805 + case 'remoteSimuParam':
  806 + if (!filter || !filter.simu) {
  807 + // No filter applied
  808 + node.set('filtered', false);
  809 + return;
  810 + }
  811 + // Depth from remote param root node
  812 + pos = node.get('depth') - 3;
  813 + if (pos < 0 || pos > 5) {
  814 + node.set('filtered', false);
  815 + return;
  816 + }
  817 + isFiltered = true;
  818 + for (var i = 0; i < filter.simu.length; i++) {
  819 + if (node.get('id') == filter.simu[i].split(';')[pos]) {
  820 + isFiltered = false;
  821 + break;
  822 + }
  823 + }
  824 + node.set('filtered', isFiltered);
  825 + break;
  826 +
  827 + /*
  828 + * Case 'alias':
  829 + * if (!this.localParamFilter.result || this.localParamFilter.id == "" || !node.isLeaf()) {
  830 + * // No filter applied
  831 + * node.set('filtered',false);
  832 + * return;
  833 + * }
  834 + * var crtParam = node.get('id');
  835 + * crtParam = crtParam.replace('alias_','');
  836 + * crtParam = crtParam.replace(/_/g,':');
  837 + * var isFiltered = true;
  838 + * for (var i = 0; i < this.localParamFilter.result.length; i++) {
  839 + * s = this.localParamFilter.result[i].split(';');
  840 + * console.log(s[2]);
  841 + * if (crtParam == s[2]) {
  842 + * isFiltered = false;
  843 + * break;
  844 + * }
  845 + * }
  846 + * node.set('filtered',isFiltered);
  847 + * break;
  848 + */
  849 + default:
  850 +
  851 + }
  852 + },
  853 +
  854 + applyFilterToNodes: function (node) {
  855 + node.eachChild(function (child) {
  856 + tree.applyFilterToNodes(child);
  857 + });
  858 + tree.applyFilterToNode(node);
  859 + },
  860 +
  861 + applyDisableToNode: function (node) {
  862 + var crtNode, disable, viewNode;
  863 +
  864 + crtNode = node;
  865 + disable = false;
  866 +
  867 + do {
  868 + if (crtNode.get('disable')) {
  869 + disable = true;
  870 + break;
  871 + }
  872 + crtNode = crtNode.parentNode;
  873 + } while (crtNode);
  874 +
  875 +
  876 + viewNode = Ext.fly(tree.getView().getNode(node));
  877 + if (disable) {
  878 + node.set('disable', true);
  879 + viewNode.setStyle('opacity', 0.5);
  880 + }
  881 + }
  882 + });
  883 +
  884 + tree.addEvents('edition');
  885 +
  886 + return tree;
  887 + },
  888 +
  889 + updateFilter: function () {
  890 + var aliasNode, filter, keys, localNode, remoteNode, tree;
  891 +
  892 + filter = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.explorer.id).filter;
  893 +
  894 + keys = [];
  895 + for (var f in filter) {
  896 + if (hasOwnProperty.call(filter, f)) {
  897 + keys.push(f);
  898 + }
  899 + }
  900 +
  901 + tree = this.query('#' + amdaUI.ExplorerUI.RESRC_TAB.TREE_ID)[0];
  902 + tree.getView().refresh();
  903 +
  904 + for (var i = 0; i < keys.length; i++) {
  905 + if (keys[i] == '_empty_') {
  906 + continue;
  907 + }
  908 +
  909 + switch (keys[i]) {
  910 + case 'param':
  911 + // Apply filter to local datasets
  912 + localNode = tree.getRootNode().findChild('id', 'myLocalData-treeRootNode', true);
  913 + tree.applyFilterToNodes(localNode);
  914 + tree.setNodesVisibility(localNode, false);
  915 + tree.applyDisableToNode(localNode);
  916 +
  917 + // Apply filter to aliases
  918 + aliasNode = tree.getRootNode().findChild('id', 'alias-treeRootNode', true);
  919 + tree.applyFilterToNodes(aliasNode);
  920 + tree.setNodesVisibility(aliasNode, false);
  921 + tree.applyDisableToNode(aliasNode);
  922 + break;
  923 +
  924 + case 'simu':
  925 + // Apply filter to simulation datasets (in remote data)
  926 + remoteNode = tree.getRootNode().findChild('id', 'myRemoteSimuData-treeRootNode', true);
  927 + tree.applyFilterToNodes(remoteNode);
  928 + tree.setNodesVisibility(remoteNode, false);
  929 + tree.applyDisableToNode(remoteNode);
  930 + break;
  931 + default:
  932 + break;
  933 + }
  934 + }
  935 +
  936 + this.dockedItems.getAt(1).items.items[0].select(filter.name);
  937 + }
975 938 });
976 939  
977 940 // MyTreeEditor
978   -Ext.define( 'MyTreeEditor', {
979   - extend: 'Ext.grid.plugin.CellEditing',
980   - alias: 'editing.treeeditor',
981   -
982   - // initialization method of plugin
983   - init: function(cmp) {
984   - var me = this;
985   - me.hostCmp = cmp;
986   - // on parent event
987   - me.hostCmp.on({
988   - // on edition event
989   - edition : {
990   - delay: 50,
991   - fn : function(view, record, item, index, e){
992   - view.getHeaderAtIndex(0).field.validFlag = 'Not modified';
993   - // call the start edition method
994   - me.startEdit(record, view.getHeaderAtIndex(0));
995   - },
996   - scope: me
997   - }
998   - });
999   - me.callParent(arguments);
1000   - },
1001   -
1002   - /**
1003   - * Cancel any active editing.
1004   - */
1005   - cancelEdit: function() {
1006   - var me = this,
1007   - activeEd = me.getActiveEditor(),
1008   - viewEl = me.grid.getView().getEl(me.getActiveColumn());
1009   -
1010   - me.setActiveEditor(null);
1011   - me.setActiveColumn(null);
1012   - me.setActiveRecord(null);
1013   - if (activeEd) {
1014   - activeEd.cancelEdit();
1015   - viewEl.focus();
1016   - this.fireEvent('canceledit', activeEd, me.context);
1017   - }
1018   - },
1019   -
1020   - /**
1021   - * overwrite the initEditTriggers to disable edition on click/dblclick
1022   - * and to add custom
1023   - */
1024   - initEditTriggers: function()
1025   - {
1026   - var me = this,
1027   - view = me.view;
1028   -
1029   - me.on({
1030   - edit: function(editor,event){
1031   - // if there is a modification
1032   - if (event.originalValue !== event.value) {
1033   - // delegate rename action on model
1034   - event.record.rename(event.value,function(result){
1035   - // if a result has been returned : success
1036   - if(result) {
1037   - // delegate commit action to delete modification flag
1038   - event.record.commit();
1039   - var rec = event.record.data;
1040   - // in case of directory
1041   - if (!rec.leaf){
1042   - // set folder's ID returned by server
1043   - rec.id = result.id;
1044   - }
1045   - } else { // in case of transaction error
1046   - // reset originalValue
1047   - event.record.value = event.originalValue;
1048   - event.record.get('text') = event.originalValue;
1049   - event.record.commit();
1050   - }
1051   - });
1052   - }
1053   - }
1054   - });
1055   -
1056   - // enable Enter key and Esc Key
1057   - view.on('render', function() {
1058   - me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
1059   - enter: me.onEnterKey,
1060   - esc: me.onEscKey,
1061   - scope: me
1062   - });
1063   - }, me, { single: true });
1064   - },
1065   - //overwrite the getEditing context because we do not need the rowId
1066   - getEditingContext: function(record, columnHeader) {
1067   - var me = this,
1068   - grid = me.grid,
1069   - store = grid.store,
1070   - colIdx,
1071   - view = grid.getView(),
1072   - value;
1073   -
1074   - // getting colIdx and real columnHeader
1075   - if (Ext.isNumber(columnHeader)) {
1076   - colIdx = columnHeader;
1077   - columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
1078   - } else {
1079   - colIdx = columnHeader.getIndex();
1080   - }
1081   - // getting current value
1082   - value = record.get(columnHeader.dataIndex);
1083   -
1084   - // return editing context
1085   - return {
1086   - grid: grid,
1087   - record: record,
1088   - field: columnHeader.dataIndex,
1089   - value: value,
1090   - column: columnHeader,
1091   - colIdx: colIdx,
1092   - view: columnHeader.getOwnerHeaderCt().view
1093   - };
1094   - }
  941 +Ext.define('MyTreeEditor', {
  942 + extend: 'Ext.grid.plugin.CellEditing',
  943 + alias: 'editing.treeeditor',
  944 +
  945 + // Initialization method of plugin
  946 + init: function (cmp) {
  947 + var me = this;
  948 + me.hostCmp = cmp;
  949 + // On parent event
  950 + me.hostCmp.on({
  951 + // On edition event
  952 + edition: {
  953 + delay: 50,
  954 + fn: function (view, record, item, index, e) {
  955 +
  956 + /*
  957 + * View.getHeaderAtIndex(0).field.validFlag = 'Not modified';
  958 + * call the start edition method
  959 + */
  960 + me.startEdit(record, view.getHeaderAtIndex(0));
  961 + },
  962 + scope: me
  963 + }
  964 + });
  965 + me.callParent(arguments);
  966 + },
  967 +
  968 + /**
  969 + * Cancel any active editing.
  970 + * @returns {void}
  971 + */
  972 + cancelEdit: function () {
  973 + var me = this,
  974 + activeEd = me.getActiveEditor(),
  975 + viewEl = me.grid.getView().getEl(me.getActiveColumn());
  976 +
  977 + me.setActiveEditor(null);
  978 + me.setActiveColumn(null);
  979 + me.setActiveRecord(null);
  980 + if (activeEd) {
  981 + activeEd.cancelEdit();
  982 + viewEl.focus();
  983 + this.fireEvent('canceledit', activeEd, me.context);
  984 + }
  985 + },
  986 +
  987 + /**
  988 + * Overwrite the initEditTriggers to disable edition on click/dblclick and to add custom
  989 + * @returns {void}
  990 + */
  991 + initEditTriggers: function () {
  992 + var me = this,
  993 + view = me.view;
  994 +
  995 + me.on({
  996 + edit: function (editor, event) {
  997 + // If there is a modification
  998 + if (event.originalValue !== event.value) {
  999 + // Delegate rename action on model
  1000 + event.record.rename(event.value, function (result) {
  1001 + // If a result has been returned : success
  1002 + if (result) {
  1003 + // Delegate commit action to delete modification flag
  1004 + event.record.commit();
  1005 + var rec = event.record.data;
  1006 + // In case of directory
  1007 + if (!rec.leaf) {
  1008 + // Set folder's ID returned by server
  1009 + rec.id = result.id;
  1010 + }
  1011 + } else {
  1012 + // In case of transaction error, reset originalValue
  1013 + event.record.value = event.originalValue;
  1014 + event.record.set('text', event.originalValue);
  1015 + event.record.commit();
  1016 + }
  1017 + });
  1018 + }
  1019 + }
  1020 + });
  1021 +
  1022 + // Enable Enter key and Esc Key
  1023 + view.on('render', function () {
  1024 + me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
  1025 + enter: me.onEnterKey,
  1026 + esc: me.onEscKey,
  1027 + scope: me
  1028 + });
  1029 + }, me, {single: true});
  1030 + },
  1031 + // Overwrite the getEditing context because we do not need the rowId
  1032 + getEditingContext: function (record, columnHeader) {
  1033 + var me = this,
  1034 + grid = me.grid,
  1035 + colIdx,
  1036 + value;
  1037 +
  1038 + // Getting colIdx and real columnHeader
  1039 + if (Ext.isNumber(columnHeader)) {
  1040 + colIdx = columnHeader;
  1041 + columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
  1042 + } else {
  1043 + colIdx = columnHeader.getIndex();
  1044 + }
  1045 + // Getting current value
  1046 + value = record.get(columnHeader.dataIndex);
  1047 +
  1048 + // Return editing context
  1049 + return {
  1050 + grid: grid,
  1051 + record: record,
  1052 + field: columnHeader.dataIndex,
  1053 + value: value,
  1054 + column: columnHeader,
  1055 + colIdx: colIdx,
  1056 + view: columnHeader.getOwnerHeaderCt().view
  1057 + };
  1058 + }
1095 1059 });
... ...