@operato/data-grist 8.0.0-alpha.50 → 8.0.0-alpha.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/src/gutters/gutter-sequence.d.ts +1 -1
  3. package/dist/src/record-view/index.d.ts +1 -1
  4. package/dist/src/record-view/index.js +1 -1
  5. package/dist/src/record-view/index.js.map +1 -1
  6. package/dist/src/record-view/{record-creator.d.ts → ox-record-creator.d.ts} +8 -4
  7. package/dist/src/record-view/{record-creator.js → ox-record-creator.js} +84 -15
  8. package/dist/src/record-view/ox-record-creator.js.map +1 -0
  9. package/dist/stories/accumulator-format.stories.d.ts +1 -1
  10. package/dist/stories/accumulator-format.stories.js +1 -1
  11. package/dist/stories/accumulator-format.stories.js.map +1 -1
  12. package/dist/stories/click-event-custom.stories.d.ts +45 -0
  13. package/dist/stories/click-event-custom.stories.js +247 -0
  14. package/dist/stories/click-event-custom.stories.js.map +1 -0
  15. package/dist/stories/click-event.stories.d.ts +1 -1
  16. package/dist/stories/click-event.stories.js +1 -1
  17. package/dist/stories/click-event.stories.js.map +1 -1
  18. package/dist/stories/fixed-column.stories.d.ts +1 -1
  19. package/dist/stories/fixed-column.stories.js +1 -1
  20. package/dist/stories/fixed-column.stories.js.map +1 -1
  21. package/dist/stories/grid-setting.stories.d.ts +1 -1
  22. package/dist/stories/grid-setting.stories.js +1 -1
  23. package/dist/stories/grid-setting.stories.js.map +1 -1
  24. package/dist/stories/grist-modes.stories.d.ts +1 -1
  25. package/dist/stories/grist-modes.stories.js +1 -1
  26. package/dist/stories/grist-modes.stories.js.map +1 -1
  27. package/dist/stories/group-header.stories.d.ts +1 -1
  28. package/dist/stories/group-header.stories.js +1 -1
  29. package/dist/stories/group-header.stories.js.map +1 -1
  30. package/dist/stories/textarea.stories.d.ts +1 -1
  31. package/dist/stories/textarea.stories.js +1 -1
  32. package/dist/stories/textarea.stories.js.map +1 -1
  33. package/dist/stories/tree-column-with-checkbox.stories.d.ts +1 -1
  34. package/dist/stories/tree-column-with-checkbox.stories.js +1 -1
  35. package/dist/stories/tree-column-with-checkbox.stories.js.map +1 -1
  36. package/dist/stories/tree-column.stories.d.ts +1 -1
  37. package/dist/stories/tree-column.stories.js +1 -1
  38. package/dist/stories/tree-column.stories.js.map +1 -1
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +7 -7
  41. package/src/record-view/index.ts +1 -1
  42. package/src/record-view/{record-creator.ts → ox-record-creator.ts} +98 -23
  43. package/stories/accumulator-format.stories.ts +1 -1
  44. package/stories/click-event-custom.stories.ts +287 -0
  45. package/stories/click-event.stories.ts +1 -1
  46. package/stories/fixed-column.stories.ts +1 -1
  47. package/stories/grid-setting.stories.ts +1 -1
  48. package/stories/grist-modes.stories.ts +1 -1
  49. package/stories/group-header.stories.ts +1 -1
  50. package/stories/textarea.stories.ts +1 -1
  51. package/stories/tree-column-with-checkbox.stories.ts +1 -1
  52. package/stories/tree-column.stories.ts +1 -1
  53. package/dist/src/record-view/record-creator.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operato/data-grist",
3
- "version": "8.0.0-alpha.50",
3
+ "version": "8.0.0-alpha.52",
4
4
  "description": "User interface for grid (desktop) and list (mobile)",
5
5
  "author": "heartyoh",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "./ox-report.js": "./dist/src/data-report.js",
24
24
  "./ox-filters-form.js": "./dist/src/filters/filters-form.js",
25
25
  "./ox-sorters-control.js": "./dist/src/sorters/sorters-control.js",
26
- "./ox-record-creator.js": "./dist/src/record-view/record-creator.js",
26
+ "./ox-record-creator.js": "./dist/src/record-view/ox-record-creator.js",
27
27
  "./ox-grist-personalizer.js": "./dist/src/personalizer/ox-grist-personalizer.js"
