@things-factory/worklist 6.0.43 → 6.0.46

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 (190) hide show
  1. package/client/bootstrap.ts +5 -0
  2. package/client/components/activity-starter-form.ts +52 -303
  3. package/client/pages/activity/activity-list-page.ts +44 -28
  4. package/client/pages/activity/activity-page.ts +3 -3
  5. package/client/pages/activity/activity-partial-view.ts +2 -1
  6. package/client/pages/activity/starter-list-page.ts +16 -11
  7. package/client/pages/activity-instance/activity-instance-search-page.ts +2 -19
  8. package/client/pages/activity-instance/activity-instance-start-page.ts +514 -0
  9. package/client/pages/activity-stats/activity-stats-importer.ts +97 -0
  10. package/client/pages/activity-stats/activity-stats-list-page.ts +348 -0
  11. package/client/pages/activity-thread/activity-thread-page.ts +1 -1
  12. package/client/pages/installable-activity/installable-activity-list-page.ts +7 -5
  13. package/client/pages/todo/approval-done-list-page.ts +340 -0
  14. package/client/pages/todo/approval-pending-list-page.ts +2 -2
  15. package/client/pages/todo/done-list-calendar-page.ts +115 -0
  16. package/client/pages/todo/done-list-page.ts +2 -3
  17. package/client/pages/todo/draft-list-page.ts +26 -102
  18. package/client/pages/todo/pickable-list-page.ts +2 -1
  19. package/client/pages/todo/todo-list-page.ts +1 -1
  20. package/client/route.ts +14 -2
  21. package/client/templates/activity-approval-context-template.ts +4 -0
  22. package/client/templates/activity-instance-context-template.ts +171 -0
  23. package/client/templates/activity-thread-context-template.ts +4 -0
  24. package/client/themes/calendar-theme.css +54 -0
  25. package/client/types/activity-instance-type.ts +4 -2
  26. package/client/types/activity-instance.ts +2 -2
  27. package/client/types/activity.ts +7 -0
  28. package/client/types/types.ts +8 -0
  29. package/dist-client/bootstrap.d.ts +1 -0
  30. package/dist-client/bootstrap.js +5 -0
  31. package/dist-client/bootstrap.js.map +1 -1
  32. package/dist-client/components/activity-starter-form.d.ts +2 -5
  33. package/dist-client/components/activity-starter-form.js +54 -247
  34. package/dist-client/components/activity-starter-form.js.map +1 -1
  35. package/dist-client/pages/activity/activity-list-page.d.ts +1 -1
  36. package/dist-client/pages/activity/activity-list-page.js +45 -30
  37. package/dist-client/pages/activity/activity-list-page.js.map +1 -1
  38. package/dist-client/pages/activity/activity-page.d.ts +1 -1
  39. package/dist-client/pages/activity/activity-page.js +3 -3
  40. package/dist-client/pages/activity/activity-page.js.map +1 -1
  41. package/dist-client/pages/activity/activity-partial-view.js +2 -2
  42. package/dist-client/pages/activity/activity-partial-view.js.map +1 -1
  43. package/dist-client/pages/activity/starter-list-page.d.ts +1 -0
  44. package/dist-client/pages/activity/starter-list-page.js +14 -11
  45. package/dist-client/pages/activity/starter-list-page.js.map +1 -1
  46. package/dist-client/pages/activity-instance/activity-instance-page.d.ts +2 -2
  47. package/dist-client/pages/activity-instance/activity-instance-page.js +19 -10
  48. package/dist-client/pages/activity-instance/activity-instance-page.js.map +1 -1
  49. package/dist-client/pages/activity-instance/activity-instance-search-page.js +1 -8
  50. package/dist-client/pages/activity-instance/activity-instance-search-page.js.map +1 -1
  51. package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +49 -0
  52. package/dist-client/pages/activity-instance/activity-instance-start-page.js +450 -0
  53. package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -0
  54. package/dist-client/pages/activity-stats/activity-stats-importer.d.ts +22 -0
  55. package/dist-client/pages/activity-stats/activity-stats-importer.js +100 -0
  56. package/dist-client/pages/activity-stats/activity-stats-importer.js.map +1 -0
  57. package/dist-client/pages/activity-stats/activity-stats-list-page.d.ts +62 -0
  58. package/dist-client/pages/activity-stats/activity-stats-list-page.js +326 -0
  59. package/dist-client/pages/activity-stats/activity-stats-list-page.js.map +1 -0
  60. package/dist-client/pages/activity-thread/activity-thread-page.js +1 -1
  61. package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
  62. package/dist-client/pages/installable-activity/installable-activity-list-page.js +7 -5
  63. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
  64. package/dist-client/pages/todo/approval-done-list-page.d.ts +39 -0
  65. package/dist-client/pages/todo/approval-done-list-page.js +338 -0
  66. package/dist-client/pages/todo/approval-done-list-page.js.map +1 -0
  67. package/dist-client/pages/todo/approval-pending-list-page.js +2 -2
  68. package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
  69. package/dist-client/pages/todo/done-list-calendar-page.d.ts +24 -0
  70. package/dist-client/pages/todo/done-list-calendar-page.js +107 -0
  71. package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -0
  72. package/dist-client/pages/todo/done-list-page.js +2 -3
  73. package/dist-client/pages/todo/done-list-page.js.map +1 -1
  74. package/dist-client/pages/todo/draft-list-page.d.ts +1 -0
  75. package/dist-client/pages/todo/draft-list-page.js +25 -99
  76. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  77. package/dist-client/pages/todo/pickable-list-page.d.ts +1 -0
  78. package/dist-client/pages/todo/pickable-list-page.js +2 -1
  79. package/dist-client/pages/todo/pickable-list-page.js.map +1 -1
  80. package/dist-client/pages/todo/todo-list-page.js +1 -1
  81. package/dist-client/pages/todo/todo-list-page.js.map +1 -1
  82. package/dist-client/route.d.ts +1 -1
  83. package/dist-client/route.js +11 -2
  84. package/dist-client/route.js.map +1 -1
  85. package/dist-client/templates/activity-approval-context-template.js +4 -0
  86. package/dist-client/templates/activity-approval-context-template.js.map +1 -1
  87. package/dist-client/templates/activity-instance-context-template.d.ts +2 -0
  88. package/dist-client/templates/activity-instance-context-template.js +145 -0
  89. package/dist-client/templates/activity-instance-context-template.js.map +1 -0
  90. package/dist-client/templates/activity-thread-context-template.js +4 -0
  91. package/dist-client/templates/activity-thread-context-template.js.map +1 -1
  92. package/dist-client/tsconfig.tsbuildinfo +1 -1
  93. package/dist-client/types/activity-instance-type.d.ts +3 -2
  94. package/dist-client/types/activity-instance-type.js +2 -2
  95. package/dist-client/types/activity-instance-type.js.map +1 -1
  96. package/dist-client/types/activity-instance.d.ts +1 -1
  97. package/dist-client/types/activity-instance.js +2 -2
  98. package/dist-client/types/activity-instance.js.map +1 -1
  99. package/dist-client/types/activity.d.ts +5 -0
  100. package/dist-client/types/activity.js +5 -0
  101. package/dist-client/types/activity.js.map +1 -1
  102. package/dist-client/types/types.d.ts +4 -0
  103. package/dist-client/types/types.js +6 -0
  104. package/dist-client/types/types.js.map +1 -1
  105. package/dist-server/controllers/activity-instance/assign.js +1 -1
  106. package/dist-server/controllers/activity-instance/assign.js.map +1 -1
  107. package/dist-server/controllers/activity-instance/draft.js +24 -6
  108. package/dist-server/controllers/activity-instance/draft.js.map +1 -1
  109. package/dist-server/controllers/activity-instance/index.js +1 -1
  110. package/dist-server/controllers/activity-instance/index.js.map +1 -1
  111. package/dist-server/controllers/activity-instance/issue.js +105 -0
  112. package/dist-server/controllers/activity-instance/issue.js.map +1 -0
  113. package/dist-server/controllers/activity-instance/pick.js +1 -1
  114. package/dist-server/controllers/activity-instance/pick.js.map +1 -1
  115. package/dist-server/controllers/activity-instance/post.js +7 -7
  116. package/dist-server/controllers/activity-instance/post.js.map +1 -1
  117. package/dist-server/controllers/common.js +33 -9
  118. package/dist-server/controllers/common.js.map +1 -1
  119. package/dist-server/routes.js +2 -2
  120. package/dist-server/routes.js.map +1 -1
  121. package/dist-server/service/activity/activity-history.js +6 -2
  122. package/dist-server/service/activity/activity-history.js.map +1 -1
  123. package/dist-server/service/activity/activity-query.js +84 -1
  124. package/dist-server/service/activity/activity-query.js.map +1 -1
  125. package/dist-server/service/activity/activity-type.js +8 -0
  126. package/dist-server/service/activity/activity-type.js.map +1 -1
  127. package/dist-server/service/activity/activity.js +36 -3
  128. package/dist-server/service/activity/activity.js.map +1 -1
  129. package/dist-server/service/activity-approval/activity-approval-query.js +48 -0
  130. package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
  131. package/dist-server/service/activity-instance/activity-instance-history.js +1 -1
  132. package/dist-server/service/activity-instance/activity-instance-history.js.map +1 -1
  133. package/dist-server/service/activity-instance/activity-instance-mutation.js +6 -6
  134. package/dist-server/service/activity-instance/activity-instance-mutation.js.map +1 -1
  135. package/dist-server/service/activity-instance/activity-instance-query.js +2 -2
  136. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  137. package/dist-server/service/activity-instance/activity-instance-type.js +62 -50
  138. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  139. package/dist-server/service/activity-instance/activity-instance.js +4 -23
  140. package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
  141. package/dist-server/service/activity-stats/activity-stats-query.js +93 -0
  142. package/dist-server/service/activity-stats/activity-stats-query.js.map +1 -0
  143. package/dist-server/service/activity-stats/activity-stats-type.js +47 -0
  144. package/dist-server/service/activity-stats/activity-stats-type.js.map +1 -0
  145. package/dist-server/service/activity-stats/index.js +6 -0
  146. package/dist-server/service/activity-stats/index.js.map +1 -0
  147. package/dist-server/service/activity-summary/activity-summary-query.js +5 -23
  148. package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
  149. package/dist-server/service/index.js +2 -0
  150. package/dist-server/service/index.js.map +1 -1
  151. package/dist-server/service/installable-activity/installable-activity.js +4 -0
  152. package/dist-server/service/installable-activity/installable-activity.js.map +1 -1
  153. package/dist-server/tsconfig.tsbuildinfo +1 -1
  154. package/helps/worklist/activity-bank.md +22 -0
  155. package/helps/worklist/{activity-approval.md → activity-stats.md} +1 -1
  156. package/helps/worklist/activity.md +91 -0
  157. package/helps/worklist/draft-list.md +19 -0
  158. package/helps/worklist/starter-list.md +34 -0
  159. package/helps/worklist/worklist-concept.md +11 -8
  160. package/package.json +3 -2
  161. package/server/controllers/activity-instance/assign.ts +1 -1
  162. package/server/controllers/activity-instance/draft.ts +33 -6
  163. package/server/controllers/activity-instance/index.ts +1 -1
  164. package/server/controllers/activity-instance/issue.ts +175 -0
  165. package/server/controllers/activity-instance/pick.ts +1 -1
  166. package/server/controllers/common.ts +43 -9
  167. package/server/routes.ts +2 -2
  168. package/server/service/activity/activity-history.ts +5 -2
  169. package/server/service/activity/activity-query.ts +85 -2
  170. package/server/service/activity/activity-type.ts +15 -2
  171. package/server/service/activity/activity.ts +28 -2
  172. package/server/service/activity-approval/activity-approval-query.ts +45 -1
  173. package/server/service/activity-instance/activity-instance-history.ts +1 -1
  174. package/server/service/activity-instance/activity-instance-mutation.ts +7 -7
  175. package/server/service/activity-instance/activity-instance-query.ts +3 -3
  176. package/server/service/activity-instance/activity-instance-type.ts +13 -4
  177. package/server/service/activity-instance/activity-instance.ts +4 -16
  178. package/server/service/activity-stats/activity-stats-query.ts +94 -0
  179. package/server/service/activity-stats/activity-stats-type.ts +34 -0
  180. package/server/service/activity-stats/index.ts +3 -0
  181. package/server/service/activity-summary/activity-summary-query.ts +5 -23
  182. package/server/service/index.ts +2 -0
  183. package/server/service/installable-activity/installable-activity.ts +4 -1
  184. package/things-factory.config.js +5 -2
  185. package/translations/en.json +23 -0
  186. package/translations/ko.json +29 -6
  187. package/translations/ms.json +23 -0
  188. package/translations/zh.json +23 -0
  189. package/client/pages/activity-instance/activity-instance-page.ts +0 -445
  190. package/server/controllers/activity-instance/post.ts +0 -140
