@things-factory/dataset 5.0.13 → 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.
Files changed (86) hide show
  1. package/README.md +20 -0
  2. package/assets/data-report.jpg +0 -0
  3. package/assets/glue-table-indices.png +0 -0
  4. package/client/pages/data-archive/data-archive-list-page.js +290 -0
  5. package/client/pages/data-archive/data-archive-request-popup.js +198 -0
  6. package/client/pages/data-key-set/data-key-set-list-page.js +97 -2
  7. package/client/pages/data-report/data-report-embed-page.js +16 -12
  8. package/client/pages/data-report/data-report-list-page.js +16 -13
  9. package/client/pages/data-report/data-report-samples-page.js +186 -0
  10. package/client/pages/data-set/data-set-list-page.js +8 -0
  11. package/client/route.js +20 -12
  12. package/config/config.development.js +21 -0
  13. package/config/config.production.js +32 -11
  14. package/dist-server/controllers/create-data-sample.js +3 -1
  15. package/dist-server/controllers/create-data-sample.js.map +1 -1
  16. package/dist-server/controllers/jasper-report.js +17 -12
  17. package/dist-server/controllers/jasper-report.js.map +1 -1
  18. package/dist-server/controllers/shiny-report.js +44 -0
  19. package/dist-server/controllers/shiny-report.js.map +1 -0
  20. package/dist-server/routes.js +8 -0
  21. package/dist-server/routes.js.map +1 -1
  22. package/dist-server/service/data-archive/data-archive-mutation.js +211 -0
  23. package/dist-server/service/data-archive/data-archive-mutation.js.map +1 -0
  24. package/dist-server/service/data-archive/data-archive-query.js +85 -0
  25. package/dist-server/service/data-archive/data-archive-query.js.map +1 -0
  26. package/dist-server/service/data-archive/data-archive-type.js +74 -0
  27. package/dist-server/service/data-archive/data-archive-type.js.map +1 -0
  28. package/dist-server/service/data-archive/data-archive.js +80 -0
  29. package/dist-server/service/data-archive/data-archive.js.map +1 -0
  30. package/dist-server/service/data-archive/index.js +9 -0
  31. package/dist-server/service/data-archive/index.js.map +1 -0
  32. package/dist-server/service/data-key-set/data-key-item-type.js.map +1 -1
  33. package/dist-server/service/data-key-set/data-key-set-mutation.js.map +1 -1
  34. package/dist-server/service/data-key-set/data-key-set-query.js.map +1 -1
  35. package/dist-server/service/data-key-set/data-key-set-type.js +17 -0
  36. package/dist-server/service/data-key-set/data-key-set-type.js.map +1 -1
  37. package/dist-server/service/data-key-set/data-key-set.js +11 -0
  38. package/dist-server/service/data-key-set/data-key-set.js.map +1 -1
  39. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -1
  40. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -1
  41. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -1
  42. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -1
  43. package/dist-server/service/data-ooc/data-ooc.js.map +1 -1
  44. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  45. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  46. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  47. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  48. package/dist-server/service/data-sensor/data-sensor-mutation.js.map +1 -1
  49. package/dist-server/service/data-sensor/data-sensor-query.js.map +1 -1
  50. package/dist-server/service/data-sensor/data-sensor-type.js.map +1 -1
  51. package/dist-server/service/data-sensor/data-sensor.js.map +1 -1
  52. package/dist-server/service/data-set/data-item-type.js.map +1 -1
  53. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  54. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  55. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  56. package/dist-server/service/data-set/data-set.js +2 -0
  57. package/dist-server/service/data-set/data-set.js.map +1 -1
  58. package/dist-server/service/data-set-history/data-set-history-query.js.map +1 -1
  59. package/dist-server/service/data-set-history/data-set-history-type.js.map +1 -1
  60. package/dist-server/service/data-set-history/data-set-history.js.map +1 -1
  61. package/dist-server/service/data-set-history/event-subscriber.js.map +1 -1
  62. package/dist-server/service/data-spec/data-spec-query.js.map +1 -1
  63. package/dist-server/service/data-spec/data-spec.js.map +1 -1
  64. package/dist-server/service/index.js +5 -2
  65. package/dist-server/service/index.js.map +1 -1
  66. package/dist-server/tsconfig.tsbuildinfo +1 -1
  67. package/helps/dataset/data-archive.md +6 -0
  68. package/package.json +7 -7
  69. package/server/controllers/create-data-sample.ts +4 -0
  70. package/server/controllers/jasper-report.ts +17 -12
  71. package/server/controllers/shiny-report.ts +63 -0
  72. package/server/routes.ts +11 -0
  73. package/server/service/data-archive/data-archive-mutation.ts +234 -0
  74. package/server/service/data-archive/data-archive-query.ts +56 -0
  75. package/server/service/data-archive/data-archive-type.ts +49 -0
  76. package/server/service/data-archive/data-archive.ts +69 -0
  77. package/server/service/data-archive/index.ts +6 -0
  78. package/server/service/data-key-set/data-key-set-type.ts +13 -0
  79. package/server/service/data-key-set/data-key-set.ts +9 -0
  80. package/server/service/data-set/data-set.ts +3 -1
  81. package/server/service/index.ts +5 -2
  82. package/things-factory.config.js +20 -12
  83. package/translations/en.json +15 -1
  84. package/translations/ko.json +14 -1
  85. package/translations/ms.json +2 -0
  86. package/translations/zh.json +2 -0
@@ -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.13",
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.11",
38
- "@things-factory/aws-base": "^5.0.11",
39
- "@things-factory/board-service": "^5.0.11",
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.11",
42
- "@things-factory/work-shift": "^5.0.11",
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": "72dfd33e398eab9872600e91d1b13fef0595c174"
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, dataSetId, fromWorkDate, toWorkDate, workShift, timezone } = params
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 collected_at
114
- FROM ${table}
115
- WHERE domain='${domain}'
116
- AND datasetid = '${dataSetId}'
117
- AND workdate >= '${fromWorkDate}'
118
- AND workdate <= '${toWorkDate}'
119
- ${workShift ? "AND workshift = '" + workShift + "'" : ''}
120
- ORDER BY collected_at`,
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['template'] || 'dynamic_header_sample.jrxml', 'utf-8')
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 reportUrl = `${PROTOCOL || 'http'}://${HOST}:${PORT}/rest/report/show_html`
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[]
@@ -21,7 +21,9 @@ export enum DataSetEntryType {
21
21
  Generated = 'generated',
22
22
  Board = 'board',
23
23
  Page = 'page',
24
- ExternalURL = 'external'
24
+ ExternalURL = 'external',
25
+ Jasper = 'jasper',
26
+ Shiny = 'shiny'
25
27
  }
26
28
 
27
29
  registerEnumType(DataSetEntryType, {