@things-factory/dataset 8.0.0-beta.9 → 8.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. package/client/activities/activity-data-collect-edit.ts +105 -0
  2. package/client/activities/activity-data-collect-view.ts +91 -0
  3. package/client/activities/activity-data-review-edit.ts +278 -0
  4. package/client/activities/activity-data-review-view.ts +226 -0
  5. package/client/activities/activity-ooc-resolve-edit.ts +195 -0
  6. package/client/activities/activity-ooc-resolve-view.ts +143 -0
  7. package/client/activities/activity-ooc-review-edit.ts +173 -0
  8. package/client/activities/activity-ooc-review-view.ts +129 -0
  9. package/client/bootstrap.ts +35 -0
  10. package/client/components/data-entry-form.ts +109 -0
  11. package/client/index.ts +1 -0
  12. package/client/pages/data-archive/data-archive-list-page.ts +277 -0
  13. package/client/pages/data-archive/data-archive-request-popup.ts +177 -0
  14. package/client/pages/data-entry/data-entry-list-page.ts +464 -0
  15. package/client/pages/data-key-set/data-key-item-list.ts +183 -0
  16. package/client/pages/data-key-set/data-key-set-importer.ts +89 -0
  17. package/client/pages/data-key-set/data-key-set-list-page.ts +413 -0
  18. package/client/pages/data-ooc/data-ooc-list-page.ts +549 -0
  19. package/client/pages/data-ooc/data-ooc-page.ts +164 -0
  20. package/client/pages/data-ooc/data-ooc-view.ts +236 -0
  21. package/client/pages/data-ooc/data-oocs-page.ts +200 -0
  22. package/client/pages/data-report/data-report-embed-page.ts +108 -0
  23. package/client/pages/data-report/data-report-list-page.ts +454 -0
  24. package/client/pages/data-report/data-report-samples-page.ts +174 -0
  25. package/client/pages/data-report/jasper-report-oocs-page.ts +110 -0
  26. package/client/pages/data-report/jasper-report-samples-crosstab-page.ts +110 -0
  27. package/client/pages/data-report/jasper-report-samples-page.ts +110 -0
  28. package/client/pages/data-sample/data-sample-list-page.ts +442 -0
  29. package/client/pages/data-sample/data-sample-page.ts +55 -0
  30. package/client/pages/data-sample/data-sample-search-page.ts +424 -0
  31. package/client/pages/data-sample/data-sample-view.ts +292 -0
  32. package/client/pages/data-sample/data-samples-page.ts +249 -0
  33. package/client/pages/data-sensor/data-sensor-list-page.ts +456 -0
  34. package/client/pages/data-set/data-item-list.ts +304 -0
  35. package/client/pages/data-set/data-set-importer.ts +89 -0
  36. package/client/pages/data-set/data-set-list-page.ts +1078 -0
  37. package/client/pages/data-summary/data-summary-list-page.ts +363 -0
  38. package/client/pages/data-summary/data-summary-period-page.ts +439 -0
  39. package/client/pages/data-summary/data-summary-search-page.ts +426 -0
  40. package/client/pages/data-summary/data-summary-view.ts +133 -0
  41. package/client/route.ts +91 -0
  42. package/client/tsconfig.json +13 -0
  43. package/dist-client/activities/activity-data-review-edit.js +19 -10
  44. package/dist-client/activities/activity-data-review-edit.js.map +1 -1
  45. package/dist-client/activities/activity-data-review-view.js +80 -0
  46. package/dist-client/activities/activity-data-review-view.js.map +1 -1
  47. package/dist-client/pages/data-entry/data-entry-list-page.js +2 -2
  48. package/dist-client/pages/data-entry/data-entry-list-page.js.map +1 -1
  49. package/dist-client/tsconfig.tsbuildinfo +1 -1
  50. package/dist-server/controllers/create-data-ooc.js +2 -0
  51. package/dist-server/controllers/create-data-ooc.js.map +1 -1
  52. package/dist-server/service/data-archive/index.d.ts +1 -1
  53. package/dist-server/service/data-ooc/index.d.ts +1 -1
  54. package/dist-server/service/data-sample/data-sample-query.d.ts +1 -1
  55. package/dist-server/service/data-sample/data-sample-query.js +3 -3
  56. package/dist-server/service/data-sample/data-sample-query.js.map +1 -1
  57. package/dist-server/service/data-sample/index.d.ts +1 -1
  58. package/dist-server/service/data-set/index.d.ts +1 -1
  59. package/dist-server/service/index.d.ts +2 -2
  60. package/dist-server/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +26 -26
  62. package/server/activities/activity-data-collect.ts +100 -0
  63. package/server/activities/activity-data-review.ts +109 -0
  64. package/server/activities/activity-ooc-resolve.ts +123 -0
  65. package/server/activities/activity-ooc-review.ts +95 -0
  66. package/server/activities/index.ts +11 -0
  67. package/server/controllers/create-data-ooc.ts +80 -0
  68. package/server/controllers/create-data-sample.ts +323 -0
  69. package/server/controllers/data-use-case.ts +98 -0
  70. package/server/controllers/finalize-data-collection.ts +388 -0
  71. package/server/controllers/index.ts +6 -0
  72. package/server/controllers/issue-data-collection-task.ts +70 -0
  73. package/server/controllers/issue-ooc-resolve.ts +58 -0
  74. package/server/controllers/issue-ooc-review.ts +52 -0
  75. package/server/controllers/jasper-report.ts +186 -0
  76. package/server/controllers/query-data-summary-by-period.ts +178 -0
  77. package/server/controllers/shiny-report.ts +54 -0
  78. package/server/engine/index.ts +1 -0
  79. package/server/engine/task/create-data-sample.ts +100 -0
  80. package/server/engine/task/index.ts +2 -0
  81. package/server/engine/task/issue-collect-data.ts +45 -0
  82. package/server/index.ts +8 -0
  83. package/server/routes.ts +188 -0
  84. package/server/service/data-archive/data-archive-mutation.ts +273 -0
  85. package/server/service/data-archive/data-archive-query.ts +58 -0
  86. package/server/service/data-archive/data-archive-type.ts +48 -0
  87. package/server/service/data-archive/data-archive.ts +69 -0
  88. package/server/service/data-archive/index.ts +6 -0
  89. package/server/service/data-key-set/data-key-item-type.ts +31 -0
  90. package/server/service/data-key-set/data-key-set-mutation.ts +201 -0
  91. package/server/service/data-key-set/data-key-set-query.ts +68 -0
  92. package/server/service/data-key-set/data-key-set-type.ts +70 -0
  93. package/server/service/data-key-set/data-key-set.ts +86 -0
  94. package/server/service/data-key-set/index.ts +6 -0
  95. package/server/service/data-ooc/data-ooc-mutation.ts +154 -0
  96. package/server/service/data-ooc/data-ooc-query.ts +106 -0
  97. package/server/service/data-ooc/data-ooc-subscription.ts +48 -0
  98. package/server/service/data-ooc/data-ooc-type.ts +71 -0
  99. package/server/service/data-ooc/data-ooc.ts +259 -0
  100. package/server/service/data-ooc/index.ts +7 -0
  101. package/server/service/data-sample/data-sample-mutation.ts +18 -0
  102. package/server/service/data-sample/data-sample-query.ts +215 -0
  103. package/server/service/data-sample/data-sample-type.ts +47 -0
  104. package/server/service/data-sample/data-sample.ts +193 -0
  105. package/server/service/data-sample/index.ts +6 -0
  106. package/server/service/data-sensor/data-sensor-mutation.ts +116 -0
  107. package/server/service/data-sensor/data-sensor-query.ts +76 -0
  108. package/server/service/data-sensor/data-sensor-type.ts +104 -0
  109. package/server/service/data-sensor/data-sensor.ts +126 -0
  110. package/server/service/data-sensor/index.ts +6 -0
  111. package/server/service/data-set/data-item-type.ts +155 -0
  112. package/server/service/data-set/data-set-mutation.ts +552 -0
  113. package/server/service/data-set/data-set-query.ts +461 -0
  114. package/server/service/data-set/data-set-type.ts +204 -0
  115. package/server/service/data-set/data-set.ts +326 -0
  116. package/server/service/data-set/index.ts +6 -0
  117. package/server/service/data-set-history/data-set-history-query.ts +126 -0
  118. package/server/service/data-set-history/data-set-history-type.ts +12 -0
  119. package/server/service/data-set-history/data-set-history.ts +217 -0
  120. package/server/service/data-set-history/event-subscriber.ts +17 -0
  121. package/server/service/data-set-history/index.ts +7 -0
  122. package/server/service/data-spec/data-spec-manager.ts +21 -0
  123. package/server/service/data-spec/data-spec-query.ts +21 -0
  124. package/server/service/data-spec/data-spec.ts +45 -0
  125. package/server/service/data-spec/index.ts +5 -0
  126. package/server/service/data-summary/data-summary-mutation.ts +45 -0
  127. package/server/service/data-summary/data-summary-query.ts +179 -0
  128. package/server/service/data-summary/data-summary-type.ts +86 -0
  129. package/server/service/data-summary/data-summary.ts +170 -0
  130. package/server/service/data-summary/index.ts +7 -0
  131. package/server/service/index.ts +57 -0
  132. package/server/tsconfig.json +10 -0
  133. package/server/utils/config-resolver.ts +29 -0
  134. package/server/utils/index.ts +1 -0
