Commit e022e5b53138ede006657f293774c908d0442967

Authored by Benjamin Renard
1 parent ab7c3c63

Filter parameter columns of a catalog (#7048)

js/app/views/CatalogUI.js
... ... @@ -12,8 +12,13 @@ Ext.define('amdaUI.CatalogUI', {
12 12 alias: 'widget.panelCatalog',
13 13  
14 14 requires: [
  15 + 'Ext.ux.grid.menu.RangeMenu',
  16 + 'Ext.ux.grid.FiltersFeature',
  17 + 'Ext.ux.grid.filter.DateFilter',
  18 + 'Ext.ux.grid.filter.NumericFilter',
  19 + 'Ext.ux.grid.filter.StringFilter',
15 20 'Ext.grid.plugin.BufferedRenderer',
16   - 'amdaUI.StatisticalPlug'
  21 + 'amdaUI.StatisticalPlug'
17 22 ],
18 23  
19 24 isCatalog : true,
... ... @@ -178,6 +183,13 @@ Ext.define('amdaUI.CatalogUI', {
178 183  
179 184 if (me.toReconfigure)
180 185 {
  186 + // clear filters
  187 + if (me.TTGrid.filters) {
  188 + me.TTGrid.getStore().clearFilter(true);
  189 + me.TTGrid.filters.clearFilters();
  190 + me.TTGrid.filters.destroy();
  191 + }
  192 +
181 193 var fieldsConfig = [
182 194 {
183 195 name : 'start',
... ... @@ -277,7 +289,8 @@ Ext.define('amdaUI.CatalogUI', {
277 289 allowBlank:false,
278 290 hideTrigger: true,
279 291 format : 'Y-m-d\\TH:i:s'
280   - }
  292 + },
  293 + filter: { type: 'date', dateFormat: 'Y-m-d' }
281 294 },
282 295 {
283 296 xtype: 'datecolumn',
... ... @@ -292,7 +305,8 @@ Ext.define('amdaUI.CatalogUI', {
292 305 allowBlank:false,
293 306 hideTrigger: true,
294 307 format : 'Y-m-d\\TH:i:s'
295   - }
  308 + },
  309 + filter: { type: 'date', dateFormat: 'Y-m-d' }
296 310 },
297 311 {
298 312 xtype: 'gridcolumn',
... ... @@ -310,7 +324,8 @@ Ext.define('amdaUI.CatalogUI', {
310 324 beforeshow : function(){
311 325 updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'1');
312 326 }
313   - }
  327 + },
  328 + filter: { type: 'numeric'}
314 329 },
315 330 {
316 331 xtype: 'gridcolumn',
... ... @@ -328,7 +343,8 @@ Ext.define('amdaUI.CatalogUI', {
328 343 beforeshow : function(){
329 344 updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'2');
330 345 }
331   - }
  346 + },
  347 + filter: { type: 'numeric'}
332 348 },
333 349 {
334 350 xtype: 'gridcolumn',
... ... @@ -346,11 +362,12 @@ Ext.define('amdaUI.CatalogUI', {
346 362 beforeshow : function(){
347 363 updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'3');
348 364 }
349   - }
  365 + },
  366 + filter: { type: 'numeric'}
350 367 }
351 368 ];
352 369  
353   - Ext.Array.each(result.parameters, function(obj, index) {
  370 + Ext.Array.each(result.parameters, function(obj, index) {
354 371 var field = {
355 372 name: obj.id
356 373 };
... ... @@ -361,6 +378,17 @@ Ext.define('amdaUI.CatalogUI', {
361 378 menuDisabled: false
362 379 };
363 380 switch (obj.type) {
  381 + case 0: //double
  382 + field = Ext.apply({}, field, {
  383 + type: 'string'
  384 + });
  385 + column = Ext.apply({}, column, {
  386 + xtype: 'gridcolumn',
  387 + width : 50. * parseInt(obj.size),
  388 + editor: 'textfield',
  389 + filter: { type: 'numeric'}
  390 + });
  391 + break;
364 392 case 1: //dateTime
365 393 field = Ext.apply({}, field, {
366 394 type : 'date',
... ... @@ -382,9 +410,32 @@ Ext.define('amdaUI.CatalogUI', {
382 410 allowBlank:false,
383 411 hideTrigger: true,
384 412 format : 'Y-m-d\\TH:i:s'
385   - }
  413 + },
  414 + filter: { type: 'date', dateFormat: 'Y-m-d' }
386 415 });
387 416 break;
  417 + case 2: //string
  418 + field = Ext.apply({}, field, {
  419 + type: 'string'
  420 + });
  421 + column = Ext.apply({}, column, {
  422 + xtype: 'gridcolumn',
  423 + width : 50. * parseInt(obj.size),
  424 + editor: 'textfield',
  425 + filter: { type: 'string'}
  426 + });
  427 + break;
  428 + case 3: //int
  429 + field = Ext.apply({}, field, {
  430 + type: 'string'
  431 + });
  432 + column = Ext.apply({}, column, {
  433 + xtype: 'gridcolumn',
  434 + width : 50. * parseInt(obj.size),
  435 + editor: 'textfield',
  436 + filter: { type: 'numeric'}
  437 + });
  438 + break;
388 439 default:
389 440 field = Ext.apply({}, field, {
390 441 type: 'string'
... ... @@ -392,7 +443,8 @@ Ext.define('amdaUI.CatalogUI', {
392 443 column = Ext.apply({}, column, {
393 444 xtype: 'gridcolumn',
394 445 width : 50. * parseInt(obj.size),
395   - editor: 'textfield'
  446 + editor: 'textfield',
  447 + filter: { type: 'string'}
396 448 });
397 449 }
398 450 fieldsConfig.push(field);
... ... @@ -432,6 +484,9 @@ Ext.define('amdaUI.CatalogUI', {
432 484 });
433 485  
434 486 me.TTGrid.reconfigure(store, columnsConfig);
  487 + if (me.TTGrid.filters) {
  488 + me.TTGrid.filters.bindStore(store);
  489 + }
435 490 }
436 491 me.TTGrid.getSelectionModel().deselectAll();
437 492 //
... ... @@ -697,8 +752,18 @@ Ext.define('amdaUI.CatalogUI', {
697 752 }
698 753 });
699 754  
  755 + var filters = {
  756 + ftype: 'filters',
  757 + encode: true, // json encode the filter query
  758 + local: false,
  759 + filters: [
  760 +
  761 + ]
  762 + };
  763 +
700 764 this.TTGrid = Ext.create('Ext.grid.Panel', {
701 765 height: 530,
  766 + features: [filters],
702 767 columns: [ ],
703 768 frame: true,
704 769 columnLines: true,
... ... @@ -754,7 +819,15 @@ Ext.define('amdaUI.CatalogUI', {
754 819 }, this);
755 820 }
756 821 }
757   - }]
  822 + },'->',
  823 + {
  824 + text: 'Clear Filters',
  825 + scope: this,
  826 + handler: function () {
  827 + this.TTGrid.getStore().clearFilter(true);
  828 + this.TTGrid.filters.clearFilters();
  829 + }
  830 + }]
758 831 }]
759 832 });
760 833  
... ...
php/classes/CatalogCacheFilterObject.php 0 โ†’ 100644
... ... @@ -0,0 +1,285 @@
  1 +<?php
  2 +
  3 +class CatalogCacheFilterPartObject extends TimeTableCacheFilterPartObject
  4 +{
  5 + public static $TYPE_PARAMETER = 6;
  6 +
  7 + private $paramId = "";
  8 +
  9 + public function getParamId() {
  10 + return $this->paramId;
  11 + }
  12 +
  13 + public function isSame($part) {
  14 + $same = parent::isSame($part);
  15 + if ($this->type != self::$TYPE_PARAMETER) {
  16 + return $same;
  17 + }
  18 + return $same && ($this->paramId == $part->getParamId());
  19 + }
  20 +
  21 + public function toFiltered($interval) {
  22 + if ($this->type != self::$TYPE_PARAMETER) {
  23 + return parent::toFiltered($interval);
  24 + }
  25 +
  26 + $params = $interval->getParams();
  27 +
  28 + // Retrieve data type
  29 + $data_type = -1;
  30 + foreach ($this->cacheObject->getParametersInfo() as $parameter) {
  31 + if ($parameter['id'] == $this->paramId) {
  32 + $data_type = $parameter['type'];
  33 + break;
  34 + }
  35 + }
  36 +
  37 + if ($data_type < 0) {
  38 + return FALSE;
  39 + }
  40 + else if (!isset($params[$this->paramId])) {
  41 + return FALSE;
  42 + }
  43 +
  44 + switch ($parameter['type']) {
  45 + case 0: //double
  46 + {
  47 + $param_value = floatval($params[$this->paramId]);
  48 + switch ($this->op) {
  49 + case self::$OPERATION_LT :
  50 + return ($param_value < $this->value);
  51 + case self::$OPERATION_GT :
  52 + return ($param_value > $this->value);
  53 + case self::$OPERATION_EQ :
  54 + return ($param_value != $this->value);
  55 + default :
  56 + return FALSE;
  57 + }
  58 + break;
  59 + }
  60 + case 1: //date (timestamp)
  61 + {
  62 + $param_value = intval($params[$this->paramId]);
  63 + switch ($this->op) {
  64 + case self::$OPERATION_LT :
  65 + return ($param_value < $this->value);
  66 + case self::$OPERATION_GT :
  67 + return ($param_value > $this->value);
  68 + case self::$OPERATION_EQ :
  69 + return (!(($param_value >= $this->value) && ($param_value <= $this->value+86400)));
  70 + default :
  71 + return FALSE;
  72 + }
  73 + break;
  74 + }
  75 + case 2: //string
  76 + $param_value = $params[$this->paramId];
  77 + if (empty($this->value))
  78 + return FALSE;
  79 + if (empty($param_value))
  80 + return TRUE;
  81 + return (strpos(strtolower($param_value), strtolower($this->value)) === FALSE);
  82 + case 3: //int
  83 + {
  84 + $param_value = intval($params[$this->paramId]);
  85 + switch ($this->op) {
  86 + case self::$OPERATION_LT :
  87 + return ($param_value < $this->value);
  88 + case self::$OPERATION_GT :
  89 + return ($param_value > $this->value);
  90 + case self::$OPERATION_EQ :
  91 + return ($param_value != $this->value);
  92 + default :
  93 + return FALSE;
  94 + }
  95 + break;
  96 + }
  97 + default:
  98 + return FALSE;
  99 + }
  100 +
  101 + return FALSE;
  102 + }
  103 +
  104 + public function loadFromObject($part_obj) {
  105 + parent::loadFromObject($part_obj);
  106 + if ($this->type == self::$TYPE_UNKNOWN) {
  107 + //Check if it's a catalog parameter
  108 + foreach ($this->cacheObject->getParametersInfo() as $parameter) {
  109 + if ($parameter['id'] == $part_obj->field) {
  110 + $this->type = self::$TYPE_PARAMETER;
  111 + $this->paramId = $parameter['id'];
  112 +
  113 + switch ($parameter['type']) {
  114 + case 0: //double
  115 + $this->value = floatval($part_obj->value);
  116 + break;
  117 + case 1: //date (timestamp)
  118 + $this->value = TimeUtils::iso2stamp($part_obj->value);
  119 + break;
  120 + case 2: //string
  121 + $this->value = $part_obj->value;
  122 + break;
  123 + case 3: //int
  124 + $this->value = intval($part_obj->value);
  125 + break;
  126 + default:
  127 + $this->value = $part_obj->value;
  128 + }
  129 +
  130 + break;
  131 + }
  132 + }
  133 + }
  134 + }
  135 +
  136 + public function writeBin($handle) {
  137 + fwrite($handle,pack('L2',$this->type,$this->op));
  138 + if ($this->type == self::$TYPE_PARAMETER) {
  139 + //Param Id length
  140 + fwrite($handle,pack('L',strlen($this->paramId)));
  141 +
  142 + //Param Id
  143 + for ($i = 0; $i < strlen($this->paramId); ++$i)
  144 + fwrite($handle,pack('C',ord($this->paramId[$i])));
  145 +
  146 + // Retrieve data type
  147 + $data_type = -1;
  148 + foreach ($this->cacheObject->getParametersInfo() as $parameter) {
  149 + if ($parameter['id'] == $this->paramId) {
  150 + $data_type = $parameter['type'];
  151 + break;
  152 + }
  153 + }
  154 +
  155 + switch ($data_type) {
  156 + case 0: //double
  157 + fwrite($handle,pack('f',floatval($this->value)));
  158 + break;
  159 + case 1: //date (timestamp)
  160 + fwrite($handle,pack('L',intval($this->value)));
  161 + break;
  162 + case 2: //string
  163 + fwrite($handle,pack('L',strlen($this->value)));
  164 + for ($i = 0; $i < strlen($this->value); ++$i)
  165 + fwrite($handle,pack('C',ord($this->value[$i])));
  166 + break;
  167 + case 3: //int
  168 + fwrite($handle,pack('L',intval($this->value)));
  169 + break;
  170 + default:
  171 + fwrite($handle,pack('L',strlen($this->value)));
  172 + for ($i = 0; $i < strlen($this->value); ++$i)
  173 + fwrite($handle,pack('C',ord($this->value[$i])));
  174 + }
  175 + }
  176 + else {
  177 + fwrite($handle,pack('f',$this->value));
  178 + }
  179 + }
  180 +
  181 + public function loadBin($handle) {
  182 + $res = unpack('L2data',fread($handle,4*2));
  183 + $this->type = $res['data1'];
  184 + $this->op = $res['data2'];
  185 +
  186 + if ($this->type == self::$TYPE_PARAMETER) {
  187 + //Param Id length
  188 + if (!$res = unpack('Lidlength',fread($handle,4)))
  189 + return false;
  190 + $idlength = $res['idlength'];
  191 +
  192 + //Param Id
  193 + $this->paramId = "";
  194 + for ($j = 0; $j < $idlength; ++$j)
  195 + {
  196 + if (!$res = unpack('Cid',fread($handle,1)))
  197 + return false;
  198 + $this->paramId .= chr($res['id']);
  199 + }
  200 +
  201 + // Retrieve data type
  202 + $data_type = -1;
  203 + foreach ($this->cacheObject->getParametersInfo() as $parameter) {
  204 + if ($parameter['id'] == $this->paramId) {
  205 + $data_type = $parameter['type'];
  206 + break;
  207 + }
  208 + }
  209 +
  210 + switch ($data_type) {
  211 + case 0: //double
  212 + $res = unpack('fvalue',fread($handle,4));
  213 + $this->value = $res['value'];
  214 + break;
  215 + case 1: //date (timestamp)
  216 + $res = unpack('Lvalue',fread($handle,4));
  217 + $this->value = $res['value'];
  218 + break;
  219 + case 2: //string
  220 + $res = unpack('Llength',fread($handle,4));
  221 + $length = $res['length'];
  222 + $this->value = "";
  223 + for ($j = 0; $j < $length; ++$j)
  224 + {
  225 + if (!$res = unpack('Cvalue',fread($handle,1)))
  226 + return false;
  227 + $this->value .= chr($res['value']);
  228 + }
  229 + break;
  230 + case 3: //int
  231 + $res = unpack('Lvalue',fread($handle,4));
  232 + $this->value = $res['value'];
  233 + break;
  234 + default:
  235 + $res = unpack('Llength',fread($handle,4));
  236 + $length = $res['length'];
  237 + $this->value = "";
  238 + for ($j = 0; $j < $length; ++$j)
  239 + {
  240 + if (!$res = unpack('Cvalue',fread($handle,1)))
  241 + return false;
  242 + $this->value .= chr($res['value']);
  243 + }
  244 + break;
  245 + }
  246 + }
  247 + else {
  248 + $res = unpack('fvalue',fread($handle,4));
  249 + $this->value = $res['value'];
  250 + }
  251 + }
  252 +
  253 + public function dump() {
  254 + if ($this->type == self::$TYPE_PARAMETER) {
  255 + echo " => ".get_class($this)." : type = parameter, id = ".$this->paramId;
  256 + echo ", operation = ";
  257 + switch ($this->op)
  258 + {
  259 + case self::$OPERATION_LT :
  260 + echo "lt";
  261 + break;
  262 + case self::$OPERATION_GT :
  263 + echo "gt";
  264 + break;
  265 + case self::$OPERATION_EQ :
  266 + echo "eq";
  267 + break;
  268 + default:
  269 + echo "unknown";
  270 + }
  271 + echo ", value = ".$this->value.PHP_EOL;
  272 + return;
  273 + }
  274 + parent::dump();
  275 + }
  276 +}
  277 +
  278 +class CatalogCacheFilterObject extends TimeTableCacheFilterObject
  279 +{
  280 + protected function createNewPart() {
  281 + return new CatalogCacheFilterPartObject($this->cacheObject);
  282 + }
  283 +}
  284 +
  285 + ?>
... ...
php/classes/CatalogCacheIntervalObject.php
... ... @@ -104,7 +104,7 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
104 104 if (!$res = unpack('Lval',fread($handle,4))) {
105 105 break;
106 106 }
107   - $val = $res['val'];
  107 + $val = TimeUtils::stamp2iso($res['val']);
108 108 break;
109 109 case 2: //string
110 110 if (!$res = unpack('Llength',fread($handle,4))) {
... ...
php/classes/CatalogCacheObject.php
... ... @@ -7,9 +7,8 @@ class CatalogCacheObject extends TimeTableCacheObject
7 7 public function reset() {
8 8 parent::reset();
9 9 $this->parameters = array();
10   - //ToDo - Init sort and filters for Catalog
11   - /*unset($this->filter);
12   - $this->filter = new TimeTableCacheFilterObject();;*/
  10 + unset($this->filter);
  11 + $this->filter = new CatalogCacheFilterObject($this);
13 12 unset($this->sort);
14 13 $this->sort = new CatalogCacheSortObject($this);
15 14 }
... ...
php/classes/TimeTableCacheFilterObject.php
... ... @@ -14,14 +14,16 @@ class TimeTableCacheFilterPartObject
14 14 public static $OPERATION_GT = 2;
15 15 public static $OPERATION_EQ = 3;
16 16  
  17 + protected $cacheObject = NULL;
17 18 protected $type;
18 19 protected $op;
19 20 protected $value;
20 21  
21   - function __construct() {
  22 + function __construct($cacheObject) {
22 23 $this->type = self::$TYPE_UNKNOWN;
23 24 $this->op = self::$OPERATION_UNKNOWN;
24   - $this->value = 0.;
  25 + $this->value = 0;
  26 + $this->cacheObject = $cacheObject;
25 27 }
26 28  
27 29 public function getType() {
... ... @@ -156,7 +158,7 @@ class TimeTableCacheFilterPartObject
156 158 }
157 159  
158 160 public function dump() {
159   - echo " => TimeTableCacheFilterPartObject : type = ";
  161 + echo " => ".get_class($this)." : type = ";
160 162 switch ($this->type)
161 163 {
162 164 case self::$TYPE_START :
... ... @@ -198,10 +200,15 @@ class TimeTableCacheFilterPartObject
198 200  
199 201 class TimeTableCacheFilterObject
200 202 {
  203 + protected $cacheObject = NULL;
201 204 protected $parts = array();
202 205  
203   - function __construct() {
  206 + protected function createNewPart() {
  207 + return new TimeTableCacheFilterPartObject($this->cacheObject);
  208 + }
204 209  
  210 + function __construct($cacheObject) {
  211 + $this->cacheObject = $cacheObject;
205 212 }
206 213  
207 214 public function getParts() {
... ... @@ -222,7 +229,7 @@ class TimeTableCacheFilterObject
222 229  
223 230 foreach ($filter_obj as $filter_part)
224 231 {
225   - $part = new TimeTableCacheFilterPartObject();
  232 + $part = $this->createNewPart();
226 233 $part->loadFromObject($filter_part);
227 234 array_push($this->parts, $part);
228 235 }
... ... @@ -245,7 +252,8 @@ class TimeTableCacheFilterObject
245 252 }
246 253  
247 254 public function isSameFromJSON($filter_json) {
248   - $filter = new TimeTableCacheFilterObject();
  255 + $this_class = get_class();
  256 + $filter = new $this_class($this->cacheObject);
249 257 $filter->loadFromJSON($filter_json);
250 258 return $this->isSame($filter);
251 259 }
... ... @@ -270,14 +278,14 @@ class TimeTableCacheFilterObject
270 278 $res = unpack('Lcount',fread($handle,4));
271 279 for ($i = 0; $i < $res['count']; ++$i)
272 280 {
273   - $part = new TimeTableCacheFilterPartObject();
  281 + $part = $this->createNewPart();
274 282 $part->loadBin($handle);
275 283 array_push($this->parts, $part);
276 284 }
277 285 }
278 286  
279 287 public function dump() {
280   - echo " => TimeTableCacheFilterObject : number of parts = ".count($this->parts).PHP_EOL;
  288 + echo " => ".get_class($this)." : number of parts = ".count($this->parts).PHP_EOL;
281 289 foreach ($this->parts as $part)
282 290 $part->dump();
283 291 }
... ...
php/classes/TimeTableCacheObject.php
... ... @@ -29,7 +29,7 @@ class TimeTableCacheObject
29 29 $this->intervals = array();
30 30 $this->indexes = array();
31 31 unset($this->filter);
32   - $this->filter = new TimeTableCacheFilterObject();;
  32 + $this->filter = new TimeTableCacheFilterObject($this);
33 33 unset($this->sort);
34 34 $this->sort = new TimeTableCacheSortObject($this);
35 35 }
... ... @@ -401,15 +401,15 @@ class TimeTableCacheObject
401 401 //Modified
402 402 fwrite($handle,pack('L',$this->isModified));
403 403  
  404 + //Additional info
  405 + $this->writeAdditionalHeaderBin($handle);
  406 +
404 407 //Filter
405 408 $this->filter->writeBin($handle);
406 409  
407 410 //Sort
408 411 $this->sort->writeBin($handle);
409 412  
410   - //Additional info
411   - $this->writeAdditionalHeaderBin($handle);
412   -
413 413 //Intervals
414 414 fwrite($handle,pack('L2',count($this->intervals), $this->lastId));
415 415 foreach($this->intervals as $interval) {
... ... @@ -451,15 +451,15 @@ class TimeTableCacheObject
451 451 return false;
452 452 $this->isModified = $res['modified'];
453 453  
  454 + //Additional info
  455 + $this->loadAdditionalHeaderBin($handle);
  456 +
454 457 //Filter
455 458 $this->filter->loadBin($handle);
456 459  
457 460 //Sort
458 461 $this->sort->loadBin($handle);
459 462  
460   - //Additional info
461   - $this->loadAdditionalHeaderBin($handle);
462   -
463 463 //Intervals
464 464 $res = unpack('L2data',fread($handle,2*4));
465 465 $nbIntervals = $res['data1'];
... ...