chg: [component:CRUD] Improved filtering to support form type based on database column type
parent
e1499fb705
commit
aeda393bba
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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('<option value="%s">%s</option>', '=', '='),
|
||||
sprintf('<option value="%s">%s</option>', '!=', '!='),
|
||||
];
|
||||
if ($type === 'datetime') {
|
||||
$options = [
|
||||
sprintf('<option value="%s">%s</option>', '>=', '>='),
|
||||
sprintf('<option value="%s">%s</option>', '<=', '<='),
|
||||
];
|
||||
}
|
||||
return sprintf('<select class="fieldOperator form-select form-select-sm">%s</select>', implode('', $options));
|
||||
}
|
||||
],
|
||||
|
@ -38,8 +47,21 @@ $filteringForm = $this->Bootstrap->table(
|
|||
__('Value'),
|
||||
sprintf('<sup class="fa fa-info" title="%s"><sup>', __('Supports strict matches and LIKE matches with the `%` character. Example: `%.com`'))
|
||||
),
|
||||
'formatter' => function ($field, $row) {
|
||||
return sprintf('<input type="text" class="fieldValue form-control form-control-sm">');
|
||||
'formatter' => function ($field, $row) use ($typeMap, $formTypeMap) {
|
||||
$fieldName = $row['fieldname'];
|
||||
$formType = $formTypeMap[$typeMap[$fieldName]] ?? 'text';
|
||||
$this->Form->setTemplates([
|
||||
'formGroup' => '<div class="col-sm-10">{{input}}</div>',
|
||||
]);
|
||||
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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue