@things-factory/dataset 5.0.0-alpha.5 → 5.0.0-alpha.50

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 (107) hide show
  1. package/README.md +9 -0
  2. package/assets/data-samples.jpg +0 -0
  3. package/client/bootstrap.js +21 -1
  4. package/client/pages/{data-entry-form.js → data-entry/data-entry-form.js} +15 -2
  5. package/client/pages/data-entry/data-entry-list-page.js +423 -0
  6. package/client/pages/data-ooc/data-ooc-list-page.js +483 -0
  7. package/client/pages/data-ooc/data-ooc-view.js +183 -0
  8. package/client/pages/data-report/data-report-embed-page.js +113 -0
  9. package/client/pages/data-report/data-report-list-page.js +465 -0
  10. package/client/pages/data-report/jasper-report-oocs-page.js +122 -0
  11. package/client/pages/data-report/jasper-report-samples-crosstab-page.js +122 -0
  12. package/client/pages/data-report/jasper-report-samples-page.js +122 -0
  13. package/client/pages/data-sample/data-sample-list-page.js +386 -0
  14. package/client/pages/data-sample/data-sample-view.js +98 -0
  15. package/client/pages/{data-sensor.js → data-sensor/data-sensor-list-page.js} +43 -64
  16. package/client/pages/{data-item-list.js → data-set/data-item-list.js} +37 -12
  17. package/client/pages/{data-set-importer.js → data-set/data-set-importer.js} +0 -0
  18. package/client/pages/data-set/data-set-list-page.js +746 -0
  19. package/client/route.js +34 -6
  20. package/config/config.development.js +13 -0
  21. package/config/config.production.js +1 -0
  22. package/dist-server/controllers/create-data-sample.js +133 -0
  23. package/dist-server/controllers/create-data-sample.js.map +1 -0
  24. package/dist-server/controllers/data-use-case.js +57 -0
  25. package/dist-server/controllers/data-use-case.js.map +1 -0
  26. package/dist-server/controllers/index.js +18 -0
  27. package/dist-server/controllers/index.js.map +1 -1
  28. package/dist-server/controllers/jasper-report.js +156 -0
  29. package/dist-server/controllers/jasper-report.js.map +1 -0
  30. package/dist-server/index.js +1 -0
  31. package/dist-server/index.js.map +1 -1
  32. package/dist-server/routes.js +13 -24
  33. package/dist-server/routes.js.map +1 -1
  34. package/dist-server/service/data-item/data-item-mutation.js +5 -1
  35. package/dist-server/service/data-item/data-item-mutation.js.map +1 -1
  36. package/dist-server/service/data-item/data-item-query.js +7 -2
  37. package/dist-server/service/data-item/data-item-query.js.map +1 -1
  38. package/dist-server/service/data-item/data-item-type.js +15 -7
  39. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  40. package/dist-server/service/data-item/data-item.js +17 -3
  41. package/dist-server/service/data-item/data-item.js.map +1 -1
  42. package/dist-server/service/data-ooc/data-ooc-mutation.js +92 -0
  43. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
  44. package/dist-server/service/data-ooc/data-ooc-query.js +120 -0
  45. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
  46. package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
  47. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
  48. package/dist-server/service/data-ooc/data-ooc-type.js +107 -0
  49. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
  50. package/dist-server/service/data-ooc/data-ooc.js +237 -0
  51. package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
  52. package/dist-server/service/data-ooc/index.js +10 -0
  53. package/dist-server/service/data-ooc/index.js.map +1 -0
  54. package/dist-server/service/data-sample/data-sample-mutation.js +2 -138
  55. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  56. package/dist-server/service/data-sample/data-sample-query.js +7 -2
  57. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  58. package/dist-server/service/data-sample/data-sample-type.js +12 -42
  59. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  60. package/dist-server/service/data-sample/data-sample.js +34 -3
  61. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  62. package/dist-server/service/data-sensor/data-sensor-query.js +7 -2
  63. package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -1
  64. package/dist-server/service/data-set/data-set-mutation.js +40 -14
  65. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  66. package/dist-server/service/data-set/data-set-query.js +185 -3
  67. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  68. package/dist-server/service/data-set/data-set-type.js +84 -3
  69. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  70. package/dist-server/service/data-set/data-set.js +110 -15
  71. package/dist-server/service/data-set/data-set.js.map +1 -1
  72. package/dist-server/service/index.js +6 -2
  73. package/dist-server/service/index.js.map +1 -1
  74. package/package.json +19 -13
  75. package/server/controllers/create-data-sample.ts +177 -0
  76. package/server/controllers/data-use-case.ts +85 -0
  77. package/server/controllers/index.ts +2 -0
  78. package/server/controllers/jasper-report.ts +170 -0
  79. package/server/index.ts +1 -0
  80. package/server/routes.ts +21 -31
  81. package/server/service/data-item/data-item-mutation.ts +6 -1
  82. package/server/service/data-item/data-item-query.ts +9 -3
  83. package/server/service/data-item/data-item-type.ts +10 -6
  84. package/server/service/data-item/data-item.ts +15 -4
  85. package/server/service/data-ooc/data-ooc-mutation.ts +150 -0
  86. package/server/service/data-ooc/data-ooc-query.ts +69 -0
  87. package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
  88. package/server/service/data-ooc/data-ooc-type.ts +68 -0
  89. package/server/service/data-ooc/data-ooc.ts +204 -0
  90. package/server/service/data-ooc/index.ts +7 -0
  91. package/server/service/data-sample/data-sample-mutation.ts +3 -172
  92. package/server/service/data-sample/data-sample-query.ts +9 -3
  93. package/server/service/data-sample/data-sample-type.ts +7 -28
  94. package/server/service/data-sample/data-sample.ts +33 -3
  95. package/server/service/data-sensor/data-sensor-query.ts +9 -3
  96. package/server/service/data-set/data-set-mutation.ts +53 -14
  97. package/server/service/data-set/data-set-query.ts +156 -4
  98. package/server/service/data-set/data-set-type.ts +65 -4
  99. package/server/service/data-set/data-set.ts +100 -12
  100. package/server/service/index.ts +6 -2
  101. package/things-factory.config.js +35 -7
  102. package/translations/en.json +46 -3
  103. package/translations/ko.json +45 -3
  104. package/translations/ms.json +44 -3
  105. package/translations/zh.json +44 -3
  106. package/client/pages/data-sample.js +0 -316
  107. package/client/pages/data-set.js +0 -457
