Skip to content

Commit

Permalink
feat(filters): add new optional filterShortcuts to Column Filter (#…
Browse files Browse the repository at this point in the history
…1575)

* feat(filters): add new optional `filterShortcuts` to Column Filter
  • Loading branch information
ghiscoding committed Jun 15, 2024
1 parent 025888d commit cbd6ae4
Show file tree
Hide file tree
Showing 22 changed files with 437 additions and 48 deletions.
1 change: 1 addition & 0 deletions docs/column-functionalities/filters/compound-filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [Update Filters Dynamically](input-filter.md#update-filters-dynamically)
- [How to avoid filtering when only Operator dropdown is changed?](#how-to-avoid-filtering-when-only-operator-dropdown-is-changed)
- [Custom Filter Predicate](input-filter.md#custom-filter-predicate)
- [Filter Shortcuts](input-filter.md#filter-shortcuts)

### Description
Compound filters are a combination of 2 elements (Operator Select + Input Filter) used as a filter on a column. This is very useful to make it obvious to the user that there are Operator available and even more useful with a date picker (`Vanilla-Calendar`).
Expand Down
36 changes: 36 additions & 0 deletions docs/column-functionalities/filters/input-filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [Debounce/Throttle Text Search (wait for user to stop typing before filtering)](#debouncethrottle-text-search-wait-for-user-to-stop-typing-before-filtering)
- [Ignore Locale Accent in Text Filter/Sorting](#ignore-locale-accent-in-text-filtersorting)
- [Custom Filter Predicate](#custom-filter-predicate)
- [Filter Shortcuts](#filter-shortcuts)

### Description
Input text filter is the default filter that will be used when the user ommits the `filter.model`.
Expand Down Expand Up @@ -215,3 +216,38 @@ this.columnDefinitions = [
The custom filter predicate above was to answer a Stack Overflow question and will work similarly to an SQL LIKE matcher (it's not perfect and probably requires more work but is enough to demo the usage of a custom filter predicate)

![image](https://github.com/ghiscoding/slickgrid-universal/assets/643976/3e77774e-3a9f-4ca4-bca7-50a033a4b48d)

### Filter Shortcuts

User can declare some Filter Shortcuts, that will be added to the Header Menu of the Column it was assigned. These shortcuts are simply a list of filter search values (e.g. Filter the Blank/Non-Blanks Values), the end user can type the same search values themselves but the shortcuts are simply meant to be quicker without having to know what to type (e.g. Filter Current Year).

The shortcuts can be declared via an array that must include at least a `title` (or `titleKey`) a `searchTerms` array and lastly an optional `operator` can also be provided. The available properties of these shortcut is a merge of Header Menu Item interface (except `command` and `action` which are reserved and assigned internally) and of course the 3 properties mentioned above. The declaration is very similar to how we use it when declaring Grid Presets as shown below

```ts
this.columnDefinitions = [
{
id: 'country', name: 'Country', field: 'country',
filter: {
model: Filters.inputText,
filterShortcuts: [
{ title: 'Blank Values', searchTerms: ['A'], operator: '<', iconCssClass: 'mdi mdi-filter-minus-outline', },
{ title: 'Non-Blank Values', searchTerms: ['A'], operator: '>', iconCssClass: 'mdi mdi-filter-plus-outline', },
]
},
},
{
id: 'finish', name: 'Finish', field: 'finish',
filter: {
model: Filters.dateRange,
filterShortcuts: [
{
// using Locale translations & Tempo to calculate next 30 days
titleKey: 'NEXT_30_DAYS',
iconCssClass: 'mdi mdi-calendar',
searchTerms: [tempoFormat(new Date(), 'YYYY-MM-DD'), tempoFormat(addDay(new Date(), 30), 'YYYY-MM-DD')],
},
]
},
},
];
```
1 change: 1 addition & 0 deletions docs/column-functionalities/filters/range-filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Using a Date Range](#using-a-date-range-filter)
- [Update Filters Dynamically](input-filter.md#update-filters-dynamically)
- [Custom Filter Predicate](input-filter.md#custom-filter-predicate)
- [Filter Shortcuts](input-filter.md#filter-shortcuts)

### Introduction
Range filters allows you to search for a value between 2 min/max values, the 2 most common use case would be to filter between 2 numbers or dates, you can do that with the Slider & Date Range Filters. The range can also be defined as inclusive (`>= 0 and <= 10`) or exclusive (`> 0 and < 10`), the default is exclusive but you can change that, see below for more info.
Expand Down
1 change: 1 addition & 0 deletions docs/column-functionalities/filters/select-filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- [Query against a different field](#query-against-another-field-property)
- [Update Filters Dynamically](input-filter.md#update-filters-dynamically)
- [Custom Filter Predicate](input-filter.md#custom-filter-predicate)
- [Filter Shortcuts](input-filter.md#filter-shortcuts)

### Demo
[Demo Page](https://ghiscoding.github.io/slickgrid-universal/#/example10) / [Demo Component](https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/webpack-demo-vanilla-bundle/src/examples/example10.ts)
Expand Down
2 changes: 2 additions & 0 deletions examples/vite-demo-vanilla-bundle/public/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"EXPORT_TO_EXCEL": "Export to Excel",
"EXPORT_TO_TAB_DELIMITED": "Export in Text format (Tab delimited)",
"EXPORT_TO_TEXT_FORMAT": "Export in Text format",
"FILTER_SHORTCUTS": "Filter Shortcuts",
"FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} of {{totalItems}} items",
"FORCE_FIT_COLUMNS": "Force fit columns",
"FREEZE_COLUMNS": "Freeze Columns",
Expand Down Expand Up @@ -93,6 +94,7 @@
"MEDIUM": "Medium",
"MALE": "Male",
"NAME": "Name",
"NEXT_20_DAYS": "Next 20 days",
"NONE": "None",
"PERCENT_COMPLETE": "% Complete",
"PRIORITY": "Priority",
Expand Down
2 changes: 2 additions & 0 deletions examples/vite-demo-vanilla-bundle/public/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"EXPORT_TO_EXCEL": "Exporter vers Excel",
"EXPORT_TO_TAB_DELIMITED": "Exporter en format texte (délimité par tabulation)",
"EXPORT_TO_TEXT_FORMAT": "Exporter en format texte",
"FILTER_SHORTCUTS": "Raccourcis de filtre",
"FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} de {{totalItems}} éléments",
"FORCE_FIT_COLUMNS": "Ajustement forcé des colonnes",
"FREEZE_COLUMNS": "Geler les colonnes",
Expand Down Expand Up @@ -93,6 +94,7 @@
"MEDIUM": "Moyen",
"MALE": "Masculin",
"NAME": "Nom",
"NEXT_20_DAYS": "20 prochain jours",
"NONE": "Aucun",
"PERCENT_COMPLETE": "% Achevée",
"PRIORITY": "Priorité",
Expand Down
4 changes: 2 additions & 2 deletions examples/vite-demo-vanilla-bundle/src/examples/example10.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ <h6 class="title is-6 italic">
<span class="text-red">(*) NO DATA SHOWN</span>
- just change any of Filters/Sorting/Pages and look at the "GraphQL Query" changing.
Also note that the column Name has a filter with a custom %% operator that behaves like an SQL LIKE operator supporting % wildcards.
Depending on your configuration, your GraphQL Server might already support regex querying (e.g. Hasura [_regex](https://hasura.io/docs/latest/queries/postgres/filters/text-search-operators/#_regex))
or you could add your own implementation (e.g. see this SO: https://stackoverflow.com/a/37981802/1212166).
Depending on your configuration, your GraphQL Server might already support regex querying (e.g. Hasura <a href="https://hasura.io/docs/latest/queries/postgres/filters/text-search-operators/#_regex">_regex</a>)
or you could add your own implementation (e.g. see this <a href="https://stackoverflow.com/a/37981802/1212166">SO</a>).
</h6>

<div class="row">
Expand Down
21 changes: 14 additions & 7 deletions examples/vite-demo-vanilla-bundle/src/examples/example10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { BindingEventService } from '@slickgrid-universal/binding';
import { GraphqlService, type GraphqlPaginatedResult, type GraphqlServiceApi, type GraphqlServiceOption, } from '@slickgrid-universal/graphql';
import { Slicker, type SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { addDay, format } from '@formkit/tempo';
import { addDay, format as tempoFormat } from '@formkit/tempo';
import { type MultipleSelectOption } from 'multiple-select-vanilla';

import { ExampleGridOptions } from './example-grid-options';
Expand Down Expand Up @@ -135,12 +135,19 @@ export default class Example10 {
filterable: true,
filter: {
model: Filters.dateRange,
filterShortcuts: [
{
titleKey: 'NEXT_20_DAYS',
iconCssClass: 'mdi mdi-calendar',
searchTerms: [tempoFormat(new Date(), 'YYYY-MM-DD'), tempoFormat(addDay(new Date(), 20), 'YYYY-MM-DD')],
},
]
}
},
];

const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');
const presetLowestDay = tempoFormat(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = tempoFormat(addDay(new Date(), 20), 'YYYY-MM-DD');

this.gridOptions = {
enableAutoTooltip: true,
Expand Down Expand Up @@ -328,8 +335,8 @@ export default class Example10 {
}

setFiltersDynamically() {
const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');
const presetLowestDay = tempoFormat(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = tempoFormat(addDay(new Date(), 20), 'YYYY-MM-DD');

// we can Set Filters Dynamically (or different filters) afterward through the FilterService
this.sgb.filterService.updateFilters([
Expand All @@ -350,8 +357,8 @@ export default class Example10 {
}

resetToOriginalPresets() {
const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');
const presetLowestDay = tempoFormat(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = tempoFormat(addDay(new Date(), 20), 'YYYY-MM-DD');

this.sgb?.filterService.updateFilters([
// you can use OperatorType or type them as string, e.g.: operator: 'EQ'
Expand Down
20 changes: 17 additions & 3 deletions examples/vite-demo-vanilla-bundle/src/examples/example11.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { BindingEventService } from '@slickgrid-universal/binding';
import { SlickCustomTooltip } from '@slickgrid-universal/custom-tooltip-plugin';
import { ExcelExportService } from '@slickgrid-universal/excel-export';
import { Slicker, type SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { format as tempoFormat, addDay } from '@formkit/tempo';
import { type MultipleSelectOption } from 'multiple-select-vanilla';

import exampleModal from './example11-modal.html?raw';
Expand Down Expand Up @@ -172,15 +173,23 @@ export default class Example11 {
id: 'start', name: 'Start', field: 'start', sortable: true, minWidth: 80,
formatter: Formatters.dateIso,
type: FieldType.date, outputType: FieldType.dateIso,
filterable: true, filter: { model: Filters.compoundDate },
filterable: true,
filter: { model: Filters.compoundDate },
editor: { model: Editors.date, massUpdate: true },
},
{
id: 'finish', name: 'Finish', field: 'finish', sortable: true, minWidth: 80,
editor: { model: Editors.date, massUpdate: true, editorOptions: { range: { min: 'today' } } as VanillaCalendarOption },
formatter: Formatters.dateIso,
type: FieldType.date, outputType: FieldType.dateIso,
filterable: true, filter: { model: Filters.compoundDate },
filterable: true,
filter: {
model: Filters.compoundDate,
filterShortcuts: [
{ title: 'Until Now', searchTerms: [tempoFormat(new Date(), 'YYYY-MM-DD')], operator: '<=', iconCssClass: 'mdi mdi-calendar', },
{ title: 'In the Future', searchTerms: [tempoFormat(addDay(new Date(), 1), 'YYYY-MM-DD')], operator: '>=', iconCssClass: 'mdi mdi-calendar-clock', },
]
},
},
{
id: 'completed', name: 'Completed', field: 'completed', width: 80, minWidth: 80, maxWidth: 100,
Expand Down Expand Up @@ -265,7 +274,11 @@ export default class Example11 {
model: Filters.inputText,
type: 'string',
queryField: 'countryOfOrigin.name',
}
filterShortcuts: [
{ title: 'Blank Values', searchTerms: ['< A'], iconCssClass: 'mdi mdi-filter-minus-outline', },
{ title: 'Non-Blank Values', searchTerms: ['> A'], iconCssClass: 'mdi mdi-filter-plus-outline', },
]
},
},
{
id: 'action', name: 'Action', field: 'action', minWidth: 70, width: 75, maxWidth: 75,
Expand Down Expand Up @@ -343,6 +356,7 @@ export default class Example11 {
},
headerMenu: {
hideFreezeColumnsCommand: false,
subItemChevronClass: 'mdi mdi-chevron-down mdi-rotate-270',
},
gridMenu: {
hideClearFrozenColumnsCommand: false,
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class Constants {
TEXT_EXPORT_TO_EXCEL: 'Export to Excel',
TEXT_EXPORT_TO_TAB_DELIMITED: 'Export in Text format (Tab delimited)',
TEXT_FORCE_FIT_COLUMNS: 'Force fit columns',
TEXT_FILTER_SHORTCUTS: 'Filter Shortcuts',
TEXT_FREEZE_COLUMNS: 'Freeze Columns',
TEXT_GREATER_THAN: 'Greater than',
TEXT_GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to',
Expand Down
Loading

0 comments on commit cbd6ae4

Please sign in to comment.