@operato/data-grist 2.0.0-alpha.102 → 2.0.0-alpha.104
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 +23 -0
- package/dist/src/editors/ox-grist-editor-select.js +37 -25
- package/dist/src/editors/ox-grist-editor-select.js.map +1 -1
- package/dist/src/filters/filter-select.js +30 -16
- package/dist/src/filters/filter-select.js.map +1 -1
- package/dist/src/filters/filters-form.d.ts +6 -2
- package/dist/src/filters/filters-form.js +74 -21
- package/dist/src/filters/filters-form.js.map +1 -1
- package/dist/src/renderers/ox-grist-renderer-select.js +34 -4
- package/dist/src/renderers/ox-grist-renderer-select.js.map +1 -1
- package/dist/src/types.d.ts +14 -1
- package/dist/src/types.js.map +1 -1
- package/dist/stories/bounded-select-filters.stories.d.ts +25 -0
- package/dist/stories/bounded-select-filters.stories.js +264 -0
- package/dist/stories/bounded-select-filters.stories.js.map +1 -0
- package/dist/stories/bounded-select-record.stories.d.ts +25 -0
- package/dist/stories/bounded-select-record.stories.js +267 -0
- package/dist/stories/bounded-select-record.stories.js.map +1 -0
- package/dist/stories/default-filters.stories.js +43 -0
- package/dist/stories/default-filters.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/default-value/value-generator/date-generator.md +29 -0
- package/docs/default-value/value-generator/hour-time-generator.md +33 -0
- package/docs/default-value/value-generator/minute-time-generator.md +33 -0
- package/docs/default-value/value-generator/month-date-generator.md +2 -0
- package/docs/default-value/value-generator/now-generator.md +29 -0
- package/docs/default-value/value-generator/time-generator.md +31 -0
- package/docs/default-value/value-generator/today-generator.md +29 -0
- package/docs/default-value/value-generator/week-date-generator.md +31 -0
- package/docs/default-value/value-generator/year-date-generator.md +31 -0
- package/package.json +3 -3
- package/src/editors/ox-grist-editor-select.ts +41 -28
- package/src/filters/filter-select.ts +41 -28
- package/src/filters/filters-form.ts +74 -10
- package/src/renderers/ox-grist-renderer-select.ts +41 -6
- package/src/types.ts +19 -1
- package/stories/bounded-select-filters.stories.ts +313 -0
- package/stories/bounded-select-record.stories.ts +316 -0
- package/stories/default-filters.stories.ts +43 -0
- package/yarn-error.log +0 -16971
@@ -30,14 +30,47 @@ function getRelativeHourTime(params: RelativeHourTimeParams = {}): string | numb
|
|
30
30
|
## 예제
|
31
31
|
|
32
32
|
```typescript
|
33
|
+
/* get Date() object */
|
33
34
|
const relativeHourTime = getRelativeHourTime({
|
34
35
|
relativeHour: 2,
|
35
36
|
relativeSeconds: 120,
|
36
37
|
timeZone: 'Asia/Seoul',
|
38
|
+
loclae: 'en-CA',
|
37
39
|
format: 'date'
|
38
40
|
})
|
39
41
|
|
40
42
|
console.log(relativeHourTime)
|
41
43
|
```
|
42
44
|
|
45
|
+
```typescript
|
46
|
+
/* text format style */
|
47
|
+
const relativeHourTime = getRelativeHourTime({
|
48
|
+
relativeHour: 2,
|
49
|
+
relativeSeconds: 120,
|
50
|
+
timeZone: 'Asia/Seoul',
|
51
|
+
format: 'h:mm:ss'
|
52
|
+
})
|
53
|
+
|
54
|
+
console.log(relativeHourTime)
|
55
|
+
```
|
56
|
+
|
57
|
+
```typescript
|
58
|
+
/* Intl.DateTimeFormat style */
|
59
|
+
const relativeHourTime = getRelativeHourTime({
|
60
|
+
relativeHour: 2,
|
61
|
+
relativeSeconds: 120,
|
62
|
+
timeZone: 'Asia/Seoul',
|
63
|
+
loclae: 'en-CA',
|
64
|
+
format: {
|
65
|
+
hour: 'numeric',
|
66
|
+
minute: 'numeric',
|
67
|
+
second: 'numeric',
|
68
|
+
hour12: false,
|
69
|
+
timeZone: 'America/Los_Angeles'
|
70
|
+
}
|
71
|
+
})
|
72
|
+
|
73
|
+
console.log(relativeHourTime)
|
74
|
+
```
|
75
|
+
|
43
76
|
이 코드는 현재 시간으로부터 2시간 후와 2분 후의 시간을 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -30,14 +30,47 @@ function getRelativeMinuteTime(params: RelativeMinuteTimeParams = {}): string |
|
|
30
30
|
## 예제
|
31
31
|
|
32
32
|
```typescript
|
33
|
+
/* get Date() object */
|
33
34
|
const relativeMinuteTime = getRelativeMinuteTime({
|
34
35
|
relativeMinutes: 15,
|
35
36
|
relativeSeconds: 30,
|
36
37
|
timeZone: 'Asia/Seoul',
|
38
|
+
loclae: 'en-CA',
|
37
39
|
format: 'date'
|
38
40
|
})
|
39
41
|
|
40
42
|
console.log(relativeMinuteTime)
|
41
43
|
```
|
42
44
|
|
45
|
+
```typescript
|
46
|
+
/* text format style */
|
47
|
+
const relativeMinuteTime = getRelativeMinuteTime({
|
48
|
+
relativeMinutes: 15,
|
49
|
+
relativeSeconds: 30,
|
50
|
+
timeZone: 'Asia/Seoul',
|
51
|
+
format: 'mm:ss'
|
52
|
+
})
|
53
|
+
|
54
|
+
console.log(relativeMinuteTime)
|
55
|
+
```
|
56
|
+
|
57
|
+
```typescript
|
58
|
+
/* Intl.DateTimeFormat style */
|
59
|
+
const relativeMinuteTime = getRelativeMinuteTime({
|
60
|
+
relativeMinutes: 15,
|
61
|
+
relativeSeconds: 30,
|
62
|
+
timeZone: 'Asia/Seoul',
|
63
|
+
loclae: 'en-CA',
|
64
|
+
format: {
|
65
|
+
hour: 'numeric',
|
66
|
+
minute: 'numeric',
|
67
|
+
second: 'numeric',
|
68
|
+
hour12: false,
|
69
|
+
timeZone: 'America/Los_Angeles'
|
70
|
+
}
|
71
|
+
})
|
72
|
+
|
73
|
+
console.log(relativeMinuteTime)
|
74
|
+
```
|
75
|
+
|
43
76
|
이 코드는 현재 시간으로부터 15분 30초 후의 시간을 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -30,10 +30,12 @@ function getRelativeMonthDate(params: RelativeMonthDateParams = {}): string | nu
|
|
30
30
|
## 예제
|
31
31
|
|
32
32
|
```typescript
|
33
|
+
/* get Date() object */
|
33
34
|
const relativeMonthDate = getRelativeMonthDate({
|
34
35
|
relativeMonths: 2,
|
35
36
|
relativeDays: 3,
|
36
37
|
timeZone: 'Asia/Seoul',
|
38
|
+
loclae: 'en-CA',
|
37
39
|
format: 'date'
|
38
40
|
})
|
39
41
|
|
@@ -28,12 +28,41 @@ function getCurrentTime(
|
|
28
28
|
## 예제
|
29
29
|
|
30
30
|
```typescript
|
31
|
+
/* get Date() object */
|
31
32
|
const currentTime = getCurrentTime({
|
32
33
|
timeZone: 'Asia/Seoul',
|
34
|
+
loclae: 'en-CA',
|
33
35
|
format: 'date'
|
34
36
|
})
|
35
37
|
|
36
38
|
console.log(currentTime)
|
37
39
|
```
|
38
40
|
|
41
|
+
```typescript
|
42
|
+
/* text format style */
|
43
|
+
const relativeDate = getCurrentTime({
|
44
|
+
relativeDays: 1,
|
45
|
+
timeZone: 'Asia/Seoul',
|
46
|
+
format: 'YYYY-MM-DD'
|
47
|
+
})
|
48
|
+
|
49
|
+
console.log(relativeDate)
|
50
|
+
```
|
51
|
+
|
52
|
+
```typescript
|
53
|
+
/* Intl.DateTimeFormat style */
|
54
|
+
const relativeDate = getCurrentTime({
|
55
|
+
relativeDays: 1,
|
56
|
+
timeZone: 'Asia/Seoul',
|
57
|
+
loclae: 'en-CA' /* YYYY-MM-DD format */,
|
58
|
+
format: {
|
59
|
+
year: 'numeric',
|
60
|
+
month: '2-digit',
|
61
|
+
day: '2-digit'
|
62
|
+
}
|
63
|
+
})
|
64
|
+
|
65
|
+
console.log(relativeDate)
|
66
|
+
```
|
67
|
+
|
39
68
|
이 코드는 현재 시간을 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -28,13 +28,44 @@ function getRelativeTime(params: RelativeTimeParams = {}): string | number | Dat
|
|
28
28
|
## 예제
|
29
29
|
|
30
30
|
```typescript
|
31
|
+
/* get Date() object */
|
31
32
|
const relativeTime = getRelativeTime({
|
32
33
|
relativeSeconds: 3600,
|
33
34
|
timeZone: 'Asia/Seoul',
|
35
|
+
loclae: 'en-CA',
|
34
36
|
format: 'date'
|
35
37
|
})
|
36
38
|
|
37
39
|
console.log(relativeTime)
|
38
40
|
```
|
39
41
|
|
42
|
+
```typescript
|
43
|
+
/* text format style */
|
44
|
+
const relativeTime = getRelativeTime({
|
45
|
+
relativeSeconds: 3600,
|
46
|
+
timeZone: 'Asia/Seoul',
|
47
|
+
format: 'hh:mm:ss'
|
48
|
+
})
|
49
|
+
|
50
|
+
console.log(relativeTime)
|
51
|
+
```
|
52
|
+
|
53
|
+
```typescript
|
54
|
+
/* Intl.DateTimeFormat style */
|
55
|
+
const relativeTime = getRelativeTime({
|
56
|
+
relativeSeconds: 3600,
|
57
|
+
timeZone: 'Asia/Seoul',
|
58
|
+
loclae: 'en-CA',
|
59
|
+
format: {
|
60
|
+
hour: 'numeric',
|
61
|
+
minute: 'numeric',
|
62
|
+
second: 'numeric',
|
63
|
+
hour12: false,
|
64
|
+
timeZone: 'America/Los_Angeles'
|
65
|
+
}
|
66
|
+
})
|
67
|
+
|
68
|
+
console.log(relativeTime)
|
69
|
+
```
|
70
|
+
|
40
71
|
이 코드는 현재 시간으로부터 1시간 후의 시간을 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -28,12 +28,41 @@ function getToday(
|
|
28
28
|
## 예제
|
29
29
|
|
30
30
|
```typescript
|
31
|
+
/* get Date() object */
|
31
32
|
const todayDate = getToday({
|
32
33
|
timeZone: 'Asia/Seoul',
|
34
|
+
loclae: 'en-CA',
|
33
35
|
format: 'date'
|
34
36
|
})
|
35
37
|
|
36
38
|
console.log(todayDate)
|
37
39
|
```
|
38
40
|
|
41
|
+
```typescript
|
42
|
+
/* text format style */
|
43
|
+
const relativeDate = getToday({
|
44
|
+
relativeDays: 1,
|
45
|
+
timeZone: 'Asia/Seoul',
|
46
|
+
format: 'YYYY-MM-DD'
|
47
|
+
})
|
48
|
+
|
49
|
+
console.log(relativeDate)
|
50
|
+
```
|
51
|
+
|
52
|
+
```typescript
|
53
|
+
/* Intl.DateTimeFormat style */
|
54
|
+
const relativeDate = getToday({
|
55
|
+
relativeDays: 1,
|
56
|
+
timeZone: 'Asia/Seoul',
|
57
|
+
loclae: 'en-CA' /* YYYY-MM-DD format */,
|
58
|
+
format: {
|
59
|
+
year: 'numeric',
|
60
|
+
month: '2-digit',
|
61
|
+
day: '2-digit'
|
62
|
+
}
|
63
|
+
})
|
64
|
+
|
65
|
+
console.log(relativeDate)
|
66
|
+
```
|
67
|
+
|
39
68
|
이 코드는 오늘의 날짜를 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -30,14 +30,45 @@ function getRelativeWeekDate(params: RelativeWeekDateParams = {}): string | numb
|
|
30
30
|
## 예제
|
31
31
|
|
32
32
|
```typescript
|
33
|
+
/* get Date() object */
|
33
34
|
const relativeWeekDate = getRelativeWeekDate({
|
34
35
|
relativeWeeks: 2,
|
35
36
|
relativeDays: 3,
|
36
37
|
timeZone: 'Asia/Seoul',
|
38
|
+
loclae: 'en-CA',
|
37
39
|
format: 'date'
|
38
40
|
})
|
39
41
|
|
40
42
|
console.log(relativeWeekDate)
|
41
43
|
```
|
42
44
|
|
45
|
+
```typescript
|
46
|
+
/* text format style */
|
47
|
+
const relativeWeekDate = getRelativeWeekDate({
|
48
|
+
relativeWeeks: 2,
|
49
|
+
relativeDays: 3,
|
50
|
+
timeZone: 'Asia/Seoul',
|
51
|
+
format: 'YYYY-MM-DD'
|
52
|
+
})
|
53
|
+
|
54
|
+
console.log(relativeWeekDate)
|
55
|
+
```
|
56
|
+
|
57
|
+
```typescript
|
58
|
+
/* Intl.DateTimeFormat style */
|
59
|
+
const relativeWeekDate = getRelativeWeekDate({
|
60
|
+
relativeWeeks: 2,
|
61
|
+
relativeDays: 3,
|
62
|
+
timeZone: 'Asia/Seoul',
|
63
|
+
loclae: 'en-CA' /* YYYY-MM-DD format */,
|
64
|
+
format: {
|
65
|
+
year: 'numeric',
|
66
|
+
month: '2-digit',
|
67
|
+
day: '2-digit'
|
68
|
+
}
|
69
|
+
})
|
70
|
+
|
71
|
+
console.log(relativeWeekDate)
|
72
|
+
```
|
73
|
+
|
43
74
|
이 코드는 현재 시간으로부터 2주 후와 3일 후의 날짜를 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
@@ -30,14 +30,45 @@ function getRelativeYearDate(params: RelativeYearDateParams = {}): string | numb
|
|
30
30
|
## 예제
|
31
31
|
|
32
32
|
```typescript
|
33
|
+
/* get Date() object */
|
33
34
|
const relativeYearDate = getRelativeYearDate({
|
34
35
|
relativeYears: 2,
|
35
36
|
relativeDays: 3,
|
36
37
|
timeZone: 'Asia/Seoul',
|
38
|
+
loclae: 'en-CA',
|
37
39
|
format: 'date'
|
38
40
|
})
|
39
41
|
|
40
42
|
console.log(relativeYearDate)
|
41
43
|
```
|
42
44
|
|
45
|
+
```typescript
|
46
|
+
/* text format style */
|
47
|
+
const relativeYearDate = getRelativeYearDate({
|
48
|
+
relativeYears: 2,
|
49
|
+
relativeDays: 3,
|
50
|
+
timeZone: 'Asia/Seoul',
|
51
|
+
format: 'YYYY-MM-DD'
|
52
|
+
})
|
53
|
+
|
54
|
+
console.log(relativeYearDate)
|
55
|
+
```
|
56
|
+
|
57
|
+
```typescript
|
58
|
+
/* Intl.DateTimeFormat style */
|
59
|
+
const relativeYearDate = getRelativeYearDate({
|
60
|
+
relativeYears: 2,
|
61
|
+
relativeDays: 3,
|
62
|
+
timeZone: 'Asia/Seoul',
|
63
|
+
loclae: 'en-CA' /* YYYY-MM-DD format */,
|
64
|
+
format: {
|
65
|
+
year: 'numeric',
|
66
|
+
month: '2-digit',
|
67
|
+
day: '2-digit'
|
68
|
+
}
|
69
|
+
})
|
70
|
+
|
71
|
+
console.log(relativeYearDate)
|
72
|
+
```
|
73
|
+
|
43
74
|
이 코드는 현재 시간으로부터 2년 후와 3일 후의 날짜를 `'Asia/Seoul'` 시간대에서의 Date 객체로 반환합니다.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@operato/data-grist",
|
3
|
-
"version": "2.0.0-alpha.
|
3
|
+
"version": "2.0.0-alpha.104",
|
4
4
|
"description": "User interface for grid (desktop) and list (mobile)",
|
5
5
|
"author": "heartyoh",
|
6
6
|
"main": "dist/index.js",
|
@@ -61,7 +61,7 @@
|
|
61
61
|
"@operato/popup": "^2.0.0-alpha.102",
|
62
62
|
"@operato/pull-to-refresh": "^2.0.0-alpha.57",
|
63
63
|
"@operato/styles": "^2.0.0-alpha.102",
|
64
|
-
"@operato/time-calculator": "^2.0.0-alpha.
|
64
|
+
"@operato/time-calculator": "^2.0.0-alpha.104",
|
65
65
|
"@operato/utils": "^2.0.0-alpha.68",
|
66
66
|
"i18next": "^21.5.4",
|
67
67
|
"json5": "^2.2.0",
|
@@ -101,5 +101,5 @@
|
|
101
101
|
"prettier --write"
|
102
102
|
]
|
103
103
|
},
|
104
|
-
"gitHead": "
|
104
|
+
"gitHead": "804d35e90d66abb8d769a19f4787b440873ecd66"
|
105
105
|
}
|
@@ -1,6 +1,38 @@
|
|
1
|
-
import { OxGristEditor } from './ox-grist-editor.js'
|
2
|
-
import { customElement } from 'lit/decorators.js'
|
3
1
|
import { html } from 'lit'
|
2
|
+
import { customElement } from 'lit/decorators.js'
|
3
|
+
import { until } from 'lit/directives/until.js'
|
4
|
+
|
5
|
+
import { OxGristEditor } from './ox-grist-editor.js'
|
6
|
+
import { SelectOption, SelectOptionObject } from '../types.js'
|
7
|
+
|
8
|
+
function buildOptions(options: SelectOption[], value: any) {
|
9
|
+
const selectOptionObjects = options.map(option => {
|
10
|
+
switch (typeof option) {
|
11
|
+
case 'string':
|
12
|
+
return {
|
13
|
+
display: option,
|
14
|
+
value: option
|
15
|
+
}
|
16
|
+
case 'object':
|
17
|
+
return {
|
18
|
+
display: option.display || option.name,
|
19
|
+
value: option.value
|
20
|
+
}
|
21
|
+
default:
|
22
|
+
return option
|
23
|
+
}
|
24
|
+
}) as SelectOptionObject[]
|
25
|
+
|
26
|
+
return html`
|
27
|
+
<select>
|
28
|
+
${selectOptionObjects.map(
|
29
|
+
(option: any) => html`
|
30
|
+
<option ?selected=${option.value == value} value=${option.value}>${option.display}</option>
|
31
|
+
`
|
32
|
+
)}
|
33
|
+
</select>
|
34
|
+
`
|
35
|
+
}
|
4
36
|
|
5
37
|
@customElement('ox-grist-editor-select')
|
6
38
|
export class OxGristEditorSelect extends OxGristEditor {
|
@@ -10,33 +42,14 @@ export class OxGristEditorSelect extends OxGristEditor {
|
|
10
42
|
|
11
43
|
if (typeof options == 'function') {
|
12
44
|
options = options.call(null, this.value, this.column, this.record, this.rowIndex, this.field)
|
13
|
-
}
|
14
45
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
display: option,
|
20
|
-
value: option
|
21
|
-
}
|
22
|
-
case 'object':
|
23
|
-
return {
|
24
|
-
display: option.display,
|
25
|
-
value: option.value
|
26
|
-
}
|
27
|
-
default:
|
28
|
-
return option
|
46
|
+
if (options instanceof Promise) {
|
47
|
+
return html`${until(options.then(options => buildOptions(options, this.value)))}`
|
48
|
+
} else {
|
49
|
+
return buildOptions((options || []) as SelectOption[], rowOptionField.display || this.value)
|
29
50
|
}
|
30
|
-
}
|
31
|
-
|
32
|
-
|
33
|
-
<select>
|
34
|
-
${options.map(
|
35
|
-
(option: any) => html`
|
36
|
-
<option ?selected=${option.value == this.value} value=${option.value}>${option.display}</option>
|
37
|
-
`
|
38
|
-
)}
|
39
|
-
</select>
|
40
|
-
`
|
51
|
+
} else {
|
52
|
+
return buildOptions((options || []) as SelectOption[], this.value)
|
53
|
+
}
|
41
54
|
}
|
42
55
|
}
|
@@ -1,26 +1,14 @@
|
|
1
1
|
import '@operato/input/ox-checkbox.js'
|
2
2
|
|
3
|
-
import {
|
3
|
+
import { html } from 'lit'
|
4
|
+
import { until } from 'lit/directives/until.js'
|
4
5
|
|
5
|
-
import {
|
6
|
+
import { FilterConfigObject, FilterOperator, FilterSelectRenderer, SelectOption, SelectOptionObject } from '../types'
|
7
|
+
import { OxFiltersForm } from './filters-form'
|
8
|
+
import { DataGridHeader } from '../data-grid/data-grid-header'
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
const filter = column.filter as FilterConfigObject
|
10
|
-
const operator = filter?.operator
|
11
|
-
|
12
|
-
var options = filter?.options || column.record.options || []
|
13
|
-
|
14
|
-
if (typeof options === 'function') {
|
15
|
-
if (!filter?.options) {
|
16
|
-
console.warn(
|
17
|
-
'ox-grist의 column.filter 속성에서는 column.record.options의 함수형 options을 사용할 수 없으므로, filter 속성에서 재지정해야한다.'
|
18
|
-
)
|
19
|
-
}
|
20
|
-
options = options.call(column, owner)
|
21
|
-
}
|
22
|
-
|
23
|
-
options = options.map((option: any) => {
|
10
|
+
function buildOptions(options: SelectOption[], operator?: FilterOperator) {
|
11
|
+
const selectOptionObjects = options.map(option => {
|
24
12
|
switch (typeof option) {
|
25
13
|
case 'string':
|
26
14
|
return {
|
@@ -29,27 +17,52 @@ export const FilterSelect: FilterSelectRenderer = (column, value, owner) => {
|
|
29
17
|
}
|
30
18
|
case 'object':
|
31
19
|
return {
|
32
|
-
display: option.display,
|
20
|
+
display: option.display || option.name,
|
33
21
|
value: option.value
|
34
22
|
}
|
35
23
|
default:
|
36
24
|
return option
|
37
25
|
}
|
38
|
-
})
|
26
|
+
}) as SelectOptionObject[]
|
39
27
|
|
40
28
|
return operator === 'in'
|
41
29
|
? html`
|
42
|
-
${
|
43
|
-
?.filter(
|
30
|
+
${selectOptionObjects
|
31
|
+
?.filter(option => !!option)
|
44
32
|
.map(
|
45
|
-
(
|
46
|
-
html` <ox-checkbox option value=${option.value}>${option.display}</ox-checkbox> `
|
33
|
+
({ value, display, name }) => html` <ox-checkbox option value=${value}>${display || name}</ox-checkbox> `
|
47
34
|
)}
|
48
35
|
`
|
49
36
|
: html`
|
50
|
-
${
|
51
|
-
(
|
52
|
-
html` <div option value=${option.value}>${option.display} </div> `
|
37
|
+
${selectOptionObjects?.map(
|
38
|
+
({ value, display, name }) => html` <div option value=${value}>${display || name} </div> `
|
53
39
|
)}
|
54
40
|
`
|
55
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
|
+
}
|
@@ -23,7 +23,7 @@ export type QueryFilter = {
|
|
23
23
|
}
|
24
24
|
|
25
25
|
@customElement('ox-filters-form')
|
26
|
-
export class
|
26
|
+
export class OxFiltersForm extends LitElement {
|
27
27
|
static styles = [
|
28
28
|
FilterStyles,
|
29
29
|
css`
|
@@ -68,6 +68,9 @@ export class FiltersForm extends LitElement {
|
|
68
68
|
|
69
69
|
@queryAsync('form') form!: HTMLFormElement
|
70
70
|
|
71
|
+
private autoUpdateTargetsOnChange: { [name: string]: string[] } = {}
|
72
|
+
private objectValue?: object
|
73
|
+
|
71
74
|
connectedCallback(): void {
|
72
75
|
super.connectedCallback()
|
73
76
|
|
@@ -90,21 +93,42 @@ export class FiltersForm extends LitElement {
|
|
90
93
|
})
|
91
94
|
|
92
95
|
this.renderRoot.addEventListener('change', async (e: Event) => {
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
const { target, detail: value } = e as CustomEvent
|
97
|
+
const name = (target as HTMLInputElement).name
|
98
|
+
const { filter } = this.filterColumns.find(filter => filter.name == name) || {}
|
99
|
+
|
100
|
+
if (this.autoUpdateTargetsOnChange[name]) {
|
101
|
+
/* 일단은 심플하게, boundTo로 연결된 필터값이 바뀌면, 폼 전체를 update하도록 함. */
|
102
|
+
;(this.autoUpdateTargetsOnChange[name] || []).forEach(name => {
|
103
|
+
const target = this.renderRoot.querySelector(`[name='${name}']`)
|
104
|
+
if (target) {
|
105
|
+
;(target as HTMLInputElement).value = ''
|
100
106
|
}
|
101
107
|
})
|
102
|
-
|
108
|
+
|
109
|
+
await this.updateObjectValues()
|
110
|
+
this.requestUpdate()
|
111
|
+
}
|
112
|
+
|
113
|
+
const onchange = typeof filter == 'object' ? filter.onchange : null
|
114
|
+
const keepGoing = onchange ? await onchange.call(null, value ?? (target as HTMLInputElement).value, this) : true
|
115
|
+
|
116
|
+
keepGoing &&
|
117
|
+
this.dispatchEvent(
|
118
|
+
new CustomEvent('fetch-params-change', {
|
119
|
+
bubbles: true,
|
120
|
+
composed: true,
|
121
|
+
detail: {
|
122
|
+
filters: await this.getQueryFilters(),
|
123
|
+
from: 'filters-form'
|
124
|
+
}
|
125
|
+
})
|
126
|
+
)
|
103
127
|
})
|
104
128
|
}
|
105
129
|
}
|
106
130
|
|
107
|
-
buildDefaultValue(operator:
|
131
|
+
buildDefaultValue(operator: FilterOperator, defaultValue: any) {
|
108
132
|
if (defaultValue === undefined) {
|
109
133
|
return
|
110
134
|
}
|
@@ -137,6 +161,22 @@ export class FiltersForm extends LitElement {
|
|
137
161
|
})
|
138
162
|
|
139
163
|
this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0
|
164
|
+
|
165
|
+
this.autoUpdateTargetsOnChange = {}
|
166
|
+
this.filterColumns
|
167
|
+
?.filter(({ filter }) => {
|
168
|
+
return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0
|
169
|
+
})
|
170
|
+
.map(({ name, filter }) => {
|
171
|
+
const boundTo = (filter as FilterConfigObject).boundTo
|
172
|
+
|
173
|
+
boundTo!.forEach(to => {
|
174
|
+
const origin = this.autoUpdateTargetsOnChange[to] || []
|
175
|
+
if (name && !origin.includes(name)) {
|
176
|
+
this.autoUpdateTargetsOnChange[to] = [...origin, name]
|
177
|
+
}
|
178
|
+
})
|
179
|
+
})
|
140
180
|
}
|
141
181
|
}
|
142
182
|
|
@@ -319,4 +359,28 @@ export class FiltersForm extends LitElement {
|
|
319
359
|
const input = this.renderRoot.querySelector(`form [name="${name}"]`) as HTMLInputElement
|
320
360
|
return input?.value
|
321
361
|
}
|
362
|
+
|
363
|
+
private async updateObjectValues() {
|
364
|
+
const form = await this.form
|
365
|
+
if (!form) return []
|
366
|
+
|
367
|
+
const formData = new FormData(form)
|
368
|
+
|
369
|
+
const object = {} as any
|
370
|
+
formData.forEach((value, key) => {
|
371
|
+
const prev = object[key]
|
372
|
+
|
373
|
+
if (key in object) {
|
374
|
+
object[key] = prev instanceof Array ? [...prev, value] : [prev, value]
|
375
|
+
} else {
|
376
|
+
object[key] = value
|
377
|
+
}
|
378
|
+
})
|
379
|
+
|
380
|
+
this.objectValue = object
|
381
|
+
}
|
382
|
+
|
383
|
+
public getFormObjectValue() {
|
384
|
+
return this.objectValue
|
385
|
+
}
|
322
386
|
}
|