@@ -4,8 +4,9 @@ import { Brackets } from 'typeorm'
4
4
  import { Attachment } from '@things-factory/attachment-base'
5
5
  import { Role, User } from '@things-factory/auth-base'
6
6
  import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
7
+ import { ApprovalLineItem } from '@things-factory/organization'
7
8
 
8
- import { Activity, ActivityStatus } from './activity'
9
+ import { Activity, ActivityStartingType, ActivityStatus, AssigneeItem } from './activity'
9
10
  import { ActivityList } from './activity-type'
10
11
 
11
12
  @Resolver(Activity)
@@ -63,7 +64,9 @@ export class ActivityQuery {
63
64
  alias: 'activity',
64
65
  searchables: ['name', 'description']
65
66
  })
66
- .andWhere(`activity.startable = :startable`, { startable: true })
67
+ .andWhere(`activity.startingType IN (:...startingTypes)`, {
68
+ startingTypes: [ActivityStartingType.Issue, ActivityStartingType.Post]
69
+ })
67
70
  .andWhere(`activity.state = :state`, { state: ActivityStatus.Released })
68
71
  .andWhere(
69
72
  roles.length > 0
@@ -128,6 +131,86 @@ export class ActivityQuery {
128
131
  )
129
132
  }
130
133
 
134
+ @FieldResolver(type => [AssigneeItem])
135
+ async assignees(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<AssigneeItem[]> {
136
+ const { domain, user } = context.state
137
+ const { assignees } = activity
138
+
139
+ if (!assignees || !(assignees instanceof Array)) {
140
+ return null
141
+ }
142
+
143
+ var assigneeItemList = []
144
+
145
+ for (let item of assignees) {
146
+ var { type, value: id } = item
147
+ var assignee
148
+
149
+ switch (type) {
150
+ case 'Employee':
151
+ assignee = await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id })
152
+ break
153
+ case 'Department':
154
+ assignee = await getRepository('Department').findOneBy({ domain: { id: domain.id }, id })
155
+ break
156
+ case 'Role':
157
+ assignee = await getRepository('Role').findOneBy({ domain: { id: domain.id }, id })
158
+ break
159
+ case 'Myself':
160
+ assignee = user
161
+ break
162
+ case 'MyDepartment':
163
+ case 'MySupervisor':
164
+ break
165
+ default:
166
+ }
167
+
168
+ assignee && assigneeItemList.push({ type, value: id, assignee })
169
+ }
170
+
171
+ return assigneeItemList
172
+ }
173
+
174
+ @FieldResolver(type => [ApprovalLineItem])
175
+ async approvalLine(@Root() activity: Activity, @Ctx() context: ResolverContext): Promise<ApprovalLineItem[]> {
176
+ const { domain, user } = context.state
177
+ const { approvalLine } = activity
178
+
179
+ if (!approvalLine || !(approvalLine instanceof Array)) {
180
+ return null
181
+ }
182
+
183
+ var approvalLineItems = []
184
+
185
+ for (let item of approvalLine) {
186
+ var { type, value: id } = item
187
+ var approver
188
+
189
+ switch (type) {
190
+ case 'Employee':
191
+ approver = await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id })
192
+ break
193
+ case 'Department':
194
+ approver = await getRepository('Department').findOneBy({ domain: { id: domain.id }, id })
195
+ break
196
+ case 'Role':
197
+ approver = await getRepository('Role').findOneBy({ domain: { id: domain.id }, id })
198
+ break
199
+ case 'Myself':
200
+ approver = user
201
+ break
202
+ case 'MyDepartment':
203
+ case 'MySupervisor':
204
+ break
205
+ default:
206
+ }
207
+
208
+ approver && approvalLineItems.push({ type, value: id, approver })
209
+ }
210
+
211
+ return approvalLineItems
212
+ }
213
+
131
214
  @FieldResolver(type => Role)
