diff --git a/src/Controller/Component/CRUDComponent.php b/src/Controller/Component/CRUDComponent.php
index 7d7e612..a11937e 100644
--- a/src/Controller/Component/CRUDComponent.php
+++ b/src/Controller/Component/CRUDComponent.php
@@ -48,6 +48,8 @@ class CRUDComponent extends Component
$optionFilters = empty($options['filters']) ? [] : $options['filters'];
foreach ($optionFilters as $i => $filter) {
$optionFilters[] = "{$filter} !=";
+ $optionFilters[] = "{$filter} >=";
+ $optionFilters[] = "{$filter} <=";
}
$params = $this->Controller->ParamHandler->harvestParams($optionFilters);
$params = $this->fakeContextFilter($options, $params);
@@ -196,6 +198,16 @@ class CRUDComponent extends Component
$this->Controller->set('metaFieldsEnabled', false);
}
$filters = !empty($this->Controller->filterFields) ? $this->Controller->filterFields : [];
+ $typeMap = $this->Table->getSchema()->typeMap();
+ $associatedtypeMap = !empty($this->Controller->filterFields) ? $this->_getAssociatedTypeMap() : [];
+ $typeMap = array_merge(
+ $this->Table->getSchema()->typeMap(),
+ $associatedtypeMap
+ );
+ $typeMap = array_filter($typeMap, function ($field) use ($filters) {
+ return in_array($field, $filters);
+ }, ARRAY_FILTER_USE_KEY);
+ $this->Controller->set('typeMap', $typeMap);
$this->Controller->set('filters', $filters);
$this->Controller->viewBuilder()->setLayout('ajax');
$this->Controller->render('/genericTemplates/filters');
@@ -1522,4 +1534,24 @@ class CRUDComponent extends Component
$view = $builder->build($data);
return $view->render();
}
+
+ protected function _getAssociatedTypeMap(): array
+ {
+ $typeMap = [];
+ foreach ($this->Controller->filterFields as $filter) {
+ $exploded = explode('.', $filter);
+ if (count($exploded) > 1) {
+ $model = $exploded[0];
+ $subField = $exploded[1];
+ if ($model == $this->Table->getAlias()) {
+ $typeMap[$filter] = $this->Table->getSchema()->typeMap()[$subField] ?? 'text';
+ } else {
+ $association = $this->Table->associations()->get($model);
+ $associatedTable = $association->getTarget();
+ $typeMap[$filter] = $associatedTable->getSchema()->typeMap()[$subField] ?? 'text';
+ }
+ }
+ }
+ return $typeMap;
+ }
}
diff --git a/templates/genericTemplates/filters.php b/templates/genericTemplates/filters.php
index b101e09..d900104 100644
--- a/templates/genericTemplates/filters.php
+++ b/templates/genericTemplates/filters.php
@@ -7,6 +7,7 @@ $tableItems = array_map(function ($fieldName) {
'fieldname' => $fieldName,
];
}, $filters);
+$formTypeMap = $this->Form->getConfig('typeMap');
$filteringForm = $this->Bootstrap->table(
[
@@ -23,11 +24,19 @@ $filteringForm = $this->Bootstrap->table(
}
],
[
- 'key' => 'operator', 'label' => __('Operator'), 'formatter' => function ($field, $row) {
+ 'key' => 'operator', 'label' => __('Operator'), 'formatter' => function ($field, $row) use ($typeMap) {
+ $fieldName = $row['fieldname'];
+ $type = $typeMap[$fieldName] ?? 'text';
$options = [
sprintf('', '=', '='),
sprintf('', '!=', '!='),
];
+ if ($type === 'datetime') {
+ $options = [
+ sprintf('', '>=', '>='),
+ sprintf('', '<=', '<='),
+ ];
+ }
return sprintf('', implode('', $options));
}
],
@@ -38,8 +47,21 @@ $filteringForm = $this->Bootstrap->table(
__('Value'),
sprintf('', __('Supports strict matches and LIKE matches with the `%` character.
Example: `%.com`'))
),
- 'formatter' => function ($field, $row) {
- return sprintf('');
+ 'formatter' => function ($field, $row) use ($typeMap, $formTypeMap) {
+ $fieldName = $row['fieldname'];
+ $formType = $formTypeMap[$typeMap[$fieldName]] ?? 'text';
+ $this->Form->setTemplates([
+ 'formGroup' => '{{input}}
',
+ ]);
+ return $this->element('genericElements/Form/fieldScaffold', [
+ 'fieldData' => [
+ 'field' => $fieldName,
+ 'type' => $formType,
+ 'label' => '',
+ 'class' => 'fieldValue form-control-sm'
+ ],
+ 'params' => []
+ ]);
}
],
],
@@ -102,8 +124,8 @@ echo $this->Bootstrap->modal([
$rows.each(function() {
const rowData = getDataFromRow($(this))
let fullFilter = rowData['name']
- if (rowData['operator'] == '!=') {
- fullFilter += ' !='
+ if (rowData['operator'] != '=') {
+ fullFilter += ` ${rowData['operator']}`
}
if (rowData['value'].length > 0) {
activeFilters[fullFilter] = rowData['value']
@@ -111,7 +133,6 @@ echo $this->Bootstrap->modal([
})
if (modalObject.$modal.find('table.indexMetaFieldsFilteringTable').length > 0) {
let metaFieldFilters = modalObject.$modal.find('table.indexMetaFieldsFilteringTable')[0].getFiltersFunction()
- // activeFilters['filteringMetaFields'] = metaFieldFilters !== undefined ? metaFieldFilters : [];
metaFieldFilters = metaFieldFilters !== undefined ? metaFieldFilters : []
for (let [metaFieldPath, metaFieldValue] of Object.entries(metaFieldFilters)) {
activeFilters[metaFieldPath] = metaFieldValue
@@ -138,8 +159,8 @@ echo $this->Bootstrap->modal([
for (let [field, value] of Object.entries(activeFilters)) {
const fieldParts = field.split(' ')
let operator = '='
- if (fieldParts.length == 2 && fieldParts[1] == '!=') {
- operator = '!='
+ if (fieldParts.length == 2) {
+ operator = fieldParts[1]
field = fieldParts[0]
} else if (fieldParts.length > 2) {
console.error('Field contains multiple spaces. ' + field)
@@ -167,14 +188,24 @@ echo $this->Bootstrap->modal([
return $(this).data('fieldname') == field
}).closest('tr')
$row.find('.fieldOperator').val(operator)
- $row.find('.fieldValue').val(value)
+ const $formElement = $row.find('.fieldValue');
+ if ($formElement.attr('type') === 'datetime-local') {
+ $formElement.val(moment(value).format('yyyy-MM-DDThh:mm:ss'))
+ } else {
+ $formElement.val(value)
+ }
}
function getDataFromRow($row) {
const rowData = {};
rowData['name'] = $row.find('td > span.fieldName').data('fieldname')
rowData['operator'] = $row.find('select.fieldOperator').val()
- rowData['value'] = $row.find('input.fieldValue').val()
+ const $formElement = $row.find('.fieldValue');
+ if ($formElement.attr('type') === 'datetime-local') {
+ rowData['value'] = moment($formElement.val()).toISOString()
+ } else {
+ rowData['value'] = $formElement.val()
+ }
return rowData
}