diff --git a/src/Controller/Component/CRUDComponent.php b/src/Controller/Component/CRUDComponent.php
index c869701..c67df3f 100644
--- a/src/Controller/Component/CRUDComponent.php
+++ b/src/Controller/Component/CRUDComponent.php
@@ -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) {
diff --git a/templates/Individuals/index.php b/templates/Individuals/index.php
index 0b92b4e..91520e1 100644
--- a/templates/Individuals/index.php
+++ b/templates/Individuals/index.php
@@ -23,7 +23,6 @@ echo $this->element('genericElements/IndexTable/index_table', [
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
- 'value' => $quickFilterValue,
'searchKey' => 'value'
]
]
diff --git a/templates/element/genericElements/ListTopBar/group_search.php b/templates/element/genericElements/ListTopBar/group_search.php
index c05fd39..6347fa8 100644
--- a/templates/element/genericElements/ListTopBar/group_search.php
+++ b/templates/element/genericElements/ListTopBar/group_search.php
@@ -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(
'
%s%s
',
@@ -44,6 +44,7 @@
var controller = '= $this->request->getParam('controller') ?>';
var action = '= $this->request->getParam('action') ?>';
var additionalUrlParams = '';
+ var quickFilter = = json_encode($quickFilter) ?>;
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 = $('')
+ .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
+ }
+
});
diff --git a/webroot/js/bootstrap-helper.js b/webroot/js/bootstrap-helper.js
index dd3e50e..a24bec2 100644
--- a/webroot/js/bootstrap-helper.js
+++ b/webroot/js/bootstrap-helper.js
@@ -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 = $('')
+ const $thead = $('')
+ const $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 = $('')
+ if (options.caption) {
+ if (options.caption instanceof jQuery) {
+ $caption = options.caption
+ } else {
+ $caption.text(options.caption)
+ }
+ }
+
+ const $theadRow = $('
')
+ head.forEach(head => {
+ if (head instanceof jQuery) {
+ $theadRow.append($(' | ').append(head))
+ } else {
+ $theadRow.append($(' | ').text(head))
+ }
+ })
+ $thead.append($theadRow)
+
+ body.forEach(row => {
+ const $bodyRow = $('
')
+ row.forEach(item => {
+ if (item instanceof jQuery) {
+ $bodyRow.append($(' | ').append(item))
+ } else {
+ $bodyRow.append($(' | ').text(item))
+ }
+ })
+ $tbody.append($bodyRow)
+ })
+
+ $table.append($caption, $thead, $tbody)
+ if (options.responsive) {
+ options.responsiveBreakpoint = options.responsiveBreakpoint !== undefined ? options.responsiveBreakpoint : ''
+ $table = $('').addClass(options.responsiveBreakpoint !== undefined ? `table-responsive-${options.responsiveBreakpoint}` : 'table-responsive').append($table)
+ }
+ return $table
+ }
}
\ No newline at end of file