From e022e5b53138ede006657f293774c908d0442967 Mon Sep 17 00:00:00 2001 From: Benjamin Renard <benjamin.renard@akka.eu> Date: Fri, 9 Aug 2019 11:43:51 +0200 Subject: [PATCH] Filter parameter columns of a catalog (#7048) --- js/app/views/CatalogUI.js | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- php/classes/CatalogCacheFilterObject.php | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ php/classes/CatalogCacheIntervalObject.php | 2 +- php/classes/CatalogCacheObject.php | 5 ++--- php/classes/TimeTableCacheFilterObject.php | 24 ++++++++++++++++-------- php/classes/TimeTableCacheObject.php | 14 +++++++------- 6 files changed, 394 insertions(+), 29 deletions(-) create mode 100644 php/classes/CatalogCacheFilterObject.php diff --git a/js/app/views/CatalogUI.js b/js/app/views/CatalogUI.js index d64c96a..8d0d3a1 100644 --- a/js/app/views/CatalogUI.js +++ b/js/app/views/CatalogUI.js @@ -12,8 +12,13 @@ Ext.define('amdaUI.CatalogUI', { alias: 'widget.panelCatalog', requires: [ + 'Ext.ux.grid.menu.RangeMenu', + 'Ext.ux.grid.FiltersFeature', + 'Ext.ux.grid.filter.DateFilter', + 'Ext.ux.grid.filter.NumericFilter', + 'Ext.ux.grid.filter.StringFilter', 'Ext.grid.plugin.BufferedRenderer', - 'amdaUI.StatisticalPlug' + 'amdaUI.StatisticalPlug' ], isCatalog : true, @@ -178,6 +183,13 @@ Ext.define('amdaUI.CatalogUI', { if (me.toReconfigure) { + // clear filters + if (me.TTGrid.filters) { + me.TTGrid.getStore().clearFilter(true); + me.TTGrid.filters.clearFilters(); + me.TTGrid.filters.destroy(); + } + var fieldsConfig = [ { name : 'start', @@ -277,7 +289,8 @@ Ext.define('amdaUI.CatalogUI', { allowBlank:false, hideTrigger: true, format : 'Y-m-d\\TH:i:s' - } + }, + filter: { type: 'date', dateFormat: 'Y-m-d' } }, { xtype: 'datecolumn', @@ -292,7 +305,8 @@ Ext.define('amdaUI.CatalogUI', { allowBlank:false, hideTrigger: true, format : 'Y-m-d\\TH:i:s' - } + }, + filter: { type: 'date', dateFormat: 'Y-m-d' } }, { xtype: 'gridcolumn', @@ -310,7 +324,8 @@ Ext.define('amdaUI.CatalogUI', { beforeshow : function(){ updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'1'); } - } + }, + filter: { type: 'numeric'} }, { xtype: 'gridcolumn', @@ -328,7 +343,8 @@ Ext.define('amdaUI.CatalogUI', { beforeshow : function(){ updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'2'); } - } + }, + filter: { type: 'numeric'} }, { xtype: 'gridcolumn', @@ -346,11 +362,12 @@ Ext.define('amdaUI.CatalogUI', { beforeshow : function(){ updateDurationColumnsVisibility(this.ownerCt.getGridColumns(), amdaUI.CatalogUI.COL_TO_HIDE_DURATION+'3'); } - } + }, + filter: { type: 'numeric'} } ]; - Ext.Array.each(result.parameters, function(obj, index) { + Ext.Array.each(result.parameters, function(obj, index) { var field = { name: obj.id }; @@ -361,6 +378,17 @@ Ext.define('amdaUI.CatalogUI', { menuDisabled: false }; switch (obj.type) { + case 0: //double + field = Ext.apply({}, field, { + type: 'string' + }); + column = Ext.apply({}, column, { + xtype: 'gridcolumn', + width : 50. * parseInt(obj.size), + editor: 'textfield', + filter: { type: 'numeric'} + }); + break; case 1: //dateTime field = Ext.apply({}, field, { type : 'date', @@ -382,9 +410,32 @@ Ext.define('amdaUI.CatalogUI', { allowBlank:false, hideTrigger: true, format : 'Y-m-d\\TH:i:s' - } + }, + filter: { type: 'date', dateFormat: 'Y-m-d' } }); break; + case 2: //string + field = Ext.apply({}, field, { + type: 'string' + }); + column = Ext.apply({}, column, { + xtype: 'gridcolumn', + width : 50. * parseInt(obj.size), + editor: 'textfield', + filter: { type: 'string'} + }); + break; + case 3: //int + field = Ext.apply({}, field, { + type: 'string' + }); + column = Ext.apply({}, column, { + xtype: 'gridcolumn', + width : 50. * parseInt(obj.size), + editor: 'textfield', + filter: { type: 'numeric'} + }); + break; default: field = Ext.apply({}, field, { type: 'string' @@ -392,7 +443,8 @@ Ext.define('amdaUI.CatalogUI', { column = Ext.apply({}, column, { xtype: 'gridcolumn', width : 50. * parseInt(obj.size), - editor: 'textfield' + editor: 'textfield', + filter: { type: 'string'} }); } fieldsConfig.push(field); @@ -432,6 +484,9 @@ Ext.define('amdaUI.CatalogUI', { }); me.TTGrid.reconfigure(store, columnsConfig); + if (me.TTGrid.filters) { + me.TTGrid.filters.bindStore(store); + } } me.TTGrid.getSelectionModel().deselectAll(); // @@ -697,8 +752,18 @@ Ext.define('amdaUI.CatalogUI', { } }); + var filters = { + ftype: 'filters', + encode: true, // json encode the filter query + local: false, + filters: [ + + ] + }; + this.TTGrid = Ext.create('Ext.grid.Panel', { height: 530, + features: [filters], columns: [ ], frame: true, columnLines: true, @@ -754,7 +819,15 @@ Ext.define('amdaUI.CatalogUI', { }, this); } } - }] + },'->', + { + text: 'Clear Filters', + scope: this, + handler: function () { + this.TTGrid.getStore().clearFilter(true); + this.TTGrid.filters.clearFilters(); + } + }] }] }); diff --git a/php/classes/CatalogCacheFilterObject.php b/php/classes/CatalogCacheFilterObject.php new file mode 100644 index 0000000..baa26b8 --- /dev/null +++ b/php/classes/CatalogCacheFilterObject.php @@ -0,0 +1,285 @@ +<?php + +class CatalogCacheFilterPartObject extends TimeTableCacheFilterPartObject +{ + public static $TYPE_PARAMETER = 6; + + private $paramId = ""; + + public function getParamId() { + return $this->paramId; + } + + public function isSame($part) { + $same = parent::isSame($part); + if ($this->type != self::$TYPE_PARAMETER) { + return $same; + } + return $same && ($this->paramId == $part->getParamId()); + } + + public function toFiltered($interval) { + if ($this->type != self::$TYPE_PARAMETER) { + return parent::toFiltered($interval); + } + + $params = $interval->getParams(); + + // Retrieve data type + $data_type = -1; + foreach ($this->cacheObject->getParametersInfo() as $parameter) { + if ($parameter['id'] == $this->paramId) { + $data_type = $parameter['type']; + break; + } + } + + if ($data_type < 0) { + return FALSE; + } + else if (!isset($params[$this->paramId])) { + return FALSE; + } + + switch ($parameter['type']) { + case 0: //double + { + $param_value = floatval($params[$this->paramId]); + switch ($this->op) { + case self::$OPERATION_LT : + return ($param_value < $this->value); + case self::$OPERATION_GT : + return ($param_value > $this->value); + case self::$OPERATION_EQ : + return ($param_value != $this->value); + default : + return FALSE; + } + break; + } + case 1: //date (timestamp) + { + $param_value = intval($params[$this->paramId]); + switch ($this->op) { + case self::$OPERATION_LT : + return ($param_value < $this->value); + case self::$OPERATION_GT : + return ($param_value > $this->value); + case self::$OPERATION_EQ : + return (!(($param_value >= $this->value) && ($param_value <= $this->value+86400))); + default : + return FALSE; + } + break; + } + case 2: //string + $param_value = $params[$this->paramId]; + if (empty($this->value)) + return FALSE; + if (empty($param_value)) + return TRUE; + return (strpos(strtolower($param_value), strtolower($this->value)) === FALSE); + case 3: //int + { + $param_value = intval($params[$this->paramId]); + switch ($this->op) { + case self::$OPERATION_LT : + return ($param_value < $this->value); + case self::$OPERATION_GT : + return ($param_value > $this->value); + case self::$OPERATION_EQ : + return ($param_value != $this->value); + default : + return FALSE; + } + break; + } + default: + return FALSE; + } + + return FALSE; + } + + public function loadFromObject($part_obj) { + parent::loadFromObject($part_obj); + if ($this->type == self::$TYPE_UNKNOWN) { + //Check if it's a catalog parameter + foreach ($this->cacheObject->getParametersInfo() as $parameter) { + if ($parameter['id'] == $part_obj->field) { + $this->type = self::$TYPE_PARAMETER; + $this->paramId = $parameter['id']; + + switch ($parameter['type']) { + case 0: //double + $this->value = floatval($part_obj->value); + break; + case 1: //date (timestamp) + $this->value = TimeUtils::iso2stamp($part_obj->value); + break; + case 2: //string + $this->value = $part_obj->value; + break; + case 3: //int + $this->value = intval($part_obj->value); + break; + default: + $this->value = $part_obj->value; + } + + break; + } + } + } + } + + public function writeBin($handle) { + fwrite($handle,pack('L2',$this->type,$this->op)); + if ($this->type == self::$TYPE_PARAMETER) { + //Param Id length + fwrite($handle,pack('L',strlen($this->paramId))); + + //Param Id + for ($i = 0; $i < strlen($this->paramId); ++$i) + fwrite($handle,pack('C',ord($this->paramId[$i]))); + + // Retrieve data type + $data_type = -1; + foreach ($this->cacheObject->getParametersInfo() as $parameter) { + if ($parameter['id'] == $this->paramId) { + $data_type = $parameter['type']; + break; + } + } + + switch ($data_type) { + case 0: //double + fwrite($handle,pack('f',floatval($this->value))); + break; + case 1: //date (timestamp) + fwrite($handle,pack('L',intval($this->value))); + break; + case 2: //string + fwrite($handle,pack('L',strlen($this->value))); + for ($i = 0; $i < strlen($this->value); ++$i) + fwrite($handle,pack('C',ord($this->value[$i]))); + break; + case 3: //int + fwrite($handle,pack('L',intval($this->value))); + break; + default: + fwrite($handle,pack('L',strlen($this->value))); + for ($i = 0; $i < strlen($this->value); ++$i) + fwrite($handle,pack('C',ord($this->value[$i]))); + } + } + else { + fwrite($handle,pack('f',$this->value)); + } + } + + public function loadBin($handle) { + $res = unpack('L2data',fread($handle,4*2)); + $this->type = $res['data1']; + $this->op = $res['data2']; + + if ($this->type == self::$TYPE_PARAMETER) { + //Param Id length + if (!$res = unpack('Lidlength',fread($handle,4))) + return false; + $idlength = $res['idlength']; + + //Param Id + $this->paramId = ""; + for ($j = 0; $j < $idlength; ++$j) + { + if (!$res = unpack('Cid',fread($handle,1))) + return false; + $this->paramId .= chr($res['id']); + } + + // Retrieve data type + $data_type = -1; + foreach ($this->cacheObject->getParametersInfo() as $parameter) { + if ($parameter['id'] == $this->paramId) { + $data_type = $parameter['type']; + break; + } + } + + switch ($data_type) { + case 0: //double + $res = unpack('fvalue',fread($handle,4)); + $this->value = $res['value']; + break; + case 1: //date (timestamp) + $res = unpack('Lvalue',fread($handle,4)); + $this->value = $res['value']; + break; + case 2: //string + $res = unpack('Llength',fread($handle,4)); + $length = $res['length']; + $this->value = ""; + for ($j = 0; $j < $length; ++$j) + { + if (!$res = unpack('Cvalue',fread($handle,1))) + return false; + $this->value .= chr($res['value']); + } + break; + case 3: //int + $res = unpack('Lvalue',fread($handle,4)); + $this->value = $res['value']; + break; + default: + $res = unpack('Llength',fread($handle,4)); + $length = $res['length']; + $this->value = ""; + for ($j = 0; $j < $length; ++$j) + { + if (!$res = unpack('Cvalue',fread($handle,1))) + return false; + $this->value .= chr($res['value']); + } + break; + } + } + else { + $res = unpack('fvalue',fread($handle,4)); + $this->value = $res['value']; + } + } + + public function dump() { + if ($this->type == self::$TYPE_PARAMETER) { + echo " => ".get_class($this)." : type = parameter, id = ".$this->paramId; + echo ", operation = "; + switch ($this->op) + { + case self::$OPERATION_LT : + echo "lt"; + break; + case self::$OPERATION_GT : + echo "gt"; + break; + case self::$OPERATION_EQ : + echo "eq"; + break; + default: + echo "unknown"; + } + echo ", value = ".$this->value.PHP_EOL; + return; + } + parent::dump(); + } +} + +class CatalogCacheFilterObject extends TimeTableCacheFilterObject +{ + protected function createNewPart() { + return new CatalogCacheFilterPartObject($this->cacheObject); + } +} + + ?> diff --git a/php/classes/CatalogCacheIntervalObject.php b/php/classes/CatalogCacheIntervalObject.php index c9e2f27..2aa3197 100644 --- a/php/classes/CatalogCacheIntervalObject.php +++ b/php/classes/CatalogCacheIntervalObject.php @@ -104,7 +104,7 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject if (!$res = unpack('Lval',fread($handle,4))) { break; } - $val = $res['val']; + $val = TimeUtils::stamp2iso($res['val']); break; case 2: //string if (!$res = unpack('Llength',fread($handle,4))) { diff --git a/php/classes/CatalogCacheObject.php b/php/classes/CatalogCacheObject.php index 4b63de4..5b8eb38 100644 --- a/php/classes/CatalogCacheObject.php +++ b/php/classes/CatalogCacheObject.php @@ -7,9 +7,8 @@ class CatalogCacheObject extends TimeTableCacheObject public function reset() { parent::reset(); $this->parameters = array(); - //ToDo - Init sort and filters for Catalog - /*unset($this->filter); - $this->filter = new TimeTableCacheFilterObject();;*/ + unset($this->filter); + $this->filter = new CatalogCacheFilterObject($this); unset($this->sort); $this->sort = new CatalogCacheSortObject($this); } diff --git a/php/classes/TimeTableCacheFilterObject.php b/php/classes/TimeTableCacheFilterObject.php index 282b461..900ba69 100644 --- a/php/classes/TimeTableCacheFilterObject.php +++ b/php/classes/TimeTableCacheFilterObject.php @@ -14,14 +14,16 @@ class TimeTableCacheFilterPartObject public static $OPERATION_GT = 2; public static $OPERATION_EQ = 3; + protected $cacheObject = NULL; protected $type; protected $op; protected $value; - function __construct() { + function __construct($cacheObject) { $this->type = self::$TYPE_UNKNOWN; $this->op = self::$OPERATION_UNKNOWN; - $this->value = 0.; + $this->value = 0; + $this->cacheObject = $cacheObject; } public function getType() { @@ -156,7 +158,7 @@ class TimeTableCacheFilterPartObject } public function dump() { - echo " => TimeTableCacheFilterPartObject : type = "; + echo " => ".get_class($this)." : type = "; switch ($this->type) { case self::$TYPE_START : @@ -198,10 +200,15 @@ class TimeTableCacheFilterPartObject class TimeTableCacheFilterObject { + protected $cacheObject = NULL; protected $parts = array(); - function __construct() { + protected function createNewPart() { + return new TimeTableCacheFilterPartObject($this->cacheObject); + } + function __construct($cacheObject) { + $this->cacheObject = $cacheObject; } public function getParts() { @@ -222,7 +229,7 @@ class TimeTableCacheFilterObject foreach ($filter_obj as $filter_part) { - $part = new TimeTableCacheFilterPartObject(); + $part = $this->createNewPart(); $part->loadFromObject($filter_part); array_push($this->parts, $part); } @@ -245,7 +252,8 @@ class TimeTableCacheFilterObject } public function isSameFromJSON($filter_json) { - $filter = new TimeTableCacheFilterObject(); + $this_class = get_class(); + $filter = new $this_class($this->cacheObject); $filter->loadFromJSON($filter_json); return $this->isSame($filter); } @@ -270,14 +278,14 @@ class TimeTableCacheFilterObject $res = unpack('Lcount',fread($handle,4)); for ($i = 0; $i < $res['count']; ++$i) { - $part = new TimeTableCacheFilterPartObject(); + $part = $this->createNewPart(); $part->loadBin($handle); array_push($this->parts, $part); } } public function dump() { - echo " => TimeTableCacheFilterObject : number of parts = ".count($this->parts).PHP_EOL; + echo " => ".get_class($this)." : number of parts = ".count($this->parts).PHP_EOL; foreach ($this->parts as $part) $part->dump(); } diff --git a/php/classes/TimeTableCacheObject.php b/php/classes/TimeTableCacheObject.php index 21766a8..88f45b8 100644 --- a/php/classes/TimeTableCacheObject.php +++ b/php/classes/TimeTableCacheObject.php @@ -29,7 +29,7 @@ class TimeTableCacheObject $this->intervals = array(); $this->indexes = array(); unset($this->filter); - $this->filter = new TimeTableCacheFilterObject();; + $this->filter = new TimeTableCacheFilterObject($this); unset($this->sort); $this->sort = new TimeTableCacheSortObject($this); } @@ -401,15 +401,15 @@ class TimeTableCacheObject //Modified fwrite($handle,pack('L',$this->isModified)); + //Additional info + $this->writeAdditionalHeaderBin($handle); + //Filter $this->filter->writeBin($handle); //Sort $this->sort->writeBin($handle); - //Additional info - $this->writeAdditionalHeaderBin($handle); - //Intervals fwrite($handle,pack('L2',count($this->intervals), $this->lastId)); foreach($this->intervals as $interval) { @@ -451,15 +451,15 @@ class TimeTableCacheObject return false; $this->isModified = $res['modified']; + //Additional info + $this->loadAdditionalHeaderBin($handle); + //Filter $this->filter->loadBin($handle); //Sort $this->sort->loadBin($handle); - //Additional info - $this->loadAdditionalHeaderBin($handle); - //Intervals $res = unpack('L2data',fread($handle,2*4)); $nbIntervals = $res['data1']; -- libgit2 0.21.2