28
28
  },
29
29
  "typesVersions": {
@@ -41,7 +41,7 @@
41
41
  "dist/src/sorters/sorters-control.d.ts"
42
42
  ],
43
43
  "ox-record-creator.js": [
44
- "dist/src/record-view/record-creator.d.ts"
44
+ "dist/src/record-view/ox-record-creator.d.ts"
45
45
  ],
46
46
  "ox-grist-personalizer.js": [
47
47
  "dist/src/personalizer/ox-grist-personalizer.d.ts"
@@ -63,9 +63,9 @@
63
63
  "dependencies": {
64
64
  "@material/web": "^2.0.0",
65
65
  "@operato/headroom": "^8.0.0-alpha.37",
66
- "@operato/input": "^8.0.0-alpha.50",
67
- "@operato/p13n": "^8.0.0-alpha.50",
68
- "@operato/popup": "^8.0.0-alpha.50",
66
+ "@operato/input": "^8.0.0-alpha.51",
67
+ "@operato/p13n": "^8.0.0-alpha.51",
68
+ "@operato/popup": "^8.0.0-alpha.51",
69
69
  "@operato/pull-to-refresh": "^8.0.0-alpha.37",
70
70
  "@operato/styles": "^8.0.0-alpha.50",
71
71
  "@operato/time-calculator": "^8.0.0-alpha.37",
@@ -108,5 +108,5 @@
108
108
  "prettier --write"
109
109
  ]
110
110
  },
111
- "gitHead": "4a218d16762f21bec5de8d2551cf18073e6703ff"
111
+ "gitHead": "704510726d5c6c6b07a828203e7cafa895c2cb5f"
112
112
  }
@@ -1,2 +1,2 @@
1
1
  export * from './record-view'
2
- export * from './record-creator'
2
+ export * from './ox-record-creator'
@@ -1,7 +1,7 @@
1
1
  import '@material/web/icon/icon.js'
2
2
  import './record-view'
3
3
 
4
- import { html, LitElement } from 'lit'
4
+ import { css, html, LitElement } from 'lit'
5
5
  import { customElement, property, state } from 'lit/decorators.js'
6
6
 
7
7
  import { OxPopup } from '@operato/popup'
@@ -11,10 +11,19 @@ import { ColumnConfig, GristRecord, ValidationReason } from '../types'
11
11
  import { RecordView } from './record-view'
12
12
 
13
13
  @customElement('ox-record-creator')
14
- export class RecordCreator extends LitElement {
14
+ export class OxRecordCreator extends LitElement {
15
+ static styles = [
16
+ css`
17
+ ::slotted([slot='popup']) {
18
+ display: none;
19
+ }
20
+ `
21
+ ]
22
+
15
23
  @state() grist?: DataGrist
16
24
 
17
- @property({ type: Object }) callback?: (operation: { [key: string]: any }) => boolean
25
+ @property({ type: Object }) callback?: (record: GristRecord) => boolean
26
+ @property({ type: Object }) customPopupCallback?: (popup: any) => boolean
18
27
  @property({ type: Boolean, attribute: 'light-popup' }) lightPopup: boolean = false
19
28
  @property({ type: Boolean, attribute: 'prevent-close-on-blur' }) preventCloseOnBlur = false
20
29
 
@@ -26,9 +35,9 @@ export class RecordCreator extends LitElement {
26
35
  e.stopPropagation()
27
36
 
28
37
  if (this.lightPopup) {
29
- this.lightPopupRecordView()
38
+ this.openLightPopup()
30
39
  } else {
31
- this.popupRecordView()
40
+ this.openPopup()
32
41
  }
33
42
  })
34
43
  }
@@ -40,26 +49,55 @@ export class RecordCreator extends LitElement {
40
49
  }
41
50
 
42
51
  render() {
43
- return html`<slot></slot>`
52
+ return html`
53
+ <slot></slot>
54
+ <slot name="popup"></slot>
55
+ `
44
56
  }
45
57
 
