@things-factory/dataset 8.0.0-alpha.0 → 8.0.0-alpha.11

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 (69) hide show
  1. package/client/activities/activity-data-collect-edit.ts +3 -1
  2. package/client/activities/activity-ooc-resolve-edit.ts +4 -2
  3. package/client/activities/activity-ooc-review-edit.ts +4 -2
  4. package/client/bootstrap.ts +11 -1
  5. package/client/components/data-entry-form.ts +3 -3
  6. package/client/pages/data-entry/data-entry-list-page.ts +65 -12
  7. package/client/pages/data-report/data-report-list-page.ts +9 -2
  8. package/client/pages/data-set/data-item-list.ts +1 -1
  9. package/client/pages/data-set/data-set-list-page.ts +14 -1
  10. package/dist-client/activities/activity-data-collect-edit.d.ts +1 -1
  11. package/dist-client/activities/activity-data-collect-edit.js +2 -1
  12. package/dist-client/activities/activity-data-collect-edit.js.map +1 -1
  13. package/dist-client/activities/activity-ooc-resolve-edit.js +4 -2
  14. package/dist-client/activities/activity-ooc-resolve-edit.js.map +1 -1
  15. package/dist-client/activities/activity-ooc-review-edit.js +4 -2
  16. package/dist-client/activities/activity-ooc-review-edit.js.map +1 -1
  17. package/dist-client/bootstrap.js +4 -0
  18. package/dist-client/bootstrap.js.map +1 -1
  19. package/dist-client/components/data-entry-form.js +3 -3
  20. package/dist-client/components/data-entry-form.js.map +1 -1
  21. package/dist-client/pages/data-entry/data-entry-list-page.js +61 -10
  22. package/dist-client/pages/data-entry/data-entry-list-page.js.map +1 -1
  23. package/dist-client/pages/data-report/data-report-list-page.js +8 -2
  24. package/dist-client/pages/data-report/data-report-list-page.js.map +1 -1
  25. package/dist-client/pages/data-set/data-item-list.js +1 -1
  26. package/dist-client/pages/data-set/data-item-list.js.map +1 -1
  27. package/dist-client/pages/data-set/data-set-list-page.js +14 -1
  28. package/dist-client/pages/data-set/data-set-list-page.js.map +1 -1
  29. package/dist-client/tsconfig.tsbuildinfo +1 -1
  30. package/dist-server/controllers/issue-data-collection-task.d.ts +2 -0
  31. package/dist-server/controllers/{issue-collect-data.js → issue-data-collection-task.js} +10 -7
  32. package/dist-server/controllers/issue-data-collection-task.js.map +1 -0
  33. package/dist-server/engine/task/issue-collect-data.js +2 -2
  34. package/dist-server/engine/task/issue-collect-data.js.map +1 -1
  35. package/dist-server/routes.js +5 -3
  36. package/dist-server/routes.js.map +1 -1
  37. package/dist-server/service/data-set/data-item-type.d.ts +2 -1
  38. package/dist-server/service/data-set/data-item-type.js +1 -0
  39. package/dist-server/service/data-set/data-item-type.js.map +1 -1
  40. package/dist-server/service/data-set/data-set-mutation.d.ts +1 -0
  41. package/dist-server/service/data-set/data-set-mutation.js +44 -11
  42. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  43. package/dist-server/service/data-set/data-set-query.d.ts +2 -0
  44. package/dist-server/service/data-set/data-set-query.js +89 -29
  45. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  46. package/dist-server/tsconfig.tsbuildinfo +1 -1
  47. package/helps/dataset/data-set.ja.md +55 -59
  48. package/helps/dataset/data-set.ko.md +9 -11
  49. package/helps/dataset/data-set.md +20 -24
  50. package/helps/dataset/data-set.zh.md +3 -11
  51. package/helps/dataset/task/issue-collect-data.ja.md +1 -1
  52. package/helps/dataset/task/issue-collect-data.ko.md +1 -1
  53. package/helps/dataset/task/issue-collect-data.md +1 -1
  54. package/helps/dataset/task/issue-collect-data.ms.md +1 -1
  55. package/helps/dataset/task/issue-collect-data.zh.md +1 -1
  56. package/package.json +13 -13
  57. package/server/controllers/{issue-collect-data.ts → issue-data-collection-task.ts} +9 -5
  58. package/server/engine/task/issue-collect-data.ts +2 -2
  59. package/server/routes.ts +5 -3
  60. package/server/service/data-set/data-item-type.ts +10 -5
  61. package/server/service/data-set/data-set-mutation.ts +45 -12
  62. package/server/service/data-set/data-set-query.ts +86 -30
  63. package/translations/en.json +1 -0
  64. package/translations/ja.json +1 -0
  65. package/translations/ko.json +1 -0
  66. package/translations/ms.json +1 -0
  67. package/translations/zh.json +1 -0
  68. package/dist-server/controllers/issue-collect-data.d.ts +0 -2
  69. package/dist-server/controllers/issue-collect-data.js.map +0 -1
