@things-factory/dataset 5.0.0-alpha.1 → 5.0.0-alpha.12

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 (73) hide show
  1. package/client/bootstrap.js +15 -2
  2. package/client/pages/data-entry-form.js +75 -0
  3. package/client/pages/data-item-list.js +65 -16
  4. package/client/pages/data-sample.js +51 -16
  5. package/client/pages/data-sensor.js +446 -0
  6. package/client/pages/data-set.js +61 -16
  7. package/client/route.js +4 -0
  8. package/dist-server/index.js +1 -0
  9. package/dist-server/index.js.map +1 -1
  10. package/dist-server/routes.js +64 -0
  11. package/dist-server/routes.js.map +1 -1
  12. package/dist-server/service/data-item/data-item-mutation.js +5 -1
  13. package/dist-server/service/data-item/data-item-mutation.js.map +1 -1
  14. package/dist-server/service/data-item/data-item-type.js +15 -6
  15. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  16. package/dist-server/service/data-item/data-item.js +26 -6
  17. package/dist-server/service/data-item/data-item.js.map +1 -1
  18. package/dist-server/service/data-sample/data-sample-mutation.js +41 -7
  19. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  20. package/dist-server/service/data-sample/data-sample-type.js +23 -2
  21. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  22. package/dist-server/service/data-sample/data-sample.js +44 -5
  23. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  24. package/dist-server/service/data-sensor/data-sensor-mutation.js +120 -0
  25. package/dist-server/service/data-sensor/data-sensor-mutation.js.map +1 -0
  26. package/dist-server/service/data-sensor/data-sensor-query.js +108 -0
  27. package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -0
  28. package/dist-server/service/data-sensor/data-sensor-type.js +147 -0
  29. package/dist-server/service/data-sensor/data-sensor-type.js.map +1 -0
  30. package/dist-server/service/data-sensor/data-sensor.js +168 -0
  31. package/dist-server/service/data-sensor/data-sensor.js.map +1 -0
  32. package/dist-server/service/data-sensor/index.js +9 -0
  33. package/dist-server/service/data-sensor/index.js.map +1 -0
  34. package/dist-server/service/data-set/data-set-type.js +18 -0
  35. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  36. package/dist-server/service/data-set/data-set.js +22 -3
  37. package/dist-server/service/data-set/data-set.js.map +1 -1
  38. package/dist-server/service/data-spec/data-spec-manager.js +20 -0
  39. package/dist-server/service/data-spec/data-spec-manager.js.map +1 -0
  40. package/dist-server/service/data-spec/data-spec-query.js +48 -0
  41. package/dist-server/service/data-spec/data-spec-query.js.map +1 -0
  42. package/dist-server/service/data-spec/data-spec.js +78 -0
  43. package/dist-server/service/data-spec/data-spec.js.map +1 -0
  44. package/dist-server/service/data-spec/index.js +8 -0
  45. package/dist-server/service/data-spec/index.js.map +1 -0
  46. package/dist-server/service/index.js +10 -2
  47. package/dist-server/service/index.js.map +1 -1
  48. package/package.json +14 -11
  49. package/server/index.ts +2 -0
  50. package/server/routes.ts +76 -0
  51. package/server/service/data-item/data-item-mutation.ts +6 -1
  52. package/server/service/data-item/data-item-type.ts +11 -6
  53. package/server/service/data-item/data-item.ts +21 -5
  54. package/server/service/data-sample/data-sample-mutation.ts +51 -5
  55. package/server/service/data-sample/data-sample-type.ts +17 -2
  56. package/server/service/data-sample/data-sample.ts +37 -2
  57. package/server/service/data-sensor/data-sensor-mutation.ts +110 -0
  58. package/server/service/data-sensor/data-sensor-query.ts +56 -0
  59. package/server/service/data-sensor/data-sensor-type.ts +98 -0
  60. package/server/service/data-sensor/data-sensor.ts +139 -0
  61. package/server/service/data-sensor/index.ts +6 -0
  62. package/server/service/data-set/data-set-type.ts +14 -0
  63. package/server/service/data-set/data-set.ts +17 -1
  64. package/server/service/data-spec/data-spec-manager.ts +21 -0
  65. package/server/service/data-spec/data-spec-query.ts +21 -0
  66. package/server/service/data-spec/data-spec.ts +44 -0
  67. package/server/service/data-spec/index.ts +5 -0
  68. package/server/service/index.ts +12 -4
  69. package/things-factory.config.js +4 -0
  70. package/translations/en.json +18 -4
  71. package/translations/ko.json +17 -3
  72. package/translations/ms.json +18 -4
  73. package/translations/zh.json +18 -4
@@ -0,0 +1,446 @@
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 DataSensor 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-sensor list'),
56
+ help: 'integration/ui/data-sensor',
57
+ actions: [
58
+ {
59
+ title: i18next.t('button.copy'),
60
+ action: this._copyDataSensor.bind(this),
61
+ ...CommonButtonStyles.copy
62
+ },
63
+ {
64
+ title: i18next.t('button.save'),
65
+ action: this._updateDataSensor.bind(this),
66
+ ...CommonButtonStyles.save
67
+ },
68
+ {
69
+ title: i18next.t('button.delete'),
70
+ action: this._deleteDataSensor.bind(this),
71
+ ...CommonButtonStyles.delete
72
+ }
73
+ ]
74
+ }
75
+ }
76
+
77
+ render() {
78
+ return html`
79
+ <ox-grist
80
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
81
+ .config=${this.gristConfig}
82
+ .fetchHandler=${this.fetchHandler.bind(this)}
83
+ >
84
+ <div slot="headroom" id="filters">
85
+ <ox-filters-form></ox-filters-form>
86
+ </div>
87
+ </ox-grist>
88
+ `
89
+ }
90
+
91
+ get grist() {
92
+ return this.renderRoot.querySelector('ox-grist')
93
+ }
94
+
95
+ // update with url params value
96
+ _updateSearchConfig(lifecycle) {
97
+ // this.searchConfig = this.searchConfig.map(conf => {
98
+ // if (conf.name in lifecycle.params) {
99
+ // conf.value = lifecycle.params[conf.name]
100
+ // } else {
101
+ // delete conf.value
102
+ // }
103
+ // return conf
104
+ // })
105
+ }
106
+
107
+ // set default field value to record with searchConfig
108
+ _setDefaultFieldsValue(fields) {
109
+ // this.searchConfig.forEach(conf => {
110
+ // if (!fields[conf.name] && conf.value) {
111
+ // fields[conf.name] = conf.value
112
+ // }
113
+ // })
114
+ }
115
+
116
+ async pageInitialized(lifecycle) {
117
+ this._updateSearchConfig(lifecycle)
118
+
119
+ this.gristConfig = {
120
+ list: { fields: ['name', 'description', 'active'] },
121
+ columns: [
122
+ { type: 'gutter', gutterName: 'sequence' },
123
+ { type: 'gutter', gutterName: 'row-selector', multiple: true },
124
+ {
125
+ type: 'string',
126
+ name: 'name',
127
+ label: true,
128
+ header: i18next.t('field.name'),
129
+ record: {
130
+ editable: true
131
+ },
132
+ filter: 'search',
133
+ sortable: true,
134
+ width: 150
135
+ },
136
+ {
137
+ type: 'string',
138
+ name: 'description',
139
+ label: true,
140
+ header: i18next.t('field.description'),
141
+ record: {
142
+ editable: true
143
+ },
144
+ filter: 'search',
145
+ width: 200
146
+ },
147
+ {
148
+ type: 'checkbox',
149
+ name: 'active',
150
+ label: true,
151
+ header: i18next.t('field.active'),
152
+ record: {
153
+ editable: true
154
+ },
155
+ sortable: true,
156
+ width: 60
157
+ },
158
+ {
159
+ type: 'string',
160
+ name: 'deviceId',
161
+ label: true,
162
+ header: i18next.t('field.device-id'),
163
+ record: {
164
+ editable: true
165
+ },
166
+ filter: 'search',
167
+ sortable: true,
168
+ width: 150
169
+ },
170
+ {
171
+ type: 'string',
172
+ name: 'tag',
173
+ label: true,
174
+ header: i18next.t('field.tag'),
175
+ record: {
176
+ editable: true
177
+ },
178
+ sortable: true,
179
+ width: 150
180
+ },
181
+ {
182
+ type: 'object',
183
+ name: 'appliance',
184
+ header: i18next.t('field.appliance'),
185
+ record: {
186
+ editable: true,
187
+ options: {
188
+ queryName: 'appliances'
189
+ }
190
+ },
191
+ sortable: true,
192
+ width: 120
193
+ },
194
+ {
195
+ type: 'object',
196
+ name: 'dataSet',
197
+ header: i18next.t('field.dataSet'),
198
+ record: {
199
+ editable: true,
200
+ options: {
201
+ queryName: 'dataSets'
202
+ }
203
+ },
204
+ sortable: true,
205
+ width: 120
206
+ },
207
+ {
208
+ type: 'string',
209
+ name: 'refBy',
210
+ label: true,
211
+ header: i18next.t('field.ref-by'),
212
+ record: {
213
+ editable: true
214
+ },
215
+ sortable: true,
216
+ width: 150
217
+ },
218
+ {
219
+ type: 'string',
220
+ name: 'model',
221
+ label: true,
222
+ header: i18next.t('field.model'),
223
+ record: {
224
+ editable: true
225
+ },
226
+ sortable: true,
227
+ width: 150
228
+ },
229
+ {
230
+ type: 'string',
231
+ name: 'brand',
232
+ label: true,
233
+ header: i18next.t('field.brand'),
234
+ record: {
235
+ editable: true
236
+ },
237
+ sortable: true,
238
+ width: 150
239
+ },
240
+ {
241
+ type: 'string',
242
+ name: 'serialNo',
243
+ label: true,
244
+ header: i18next.t('field.serial-no'),
245
+ record: {
246
+ editable: true
247
+ },
248
+ sortable: true,
249
+ width: 150
250
+ },
251
+ {
252
+ type: 'string',
253
+ name: 'netmask',
254
+ label: true,
255
+ header: i18next.t('field.netmask'),
256
+ record: {
257
+ editable: true
258
+ },
259
+ sortable: true,
260
+ width: 150
261
+ },
262
+ {
263
+ type: 'object',
264
+ name: 'updater',
265
+ header: i18next.t('field.updater'),
266
+ record: {
267
+ editable: false
268
+ },
269
+ sortable: true,
270
+ width: 120
271
+ },
272
+ {
273
+ type: 'datetime',
274
+ name: 'collectedAt',
275
+ header: i18next.t('field.collected_at'),
276
+ record: {
277
+ editable: false
278
+ },
279
+ sortable: true,
280
+ width: 180
281
+ }
282
+ ],
283
+ rows: {
284
+ selectable: {
285
+ multiple: true
286
+ }
287
+ },
288
+ sorters: [
289
+ {
290
+ name: 'name'
291
+ }
292
+ ]
293
+ }
294
+
295
+ await this.updateComplete
296
+
297
+ this.grist.fetch()
298
+ }
299
+
300
+ async pageUpdated(changes, lifecycle) {
301
+ if (this.active) {
302
+ // update with url params value
303
+ this._updateSearchConfig(lifecycle)
304
+ await this.updateComplete
305
+
306
+ this.grist.fetch()
307
+ }
308
+ }
309
+
310
+ async fetchHandler({ page, limit, sortings = [], filters = [] }) {
311
+ const response = await client.query({
312
+ query: gql`
313
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
314
+ responses: dataSensors(filters: $filters, pagination: $pagination, sortings: $sortings) {
315
+ items {
316
+ id
317
+ name
318
+ description
319
+ active
320
+ deviceId
321
+ tag
322
+ appliance {
323
+ id
324
+ name
325
+ description
326
+ }
327
+ dataSet {
328
+ id
329
+ name
330
+ description
331
+ }
332
+ refBy
333
+ brand
334
+ model
335
+ serialNo
336
+ netmask
337
+ updater {
338
+ id
339
+ name
340
+ }
341
+ updatedAt
342
+ }
343
+ total
344
+ }
345
+ }
346
+ `,
347
+ variables: {
348
+ filters,
349
+ pagination: { page, limit },
350
+ sortings
351
+ }
352
+ })
353
+
354
+ return {
355
+ total: response.data.responses.total || 0,
356
+ records: response.data.responses.items || []
357
+ }
358
+ }
359
+
360
+ async _deleteDataSensor() {
361
+ if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
362
+ const ids = this.grist.selected.map(record => record.id)
363
+ if (ids && ids.length > 0) {
364
+ const response = await client.mutate({
365
+ mutation: gql`
366
+ mutation ($ids: [String!]!) {
367
+ deleteDataSensors(ids: $ids)
368
+ }
369
+ `,
370
+ variables: {
371
+ ids
372
+ }
373
+ })
374
+
375
+ if (!response.errors) {
376
+ this.grist.fetch()
377
+ notify({
378
+ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
379
+ })
380
+ }
381
+ }
382
+ }
383
+ }
384
+
385
+ async stateChanged(state) {
386
+ if (this.active && this._currentPopupName && !state.layout.viewparts[this._currentPopupName]) {
387
+ this.grist.fetch()
388
+ this._currentPopupName = null
389
+ }
390
+ }
391
+
392
+ async _copyDataSensor() {
393
+ var selected = this.grist.selected
394
+ if (selected.length == 0) return
395
+
396
+ if (!confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.copy') }))) return
397
+ var response = await client.mutate({
398
+ mutation: gql`
399
+ mutation ($ids: [String!]!) {
400
+ copyDataSensors(ids: $ids) {
401
+ id
402
+ }
403
+ }
404
+ `,
405
+ variables: {
406
+ ids: selected.map(r => r.id)
407
+ }
408
+ })
409
+
410
+ if (!response.errors) this.grist.fetch()
411
+ }
412
+
413
+ async _updateDataSensor() {
414
+ let patches = this.grist.dirtyRecords
415
+ if (patches && patches.length) {
416
+ patches = patches.map(patch => {
417
+ let patchField = patch.id ? { id: patch.id } : {}
418
+ const dirtyFields = patch.__dirtyfields__
419
+ for (let key in dirtyFields) {
420
+ patchField[key] = dirtyFields[key].after
421
+ }
422
+ this._setDefaultFieldsValue(patchField)
423
+ patchField.cuFlag = patch.__dirty__
424
+
425
+ return patchField
426
+ })
427
+
428
+ const response = await client.mutate({
429
+ mutation: gql`
430
+ mutation ($patches: [DataSensorPatch!]!) {
431
+ updateMultipleDataSensor(patches: $patches) {
432
+ name
433
+ }
434
+ }
435
+ `,
436
+ variables: {
437
+ patches
438
+ }
439
+ })
440
+
441
+ if (!response.errors) this.grist.fetch()
442
+ }
443
+ }
444
+ }
445
+
446
+ window.customElements.define('data-sensor-page', DataSensor)
@@ -1,18 +1,19 @@
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, 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 { client } from '@operato/graphql'
13
+ import { connect } from 'pwa-helpers/connect-mixin'
14
+ import gql from 'graphql-tag'
15
15
  import { isMobileDevice } from '@operato/utils'
16
+ import moment from 'moment-timezone'
16
17
 
17
18
  export class DataSet extends connect(store)(localize(i18next)(PageView)) {
18
19
  static get properties() {
@@ -147,6 +148,23 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
147
148
  }
148
149
  }
149
150
  },
151
+ {
152
+ type: 'gutter',
153
+ gutterName: 'button',
154
+ icon: 'fact_check',
155
+ handlers: {
156
+ click: (columns, data, column, record, rowIndex) => {
157
+ openPopup(
158
+ html` <data-entry-form .dataSet=${record} style="background-color: white;"></data-entry-form> `,
159
+ {
160
+ backdrop: true,
161
+ size: 'large',
162
+ title: i18next.t('title.data-entry-form')
163
+ }
164
+ )
165
+ }
166
+ }
167
+ },
150
168
  {
151
169
  type: 'string',
152
170
  name: 'name',
@@ -181,13 +199,28 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
181
199
  sortable: true,
182
200
  width: 60
183
201
  },
202
+ {
203
+ type: 'partition-keys',
204
+ name: 'partitionKeys',
205
+ header: i18next.t('field.partition-keys'),
206
+ record: {
207
+ editable: true,
208
+ options: {
209
+ objectified: true /* transfered as a object type */
210
+ }
211
+ },
212
+ width: 200
213
+ },
184
214
  {
185
215
  type: 'crontab',
186
216
  name: 'schedule',
187
217
  label: true,
188
218
  header: i18next.t('field.schedule'),
189
219
  record: {
190
- editable: true
220
+ editable: true,
221
+ options: {
222
+ objectified: true
223
+ }
191
224
  },
192
225
  width: 80,
193
226
  label: true
@@ -203,7 +236,7 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
203
236
  width: 120
204
237
  },
205
238
  {
206
- type: 'object',
239
+ type: 'resource-object',
207
240
  name: 'updater',
208
241
  header: i18next.t('field.updater'),
209
242
  record: {
@@ -259,6 +292,8 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
259
292
  id
260
293
  name
261
294
  description
295
+ partitionKeys
296
+ slugger
262
297
  active
263
298
  schedule
264
299
  timezone
@@ -272,7 +307,9 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
272
307
  description
273
308
  sequence
274
309
  active
310
+ tag
275
311
  type
312
+ options
276
313
  quota
277
314
  spec
278
315
  }
@@ -354,9 +391,7 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
354
391
  let patchField = patch.id ? { id: patch.id } : {}
355
392
  const dirtyFields = patch.__dirtyfields__
356
393
  for (let key in dirtyFields) {
357
- if (['message', 'step', 'steps', 'progress', 'rounds'].indexOf(key) == -1) {
358
- patchField[key] = dirtyFields[key].after
359
- }
394
+ patchField[key] = dirtyFields[key].after
360
395
  }
361
396
  this._setDefaultFieldsValue(patchField)
362
397
  patchField.cuFlag = patch.__dirty__
@@ -383,7 +418,17 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
383
418
 
384
419
  async exportHandler() {
385
420
  const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records
386
- const targetFieldSet = new Set(['id', 'name', 'type', 'description', 'schedule', 'timezone', 'active', 'dataItems'])
421
+ const targetFieldSet = new Set([
422
+ 'id',
423
+ 'name',
424
+ 'type',
425
+ 'description',
426
+ 'tag',
427
+ 'schedule',
428
+ 'timezone',
429
+ 'active',
430
+ 'dataItems'
431
+ ])
387
432
 
388
433
  return exportTargets.map(dataSet => {
389
434
  let tempObj = {}
@@ -399,11 +444,11 @@ export class DataSet extends connect(store)(localize(i18next)(PageView)) {
399
444
  openPopup(
400
445
  html`
401
446
  <data-set-importer
402
- .dataSets="${records}"
403
- @imported="${() => {
447
+ .dataSets=${records}
448
+ @imported=${() => {
404
449
  history.back()
405
450
  this.grist.fetch()
406
- }}"
451
+ }}
407
452
  ></data-set-importer>
408
453
  `,
409
454
  {
package/client/route.js CHANGED
@@ -4,6 +4,10 @@ export default function route(page) {
4
4
  import('./pages/data-set')
5
5
  return page
6
6
 
7
+ case 'data-sensor':
8
+ import('./pages/data-sensor')
9
+ return page
10
+
7
11
  case 'data-sample':
8
12
  import('./pages/data-sample')
9
13
  return page
@@ -18,4 +18,5 @@ require("./routes");
18
18
  __exportStar(require("./migrations"), exports);
19
19
  __exportStar(require("./middlewares"), exports);
20
20
  __exportStar(require("./service"), exports);
21
+ __exportStar(require("./service/data-spec/data-spec-manager"), exports);
21
22
  //# 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,+CAA4B;AAC5B,gDAA6B;AAC7B,4CAAyB;AAEzB,wEAAqD"}
@@ -1,3 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const typeorm_1 = require("typeorm");
4
+ const service_1 = require("./service");
5
+ const data_item_1 = require("./service/data-item/data-item");
6
+ const data_sensor_1 = require("./service/data-sensor/data-sensor");
1
7
  const debug = require('debug')('things-factory:dataset:routes');
2
8
  process.on('bootstrap-module-global-public-route', (app, globalPublicRouter) => {
3
9
  /*
@@ -6,6 +12,64 @@ process.on('bootstrap-module-global-public-route', (app, globalPublicRouter) =>
6
12
  * ex) routes.get('/path', async(context, next) => {})
7
13
  * ex) routes.post('/path', async(context, next) => {})
8
14
  */
15
+ globalPublicRouter.post('/sensor-data', async (context, next) => {
16
+ // 데이타 검증
17
+ const { deviceId, data, rawData, timestamp = Date.now() } = context.request.body;
18
+ if (!deviceId || !data) {
19
+ throw new Error(`deviceId(${deviceId}) and data(${JSON.stringify(data)}) properties are mandatory`);
20
+ }
21
+ // make new data-sample
22
+ await (0, typeorm_1.getConnection)().transaction(async (tx) => {
23
+ // find sensor through deviceId
24
+ const sensor = await tx.getRepository(data_sensor_1.DataSensor).findOne({
25
+ where: { deviceId },
26
+ relations: ['domain', 'appliance', 'dataSet']
27
+ });
28
+ if (!sensor) {
29
+ throw new Error(`Sensor having given deviceId(${deviceId}) not found`);
30
+ }
31
+ if (!sensor.active) {
32
+ throw new Error(`State of the sensor given deviceId(${deviceId}) is not active`);
33
+ }
34
+ if (!sensor.appliance) {
35
+ throw new Error(`Appliance of the sensor given deviceId(${deviceId}) is not set up`);
36
+ }
37
+ if (!sensor.dataSet) {
38
+ throw new Error(`DataSet of the sensor given deviceId(${deviceId}) is not set up`);
39
+ }
40
+ const domain = sensor.domain;
41
+ const dataSet = sensor.dataSet;
42
+ const user = sensor.appliance;
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
+ var spec = {};
53
+ dataItems.forEach(dataItem => {
54
+ spec[dataItem.name] = dataItem.spec;
55
+ });
56
+ await tx.getRepository(service_1.DataSample).save({
57
+ domain,
58
+ name: dataSet.name,
59
+ description: dataSet.description,
60
+ partitionKeys: dataSet.partitionKeys,
61
+ dataSet,
62
+ data,
63
+ rawData,
64
+ spec,
65
+ source: deviceId,
66
+ collectedAt: new Date(timestamp),
67
+ creator: user,
68
+ updater: user
69
+ });
70
+ });
71
+ return 'OK';
72
+ });
9
73
  });
10
74
  process.on('bootstrap-module-global-private-route', (app, globalPrivateRouter) => {
11
75
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../server/routes.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,+BAA+B,CAAC,CAAA;AAE/D,OAAO,CAAC,EAAE,CAAC,sCAA6C,EAAE,CAAC,GAAG,EAAE,kBAAkB,EAAE,EAAE;IACpF;;;;;OAKG;AACL,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,uCAA8C,EAAE,CAAC,GAAG,EAAE,mBAAmB,EAAE,EAAE;IACtF;;OAEG;AACL,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,sCAA6C,EAAE,CAAC,GAAG,EAAE,kBAAkB,EAAE,EAAE;IACpF;;OAEG;AACL,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,uCAA8C,EAAE,CAAC,GAAG,EAAE,mBAAmB,EAAE,EAAE;IACtF;;OAEG;AACL,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../server/routes.ts"],"names":[],"mappings":"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"}