@@ -0,0 +1,188 @@
1
+ import { In } from 'typeorm'
2
+
3
+ import { Domain, getDataSource } from '@things-factory/shell'
4
+ import { User } from '@things-factory/auth-base'
5
+ import { runScenario } from '@things-factory/integration-base'
6
+ import { ScheduleRegisterRequest } from '@things-factory/scheduler-client'
7
+
8
+ import { createDataSample } from './controllers/create-data-sample'
9
+ import { renderJasperReport } from './controllers/jasper-report'
10
+ import { renderShinyReport } from './controllers/shiny-report'
11
+ import { issueDataCollectionTask } from './controllers/issue-data-collection-task'
12
+ import { DataSensor } from './service/data-sensor/data-sensor'
13
+ import { DataSet } from './service/data-set/data-set'
14
+
15
+ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
16
+ /*
17
+ * can add global public routes to application (auth not required, tenancy not required)
18
+ *
19
+ * ex) routes.get('/path', async(context, next) => {})
20
+ * ex) routes.post('/path', async(context, next) => {})
21
+ */
22
+
23
+ globalPublicRouter.post('/sensor-data', async (context, next) => {
24
+ // 데이타 검증
25
+ const { deviceId, data, rawData, timestamp = Date.now() } = context.request.body
26
+ if (!deviceId) {
27
+ throw new Error(`The deviceId(${deviceId}) property are mandatory`)
28
+ }
29
+
30
+ // make new data-sample
31
+ await getDataSource().transaction(async tx => {
32
+ // find sensor through deviceId
33
+ const sensor = await tx.getRepository(DataSensor).findOne({
34
+ where: { deviceId },
35
+ relations: ['domain', 'appliance', 'dataSet', 'decoder']
36
+ })
37
+
38
+ if (!sensor) {
39
+ throw new Error(`Sensor having given deviceId(${deviceId}) not found`)
40
+ }
41
+
42
+ if (!sensor.active) {
43
+ throw new Error(`State of the sensor given deviceId(${deviceId}) is not active`)
44
+ }
45
+
46
+ if (!sensor.appliance) {
47
+ throw new Error(`Appliance of the sensor given deviceId(${deviceId}) is not set up`)
48
+ }
49
+
50
+ const domain = sensor.domain
51
+ const dataSet = sensor.dataSet
52
+
53
+ /*
54
+ 원칙적으로 user 인증정보를 가지고 요청해야 하지만, 인증정보를 보낼 수 없는 상황이라고 전제하여 처리한다.
55
+ 앞으로, 보완되어야 한다.
56
+ */
57
+ const user: User =
58
+ context.user ||
59
+ (await tx.getRepository(User).findOne({
60
+ where: {
61
+ reference: sensor.appliance.id,
62
+ userType: 'appliance'
63
+ }
64
+ }))
65
+
66
+ context.state = {
67
+ user,
68
+ ...context.state,
69
+ domain,
70
+ tx
71
+ }
72
+
73
+ var decoded
74
+ if (sensor.decoder) {
75
+ const { name: scenarioName } = sensor.decoder
76
+ const variables = {
77
+ dataSensor: sensor,
78
+ source: deviceId,
79
+ data,
80
+ rawData,
81
+ timestamp
82
+ }
83
+
84
+ decoded = (await runScenario(null, scenarioName, variables, context))?.result
85
+ }
86
+
87
+ if (dataSet) {
88
+ await createDataSample(
89
+ {
90
+ dataSet,
91
+ data,
92
+ rawData,
93
+ source: deviceId,
94
+ collectedAt: new Date(timestamp),
95
+ ...decoded
96
+ },
97
+ context
98
+ )
99
+ }
100
+
101
+ context.status = 200
102
+ context.body = {
103
+ data,
104
+ ...decoded
105
+ }
106
+ })
107
+ })
108
+
109
+ /* When a callback occurs from the scheduler when a scheduled dataset is on schedule, data collection task for the dataset should be issued. */
110
+ globalPublicRouter.post('/callback-schedule-for-dataset', async (context, next) => {
111
+ const { client } = context.request.body as ScheduleRegisterRequest
112
+
113
+ if (!client || typeof client !== 'object') {
114
+ throw new Error('client property should be a part of callback body.')
115
+ }
116
+
117
+ const { group: domainId, key: dataSetId } = client
118
+
119
+ if (!domainId || !dataSetId) {
120
+ throw new Error(`group(${domainId}) and key(${dataSetId}) properties should not be empty`)
121
+ }
122
+
123
+ await issueDataCollectionTask(domainId, dataSetId, context)
124
+
125
+ context.status = 200
126
+ })
127
+
128
+ /* When a callback occurs from the scheduler when a scheduled summary is on schedule, data summary procedure for the dataset should be executed. */
129
+ globalPublicRouter.post('/callback-schedule-for-data-summary', async (context, next) => {
130
+ const { client } = context.request.body as ScheduleRegisterRequest
131
+
132
+ if (!client || typeof client !== 'object') {
133
+ throw new Error('client property should be a part of callback body.')
134
+ }
135
+
136
+ const { group: domainId, key: dataSetId } = client
137
+
138
+ if (!domainId || !dataSetId) {
139
+ throw new Error(`group(${domainId}) and key(${dataSetId}) properties should not be empty`)
140
+ }
141
+
142
+ await getDataSource().transaction(async tx => {
143
+ const domain = await tx.getRepository(Domain).findOneBy({ id: domainId })
144
+
145
+ if (!domain) {
146
+ throw new Error(`domain(${domainId}) not found`)
147
+ }
148
+
149
+ const dataSet = await tx
150
+ .getRepository(DataSet)
151
+ .findOne({ where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId } })
152
+
153
+ // do what you gotta do
154
+ })
155
+
156
+ context.status = 200
157
+ })
158
+ })
159
+
160
+ process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
161
+ /*
162
+ * can add global private routes to application (auth required, tenancy not required)
163
+ */
164
+ })
165
+
166
+ process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
167
+ /*
168
+ * can add domain public routes to application (auth not required, tenancy required)
169
+ */
170
+ })
171
+
172
+ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
173
+ /*
174
+ * can add domain private routes to application (auth required, tenancy required)
175
+ */
176
+ domainPrivateRouter.get('/data-report/jasper', async (context, next) => {
177
+ context.body = await renderJasperReport(context)
178
+ })
179
+
180
+ domainPrivateRouter.get('/data-report/shiny', async (context, next) => {
181
+ await renderShinyReport(context)
182
+ })
183
+
184
+ domainPrivateRouter.get('/data-report/:reportType', async (context, next) => {
185
+ let { reportType } = context.params
186
+ context.body = `${reportType} Not Implemented.`
187
+ })
188
+ })
@@ -0,0 +1,273 @@
1
+ import i18next from 'i18next'
2
+ import fetch from 'node-fetch'
3
+ import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
4
+ import { In } from 'typeorm'
5
+
6
+ import { getEndpointUrl } from '../../utils/config-resolver'
7
+ import { DataArchive } from './data-archive'
8
+ import { DataArchivePatch, NewDataArchive } from './data-archive-type'
9
+
10
+ const { config } = require('@things-factory/env')
11
+ const crypto = require('crypto')
12
+
13
+ @Resolver(DataArchive)
14
+ export class DataArchiveMutation {
15
+ /**
16
+ * It may use 'func-[dev]-data-set-download' in https://github.com/operatochef/serverless
17
+ * This function requests athena query and save the result as csv.gz in s3
18
+ */
19
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
20
+ @Directive('@transaction')
21
+ @Mutation(returns => DataArchive, { description: 'To create new DataArchive' })
22
+ async generatePresignedUrl(
23
+ @Arg('patch') patch: DataArchivePatch,
24
+ @Ctx() context: ResolverContext
25
+ ): Promise<DataArchive> {
26
+ const { domain, user, tx, notify, lng } = context.state
27
+ // const dataArchiveRepo = tx.getRepository(DataArchive)
28
+ const t = i18next.getFixedT(lng, 'translations')
29
+ const {
30
+ dataset: {
31
+ endpoint,
32
+ datasource: { database }
33
+ }
34
+ } = config.get('dataArchive')
35
+
36
+ const body = JSON.stringify({
37
+ domain: domain?.subdomain,
38
+ database,
39
+ ...patch?.requestParams
40
+ })
41
+
42
+ const url = getEndpointUrl(endpoint)
43
+
44
+ const fetched = await fetch(`${url}`, {
45
+ method: 'POST',
46
+ headers: { 'Content-Type': 'application/json' },
47
+ body
48
+ })
49
+
50
+ const message = {
51
+ receivers: [user.email],
52
+ mode: 'in-app',
53
+ title: '',
54
+ body: '',
55
+ url: ''
56
+ }
57
+
58
+ if (fetched.ok) {
59
+ const response = await fetched.json()
60
+ patch.downloadUrl = response['presignedUrl']
61
+ patch.status = 'done'
62
+
63
+ message['title'] = t('title.data-archive downloads ready')
64
+ message['url'] = patch.downloadUrl
65
+ } else {
66
+ const error = await fetched.text()
67
+ console.log(error)
68
+ patch.status = 'error'
69
+
70
+ message['title'] = t('title.data-archive request failed')
71
+ // may not user-friendly message
72
+ message['body'] = error
73
+ }
74
+
75
+ const result = await this.updateDataArchive(patch.id, patch, context)
76
+
77
+ notify && notify(message)
78
+
79
+ return result
80
+ }
81
+
82
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
83
+ @Directive('@transaction')
84
+ @Mutation(returns => DataArchive, { description: 'To create new DataArchive' })
85
+ async createDataArchive(
86
+ @Arg('dataArchive') dataArchive: NewDataArchive,
87
+ @Ctx() context: ResolverContext
88
+ ): Promise<DataArchive> {
89
+ const { domain, user, tx } = context.state
90
+ const dataArchiveRepo = tx.getRepository(DataArchive)
91
+
92
+ const result = await dataArchiveRepo.save({
93
+ ...dataArchive,
94
+ domain,
95
+ creator: user,
96
+ updater: user
97
+ })
98
+
99
+ return result
100
+ }
101
+
102
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
103
+ @Directive('@transaction')
104
+ @Mutation(returns => DataArchive, { description: 'To modify DataArchive information' })
105
+ async updateDataArchive(
106
+ @Arg('id') id: string,
107
+ @Arg('patch') patch: DataArchivePatch,
108
+ @Ctx() context: ResolverContext
109
+ ): Promise<DataArchive> {
110
+ const { domain, user, tx } = context.state
111
+ const dataArchiveRepo = tx.getRepository(DataArchive)
112
+
113
+ const dataArchive = await dataArchiveRepo.findOne({
114
+ where: { domain: { id: domain.id }, id },
115
+ relations: ['domain', 'creator', 'updater']
116
+ })
117
+
118
+ const result = await dataArchiveRepo.save({
119
+ ...dataArchive,
120
+ ...patch,
121
+ updater: user
122
+ })
123
+
124
+ return result
125
+ }
126
+
127
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
128
+ @Directive('@transaction')
129
+ @Mutation(returns => [DataArchive], { description: "To modify multiple DataArchives' information" })
130
+ async updateMultipleDataArchive(
131
+ @Arg('patches', type => [DataArchivePatch]) patches: DataArchivePatch[],
132
+ @Ctx() context: any
133
+ ): Promise<DataArchive[]> {
134
+ const { domain, user, tx } = context.state
135
+ const dataArchiveRepo = tx.getRepository(DataArchive)
136
+
137
+ let results = []
138
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
139
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
140
+
141
+ if (_createRecords.length > 0) {
142
+ const cuFlag = '+'
143
+ for (let i = 0; i < _createRecords.length; i++) {
144
+ const newRecord = _createRecords[i]
145
+
146
+ const result = await dataArchiveRepo.save({
147
+ ...newRecord,
148
+ domain,
149
+ creator: user,
150
+ updater: user
151
+ })
152
+
153
+ results.push({
154
+ ...result,
155
+ cuFlag
156
+ })
157
+ }
158
+ }
159
+
160
+ if (_updateRecords.length > 0) {
161
+ const cuFlag = 'M'
162
+ for (let i = 0; i < _updateRecords.length; i++) {
163
+ const newRecord = _updateRecords[i]
164
+ const dataArchive = await dataArchiveRepo.findOne(newRecord.id, {
165
+ relations: ['domain', 'creator', 'updater']
166
+ })
167
+
168
+ const result = await dataArchiveRepo.save({
169
+ ...dataArchive,
170
+ ...newRecord,
171
+ updater: user
172
+ })
173
+
174
+ results.push({
175
+ ...result,
176
+ cuFlag
177
+ })
178
+ }
179
+ }
180
+
181
+ return results
182
+ }
183
+
184
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
185
+ @Directive('@transaction')
186
+ @Mutation(returns => Boolean, { description: 'To delete DataArchive' })
187
+ async deleteDataArchive(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
188
+ const { domain, tx } = context.state
189
+
190
+ await tx.getRepository(DataArchive).delete({ domain: { id: domain.id }, id })
191
+ return true
192
+ }
193
+
194
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
195
+ @Directive('@transaction')
196
+ @Mutation(returns => Boolean, { description: 'To delete multiple dataArchives' })
197
+ async deleteDataArchives(
198
+ @Arg('ids', type => [String]) ids: string[],
199
+ @Ctx() context: ResolverContext
200
+ ): Promise<boolean> {
201
+ const { domain, tx } = context.state
202
+
203
+ await tx.getRepository(DataArchive).delete({
204
+ domain: { id: domain.id },
205
+ id: In(ids)
206
+ })
207
+
208
+ return true
209
+ }
210
+
211
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
212
+ @Directive('@transaction')
213
+ @Mutation(returns => Boolean, { description: 'To import multiple data-archives' })
214
+ async importDataArchives(
215
+ @Arg('dataArchives', type => [DataArchivePatch]) dataArchives: DataArchive[],
216
+ @Ctx() context: ResolverContext
217
+ ): Promise<boolean> {
218
+ const { domain, tx } = context.state
219
+ const dataArchiveRepo = tx.getRepository(DataArchive)
220
+
221
+ await Promise.all(
222
+ dataArchives.map(async (dataArchive: DataArchive) => {
223
+ const createdDataArchive: DataArchive = await dataArchiveRepo.save({
224
+ domain,
225
+ ...dataArchive
226
+ })
227
+ })
228
+ )
229
+
230
+ return true
231
+ }
232
+
233
+ @Directive('@privilege(category: "data-archive", privilege: "mutation", domainOwnerGranted: true)')
234
+ @Directive('@transaction')
235
+ @Mutation(returns => [DataArchive], { description: 'To copy multiple data-archives' })
236
+ async copyDataArchives(
237
+ @Arg('ids', type => [String]) ids: string[],
238
+ @Ctx() context: ResolverContext
239
+ ): Promise<DataArchive[]> {
240
+ const { domain, user, tx } = context.state
241
+ const dataArchiveRepo = tx.getRepository(DataArchive)
242
+
243
+ const originals = await dataArchiveRepo.find({
244
+ where: {
245
+ id: In(ids),
246
+ domain: { id: domain.id }
247
+ },
248
+ relations: ['domain']
249
+ })
250
+
251
+ if (originals.length == 0) {
252
+ return []
253
+ }
254
+
255
+ var newCopys = originals.map(dataArchive => {
256
+ let dataArchiveId = crypto.randomUUID()
257
+
258
+ return {
259
+ ...dataArchive,
260
+ id: dataArchiveId,
261
+ domain,
262
+ creator: user,
263
+ updater: user,
264
+ updatedAt: undefined,
265
+ createdAt: undefined
266
+ }
267
+ })
268
+
269
+ var copiedDataArchives = await dataArchiveRepo.save(newCopys)
270
+
271
+ return copiedDataArchives
272
+ }
273
+ }
@@ -0,0 +1,58 @@
1
+ import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
+
3
+ import { Role, User } from '@things-factory/auth-base'
4
+ import { Domain, getQueryBuilderFromListParams, ListParam, getRepository } from '@things-factory/shell'
5
+
6
+ import { DataArchive } from './data-archive'
7
+ import { DataArchiveList } from './data-archive-type'
8
+
9
+ var parser = require('cron-parser')
10
+
11
+ @Resolver(DataArchive)
12
+ export class DataArchiveQuery {
13
+ @Directive('@privilege(category: "data-archive", privilege: "query", domainOwnerGranted: true)')
14
+ @Query(returns => DataArchive, { description: 'To fetch a DataArchive' })
15
+ async dataArchive(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<DataArchive> {
16
+ const { domain } = context.state
17
+
18
+ return await getRepository(DataArchive).findOne({
19
+ where: { domain: { id: domain.id }, id }
20
+ })
21
+ }
22
+
23
+ @Directive('@privilege(category: "data-archive", privilege: "query", domainOwnerGranted: true)')
24
+ @Query(returns => DataArchiveList, { description: 'To fetch multiple DataArchives' })
25
+ async dataArchives(
26
+ @Args(type => ListParam) params: ListParam,
27
+ @Ctx() context: ResolverContext
28
+ ): Promise<DataArchiveList> {
29
+ const { domain } = context.state
30
+
31
+ const queryBuilder = getQueryBuilderFromListParams({
32
+ repository: getRepository(DataArchive),
33
+ params,
34
+ domain,
35
+ alias: 'dataArchive',
36
+ searchables: []
37
+ })
38
+
39
+ const [items, total] = await queryBuilder.getManyAndCount()
40
+
41
+ return { items, total }
42
+ }
43
+
44
+ @FieldResolver(type => Domain)
45
+ async domain(@Root() dataArchive: DataArchive): Promise<Domain> {
46
+ return dataArchive.domainId && (await getRepository(Domain).findOneBy({ id: dataArchive.domainId }))
47
+ }
48
+
49
+ @FieldResolver(type => User)
50
+ async updater(@Root() dataArchive: DataArchive): Promise<User> {
51
+ return dataArchive.updaterId && (await getRepository(User).findOneBy({ id: dataArchive.updaterId }))
52
+ }
53
+
54
+ @FieldResolver(type => User)
55
+ async creator(@Root() dataArchive: DataArchive): Promise<User> {
56
+ return dataArchive.creatorId && (await getRepository(User).findOneBy({ id: dataArchive.creatorId }))
57
+ }
58
+ }
@@ -0,0 +1,48 @@
1
+ import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
2
+ import { DataArchive } from './data-archive'
3
+ import { 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
+ @InputType()
21
+ export class DataArchivePatch {
22
+ @Field(type => ID, { nullable: true })
23
+ id?: string
24
+
25
+ @Field({ nullable: true })
26
+ type?: 'manual' | 'automatic' | string
27
+
28
+ @Field(type => ScalarObject, { nullable: true })
29
+ requestParams?: { [key: string]: any }
30
+
31
+ @Field({ nullable: true })
32
+ downloadUrl?: string
33
+
34
+ @Field({ nullable: true })
35
+ status?: string
36
+
37
+ @Field({ nullable: true })
38
+ cuFlag: string
39
+ }
40
+
41
+ @ObjectType()
42
+ export class DataArchiveList {
43
+ @Field(type => [DataArchive])
44
+ items: DataArchive[]
45
+
46
+ @Field(type => Int)
47
+ total: number
48
+ }
@@ -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(type => Domain)
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(type => User, { nullable: true })
58
+ creator?: User
59
+
60
+ @RelationId((dataArchive: DataArchive) => dataArchive.creator)
61
+ creatorId?: string
62
+
63
+ @ManyToOne(type => User, { nullable: true })
64
+ @Field(type => User, { nullable: true })
65
+ updater?: User
66
+
67
+ @RelationId((dataArchive: DataArchive) => dataArchive.updater)
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]
@@ -0,0 +1,31 @@
1
+ import { Field, InputType, ObjectType } from 'type-graphql'
2
+
3
+ @ObjectType({ description: 'Entity for DataKeyItem' })
4
+ export class DataKeyItem {
5
+ @Field()
6
+ name: string
7
+
8
+ @Field({ nullable: true })
9
+ description?: string
10
+
11
+ @Field({ nullable: true })
12
+ dataKey: string
13
+
14
+ @Field({ nullable: true })
15
+ tKey?: string
16
+ }
17
+
18
+ @InputType()
19
+ export class DataKeyItemPatch {
20
+ @Field({ nullable: true })
21
+ name?: string
22
+
23
+ @Field({ nullable: true })
24
+ description?: string
25
+
26
+ @Field({ nullable: true })
27
+ dataKey?: string
28
+
29
+ @Field({ nullable: true })
30
+ tKey?: string
31
+ }