@things-factory/worklist 6.0.21 → 6.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/activity-summary-generator.ts +132 -0
- package/client/components/activity-starter-form.ts +89 -3
- package/client/index.ts +1 -0
- package/client/pages/installable-activity/installable-activity-list-page.ts +410 -0
- package/client/pages/installable-activity/installable-activity-model-item-list.ts +18 -0
- package/client/pages/todo/draft-list-page.ts +9 -0
- package/client/route.ts +4 -0
- package/dist-client/activity-summary-generator.d.ts +2 -0
- package/dist-client/activity-summary-generator.js +114 -0
- package/dist-client/activity-summary-generator.js.map +1 -0
- package/dist-client/components/activity-starter-form.d.ts +1 -0
- package/dist-client/components/activity-starter-form.js +66 -4
- package/dist-client/components/activity-starter-form.js.map +1 -1
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +1 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +45 -0
- package/dist-client/pages/installable-activity/installable-activity-list-page.js +414 -0
- package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -0
- package/dist-client/pages/installable-activity/installable-activity-model-item-list.d.ts +1 -0
- package/dist-client/pages/installable-activity/installable-activity-model-item-list.js +20 -0
- package/dist-client/pages/installable-activity/installable-activity-model-item-list.js.map +1 -0
- package/dist-client/pages/installed-activity/installed-activity-list-page.d.ts +45 -0
- package/dist-client/pages/installed-activity/installed-activity-list-page.js +412 -0
- package/dist-client/pages/installed-activity/installed-activity-list-page.js.map +1 -0
- package/dist-client/pages/installed-activity/installed-activity-model-item-list.d.ts +1 -0
- package/dist-client/pages/installed-activity/installed-activity-model-item-list.js +20 -0
- package/dist-client/pages/installed-activity/installed-activity-model-item-list.js.map +1 -0
- package/dist-client/pages/todo/draft-list-page.js +9 -0
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-installation-controller.js +17 -0
- package/dist-server/controllers/activity-installation-controller.js.map +1 -0
- package/dist-server/controllers/activity-instance/post.js +3 -6
- package/dist-server/controllers/activity-instance/post.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/controllers/call-webhook.js +4 -2
- package/dist-server/controllers/call-webhook.js.map +1 -1
- package/dist-server/controllers/common.js +44 -4
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/controllers/index.js +4 -0
- package/dist-server/controllers/index.js.map +1 -1
- package/dist-server/index.js +1 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/activity/activity-model-type.js +1 -1
- package/dist-server/service/activity/activity-model-type.js.map +1 -1
- package/dist-server/service/activity/activity-query.js +1 -0
- package/dist-server/service/activity/activity-query.js.map +1 -1
- package/dist-server/service/activity/activity.js +9 -0
- package/dist-server/service/activity/activity.js.map +1 -1
- package/dist-server/service/activity-approval/event-subscriber.js +21 -4
- package/dist-server/service/activity-approval/event-subscriber.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +40 -0
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-type.js +13 -1
- package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance.js +25 -1
- package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
- package/dist-server/service/index.js +4 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/installable-activity/index.js +10 -0
- package/dist-server/service/installable-activity/index.js.map +1 -0
- package/dist-server/service/installable-activity/installable-activity-mutation.js +60 -0
- package/dist-server/service/installable-activity/installable-activity-mutation.js.map +1 -0
- package/dist-server/service/installable-activity/installable-activity-query.js +48 -0
- package/dist-server/service/installable-activity/installable-activity-query.js.map +1 -0
- package/dist-server/service/installable-activity/installable-activity-type.js +21 -0
- package/dist-server/service/installable-activity/installable-activity-type.js.map +1 -0
- package/dist-server/service/installable-activity/installable-activity.js +70 -0
- package/dist-server/service/installable-activity/installable-activity.js.map +1 -0
- package/dist-server/service/installed-activity/index.js +10 -0
- package/dist-server/service/installed-activity/index.js.map +1 -0
- package/dist-server/service/installed-activity/installed-activity-mutation.js +60 -0
- package/dist-server/service/installed-activity/installed-activity-mutation.js.map +1 -0
- package/dist-server/service/installed-activity/installed-activity-query.js +48 -0
- package/dist-server/service/installed-activity/installed-activity-query.js.map +1 -0
- package/dist-server/service/installed-activity/installed-activity-type.js +21 -0
- package/dist-server/service/installed-activity/installed-activity-type.js.map +1 -0
- package/dist-server/service/installed-activity/installed-activity.js +70 -0
- package/dist-server/service/installed-activity/installed-activity.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/server/controllers/activity-installation-controller.ts +17 -0
- package/server/controllers/activity-instance/bid.ts +52 -0
- package/server/controllers/activity-instance/post.ts +9 -9
- package/server/controllers/activity-thread/submit.ts +1 -1
- package/server/controllers/call-webhook.ts +40 -0
- package/server/controllers/common.ts +41 -5
- package/server/controllers/index.ts +1 -0
- package/server/index.ts +1 -1
- package/server/service/activity/activity-model-type.ts +3 -3
- package/server/service/activity/activity-query.ts +2 -1
- package/server/service/activity/activity.ts +7 -0
- package/server/service/activity-approval/event-subscriber.ts +22 -5
- package/server/service/activity-instance/activity-instance-query.ts +44 -1
- package/server/service/activity-instance/activity-instance-type.ts +12 -4
- package/server/service/activity-instance/activity-instance.ts +17 -1
- package/server/service/index.ts +7 -0
- package/server/service/installable-activity/index.ts +7 -0
- package/server/service/installable-activity/installable-activity-mutation.ts +61 -0
- package/server/service/installable-activity/installable-activity-query.ts +36 -0
- package/server/service/installable-activity/installable-activity-type.ts +12 -0
- package/server/service/installable-activity/installable-activity.ts +49 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +2 -0
- package/translations/ko.json +2 -0
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
- package/server/controllers/activity-extension-controller.ts +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/worklist",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.25",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@operato/graphql": "^1.0.0",
|
|
29
29
|
"@operato/grist-editor": "^1.0.0",
|
|
30
|
-
"@things-factory/attachment-base": "^6.0.
|
|
31
|
-
"@things-factory/auth-base": "^6.0.
|
|
32
|
-
"@things-factory/board-service": "^6.0.
|
|
33
|
-
"@things-factory/organization": "^6.0.
|
|
34
|
-
"@things-factory/shell": "^6.0.
|
|
30
|
+
"@things-factory/attachment-base": "^6.0.25",
|
|
31
|
+
"@things-factory/auth-base": "^6.0.25",
|
|
32
|
+
"@things-factory/board-service": "^6.0.25",
|
|
33
|
+
"@things-factory/organization": "^6.0.25",
|
|
34
|
+
"@things-factory/shell": "^6.0.25"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "8a987a42de944dc915b8cfddb047eb7bc0d4ba41"
|
|
37
37
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { InstallableActivity } from '../service/installable-activity/installable-activity'
|
|
2
|
+
|
|
3
|
+
export class ActivityInstallations {
|
|
4
|
+
static templates: { [name: string]: InstallableActivity } = {}
|
|
5
|
+
|
|
6
|
+
static installActivityTemplate(template: InstallableActivity) {
|
|
7
|
+
ActivityInstallations.templates[template.name] = template
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static get(name: string): InstallableActivity {
|
|
11
|
+
return ActivityInstallations.templates[name]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static list(): InstallableActivity[] {
|
|
15
|
+
return Object.values(ActivityInstallations.templates)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { In } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
import { User } from '@things-factory/auth-base'
|
|
4
|
+
|
|
5
|
+
import { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance'
|
|
6
|
+
import { ActivityInstancePost } from '../../service/activity-instance/activity-instance-type'
|
|
7
|
+
import { createActivityThreadsForAllRoleUsers, createActivityThreadsForUsers } from '../common'
|
|
8
|
+
|
|
9
|
+
export async function bid(activityInstance: ActivityInstancePost, context: ResolverContext): Promise<ActivityInstance> {
|
|
10
|
+
const { domain, user, tx } = context.state
|
|
11
|
+
const { id, assignees } = activityInstance
|
|
12
|
+
|
|
13
|
+
var origin = id
|
|
14
|
+
? await tx.getRepository(ActivityInstance).findOne({
|
|
15
|
+
where: { domain: { id: domain.id }, id },
|
|
16
|
+
relations: [
|
|
17
|
+
'domain',
|
|
18
|
+
'activity',
|
|
19
|
+
'assigneeRole',
|
|
20
|
+
'supervisoryRole',
|
|
21
|
+
'updater',
|
|
22
|
+
'creator',
|
|
23
|
+
'starter',
|
|
24
|
+
'terminator'
|
|
25
|
+
]
|
|
26
|
+
})
|
|
27
|
+
: null
|
|
28
|
+
|
|
29
|
+
const bid = await tx.getRepository(ActivityInstance).save({
|
|
30
|
+
...origin,
|
|
31
|
+
...activityInstance,
|
|
32
|
+
transaction: 'bid',
|
|
33
|
+
state: ActivityInstanceStatus.Posted,
|
|
34
|
+
domain,
|
|
35
|
+
creator: user,
|
|
36
|
+
updater: user
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const assignedUsers = await tx.getRepository(User).findBy({
|
|
40
|
+
email: In(assignees || [])
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (bid.threadsMin === 0 && bid.assigneeRoleId) {
|
|
44
|
+
await createActivityThreadsForAllRoleUsers('post', bid, context)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (assignedUsers.length > 0) {
|
|
48
|
+
await createActivityThreadsForUsers('post', bid, assignedUsers, context)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return await tx.getRepository(ActivityInstance).findOneBy({ id: bid.id })
|
|
52
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { In } from 'typeorm'
|
|
2
|
-
|
|
3
|
-
import { User } from '@things-factory/auth-base'
|
|
4
|
-
|
|
5
1
|
import { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance'
|
|
6
2
|
import { ActivityInstancePost } from '../../service/activity-instance/activity-instance-type'
|
|
7
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createActivityThreadsForAllRoleUsers,
|
|
5
|
+
createActivityThreadsForUsers,
|
|
6
|
+
getSystemUserFromAssigneeItem
|
|
7
|
+
} from '../common'
|
|
8
8
|
|
|
9
9
|
export async function post(
|
|
10
10
|
activityInstance: ActivityInstancePost,
|
|
@@ -39,11 +39,11 @@ export async function post(
|
|
|
39
39
|
updater: user
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
const assignedUsers = await
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const assignedUsers = await Promise.all(assignees.map(assignee => getSystemUserFromAssigneeItem(assignee, context)))
|
|
43
|
+
|
|
44
|
+
assignees.map(async assignee => await getSystemUserFromAssigneeItem(assignee, context))
|
|
45
45
|
|
|
46
|
-
if (posted.threadsMin === 0 && posted.assigneeRoleId) {
|
|
46
|
+
if (assignedUsers.length == 0 && posted.threadsMin === 0 && posted.assigneeRoleId) {
|
|
47
47
|
await createActivityThreadsForAllRoleUsers('post', posted, context)
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -2,7 +2,7 @@ import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thr
|
|
|
2
2
|
import { ActivityApproval, ActivityApprovalJudgment } from '../../service/activity-approval/activity-approval'
|
|
3
3
|
import { getSystemUserFromApprovalLineItem, updateActivityInstanceState } from '../common'
|
|
4
4
|
import { User } from '@things-factory/auth-base'
|
|
5
|
-
import { Department, Employee, ApprovalLineItem,
|
|
5
|
+
import { Department, Employee, ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'
|
|
6
6
|
|
|
7
7
|
export async function submit(
|
|
8
8
|
{ id, output, reason }: { id: string; output?: object; reason?: string },
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EntityManager } from 'typeorm'
|
|
2
|
+
import { Application } from '@things-factory/auth-base'
|
|
3
|
+
import { Domain, getRepository } from '@things-factory/shell'
|
|
4
|
+
|
|
5
|
+
export async function callWebhook(domain: Domain, tag: string, data: any, tx?: EntityManager) {
|
|
6
|
+
/*
|
|
7
|
+
TODO webhook callback의 다양한 subscription 조건을 지원한다.
|
|
8
|
+
- activity의 client에 해당하는 application
|
|
9
|
+
- activityInstance의 starter에 해당하는 application
|
|
10
|
+
- 모든 이벤트를 받고자하는 application
|
|
11
|
+
- 특정 activity들의 이벤트를 받고자하는 application
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const applications = await (tx ? tx.getRepository(Application) : getRepository(Application)).findBy({
|
|
15
|
+
domain: { id: domain.id }
|
|
16
|
+
})
|
|
17
|
+
const options = {
|
|
18
|
+
method: 'post',
|
|
19
|
+
headers: {
|
|
20
|
+
'x-things-factory-domain': domain.name,
|
|
21
|
+
'Content-Type': 'application/json'
|
|
22
|
+
},
|
|
23
|
+
body: {
|
|
24
|
+
tag,
|
|
25
|
+
data
|
|
26
|
+
} as any
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
applications
|
|
31
|
+
.filter(app => app.webhook)
|
|
32
|
+
.every(app => {
|
|
33
|
+
const webhook = app.webhook
|
|
34
|
+
|
|
35
|
+
fetch(webhook, options)
|
|
36
|
+
})
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.error(err)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Role, User } from '@things-factory/auth-base'
|
|
2
2
|
|
|
3
|
-
import { ActivityInstance, ActivityInstanceStatus } from '../service/activity-instance/activity-instance'
|
|
3
|
+
import { ActivityInstance, ActivityInstanceStatus, AssigneeItem } from '../service/activity-instance/activity-instance'
|
|
4
4
|
import { ActivityThread, ActivityThreadStatus } from '../service/activity-thread/activity-thread'
|
|
5
|
-
import { Department, Employee, ApprovalLineItem,
|
|
5
|
+
import { Department, Employee, ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'
|
|
6
6
|
|
|
7
7
|
export async function updateActivityInstanceState(id: string, context: ResolverContext) {
|
|
8
8
|
const { tx } = context.state
|
|
@@ -120,20 +120,56 @@ export async function getSystemUserFromApprovalLineItem(
|
|
|
120
120
|
const { type, value, approver } = approvalLineItem
|
|
121
121
|
const { id: approverId, name, description, controlNo } = approver
|
|
122
122
|
|
|
123
|
-
if (type ==
|
|
123
|
+
if (type == OrgMemberTargetType.Employee) {
|
|
124
124
|
const employee = await tx.getRepository(Employee).findOne({ where: { id: approverId }, relations: ['user'] })
|
|
125
125
|
|
|
126
126
|
if (!employee || !employee.user) {
|
|
127
127
|
return
|
|
128
128
|
}
|
|
129
129
|
return employee.user
|
|
130
|
-
} else if (type ==
|
|
130
|
+
} else if (type == OrgMemberTargetType.Department) {
|
|
131
131
|
const department = await tx.getRepository(Department).findOne({ where: { id: approverId }, relations: ['manager'] })
|
|
132
132
|
|
|
133
133
|
if (!department || !department.manager) {
|
|
134
134
|
return
|
|
135
135
|
}
|
|
136
136
|
return await tx.getRepository(User).findOneBy({ id: department.manager.userId })
|
|
137
|
-
} else if (type ==
|
|
137
|
+
} else if (type == OrgMemberTargetType.Role) {
|
|
138
|
+
} else if (type == OrgMemberTargetType.Myself) {
|
|
139
|
+
return user
|
|
140
|
+
} else if (type == OrgMemberTargetType.MyDepartment) {
|
|
141
|
+
// return user
|
|
142
|
+
} else if (type == OrgMemberTargetType.MySupervisor) {
|
|
143
|
+
// return user
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function getSystemUserFromAssigneeItem(assigneeItem: AssigneeItem, context: any): Promise<User> {
|
|
148
|
+
const { domain, user, tx } = context.state
|
|
149
|
+
|
|
150
|
+
const { type, value, assignee } = assigneeItem
|
|
151
|
+
const { id: assigneeId, name, description, controlNo } = assignee
|
|
152
|
+
|
|
153
|
+
if (type == OrgMemberTargetType.Employee) {
|
|
154
|
+
const employee = await tx.getRepository(Employee).findOne({ where: { id: assigneeId }, relations: ['user'] })
|
|
155
|
+
|
|
156
|
+
if (!employee || !employee.user) {
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
return employee.user
|
|
160
|
+
} else if (type == OrgMemberTargetType.Department) {
|
|
161
|
+
const department = await tx.getRepository(Department).findOne({ where: { id: assigneeId }, relations: ['manager'] })
|
|
162
|
+
|
|
163
|
+
if (!department || !department.manager) {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
return await tx.getRepository(User).findOneBy({ id: department.manager.userId })
|
|
167
|
+
} else if (type == OrgMemberTargetType.Role) {
|
|
168
|
+
} else if (type == OrgMemberTargetType.Myself) {
|
|
169
|
+
return user
|
|
170
|
+
} else if (type == OrgMemberTargetType.MyDepartment) {
|
|
171
|
+
// return user
|
|
172
|
+
} else if (type == OrgMemberTargetType.MySupervisor) {
|
|
173
|
+
// return user
|
|
138
174
|
}
|
|
139
175
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './activity-installation-controller'
|
package/server/index.ts
CHANGED
|
@@ -29,8 +29,8 @@ registerEnumType(ActivityModelItemType, {
|
|
|
29
29
|
|
|
30
30
|
@ObjectType({ description: 'Entity for ActivityModelItem' })
|
|
31
31
|
export class ActivityModelItem {
|
|
32
|
-
@Field()
|
|
33
|
-
name
|
|
32
|
+
@Field({ nullable: true })
|
|
33
|
+
name?: string
|
|
34
34
|
|
|
35
35
|
@Field({ nullable: true })
|
|
36
36
|
description?: string
|
|
@@ -60,7 +60,7 @@ export class ActivityModelItem {
|
|
|
60
60
|
unit?: string
|
|
61
61
|
|
|
62
62
|
@Field(type => [Int], { nullable: true })
|
|
63
|
-
quantifier
|
|
63
|
+
quantifier?: number[]
|
|
64
64
|
|
|
65
65
|
@Field(type => ScalarObject, { nullable: true })
|
|
66
66
|
spec?: { [key: string]: any }
|
|
@@ -5,7 +5,7 @@ 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
7
|
|
|
8
|
-
import { Activity } from './activity'
|
|
8
|
+
import { Activity, ActivityStatus } from './activity'
|
|
9
9
|
import { ActivityList } from './activity-type'
|
|
10
10
|
|
|
11
11
|
@Resolver(Activity)
|
|
@@ -64,6 +64,7 @@ export class ActivityQuery {
|
|
|
64
64
|
searchables: ['name', 'description']
|
|
65
65
|
})
|
|
66
66
|
.andWhere(`activity.startable = :startable`, { startable: true })
|
|
67
|
+
.andWhere(`activity.state = :state`, { state: ActivityStatus.Released })
|
|
67
68
|
.andWhere(
|
|
68
69
|
roles.length > 0
|
|
69
70
|
? new Brackets(qb => {
|
|
@@ -173,6 +173,13 @@ export class Activity {
|
|
|
173
173
|
@Field({ nullable: true })
|
|
174
174
|
updatedAt?: Date
|
|
175
175
|
|
|
176
|
+
@ManyToOne(type => User, { nullable: true })
|
|
177
|
+
@Field(type => User, { nullable: true, description: 'User assigned to the client application' })
|
|
178
|
+
client?: User
|
|
179
|
+
|
|
180
|
+
@RelationId((activity: Activity) => activity.creator)
|
|
181
|
+
clientId?: string
|
|
182
|
+
|
|
176
183
|
@ManyToOne(type => User, { nullable: true })
|
|
177
184
|
@Field(type => User, { nullable: true })
|
|
178
185
|
creator?: User
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { EventSubscriber, EntitySubscriberInterface, InsertEvent, UpdateEvent } from 'typeorm'
|
|
2
2
|
|
|
3
|
-
import { pubsub } from '@things-factory/shell'
|
|
3
|
+
import { Domain, pubsub } from '@things-factory/shell'
|
|
4
4
|
|
|
5
5
|
import { ActivityApproval } from './activity-approval'
|
|
6
|
+
import { callWebhook } from '../../controllers/call-webhook'
|
|
6
7
|
|
|
7
8
|
@EventSubscriber()
|
|
8
9
|
export class ActivityApprovalSubscriber implements EntitySubscriberInterface<ActivityApproval> {
|
|
@@ -10,19 +11,35 @@ export class ActivityApprovalSubscriber implements EntitySubscriberInterface<Act
|
|
|
10
11
|
return ActivityApproval
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
afterInsert(event: InsertEvent<ActivityApproval>): Promise<any
|
|
14
|
-
const
|
|
14
|
+
async afterInsert(event: InsertEvent<ActivityApproval>): Promise<any | void> {
|
|
15
|
+
const { manager: tx, entity } = event
|
|
16
|
+
const activityApproval = await tx.getRepository(ActivityApproval).findOne({
|
|
17
|
+
where: { id: entity.id },
|
|
18
|
+
relations: ['domain', 'activityThread']
|
|
19
|
+
})
|
|
15
20
|
|
|
16
21
|
pubsub.publish('activity-approval', {
|
|
17
22
|
activityApproval
|
|
18
23
|
})
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
callWebhook(activityApproval.domain, 'activity-approval-created', activityApproval, tx)
|
|
27
|
+
} catch (err) {}
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
afterUpdate(event: UpdateEvent<ActivityApproval>): Promise<any
|
|
22
|
-
const
|
|
30
|
+
async afterUpdate(event: UpdateEvent<ActivityApproval>): Promise<any | void> {
|
|
31
|
+
const { manager: tx, entity } = event
|
|
32
|
+
const activityApproval = await tx.getRepository(ActivityApproval).findOne({
|
|
33
|
+
where: { id: entity.id },
|
|
34
|
+
relations: ['domain', 'activityThread']
|
|
35
|
+
})
|
|
23
36
|
|
|
24
37
|
pubsub.publish('activity-approval', {
|
|
25
38
|
activityApproval
|
|
26
39
|
})
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
callWebhook(activityApproval.domain, 'activity-approval-updated', activityApproval, tx)
|
|
43
|
+
} catch (err) {}
|
|
27
44
|
}
|
|
28
45
|
}
|
|
@@ -6,7 +6,7 @@ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from
|
|
|
6
6
|
|
|
7
7
|
import { ActivityThread } from '../activity-thread/activity-thread'
|
|
8
8
|
import { Activity } from '../activity/activity'
|
|
9
|
-
import { ActivityInstance, ActivityInstanceStatus } from './activity-instance'
|
|
9
|
+
import { ActivityInstance, ActivityInstanceStatus, AssigneeItem } from './activity-instance'
|
|
10
10
|
import { ActivityInstanceList } from './activity-instance-type'
|
|
11
11
|
|
|
12
12
|
@Resolver(ActivityInstance)
|
|
@@ -150,6 +150,49 @@ export class ActivityInstanceQuery {
|
|
|
150
150
|
)
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
@FieldResolver(type => [AssigneeItem])
|
|
154
|
+
async assignees(
|
|
155
|
+
@Root() activityInstance: ActivityInstance,
|
|
156
|
+
@Ctx() context: ResolverContext
|
|
157
|
+
): Promise<AssigneeItem[]> {
|
|
158
|
+
const { domain, user } = context.state
|
|
159
|
+
const { assignees } = activityInstance
|
|
160
|
+
|
|
161
|
+
if (!assignees || !(assignees instanceof Array)) {
|
|
162
|
+
return null
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
var assigneeItemList = []
|
|
166
|
+
|
|
167
|
+
for (let item of assignees) {
|
|
168
|
+
var { type, value: id } = item
|
|
169
|
+
var assignee
|
|
170
|
+
|
|
171
|
+
switch (type) {
|
|
172
|
+
case 'Employee':
|
|
173
|
+
assignee = await getRepository('Employee').findOneBy({ domain: { id: domain.id }, id })
|
|
174
|
+
break
|
|
175
|
+
case 'Department':
|
|
176
|
+
assignee = await getRepository('Department').findOneBy({ domain: { id: domain.id }, id })
|
|
177
|
+
break
|
|
178
|
+
case 'Role':
|
|
179
|
+
assignee = await getRepository('Role').findOneBy({ domain: { id: domain.id }, id })
|
|
180
|
+
break
|
|
181
|
+
case 'Myself':
|
|
182
|
+
assignee = user
|
|
183
|
+
break
|
|
184
|
+
case 'MyDepartment':
|
|
185
|
+
case 'MySupervisor':
|
|
186
|
+
break
|
|
187
|
+
default:
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
assignee && assigneeItemList.push({ type, value: id, assignee })
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return assigneeItemList
|
|
194
|
+
}
|
|
195
|
+
|
|
153
196
|
@FieldResolver(type => Role)
|
|
154
197
|
async supervisoryRole(@Root() activityInstance: ActivityInstance): Promise<Role> {
|
|
155
198
|
return (
|
|
@@ -5,8 +5,7 @@ import { ObjectRef, ScalarDate, ScalarObject } from '@things-factory/shell'
|
|
|
5
5
|
import { ApprovalLineItem } from '@things-factory/organization'
|
|
6
6
|
|
|
7
7
|
import { ActivityType, ActivityUIType } from '../activity/activity'
|
|
8
|
-
import { ActivityInstance, ActivityInstanceStatus } from './activity-instance'
|
|
9
|
-
|
|
8
|
+
import { AssigneeItem, ActivityInstance, ActivityInstanceStatus } from './activity-instance'
|
|
10
9
|
@InputType()
|
|
11
10
|
export class NewActivityInstance {
|
|
12
11
|
@Field()
|
|
@@ -57,6 +56,9 @@ export class NewActivityInstance {
|
|
|
57
56
|
@Field(type => ObjectRef, { nullable: true })
|
|
58
57
|
assigneeRole?: Role
|
|
59
58
|
|
|
59
|
+
@Field(type => ScalarObject, { nullable: true })
|
|
60
|
+
assignees?: AssigneeItem[]
|
|
61
|
+
|
|
60
62
|
@Field(type => ScalarObject, { nullable: true })
|
|
61
63
|
approvalLine?: ApprovalLineItem[]
|
|
62
64
|
}
|
|
@@ -114,8 +116,8 @@ export class ActivityInstancePost {
|
|
|
114
116
|
@Field(type => ObjectRef, { nullable: true })
|
|
115
117
|
assigneeRole?: Role
|
|
116
118
|
|
|
117
|
-
@Field(type =>
|
|
118
|
-
assignees?:
|
|
119
|
+
@Field(type => ScalarObject, { nullable: true })
|
|
120
|
+
assignees?: AssigneeItem[]
|
|
119
121
|
|
|
120
122
|
@Field(type => ScalarObject, { nullable: true })
|
|
121
123
|
approvalLine?: ApprovalLineItem[]
|
|
@@ -126,6 +128,9 @@ export class ActivityInstanceSave {
|
|
|
126
128
|
@Field(type => ScalarObject, { nullable: true })
|
|
127
129
|
output?: { [key: string]: any }
|
|
128
130
|
|
|
131
|
+
@Field(type => ScalarObject, { nullable: true })
|
|
132
|
+
assignees?: AssigneeItem[]
|
|
133
|
+
|
|
129
134
|
@Field(type => ScalarObject, { nullable: true })
|
|
130
135
|
approvalLine?: ApprovalLineItem[]
|
|
131
136
|
}
|
|
@@ -159,6 +164,9 @@ export class ActivityInstancePatch {
|
|
|
159
164
|
@Field(type => ScalarObject, { nullable: true })
|
|
160
165
|
input?: { [key: string]: any }
|
|
161
166
|
|
|
167
|
+
@Field(type => ScalarObject, { nullable: true })
|
|
168
|
+
assignees?: AssigneeItem[]
|
|
169
|
+
|
|
162
170
|
@Field(type => ScalarObject, { nullable: true })
|
|
163
171
|
approvalLine?: ApprovalLineItem[]
|
|
164
172
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
import { Role, User } from '@things-factory/auth-base'
|
|
16
16
|
import { Domain, ScalarObject } from '@things-factory/shell'
|
|
17
|
-
import { ApprovalLineItem } from '@things-factory/organization'
|
|
17
|
+
import { OrgMemberTargetType, OrgMemberTarget, ApprovalLineItem } from '@things-factory/organization'
|
|
18
18
|
|
|
19
19
|
import { ActivityThread } from '../activity-thread/activity-thread'
|
|
20
20
|
import { Activity, ActivityType, ActivityUIType } from '../activity/activity'
|
|
@@ -35,6 +35,18 @@ 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
|
+
|
|
38
50
|
@Entity()
|
|
39
51
|
@Index(
|
|
40
52
|
'ix_activity_instance_0',
|
|
@@ -152,6 +164,10 @@ export class ActivityInstance {
|
|
|
152
164
|
@Field({ nullable: true })
|
|
153
165
|
transaction?: string
|
|
154
166
|
|
|
167
|
+
@Column('simple-json', { nullable: true })
|
|
168
|
+
@Field(type => [AssigneeItem], { nullable: true })
|
|
169
|
+
assignees?: AssigneeItem[]
|
|
170
|
+
|
|
155
171
|
@Column('simple-json', { nullable: true })
|
|
156
172
|
@Field(type => [ApprovalLineItem], { nullable: true })
|
|
157
173
|
approvalLine?: ApprovalLineItem[]
|
package/server/service/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './activity-thread/activity-thread'
|
|
|
4
4
|
export * from './activity-template/activity-template'
|
|
5
5
|
export * from './activity-instance/activity-instance'
|
|
6
6
|
export * from './activity/activity'
|
|
7
|
+
export * from './installable-activity/installable-activity'
|
|
7
8
|
export * from './activity-summary/activity-summary'
|
|
8
9
|
|
|
9
10
|
/* IMPORT ENTITIES AND RESOLVERS */
|
|
@@ -28,6 +29,10 @@ import {
|
|
|
28
29
|
resolvers as ActivityThreadResolvers,
|
|
29
30
|
subscribers as ActivityThreadSubscribers
|
|
30
31
|
} from './activity-thread'
|
|
32
|
+
import {
|
|
33
|
+
entities as InstallableActivityEntities,
|
|
34
|
+
resolvers as InstallableActivityResolvers
|
|
35
|
+
} from './installable-activity'
|
|
31
36
|
import { entities as ActivitySummaryEntities, resolvers as ActivitySummaryResolvers } from './activity-summary'
|
|
32
37
|
|
|
33
38
|
export const entities = [
|
|
@@ -37,6 +42,7 @@ export const entities = [
|
|
|
37
42
|
...ActivityInstanceEntities,
|
|
38
43
|
...ActivityTemplateEntities,
|
|
39
44
|
...ActivityThreadEntities,
|
|
45
|
+
...InstallableActivityEntities,
|
|
40
46
|
...ActivitySummaryEntities
|
|
41
47
|
]
|
|
42
48
|
|
|
@@ -56,6 +62,7 @@ export const schema = {
|
|
|
56
62
|
...ActivityInstanceResolvers,
|
|
57
63
|
...ActivityTemplateResolvers,
|
|
58
64
|
...ActivityThreadResolvers,
|
|
65
|
+
...InstallableActivityResolvers,
|
|
59
66
|
...ActivitySummaryResolvers
|
|
60
67
|
]
|
|
61
68
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { InstallableActivity } from './installable-activity'
|
|
2
|
+
import { InstallableActivityQuery } from './installable-activity-query'
|
|
3
|
+
import { InstallableActivityMutation } from './installable-activity-mutation'
|
|
4
|
+
|
|
5
|
+
export const entities = [InstallableActivity]
|
|
6
|
+
export const resolvers = [InstallableActivityQuery, InstallableActivityMutation]
|
|
7
|
+
export const subscribers = []
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { ActivityInstallations } from '../../controllers/activity-installation-controller'
|
|
4
|
+
import { Activity, ActivityStatus } from '../activity/activity'
|
|
5
|
+
import { InstallableActivity } from './installable-activity'
|
|
6
|
+
|
|
7
|
+
@Resolver(InstallableActivity)
|
|
8
|
+
export class InstallableActivityMutation {
|
|
9
|
+
@Directive('@transaction')
|
|
10
|
+
@Mutation(returns => Activity, { description: 'To activate installable activity to Activity on given domain' })
|
|
11
|
+
async activateInstallableActivity(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Activity> {
|
|
12
|
+
const { domain, user, tx } = context.state
|
|
13
|
+
const installableActivity = ActivityInstallations.get(name)
|
|
14
|
+
const repository = tx.getRepository(Activity)
|
|
15
|
+
|
|
16
|
+
const activity = await repository.findOneBy({
|
|
17
|
+
domain: { id: domain.id },
|
|
18
|
+
name
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
if (!activity) {
|
|
22
|
+
return await repository.save({
|
|
23
|
+
...(installableActivity as any),
|
|
24
|
+
state: ActivityStatus.Released,
|
|
25
|
+
domain,
|
|
26
|
+
creator: user,
|
|
27
|
+
updater: user
|
|
28
|
+
})
|
|
29
|
+
} else {
|
|
30
|
+
return await repository.save({
|
|
31
|
+
...activity,
|
|
32
|
+
...(installableActivity as any),
|
|
33
|
+
state: ActivityStatus.Released,
|
|
34
|
+
domain,
|
|
35
|
+
updater: user
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Directive('@transaction')
|
|
41
|
+
@Mutation(returns => Activity, { description: 'To deactivate installable activity to Activity on given domain' })
|
|
42
|
+
async deactivateInstallableActivity(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Activity> {
|
|
43
|
+
const { domain, user, tx } = context.state
|
|
44
|
+
const repository = tx.getRepository(Activity)
|
|
45
|
+
|
|
46
|
+
const activity = await repository.findOneBy({
|
|
47
|
+
domain: { id: domain.id },
|
|
48
|
+
name
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
if (!activity) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return await repository.save({
|
|
56
|
+
...activity,
|
|
57
|
+
state: ActivityStatus.Deprecated,
|
|
58
|
+
updater: user
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Arg, Args, Ctx, Query, Resolver, FieldResolver, Root } from 'type-graphql'
|
|
2
|
+
import { Domain, getRepository, ListParam } from '@things-factory/shell'
|
|
3
|
+
|
|
4
|
+
import { ActivityInstallations } from '../../controllers/activity-installation-controller'
|
|
5
|
+
import { Activity } from '../activity/activity'
|
|
6
|
+
import { InstallableActivity } from './installable-activity'
|
|
7
|
+
import { InstallableActivityList } from './installable-activity-type'
|
|
8
|
+
|
|
9
|
+
@Resolver(InstallableActivity)
|
|
10
|
+
export class InstallableActivityQuery {
|
|
11
|
+
@Query(returns => InstallableActivity!, { nullable: true, description: 'To fetch a InstallableActivity' })
|
|
12
|
+
async installableActivity(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<InstallableActivity> {
|
|
13
|
+
return await ActivityInstallations.get(name)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Query(returns => InstallableActivityList, { description: 'To fetch multiple InstallableActivitys' })
|
|
17
|
+
async installableActivities(
|
|
18
|
+
@Args() params: ListParam,
|
|
19
|
+
@Ctx() context: ResolverContext
|
|
20
|
+
): Promise<InstallableActivityList> {
|
|
21
|
+
const { domain } = context.state
|
|
22
|
+
|
|
23
|
+
const items = ActivityInstallations.list()
|
|
24
|
+
|
|
25
|
+
for (var item of items) {
|
|
26
|
+
item.activity = await getRepository(Activity).findOneBy({
|
|
27
|
+
domain: { id: domain.id },
|
|
28
|
+
name: item.name
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const total = items.length
|
|
33
|
+
|
|
34
|
+
return { items, total }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Field, Int, ObjectType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { InstallableActivity } from './installable-activity'
|
|
4
|
+
|
|
5
|
+
@ObjectType()
|
|
6
|
+
export class InstallableActivityList {
|
|
7
|
+
@Field(type => [InstallableActivity])
|
|
8
|
+
items: InstallableActivity[]
|
|
9
|
+
|
|
10
|
+
@Field(type => Int)
|
|
11
|
+
total: number
|
|
12
|
+
}
|