@things-factory/dataset 5.0.0-alpha.2 → 5.0.0-alpha.22

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 (96) hide show
  1. package/README.md +13 -0
  2. package/assets/data-samples.jpg +0 -0
  3. package/client/bootstrap.js +16 -1
  4. package/client/pages/data-entry-form.js +84 -0
  5. package/client/pages/data-item-list.js +58 -16
  6. package/client/pages/data-ooc-view.js +182 -0
  7. package/client/pages/data-ooc.js +487 -0
  8. package/client/pages/data-sample-view.js +97 -0
  9. package/client/pages/data-sample.js +149 -56
  10. package/client/pages/data-sensor.js +8 -18
  11. package/client/pages/data-set.js +200 -75
  12. package/client/route.js +4 -0
  13. package/dist-server/controllers/create-data-sample.js +124 -0
  14. package/dist-server/controllers/create-data-sample.js.map +1 -0
  15. package/dist-server/controllers/data-use-case.js +57 -0
  16. package/dist-server/controllers/data-use-case.js.map +1 -0
  17. package/dist-server/controllers/index.js +17 -0
  18. package/dist-server/controllers/index.js.map +1 -1
  19. package/dist-server/index.js +2 -0
  20. package/dist-server/index.js.map +1 -1
  21. package/dist-server/routes.js +9 -24
  22. package/dist-server/routes.js.map +1 -1
  23. package/dist-server/service/data-item/data-item-mutation.js +5 -1
  24. package/dist-server/service/data-item/data-item-mutation.js.map +1 -1
  25. package/dist-server/service/data-item/data-item-type.js +14 -5
  26. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  27. package/dist-server/service/data-item/data-item.js +20 -7
  28. package/dist-server/service/data-item/data-item.js.map +1 -1
  29. package/dist-server/service/data-ooc/data-ooc-mutation.js +92 -0
  30. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
  31. package/dist-server/service/data-ooc/data-ooc-query.js +115 -0
  32. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
  33. package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
  34. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
  35. package/dist-server/service/data-ooc/data-ooc-type.js +107 -0
  36. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
  37. package/dist-server/service/data-ooc/data-ooc.js +237 -0
  38. package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
  39. package/dist-server/service/data-ooc/index.js +10 -0
  40. package/dist-server/service/data-ooc/index.js.map +1 -0
  41. package/dist-server/service/data-sample/data-sample-mutation.js +3 -105
  42. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  43. package/dist-server/service/data-sample/data-sample-type.js +13 -42
  44. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  45. package/dist-server/service/data-sample/data-sample.js +40 -9
  46. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  47. package/dist-server/service/data-set/data-set-mutation.js +1 -2
  48. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  49. package/dist-server/service/data-set/data-set-query.js +12 -0
  50. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  51. package/dist-server/service/data-set/data-set-type.js +19 -2
  52. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  53. package/dist-server/service/data-set/data-set.js +22 -10
  54. package/dist-server/service/data-set/data-set.js.map +1 -1
  55. package/dist-server/service/data-spec/data-spec-manager.js +20 -0
  56. package/dist-server/service/data-spec/data-spec-manager.js.map +1 -0
  57. package/dist-server/service/data-spec/data-spec-query.js +48 -0
  58. package/dist-server/service/data-spec/data-spec-query.js.map +1 -0
  59. package/dist-server/service/data-spec/data-spec.js +78 -0
  60. package/dist-server/service/data-spec/data-spec.js.map +1 -0
  61. package/dist-server/service/data-spec/index.js +8 -0
  62. package/dist-server/service/data-spec/index.js.map +1 -0
  63. package/dist-server/service/index.js +12 -4
  64. package/dist-server/service/index.js.map +1 -1
  65. package/package.json +15 -12
  66. package/server/controllers/create-data-sample.ts +166 -0
  67. package/server/controllers/data-use-case.ts +85 -0
  68. package/server/controllers/index.ts +1 -0
  69. package/server/index.ts +3 -0
  70. package/server/routes.ts +17 -31
  71. package/server/service/data-item/data-item-mutation.ts +6 -1
  72. package/server/service/data-item/data-item-type.ts +11 -7
  73. package/server/service/data-item/data-item.ts +16 -6
  74. package/server/service/data-ooc/data-ooc-mutation.ts +150 -0
  75. package/server/service/data-ooc/data-ooc-query.ts +63 -0
  76. package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
  77. package/server/service/data-ooc/data-ooc-type.ts +68 -0
  78. package/server/service/data-ooc/data-ooc.ts +204 -0
  79. package/server/service/data-ooc/index.ts +7 -0
  80. package/server/service/data-sample/data-sample-mutation.ts +6 -128
  81. package/server/service/data-sample/data-sample-type.ts +8 -29
  82. package/server/service/data-sample/data-sample.ts +36 -6
  83. package/server/service/data-set/data-set-mutation.ts +1 -4
  84. package/server/service/data-set/data-set-query.ts +8 -1
  85. package/server/service/data-set/data-set-type.ts +17 -6
  86. package/server/service/data-set/data-set.ts +18 -8
  87. package/server/service/data-spec/data-spec-manager.ts +21 -0
  88. package/server/service/data-spec/data-spec-query.ts +21 -0
  89. package/server/service/data-spec/data-spec.ts +44 -0
  90. package/server/service/data-spec/index.ts +5 -0
  91. package/server/service/index.ts +16 -8
  92. package/things-factory.config.js +4 -0
  93. package/translations/en.json +21 -0
  94. package/translations/ko.json +22 -1
  95. package/translations/ms.json +21 -0
  96. package/translations/zh.json +21 -0
