new: [crud:filter] Added support of IN searches using dropdown
parent
fdd876b1b2
commit
4d4642770f
|
@ -226,22 +226,41 @@ class CRUDComponent extends Component
|
|||
} else {
|
||||
$this->Controller->set('metaFieldsEnabled', false);
|
||||
}
|
||||
$filters = !empty($this->Controller->filterFields) ? $this->Controller->filterFields : [];
|
||||
$filtersConfigRaw= !empty($this->Controller->filterFields) ? $this->Controller->filterFields : [];
|
||||
$filtersConfig = [];
|
||||
foreach ($filtersConfigRaw as $fieldConfig) {
|
||||
if (is_array($fieldConfig)) {
|
||||
$filtersConfig[$fieldConfig['name']] = $fieldConfig;
|
||||
} else {
|
||||
$filtersConfig[$fieldConfig] = ['name' => $fieldConfig];
|
||||
}
|
||||
}
|
||||
$filtersName = $this->getFilterFieldsName();
|
||||
$typeMap = $this->Table->getSchema()->typeMap();
|
||||
$associatedtypeMap = !empty($this->Controller->filterFields) ? $this->_getAssociatedTypeMap() : [];
|
||||
$associatedtypeMap = !empty($filtersName) ? $this->_getAssociatedTypeMap() : [];
|
||||
$typeMap = array_merge(
|
||||
$this->Table->getSchema()->typeMap(),
|
||||
$associatedtypeMap
|
||||
);
|
||||
$typeMap = array_filter($typeMap, function ($field) use ($filters) {
|
||||
return in_array($field, $filters);
|
||||
$typeMap = array_filter($typeMap, function ($field) use ($filtersName) {
|
||||
return in_array($field, $filtersName);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
$this->Controller->set('typeMap', $typeMap);
|
||||
$this->Controller->set('filters', $filters);
|
||||
$this->Controller->set('filters', $filtersName);
|
||||
$this->Controller->set('filtersConfig', $filtersConfig);
|
||||
$this->Controller->viewBuilder()->setLayout('ajax');
|
||||
$this->Controller->render('/genericTemplates/filters');
|
||||
}
|
||||
|
||||
public function getFilterFieldsName(): array
|
||||
{
|
||||
$filters = !empty($this->Controller->filterFields) ? $this->Controller->filterFields : [];
|
||||
$filters = array_map(function($item) {
|
||||
return is_array($item) ? $item['name'] : $item;
|
||||
}, $filters);
|
||||
return $filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* getResponsePayload Returns the adaquate response payload based on the request context
|
||||
*
|
||||
|
@ -1613,7 +1632,7 @@ class CRUDComponent extends Component
|
|||
protected function _getAssociatedTypeMap(): array
|
||||
{
|
||||
$typeMap = [];
|
||||
foreach ($this->Controller->filterFields as $filter) {
|
||||
foreach ($this->getFilterFieldsName() as $filter) {
|
||||
$exploded = explode('.', $filter);
|
||||
if (count($exploded) > 1) {
|
||||
$model = $exploded[0];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
$seed = 's-' . mt_rand();
|
||||
$controlParams = [
|
||||
'type' => 'select',
|
||||
'options' => $fieldData['options'],
|
||||
'options' => $fieldData['options'] ?? [],
|
||||
'empty' => $fieldData['empty'] ?? false,
|
||||
'value' => $fieldData['value'] ?? null,
|
||||
'multiple' => $fieldData['multiple'] ?? false,
|
||||
|
@ -20,8 +20,10 @@ if ($controlParams['options'] instanceof \Cake\ORM\Query) {
|
|||
$controlParams['options'] = $controlParams['options']->all()->toList();
|
||||
}
|
||||
if (!empty($fieldData['select2'])) {
|
||||
$fieldData['select2'] = $fieldData['select2'] === true ? [] : $fieldData['select2'];
|
||||
$controlParams['class'] .= ' select2-input';
|
||||
}
|
||||
$controlParams['class'] .= ' dropdown-custom-value' . "-$seed";
|
||||
if (in_array('_custom', array_keys($controlParams['options']))) {
|
||||
$customInputValue = $this->Form->getSourceValue($fieldData['field']);
|
||||
if (!in_array($customInputValue, $controlParams['options'])) {
|
||||
|
@ -34,7 +36,6 @@ if (in_array('_custom', array_keys($controlParams['options']))) {
|
|||
} else {
|
||||
$customInputValue = '';
|
||||
}
|
||||
$controlParams['class'] .= ' dropdown-custom-value' . "-$seed";
|
||||
$adaptedField = $fieldData['field'] . '_custom';
|
||||
$controlParams['templates']['formGroup'] = sprintf(
|
||||
'<label class="col-sm-2 col-form-label form-label" {{attrs}}>{{label}}</label><div class="col-sm-10 multi-metafield-input-container"><div class="d-flex form-dropdown-with-freetext input-group">{{input}}{{error}}%s</div></div>',
|
||||
|
@ -57,9 +58,12 @@ echo $this->FormFieldMassage->prepareFormElement($this->Form, $controlParams, $f
|
|||
if ($container.length == 0) {
|
||||
$container = $(document.body)
|
||||
}
|
||||
$select.select2({
|
||||
const defaultSelect2Options = {
|
||||
dropdownParent: $container,
|
||||
})
|
||||
}
|
||||
const passedSelect2Options = <?= json_encode($fieldData['select2']) ?>;
|
||||
const select2Options = Object.assign({}, passedSelect2Options, defaultSelect2Options)
|
||||
$select.select2(select2Options)
|
||||
<?php endif; ?>
|
||||
})
|
||||
|
||||
|
|
|
@ -47,19 +47,28 @@ $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) use ($typeMap, $formTypeMap) {
|
||||
'formatter' => function ($field, $row) use ($typeMap, $formTypeMap, $filtersConfig) {
|
||||
$fieldName = $row['fieldname'];
|
||||
$formType = $formTypeMap[$typeMap[$fieldName]] ?? 'text';
|
||||
$fieldData = [
|
||||
'field' => $fieldName,
|
||||
'type' => $formType,
|
||||
'label' => '',
|
||||
'class' => 'fieldValue form-control-sm'
|
||||
];
|
||||
if (!empty($filtersConfig[$fieldName]['multiple'])) {
|
||||
$fieldData['type'] = 'dropdown';
|
||||
$fieldData['multiple'] = true;
|
||||
$fieldData['select2'] = [
|
||||
'tags' => true,
|
||||
'tokenSeparators' => [',', ' '],
|
||||
];
|
||||
}
|
||||
$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'
|
||||
],
|
||||
'fieldData' => $fieldData,
|
||||
'params' => []
|
||||
]);
|
||||
}
|
||||
|
@ -169,6 +178,36 @@ echo $this->Bootstrap->modal([
|
|||
}
|
||||
setFilteringValues($filteringTable, field, value, operator)
|
||||
}
|
||||
if (tags.length > 0) {
|
||||
setFilteringTags($filteringTable, tags)
|
||||
}
|
||||
}
|
||||
|
||||
function setFilteringValues($filteringTable, field, value, operator) {
|
||||
$row = $filteringTable.find('td > span.fieldName').filter(function() {
|
||||
return $(this).data('fieldname') == field
|
||||
}).closest('tr')
|
||||
$row.find('.fieldOperator').val(operator)
|
||||
const $formElement = $row.find('.fieldValue');
|
||||
if ($formElement.attr('type') === 'datetime-local') {
|
||||
$formElement.val(moment(value).format('yyyy-MM-DDThh:mm:ss'))
|
||||
} else if ($formElement.is('select') && Array.isArray(value)) {
|
||||
let newOptions = [];
|
||||
value.forEach(aValue => {
|
||||
const existingOption = $formElement.find('option').filter(function() {
|
||||
return $(this).val() === aValue
|
||||
})
|
||||
if (existingOption.length == 0) {
|
||||
newOptions.push(new Option(aValue, aValue, true, true))
|
||||
}
|
||||
})
|
||||
$formElement.append(newOptions).trigger('change');
|
||||
} else {
|
||||
$formElement.val(value)
|
||||
}
|
||||
}
|
||||
|
||||
function setFilteringTags($filteringTable, tags) {
|
||||
$select = $filteringTable.closest('.modal-body').find('select.select2-input')
|
||||
let passedTags = []
|
||||
tags.forEach(tagname => {
|
||||
|
@ -185,19 +224,6 @@ echo $this->Bootstrap->modal([
|
|||
.trigger('change')
|
||||
}
|
||||
|
||||
function setFilteringValues($filteringTable, field, value, operator) {
|
||||
$row = $filteringTable.find('td > span.fieldName').filter(function() {
|
||||
return $(this).data('fieldname') == field
|
||||
}).closest('tr')
|
||||
$row.find('.fieldOperator').val(operator)
|
||||
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')
|
||||
|
|
Loading…
Reference in New Issue