@operato/data-grist 2.0.0-alpha.132 → 2.0.0-alpha.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/src/data-grid/data-grid-header.js +1 -1
  3. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  4. package/dist/src/data-grist.d.ts +5 -6
  5. package/dist/src/data-grist.js +53 -32
  6. package/dist/src/data-grist.js.map +1 -1
  7. package/dist/src/filters/filter-styles.js +21 -11
  8. package/dist/src/filters/filter-styles.js.map +1 -1
  9. package/dist/src/filters/filters-form.d.ts +8 -2
  10. package/dist/src/filters/filters-form.js +128 -62
  11. package/dist/src/filters/filters-form.js.map +1 -1
  12. package/dist/src/personalizer/ox-grist-filter-personalizer.d.ts +8 -0
  13. package/dist/src/personalizer/ox-grist-filter-personalizer.js +177 -0
  14. package/dist/src/personalizer/ox-grist-filter-personalizer.js.map +1 -0
  15. package/dist/src/personalizer/ox-grist-personalizer.d.ts +0 -2
  16. package/dist/src/personalizer/ox-grist-personalizer.js +15 -9
  17. package/dist/src/personalizer/ox-grist-personalizer.js.map +1 -1
  18. package/dist/src/types.d.ts +11 -0
  19. package/dist/src/types.js.map +1 -1
  20. package/dist/stories/grid-setting.stories.d.ts +1 -0
  21. package/dist/stories/grid-setting.stories.js +21 -25
  22. package/dist/stories/grid-setting.stories.js.map +1 -1
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +6 -5
  25. package/src/data-grid/data-grid-header.ts +1 -1
  26. package/src/data-grist.ts +58 -36
  27. package/src/filters/filter-styles.ts +21 -11
  28. package/src/filters/filters-form.ts +196 -125
  29. package/src/personalizer/ox-grist-filter-personalizer.ts +191 -0
  30. package/src/personalizer/ox-grist-personalizer.ts +15 -5
  31. package/src/types.ts +12 -0
  32. package/stories/grid-setting.stories.ts +22 -25
package/src/data-grist.ts CHANGED
@@ -10,6 +10,7 @@ import isEqual from 'lodash-es/isEqual'
10
10
  import Headroom from '@operato/headroom'
11
11
  import { pulltorefresh } from '@operato/pull-to-refresh'
12
12
  import { HeadroomStyles, ScrollbarStyles, SpinnerStyles } from '@operato/styles'
13
+ import { PagePreferenceProvider } from '@operato/p13n'
13
14
  import { SnapshotTaker, TimeCapsule } from '@operato/utils'
14
15
 
15
16
  import { buildConfig } from './configure/config-builder'
