@operato/data-grist 0.2.35 → 0.2.36
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 +25 -0
- package/custom-elements.json +1697 -5
- package/demo/data-grist-test.html +1 -1
- package/demo/index.html +18 -1
- package/dist/src/data-card/data-card-gutter-menu.js +2 -2
- package/dist/src/data-card/data-card-gutter-menu.js.map +1 -1
- package/dist/src/data-card/data-card-gutter.d.ts +13 -1
- package/dist/src/data-card/data-card-gutter.js +1 -0
- package/dist/src/data-card/data-card-gutter.js.map +1 -1
- package/dist/src/data-grid/data-grid-field.d.ts +2 -2
- package/dist/src/data-grid/data-grid-field.js.map +1 -1
- package/dist/src/data-grid/data-grid-header.d.ts +3 -0
- package/dist/src/data-grid/data-grid-header.js +38 -10
- package/dist/src/data-grid/data-grid-header.js.map +1 -1
- package/dist/src/data-grist.d.ts +9 -7
- package/dist/src/data-grist.js +26 -18
- package/dist/src/data-grist.js.map +1 -1
- package/dist/src/data-list/data-list-field.js +3 -3
- package/dist/src/data-list/data-list-field.js.map +1 -1
- package/dist/src/data-list/data-list-gutter.d.ts +13 -1
- package/dist/src/data-list/data-list-gutter.js +1 -0
- package/dist/src/data-list/data-list-gutter.js.map +1 -1
- package/dist/src/data-report/data-report-field.d.ts +2 -2
- package/dist/src/data-report/data-report-field.js.map +1 -1
- package/dist/src/filters/index.d.ts +2 -0
- package/dist/src/filters/index.js +3 -0
- package/dist/src/filters/index.js.map +1 -0
- package/dist/src/filters/list-select.d.ts +3 -0
- package/dist/src/filters/list-select.js +12 -0
- package/dist/src/filters/list-select.js.map +1 -0
- package/dist/src/filters/registry.d.ts +7 -0
- package/dist/src/filters/registry.js +40 -0
- package/dist/src/filters/registry.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces/index.d.ts +2 -0
- package/dist/src/interfaces/index.js +3 -0
- package/dist/src/interfaces/index.js.map +1 -0
- package/dist/src/interfaces/ox-grist-search-form.d.ts +6 -0
- package/dist/src/interfaces/ox-grist-search-form.js +2 -0
- package/dist/src/interfaces/ox-grist-search-form.js.map +1 -0
- package/dist/src/interfaces/ox-search-field.d.ts +39 -0
- package/dist/src/interfaces/ox-search-field.js +2 -0
- package/dist/src/interfaces/ox-search-field.js.map +1 -0
- package/dist/src/search-form/index.d.ts +7 -0
- package/dist/src/search-form/index.js +8 -0
- package/dist/src/search-form/index.js.map +1 -0
- package/dist/src/search-form/ox-basic-field.d.ts +18 -0
- package/dist/src/search-form/ox-basic-field.js +75 -0
- package/dist/src/search-form/ox-basic-field.js.map +1 -0
- package/dist/src/search-form/ox-checkbox-field.d.ts +11 -0
- package/dist/src/search-form/ox-checkbox-field.js +60 -0
- package/dist/src/search-form/ox-checkbox-field.js.map +1 -0
- package/dist/src/search-form/ox-grist-search-form.d.ts +11 -0
- package/dist/src/search-form/ox-grist-search-form.js +177 -0
- package/dist/src/search-form/ox-grist-search-form.js.map +1 -0
- package/dist/src/search-form/ox-number-field.d.ts +14 -0
- package/dist/src/search-form/ox-number-field.js +112 -0
- package/dist/src/search-form/ox-number-field.js.map +1 -0
- package/dist/src/search-form/ox-search-form.d.ts +15 -0
- package/dist/src/search-form/ox-search-form.js +53 -0
- package/dist/src/search-form/ox-search-form.js.map +1 -0
- package/dist/src/search-form/ox-select-field.d.ts +21 -0
- package/dist/src/search-form/ox-select-field.js +181 -0
- package/dist/src/search-form/ox-select-field.js.map +1 -0
- package/dist/src/search-form/ox-text-field.d.ts +11 -0
- package/dist/src/search-form/ox-text-field.js +60 -0
- package/dist/src/search-form/ox-text-field.js.map +1 -0
- package/dist/src/types.d.ts +20 -3
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/data-card/data-card-gutter-menu.ts +2 -2
- package/src/data-card/data-card-gutter.ts +3 -3
- package/src/data-grid/data-grid-field.ts +2 -2
- package/src/data-grid/data-grid-header.ts +42 -11
- package/src/data-grist.ts +30 -20
- package/src/data-list/data-list-field.ts +3 -3
- package/src/data-list/data-list-gutter.ts +3 -3
- package/src/data-report/data-report-field.ts +2 -2
- package/src/filters/index.ts +3 -0
- package/src/filters/list-select.ts +14 -0
- package/src/filters/registry.ts +48 -0
- package/src/index.ts +3 -0
- package/src/interfaces/index.ts +2 -0
- package/src/interfaces/ox-grist-search-form.ts +7 -0
- package/src/interfaces/ox-search-field.ts +52 -0
- package/src/search-form/index.ts +7 -0
- package/src/search-form/ox-basic-field.ts +86 -0
- package/src/search-form/ox-checkbox-field.ts +57 -0
- package/src/search-form/ox-grist-search-form.ts +200 -0
- package/src/search-form/ox-number-field.ts +113 -0
- package/src/search-form/ox-search-form.ts +71 -0
- package/src/search-form/ox-select-field.ts +188 -0
- package/src/search-form/ox-text-field.ts +55 -0
- package/src/types.ts +28 -3
- package/yarn-error.log +2427 -3205
package/src/data-grist.ts
CHANGED
|
@@ -88,37 +88,44 @@ export class DataGrist extends LitElement implements DataConsumer {
|
|
|
88
88
|
@state() private _showSpinner: boolean = false
|
|
89
89
|
|
|
90
90
|
private dataProvider?: DataProvider
|
|
91
|
-
private
|
|
92
|
-
private
|
|
91
|
+
private _pulltorefreshHandle?: any
|
|
92
|
+
private _headroom?: Headroom
|
|
93
|
+
private _resizeObserver = new ResizeObserver(entries => {
|
|
94
|
+
this._adjustPaddingTop()
|
|
95
|
+
})
|
|
93
96
|
|
|
94
97
|
@query('slot[name=headroom]') head!: HTMLElement
|
|
95
98
|
@query('#grist') grist!: DataGrid | DataList | DataCard
|
|
96
99
|
@queryAsync('#wrap') private wrap!: Promise<HTMLElement>
|
|
97
100
|
|
|
98
|
-
connectedCallback() {
|
|
101
|
+
async connectedCallback() {
|
|
99
102
|
super.connectedCallback()
|
|
100
103
|
|
|
101
104
|
this.dataProvider = new DataProvider(this)
|
|
105
|
+
|
|
106
|
+
await this.updateComplete
|
|
107
|
+
this._resizeObserver.observe(this.head)
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
disconnectedCallback() {
|
|
105
111
|
super.disconnectedCallback()
|
|
106
112
|
|
|
107
113
|
this.dataProvider?.dispose()
|
|
108
|
-
this.
|
|
114
|
+
this._resetPullToRefresh()
|
|
115
|
+
this._resizeObserver.unobserve(this.head)
|
|
109
116
|
}
|
|
110
117
|
|
|
111
|
-
private
|
|
112
|
-
if (this.
|
|
113
|
-
this.
|
|
114
|
-
delete this.
|
|
118
|
+
private _resetPullToRefresh() {
|
|
119
|
+
if (this._pulltorefreshHandle) {
|
|
120
|
+
this._pulltorefreshHandle()
|
|
121
|
+
delete this._pulltorefreshHandle
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
|
|
118
|
-
private async
|
|
119
|
-
this.
|
|
125
|
+
private async _setPullToRefresh() {
|
|
126
|
+
this._resetPullToRefresh()
|
|
120
127
|
if (this.fetchHandler) {
|
|
121
|
-
this.
|
|
128
|
+
this._pulltorefreshHandle = pulltorefresh({
|
|
122
129
|
container: await this.wrap,
|
|
123
130
|
scrollable: this.grist.pullToRefreshTarget,
|
|
124
131
|
refresh: () => {
|
|
@@ -128,17 +135,20 @@ export class DataGrist extends LitElement implements DataConsumer {
|
|
|
128
135
|
}
|
|
129
136
|
}
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
this.
|
|
138
|
+
private _adjustPaddingTop() {
|
|
139
|
+
this.grist.style.paddingTop = this.head.clientHeight + 'px'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private _setHeadroom() {
|
|
143
|
+
this._headroom?.destroy()
|
|
133
144
|
|
|
134
145
|
if (this.grist && this.head) {
|
|
135
|
-
|
|
136
|
-
this.grist.style.paddingTop = this.head.clientHeight + originPaddingTop + 'px'
|
|
146
|
+
this._adjustPaddingTop()
|
|
137
147
|
|
|
138
|
-
this.
|
|
148
|
+
this._headroom = new Headroom(this.head, {
|
|
139
149
|
scroller: this.grist
|
|
140
150
|
})
|
|
141
|
-
this.
|
|
151
|
+
this._headroom.init()
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
154
|
|
|
@@ -228,7 +238,7 @@ export class DataGrist extends LitElement implements DataConsumer {
|
|
|
228
238
|
|
|
229
239
|
if (changes.has('mode')) {
|
|
230
240
|
needToSetPullToRefresh = true
|
|
231
|
-
this.
|
|
241
|
+
this._setHeadroom()
|
|
232
242
|
}
|
|
233
243
|
|
|
234
244
|
if (changes.has('selectedRecords')) {
|
|
@@ -251,7 +261,7 @@ export class DataGrist extends LitElement implements DataConsumer {
|
|
|
251
261
|
}
|
|
252
262
|
|
|
253
263
|
if (needToSetPullToRefresh) {
|
|
254
|
-
await this.
|
|
264
|
+
await this._setPullToRefresh()
|
|
255
265
|
}
|
|
256
266
|
}
|
|
257
267
|
|
|
@@ -355,7 +365,7 @@ export class DataGrist extends LitElement implements DataConsumer {
|
|
|
355
365
|
/**
|
|
356
366
|
* Forced internal data to be reflected on the screen
|
|
357
367
|
* Data changing through a normal method is automatically reflected on the screen, so it is a method that does not need to be used in general.
|
|
358
|
-
Therefore, it will be deprecated.
|
|
368
|
+
* Therefore, it will be deprecated.
|
|
359
369
|
* @deprecated
|
|
360
370
|
* @method
|
|
361
371
|
*/
|
|
@@ -61,14 +61,14 @@ export class DataListField extends LitElement {
|
|
|
61
61
|
|
|
62
62
|
var {
|
|
63
63
|
label,
|
|
64
|
-
record: { renderer:
|
|
64
|
+
record: { renderer: fieldRenderer }
|
|
65
65
|
} = column
|
|
66
66
|
|
|
67
67
|
if (typeof label == 'object') {
|
|
68
68
|
let { renderer: labelRenderer } = label
|
|
69
|
-
return html`<label>${labelRenderer()}</label>${
|
|
69
|
+
return html`<label>${labelRenderer()}</label>${fieldRenderer(value, column, record, rowIndex, this)}`
|
|
70
70
|
} else {
|
|
71
|
-
return html`${
|
|
71
|
+
return html`${fieldRenderer(value, column, record, rowIndex, this)}`
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ColumnConfig, GristRecord } from '../types'
|
|
2
|
-
import { LitElement, PropertyValues, css, html } from 'lit'
|
|
2
|
+
import { LitElement, PropertyValues, TemplateResult, css, html } from 'lit'
|
|
3
3
|
import { ZERO_COLUMN, ZERO_RECORD } from '../configure/zero-config'
|
|
4
4
|
import { customElement, property } from 'lit/decorators.js'
|
|
5
5
|
|
|
6
6
|
const DEFAULT_TEXT_ALIGN = 'left'
|
|
7
7
|
|
|
8
8
|
@customElement('ox-list-gutter')
|
|
9
|
-
class DataListGutter extends LitElement {
|
|
9
|
+
export class DataListGutter extends LitElement {
|
|
10
10
|
static styles = [
|
|
11
11
|
css`
|
|
12
12
|
:host {
|
|
@@ -46,7 +46,7 @@ class DataListGutter extends LitElement {
|
|
|
46
46
|
return this.hasAttribute('editing')
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
render() {
|
|
49
|
+
render(): TemplateResult {
|
|
50
50
|
if (!this.column) {
|
|
51
51
|
return html``
|
|
52
52
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ColumnConfig, GristRecord } from '../types'
|
|
2
|
-
import { LitElement, PropertyValues, css, html } from 'lit'
|
|
2
|
+
import { LitElement, PropertyValues, TemplateResult, css, html } from 'lit'
|
|
3
3
|
import { ZERO_COLUMN, ZERO_RECORD } from '../configure/zero-config'
|
|
4
4
|
import { customElement, property } from 'lit/decorators.js'
|
|
5
5
|
|
|
@@ -52,7 +52,7 @@ export class DataReportField extends LitElement {
|
|
|
52
52
|
@property({ type: Number }) columnIndex: number = -1
|
|
53
53
|
@property({ type: Object }) value: any
|
|
54
54
|
|
|
55
|
-
render() {
|
|
55
|
+
render(): TemplateResult {
|
|
56
56
|
if (!this.column) {
|
|
57
57
|
return html``
|
|
58
58
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '@operato/popup'
|
|
2
|
+
|
|
3
|
+
import { FilterSelectRenderer } from '../types'
|
|
4
|
+
import { html } from 'lit-html'
|
|
5
|
+
|
|
6
|
+
export const ListSelect: FilterSelectRenderer = (column, owner) => {
|
|
7
|
+
const options = column.filter?.options
|
|
8
|
+
|
|
9
|
+
return html`
|
|
10
|
+
<ox-popup-list .config=${column} multiple attr-selected="checked" popup>
|
|
11
|
+
${options?.map((option: string) => html` <ox-checkbox option value="${option}">${option}</ox-checkbox> `)}
|
|
12
|
+
</ox-popup-list>
|
|
13
|
+
`
|
|
14
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { FilterSelectRenderer } from '../types'
|
|
2
|
+
import { ListSelect } from './list-select'
|
|
3
|
+
|
|
4
|
+
var RENDERERS: {
|
|
5
|
+
[name: string]: FilterSelectRenderer
|
|
6
|
+
} = {
|
|
7
|
+
string: ListSelect,
|
|
8
|
+
text: ListSelect,
|
|
9
|
+
email: ListSelect,
|
|
10
|
+
tel: ListSelect,
|
|
11
|
+
password: ListSelect,
|
|
12
|
+
integer: ListSelect,
|
|
13
|
+
float: ListSelect,
|
|
14
|
+
number: ListSelect,
|
|
15
|
+
select: ListSelect,
|
|
16
|
+
boolean: ListSelect,
|
|
17
|
+
checkbox: ListSelect,
|
|
18
|
+
month: ListSelect,
|
|
19
|
+
week: ListSelect,
|
|
20
|
+
date: ListSelect,
|
|
21
|
+
time: ListSelect,
|
|
22
|
+
datetime: ListSelect,
|
|
23
|
+
color: ListSelect,
|
|
24
|
+
progress: ListSelect,
|
|
25
|
+
link: ListSelect,
|
|
26
|
+
image: ListSelect,
|
|
27
|
+
json5: ListSelect
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function registerRenderer(type: string, renderer: FilterSelectRenderer) {
|
|
31
|
+
RENDERERS[type] = renderer
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function unregisterRenderer(type: string): void {
|
|
35
|
+
delete RENDERERS[type]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getRenderers(): { [name: string]: FilterSelectRenderer } {
|
|
39
|
+
return { ...RENDERERS }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getRenderer(type: string | FilterSelectRenderer): FilterSelectRenderer {
|
|
43
|
+
if (typeof type == 'function') {
|
|
44
|
+
return type
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return RENDERERS[type || 'text'] || ListSelect
|
|
48
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type OXSearchFieldType = 'select' | 'checkbox' | 'text' | 'number'
|
|
2
|
+
|
|
3
|
+
export interface OXFieldOptionProps {
|
|
4
|
+
name?: string
|
|
5
|
+
value: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface OXBasicFieldProps {
|
|
9
|
+
name: string
|
|
10
|
+
type?: OXSearchFieldType
|
|
11
|
+
hidden?: boolean
|
|
12
|
+
id?: string
|
|
13
|
+
placeholder?: string
|
|
14
|
+
handlers?: Record<string, (event: Event) => void>
|
|
15
|
+
defaultValue?: any
|
|
16
|
+
operator?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface OXTextFieldProps extends OXBasicFieldProps {
|
|
20
|
+
defaultValue?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface OXNumberFieldProps extends OXBasicFieldProps {
|
|
24
|
+
min?: number
|
|
25
|
+
max?: number
|
|
26
|
+
step: number
|
|
27
|
+
defaultValue?: number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface OXObjectFieldProps extends OXBasicFieldProps {
|
|
31
|
+
field: string
|
|
32
|
+
queryName: string
|
|
33
|
+
defaultValue?: Record<string, any>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface OXSelectFieldProps extends OXBasicFieldProps {
|
|
37
|
+
searchEnable?: boolean
|
|
38
|
+
options: OXFieldOptionProps[]
|
|
39
|
+
defaultValue?: any
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface OXCheckboxFieldProps extends OXBasicFieldProps {
|
|
43
|
+
indeterminate?: boolean
|
|
44
|
+
defaultValue?: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type OXSearchFieldProps =
|
|
48
|
+
| OXTextFieldProps
|
|
49
|
+
| OXNumberFieldProps
|
|
50
|
+
| OXObjectFieldProps
|
|
51
|
+
| OXSelectFieldProps
|
|
52
|
+
| OXCheckboxFieldProps
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { css, LitElement } from 'lit-element'
|
|
2
|
+
|
|
3
|
+
import { OXBasicFieldProps } from '../interfaces/ox-search-field'
|
|
4
|
+
|
|
5
|
+
export abstract class OXBasicField extends LitElement {
|
|
6
|
+
static styles = [
|
|
7
|
+
css`
|
|
8
|
+
input,
|
|
9
|
+
select {
|
|
10
|
+
background-color: transparent;
|
|
11
|
+
border: none;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
outline: none;
|
|
14
|
+
padding: 4px 9px;
|
|
15
|
+
font-size: var(--fontsize-default, 14px);
|
|
16
|
+
color: var(--primary-text-color, #476172);
|
|
17
|
+
font-weight: bold;
|
|
18
|
+
}
|
|
19
|
+
`
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
field!: OXBasicFieldProps
|
|
23
|
+
|
|
24
|
+
private form: HTMLFormElement | null = null
|
|
25
|
+
value?: any
|
|
26
|
+
|
|
27
|
+
abstract setDefaultValue(defaultValue: unknown): void
|
|
28
|
+
|
|
29
|
+
get input(): HTMLInputElement | HTMLSelectElement {
|
|
30
|
+
if (!this.field.name) throw new Error('No name property provided')
|
|
31
|
+
const input: HTMLInputElement | null = this.renderRoot.querySelector(
|
|
32
|
+
`input[name=${this.field.name}],select[name=${this.field.name}]`
|
|
33
|
+
)
|
|
34
|
+
if (!input) throw new Error('Failed to find input element')
|
|
35
|
+
|
|
36
|
+
return input
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override connectedCallback(): void {
|
|
40
|
+
super.connectedCallback()
|
|
41
|
+
this.form = this.findFormElement()
|
|
42
|
+
this.form?.addEventListener('formdata', this.appendFormData.bind(this))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override disconnectedCallback(): void {
|
|
46
|
+
super.disconnectedCallback()
|
|
47
|
+
this.form?.removeEventListener('formdata', this.appendFormData.bind(this))
|
|
48
|
+
this.form = null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override firstUpdated(): void {
|
|
52
|
+
const { handlers } = this.field || {}
|
|
53
|
+
|
|
54
|
+
this.registerBasicEventHandlers()
|
|
55
|
+
if (handlers) this.registerCustomEventHandlers(handlers)
|
|
56
|
+
if (this.field.defaultValue !== undefined) this.setDefaultValue(this.field.defaultValue)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private findFormElement(): HTMLFormElement | null {
|
|
60
|
+
const rootNode: HTMLElement = this.getRootNode() as HTMLElement
|
|
61
|
+
const forms: HTMLFormElement[] = Array.from(rootNode.querySelectorAll('form'))
|
|
62
|
+
|
|
63
|
+
return forms.find((form: HTMLFormElement) => form.contains(this)) || null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private registerCustomEventHandlers(handlers: Record<string, (event: Event) => void>): void {
|
|
67
|
+
const eventNames: string[] = Object.keys(handlers)
|
|
68
|
+
if (!eventNames.length) return
|
|
69
|
+
|
|
70
|
+
eventNames.forEach((eventName: string) => this.input.addEventListener(eventName, handlers[eventName]))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private registerBasicEventHandlers(): void {
|
|
74
|
+
this.input.onkeydown = (event: KeyboardEvent) => {
|
|
75
|
+
if (event.key === 'Enter') this.submit()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private appendFormData({ formData }: FormDataEvent): void {
|
|
80
|
+
formData.append(this.field.name, this.value)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private submit(): void {
|
|
84
|
+
if (this.form) this.dispatchEvent(new CustomEvent('submit-field', { composed: true, bubbles: true }))
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { css, html, TemplateResult } from 'lit'
|
|
2
|
+
import { ifDefined } from 'lit-html/directives/if-defined.js'
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
4
|
+
|
|
5
|
+
import { OXCheckboxFieldProps } from '..'
|
|
6
|
+
import { OXBasicField } from './ox-basic-field'
|
|
7
|
+
|
|
8
|
+
@customElement('ox-checkbox-field')
|
|
9
|
+
export class OXCheckboxField extends OXBasicField {
|
|
10
|
+
@property({ type: Object }) field!: OXCheckboxFieldProps
|
|
11
|
+
@property({ type: Boolean }) value?: boolean
|
|
12
|
+
|
|
13
|
+
static styles = [
|
|
14
|
+
css`
|
|
15
|
+
label {
|
|
16
|
+
font-size: var(--fontsize-default, 14px);
|
|
17
|
+
color: var(--primary-text-color, #476172);
|
|
18
|
+
}
|
|
19
|
+
`
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
setDefaultValue(defaultValue: boolean): void {
|
|
23
|
+
this.value = defaultValue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render(): TemplateResult {
|
|
27
|
+
const { name, hidden, placeholder, id } = this.field
|
|
28
|
+
|
|
29
|
+
return html`<label ?hidden=${hidden}>
|
|
30
|
+
<input
|
|
31
|
+
id=${ifDefined(id)}
|
|
32
|
+
type="checkbox"
|
|
33
|
+
name=${name}
|
|
34
|
+
.checked=${Boolean(this.value)}
|
|
35
|
+
@click=${this.onClickHandler.bind(this)}
|
|
36
|
+
/>
|
|
37
|
+
${placeholder || name}
|
|
38
|
+
</label>`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private onClickHandler(): void {
|
|
42
|
+
const checkbox: HTMLInputElement = this.input as HTMLInputElement
|
|
43
|
+
|
|
44
|
+
if (!this.field.indeterminate) {
|
|
45
|
+
this.value = !this.value
|
|
46
|
+
} else {
|
|
47
|
+
if (this.value === false) {
|
|
48
|
+
this.value = undefined
|
|
49
|
+
checkbox.indeterminate = true
|
|
50
|
+
} else if (this.value === undefined) {
|
|
51
|
+
this.value = true
|
|
52
|
+
} else {
|
|
53
|
+
this.value = false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { ColumnConfig, GristConfig } from '../types'
|
|
2
|
+
import { LitElement, TemplateResult, html } from 'lit'
|
|
3
|
+
import {
|
|
4
|
+
OXBasicFieldProps,
|
|
5
|
+
OXCheckboxFieldProps,
|
|
6
|
+
OXNumberFieldProps,
|
|
7
|
+
OXSearchFieldProps,
|
|
8
|
+
OXSearchFieldTypes,
|
|
9
|
+
OXSearchForm,
|
|
10
|
+
OXSelectFieldProps,
|
|
11
|
+
OXTextFieldProps,
|
|
12
|
+
QueryFilter
|
|
13
|
+
} from '..'
|
|
14
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
15
|
+
|
|
16
|
+
@customElement('ox-grist-search-form')
|
|
17
|
+
export class OXGristSearchForm extends LitElement {
|
|
18
|
+
@property({ type: Object }) config!: GristConfig
|
|
19
|
+
@property({ type: String }) defaultOperator: string = 'eq'
|
|
20
|
+
|
|
21
|
+
private timeout?: NodeJS.Timeout
|
|
22
|
+
|
|
23
|
+
render(): TemplateResult {
|
|
24
|
+
const fields: OXSearchFieldProps[] = this.convertToSearchFields(this.config)
|
|
25
|
+
|
|
26
|
+
return html` <ox-search-form .fields=${fields}></ox-search-form> `
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private convertToSearchFields(config: GristConfig): OXSearchFieldProps[] {
|
|
30
|
+
const supportingTypes: string[] = ['string', 'integer', 'number', 'float', 'select', 'boolean', 'checkbox']
|
|
31
|
+
|
|
32
|
+
return config.columns
|
|
33
|
+
.filter((columnConfig: ColumnConfig) => supportingTypes.indexOf(columnConfig.type) >= 0)
|
|
34
|
+
.map((columnConfig: ColumnConfig) => {
|
|
35
|
+
let fieldProps: OXBasicFieldProps = {
|
|
36
|
+
name: columnConfig.name,
|
|
37
|
+
hidden: Boolean(columnConfig.hidden),
|
|
38
|
+
placeholder: typeof columnConfig.label === 'string' ? columnConfig.label : columnConfig.name
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
switch (columnConfig.type) {
|
|
42
|
+
case 'string':
|
|
43
|
+
return {
|
|
44
|
+
...fieldProps,
|
|
45
|
+
type: 'text'
|
|
46
|
+
} as OXTextFieldProps
|
|
47
|
+
|
|
48
|
+
case 'integer':
|
|
49
|
+
return {
|
|
50
|
+
...fieldProps,
|
|
51
|
+
type: 'number',
|
|
52
|
+
min: columnConfig.record?.options?.min || undefined,
|
|
53
|
+
max: columnConfig.record?.options?.max || undefined
|
|
54
|
+
} as OXNumberFieldProps
|
|
55
|
+
|
|
56
|
+
case 'number':
|
|
57
|
+
return {
|
|
58
|
+
...fieldProps,
|
|
59
|
+
type: 'number',
|
|
60
|
+
min: columnConfig.record?.options?.min || undefined,
|
|
61
|
+
max: columnConfig.record?.options?.max || undefined
|
|
62
|
+
} as OXNumberFieldProps
|
|
63
|
+
|
|
64
|
+
case 'float':
|
|
65
|
+
return {
|
|
66
|
+
...fieldProps,
|
|
67
|
+
type: 'number',
|
|
68
|
+
min: columnConfig.record?.options?.min || undefined,
|
|
69
|
+
max: columnConfig.record?.options?.max || undefined
|
|
70
|
+
} as OXNumberFieldProps
|
|
71
|
+
|
|
72
|
+
case 'select':
|
|
73
|
+
return {
|
|
74
|
+
...fieldProps,
|
|
75
|
+
type: 'select',
|
|
76
|
+
searchEnable: true,
|
|
77
|
+
options: columnConfig.record?.options.map((option: string | Record<string, any>) => {
|
|
78
|
+
if (typeof option === 'string') {
|
|
79
|
+
return { value: option }
|
|
80
|
+
} else if (option.display && option.value) {
|
|
81
|
+
return {
|
|
82
|
+
name: option.display,
|
|
83
|
+
value: option.value
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
throw new Error('Unexpected option property')
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
} as OXSelectFieldProps
|
|
90
|
+
|
|
91
|
+
case 'boolean':
|
|
92
|
+
return {
|
|
93
|
+
...fieldProps,
|
|
94
|
+
type: 'checkbox',
|
|
95
|
+
indeterminate: true
|
|
96
|
+
} as OXCheckboxFieldProps
|
|
97
|
+
|
|
98
|
+
case 'checkbox':
|
|
99
|
+
return {
|
|
100
|
+
...fieldProps,
|
|
101
|
+
type: 'checkbox',
|
|
102
|
+
indeterminate: true
|
|
103
|
+
} as OXCheckboxFieldProps
|
|
104
|
+
|
|
105
|
+
default:
|
|
106
|
+
throw new Error('Non-supported type of column config')
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// return searchFields
|
|
111
|
+
// .filter((searchField: string) => fieldMap.has(searchField))
|
|
112
|
+
// .map((searchField: string) => {
|
|
113
|
+
// const columnConfig: ColumnConfig | undefined = fieldMap.get(searchField)
|
|
114
|
+
// if (!columnConfig) throw new Error('No matched column config')
|
|
115
|
+
|
|
116
|
+
// let fieldProps: OXBasicFieldProps = {
|
|
117
|
+
// name: columnConfig.name,
|
|
118
|
+
// hidden: Boolean(columnConfig.hidden),
|
|
119
|
+
// label: typeof columnConfig.label === 'string' ? columnConfig.label : undefined
|
|
120
|
+
// }
|
|
121
|
+
|
|
122
|
+
// switch (columnConfig.type) {
|
|
123
|
+
// case 'string':
|
|
124
|
+
// return {
|
|
125
|
+
// ...fieldProps,
|
|
126
|
+
// type: 'text'
|
|
127
|
+
// } as OXTextFieldProps
|
|
128
|
+
|
|
129
|
+
// case 'integer':
|
|
130
|
+
// return {
|
|
131
|
+
// ...fieldProps,
|
|
132
|
+
// type: 'number',
|
|
133
|
+
// min: columnConfig.record?.options?.min || undefined,
|
|
134
|
+
// max: columnConfig.record?.options?.max || undefined
|
|
135
|
+
// } as OXNumberFieldProps
|
|
136
|
+
|
|
137
|
+
// case 'number':
|
|
138
|
+
// return {
|
|
139
|
+
// ...fieldProps,
|
|
140
|
+
// type: 'number',
|
|
141
|
+
// min: columnConfig.record?.options?.min || undefined,
|
|
142
|
+
// max: columnConfig.record?.options?.max || undefined
|
|
143
|
+
// } as OXNumberFieldProps
|
|
144
|
+
|
|
145
|
+
// case 'float':
|
|
146
|
+
// return {
|
|
147
|
+
// ...fieldProps,
|
|
148
|
+
// type: 'number',
|
|
149
|
+
// min: columnConfig.record?.options?.min || undefined,
|
|
150
|
+
// max: columnConfig.record?.options?.max || undefined
|
|
151
|
+
// } as OXNumberFieldProps
|
|
152
|
+
|
|
153
|
+
// case 'select':
|
|
154
|
+
// return {
|
|
155
|
+
// ...fieldProps,
|
|
156
|
+
// type: 'select',
|
|
157
|
+
// searchEnable: true,
|
|
158
|
+
// options: columnConfig.record?.options.map((option: Record<string, any>) => ({
|
|
159
|
+
// name: option.display,
|
|
160
|
+
// value: option.value
|
|
161
|
+
// }))
|
|
162
|
+
// } as OXSelectFieldProps
|
|
163
|
+
|
|
164
|
+
// case 'boolean':
|
|
165
|
+
// return {
|
|
166
|
+
// ...fieldProps,
|
|
167
|
+
// type: 'checkbox',
|
|
168
|
+
// indeterminate: true
|
|
169
|
+
// } as OXCheckboxFieldProps
|
|
170
|
+
|
|
171
|
+
// case 'checkbox':
|
|
172
|
+
// return {
|
|
173
|
+
// ...fieldProps,
|
|
174
|
+
// type: 'checkbox',
|
|
175
|
+
// indeterminate: true
|
|
176
|
+
// } as OXCheckboxFieldProps
|
|
177
|
+
|
|
178
|
+
// default:
|
|
179
|
+
// throw new Error('Non-supported type of column config')
|
|
180
|
+
// }
|
|
181
|
+
// })
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get queryFilters(): QueryFilter[] {
|
|
185
|
+
const searchForm: OXSearchForm | null = this.renderRoot.querySelector<OXSearchForm>('ox-search-form')
|
|
186
|
+
if (!searchForm) throw new Error('Failed to find search form')
|
|
187
|
+
|
|
188
|
+
const searchFields: OXSearchFieldTypes[] = searchForm.searchFields
|
|
189
|
+
|
|
190
|
+
return searchFields
|
|
191
|
+
.filter(({ value }: OXSearchFieldTypes) => value !== null && value !== undefined && value !== '')
|
|
192
|
+
.map((searchField: OXSearchFieldTypes) => {
|
|
193
|
+
return {
|
|
194
|
+
name: searchField.field.name,
|
|
195
|
+
operator: searchField.field.operator || this.defaultOperator,
|
|
196
|
+
value: searchField.value
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
}
|