@operato/data-grist 7.1.31 → 7.1.32

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 (173) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/tsconfig.tsbuildinfo +1 -1
  3. package/package.json +10 -10
  4. package/.storybook/main.js +0 -3
  5. package/.storybook/preview.js +0 -52
  6. package/.storybook/server.mjs +0 -8
  7. package/demo/data-grist-test.html +0 -468
  8. package/demo/favicon.ico +0 -0
  9. package/demo/index.html +0 -541
  10. package/demo/report-test.html +0 -249
  11. package/dist/src/record-view/record-creator.d.ts +0 -17
  12. package/dist/src/record-view/record-creator.js +0 -148
  13. package/dist/src/record-view/record-creator.js.map +0 -1
  14. package/src/accumulator/accumulator.ts +0 -63
  15. package/src/configure/column-builder.ts +0 -114
  16. package/src/configure/config-builder.ts +0 -40
  17. package/src/configure/filters-option-builder.ts +0 -8
  18. package/src/configure/imex-option-builder.ts +0 -5
  19. package/src/configure/list-option-builder.ts +0 -9
  20. package/src/configure/rows-option-builder.ts +0 -38
  21. package/src/configure/tree-option-builder.ts +0 -22
  22. package/src/configure/zero-config.ts +0 -83
  23. package/src/const.ts +0 -1
  24. package/src/data-card/data-card-field.ts +0 -94
  25. package/src/data-card/data-card-gutter-menu.ts +0 -94
  26. package/src/data-card/data-card-gutter.ts +0 -103
  27. package/src/data-card/data-card.ts +0 -154
  28. package/src/data-card/event-handlers/record-card-click-handler.ts +0 -34
  29. package/src/data-card/event-handlers/record-card-dblclick-handler.ts +0 -34
  30. package/src/data-card/record-card.ts +0 -289
  31. package/src/data-consumer.ts +0 -11
  32. package/src/data-grid/data-grid-accum-field.ts +0 -109
  33. package/src/data-grid/data-grid-body-style.ts +0 -99
  34. package/src/data-grid/data-grid-body.ts +0 -753
  35. package/src/data-grid/data-grid-field.ts +0 -236
  36. package/src/data-grid/data-grid-footer.ts +0 -117
  37. package/src/data-grid/data-grid-header.ts +0 -574
  38. package/src/data-grid/data-grid.ts +0 -293
  39. package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +0 -69
  40. package/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.ts +0 -32
  41. package/src/data-grid/event-handlers/data-grid-body-dblclick-handler.ts +0 -42
  42. package/src/data-grid/event-handlers/data-grid-body-focus-change-handler.ts +0 -24
  43. package/src/data-grid/event-handlers/data-grid-body-keydown-handler.ts +0 -234
  44. package/src/data-grist.ts +0 -1233
  45. package/src/data-list/data-list-field.ts +0 -82
  46. package/src/data-list/data-list-gutter.ts +0 -108
  47. package/src/data-list/data-list.ts +0 -145
  48. package/src/data-list/event-handlers/record-partial-click-handler.ts +0 -34
  49. package/src/data-list/event-handlers/record-partial-dblclick-handler.ts +0 -33
  50. package/src/data-list/event-handlers/record-partial-long-press-handler.ts +0 -33
  51. package/src/data-list/record-partial.ts +0 -255
  52. package/src/data-manipulator.ts +0 -426
  53. package/src/data-provider.ts +0 -271
  54. package/src/data-report/data-report-body-style.ts +0 -58
  55. package/src/data-report/data-report-body.ts +0 -189
  56. package/src/data-report/data-report-component.ts +0 -138
  57. package/src/data-report/data-report-field.ts +0 -83
  58. package/src/data-report/data-report-header.ts +0 -242
  59. package/src/data-report/event-handlers/data-report-body-click-handler.ts +0 -38
  60. package/src/data-report/event-handlers/data-report-body-dblclick-handler.ts +0 -25
  61. package/src/data-report/event-handlers/data-report-body-keydown-handler.ts +0 -68
  62. package/src/data-report.ts +0 -424
  63. package/src/editors/index.ts +0 -4
  64. package/src/editors/ox-grist-editor-checkbox.ts +0 -28
  65. package/src/editors/ox-grist-editor-color.ts +0 -10
  66. package/src/editors/ox-grist-editor-date.ts +0 -10
  67. package/src/editors/ox-grist-editor-datetime.ts +0 -27
  68. package/src/editors/ox-grist-editor-email.ts +0 -10
  69. package/src/editors/ox-grist-editor-file.ts +0 -28
  70. package/src/editors/ox-grist-editor-image.ts +0 -31
  71. package/src/editors/ox-grist-editor-month.ts +0 -10
  72. package/src/editors/ox-grist-editor-multiple-select.ts +0 -57
  73. package/src/editors/ox-grist-editor-number.ts +0 -27
  74. package/src/editors/ox-grist-editor-password.ts +0 -10
  75. package/src/editors/ox-grist-editor-select.ts +0 -55
  76. package/src/editors/ox-grist-editor-tel.ts +0 -10
  77. package/src/editors/ox-grist-editor-text.ts +0 -14
  78. package/src/editors/ox-grist-editor-textarea.ts +0 -16
  79. package/src/editors/ox-grist-editor-time.ts +0 -10
  80. package/src/editors/ox-grist-editor-tree.ts +0 -27
  81. package/src/editors/ox-grist-editor-varname.ts +0 -36
  82. package/src/editors/ox-grist-editor-week.ts +0 -10
  83. package/src/editors/ox-grist-editor.ts +0 -207
  84. package/src/editors/ox-input-tree.ts +0 -226
  85. package/src/editors/registry.ts +0 -82
  86. package/src/empty-note.ts +0 -46
  87. package/src/filters/filter-checkbox.ts +0 -49
  88. package/src/filters/filter-input-barcode.ts +0 -34
  89. package/src/filters/filter-input.ts +0 -30
  90. package/src/filters/filter-range-date.ts +0 -81
  91. package/src/filters/filter-range-number.ts +0 -64
  92. package/src/filters/filter-select-buttons.ts +0 -60
  93. package/src/filters/filter-select.ts +0 -68
  94. package/src/filters/filter-styles.ts +0 -119
  95. package/src/filters/filters-form.ts +0 -476
  96. package/src/filters/index.ts +0 -10
  97. package/src/filters/registry.ts +0 -56
  98. package/src/formatters/date-formatter.ts +0 -3
  99. package/src/formatters/index.ts +0 -1
  100. package/src/formatters/number-formatter.ts +0 -3
  101. package/src/formatters/registry.ts +0 -30
  102. package/src/formatters/text-formatter.ts +0 -3
  103. package/src/gutters/gutter-button.ts +0 -51
  104. package/src/gutters/gutter-dirty.ts +0 -96
  105. package/src/gutters/gutter-row-selector.ts +0 -89
  106. package/src/gutters/gutter-sequence.ts +0 -54
  107. package/src/gutters/index.ts +0 -1
  108. package/src/gutters/registry.ts +0 -32
  109. package/src/handlers/contextmenu-tree-mutation.ts +0 -80
  110. package/src/handlers/index.ts +0 -1
  111. package/src/handlers/move-down.ts +0 -44
  112. package/src/handlers/move-up.ts +0 -44
  113. package/src/handlers/record-copy.ts +0 -38
  114. package/src/handlers/record-delete.ts +0 -30
  115. package/src/handlers/record-view-handler.ts +0 -27
  116. package/src/handlers/registry.ts +0 -42
  117. package/src/handlers/select-row-toggle.ts +0 -30
  118. package/src/handlers/select-row.ts +0 -27
  119. package/src/index.ts +0 -17
  120. package/src/personalizer/index.ts +0 -1
  121. package/src/personalizer/ox-grist-filter-personalizer.ts +0 -192
  122. package/src/personalizer/ox-grist-personalizer.ts +0 -226
  123. package/src/record-view/event-handlers/record-view-body-click-handler.ts +0 -33
  124. package/src/record-view/event-handlers/record-view-body-keydown-handler.ts +0 -26
  125. package/src/record-view/index.ts +0 -2
  126. package/src/record-view/ox-record-creator.ts +0 -289
  127. package/src/record-view/record-view-body.ts +0 -250
  128. package/src/record-view/record-view-handler.ts +0 -86
  129. package/src/record-view/record-view.ts +0 -122
  130. package/src/renderers/index.ts +0 -14
  131. package/src/renderers/ox-grist-renderer-boolean.ts +0 -43
  132. package/src/renderers/ox-grist-renderer-color.ts +0 -15
  133. package/src/renderers/ox-grist-renderer-date.ts +0 -62
  134. package/src/renderers/ox-grist-renderer-file.ts +0 -31
  135. package/src/renderers/ox-grist-renderer-image.ts +0 -27
  136. package/src/renderers/ox-grist-renderer-json5.ts +0 -36
  137. package/src/renderers/ox-grist-renderer-link.ts +0 -17
  138. package/src/renderers/ox-grist-renderer-password.ts +0 -7
  139. package/src/renderers/ox-grist-renderer-progress.ts +0 -45
  140. package/src/renderers/ox-grist-renderer-select.ts +0 -58
  141. package/src/renderers/ox-grist-renderer-text.ts +0 -16
  142. package/src/renderers/ox-grist-renderer-textarea.ts +0 -7
  143. package/src/renderers/ox-grist-renderer-tree.ts +0 -189
  144. package/src/renderers/ox-grist-renderer.ts +0 -35
  145. package/src/renderers/registry.ts +0 -111
  146. package/src/sorters/sorters-control.ts +0 -143
  147. package/src/types.ts +0 -813
  148. package/src/utils/index.ts +0 -2
  149. package/src/utils/list-param.ts +0 -72
  150. package/src/utils/supports-passive.ts +0 -13
  151. package/stories/accumulator-format.stories.ts +0 -276
  152. package/stories/barcode-input-filter.stories.ts +0 -216
  153. package/stories/bounded-select-filters.stories.ts +0 -333
  154. package/stories/bounded-select-record.stories.ts +0 -336
  155. package/stories/click-event-custom.stories.ts +0 -288
  156. package/stories/click-event.stories.ts +0 -283
  157. package/stories/creatable-only-column.stories.ts +0 -253
  158. package/stories/default-filters.stories.ts +0 -241
  159. package/stories/dynamic-editable.stories.ts +0 -313
  160. package/stories/empty-sorters.stories.ts +0 -180
  161. package/stories/explicit-fetch.stories.ts +0 -186
  162. package/stories/fixed-column.stories.ts +0 -416
  163. package/stories/grid-setting.stories.ts +0 -501
  164. package/stories/grist-modes.stories.ts +0 -451
  165. package/stories/group-header.stories.ts +0 -442
  166. package/stories/record-view.stories.ts +0 -143
  167. package/stories/textarea.stories.ts +0 -261
  168. package/stories/tree-column-with-checkbox.stories.ts +0 -297
  169. package/stories/tree-column.stories.ts +0 -296
  170. package/tsconfig.json +0 -26
  171. package/web-dev-server.config.mjs +0 -27
  172. package/web-test-runner.config.mjs +0 -45
  173. package/yarn-error.log +0 -16971
