@operato/data-grist 2.0.0-alpha.0 → 2.0.0-alpha.3
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 +24 -0
- package/dist/src/configure/column-builder.js +5 -5
- package/dist/src/configure/column-builder.js.map +1 -1
- package/dist/src/configure/zero-config.js +3 -1
- package/dist/src/configure/zero-config.js.map +1 -1
- package/dist/src/data-card/data-card-field.js +1 -1
- package/dist/src/data-card/data-card-field.js.map +1 -1
- package/dist/src/data-grid/data-grid-accum-field.d.ts +1 -0
- package/dist/src/data-grid/data-grid-accum-field.js +8 -0
- package/dist/src/data-grid/data-grid-accum-field.js.map +1 -1
- package/dist/src/data-grid/data-grid-body.js +24 -3
- package/dist/src/data-grid/data-grid-body.js.map +1 -1
- package/dist/src/data-grid/data-grid-field.d.ts +1 -0
- package/dist/src/data-grid/data-grid-field.js +5 -0
- package/dist/src/data-grid/data-grid-field.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.d.ts +7 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.js +25 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.js.map +1 -0
- package/dist/src/data-grid/event-handlers/data-grid-body-dblclick-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-dblclick-handler.js.map +1 -1
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler.js +2 -2
- package/dist/src/data-grid/event-handlers/data-grid-body-focus-change-handler.js.map +1 -1
- package/dist/src/data-list/data-list-field.js +1 -1
- package/dist/src/data-list/data-list-field.js.map +1 -1
- package/dist/src/data-manipulator.d.ts +7 -3
- package/dist/src/data-manipulator.js +86 -18
- package/dist/src/data-manipulator.js.map +1 -1
- package/dist/src/editors/ox-grist-editor-tree.d.ts +6 -0
- package/dist/src/editors/ox-grist-editor-tree.js +27 -0
- package/dist/src/editors/ox-grist-editor-tree.js.map +1 -0
- package/dist/src/editors/ox-grist-editor.d.ts +1 -0
- package/dist/src/editors/ox-grist-editor.js +3 -0
- package/dist/src/editors/ox-grist-editor.js.map +1 -1
- package/dist/src/editors/ox-input-tree.d.ts +20 -0
- package/dist/src/editors/ox-input-tree.js +221 -0
- package/dist/src/editors/ox-input-tree.js.map +1 -0
- package/dist/src/editors/registry.js +3 -1
- package/dist/src/editors/registry.js.map +1 -1
- package/dist/src/filters/filters-form.js +1 -1
- package/dist/src/filters/filters-form.js.map +1 -1
- package/dist/src/handlers/contextmenu-tree-mutation.d.ts +3 -0
- package/dist/src/handlers/contextmenu-tree-mutation.js +82 -0
- package/dist/src/handlers/contextmenu-tree-mutation.js.map +1 -0
- package/dist/src/handlers/registry.js +3 -1
- package/dist/src/handlers/registry.js.map +1 -1
- package/dist/src/renderers/ox-grist-renderer-tree.d.ts +1 -0
- package/dist/src/renderers/ox-grist-renderer-tree.js +6 -3
- package/dist/src/renderers/ox-grist-renderer-tree.js.map +1 -1
- package/dist/src/types.d.ts +437 -6
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -1
- package/dist/stories/tree-column-with-checkbox.stories.js +8 -3
- package/dist/stories/tree-column-with-checkbox.stories.js.map +1 -1
- package/dist/stories/tree-column.stories.js +8 -3
- package/dist/stories/tree-column.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/gutter/gutter.md +7 -0
- package/package.json +4 -4
- package/src/configure/column-builder.ts +4 -4
- package/src/configure/zero-config.ts +3 -1
- package/src/data-card/data-card-field.ts +1 -1
- package/src/data-grid/data-grid-accum-field.ts +7 -0
- package/src/data-grid/data-grid-body.ts +30 -3
- package/src/data-grid/data-grid-field.ts +6 -0
- package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +2 -2
- package/src/data-grid/event-handlers/data-grid-body-contextmenu-handler.ts +32 -0
- package/src/data-grid/event-handlers/data-grid-body-dblclick-handler.ts +2 -2
- package/src/data-grid/event-handlers/data-grid-body-focus-change-handler.ts +2 -2
- package/src/data-list/data-list-field.ts +1 -1
- package/src/data-manipulator.ts +109 -22
- package/src/editors/ox-grist-editor-tree.ts +27 -0
- package/src/editors/ox-grist-editor.ts +4 -0
- package/src/editors/ox-input-tree.ts +226 -0
- package/src/editors/registry.ts +3 -1
- package/src/filters/filters-form.ts +1 -1
- package/src/handlers/contextmenu-tree-mutation.ts +98 -0
- package/src/handlers/registry.ts +3 -1
- package/src/renderers/ox-grist-renderer-tree.ts +7 -3
- package/src/types.ts +446 -6
- package/stories/tree-column-with-checkbox.stories.ts +8 -3
- package/stories/tree-column.stories.ts +8 -3
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.3",
|
4
4
|
"description": "User interface for grid (desktop) and list (mobile)",
|
5
5
|
"author": "heartyoh",
|
6
6
|
"main": "dist/index.js",
|
@@ -57,8 +57,8 @@
|
|
57
57
|
"dependencies": {
|
58
58
|
"@material/mwc-icon": "^0.27.0",
|
59
59
|
"@operato/headroom": "^2.0.0-alpha.0",
|
60
|
-
"@operato/input": "^2.0.0-alpha.
|
61
|
-
"@operato/popup": "^2.0.0-alpha.
|
60
|
+
"@operato/input": "^2.0.0-alpha.3",
|
61
|
+
"@operato/popup": "^2.0.0-alpha.2",
|
62
62
|
"@operato/pull-to-refresh": "^2.0.0-alpha.0",
|
63
63
|
"@operato/styles": "^2.0.0-alpha.0",
|
64
64
|
"@operato/utils": "^2.0.0-alpha.0",
|
@@ -100,5 +100,5 @@
|
|
100
100
|
"prettier --write"
|
101
101
|
]
|
102
102
|
},
|
103
|
-
"gitHead": "
|
103
|
+
"gitHead": "9943c2c54a27be3619920543344c699d3a9a55de"
|
104
104
|
}
|
@@ -36,9 +36,8 @@ export const buildColumn = (column: any): ColumnConfig => {
|
|
36
36
|
let type = typeof label
|
37
37
|
switch (type) {
|
38
38
|
case 'boolean':
|
39
|
-
let title = typeof header == 'string' ? header : name
|
40
39
|
compiled.label = {
|
41
|
-
renderer: () =>
|
40
|
+
renderer: compiled.header?.renderer || (() => name)
|
42
41
|
}
|
43
42
|
break
|
44
43
|
case 'string':
|
@@ -101,12 +100,13 @@ export const buildColumn = (column: any): ColumnConfig => {
|
|
101
100
|
}
|
102
101
|
|
103
102
|
/* handler */
|
104
|
-
var { click, dblclick, focus } = handlers || {}
|
103
|
+
var { click, dblclick, focus, contextmenu } = handlers || {}
|
105
104
|
|
106
105
|
compiled.handlers = {
|
107
106
|
click: click && getGristEventHandler(click),
|
108
107
|
dblclick: dblclick && getGristEventHandler(dblclick),
|
109
|
-
focus: focus && getGristEventHandler(focus)
|
108
|
+
focus: focus && getGristEventHandler(focus),
|
109
|
+
contextmenu: contextmenu && getGristEventHandler(contextmenu)
|
110
110
|
}
|
111
111
|
|
112
112
|
return compiled
|
@@ -18,7 +18,9 @@ export const ZERO_FIELD_RENDERER: FieldRenderer = (value, column, record, rowInd
|
|
18
18
|
|
19
19
|
export const ZERO_EVENTHANDLERSET: GristEventHandlerSet = {
|
20
20
|
click: undefined,
|
21
|
-
dblclick: undefined
|
21
|
+
dblclick: undefined,
|
22
|
+
focus: undefined,
|
23
|
+
contextmenu: undefined
|
22
24
|
}
|
23
25
|
export const ZERO_COLUMNS: ColumnConfig[] = []
|
24
26
|
export const ZERO_GROUPS: GroupConfig[] = []
|
@@ -89,7 +89,7 @@ export class DataCardField extends LitElement {
|
|
89
89
|
|
90
90
|
if (typeof label == 'object') {
|
91
91
|
let { renderer: labelRenderer } = label
|
92
|
-
return html`<label>${labelRenderer()}</label>${recordRenderer(value, column, record, rowIndex, this)}`
|
92
|
+
return html`<label>${labelRenderer(column)}</label>${recordRenderer(value, column, record, rowIndex, this)}`
|
93
93
|
} else {
|
94
94
|
return html`${recordRenderer(value, column, record, rowIndex, this)}`
|
95
95
|
}
|
@@ -58,6 +58,7 @@ export class DataGridAccumField extends LitElement {
|
|
58
58
|
@property({ type: Boolean }) editing = false
|
59
59
|
@property({ type: Object }) value = {}
|
60
60
|
@property({ attribute: false }) emphasized: any = false
|
61
|
+
@property({ type: String }) fixed?: string
|
61
62
|
|
62
63
|
render(): TemplateResult {
|
63
64
|
if (!this.column || !this.column.accumulator) {
|
@@ -90,5 +91,11 @@ export class DataGridAccumField extends LitElement {
|
|
90
91
|
this.style.setProperty('--data-grid-field-text-align', align)
|
91
92
|
}
|
92
93
|
}
|
94
|
+
|
95
|
+
if (changes.has('fixed')) {
|
96
|
+
if (this.fixed) {
|
97
|
+
this.style.left = this.fixed + 'px'
|
98
|
+
}
|
99
|
+
}
|
93
100
|
}
|
94
101
|
}
|
@@ -18,6 +18,7 @@ import { DataGridField } from './data-grid-field'
|
|
18
18
|
import { dataGridBodyClickHandler } from './event-handlers/data-grid-body-click-handler'
|
19
19
|
import { dataGridBodyDblclickHandler } from './event-handlers/data-grid-body-dblclick-handler'
|
20
20
|
import { dataGridBodyFocusChangeHandler } from './event-handlers/data-grid-body-focus-change-handler'
|
21
|
+
import { dataGridBodyContextMenuHandler } from './event-handlers/data-grid-body-contextmenu-handler'
|
21
22
|
import { dataGridBodyKeydownHandler } from './event-handlers/data-grid-body-keydown-handler'
|
22
23
|
import { accumulate } from '../accumulator/accumulator'
|
23
24
|
|
@@ -75,7 +76,7 @@ export class DataGridBody extends LitElement {
|
|
75
76
|
[fixed] {
|
76
77
|
position: sticky;
|
77
78
|
background-color: var(--grid-record-background-color);
|
78
|
-
z-index:
|
79
|
+
z-index: 2; /* 고정된 열을 다른 열 위에 표시. */
|
79
80
|
}
|
80
81
|
|
81
82
|
:host([raised]) [fixed] {
|
@@ -88,6 +89,10 @@ export class DataGridBody extends LitElement {
|
|
88
89
|
bottom: 0;
|
89
90
|
z-index: 1;
|
90
91
|
}
|
92
|
+
|
93
|
+
ox-grid-accum-field[fixed] {
|
94
|
+
background-color: var(--grid-accum-record-background-color, #ccc);
|
95
|
+
}
|
91
96
|
`
|
92
97
|
]
|
93
98
|
|
@@ -135,7 +140,6 @@ export class DataGridBody extends LitElement {
|
|
135
140
|
var columns = this.columns.filter(column => !column.hidden)
|
136
141
|
var data = this.data
|
137
142
|
var { records } = data
|
138
|
-
records = records.filter(record => !record.__parent__ || !record.__parent__.collapsed)
|
139
143
|
var { appendable, classifier, accumulator } = this.config.rows
|
140
144
|
const { start, end } = this._selectBlock || {}
|
141
145
|
|
@@ -208,6 +212,7 @@ export class DataGridBody extends LitElement {
|
|
208
212
|
.column=${column}
|
209
213
|
.record=${accumRecord!}
|
210
214
|
.value=${accumRecord[column.name]}
|
215
|
+
fixed=${ifDefined(this.fixedLefts[idxColumn])}
|
211
216
|
></ox-grid-accum-field>
|
212
217
|
`
|
213
218
|
)}
|
@@ -261,6 +266,27 @@ export class DataGridBody extends LitElement {
|
|
261
266
|
this.setSelectBlock(start, end)
|
262
267
|
})
|
263
268
|
|
269
|
+
this.renderRoot.addEventListener('contextmenu', (event: Event) => {
|
270
|
+
const e = event as MouseEvent
|
271
|
+
this.setSelectBlock()
|
272
|
+
|
273
|
+
this._draggable = false
|
274
|
+
|
275
|
+
var target = (e.target as Element).closest('ox-grid-field') as DataGridField
|
276
|
+
var { rowIndex, columnIndex } = target || {}
|
277
|
+
|
278
|
+
this.dispatchEvent(
|
279
|
+
new CustomEvent('focus-change', {
|
280
|
+
bubbles: true,
|
281
|
+
composed: true,
|
282
|
+
detail: {
|
283
|
+
row: rowIndex,
|
284
|
+
column: columnIndex
|
285
|
+
}
|
286
|
+
})
|
287
|
+
)
|
288
|
+
})
|
289
|
+
|
264
290
|
this.renderRoot.addEventListener('mousedown', (event: Event) => {
|
265
291
|
const e = event as MouseEvent
|
266
292
|
this.setSelectBlock()
|
@@ -285,7 +311,7 @@ export class DataGridBody extends LitElement {
|
|
285
311
|
})
|
286
312
|
)
|
287
313
|
|
288
|
-
if (!isNaN(rowIndex) && !isNaN(columnIndex)) {
|
314
|
+
if (columnIndex >= 0 && target.editableOnClick && !isNaN(rowIndex) && !isNaN(columnIndex)) {
|
289
315
|
this.startEditTarget(rowIndex, columnIndex)
|
290
316
|
}
|
291
317
|
})
|
@@ -318,6 +344,7 @@ export class DataGridBody extends LitElement {
|
|
318
344
|
|
319
345
|
this.renderRoot.addEventListener('click', dataGridBodyClickHandler.bind(this))
|
320
346
|
this.renderRoot.addEventListener('dblclick', dataGridBodyDblclickHandler.bind(this))
|
347
|
+
this.renderRoot.addEventListener('contextmenu', dataGridBodyContextMenuHandler.bind(this))
|
321
348
|
|
322
349
|
this.addEventListener('focus-change', dataGridBodyFocusChangeHandler.bind(this))
|
323
350
|
|
@@ -173,4 +173,10 @@ export class DataGridField extends LitElement {
|
|
173
173
|
this.removeAttribute('emphasized-row')
|
174
174
|
}
|
175
175
|
}
|
176
|
+
|
177
|
+
get editableOnClick() {
|
178
|
+
const renderer = this.renderRoot.firstElementChild as HTMLElement
|
179
|
+
//@ts-ignore
|
180
|
+
return renderer && 'editableOnClick' in renderer ? renderer.editableOnClick : true
|
181
|
+
}
|
176
182
|
}
|
@@ -56,10 +56,10 @@ export function dataGridBodyClickHandler(this: DataGridBody, e: Event): void {
|
|
56
56
|
/* do column click handler */
|
57
57
|
if (column) {
|
58
58
|
var { click } = column.handlers
|
59
|
-
click && click(this.columns, this.data, column, record, rowIndex, target)
|
59
|
+
click && click(this.columns, this.data, column, record, rowIndex, target, e)
|
60
60
|
}
|
61
61
|
|
62
62
|
/* do rows click handler */
|
63
63
|
var { click: rowsClick } = this.config.rows.handlers
|
64
|
-
rowsClick && rowsClick(this.columns, this.data, column, record, rowIndex, target)
|
64
|
+
rowsClick && rowsClick(this.columns, this.data, column, record, rowIndex, target, e)
|
65
65
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { DataGridBody } from '../data-grid-body'
|
2
|
+
import { DataGridField } from '../data-grid-field'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* ox-grid-body 의 focus-change handler
|
6
|
+
*
|
7
|
+
* - handler의 this 는 ox-grid-body임.
|
8
|
+
*/
|
9
|
+
export async function dataGridBodyContextMenuHandler(this: DataGridBody, e: Event): Promise<void> {
|
10
|
+
e.stopPropagation()
|
11
|
+
|
12
|
+
if (this.editTarget) {
|
13
|
+
/* editTarget이 새로 설정되지 않았다면, 이후 기능이 실행된다. */
|
14
|
+
return
|
15
|
+
}
|
16
|
+
|
17
|
+
/* target should be 'ox-grid-field' */
|
18
|
+
var target = (e.target as Element).closest('ox-grid-field') as DataGridField
|
19
|
+
var { column, record, rowIndex, columnIndex } = target || {}
|
20
|
+
|
21
|
+
var { column, record } = target || {}
|
22
|
+
|
23
|
+
/* do column contextmenu handler */
|
24
|
+
if (column) {
|
25
|
+
var { contextmenu } = column.handlers
|
26
|
+
contextmenu && contextmenu(this.columns, this.data, column, record, rowIndex, target, e)
|
27
|
+
}
|
28
|
+
|
29
|
+
/* do rows contextmenu handler */
|
30
|
+
var { contextmenu: rowsContextMenu } = this.config.rows.handlers
|
31
|
+
rowsContextMenu && rowsContextMenu(this.columns, this.data, column, record, rowIndex, target, e)
|
32
|
+
}
|
@@ -33,10 +33,10 @@ export async function dataGridBodyDblclickHandler(this: DataGridBody, e: Event):
|
|
33
33
|
/* do column dblclick handler */
|
34
34
|
if (column) {
|
35
35
|
var { dblclick } = column.handlers
|
36
|
-
dblclick && dblclick(this.columns, this.data, column, record, rowIndex, target)
|
36
|
+
dblclick && dblclick(this.columns, this.data, column, record, rowIndex, target, e)
|
37
37
|
}
|
38
38
|
|
39
39
|
/* do rows dblclick handler */
|
40
40
|
var { dblclick: rowsDblclick } = this.config.rows.handlers
|
41
|
-
rowsDblclick && rowsDblclick(this.columns, this.data, column, record, rowIndex, target)
|
41
|
+
rowsDblclick && rowsDblclick(this.columns, this.data, column, record, rowIndex, target, e)
|
42
42
|
}
|
@@ -15,10 +15,10 @@ export async function dataGridBodyFocusChangeHandler(this: DataGridBody, e: Even
|
|
15
15
|
/* do column focus handler */
|
16
16
|
if (column) {
|
17
17
|
var { focus } = column.handlers
|
18
|
-
focus && focus(this.columns, this.data, column, record, rowIndex, target)
|
18
|
+
focus && focus(this.columns, this.data, column, record, rowIndex, target, e)
|
19
19
|
}
|
20
20
|
|
21
21
|
/* do rows focus handler */
|
22
22
|
var { focus: rowsFocus } = this.config.rows.handlers
|
23
|
-
rowsFocus && rowsFocus(this.columns, this.data, column, record, rowIndex, target)
|
23
|
+
rowsFocus && rowsFocus(this.columns, this.data, column, record, rowIndex, target, e)
|
24
24
|
}
|
@@ -77,7 +77,7 @@ export class DataListField extends LitElement {
|
|
77
77
|
|
78
78
|
if (typeof label == 'object') {
|
79
79
|
let { renderer: labelRenderer } = label
|
80
|
-
return html`<label>${labelRenderer()}</label>${fieldRenderer(value, column, record, rowIndex, this)}`
|
80
|
+
return html`<label>${labelRenderer(column)}</label>${fieldRenderer(value, column, record, rowIndex, this)}`
|
81
81
|
} else {
|
82
82
|
return html`${fieldRenderer(value, column, record, rowIndex, this)}`
|
83
83
|
}
|
package/src/data-manipulator.ts
CHANGED
@@ -15,8 +15,8 @@ import {
|
|
15
15
|
export class DataManipulator extends LitElement {
|
16
16
|
@property({ type: Object }) config: GristConfig = ZERO_CONFIG
|
17
17
|
@property({ type: Object }) data: GristData = ZERO_DATA
|
18
|
-
@property({ type:
|
19
|
-
@property({ type:
|
18
|
+
@property({ type: Array }) sorters: SortersConfig = []
|
19
|
+
@property({ type: Array }) filters: FilterValue[] = []
|
20
20
|
@property({ type: Object }) pagination: PaginationConfig = {}
|
21
21
|
|
22
22
|
constructor() {
|
@@ -64,16 +64,15 @@ export class DataManipulator extends LitElement {
|
|
64
64
|
})
|
65
65
|
|
66
66
|
/* tree processing */
|
67
|
-
this.addEventListener('
|
68
|
-
this.addEventListener('
|
67
|
+
this.addEventListener('collapse-all', (e: Event) => this.onCollapseAll(e as CustomEvent))
|
68
|
+
this.addEventListener('expand-all', (e: Event) => this.onExpandAll(e as CustomEvent))
|
69
|
+
this.addEventListener('collapse-node', (e: Event) => this.onCollapse(e as CustomEvent))
|
70
|
+
this.addEventListener('expand-node', (e: Event) => this.onExpand(e as CustomEvent))
|
69
71
|
this.addEventListener('check-in-tree', (e: Event) => this.onCheckInTree(e as CustomEvent))
|
70
|
-
}
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
// }
|
76
|
-
// }
|
73
|
+
this.addEventListener('add-sibling-node', (e: Event) => this.onAddSiblingNode(e as CustomEvent))
|
74
|
+
this.addEventListener('add-child-node', (e: Event) => this.onAddChildNode(e as CustomEvent))
|
75
|
+
}
|
77
76
|
|
78
77
|
onFieldChange({
|
79
78
|
after,
|
@@ -213,23 +212,101 @@ export class DataManipulator extends LitElement {
|
|
213
212
|
this.requestUpdate()
|
214
213
|
}
|
215
214
|
|
216
|
-
|
217
|
-
|
215
|
+
onCollapseAll(e: CustomEvent) {
|
216
|
+
this.refresh(false)
|
217
|
+
}
|
218
|
+
|
219
|
+
onExpandAll(e: CustomEvent) {
|
220
|
+
this.refresh(true)
|
221
|
+
}
|
222
|
+
|
223
|
+
onCollapse(e: CustomEvent) {
|
224
|
+
const record = e.detail as GristRecord
|
218
225
|
record.__expanded__ = false
|
219
226
|
|
220
227
|
this.refresh()
|
221
228
|
}
|
222
229
|
|
223
|
-
|
224
|
-
const record = e.detail
|
230
|
+
onExpand(e: CustomEvent) {
|
231
|
+
const record = e.detail as GristRecord
|
225
232
|
record.__expanded__ = true
|
226
233
|
|
227
234
|
this.refresh()
|
228
235
|
}
|
229
236
|
|
230
|
-
|
231
|
-
const
|
237
|
+
onAddSiblingNode(e: CustomEvent) {
|
238
|
+
const { records } = this.data
|
239
|
+
const toplevelRecords = records.filter(
|
240
|
+
record => !record.__depth__
|
241
|
+
) /* __depth__ 가 설정되지 않았거나, 0 인 경우만 수집 */
|
242
|
+
|
243
|
+
const field = e.detail
|
244
|
+
const { record } = field
|
245
|
+
const { __depth__ } = record as GristRecord
|
246
|
+
|
247
|
+
function findParent(record: GristRecord, parent?: GristRecord): GristRecord | undefined {
|
248
|
+
var children = (parent ? parent.__children__ || [] : toplevelRecords) as GristRecord[]
|
249
|
+
|
250
|
+
if (children.find(child => child === record)) {
|
251
|
+
return parent
|
252
|
+
} else {
|
253
|
+
for (let child of children) {
|
254
|
+
const found = findParent(record, child)
|
255
|
+
if (found) {
|
256
|
+
return found
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
262
|
+
const parent = findParent(record)
|
263
|
+
|
264
|
+
const sibling = {
|
265
|
+
__depth__,
|
266
|
+
__dirty__: '+'
|
267
|
+
}
|
268
|
+
|
269
|
+
if (parent) {
|
270
|
+
const { __children__ } = parent as GristRecord
|
232
271
|
|
272
|
+
if (!__children__) {
|
273
|
+
parent.__children__ = [sibling]
|
274
|
+
} else {
|
275
|
+
parent.__children__ = [...__children__, sibling]
|
276
|
+
}
|
277
|
+
|
278
|
+
parent.__expanded__ = true
|
279
|
+
} else {
|
280
|
+
this.data.records = [...toplevelRecords, sibling]
|
281
|
+
}
|
282
|
+
|
283
|
+
this.refresh()
|
284
|
+
}
|
285
|
+
|
286
|
+
onAddChildNode(e: CustomEvent) {
|
287
|
+
const field = e.detail
|
288
|
+
const { record } = field
|
289
|
+
|
290
|
+
const { __children__, __depth__, __seq__ } = record as GristRecord
|
291
|
+
const child = {
|
292
|
+
__depth__: (__depth__ || 0) + 1,
|
293
|
+
__dirty__: '+'
|
294
|
+
}
|
295
|
+
|
296
|
+
if (!__children__) {
|
297
|
+
record.__children__ = [child]
|
298
|
+
} else {
|
299
|
+
record.__children__.push(child)
|
300
|
+
}
|
301
|
+
|
302
|
+
record.__expanded__ = true
|
303
|
+
|
304
|
+
field.requestUpdate()
|
305
|
+
|
306
|
+
this.refresh()
|
307
|
+
}
|
308
|
+
|
309
|
+
onCheckInTree(e: CustomEvent) {
|
233
310
|
function walkTreeCheckedUpdate(record: GristRecord, checked: 'checked' | 'unchecked') {
|
234
311
|
const children = record.__children__
|
235
312
|
|
@@ -248,7 +325,8 @@ export class DataManipulator extends LitElement {
|
|
248
325
|
|
249
326
|
children.forEach(child => updateCheckedAll(child))
|
250
327
|
|
251
|
-
var checked: 'checked' | 'half-checked' | 'unchecked' | undefined
|
328
|
+
var checked: 'checked' | 'half-checked' | 'unchecked' | undefined =
|
329
|
+
record.__check_in_tree__ == 'checked' ? 'checked' : undefined
|
252
330
|
|
253
331
|
children.forEach(child => {
|
254
332
|
const { __check_in_tree__ } = child
|
@@ -256,7 +334,7 @@ export class DataManipulator extends LitElement {
|
|
256
334
|
if (__check_in_tree__ == 'half-checked') {
|
257
335
|
checked = 'half-checked'
|
258
336
|
} else if (__check_in_tree__ == 'checked') {
|
259
|
-
checked = checked == 'checked'
|
337
|
+
checked = checked == 'checked' ? 'checked' : 'half-checked'
|
260
338
|
} else {
|
261
339
|
checked = checked == 'unchecked' || !checked ? 'unchecked' : 'half-checked'
|
262
340
|
}
|
@@ -287,7 +365,7 @@ export class DataManipulator extends LitElement {
|
|
287
365
|
* Therefore, it will be deprecated.
|
288
366
|
* @method
|
289
367
|
*/
|
290
|
-
refresh() {
|
368
|
+
refresh(forceExpandOrCollapse?: boolean) {
|
291
369
|
/*
|
292
370
|
- TODO 여기에서 TREE 형태 데이터의 접고, 펴는 것을 재구성한다.
|
293
371
|
- 동적으로 서브항목을 fetch 하는 기능은 제공하지 않는다.
|
@@ -302,15 +380,24 @@ export class DataManipulator extends LitElement {
|
|
302
380
|
) /* __depth__ 가 설정되지 않았거나, 0 인 경우만 수집 */
|
303
381
|
this.data = {
|
304
382
|
...this.data,
|
305
|
-
records: ([] as GristRecord[]).concat(
|
383
|
+
records: ([] as GristRecord[]).concat(
|
384
|
+
...toplevelRecords.map(record => this.traverseRefresh(record, forceExpandOrCollapse))
|
385
|
+
)
|
306
386
|
}
|
307
387
|
}
|
308
388
|
|
309
|
-
private traverseRefresh(record: GristRecord): GristRecord[] {
|
389
|
+
private traverseRefresh(record: GristRecord, forceExpandOrCollapse?: boolean): GristRecord[] {
|
390
|
+
if (forceExpandOrCollapse !== undefined) {
|
391
|
+
record = {
|
392
|
+
...record,
|
393
|
+
__expanded__: forceExpandOrCollapse
|
394
|
+
}
|
395
|
+
}
|
396
|
+
|
310
397
|
const { __expanded__, __children__ = [] } = record
|
311
398
|
|
312
399
|
if (__expanded__ && __children__.length > 0) {
|
313
|
-
return [record].concat(...__children__.map(child => this.traverseRefresh(child)))
|
400
|
+
return [record].concat(...__children__.map(child => this.traverseRefresh(child, forceExpandOrCollapse)))
|
314
401
|
} else {
|
315
402
|
return [record]
|
316
403
|
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import './ox-input-tree'
|
2
|
+
|
3
|
+
import { html, css } from 'lit'
|
4
|
+
import { customElement, query } from 'lit/decorators.js'
|
5
|
+
|
6
|
+
import { OxGristEditor } from './ox-grist-editor.js'
|
7
|
+
|
8
|
+
@customElement('ox-grist-editor-tree')
|
9
|
+
export class OxGristEditorTree extends OxGristEditor {
|
10
|
+
static styles = [
|
11
|
+
css`
|
12
|
+
:host {
|
13
|
+
flex: 1;
|
14
|
+
}
|
15
|
+
|
16
|
+
ox-input-tree {
|
17
|
+
flex: 1;
|
18
|
+
}
|
19
|
+
`
|
20
|
+
]
|
21
|
+
|
22
|
+
get editorTemplate() {
|
23
|
+
var { selectable } = this.column.record.options || {}
|
24
|
+
|
25
|
+
return html`<ox-input-tree .value=${this.value} .record=${this.record} ?selectable=${selectable}></ox-input-tree>`
|
26
|
+
}
|
27
|
+
}
|
@@ -91,6 +91,10 @@ export class OxGristEditor extends LitElement {
|
|
91
91
|
return this.renderRoot.firstElementChild as HTMLElement
|
92
92
|
}
|
93
93
|
|
94
|
+
get directEditable() {
|
95
|
+
return true
|
96
|
+
}
|
97
|
+
|
94
98
|
async firstUpdated() {
|
95
99
|
this.renderRoot.addEventListener('change', this._onchange.bind(this))
|
96
100
|
this.renderRoot.addEventListener('focusout', this._onfocusout.bind(this))
|