@things-factory/dataset 5.0.14 → 5.0.15
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/README.md +20 -0
- package/assets/data-report.jpg +0 -0
- package/assets/glue-table-indices.png +0 -0
- package/client/pages/data-archive/data-archive-list-page.js +290 -0
- package/client/pages/data-archive/data-archive-request-popup.js +198 -0
- package/client/pages/data-key-set/data-key-set-list-page.js +97 -2
- package/client/pages/data-report/data-report-embed-page.js +16 -12
- package/client/pages/data-report/data-report-list-page.js +16 -13
- package/client/pages/data-report/data-report-samples-page.js +186 -0
- package/client/pages/data-set/data-set-list-page.js +8 -0
- package/client/route.js +20 -12
- package/config/config.development.js +21 -0
- package/config/config.production.js +32 -11
- package/dist-server/controllers/create-data-sample.js +3 -1
- package/dist-server/controllers/create-data-sample.js.map +1 -1
- package/dist-server/controllers/jasper-report.js +17 -12
- package/dist-server/controllers/jasper-report.js.map +1 -1
- package/dist-server/controllers/shiny-report.js +44 -0
- package/dist-server/controllers/shiny-report.js.map +1 -0
- package/dist-server/routes.js +8 -0
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/data-archive/data-archive-mutation.js +211 -0
- package/dist-server/service/data-archive/data-archive-mutation.js.map +1 -0
- package/dist-server/service/data-archive/data-archive-query.js +85 -0
- package/dist-server/service/data-archive/data-archive-query.js.map +1 -0
- package/dist-server/service/data-archive/data-archive-type.js +74 -0
- package/dist-server/service/data-archive/data-archive-type.js.map +1 -0
- package/dist-server/service/data-archive/data-archive.js +80 -0
- package/dist-server/service/data-archive/data-archive.js.map +1 -0
- package/dist-server/service/data-archive/index.js +9 -0
- package/dist-server/service/data-archive/index.js.map +1 -0
- package/dist-server/service/data-key-set/data-key-item-type.js.map +1 -1
- package/dist-server/service/data-key-set/data-key-set-mutation.js.map +1 -1
- package/dist-server/service/data-key-set/data-key-set-query.js.map +1 -1
- package/dist-server/service/data-key-set/data-key-set-type.js +17 -0
- package/dist-server/service/data-key-set/data-key-set-type.js.map +1 -1
- package/dist-server/service/data-key-set/data-key-set.js +11 -0
- package/dist-server/service/data-key-set/data-key-set.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -1
- package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
- package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
- package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
- package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
- package/dist-server/service/data-sample/data-sample.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor-mutation.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor-type.js.map +1 -1
- package/dist-server/service/data-sensor/data-sensor.js.map +1 -1
- package/dist-server/service/data-set/data-item-type.js.map +1 -1
- package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
- package/dist-server/service/data-set/data-set-query.js.map +1 -1
- package/dist-server/service/data-set/data-set-type.js.map +1 -1
- package/dist-server/service/data-set/data-set.js +2 -0
- package/dist-server/service/data-set/data-set.js.map +1 -1
- package/dist-server/service/data-set-history/data-set-history-query.js.map +1 -1
- package/dist-server/service/data-set-history/data-set-history-type.js.map +1 -1
- package/dist-server/service/data-set-history/data-set-history.js.map +1 -1
- package/dist-server/service/data-set-history/event-subscriber.js.map +1 -1
- package/dist-server/service/data-spec/data-spec-query.js.map +1 -1
- package/dist-server/service/data-spec/data-spec.js.map +1 -1
- package/dist-server/service/index.js +5 -2
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/dataset/data-archive.md +6 -0
- package/package.json +7 -7
- package/server/controllers/create-data-sample.ts +4 -0
- package/server/controllers/jasper-report.ts +17 -12
- package/server/controllers/shiny-report.ts +63 -0
- package/server/routes.ts +11 -0
- package/server/service/data-archive/data-archive-mutation.ts +234 -0
- package/server/service/data-archive/data-archive-query.ts +56 -0
- package/server/service/data-archive/data-archive-type.ts +49 -0
- package/server/service/data-archive/data-archive.ts +69 -0
- package/server/service/data-archive/index.ts +6 -0
- package/server/service/data-key-set/data-key-set-type.ts +13 -0
- package/server/service/data-key-set/data-key-set.ts +9 -0
- package/server/service/data-set/data-set.ts +3 -1
- package/server/service/index.ts +5 -2
- package/things-factory.config.js +20 -12
- package/translations/en.json +15 -1
- package/translations/ko.json +14 -1
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
- package/dist-server/service/data-item/data-item-mutation.js +0 -69
- package/dist-server/service/data-item/data-item-mutation.js.map +0 -1
- package/dist-server/service/data-item/data-item-query.js +0 -100
- package/dist-server/service/data-item/data-item-query.js.map +0 -1
- package/dist-server/service/data-item/data-item-type.js +0 -80
- package/dist-server/service/data-item/data-item-type.js.map +0 -1
- package/dist-server/service/data-item/data-item.js +0 -136
- package/dist-server/service/data-item/data-item.js.map +0 -1
- package/dist-server/service/data-item/index.js +0 -9
- package/dist-server/service/data-item/index.js.map +0 -1
@@ -0,0 +1,6 @@
|
|
1
|
+
# DataArchive
|
2
|
+
데이터셋의 원형 데이터(raw data)를 csv.gz 파일로 다운로드할 수 있습니다. <br>
|
3
|
+
요청 후 시간이 수 분 소요될 수 있으며, 정상적으로 요청이 수행되면 다운로드 가능한 링크를 알림으로 알려줍니다. 알림의 링크를 클릭하여 파일을 다운로드 할 수 있습니다. <br>
|
4
|
+
조회 페이지에서도 다운로드 주소를 확인할 수 있습니다. <br>
|
5
|
+
다운로드 링크는 유효기간이 있으며, 만료되면 더 이상 다운로드할 수 없습니다. <br>
|
6
|
+
요청시간 초과(timeout)가 발생하는 경우에는 관리자에게 문의하시기 바랍니다.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/dataset",
|
3
|
-
"version": "5.0.
|
3
|
+
"version": "5.0.15",
|
4
4
|
"main": "dist-server/index.js",
|
5
5
|
"browser": "client/index.js",
|
6
6
|
"things-factory": true,
|
@@ -34,14 +34,14 @@
|
|
34
34
|
"@operato/shell": "^1.0.1",
|
35
35
|
"@operato/styles": "^1.0.0",
|
36
36
|
"@operato/utils": "^1.0.1",
|
37
|
-
"@things-factory/auth-base": "^5.0.
|
38
|
-
"@things-factory/aws-base": "^5.0.
|
39
|
-
"@things-factory/board-service": "^5.0.
|
37
|
+
"@things-factory/auth-base": "^5.0.15",
|
38
|
+
"@things-factory/aws-base": "^5.0.15",
|
39
|
+
"@things-factory/board-service": "^5.0.15",
|
40
40
|
"@things-factory/env": "^5.0.0",
|
41
|
-
"@things-factory/shell": "^5.0.
|
42
|
-
"@things-factory/work-shift": "^5.0.
|
41
|
+
"@things-factory/shell": "^5.0.15",
|
42
|
+
"@things-factory/work-shift": "^5.0.15",
|
43
43
|
"cron-parser": "^4.3.0",
|
44
44
|
"moment-timezone": "^0.5.34"
|
45
45
|
},
|
46
|
-
"gitHead": "
|
46
|
+
"gitHead": "87b738da786f92983d009d72548918be93e4ae2c"
|
47
47
|
}
|
@@ -11,6 +11,9 @@ 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
13
|
|
14
|
+
// See README.md at ## Data Samples
|
15
|
+
process.env.TZ = 'UTC'
|
16
|
+
|
14
17
|
const fillDataKeys = (dataKeySet, data) => {
|
15
18
|
const keys = dataKeySet?.dataKeyItems || []
|
16
19
|
return keys.reduce((sum, key, index) => {
|
@@ -93,6 +96,7 @@ export async function createDataSample(
|
|
93
96
|
name: dataSet.name,
|
94
97
|
description: dataSet.description,
|
95
98
|
useCase: dataSet.useCase,
|
99
|
+
type: dataSet.type,
|
96
100
|
...dataSample,
|
97
101
|
...dataKeys,
|
98
102
|
dataSetVersion: dataSet.version,
|
@@ -104,20 +104,23 @@ function parseJsonDataField(rows) {
|
|
104
104
|
const athenaClient = new AthenaController()
|
105
105
|
|
106
106
|
async function queryAthena(params) {
|
107
|
-
const { table, domain,
|
107
|
+
const { table, domain, datasetId, startDate, endDate, workShift, timezone } = params
|
108
108
|
const queryData = {
|
109
|
-
sql: `SELECT name, description, data, spec, workdate, workshift,
|
109
|
+
sql: `SELECT ds.name, ds.description, ds.data, dsh.data_items as spec, ds.workdate, ds.workshift,
|
110
110
|
DATE_FORMAT(
|
111
111
|
FROM_UNIXTIME(collected_at / 1000 / 1000) AT TIME ZONE '${timezone || 'UTC'}',
|
112
112
|
'%Y-%m-%d %H:%i:%s'
|
113
|
-
) AS
|
114
|
-
FROM ${table}
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
) AS dscollected_at
|
114
|
+
FROM ${table} ds
|
115
|
+
JOIN data_set_histories dsh
|
116
|
+
ON (ds.datasetid = dsh.original_id
|
117
|
+
and ds.data_set_version = dsh.version)
|
118
|
+
WHERE ds.domain='${domain}'
|
119
|
+
AND ds.datasetid = '${datasetId}'
|
120
|
+
AND ds.workdate >= '${startDate}'
|
121
|
+
AND ds.workdate <= '${endDate}'
|
122
|
+
${workShift ? "AND ds.workshift = '" + workShift + "'" : ''}
|
123
|
+
ORDER BY ds.collected_at`,
|
121
124
|
db: DATABASE
|
122
125
|
}
|
123
126
|
// and json_extract_scalar(data, '$.dauid') = 'A8032AD81730'
|
@@ -131,7 +134,7 @@ export async function renderJasperReport(context: any) {
|
|
131
134
|
query
|
132
135
|
} = context
|
133
136
|
|
134
|
-
const template = await STORAGE.readFile(query['
|
137
|
+
const template = await STORAGE.readFile(query['reportTemplate'] || 'dynamic_header_sample.jrxml', 'utf-8')
|
135
138
|
let templateType = query['templateType'] || 'crosstab'
|
136
139
|
let parsedData = []
|
137
140
|
|
@@ -169,7 +172,9 @@ export async function renderJasperReport(context: any) {
|
|
169
172
|
formData.append('jsonString', JSON.stringify(parsedData))
|
170
173
|
formData.append('parameters', JSON.stringify(parameters))
|
171
174
|
|
172
|
-
const
|
175
|
+
const { reportView } = query
|
176
|
+
const subpath = reportView ? reportView.split('/').filter(x => x).join('/') : ''
|
177
|
+
const reportUrl = `${PROTOCOL || 'http'}://${HOST}:${PORT}/${subpath}`
|
173
178
|
const response = await fetch(reportUrl, {
|
174
179
|
method: 'POST',
|
175
180
|
body: formData
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import FormData from 'form-data'
|
2
|
+
import fetch from 'node-fetch'
|
3
|
+
import { config } from '@things-factory/env'
|
4
|
+
|
5
|
+
const querystring = require('querystring')
|
6
|
+
const debug = require('debug')('things-factory:dataset:shiny-report')
|
7
|
+
const dataReportConfig = config.get('dataReport')
|
8
|
+
const {
|
9
|
+
shiny: {
|
10
|
+
endpoint: { protocol: PROTOCOL, host: HOST, port: PORT },
|
11
|
+
datasource: { database: DATABASE }
|
12
|
+
}
|
13
|
+
} = Object.assign({
|
14
|
+
shiny: {
|
15
|
+
endpoint: {},
|
16
|
+
datasource: {}
|
17
|
+
}}, dataReportConfig)
|
18
|
+
|
19
|
+
|
20
|
+
export async function renderShinyReport(context: any) {
|
21
|
+
debug('render:context', context)
|
22
|
+
|
23
|
+
try {
|
24
|
+
const { access_token: token } = querystring.parse(context.header.cookie, ';')
|
25
|
+
const {
|
26
|
+
state: { domain },
|
27
|
+
query,
|
28
|
+
response,
|
29
|
+
} = context
|
30
|
+
|
31
|
+
const urlParams = querystring.stringify({
|
32
|
+
token,
|
33
|
+
...query,
|
34
|
+
...{ database: DATABASE,
|
35
|
+
domain: domain?.subdomain }
|
36
|
+
})
|
37
|
+
|
38
|
+
// const jsonParams = JSON.stringify({
|
39
|
+
// ...query,
|
40
|
+
// ...{ database: DATABASE,
|
41
|
+
// domain: domain?.subdomain }
|
42
|
+
// })
|
43
|
+
|
44
|
+
const protocol = `${PROTOCOL || 'http'}://`
|
45
|
+
const host = `${HOST}:${PORT}/`
|
46
|
+
const subpath = query?.reportView || ''
|
47
|
+
|
48
|
+
if (!subpath) {
|
49
|
+
return context.body = ''
|
50
|
+
}
|
51
|
+
|
52
|
+
// filter not empty and join '/'
|
53
|
+
const url = host.split('/').concat(subpath.split('/'))
|
54
|
+
.filter(x => x).join('/')
|
55
|
+
// const reportUrl = `${protocol}${url}/?params=${jsonParams}`
|
56
|
+
const reportUrl = `${protocol}${url}/?${urlParams}`
|
57
|
+
|
58
|
+
response.redirect(reportUrl)
|
59
|
+
} catch(ex) {
|
60
|
+
context.body = `Error: ${ex.message} || ''`
|
61
|
+
}
|
62
|
+
|
63
|
+
}
|
package/server/routes.ts
CHANGED
@@ -4,6 +4,7 @@ import { User } from '@things-factory/auth-base'
|
|
4
4
|
|
5
5
|
import { createDataSample } from './controllers/create-data-sample'
|
6
6
|
import { renderJasperReport } from './controllers/jasper-report'
|
7
|
+
import { renderShinyReport } from './controllers/shiny-report'
|
7
8
|
import { DataSensor } from './service/data-sensor/data-sensor'
|
8
9
|
|
9
10
|
process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
|
@@ -89,4 +90,14 @@ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRo
|
|
89
90
|
domainPrivateRouter.get('/data-report/jasper', async (context, next) => {
|
90
91
|
context.body = await renderJasperReport(context)
|
91
92
|
})
|
93
|
+
|
94
|
+
domainPrivateRouter.get('/data-report/shiny', async (context, next) => {
|
95
|
+
await renderShinyReport(context)
|
96
|
+
})
|
97
|
+
|
98
|
+
domainPrivateRouter.get('/data-report/:reportType', async (context, next) => {
|
99
|
+
let { reportType } = context.params
|
100
|
+
context.body = `${reportType} Not Implemented.`
|
101
|
+
})
|
102
|
+
|
92
103
|
})
|
@@ -0,0 +1,234 @@
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
2
|
+
import { In } from 'typeorm'
|
3
|
+
import fetch from 'node-fetch'
|
4
|
+
|
5
|
+
import { DataArchive } from './data-archive'
|
6
|
+
import { DataArchivePatch, NewDataArchive } from './data-archive-type'
|
7
|
+
|
8
|
+
const { config } = require('@things-factory/env')
|
9
|
+
const crypto = require('crypto')
|
10
|
+
|
11
|
+
@Resolver(DataArchive)
|
12
|
+
export class DataArchiveMutation {
|
13
|
+
|
14
|
+
/**
|
15
|
+
* It may use 'func-[dev]-data-set-download' in https://github.com/operatochef/serverless
|
16
|
+
* This function requests athena query and save the result as csv.gz in s3
|
17
|
+
*/
|
18
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
19
|
+
@Directive('@transaction')
|
20
|
+
@Mutation(returns => DataArchive, { description: 'To create new DataArchive' })
|
21
|
+
async generatePresignedUrl(@Arg('patch') patch: DataArchivePatch, @Ctx() context: any): Promise<DataArchive> {
|
22
|
+
const { domain, user, tx } = context.state
|
23
|
+
// const dataArchiveRepo = tx.getRepository(DataArchive)
|
24
|
+
|
25
|
+
const { dataset: { endpoint: { host, port=80 }, datasource: { database } }} = config.get('dataArchive')
|
26
|
+
|
27
|
+
const body = JSON.stringify({
|
28
|
+
domain: domain?.subdomain,
|
29
|
+
database,
|
30
|
+
...patch?.requestParams
|
31
|
+
})
|
32
|
+
|
33
|
+
const fetched = await fetch(`${host}:${port}`, {
|
34
|
+
method: 'POST',
|
35
|
+
headers: {'Content-Type': 'application/json'},
|
36
|
+
body
|
37
|
+
})
|
38
|
+
|
39
|
+
let result
|
40
|
+
if (fetched.ok) {
|
41
|
+
const response = await fetched.json()
|
42
|
+
patch.downloadUrl = response['presignedUrl']
|
43
|
+
patch.status = 'done'
|
44
|
+
|
45
|
+
result = await this.updateDataArchive(patch.id, patch, context)
|
46
|
+
} else {
|
47
|
+
console.log(fetched.text())
|
48
|
+
patch.status = 'error'
|
49
|
+
|
50
|
+
result = await this.updateDataArchive(patch.id, patch, context)
|
51
|
+
}
|
52
|
+
|
53
|
+
return result
|
54
|
+
}
|
55
|
+
|
56
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
57
|
+
@Directive('@transaction')
|
58
|
+
@Mutation(returns => DataArchive, { description: 'To create new DataArchive' })
|
59
|
+
async createDataArchive(@Arg('dataArchive') dataArchive: NewDataArchive, @Ctx() context: any): Promise<DataArchive> {
|
60
|
+
const { domain, user, tx } = context.state
|
61
|
+
const dataArchiveRepo = tx.getRepository(DataArchive)
|
62
|
+
|
63
|
+
const result = await dataArchiveRepo.save({
|
64
|
+
...dataArchive,
|
65
|
+
domain,
|
66
|
+
creator: user,
|
67
|
+
updater: user
|
68
|
+
})
|
69
|
+
|
70
|
+
return result
|
71
|
+
}
|
72
|
+
|
73
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
74
|
+
@Directive('@transaction')
|
75
|
+
@Mutation(returns => DataArchive, { description: 'To modify DataArchive information' })
|
76
|
+
async updateDataArchive(@Arg('id') id: string, @Arg('patch') patch: DataArchivePatch, @Ctx() context: any): Promise<DataArchive> {
|
77
|
+
const { domain, user, tx } = context.state
|
78
|
+
const dataArchiveRepo = tx.getRepository(DataArchive)
|
79
|
+
|
80
|
+
const dataArchive = await dataArchiveRepo.findOne({
|
81
|
+
where: { domain, id },
|
82
|
+
relations: ['domain', 'creator', 'updater']
|
83
|
+
})
|
84
|
+
|
85
|
+
const result = await dataArchiveRepo.save({
|
86
|
+
...dataArchive,
|
87
|
+
...patch,
|
88
|
+
updater: user
|
89
|
+
})
|
90
|
+
|
91
|
+
return result
|
92
|
+
}
|
93
|
+
|
94
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
95
|
+
@Directive('@transaction')
|
96
|
+
@Mutation(returns => [DataArchive], { description: "To modify multiple DataArchives' information" })
|
97
|
+
async updateMultipleDataArchive(
|
98
|
+
@Arg('patches', type => [DataArchivePatch]) patches: DataArchivePatch[],
|
99
|
+
@Ctx() context: any
|
100
|
+
): Promise<DataArchive[]> {
|
101
|
+
const { domain, user, tx } = context.state
|
102
|
+
const dataArchiveRepo = tx.getRepository(DataArchive)
|
103
|
+
|
104
|
+
let results = []
|
105
|
+
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
106
|
+
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
107
|
+
|
108
|
+
if (_createRecords.length > 0) {
|
109
|
+
const cuFlag = '+'
|
110
|
+
for (let i = 0; i < _createRecords.length; i++) {
|
111
|
+
const newRecord = _createRecords[i]
|
112
|
+
|
113
|
+
const result = await dataArchiveRepo.save({
|
114
|
+
...newRecord,
|
115
|
+
domain,
|
116
|
+
creator: user,
|
117
|
+
updater: user
|
118
|
+
})
|
119
|
+
|
120
|
+
results.push({
|
121
|
+
...result,
|
122
|
+
cuFlag
|
123
|
+
})
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
if (_updateRecords.length > 0) {
|
128
|
+
const cuFlag = 'M'
|
129
|
+
for (let i = 0; i < _updateRecords.length; i++) {
|
130
|
+
const newRecord = _updateRecords[i]
|
131
|
+
const dataArchive = await dataArchiveRepo.findOne(newRecord.id, {
|
132
|
+
relations: ['domain', 'creator', 'updater']
|
133
|
+
})
|
134
|
+
|
135
|
+
const result = await dataArchiveRepo.save({
|
136
|
+
...dataArchive,
|
137
|
+
...newRecord,
|
138
|
+
updater: user
|
139
|
+
})
|
140
|
+
|
141
|
+
results.push({
|
142
|
+
...result,
|
143
|
+
cuFlag
|
144
|
+
})
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
return results
|
149
|
+
}
|
150
|
+
|
151
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
152
|
+
@Directive('@transaction')
|
153
|
+
@Mutation(returns => Boolean, { description: 'To delete DataArchive' })
|
154
|
+
async deleteDataArchive(@Arg('id') id: string, @Ctx() context: any): Promise<boolean> {
|
155
|
+
const { domain, tx } = context.state
|
156
|
+
|
157
|
+
await tx.getRepository(DataArchive).delete({ domain, id })
|
158
|
+
return true
|
159
|
+
}
|
160
|
+
|
161
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
162
|
+
@Directive('@transaction')
|
163
|
+
@Mutation(returns => Boolean, { description: 'To delete multiple dataArchives' })
|
164
|
+
async deleteDataArchives(@Arg('ids', type => [String]) ids: string[], @Ctx() context: any): Promise<boolean> {
|
165
|
+
const { domain, tx } = context.state
|
166
|
+
|
167
|
+
await tx.getRepository(DataArchive).delete({
|
168
|
+
domain,
|
169
|
+
id: In(ids)
|
170
|
+
})
|
171
|
+
|
172
|
+
return true
|
173
|
+
}
|
174
|
+
|
175
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
176
|
+
@Directive('@transaction')
|
177
|
+
@Mutation(returns => Boolean, { description: 'To import multiple data-archives' })
|
178
|
+
async importDataArchives(
|
179
|
+
@Arg('dataArchives', type => [DataArchivePatch]) dataArchives: DataArchive[],
|
180
|
+
@Ctx() context: any
|
181
|
+
): Promise<boolean> {
|
182
|
+
const { domain, tx } = context.state
|
183
|
+
const dataArchiveRepo = tx.getRepository(DataArchive)
|
184
|
+
|
185
|
+
await Promise.all(
|
186
|
+
dataArchives.map(async (dataArchive: DataArchive) => {
|
187
|
+
const createdDataArchive: DataArchive = await dataArchiveRepo.save({
|
188
|
+
domain,
|
189
|
+
...dataArchive
|
190
|
+
})
|
191
|
+
})
|
192
|
+
)
|
193
|
+
|
194
|
+
return true
|
195
|
+
}
|
196
|
+
|
197
|
+
@Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
|
198
|
+
@Directive('@transaction')
|
199
|
+
@Mutation(returns => [DataArchive], { description: 'To copy multiple data-archives' })
|
200
|
+
async copyDataArchives(@Arg('ids', type => [String]) ids: string[], @Ctx() context: any): Promise<DataArchive[]> {
|
201
|
+
const { domain, user, tx } = context.state
|
202
|
+
const dataArchiveRepo = tx.getRepository(DataArchive)
|
203
|
+
|
204
|
+
const originals = await dataArchiveRepo.find({
|
205
|
+
where: {
|
206
|
+
id: In(ids),
|
207
|
+
domain
|
208
|
+
},
|
209
|
+
relations: ['domain']
|
210
|
+
})
|
211
|
+
|
212
|
+
if (originals.length == 0) {
|
213
|
+
return []
|
214
|
+
}
|
215
|
+
|
216
|
+
var newCopys = originals.map(dataArchive => {
|
217
|
+
let dataArchiveId = crypto.randomUUID()
|
218
|
+
|
219
|
+
return {
|
220
|
+
...dataArchive,
|
221
|
+
id: dataArchiveId,
|
222
|
+
domain,
|
223
|
+
creator: user,
|
224
|
+
updater: user,
|
225
|
+
updatedAt: undefined,
|
226
|
+
createdAt: undefined
|
227
|
+
}
|
228
|
+
})
|
229
|
+
|
230
|
+
var copiedDataArchives = await dataArchiveRepo.save(newCopys)
|
231
|
+
|
232
|
+
return copiedDataArchives
|
233
|
+
}
|
234
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
2
|
+
import { getRepository } from 'typeorm'
|
3
|
+
|
4
|
+
import { Role, User } from '@things-factory/auth-base'
|
5
|
+
import { Domain, getQueryBuilderFromListParams, ListParam } from '@things-factory/shell'
|
6
|
+
|
7
|
+
import { DataArchive } from './data-archive'
|
8
|
+
import { DataArchiveList } from './data-archive-type'
|
9
|
+
|
10
|
+
var parser = require('cron-parser')
|
11
|
+
|
12
|
+
@Resolver(DataArchive)
|
13
|
+
export class DataArchiveQuery {
|
14
|
+
@Directive('@privilege(category: "data-archive", privilege: "query", domainOwnerGranted: true)')
|
15
|
+
@Query(returns => DataArchive, { description: 'To fetch a DataArchive' })
|
16
|
+
async dataArchive(@Arg('id') id: string, @Ctx() context: any): Promise<DataArchive> {
|
17
|
+
const { domain } = context.state
|
18
|
+
|
19
|
+
return await getRepository(DataArchive).findOne({
|
20
|
+
where: { domain, id }
|
21
|
+
})
|
22
|
+
}
|
23
|
+
|
24
|
+
@Directive('@privilege(category: "data-archive", privilege: "query", domainOwnerGranted: true)')
|
25
|
+
@Query(returns => DataArchiveList, { description: 'To fetch multiple DataArchives' })
|
26
|
+
async dataArchives(@Args() params: ListParam, @Ctx() context: any): Promise<DataArchiveList> {
|
27
|
+
const { domain } = context.state
|
28
|
+
|
29
|
+
const queryBuilder = getQueryBuilderFromListParams({
|
30
|
+
repository: getRepository(DataArchive),
|
31
|
+
params,
|
32
|
+
domain,
|
33
|
+
alias: 'dataArchive',
|
34
|
+
searchables: []
|
35
|
+
})
|
36
|
+
|
37
|
+
const [items, total] = await queryBuilder.getManyAndCount()
|
38
|
+
|
39
|
+
return { items, total }
|
40
|
+
}
|
41
|
+
|
42
|
+
@FieldResolver(type => Domain)
|
43
|
+
async domain(@Root() dataArchive: DataArchive): Promise<Domain> {
|
44
|
+
return await getRepository(Domain).findOne(dataArchive.domainId)
|
45
|
+
}
|
46
|
+
|
47
|
+
@FieldResolver(type => User)
|
48
|
+
async updater(@Root() dataArchive: DataArchive): Promise<User> {
|
49
|
+
return await getRepository(User).findOne(dataArchive.updaterId)
|
50
|
+
}
|
51
|
+
|
52
|
+
@FieldResolver(type => User)
|
53
|
+
async creator(@Root() dataArchive: DataArchive): Promise<User> {
|
54
|
+
return await getRepository(User).findOne(dataArchive.creatorId)
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
|
2
|
+
import { DataArchive } from './data-archive'
|
3
|
+
import { ObjectRef, ScalarObject } from '@things-factory/shell'
|
4
|
+
|
5
|
+
@InputType()
|
6
|
+
export class NewDataArchive {
|
7
|
+
@Field({ nullable: true })
|
8
|
+
type?: 'manual' | 'automatic' | string
|
9
|
+
|
10
|
+
@Field(type => ScalarObject, { nullable: true })
|
11
|
+
requestParams?: { [key: string]: any }
|
12
|
+
|
13
|
+
@Field({ nullable: true })
|
14
|
+
downloadUrl?: string
|
15
|
+
|
16
|
+
@Field({ nullable: true })
|
17
|
+
status?: string
|
18
|
+
|
19
|
+
}
|
20
|
+
|
21
|
+
@InputType()
|
22
|
+
export class DataArchivePatch {
|
23
|
+
@Field(type => ID, { nullable: true })
|
24
|
+
id?: string
|
25
|
+
|
26
|
+
@Field({ nullable: true })
|
27
|
+
type?: 'manual' | 'automatic' | string
|
28
|
+
|
29
|
+
@Field(type => ScalarObject, { nullable: true })
|
30
|
+
requestParams?: { [key: string]: any }
|
31
|
+
|
32
|
+
@Field({ nullable: true })
|
33
|
+
downloadUrl?: string
|
34
|
+
|
35
|
+
@Field({ nullable: true })
|
36
|
+
status?: string
|
37
|
+
|
38
|
+
@Field({ nullable: true })
|
39
|
+
cuFlag: string
|
40
|
+
}
|
41
|
+
|
42
|
+
@ObjectType()
|
43
|
+
export class DataArchiveList {
|
44
|
+
@Field(type => [DataArchive])
|
45
|
+
items: DataArchive[]
|
46
|
+
|
47
|
+
@Field(type => Int)
|
48
|
+
total: number
|
49
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import { Field, ID, ObjectType, registerEnumType } from 'type-graphql'
|
2
|
+
import {
|
3
|
+
Column,
|
4
|
+
CreateDateColumn,
|
5
|
+
Entity,
|
6
|
+
Index,
|
7
|
+
ManyToOne,
|
8
|
+
PrimaryGeneratedColumn,
|
9
|
+
RelationId,
|
10
|
+
UpdateDateColumn,
|
11
|
+
VersionColumn
|
12
|
+
} from 'typeorm'
|
13
|
+
|
14
|
+
import { Role, User } from '@things-factory/auth-base'
|
15
|
+
import { Domain, ScalarObject } from '@things-factory/shell'
|
16
|
+
|
17
|
+
@Entity()
|
18
|
+
@Index('ix_data_archive_0', (dataArchive: DataArchive) => [dataArchive.id], { unique: true })
|
19
|
+
@ObjectType({ description: 'Entity for DataArchive' })
|
20
|
+
export class DataArchive {
|
21
|
+
@PrimaryGeneratedColumn('uuid')
|
22
|
+
@Field(type => ID)
|
23
|
+
readonly id: string
|
24
|
+
|
25
|
+
@ManyToOne(type => Domain)
|
26
|
+
@Field({ nullable: true })
|
27
|
+
domain?: Domain
|
28
|
+
|
29
|
+
@RelationId((dataArchive: DataArchive) => dataArchive.domain)
|
30
|
+
domainId?: string
|
31
|
+
|
32
|
+
@Column({ nullable: true })
|
33
|
+
@Field({ nullable: true })
|
34
|
+
type?: 'manual' | 'automatic' | string
|
35
|
+
|
36
|
+
@Column('simple-json', { nullable: true })
|
37
|
+
@Field(type => ScalarObject, { nullable: true })
|
38
|
+
requestParams?: { [key: string]: any }
|
39
|
+
|
40
|
+
@Column({ nullable: true })
|
41
|
+
@Field({ nullable: true })
|
42
|
+
downloadUrl?: string
|
43
|
+
|
44
|
+
@Column({ nullable: true })
|
45
|
+
@Field({ nullable: true })
|
46
|
+
status?: string
|
47
|
+
|
48
|
+
@CreateDateColumn()
|
49
|
+
@Field({ nullable: true })
|
50
|
+
createdAt?: Date
|
51
|
+
|
52
|
+
@UpdateDateColumn()
|
53
|
+
@Field({ nullable: true })
|
54
|
+
updatedAt?: Date
|
55
|
+
|
56
|
+
@ManyToOne(type => User, { nullable: true })
|
57
|
+
@Field({ nullable: true })
|
58
|
+
creator?: User
|
59
|
+
|
60
|
+
@RelationId((dataArchive: DataArchive) => dataArchive.creator)
|
61
|
+
creatorId?: string
|
62
|
+
|
63
|
+
@ManyToOne(type => User, { nullable: true })
|
64
|
+
@Field({ nullable: true })
|
65
|
+
updater?: User
|
66
|
+
|
67
|
+
@RelationId((dataArchive: DataArchive) => dataArchive.creator)
|
68
|
+
updaterId?: string
|
69
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { DataArchive } from './data-archive'
|
2
|
+
import { DataArchiveMutation } from './data-archive-mutation'
|
3
|
+
import { DataArchiveQuery } from './data-archive-query'
|
4
|
+
|
5
|
+
export const entities = [DataArchive]
|
6
|
+
export const resolvers = [DataArchiveQuery, DataArchiveMutation]
|
@@ -4,6 +4,7 @@ import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
|
|
4
4
|
|
5
5
|
import { DataKeyItemPatch } from './data-key-item-type'
|
6
6
|
import { DataKeySet } from './data-key-set'
|
7
|
+
import { DataSetReportType } from '../data-set/data-set'
|
7
8
|
|
8
9
|
@InputType()
|
9
10
|
export class NewDataKeySet {
|
@@ -16,6 +17,12 @@ export class NewDataKeySet {
|
|
16
17
|
@Field({ nullable: true })
|
17
18
|
active?: boolean
|
18
19
|
|
20
|
+
@Field({ nullable: true })
|
21
|
+
reportType?: DataSetReportType
|
22
|
+
|
23
|
+
@Field({ nullable: true })
|
24
|
+
reportView?: string
|
25
|
+
|
19
26
|
@Field(type => [DataKeyItemPatch], { nullable: true })
|
20
27
|
dataKeyItems?: DataKeyItemPatch[]
|
21
28
|
|
@@ -37,6 +44,12 @@ export class DataKeySetPatch {
|
|
37
44
|
@Field({ nullable: true })
|
38
45
|
active?: boolean
|
39
46
|
|
47
|
+
@Field({ nullable: true })
|
48
|
+
reportType?: DataSetReportType
|
49
|
+
|
50
|
+
@Field({ nullable: true })
|
51
|
+
reportView?: string
|
52
|
+
|
40
53
|
@Field(type => [DataKeyItemPatch], { nullable: true })
|
41
54
|
dataKeyItems?: DataKeyItemPatch[]
|
42
55
|
|
@@ -14,6 +14,7 @@ import { User } from '@things-factory/auth-base'
|
|
14
14
|
import { Domain } from '@things-factory/shell'
|
15
15
|
|
16
16
|
import { DataKeyItem } from './data-key-item-type'
|
17
|
+
import { DataSetReportType } from '../data-set/data-set'
|
17
18
|
|
18
19
|
@Entity()
|
19
20
|
@Index('ix_data_key_set_0', (dataKeySet: DataKeySet) => [dataKeySet.domain, dataKeySet.name], { unique: true })
|
@@ -46,6 +47,14 @@ export class DataKeySet {
|
|
46
47
|
@Field({ nullable: true })
|
47
48
|
active?: boolean
|
48
49
|
|
50
|
+
@Column({ nullable: true })
|
51
|
+
@Field({ nullable: true })
|
52
|
+
reportType?: DataSetReportType
|
53
|
+
|
54
|
+
@Column({ nullable: true })
|
55
|
+
@Field({ nullable: true })
|
56
|
+
reportView?: string
|
57
|
+
|
49
58
|
@Column('simple-json', { nullable: true })
|
50
59
|
@Field(type => [DataKeyItem], { nullable: true })
|
51
60
|
dataKeyItems: DataKeyItem[]
|