@things-factory/dataset 5.0.0-zeta.7 → 5.0.0

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 (94) hide show
  1. package/client/bootstrap.js +2 -3
  2. package/client/{pages/data-entry → components}/data-entry-form.js +1 -1
  3. package/client/index.js +1 -0
  4. package/client/pages/data-entry/data-entry-list-page.js +2 -3
  5. package/client/pages/data-ooc/data-ooc-list-page.js +13 -18
  6. package/client/pages/data-ooc/data-ooc-view.js +19 -14
  7. package/client/pages/data-report/data-report-list-page.js +1 -2
  8. package/client/pages/data-sample/data-sample-list-page.js +12 -13
  9. package/client/pages/data-sample/data-sample-view.js +3 -2
  10. package/client/pages/data-sensor/data-sensor-list-page.js +1 -1
  11. package/client/pages/data-set/data-item-list.js +32 -98
  12. package/client/pages/data-set/data-set-list-page.js +3 -3
  13. package/config/config.development.js +1 -1
  14. package/config/config.production.js +13 -1
  15. package/dist-server/controllers/create-data-sample.js +10 -44
  16. package/dist-server/controllers/create-data-sample.js.map +1 -1
  17. package/dist-server/controllers/data-use-case.js +11 -5
  18. package/dist-server/controllers/data-use-case.js.map +1 -1
  19. package/dist-server/controllers/index.js +1 -1
  20. package/dist-server/controllers/index.js.map +1 -1
  21. package/dist-server/controllers/jasper-report.js +14 -9
  22. package/dist-server/controllers/jasper-report.js.map +1 -1
  23. package/dist-server/service/data-item/index.js +1 -4
  24. package/dist-server/service/data-item/index.js.map +1 -1
  25. package/dist-server/service/data-ooc/data-ooc-query.js +15 -10
  26. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -1
  27. package/dist-server/service/data-ooc/data-ooc-type.js +4 -0
  28. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -1
  29. package/dist-server/service/data-ooc/data-ooc.js +11 -14
  30. package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
  31. package/dist-server/service/data-sample/data-sample-query.js +18 -0
  32. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  33. package/dist-server/service/data-sample/data-sample-type.js +4 -0
  34. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  35. package/dist-server/service/data-sample/data-sample.js +12 -3
  36. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  37. package/dist-server/service/{data-item → data-set}/data-item-type.js +60 -33
  38. package/dist-server/service/data-set/data-item-type.js.map +1 -0
  39. package/dist-server/service/data-set/data-set-mutation.js +21 -61
  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 +4 -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 +21 -9
  44. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  45. package/dist-server/service/data-set/data-set.js +11 -3
  46. package/dist-server/service/data-set/data-set.js.map +1 -1
  47. package/dist-server/service/data-set-history/data-set-history-query.js +173 -0
  48. package/dist-server/service/data-set-history/data-set-history-query.js.map +1 -0
  49. package/dist-server/service/data-set-history/data-set-history-type.js +29 -0
  50. package/dist-server/service/data-set-history/data-set-history-type.js.map +1 -0
  51. package/dist-server/service/data-set-history/data-set-history.js +196 -0
  52. package/dist-server/service/data-set-history/data-set-history.js.map +1 -0
  53. package/dist-server/service/data-set-history/event-subscriber.js +26 -0
  54. package/dist-server/service/data-set-history/event-subscriber.js.map +1 -0
  55. package/dist-server/service/data-set-history/index.js +10 -0
  56. package/dist-server/service/data-set-history/index.js.map +1 -0
  57. package/dist-server/service/index.js +11 -4
  58. package/dist-server/service/index.js.map +1 -1
  59. package/package.json +18 -17
  60. package/server/controllers/create-data-sample.ts +13 -50
  61. package/server/controllers/data-use-case.ts +19 -7
  62. package/server/controllers/index.ts +1 -1
  63. package/server/controllers/jasper-report.ts +58 -48
  64. package/server/service/data-item/index.ts +0 -3
  65. package/server/service/data-ooc/data-ooc-query.ts +13 -8
  66. package/server/service/data-ooc/data-ooc-type.ts +3 -0
  67. package/server/service/data-ooc/data-ooc.ts +9 -14
  68. package/server/service/data-sample/data-sample-query.ts +14 -1
  69. package/server/service/data-sample/data-sample-type.ts +3 -0
  70. package/server/service/data-sample/data-sample.ts +10 -3
  71. package/server/service/data-set/data-item-type.ts +82 -0
  72. package/server/service/data-set/data-set-mutation.ts +33 -60
  73. package/server/service/data-set/data-set-query.ts +5 -0
  74. package/server/service/data-set/data-set-type.ts +9 -1
  75. package/server/service/data-set/data-set.ts +8 -4
  76. package/server/service/data-set-history/data-set-history-query.ts +110 -0
  77. package/server/service/data-set-history/data-set-history-type.ts +12 -0
  78. package/server/service/data-set-history/data-set-history.ts +161 -0
  79. package/server/service/data-set-history/event-subscriber.ts +17 -0
  80. package/server/service/data-set-history/index.ts +7 -0
  81. package/server/service/index.ts +16 -4
  82. package/translations/en.json +5 -5
  83. package/translations/ko.json +10 -10
  84. package/translations/ms.json +5 -5
  85. package/translations/zh.json +5 -5
  86. package/dist-server/service/data-item/data-item-mutation.js +0 -73
  87. package/dist-server/service/data-item/data-item-mutation.js.map +0 -1
  88. package/dist-server/service/data-item/data-item-query.js +0 -104
  89. package/dist-server/service/data-item/data-item-query.js.map +0 -1
  90. package/dist-server/service/data-item/data-item-type.js.map +0 -1
  91. package/server/service/data-item/data-item-mutation.ts +0 -61
  92. package/server/service/data-item/data-item-query.ts +0 -58
  93. package/server/service/data-item/data-item-type.ts +0 -57
  94. package/yarn-error.log +0 -23244