@@ -171,12 +172,12 @@ export class DataGrist extends LitElement implements DataConsumer {
171
172
  */
172
173
  @property({ type: Boolean, attribute: 'url-params-sensitive' }) urlParamsSensitive?: boolean
173
174
 
174
- @property({ type: Object }) personalConfigProvider?: {
175
- load(): PersonalGristPreference | Promise<PersonalGristPreference | undefined> | undefined
176
- save(
177
- preference?: PersonalGristPreference
178
- ): PersonalGristPreference | Promise<PersonalGristPreference | undefined> | undefined
179
- reset(): void | Promise<void>
175
+ @property({ type: Object }) personalConfigProvider: PagePreferenceProvider = {
176
+ load: () => {
177
+ return {}
178
+ },
179
+ save: (preference: any) => preference,
180
+ reset: () => {}
180
181
  }
181
182
 
182
183
  @state() personalConfig?: {
@@ -202,6 +203,9 @@ export class DataGrist extends LitElement implements DataConsumer {
202
203
  private originMarginTop?: string
203
204
  private lastLocation: { origin?: string; pathname?: string; search?: string } = {}
204
205
 
206
+ /* 그리드가 준비되기 전에 fetch 요청이 있었음을 나타내는 플래그임 */
207
+ private pendingFetch?: boolean
208
+
205
209
  private popstateEventHandler: EventListener = ((e: Event) => {
206
210
  const { origin, pathname, search } = window.location
207
211
  if (
@@ -315,46 +319,56 @@ export class DataGrist extends LitElement implements DataConsumer {
315
319
  }
316
320
 
317
321
  public applyUpdatedConfiguration() {
318
- if (!this.config?.columns) {
322
+ if (!this.personalConfig) {
319
323
  return
320
324
  }
321
325
 
322
326
  const config = { ...this.config }
323
327
  const columns: Partial<ColumnConfig>[] = config.columns
324
328
 
325
- if (this.personalConfig) {
326
- const { columns: personalColumns } = this.personalConfig
329
+ const { columns: personalColumns, sorters, pagination, mode } = this.personalConfig
330
+
331
+ if (personalColumns) {
332
+ const xcolumns = columns.map((column: Partial<ColumnConfig>) => {
333
+ const personalColumn = personalColumns.find(pcolumn => pcolumn.name == column.name)
334
+ return personalColumn ? { ...column, ...personalColumn } : column
335
+ })
336
+
337
+ function reorderList(a: { name: string }[], b: { name: string }[]): { name: string }[] {
338
+ // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
339
+ const result = new Array(a.length)
327
340
 
328
- if (personalColumns) {
329
- const xcolumns = columns.map((column: Partial<ColumnConfig>) => {
330
- const personalColumn = personalColumns.find(pcolumn => pcolumn.name == column.name)
331
- return personalColumn ? { ...column, ...personalColumn } : column
341
+ // b 배열에 없는 아이템은 원래 위치로 채움
342
+ a.forEach((item, index) => {
343
+ if (!item.name || !b.find(bi => bi.name == item.name)) {
344
+ result[index] = item
345
+ }
332
346
  })
333
347
 
334
- function reorderList(a: { name: string }[], b: { name: string }[]): { name: string }[] {
335
- // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
336
- const result = new Array(a.length)
348
+ b.forEach(item => {
349
+ const ai = a.find(ai => ai.name == item.name)
350
+ if (ai) {
351
+ result[result.findIndex(slot => slot === undefined)] = ai
352
+ }
353
+ })
337
354
 
338
- // b 배열에 없는 아이템은 원래 위치로 채움
339
- a.forEach((item, index) => {
340
- if (!item.name || !b.find(bi => bi.name == item.name)) {
341
- result[index] = item
342
- }
343
- })
355
+ return result
356
+ }
344
357
 
345
- b.forEach(item => {
346
- const ai = a.find(ai => ai.name == item.name)
347
- if (ai) {
348
- result[result.findIndex(slot => slot === undefined)] = ai
349
- }
350
- })
358
+ // 배열 재정렬 실행
359
+ config.columns = reorderList(xcolumns as any, personalColumns as any)
360
+ }
351
361
 
352
- return result
353
- }
362
+ if (pagination) {
363
+ config.pagination = pagination
364
+ }
354
365
 
355
- // 배열 재정렬 실행
356
- config.columns = reorderList(xcolumns as any, personalColumns as any)
357
- }
366
+ if (sorters) {
367
+ config.sorters = sorters
368
+ }
369
+
370
+ if (mode) {
371
+ this.mode = mode
358
372
  }
359
373
 
360
374
  this._config = buildConfig({
@@ -404,7 +418,8 @@ export class DataGrist extends LitElement implements DataConsumer {
404
418
  this.dataProvider.limit = limit || pages[0] || ZERO_PAGES[0]
405
419
  }
406
420
 
407
- if (!this.urlParamsSensitive && !this.explicitFetch) {
421
+ if (this.pendingFetch || (!this.urlParamsSensitive && !this.explicitFetch)) {
422
+ this.pendingFetch = false
408
423
  this.fetch()
409
424
  }
410
425
  }
@@ -546,9 +561,10 @@ export class DataGrist extends LitElement implements DataConsumer {
546
561
  * @param {boolean} reset - If true, the method resets the scroll position to the top.
547
562
  */
548
563
  async fetch(reset = true) {
549
- if (!this.compiledConfig) {
564
+ if (this.compiledConfig === ZERO_CONFIG) {
550
565
  /* avoid to be here */
551
566
  console.warn('grist is not configured yet.')
567
+ this.pendingFetch = true
552
568
  return
553
569
  }
554
570
 
@@ -574,6 +590,8 @@ export class DataGrist extends LitElement implements DataConsumer {
574
590
  sortings: this.sorters || this.compiledConfig?.sorters,
575
591
  filters: this.filters
576
592
  })
593
+
594
+ this.pagination && (this.pagination!.limit = limit)
577
595
  }
578
596
  }
579
597
  }
@@ -589,7 +607,7 @@ export class DataGrist extends LitElement implements DataConsumer {
589
607
  await this.requestUpdate()
590
608
  }
591
609
 
592
- if (changes.has('personalConfigProvider') && this.personalConfigProvider) {
610
+ if (changes.has('personalConfigProvider')) {
593
611
  this.personalConfig = await this.personalConfigProvider.load()
594
612
  } else if (changes.has('config') || changes.has('personalConfig')) {
595
613
  this.applyUpdatedConfiguration()
@@ -1151,4 +1169,8 @@ export class DataGrist extends LitElement implements DataConsumer {
1151
1169
  })
1152
1170
  )
1153
1171
  }
1172
+
1173
+ getCurrentLimit() {
1174
+ return this.dataProvider?.limit || ZERO_PAGINATION.limit
1175
+ }
1154
1176
  }
@@ -47,10 +47,6 @@ export const FilterStyles = css`
47
47
  background-color: var(--ox-filters-input-background-color, transparent);
48
48
  }
49
49
 
50
- label > span + * {
51
- min-width: 120px;
52
- }
53
-
54
50
  ox-select:focus,
55
51
  input:focus {
56
52
  outline: none;
@@ -88,15 +84,29 @@ export const FilterStyles = css`
88
84
  --ox-filters-input-font: normal 16px var(--theme-font);
89
85
  }
90
86
 
91
- input[from],
92
- input[to] {
93
- max-width: 44%;
87
+ ox-input-barcode {
88
+ max-width: unset;
89
+ flex: 1;
90
+ }
91
+
92
+ ox-input-search {
93
+ max-width: unset;
94
+ }
95
+
96
+ ox-select {
97
+ max-width: unset;
98
+ }
99
+
100
+ ox-checkbox {
101
+ max-width: unset;
102
+ }
103
+
104
+ input[type='number'] {
105
+ max-width: unset;
94
106
  }
95
107
 
96
- input[type*='datetime'][from],
97
- input[type*='datetime'][to] {
98
- padding-right: var(--padding-narrow);
99
- min-width: 91%;
108
+ input {
109
+ flex: 1;
100
110
  }
101
111
  }
102
112
  `
@@ -6,11 +6,12 @@ import '@operato/input/ox-input-search.js'
6
6
  import { css, html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'
7
7
  import { customElement, property, queryAsync, state } from 'lit/decorators.js'
8
8
 
9
+ import { PagePreferenceProvider } from '@operato/p13n'
9
10
  import { getDefaultValue } from '@operato/time-calculator'
10
11
 
11
- import { FilterConfigObject } from '..'
12
+ import { FilterConfigObject, FilterPreference } from '../types.js'
12
13
  import { DataGrist } from '../data-grist'
13
- import { ColumnConfig, FilterOperator, FilterValue, GristConfig } from '../types'
14
+ import { ColumnConfig, FilterOperator, FilterValue, GristConfig, PersonalGristPreference } from '../types'
14
15
  import { FilterStyles } from './filter-styles'
15
16
  import { getFilterRenderer } from './registry'
16
17
 
@@ -50,8 +51,9 @@ export class OxFiltersForm extends LitElement {
50
51
  }
51
52
 
52
53
  @media only screen and (max-width: 460px) {
53
- label[between] {
54
- display: block;
54
+ form {
55
+ flex-direction: column;
56
+ flex-flow: column;
55
57
  }
56
58
  }
57
59
  `
@@ -62,6 +64,10 @@ export class OxFiltersForm extends LitElement {
62
64
  @property({ type: Boolean, attribute: 'autofocus' }) autofocus: boolean = true
63
65
  @property({ type: Boolean, attribute: 'empty', reflect: true }) empty: boolean = true
64
66
 
67
+ @state() personalConfigProvider?: PagePreferenceProvider
68
+ @state() personalConfig?: PersonalGristPreference
69
+ @state() personalFilters?: FilterPreference[]
70
+
65
71
  @state() config!: GristConfig
66
72
  @state() filterColumns: ColumnConfig[] = []
67
73
  @state() searchColumns: ColumnConfig[] = []
@@ -78,6 +84,7 @@ export class OxFiltersForm extends LitElement {
78
84
 
79
85
  if (grist) {
80
86
  this.config = grist.compiledConfig
87
+ this.personalConfigProvider = grist.personalConfigProvider
81
88
 
82
89
  grist.addEventListener('config-change', (e: Event) => {
83
90
  this.config = (e as CustomEvent).detail
@@ -139,44 +146,11 @@ export class OxFiltersForm extends LitElement {
139
146
  }
140
147
  }
141
148
 
142
- updated(changes: PropertyValues<this>) {
143
- if (changes.has('config')) {
144
- const filters = this.config.columns.filter(columnConfig => !!columnConfig.filter)
145
- this.filterColumns = filters.filter((columnConfig: ColumnConfig) => {
146
- const filter = columnConfig.filter as FilterConfigObject
147
- return filter!.operator !== 'search'
148
- })
149
- this.searchColumns = filters.filter(columnConfig => {
150
- const filter = columnConfig.filter as FilterConfigObject
151
- return filter!.operator === 'search'
152
- })
153
-
154
- const grist = this.closest('ox-grist') as DataGrist
155
-
156
- this.value = (grist?.filters || []).map(filter => {
157
- return {
158
- ...filter,
159
- value: this.buildDefaultValue(filter!.operator, filter!.value)
160
- }
161
- })
162
-
163
- this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0
164
-
165
- this.autoUpdateTargetsOnChange = {}
166
- this.filterColumns
167
- ?.filter(({ filter }) => {
168
- return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0
169
- })
170
- .map(({ name, filter }) => {
171
- const boundTo = (filter as FilterConfigObject).boundTo
172
-
173
- boundTo!.forEach(to => {
174
- const origin = this.autoUpdateTargetsOnChange[to] || []
175
- if (name && !origin.includes(name)) {
176
- this.autoUpdateTargetsOnChange[to] = [...origin, name]
177
- }
178
- })
179
- })
149
+ async updated(changes: PropertyValues<this>) {
150
+ if (changes.has('personalConfigProvider') && this.personalConfigProvider) {
151
+ this.personalConfig = await this.personalConfigProvider.load()
152
+ } else if (changes.has('config') || changes.has('personalConfig')) {
153
+ this.applyUpdatedConfiguration()
180
154
  }
181
155
  }
182
156
 
@@ -197,93 +171,189 @@ export class OxFiltersForm extends LitElement {
197
171
  grist && grist.fetch()
198
172
  }}
199
173
  >
200
- ${this.searchColumns.length === 0 || this.withoutSearch
201
- ? html``
202
- : html`
203
- <ox-input-search name="search" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>
204
- `}
205
- ${this.filterColumns.map((column: ColumnConfig) => {
206
- const { name, header, label, filter } = column
207
-
208
- const type = (filter as FilterConfigObject).type
209
- const operator = (filter as FilterConfigObject).operator
210
- const filterLabel = (filter as FilterConfigObject).label
211
-
212
- const labelText =
213
- filterLabel !== undefined
214
- ? filterLabel
215
- : typeof label === 'object' && label.renderer
216
- ? label.renderer(column)
217
- : header.renderer(column) || name
218
-
219
- const idx = operator === 'between' ? 1 : 0
220
- const renderer = getFilterRenderer(
221
- operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'
222
- ? 'text'
223
- : type
224
- )[idx]
225
- const value =
226
- this.value?.find(filter => filter.name == name)?.value ??
227
- this.buildDefaultValue(operator!, (filter as FilterConfigObject)?.value)
228
-
229
- if (!renderer) {
230
- return html``
231
- }
232
-
233
- return type === 'boolean' || type === 'checkbox'
234
- ? renderer(column, value, this)
235
- : type !== 'select' && labelText
236
- ? html`<label filter-title ?between=${operator === 'between'}
237
- ><span>${labelText}</span> ${renderer(column, value, this)}
238
- </label> `
239
- : type !== 'select' && !labelText
240
- ? renderer(column, value, this)
241
- : operator === 'in'
242
- ? html`
243
- <ox-select
244
- name=${name}
245
- placeholder=${labelText}
246
- .value=${value}
247
- @change=${(e: CustomEvent) =>
248
- e.target?.dispatchEvent(
249
- new CustomEvent('filter-change', {
250
- detail: {
251
- name,
252
- operator,
253
- value: e.detail
254
- }
255
- })
256
- )}
257
- >
258
- <ox-popup-list multiple attr-selected="checked" with-search>
259
- ${renderer(column, value, this)}
260
- </ox-popup-list>
261
- </ox-select>
262
- `
263
- : html`
264
- <ox-select
265
- name=${name}
266
- placeholder=${labelText}
267
- .value=${value}
268
- @change=${(e: CustomEvent) =>
269
- e.target?.dispatchEvent(
270
- new CustomEvent('filter-change', {
271
- detail: {
272
- name,
273
- operator,
274
- value: e.detail
275
- }
276
- })
277
- )}
278
- >
279
- <ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>
280
- </ox-select>
281
- `
282
- })}
174
+ ${this.filterColumns
175
+ .filter(column => !(column.filter as FilterConfigObject).hidden)
176
+ .map((column: ColumnConfig) => {
177
+ const { name, header, label, filter } = column
178
+
179
+ const type = (filter as FilterConfigObject).type
180
+
181
+ if (type == 'search') {
182
+ return html`
183
+ <ox-input-search name="search" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>
184
+ `
185
+ }
186
+
187
+ const operator = (filter as FilterConfigObject).operator
188
+ const filterLabel = (filter as FilterConfigObject).label
189
+
190
+ const labelText =
191
+ filterLabel !== undefined
192
+ ? filterLabel
193
+ : typeof label === 'object' && label.renderer
194
+ ? label.renderer(column)
195
+ : header.renderer(column) || name
196
+
197
+ const idx = operator === 'between' ? 1 : 0
198
+ const renderer = getFilterRenderer(
199
+ operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'
200
+ ? 'text'
201
+ : type
202
+ )[idx]
203
+ const value =
204
+ this.value?.find(filter => filter.name == name)?.value ??
205
+ this.buildDefaultValue(operator!, (filter as FilterConfigObject)?.value)
206
+
207
+ if (!renderer) {
208
+ return html``
209
+ }
210
+
211
+ return type === 'boolean' || type === 'checkbox'
212
+ ? renderer(column, value, this)
213
+ : type !== 'select' && labelText
214
+ ? html`<label filter-title ?between=${operator === 'between'}
215
+ ><span>${labelText}</span> ${renderer(column, value, this)}
216
+ </label> `
217
+ : type !== 'select' && !labelText
218
+ ? renderer(column, value, this)
219
+ : operator === 'in'
220
+ ? html`
221
+ <ox-select
222
+ name=${name}
223
+ placeholder=${labelText}
224
+ .value=${value}
225
+ @change=${(e: CustomEvent) =>
226
+ e.target?.dispatchEvent(
227
+ new CustomEvent('filter-change', {
228
+ detail: {
229
+ name,
230
+ operator,
231
+ value: e.detail
232
+ }
233
+ })
234
+ )}
235
+ >
236
+ <ox-popup-list multiple attr-selected="checked" with-search>
237
+ ${renderer(column, value, this)}
238
+ </ox-popup-list>
239
+ </ox-select>
240
+ `
241
+ : html`
242
+ <ox-select
243
+ name=${name}
244
+ placeholder=${labelText}
245
+ .value=${value}
246
+ @change=${(e: CustomEvent) =>
247
+ e.target?.dispatchEvent(
248
+ new CustomEvent('filter-change', {
249
+ detail: {
250
+ name,
251
+ operator,
252
+ value: e.detail
253
+ }
254
+ })
255
+ )}
256
+ >
257
+ <ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>
258
+ </ox-select>
259
+ `
260
+ })}
283
261
  </form>
262
+ <slot name="setting"></slot>
284
263
  `
285
264
  }
286
265
 
266
+ applyUpdatedConfiguration() {
267
+ const filters = this.config.columns.filter(columnConfig => !!columnConfig.filter)
268
+ this.filterColumns = filters.filter((columnConfig: ColumnConfig) => {
269
+ const filter = columnConfig.filter as FilterConfigObject
270
+ return filter!.operator !== 'search'
271
+ })
272
+ this.searchColumns = filters.filter(columnConfig => {
273
+ const filter = columnConfig.filter as FilterConfigObject
274
+ return filter!.operator === 'search'
275
+ })
276
+
277
+ if (this.searchColumns.length > 0) {
278
+ this.filterColumns.unshift({ name: 'search', filter: { type: 'search' } } as any)
279
+ }
280
+
281
+ if (!this.personalConfig) {
282
+ this.personalFilters = this.filterColumns.map(column => {
283
+ return { name: column.name }
284
+ })
285
+ } else {
286
+ const { filters: personalFilters = [] } = this.personalConfig
287
+
288
+ if (personalFilters) {
289
+ const xfilters = this.filterColumns.map(column => {
290
+ return personalFilters.find(pFilter => pFilter.name == column.name) || { name: column.name }
291
+ })
292
+
293
+ function reorderList(a: FilterPreference[], b: FilterPreference[]): FilterPreference[] {
294
+ // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
295
+ const result = new Array(a.length)
296
+
297
+ // b 배열에 없는 아이템은 원래 위치로 채움
298
+ a.forEach((item, index) => {
299
+ if (!item.name || !b.find(bi => bi.name == item.name)) {
300
+ result[index] = item
301
+ }
302
+ })
303
+
304
+ b.forEach(item => {
305
+ const ai = a.find(ai => ai.name == item.name)
306
+ if (ai) {
307
+ result[result.findIndex(slot => slot === undefined)] = ai
308
+ }
309
+ })
310
+
311
+ return result
312
+ }
313
+
314
+ // 배열 재정렬 실행
315
+ this.personalFilters = reorderList(xfilters as any, personalFilters as any) as FilterPreference[]
316
+
317
+ this.filterColumns = this.personalFilters
318
+ .map(filter => {
319
+ const column = this.filterColumns.find(column => column.name == filter.name)
320
+ if (column?.filter) {
321
+ ;(column.filter as FilterConfigObject)!.hidden = filter.hidden
322
+ }
323
+ return column
324
+ })
325
+ .filter(Boolean) as ColumnConfig[]
326
+ }
327
+ }
328
+
329
+ const grist = this.closest('ox-grist') as DataGrist
330
+
331
+ this.value = (grist?.filters || []).map(filter => {
332
+ return {
333
+ ...filter,
334
+ value: this.buildDefaultValue(filter!.operator, filter!.value)
335
+ }
336
+ })
337
+
338
+ this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0
339
+
340
+ this.autoUpdateTargetsOnChange = {}
341
+ this.filterColumns
342
+ ?.filter(({ filter }) => {
343
+ return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0
344
+ })
345
+ .map(({ name, filter }) => {
346
+ const boundTo = (filter as FilterConfigObject).boundTo
347
+
348
+ boundTo!.forEach(to => {
349
+ const origin = this.autoUpdateTargetsOnChange[to] || []
350
+ if (name && !origin.includes(name)) {
351
+ this.autoUpdateTargetsOnChange[to] = [...origin, name]
352
+ }
353
+ })
354
+ })
355
+ }
356
+
287
357
  async getQueryFilters(): Promise<QueryFilter[]> {
288
358
  const form = await this.form
289
359
  if (!form) return []
@@ -292,6 +362,7 @@ export class OxFiltersForm extends LitElement {
292
362
  const search: string | undefined = formData.get('search')?.toString()
293
363
 
294
364
  var filters = this.filterColumns
365
+ .filter(column => column.name !== 'search' && !(column.filter as FilterConfigObject)!.hidden)
295
366
  .map((column: ColumnConfig) => {
296
367
  const { name, type, filter } = column
297
368
  const operator = (filter as FilterConfigObject).operator