132
215
  async supervisoryRole(@Root() activity: Activity): Promise<Role> {
133
216
  return (
@@ -5,8 +5,15 @@ import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
5
5
  import { ObjectRef, ScalarObject } from '@things-factory/shell'
6
6
  import { ApprovalLineItem } from '@things-factory/organization'
7
7
 
8
- import { AssigneeItem } from '../activity-instance/activity-instance'
9
- import { Activity, ActivityStatus, ActivityType, ActivityUIType, MultipleInstanceType } from './activity'
8
+ import {
9
+ Activity,
10
+ ActivityStartingType,
11
+ ActivityStatus,
12
+ ActivityType,
13
+ ActivityUIType,
14
+ AssigneeItem,
15
+ MultipleInstanceType
16
+ } from './activity'
10
17
  import { ActivityModelItem } from './activity-model-type'
11
18
  import { ActivitySearchKeyItem } from './activity-search-key-item-type'
12
19
 
@@ -36,6 +43,9 @@ export class NewActivity {
36
43
  @Field({ nullable: true })
37
44
  startable?: boolean
38
45
 
46
+ @Field({ nullable: true })
47
+ startingType?: ActivityStartingType
48
+
39
49
  @Field({ nullable: true })
40
50
  multiple?: MultipleInstanceType
41
51
 
@@ -120,6 +130,9 @@ export class ActivityPatch {
120
130
  @Field({ nullable: true })
121
131
  startable?: boolean
122
132
 
133
+ @Field({ nullable: true })
134
+ startingType?: ActivityStartingType
135
+
123
136
  @Field({ nullable: true })
124
137
  multiple?: MultipleInstanceType
125
138
 
@@ -13,9 +13,8 @@ import {
13
13
 
14
14
  import { Role, User } from '@things-factory/auth-base'
15
15
  import { Domain } from '@things-factory/shell'
16
- import { ApprovalLineItem } from '@things-factory/organization'
16
+ import { OrgMemberTargetType, OrgMemberTarget, ApprovalLineItem } from '@things-factory/organization'
17
17
 
18
- import { AssigneeItem } from '../activity-instance/activity-instance'
19
18
  import { ActivityModelItem } from './activity-model-type'
20
19
  import { ActivitySearchKeyItem } from './activity-search-key-item-type'
21
20
 
@@ -30,6 +29,17 @@ registerEnumType(ActivityStatus, {
30
29
  description: 'state enumeration of a activity'
31
30
  })
32
31
 
32
+ export enum ActivityStartingType {
33
+ None = '',
34
+ Post = 'post',
35
+ Issue = 'issue'
36
+ }
37
+
38
+ registerEnumType(ActivityStartingType, {
39
+ name: 'ActivityStartingType',
40
+ description: 'whether the purpose of starting the activity is to issue or post'
41
+ })
42
+
33
43
  export enum ActivityType {
34
44
  Task = 'task',
35
45
  Service = 'service',
@@ -73,6 +83,18 @@ registerEnumType(ActivityUIType, {
73
83
  description: 'user-interface type enumeration of a activity'
74
84
  })
75
85
 
86
+ @ObjectType()
87
+ export class AssigneeItem {
88
+ @Field(type => OrgMemberTargetType, { nullable: true })
89
+ type?: OrgMemberTargetType
90
+
91
+ @Field({ nullable: true })
92
+ value?: string
93
+
94
+ @Field(type => OrgMemberTarget, { nullable: true })
95
+ assignee?: OrgMemberTarget
96
+ }
97
+
76
98
  @Entity()
77
99
  @Index('ix_activity_0', (activity: Activity) => [activity.domain, activity.name], { unique: true })
78
100
  @Index('ix_activity_1', (activity: Activity) => [activity.domain, activity.state, activity.priority], { unique: false })
@@ -125,6 +147,10 @@ export class Activity {
125
147
  @Field({ nullable: true, description: 'Whether the task can be started arbitrarily by a user with privileges' })
126
148
  startable?: boolean
127
149
 
150
+ @Column({ nullable: true })
151
+ @Field({ nullable: true, description: 'Whether the purpose of starting the activity is to issue or post' })
152
+ startingType?: ActivityStartingType
153
+
128
154
  @Column({ nullable: true })
129
155
  @Field({
130
156
  nullable: true,
@@ -1,7 +1,6 @@
1
1
  import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
2
  import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
3
  import { User } from '@things-factory/auth-base'
4
- import { ActivityInstance } from '../activity-instance/activity-instance'
5
4
  import { ActivityThread } from '../activity-thread/activity-thread'
6
5
  import { ActivityApproval, ActivityApprovalJudgment } from './activity-approval'
7
6
  import { ActivityApprovalList } from './activity-approval-type'
@@ -76,6 +75,51 @@ export class ActivityApprovalQuery {
76
75
  return { items, total }
77
76
  }
78
77
 
78
+ @Query(returns => ActivityApprovalList, {
79
+ description: 'To fetch the approvals(ActivityApprovals) which has done by me'
80
+ })
81
+ async approvalDoneList(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<ActivityApprovalList> {
82
+ var { domain, user } = context.state
83
+
84
+ const judgment = [
85
+ ActivityApprovalJudgment.Escalated,
86
+ ActivityApprovalJudgment.Delegated,
87
+ ActivityApprovalJudgment.Approved,
88
+ ActivityApprovalJudgment.Rejected
89
+ ]
90
+
91
+ const [items, total] = await getQueryBuilderFromListParams({
92
+ repository: getRepository(ActivityApproval),
93
+ params,
94
+ domain,
95
+ alias: 'ap',
96
+ searchables: ['name', 'description'],
97
+ filtersMap: {
98
+ name: {
99
+ relationColumn: 'activityThread.activityInstance',
100
+ columnName: 'name'
101
+ },
102
+ description: {
103
+ relationColumn: 'activityThread.activityInstance',
104
+ columnName: 'description'
105
+ },
106
+ priority: {
107
+ relationColumn: 'activityThread.activityInstance',
108
+ columnName: 'priority'
109
+ },
110
+ dueAt: {
111
+ relationColumn: 'activityThread.activityInstance',
112
+ columnName: 'dueAt'
113
+ }
114
+ }
115
+ })
116
+ .andWhere('ap.judgment IN (:...judgment)', { judgment })
117
+ .andWhere('ap.approver = :user', { user: user.id })
118
+ .getManyAndCount()
119
+
120
+ return { items, total }
121
+ }
122
+
79
123
  @FieldResolver(type => ActivityThread)
80
124
  async activityThread(@Root() activityApproval: ActivityApproval): Promise<ActivityThread> {
81
125
  return await getRepository(ActivityThread).findOneBy({ id: activityApproval.activityThreadId })
@@ -234,7 +234,7 @@ export class ActivityInstanceHistory implements HistoryEntityInterface<ActivityI
234
234
 
235
235
  isDelegatable(): boolean {
236
236
  switch (this.state) {
237
- case ActivityInstanceStatus.Posted:
237
+ case ActivityInstanceStatus.Issued:
238
238
  case ActivityInstanceStatus.Assigned:
239
239
  return true
240
240
  default:
@@ -2,29 +2,29 @@ import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
2
 
3
3
  import { ObjectRef, ScalarObject } from '@things-factory/shell'
4
4
 
5
- import { abort, assign, draft, end, pick, post } from '../../controllers/activity-instance'
5
+ import { abort, assign, draft, end, pick, issue } from '../../controllers/activity-instance'
6
6
  import { ActivityThread } from '../activity-thread/activity-thread'
7
7
  import { ActivityInstance } from './activity-instance'
8
- import { ActivityInstancePatch, ActivityInstancePost, NewActivityInstance } from './activity-instance-type'
8
+ import { ActivityInstanceIssue, ActivityInstanceDraft } from './activity-instance-type'
9
9
 
10
10
  @Resolver(ActivityInstance)
11
11
  export class ActivityInstanceMutation {
12
12
  @Directive('@transaction')
13
13
  @Mutation(returns => ActivityInstance, { description: 'To draft standard ActivityInstance' })
14
14
  async draftActivityInstance(
15
- @Arg('activityInstance') activityInstance: NewActivityInstance,
15
+ @Arg('activityInstance') activityInstance: ActivityInstanceDraft,
16
16
  @Ctx() context: ResolverContext
17
17
  ): Promise<ActivityInstance> {
18
18
  return await draft(activityInstance, context)
19
19
  }
20
20
 
21
21
  @Directive('@transaction')
22
- @Mutation(returns => ActivityInstance, { description: 'To post standard ActivityInstance' })
23
- async postActivityInstance(
24
- @Arg('activityInstance') activityInstance: ActivityInstancePost,
22
+ @Mutation(returns => ActivityInstance, { description: 'To issue standard ActivityInstance' })
23
+ async issueActivityInstance(
24
+ @Arg('activityInstance') activityInstance: ActivityInstanceIssue,
25
25
  @Ctx() context: ResolverContext
26
26
  ): Promise<ActivityInstance> {
27
- return await post(activityInstance, context)
27
+ return await issue(activityInstance, context)
28
28
  }
29
29
 
30
30
  @Directive('@transaction')
@@ -5,8 +5,8 @@ import { Role, User } from '@things-factory/auth-base'
5
5
  import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
6
6
 
7
7
  import { ActivityThread } from '../activity-thread/activity-thread'
8
- import { Activity } from '../activity/activity'
9
- import { ActivityInstance, ActivityInstanceStatus, AssigneeItem } from './activity-instance'
8
+ import { Activity, AssigneeItem } from '../activity/activity'
9
+ import { ActivityInstance, ActivityInstanceStatus } from './activity-instance'
10
10
  import { ActivityInstanceList } from './activity-instance-type'
11
11
  import { ApprovalLineItem } from '@things-factory/organization'
12
12
 
@@ -97,7 +97,7 @@ export class ActivityInstanceQuery {
97
97
  })
98
98
  .leftJoinAndSelect('ai.activityThreads', 'threads', 'threads.assignee = :user', { user: user.id })
99
99
  .andWhere('ai.state IN (:...status)', {
100
- status: [ActivityInstanceStatus.Posted, ActivityInstanceStatus.PendingAssignment]
100
+ status: [ActivityInstanceStatus.Issued, ActivityInstanceStatus.PendingAssignment]
101
101
  })
102
102
  .andWhere('ai.assigneeRole IN (:...roles)', { roles })
103
103
  .andWhere('threads.id IS NULL') /* 이미 내가 할당된 경우는 제외한다. */
@@ -4,10 +4,13 @@ import { Role } from '@things-factory/auth-base'
4
4
  import { ObjectRef, ScalarDate, ScalarObject } from '@things-factory/shell'
5
5
  import { ApprovalLineItem } from '@things-factory/organization'
6
6
 
7
- import { ActivityType, ActivityUIType } from '../activity/activity'
8
- import { AssigneeItem, ActivityInstance, ActivityInstanceStatus } from './activity-instance'
7
+ import { ActivityType, ActivityUIType, AssigneeItem } from '../activity/activity'
8
+ import { ActivityInstance, ActivityInstanceStatus } from './activity-instance'
9
9
  @InputType()
10
- export class NewActivityInstance {
10
+ export class ActivityInstanceDraft {
11
+ @Field(type => ID, { nullable: true })
12
+ id?: string
13
+
11
14
  @Field()
12
15
  name: string
13
16
 
@@ -35,6 +38,9 @@ export class NewActivityInstance {
35
38
  @Field(type => ScalarObject, { nullable: true })
36
39
  input?: { [key: string]: any }
37
40
 
41
+ @Field(type => ScalarObject, { nullable: true })
42
+ output?: { [key: string]: any }
43
+
38
44
  @Field({ nullable: true })
39
45
  adhocType?: string
40
46
 
@@ -70,7 +76,7 @@ export class NewActivityInstance {
70
76
  }
71
77
 
72
78
  @InputType()
73
- export class ActivityInstancePost {
79
+ export class ActivityInstanceIssue {
74
80
  @Field(type => ID, { nullable: true })
75
81
  id?: string
76
82
 
@@ -101,6 +107,9 @@ export class ActivityInstancePost {
101
107
  @Field(type => ScalarObject, { nullable: true })
102
108
  input?: { [key: string]: any }
103
109
 
110
+ @Field(type => ScalarObject, { nullable: true })
111
+ output?: { [key: string]: any }
112
+
104
113
  @Field({ nullable: true })
105
114
  adhocType?: string
106
115
 
@@ -14,14 +14,14 @@ import {
14
14
 
15
15
  import { Role, User } from '@things-factory/auth-base'
16
16
  import { Domain, ScalarObject } from '@things-factory/shell'
17
- import { OrgMemberTargetType, OrgMemberTarget, ApprovalLineItem } from '@things-factory/organization'
17
+ import { ApprovalLineItem } from '@things-factory/organization'
18
18
 
19
19
  import { ActivityThread } from '../activity-thread/activity-thread'
20
- import { Activity, ActivityType, ActivityUIType } from '../activity/activity'
20
+ import { Activity, ActivityType, ActivityUIType, AssigneeItem } from '../activity/activity'
21
21
 
22
22
  export enum ActivityInstanceStatus {
23
23
  Draft = 'draft',
24
- Posted = 'posted',
24
+ Issued = 'issued',
25
25
  PendingAssignment = 'pending-assignment',
26
26
  Assigned = 'assigned',
27
27
  Started = 'started',
@@ -35,18 +35,6 @@ registerEnumType(ActivityInstanceStatus, {
35
35
  description: 'state enumeration of a activityInstance'
36
36
  })
37
37
 
38
- @ObjectType()
39
- export class AssigneeItem {
40
- @Field(type => OrgMemberTargetType, { nullable: true })
41
- type?: OrgMemberTargetType
42
-
43
- @Field({ nullable: true })
44
- value?: string
45
-
46
- @Field(type => OrgMemberTarget, { nullable: true })
47
- assignee?: OrgMemberTarget
48
- }
49
-
50
38
  @Entity()
51
39
  @Index(
52
40
  'ix_activity_instance_0',
@@ -264,7 +252,7 @@ export class ActivityInstance {
264
252
 
265
253
  isDelegatable(): boolean {
266
254
  switch (this.state) {
267
- case ActivityInstanceStatus.Posted:
255
+ case ActivityInstanceStatus.Issued:
268
256
  case ActivityInstanceStatus.Assigned:
269
257
  return true
270
258
  default:
@@ -0,0 +1,94 @@
1
+ import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
+ import { User } from '@things-factory/auth-base'
4
+ import { ActivityEvent, ActivityEventStatus } from './activity-stats-type'
5
+ import { ActivityThread, ActivityThreadStatus } from '../activity-thread/activity-thread'
6
+ import { ActivityApproval, ActivityApprovalJudgment } from '../activity-approval/activity-approval'
7
+
8
+ @Resolver(ActivityStatsQuery)
9
+ export class ActivityStatsQuery {
10
+ @Query(returns => [ActivityEvent], { description: 'To fetch activity events by period' })
11
+ async activityEvents(
12
+ @Arg('from') from: string,
13
+ @Arg('to') to: string,
14
+ @Ctx() context: ResolverContext
15
+ ): Promise<ActivityEvent[]> {
16
+ const { domain, user } = context.state
17
+
18
+ if (!from) {
19
+ const beginOfToday = new Date()
20
+ beginOfToday.setHours(0, 0, 0, 0)
21
+ from = beginOfToday.toISOString().split('T').join(' ')
22
+ }
23
+
24
+ if (!to) {
25
+ const endOfToday = new Date()
26
+ endOfToday.setDate(endOfToday.getDate() + 1)
27
+ endOfToday.setHours(0, 0, 0, 0)
28
+ to = endOfToday.toISOString().split('T').join(' ')
29
+ }
30
+
31
+ const status = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]
32
+
33
+ var params = { filters: [{ name: 'terminatedAt', operator: 'between', value: [from, to] }] }
34
+
35
+ var doneItems = await getQueryBuilderFromListParams({
36
+ repository: getRepository(ActivityThread),
37
+ params,
38
+ domain,
39
+ alias: 'at'
40
+ })
41
+ .leftJoinAndSelect('at.activityInstance', 'ai')
42
+ .andWhere('at.state IN (:...status)', { status })
43
+ .andWhere('at.assignee = :user', { user: user.id })
44
+ .getMany()
45
+
46
+ const activityThreadDoneEvents = doneItems.map(({ id, activityInstance, terminatedAt }) => {
47
+ return {
48
+ id,
49
+ name: activityInstance.name,
50
+ date: terminatedAt,
51
+ priority: activityInstance.priority,
52
+ state: ActivityEventStatus.Done,
53
+ type: 'activity-thread'
54
+ }
55
+ })
56
+
57
+ const judgment = [
58
+ ActivityApprovalJudgment.Escalated,
59
+ ActivityApprovalJudgment.Delegated,
60
+ ActivityApprovalJudgment.Approved,
61
+ ActivityApprovalJudgment.Rejected
62
+ ]
63
+
64
+ const approvalDoneItems = await getQueryBuilderFromListParams({
65
+ repository: getRepository(ActivityApproval),
66
+ params,
67
+ domain,
68
+ alias: 'ap'
69
+ })
70
+ .leftJoinAndSelect('ap.activityThread', 'at')
71
+ .leftJoinAndSelect('at.activityInstance', 'ai')
72
+ .andWhere('ap.judgment IN (:...judgment)', { judgment })
73
+ .andWhere('ap.approver = :user', { user: user.id })
74
+ .getMany()
75
+
76
+ const activityApprovalDoneEvents = approvalDoneItems.map(({ id, activityThread, terminatedAt, judgment }) => {
77
+ const activityInstance = activityThread.activityInstance
78
+
79
+ return {
80
+ id,
81
+ name: activityInstance.name,
82
+ date: terminatedAt,
83
+ priority: activityInstance.priority,
84
+ state:
85
+ judgment == ActivityApprovalJudgment.Approved || ActivityApprovalJudgment.Escalated
86
+ ? ActivityEventStatus.Approved
87
+ : ActivityEventStatus.Rejected,
88
+ type: 'activity-approval'
89
+ }
90
+ })
91
+
92
+ return [...activityThreadDoneEvents, ...activityApprovalDoneEvents]
93
+ }
94
+ }
@@ -0,0 +1,34 @@
1
+ import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
2
+
3
+ export enum ActivityEventStatus {
4
+ Done = 'done',
5
+ Pending = 'pending',
6
+ Approved = 'approved',
7
+ Rejected = 'rejected'
8
+ }
9
+
10
+ registerEnumType(ActivityEventStatus, {
11
+ name: 'ActivityEventStatus',
12
+ description: 'state enumeration of a Activity Event'
13
+ })
14
+
15
+ @ObjectType()
16
+ export class ActivityEvent {
17
+ @Field({ nullable: true })
18
+ id?: string
19
+
20
+ @Field({ nullable: true })
21
+ name?: string
22
+
23
+ @Field({ nullable: true })
24
+ type?: string
25
+
26
+ @Field({ nullable: true })
27
+ priority?: number
28
+
29
+ @Field({ nullable: true })
30
+ state?: ActivityEventStatus
31
+
32
+ @Field({ nullable: true })
33
+ date?: Date
34
+ }
@@ -0,0 +1,3 @@
1
+ import { ActivityStatsQuery } from './activity-stats-query'
2
+
3
+ export const resolvers = [ActivityStatsQuery]
@@ -25,12 +25,7 @@ export class ActivitySummaryQuery {
25
25
  repository: getRepository(ActivityThread),
26
26
  params: {},
27
27
  domain,
28
- alias: 'at',
29
- searchables: ['name', 'description'],
30
- filtersMap: {
31
- name: { columnName: 'name', relationColumn: 'activityInstance' },
32
- description: { columnName: 'description', relationColumn: 'activityInstance' }
33
- }
28
+ alias: 'at'
34
29
  })
35
30
  .andWhere('at.state NOT IN (:...status)', { status })
36
31
  .andWhere('at.assignee = :user', { user: user.id })
@@ -55,18 +50,7 @@ export class ActivitySummaryQuery {
55
50
  repository: getRepository(ActivityApproval),
56
51
  params: {},
57
52
  domain,
58
- alias: 'ap',
59
- searchables: ['name', 'description'],
60
- filtersMap: {
61
- name: {
62
- relationColumn: 'activityThread.activityInstance',
63
- columnName: 'name'
64
- },
65
- description: {
66
- relationColumn: 'activityThread.activityInstance',
67
- columnName: 'description'
68
- }
69
- }
53
+ alias: 'ap'
70
54
  })
71
55
  .andWhere('ap.judgment NOT IN (:...judgment)', { judgment })
72
56
  .andWhere('ap.approver = :user', { user: user.id })
@@ -99,12 +83,11 @@ export class ActivitySummaryQuery {
99
83
  repository: getRepository(ActivityInstance),
100
84
  params: {},
101
85
  domain,
102
- alias: 'ai',
103
- searchables: ['name', 'description']
86
+ alias: 'ai'
104
87
  })
105
88
  .leftJoinAndSelect('ai.activityThreads', 'threads', 'threads.assignee = :user', { user: user.id })
106
89
  .andWhere('ai.state IN (:...status)', {
107
- status: [ActivityInstanceStatus.Posted, ActivityInstanceStatus.PendingAssignment]
90
+ status: [ActivityInstanceStatus.Issued, ActivityInstanceStatus.PendingAssignment]
108
91
  })
109
92
  .andWhere('ai.assigneeRole IN (:...roles)', { roles })
110
93
  .andWhere('threads.id IS NULL') /* 이미 내가 할당된 경우는 제외한다. */
@@ -122,8 +105,7 @@ export class ActivitySummaryQuery {
122
105
  repository: getRepository(ActivityInstance),
123
106
  params: {},
124
107
  domain,
125
- alias: 'ai',
126
- searchables: ['name', 'description']
108
+ alias: 'ai'
127
109
  })
128
110
  .andWhere('ai.state IN (:...status)', { status })
129
111
  .andWhere('ai.creator = :user', { user: user.id })
@@ -8,6 +8,7 @@ export * from './installable-activity/installable-activity'
8
8
  export * from './activity-summary/activity-summary'
9
9
 
10
10
  /* IMPORT ENTITIES AND RESOLVERS */
11
+ import { resolvers as ActivityStatsResolvers } from './activity-stats'
11
12
  import {
12
13
  entities as ActivityApprovalEntities,
13
14
  resolvers as ActivityApprovalResolvers,
@@ -57,6 +58,7 @@ export const subscribers = [
57
58
  export const schema = {
58
59
  resolverClasses: [
59
60
  /* RESOLVER CLASSES */
61
+ ...ActivityStatsResolvers,
60
62
  ...ActivityApprovalResolvers,
61
63
  ...ActivityResolvers,
62
64
  ...ActivityInstanceResolvers,
@@ -1,6 +1,6 @@
1
1
  import { Field, ObjectType } from 'type-graphql'
2
2
 
3
- import { Activity, ActivityType, ActivityUIType } from '../activity/activity'
3
+ import { Activity, ActivityStartingType, ActivityType, ActivityUIType } from '../activity/activity'
4
4
  import { ActivityModelItem } from '../activity/activity-model-type'
5
5
 
6
6
  @ObjectType({ description: 'Entity for InstallableActivity' })
@@ -29,6 +29,9 @@ export class InstallableActivity {
29
29
  @Field({ nullable: true })
30
30
  startable?: boolean
31
31
 
32
+ @Field({ nullable: true })
33
+ startingType?: ActivityStartingType
34
+
32
35
  @Field(type => [ActivityModelItem], { nullable: true })
33
36
  model?: ActivityModelItem[]
34
37