@@ -3,15 +3,13 @@ import { EntityManager } from 'typeorm'
3
3
 
4
4
  import { User } from '@things-factory/auth-base'
5
5
  import { Domain, getRedirectSubdomainPath, pubsub } from '@things-factory/shell'
6
+ import { getWorkDateAndShift } from '@things-factory/work-shift'
6
7
 
7
- import { DataItem } from '../service/data-item/data-item'
8
8
  import { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc'
9
9
  import { DataSample } from '../service/data-sample/data-sample'
10
10
  import { NewDataSample } from '../service/data-sample/data-sample-type'
11
11
  import { DataSet } from '../service/data-set/data-set'
12
12
  import { DataUseCase } from './data-use-case'
13
- import { getWorkDateAndShift } from '@things-factory/work-shift'
14
-
15
13
 
16
14
  const debug = require('debug')('things-factory:dataset:controller/save-data-sample')
17
15
 
@@ -56,26 +54,7 @@ export async function createDataSample(
56
54
  where: { id: dataSample.dataSet.id }
57
55
  })
58
56
 
59
- const dataItems = await tx.getRepository(DataItem).find({
60
- where: {
61
- domain,
62
- dataSet
63
- },
64
- order: {
65
- sequence: 'DESC'
66
- }
67
- })
68
-
69
- const spec = dataItems.reduce((spec, dataItem) => {
70
- spec[dataItem.tag] = {
71
- ...dataItem.spec,
72
- name: dataItem.name, /* do we need ? */
73
- hidden: dataItem.hidden
74
- }
75
-
76
- return spec
77
- }, {})
78
-
57
+ const dataItems = dataSet.dataItems
79
58
  const collectedAt = dataSample.collectedAt || new Date()
80
59
 
81
60
  const timezone = dataSet.timezone || domain.timezone || 'UTC'