46
58
  validateRecord(record: GristRecord): { field: string; reason: ValidationReason }[] {
47
- const columns = this.grist!.compiledConfig.columns;
48
- const invalidFields: { field: string; reason: ValidationReason }[] = [];
59
+ const columns = this.grist!.compiledConfig.columns
60
+ const invalidFields: { field: string; reason: ValidationReason }[] = []
49
61
 
50
62
  columns.forEach(column => {
51
- if (column.record?.mandatory && (record[column.name] === undefined || record[column.name] === null || record[column.name] === '')) {
63
+ if (
64
+ column.record?.mandatory &&
65
+ (record[column.name] === undefined || record[column.name] === null || record[column.name] === '')
66
+ ) {
52
67
  invalidFields.push({
53
68
  field: column.name,
54
69
  reason: ValidationReason.MANDATORY
55
- });
70
+ })
56
71
  }
57
- // 여기에 추가적인 유효성 검사 규칙을 구현할 수 있습니다.
58
- });
72
+ })
59
73
 
60
74
  return invalidFields
61
75
  }
62
76
 
77
+ openLightPopup() {
78
+ const slot = this.renderRoot?.querySelector(`slot[name='popup']`) as HTMLSlotElement
79
+ const slottedElements = slot?.assignedElements({ flatten: true })
80
+ const originalContent = slottedElements?.[0] as HTMLElement
81
+
82
+ if (originalContent) {
83
+ this.lightPopupCustomCreator(originalContent)
84
+ } else {
85
+ this.lightPopupRecordView()
86
+ }
87
+ }
88
+
89
+ openPopup() {
90
+ const slot = this.renderRoot?.querySelector(`slot[name='popup']`) as HTMLSlotElement
91
+ const slottedElements = slot?.assignedElements({ flatten: true })
92
+ const originalContent = slottedElements?.[0] as HTMLElement
93
+
94
+ if (originalContent) {
95
+ this.popupCustomCreator(originalContent)
96
+ } else {
97
+ this.popupRecordView()
98
+ }
99
+ }
100
+
63
101
  lightPopupRecordView() {
64
102
  const config = this.grist!.compiledConfig
65
103
  var title = 'create'
@@ -105,17 +143,17 @@ export class RecordCreator extends LitElement {
105
143
  popup.close()
106
144
  }}
107
145
  @ok=${async (e: Event) => {
108
- const view = e.currentTarget as RecordView
146
+ const view = e.currentTarget as RecordView
109
147
 
110
148
  // 레코드 밸리데이션 체크
111
- const invalidFields = await this.validateRecord(view.record);
149
+ const invalidFields = await this.validateRecord(view.record)
112
150
  if (invalidFields.length > 0) {
113
151
  // const firstInvalidField = invalidFields[0];
114
152
  // if (firstInvalidField) {
115
153
  // view.setFocus(firstInvalidField.field)
116
154
  // }
117
- view.setFocusOnInvalid(invalidFields);
118
- return false;
155
+ view.setFocusOnInvalid(invalidFields)
156
+ return false
119
157
  }
120
158
 
121
159
  popup.close()
@@ -172,23 +210,23 @@ export class RecordCreator extends LitElement {
172
210
  const view = e.currentTarget as RecordView
173
211
 
174
212
  // 레코드 밸리데이션 체크
175
- const invalidFields = await this.validateRecord(view.record);
213
+ const invalidFields = await this.validateRecord(view.record)
176
214
  if (invalidFields.length > 0) {
177
- const firstInvalidField = invalidFields[0];
215
+ const firstInvalidField = invalidFields[0]
178
216
  if (firstInvalidField) {
179
- const fieldElement = view.renderRoot?.querySelector(`[name="${firstInvalidField}"]`);
217
+ const fieldElement = view.renderRoot?.querySelector(`[name="${firstInvalidField}"]`)
180
218
  if (fieldElement) {
181
- (fieldElement as HTMLElement).focus();
219
+ ;(fieldElement as HTMLElement).focus()
182
220
  }
183
221
  }
184
- return false;
222
+ return false
185
223
  }
186
-
224
+
187
225
  if (await this.callback?.(view.record)) {
188
226
  popup.close()
189
227
  } else {
190
228
  // 밸리데이션 실패 시 처리
191
- console.error('레코드 밸리데이션 실패');
229
+ console.error('레코드 밸리데이션 실패')
192
230
  // 여기에 사용자에게 오류 메시지를 표시하는 로직을 추가할 수 있습니다.
193
231
  }
194
232
  })
@@ -223,4 +261,41 @@ export class RecordCreator extends LitElement {
223
261
  })
224
262
  )
225
263
  }
