@operato/form 2.0.0-alpha.94 → 2.0.0-beta.1
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.
- package/CHANGELOG.md +280 -0
- package/dist/src/components/ox-custom-input.js +5 -5
- package/dist/src/components/ox-custom-input.js.map +1 -1
- package/dist/src/components/ox-custom-select.js +2 -1
- package/dist/src/components/ox-custom-select.js.map +1 -1
- package/dist/src/components/ox-file-uploader.js +1 -1
- package/dist/src/components/ox-file-uploader.js.map +1 -1
- package/dist/src/components/ox-search-form.d.ts +12 -23
- package/dist/src/components/ox-search-form.js +227 -91
- package/dist/src/components/ox-search-form.js.map +1 -1
- package/dist/src/filters/filter-checkbox.js +2 -1
- package/dist/src/filters/filter-checkbox.js.map +1 -1
- package/dist/src/filters/filter-input-barcode.js +5 -3
- package/dist/src/filters/filter-input-barcode.js.map +1 -1
- package/dist/src/filters/filter-input.js +2 -1
- package/dist/src/filters/filter-input.js.map +1 -1
- package/dist/src/filters/filter-range-date.js +3 -1
- package/dist/src/filters/filter-range-date.js.map +1 -1
- package/dist/src/filters/filter-range-number.js +3 -1
- package/dist/src/filters/filter-range-number.js.map +1 -1
- package/dist/src/filters/filter-select.js +23 -11
- package/dist/src/filters/filter-select.js.map +1 -1
- package/dist/src/filters/filter-styles.js +56 -24
- package/dist/src/filters/filter-styles.js.map +1 -1
- package/dist/src/filters/ox-filter-personalizer.d.ts +8 -0
- package/dist/src/filters/ox-filter-personalizer.js +175 -0
- package/dist/src/filters/ox-filter-personalizer.js.map +1 -0
- package/dist/src/filters/ox-filters-form-base.d.ts +13 -3
- package/dist/src/filters/ox-filters-form-base.js +196 -60
- package/dist/src/filters/ox-filters-form-base.js.map +1 -1
- package/dist/src/styles/multi-column-form-styles.js +6 -6
- package/dist/src/styles/multi-column-form-styles.js.map +1 -1
- package/dist/src/styles/search-form-styles.js +23 -18
- package/dist/src/styles/search-form-styles.js.map +1 -1
- package/dist/src/styles/single-column-form-styles.js +5 -5
- package/dist/src/styles/single-column-form-styles.js.map +1 -1
- package/dist/src/types.d.ts +42 -2
- package/dist/src/types.js.map +1 -1
- package/dist/stories/ox-filters-form-barcode.stories.d.ts +5 -0
- package/dist/stories/ox-filters-form-barcode.stories.js +51 -12
- package/dist/stories/ox-filters-form-barcode.stories.js.map +1 -1
- package/dist/stories/ox-filters-form-base-bounded.stories.d.ts +35 -0
- package/dist/stories/ox-filters-form-base-bounded.stories.js +187 -0
- package/dist/stories/ox-filters-form-base-bounded.stories.js.map +1 -0
- package/dist/stories/ox-filters-form-base-change-handler.stories.d.ts +35 -0
- package/dist/stories/ox-filters-form-base-change-handler.stories.js +199 -0
- package/dist/stories/ox-filters-form-base-change-handler.stories.js.map +1 -0
- package/dist/stories/ox-filters-form-base-page-preference.stories.d.ts +31 -0
- package/dist/stories/ox-filters-form-base-page-preference.stories.js +173 -0
- package/dist/stories/ox-filters-form-base-page-preference.stories.js.map +1 -0
- package/dist/stories/ox-filters-form-base.stories.d.ts +5 -0
- package/dist/stories/ox-filters-form-base.stories.js +57 -27
- package/dist/stories/ox-filters-form-base.stories.js.map +1 -1
- package/dist/stories/ox-search-form-change-handler.stories.d.ts +34 -0
- package/dist/stories/ox-search-form-change-handler.stories.js +227 -0
- package/dist/stories/ox-search-form-change-handler.stories.js.map +1 -0
- package/dist/stories/ox-search-form.stories.d.ts +45 -0
- package/dist/stories/ox-search-form.stories.js +235 -0
- package/dist/stories/ox-search-form.stories.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -5
- package/src/components/ox-custom-input.ts +5 -5
- package/src/components/ox-custom-select.ts +2 -1
- package/src/components/ox-file-uploader.ts +1 -1
- package/src/components/ox-search-form.ts +231 -97
- package/src/filters/filter-checkbox.ts +2 -1
- package/src/filters/filter-input-barcode.ts +5 -3
- package/src/filters/filter-input.ts +2 -1
- package/src/filters/filter-range-date.ts +3 -1
- package/src/filters/filter-range-number.ts +3 -1
- package/src/filters/filter-select.ts +29 -20
- package/src/filters/filter-styles.ts +56 -24
- package/src/filters/ox-filter-personalizer.ts +188 -0
- package/src/filters/ox-filters-form-base.ts +222 -79
- package/src/styles/multi-column-form-styles.ts +6 -6
- package/src/styles/search-form-styles.ts +23 -18
- package/src/styles/single-column-form-styles.ts +5 -5
- package/src/types.ts +48 -2
- package/stories/ox-filters-form-barcode.stories.ts +54 -14
- package/stories/ox-filters-form-base-bounded.stories.ts +213 -0
- package/stories/ox-filters-form-base-change-handler.stories.ts +225 -0
- package/stories/ox-filters-form-base-page-preference.stories.ts +192 -0
- package/stories/ox-filters-form-base.stories.ts +63 -31
- package/stories/ox-search-form-change-handler.stories.ts +252 -0
- package/stories/ox-search-form.stories.ts +269 -0
- package/themes/dark-hc.css +151 -0
- package/themes/dark-mc.css +151 -0
- package/themes/dark.css +151 -0
- package/themes/grist-theme.css +169 -0
- package/themes/light-hc.css +151 -0
- package/themes/light-mc.css +151 -0
- package/themes/light.css +151 -0
- package/themes/md-typescale-styles.css +100 -0
- package/themes/spacing.css +43 -0
- package/themes/state-color.css +6 -0
- package/themes/app-theme.css +0 -145
- package/themes/form-theme.css +0 -75
|
@@ -4,24 +4,28 @@ import '@operato/popup/ox-popup-list.js'
|
|
|
4
4
|
import '@operato/input/ox-input-search.js'
|
|
5
5
|
|
|
6
6
|
import json5 from 'json5'
|
|
7
|
-
import { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'
|
|
8
|
-
import { customElement, property, queryAsync } from 'lit/decorators.js'
|
|
7
|
+
import { css, html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit'
|
|
8
|
+
import { customElement, property, queryAsync, state } from 'lit/decorators.js'
|
|
9
|
+
import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
|
|
9
10
|
|
|
10
11
|
import { getDefaultValue } from '@operato/time-calculator'
|
|
12
|
+
import { PagePreferenceProvider } from '@operato/p13n'
|
|
11
13
|
|
|
12
14
|
import { FilterStyles } from './filter-styles.js'
|
|
13
15
|
import { getFilterRenderer } from './registry.js'
|
|
14
|
-
import { FilterConfig, FilterOperator, FilterValue } from '../types.js'
|
|
16
|
+
import { FilterConfig, FilterOperator, FilterSelectRenderer, FilterValue, PersonalFilterPreference } from '../types.js'
|
|
15
17
|
|
|
16
18
|
export type QueryFilterRangeValue = [from: number, to: number]
|
|
17
19
|
|
|
18
20
|
@customElement('ox-filters-form-base')
|
|
19
21
|
export class OxFiltersFormBase extends LitElement {
|
|
20
22
|
static styles = [
|
|
23
|
+
MDTypeScaleStyles,
|
|
21
24
|
FilterStyles,
|
|
22
25
|
css`
|
|
23
26
|
:host {
|
|
24
27
|
display: flex;
|
|
28
|
+
padding: var(--spacing-small);
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
form {
|
|
@@ -29,13 +33,13 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
29
33
|
|
|
30
34
|
display: flex;
|
|
31
35
|
flex-flow: row wrap;
|
|
32
|
-
gap: var(--
|
|
36
|
+
gap: var(--spacing-medium) var(--spacing-large);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
form > * {
|
|
36
40
|
display: flex;
|
|
37
41
|
align-items: center;
|
|
38
|
-
gap: var(--
|
|
42
|
+
gap: var(--spacing-small, 4px);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
label span {
|
|
@@ -43,8 +47,9 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
@media only screen and (max-width: 460px) {
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
form {
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
flex-flow: column;
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
`
|
|
@@ -54,11 +59,16 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
54
59
|
@property({ type: Array }) filters: FilterConfig[] = []
|
|
55
60
|
@property({ type: Boolean, attribute: 'url-params-sensitive' }) urlParamsSensitive?: boolean
|
|
56
61
|
@property({ type: Boolean, attribute: 'autofocus' }) autofocus: boolean = true
|
|
62
|
+
@property({ type: Object }) personalConfigProvider?: PagePreferenceProvider
|
|
63
|
+
|
|
64
|
+
@state() personalConfig?: PersonalFilterPreference
|
|
65
|
+
@state() personalFilters?: FilterConfig[]
|
|
57
66
|
|
|
58
67
|
@queryAsync('form') form!: HTMLFormElement
|
|
59
68
|
|
|
60
69
|
private _popstateEventHandler?: EventListener
|
|
61
70
|
private _filtersChangeHandler?: EventListener
|
|
71
|
+
private autoUpdateTargetsOnChange: { [name: string]: string[] } = {}
|
|
62
72
|
|
|
63
73
|
connectedCallback(): void {
|
|
64
74
|
super.connectedCallback()
|
|
@@ -72,9 +82,25 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
72
82
|
operator,
|
|
73
83
|
value: defaultValue,
|
|
74
84
|
onchange
|
|
75
|
-
} = this.
|
|
85
|
+
} = (this.personalFilters || []).find(filter => filter.name == name) || {}
|
|
86
|
+
|
|
87
|
+
if (this.autoUpdateTargetsOnChange[name]) {
|
|
88
|
+
/*
|
|
89
|
+
일단은 심플하게, boundTo로 연결된 필터값이 바뀌면, 폼 전체를 update하도록 함.
|
|
90
|
+
*/
|
|
91
|
+
;(this.autoUpdateTargetsOnChange[name] || []).forEach(name => {
|
|
92
|
+
const target = this.renderRoot.querySelector(`[name='${name}']`)
|
|
93
|
+
if (target) {
|
|
94
|
+
;(target as HTMLInputElement).value = ''
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
this.requestUpdate()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const keepGoing = onchange ? await onchange.call(null, value ?? (target as HTMLInputElement).value, this) : true
|
|
76
102
|
|
|
77
|
-
|
|
103
|
+
this.value = await this.getQueryFilters()
|
|
78
104
|
|
|
79
105
|
keepGoing &&
|
|
80
106
|
this.dispatchEvent(
|
|
@@ -90,12 +116,12 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
90
116
|
})
|
|
91
117
|
}
|
|
92
118
|
|
|
93
|
-
buildDefaultValue(operator:
|
|
119
|
+
buildDefaultValue(operator: FilterOperator, defaultValue: any) {
|
|
94
120
|
if (defaultValue === undefined) {
|
|
95
121
|
return
|
|
96
122
|
}
|
|
97
123
|
if (operator == 'between') {
|
|
98
|
-
return (defaultValue as Array<any>).map(v => getDefaultValue(v, this))
|
|
124
|
+
return defaultValue instanceof Array && (defaultValue as Array<any>).map(v => getDefaultValue(v, this))
|
|
99
125
|
} else {
|
|
100
126
|
return getDefaultValue(defaultValue, this)
|
|
101
127
|
}
|
|
@@ -104,84 +130,98 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
104
130
|
render(): TemplateResult {
|
|
105
131
|
return html`
|
|
106
132
|
<form
|
|
133
|
+
class="md-typescale-body-medium-prominent"
|
|
107
134
|
@submit=${(e: Event) => {
|
|
108
135
|
e.preventDefault()
|
|
109
136
|
}}
|
|
110
137
|
>
|
|
111
|
-
${this.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
138
|
+
${(this.personalFilters || [])
|
|
139
|
+
.filter(filter => !filter.hidden)
|
|
140
|
+
.map((filter: FilterConfig) => {
|
|
141
|
+
const { name, label, type, operator, readonly, value: defaultValue } = filter
|
|
142
|
+
const idx = operator === 'between' ? 1 : 0
|
|
143
|
+
const renderer = getFilterRenderer(
|
|
144
|
+
operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'
|
|
145
|
+
? 'text'
|
|
146
|
+
: type
|
|
147
|
+
)[idx]
|
|
148
|
+
|
|
149
|
+
const value =
|
|
150
|
+
this.value?.find(filter => filter.name == name)?.value ?? this.buildDefaultValue(operator!, defaultValue)
|
|
151
|
+
|
|
152
|
+
if (!renderer) {
|
|
153
|
+
return nothing
|
|
154
|
+
}
|
|
126
155
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
: operator === 'in'
|
|
156
|
+
return type === 'search'
|
|
157
|
+
? html`<ox-input-search
|
|
158
|
+
name="search"
|
|
159
|
+
.value=${value}
|
|
160
|
+
?autofocus=${this.autofocus}
|
|
161
|
+
?readonly=${readonly}
|
|
162
|
+
></ox-input-search>`
|
|
163
|
+
: type === 'boolean' || type === 'checkbox'
|
|
164
|
+
? renderer(filter, value, this)
|
|
165
|
+
: type !== 'select'
|
|
138
166
|
? html`
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
.value=${value}
|
|
143
|
-
@change=${(e: CustomEvent) =>
|
|
144
|
-
e.target?.dispatchEvent(
|
|
145
|
-
new CustomEvent('filter-change', {
|
|
146
|
-
detail: {
|
|
147
|
-
name,
|
|
148
|
-
operator,
|
|
149
|
-
value: e.detail
|
|
150
|
-
}
|
|
151
|
-
})
|
|
152
|
-
)}
|
|
153
|
-
>
|
|
154
|
-
<ox-popup-list multiple attr-selected="checked" with-search>
|
|
155
|
-
${renderer(filter, value, this)}
|
|
156
|
-
</ox-popup-list>
|
|
157
|
-
</ox-select>
|
|
167
|
+
<label filter-title ?between=${operator == 'between'}
|
|
168
|
+
><span>${label}</span> ${renderer(filter, value, this)}
|
|
169
|
+
</label>
|
|
158
170
|
`
|
|
159
|
-
:
|
|
160
|
-
|
|
161
|
-
name=${name}
|
|
162
|
-
placeholder=${label}
|
|
163
|
-
.value=${value}
|
|
164
|
-
@change=${(e: CustomEvent) =>
|
|
165
|
-
e.target?.dispatchEvent(
|
|
166
|
-
new CustomEvent('filter-change', {
|
|
167
|
-
detail: {
|
|
168
|
-
name,
|
|
169
|
-
operator,
|
|
170
|
-
value: e.detail
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
)}
|
|
174
|
-
>
|
|
175
|
-
<ox-popup-list with-search> ${renderer(filter, value, this)} </ox-popup-list>
|
|
176
|
-
</ox-select>
|
|
177
|
-
`
|
|
178
|
-
})}
|
|
171
|
+
: this.renderSelect(filter, value, renderer)
|
|
172
|
+
})}
|
|
179
173
|
</form>
|
|
174
|
+
|
|
175
|
+
<slot name="setting"></slot>
|
|
180
176
|
`
|
|
181
177
|
}
|
|
182
178
|
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
renderSelect(filter: FilterConfig, value: any, renderer: FilterSelectRenderer) {
|
|
180
|
+
const { name, label, operator, readonly, value: defaultValue } = filter
|
|
181
|
+
|
|
182
|
+
return operator === 'in'
|
|
183
|
+
? html`
|
|
184
|
+
<ox-select
|
|
185
|
+
name=${name}
|
|
186
|
+
placeholder=${label}
|
|
187
|
+
.value=${value ?? defaultValue}
|
|
188
|
+
@change=${(e: CustomEvent) =>
|
|
189
|
+
e.target?.dispatchEvent(
|
|
190
|
+
new CustomEvent('filter-change', {
|
|
191
|
+
detail: {
|
|
192
|
+
name,
|
|
193
|
+
operator,
|
|
194
|
+
value: e.detail
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
)}
|
|
198
|
+
?readonly=${readonly}
|
|
199
|
+
>
|
|
200
|
+
<ox-popup-list multiple attr-selected="checked" with-search>
|
|
201
|
+
${renderer(filter, value, this)}
|
|
202
|
+
</ox-popup-list>
|
|
203
|
+
</ox-select>
|
|
204
|
+
`
|
|
205
|
+
: html`
|
|
206
|
+
<ox-select
|
|
207
|
+
name=${name}
|
|
208
|
+
placeholder=${label}
|
|
209
|
+
.value=${value ?? defaultValue}
|
|
210
|
+
@change=${(e: CustomEvent) =>
|
|
211
|
+
e.target?.dispatchEvent(
|
|
212
|
+
new CustomEvent('filter-change', {
|
|
213
|
+
detail: {
|
|
214
|
+
name,
|
|
215
|
+
operator,
|
|
216
|
+
value: e.detail
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
)}
|
|
220
|
+
?readonly=${readonly}
|
|
221
|
+
>
|
|
222
|
+
<ox-popup-list with-search> ${renderer(filter, value, this)} </ox-popup-list>
|
|
223
|
+
</ox-select>
|
|
224
|
+
`
|
|
185
225
|
}
|
|
186
226
|
|
|
187
227
|
async updated(changes: PropertyValues<this>) {
|
|
@@ -245,12 +285,82 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
245
285
|
}
|
|
246
286
|
}
|
|
247
287
|
}
|
|
288
|
+
|
|
289
|
+
if (changes.has('personalConfigProvider') && this.personalConfigProvider) {
|
|
290
|
+
this.personalConfig = await this.personalConfigProvider.load()
|
|
291
|
+
} else if (changes.has('filters') || changes.has('personalConfig')) {
|
|
292
|
+
this.applyUpdatedConfiguration()
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async applyUpdatedConfiguration() {
|
|
297
|
+
if (!this.filters) {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!this.personalConfig) {
|
|
302
|
+
this.personalFilters = [...this.filters]
|
|
303
|
+
} else {
|
|
304
|
+
const { filters: personalFilters } = this.personalConfig
|
|
305
|
+
|
|
306
|
+
if (personalFilters) {
|
|
307
|
+
const xfilters = this.filters.map((filter: Partial<FilterConfig>) => {
|
|
308
|
+
const personalFilter = personalFilters.find(pFilter => pFilter.name == filter.name)
|
|
309
|
+
return personalFilter ? { ...filter, ...personalFilter } : filter
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
function reorderList(a: Partial<FilterConfig>[], b: Partial<FilterConfig>[]): Partial<FilterConfig>[] {
|
|
313
|
+
// 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
|
|
314
|
+
const result = new Array(a.length)
|
|
315
|
+
|
|
316
|
+
// b 배열에 없는 아이템은 원래 위치로 채움
|
|
317
|
+
a.forEach((item, index) => {
|
|
318
|
+
if (!item.name || !b.find(bi => bi.name == item.name)) {
|
|
319
|
+
result[index] = item
|
|
320
|
+
}
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
b.forEach(item => {
|
|
324
|
+
const ai = a.find(ai => ai.name == item.name)
|
|
325
|
+
if (ai) {
|
|
326
|
+
result[result.findIndex(slot => slot === undefined)] = ai
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
return result
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// 배열 재정렬 실행
|
|
334
|
+
this.personalFilters = reorderList(xfilters as any, personalFilters as any) as FilterConfig[]
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
this.autoUpdateTargetsOnChange = {}
|
|
339
|
+
|
|
340
|
+
this.personalFilters
|
|
341
|
+
?.filter(filter => filter.boundTo && filter.boundTo.length > 0)
|
|
342
|
+
.map(({ name, boundTo }) => {
|
|
343
|
+
boundTo!.forEach(to => {
|
|
344
|
+
const origin = this.autoUpdateTargetsOnChange[to] || []
|
|
345
|
+
if (name && !origin.includes(name)) {
|
|
346
|
+
this.autoUpdateTargetsOnChange[to] = [...origin, name]
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
if (!this.urlParamsSensitive) {
|
|
352
|
+
this.value = await this.getQueryFilters()
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
getFieldByName(name: string) {
|
|
357
|
+
return this.renderRoot.querySelector(`[name=${name}]`)
|
|
248
358
|
}
|
|
249
359
|
|
|
250
360
|
async getQueryFilters(): Promise<FilterValue[]> {
|
|
251
361
|
const formData = new FormData(await this.form)
|
|
252
362
|
|
|
253
|
-
var filters = this.
|
|
363
|
+
var filters = (this.personalFilters || [])
|
|
254
364
|
.map((filter: FilterConfig) => {
|
|
255
365
|
const { name, type, operator } = filter
|
|
256
366
|
|
|
@@ -290,4 +400,37 @@ export class OxFiltersFormBase extends LitElement {
|
|
|
290
400
|
|
|
291
401
|
return filters
|
|
292
402
|
}
|
|
403
|
+
|
|
404
|
+
reset(value?: string[] | { [field: string]: any }) {
|
|
405
|
+
this.form
|
|
406
|
+
.then((form: HTMLFormElement) => {
|
|
407
|
+
if (value) {
|
|
408
|
+
if (value instanceof Array) {
|
|
409
|
+
value
|
|
410
|
+
.filter(item => typeof item == 'string')
|
|
411
|
+
.forEach(item => {
|
|
412
|
+
const field = this.getFieldByName(item)
|
|
413
|
+
if (field) {
|
|
414
|
+
;(field as HTMLInputElement).value = ''
|
|
415
|
+
}
|
|
416
|
+
})
|
|
417
|
+
} else {
|
|
418
|
+
const keys = Object.keys(value)
|
|
419
|
+
keys
|
|
420
|
+
.filter(key => typeof key == 'string')
|
|
421
|
+
.forEach(key => {
|
|
422
|
+
const field = this.getFieldByName(key)
|
|
423
|
+
if (field) {
|
|
424
|
+
;(field as HTMLInputElement).value = value[key]
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
} else {
|
|
429
|
+
form.reset()
|
|
430
|
+
}
|
|
431
|
+
})
|
|
432
|
+
.catch((error: any) => {
|
|
433
|
+
console.error('Error resetting the form:', error)
|
|
434
|
+
})
|
|
435
|
+
}
|
|
293
436
|
}
|
|
@@ -23,7 +23,7 @@ export const MultiColumnFormStyles = css`
|
|
|
23
23
|
|
|
24
24
|
padding: var(--legend-padding);
|
|
25
25
|
font: var(--legend-font);
|
|
26
|
-
color: var(--legend-text-color);
|
|
26
|
+
color: var(--legend-text-color, var(--md-sys-color-on-surface-variant));
|
|
27
27
|
border-bottom: var(--legend-border-bottom);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -33,7 +33,7 @@ export const MultiColumnFormStyles = css`
|
|
|
33
33
|
text-transform: capitalize;
|
|
34
34
|
align-self: center;
|
|
35
35
|
|
|
36
|
-
color: var(--label-color);
|
|
36
|
+
color: var(--label-color, var(--md-sys-color-on-surface));
|
|
37
37
|
font: var(--label-font);
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -72,7 +72,7 @@ export const MultiColumnFormStyles = css`
|
|
|
72
72
|
grid-column: span 9 / auto;
|
|
73
73
|
|
|
74
74
|
font: var(--form-sublabel-font);
|
|
75
|
-
color: var(--form-sublabel-color);
|
|
75
|
+
color: var(--form-sublabel-color, var(--md-sys-color-on-surface));
|
|
76
76
|
}
|
|
77
77
|
.multi-column-form [options-wrap] {
|
|
78
78
|
grid-column: span 21 / auto;
|
|
@@ -80,7 +80,7 @@ export const MultiColumnFormStyles = css`
|
|
|
80
80
|
|
|
81
81
|
input:focus {
|
|
82
82
|
outline: none;
|
|
83
|
-
border: 1px solid var(--focus-background-color);
|
|
83
|
+
border: 1px solid var(--focus-background-color, var(--md-sys-color-surface-variant));
|
|
84
84
|
}
|
|
85
85
|
input[type='checkbox'] {
|
|
86
86
|
margin: 0;
|
|
@@ -109,7 +109,7 @@ export const MultiColumnFormStyles = css`
|
|
|
109
109
|
.multi-column-form [custom-input] {
|
|
110
110
|
grid-column: span 8 / auto;
|
|
111
111
|
max-width: initial;
|
|
112
|
-
padding: var(--padding-default);
|
|
112
|
+
padding: var(--padding-default, var(--spacing-medium));
|
|
113
113
|
font: normal 15px var(--theme-font);
|
|
114
114
|
}
|
|
115
115
|
.multi-column-form input[type='checkbox'],
|
|
@@ -131,7 +131,7 @@ export const MultiColumnFormStyles = css`
|
|
|
131
131
|
.multi-column-form [options-wrap] {
|
|
132
132
|
grid-column: span 12 / auto;
|
|
133
133
|
display: grid;
|
|
134
|
-
grid-gap: var(--padding-default) var(--padding-narrow);
|
|
134
|
+
grid-gap: var(--padding-default, var(--spacing-small)) var(--padding-narrow, var(--spacing-small));
|
|
135
135
|
grid-template-columns: repeat(12, 1fr);
|
|
136
136
|
}
|
|
137
137
|
.multi-column-form [options-wrap] input[type='checkbox'] + label,
|
|
@@ -3,17 +3,16 @@ import { css } from 'lit'
|
|
|
3
3
|
export const SearchFormStyles = css`
|
|
4
4
|
:host {
|
|
5
5
|
overflow: auto;
|
|
6
|
-
background-color:
|
|
6
|
+
background-color: transparent;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.search-form {
|
|
10
10
|
position: relative;
|
|
11
11
|
display: grid;
|
|
12
12
|
grid-template-columns: repeat(24, 1fr);
|
|
13
|
-
grid-gap: var(--form-grid-gap);
|
|
13
|
+
grid-gap: var(--form-grid-gap, var(--spacing-medium));
|
|
14
14
|
grid-auto-rows: minmax(24px, auto);
|
|
15
|
-
|
|
16
|
-
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
15
|
+
background-color: var(--search-form-background-color, var(--md-sys-color-surface));
|
|
17
16
|
}
|
|
18
17
|
.search-form label {
|
|
19
18
|
grid-column: span 3;
|
|
@@ -21,8 +20,8 @@ export const SearchFormStyles = css`
|
|
|
21
20
|
align-self: center;
|
|
22
21
|
text-transform: capitalize;
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
font-size: var(--md-sys-typescale-label-large-size, 0.875rem);
|
|
24
|
+
color: var(--md-sys-color-on-primary-container);
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
.search-form input,
|
|
@@ -30,12 +29,13 @@ export const SearchFormStyles = css`
|
|
|
30
29
|
grid-column: span 9;
|
|
31
30
|
|
|
32
31
|
border: var(--input-field-border);
|
|
32
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
|
33
33
|
border-radius: var(--input-field-border-radius);
|
|
34
|
-
padding: var(--input-field-padding);
|
|
34
|
+
padding: var(--input-field-padding, var(--spacing-tiny));
|
|
35
35
|
font: var(--input-field-font);
|
|
36
36
|
max-width: 85%;
|
|
37
|
-
color: var(--input-field-color);
|
|
38
|
-
background-color:
|
|
37
|
+
color: var(--input-field-color, var(--md-sys-color-on-surface-variant));
|
|
38
|
+
background-color: transparent;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.search-form select {
|
|
@@ -60,13 +60,13 @@ export const SearchFormStyles = css`
|
|
|
60
60
|
grid-column: span 9 / auto;
|
|
61
61
|
|
|
62
62
|
font: var(--form-sublabel-font);
|
|
63
|
-
color: var(--form-sublabel-color);
|
|
63
|
+
color: var(--form-sublabel-color, var(--md-sys-color-on-surface-variant));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
input:focus {
|
|
67
67
|
outline: none;
|
|
68
|
-
border: 1px solid var(--focus-background-color);
|
|
69
68
|
}
|
|
69
|
+
|
|
70
70
|
input[type='checkbox'] {
|
|
71
71
|
margin: 0;
|
|
72
72
|
}
|
|
@@ -75,14 +75,19 @@ export const SearchFormStyles = css`
|
|
|
75
75
|
position: absolute;
|
|
76
76
|
right: 1%;
|
|
77
77
|
bottom: 15px;
|
|
78
|
-
color: var(--search-form-icon-color);
|
|
78
|
+
color: var(--search-form-icon-color, var(--md-sys-color-on-surface-variant));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
input[readonly],
|
|
82
|
+
select[readonly] {
|
|
83
|
+
background-color: #f0f0f0;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
@media screen and (max-width: 460px) {
|
|
82
87
|
.search-form {
|
|
83
88
|
grid-template-columns: repeat(12, 1fr);
|
|
84
|
-
grid-gap:
|
|
85
|
-
background-color:
|
|
89
|
+
grid-gap: var(--spacing-medium) var(--spacing-medium);
|
|
90
|
+
background-color: transparent;
|
|
86
91
|
|
|
87
92
|
max-height: 100%;
|
|
88
93
|
overflow-y: auto;
|
|
@@ -91,13 +96,13 @@ export const SearchFormStyles = css`
|
|
|
91
96
|
grid-column: span 3;
|
|
92
97
|
padding-right: 5px;
|
|
93
98
|
align-self: center;
|
|
94
|
-
color: var(--search-form-narrow-text-color);
|
|
99
|
+
color: var(--search-form-narrow-text-color, var(--md-sys-color-on-surface));
|
|
95
100
|
}
|
|
96
101
|
.search-form input,
|
|
97
102
|
.search-form select {
|
|
98
103
|
grid-column: span 8;
|
|
99
104
|
max-width: 100%;
|
|
100
|
-
color: var(--
|
|
105
|
+
color: var(--md-sys-color-surface, var(--md-sys-color-on-surface));
|
|
101
106
|
}
|
|
102
107
|
.search-form input[type='checkbox'],
|
|
103
108
|
.search-form input[type='radio'] {
|
|
@@ -112,12 +117,12 @@ export const SearchFormStyles = css`
|
|
|
112
117
|
align-self: center;
|
|
113
118
|
position: relative;
|
|
114
119
|
left: 5px;
|
|
115
|
-
color: var(--search-form-narrow-text-color);
|
|
120
|
+
color: var(--search-form-narrow-text-color, var(--md-sys-color-on-surface));
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
[search] {
|
|
119
124
|
right: 3%;
|
|
120
|
-
color: var(--search-form-narrow-text-color);
|
|
125
|
+
color: var(--search-form-narrow-text-color, var(--md-sys-color-on-surface));
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
128
|
@media (min-width: 461px) and (max-width: 1024px) {
|
|
@@ -24,7 +24,7 @@ export const SingleColumnFormStyles = css`
|
|
|
24
24
|
|
|
25
25
|
padding: var(--legend-padding);
|
|
26
26
|
font: var(--legend-font);
|
|
27
|
-
color: var(--legend-text-color);
|
|
27
|
+
color: var(--legend-text-color, var(--md-sys-color-on-surface-variant));
|
|
28
28
|
border-bottom: var(--legend-border-bottom);
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ export const SingleColumnFormStyles = css`
|
|
|
33
33
|
text-align: right;
|
|
34
34
|
text-transform: capitalize;
|
|
35
35
|
|
|
36
|
-
color: var(--label-color);
|
|
36
|
+
color: var(--label-color, var(--md-sys-color-on-surface));
|
|
37
37
|
font: var(--label-font);
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -66,12 +66,12 @@ export const SingleColumnFormStyles = css`
|
|
|
66
66
|
grid-column: span 9 / auto;
|
|
67
67
|
|
|
68
68
|
font: var(--form-sublabel-font);
|
|
69
|
-
color: var(--form-sublabel-color);
|
|
69
|
+
color: var(--form-sublabel-color, var(--md-sys-color-on-surface));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
input:focus {
|
|
73
73
|
outline: none;
|
|
74
|
-
border: 1px solid var(--focus-background-color);
|
|
74
|
+
border: 1px solid var(--focus-background-color, var(--md-sys-color-surface-variant));
|
|
75
75
|
}
|
|
76
76
|
input[type='checkbox'] {
|
|
77
77
|
margin: 0;
|
|
@@ -94,7 +94,7 @@ export const SingleColumnFormStyles = css`
|
|
|
94
94
|
.single-column-form [custom-input] {
|
|
95
95
|
grid-column: span 12;
|
|
96
96
|
|
|
97
|
-
padding: var(--padding-default);
|
|
97
|
+
padding: var(--padding-default, var(--spacing-medium));
|
|
98
98
|
font: normal 15px var(--theme-font);
|
|
99
99
|
}
|
|
100
100
|
.single-column-form input[type='checkbox'],
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit-html'
|
|
2
2
|
import { OxFiltersFormBase } from './filters/ox-filters-form-base'
|
|
3
|
+
import { OxSearchForm } from './components/ox-search-form'
|
|
3
4
|
|
|
4
5
|
export type FilterOperator =
|
|
5
6
|
| 'search'
|
|
@@ -27,12 +28,31 @@ export type FilterOperator =
|
|
|
27
28
|
| 'i_nlike'
|
|
28
29
|
| 'nlike'
|
|
29
30
|
|
|
31
|
+
export type SelectOptionObject =
|
|
32
|
+
| {
|
|
33
|
+
name: string
|
|
34
|
+
display?: never
|
|
35
|
+
value: string
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
display: string
|
|
39
|
+
name?: never
|
|
40
|
+
value: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type SelectOption = SelectOptionObject | string
|
|
44
|
+
|
|
45
|
+
export type FilterChangedCallback = (value: any, form: OxFiltersFormBase) => boolean | Promise<boolean>
|
|
46
|
+
|
|
30
47
|
export type FilterConfig = {
|
|
31
48
|
name: string
|
|
32
49
|
label: string
|
|
33
50
|
type: string
|
|
34
51
|
operator?: FilterOperator
|
|
35
|
-
options?:
|
|
52
|
+
options?:
|
|
53
|
+
| { [key: string]: any }
|
|
54
|
+
| SelectOption[]
|
|
55
|
+
| ((form: OxFiltersFormBase) => SelectOption[] | Promise<SelectOption[]>)
|
|
36
56
|
value?:
|
|
37
57
|
| string
|
|
38
58
|
| number
|
|
@@ -42,6 +62,9 @@ export type FilterConfig = {
|
|
|
42
62
|
| number[]
|
|
43
63
|
| { name: string; [params: string]: any }[]
|
|
44
64
|
| undefined
|
|
65
|
+
boundTo?: string[]
|
|
66
|
+
hidden?: boolean
|
|
67
|
+
readonly?: boolean
|
|
45
68
|
onchange?: FilterChangedCallback
|
|
46
69
|
}
|
|
47
70
|
|
|
@@ -57,4 +80,27 @@ export type FilterSelectRenderer = (
|
|
|
57
80
|
owner: Element
|
|
58
81
|
) => TemplateResult | string | void
|
|
59
82
|
|
|
60
|
-
export type
|
|
83
|
+
export type SearchFilterChangedCallback = (value: any, form: OxSearchForm) => boolean | Promise<boolean>
|
|
84
|
+
|
|
85
|
+
export type SearchFormField = {
|
|
86
|
+
type: string
|
|
87
|
+
hidden?: boolean
|
|
88
|
+
name?: string
|
|
89
|
+
id?: string
|
|
90
|
+
label?: string
|
|
91
|
+
placeholder?: string
|
|
92
|
+
value?: any
|
|
93
|
+
field?: string
|
|
94
|
+
queryName?: string
|
|
95
|
+
props?: { [prop: string]: string }
|
|
96
|
+
attrs?: string[]
|
|
97
|
+
options?: SelectOption[] | ((form: OxSearchForm) => SelectOption[] | Promise<SelectOption[]>)
|
|
98
|
+
boundTo?: string[]
|
|
99
|
+
readonly?: boolean
|
|
100
|
+
handlers?: { [event: string]: EventListener }
|
|
101
|
+
onchange?: SearchFilterChangedCallback
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type PersonalFilterPreference = {
|
|
105
|
+
filters?: Partial<FilterConfig>[]
|
|
106
|
+
}
|