@@ -83,16 +62,15 @@ export async function createDataSample(
83
62
 
84
63
  // workDate ex) 2022-04-04
85
64
  const { workDate, workShift } = await getWorkDateAndShift(domain, collectedAt, { timezone, format })
86
-
65
+
87
66
  // local time dataSet timezone or domain timezone or default 'UTC'
88
-
89
- // const collectedAt = dataSample.collectedAt || new Date()
67
+
90
68
  const localDateTz = moment(collectedAt).tz(timezone)
91
69
  const defaultPartitionKeys = {
92
70
  domain: domain.subdomain,
93
- datasetid: dataSample.dataSet.id, /* It should not be 'data_set_id' as column name duplicated for Glue */
94
- date: localDateTz.format(format), /* local time date */
95
- workdate: workDate, /* working date */
71
+ datasetid: dataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,
72
+ date: localDateTz.format(format) /* local time date */,
73
+ workdate: workDate /* working date */,
96
74
  workshift: workShift
97
75
  }
98
76
 
@@ -106,17 +84,18 @@ export async function createDataSample(
106
84
  ...dataSample.data
107
85
  })
108
86
 
109
- const { ooc, oos } = DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {}
87
+ const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {}
110
88
  const result = await tx.getRepository(DataSample).save({
111
89
  name: dataSet.name,
112
90
  description: dataSet.description,
113
91
  useCase: dataSet.useCase,
114
92
  ...dataSample,
93
+ dataSetVersion: dataSet.version,
115
94
  domain,
116
95
  partitionKeys,
117
- spec,
118
96
  ooc,
119
97
  oos,
98
+ judgment,
120
99
  collectedAt,
121
100
  workDate,
122
101
  workShift,
@@ -126,18 +105,7 @@ export async function createDataSample(
126
105
 
127
106
  if (ooc || oos) {
128
107
  const dataOoc = await tx.getRepository(DataOoc).save({
129
- name: dataSet.name,
130
- description: dataSet.description,
131
- useCase: dataSet.useCase,
132
- dataSet,
133
- dataSample: result,
134
- data: dataSample.data,
135
- rawData: dataSample.rawData,
136
- domain,
137
- partitionKeys,
138
- spec,
139
- ooc,
140
- oos,
108
+ ...result,
141
109
  history: [
142
110
  {
143
111
  user: {
@@ -148,12 +116,7 @@ export async function createDataSample(
148
116
  timestamp: Date.now()
149
117
  }
150
118
  ],
151
- state: DataOocStatus.CREATED,
152
- workDate,
153
- workShift,
154
- collectedAt,
155
- creator: user,
156
- updater: user
119
+ state: DataOocStatus.CREATED
157
120
  })
158
121
 
159
122
  pubsub.publish('data-ooc', {
@@ -174,4 +137,4 @@ export async function createDataSample(
174
137
  }
175
138
 
176
139
  return result
177
- }
140
+ }
@@ -1,4 +1,5 @@
1
- import { DataItem, DataSet } from 'server/service'
1
+ import { DataItem } from '../service/data-set/data-item-type'
2
+ import { DataSet } from '../service/data-set/data-set'
2
3
 
3
4
  export type DataItemSpec = {
4
5
  type: string
@@ -13,7 +14,11 @@ export type DataItemSpecSet = {
13
14
  specs: DataItemSpec[]
14
15
  }
15
16
 
16
- export type EvaluationResult = { oos: boolean; ooc: boolean }
17
+ export type EvaluationResult = {
18
+ oos: boolean
19
+ ooc: boolean
20
+ judgment?: { [tag: string]: { ooc: boolean; oos: boolean } }
21
+ }
17
22
 
18
23
  export abstract class DataUseCase {
19
24
  static registry: { [name: string]: DataUseCase } = {}
@@ -33,6 +38,7 @@ export abstract class DataUseCase {
33
38
  public static evaluate(dataSet: DataSet, dataItems: DataItem[], data: any): EvaluationResult {
34
39
  var ooc = false
35
40
  var oos = false
41
+ var judgment: { [tag: string]: { ooc: boolean; oos: boolean } } = {}
36
42
 
37
43
  if (!dataSet.useCase) {
38
44
  return { ooc, oos }
@@ -49,7 +55,7 @@ export abstract class DataUseCase {
49
55
  }
50
56
 
51
57
  let values: any | any[] = data[tag]
52
- if (typeof values === 'undefined') {
58
+ if (values == null) {
53
59
  continue // TODO what if in case no value ?
54
60
  }
55
61
 
@@ -57,6 +63,9 @@ export abstract class DataUseCase {
57
63
  values = [values]
58
64
  }
59
65
 
66
+ let oocForTag = false
67
+ let oosForTag = false
68
+
60
69
  for (let j = 0; j < useCases.length; j++) {
61
70
  const useCase = useCases[j]
62
71
 
@@ -68,17 +77,20 @@ export abstract class DataUseCase {
68
77
  const result = useCase.evaluate(specs, values)
69
78
 
70
79
  if (result) {
80
+ oocForTag ||= result.ooc
81
+ oosForTag ||= result.oos
71
82
  ooc ||= result.ooc
72
83
  oos ||= result.oos
73
84
  }
85
+ }
74
86
 
75
- // if (ooc && oos) {
76
- // return { ooc, oos }
77
- // }
87
+ judgment[tag] = {
88
+ ooc: oocForTag,
89
+ oos: oosForTag
78
90
  }
79
91
  }
80
92
 
81
- return { ooc, oos }
93
+ return { ooc, oos, judgment }
82
94
  }
83
95
 
84
96
  public abstract evaluate(specs: any, values: any[]): EvaluationResult
@@ -1,2 +1,2 @@
1
- export * from './data-use-case'
2
1
  export * from './create-data-sample'
2
+ export * from './data-use-case'
@@ -6,47 +6,53 @@ import { AthenaController } from '@things-factory/aws-base'
6
6
  import { config } from '@things-factory/env'
7
7
 
8
8
  const dataReportConfig = config.get('dataReport')
9
- const { jasper: {
10
- endpoint: { protocol: PROTOCOL, host:HOST, port:PORT },
11
- datasource: { database: DATABASE } }
12
- } = dataReportConfig
9
+ const {
10
+ jasper: {
11
+ endpoint: { protocol: PROTOCOL, host: HOST, port: PORT },
12
+ datasource: { database: DATABASE }
13
+ }
14
+ } = dataReportConfig || {
15
+ jasper: {
16
+ endpoint: {},
17
+ datasource: {}
18
+ }
19
+ }
13
20
 
14
- /** author: ywnam123 */
15
21
  function transformValuesToRows(queryResult) {
16
22
  var parseData = []
17
- let index = 1
18
- for (let i = 0; i < queryResult.Items.length; i++) {
19
- var j = 0
20
- const data = JSON.parse(queryResult.Items[i].data)
21
- const spec = JSON.parse(queryResult.Items[i].spec)
22
-
23
- for (let key in data) {
24
- if (Array.isArray(data[key])) {
25
- for (j = 0; j < data[key].length; j++) {
26
- for (let specKey in spec) {
27
- if (key === specKey) {
28
- parseData.push({
29
- item: spec[specKey].name,
30
- index: index + j,
31
- value: String(data[key][j])
32
- })
33
- }
23
+ let index = 1
24
+ for (let i = 0; i < queryResult.Items.length; i++) {
25
+ var j = 0
26
+ const data = JSON.parse(queryResult.Items[i].data)
27
+ const spec = JSON.parse(queryResult.Items[i].spec)
28
+
29
+ for (let key in data) {
30
+ if (Array.isArray(data[key])) {
31
+ for (j = 0; j < data[key].length; j++) {
32
+ for (let specKey in spec) {
33
+ if (key === specKey) {
34
+ parseData.push({
35
+ item: spec[specKey].name,
36
+ index: index + j,
37
+ value: String(data[key][j])
38
+ })
34
39
  }
35
40
  }
36
- } else {
37
- parseData.push({
38
- item: key,
39
- index,
40
- value: String(data[key])
41
- })
42
41
  }
43
- }
44
- if (j !== 0) {
45
- index = index + j
46
42
  } else {
47
- index = index + 1
43
+ parseData.push({
44
+ item: key,
45
+ index,
46
+ value: String(data[key])
47
+ })
48
48
  }
49
49
  }
50
+ if (j !== 0) {
51
+ index = index + j
52
+ } else {
53
+ index = index + 1
54
+ }
55
+ }
50
56
  }
51
57
 
52
58
  /** @todo considering trasformation in lambda, as massive dataset */
@@ -61,11 +67,12 @@ function pivotData(rows) {
61
67
  for (let key in data) {
62
68
  /** @todo rule to display or not, about unspecified spec */
63
69
  const value = data[key]
64
- !(spec[key]?.hidden) && parsedData.push({
65
- item: spec[key]?.name || key,
66
- index,
67
- value: Array.isArray(value) ? value.join(', ') : value
68
- })
70
+ !spec[key]?.hidden &&
71
+ parsedData.push({
72
+ item: spec[key]?.name || key,
73
+ index,
74
+ value: Array.isArray(value) ? value.join(', ') : value
75
+ })
69
76
  }
70
77
  if (j !== 0) {
71
78
  index = index + j
@@ -95,6 +102,7 @@ function parseJsonDataField(rows) {
95
102
  }
96
103
 
97
104
  const athenaClient = new AthenaController()
105
+
98
106
  async function queryAthena(params) {
99
107
  const { table, domain, dataSetId, fromWorkDate, toWorkDate, workShift, timezone } = params
100
108
  const queryData = {
@@ -108,7 +116,7 @@ async function queryAthena(params) {
108
116
  AND datasetid = '${dataSetId}'
109
117
  AND workdate >= '${fromWorkDate}'
110
118
  AND workdate <= '${toWorkDate}'
111
- ${workShift ? 'AND workshift = \'' + workShift + '\'' : ''}
119
+ ${workShift ? "AND workshift = '" + workShift + "'" : ''}
112
120
  ORDER BY collected_at`,
113
121
  db: DATABASE
114
122
  }
@@ -116,19 +124,23 @@ async function queryAthena(params) {
116
124
 
117
125
  return await athenaClient.query(queryData)
118
126
  }
119
- export async function renderJasperReport(context: any) {
120
- const { state: { domain }, query } = context
127
+
128
+ export async function renderJasperReport(context: any) {
129
+ const {
130
+ state: { domain },
131
+ query
132
+ } = context
121
133
 
122
134
  const template = await STORAGE.readFile(query['template'] || 'dynamic_header_sample.jrxml', 'utf-8')
123
135
  let templateType = query['templateType'] || 'crosstab'
124
136
  let parsedData = []
125
137
 
126
138
  // @todo: get dataset timezone
127
- /**
139
+ /**
128
140
  * const variables = await gql(dataSet(id:${dataSetId}) {
129
141
  * name, description, partition_keys, timezone
130
142
  * })
131
- */
143
+ */
132
144
 
133
145
  query['domain'] = domain?.subdomain
134
146
  query['timezone'] = domain?.timezone
@@ -137,8 +149,7 @@ export async function renderJasperReport(context: any) {
137
149
 
138
150
  if (!rows.length) {
139
151
  return '<h3>Not found result.</h3>'
140
- }
141
- else {
152
+ } else {
142
153
  const firstRow = rows[0]
143
154
  // uses the first row values as data-set has no history data.
144
155
  const parameters = {
@@ -146,18 +157,18 @@ export async function renderJasperReport(context: any) {
146
157
  description: firstRow.description,
147
158
  ...query
148
159
  }
149
-
160
+
150
161
  if (templateType === 'crosstab') {
151
162
  parsedData = pivotData(rows)
152
163
  } else {
153
164
  parsedData = parseJsonDataField(rows)
154
165
  }
155
-
166
+
156
167
  const formData = new FormData()
157
168
  formData.append('template', template)
158
169
  formData.append('jsonString', JSON.stringify(parsedData))
159
170
  formData.append('parameters', JSON.stringify(parameters))
160
-
171
+
161
172
  const reportUrl = `${PROTOCOL || 'http'}://${HOST}:${PORT}/rest/report/show_html`
162
173
  const response = await fetch(reportUrl, {
163
174
  method: 'POST',
@@ -166,5 +177,4 @@ export async function renderJasperReport(context: any) {
166
177
 
167
178
  return await response.text()
168
179
  }
169
-
170
180
  }
@@ -1,6 +1,3 @@
1
1
  import { DataItem } from './data-item'
2
- import { DataItemQuery } from './data-item-query'
3
- import { DataItemMutation } from './data-item-mutation'
4
2
 
5
3
  export const entities = [DataItem]
6
- export const resolvers = [DataItemQuery, DataItemMutation]
@@ -4,7 +4,8 @@ import { getRepository } from 'typeorm'
4
4
  import { User } from '@things-factory/auth-base'
5
5
  import { Domain, getQueryBuilderFromListParams, ListParam } from '@things-factory/shell'
6
6
 
7
- import { DataSample } from '../data-sample/data-sample'
7
+ import { DataSetHistory } from '../data-set-history/data-set-history'
8
+ import { DataItem } from '../data-set/data-item-type'
8
9
  import { DataSet } from '../data-set/data-set'
9
10
  import { DataOoc } from './data-ooc'
10
11
  import { DataOocList } from './data-ooc-type'
@@ -38,6 +39,17 @@ export class DataOocQuery {
38
39
  return { items, total }
39
40
  }
40
41
 
42
+ @FieldResolver(type => [DataItem])
43
+ async dataItems(@Root() dataOoc: DataOoc): Promise<DataItem[]> {
44
+ const dataSetHistory: DataSetHistory = await getRepository(DataSetHistory).findOne({
45
+ where: {
46
+ originalId: dataOoc.dataSetId,
47
+ version: dataOoc.dataSetVersion
48
+ }
49
+ })
50
+ return dataSetHistory?.dataItems || []
51
+ }
52
+
41
53
  @FieldResolver(type => DataSet)
42
54
  async dataSet(@Root() dataOoc: DataOoc): Promise<DataSet> {
43
55
  return await getRepository(DataSet).findOne({
@@ -45,13 +57,6 @@ export class DataOocQuery {
45
57
  })
46
58
  }
47
59
 
48
- @FieldResolver(type => DataSample)
49
- async dataSample(@Root() dataOoc: DataOoc): Promise<DataSample> {
50
- return await getRepository(DataSample).findOne({
51
- id: dataOoc.dataSampleId
52
- })
53
- }
54
-
55
60
  @FieldResolver(type => Domain)
56
61
  async domain(@Root() dataOoc: DataOoc): Promise<Domain> {
57
62
  return await getRepository(Domain).findOne(dataOoc.domainId)
@@ -15,6 +15,9 @@ export class NewDataOoc {
15
15
  @Field(type => ObjectRef, { nullable: true })
16
16
  dataSet?: ObjectRef
17
17
 
18
+ @Field({ nullable: true })
19
+ dataSetVersion?: number
20
+
18
21
  @Field(type => ObjectRef, { nullable: true })
19
22
  dataSample?: ObjectRef
20
23
 
@@ -4,9 +4,7 @@ import {
4
4
  CreateDateColumn,
5
5
  Entity,
6
6
  Index,
7
- JoinColumn,
8
7
  ManyToOne,
9
- OneToOne,
10
8
  PrimaryGeneratedColumn,
11
9
  RelationId,
12
10
  UpdateDateColumn
@@ -16,7 +14,7 @@ import { User } from '@things-factory/auth-base'
16
14
  import { config } from '@things-factory/env'
17
15
  import { Domain, ScalarObject } from '@things-factory/shell'
18
16
 
19
- import { DataSample } from '../data-sample/data-sample'
17
+ import { DataItem } from '../data-set/data-item-type'
20
18
  import { DataSet } from '../data-set/data-set'
21
19
 
22
20
  const ORMCONFIG = config.get('ormconfig', {})
@@ -34,9 +32,7 @@ registerEnumType(DataOocStatus, {
34
32
  })
35
33
 
36
34
  @Entity()
37
- @Index('ix_data_ooc_0', (dataOoc: DataOoc) => [dataOoc.domain, dataOoc.dataSet], { unique: false })
38
- @Index('ix_data_ooc_1', (dataOoc: DataOoc) => [dataOoc.domain, dataOoc.dataSample], { unique: true })
39
- @Index('ix_data_ooc_2', (dataOoc: DataOoc) => [dataOoc.domain, dataOoc.collectedAt], { unique: false })
35
+ @Index('ix_data_ooc_0', (dataOoc: DataOoc) => [dataOoc.domain, dataOoc.dataSet, dataOoc.collectedAt], { unique: false })
40
36
  @ObjectType({ description: 'Entity for Out of control data' })
41
37
  export class DataOoc {
42
38
  @PrimaryGeneratedColumn('uuid')
@@ -67,13 +63,9 @@ export class DataOoc {
67
63
  @RelationId((dataOoc: DataOoc) => dataOoc.dataSet)
68
64
  dataSetId?: string
69
65
 
70
- @OneToOne(type => DataSample)
71
- @JoinColumn()
72
- @Field(type => DataSample, { nullable: true })
73
- dataSample?: DataSample
74
-
75
- @RelationId((dataOoc: DataOoc) => dataOoc.dataSample)
76
- dataSampleId?: string
66
+ @Column({ nullable: true })
67
+ @Field({ nullable: true })
68
+ dataSetVersion?: number
77
69
 
78
70
  @Column({
79
71
  nullable: true
@@ -127,7 +119,10 @@ export class DataOoc {
127
119
 
128
120
  @Column('simple-json', { nullable: true })
129
121
  @Field(type => ScalarObject, { nullable: true })
130
- spec?: ScalarObject
122
+ judgment?: ScalarObject
123
+
124
+ @Field(type => [DataItem], { nullable: true })
125
+ dataItems?: DataItem[]
131
126
 
132
127
  @Column('simple-json', { nullable: true })
133
128
  @Field(type => ScalarObject, { nullable: true })
@@ -4,6 +4,8 @@ import { getRepository } from 'typeorm'
4
4
  import { User } from '@things-factory/auth-base'
5
5
  import { Domain, getQueryBuilderFromListParams, ListParam } from '@things-factory/shell'
6
6
 
7
+ import { DataSetHistory } from '../data-set-history/data-set-history'
8
+ import { DataItem } from '../data-set/data-item-type'
7
9
  import { DataSet } from '../data-set/data-set'
8
10
  import { DataSample } from './data-sample'
9
11
  import { DataSampleList } from './data-sample-type'
@@ -37,8 +39,19 @@ export class DataSampleQuery {
37
39
  return { items, total }
38
40
  }
39
41
 
42
+ @FieldResolver(type => [DataItem])
43
+ async dataItems(@Root() dataSample: DataSample): Promise<DataItem[]> {
44
+ const dataSetHistory: DataSetHistory = await getRepository(DataSetHistory).findOne({
45
+ where: {
46
+ originalId: dataSample.dataSetId,
47
+ version: dataSample.dataSetVersion
48
+ }
49
+ })
50
+ return dataSetHistory?.dataItems || []
51
+ }
52
+
40
53
  @FieldResolver(type => DataSet)
41
- async dataSet(@Root() dataSample: DataSample): Promise<Domain> {
54
+ async dataSet(@Root() dataSample: DataSample): Promise<DataSet> {
42
55
  return await getRepository(DataSet).findOne(dataSample.dataSetId)
43
56
  }
44
57
 
@@ -15,6 +15,9 @@ export class NewDataSample {
15
15
  @Field(type => ObjectRef, { nullable: true })
16
16
  dataSet?: ObjectRef
17
17
 
18
+ @Field({ nullable: true })
19
+ dataSetVersion?: number
20
+
18
21
  @Field(type => ScalarObject, { nullable: true })
19
22
  data?: ScalarObject
20
23
 
@@ -14,14 +14,14 @@ import { User } from '@things-factory/auth-base'
14
14
  import { config } from '@things-factory/env'
15
15
  import { Domain, ScalarObject } from '@things-factory/shell'
16
16
 
17
+ import { DataItem } from '../data-set/data-item-type'
17
18
  import { DataSet } from '../data-set/data-set'
18
19
 
19
20
  const ORMCONFIG = config.get('ormconfig', {})
20
21
  const DATABASE_TYPE = ORMCONFIG.type
21
22
  @Entity()
22
- @Index('ix_data_sample_0', (dataSample: DataSample) => [dataSample.domain, dataSample.dataSet], { unique: false })
23
23
  @Index(
24
- 'ix_data_sample_2',
24
+ 'ix_data_sample_0',
25
25
  (dataSample: DataSample) => [dataSample.domain, dataSample.dataSet, dataSample.collectedAt],
26
26
  { unique: false }
27
27
  )
@@ -71,13 +71,20 @@ export class DataSample {
71
71
  @RelationId((dataSample: DataSample) => dataSample.dataSet)
72
72
  dataSetId?: string
73
73
 
74
+ @Column({ nullable: true })
75
+ @Field({ nullable: true })
76
+ dataSetVersion?: number
77
+
74
78
  @Column('simple-json', { nullable: true })
75
79
  @Field(type => ScalarObject, { nullable: true })
76
80
  data?: ScalarObject
77
81
 
78
82
  @Column('simple-json', { nullable: true })
79
83
  @Field(type => ScalarObject, { nullable: true })
80
- spec?: ScalarObject
84
+ judgment?: ScalarObject
85
+
86
+ @Field(type => [DataItem], { nullable: true })
87
+ dataItems?: DataItem[]
81
88
 
82
89
  @Column({
83
90
  nullable: true,
@@ -0,0 +1,82 @@
1
+ import { Field, InputType, Int, ObjectType, registerEnumType } from 'type-graphql'
2
+
3
+ import { ScalarObject } from '@things-factory/shell'
4
+
5
+ export enum DataItemType {
6
+ number = 'number',
7
+ text = 'text',
8
+ boolean = 'boolean',
9
+ select = 'select',
10
+ file = 'file'
11
+ }
12
+
13
+ registerEnumType(DataItemType, {
14
+ name: 'DataItemType',
15
+ description: 'state enumeration of a data-item'
16
+ })
17
+
18
+ @ObjectType({ description: 'Entity for DataItem' })
19
+ export class DataItem {
20
+ @Field()
21
+ name: string
22
+
23
+ @Field({ nullable: true })
24
+ description?: string
25
+
26
+ @Field({ nullable: true })
27
+ tag?: string
28
+
29
+ @Field({ nullable: true })
30
+ active?: boolean
31
+
32
+ @Field({ nullable: true })
33
+ hidden?: boolean
34
+
35
+ @Field({ nullable: true })
36
+ type?: DataItemType
37
+
38
+ @Field(type => ScalarObject, { nullable: true })
39
+ options?: ScalarObject
40
+
41
+ @Field({ nullable: true })
42
+ unit?: string
43
+
44
+ @Field(type => Int, { nullable: true })
45
+ quota: number
46
+
47
+ @Field(type => ScalarObject, { nullable: true })
48
+ spec?: ScalarObject
49
+ }
50
+
51
+ @InputType()
52
+ export class DataItemPatch {
53
+ @Field({ nullable: true })
54
+ name?: string
55
+
56
+ @Field({ nullable: true })
57
+ description?: string
58
+
59
+ @Field({ nullable: true })
60
+ tag?: string
61
+
62
+ @Field(type => DataItemType, { nullable: true })
63
+ type?: DataItemType
64
+
65
+ @Field(type => ScalarObject, { nullable: true })
66
+ options?: ScalarObject
67
+
68
+ @Field({ nullable: true })
69
+ unit?: string
70
+
71
+ @Field(type => Int, { nullable: true })
72
+ quota?: number
73
+
74
+ @Field({ nullable: true })
75
+ active?: boolean
76
+
77
+ @Field({ nullable: true })
78
+ hidden?: boolean
79
+
80
+ @Field(type => ScalarObject, { nullable: true })
81
+ spec?: ScalarObject
82
+ }