2020-05-29 13:41:58 +02:00
|
|
|
<?php
|
|
|
|
/*
|
|
|
|
* Run a quick filter against the current API endpoint
|
|
|
|
* Result is passed via URL parameters, by default using the searchall key
|
|
|
|
* Valid parameters:
|
|
|
|
* - data: data-* fields
|
|
|
|
* - searchKey: data-search-key, specifying the key to be used (defaults to searchall)
|
|
|
|
* - fa-icon: an icon to use for the lookup $button
|
|
|
|
* - buttong: Text to use for the lookup button
|
|
|
|
* - cancel: Button for quickly removing the filters
|
|
|
|
* - placeholder: optional placeholder for the text field
|
|
|
|
* - id: element ID for the input field - defaults to quickFilterField
|
|
|
|
*/
|
|
|
|
if (!isset($data['requirement']) || $data['requirement']) {
|
2021-06-14 08:37:00 +02:00
|
|
|
if (!empty($data['quickFilter'])) {
|
|
|
|
$quickFilter = $data['quickFilter'];
|
|
|
|
}
|
2021-03-15 22:47:13 +01:00
|
|
|
$filterEffective = !empty($quickFilter); // No filters will be picked up, thus rendering the filtering useless
|
2021-03-10 09:43:36 +01:00
|
|
|
$filteringButton = '';
|
|
|
|
if (!empty($data['allowFilering'])) {
|
|
|
|
$activeFilters = !empty($activeFilters) ? $activeFilters : [];
|
2021-11-10 12:07:27 +01:00
|
|
|
$numberActiveFilters = count($activeFilters);
|
|
|
|
if (!empty($activeFilters['filteringMetaFields'])) {
|
|
|
|
$numberActiveFilters += count($activeFilters['filteringMetaFields']) - 1;
|
|
|
|
}
|
2021-03-10 09:43:36 +01:00
|
|
|
$buttonConfig = [
|
|
|
|
'icon' => 'filter',
|
|
|
|
'params' => [
|
|
|
|
'title' => __('Filter index'),
|
|
|
|
'id' => sprintf('toggleFilterButton-%s', h($tableRandomValue))
|
|
|
|
]
|
|
|
|
];
|
|
|
|
if (count($activeFilters) > 0) {
|
|
|
|
$buttonConfig['badge'] = [
|
|
|
|
'variant' => 'light',
|
2021-11-10 12:07:27 +01:00
|
|
|
'text' => $numberActiveFilters,
|
|
|
|
'title' => __n('There is {0} active filter', 'There are {0} active filters', $numberActiveFilters, $numberActiveFilters)
|
2021-03-10 09:43:36 +01:00
|
|
|
];
|
|
|
|
}
|
|
|
|
$filteringButton = $this->Bootstrap->button($buttonConfig);
|
|
|
|
}
|
2020-05-29 13:41:58 +02:00
|
|
|
$button = empty($data['button']) && empty($data['fa-icon']) ? '' : sprintf(
|
2021-09-17 13:04:37 +02:00
|
|
|
'<button class="btn btn-primary" %s id="quickFilterButton-%s" %s>%s%s</button>%s',
|
2020-05-29 13:41:58 +02:00
|
|
|
empty($data['data']) ? '' : h($data['data']),
|
|
|
|
h($tableRandomValue),
|
2021-03-15 22:47:13 +01:00
|
|
|
$filterEffective ? '' : 'disabled="disabled"',
|
2020-05-29 13:41:58 +02:00
|
|
|
empty($data['fa-icon']) ? '' : sprintf('<i class="fa fa-%s"></i>', h($data['fa-icon'])),
|
2021-03-10 09:43:36 +01:00
|
|
|
empty($data['button']) ? '' : h($data['button']),
|
|
|
|
$filteringButton
|
2020-05-29 13:41:58 +02:00
|
|
|
);
|
|
|
|
if (!empty($data['cancel'])) {
|
|
|
|
$button .= $this->element('/genericElements/ListTopBar/element_simple', array('data' => $data['cancel']));
|
|
|
|
}
|
|
|
|
$input = sprintf(
|
2021-03-15 22:47:13 +01:00
|
|
|
'<input id="quickFilterField-%s" type="text" class="form-control" placeholder="%s" aria-label="%s" style="padding: 2px 6px;" id="%s" data-searchkey="%s" value="%s" %s>',
|
2020-05-29 13:41:58 +02:00
|
|
|
h($tableRandomValue),
|
|
|
|
empty($data['placeholder']) ? '' : h($data['placeholder']),
|
|
|
|
empty($data['placeholder']) ? '' : h($data['placeholder']),
|
|
|
|
empty($data['id']) ? 'quickFilterField' : h($data['id']),
|
|
|
|
empty($data['searchKey']) ? 'searchall' : h($data['searchKey']),
|
2021-03-15 22:47:13 +01:00
|
|
|
empty($data['value']) ? (!empty($quickFilterValue) ? h($quickFilterValue) : '') : h($data['value']),
|
|
|
|
$filterEffective ? '' : 'disabled="disabled"'
|
2020-05-29 13:41:58 +02:00
|
|
|
);
|
|
|
|
echo sprintf(
|
2021-10-28 09:27:30 +02:00
|
|
|
'<div class="input-group %s" data-table-random-value="%s" style="margin-left: auto;">%s%s</div>',
|
|
|
|
$filterEffective ? '' : 'd-none',
|
2020-05-29 13:41:58 +02:00
|
|
|
h($tableRandomValue),
|
|
|
|
$input,
|
|
|
|
$button
|
|
|
|
);
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
<script type="text/javascript">
|
|
|
|
$(document).ready(function() {
|
|
|
|
var controller = '<?= $this->request->getParam('controller') ?>';
|
|
|
|
var action = '<?= $this->request->getParam('action') ?>';
|
2021-01-13 14:23:11 +01:00
|
|
|
var additionalUrlParams = '';
|
2021-01-18 17:25:18 +01:00
|
|
|
var quickFilter = <?= json_encode(!empty($quickFilter) ? $quickFilter : []) ?>;
|
2021-03-10 09:43:36 +01:00
|
|
|
var activeFilters = <?= json_encode(!empty($activeFilters) ? $activeFilters : []) ?>;
|
2021-01-13 14:23:11 +01:00
|
|
|
<?php
|
|
|
|
if (!empty($data['additionalUrlParams'])) {
|
|
|
|
echo sprintf(
|
|
|
|
'additionalUrlParams = \'/%s\';',
|
|
|
|
h($data['additionalUrlParams'])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
?>
|
2020-05-29 13:41:58 +02:00
|
|
|
var randomValue = '<?= h($tableRandomValue) ?>';
|
2021-09-17 17:51:45 +02:00
|
|
|
new bootstrap.Popover(`#quickFilterField-${randomValue}`, {
|
2021-01-15 16:58:46 +01:00
|
|
|
title: '<?= __('Searcheable fields') ?>',
|
|
|
|
content: function() { return buildPopoverQuickFilterBody(quickFilter) },
|
2021-09-17 17:51:45 +02:00
|
|
|
placement: 'left',
|
2021-01-15 16:58:46 +01:00
|
|
|
html: true,
|
|
|
|
sanitize: false,
|
|
|
|
trigger: 'manual',
|
|
|
|
})
|
2021-01-15 14:42:38 +01:00
|
|
|
$(`#quickFilterButton-${randomValue}`).click((e) => {
|
|
|
|
doFilter($(e.target))
|
2020-05-29 13:41:58 +02:00
|
|
|
});
|
2021-01-15 12:12:55 +01:00
|
|
|
$(`#quickFilterField-${randomValue}`).on('keypress', (e) => {
|
2021-01-15 14:42:38 +01:00
|
|
|
if (e.which === 13) {
|
|
|
|
const $button = $(`#quickFilterButton-${randomValue}`)
|
2021-01-15 12:12:55 +01:00
|
|
|
doFilter($button)
|
2020-05-29 13:41:58 +02:00
|
|
|
}
|
2021-01-15 16:58:46 +01:00
|
|
|
}).on('focus', (e) => {
|
2021-09-17 17:51:45 +02:00
|
|
|
bootstrap.Popover.getInstance(`#quickFilterField-${randomValue}`).show()
|
2021-01-15 16:58:46 +01:00
|
|
|
}).on('focusout', (e) => {
|
2021-09-17 17:51:45 +02:00
|
|
|
bootstrap.Popover.getInstance(`#quickFilterField-${randomValue}`).hide()
|
2020-05-29 13:41:58 +02:00
|
|
|
});
|
2021-01-15 12:12:55 +01:00
|
|
|
|
2021-03-10 09:43:36 +01:00
|
|
|
$(`#toggleFilterButton-${randomValue}`)
|
|
|
|
.data('activeFilters', activeFilters)
|
|
|
|
.click(function() {
|
|
|
|
const url = `/${controller}/filtering`
|
|
|
|
const reloadUrl = `/${controller}/index${additionalUrlParams}`
|
2021-06-30 08:33:09 +02:00
|
|
|
openFilteringModal(this, url, reloadUrl, $(`#index-table-${randomValue}`));
|
2021-03-10 09:43:36 +01:00
|
|
|
})
|
|
|
|
|
2021-01-15 12:12:55 +01:00
|
|
|
function doFilter($button) {
|
2021-09-17 17:51:45 +02:00
|
|
|
bootstrap.Popover.getInstance(`#quickFilterField-${randomValue}`).hide()
|
2021-01-15 12:12:55 +01:00
|
|
|
const encodedFilters = encodeURIComponent($(`#quickFilterField-${randomValue}`).val())
|
|
|
|
const url = `/${controller}/${action}${additionalUrlParams}?quickFilter=${encodedFilters}`
|
|
|
|
UI.reload(url, $(`#table-container-${randomValue}`), $(`#table-container-${randomValue} table.table`), [{
|
|
|
|
node: $button,
|
|
|
|
config: {}
|
|
|
|
}])
|
|
|
|
}
|
2021-01-15 16:58:46 +01:00
|
|
|
|
|
|
|
function buildPopoverQuickFilterBody(quickFilter) {
|
|
|
|
let tableData = []
|
|
|
|
quickFilter.forEach(field => {
|
|
|
|
let fieldName, searchContain
|
|
|
|
if (typeof field === 'object') {
|
|
|
|
fieldName = Object.keys(field)[0];
|
|
|
|
searchContain = field[fieldName]
|
|
|
|
} else {
|
|
|
|
fieldName = field
|
|
|
|
searchContain = false
|
|
|
|
}
|
|
|
|
$searchType = $('<span/>')
|
|
|
|
.text(searchContain ? '<?= __('Contain') ?>' : '<?= __('Exact match') ?>')
|
2021-03-19 11:17:00 +01:00
|
|
|
.attr('title', searchContain ? '<?= __('The search value can be used as a substring with the wildcard operator `%`') ?>' : '<?= __('The search value must strictly match') ?>')
|
|
|
|
.attr('style', 'cursor: help;')
|
2021-01-15 16:58:46 +01:00
|
|
|
tableData.push([fieldName, $searchType])
|
|
|
|
});
|
|
|
|
tableData.sort((a, b) => a[0] < b[0] ? -1 : 1)
|
|
|
|
$table = HtmlHelper.table(
|
|
|
|
['<?= __('Field name') ?>', '<?= __('Search type') ?>'],
|
|
|
|
tableData,
|
|
|
|
{
|
|
|
|
small: true,
|
|
|
|
tableClass: ['mb-0'],
|
|
|
|
caption: '<?= __('All these fields will be searched simultaneously') ?>'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
return $table[0].outerHTML
|
|
|
|
}
|
|
|
|
|
2021-03-10 09:43:36 +01:00
|
|
|
function openFilteringModal(clicked, url, reloadUrl, tableId) {
|
2021-06-30 08:33:09 +02:00
|
|
|
const modalPromise = UI.submissionModalForIndex(url, reloadUrl, tableId)
|
|
|
|
UI.overlayUntilResolve(clicked, modalPromise)
|
2021-03-10 09:43:36 +01:00
|
|
|
}
|
2020-05-29 13:41:58 +02:00
|
|
|
});
|
|
|
|
</script>
|