264
+
265
+ lightPopupCustomCreator(originalContent: HTMLElement) {
266
+ const title = 'create'
267
+ const popupContent = originalContent.cloneNode(true) as HTMLElement
268
+ popupContent.removeAttribute('slot')
269
+
270
+ OxPopup.open({
271
+ template: html`
272
+ <div title>${title}</div>
273
+ ${popupContent}
274
+ `,
275
+ parent: document.body,
276
+ preventCloseOnBlur: this.preventCloseOnBlur
277
+ })
278
+
279
+ this.customPopupCallback?.(popupContent) // 사용자 정의 팝업용 콜백 실행
280
+ }
281
+
282
+ popupCustomCreator(originalContent: HTMLElement) {
283
+ const title = 'create'
284
+ const popupContent = originalContent.cloneNode(true) as HTMLElement
285
+ popupContent.removeAttribute('slot')
286
+
287
+ document.dispatchEvent(
288
+ new CustomEvent('open-popup', {
289
+ detail: {
290
+ template: popupContent,
291
+ options: {
292
+ backdrop: true,
293
+ size: 'large',
294
+ title
295
+ },
296
+ callback: this.customPopupCallback
297
+ }
298
+ })
299
+ )
300
+ }
226
301
  }
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -0,0 +1,287 @@
1
+ import '../src/index.js'
2
+ import '../src/filters/filters-form.js'
3
+ import '../src/sorters/sorters-control.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
+ import '@operato/popup/ox-popup-list.js'
6
+ import '@material/web/icon/icon.js'
7
+
8
+ import { html, TemplateResult } from 'lit'
9
+ import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
10
+
11
+ import { FetchHandler, FetchOption, GristEventHandler } from '../src/types.js'
12
+
13
+ import { CommonHeaderStyles, CommonGristStyles } from '@operato/styles'
14
+
15
+ const fetchHandler: FetchHandler = async ({ page, limit }: FetchOption) => {
16
+ var total = 25
17
+ var start = (page! - 1) * limit!
18
+
19
+ await new Promise(resolve => setTimeout(resolve, 500))
20
+
21
+ return {
22
+ total,
23
+ records: Array(limit! * page! > total ? total % limit! : limit)
24
+ .fill('')
25
+ .map((item, idx) => {
26
+ return {
27
+ id: String(idx),
28
+ name: idx % 2 ? `shnam-${start + idx + 1}` : `heartyoh-${start + idx + 1}`,
29
+ description: idx % 2 ? `hatiolabmanager${start + idx + 1}1234567890` : `hatiosea manager-${start + idx + 1}`,
30
+ accval: Math.random(),
31
+ accval2: Math.round(Math.random() * 15),
32
+ createdAt: Date.now(),
33
+ updatedAt: Date.now()
34
+ }
35
+ })
36
+ }
37
+ }
38
+
39
+ const config = {
40
+ columns: [
41
+ {
42
+ type: 'gutter',
43
+ gutterName: 'dirty'
44
+ },
45
+ {
46
+ type: 'gutter',
47
+ gutterName: 'sequence'
48
+ },
49
+ {
50
+ type: 'gutter',
51
+ gutterName: 'row-selector',
52
+ multiple: true
53
+ },
54
+ {
55
+ type: 'gutter',
56
+ gutterName: 'button',
57
+ icon: 'add',
58
+ title: 'add',
59
+ handlers: {
60
+ click: ((columns, data, column, record, rowIndex, target, e) =>
61
+ console.log('column - clicked')) as GristEventHandler,
62
+ dblclick: ((columns, data, column, record, rowIndex, target, e) =>
63
+ console.log('column - dblclicked')) as GristEventHandler,
64
+ contextmenu: ((columns, data, column, record, rowIndex, target, e) =>
65
+ console.log('column - contextmenued')) as GristEventHandler,
66
+ focus: ((columns, data, column, record, rowIndex, target, e) =>
67
+ console.log('column - focused')) as GristEventHandler
68
+ }
69
+ },
70
+ {
71
+ type: 'string',
72
+ name: 'id',
73
+ hidden: true
74
+ },
75
+ {
76
+ type: 'string',
77
+ name: 'name',
78
+ label: true,
79
+ header: 'name',
80
+ record: {
81
+ editable: true
82
+ },
83
+ filter: 'search',
84
+ sortable: true,
85
+ width: 120,
86
+ fixed: true
87
+ },
88
+ {
89
+ type: 'string',
90
+ name: 'description',
91
+ header: {
92
+ renderer: () => 'description',
93
+ style: 'text-transform: none;'
94
+ },
95
+ filter: 'search',
96
+ record: {
97
+ editable: true,
98
+ align: 'left'
99
+ },
100
+ width: 200
101
+ },
102
+ {
103
+ type: 'number',
104
+ name: 'accval',
105
+ label: true,
106
+ header: 'accval',
107
+ record: {
108
+ editable: true,
109
+ align: 'right',
110
+ defaultValue: 100,
111
+ format: '+$#,##0.00'
112
+ },
113
+ accumulator: 'avg',
114
+ sortable: true,
115
+ width: 130
116
+ },
117
+ {
118
+ type: 'number',
119
+ name: 'accval2',
120
+ label: true,
121
+ header: 'accval2',
122
+ record: {
123
+ editable: true,
124
+ align: 'right',
125
+ renderer: (value: any, column: any, record: any) => {
126
+ return value && Intl.NumberFormat('en-US').format(value)
127
+ }
128
+ },
129
+ accumulator: {
130
+ type: 'sum',
131
+ tag: true
132
+ },
133
+ sortable: true,
134
+ width: 130
135
+ },
136
+ {
137
+ type: 'datetime',
138
+ name: 'updatedAt',
139
+ header: 'updated at',
140
+ record: {
141
+ editable: true,
142
+ defaultValue: {
143
+ name: 'now'
144
+ }
145
+ },
146
+ filter: 'between',
147
+ sortable: true,
148
+ width: 180
149
+ },
150
+ {
151
+ type: 'datetime',
152
+ name: 'createdAt',
153
+ header: 'created at',
154
+ record: {
155
+ editable: false
156
+ },
157
+ sortable: true,
158
+ width: 180
159
+ }
160
+ ],
161
+ rows: {
162
+ selectable: {
163
+ multiple: false
164
+ },
165
+ handlers: {
166
+ click: ((columns, data, column, record, rowIndex, target, e) =>
167
+ console.log('row - clicked')) as GristEventHandler,
168
+ dblclick: ((columns, data, column, record, rowIndex, target, e) =>
169
+ console.log('row - dblclicked')) as GristEventHandler,
170
+ contextmenu: ((columns, data, column, record, rowIndex, target, e) =>
171
+ console.log('row - contextmenued')) as GristEventHandler,
172
+ focus: ((columns, data, column, record, rowIndex, target, e) => console.log('row - focused')) as GristEventHandler
173
+ },
174
+ accumulator: true
175
+ },
176
+ sorters: [
177
+ {
178
+ name: 'name',
179
+ desc: true
180
+ }
181
+ ],
182
+ pagination: {
183
+ pages: [20, 30, 50, 100, 200]
184
+ }
185
+ }
186
+
187
+ export default {
188
+ title: 'click events for custom popup in ox-grist',
189
+ component: 'ox-grist',
190
+ argTypes: {
191
+ config: { control: 'object' },
192
+ mode: { control: 'select', options: ['GRID', 'LIST', 'CARD'] },
193
+ urlParamsSensitive: { control: 'boolean' },
194
+ withoutSearch: { control: 'boolean' },
195
+ preventCloseOnBlur: { control: 'boolean' }
196
+ }
197
+ }
198
+
199
+ interface Story<T> {
200
+ (args: T): TemplateResult
201
+ args?: Partial<T>
202
+ argTypes?: Record<string, unknown>
203
+ }
204
+
205
+ interface ArgTypes {
206
+ config: object
207
+ mode: 'GRID' | 'LIST' | 'CARD'
208
+ urlParamsSensitive: boolean
209
+ withoutSearch: boolean
210
+ preventCloseOnBlur: boolean
211
+ fetchHandler: FetchHandler
212
+ }
213
+
214
+ const Template: Story<ArgTypes> = ({
215
+ config,
216
+ mode = 'GRID',
217
+ urlParamsSensitive = false,
218
+ withoutSearch = false,
219
+ preventCloseOnBlur = false,
220
+ fetchHandler
221
+ }: ArgTypes) =>
222
+ html` <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
223
+
224
+ <link href="/themes/light.css" rel="stylesheet" />
225
+ <link href="/themes/dark.css" rel="stylesheet" />
226
+ <link href="/themes/spacing.css" rel="stylesheet" />
227
+ <link href="/themes/grist-theme.css" rel="stylesheet" />
228
+
229
+ <link
230
+ href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
231
+ rel="stylesheet"
232
+ />
233
+ <link
234
+ href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL@20..48,100..700,0..1"
235
+ rel="stylesheet"
236
+ />
237
+ <link
238
+ href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL@20..48,100..700,0..1"
239
+ rel="stylesheet"
240
+ />
241
+
242
+ <style>
243
+ ${MDTypeScaleStyles.cssText}
244
+ </style>
245
+
246
+ <style>
247
+ ${CommonGristStyles.cssText}
248
+ ${CommonHeaderStyles.cssText}
249
+ </style>
250
+
251
+ <style>
252
+ ox-grist {
253
+ height: 600px;
254
+ }
255
+
256
+ ox-filters-form {
257
+ flex: 1;
258
+ }
259
+ </style>
260
+
261
+ <ox-grist
262
+ mode=${mode}
263
+ .config=${config}
264
+ .fetchHandler=${fetchHandler}
265
+ ?url-params-sensitive=${urlParamsSensitive}
266
+ @filters-change=${(e: Event) => console.log('filters', (e.target as any).filters)}
267
+ >
268
+ <div slot="headroom" class="header">
269
+ <div class="filters">
270
+ <ox-filters-form ?without-search=${withoutSearch} autofocus></ox-filters-form>
271
+ <ox-record-creator id="add" light-popup ?prevent-close-on-blur=${preventCloseOnBlur}>
272
+ <button><md-icon>add</md-icon></button>
273
+ <div slot="popup">
274
+ <label>Test</label>
275
+ <input />
276
+ </div>
277
+ </ox-record-creator>
278
+ </div>
279
+ </div>
280
+ </ox-grist>`
281
+
282
+ export const Regular = Template.bind({})
283
+ Regular.args = {
284
+ config,
285
+ fetchHandler,
286
+ mode: 'GRID'
287
+ }
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -6,7 +6,7 @@ import { sleep } from '@operato/utils'
6
6
  import '../src/index.js'