@@ -1,14 +1,17 @@
1
1
  import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
2
  import { In } from 'typeorm'
3
3
 
4
+ import { getRepository } from '@things-factory/shell'
5
+ import { User } from '@things-factory/auth-base'
4
6
  import { createAttachment, deleteAttachmentsByRef } from '@things-factory/attachment-base'
5
7
  import { ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'
6
8
  import { Application, CallbackBase, registerSchedule, unregisterSchedule } from '@things-factory/scheduler-client'
7
- import { AssigneeItem } from '@things-factory/worklist'
9
+ import { Activity, AssigneeItem, issue } from '@things-factory/worklist'
8
10
 
9
11
  import { getDataFinalizeCrontabSchedule } from '../../controllers/finalize-data-collection'
10
12
  import { DataSet } from './data-set'
11
13
  import { DataSetPatch, NewDataSet } from './data-set-type'
14
+ import { issueDataCollectionTask } from '../../controllers/issue-data-collection-task'
12
15
 
13
16
  const crypto = require('crypto')
14
17
 
@@ -118,7 +121,7 @@ export class DataSetMutation {
118
121
  @Mutation(returns => DataSet, { description: 'To create new DataSet' })
119
122
  async createDataSet(@Arg('dataSet') dataSet: NewDataSet, @Ctx() context: ResolverContext): Promise<DataSet> {
120
123
  const { domain, user, tx } = context.state
121
- const dataSetRepo = tx.getRepository(DataSet)
124
+ const dataSetRepo = getRepository(DataSet, tx)
122
125
 
123
126
  const result = await dataSetRepo.save({
124
127
  ...dataSet,
@@ -145,7 +148,7 @@ export class DataSetMutation {
145
148
  @Ctx() context: ResolverContext
146
149
  ): Promise<DataSet> {
147
150
  const { domain, user, tx } = context.state
148
- const dataSetRepo = tx.getRepository(DataSet)
151
+ const dataSetRepo = getRepository(DataSet, tx)
149
152
 
150
153
  const dataSet = await dataSetRepo.findOne({
151
154
  where: { domain: { id: domain.id }, id },
@@ -175,7 +178,7 @@ export class DataSetMutation {
175
178
  @Ctx() context: ResolverContext
176
179
  ): Promise<DataSet[]> {
177
180
  const { domain, user, tx } = context.state
178
- const dataSetRepo = tx.getRepository(DataSet)
181
+ const dataSetRepo = getRepository(DataSet, tx)
179
182
 
180
183
  let results = []
181
184
  const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
@@ -242,7 +245,7 @@ export class DataSetMutation {
242
245
  async deleteDataSet(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
243
246
  const { domain, tx } = context.state
244
247
 
245
- await tx.getRepository(DataSet).delete({ domain: { id: domain.id }, id })
248
+ await getRepository(DataSet, tx).delete({ domain: { id: domain.id }, id })
246
249
  await deleteAttachmentsByRef(null, { refBys: [`report-${id}`] }, context)
247
250
 
248
251
  return true
@@ -254,7 +257,7 @@ export class DataSetMutation {
254
257
  async deleteDataSets(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<boolean> {
255
258
  const { domain, tx } = context.state
256
259
 
257
- await tx.getRepository(DataSet).delete({
260
+ await getRepository(DataSet, tx).delete({
258
261
  domain: { id: domain.id },
259
262
  id: In(ids)
260
263
  })
@@ -264,6 +267,36 @@ export class DataSetMutation {
264
267
  return true
265
268
  }
266
269
 
270
+ @Directive('@transaction')
271
+ @Mutation(returns => Boolean, { description: 'To issue data-collection task for the given dataset' })
272
+ async issueDataCollection(@Arg('dataSetId') dataSetId: string, @Ctx() context: ResolverContext): Promise<boolean> {
273
+ const { domain, tx, user } = context.state
274
+
275
+ const dataSet = await getRepository(DataSet, tx).findOne({
276
+ where: {
277
+ domain: {
278
+ id: In([domain.id, domain.parentId].filter(Boolean))
279
+ },
280
+ id: dataSetId
281
+ }
282
+ })
283
+
284
+ const { supervisoryRoleId } = dataSet
285
+
286
+ const me = await getRepository(User, tx).findOne({
287
+ where: { id: user.id },
288
+ relations: ['roles']
289
+ })
290
+
291
+ if (!me.roles.find(role => role.id == supervisoryRoleId)) {
292
+ throw new Error(`You don't have permission to issue data collection task for this dataset.`)
293
+ }
294
+
295
+ const activityInstance = await issueDataCollectionTask(domain.id, dataSet.id, context)
296
+
297
+ return !!activityInstance
298
+ }
299
+
267
300
  @Directive('@transaction')
268
301
  @Mutation(returns => DataSet, { description: 'To start data collection schedule for the given dataset' })
269
302
  async startDataCollectionSchedule(
@@ -272,7 +305,7 @@ export class DataSetMutation {
272
305
  ): Promise<DataSet> {
273
306
  const { domain, tx } = context.state
274
307
 
275
- var repository = tx.getRepository(DataSet)
308
+ var repository = getRepository(DataSet, tx)
276
309
  var dataSet = await repository.findOne({
277
310
  where: { domain: { id: domain.id }, id: dataSetId }
278
311
  })
@@ -338,7 +371,7 @@ export class DataSetMutation {
338
371
  ): Promise<DataSet | undefined> {
339
372
  const { domain, tx } = context.state
340
373
 
341
- var repository = tx.getRepository(DataSet)
374
+ var repository = getRepository(DataSet, tx)
342
375
  var dataSet = await repository.findOne({
343
376
  where: { domain: { id: domain.id }, id: dataSetId }
344
377
  })
@@ -371,7 +404,7 @@ export class DataSetMutation {
371
404
  ): Promise<DataSet> {
372
405
  const { domain, tx } = context.state
373
406
 
374
- var repository = tx.getRepository(DataSet)
407
+ var repository = getRepository(DataSet, tx)
375
408
  var dataSet = await repository.findOne({
376
409
  where: { domain: { id: domain.id }, id: dataSetId }
377
410
  })
@@ -448,7 +481,7 @@ export class DataSetMutation {
448
481
  ): Promise<DataSet | undefined> {
449
482
  const { domain, tx } = context.state
450
483
 
451
- var repository = tx.getRepository(DataSet)
484
+ var repository = getRepository(DataSet, tx)
452
485
  var dataSet = await repository.findOne({
453
486
  where: { domain: { id: domain.id }, id: dataSetId }
454
487
  })
@@ -482,7 +515,7 @@ export class DataSetMutation {
482
515
  @Ctx() context: ResolverContext
483
516
  ): Promise<boolean> {
484
517
  const { domain, tx } = context.state
485
- const dataSetRepo = tx.getRepository(DataSet)
518
+ const dataSetRepo = getRepository(DataSet, tx)
486
519
 
487
520
  await Promise.all(
488
521
  dataSets.map(async (dataSet: DataSet) => {
@@ -501,7 +534,7 @@ export class DataSetMutation {
501
534
  @Mutation(returns => [DataSet], { description: 'To copy multiple data-sets' })
502
535
  async copyDataSets(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<DataSet[]> {
503
536
  const { domain, user, tx } = context.state
504
- const dataSetRepo = tx.getRepository(DataSet)
537
+ const dataSetRepo = getRepository(DataSet, tx)
505
538
 
506
539
  const originals = await dataSetRepo.find({
507
540
  where: {
@@ -1,5 +1,5 @@
1
1
  import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
- import { In } from 'typeorm'
2
+ import { Brackets, In } from 'typeorm'
3
3
 
4
4
  import { Attachment } from '@things-factory/attachment-base'
5
5
  import { Role, User } from '@things-factory/auth-base'
@@ -19,6 +19,7 @@ var parser = require('cron-parser')
19
19
 
20
20
  @Resolver(DataSet)
21
21
  export class DataSetQuery {
22
+ // 데이터셋을 ID로 조회
22
23
  @Directive('@privilege(category: "data-set", privilege: "query", domainOwnerGranted: true)')
23
24
  @Query(returns => DataSet, { description: 'To fetch a DataSet' })
24
25
  async dataSet(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<DataSet> {
@@ -29,6 +30,7 @@ export class DataSetQuery {
29
30
  })
30
31
  }
31
32
 
33
+ // 데이터셋을 이름으로 조회
32
34
  @Directive('@privilege(category: "data-set", privilege: "query", domainOwnerGranted: true)')
33
35
  @Query(returns => DataSet, { description: 'To fetch a DataSet by name' })
34
36
  async dataSetByName(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<DataSet> {
@@ -39,6 +41,7 @@ export class DataSetQuery {
39
41
  })
40
42
  }
41
43
 
44
+ // 여러 데이터셋을 조회
42
45
  @Directive('@privilege(category: "data-set", privilege: "query", domainOwnerGranted: true)')
43
46
  @Query(returns => DataSetList, { description: 'To fetch multiple DataSets' })
44
47
  async dataSets(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<DataSetList> {
@@ -57,6 +60,7 @@ export class DataSetQuery {
57
60
  return { items, total }
58
61
  }
59
62
 
63
+ // 데이터 입력을 위한 데이터셋 조회
60
64
  @Query(returns => DataSetList, { description: 'To fetch multiple DataSets for data entry manually' })
61
65
  async dataSetsForEntry(
62
66
  @Args(type => ListParam) params: ListParam,
@@ -64,13 +68,15 @@ export class DataSetQuery {
64
68
  ): Promise<DataSetList> {
65
69
  var { domain, user } = context.state
66
70
 
67
- /* 조회한 사용자가 entry-role을 가진 data-set 리스트만 반환 */
71
+ // 조회한 사용자가 entry-role을 가진 data-set 리스트만 반환
68
72
  user = await getRepository(User).findOne({
69
73
  where: { id: user.id },
70
74
  relations: ['roles']
71
75
  })
72
76
 
73
- const roles = user.roles.filter(role => role.domainId === domain.id || (domain.parentId && role.domainId === domain.parentId)).map(role => role.id)
77
+ const roles = user.roles
78
+ .filter(role => role.domainId === domain.id || (domain.parentId && role.domainId === domain.parentId))
79
+ .map(role => role.id)
74
80
 
75
81
  if (!roles.length) {
76
82
  return { items: [], total: 0 }
@@ -83,13 +89,22 @@ export class DataSetQuery {
83
89
  alias: 'dataset',
84
90
  searchables: ['name', 'description']
85
91
  })
86
- .andWhere(`dataset.active = :active`, { active: true })
87
- .andWhere('dataset.entryRole IN (:...roles)', { roles })
92
+ .andWhere('dataset.active = :active', { active: true })
93
+ .andWhere(
94
+ new Brackets(qb => {
95
+ qb.where('dataset.supervisoryRole IN (:...roles)').orWhere('dataset.entryRole IN (:...roles)')
96
+ })
97
+ )
98
+ .setParameter('roles', roles)
88
99
  .getManyAndCount()
89
100
 
90
- return { items, total }
101
+ return {
102
+ items,
103
+ total
104
+ }
91
105
  }
92
106
 
107
+ // 데이터 보고를 위한 데이터셋 조회
93
108
  @Query(returns => DataSetList, { description: 'To fetch multiple DataSets to see data report' })
94
109
  async dataSetsForReport(
95
110
  @Args(type => ListParam) params: ListParam,
@@ -97,7 +112,7 @@ export class DataSetQuery {
97
112
  ): Promise<DataSetList> {
98
113
  var { domain, user } = context.state
99
114
 
100
- /* 조회한 사용자가 supervisory 역할을 가진 data-set 리스트만 반환 */
115
+ // 조회한 사용자가 supervisory 역할을 가진 data-set 리스트만 반환
101
116
  user = await getRepository(User).findOne({
102
117
  where: { id: user.id },
103
118
  relations: ['roles']
@@ -122,9 +137,10 @@ export class DataSetQuery {
122
137
  return { items, total }
123
138
  }
124
139
 
140
+ // 데이터셋의 상태를 조회
125
141
  @FieldResolver(type => DataSetState)
126
142
  async status(@Root() dataSet: DataSet): Promise<DataSetState> {
127
- // get information from scheduler service
143
+ // 스케줄러 서비스에서 정보 가져오기
128
144
  return {
129
145
  id: '',
130
146
  scheduleId: '',
@@ -134,6 +150,7 @@ export class DataSetQuery {
134
150
  }
135
151
  }
136
152
 
153
+ // 데이터셋의 데이터 항목을 조회
137
154
  @FieldResolver(type => [DataItem])
138
155
  async dataItems(@Root() dataSet: DataSet): Promise<DataItem[]> {
139
156
  if (dataSet.dataItems instanceof Array) {
@@ -143,6 +160,7 @@ export class DataSetQuery {
143
160
  return []
144
161
  }
145
162
 
163
+ // 데이터셋의 entry 역할을 조회
146
164
  @FieldResolver(type => Role)
147
165
  async entryRole(@Root() dataSet: DataSet): Promise<Role> {
148
166
  return (
@@ -154,7 +172,8 @@ export class DataSetQuery {
154
172
  )
155
173
  }
156
174
 
157
- @FieldResolver(type => Role)
175
+ // 데이터셋의 supervisory 역할을 조회
176
+ @FieldResolver(type => Role, { description: 'Retrieves the supervisory role for the dataset' })
158
177
  async supervisoryRole(@Root() dataSet: DataSet): Promise<Role> {
159
178
  return (
160
179
  dataSet.supervisoryRole ||
@@ -165,7 +184,7 @@ export class DataSetQuery {
165
184
  )
166
185
  }
167
186
 
168
- @FieldResolver(type => [AssigneeItem])
187
+ @FieldResolver(type => [AssigneeItem], { description: 'Retrieves the assignee items for the dataset' })
169
188
  async assignees(@Root() dataSet: DataSet, @Ctx() context: ResolverContext): Promise<AssigneeItem[]> {
170
189
  const { domain, user } = context.state
171
190
  const { assignees } = dataSet
@@ -206,7 +225,7 @@ export class DataSetQuery {
206
225
  return assigneeItemList
207
226
  }
208
227
 
209
- @FieldResolver(type => [ApprovalLineItem])
228
+ @FieldResolver(type => [ApprovalLineItem], { description: 'Retrieves the approval line items for the dataset' })
210
229
  async approvalLine(@Root() dataSet: DataSet, @Ctx() context: ResolverContext): Promise<ApprovalLineItem[]> {
211
230
  const { domain, user } = context.state
212
231
  const { reviewApprovalLine } = dataSet
@@ -248,21 +267,21 @@ export class DataSetQuery {
248
267
  return approvalLineItems
249
268
  }
250
269
 
251
- @FieldResolver(type => Board, { nullable: true })
270
+ @FieldResolver(type => Board, { nullable: true, description: 'Retrieves the entry board for the dataset' })
252
271
  async entryBoard(@Root() dataSet: DataSet): Promise<Board> {
253
272
  if (dataSet.entryType == 'board' && dataSet.entryView) {
254
273
  return await getRepository(Board).findOneBy({ id: dataSet.entryView })
255
274
  }
256
275
  }
257
276
 
258
- @FieldResolver(type => Board, { nullable: true })
277
+ @FieldResolver(type => Board, { nullable: true, description: 'Retrieves the monitor board for the dataset' })
259
278
  async monitorBoard(@Root() dataSet: DataSet): Promise<Board> {
260
279
  if (dataSet.monitorType == 'board' && dataSet.monitorView) {
261
280
  return await getRepository(Board).findOneBy({ id: dataSet.monitorView })
262
281
  }
263
282
  }
264
283
 
265
- @FieldResolver(type => DataKeySet, { nullable: true })
284
+ @FieldResolver(type => DataKeySet, { nullable: true, description: 'Retrieves the data key set for the dataset' })
266
285
  async dataKeySet(@Root() dataSet: DataSet): Promise<DataKeySet> {
267
286
  return (
268
287
  dataSet.dataKeySet ||
@@ -273,7 +292,7 @@ export class DataSetQuery {
273
292
  )
274
293
  }
275
294
 
276
- @FieldResolver(type => Scenario)
295
+ @FieldResolver(type => Scenario, { description: 'Retrieves the normal scenario for the dataset.' })
277
296
  async normalScenario(@Root() dataSet: DataSet): Promise<Scenario> {
278
297
  return (
279
298
  dataSet.normalScenario ||
@@ -284,7 +303,7 @@ export class DataSetQuery {
284
303
  )
285
304
  }
286
305
 
287
- @FieldResolver(type => Scenario)
306
+ @FieldResolver(type => Scenario, { description: 'Retrieves the outlier scenario for the dataset.' })
288
307
  async outlierScenario(@Root() dataSet: DataSet): Promise<Scenario> {
289
308
  return (
290
309
  dataSet.outlierScenario ||
@@ -295,22 +314,25 @@ export class DataSetQuery {
295
314
  )
296
315
  }
297
316
 
317
+ // 데이터셋의 도메인을 조회
298
318
  @FieldResolver(type => Domain)
299
319
  async domain(@Root() dataSet: DataSet): Promise<Domain> {
300
320
  return dataSet.domainId && (await getRepository(Domain).findOneBy({ id: dataSet.domainId }))
301
321
  }
302
322
 
323
+ // 데이터셋의 업데이트한 사용자를 조회
303
324
  @FieldResolver(type => User)
304
325
  async updater(@Root() dataSet: DataSet): Promise<User> {
305
326
  return dataSet.updaterId && (await getRepository(User).findOneBy({ id: dataSet.updaterId }))
306
327
  }
307
328
 
329
+ // 데이터셋의 생성자를 조회
308
330
  @FieldResolver(type => User)
309
331
  async creator(@Root() dataSet: DataSet): Promise<User> {
310
332
  return dataSet.creatorId && (await getRepository(User).findOneBy({ id: dataSet.creatorId }))
311
333
  }
312
334
 
313
- @FieldResolver(type => Date, { nullable: true })
335
+ @FieldResolver(type => Date, { nullable: true, description: 'Retrieves the latest collection time for the dataset.' })
314
336
  async latestCollectedAt(@Root() dataSet: DataSet): Promise<Date> {
315
337
  const sample = await getRepository(DataSample).findOne({
316
338
  select: ['id', 'collectedAt'],
@@ -321,7 +343,7 @@ export class DataSetQuery {
321
343
  return sample?.collectedAt
322
344
  }
323
345
 
324
- @FieldResolver(type => Date, { nullable: true })
346
+ @FieldResolver(type => Date, { nullable: true, description: 'Retrieves the next schedule time for the dataset.' })
325
347
  async nextSchedule(@Root() dataSet: DataSet): Promise<Date> {
326
348
  const { domainId, schedule, timezone } = dataSet
327
349
 
@@ -336,7 +358,7 @@ export class DataSetQuery {
336
358
  return interval.next().toDate()
337
359
  }
338
360
 
339
- @FieldResolver(type => Date, { nullable: true })
361
+ @FieldResolver(type => Date, { nullable: true, description: 'Retrieves the previous schedule time for the dataset.' })
340
362
  async prevSchedule(@Root() dataSet: DataSet): Promise<Date> {
341
363
  const { domainId, schedule, timezone } = dataSet
342
364
 
@@ -351,7 +373,10 @@ export class DataSetQuery {
351
373
  return interval.prev().toDate()
352
374
  }
353
375
 
354
- @FieldResolver(type => Date, { nullable: true })
376
+ @FieldResolver(type => Date, {
377
+ nullable: true,
378
+ description: 'Retrieves the next summary schedule time for the dataset.'
379
+ })
355
380
  async nextSummarySchedule(@Root() dataSet: DataSet): Promise<Date> {
356
381
  const { domainId, summarySchedule, timezone } = dataSet
357
382
 
@@ -365,20 +390,19 @@ export class DataSetQuery {
365
390
 
366
391
  return interval.next().toDate()
367
392
 
368
- // /* FIXME: getSchedules 의 파라미터를 수정해야한다. scheduler 가 없거나 커넥션이 끊겨있어서 오래걸리는 문제는 어떻게 ?? 비동기로 처리한다. 어떻게???
369
- // client: {
370
- // application: Application,
371
- // group: `${domain.id}`,
372
- // type: 'data-set',
373
- // key: dataSet.id,
374
- // operation: 'summary'
375
- // },
376
- // */
393
+ // FIXME: getSchedules 의 파라미터를 수정해야한다. scheduler 가 없거나 커넥션이 끊겨있어서 오래걸리는 문제는 어떻게 ?? 비동기로 처리한다. 어떻게???
394
+ // client: {
395
+ // application: Application,
396
+ // group: `${domain.id}`,
397
+ // type: 'data-set',
398
+ // key: dataSet.id,
399
+ // operation: 'summary'
400
+ // }
377
401
  // const schedule = getSchedules('name', 'group', false)
378
402
  // return schedule.nextSchedule
379
403
  }
380
404
 
381
- @FieldResolver(type => String)
405
+ @FieldResolver(type => String, { description: 'Retrieves the report template for the dataset.' })
382
406
  async reportTemplate(@Root() dataset: DataSet): Promise<string | undefined> {
383
407
  const attachment: Attachment = await getRepository(Attachment).findOne({
384
408
  where: {
@@ -390,4 +414,36 @@ export class DataSetQuery {
390
414
 
391
415
  return attachment?.path
392
416
  }
417
+
418
+ @FieldResolver(returns => Boolean, { description: 'Whether the user is a supervisor for this dataset' })
419
+ async isSupervisor(@Root() dataset: DataSet, @Ctx() context: ResolverContext): Promise<boolean> {
420
+ const { user, domain } = context.state
421
+
422
+ const foundUser = await getRepository(User).findOne({
423
+ where: { id: user.id },
424
+ relations: ['roles']
425
+ })
426
+
427
+ const roles = foundUser.roles
428
+ .filter(role => role.domainId === domain.id || (domain.parentId && role.domainId === domain.parentId))
429
+ .map(role => role.id)
430
+
431
+ return roles.includes(dataset.supervisoryRoleId)
432
+ }
433
+
434
+ @FieldResolver(returns => Boolean, { description: 'Whether the user is allowed to enter data for this dataset' })
435
+ async isEntryAllowed(@Root() dataset: DataSet, @Ctx() context: ResolverContext): Promise<boolean> {
436
+ const { user, domain } = context.state
437
+
438
+ const foundUser = await getRepository(User).findOne({
439
+ where: { id: user.id },
440
+ relations: ['roles']
441
+ })
442
+
443
+ const roles = foundUser.roles
444
+ .filter(role => role.domainId === domain.id || (domain.parentId && role.domainId === domain.parentId))
445
+ .map(role => role.id)
446
+
447
+ return roles.includes(dataset.entryRoleId)
448
+ }
393
449
  }
@@ -1,4 +1,5 @@
1
1
  {
2
+ "button.assign-data-collection": "assign data collection",
2
3
  "button.corrected": "corrected",
3
4
  "button.edit-model": "edit model",
4
5
  "button.enter-data": "enter data",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "button.assign-data-collection": "データ収集を割り当てる",
2
3
  "button.corrected": "措置完了",
3
4
  "button.edit-model": "モデルを編集",
4
5
  "button.enter-data": "データを入力",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "button.assign-data-collection": "데이타수집 작업할당",
2
3
  "button.corrected": "조치완료",
3
4
  "button.edit-model": "모델 편집",
4
5
  "button.enter-data": "데이타 입력",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "button.assign-data-collection": "tetapkan pengumpulan data",
2
3
  "button.corrected": "diperbetulkan",
3
4
  "button.edit-model": "edit model",
4
5
  "button.enter-data": "enter data",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "button.assign-data-collection": "分配数据收集",
2
3
  "button.corrected": "已处理",
3
4
  "button.edit-model": "编辑模型",
4
5
  "button.enter-data": "输入数据",
@@ -1,2 +0,0 @@
1
- import { ActivityInstance } from '@things-factory/worklist';
2
- export declare function issueCollectData(domainId: string, dataSetId: string, context: ResolverContext): Promise<ActivityInstance | void>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"issue-collect-data.js","sourceRoot":"","sources":["../../server/controllers/issue-collect-data.ts"],"names":[],"mappings":";;AAOA,4CA2DC;AAlED,qCAA4B;AAE5B,iDAA6D;AAC7D,uDAA4E;AAE5E,2DAAsD;AAE/C,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,SAAiB,EACjB,OAAwB;IAExB,MAAM,IAAA,qBAAa,GAAE,CAAC,WAAW,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QAEzE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,aAAa,CAAC,CAAA;QAClD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,kBAAO,CAAC,CAAC,OAAO,CAAC;YACtD,KAAK,EAAE;gBACL,MAAM,EAAE;oBACN,EAAE,EAAE,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;iBACrD;gBACD,EAAE,EAAE,SAAS;aACd;SACF,CAAC,CAAA;QAEF,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,mBAAQ,CAAC,CAAC,SAAS,CAAC;YAC3D,MAAM,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE;YAChE,IAAI,EAAE,cAAc;SACrB,CAAC,CAAa,CAAA;QAEf,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;YAE7B,0DAA0D;YAC1D,IAAI,SAAS,IAAI,SAAS,YAAY,KAAK,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpE,MAAM,gBAAgB,GAAG;oBACvB,IAAI,EAAE,aAAa,OAAO,CAAC,IAAI,EAAE;oBACjC,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;oBACjD,KAAK,EAAE;wBACL,SAAS,EAAE,OAAO,CAAC,EAAE;wBACrB,WAAW,EAAE,OAAO,CAAC,IAAI;qBAC1B;oBACD,SAAS;iBACV,CAAA;gBAED,OAAO,CAAC,KAAK,mCACR,OAAO,CAAC,KAAK,KAChB,MAAM;oBACN,EAAE,GACH,CAAA;gBAED,OAAO,MAAM,IAAA,gBAAK,EAAC,gBAAgB,EAAE,OAAO,CAAC,CAAA;YAC/C,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,mDAAmD,OAAO,CAAC,IAAI,oCAAoC,CACpG,CAAA;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { In } from 'typeorm'\n\nimport { Domain, getDataSource } from '@things-factory/shell'\nimport { Activity, ActivityInstance, issue } from '@things-factory/worklist'\n\nimport { DataSet } from '../service/data-set/data-set'\n\nexport async function issueCollectData(\n domainId: string,\n dataSetId: string,\n context: ResolverContext\n): Promise<ActivityInstance | void> {\n await getDataSource().transaction(async tx => {\n const domain = await tx.getRepository(Domain).findOneBy({ id: domainId })\n\n if (!domain) {\n throw new Error(`domain(${domainId}) not found`)\n }\n\n const dataSet = await tx.getRepository(DataSet).findOne({\n where: {\n domain: {\n id: In([domain.id, domain.parentId].filter(Boolean))\n },\n id: dataSetId\n }\n })\n\n const activity = (await tx.getRepository(Activity).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n name: 'Collect Data'\n })) as Activity\n\n if (activity) {\n const { assignees } = dataSet\n\n /* 해당 dataset에 대한 데이타 수집 태스크를 dataset assignees에게 할당한다. */\n if (assignees && assignees instanceof Array && assignees.length > 0) {\n const activityInstance = {\n name: `[Data 수집] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(Date.now() + 24 * 60 * 60 * 1000),\n input: {\n dataSetId: dataSet.id,\n dataSetName: dataSet.name\n },\n assignees\n }\n\n context.state = {\n ...context.state,\n domain,\n tx\n }\n\n return await issue(activityInstance, context)\n } else {\n throw new Error(\n `Assignees not set. So Data Collect Activity for ${dataSet.name}($dataSet.id) could not be issued.`\n )\n }\n } else {\n throw new Error(`Data Collect Activity is not installed.`)\n }\n })\n}\n"]}