@operato/data-grist 8.0.0-beta.0 → 8.0.0-beta.2

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 (168) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +10 -10
  3. package/.storybook/main.js +0 -3
  4. package/.storybook/preview.js +0 -52
  5. package/.storybook/server.mjs +0 -8
  6. package/demo/data-grist-test.html +0 -468
  7. package/demo/favicon.ico +0 -0
  8. package/demo/index.html +0 -541
  9. package/demo/report-test.html +0 -249
  10. package/src/accumulator/accumulator.ts +0 -63
  11. package/src/configure/column-builder.ts +0 -114
  12. package/src/configure/config-builder.ts +0 -40
  13. package/src/configure/filters-option-builder.ts +0 -8
  14. package/src/configure/imex-option-builder.ts +0 -5
  15. package/src/configure/list-option-builder.ts +0 -9
  16. package/src/configure/rows-option-builder.ts +0 -38
  17. package/src/configure/tree-option-builder.ts +0 -22
  18. package/src/configure/zero-config.ts +0 -83
  19. package/src/const.ts +0 -1
  20. package/src/data-card/data-card-field.ts +0 -94
  21. package/src/data-card/data-card-gutter-menu.ts +0 -94
  22. package/src/data-card/data-card-gutter.ts +0 -103
  23. package/src/data-card/data-card.ts +0 -154
  24. package/src/data-card/event-handlers/record-card-click-handler.ts +0 -34
  25. package/src/data-card/event-handlers/record-card-dblclick-handler.ts +0 -34
  26. package/src/data-card/record-card.ts +0 -298
  27. package/src/data-consumer.ts +0 -11
  28. package/src/data-grid/data-grid-accum-field.ts +0 -109
  29. package/src/data-grid/data-grid-body-style.ts +0 -85
  30. package/src/data-grid/data-grid-body.ts +0 -765
  31. package/src/data-grid/data-grid-field.ts +0 -227
  32. package/src/data-grid/data-grid-footer.ts +0 -119
  33. package/src/data-grid/data-grid-header.ts +0 -578
  34. package/src/data-grid/data-grid.ts +0 -293
  35. package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +0 -69
  36. package/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.ts +0 -32
  37. package/src/data-grid/event-handlers/data-grid-body-dblclick-handler.ts +0 -42
  38. package/src/data-grid/event-handlers/data-grid-body-focus-change-handler.ts +0 -24
  39. package/src/data-grid/event-handlers/data-grid-body-keydown-handler.ts +0 -234
  40. package/src/data-grist.ts +0 -1233
  41. package/src/data-list/data-list-field.ts +0 -82
  42. package/src/data-list/data-list-gutter.ts +0 -108
  43. package/src/data-list/data-list.ts +0 -145
  44. package/src/data-list/event-handlers/record-partial-click-handler.ts +0 -34
  45. package/src/data-list/event-handlers/record-partial-dblclick-handler.ts +0 -33
  46. package/src/data-list/event-handlers/record-partial-long-press-handler.ts +0 -33
  47. package/src/data-list/record-partial.ts +0 -264
  48. package/src/data-manipulator.ts +0 -426
  49. package/src/data-provider.ts +0 -271
  50. package/src/data-report/data-report-body-style.ts +0 -58
  51. package/src/data-report/data-report-body.ts +0 -189
  52. package/src/data-report/data-report-component.ts +0 -138
  53. package/src/data-report/data-report-field.ts +0 -83
  54. package/src/data-report/data-report-header.ts +0 -242
  55. package/src/data-report/event-handlers/data-report-body-click-handler.ts +0 -38
  56. package/src/data-report/event-handlers/data-report-body-dblclick-handler.ts +0 -25
  57. package/src/data-report/event-handlers/data-report-body-keydown-handler.ts +0 -68
  58. package/src/data-report.ts +0 -424
  59. package/src/editors/index.ts +0 -4
  60. package/src/editors/ox-grist-editor-checkbox.ts +0 -28
  61. package/src/editors/ox-grist-editor-color.ts +0 -10
  62. package/src/editors/ox-grist-editor-date.ts +0 -10
  63. package/src/editors/ox-grist-editor-datetime.ts +0 -27
  64. package/src/editors/ox-grist-editor-email.ts +0 -10
  65. package/src/editors/ox-grist-editor-file.ts +0 -28
  66. package/src/editors/ox-grist-editor-image.ts +0 -31
  67. package/src/editors/ox-grist-editor-month.ts +0 -10
  68. package/src/editors/ox-grist-editor-multiple-select.ts +0 -57
  69. package/src/editors/ox-grist-editor-number.ts +0 -27
  70. package/src/editors/ox-grist-editor-password.ts +0 -10
  71. package/src/editors/ox-grist-editor-select.ts +0 -55
  72. package/src/editors/ox-grist-editor-tel.ts +0 -10
  73. package/src/editors/ox-grist-editor-text.ts +0 -14
  74. package/src/editors/ox-grist-editor-textarea.ts +0 -16
  75. package/src/editors/ox-grist-editor-time.ts +0 -10
  76. package/src/editors/ox-grist-editor-tree.ts +0 -27
  77. package/src/editors/ox-grist-editor-varname.ts +0 -36
  78. package/src/editors/ox-grist-editor-week.ts +0 -10
  79. package/src/editors/ox-grist-editor.ts +0 -207
  80. package/src/editors/ox-input-tree.ts +0 -226
  81. package/src/editors/registry.ts +0 -82
  82. package/src/empty-note.ts +0 -46
  83. package/src/filters/filter-checkbox.ts +0 -49
  84. package/src/filters/filter-input-barcode.ts +0 -34
  85. package/src/filters/filter-input.ts +0 -30
  86. package/src/filters/filter-range-date.ts +0 -81
  87. package/src/filters/filter-range-number.ts +0 -64
  88. package/src/filters/filter-select-buttons.ts +0 -60
  89. package/src/filters/filter-select.ts +0 -68
  90. package/src/filters/filter-styles.ts +0 -119
  91. package/src/filters/filters-form.ts +0 -476
  92. package/src/filters/index.ts +0 -10
  93. package/src/filters/registry.ts +0 -56
  94. package/src/formatters/date-formatter.ts +0 -3
  95. package/src/formatters/index.ts +0 -1
  96. package/src/formatters/number-formatter.ts +0 -3
  97. package/src/formatters/registry.ts +0 -30
  98. package/src/formatters/text-formatter.ts +0 -3
  99. package/src/gutters/gutter-button.ts +0 -51
  100. package/src/gutters/gutter-dirty.ts +0 -96
  101. package/src/gutters/gutter-row-selector.ts +0 -89
  102. package/src/gutters/gutter-sequence.ts +0 -54
  103. package/src/gutters/index.ts +0 -1
  104. package/src/gutters/registry.ts +0 -32
  105. package/src/handlers/contextmenu-tree-mutation.ts +0 -80
  106. package/src/handlers/index.ts +0 -1
  107. package/src/handlers/move-down.ts +0 -44
  108. package/src/handlers/move-up.ts +0 -44
  109. package/src/handlers/record-copy.ts +0 -38
  110. package/src/handlers/record-delete.ts +0 -30
  111. package/src/handlers/record-view-handler.ts +0 -27
  112. package/src/handlers/registry.ts +0 -42
  113. package/src/handlers/select-row-toggle.ts +0 -30
  114. package/src/handlers/select-row.ts +0 -27
  115. package/src/index.ts +0 -17
  116. package/src/personalizer/index.ts +0 -1
  117. package/src/personalizer/ox-grist-filter-personalizer.ts +0 -192
  118. package/src/personalizer/ox-grist-personalizer.ts +0 -226
  119. package/src/record-view/event-handlers/record-view-body-click-handler.ts +0 -33
  120. package/src/record-view/event-handlers/record-view-body-keydown-handler.ts +0 -26
  121. package/src/record-view/index.ts +0 -2
  122. package/src/record-view/ox-record-creator.ts +0 -289
  123. package/src/record-view/record-view-body.ts +0 -257
  124. package/src/record-view/record-view-handler.ts +0 -86
  125. package/src/record-view/record-view.ts +0 -122
  126. package/src/renderers/index.ts +0 -14
  127. package/src/renderers/ox-grist-renderer-boolean.ts +0 -43
  128. package/src/renderers/ox-grist-renderer-color.ts +0 -15
  129. package/src/renderers/ox-grist-renderer-date.ts +0 -62
  130. package/src/renderers/ox-grist-renderer-file.ts +0 -31
  131. package/src/renderers/ox-grist-renderer-image.ts +0 -27
  132. package/src/renderers/ox-grist-renderer-json5.ts +0 -36
  133. package/src/renderers/ox-grist-renderer-link.ts +0 -17
  134. package/src/renderers/ox-grist-renderer-password.ts +0 -7
  135. package/src/renderers/ox-grist-renderer-progress.ts +0 -45
  136. package/src/renderers/ox-grist-renderer-select.ts +0 -58
  137. package/src/renderers/ox-grist-renderer-text.ts +0 -16
  138. package/src/renderers/ox-grist-renderer-textarea.ts +0 -7
  139. package/src/renderers/ox-grist-renderer-tree.ts +0 -189
  140. package/src/renderers/ox-grist-renderer.ts +0 -35
  141. package/src/renderers/registry.ts +0 -111
  142. package/src/sorters/sorters-control.ts +0 -143
  143. package/src/types.ts +0 -813
  144. package/src/utils/index.ts +0 -2
  145. package/src/utils/list-param.ts +0 -72
  146. package/src/utils/supports-passive.ts +0 -13
  147. package/stories/accumulator-format.stories.ts +0 -276
  148. package/stories/barcode-input-filter.stories.ts +0 -216
  149. package/stories/bounded-select-filters.stories.ts +0 -333
  150. package/stories/bounded-select-record.stories.ts +0 -336
  151. package/stories/click-event-custom.stories.ts +0 -287
  152. package/stories/click-event.stories.ts +0 -283
  153. package/stories/creatable-only-column.stories.ts +0 -253
  154. package/stories/default-filters.stories.ts +0 -241
  155. package/stories/dynamic-editable.stories.ts +0 -313
  156. package/stories/empty-sorters.stories.ts +0 -180
  157. package/stories/explicit-fetch.stories.ts +0 -186
  158. package/stories/fixed-column.stories.ts +0 -416
  159. package/stories/grid-setting.stories.ts +0 -501
  160. package/stories/grist-modes.stories.ts +0 -451
  161. package/stories/group-header.stories.ts +0 -442
  162. package/stories/record-view.stories.ts +0 -143
  163. package/stories/textarea.stories.ts +0 -261
  164. package/stories/tree-column-with-checkbox.stories.ts +0 -297
  165. package/stories/tree-column.stories.ts +0 -296
  166. package/tsconfig.json +0 -26
  167. package/web-dev-server.config.mjs +0 -27
  168. package/web-test-runner.config.mjs +0 -45
@@ -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'