@things-factory/dataset 5.0.2 → 5.0.5

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 (60) hide show
  1. package/client/pages/data-key-set/data-key-item-list.js +196 -0
  2. package/client/pages/data-key-set/data-key-set-importer.js +107 -0
  3. package/client/pages/data-key-set/data-key-set-list-page.js +354 -0
  4. package/client/pages/data-ooc/data-ooc-list-page.js +60 -0
  5. package/client/pages/data-sample/data-sample-list-page.js +55 -16
  6. package/client/pages/data-sample/data-sample-search-page.js +402 -0
  7. package/client/pages/data-sample/data-sample-view.js +48 -33
  8. package/client/pages/data-set/data-set-list-page.js +20 -1
  9. package/client/route.js +9 -1
  10. package/dist-server/controllers/create-data-sample.js +15 -3
  11. package/dist-server/controllers/create-data-sample.js.map +1 -1
  12. package/dist-server/service/data-key-set/data-key-item-type.js +58 -0
  13. package/dist-server/service/data-key-set/data-key-item-type.js.map +1 -0
  14. package/dist-server/service/data-key-set/data-key-set-mutation.js +179 -0
  15. package/dist-server/service/data-key-set/data-key-set-mutation.js.map +1 -0
  16. package/dist-server/service/data-key-set/data-key-set-query.js +110 -0
  17. package/dist-server/service/data-key-set/data-key-set-query.js.map +1 -0
  18. package/dist-server/service/data-key-set/data-key-set-type.js +94 -0
  19. package/dist-server/service/data-key-set/data-key-set-type.js.map +1 -0
  20. package/dist-server/service/data-key-set/data-key-set.js +101 -0
  21. package/dist-server/service/data-key-set/data-key-set.js.map +1 -0
  22. package/dist-server/service/data-key-set/index.js +9 -0
  23. package/dist-server/service/data-key-set/index.js.map +1 -0
  24. package/dist-server/service/data-ooc/data-ooc.js +32 -0
  25. package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
  26. package/dist-server/service/data-sample/data-sample-query.js +29 -1
  27. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  28. package/dist-server/service/data-sample/data-sample.js +42 -0
  29. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  30. package/dist-server/service/data-set/data-item-type.js +1 -1
  31. package/dist-server/service/data-set/data-item-type.js.map +1 -1
  32. package/dist-server/service/data-set/data-set-query.js +14 -0
  33. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  34. package/dist-server/service/data-set/data-set-type.js +14 -6
  35. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  36. package/dist-server/service/data-set/data-set.js +32 -54
  37. package/dist-server/service/data-set/data-set.js.map +1 -1
  38. package/dist-server/service/index.js +4 -1
  39. package/dist-server/service/index.js.map +1 -1
  40. package/package.json +2 -2
  41. package/server/controllers/create-data-sample.ts +19 -12
  42. package/server/service/data-key-set/data-key-item-type.ts +31 -0
  43. package/server/service/data-key-set/data-key-set-mutation.ts +198 -0
  44. package/server/service/data-key-set/data-key-set-query.ts +65 -0
  45. package/server/service/data-key-set/data-key-set-type.ts +57 -0
  46. package/server/service/data-key-set/data-key-set.ts +81 -0
  47. package/server/service/data-key-set/index.ts +6 -0
  48. package/server/service/data-ooc/data-ooc.ts +20 -0
  49. package/server/service/data-sample/data-sample-query.ts +29 -0
  50. package/server/service/data-sample/data-sample.ts +34 -0
  51. package/server/service/data-set/data-item-type.ts +1 -1
  52. package/server/service/data-set/data-set-query.ts +11 -0
  53. package/server/service/data-set/data-set-type.ts +6 -0
  54. package/server/service/data-set/data-set.ts +24 -48
  55. package/server/service/index.ts +4 -1
  56. package/things-factory.config.js +8 -0
  57. package/translations/en.json +11 -0
  58. package/translations/ko.json +11 -0
  59. package/translations/ms.json +12 -1
  60. package/translations/zh.json +11 -0
@@ -217,6 +217,61 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
217
217
  width: 120,
218
218
  imex: true
219
219
  },
