From 8145f46229509175e22d83317988c68b58db36ec Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Sat, 7 May 2022 21:02:12 +0300 Subject: [PATCH] [WIP]Support date range filtering --- app/src/Controller/StandardController.php | 7 +++ app/src/Lib/Traits/SearchFilterTrait.php | 24 +++---- app/templates/element/filter.php | 76 ++++++++++++++++++++++- app/webroot/css/co-base.css | 4 ++ app/webroot/css/co-responsive.css | 3 + 5 files changed, 102 insertions(+), 12 deletions(-) diff --git a/app/src/Controller/StandardController.php b/app/src/Controller/StandardController.php index eb7ec11cc..180629d86 100644 --- a/app/src/Controller/StandardController.php +++ b/app/src/Controller/StandardController.php @@ -444,6 +444,13 @@ public function index() { foreach(array_keys($searchableAttributes) as $attribute) { if(!empty($this->request->getQuery($attribute))) { $query = $table->whereFilter($query, $attribute, $this->request->getQuery($attribute)); + } elseif (!empty($this->request->getQuery($attribute . "_starts_at")) + || !empty($this->request->getQuery($attribute . "_ends_at"))) { + $search_date = []; + // We allow empty for dates since we might refer to infinity (from whenever or to always) + $search_date[] = $this->request->getQuery($attribute . "_starts_at") ?? ""; + $search_date[] = $this->request->getQuery($attribute . "_ends_at") ?? ""; + $query = $table->whereFilter($query, $attribute, $search_date); } } diff --git a/app/src/Lib/Traits/SearchFilterTrait.php b/app/src/Lib/Traits/SearchFilterTrait.php index 9f031df0a..c401034af 100644 --- a/app/src/Lib/Traits/SearchFilterTrait.php +++ b/app/src/Lib/Traits/SearchFilterTrait.php @@ -49,7 +49,6 @@ public function getSearchableAttributes(): array { } $this->searchFilters[$column] = [ 'type' => $type, - // todo: Probably the following line is redundant but i am leaving it for now 'label' => (__d('field', $column) ?? Inflector::humanize($column)) ]; } @@ -60,14 +59,15 @@ public function getSearchableAttributes(): array { /** * Build a query where() clause for the configured attribute. * - * @since COmanage Registry v5.0.0 - * @param \Cake\ORM\Query $query Cake ORM Query object - * @param string $attribute Attribute to filter on (database name) - * @param string $q Value to filter on + * @param \Cake\ORM\Query $query Cake ORM Query object + * @param string|array $attribute Attribute to filter on (database name) + * @param string $q Value to filter on + * * @return \Cake\ORM\Query Cake ORM Query object + * @since COmanage Registry v5.0.0 */ - public function whereFilter(\Cake\ORM\Query $query, string $attribute, string $q): object { + public function whereFilter(\Cake\ORM\Query $query, string|array $attribute, string $q): object { // not a permitted attribute if(empty($this->searchFilters[$attribute])) { return $query; @@ -75,15 +75,17 @@ public function whereFilter(\Cake\ORM\Query $query, string $attribute, string $q $search = $q; $sub = false; + // Primitive types + $search_types = ['integer', 'boolean']; if( $this->searchFilters[$attribute]['type'] == "string") { $search = "%" . $search . "%"; $sub = true; - } - - // Primitive types - $search_types = ['integer', 'boolean']; - if(in_array($this->searchFilters[$attribute]['type'], $search_types, true)) { + } elseif(in_array($this->searchFilters[$attribute]['type'], $search_types, true)) { return $query->where([$attribute => $search]); + } elseif( $this->searchFilters[$attribute]['type'] == "timestamp") { + return $query->where(function (\Cake\Database\Expression\QueryExpression $exp, \Cake\ORM\Query $query) use ($attribute, $search) { + return $exp->between($attribute, $search[0], $search[1]); + }); } // String values diff --git a/app/templates/element/filter.php b/app/templates/element/filter.php index eec0a41bd..6ca492da8 100644 --- a/app/templates/element/filter.php +++ b/app/templates/element/filter.php @@ -100,11 +100,15 @@
$options) { if($options['type'] == 'boolean') { $field_booleans_columns[$key] = $options; continue; + } elseif ($options['type'] == 'timestamp') { + $field_datetime_columns[$key] = $options; + continue; } $formParams = [ 'label' => $options['label'], @@ -130,9 +134,79 @@ } ?>
+ + $options): ?> +
+
+
+ +
+
+ i18nFormat("yyyy-MM-dd HH:mm:ss", $this->get('vv_tz')); + $pickerDate = $query[$starts_field]->i18nFormat("yyyy-MM-dd", $this->get('vv_tz')); + } + + $date_args = [ + 'fieldName' => $starts_field, + 'pickerDate' => $pickerDate + ]; + // Create a text field to hold our value. + print $this->Form->label($starts_field, 'Starts at:', ['class' => 'filter-datepicker-lbl']); + print $this->Form->text($starts_field, $coptions) . $this->element('datePicker', $date_args); + ?> +
+
+ +
+
+ i18nFormat("yyyy-MM-dd HH:mm:ss", $this->get('vv_tz')); + $pickerDate = $query[$ends_field]->i18nFormat("yyyy-MM-dd", $this->get('vv_tz')); + } + + $date_args = [ + 'fieldName' => $ends_field, + 'pickerDate' => $pickerDate + ]; + // Create a text field to hold our value. + print $this->Form->label($ends_field, 'Ends at:', ['class' => 'filter-datepicker-lbl']); + print $this->Form->text($ends_field, $coptions) . $this->element('datePicker', $date_args); + ?> +
+
+
+
+ + +
-
Some Title here
+
On-Off
$options): ?>
diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css index c19df5a3c..139dd4d63 100644 --- a/app/webroot/css/co-base.css +++ b/app/webroot/css/co-base.css @@ -713,6 +713,10 @@ instead, reveal in user menu */ .top-filters-active-filters-remove button:hover { background-color: var(--cmg-color-lightgray-005); } +.filter-datepicker-lbl { + white-space: nowrap; + margin-right: 0.5em; +} /* RECONCILE TABLE */ #reconcile-table { width: auto; diff --git a/app/webroot/css/co-responsive.css b/app/webroot/css/co-responsive.css index 2ce80639d..b80bc40d0 100644 --- a/app/webroot/css/co-responsive.css +++ b/app/webroot/css/co-responsive.css @@ -205,6 +205,9 @@ margin-top: -3.5em; position: relative; } + .top-search-date-label { + padding: 0 0.5em; + } /* CO CONFIGURATION DASHBOARD */ #configuration-menu { column-count: 3;