@things-factory/dataset 7.0.0-alpha.6 → 7.0.0-alpha.8
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.
- package/client/activities/activity-data-collect-view.ts +7 -0
- package/client/activities/activity-data-review-edit.ts +66 -4
- package/client/activities/activity-data-review-view.ts +78 -4
- package/client/activities/activity-ooc-resolve-view.ts +12 -0
- package/client/activities/activity-ooc-review-view.ts +12 -0
- package/client/pages/data-ooc/data-ooc-list-page.ts +50 -21
- package/client/pages/data-ooc/data-ooc-page.ts +44 -0
- package/client/pages/data-ooc/data-ooc-view.ts +158 -19
- package/client/pages/data-ooc/data-oocs-page.ts +71 -3
- package/client/pages/data-sample/data-sample-list-page.ts +33 -16
- package/client/pages/data-sample/data-sample-page.ts +7 -0
- package/client/pages/data-sample/data-sample-search-page.ts +12 -12
- package/client/pages/data-sample/data-sample-view.ts +145 -22
- package/client/pages/data-sample/data-samples-page.ts +133 -5
- package/client/pages/data-sensor/data-sensor-list-page.ts +28 -6
- package/client/pages/data-set/data-item-list.ts +2 -2
- package/client/pages/data-summary/data-summary-list-page.ts +12 -24
- package/dist-client/activities/activity-data-collect-view.js +7 -0
- package/dist-client/activities/activity-data-collect-view.js.map +1 -1
- package/dist-client/activities/activity-data-review-edit.d.ts +1 -1
- package/dist-client/activities/activity-data-review-edit.js +63 -5
- package/dist-client/activities/activity-data-review-edit.js.map +1 -1
- package/dist-client/activities/activity-data-review-view.d.ts +1 -1
- package/dist-client/activities/activity-data-review-view.js +75 -5
- package/dist-client/activities/activity-data-review-view.js.map +1 -1
- package/dist-client/activities/activity-ooc-resolve-view.js +12 -0
- package/dist-client/activities/activity-ooc-resolve-view.js.map +1 -1
- package/dist-client/activities/activity-ooc-review-view.js +12 -0
- package/dist-client/activities/activity-ooc-review-view.js.map +1 -1
- package/dist-client/pages/data-ooc/data-ooc-list-page.js +50 -21
- package/dist-client/pages/data-ooc/data-ooc-list-page.js.map +1 -1
- package/dist-client/pages/data-ooc/data-ooc-page.js +44 -0
- package/dist-client/pages/data-ooc/data-ooc-page.js.map +1 -1
- package/dist-client/pages/data-ooc/data-ooc-view.d.ts +6 -3
- package/dist-client/pages/data-ooc/data-ooc-view.js +155 -22
- package/dist-client/pages/data-ooc/data-ooc-view.js.map +1 -1
- package/dist-client/pages/data-ooc/data-oocs-page.d.ts +1 -0
- package/dist-client/pages/data-ooc/data-oocs-page.js +71 -3
- package/dist-client/pages/data-ooc/data-oocs-page.js.map +1 -1
- package/dist-client/pages/data-sample/data-sample-list-page.js +33 -16
- package/dist-client/pages/data-sample/data-sample-list-page.js.map +1 -1
- package/dist-client/pages/data-sample/data-sample-page.js +7 -0
- package/dist-client/pages/data-sample/data-sample-page.js.map +1 -1
- package/dist-client/pages/data-sample/data-sample-search-page.js +12 -12
- package/dist-client/pages/data-sample/data-sample-search-page.js.map +1 -1
- package/dist-client/pages/data-sample/data-sample-view.d.ts +18 -0
- package/dist-client/pages/data-sample/data-sample-view.js +144 -21
- package/dist-client/pages/data-sample/data-sample-view.js.map +1 -1
- package/dist-client/pages/data-sample/data-samples-page.d.ts +2 -0
- package/dist-client/pages/data-sample/data-samples-page.js +134 -5
- package/dist-client/pages/data-sample/data-samples-page.js.map +1 -1
- package/dist-client/pages/data-sensor/data-sensor-list-page.js +28 -6
- package/dist-client/pages/data-sensor/data-sensor-list-page.js.map +1 -1
- package/dist-client/pages/data-set/data-item-list.js +2 -2
- package/dist-client/pages/data-set/data-item-list.js.map +1 -1
- package/dist-client/pages/data-summary/data-summary-list-page.js +12 -21
- package/dist-client/pages/data-summary/data-summary-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/activities/activity-data-collect.js.map +1 -1
- package/dist-server/activities/activity-data-review.js.map +1 -1
- package/dist-server/activities/activity-ooc-review.js +3 -2
- package/dist-server/activities/activity-ooc-review.js.map +1 -1
- package/dist-server/controllers/create-data-sample.js +27 -29
- package/dist-server/controllers/create-data-sample.js.map +1 -1
- package/dist-server/controllers/issue-collect-data.js +55 -0
- package/dist-server/controllers/issue-collect-data.js.map +1 -0
- package/dist-server/engine/index.js +4 -0
- package/dist-server/engine/index.js.map +1 -0
- package/dist-server/engine/task/create-data-sample.js +80 -0
- package/dist-server/engine/task/create-data-sample.js.map +1 -0
- package/dist-server/engine/task/index.js +5 -0
- package/dist-server/engine/task/index.js.map +1 -0
- package/dist-server/engine/task/issue-collect-data.js +40 -0
- package/dist-server/engine/task/issue-collect-data.js.map +1 -0
- package/dist-server/index.js +1 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/routes.js +36 -65
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-query.js +32 -0
- package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc.js +15 -26
- package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
- package/dist-server/service/data-sample/data-sample-query.js +24 -0
- package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
- package/dist-server/service/data-sample/data-sample.js +17 -21
- package/dist-server/service/data-sample/data-sample.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor-query.js +16 -1
- package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor-type.js +8 -0
- package/dist-server/service/data-sensor/data-sensor-type.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor.js +15 -1
- package/dist-server/service/data-sensor/data-sensor.js.map +1 -1
- package/dist-server/service/data-set/data-item-type.js +1 -0
- package/dist-server/service/data-set/data-item-type.js.map +1 -1
- package/dist-server/service/data-set/data-set-query.js +2 -2
- package/dist-server/service/data-set/data-set-query.js.map +1 -1
- package/dist-server/service/data-summary/data-summary.js +8 -8
- package/dist-server/service/data-summary/data-summary.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/dataset/task/create-data-sample.ja.md +28 -0
- package/helps/dataset/task/create-data-sample.ko.md +28 -0
- package/helps/dataset/task/create-data-sample.md +28 -0
- package/helps/dataset/task/create-data-sample.ms.md +30 -0
- package/helps/dataset/task/create-data-sample.zh.md +28 -0
- package/helps/dataset/task/issue-collect-data.ja.md +35 -0
- package/helps/dataset/task/issue-collect-data.ko.md +32 -0
- package/helps/dataset/task/issue-collect-data.md +32 -0
- package/helps/dataset/task/issue-collect-data.ms.md +34 -0
- package/helps/dataset/task/issue-collect-data.zh.md +32 -0
- package/package.json +11 -11
- package/server/activities/activity-data-collect.ts +3 -11
- package/server/activities/activity-data-review.ts +1 -5
- package/server/activities/activity-ooc-review.ts +6 -16
- package/server/controllers/create-data-sample.ts +31 -38
- package/server/controllers/issue-collect-data.ts +61 -0
- package/server/engine/index.ts +1 -0
- package/server/engine/task/create-data-sample.ts +92 -0
- package/server/engine/task/index.ts +2 -0
- package/server/engine/task/issue-collect-data.ts +45 -0
- package/server/index.ts +1 -0
- package/server/routes.ts +47 -76
- package/server/service/data-ooc/data-ooc-query.ts +17 -0
- package/server/service/data-ooc/data-ooc.ts +17 -28
- package/server/service/data-sample/data-sample-query.ts +17 -17
- package/server/service/data-sample/data-sample.ts +18 -23
- package/server/service/data-sensor/data-sensor-query.ts +13 -1
- package/server/service/data-sensor/data-sensor-type.ts +6 -0
- package/server/service/data-sensor/data-sensor.ts +13 -11
- package/server/service/data-set/data-item-type.ts +1 -0
- package/server/service/data-set/data-set-query.ts +7 -7
- package/server/service/data-summary/data-summary.ts +10 -23
- package/translations/en.json +14 -2
- package/translations/ja.json +11 -1
- package/translations/ko.json +13 -1
- package/translations/ms.json +10 -0
- package/translations/zh.json +11 -1
@@ -55,16 +55,16 @@ const formatDate = (keys, _moment) => {
|
|
55
55
|
return keys
|
56
56
|
}
|
57
57
|
|
58
|
-
export async function createDataSample(
|
58
|
+
export async function createDataSample(newDataSample: NewDataSample, context: ResolverContext): Promise<DataSample> {
|
59
59
|
const { domain, user, tx } = context.state
|
60
60
|
|
61
61
|
const dataSet = await tx.getRepository(DataSet).findOne({
|
62
|
-
where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id:
|
62
|
+
where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: newDataSample.dataSet.id },
|
63
63
|
relations: ['dataKeySet']
|
64
64
|
})
|
65
65
|
|
66
66
|
const { dataItems, tag: publishTag, normalScenarioId, outlierScenarioId } = dataSet
|
67
|
-
const collectedAt =
|
67
|
+
const collectedAt = newDataSample.collectedAt || new Date()
|
68
68
|
|
69
69
|
const timezone = dataSet.timezone || domain.timezone || 'UTC'
|
70
70
|
const format = 'YYYY-MM-DD'
|
@@ -77,7 +77,7 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
77
77
|
const localDateTz = moment(collectedAt).tz(timezone)
|
78
78
|
const defaultPartitionKeys = {
|
79
79
|
domain: domain.subdomain,
|
80
|
-
datasetid:
|
80
|
+
datasetid: newDataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,
|
81
81
|
date: localDateTz.format(format) /* local time date */,
|
82
82
|
workdate: workDate /* working date */,
|
83
83
|
workshift: workShift
|
@@ -89,11 +89,11 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
89
89
|
}
|
90
90
|
|
91
91
|
partitionKeys = formatDate(partitionKeys, localDateTz)
|
92
|
-
partitionKeys = replaceVariables(partitionKeys,
|
92
|
+
partitionKeys = replaceVariables(partitionKeys, newDataSample.data)
|
93
93
|
|
94
|
-
const dataKeys = fillDataKeys(dataSet?.dataKeySet,
|
94
|
+
const dataKeys = fillDataKeys(dataSet?.dataKeySet, newDataSample.data)
|
95
95
|
|
96
|
-
const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems,
|
96
|
+
const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems, newDataSample.data) || {}
|
97
97
|
|
98
98
|
const old = await tx.getRepository(DataSample).findOne({
|
99
99
|
where: {
|
@@ -110,7 +110,7 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
110
110
|
If [FileUpload[]] type needed, add 'files' type for dataset
|
111
111
|
*/
|
112
112
|
|
113
|
-
const data =
|
113
|
+
const data = newDataSample.data
|
114
114
|
const attachments = []
|
115
115
|
|
116
116
|
for (let dataItem of dataItems) {
|
@@ -164,13 +164,13 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
164
164
|
}
|
165
165
|
}
|
166
166
|
|
167
|
-
const
|
167
|
+
const dataSample = await tx.getRepository(DataSample).save({
|
168
168
|
...old,
|
169
169
|
name: dataSet.name,
|
170
170
|
description: dataSet.description,
|
171
171
|
useCase: dataSet.useCase,
|
172
172
|
type: dataSet.type,
|
173
|
-
...
|
173
|
+
...newDataSample,
|
174
174
|
...dataKeys,
|
175
175
|
dataSetVersion: dataSet.version,
|
176
176
|
domain,
|
@@ -197,13 +197,13 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
197
197
|
|
198
198
|
/* post-process for for file attachment. */
|
199
199
|
if (attachments.length > 0) {
|
200
|
-
attachments.forEach(attachment => (attachment.refId =
|
200
|
+
attachments.forEach(attachment => (attachment.refId = dataSample.id))
|
201
201
|
tx.getRepository(Attachment).save(attachments)
|
202
202
|
}
|
203
203
|
|
204
204
|
if (ooc || oos) {
|
205
205
|
const dataOoc = await tx.getRepository(DataOoc).save({
|
206
|
-
...
|
206
|
+
...dataSample,
|
207
207
|
history: [
|
208
208
|
{
|
209
209
|
user: {
|
@@ -214,7 +214,8 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
214
214
|
timestamp: collectedAt
|
215
215
|
}
|
216
216
|
],
|
217
|
-
state: DataOocStatus.ISSUED
|
217
|
+
state: DataOocStatus.ISSUED,
|
218
|
+
dataSample: dataSample
|
218
219
|
})
|
219
220
|
|
220
221
|
if (outlierScenarioId) {
|
@@ -227,9 +228,9 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
227
228
|
})
|
228
229
|
|
229
230
|
if (scenario) {
|
230
|
-
scenario.start(scenario.name + ':' + dataSet.name + ':' +
|
231
|
+
scenario.start(scenario.name + ':' + dataSet.name + ':' + dataSample.id, {
|
231
232
|
dataOocId: dataOoc.id,
|
232
|
-
dataSampleId:
|
233
|
+
dataSampleId: dataSample.id,
|
233
234
|
dataSet: dataSet.id,
|
234
235
|
data,
|
235
236
|
ooc,
|
@@ -260,9 +261,7 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
260
261
|
})) as Activity
|
261
262
|
|
262
263
|
if (activity) {
|
263
|
-
const assignee =
|
264
|
-
dataSet.supervisoryRoleId &&
|
265
|
-
(await tx.getRepository(Role).findOneBy({ domain: { id: domain.id }, id: dataSet.supervisoryRoleId }))
|
264
|
+
const assignee = dataSet.supervisoryRoleId && (await tx.getRepository(Role).findOneBy({ domain: { id: domain.id }, id: dataSet.supervisoryRoleId }))
|
266
265
|
|
267
266
|
const assignees = dataSet.supervisoryRoleId ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assignee }] : []
|
268
267
|
|
@@ -280,11 +279,10 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
280
279
|
approvalLine: []
|
281
280
|
}
|
282
281
|
|
283
|
-
await issue(activityInstance, context)
|
282
|
+
dataOoc.reviewActivityInstance = await issue(activityInstance, context)
|
283
|
+
await tx.getRepository(DataOoc).save(dataOoc)
|
284
284
|
} else {
|
285
|
-
console.error(
|
286
|
-
`Assignees are not set. So Data OOC Review task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`
|
287
|
-
)
|
285
|
+
console.error(`Assignees are not set. So Data OOC Review task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`)
|
288
286
|
}
|
289
287
|
} else {
|
290
288
|
console.error('OOC Review Activity not installed.')
|
@@ -320,8 +318,8 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
320
318
|
})
|
321
319
|
|
322
320
|
if (scenario) {
|
323
|
-
scenario.start(scenario.name + ':' + dataSet.name + ':' +
|
324
|
-
dataSampleId:
|
321
|
+
scenario.start(scenario.name + ':' + dataSet.name + ':' + dataSample.id, {
|
322
|
+
dataSampleId: dataSample.id,
|
325
323
|
dataSet: dataSet.id,
|
326
324
|
data,
|
327
325
|
ooc,
|
@@ -353,30 +351,27 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
353
351
|
})) as Activity
|
354
352
|
|
355
353
|
if (activity) {
|
356
|
-
const assignee =
|
357
|
-
dataSet.supervisoryRoleId &&
|
358
|
-
(await tx.getRepository(Role).findOneBy({ domain: { id: domain.id }, id: dataSet.supervisoryRoleId }))
|
354
|
+
const assignee = dataSet.supervisoryRoleId && (await tx.getRepository(Role).findOneBy({ domain: { id: domain.id }, id: dataSet.supervisoryRoleId }))
|
359
355
|
|
360
|
-
const assignees = dataSet.supervisoryRoleId
|
361
|
-
? [{ type: 'Role', value: dataSet.supervisoryRoleId, assignee }]
|
362
|
-
: []
|
356
|
+
const assignees = dataSet.supervisoryRoleId ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assignee }] : []
|
363
357
|
|
364
358
|
/* 해당 dataset의 supervisor로 하여금, data를 리뷰하고 instruction을 작성해서, approvalLine을 이용해서 승인을 한다. */
|
365
359
|
if (assignees && assignees instanceof Array && assignees.length > 0) {
|
366
|
-
|
360
|
+
dataSample.dataItems = dataItems
|
367
361
|
const activityInstance = {
|
368
362
|
name: `[Data 검토] ${dataSet.name}`,
|
369
363
|
description: dataSet.description,
|
370
364
|
activityId: activity.id,
|
371
365
|
dueAt: new Date(collectedAt.getTime() + 24 * 60 * 60 * 1000),
|
372
366
|
input: {
|
373
|
-
|
367
|
+
dataSampleId: dataSample.id
|
374
368
|
},
|
375
369
|
assignees,
|
376
370
|
approvalLine: dataSet.reviewApprovalLine
|
377
371
|
}
|
378
372
|
|
379
|
-
await issue(activityInstance, context)
|
373
|
+
dataSample.reviewActivityInstance = await issue(activityInstance, context)
|
374
|
+
await tx.getRepository(DataSample).save(dataSample)
|
380
375
|
|
381
376
|
try {
|
382
377
|
pubsub.publish('notification', {
|
@@ -385,7 +380,7 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
385
380
|
type: 'info',
|
386
381
|
title: `[Data Review] ${dataSet.name}`,
|
387
382
|
body: `Data Review occurred on '${dataSet.name}'`,
|
388
|
-
url: getRedirectSubdomainPath(context, domain.subdomain, `/data-sample/${
|
383
|
+
url: getRedirectSubdomainPath(context, domain.subdomain, `/data-sample/${dataSample.id}`),
|
389
384
|
timestamp: collectedAt
|
390
385
|
}
|
391
386
|
})
|
@@ -393,9 +388,7 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
393
388
|
logger.error('Notification', err)
|
394
389
|
}
|
395
390
|
} else {
|
396
|
-
console.error(
|
397
|
-
`Assignees are not set. So Data Review task for ${dataSet.name}(${dataSet.id}) could not be issued.`
|
398
|
-
)
|
391
|
+
console.error(`Assignees are not set. So Data Review task for ${dataSet.name}(${dataSet.id}) could not be issued.`)
|
399
392
|
}
|
400
393
|
} else {
|
401
394
|
console.error('Data Review Activity not installed.')
|
@@ -403,5 +396,5 @@ export async function createDataSample(dataSample: NewDataSample, context: Resol
|
|
403
396
|
}
|
404
397
|
}
|
405
398
|
|
406
|
-
return
|
399
|
+
return dataSample
|
407
400
|
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { In } from 'typeorm'
|
2
|
+
|
3
|
+
import { Domain, getDataSource } from '@things-factory/shell'
|
4
|
+
import { Activity, ActivityInstance, issue } from '@things-factory/worklist'
|
5
|
+
|
6
|
+
import { DataSet } from '../service/data-set/data-set'
|
7
|
+
|
8
|
+
export async function issueCollectData(domainId: string, dataSetId: string, context: ResolverContext): Promise<ActivityInstance> {
|
9
|
+
await getDataSource().transaction(async tx => {
|
10
|
+
const domain = await tx.getRepository(Domain).findOneBy({ id: domainId })
|
11
|
+
|
12
|
+
if (!domain) {
|
13
|
+
throw new Error(`domain(${domainId}) not found`)
|
14
|
+
}
|
15
|
+
|
16
|
+
const dataSet = await tx.getRepository(DataSet).findOne({
|
17
|
+
where: {
|
18
|
+
domain: {
|
19
|
+
id: In([domain.id, domain.parentId].filter(Boolean))
|
20
|
+
},
|
21
|
+
id: dataSetId
|
22
|
+
}
|
23
|
+
})
|
24
|
+
|
25
|
+
const activity = (await tx.getRepository(Activity).findOneBy({
|
26
|
+
domain: { id: domain.id },
|
27
|
+
name: 'Collect Data'
|
28
|
+
})) as Activity
|
29
|
+
|
30
|
+
if (activity) {
|
31
|
+
const { assignees } = dataSet
|
32
|
+
|
33
|
+
/* 해당 dataset에 대한 데이타 수집 태스크를 dataset assignees에게 할당한다. */
|
34
|
+
if (assignees && assignees instanceof Array && assignees.length > 0) {
|
35
|
+
const activityInstance = {
|
36
|
+
name: `[Data 수집] ${dataSet.name}`,
|
37
|
+
description: dataSet.description,
|
38
|
+
activityId: activity.id,
|
39
|
+
dueAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
|
40
|
+
input: {
|
41
|
+
dataSetId: dataSet.id,
|
42
|
+
dataSetName: dataSet.name
|
43
|
+
},
|
44
|
+
assignees
|
45
|
+
}
|
46
|
+
|
47
|
+
context.state = {
|
48
|
+
...context.state,
|
49
|
+
domain,
|
50
|
+
tx
|
51
|
+
}
|
52
|
+
|
53
|
+
return await issue(activityInstance, context)
|
54
|
+
} else {
|
55
|
+
throw new Error(`Assignees not set. So Data Collect Activity for ${dataSet.name}($dataSet.id) could not be issued.`)
|
56
|
+
}
|
57
|
+
} else {
|
58
|
+
throw new Error(`Data Collect Activity is not installed.`)
|
59
|
+
}
|
60
|
+
})
|
61
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
import './task'
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import { TaskRegistry, InputStep, Context } from '@things-factory/integration-base'
|
2
|
+
import { getDataSource } from '@things-factory/shell'
|
3
|
+
import { access } from '@things-factory/utils'
|
4
|
+
import i18next from 'i18next'
|
5
|
+
|
6
|
+
import { DataSet } from '../../service/data-set/data-set'
|
7
|
+
|
8
|
+
import { createDataSample } from '../../controllers/create-data-sample'
|
9
|
+
|
10
|
+
async function CreateDataSample(step: InputStep, context: Context) {
|
11
|
+
const { logger, data, domain, user, lng } = context
|
12
|
+
var {
|
13
|
+
params: { dataset: dataSetId, source: sourceAccessor, rawData: rawDataAccessor, data: dataAccessor, timestamp }
|
14
|
+
} = step
|
15
|
+
|
16
|
+
if (!dataSetId) {
|
17
|
+
throw new Error(`no dataset found`)
|
18
|
+
}
|
19
|
+
|
20
|
+
// make new data-sample
|
21
|
+
await getDataSource().transaction(async tx => {
|
22
|
+
const dataSet = await tx.getRepository(DataSet).findOne({
|
23
|
+
where: {
|
24
|
+
id: dataSetId
|
25
|
+
}
|
26
|
+
})
|
27
|
+
|
28
|
+
var source = await access(sourceAccessor, data)
|
29
|
+
var extractedData = await access(dataAccessor, data)
|
30
|
+
var extractedRawData = rawDataAccessor && (await access(rawDataAccessor, data))
|
31
|
+
|
32
|
+
const dataSample = await createDataSample(
|
33
|
+
{
|
34
|
+
dataSet,
|
35
|
+
data: extractedData,
|
36
|
+
rawData: extractedRawData,
|
37
|
+
source,
|
38
|
+
collectedAt: new Date(timestamp || new Date())
|
39
|
+
},
|
40
|
+
{
|
41
|
+
t: i18next.t,
|
42
|
+
state: {
|
43
|
+
domain,
|
44
|
+
user,
|
45
|
+
lng,
|
46
|
+
tx
|
47
|
+
}
|
48
|
+
}
|
49
|
+
)
|
50
|
+
|
51
|
+
return {
|
52
|
+
data: dataSample
|
53
|
+
}
|
54
|
+
})
|
55
|
+
}
|
56
|
+
|
57
|
+
CreateDataSample.parameterSpec = [
|
58
|
+
{
|
59
|
+
type: 'entity-selector',
|
60
|
+
name: 'dataset',
|
61
|
+
label: 'data-set',
|
62
|
+
property: {
|
63
|
+
queryName: 'dataSets',
|
64
|
+
valueKey: 'id'
|
65
|
+
}
|
66
|
+
},
|
67
|
+
{
|
68
|
+
type: 'string',
|
69
|
+
name: 'source',
|
70
|
+
label: 'source'
|
71
|
+
},
|
72
|
+
{
|
73
|
+
type: 'string',
|
74
|
+
name: 'rawData',
|
75
|
+
label: 'raw-data'
|
76
|
+
},
|
77
|
+
{
|
78
|
+
type: 'string',
|
79
|
+
name: 'data',
|
80
|
+
label: 'data'
|
81
|
+
},
|
82
|
+
{
|
83
|
+
type: 'string',
|
84
|
+
name: 'timestamp',
|
85
|
+
label: 'timestamp'
|
86
|
+
}
|
87
|
+
]
|
88
|
+
|
89
|
+
CreateDataSample.connectorFree = true
|
90
|
+
CreateDataSample.help = 'dataset/task/create-data-sample'
|
91
|
+
|
92
|
+
TaskRegistry.registerTaskHandler('create-data-sample', CreateDataSample)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { TaskRegistry, InputStep, Context } from '@things-factory/integration-base'
|
2
|
+
import { issueCollectData } from '../../controllers/issue-collect-data'
|
3
|
+
import i18next from 'i18next'
|
4
|
+
|
5
|
+
async function IssueCollectData(step: InputStep, context: Context) {
|
6
|
+
const { logger, data, domain, user, lng } = context
|
7
|
+
var {
|
8
|
+
params: { dataset: dataSetId }
|
9
|
+
} = step
|
10
|
+
|
11
|
+
if (!dataSetId) {
|
12
|
+
throw new Error(`no dataset found`)
|
13
|
+
}
|
14
|
+
|
15
|
+
const activityInstance = await issueCollectData(domain.id, dataSetId, {
|
16
|
+
t: i18next.t,
|
17
|
+
state: {
|
18
|
+
domain,
|
19
|
+
user,
|
20
|
+
lng,
|
21
|
+
tx: undefined
|
22
|
+
}
|
23
|
+
})
|
24
|
+
|
25
|
+
return {
|
26
|
+
data: activityInstance
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
IssueCollectData.parameterSpec = [
|
31
|
+
{
|
32
|
+
type: 'entity-selector',
|
33
|
+
name: 'dataset',
|
34
|
+
label: 'data-set',
|
35
|
+
property: {
|
36
|
+
queryName: 'dataSets',
|
37
|
+
valueKey: 'id'
|
38
|
+
}
|
39
|
+
}
|
40
|
+
]
|
41
|
+
|
42
|
+
IssueCollectData.connectorFree = true
|
43
|
+
IssueCollectData.help = 'dataset/task/issue-collect-data'
|
44
|
+
|
45
|
+
TaskRegistry.registerTaskHandler('issue-collect-data', IssueCollectData)
|
package/server/index.ts
CHANGED
package/server/routes.ts
CHANGED
@@ -2,13 +2,13 @@ import { In } from 'typeorm'
|
|
2
2
|
|
3
3
|
import { Domain, getDataSource } from '@things-factory/shell'
|
4
4
|
import { User } from '@things-factory/auth-base'
|
5
|
-
import {
|
6
|
-
import { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'
|
5
|
+
import { runScenario } from '@things-factory/integration-base'
|
7
6
|
import { ScheduleRegisterRequest } from '@things-factory/scheduler-client'
|
8
7
|
|
9
8
|
import { createDataSample } from './controllers/create-data-sample'
|
10
9
|
import { renderJasperReport } from './controllers/jasper-report'
|
11
10
|
import { renderShinyReport } from './controllers/shiny-report'
|
11
|
+
import { issueCollectData } from './controllers/issue-collect-data'
|
12
12
|
import { DataSensor } from './service/data-sensor/data-sensor'
|
13
13
|
import { DataSet } from './service/data-set/data-set'
|
14
14
|
|
@@ -23,8 +23,8 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
23
23
|
globalPublicRouter.post('/sensor-data', async (context, next) => {
|
24
24
|
// 데이타 검증
|
25
25
|
const { deviceId, data, rawData, timestamp = Date.now() } = context.request.body
|
26
|
-
if (!deviceId
|
27
|
-
throw new Error(`deviceId(${deviceId})
|
26
|
+
if (!deviceId) {
|
27
|
+
throw new Error(`The deviceId(${deviceId}) property are mandatory`)
|
28
28
|
}
|
29
29
|
|
30
30
|
// make new data-sample
|
@@ -32,7 +32,7 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
32
32
|
// find sensor through deviceId
|
33
33
|
const sensor = await tx.getRepository(DataSensor).findOne({
|
34
34
|
where: { deviceId },
|
35
|
-
relations: ['domain', 'appliance', 'dataSet']
|
35
|
+
relations: ['domain', 'appliance', 'dataSet', 'decoder']
|
36
36
|
})
|
37
37
|
|
38
38
|
if (!sensor) {
|
@@ -47,18 +47,18 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
47
47
|
throw new Error(`Appliance of the sensor given deviceId(${deviceId}) is not set up`)
|
48
48
|
}
|
49
49
|
|
50
|
-
if (!sensor.dataSet) {
|
51
|
-
|
52
|
-
}
|
50
|
+
// if (!sensor.dataSet) {
|
51
|
+
// throw new Error(`DataSet of the sensor given deviceId(${deviceId}) is not set up`)
|
52
|
+
// }
|
53
53
|
|
54
54
|
const domain = sensor.domain
|
55
55
|
const dataSet = sensor.dataSet
|
56
|
-
const user: User = await tx.getRepository(User).findOne({
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
})
|
56
|
+
// const user: User = await tx.getRepository(User).findOne({
|
57
|
+
// where: {
|
58
|
+
// reference: sensor.appliance.id,
|
59
|
+
// userType: 'appliance'
|
60
|
+
// }
|
61
|
+
// })
|
62
62
|
|
63
63
|
context.state = {
|
64
64
|
...context.state,
|
@@ -66,19 +66,40 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
66
66
|
tx
|
67
67
|
}
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
var decoded
|
70
|
+
if (sensor.decoder) {
|
71
|
+
const { name: scenarioName } = sensor.decoder
|
72
|
+
const variables = {
|
73
|
+
dataSensor: sensor,
|
74
|
+
source: deviceId,
|
72
75
|
data,
|
73
76
|
rawData,
|
74
|
-
|
75
|
-
|
76
|
-
},
|
77
|
-
context
|
78
|
-
)
|
79
|
-
})
|
77
|
+
timestamp
|
78
|
+
}
|
80
79
|
|
81
|
-
|
80
|
+
decoded = (await runScenario(null, scenarioName, variables, context))?.result
|
81
|
+
}
|
82
|
+
|
83
|
+
if (dataSet) {
|
84
|
+
await createDataSample(
|
85
|
+
{
|
86
|
+
dataSet,
|
87
|
+
data,
|
88
|
+
rawData,
|
89
|
+
source: deviceId,
|
90
|
+
collectedAt: new Date(timestamp),
|
91
|
+
...decoded
|
92
|
+
},
|
93
|
+
context
|
94
|
+
)
|
95
|
+
}
|
96
|
+
|
97
|
+
context.status = 200
|
98
|
+
context.body = {
|
99
|
+
data,
|
100
|
+
...decoded
|
101
|
+
}
|
102
|
+
})
|
82
103
|
})
|
83
104
|
|
84
105
|
/* When a callback occurs from the scheduler when a scheduled dataset is on schedule, data collection task for the dataset should be issued. */
|
@@ -95,55 +116,7 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
95
116
|
throw new Error(`group(${domainId}) and key(${dataSetId}) properties should not be empty`)
|
96
117
|
}
|
97
118
|
|
98
|
-
await
|
99
|
-
const domain = await tx.getRepository(Domain).findOneBy({ id: domainId })
|
100
|
-
|
101
|
-
if (!domain) {
|
102
|
-
throw new Error(`domain(${domainId}) not found`)
|
103
|
-
}
|
104
|
-
|
105
|
-
const dataSet = await tx
|
106
|
-
.getRepository(DataSet)
|
107
|
-
.findOne({ where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId } })
|
108
|
-
|
109
|
-
const activity = (await tx.getRepository(Activity).findOneBy({
|
110
|
-
domain: { id: domainId },
|
111
|
-
name: 'Collect Data'
|
112
|
-
})) as Activity
|
113
|
-
|
114
|
-
if (activity) {
|
115
|
-
const { assignees } = dataSet
|
116
|
-
|
117
|
-
/* 해당 dataset에 대한 데이타 수집 태스크를 dataset assignees에게 할당한다. */
|
118
|
-
if (assignees && assignees instanceof Array && assignees.length > 0) {
|
119
|
-
const activityInstance = {
|
120
|
-
name: `[Data 수집] ${dataSet.name}`,
|
121
|
-
description: dataSet.description,
|
122
|
-
activityId: activity.id,
|
123
|
-
dueAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
|
124
|
-
input: {
|
125
|
-
dataSetId: dataSet.id,
|
126
|
-
dataSetName: dataSet.name
|
127
|
-
},
|
128
|
-
assignees
|
129
|
-
}
|
130
|
-
|
131
|
-
context.state = {
|
132
|
-
...context.state,
|
133
|
-
domain,
|
134
|
-
tx
|
135
|
-
}
|
136
|
-
|
137
|
-
await issue(activityInstance, context)
|
138
|
-
} else {
|
139
|
-
throw new Error(
|
140
|
-
`Assignees not set. So Data Collect Activity for ${dataSet.name}($dataSet.id) could not be issued.`
|
141
|
-
)
|
142
|
-
}
|
143
|
-
} else {
|
144
|
-
throw new Error(`Data Collect Activity is not installed.`)
|
145
|
-
}
|
146
|
-
})
|
119
|
+
await issueCollectData(domainId, dataSetId, context)
|
147
120
|
|
148
121
|
context.status = 200
|
149
122
|
})
|
@@ -169,9 +142,7 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
|
|
169
142
|
throw new Error(`domain(${domainId}) not found`)
|
170
143
|
}
|
171
144
|
|
172
|
-
const dataSet = await tx
|
173
|
-
.getRepository(DataSet)
|
174
|
-
.findOne({ where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId } })
|
145
|
+
const dataSet = await tx.getRepository(DataSet).findOne({ where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId } })
|
175
146
|
|
176
147
|
// do what you gotta do
|
177
148
|
})
|
@@ -2,10 +2,12 @@ import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from
|
|
2
2
|
|
3
3
|
import { User } from '@things-factory/auth-base'
|
4
4
|
import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
|
5
|
+
import { ActivityInstance } from '@things-factory/worklist'
|
5
6
|
|
6
7
|
import { DataSetHistory } from '../data-set-history/data-set-history'
|
7
8
|
import { DataItem } from '../data-set/data-item-type'
|
8
9
|
import { DataSet } from '../data-set/data-set'
|
10
|
+
import { DataSample } from '../data-sample/data-sample'
|
9
11
|
import { DataOoc } from './data-ooc'
|
10
12
|
import { DataOocList } from './data-ooc-type'
|
11
13
|
|
@@ -51,11 +53,26 @@ export class DataOocQuery {
|
|
51
53
|
return dataSetHistory?.dataItems || []
|
52
54
|
}
|
53
55
|
|
56
|
+
@FieldResolver(type => DataSample)
|
57
|
+
async dataSample(@Root() dataOoc: DataOoc): Promise<DataSample> {
|
58
|
+
return dataOoc.dataSampleId && (await getRepository(DataSample).findOneBy({ id: dataOoc.dataSampleId }))
|
59
|
+
}
|
60
|
+
|
54
61
|
@FieldResolver(type => DataSet)
|
55
62
|
async dataSet(@Root() dataOoc: DataOoc): Promise<DataSet> {
|
56
63
|
return dataOoc.dataSetId && (await getRepository(DataSet).findOneBy({ id: dataOoc.dataSetId }))
|
57
64
|
}
|
58
65
|
|
66
|
+
@FieldResolver(type => ActivityInstance)
|
67
|
+
async reviewActivityInstance(@Root() dataOoc: DataOoc): Promise<ActivityInstance> {
|
68
|
+
return dataOoc.reviewActivityInstanceId && (await getRepository(ActivityInstance).findOneBy({ id: dataOoc.reviewActivityInstanceId }))
|
69
|
+
}
|
70
|
+
|
71
|
+
@FieldResolver(type => ActivityInstance)
|
72
|
+
async resolveActivityInstance(@Root() dataOoc: DataOoc): Promise<ActivityInstance> {
|
73
|
+
return dataOoc.resolveActivityInstanceId && (await getRepository(ActivityInstance).findOneBy({ id: dataOoc.resolveActivityInstanceId }))
|
74
|
+
}
|
75
|
+
|
59
76
|
@FieldResolver(type => User)
|
60
77
|
async corrector(@Root() dataOoc: DataOoc): Promise<User> {
|
61
78
|
return dataOoc.correctorId && (await getRepository(User).findOneBy({ id: dataOoc.correctorId }))
|