Skip to content

Commit

Permalink
[WIP]Support date range filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis Igoumenos committed May 7, 2022
1 parent fd96287 commit 13a559e
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 12 deletions.
7 changes: 7 additions & 0 deletions app/src/Controller/StandardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
24 changes: 13 additions & 11 deletions app/src/Lib/Traits/SearchFilterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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))
];
}
Expand All @@ -60,30 +59,33 @@ 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;
}

$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
Expand Down
76 changes: 75 additions & 1 deletion app/templates/element/filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,15 @@
<div id="top-filters-fields-subgroups">
<?php
$field_booleans_columns = [];
$field_datetime_columns = [];

foreach($vv_searchable_attributes as $key => $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'],
Expand All @@ -130,9 +134,79 @@
}
?>
</div>
<?php if(!empty($field_booleans_columns)): ?>
<?php foreach($field_datetime_columns as $key => $options): ?>
<div class="input">
<div class="top-search-date-label"><?= Cake\Utility\Inflector::humanize($key) ?></div>
<div id="top-filters-fields-subgroups">
<!-- Start at -->
<div class="top-search-date-fields">
<div class="d-flex">
<?php
// A datetime field will be rendered as plain text input with adjacent date and time pickers
// that will interact with the field value. Allowing direct access to the input field is for
// accessibility purposes.
$starts_field = $key . "_starts_at";
$coptions['class'] = 'form-control datepicker';
$coptions['label'] = 'Starts at:';
$coptions['placeholder'] = 'YYYY-MM-DD HH:MM:SS'; // TODO: test for date-only inputs and send only the date
$coptions['id'] = $starts_field;

$pickerDate = '';
if(!empty($query[$starts_field])) {
// Adjust the time back to the user's timezone
$coptions['value'] = $query[$starts_field]->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);
?>
</div>
</div>
<!-- Ends at -->
<div class="top-search-checkbox-fields">
<div class="d-flex">
<?php
// A datetime field will be rendered as plain text input with adjacent date and time pickers
// that will interact with the field value. Allowing direct access to the input field is for
// accessibility purposes.
$ends_field = $key . "_ends_at";
$coptions['class'] = 'form-control datepicker';
$coptions['label'] = 'Ends at:';
$coptions['placeholder'] = 'YYYY-MM-DD HH:MM:SS'; // TODO: test for date-only inputs and send only the date
$coptions['id'] = $ends_field;

$pickerDate = '';
if(!empty($query[$ends_field])) {
// Adjust the time back to the user's timezone
$coptions['value'] = $query[$ends_field]->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);
?>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>

<?php if(!empty($field_booleans_columns)): ?>
<div class="top-search-checkboxes input">
<div class="top-search-checkbox-label">Some Title here</div>
<div class="top-search-checkbox-label">On-Off</div>
<div class="top-search-checkbox-fields">
<?php foreach($field_booleans_columns as $key => $options): ?>
<div class="form-check form-check-inline">
Expand Down
4 changes: 4 additions & 0 deletions app/webroot/css/co-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions app/webroot/css/co-responsive.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 13a559e

Please sign in to comment.