chg: [element:generic_index] Improved quick filter functionality and UI
parent
c4ef14077f
commit
13c8f3f7c5
|
@ -340,6 +340,7 @@ class CRUDComponent extends Component
|
|||
protected function setQuickFilters(array $params, \Cake\ORM\Query $query, array $quickFilterFields): \Cake\ORM\Query
|
||||
{
|
||||
$queryConditions = [];
|
||||
$this->Controller->set('quickFilter', empty($quickFilterFields) ? [] : $quickFilterFields);
|
||||
if (!empty($params['quickFilter']) && !empty($quickFilterFields)) {
|
||||
$this->Controller->set('quickFilterValue', $params['quickFilter']);
|
||||
foreach ($quickFilterFields as $filterField) {
|
||||
|
|
|
@ -23,7 +23,6 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'button' => __('Filter'),
|
||||
'placeholder' => __('Enter value to search'),
|
||||
'data' => '',
|
||||
'value' => $quickFilterValue,
|
||||
'searchKey' => 'value'
|
||||
]
|
||||
]
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
empty($data['placeholder']) ? '' : h($data['placeholder']),
|
||||
empty($data['id']) ? 'quickFilterField' : h($data['id']),
|
||||
empty($data['searchKey']) ? 'searchall' : h($data['searchKey']),
|
||||
empty($data['value']) ? '' : h($data['value'])
|
||||
empty($data['value']) ? (!empty($quickFilterValue) ? h($quickFilterValue) : '') : h($data['value'])
|
||||
);
|
||||
echo sprintf(
|
||||
'<div class="input-group" data-table-random-value="%s" style="margin-left: auto;">%s%s</div>',
|
||||
|
@ -44,6 +44,7 @@
|
|||
var controller = '<?= $this->request->getParam('controller') ?>';
|
||||
var action = '<?= $this->request->getParam('action') ?>';
|
||||
var additionalUrlParams = '';
|
||||
var quickFilter = <?= json_encode($quickFilter) ?>;
|
||||
<?php
|
||||
if (!empty($data['additionalUrlParams'])) {
|
||||
echo sprintf(
|
||||
|
@ -53,6 +54,13 @@
|
|||
}
|
||||
?>
|
||||
var randomValue = '<?= h($tableRandomValue) ?>';
|
||||
$(`#quickFilterField-${randomValue}`).popover({
|
||||
title: '<?= __('Searcheable fields') ?>',
|
||||
content: function() { return buildPopoverQuickFilterBody(quickFilter) },
|
||||
html: true,
|
||||
sanitize: false,
|
||||
trigger: 'manual',
|
||||
})
|
||||
$(`#quickFilterButton-${randomValue}`).click((e) => {
|
||||
doFilter($(e.target))
|
||||
});
|
||||
|
@ -61,9 +69,14 @@
|
|||
const $button = $(`#quickFilterButton-${randomValue}`)
|
||||
doFilter($button)
|
||||
}
|
||||
}).on('focus', (e) => {
|
||||
$(`#quickFilterField-${randomValue}`).popover('show')
|
||||
}).on('focusout', (e) => {
|
||||
$(`#quickFilterField-${randomValue}`).popover('hide')
|
||||
});
|
||||
|
||||
function doFilter($button) {
|
||||
$(`#quickFilterField-${randomValue}`).popover('hide')
|
||||
const encodedFilters = encodeURIComponent($(`#quickFilterField-${randomValue}`).val())
|
||||
const url = `/${controller}/${action}${additionalUrlParams}?quickFilter=${encodedFilters}`
|
||||
UI.reload(url, $(`#table-container-${randomValue}`), $(`#table-container-${randomValue} table.table`), [{
|
||||
|
@ -71,5 +84,35 @@
|
|||
config: {}
|
||||
}])
|
||||
}
|
||||
|
||||
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') ?>')
|
||||
.attr('title', searchContain ? '<?= __('The search value will be used as a substring') ?>' : '<?= __('The search value must strictly match') ?>')
|
||||
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
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -649,7 +649,7 @@ class OverlayFactory {
|
|||
static defaultOptions = {
|
||||
text: '',
|
||||
variant: 'light',
|
||||
opacity: 0.85,
|
||||
opacity: 0.15,
|
||||
blur: '2px',
|
||||
rounded: false,
|
||||
auto: true,
|
||||
|
@ -828,4 +828,74 @@ class FormValidationHelper {
|
|||
$(this.form).find('.invalid-feedback').remove()
|
||||
$(this.form).parent().find('.alert').remove()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HtmlHelper {
|
||||
static table(head=[], body=[], options={}) {
|
||||
const $table = $('<table/>')
|
||||
const $thead = $('<thead/>')
|
||||
const $tbody = $('<tbody/>')
|
||||
|
||||
$table.addClass('table')
|
||||
if (options.striped) {
|
||||
$table.addClass('table-striped')
|
||||
}
|
||||
if (options.bordered) {
|
||||
$table.addClass('table-bordered')
|
||||
}
|
||||
if (options.borderless) {
|
||||
$table.addClass('table-borderless')
|
||||
}
|
||||
if (options.hoverable) {
|
||||
$table.addClass('table-hover')
|
||||
}
|
||||
if (options.small) {
|
||||
$table.addClass('table-sm')
|
||||
}
|
||||
if (options.variant) {
|
||||
$table.addClass(`table-${options.variant}`)
|
||||
}
|
||||
if (options.tableClass) {
|
||||
$table.addClass(options.tableClass)
|
||||
}
|
||||
|
||||
const $caption = $('<caption/>')
|
||||
if (options.caption) {
|
||||
if (options.caption instanceof jQuery) {
|
||||
$caption = options.caption
|
||||
} else {
|
||||
$caption.text(options.caption)
|
||||
}
|
||||
}
|
||||
|
||||
const $theadRow = $('<tr/>')
|
||||
head.forEach(head => {
|
||||
if (head instanceof jQuery) {
|
||||
$theadRow.append($('<td/>').append(head))
|
||||
} else {
|
||||
$theadRow.append($('<th/>').text(head))
|
||||
}
|
||||
})
|
||||
$thead.append($theadRow)
|
||||
|
||||
body.forEach(row => {
|
||||
const $bodyRow = $('<tr/>')
|
||||
row.forEach(item => {
|
||||
if (item instanceof jQuery) {
|
||||
$bodyRow.append($('<td/>').append(item))
|
||||
} else {
|
||||
$bodyRow.append($('<td/>').text(item))
|
||||
}
|
||||
})
|
||||
$tbody.append($bodyRow)
|
||||
})
|
||||
|
||||
$table.append($caption, $thead, $tbody)
|
||||
if (options.responsive) {
|
||||
options.responsiveBreakpoint = options.responsiveBreakpoint !== undefined ? options.responsiveBreakpoint : ''
|
||||
$table = $('<div/>').addClass(options.responsiveBreakpoint !== undefined ? `table-responsive-${options.responsiveBreakpoint}` : 'table-responsive').append($table)
|
||||
}
|
||||
return $table
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue