@things-factory/dataset 5.0.0-alpha.13 → 5.0.0-alpha.17

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 (75) hide show
  1. package/client/pages/data-entry-form.js +3 -1
  2. package/client/pages/data-ooc.js +450 -0
  3. package/client/pages/data-sample.js +39 -37
  4. package/client/pages/data-sensor.js +1 -1
  5. package/client/pages/data-set.js +61 -0
  6. package/client/route.js +4 -0
  7. package/dist-server/controllers/create-data-sample.js +102 -0
  8. package/dist-server/controllers/create-data-sample.js.map +1 -0
  9. package/dist-server/controllers/data-use-case.js +57 -0
  10. package/dist-server/controllers/data-use-case.js.map +1 -0
  11. package/dist-server/controllers/index.js +17 -0
  12. package/dist-server/controllers/index.js.map +1 -1
  13. package/dist-server/index.js +1 -0
  14. package/dist-server/index.js.map +1 -1
  15. package/dist-server/routes.js +5 -16
  16. package/dist-server/routes.js.map +1 -1
  17. package/dist-server/service/data-item/data-item-type.js +6 -6
  18. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  19. package/dist-server/service/data-item/data-item.js +1 -1
  20. package/dist-server/service/data-item/data-item.js.map +1 -1
  21. package/dist-server/service/data-ooc/data-ooc-mutation.js +130 -0
  22. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
  23. package/dist-server/service/data-ooc/data-ooc-query.js +115 -0
  24. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
  25. package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
  26. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
  27. package/dist-server/service/data-ooc/data-ooc-type.js +99 -0
  28. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
  29. package/dist-server/service/data-ooc/data-ooc.js +218 -0
  30. package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
  31. package/dist-server/service/data-ooc/index.js +10 -0
  32. package/dist-server/service/data-ooc/index.js.map +1 -0
  33. package/dist-server/service/data-sample/data-sample-mutation.js +2 -140
  34. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  35. package/dist-server/service/data-sample/data-sample-type.js +5 -43
  36. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  37. package/dist-server/service/data-sample/data-sample.js +17 -3
  38. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  39. package/dist-server/service/data-set/data-set-mutation.js +1 -2
  40. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  41. package/dist-server/service/data-set/data-set-query.js +12 -0
  42. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  43. package/dist-server/service/data-set/data-set-type.js +19 -3
  44. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  45. package/dist-server/service/data-set/data-set.js +22 -10
  46. package/dist-server/service/data-set/data-set.js.map +1 -1
  47. package/dist-server/service/index.js +6 -2
  48. package/dist-server/service/index.js.map +1 -1
  49. package/package.json +14 -14
  50. package/server/controllers/create-data-sample.ts +139 -0
  51. package/server/controllers/data-use-case.ts +85 -0
  52. package/server/controllers/index.ts +1 -0
  53. package/server/index.ts +1 -0
  54. package/server/routes.ts +12 -23
  55. package/server/service/data-item/data-item-type.ts +3 -4
  56. package/server/service/data-item/data-item.ts +1 -1
  57. package/server/service/data-ooc/data-ooc-mutation.ts +117 -0
  58. package/server/service/data-ooc/data-ooc-query.ts +63 -0
  59. package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
  60. package/server/service/data-ooc/data-ooc-type.ts +62 -0
  61. package/server/service/data-ooc/data-ooc.ts +188 -0
  62. package/server/service/data-ooc/index.ts +7 -0
  63. package/server/service/data-sample/data-sample-mutation.ts +3 -171
  64. package/server/service/data-sample/data-sample-type.ts +3 -31
  65. package/server/service/data-sample/data-sample.ts +19 -3
  66. package/server/service/data-set/data-set-mutation.ts +1 -4
  67. package/server/service/data-set/data-set-query.ts +8 -1
  68. package/server/service/data-set/data-set-type.ts +15 -4
  69. package/server/service/data-set/data-set.ts +17 -7
  70. package/server/service/index.ts +6 -2
  71. package/things-factory.config.js +4 -0
  72. package/translations/en.json +12 -2
  73. package/translations/ko.json +12 -2
  74. package/translations/ms.json +11 -1
  75. package/translations/zh.json +11 -1
@@ -53,7 +53,9 @@ class DataEntryForm extends localize(i18next)(LitElement) {
53
53
  async _updateDataItems() {
54
54
  const data = this.entryForm.buildValue()
55
55
  const dataSample = {
56
- dataSetId: this.dataSet.id,
56
+ dataSet: {
57
+ id: this.dataSet.id
58
+ },
57
59
  data
58
60
  }
59
61
 
@@ -0,0 +1,450 @@
1
+ import '@operato/data-grist'
2
+
3
+ import { CommonButtonStyles, ScrollbarStyles } from '@operato/styles'
4
+ import { PageView, store } from '@operato/shell'
5
+ import { css, html } from 'lit'
6
+ import { i18next, localize } from '@operato/i18n'
7
+
8
+ import { client } from '@operato/graphql'
9
+ import { connect } from 'pwa-helpers/connect-mixin'
10
+ import gql from 'graphql-tag'
11
+ import { isMobileDevice } from '@operato/utils'
12
+ import { notify } from '@operato/layout'
13
+
14
+ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
15
+ static get properties() {
16
+ return {
17
+ active: String,
18
+ gristConfig: Object
19
+ }
20
+ }
21
+
22
+ static get styles() {
23
+ return [
24
+ ScrollbarStyles,
25
+ css`
26
+ :host {
27
+ display: flex;
28
+ flex-direction: column;
29
+
30
+ overflow: hidden;
31
+ }
32
+
33
+ ox-grist {
34
+ overflow-y: auto;
35
+ flex: 1;
36
+ }
37
+
38
+ #filters {
39
+ display: flex;
40
+ flex-direction: row;
41
+ justify-content: space-between;
42
+
43
+ background-color: white;
44
+ }
45
+
46
+ #filters > * {
47
+ padding: var(--padding-default) var(--padding-wide);
48
+ }
49
+ `
50
+ ]
51
+ }
52
+
53
+ get context() {
54
+ return {
55
+ title: i18next.t('title.data-ooc list'),
56
+ help: 'integration/ui/data-ooc',
57
+ actions: [
58
+ {
59
+ title: i18next.t('button.save'),
60
+ action: this._updateDataOoc.bind(this),
61
+ ...CommonButtonStyles.save
62
+ }
63
+ ],
64
+ exportable: {
65
+ name: i18next.t('title.data-ooc list'),
66
+ data: this._exportableData.bind(this)
67
+ }
68
+ }
69
+ }
70
+
71
+ render() {
72
+ return html`
73
+ <ox-grist
74
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
75
+ .config=${this.gristConfig}
76
+ .fetchHandler=${this.fetchHandler.bind(this)}
77
+ >
78
+ <div slot="headroom" id="filters">
79
+ <ox-filters-form></ox-filters-form>
80
+ </div>
81
+ </ox-grist>
82
+ `
83
+ }
84
+
85
+ get grist() {
86
+ return this.renderRoot.querySelector('ox-grist')
87
+ }
88
+
89
+ // update with url params value
90
+ _updateSearchConfig(lifecycle) {
91
+ // this.searchConfig = this.searchConfig.map(conf => {
92
+ // if (conf.name in lifecycle.params) {
93
+ // conf.value = lifecycle.params[conf.name]
94
+ // } else {
95
+ // delete conf.value
96
+ // }
97
+ // return conf
98
+ // })
99
+ }
100
+
101
+ // set default field value to record with searchConfig
102
+ _setDefaultFieldsValue(fields) {
103
+ // this.searchConfig.forEach(conf => {
104
+ // if (!fields[conf.name] && conf.value) {
105
+ // fields[conf.name] = conf.value
106
+ // }
107
+ // })
108
+ }
109
+
110
+ async pageInitialized(lifecycle) {
111
+ this._updateSearchConfig(lifecycle)
112
+
113
+ this.gristConfig = {
114
+ list: {
115
+ fields: ['dataSet', 'data', 'spec', 'correctiveAction', 'corrector', 'correctedAt', 'collectedAt', 'creator']
116
+ },
117
+ columns: [
118
+ { type: 'gutter', gutterName: 'sequence' },
119
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
120
+ {
121
+ type: 'string',
122
+ name: 'name',
123
+ label: true,
124
+ header: i18next.t('field.name'),
125
+ record: {
126
+ editable: true
127
+ },
128
+ filter: 'search',
129
+ sortable: true,
130
+ width: 120,
131
+ imex: true
132
+ },
133
+ {
134
+ type: 'string',
135
+ name: 'description',
136
+ label: true,
137
+ header: i18next.t('field.description'),
138
+ record: {
139
+ editable: true
140
+ },
141
+ filter: 'search',
142
+ width: 150,
143
+ imex: true
144
+ },
145
+ {
146
+ type: 'checkbox',
147
+ name: 'ooc',
148
+ header: i18next.t('field.ooc'),
149
+ record: {
150
+ editable: false
151
+ },
152
+ width: 30
153
+ },
154
+ {
155
+ type: 'checkbox',
156
+ name: 'oos',
157
+ header: i18next.t('field.oos'),
158
+ record: {
159
+ editable: false
160
+ },
161
+ width: 30
162
+ },
163
+ {
164
+ type: 'string',
165
+ name: 'state',
166
+ label: true,
167
+ header: i18next.t('field.state'),
168
+ record: {
169
+ editable: false
170
+ },
171
+ width: 150,
172
+ imex: true
173
+ },
174
+ {
175
+ type: 'textarea',
176
+ name: 'correctiveAction',
177
+ label: true,
178
+ header: i18next.t('field.corrective-action'),
179
+ record: {
180
+ editable: true
181
+ },
182
+ width: 150,
183
+ imex: true
184
+ },
185
+ {
186
+ type: 'resource-object',
187
+ name: 'dataSet',
188
+ header: i18next.t('field.data-set'),
189
+ record: {
190
+ editable: false
191
+ },
192
+ sortable: true,
193
+ width: 120,
194
+ imex: true
195
+ },
196
+ {
197
+ type: 'resource-object',
198
+ name: 'dataSample',
199
+ header: i18next.t('field.data-sample'),
200
+ record: {
201
+ editable: false
202
+ },
203
+ sortable: true,
204
+ width: 120,
205
+ imex: true
206
+ },
207
+ {
208
+ type: 'json5',
209
+ name: 'partitionKeys',
210
+ header: i18next.t('field.partition-keys'),
211
+ record: {
212
+ editable: false
213
+ },
214
+ width: 200,
215
+ imex: true
216
+ },
217
+ {
218
+ type: 'json5',
219
+ name: 'data',
220
+ header: i18next.t('field.data'),
221
+ record: {
222
+ editable: false
223
+ },
224
+ width: 200,
225
+ imex: true
226
+ },
227
+ {
228
+ type: 'json5',
229
+ name: 'spec',
230
+ header: i18next.t('field.spec'),
231
+ record: {
232
+ editable: false
233
+ },
234
+ width: 200
235
+ },
236
+ {
237
+ type: 'text',
238
+ name: 'rawData',
239
+ header: i18next.t('field.raw-data'),
240
+ record: {
241
+ editable: false
242
+ },
243
+ width: 200,
244
+ imex: true
245
+ },
246
+ {
247
+ type: 'resource-object',
248
+ name: 'updater',
249
+ header: i18next.t('field.updater'),
250
+ sortable: true,
251
+ width: 120,
252
+ imex: true
253
+ },
254
+ {
255
+ type: 'datetime',
256
+ name: 'updatedAt',
257
+ header: i18next.t('field.updated_at'),
258
+ sortable: true,
259
+ width: 180,
260
+ imex: true
261
+ },
262
+ {
263
+ type: 'datetime',
264
+ name: 'collectedAt',
265
+ header: i18next.t('field.collected_at'),
266
+ sortable: true,
267
+ width: 180,
268
+ imex: true
269
+ }
270
+ ],
271
+ rows: {
272
+ appendable: false,
273
+ selectable: {
274
+ multiple: true
275
+ }
276
+ },
277
+ sorters: [
278
+ {
279
+ name: 'updatedAt',
280
+ desc: true
281
+ }
282
+ ]
283
+ }
284
+
285
+ await this.updateComplete
286
+
287
+ this.grist.fetch()
288
+ }
289
+
290
+ async pageUpdated(changes, lifecycle) {
291
+ if (this.active) {
292
+ // update with url params value
293
+ this._updateSearchConfig(lifecycle)
294
+ await this.updateComplete
295
+
296
+ this.grist.fetch()
297
+ }
298
+ }
299
+
300
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
301
+ const response = await client.query({
302
+ query: gql`
303
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
304
+ responses: dataOocs(filters: $filters, pagination: $pagination, sortings: $sortings) {
305
+ items {
306
+ id
307
+ name
308
+ description
309
+ dataSet {
310
+ id
311
+ name
312
+ }
313
+ dataSample {
314
+ id
315
+ name
316
+ }
317
+ partitionKeys
318
+ data
319
+ state
320
+ spec
321
+ ooc
322
+ oos
323
+ correctiveAction
324
+ correctedAt
325
+ corrector {
326
+ id
327
+ name
328
+ }
329
+ updater {
330
+ id
331
+ name
332
+ }
333
+ updatedAt
334
+ collectedAt
335
+ }
336
+ total
337
+ }
338
+ }
339
+ `,
340
+ variables: {
341
+ filters,
342
+ pagination: { page, limit },
343
+ sortings
344
+ }
345
+ })
346
+
347
+ return {
348
+ total: response.data.responses.total || 0,
349
+ records: response.data.responses.items || []
350
+ }
351
+ }
352
+
353
+ async _updateDataOoc() {
354
+ let patches = this.grist.dirtyRecords
355
+ if (patches && patches.length) {
356
+ patches = patches.map(patch => {
357
+ let patchField = patch.id ? { id: patch.id } : {}
358
+ const dirtyFields = patch.__dirtyfields__
359
+ for (let key in dirtyFields) {
360
+ patchField[key] = dirtyFields[key].after
361
+ }
362
+ this._setDefaultFieldsValue(patchField)
363
+ patchField.cuFlag = patch.__dirty__
364
+
365
+ return patchField
366
+ })
367
+
368
+ const response = await client.mutate({
369
+ mutation: gql`
370
+ mutation ($patches: [DataOocPatch!]!) {
371
+ updateMultipleDataOoc(patches: $patches) {
372
+ name
373
+ }
374
+ }
375
+ `,
376
+ variables: {
377
+ patches
378
+ }
379
+ })
380
+
381
+ if (!response.errors) this.grist.fetch()
382
+ }
383
+ }
384
+
385
+ async _deleteDataOoc() {
386
+ if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
387
+ const ids = this.grist.selected.map(record => record.id)
388
+ if (ids && ids.length > 0) {
389
+ const response = await client.mutate({
390
+ mutation: gql`
391
+ mutation ($ids: [String!]!) {
392
+ deleteDataOocs(ids: $ids)
393
+ }
394
+ `,
395
+ variables: {
396
+ ids
397
+ }
398
+ })
399
+
400
+ if (!response.errors) {
401
+ this.grist.fetch()
402
+ notify({
403
+ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
404
+ })
405
+ }
406
+ }
407
+ }
408
+ }
409
+
410
+ _exportableData() {
411
+ let records = []
412
+ if (this.grist.selected && this.grist.selected.length > 0) {
413
+ records = this.grist.selected
414
+ } else {
415
+ records = this.grist.data.records
416
+ }
417
+
418
+ var headerSetting = this.grist.compiledConfig.columns
419
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
420
+ .map(column => {
421
+ return column.imex === true
422
+ ? {
423
+ header: column.header.renderer(),
424
+ key: column.name,
425
+ width: column.width,
426
+ type: column.type
427
+ }
428
+ : column.imex
429
+ })
430
+
431
+ var data = records.map(item => {
432
+ return {
433
+ id: item.id,
434
+ ...this.gristConfig.columns
435
+ .filter(column => column.type !== 'gutter' && column.record !== undefined && column.imex !== undefined)
436
+ .reduce((record, column) => {
437
+ const key = column.imex === true ? column.name : column.imex.key
438
+ record[key] = key
439
+ .split('.')
440
+ .reduce((obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : undefined), item)
441
+ return record
442
+ }, {})
443
+ }
444
+ })
445
+
446
+ return { header: headerSetting, data: data }
447
+ }
448
+ }
449
+
450
+ window.customElements.define('data-ooc-page', DataOoc)
@@ -1,10 +1,10 @@
1
1
  import '@operato/data-grist'
2
2
 
3
- import { CommonButtonStyles, ScrollbarStyles } from '@operato/styles'
4
3
  import { PageView, store } from '@operato/shell'
5
4
  import { css, html } from 'lit'
6
5
  import { i18next, localize } from '@operato/i18n'
7
6
 
7
+ import { ScrollbarStyles } from '@operato/styles'
8
8
  import { client } from '@operato/graphql'
9
9
  import { connect } from 'pwa-helpers/connect-mixin'
10
10
  import gql from 'graphql-tag'
@@ -54,13 +54,7 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
54
54
  return {
55
55
  title: i18next.t('title.data-sample list'),
56
56
  help: 'integration/ui/data-sample',
57
- actions: [
58
- {
59
- title: i18next.t('button.delete'),
60
- action: this._deleteDataSample.bind(this),
61
- ...CommonButtonStyles.delete
62
- }
63
- ],
57
+ actions: [],
64
58
  exportable: {
65
59
  name: i18next.t('title.data-sample list'),
66
60
  data: this._exportableData.bind(this)
@@ -121,7 +115,7 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
121
115
  label: true,
122
116
  header: i18next.t('field.name'),
123
117
  record: {
124
- editable: true
118
+ editable: false
125
119
  },
126
120
  filter: 'search',
127
121
  sortable: true,
@@ -134,7 +128,7 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
134
128
  label: true,
135
129
  header: i18next.t('field.description'),
136
130
  record: {
137
- editable: true
131
+ editable: false
138
132
  },
139
133
  filter: 'search',
140
134
  width: 150,
@@ -143,7 +137,7 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
143
137
  {
144
138
  type: 'resource-object',
145
139
  name: 'dataSet',
146
- header: i18next.t('field.dataSet'),
140
+ header: i18next.t('field.data-set'),
147
141
  record: {
148
142
  editable: false
149
143
  },
@@ -161,6 +155,24 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
161
155
  width: 200,
162
156
  imex: true
163
157
  },
158
+ {
159
+ type: 'checkbox',
160
+ name: 'ooc',
161
+ header: i18next.t('field.ooc'),
162
+ record: {
163
+ editable: false
164
+ },
165
+ width: 30
166
+ },
167
+ {
168
+ type: 'checkbox',
169
+ name: 'oos',
170
+ header: i18next.t('field.oos'),
171
+ record: {
172
+ editable: false
173
+ },
174
+ width: 30
175
+ },
164
176
  {
165
177
  type: 'json5',
166
178
  name: 'data',
@@ -219,11 +231,24 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
219
231
  appendable: false,
220
232
  selectable: {
221
233
  multiple: true
234
+ },
235
+ classifier: function (record, rowIndex) {
236
+ var emphasized
237
+ if (record['oos']) {
238
+ emphasized = ['red']
239
+ } else if (record['ooc']) {
240
+ emphasized = 'orange'
241
+ }
242
+
243
+ return {
244
+ emphasized
245
+ }
222
246
  }
223
247
  },
224
248
  sorters: [
225
249
  {
226
- name: 'name'
250
+ name: 'updatedAt',
251
+ desc: true
227
252
  }
228
253
  ]
229
254
  }
@@ -260,6 +285,8 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
260
285
  partitionKeys
261
286
  data
262
287
  spec
288
+ ooc
289
+ oos
263
290
  updater {
264
291
  id
265
292
  name
@@ -284,31 +311,6 @@ export class DataSample extends connect(store)(localize(i18next)(PageView)) {
284
311
  }
285
312
  }
286
313
 
287
- async _deleteDataSample() {
288
- if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
289
- const ids = this.grist.selected.map(record => record.id)
290
- if (ids && ids.length > 0) {
291
- const response = await client.mutate({
292
- mutation: gql`
293
- mutation ($ids: [String!]!) {
294
- deleteDataSamples(ids: $ids)
295
- }
296
- `,
297
- variables: {
298
- ids
299
- }
300
- })
301
-
302
- if (!response.errors) {
303
- this.grist.fetch()
304
- notify({
305
- message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
306
- })
307
- }
308
- }
309
- }
310
- }
311
-
312
314
  _exportableData() {
313
315
  let records = []
314
316
  if (this.grist.selected && this.grist.selected.length > 0) {
@@ -194,7 +194,7 @@ export class DataSensor extends connect(store)(localize(i18next)(PageView)) {
194
194
  {
195
195
  type: 'object',
196
196
  name: 'dataSet',
197
- header: i18next.t('field.dataSet'),
197
+ header: i18next.t('field.data-set'),
198
198
  record: {
199
199
  editable: true,
200
200
  options: {
@@ -9,6 +9,7 @@ import { css, html } from 'lit'
9
9
  import { i18next, localize } from '@operato/i18n'
10
10
  import { notify, openPopup } from '@operato/layout'
11
11
 
12
+ import { OxDataItemSpec } from '@operato/dataset'
12
13
  import { client } from '@operato/graphql'
13
14
  import { connect } from 'pwa-helpers/connect-mixin'
14
15
  import gql from 'graphql-tag'
@@ -202,6 +203,47 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
202
203
  sortable: true,
203
204
  width: 60
204
205
  },
206
+ {
207
+ type: 'select',
208
+ name: 'type',
209
+ label: true,
210
+ header: i18next.t('field.type'),
211
+ record: {
212
+ editable: true,
213
+ options: [
214
+ {},
215
+ {
216
+ display: 'Manually Collected',
217
+ value: 'manual'
218
+ },
219
+ {
220
+ display: 'Automatically Collected',
221
+ value: 'automatic'
222
+ }
223
+ ]
224
+ },
225
+ sortable: true,
226
+ width: 60
227
+ },
228
+ {
229
+ type: 'select',
230
+ name: 'useCase',
231
+ label: true,
232
+ header: i18next.t('field.use-case'),
233
+ record: {
234
+ editable: true,
235
+ options: () => {
236
+ return ['', ...OxDataItemSpec.getProviderNames()].map(name => {
237
+ return {
238
+ display: name,
239
+ value: name
240
+ }
241
+ })
242
+ }
243
+ },
244
+ sortable: true,
245
+ width: 80
246
+ },
205
247
  {
206
248
  type: 'partition-keys',
207
249
  name: 'partitionKeys',
@@ -238,6 +280,19 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
238
280
  },
239
281
  width: 120
240
282
  },
283
+ {
284
+ type: 'resource-object',
285
+ name: 'supervisoryRole',
286
+ header: i18next.t('field.supervisory-role'),
287
+ record: {
288
+ editable: true,
289
+ options: {
290
+ queryName: 'roles'
291
+ }
292
+ },
293
+ sortable: true,
294
+ width: 120
295
+ },
241
296
  {
242
297
  type: 'resource-object',
243
298
  name: 'updater',
@@ -298,8 +353,14 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
298
353
  partitionKeys
299
354
  slugger
300
355
  active
356
+ type
357
+ useCase
301
358
  schedule
302
359
  timezone
360
+ supervisoryRole {
361
+ id
362
+ name
363
+ }
303
364
  updater {
304
365
  id
305
366
  name
package/client/route.js CHANGED
@@ -11,5 +11,9 @@ export default function route(page) {
11
11
  case 'data-sample':
12
12
  import('./pages/data-sample')
13
13
  return page
14
+
15
+ case 'data-ooc':
16
+ import('./pages/data-ooc')
17
+ return page
14
18
  }
15
19
  }