@things-factory/reference-app 5.0.0-zeta.8 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/client/bootstrap.js +21 -11
  2. package/client/components/ocr-viewpart.js +1 -1
  3. package/client/editors/id-editor.js +1 -1
  4. package/client/editors/id-selector.js +1 -1
  5. package/client/menu.js +10 -5
  6. package/client/pages/data-entry/data-entry-form.js +117 -0
  7. package/client/pages/data-entry/data-entry-generator-popup.js +110 -0
  8. package/client/pages/data-set/data-item-list.js +277 -0
  9. package/client/pages/data-set/data-set-importer.js +103 -0
  10. package/client/pages/data-set/data-set-list-page.js +738 -0
  11. package/client/pages/ocr-page.js +1 -1
  12. package/client/pages/operation/operation-api.js +85 -0
  13. package/client/pages/operation/operation-master.js +432 -0
  14. package/client/pages/pending-job-page.js +1 -1
  15. package/client/pages/product/product-api.js +150 -0
  16. package/client/pages/product/product-master.js +888 -0
  17. package/client/pages/product-combination-settings-popup.js +395 -0
  18. package/client/pages/product-combinations-popup.js +372 -0
  19. package/client/pages/product-details-popup.js +744 -0
  20. package/client/pages/upload-page.js +1 -1
  21. package/client/route.js +12 -0
  22. package/config/config.development.js +1 -1
  23. package/config.development.js +21 -0
  24. package/db.sqlite +0 -0
  25. package/dist-server/constants/index.js +18 -0
  26. package/dist-server/constants/index.js.map +1 -0
  27. package/dist-server/constants/type-constants.js +26 -0
  28. package/dist-server/constants/type-constants.js.map +1 -0
  29. package/dist-server/controllers/create-data-sample-mockup.js +236 -0
  30. package/dist-server/controllers/create-data-sample-mockup.js.map +1 -0
  31. package/dist-server/controllers/index.js +17 -0
  32. package/dist-server/controllers/index.js.map +1 -1
  33. package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js +40 -0
  34. package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js.map +1 -0
  35. package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js +28 -0
  36. package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js.map +1 -0
  37. package/dist-server/service/data-sample-mockup/index.js +7 -0
  38. package/dist-server/service/data-sample-mockup/index.js.map +1 -0
  39. package/dist-server/service/index.js +5 -2
  40. package/dist-server/service/index.js.map +1 -1
  41. package/dist-server/service/reference/reference-mutation.js +6 -3
  42. package/dist-server/service/reference/reference-mutation.js.map +1 -1
  43. package/dist-server/service/reference/reference-query.js +7 -4
  44. package/dist-server/service/reference/reference-query.js.map +1 -1
  45. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +4 -14
  46. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +19 -69
  47. package/logs/application-2022-07-22-10.log +26 -0
  48. package/logs/connections-2022-07-12-00.log +0 -0
  49. package/logs/connections-2022-07-14-14.log +0 -0
  50. package/logs/connections-2022-07-14-15.log +0 -0
  51. package/logs/connections-2022-07-14-16.log +0 -0
  52. package/logs/connections-2022-07-14-17.log +0 -0
  53. package/logs/connections-2022-07-22-10.log +0 -0
  54. package/package.json +58 -56
  55. package/server/constants/index.ts +1 -0
  56. package/server/constants/type-constants.ts +24 -0
  57. package/server/controllers/create-data-sample-mockup.ts +268 -0
  58. package/server/controllers/index.ts +1 -0
  59. package/server/service/data-sample-mockup/data-sample-mockup-mutation.ts +18 -0
  60. package/server/service/data-sample-mockup/data-sample-mockup-type.ts +10 -0
  61. package/server/service/data-sample-mockup/index.ts +4 -0
  62. package/server/service/index.ts +5 -2
  63. package/server/service/reference/reference-mutation.ts +5 -3
  64. package/server/service/reference/reference-query.ts +8 -7
  65. package/things-factory.config.js +8 -0
  66. package/translations/en.json +6 -1
  67. package/translations/ko.json +7 -1
