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