220
+ {
221
+ type: 'string',
222
+ name: 'key01',
223
+ header: i18next.t('field.key-01'),
224
+ record: {
225
+ editable: false
226
+ },
227
+ sortable: true,
228
+ width: 120,
229
+ imex: true
230
+ },
231
+ {
232
+ type: 'string',
233
+ name: 'key02',
234
+ header: i18next.t('field.key-02'),
235
+ record: {
236
+ editable: false
237
+ },
238
+ sortable: true,
239
+ width: 120,
240
+ imex: true
241
+ },
242
+ {
243
+ type: 'string',
244
+ name: 'key03',
245
+ header: i18next.t('field.key-03'),
246
+ record: {
247
+ editable: false
248
+ },
249
+ sortable: true,
250
+ width: 120,
251
+ imex: true
252
+ },
253
+ {
254
+ type: 'string',
255
+ name: 'key04',
256
+ header: i18next.t('field.key-04'),
257
+ record: {
258
+ editable: false
259
+ },
260
+ sortable: true,
261
+ width: 120,
262
+ imex: true
263
+ },
264
+ {
265
+ type: 'string',
266
+ name: 'key05',
267
+ header: i18next.t('field.key-05'),
268
+ record: {
269
+ editable: false
270
+ },
271
+ sortable: true,
272
+ width: 120,
273
+ imex: true
274
+ },
220
275
  {
221
276
  type: 'json5',
222
277
  name: 'partitionKeys',
@@ -321,6 +376,11 @@ export class DataOocListPage extends connect(store)(localize(i18next)(PageView))
321
376
  id
322
377
  name
323
378
  }
379
+ key01
380
+ key02
381
+ key03
382
+ key04
383
+ key05
324
384
  partitionKeys