@@ -0,0 +1,746 @@
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></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: {
338
+ operator: 'eq',
339
+ options: USECASE_OPTIONS /* in case select options type is a function, filter should have its own options */
340
+ },
341
+ width: 80
342
+ },
343
+ {
344
+ type: 'partition-keys',
345
+ name: 'partitionKeys',
346
+ header: i18next.t('field.partition-keys'),
347
+ record: {
348
+ editable: true,
349
+ options: {
350
+ objectified: true /* transfered as a object type */
351
+ }
352
+ },
353
+ width: 200
354
+ },
355
+ {
356
+ type: 'crontab',
357
+ name: 'schedule',
358
+ label: true,
359
+ header: i18next.t('field.schedule'),
360
+ record: {
361
+ editable: true,
362
+ options: {
363
+ objectified: true
364
+ }
365
+ },
366
+ width: 80,
367
+ label: true,
368
+ imex: {
369
+ width: 13,
370
+ header: i18next.t('field.schedule'),
371
+ type: 'string',
372
+ key: 'schedule'
373
+ }
374
+ },
375
+ {
376
+ type: 'select',
377
+ name: 'timezone',
378
+ header: i18next.t('field.timezone'),
379
+ record: {
380
+ editable: true,
381
+ options: TIMEZONE_OPTIONS
382
+ },
383
+ width: 120,
384
+ imex: {
385
+ width: 13,
386
+ header: i18next.t('field.timezone'),
387
+ type: 'select',
388
+ key: 'timezone'
389
+ }
390
+ },
391
+ {
392
+ type: 'resource-object',
393
+ name: 'supervisoryRole',
394
+ header: i18next.t('field.supervisory-role'),
395
+ record: {
396
+ editable: true,
397
+ options: {
398
+ queryName: 'roles'
399
+ }
400
+ },
401
+ sortable: true,
402
+ filter: 'like',
403
+ width: 120
404
+ },
405
+ {
406
+ type: 'resource-object',
407
+ name: 'entryRole',
408
+ header: i18next.t('field.entry-role'),
409
+ record: {
410
+ editable: true,
411
+ options: {
412
+ queryName: 'roles'
413
+ }
414
+ },
415
+ sortable: true,
416
+ width: 120
417
+ },
418
+ {
419
+ type: 'select',
420
+ name: 'entryType',
421
+ label: true,
422
+ header: i18next.t('field.entry-type'),
423
+ record: {
424
+ editable: true,
425
+ options: ENTRY_TYPES
426
+ },
427
+ width: 80
428
+ },
429
+ {
430
+ type: 'string',
431
+ name: 'entryView',
432
+ header: i18next.t('field.entry-view'),
433
+ record: {
434
+ editable: true,
435
+ editor: function (value, column, record, rowIndex, field) {
436
+ var type = record.entryType !== 'board' ? 'string' : 'board'
437
+ return getEditor(type)(value, column, record, rowIndex, field)
438
+ },
439
+ renderer: function (value, column, record, rowIndex, field) {
440
+ var type = record.entryType !== 'board' ? 'string' : 'board'
441
+ return getRenderer(type)(value, column, record, rowIndex, field)
442
+ }
443
+ },
444
+ width: 140
445
+ },
446
+ {
447
+ type: 'select',
448
+ name: 'monitorType',
449
+ label: true,
450
+ header: i18next.t('field.monitor-type'),
451
+ record: {
452
+ editable: true,
453
+ options: MONITOR_TYPES
454
+ },
455
+ width: 80
456
+ },
457
+ {
458
+ type: 'string',
459
+ name: 'monitorView',
460
+ header: i18next.t('field.monitor-view'),
461
+ record: {
462
+ editable: true,
463
+ editor: function (value, column, record, rowIndex, field) {
464
+ var type = record.monitorType !== 'board' ? 'string' : 'board'
465
+ return getEditor(type)(value, column, record, rowIndex, field)
466
+ },
467
+ renderer: function (value, column, record, rowIndex, field) {
468
+ var type = record.monitorType !== 'board' ? 'string' : 'board'
469
+ return getRenderer(type)(value, column, record, rowIndex, field)
470
+ }
471
+ },
472
+ width: 140
473
+ },
474
+ {
475
+ type: 'select',
476
+ name: 'reportType',
477
+ label: true,
478
+ header: i18next.t('field.report-type'),
479
+ record: {
480
+ editable: true,
481
+ options: REPORT_TYPES
482
+ },
483
+ width: 80
484
+ },
485
+ {
486
+ type: 'string',
487
+ name: 'reportView',
488
+ header: i18next.t('field.report-view'),
489
+ record: {
490
+ editable: true,
491
+ editor: function (value, column, record, rowIndex, field) {
492
+ var type = record.reportType !== 'custom' ? 'string' : 'script'
493
+ return getEditor(type)(value, column, record, rowIndex, field)
494
+ },
495
+ renderer: function (value, column, record, rowIndex, field) {
496
+ var type = record.reportType !== 'custom' ? 'string' : 'string'
497
+ return getRenderer(type)(value, column, record, rowIndex, field)
498
+ }
499
+ },
500
+ width: 140
501
+ },
502
+ {
503
+ type: 'file',
504
+ name: 'reportTemplate',
505
+ header: i18next.t('field.report-template'),
506
+ record: {
507
+ editable: true
508
+ },
509
+ width: 80
510
+ },
511
+ {
512
+ type: 'resource-object',
513
+ name: 'updater',
514
+ header: i18next.t('field.updater'),
515
+ record: {
516
+ editable: false
517
+ },
518
+ sortable: true,
519
+ width: 120
520
+ },
521
+ {
522
+ type: 'datetime',
523
+ name: 'updatedAt',
524
+ header: i18next.t('field.updated_at'),
525
+ record: {
526
+ editable: false
527
+ },
528
+ sortable: true,
529
+ width: 180
530
+ }
531
+ ],
532
+ rows: {
533
+ selectable: {
534
+ multiple: true
535
+ }
536
+ },
537
+ sorters: [
538
+ {
539
+ name: 'name'
540
+ }
541
+ ]
542
+ }
543
+
544
+ await this.updateComplete
545
+
546
+ this.grist.fetch()
547
+ }
548
+
549
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
550
+ const response = await client.query({
551
+ query: gql`
552
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
553
+ responses: dataSets(filters: $filters, pagination: $pagination, sortings: $sortings) {
554
+ items {
555
+ id
556
+ name
557
+ description
558
+ partitionKeys
559
+ active
560
+ type
561
+ useCase
562
+ schedule
563
+ timezone
564
+ entryRole {
565
+ id
566
+ name
567
+ }
568
+ supervisoryRole {
569
+ id
570
+ name
571
+ }
572
+ entryType
573
+ entryView
574
+ monitorType
575
+ monitorView
576
+ reportType
577
+ reportView
578
+ reportTemplate
579
+ updater {
580
+ id
581
+ name
582
+ }
583
+ updatedAt
584
+ dataItems {
585
+ name
586
+ description
587
+ sequence
588
+ active
589
+ tag
590
+ type
591
+ unit
592
+ options
593
+ quota
594
+ spec
595
+ }
596
+ }
597
+ total
598
+ }
599
+ }
600
+ `,
601
+ variables: {
602
+ filters,
603
+ pagination: { page, limit },
604
+ sortings
605
+ }
606
+ })
607
+
608
+ return {
609
+ total: response.data.responses.total || 0,
610
+ records: response.data.responses.items || []
611
+ }
612
+ }
613
+
614
+ async _deleteDataSet() {
615
+ if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
616
+ const ids = this.grist.selected.map(record => record.id)
617
+ if (ids && ids.length > 0) {
618
+ const response = await client.mutate({
619
+ mutation: gql`
620
+ mutation ($ids: [String!]!) {
621
+ deleteDataSets(ids: $ids)
622
+ }
623
+ `,
624
+ variables: {
625
+ ids
626
+ }
627
+ })
628
+
629
+ if (!response.errors) {
630
+ this.grist.fetch()
631
+ notify({
632
+ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
633
+ })
634
+ }
635
+ }
636
+ }
637
+ }
638
+
639
+ async _copyDataSet() {
640
+ var selected = this.grist.selected
641
+ if (selected.length == 0) return
642
+
643
+ if (!confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.copy') }))) return
644
+ var response = await client.mutate({
645
+ mutation: gql`
646
+ mutation ($ids: [String!]!) {
647
+ copyDataSets(ids: $ids) {
648
+ id
649
+ }
650
+ }
651
+ `,
652
+ variables: {
653
+ ids: selected.map(r => r.id)
654
+ }
655
+ })
656
+
657
+ if (!response.errors) {
658
+ this.grist.fetch()
659
+ }
660
+ }
661
+
662
+ async _updateDataSet() {
663
+ let patches = this.grist.dirtyRecords
664
+ if (patches && patches.length) {
665
+ patches = patches.map(patch => {
666
+ let patchField = patch.id ? { id: patch.id } : {}
667
+ const dirtyFields = patch.__dirtyfields__
668
+ for (let key in dirtyFields) {
669
+ patchField[key] = dirtyFields[key].after
670
+ }
671
+ if (patchField['reportTemplate'] instanceof FileList) {
672
+ patchField['reportTemplate'] = patchField['reportTemplate'][0]
673
+ }
674
+ patchField.cuFlag = patch.__dirty__
675
+
676
+ return patchField
677
+ })
678
+
679
+ const response = await client.mutate({
680
+ mutation: gql`
681
+ mutation ($patches: [DataSetPatch!]!) {
682
+ updateMultipleDataSet(patches: $patches) {
683
+ name
684
+ }
685
+ }
686
+ `,
687
+ variables: {
688
+ patches
689
+ },
690
+ context: {
691
+ hasUpload: true
692
+ }
693
+ })
694
+
695
+ if (!response.errors) {
696
+ this.grist.fetch()
697
+ }
698
+ }
699
+ }
700
+
701
+ async exportHandler() {
702
+ var headerSetting = this.grist._config.columns
703
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
704
+ .map(column => {
705
+ return column.imex
706
+ })
707
+
708
+ let records = this.grist.data.records
709
+
710
+ var data = records.map(item => {
711
+ return {
712
+ id: item.id,
713
+ ...this.grist._config.columns
714
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
715
+ .reduce((record, column) => {
716
+ record[column.imex.key] = column.imex.key
717
+ .split('.')
718
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
719
+ return record
720
+ }, {})
721
+ }
722
+ })
723
+ return { header: headerSetting, data: data }
724
+ }
725
+
726
+ async importHandler(records) {
727
+ openPopup(
728
+ html`
729
+ <data-set-importer
730
+ .dataSets=${records}
731
+ @imported=${() => {
732
+ history.back()
733
+ this.grist.fetch()
734
+ }}
735
+ ></data-set-importer>
736
+ `,
737
+ {
738
+ backdrop: true,
739
+ size: 'large',
740
+ title: i18next.t('title.import data-set')
741
+ }
742
+ )
743
+ }
744
+ }
745
+
746
+ window.customElements.define('data-set-list-page', DataSetListPage)