7
7
  import '../src/filters/filters-form.js'
8
8
  import '../src/sorters/sorters-control.js'
9
- import '../src/record-view/record-creator.js'
9
+ import '../src/record-view/ox-record-creator.js'
10
10
  import '../src/personalizer/ox-grist-personalizer.js'
11
11
  import '../src/personalizer/ox-grist-filter-personalizer.js'
12
12
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1,7 +1,7 @@
1
1
  import '../src/index.js'
2
2
  import '../src/filters/filters-form.js'
3
3
  import '../src/sorters/sorters-control.js'
4
- import '../src/record-view/record-creator.js'
4
+ import '../src/record-view/ox-record-creator.js'
5
5
  import '@operato/popup/ox-popup-list.js'
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"record-creator.js","sourceRoot":"","sources":["../../../src/record-view/record-creator.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport './record-view'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { OxPopup } from '@operato/popup'\n\nimport { DataGrist } from '../data-grist'\nimport { ColumnConfig, GristRecord, ValidationReason } from '../types'\nimport { RecordView } from './record-view'\n\n@customElement('ox-record-creator')\nexport class RecordCreator extends LitElement {\n @state() grist?: DataGrist\n\n @property({ type: Object }) callback?: (operation: { [key: string]: any }) => boolean\n @property({ type: Boolean, attribute: 'light-popup' }) lightPopup: boolean = false\n @property({ type: Boolean, attribute: 'prevent-close-on-blur' }) preventCloseOnBlur = false\n\n constructor() {\n super()\n\n this.addEventListener('click', (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n\n if (this.lightPopup) {\n this.lightPopupRecordView()\n } else {\n this.popupRecordView()\n }\n })\n }\n\n connectedCallback(): void {\n super.connectedCallback()\n\n this.grist = this.closest('ox-grist') as DataGrist\n }\n\n render() {\n return html`<slot></slot>`\n }\n\n validateRecord(record: GristRecord): { field: string; reason: ValidationReason }[] {\n const columns = this.grist!.compiledConfig.columns;\n const invalidFields: { field: string; reason: ValidationReason }[] = [];\n\n columns.forEach(column => {\n if (column.record?.mandatory && (record[column.name] === undefined || record[column.name] === null || record[column.name] === '')) {\n invalidFields.push({\n field: column.name,\n reason: ValidationReason.MANDATORY\n });\n }\n // 여기에 추가적인 유효성 검사 규칙을 구현할 수 있습니다.\n });\n\n return invalidFields\n }\n\n lightPopupRecordView() {\n const config = this.grist!.compiledConfig\n var title = 'create'\n const rowIndex = -1\n var record: GristRecord = {}\n const columns = config.columns\n\n var popup = OxPopup.open({\n template: html`\n <div title>${title}</div>\n <ox-record-view\n @field-change=${(e: CustomEvent) => {\n const view = e.currentTarget as RecordView\n\n var { after, before, column, record, row } = (e as CustomEvent).detail as {\n after: any\n before: any\n column: ColumnConfig\n record: GristRecord\n row: number\n }\n\n var validation = column.validation\n if (validation && typeof validation == 'function') {\n if (!validation.call(this, after, before, record, column)) {\n return\n }\n }\n\n view.record = {\n ...record,\n [column.name]: after\n }\n }}\n .columns=${columns}\n .record=${record}\n .rowIndex=${rowIndex}\n @reset=${(e: Event) => {\n const view = e.currentTarget as RecordView\n view.record = {}\n }}\n @cancel=${(e: Event) => {\n popup.close()\n }}\n @ok=${async (e: Event) => {\n const view = e.currentTarget as RecordView\n\n // 레코드 밸리데이션 체크\n const invalidFields = await this.validateRecord(view.record);\n if (invalidFields.length > 0) {\n // const firstInvalidField = invalidFields[0];\n // if (firstInvalidField) {\n // view.setFocus(firstInvalidField.field)\n // }\n view.setFocusOnInvalid(invalidFields);\n return false;\n }\n\n popup.close()\n\n this.dispatchEvent(\n new CustomEvent('ok', {\n bubbles: true,\n composed: true,\n detail: view.record\n })\n )\n }}\n ></ox-record-view>\n `,\n parent: document.body,\n preventCloseOnBlur: this.preventCloseOnBlur\n })\n }\n\n popupRecordView() {\n const config = this.grist!.compiledConfig\n const rowIndex = -1\n var record: GristRecord = {}\n const columns = config.columns\n\n var title = 'create'\n\n var recordView = document.createElement('ox-record-view') as RecordView\n\n recordView.columns = columns\n recordView.record = record\n recordView.rowIndex = rowIndex\n\n document.dispatchEvent(\n new CustomEvent('open-popup', {\n detail: {\n template: recordView,\n options: {\n backdrop: true,\n size: 'large',\n title\n },\n callback: (popup: any) => {\n recordView.addEventListener('reset', (e: Event) => {\n const view = e.currentTarget as RecordView\n view.record = {}\n })\n\n recordView.addEventListener('cancel', (e: Event) => {\n popup.close()\n })\n\n recordView.addEventListener('ok', async (e: Event) => {\n const view = e.currentTarget as RecordView\n\n // 레코드 밸리데이션 체크\n const invalidFields = await this.validateRecord(view.record);\n if (invalidFields.length > 0) {\n const firstInvalidField = invalidFields[0];\n if (firstInvalidField) {\n const fieldElement = view.renderRoot?.querySelector(`[name=\"${firstInvalidField}\"]`);\n if (fieldElement) {\n (fieldElement as HTMLElement).focus();\n }\n }\n return false;\n }\n \n if (await this.callback?.(view.record)) {\n popup.close()\n } else {\n // 밸리데이션 실패 시 처리\n console.error('레코드 밸리데이션 실패');\n // 여기에 사용자에게 오류 메시지를 표시하는 로직을 추가할 수 있습니다.\n }\n })\n\n recordView.addEventListener('field-change', async (e: Event) => {\n const view = e.currentTarget as RecordView\n\n var { after, before, column, record, row } = (e as CustomEvent).detail as {\n after: any\n before: any\n column: ColumnConfig\n record: GristRecord\n row: number\n }\n\n var validation = column.validation\n if (validation && typeof validation == 'function') {\n if (!(await validation.call(this, after, before, record, column))) {\n return\n }\n }\n\n view.record = {\n ...record,\n [column.name]: after\n }\n })\n\n popup.onclosed = () => {}\n }\n }\n })\n )\n }\n}\n"]}