325
385
  dataItems {
326
386
  name
@@ -112,7 +112,9 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
112
112
  handlers: {
113
113
  click: (columns, data, column, record, rowIndex) => {
114
114
  openPopup(
115
- html` <data-sample-view .dataSample=${record} style="background-color: white;"></data-sample-view> `,
115
+ html`
116
+ <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view>
117
+ `,
116
118
  {
117
119
  backdrop: true,
118
120
  size: 'large',
@@ -148,9 +150,53 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
148
150
  imex: true
149
151
  },
150
152
  {
151
- type: 'resource-object',
152
- name: 'dataSet',
153
- header: i18next.t('field.data-set'),
153
+ type: 'string',
154
+ name: 'key01',
155
+ header: i18next.t('field.key-01'),
156
+ record: {
157
+ editable: false
158
+ },
159
+ sortable: true,
160
+ width: 120,
161
+ imex: true
162
+ },
163
+ {
164
+ type: 'string',
165
+ name: 'key02',
166
+ header: i18next.t('field.key-02'),
167
+ record: {
168
+ editable: false
169
+ },
170
+ sortable: true,
171
+ width: 120,
172
+ imex: true
173
+ },
174
+ {
175
+ type: 'string',
176
+ name: 'key03',
177
+ header: i18next.t('field.key-03'),
178
+ record: {
179
+ editable: false
180
+ },
181
+ sortable: true,
182
+ width: 120,
183
+ imex: true
184
+ },
185
+ {
186
+ type: 'string',
187
+ name: 'key04',
188
+ header: i18next.t('field.key-04'),
189
+ record: {
190
+ editable: false
191
+ },
192
+ sortable: true,
193
+ width: 120,
194
+ imex: true
195
+ },
196
+ {
197
+ type: 'string',
198
+ name: 'key05',
199
+ header: i18next.t('field.key-05'),
154
200
  record: {
155
201
  editable: false
156
202
  },
@@ -284,19 +330,12 @@ export class DataSampleListPage extends connect(store)(localize(i18next)(PageVie
284
330
  name
285
331
  description
286
332
  useCase
287
- dataSet {
288
- id
289
- name
290
- description
291
- }
333
+ key01
334
+ key02
335
+ key03
336
+ key04
337
+ key05
292
338
  partitionKeys
293
- dataItems {
294
- name
295
- description
296
- tag
297
- unit
298
- spec
299
- }
300
339
  data
301
340
  rawData
302
341
  ooc
@@ -0,0 +1,402 @@
1
+ import '@operato/data-grist'
2
+ import './data-sample-view.js'
3
+
4
+ import gql from 'graphql-tag'
5
+ import { css, html } from 'lit'
6
+ import { connect } from 'pwa-helpers/connect-mixin'
7
+
8
+ import { client } from '@operato/graphql'
9
+ import { i18next, localize } from '@operato/i18n'
10
+ import { openPopup } from '@operato/layout'
11
+ import { PageView, store } from '@operato/shell'
12
+ import { CommonGristStyles, ScrollbarStyles } from '@operato/styles'
13
+ import { isMobileDevice } from '@operato/utils'
14
+
15
+ export class DataSampleSearchPage extends connect(store)(localize(i18next)(PageView)) {
16
+ static get properties() {
17
+ return {
18
+ dataKeySetId: String,
19
+ dataKeySet: Object,
20
+ active: String,
21
+ gristConfig: Object,
22
+ mode: String
23
+ }
24
+ }
25
+
26
+ static get styles() {
27
+ return [
28
+ ScrollbarStyles,
29
+ CommonGristStyles,
30
+ css`
31
+ :host {
32
+ display: flex;
33
+ flex-direction: column;
34
+
35
+ overflow: hidden;
36
+ }
37
+
38
+ ox-grist {
39
+ overflow-y: auto;
40
+ flex: 1;
41
+ }
42
+ `
43
+ ]
44
+ }
45
+
46
+ get context() {
47
+ return {
48
+ title: i18next.t('title.data-sample search'),
49
+ help: 'dataset/data-sample-search',
50
+ actions: [],
51
+ exportable: {
52
+ name: i18next.t('title.data-sample search'),
53
+ data: this._exportableData.bind(this)
54
+ }
55
+ }
56
+ }
57
+
58
+ render() {
59
+ const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
60
+
61
+ return html`
62
+ <ox-grist
63
+ .mode=${mode}
64
+ .config=${this.gristConfig}
65
+ .fetchHandler=${this.fetchHandler.bind(this)}
66
+ ?url-params-sensitive=${this.active}
67
+ >
68
+ <div slot="headroom">
69
+ <div id="filters">
70
+ <ox-filters-form autofocus></ox-filters-form>
71
+ </div>
72
+
73
+ <div id="sorters">
74
+ Sort
75
+ <mwc-icon
76
+ @click=${e => {
77
+ const target = e.currentTarget
78
+ this.renderRoot.querySelector('#sorter-control').open({
79
+ right: 0,
80
+ top: target.offsetTop + target.offsetHeight
81
+ })
82
+ }}
83
+ >expand_more</mwc-icon
84
+ >
85
+ <ox-popup id="sorter-control">
86
+ <ox-sorters-control> </ox-sorters-control>
87
+ </ox-popup>
88
+ </div>
89
+
90
+ <div id="modes">
91
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
92
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</mwc-icon>
93
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
94
+ </div>
95
+ </div>
96
+ </ox-grist>
97
+ `
98
+ }
99
+
100
+ get grist() {
101
+ return this.renderRoot.querySelector('ox-grist')
102
+ }
103
+
104
+ pageUpdated(changes, lifecycle) {
105
+ if (this.active) {
106
+ this.dataKeySetId = lifecycle.resourceId
107
+ return
108
+ }
109
+ }
110
+
111
+ async updated(changes) {
112
+ if (changes.has('dataKeySetId')) {
113
+ const response = await client.query({
114
+ query: gql`
115
+ query ($id: String!) {
116
+ dataKeySet(id: $id) {
117
+ id
118
+ name
119
+ description
120
+ dataKeyItems {
121
+ name
122
+ description
123
+ dataKey
124
+ tKey
125
+ }
126
+ }
127
+ }
128
+ `,
129
+ variables: {
130
+ id: this.dataKeySetId
131
+ }
132
+ })
133
+
134
+ this.dataKeySet = response.data.dataKeySet
135
+ this.refreshGristConfig()
136
+
137
+ this.grist.fetch()
138
+ }
139
+ }
140
+
141
+ getDataKeyColumns() {
142
+ return (
143
+ this.dataKeySet?.dataKeyItems.map((item, index) => {
144
+ return {
145
+ type: 'string',
146
+ name: `key0${index + 1}`,
147
+ header: i18next.t(item.tKey),
148
+ record: {
149
+ editable: false
150
+ },
151
+ sortable: true,
152
+ filter: 'i_like',
153
+ width: 120,
154
+ imex: true
155
+ }
156
+ }) || []
157
+ )
158
+ }
159
+
160
+ refreshGristConfig() {
161
+ this.gristConfig = {
162
+ list: { fields: ['dataSet', 'data', 'updater', 'updatedAt'] },
163
+ columns: [
164
+ { type: 'gutter', gutterName: 'sequence' },
165
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
166
+ {
167
+ type: 'gutter',
168
+ gutterName: 'button',
169
+ icon: 'assignment',
170
+ handlers: {
171
+ click: (columns, data, column, record, rowIndex) => {
172
+ openPopup(
173
+ html`
174
+ <data-sample-view data-sample-id=${record.id} style="background-color: white;"></data-sample-view>
175
+ `,
176
+ {
177
+ backdrop: true,
178
+ size: 'large',
179
+ title: i18next.t('title.data-sample view')
180
+ }
181
+ )
182
+ }
183
+ }
184
+ },
185
+ {
186
+ type: 'string',
187
+ name: 'name',
188
+ label: true,
189
+ header: i18next.t('field.name'),
190
+ record: {
191
+ editable: false
192
+ },
193
+ filter: 'search',
194
+ sortable: true,
195
+ width: 120,
196
+ imex: true
197
+ },
198
+ {
199
+ type: 'string',
200
+ name: 'description',
201
+ label: true,
202
+ header: i18next.t('field.description'),
203
+ record: {
204
+ editable: false
205
+ },
206
+ filter: 'search',
207
+ width: 150,
208
+ imex: true
209
+ },
210
+ ...this.getDataKeyColumns(),
211
+ {
212
+ type: 'checkbox',
213
+ name: 'ooc',
214
+ header: i18next.t('field.ooc'),
215
+ record: {
216
+ editable: false
217
+ },
218
+ width: 30
219
+ },
220
+ {
221
+ type: 'checkbox',
222
+ name: 'oos',
223
+ header: i18next.t('field.oos'),
224
+ record: {
225
+ editable: false
226
+ },
227
+ width: 30
228
+ },
229
+ {
230
+ type: 'json5',
231
+ name: 'data',
232
+ header: i18next.t('field.data'),
233
+ record: {
234
+ editable: false
235
+ },
236
+ width: 200,
237
+ imex: true
238
+ },
239
+ {
240
+ type: 'string',
241
+ name: 'workDate',
242
+ header: i18next.t('field.work-date'),
243
+ sortable: true,
244
+ width: 80,
245
+ imex: true
246
+ },
247
+ {
248
+ type: 'string',
249
+ name: 'workShift',
250
+ header: i18next.t('field.work-shift'),
251
+ sortable: true,
252
+ width: 40,
253
+ imex: true
254
+ },
255
+ {
256
+ type: 'datetime',
257
+ name: 'collectedAt',
258
+ header: i18next.t('field.collected-at'),
259
+ sortable: true,
260
+ width: 180,
261
+ imex: true
262
+ },
263
+ {
264
+ type: 'resource-object',
265
+ name: 'updater',
266
+ header: i18next.t('field.updater'),
267
+ sortable: true,
268
+ width: 120,
269
+ imex: true
270
+ },
271
+ {
272
+ type: 'datetime',
273
+ name: 'updatedAt',
274
+ header: i18next.t('field.updated_at'),
275
+ sortable: true,
276
+ width: 180,
277
+ imex: true
278
+ }
279
+ ],
280
+ rows: {
281
+ appendable: false,
282
+ selectable: {
283
+ multiple: true
284
+ },
285
+ classifier: function (record, rowIndex) {
286
+ var emphasized
287
+ if (record['oos']) {
288
+ emphasized = ['red']
289
+ } else if (record['ooc']) {
290
+ emphasized = 'orange'
291
+ }
292
+
293
+ return {
294
+ emphasized
295
+ }
296
+ }
297
+ },
298
+ sorters: [
299
+ {
300
+ name: 'collectedAt',
301
+ desc: true
302
+ }
303
+ ]
304
+ }
305
+ }
306
+
307
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
308
+ if (!this.dataKeySetId) {
309
+ return { records: [], total: 0 }
310
+ }
311
+
312
+ const response = await client.query({
313
+ query: gql`
314
+ query ($dataKeySetId: String!, $filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
315
+ responses: dataSamplesByDataKeySet(
316
+ dataKeySetId: $dataKeySetId
317
+ filters: $filters
318
+ pagination: $pagination
319
+ sortings: $sortings
320
+ ) {
321
+ items {
322
+ id
323
+ name
324
+ description
325
+ useCase
326
+ key01
327
+ key02
328
+ key03
329
+ key04
330
+ key05
331
+ data
332
+ ooc
333
+ oos
334
+ judgment
335
+ workDate
336
+ workShift
337
+ updater {
338
+ id
339
+ name
340
+ }
341
+ updatedAt
342
+ collectedAt
343
+ }
344
+ total
345
+ }
346
+ }
347
+ `,
348
+ variables: {
349
+ dataKeySetId: this.dataKeySetId,
350
+ filters,
351
+ pagination: { page, limit },
352
+ sortings
353
+ }
354
+ })
355
+
356
+ return {
357
+ total: response.data.responses.total || 0,
358
+ records: response.data.responses.items || []
359
+ }
360
+ }
361
+
362
+ _exportableData() {
363
+ let records = []
364
+ if (this.grist.selected && this.grist.selected.length > 0) {
365
+ records = this.grist.selected
366
+ } else {
367
+ records = this.grist.data.records
368
+ }
369
+
370
+ var headerSetting = this.grist.compiledConfig.columns
371
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
372
+ .map(column => {
373
+ return column.imex === true
374
+ ? {
375
+ header: column.header.renderer(),
376
+ key: column.name,
377
+ width: column.width,
378
+ type: column.type
379
+ }
380
+ : column.imex
381
+ })
382
+
383
+ var data = records.map(item => {
384
+ return {
385
+ id: item.id,
386
+ ...this.gristConfig.columns
387
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
388
+ .reduce((record, column) => {
389
+ const key = column.imex === true ? column.name : column.imex.key
390
+ record[key] = key
391
+ .split('.')
392
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
393
+ return record
394
+ }, {})
395
+ }
396
+ })
397
+
398
+ return { header: headerSetting, data: data }
399
+ }
400
+ }
401
+
402
+ window.customElements.define('data-sample-search-page', DataSampleSearchPage)
@@ -10,7 +10,10 @@ import { ScrollbarStyles } from '@operato/styles'
10
10
  class DataSampleView extends localize(i18next)(LitElement) {
11
11
  static get properties() {
12
12
  return {
13
- dataSet: Object,
13
+ dataSampleId: {
14
+ type: String,
15
+ attribute: 'data-sample-id'
16
+ },
14
17
  dataSample: Object
15
18
  }
16
19
  }
@@ -42,57 +45,69 @@ class DataSampleView extends localize(i18next)(LitElement) {
42
45
  ]
43
46
  }
44
47
 
45
- get sampleView() {
46
- return this.renderRoot.querySelector('ox-data-sample-view')
47
- }
48
-
49
48
  render() {
50
49
  return html`
51
50
  <div content>
52
- <ox-data-sample-view .dataSet=${this.dataSet} .dataSample=${this.dataSample}></ox-data-sample-view>
51
+ ${this.dataSample ? html`<ox-data-sample-view .dataSample=${this.dataSample}></ox-data-sample-view>` : html``}
53
52
  </div>
54
53
  `
55
54
  }
56
55
 
57
56
  updated(changes) {
58
- if (changes.has('dataSample')) {
59
- this.fetchDataSet()
57
+ if (changes.has('dataSampleId')) {
58
+ this.fetchDataSample()
60
59
  }
61
60
  }
62
61
 
63
- async fetchDataSet() {
64
- const id = this.dataSample?.dataSet?.id
62
+ async fetchDataSample() {
63
+ const id = this.dataSampleId
65
64
 
66
- if (id) {
67
- const response = await client.query({
68
- query: gql`
69
- query ($id: String!) {
70
- dataSet(id: $id) {
65
+ const response = await client.query({
66
+ query: gql`
67
+ query ($id: String!) {
68
+ dataSample(id: $id) {
69
+ id
70
+ name
71
+ description
72
+ useCase
73
+ key01
74
+ key02
75
+ key03
76
+ key04
77
+ key05
78
+ data
79
+ ooc
80
+ oos
81
+ dataSet {
71
82
  id
72
83
  name
73
84
  description
74
- useCase
75
- dataItems {
76
- name
77
- description
78
- active
79
- tag
80
- type
81
- unit
82
- options
83
- quota
84
- spec
85
- }
86
85
  }
86
+ dataItems {
87
+ name
88
+ description
89
+ tag
90
+ unit
91
+ spec
92
+ }
93
+ judgment
94
+ workDate
95
+ workShift
96
+ updater {
97
+ id
98
+ name
99
+ }
100
+ updatedAt
101
+ collectedAt
87
102
  }
88
- `,
89
- variables: {
90
- id: this.dataSample.dataSet.id
91
103
  }
92
- })
104
+ `,
105
+ variables: {
106
+ id
107
+ }
108
+ })
93
109
 
94
- this.dataSet = response.data.dataSet
95
- }
110
+ this.dataSample = response.data.dataSample
96
111
  }
97
112
  }
98
113