@@ -1,53 +1,45 @@
1
1
  import '@operato/data-grist'
2
2
  import './data-item-list'
3
3
  import './data-set-importer'
4
+ import './data-entry-form'
4
5
 
5
- import gql from 'graphql-tag'
6
+ import { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
7
+ import { PageView, store } from '@operato/shell'
6
8
  import { css, html } from 'lit'
7
- import moment from 'moment-timezone'
8
- import { connect } from 'pwa-helpers/connect-mixin'
9
-
10
- import { client } from '@operato/graphql'
11
9
  import { i18next, localize } from '@operato/i18n'
12
10
  import { notify, openPopup } from '@operato/layout'
13
- import { PageView, store } from '@operato/shell'
14
- import { CommonButtonStyles, ScrollbarStyles } from '@operato/styles'
11
+
12
+ import JSON5 from 'json5'
13
+ import { OxDataUseCase } from '@operato/dataset'
14
+ import { client } from '@operato/graphql'
15
+ import { connect } from 'pwa-helpers/connect-mixin'
16
+ import gql from 'graphql-tag'
15
17
  import { isMobileDevice } from '@operato/utils'
18
+ import moment from 'moment-timezone'
16
19
 
17
20
  export class DataSet extends connect(store)(localize(i18next)(PageView)) {
18
21
  static get properties() {
19
22
  return {
20
23
  active: String,
21
- gristConfig: Object
24
+ gristConfig: Object,
25
+ filters: Object,
26
+ sorters: Object,
27
+ mode: String
22
28
  }
23
29
  }
24
30
 
25
31
  static get styles() {
26
32
  return [
27
33
  ScrollbarStyles,
34
+ CommonGristStyles,
28
35
  css`
29
36
  :host {
30
37
  display: flex;
31
- flex-direction: column;
32
38
 
33
- overflow: hidden;
34
- }
35
-
36
- ox-grist {
37
- overflow-y: auto;
38
- flex: 1;
39
- }
39
+ width: 100%;
40
40
 
41
- #filters {
42
- display: flex;
43
- flex-direction: row;
44
- justify-content: space-between;
45
-
46
- background-color: white;
47
- }
48
-
49
- #filters > * {
50
- padding: var(--padding-default) var(--padding-wide);
41
+ --grid-record-emphasized-background-color: red;
42
+ --grid-record-emphasized-color: yellow;
51
43
  }
52
44
  `
53
45
  ]
@@ -85,14 +77,43 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
85
77
  }
86
78
 
87
79
  render() {
80
+ const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
81
+
88
82
  return html`
89
83
  <ox-grist
90
- .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
84
+ .mode=${mode}
91
85
  .config=${this.gristConfig}
86
+ .filters=${this.filters}
87
+ .orders=${this.orders}
92
88
  .fetchHandler=${this.fetchHandler.bind(this)}
93
89
  >
94
90
  <div slot="headroom" id="filters">
95
- <ox-filters-form></ox-filters-form>
91
+ <div id="filters">
92
+ <ox-filters-form></ox-filters-form>
93
+ </div>
94
+
95
+ <div id="sorters">
96
+ Sort
97
+ <mwc-icon
98
+ @click=${e => {
99
+ const target = e.currentTarget
100
+ this.renderRoot.querySelector('#sorter-control').open({
101
+ right: 0,
102
+ top: target.offsetTop + target.offsetHeight
103
+ })
104
+ }}
105
+ >expand_more</mwc-icon
106
+ >
107
+ <ox-popup id="sorter-control">
108
+ <ox-sorters-control> </ox-sorters-control>
109
+ </ox-popup>
110
+ </div>
111
+
112
+ <div id="modes">
113
+ <mwc-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</mwc-icon>
114
+ <mwc-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</mwc-icon>
115
+ <mwc-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</mwc-icon>
116
+ </div>
96
117
  </div>
97
118
  </ox-grist>
98
119
  `
@@ -102,32 +123,12 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
102
123
  return this.renderRoot.querySelector('ox-grist')
103
124
  }
104
125
 
105
- // update with url params value
106
- _updateSearchConfig(lifecycle) {
107
- // this.searchConfig = this.searchConfig.map(conf => {
108
- // if (conf.name in lifecycle.params) {
109
- // conf.value = lifecycle.params[conf.name]
110
- // } else {
111
- // delete conf.value
112
- // }
113
- // return conf
114
- // })
115
- }
116
-
117
- // set default field value to record with searchConfig
118
- _setDefaultFieldsValue(fields) {
119
- // this.searchConfig.forEach(conf => {
120
- // if (!fields[conf.name] && conf.value) {
121
- // fields[conf.name] = conf.value
122
- // }
123
- // })
124
- }
125
-
126
126
  async pageInitialized(lifecycle) {
127
- this._updateSearchConfig(lifecycle)
128
-
129
127
  this.gristConfig = {
130
- list: { fields: ['name', 'description', 'schedule', 'active'] },
128
+ list: {
129
+ fields: ['name', 'description'],
130
+ details: ['schedule', 'active']
131
+ },
131
132
  columns: [
132
133
  { type: 'gutter', gutterName: 'sequence' },
133
134
  { type: 'gutter', gutterName: 'row-selector', multiple: true },
@@ -138,19 +139,38 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
138
139
  handlers: {
139
140
  click: (columns, data, column, record, rowIndex) => {
140
141
  if (!record.id) return
141
- openPopup(html` <data-item-list .dataSet=${record}></data-item-list> `, {
142
+ const popup = openPopup(html` <data-item-list .dataSet=${record}></data-item-list> `, {
142
143
  backdrop: true,
143
144
  help: 'data-set/ui/data-item-list',
144
145
  size: 'large',
145
146
  title: i18next.t('title.data-item list')
146
147
  })
148
+ popup.onclosed = () => {
149
+ this.grist.fetch()
150
+ }
151
+ }
152
+ }
153
+ },
154
+ {
155
+ type: 'gutter',
156
+ gutterName: 'button',
157
+ icon: 'fact_check',
158
+ handlers: {
159
+ click: (columns, data, column, record, rowIndex) => {
160
+ openPopup(
161
+ html` <data-entry-form .dataSet=${record} style="background-color: white;"></data-entry-form> `,
162
+ {
163
+ backdrop: true,
164
+ size: 'large',
165
+ title: i18next.t('title.data-entry-form')
166
+ }
167
+ )
147
168
  }
148
169
  }
149
170
  },
150
171
  {
151
172
  type: 'string',
152
173
  name: 'name',
153
- label: true,
154
174
  header: i18next.t('field.name'),
155
175
  record: {
156
176
  editable: true
@@ -162,7 +182,6 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
162
182
  {
163
183
  type: 'string',
164
184
  name: 'description',
165
- label: true,
166
185
  header: i18next.t('field.description'),
167
186
  record: {
168
187
  editable: true
@@ -178,15 +197,72 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
178
197
  record: {
179
198
  editable: true
180
199
  },
200
+ filter: true,
201
+ sortable: true,
202
+ width: 60
203
+ },
204
+ {
205
+ type: 'select',
206
+ name: 'type',
207
+ label: true,
208
+ header: i18next.t('field.type'),
209
+ record: {
210
+ editable: true,
211
+ options: [
212
+ {},
213
+ {
214
+ display: 'Manually Collected',
215
+ value: 'manual'
216
+ },
217
+ {
218
+ display: 'Automatically Collected',
219
+ value: 'automatic'
220
+ }
221
+ ]
222
+ },
181
223
  sortable: true,
224
+ filter: true,
182
225
  width: 60
183
226
  },
184
227
  {
185
- type: 'json',
228
+ type: 'select',
229
+ name: 'useCase',
230
+ label: true,
231
+ header: i18next.t('field.use-case'),
232
+ record: {
233
+ editable: true,
234
+ options: () => {
235
+ return ['', ...OxDataUseCase.getUseCaseNames()].map(name => {
236
+ return {
237
+ display: name,
238
+ value: name
239
+ }
240
+ })
241
+ }
242
+ },
243
+ sortable: true,
244
+ filter: {
245
+ operator: 'eq',
246
+ options: () => {
247
+ return ['', ...OxDataUseCase.getUseCaseNames()].map(name => {
248
+ return {
249
+ display: name,
250
+ value: name
251
+ }
252
+ })
253
+ }
254
+ },
255
+ width: 80
256
+ },
257
+ {
258
+ type: 'partition-keys',
186
259
  name: 'partitionKeys',
187
260
  header: i18next.t('field.partition-keys'),
188
261
  record: {
189
- editable: true
262
+ editable: true,
263
+ options: {
264
+ objectified: true /* transfered as a object type */
265
+ }
190
266
  },
191
267
  width: 200
192
268
  },
@@ -196,7 +272,10 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
196
272
  label: true,
197
273
  header: i18next.t('field.schedule'),
198
274
  record: {
199
- editable: true
275
+ editable: true,
276
+ options: {
277
+ objectified: true
278
+ }
200
279
  },
201
280
  width: 80,
202
281
  label: true
@@ -212,7 +291,20 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
212
291
  width: 120
213
292
  },
214
293
  {
215
- type: 'object',
294
+ type: 'resource-object',
295
+ name: 'supervisoryRole',
296
+ header: i18next.t('field.supervisory-role'),
297
+ record: {
298
+ editable: true,
299
+ options: {
300
+ queryName: 'roles'
301
+ }
302
+ },
303
+ sortable: true,
304
+ width: 120
305
+ },
306
+ {
307
+ type: 'resource-object',
216
308
  name: 'updater',
217
309
  header: i18next.t('field.updater'),
218
310
  record: {
@@ -251,10 +343,28 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
251
343
 
252
344
  async pageUpdated(changes, lifecycle) {
253
345
  if (this.active) {
254
- // update with url params value
255
- this._updateSearchConfig(lifecycle)
256
346
  await this.updateComplete
257
347
 
348
+ var filters = lifecycle.params?.['filters']
349
+ if (filters) {
350
+ try {
351
+ filters = JSON5.parse(filters)
352
+ this.filters = filters
353
+ } catch (e) {
354
+ console.error(`filters parameter parsing error: ${e}`)
355
+ }
356
+ }
357
+
358
+ var sorters = lifecycle.params?.['sorters']
359
+ if (sorters) {
360
+ try {
361
+ sorters = JSON5.parse(sorters)
362
+ this.sorters = sorters
363
+ } catch (e) {
364
+ console.error(`sorters parameter parsing error: ${e}`)
365
+ }
366
+ }
367
+
258
368
  this.grist.fetch()
259
369
  }
260
370
  }
@@ -271,8 +381,14 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
271
381
  partitionKeys
272
382
  slugger
273
383
  active
384
+ type
385
+ useCase
274
386
  schedule
275
387
  timezone
388
+ supervisoryRole {
389
+ id
390
+ name
391
+ }
276
392
  updater {
277
393
  id
278
394
  name
@@ -283,7 +399,10 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
283
399
  description
284
400
  sequence
285
401
  active
402
+ tag
286
403
  type
404
+ unit
405
+ options
287
406
  quota
288
407
  spec
289
408
  }
@@ -330,13 +449,6 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
330
449
  }
331
450
  }
332
451
 
333
- async stateChanged(state) {
334
- if (this.active && this._currentPopupName && !state.layout.viewparts[this._currentPopupName]) {
335
- this.grist.fetch()
336
- this._currentPopupName = null
337
- }
338
- }
339
-
340
452
  async _copyDataSet() {
341
453
  var selected = this.grist.selected
342
454
  if (selected.length == 0) return
@@ -355,7 +467,9 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
355
467
  }
356
468
  })
357
469
 
358
- if (!response.errors) this.grist.fetch()
470
+ if (!response.errors) {
471
+ this.grist.fetch()
472
+ }
359
473
  }
360
474
 
361
475
  async _updateDataSet() {
@@ -367,7 +481,6 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
367
481
  for (let key in dirtyFields) {
368
482
  patchField[key] = dirtyFields[key].after
369
483
  }
370
- this._setDefaultFieldsValue(patchField)
371
484
  patchField.cuFlag = patch.__dirty__
372
485
 
373
486
  return patchField
@@ -386,13 +499,25 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
386
499
  }
387
500
  })
388
501
 
389
- if (!response.errors) this.grist.fetch()
502
+ if (!response.errors) {
503
+ this.grist.fetch()
504
+ }
390
505
  }
391
506
  }
392
507
 
393
508
  async exportHandler() {
394
509
  const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records
395
- const targetFieldSet = new Set(['id', 'name', 'type', 'description', 'schedule', 'timezone', 'active', 'dataItems'])
510
+ const targetFieldSet = new Set([
511
+ 'id',
512
+ 'name',
513
+ 'type',
514
+ 'description',
515
+ 'tag',
516
+ 'schedule',
517
+ 'timezone',
518
+ 'active',
519
+ 'dataItems'
520
+ ])
396
521
 
397
522
  return exportTargets.map(dataSet => {
398
523
  let tempObj = {}
@@ -408,11 +533,11 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
408
533
  openPopup(
409
534
  html`
410
535
  <data-set-importer
411
- .dataSets="${records}"
412
- @imported="${() => {
536
+ .dataSets=${records}
537
+ @imported=${() => {
413
538
  history.back()
414
539
  this.grist.fetch()
415
- }}"
540
+ }}
416
541
  ></data-set-importer>
417
542
  `,
418
543
  {
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
  }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createDataSample = void 0;
7
+ const moment_1 = __importDefault(require("moment"));
8
+ const shell_1 = require("@things-factory/shell");
9
+ const data_item_1 = require("../service/data-item/data-item");
10
+ const data_ooc_1 = require("../service/data-ooc/data-ooc");
11
+ const data_sample_1 = require("../service/data-sample/data-sample");
12
+ const data_set_1 = require("../service/data-set/data-set");
13
+ const data_use_case_1 = require("./data-use-case");
14
+ const debug = require('debug')('things-factory:dataset:controller/save-data-sample');
15
+ // parse variable javascript string pattern
16
+ const replaceVariables = (keys, dic) => {
17
+ for (const k in keys) {
18
+ const matches = keys[k].match(/\$\{\w*\}/g);
19
+ matches &&
20
+ matches.forEach(m => {
21
+ keys[k] = keys[k].replace(m, dic[m.slice(2, -1)]);
22
+ });
23
+ }
24
+ return keys;
25
+ };
26
+ // It is required UTC date for Partitioning File System like AWS S3 from Athena.
27
+ // ex) %YYYY, %MM, %DD
28
+ const formatDate = (keys, _moment) => {
29
+ for (const k in keys) {
30
+ const matches = keys[k].match(/%\w*/g);
31
+ matches &&
32
+ matches.forEach(m => {
33
+ keys[k] = keys[k].replace(m, _moment.format(m.substr(1)));
34
+ });
35
+ }
36
+ return keys;
37
+ };
38
+ async function createDataSample(dataSample, context) {
39
+ const { domain, user, tx } = context.state;
40
+ const dataSet = await tx.getRepository(data_set_1.DataSet).findOne({
41
+ where: { id: dataSample.dataSet.id }
42
+ });
43
+ const dataItems = await tx.getRepository(data_item_1.DataItem).find({
44
+ where: {
45
+ domain,
46
+ dataSet
47
+ },
48
+ order: {
49
+ sequence: 'DESC'
50
+ }
51
+ });
52
+ const spec = dataItems.reduce((spec, dataItem) => {
53
+ spec[dataItem.tag] = Object.assign(Object.assign({}, dataItem.spec), { name: dataItem.name /* do we need ? */ });
54
+ return spec;
55
+ }, {});
56
+ const collectedAt = dataSample.collectedAt || new Date();
57
+ const momentUtc = (0, moment_1.default)(collectedAt).utc();
58
+ const defaultPartitionKeys = {
59
+ domain: domain.subdomain,
60
+ datasetid: dataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,
61
+ year: momentUtc.format('Y'),
62
+ month: momentUtc.format('M'),
63
+ day: momentUtc.format('D')
64
+ };
65
+ var partitionKeys = Object.assign(Object.assign({}, defaultPartitionKeys), dataSet.partitionKeys);
66
+ partitionKeys = formatDate(partitionKeys, momentUtc);
67
+ partitionKeys = replaceVariables(partitionKeys, Object.assign({}, dataSample.data));
68
+ const { ooc, oos } = data_use_case_1.DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {};
69
+ const result = await tx.getRepository(data_sample_1.DataSample).save(Object.assign(Object.assign({ name: dataSet.name, description: dataSet.description, useCase: dataSet.useCase }, dataSample), { domain,
70
+ partitionKeys,
71
+ spec,
72
+ ooc,
73
+ oos,
74
+ collectedAt, workDate: momentUtc.format('YYYY-MM-DD'), workShift: 'DAY', creator: user, updater: user }));
75
+ if (ooc || oos) {
76
+ const dataOoc = await tx.getRepository(data_ooc_1.DataOoc).save({
77
+ name: dataSet.name,
78
+ description: dataSet.description,
79
+ useCase: dataSet.useCase,
80
+ dataSet,
81
+ dataSample: result,
82
+ data: dataSample.data,
83
+ domain,
84
+ partitionKeys,
85
+ spec,
86
+ ooc,
87
+ oos,
88
+ history: [
89
+ {
90
+ user: {
91
+ id: user.id,
92
+ name: user.name
93
+ },
94
+ state: data_ooc_1.DataOocStatus.CREATED,
95
+ timestamp: Date.now()
96
+ }
97
+ ],
98
+ state: data_ooc_1.DataOocStatus.CREATED,
99
+ workDate: momentUtc.format('YYYY-MM-DD'),
100
+ workShift: 'DAY',
101
+ collectedAt,
102
+ creator: user,
103
+ updater: user
104
+ });
105
+ debug('dataOoc is about to publish...', dataOoc);
106
+ shell_1.pubsub.publish('data-ooc', {
107
+ dataOoc,
108
+ supervisoryRoleId: dataSet.supervisoryRoleId
109
+ });
110
+ shell_1.pubsub.publish('notification', {
111
+ notification: {
112
+ domain,
113
+ type: 'error',
114
+ title: `Data OOC occurred on '${dataSet.name}'`,
115
+ body: `Data OOC occurred on '${dataSet.name}'`,
116
+ url: (0, shell_1.getRedirectSubdomainPath)(context, domain.subdomain, `/data-ooc/${dataOoc.id}`),
117
+ timestamp: collectedAt
118
+ }
119
+ });
120
+ }
121
+ return result;
122
+ }
123
+ exports.createDataSample = createDataSample;
124
+ //# sourceMappingURL=create-data-sample.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-data-sample.js","sourceRoot":"","sources":["../../server/controllers/create-data-sample.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataUseCase = void 0;
4
+ class DataUseCase {
5
+ static registerUseCase(name, provider) {
6
+ DataUseCase.registry[name] = provider;
7
+ }
8
+ static getUseCaseNames() {
9
+ return Object.keys(DataUseCase.registry);
10
+ }
11
+ static getUseCase(name) {
12
+ return DataUseCase.registry[name];
13
+ }
14
+ static evaluate(dataSet, dataItems, data) {
15
+ var _a;
16
+ var ooc = false;
17
+ var oos = false;
18
+ if (!dataSet.useCase) {
19
+ return { ooc, oos };
20
+ }
21
+ const useCaseNames = dataSet.useCase.split(',').map(useCaseName => useCaseName.trim());
22
+ const useCases = useCaseNames.map(useCaseName => DataUseCase.getUseCase(useCaseName)).filter(useCase => !!useCase);
23
+ for (let i = 0; i < dataItems.length; i++) {
24
+ const dataItem = dataItems[i];
25
+ const { active, tag } = dataItem;
26
+ if (!active || !tag) {
27
+ continue;
28
+ }
29
+ let values = data[tag];
30
+ if (typeof values === 'undefined') {
31
+ continue; // TODO what if in case no value ?
32
+ }
33
+ if (!(values instanceof Array)) {
34
+ values = [values];
35
+ }
36
+ for (let j = 0; j < useCases.length; j++) {
37
+ const useCase = useCases[j];
38
+ const specs = (_a = dataItem.spec) === null || _a === void 0 ? void 0 : _a[dataSet.useCase];
39
+ if (!specs) {
40
+ continue;
41
+ }
42
+ const result = useCase.evaluate(specs, values);
43
+ if (result) {
44
+ ooc || (ooc = result.ooc);
45
+ oos || (oos = result.oos);
46
+ }
47
+ // if (ooc && oos) {
48
+ // return { ooc, oos }
49
+ // }
50
+ }
51
+ }
52
+ return { ooc, oos };
53
+ }
54
+ }
55
+ exports.DataUseCase = DataUseCase;
56
+ DataUseCase.registry = {};
57
+ //# sourceMappingURL=data-use-case.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-use-case.js","sourceRoot":"","sources":["../../server/controllers/data-use-case.ts"],"names":[],"mappings":";;;AAiBA,MAAsB,WAAW;IAGxB,MAAM,CAAC,eAAe,CAAC,IAAY,EAAE,QAAqB;QAC/D,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAA;IACvC,CAAC;IAEM,MAAM,CAAC,eAAe;QAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC1C,CAAC;IAEM,MAAM,CAAC,UAAU,CAAC,IAAY;QACnC,OAAO,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACnC,CAAC;IAEM,MAAM,CAAC,QAAQ,CAAC,OAAgB,EAAE,SAAqB,EAAE,IAAS;;QACvE,IAAI,GAAG,GAAG,KAAK,CAAA;QACf,IAAI,GAAG,GAAG,KAAK,CAAA;QAEf,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YACpB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;SACpB;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAA;QACtF,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;QAElH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAA;YAChC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE;gBACnB,SAAQ;aACT;YAED,IAAI,MAAM,GAAgB,IAAI,CAAC,GAAG,CAAC,CAAA;YACnC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;gBACjC,SAAQ,CAAC,kCAAkC;aAC5C;YAED,IAAI,CAAC,CAAC,MAAM,YAAY,KAAK,CAAC,EAAE;gBAC9B,MAAM,GAAG,CAAC,MAAM,CAAC,CAAA;aAClB;YAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;gBAE3B,MAAM,KAAK,GAAG,MAAA,QAAQ,CAAC,IAAI,0CAAG,OAAO,CAAC,OAAO,CAAC,CAAA;gBAC9C,IAAI,CAAC,KAAK,EAAE;oBACV,SAAQ;iBACT;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;gBAE9C,IAAI,MAAM,EAAE;oBACV,GAAG,KAAH,GAAG,GAAK,MAAM,CAAC,GAAG,EAAA;oBAClB,GAAG,KAAH,GAAG,GAAK,MAAM,CAAC,GAAG,EAAA;iBACnB;gBAED,oBAAoB;gBACpB,wBAAwB;gBACxB,IAAI;aACL;SACF;QAED,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IACrB,CAAC;;AAhEH,kCAmEC;AAlEQ,oBAAQ,GAAoC,EAAE,CAAA"}
@@ -1 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./data-use-case"), exports);
1
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/controllers/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/controllers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAA+B"}
@@ -15,7 +15,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  require("./routes");
18
+ __exportStar(require("./controllers"), exports);
18
19
  __exportStar(require("./migrations"), exports);
19
20
  __exportStar(require("./middlewares"), exports);
20
21
  __exportStar(require("./service"), exports);
22
+ __exportStar(require("./service/data-spec/data-spec-manager"), exports);
21
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oBAAiB;AAEjB,+CAA4B;AAC5B,gDAA6B;AAC7B,4CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oBAAiB;AAEjB,gDAA6B;AAC7B,+CAA4B;AAC5B,gDAA6B;AAC7B,4CAAyB;AAEzB,wEAAqD"}