@@ -0,0 +1,738 @@
1
+ import '@operato/data-grist'
2
+ import './data-item-list.js'
3
+ import './data-set-importer.js'
4
+ import '../data-entry/data-entry-form.js'
5
+
6
+ import gql from 'graphql-tag'
7
+ import { css, html } from 'lit'
8
+ import moment from 'moment-timezone'
9
+ import { connect } from 'pwa-helpers/connect-mixin'
10
+
11
+ import { getEditor, getRenderer } from '@operato/data-grist'
12
+ import { OxDataUseCase } from '@operato/dataset'
13
+ import { client } from '@operato/graphql'
14
+ import { i18next, localize } from '@operato/i18n'
15
+ import { notify, openPopup } from '@operato/layout'
16
+ import { PageView, store } from '@operato/shell'
17
+ import { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
18
+ import { isMobileDevice } from '@operato/utils'
19
+
20
+ const DEFAULT_TZ = Intl.DateTimeFormat().resolvedOptions().timeZone
21
+ const TIMEZONE_OPTIONS = ['', DEFAULT_TZ, ...moment.tz.names().filter(tz => tz !== DEFAULT_TZ)]
22
+
23
+ const ENTRY_TYPES = [
24
+ {
25
+ display: '',
26
+ value: ''
27
+ },
28
+ {
29
+ display: 'Generated',
30
+ value: 'generated'
31
+ },
32
+ {
33
+ display: 'Board',
34
+ value: 'board'
35
+ },
36
+ {
37
+ display: 'Page',
38
+ value: 'page'
39
+ },
40
+ {
41
+ display: 'External URL',
42
+ value: 'external'
43
+ }
44
+ ]
45
+
46
+ const MONITOR_TYPES = [
47
+ {
48
+ display: '',
49
+ value: ''
50
+ },
51
+ {
52
+ display: 'Generated',
53
+ value: 'generated'
54
+ },
55
+ {
56
+ display: 'Board',
57
+ value: 'board'
58
+ },
59
+ {
60
+ display: 'Page',
61
+ value: 'page'
62
+ },
63
+ {
64
+ display: 'External URL',
65
+ value: 'external'
66
+ }
67
+ ]
68
+
69
+ const REPORT_TYPES = [
70
+ {
71
+ display: '',
72
+ value: ''
73
+ },
74
+ {
75
+ display: 'Generated',
76
+ value: 'generated'
77
+ },
78
+ {
79
+ display: 'Embed',
80
+ value: 'embed'
81
+ },
82
+ {
83
+ display: 'Page',
84
+ value: 'page'
85
+ },
86
+ {
87
+ display: 'External URL',
88
+ value: 'external'
89
+ }
90
+ ]
91
+
92
+ const USECASE_OPTIONS = () => {
93
+ return ['', ...OxDataUseCase.getUseCaseNames()].map(name => {
94
+ return {
95
+ display: name,
96
+ value: name
97
+ }
98
+ })
99
+ }
100
+ export class DataSetListPage extends connect(store)(localize(i18next)(PageView)) {
101
+ static get properties() {
102
+ return {
103
+ gristConfig: Object,
104
+ mode: String
105
+ }
106
+ }
107
+
108
+ static get styles() {
109
+ return [
110
+ ScrollbarStyles,
111
+ CommonGristStyles,
112
+ css`
113
+ :host {
114
+ display: flex;
115
+
116
+ width: 100%;
117
+
118
+ --grid-record-emphasized-background-color: red;
119
+ --grid-record-emphasized-color: yellow;
120
+ }
121
+ `
122
+ ]
123
+ }
124
+
125
+ get context() {
126
+ return {
127
+ title: i18next.t('title.data-set list'),
128
+ help: 'dataset/data-set',
129
+ actions: [
130
+ {
131
+ title: i18next.t('button.copy'),
132
+ action: this._copyDataSet.bind(this),
133
+ ...CommonButtonStyles.copy
134
+ },
135
+ {
136
+ title: i18next.t('button.save'),
137
+ action: this._updateDataSet.bind(this),
138
+ ...CommonButtonStyles.save
139
+ },
140
+ {
141
+ title: i18next.t('button.delete'),
142
+ action: this._deleteDataSet.bind(this),
143
+ ...CommonButtonStyles.delete
144
+ }
145
+ ],
146
+ exportable: {
147
+ name: i18next.t('title.data-set list'),
148
+ data: this.exportHandler.bind(this)
149
+ },
150
+ importable: {
151
+ handler: this.importHandler.bind(this)
152
+ }
153
+ }
154
+ }
155
+
156
+ render() {
157
+ const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
158
+
159
+ return html`
160
+ <ox-grist
161
+ .mode=${mode}
162
+ .config=${this.gristConfig}
163
+ .fetchHandler=${this.fetchHandler.bind(this)}
164
+ ?url-params-sensitive=${this.active}
165
+ >
166
+ <div slot="headroom">
167
+ <div id="filters">
168
+ <ox-filters-form autofocus></ox-filters-form>
169
+ </div>
170
+
171
+ <div id="sorters">
172
+ Sort
173
+ <mwc-icon
174
+ @click=${e => {
175
+ const target = e.currentTarget
176
+ this.renderRoot.querySelector('#sorter-control').open({
177
+ right: 0,
178
+ top: target.offsetTop + target.offsetHeight
179
+ })
180
+ }}
181
+ >expand_more</mwc-icon
182
+ >
183
+ <ox-popup id="sorter-control">
184
+ <ox-sorters-control> </ox-sorters-control>
185
+ </ox-popup>
186
+ </div>
187
+
188
+ <div id="modes">
189
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
190
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</mwc-icon>
191
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
192
+ </div>
193
+ </div>
194
+ </ox-grist>
195
+ `
196
+ }
197
+
198
+ get grist() {
199
+ return this.renderRoot.querySelector('ox-grist')
200
+ }
201
+
202
+ async pageInitialized(lifecycle) {
203
+ this.gristConfig = {
204
+ list: {
205
+ fields: ['name', 'description'],
206
+ details: ['schedule', 'active']
207
+ },
208
+ columns: [
209
+ { type: 'gutter', gutterName: 'sequence' },
210
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
211
+ {
212
+ type: 'gutter',
213
+ gutterName: 'button',
214
+ icon: 'reorder',
215
+ handlers: {
216
+ click: (columns, data, column, record, rowIndex) => {
217
+ if (!record.id) return
218
+ const popup = openPopup(html` <data-item-list .dataSet=${record}></data-item-list> `, {
219
+ backdrop: true,
220
+ help: 'data-set/ui/data-item-list',
221
+ size: 'large',
222
+ title: i18next.t('title.data-item list')
223
+ })
224
+ popup.onclosed = () => {
225
+ this.grist.fetch()
226
+ }
227
+ }
228
+ }
229
+ },
230
+ {
231
+ type: 'gutter',
232
+ gutterName: 'button',
233
+ icon: 'fact_check',
234
+ handlers: {
235
+ click: (columns, data, column, record, rowIndex) => {
236
+ openPopup(
237
+ html` <data-entry-form .dataSet=${record} style="background-color: white;"></data-entry-form> `,
238
+ {
239
+ backdrop: true,
240
+ size: 'large',
241
+ title: i18next.t('title.data-entry-form')
242
+ }
243
+ )
244
+ }
245
+ }
246
+ },
247
+ {
248
+ type: 'string',
249
+ name: 'name',
250
+ header: i18next.t('field.name'),
251
+ record: {
252
+ editable: true
253
+ },
254
+ filter: 'search',
255
+ sortable: true,
256
+ width: 150,
257
+ imex: {
258
+ width: 25,
259
+ header: i18next.t('field.name'),
260
+ type: 'string',
261
+ key: 'name'
262
+ }
263
+ },
264
+ {
265
+ type: 'string',
266
+ name: 'description',
267
+ header: i18next.t('field.description'),
268
+ record: {
269
+ editable: true
270
+ },
271
+ filter: 'search',
272
+ width: 200,
273
+ imex: {
274
+ width: 33,
275
+ header: i18next.t('field.description'),
276
+ type: 'string',
277
+ key: 'description'
278
+ }
279
+ },
280
+ {
281
+ type: 'checkbox',
282
+ name: 'active',
283
+ label: true,
284
+ header: i18next.t('field.active'),
285
+ record: {
286
+ editable: true
287
+ },
288
+ filter: true,
289
+ sortable: true,
290
+ width: 60,
291
+ imex: {
292
+ width: 10,
293
+ header: i18next.t('field.active'),
294
+ type: 'checkbox',
295
+ key: 'active'
296
+ }
297
+ },
298
+ {
299
+ type: 'select',
300
+ name: 'type',
301
+ label: true,
302
+ header: i18next.t('field.type'),
303
+ record: {
304
+ editable: true,
305
+ options: [
306
+ {},
307
+ {
308
+ display: i18next.t('text.manually collected'),
309
+ value: 'manual'
310
+ },
311
+ {
312
+ display: i18next.t('text.automatically collected'),
313
+ value: 'automatic'
314
+ }
315
+ ]
316
+ },
317
+ sortable: true,
318
+ filter: true,
319
+ width: 60,
320
+ imex: {
321
+ width: 10,
322
+ header: i18next.t('field.type'),
323
+ type: 'select',
324
+ key: 'type'
325
+ }
326
+ },
327
+ {
328
+ type: 'select',
329
+ name: 'useCase',
330
+ label: true,
331
+ header: i18next.t('field.use-case'),
332
+ record: {
333
+ editable: true,
334
+ options: USECASE_OPTIONS
335
+ },
336
+ sortable: true,
337
+ filter: true,
338
+ width: 80
339
+ },
340
+ {
341
+ type: 'partition-keys',
342
+ name: 'partitionKeys',
343
+ header: i18next.t('field.partition-keys'),
344
+ record: {
345
+ editable: true,
346
+ options: {
347
+ objectified: true /* transfered as a object type */
348
+ }
349
+ },
350
+ width: 200
351
+ },
352
+ {
353
+ type: 'crontab',
354
+ name: 'schedule',
355
+ label: true,
356
+ header: i18next.t('field.schedule'),
357
+ record: {
358
+ editable: true,
359
+ options: {
360
+ objectified: true
361
+ }
362
+ },
363
+ width: 80,
364
+ label: true,
365
+ imex: {
366
+ width: 13,
367
+ header: i18next.t('field.schedule'),
368
+ type: 'string',
369
+ key: 'schedule'
370
+ }
371
+ },
372
+ {
373
+ type: 'select',
374
+ name: 'timezone',
375
+ header: i18next.t('field.timezone'),
376
+ record: {
377
+ editable: true,
378
+ options: TIMEZONE_OPTIONS
379
+ },
380
+ width: 120,
381
+ imex: {
382
+ width: 13,
383
+ header: i18next.t('field.timezone'),
384
+ type: 'select',
385
+ key: 'timezone'
386
+ }
387
+ },
388
+ {
389
+ type: 'resource-object',
390
+ name: 'supervisoryRole',
391
+ header: i18next.t('field.supervisory-role'),
392
+ record: {
393
+ editable: true,
394
+ options: {
395
+ queryName: 'roles'
396
+ }
397
+ },
398
+ sortable: true,
399
+ filter: 'like',
400
+ width: 120
401
+ },
402
+ {
403
+ type: 'resource-object',
404
+ name: 'entryRole',
405
+ header: i18next.t('field.entry-role'),
406
+ record: {
407
+ editable: true,
408
+ options: {
409
+ queryName: 'roles'
410
+ }
411
+ },
412
+ sortable: true,
413
+ width: 120
414
+ },
415
+ {
416
+ type: 'select',
417
+ name: 'entryType',
418
+ label: true,
419
+ header: i18next.t('field.entry-type'),
420
+ record: {
421
+ editable: true,
422
+ options: ENTRY_TYPES
423
+ },
424
+ width: 80
425
+ },
426
+ {
427
+ type: 'string',
428
+ name: 'entryView',
429
+ header: i18next.t('field.entry-view'),
430
+ record: {
431
+ editable: true,
432
+ editor: function (value, column, record, rowIndex, field) {
433
+ var type = record.entryType !== 'board' ? 'string' : 'board'
434
+ return getEditor(type)(value, column, record, rowIndex, field)
435
+ },
436
+ renderer: function (value, column, record, rowIndex, field) {
437
+ var type = record.entryType !== 'board' ? 'string' : 'board'
438
+ return getRenderer(type)(value, column, record, rowIndex, field)
439
+ }
440
+ },
441
+ width: 140
442
+ },
443
+ {
444
+ type: 'select',
445
+ name: 'monitorType',
446
+ label: true,
447
+ header: i18next.t('field.monitor-type'),
448
+ record: {
449
+ editable: true,
450
+ options: MONITOR_TYPES
451
+ },
452
+ width: 80
453
+ },
454
+ {
455
+ type: 'string',
456
+ name: 'monitorView',
457
+ header: i18next.t('field.monitor-view'),
458
+ record: {
459
+ editable: true,
460
+ editor: function (value, column, record, rowIndex, field) {
461
+ var type = record.monitorType !== 'board' ? 'string' : 'board'
462
+ return getEditor(type)(value, column, record, rowIndex, field)
463
+ },
464
+ renderer: function (value, column, record, rowIndex, field) {
465
+ var type = record.monitorType !== 'board' ? 'string' : 'board'
466
+ return getRenderer(type)(value, column, record, rowIndex, field)
467
+ }
468
+ },
469
+ width: 140
470
+ },
471
+ {
472
+ type: 'select',
473
+ name: 'reportType',
474
+ label: true,
475
+ header: i18next.t('field.report-type'),
476
+ record: {
477
+ editable: true,
478
+ options: REPORT_TYPES
479
+ },
480
+ width: 80
481
+ },
482
+ {
483
+ type: 'string',
484
+ name: 'reportView',
485
+ header: i18next.t('field.report-view'),
486
+ record: {
487
+ editable: true,
488
+ editor: function (value, column, record, rowIndex, field) {
489
+ var type = record.reportType !== 'custom' ? 'string' : 'script'
490
+ return getEditor(type)(value, column, record, rowIndex, field)
491
+ },
492
+ renderer: function (value, column, record, rowIndex, field) {
493
+ var type = record.reportType !== 'custom' ? 'string' : 'string'
494
+ return getRenderer(type)(value, column, record, rowIndex, field)
495
+ }
496
+ },
497
+ width: 140
498
+ },
499
+ {
500
+ type: 'file',
501
+ name: 'reportTemplate',
502
+ header: i18next.t('field.report-template'),
503
+ record: {
504
+ editable: true
505
+ },
506
+ width: 80
507
+ },
508
+ {
509
+ type: 'resource-object',
510
+ name: 'updater',
511
+ header: i18next.t('field.updater'),
512
+ record: {
513
+ editable: false
514
+ },
515
+ sortable: true,
516
+ width: 120
517
+ },
518
+ {
519
+ type: 'datetime',
520
+ name: 'updatedAt',
521
+ header: i18next.t('field.updated_at'),
522
+ record: {
523
+ editable: false
524
+ },
525
+ sortable: true,
526
+ width: 180
527
+ }
528
+ ],
529
+ rows: {
530
+ selectable: {
531
+ multiple: true
532
+ }
533
+ },
534
+ sorters: [
535
+ {
536
+ name: 'name'
537
+ }
538
+ ]
539
+ }
540
+ }
541
+
542
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
543
+ const response = await client.query({
544
+ query: gql`
545
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
546
+ responses: dataSets(filters: $filters, pagination: $pagination, sortings: $sortings) {
547
+ items {
548
+ id
549
+ name
550
+ description
551
+ partitionKeys
552
+ active
553
+ type
554
+ useCase
555
+ schedule
556
+ timezone
557
+ entryRole {
558
+ id
559
+ name
560
+ }
561
+ supervisoryRole {
562
+ id
563
+ name
564
+ }
565
+ entryType
566
+ entryView
567
+ monitorType
568
+ monitorView
569
+ reportType
570
+ reportView
571
+ reportTemplate
572
+ updater {
573
+ id
574
+ name
575
+ }
576
+ updatedAt
577
+ dataItems {
578
+ name
579
+ description
580
+ active
581
+ tag
582
+ type
583
+ unit
584
+ options
585
+ quota
586
+ spec
587
+ }
588
+ }
589
+ total
590
+ }
591
+ }
592
+ `,
593
+ variables: {
594
+ filters,
595
+ pagination: { page, limit },
596
+ sortings
597
+ }
598
+ })
599
+
600
+ return {
601
+ total: response.data.responses.total || 0,
602
+ records: response.data.responses.items || []
603
+ }
604
+ }
605
+
606
+ async _deleteDataSet() {
607
+ if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
608
+ const ids = this.grist.selected.map(record => record.id)
609
+ if (ids && ids.length > 0) {
610
+ const response = await client.mutate({
611
+ mutation: gql`
612
+ mutation ($ids: [String!]!) {
613
+ deleteDataSets(ids: $ids)
614
+ }
615
+ `,
616
+ variables: {
617
+ ids
618
+ }
619
+ })
620
+
621
+ if (!response.errors) {
622
+ this.grist.fetch()
623
+ notify({
624
+ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
625
+ })
626
+ }
627
+ }
628
+ }
629
+ }
630
+
631
+ async _copyDataSet() {
632
+ var selected = this.grist.selected
633
+ if (selected.length == 0) return
634
+
635
+ if (!confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.copy') }))) return
636
+ var response = await client.mutate({
637
+ mutation: gql`
638
+ mutation ($ids: [String!]!) {
639
+ copyDataSets(ids: $ids) {
640
+ id
641
+ }
642
+ }
643
+ `,
644
+ variables: {
645
+ ids: selected.map(r => r.id)
646
+ }
647
+ })
648
+
649
+ if (!response.errors) {
650
+ this.grist.fetch()
651
+ }
652
+ }
653
+
654
+ async _updateDataSet() {
655
+ let patches = this.grist.dirtyRecords
656
+ if (patches && patches.length) {
657
+ patches = patches.map(patch => {
658
+ let patchField = patch.id ? { id: patch.id } : {}
659
+ const dirtyFields = patch.__dirtyfields__
660
+ for (let key in dirtyFields) {
661
+ patchField[key] = dirtyFields[key].after
662
+ }
663
+ if (patchField['reportTemplate'] instanceof FileList) {
664
+ patchField['reportTemplate'] = patchField['reportTemplate'][0]
665
+ }
666
+ patchField.cuFlag = patch.__dirty__
667
+
668
+ return patchField
669
+ })
670
+
671
+ const response = await client.mutate({
672
+ mutation: gql`
673
+ mutation ($patches: [DataSetPatch!]!) {
674
+ updateMultipleDataSet(patches: $patches) {
675
+ name
676
+ }
677
+ }
678
+ `,
679
+ variables: {
680
+ patches
681
+ },
682
+ context: {
683
+ hasUpload: true
684
+ }
685
+ })
686
+
687
+ if (!response.errors) {
688
+ this.grist.fetch()
689
+ }
690
+ }
691
+ }
692
+
693
+ async exportHandler() {
694
+ var headerSetting = this.grist._config.columns
695
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
696
+ .map(column => {
697
+ return column.imex
698
+ })
699
+
700
+ let records = this.grist.data.records
701
+
702
+ var data = records.map(item => {
703
+ return {
704
+ id: item.id,
705
+ ...this.grist._config.columns
706
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
707
+ .reduce((record, column) => {
708
+ record[column.imex.key] = column.imex.key
709
+ .split('.')
710
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
711
+ return record
712
+ }, {})
713
+ }
714
+ })
715
+ return { header: headerSetting, data: data }
716
+ }
717
+
718
+ async importHandler(records) {
719
+ openPopup(
720
+ html`
721
+ <data-set-importer
722
+ .dataSets=${records}
723
+ @imported=${() => {
724
+ history.back()
725
+ this.grist.fetch()
726
+ }}
727
+ ></data-set-importer>
728
+ `,
729
+ {
730
+ backdrop: true,
731
+ size: 'large',
732
+ title: i18next.t('title.import data-set')
733
+ }
734
+ )
735
+ }
736
+ }
737
+
738
+ window.customElements.define('data-set-list-page', DataSetListPage)