Commit 8be9a1a8495581d93c9bb5596df16db0d2901791

Authored by Benjamin Renard
1 parent d7edb1cf

Fix catalog visu

js/app/views/VisuUI.js
... ... @@ -9,32 +9,32 @@
9 9  
10 10 Ext.define('amdaUI.VisuUI', {
11 11 extend: 'Ext.container.Container',
12   - alias: 'widget.panelVisu',
13   -
  12 + alias: 'widget.panelVisu',
  13 +
14 14 constructor: function(config) {
15 15 this.init(config);
16   - this.callParent(arguments);
  16 + this.callParent(arguments);
17 17 if (this.object) this.reformObject();
18 18 },
19   -
20   - setObject : function (obj) {
  19 +
  20 + setObject : function (obj) {
21 21 this.object = obj;
22 22 this.reformObject();
23 23 },
24   -
25   - updateObject : function () {
  24 +
  25 + updateObject : function () {
26 26 return true;
27 27 },
28   -
  28 +
29 29 reformObject : function () {
30   - this.fromPlugin = this.object.get('fromPlugin');
31   -
  30 + this.fromPlugin = this.object.get('fromPlugin');
  31 +
32 32 if (this.fromPlugin) {
33 33 if (this.object.get('folderId') == '')
34 34 this.object.set('id','cacheCat');
35 35 else
36 36 this.object.set('id',this.object.get('folderId'));
37   -
  37 +
38 38 this.object.set('objName',this.object.get('objName'));
39 39 }
40 40 else {
... ... @@ -45,7 +45,7 @@ Ext.define('amdaUI.VisuUI', {
45 45 if (this.object.get('id') != '')
46 46 this.loadObject();
47 47 },
48   -
  48 +
49 49 reset : function() {
50 50 //reset all fieldsets except the first one (name, intervals)
51 51 var form = this.items.items[0].items.items[0];
... ... @@ -55,22 +55,22 @@ Ext.define('amdaUI.VisuUI', {
55 55 field.reset();
56 56 });
57 57 }
58   - this.resetChart();
  58 + this.resetChart();
59 59 },
60   -
  60 +
61 61 /**
62 62 * load object catalog into this view
63 63 */
64 64 loadObject : function()
65   - {
  65 + {
66 66 var me = this;
67   -
68   - var onAfterInit = function(result, e)
  67 +
  68 + var onAfterInit = function(result, e)
69 69 {
70   - if (!result) {
  70 + if (!result) {
71 71 myDesktopApp.errorMsg(e.message);
72 72 Ext.defer(function(){Ext.Msg.toFront()},10);
73   -
  73 +
74 74 return;
75 75 }
76 76 else if (!result.success)
... ... @@ -81,61 +81,61 @@ Ext.define('amdaUI.VisuUI', {
81 81 myDesktopApp.errorMsg('Unknown error during catalog cache initialisation');
82 82  
83 83 Ext.defer(function(){Ext.Msg.toFront()},10);
84   -
  84 +
85 85 return;
86 86 }
87   -
  87 +
88 88 var fields = [], i = 0, index;
89 89  
90 90 if (!result.cache) {
91 91 me.object.set('name', result.name);
92 92 me.object.set('nbIntervals', result.totalCount);
93   -
  93 +
94 94 var params = [];
95 95 Ext.Array.each(result.parameters, function(item, index) {
96   - params[index] = item;
  96 + params[index] = item;
97 97 }, this);
98   -
99   - me.object.set('parameters', params);
  98 +
  99 + me.object.set('parameters', params);
100 100 }
101 101 else {
102 102 fields[0] = Ext.create('Ext.data.Field', { name : 'start', id: 'start', text : 'start: date' });
103 103 fields[1] = Ext.create('Ext.data.Field', { name : 'stop', id: 'stop', text : 'stop: date' });
104 104 i = 2;
105   - }
106   -
  105 + }
  106 +
107 107 Ext.Array.each(me.object.get('parameters'), function(obj) {
108 108 index = 'param'+i.toString();
109 109 if (obj.type == 2) {
110 110 fields[i] = Ext.create('Ext.data.Field', { name : index, id: index, text : obj.name + ': string' });
111   -
  111 +
112 112 }
113 113 else if (obj.type == 1){
114 114 fields[i] = Ext.create('Ext.data.Field', { name : index, id: index, text : obj.name + ': date' });
115 115 }
116 116 else {
117 117 fields[i] = Ext.create('Ext.data.Field', { name : index, id: index, text : obj.name,
118   - convert: function(value, record) {
  118 + convert: function(value, record) {
119 119 return parseFloat(value);
120 120 }
121 121 });
122 122 }
123 123 i++;
124 124 });
125   -
126   - if (me.chartStore) {
  125 +
  126 + if (me.chartStore) {
127 127 me.parList.removeAll();
128 128 me.reset();
129 129 me.chartStore = null;
130 130 }
131   -
  131 +
132 132 me.parList.add(fields);
133   -
  133 +
134 134 me.chartStore = Ext.create('Ext.data.Store', {
135   - fields : fields,
  135 + fields : fields,
136 136 // autoDestroy: false,
137 137 // pageSize : 200,
138   - // buffered : true,
  138 + // buffered : true,
139 139 // purgePageCount: 0,
140 140 // remoteSort: true,
141 141 autoload: false,
... ... @@ -146,7 +146,7 @@ Ext.define('amdaUI.VisuUI', {
146 146 read : AmdaAction.readIntervalsForChart
147 147 },
148 148 // remplir automatiquement tt, sharedtt , catalog, shared catalog
149   - extraParams : {'typeTT' : 'catalog', 'id' : me.object.get('id'),
  149 + extraParams : {'typeTT' : 'catalog', 'id' : me.object.get('id'),
150 150 'name' : me.object.get('objName'), 'fromPlugin' : me.fromPlugin},
151 151 reader:
152 152 {
... ... @@ -157,7 +157,7 @@ Ext.define('amdaUI.VisuUI', {
157 157 },
158 158 listeners: {
159 159 scope : me,
160   - load: function(store,records) {
  160 + load: function(store,records) {
161 161 //TODO enable plot button
162 162 // me.object.set('nbIntervals',me.chartStore.getTotalCount());
163 163  
... ... @@ -167,25 +167,25 @@ Ext.define('amdaUI.VisuUI', {
167 167 }
168 168 }
169 169 });
170   -
171   - me.chartStore.load();
  170 +
  171 + me.chartStore.load();
172 172 }
173 173  
174   - AmdaAction.initForChart(this.object.get('id'), this.object.get('objName'), this.fromPlugin, 'catalog', onAfterInit);
  174 + AmdaAction.initForChart(this.object.get('id'), this.object.get('folderId'), this.object.get('objName'), this.fromPlugin, 'catalog', onAfterInit);
175 175 },
176   -
177   -
  176 +
  177 +
178 178 /**
179   - * Check if changes were made before closing window
  179 + * Check if changes were made before closing window
180 180 * @return true if changes
181   - */
182   - fclose : function()
183   - {
  181 + */
  182 + fclose : function()
  183 + {
184 184 return false;
185 185 },
186 186  
187 187 resetChart : function () {
188   -
  188 +
189 189 var emptyAxesConfig = [{
190 190 type: 'Numeric',
191 191 position: 'bottom',
... ... @@ -199,32 +199,32 @@ Ext.define('amdaUI.VisuUI', {
199 199 title: 'Y axis',
200 200 grid: true
201 201 }];
202   -
  202 +
203 203 this.chartConfig.series[0].xField = '';
204 204 this.chartConfig.series[0].yField = '';
205   -
  205 +
206 206 this.chartConfig.theme = 'Blue';
207   -
208   - this.chartConfig.axes = emptyAxesConfig;
209   -
210   - var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
  207 +
  208 + this.chartConfig.axes = emptyAxesConfig;
  209 +
  210 + var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
211 211 this.replaceChart(chart);
212   -
  212 +
213 213 },
214   -
  214 +
215 215 plotChart : function () {
216   -
217   - this.chartConfig.store = this.chartStore;
218   -
219   - var xTitle = this.items.items[0].items.items[0].items.items[1].items.items[2].getValue();
220   - var yTitle = this.items.items[0].items.items[0].items.items[2].items.items[2].getValue();
221   -
  216 +
  217 + this.chartConfig.store = this.chartStore;
  218 +
  219 + var xTitle = this.items.items[0].items.items[0].items.items[1].items.items[2].getValue();
  220 + var yTitle = this.items.items[0].items.items[0].items.items[2].items.items[2].getValue();
  221 +
222 222 if (xTitle) this.chartConfig.axes[0].title = xTitle;
223 223 if (xTitle) this.chartConfig.axes[1].title = yTitle;
224   -
  224 +
225 225 // axis modifs
226 226 if (this.comboXrange.getValue() == 'manual') {
227   - var minX = this.comboXrange.next().next().getValue();
  227 + var minX = this.comboXrange.next().next().getValue();
228 228 var maxX = this.comboXrange.next().next().next().next().getValue();
229 229 this.chartConfig.axes[0].minimum = minX;
230 230 this.chartConfig.axes[0].maximum = maxX ;
... ... @@ -239,39 +239,39 @@ Ext.define('amdaUI.VisuUI', {
239 239 // if (minX && maxX) {
240 240 this.chartConfig.axes[1].minimum = minX;
241 241 this.chartConfig.axes[1].maximum = maxX;
242   - // }
  242 + // }
243 243 } else {
244 244 // unset min/max in config
245 245 delete this.chartConfig.axes[1].minimum;
246 246 delete this.chartConfig.axes[1].maximum;
247 247 }
248   -
249   - var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
250   -
251   - this.replaceChart(chart);
  248 +
  249 + var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
  250 +
  251 + this.replaceChart(chart);
252 252 },
253   -
254   - replaceChart: function(chart) {
  253 +
  254 + replaceChart: function(chart) {
255 255 var chartPanel = this.items.items[0].items.items[1];
256 256 var oldChart = chartPanel.down('chart');
257 257 oldIndex = chartPanel.items.indexOf(oldChart);
258 258 chartPanel.remove(oldChart);
259   - chartPanel.insert(oldIndex, chart);
  259 + chartPanel.insert(oldIndex, chart);
260 260 },
261   -
262   - init : function (config)
263   - {
  261 +
  262 + init : function (config)
  263 + {
264 264 var store = Ext.create('Ext.data.Store', {
265   - fields : [],
  265 + fields : [],
266 266 autoload : false
267 267 });
268   -
  268 +
269 269 var rangeStore = Ext.create('Ext.data.Store', {
270   - fields : [],
  270 + fields : [],
271 271 autoload : false
272 272 });
273   -
274   - this.chartConfig = {
  273 +
  274 + this.chartConfig = {
275 275 width: 500,
276 276 height: 500,
277 277 animate: false,
... ... @@ -316,19 +316,19 @@ Ext.define('amdaUI.VisuUI', {
316 316 height: 20,
317 317 hideDelay: 100, //200 ms
318 318 mouseOffset: [0,0], //[15,18]
319   - renderer: function(storeItem, item) {
  319 + renderer: function(storeItem, item) {
320 320 this.setTitle(storeItem.index + 1);
321 321 }
322 322 }
323 323 }]
324 324 }
325   -
  325 +
326 326 this.parList = Ext.create('Ext.data.Store', {
327   - fields : [ 'text', 'id']
  327 + fields : [ 'text', 'id']
328 328 });
329   -
330   - var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
331   -
  329 +
  330 + var chart = Ext.create('Ext.chart.Chart', this.chartConfig);
  331 +
332 332 this.parCombo = Ext.create('Ext.form.ComboBox', {
333 333 emptyText: 'select parameter',
334 334 editable: false,
... ... @@ -336,21 +336,21 @@ Ext.define('amdaUI.VisuUI', {
336 336 queryMode: 'local',
337 337 displayField: 'text',
338 338 valueField: 'id',
339   - // tpl:'<tpl for="."><div ext:qtip="{qtip}" class="x-combo-list-item">{Name}</div></tpl>',
  339 + // tpl:'<tpl for="."><div ext:qtip="{qtip}" class="x-combo-list-item">{Name}</div></tpl>',
340 340 listeners : {
341 341 scope : this,
342 342 change : function(combo, newValue, oldValue) {
343 343 if (newValue) {
344 344 this.chartConfig.axes[0].fields = [newValue];
345 345 var rec = combo.findRecordByValue(newValue);
346   -
347   - this.chartConfig.axes[0].title = rec.get('text');
  346 +
  347 + this.chartConfig.axes[0].title = rec.get('text');
348 348 this.chartConfig.series[0].xField = newValue;
349 349 }
350 350 }
351 351 }
352 352 });
353   -
  353 +
354 354 this.parCombo1 = Ext.create('Ext.form.ComboBox', {
355 355 emptyText: 'select parameter',
356 356 editable: false,
... ... @@ -361,16 +361,16 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
361 361 listeners : {
362 362 scope : this,
363 363 change : function(combo, newValue, oldValue) {
364   - if (newValue) {
  364 + if (newValue) {
365 365 this.chartConfig.axes[1].fields = [newValue];
366 366 var rec = combo.findRecordByValue(newValue);
367   - this.chartConfig.axes[1].title = rec.get('text');
  367 + this.chartConfig.axes[1].title = rec.get('text');
368 368 this.chartConfig.series[0].yField = newValue;
369 369 }
370 370 }
371 371 }
372   - });
373   -
  372 + });
  373 +
374 374 var plotTypeCombo = Ext.create('Ext.form.ComboBox', {
375 375 emptyText: 'select plot type',
376 376 editable: false,
... ... @@ -380,12 +380,12 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
380 380 value: 'scatter',
381 381 listeners : {
382 382 scope : this,
383   - change : function(combo, newValue, oldValue) {
  383 + change : function(combo, newValue, oldValue) {
384 384 this.chartConfig.series[0].type = newValue;
385 385 }
386 386 }
387   - });
388   -
  387 + });
  388 +
389 389 var plotThemeCombo = Ext.create('Ext.form.ComboBox', {
390 390 emptyText: 'select theme',
391 391 editable: false,
... ... @@ -396,12 +396,12 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
396 396 value: 'Blue',
397 397 listeners : {
398 398 scope : this,
399   - change : function(combo, newValue, oldValue) {
  399 + change : function(combo, newValue, oldValue) {
400 400 this.chartConfig.theme = newValue;
401 401 }
402 402 }
403 403 });
404   -
  404 +
405 405 var comboRangeConfig = {
406 406 // fieldLabel:'X Range',
407 407 name:'scaling',
... ... @@ -413,48 +413,48 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
413 413 width: 80,
414 414 listeners : {
415 415 scope : this,
416   - change : function(combo, newValue, oldValue) {
  416 + change : function(combo, newValue, oldValue) {
417 417 var minValue = combo.next().next();
418 418 var maxValue = minValue.next().next();
419 419 var disabled = newValue == "auto";
420 420 minValue.reset();
421 421 maxValue.reset();
422   - minValue.setDisabled(disabled);
423   - maxValue.setDisabled(disabled);
  422 + minValue.setDisabled(disabled);
  423 + maxValue.setDisabled(disabled);
424 424 }
425 425 }
426 426 };
427   -
  427 +
428 428 this.comboXrange = Ext.create('Ext.form.ComboBox', comboRangeConfig);
429 429 this.comboYrange = Ext.create('Ext.form.ComboBox', comboRangeConfig);
430   -
431   - var formPanel = Ext.create('Ext.form.Panel', {
  430 +
  431 + var formPanel = Ext.create('Ext.form.Panel', {
432 432 region : 'center',
433   - layout: 'hbox',
  433 + layout: 'hbox',
434 434 bodyStyle: {background : '#dfe8f6'},
435 435 defaults: { border : false, align: 'stretch', padding: '3'},
436 436 fieldDefaults: { labelWidth: 80, labelAlign : 'top' },
437   - items: [ {
  437 + items: [ {
438 438 xtype: 'form',
439 439 flex : 1,
440   - bodyStyle: {background : '#dfe8f6'},
441   - items: [{
442   - xtype : 'fieldset',
  440 + bodyStyle: {background : '#dfe8f6'},
  441 + items: [{
  442 + xtype : 'fieldset',
443 443 items : [{
444 444 xtype: 'fieldcontainer',
445   - layout: 'hbox',
  445 + layout: 'hbox',
446 446 items: [
447   - { xtype:'textfield', fieldLabel: 'Catalog Name', name: 'name', readOnly: true},
448   - { xtype: 'splitter' },
  447 + { xtype:'textfield', fieldLabel: 'Catalog Name', name: 'name', readOnly: true},
  448 + { xtype: 'splitter' },
449 449 { xtype:'textfield', fieldLabel: 'Intervals', name: 'nbIntervals', readOnly: true}
450   - ]
  450 + ]
451 451 }]
452   - },{
  452 + },{
453 453 xtype : 'fieldset',
454 454 title : 'X axis',
455   - items : [
456   - this.parCombo,
457   - {
  455 + items : [
  456 + this.parCombo,
  457 + {
458 458 xtype : 'fieldcontainer',
459 459 layout: 'hbox',
460 460 items: [{
... ... @@ -462,8 +462,8 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
462 462 title: 'X Range',
463 463 border: false,
464 464 layout: 'hbox',
465   - items: [
466   - this.comboXrange,
  465 + items: [
  466 + this.comboXrange,
467 467 {
468 468 xtype: 'splitter'
469 469 }, {
... ... @@ -484,12 +484,12 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
484 484 // { xtype : 'checkbox', boxLabel: 'Logarithmic'},
485 485 { xtype: 'textfield', fieldLabel: 'X title', name: 'xtitle'}
486 486 ]
487   - },{
  487 + },{
488 488 xtype : 'fieldset',
489 489 title : 'Y axis',
490 490 items : [
491   - this.parCombo1,
492   - {
  491 + this.parCombo1,
  492 + {
493 493 xtype : 'fieldcontainer',
494 494 layout: 'hbox',
495 495 items: [{
... ... @@ -497,8 +497,8 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
497 497 title: 'Y Range',
498 498 border: false,
499 499 layout: 'hbox',
500   - items: [
501   - this.comboYrange,
  500 + items: [
  501 + this.comboYrange,
502 502 {
503 503 xtype: 'splitter'
504 504 }, {
... ... @@ -514,20 +514,20 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
514 514 width: 50,
515 515 disabled: true
516 516 }]
517   - }]
  517 + }]
518 518 },
519 519 // { xtype : 'checkbox', boxLabel: 'Logarithmic',
520 520 // listeners: {
521 521 // scope: this,
522 522 // change : function( check, newValue, oldValue) {
523   -//
  523 +//
524 524 // }
525 525 // }
526 526 // },
527 527 { xtype: 'textfield', fieldLabel: 'Y title', name: 'ytitle'}
528 528 ]
529 529 },
530   - {
  530 + {
531 531 xtype : 'fieldset',
532 532 title : 'Plotting Options',
533 533 items : [
... ... @@ -536,26 +536,26 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
536 536 ]
537 537 }
538 538 ],
539   - fbar:[{
  539 + fbar:[{
540 540 type: 'button',
541 541 text: 'Plot',
542 542 scope : this,
543 543 handler: this.plotChart
544   -
545   - },{
  544 +
  545 + },{
546 546 type: 'button',
547 547 text: 'Reset',
548 548 scope : this,
549 549 handler: this.reset
550   -
  550 +
551 551 }]
552 552 }, {
553   - xtype: 'form',
  553 + xtype: 'form',
554 554 // padding: '3',
555 555 flex: 2,
556 556 items : [ chart ],
557 557 fbar:[
558   - {
  558 + {
559 559 type: 'button',
560 560 text: 'Save Chart',
561 561 scope: this,
... ... @@ -568,16 +568,16 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
568 568 });
569 569 }
570 570 }]
571   - }
572   - ]
573   - });
574   -
  571 + }
  572 + ]
  573 + });
  574 +
575 575 var myConf = {
576 576 layout: 'border',
577   - items: [
578   - formPanel,
  577 + items: [
  578 + formPanel,
579 579 {
580   - xtype: 'panel',
  580 + xtype: 'panel',
581 581 region: 'south',
582 582 title: 'Information',
583 583 collapsible: true,
... ... @@ -589,11 +589,11 @@ Ext.define(&#39;amdaUI.VisuUI&#39;, {
589 589 loader: {
590 590 autoLoad: true,
591 591 url: helpDir+'visuHOWTO'
592   - }
  592 + }
593 593 }
594   - ]
  594 + ]
595 595 };
596   -
597   - Ext.apply (this, Ext.apply(arguments, myConf));
598   - }
599   -});
  596 +
  597 + Ext.apply (this, Ext.apply(arguments, myConf));
  598 + }
  599 +});
... ...
php/classes/AmdaAction.php
... ... @@ -1126,14 +1126,14 @@ class AmdaAction
1126 1126 }
1127 1127  
1128 1128  
1129   - public function initForChart($id, $name, $isTmpObject, $type)
  1129 + public function initForChart($id, $folderId, $name, $isTmpObject, $type)
1130 1130 {
1131 1131 if ($isTmpObject && $type == 'catalog' && $id == 'cacheCat')
1132 1132 return array('success' => true, 'cache' => $id);
1133 1133  
1134 1134 if ($type == 'catalog' || $type == 'sharedcatalog') $objMgr = new CatalogMgr();
1135 1135  
1136   - return $objMgr->initForChart($id, $name, $isTmpObject, $type);
  1136 + return $objMgr->initForChart($id, $folderId, $name, $isTmpObject, $type);
1137 1137 }
1138 1138  
1139 1139 public function initObjectCacheFromTmpObject($folderId, $name, $isCatalog = false)
... ...
php/classes/CatalogMgr.php
... ... @@ -101,9 +101,21 @@ class CatalogMgr extends TimeTableMgr
101 101  
102 102 }
103 103  
104   - public function initForChart($id, $name, $isTmpObject, $type)
  104 + public function initForChart($id, $folderId, $name, $isTmpObject, $type)
105 105 {
106   - $intervals_res = $this->getCatalogParamDescription($id, $name, $isTmpObject, $type);
  106 + if ($isTmpObject)
  107 + $options = array(
  108 + 'name' => $name,
  109 + 'folder' => empty($folderId) ? USERTEMPDIR : USERWORKINGDIR.$folderId,
  110 + 'type' => $type,
  111 + );
  112 + else
  113 + $options = array(
  114 + 'id' => $id,
  115 + 'type' => $type,
  116 + );
  117 +
  118 + $intervals_res = $this->getCatalogParamDescription($options);
107 119  
108 120 if (!$intervals_res['success'])
109 121 return $intervals_res;
... ... @@ -145,6 +157,7 @@ class CatalogMgr extends TimeTableMgr
145 157 if (!$intervals_res['success'])
146 158 return $intervals_res;
147 159  
  160 +
148 161 $newIntervals = array();
149 162  
150 163 foreach ($intervals_res['intervals'] as $interval)
... ... @@ -192,7 +205,7 @@ class CatalogMgr extends TimeTableMgr
192 205  
193 206 //load intervals from Catalog id
194 207 if (!file_exists($path))
195   - return array('success' => false, 'message' => "Cannot find Catalog file ".$path);
  208 + return array('success' => false, 'message' => "Cannot find Catalog file");
196 209  
197 210 if (!$this->objectDom->load($path))
198 211 return array('success' => false, 'message' => "Cannot load Catalog file");
... ...
php/config.php
... ... @@ -157,7 +157,7 @@ $API = array(
157 157 'saveTTCacheIntervalsInTT'=>array('len'=>1),
158 158 'initObjectCache'=>array ('len'=>2),
159 159 'initObjectCacheFromObject'=>array('len'=>2),
160   - 'initForChart'=>array('len'=>4),
  160 + 'initForChart'=>array('len'=>5),
161 161 'initObjectCacheFromTmpObject'=>array('len'=>3),
162 162 'initObjectCacheFromUploadedFile'=>array('len'=>3),
163 163 'initObjectCacheFromCatalog'=>array('len'=>2),
... ...