@@ -1,68 +0,0 @@
1
- import '@operato/input/ox-checkbox.js'
2
-
3
- import { html } from 'lit'
4
- import { until } from 'lit/directives/until.js'
5
-
6
- import { FilterConfigObject, FilterOperator, FilterSelectRenderer, SelectOption, SelectOptionObject } from '../types'
7
- import { OxFiltersForm } from './filters-form'
8
- import { DataGridHeader } from '../data-grid/data-grid-header'
9
-
10
- function buildOptions(options: SelectOption[], operator?: FilterOperator) {
11
- const selectOptionObjects = options.map(option => {
12
- switch (typeof option) {
13
- case 'string':
14
- return {
15
- display: option,
16
- value: option
17
- }
18
- case 'object':
19
- return {
20
- display: option.display || option.name,
21
- value: option.value
22
- }
23
- default:
24
- return option
25
- }
26
- }) as SelectOptionObject[]
27
-
28
- return operator === 'in'
29
- ? html`
30
- ${selectOptionObjects
31
- ?.filter(option => !!option)
32
- .map(
33
- ({ value, display, name }) => html` <ox-checkbox option value=${value}>${display || name}</ox-checkbox> `
34
- )}
35
- `
36
- : html`
37
- ${selectOptionObjects?.map(
38
- ({ value, display, name }) => html` <div option value=${value}>${display || name}&nbsp;</div> `
39
- )}
40
- `
41
- }
42
-
43
- export const FilterSelect: FilterSelectRenderer = (column, value, owner) => {
44
- /* value는 filters-form이나 grid-header에서 처리되므로 이 곳에서는 무시한다. */
45
- const filter = column.filter as FilterConfigObject
46
- const operator = filter?.operator
47
- const form = owner as OxFiltersForm | DataGridHeader
48
-
49
- var options = filter?.options || column.record.options || []
50
-
51
- if (typeof options === 'function') {
52
- if (!filter?.options) {
53
- console.warn(
54
- 'ox-grist의 column.filter 속성에서는 column.record.options의 함수형 options을 사용할 수 없으므로, filter 속성에서 재지정해야한다.'
55
- )
56
- }
57
-
58
- options = options.call(null, value, column, form instanceof OxFiltersForm ? form.getFormObjectValue() : {}, owner)
59
-
60
- if (options instanceof Promise) {
61
- return html`${until(options.then(options => buildOptions(options, operator)))}`
62
- } else {
63
- return buildOptions((options || []) as SelectOption[], operator)
64
- }
65
- } else {
66
- return buildOptions((options || []) as SelectOption[], operator)
67
- }
68
- }
@@ -1,119 +0,0 @@
1
- import { css } from 'lit'
2
-
3
- export const FilterStyles = css`
4
- :host {
5
- --ox-filters-input-placeholder-color: var(--input-placeholder-color, var(--md-sys-color-on-surface));
6
-
7
- --ox-filters-input-border: var(--input-border, 1px solid rgba(0, 0, 0, 0.2));
8
- --ox-filters-input-focus-border: var(--input-focus-border, 1px solid var(--md-sys-color-outline-variant));
9
- --ox-filters-input-font: var(--input-font, normal 14px var(--theme-font));
10
- --ox-filters-input-color: var(--input-color, var(--md-sys-color-on-surface));
11
- --ox-filters-input-focus-color: var(--input-focus-color, var(--md-sys-color-on-surface-variant));
12
- --ox-filters-label-font: var(--label-font, normal 14px var(--theme-font));
13
- --ox-filters-label-color: var(--label-color, var(--md-sys-color-on-surface));
14
- --ox-filters-input-background-color: transparent;
15
-
16
- --ox-filters-form-gap: var(--input-gap-vertical, 8px) var(--input-gap-horizontal, 16px);
17
- --ox-filters-input-padding: var(--spacing-small, 4px);
18
-
19
- --ox-select-padding: var(--ox-filters-input-padding);
20
- --ox-checkbox-background-color: var(--ox-filters-input-background-color, transparent);
21
- }
22
-
23
- label {
24
- color: var(--ox-filters-label-color, var(--md-sys-color-on-primary-container));
25
- }
26
-
27
- span {
28
- font-weight: var(--md-sys-typescale-label-medium-weight);
29
- text-transform: capitalize;
30
- }
31
-
32
- input::placeholder {
33
- color: var(--ox-filters-input-placeholder-color, var(--md-sys-color-surface-dim));
34
- opacity: 0.6;
35
- }
36
-
37
- input,
38
- ox-input-search,
39
- [filter-input] {
40
- padding: var(--ox-filters-input-padding);
41
- }
42
-
43
- ox-select,
44
- ox-input-search,
45
- input,
46
- [filter-input] {
47
- border: none;
48
- border-bottom: var(--ox-filters-input-border, var(--md-sys-color-outline));
49
- font: var(--ox-filters-input-font);
50
- color: var(--ox-filters-input-color, var(--md-sys-color-on-surface));
51
- background-color: var(--ox-filters-input-background-color, transparent);
52
- vertical-align: middle;
53
- }
54
-
55
- ox-select:focus,
56
- input:focus,
57
- [filter-input]:focus {
58
- outline: none;
59
- border-bottom: var(--ox-filters-input-focus-border, var(--md-sys-color-outline-variant));
60
- color: var(--ox-filters-input-focus-color, var(--md-sys-color-on-surface-variant));
61
- }
62
-
63
- ox-select {
64
- min-width: 90px;
65
- max-width: 170px;
66
- }
67
-
68
- ox-input-search {
69
- max-width: 150px;
70
- }
71
-
72
- input[type='number'] {
73
- max-width: 90px;
74
- }
75
-
76
- input[type*='date'],
77
- input[type*='time'],
78
- input[type='week'],
79
- input[type='month'] {
80
- max-width: 170px;
81
- }
82
-
83
- [filter-input] {
84
- min-width: 140px;
85
- max-width: 170px;
86
- }
87
-
88
- @media only screen and (max-width: 460px) {
89
- :host {
90
- --ox-filters-form-label-font: bold 13px var(--theme-font);
91
- --ox-filters-input-font: normal 16px var(--theme-font);
92
- }
93
-
94
- ox-input-barcode {
95
- max-width: unset;
96
- flex: 1;
97
- }
98
-
99
- ox-input-search {
100
- max-width: unset;
101
- }
102
-
103
- ox-select {
104
- max-width: unset;
105
- }
106
-
107
- ox-checkbox {
108
- max-width: unset;
109
- }
110
-
111
- input[type='number'] {
112
- max-width: unset;
113
- }
114
-
115
- input {
116
- flex: 1;
117
- }
118
- }
119
- `
@@ -1,476 +0,0 @@
1
- import '@operato/input/ox-checkbox.js'
2
- import '@operato/input/ox-select.js'
3
- import '@operato/popup/ox-popup-list.js'
4
- import '@operato/input/ox-input-search.js'
5
-
6
- import { css, html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'
7
- import { customElement, property, queryAsync, state } from 'lit/decorators.js'
8
- import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
9
-
10
- import { PagePreferenceProvider } from '@operato/p13n'
11
- import { getDefaultValue } from '@operato/time-calculator'
12
-
13
- import { FilterConfigObject, FilterPreference } from '../types.js'
14
- import { DataGrist } from '../data-grist'
15
- import { ColumnConfig, FilterOperator, FilterValue, GristConfig, PersonalGristPreference } from '../types'
16
- import { FilterStyles } from './filter-styles'
17
- import { getFilterRenderer } from './registry'
18
-
19
- export type QueryFilterRangeValue = [from: number, to: number]
20
-
21
- export type QueryFilter = {
22
- name: string
23
- operator: FilterOperator
24
- value: any
25
- }
26
-
27
- @customElement('ox-filters-form')
28
- export class OxFiltersForm extends LitElement {
29
- static styles = [
30
- MDTypeScaleStyles,
31
- FilterStyles,
32
- css`
33
- :host {
34
- display: flex;
35
- padding: var(--spacing-small);
36
- }
37
-
38
- form {
39
- flex: 1;
40
-
41
- display: flex;
42
- flex-flow: row wrap;
43
- gap: var(--ox-filters-form-gap);
44
- }
45
-
46
- form > * {
47
- display: flex;
48
- align-items: center;
49
- gap: var(--input-intra-gap, 7px);
50
- }
51
-
52
- label span {
53
- display: block;
54
- }
55
-
56
- @media only screen and (max-width: 460px) {
57
- form {
58
- flex-direction: column;
59
- flex-flow: column;
60
- }
61
- }
62
- `
63
- ]
64
-
65
- @property({ type: Array }) value: FilterValue[] = []
66
- @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false
67
- @property({ type: Boolean, attribute: 'autofocus' }) autofocus: boolean = true
68
- @property({ type: Boolean, attribute: 'empty', reflect: true }) empty: boolean = true
69
-
70
- @state() personalConfigProvider?: PagePreferenceProvider
71
- @state() personalConfig?: PersonalGristPreference
72
- @state() personalFilters?: FilterPreference[]
73
-
74
- @state() config!: GristConfig
75
- @state() filterColumns: ColumnConfig[] = []
76
- @state() searchColumns: ColumnConfig[] = []
77
-
78
- @queryAsync('form') form!: HTMLFormElement
79
-
80
- private autoUpdateTargetsOnChange: { [name: string]: string[] } = {}
81
- private objectValue?: object
82
-
83
- connectedCallback(): void {
84
- super.connectedCallback()
85
-
86
- const grist = this.closest('ox-grist') as DataGrist
87
-
88
- if (grist) {
89
- this.config = grist.compiledConfig
90
- this.personalConfigProvider = grist.personalConfigProvider
91
-
92
- grist.addEventListener('config-change', (e: Event) => {
93
- this.config = (e as CustomEvent).detail
94
- })
95
-
96
- grist.addEventListener('fetch-params-change', (e: Event) => {
97
- const { filters, from } = (e as CustomEvent).detail || {}
98
- if (from === 'filters-form') {
99
- return
100
- }
101
-
102
- this.value = filters
103
- })
104
-
105
- this.renderRoot.addEventListener('change', async (e: Event) => {
106
- const { target, detail: value } = e as CustomEvent
107
- const name = (target as HTMLInputElement).name
108
- const { filter } = this.filterColumns.find(filter => filter.name == name) || {}
109
-
110
- if (this.autoUpdateTargetsOnChange[name]) {
111
- /* 일단은 심플하게, boundTo로 연결된 필터값이 바뀌면, 폼 전체를 update하도록 함. */
112
- ;(this.autoUpdateTargetsOnChange[name] || []).forEach(name => {
113
- const target = this.renderRoot.querySelector(`[name='${name}']`)
114
- if (target) {
115
- ;(target as HTMLInputElement).value = ''
116
- }
117
- })
118
-
119
- await this.updateObjectValues()
120
- this.requestUpdate()
121
- }
122
-
123
- const onchange = typeof filter == 'object' ? filter.onchange : null
124
- const keepGoing = onchange ? await onchange.call(null, value ?? (target as HTMLInputElement).value, this) : true
125
-
126
- keepGoing &&
127
- this.dispatchEvent(
128
- new CustomEvent('fetch-params-change', {
129
- bubbles: true,
130
- composed: true,
131
- detail: {
132
- filters: await this.getQueryFilters(),
133
- from: 'filters-form'
134
- }
135
- })
136
- )
137
- })
138
- }
139
- }
140
-
141
- buildDefaultValue(operator: FilterOperator, defaultValue: any) {
142
- if (defaultValue === undefined) {
143
- return
144
- }
145
- if (operator == 'between') {
146
- return (defaultValue as Array<any>).map(v => getDefaultValue(v, this))
147
- } else {
148
- return getDefaultValue(defaultValue, this)
149
- }
150
- }
151
-
152
- async updated(changes: PropertyValues<this>) {
153
- if (changes.has('personalConfigProvider') && this.personalConfigProvider) {
154
- this.personalConfig = await this.personalConfigProvider.load()
155
- } else if (changes.has('config') || changes.has('personalConfig')) {
156
- this.applyUpdatedConfiguration()
157
- }
158
- }
159
-
160
- render(): TemplateResult {
161
- const searchValue =
162
- (this.value?.find(filter => filter.operator === 'search')?.value as string)?.match(/^\%(.*)\%$/)?.[1] || ''
163
-
164
- return this.empty
165
- ? html``
166
- : html`
167
- <form
168
- class="md-typescale-body-medium-prominent"
169
- @submit=${(e: Event) => {
170
- e.stopPropagation()
171
- e.preventDefault()
172
-
173
- const grist = this.closest('ox-grist') as DataGrist
174
-
175
- grist && grist.fetch()
176
- }}
177
- >
178
- ${this.filterColumns
179
- .filter(column => !(column.filter as FilterConfigObject).hidden)
180
- .map((column: ColumnConfig) => {
181
- const { name, header, label, filter } = column
182
-
183
- const type = (filter as FilterConfigObject).type
184
-
185
- if (type == 'search') {
186
- return html`
187
- <ox-input-search name="search" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>
188
- `
189
- }
190
-
191
- const operator = (filter as FilterConfigObject).operator
192
- const filterLabel = (filter as FilterConfigObject).label
193
-
194
- const labelText =
195
- filterLabel !== undefined
196
- ? filterLabel
197
- : typeof label === 'object' && label.renderer
198
- ? label.renderer(column)
199
- : header.renderer(column) || name
200
-
201
- const idx = operator === 'between' ? 1 : 0
202
- const renderer = getFilterRenderer(
203
- operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'
204
- ? 'text'
205
- : type
206
- )[idx]
207
- const value =
208
- this.value?.find(filter => filter.name == name)?.value ??
209
- this.buildDefaultValue(operator!, (filter as FilterConfigObject)?.value)
210
-
211
- if (!renderer) {
212
- return html``
213
- }
214
-
215
- return type === 'boolean' || type === 'checkbox'
216
- ? renderer(column, value, this)
217
- : type !== 'select' && labelText
218
- ? html`<label filter-title ?between=${operator === 'between'}
219
- ><span>${labelText}</span> ${renderer(column, value, this)}
220
- </label> `
221
- : type !== 'select' && !labelText
222
- ? renderer(column, value, this)
223
- : operator === 'in'
224
- ? html`
225
- <ox-select
226
- name=${name}
227
- placeholder=${labelText}
228
- .value=${value}
229
- @change=${(e: CustomEvent) =>
230
- e.target?.dispatchEvent(
231
- new CustomEvent('filter-change', {
232
- detail: {
233
- name,
234
- operator,
235
- value: e.detail
236
- }
237
- })
238
- )}
239
- >
240
- <ox-popup-list multiple attr-selected="checked" with-search>
241
- ${renderer(column, value, this)}
242
- </ox-popup-list>
243
- </ox-select>
244
- `
245
- : html`
246
- <ox-select
247
- name=${name}
248
- placeholder=${labelText}
249
- .value=${value}
250
- @change=${(e: CustomEvent) =>
251
- e.target?.dispatchEvent(
252
- new CustomEvent('filter-change', {
253
- detail: {
254
- name,
255
- operator,
256
- value: e.detail
257
- }
258
- })
259
- )}
260
- >
261
- <ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>
262
- </ox-select>
263
- `
264
- })}
265
- </form>
266
- <slot name="setting"></slot>
267
- `
268
- }
269
-
270
- applyUpdatedConfiguration() {
271
- if (!this.config) {
272
- return
273
- }
274
-
275
- const filters = this.config.columns.filter(columnConfig => !!columnConfig.filter)
276
-
277
- this.filterColumns = filters.filter((columnConfig: ColumnConfig) => {
278
- const filter = columnConfig.filter as FilterConfigObject
279
- return filter!.operator !== 'search'
280
- })
281
- this.searchColumns = filters.filter(columnConfig => {
282
- const filter = columnConfig.filter as FilterConfigObject
283
- return filter!.operator === 'search'
284
- })
285
-
286
- if (this.searchColumns.length > 0 && !this.withoutSearch) {
287
- this.filterColumns.unshift({ name: 'search', filter: { type: 'search' } } as any)
288
- }
289
-
290
- if (!this.personalConfig) {
291
- this.personalFilters = this.filterColumns.map(column => {
292
- return { name: column.name }
293
- })
294
- } else {
295
- const { filters: personalFilters = [] } = this.personalConfig
296
-
297
- if (personalFilters) {
298
- const xfilters = this.filterColumns.map(column => {
299
- return personalFilters.find(pFilter => pFilter.name == column.name) || { name: column.name }
300
- })
301
-
302
- function reorderList(a: FilterPreference[], b: FilterPreference[]): FilterPreference[] {
303
- // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
304
- const result = new Array(a.length)
305
-
306
- // b 배열에 없는 아이템은 원래 위치로 채움
307
- a.forEach((item, index) => {
308
- if (!item.name || !b.find(bi => bi.name == item.name)) {
309
- result[index] = item
310
- }
311
- })
312
-
313
- b.forEach(item => {
314
- const ai = a.find(ai => ai.name == item.name)
315
- if (ai) {
316
- result[result.findIndex(slot => slot === undefined)] = ai
317
- }
318
- })
319
-
320
- return result
321
- }
322
-
323
- // 배열 재정렬 실행
324
- this.personalFilters = reorderList(xfilters as any, personalFilters as any) as FilterPreference[]
325
-
326
- this.filterColumns = this.personalFilters
327
- .map(filter => {
328
- const column = this.filterColumns.find(column => column.name == filter.name)
329
- if (column?.filter) {
330
- ;(column.filter as FilterConfigObject)!.hidden = filter.hidden
331
- }
332
- return column
333
- })
334
- .filter(Boolean) as ColumnConfig[]
335
- }
336
- }
337
-
338
- const grist = this.closest('ox-grist') as DataGrist
339
-
340
- this.value = (grist?.filters || []).map(filter => {
341
- return {
342
- ...filter,
343
- value: this.buildDefaultValue(filter!.operator, filter!.value)
344
- }
345
- })
346
-
347
- this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0
348
-
349
- this.autoUpdateTargetsOnChange = {}
350
- this.filterColumns
351
- ?.filter(({ filter }) => {
352
- return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0
353
- })
354
- .map(({ name, filter }) => {
355
- const boundTo = (filter as FilterConfigObject).boundTo
356
-
357
- boundTo!.forEach(to => {
358
- const origin = this.autoUpdateTargetsOnChange[to] || []
359
- if (name && !origin.includes(name)) {
360
- this.autoUpdateTargetsOnChange[to] = [...origin, name]
361
- }
362
- })
363
- })
364
- }
365
-
366
- async getQueryFilters(): Promise<QueryFilter[]> {
367
- const form = await this.form
368
- if (!form) return []
369
-
370
- const formData = new FormData(form)
371
- const search: string | undefined = formData.get('search')?.toString()
372
-
373
- var filters = this.filterColumns
374
- .filter(column => column.name !== 'search' && !(column.filter as FilterConfigObject)!.hidden)
375
- .map((column: ColumnConfig) => {
376
- const { name, type, filter } = column
377
- const operator = (filter as FilterConfigObject).operator
378
-
379
- var value = formData.getAll(name)
380
- if (value.length == 0) {
381
- return
382
- }
383
-
384
- if (-1 === value.findIndex(v => v !== '')) {
385
- return
386
- }
387
-
388
- const filterValue = value.map(v => {
389
- const value = v.toString()
390
-
391
- /* TODO registry에서 타입별로 parsing 방법을 지정할 수 있도록 해야한다. */
392
- switch (type) {
393
- case 'integer':
394
- case 'float':
395
- case 'number':
396
- case 'progress':
397
- case 'checkbox':
398
- case 'boolean':
399
- return !value ? undefined : JSON.parse(value)
400
- default:
401
- return value
402
- }
403
- })
404
-
405
- return {
406
- name,
407
- operator,
408
- value: filterValue.length === 1 ? filterValue[0] : filterValue
409
- }
410
- })
411
- .filter(result => result !== undefined) as QueryFilter[]
412
-
413
- if (search) {
414
- filters = filters.concat(
415
- this.searchColumns.map((column: ColumnConfig) => {
416
- const { name } = column
417
-
418
- return {
419
- name,
420
- operator: 'search',
421
- value: `%${search}%`
422
- }
423
- })
424
- )
425
- }
426
-
427
- return filters
428
- }
429
-
430
- public setInputValue(name: string, value: any) {
431
- const input = this.renderRoot.querySelector(`form [name="${name}"]`) as HTMLInputElement
432
- if (input) {
433
- input.value = value
434
- input.dispatchEvent(new Event('change', { bubbles: true }))
435
- }
436
- }
437
-
438
- public getInputValue(name: string): any {
439
- const input = this.renderRoot.querySelector(`form [name="${name}"]`) as HTMLInputElement
440
- return input?.value
441
- }
442
-
443
- private async updateObjectValues() {
444
- const form = await this.form
445
- if (!form) return []
446
-
447
- const formData = new FormData(form)
448
-
449
- const object = {} as any
450
- formData.forEach((value, key) => {
451
- const prev = object[key]
452
-
453
- if (key in object) {
454
- object[key] = prev instanceof Array ? [...prev, value] : [prev, value]
455
- } else {
456
- object[key] = value
457
- }
458
- })
459
-
460
- this.objectValue = object
461
- }
462
-
463
- public getFormObjectValue() {
464
- return this.objectValue
465
- }
466
-
467
- reset() {
468
- this.form
469
- .then((form: HTMLFormElement) => {
470
- form.reset()
471
- })
472
- .catch((error: any) => {
473
- console.error('Error resetting the form:', error)
474
- })
475
- }
476
- }
@@ -1,10 +0,0 @@
1
- export * from './registry'
2
-
3
- export * from './filter-select'
4
- export * from './filter-input'
5
- export * from './filter-checkbox'
6
- export * from './filter-range-date'
7
- export * from './filter-range-number'
8
- export * from './filter-select-buttons'
9
-
10
- export * from './filters-form'