@things-factory/worklist 6.0.12 → 6.0.16
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/pages/activity-approval/activity-approval-page.ts +17 -3
- package/client/pages/activity-thread/activity-thread-page.ts +93 -3
- package/dist-client/pages/activity-approval/activity-approval-page.js +19 -5
- package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +4 -0
- package/dist-client/pages/activity-thread/activity-thread-page.js +67 -6
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/approve.js +3 -4
- package/dist-server/controllers/activity-approval/approve.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegate.js +10 -4
- package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
- package/dist-server/controllers/activity-approval/reject.js +5 -3
- package/dist-server/controllers/activity-approval/reject.js.map +1 -1
- package/dist-server/controllers/activity-thread/delegate.js +2 -3
- package/dist-server/controllers/activity-thread/delegate.js.map +1 -1
- package/dist-server/controllers/activity-thread/end.js +1 -2
- package/dist-server/controllers/activity-thread/end.js.map +1 -1
- package/dist-server/controllers/activity-thread/index.js +1 -0
- package/dist-server/controllers/activity-thread/index.js.map +1 -1
- package/dist-server/controllers/activity-thread/restart.js +25 -0
- package/dist-server/controllers/activity-thread/restart.js.map +1 -0
- package/dist-server/controllers/activity-thread/save.js +6 -2
- package/dist-server/controllers/activity-thread/save.js.map +1 -1
- package/dist-server/controllers/activity-thread/start.js +3 -4
- package/dist-server/controllers/activity-thread/start.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js +2 -1
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/controllers/activity-thread/terminate.js +2 -3
- package/dist-server/controllers/activity-thread/terminate.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-mutation.js +10 -8
- package/dist-server/service/activity-approval/activity-approval-mutation.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-query.js +21 -1
- package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-subscription.js +48 -0
- package/dist-server/service/activity-approval/activity-approval-subscription.js.map +1 -0
- package/dist-server/service/activity-approval/activity-approval.js +23 -2
- package/dist-server/service/activity-approval/activity-approval.js.map +1 -1
- package/dist-server/service/activity-approval/index.js +2 -1
- package/dist-server/service/activity-approval/index.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-subscription.js +2 -2
- package/dist-server/service/activity-instance/activity-instance-subscription.js.map +1 -1
- package/dist-server/service/activity-summary/activity-summary-query.js +154 -0
- package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -0
- package/dist-server/service/activity-summary/activity-summary.js +28 -0
- package/dist-server/service/activity-summary/activity-summary.js.map +1 -0
- package/dist-server/service/activity-summary/index.js +8 -0
- package/dist-server/service/activity-summary/index.js.map +1 -0
- package/dist-server/service/activity-thread/activity-thread-history.js +194 -0
- package/dist-server/service/activity-thread/activity-thread-history.js.map +1 -0
- package/dist-server/service/activity-thread/activity-thread-mutation.js +15 -1
- package/dist-server/service/activity-thread/activity-thread-mutation.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread-query.js +18 -5
- package/dist-server/service/activity-thread/activity-thread-query.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread-subscription.js +2 -2
- package/dist-server/service/activity-thread/activity-thread-subscription.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread.js +21 -22
- package/dist-server/service/activity-thread/activity-thread.js.map +1 -1
- package/dist-server/service/activity-thread/event-subscriber.js +15 -1
- package/dist-server/service/activity-thread/event-subscriber.js.map +1 -1
- package/dist-server/service/activity-thread/index.js +3 -2
- package/dist-server/service/activity-thread/index.js.map +1 -1
- package/dist-server/service/index.js +6 -2
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/server/controllers/activity-approval/approve.ts +5 -4
- package/server/controllers/activity-approval/delegate.ts +21 -6
- package/server/controllers/activity-approval/reject.ts +12 -4
- package/server/controllers/activity-thread/delegate.ts +2 -3
- package/server/controllers/activity-thread/end.ts +1 -2
- package/server/controllers/activity-thread/index.ts +1 -0
- package/server/controllers/activity-thread/restart.ts +42 -0
- package/server/controllers/activity-thread/save.ts +9 -2
- package/server/controllers/activity-thread/start.ts +3 -4
- package/server/controllers/activity-thread/submit.ts +2 -1
- package/server/controllers/activity-thread/terminate.ts +2 -3
- package/server/service/activity-approval/activity-approval-mutation.ts +6 -4
- package/server/service/activity-approval/activity-approval-query.ts +11 -1
- package/server/service/activity-approval/activity-approval-subscription.ts +46 -0
- package/server/service/activity-approval/activity-approval.ts +16 -0
- package/server/service/activity-approval/index.ts +2 -1
- package/server/service/activity-instance/activity-instance-subscription.ts +2 -2
- package/server/service/activity-summary/activity-summary-query.ts +132 -0
- package/server/service/activity-summary/activity-summary.ts +16 -0
- package/server/service/activity-summary/index.ts +5 -0
- package/server/service/activity-thread/activity-thread-history.ts +177 -0
- package/server/service/activity-thread/activity-thread-mutation.ts +21 -2
- package/server/service/activity-thread/activity-thread-query.ts +13 -5
- package/server/service/activity-thread/activity-thread-subscription.ts +2 -2
- package/server/service/activity-thread/activity-thread.ts +13 -15
- package/server/service/activity-thread/event-subscriber.ts +17 -1
- package/server/service/activity-thread/index.ts +4 -3
- package/server/service/index.ts +14 -6
- package/translations/en.json +3 -0
- package/translations/ko.json +3 -0
- package/translations/ms.json +3 -0
- package/translations/zh.json +3 -0
- package/server/controllers/activity-approval/abort.ts +0 -33
- package/server/controllers/activity-approval/escalate.ts +0 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/worklist",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.16",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@things-factory/attachment-base": "^6.0.12",
|
|
31
31
|
"@things-factory/auth-base": "^6.0.12",
|
|
32
32
|
"@things-factory/board-service": "^6.0.12",
|
|
33
|
-
"@things-factory/organization": "^6.0.
|
|
33
|
+
"@things-factory/organization": "^6.0.15",
|
|
34
34
|
"@things-factory/shell": "^6.0.12"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "b133bc7f47a51e8ad177c0c519ec136e27ab02e1"
|
|
37
37
|
}
|
|
@@ -12,8 +12,7 @@ export async function approve(
|
|
|
12
12
|
var repository = tx.getRepository(ActivityApproval)
|
|
13
13
|
|
|
14
14
|
var activityApproval = await repository.findOne({
|
|
15
|
-
where: { domain: { id: domain.id }, id }
|
|
16
|
-
relations: ['domain', 'activityThread', 'updater', 'creator']
|
|
15
|
+
where: { domain: { id: domain.id }, id }
|
|
17
16
|
})
|
|
18
17
|
|
|
19
18
|
if (!activityApproval) {
|
|
@@ -26,7 +25,7 @@ export async function approve(
|
|
|
26
25
|
|
|
27
26
|
const activityThread = await tx.getRepository(ActivityThread).findOne({
|
|
28
27
|
where: { domain: { id: domain.id }, id: activityApproval.activityThreadId },
|
|
29
|
-
relations: ['
|
|
28
|
+
relations: ['activityInstance']
|
|
30
29
|
})
|
|
31
30
|
|
|
32
31
|
const approvalLine: ApprovalLineItem[] = activityThread.activityInstance.approvalLine
|
|
@@ -37,7 +36,9 @@ export async function approve(
|
|
|
37
36
|
judgment: approvalLine[order] ? ActivityApprovalJudgment.Escalated : ActivityApprovalJudgment.Approved,
|
|
38
37
|
comment,
|
|
39
38
|
transaction: approvalLine[order] ? 'escalate' : 'approve',
|
|
40
|
-
updater: user
|
|
39
|
+
updater: user,
|
|
40
|
+
terminatedAt: new Date(),
|
|
41
|
+
terminator: user
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
if (approvalLine && approvalLine.length > order) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { User } from '@things-factory/auth-base'
|
|
2
|
+
import { ObjectRef } from '@things-factory/shell'
|
|
1
3
|
import { ActivityApproval, ActivityApprovalJudgment } from '../../service/activity-approval/activity-approval'
|
|
2
4
|
|
|
3
5
|
export async function delegate(
|
|
4
|
-
{ id, comment }: { id: string; comment: string },
|
|
6
|
+
{ id, to, comment }: { id: string; to: ObjectRef; comment: string },
|
|
5
7
|
context: ResolverContext
|
|
6
8
|
): Promise<ActivityApproval> {
|
|
7
9
|
const { domain, user, tx } = context.state
|
|
@@ -9,8 +11,7 @@ export async function delegate(
|
|
|
9
11
|
var repository = tx.getRepository(ActivityApproval)
|
|
10
12
|
|
|
11
13
|
var activityApproval = await repository.findOne({
|
|
12
|
-
where: { domain: { id: domain.id }, id }
|
|
13
|
-
relations: ['domain', 'activityThread', 'updater', 'creator']
|
|
14
|
+
where: { domain: { id: domain.id }, id }
|
|
14
15
|
})
|
|
15
16
|
|
|
16
17
|
if (!activityApproval) {
|
|
@@ -21,13 +22,27 @@ export async function delegate(
|
|
|
21
22
|
)
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
/* TODO user validation .. */
|
|
26
|
+
const approver = await tx.getRepository(User).findOneBy({ id: to.id })
|
|
27
|
+
|
|
28
|
+
/* create new delegated approval */
|
|
29
|
+
await repository.save({
|
|
30
|
+
...activityApproval,
|
|
31
|
+
originalApproval: activityApproval,
|
|
32
|
+
comment,
|
|
33
|
+
approver,
|
|
34
|
+
creator: user,
|
|
35
|
+
updater: user
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
/* terminate origin approval */
|
|
24
39
|
return await repository.save({
|
|
25
40
|
...activityApproval,
|
|
26
41
|
judgment: ActivityApprovalJudgment.Delegated,
|
|
27
42
|
comment,
|
|
28
|
-
transaction: '
|
|
43
|
+
transaction: 'delegate',
|
|
29
44
|
updater: user,
|
|
30
|
-
|
|
31
|
-
|
|
45
|
+
terminator: user,
|
|
46
|
+
terminatedAt: new Date()
|
|
32
47
|
})
|
|
33
48
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread'
|
|
1
2
|
import { ActivityApproval, ActivityApprovalJudgment } from '../../service/activity-approval/activity-approval'
|
|
2
3
|
|
|
3
4
|
export async function reject(
|
|
@@ -10,7 +11,7 @@ export async function reject(
|
|
|
10
11
|
|
|
11
12
|
var activityApproval = await repository.findOne({
|
|
12
13
|
where: { domain: { id: domain.id }, id },
|
|
13
|
-
relations: ['
|
|
14
|
+
relations: ['activityThread']
|
|
14
15
|
})
|
|
15
16
|
|
|
16
17
|
if (!activityApproval) {
|
|
@@ -21,9 +22,7 @@ export async function reject(
|
|
|
21
22
|
)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return await repository.save({
|
|
25
|
+
var result = await repository.save({
|
|
27
26
|
...activityApproval,
|
|
28
27
|
judgment: ActivityApprovalJudgment.Rejected,
|
|
29
28
|
comment,
|
|
@@ -32,4 +31,13 @@ export async function reject(
|
|
|
32
31
|
terminatedAt: new Date(),
|
|
33
32
|
terminator: user
|
|
34
33
|
})
|
|
34
|
+
|
|
35
|
+
await tx.getRepository(ActivityThread).save({
|
|
36
|
+
...activityApproval.activityThread,
|
|
37
|
+
transaction: 'reject',
|
|
38
|
+
state: ActivityThreadStatus.Rejected,
|
|
39
|
+
updater: user
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return result
|
|
35
43
|
}
|
|
@@ -20,13 +20,12 @@ export async function delegate(
|
|
|
20
20
|
const repository = tx.getRepository(ActivityThread)
|
|
21
21
|
|
|
22
22
|
var activityThread = await repository.findOne({
|
|
23
|
-
where: { domain: { id: domain.id }, id }
|
|
24
|
-
relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']
|
|
23
|
+
where: { domain: { id: domain.id }, id }
|
|
25
24
|
})
|
|
26
25
|
|
|
27
26
|
if (!activityThread) {
|
|
28
27
|
throw new Error(
|
|
29
|
-
context.t('error.activity-
|
|
28
|
+
context.t('error.activity-thread not found', {
|
|
30
29
|
activityThread: id
|
|
31
30
|
})
|
|
32
31
|
)
|
|
@@ -10,8 +10,7 @@ export async function end(
|
|
|
10
10
|
const repository = tx.getRepository(ActivityThread)
|
|
11
11
|
|
|
12
12
|
var activityThread = await repository.findOne({
|
|
13
|
-
where: { domain: { id: domain.id }, id }
|
|
14
|
-
relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']
|
|
13
|
+
where: { domain: { id: domain.id }, id }
|
|
15
14
|
})
|
|
16
15
|
|
|
17
16
|
if (!activityThread) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread'
|
|
2
|
+
import { updateActivityInstanceState } from '../common'
|
|
3
|
+
|
|
4
|
+
export async function restart(
|
|
5
|
+
id: string,
|
|
6
|
+
output: object,
|
|
7
|
+
reason: string,
|
|
8
|
+
context: ResolverContext
|
|
9
|
+
): Promise<ActivityThread> {
|
|
10
|
+
const { domain, user, tx } = context.state
|
|
11
|
+
|
|
12
|
+
const repository = tx.getRepository(ActivityThread)
|
|
13
|
+
const activityThread = await repository.findOne({
|
|
14
|
+
where: { domain: { id: domain.id }, id }
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
if (!activityThread) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
context.t('error.activity-thread not found', {
|
|
20
|
+
activityThread: id
|
|
21
|
+
})
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (output) {
|
|
26
|
+
activityThread.output = output
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = await tx.getRepository(ActivityThread).save({
|
|
30
|
+
...activityThread,
|
|
31
|
+
reason,
|
|
32
|
+
state: ActivityThreadStatus.Started,
|
|
33
|
+
transaction: 'restart',
|
|
34
|
+
round: activityThread.round + 1,
|
|
35
|
+
updater: user,
|
|
36
|
+
startedAt: new Date()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
await updateActivityInstanceState(activityThread.activityInstanceId, context)
|
|
40
|
+
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
@@ -7,10 +7,17 @@ export async function save(id: string, save: ActivityThreadSave, context: Resolv
|
|
|
7
7
|
const repository = tx.getRepository(ActivityThread)
|
|
8
8
|
|
|
9
9
|
const activityThread = await repository.findOne({
|
|
10
|
-
where: { domain: { id: domain.id }, id }
|
|
11
|
-
relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']
|
|
10
|
+
where: { domain: { id: domain.id }, id }
|
|
12
11
|
})
|
|
13
12
|
|
|
13
|
+
if (!activityThread) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
context.t('error.activity-thread not found', {
|
|
16
|
+
activityThread: id
|
|
17
|
+
})
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
const result = await repository.save({
|
|
15
22
|
...activityThread,
|
|
16
23
|
...save,
|
|
@@ -11,14 +11,13 @@ export async function start(
|
|
|
11
11
|
|
|
12
12
|
const repository = tx.getRepository(ActivityThread)
|
|
13
13
|
const activityThread = await repository.findOne({
|
|
14
|
-
where: { domain: { id: domain.id }, id }
|
|
15
|
-
relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']
|
|
14
|
+
where: { domain: { id: domain.id }, id }
|
|
16
15
|
})
|
|
17
16
|
|
|
18
17
|
if (!activityThread) {
|
|
19
18
|
throw new Error(
|
|
20
|
-
context.t('error.activity-
|
|
21
|
-
|
|
19
|
+
context.t('error.activity-thread not found', {
|
|
20
|
+
activityThread: id
|
|
22
21
|
})
|
|
23
22
|
)
|
|
24
23
|
}
|
|
@@ -14,7 +14,7 @@ export async function submit(
|
|
|
14
14
|
|
|
15
15
|
var activityThread = await repository.findOne({
|
|
16
16
|
where: { domain: { id: domain.id }, id },
|
|
17
|
-
relations: ['
|
|
17
|
+
relations: ['activityInstance']
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
if (!activityThread) {
|
|
@@ -37,6 +37,7 @@ export async function submit(
|
|
|
37
37
|
await tx.getRepository(ActivityApproval).save({
|
|
38
38
|
domain,
|
|
39
39
|
activityThread,
|
|
40
|
+
round: activityThread.round,
|
|
40
41
|
order: 1,
|
|
41
42
|
judgment: ActivityApprovalJudgment.Pending,
|
|
42
43
|
transaction: 'submit',
|
|
@@ -9,13 +9,12 @@ export async function terminate(
|
|
|
9
9
|
var repository = tx.getRepository(ActivityThread)
|
|
10
10
|
|
|
11
11
|
var activityThread = await repository.findOne({
|
|
12
|
-
where: { domain: { id: domain.id }, id }
|
|
13
|
-
relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']
|
|
12
|
+
where: { domain: { id: domain.id }, id }
|
|
14
13
|
})
|
|
15
14
|
|
|
16
15
|
if (!activityThread) {
|
|
17
16
|
throw new Error(
|
|
18
|
-
context.t('error.activity-
|
|
17
|
+
context.t('error.activity-thread not found', {
|
|
19
18
|
activityThread: id
|
|
20
19
|
})
|
|
21
20
|
)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
|
|
2
2
|
|
|
3
3
|
import { ActivityApproval, ActivityApprovalJudgment } from './activity-approval'
|
|
4
|
-
import { abort } from '../../controllers/activity-approval/abort'
|
|
5
4
|
import { reject } from '../../controllers/activity-approval/reject'
|
|
6
5
|
import { approve } from '../../controllers/activity-approval/approve'
|
|
6
|
+
import { delegate } from '../../controllers/activity-approval/delegate'
|
|
7
|
+
import { ObjectRef } from '@things-factory/shell'
|
|
7
8
|
|
|
8
9
|
@Resolver(ActivityApproval)
|
|
9
10
|
export class ActivityApprovalMutation {
|
|
@@ -60,12 +61,13 @@ export class ActivityApprovalMutation {
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
@Directive('@transaction')
|
|
63
|
-
@Mutation(returns => ActivityApproval!, { nullable: true, description: 'To
|
|
64
|
-
async
|
|
64
|
+
@Mutation(returns => ActivityApproval!, { nullable: true, description: 'To delegate ActivityApproval' })
|
|
65
|
+
async delegateActivityApproval(
|
|
65
66
|
@Arg('id') id: string,
|
|
67
|
+
@Arg('to', type => ObjectRef) to: ObjectRef,
|
|
66
68
|
@Arg('comment', { nullable: true }) comment: string,
|
|
67
69
|
@Ctx() context: ResolverContext
|
|
68
70
|
): Promise<ActivityApproval> {
|
|
69
|
-
return await
|
|
71
|
+
return await delegate({ id, to, comment }, context)
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -33,7 +33,7 @@ export class ActivityApprovalQuery {
|
|
|
33
33
|
return { items, total }
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
@Query(returns => ActivityApprovalList, { description: 'To fetch
|
|
36
|
+
@Query(returns => ActivityApprovalList, { description: 'To fetch the list of work results I need to review' })
|
|
37
37
|
async approvalWaitingList(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<ActivityApprovalList> {
|
|
38
38
|
var { domain, user } = context.state
|
|
39
39
|
|
|
@@ -78,6 +78,11 @@ export class ActivityApprovalQuery {
|
|
|
78
78
|
return await getRepository(Domain).findOneBy({ id: activityApproval.domainId })
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
@FieldResolver(type => User)
|
|
82
|
+
async approver(@Root() activityApproval: ActivityApproval): Promise<User> {
|
|
83
|
+
return await getRepository(User).findOneBy({ id: activityApproval.approverId })
|
|
84
|
+
}
|
|
85
|
+
|
|
81
86
|
@FieldResolver(type => User)
|
|
82
87
|
async updater(@Root() activityApproval: ActivityApproval): Promise<User> {
|
|
83
88
|
return await getRepository(User).findOneBy({ id: activityApproval.updaterId })
|
|
@@ -87,4 +92,9 @@ export class ActivityApprovalQuery {
|
|
|
87
92
|
async creator(@Root() activityApproval: ActivityApproval): Promise<User> {
|
|
88
93
|
return await getRepository(User).findOneBy({ id: activityApproval.creatorId })
|
|
89
94
|
}
|
|
95
|
+
|
|
96
|
+
@FieldResolver(type => User)
|
|
97
|
+
async terminator(@Root() activityApproval: ActivityApproval): Promise<User> {
|
|
98
|
+
return await getRepository(User).findOneBy({ id: activityApproval.terminatorId })
|
|
99
|
+
}
|
|
90
100
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { withFilter } from 'graphql-subscriptions'
|
|
2
|
+
import { Resolver, Root, Subscription } from 'type-graphql'
|
|
3
|
+
|
|
4
|
+
import { User } from '@things-factory/auth-base'
|
|
5
|
+
import { getRepository, pubsub } from '@things-factory/shell'
|
|
6
|
+
|
|
7
|
+
import { ActivityApproval } from './activity-approval'
|
|
8
|
+
|
|
9
|
+
@Resolver(ActivityApproval)
|
|
10
|
+
export class ActivityApprovalSubscription {
|
|
11
|
+
@Subscription({
|
|
12
|
+
subscribe: (_, args, context, info) => {
|
|
13
|
+
const { domain, user } = context.state
|
|
14
|
+
const subdomain = domain?.subdomain
|
|
15
|
+
|
|
16
|
+
if (!domain) {
|
|
17
|
+
throw new Error('domain required')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!user.domains?.find(d => d.subdomain === subdomain) && !process.superUserGranted(domain, user)) {
|
|
21
|
+
throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return withFilter(
|
|
25
|
+
() => pubsub.asyncIterator('activity-approval'),
|
|
26
|
+
async (payload, variables, context, info) => {
|
|
27
|
+
const { activityApproval } = payload
|
|
28
|
+
const { domainId } = activityApproval
|
|
29
|
+
|
|
30
|
+
if (domainId !== domain?.id) {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (activityApproval.approverId === user.id) {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
)(_, args, context, info)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
activityApproval(@Root() payload: { activityApproval: ActivityApproval }): ActivityApproval {
|
|
44
|
+
return payload.activityApproval
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Column,
|
|
7
7
|
RelationId,
|
|
8
8
|
ManyToOne,
|
|
9
|
+
OneToMany,
|
|
9
10
|
PrimaryGeneratedColumn
|
|
10
11
|
} from 'typeorm'
|
|
11
12
|
import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
|
|
@@ -53,6 +54,17 @@ export class ActivityApproval {
|
|
|
53
54
|
@RelationId((activityApproval: ActivityApproval) => activityApproval.domain)
|
|
54
55
|
domainId?: string
|
|
55
56
|
|
|
57
|
+
@ManyToOne(type => ActivityApproval, { nullable: true })
|
|
58
|
+
@Field(type => ActivityApproval, { nullable: true })
|
|
59
|
+
originalApproval?: ActivityApproval
|
|
60
|
+
|
|
61
|
+
@RelationId((activityApproval: ActivityApproval) => activityApproval.originalApproval)
|
|
62
|
+
originalApprovalId?: string
|
|
63
|
+
|
|
64
|
+
@OneToMany(type => ActivityApproval, activityApproval => activityApproval.originalApproval)
|
|
65
|
+
@Field(type => [ActivityApproval])
|
|
66
|
+
derivedApprovals?: ActivityApproval
|
|
67
|
+
|
|
56
68
|
@ManyToOne(type => ActivityThread, { nullable: true })
|
|
57
69
|
@Field(type => ActivityThread, { nullable: true })
|
|
58
70
|
activityThread?: ActivityThread
|
|
@@ -60,6 +72,10 @@ export class ActivityApproval {
|
|
|
60
72
|
@RelationId((activityApproval: ActivityApproval) => activityApproval.activityThread)
|
|
61
73
|
activityThreadId?: string
|
|
62
74
|
|
|
75
|
+
@Column({ nullable: true, default: 1 })
|
|
76
|
+
@Field({ nullable: true })
|
|
77
|
+
round: number = 1
|
|
78
|
+
|
|
63
79
|
@Column({ nullable: true, default: 0 })
|
|
64
80
|
@Field({ nullable: true, description: 'Nth order approval for given activity thread' })
|
|
65
81
|
order?: number = 0
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ActivityApproval } from './activity-approval'
|
|
2
2
|
import { ActivityApprovalQuery } from './activity-approval-query'
|
|
3
3
|
import { ActivityApprovalMutation } from './activity-approval-mutation'
|
|
4
|
+
import { ActivityApprovalSubscription } from './activity-approval-subscription'
|
|
4
5
|
import { ActivityApprovalSubscriber } from './event-subscriber'
|
|
5
6
|
|
|
6
7
|
export const entities = [ActivityApproval]
|
|
7
|
-
export const resolvers = [ActivityApprovalQuery, ActivityApprovalMutation]
|
|
8
|
+
export const resolvers = [ActivityApprovalQuery, ActivityApprovalMutation, ActivityApprovalSubscription]
|
|
8
9
|
export const subscribers = [ActivityApprovalSubscriber]
|
|
@@ -25,9 +25,9 @@ export class ActivityInstanceSubscription {
|
|
|
25
25
|
() => pubsub.asyncIterator('activity-instance'),
|
|
26
26
|
async (payload, variables, context, info) => {
|
|
27
27
|
const { activityInstance } = payload
|
|
28
|
-
const {
|
|
28
|
+
const { domainId } = activityInstance
|
|
29
29
|
|
|
30
|
-
if (
|
|
30
|
+
if (domainId !== domain?.id) {
|
|
31
31
|
return false
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Arg, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { User } from '@things-factory/auth-base'
|
|
4
|
+
import { getQueryBuilderFromListParams, getRepository } from '@things-factory/shell'
|
|
5
|
+
|
|
6
|
+
import { ActivitySummary } from './activity-summary'
|
|
7
|
+
import { ActivityThread, ActivityThreadStatus } from '../activity-thread/activity-thread'
|
|
8
|
+
import { ActivityApproval, ActivityApprovalJudgment } from '../activity-approval/activity-approval'
|
|
9
|
+
import { ActivityInstance, ActivityInstanceStatus } from '../activity-instance/activity-instance'
|
|
10
|
+
|
|
11
|
+
@Resolver(ActivitySummary)
|
|
12
|
+
export class ActivitySummaryQuery {
|
|
13
|
+
@Query(returns => ActivitySummary!, { nullable: true, description: 'To fetch a Activity Summary' })
|
|
14
|
+
async activitySummary(@Ctx() context: ResolverContext): Promise<ActivitySummary> {
|
|
15
|
+
return {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@FieldResolver(type => Number)
|
|
19
|
+
async numberOfToDos(@Root() activitySummary: ActivitySummary, @Ctx() context: ResolverContext): Promise<number> {
|
|
20
|
+
var { domain, user } = context.state
|
|
21
|
+
|
|
22
|
+
const status = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]
|
|
23
|
+
|
|
24
|
+
return await getQueryBuilderFromListParams({
|
|
25
|
+
repository: getRepository(ActivityThread),
|
|
26
|
+
params: {},
|
|
27
|
+
domain,
|
|
28
|
+
alias: 'at',
|
|
29
|
+
searchables: ['name', 'description'],
|
|
30
|
+
filtersMap: {
|
|
31
|
+
name: { columnName: 'name', relationColumn: 'activityInstance' },
|
|
32
|
+
description: { columnName: 'description', relationColumn: 'activityInstance' }
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
.andWhere('at.state NOT IN (:...status)', { status })
|
|
36
|
+
.andWhere('at.assignee = :user', { user: user.id })
|
|
37
|
+
.getCount()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@FieldResolver(type => Number)
|
|
41
|
+
async numberOfApprovalWaitings(
|
|
42
|
+
@Root() activitySummary: ActivitySummary,
|
|
43
|
+
@Ctx() context: ResolverContext
|
|
44
|
+
): Promise<number> {
|
|
45
|
+
var { domain, user } = context.state
|
|
46
|
+
|
|
47
|
+
const judgment = [
|
|
48
|
+
ActivityApprovalJudgment.Escalated,
|
|
49
|
+
ActivityApprovalJudgment.Delegated,
|
|
50
|
+
ActivityApprovalJudgment.Approved,
|
|
51
|
+
ActivityApprovalJudgment.Rejected
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
return await getQueryBuilderFromListParams({
|
|
55
|
+
repository: getRepository(ActivityApproval),
|
|
56
|
+
params: {},
|
|
57
|
+
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
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.andWhere('ap.judgment NOT IN (:...judgment)', { judgment })
|
|
72
|
+
.andWhere('ap.approver = :user', { user: user.id })
|
|
73
|
+
.getCount()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@FieldResolver(type => Number)
|
|
77
|
+
async numberOfPicks(@Root() activitySummary: ActivitySummary, @Ctx() context: ResolverContext): Promise<number> {
|
|
78
|
+
var { domain, user } = context.state
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
activity-instance 중에서 아직 created 상태이면서,
|
|
82
|
+
activity-instance의 assigneeRole 이 지정되지 않았거나,
|
|
83
|
+
assigneeRole이 지정되었으면 그 Role에 내가 해당된 경우이면서,
|
|
84
|
+
나는 아직 해당 activity-instance의 thread를 할당받지 않은 경우에 해당하는
|
|
85
|
+
activity-instance 리스트를 모두 가져오는 쿼리이다.
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
user = await getRepository(User).findOne({
|
|
89
|
+
where: { id: user.id },
|
|
90
|
+
relations: ['roles']
|
|
91
|
+
})
|
|
92
|
+
const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)
|
|
93
|
+
|
|
94
|
+
if (!roles.length) {
|
|
95
|
+
return 0
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return await getQueryBuilderFromListParams({
|
|
99
|
+
repository: getRepository(ActivityInstance),
|
|
100
|
+
params: {},
|
|
101
|
+
domain,
|
|
102
|
+
alias: 'ai',
|
|
103
|
+
searchables: ['name', 'description']
|
|
104
|
+
})
|
|
105
|
+
.leftJoinAndSelect('ai.activityThreads', 'threads', 'threads.assignee = :user', { user: user.id })
|
|
106
|
+
.andWhere('ai.state IN (:...status)', {
|
|
107
|
+
status: [ActivityInstanceStatus.Posted, ActivityInstanceStatus.WaitingAssignment]
|
|
108
|
+
})
|
|
109
|
+
.andWhere('ai.assigneeRole IN (:...roles)', { roles })
|
|
110
|
+
.andWhere('threads.id IS NULL') /* 이미 내가 할당된 경우는 제외한다. */
|
|
111
|
+
.getCount()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@FieldResolver(type => Number)
|
|
115
|
+
async numberOfDrafts(@Root() activitySummary: ActivitySummary, @Ctx() context: ResolverContext): Promise<number> {
|
|
116
|
+
var { domain, user } = context.state
|
|
117
|
+
|
|
118
|
+
/* 생성자가 자신이면서, 아직 Draft 상태인 activity-instance 리스트만 반환 */
|
|
119
|
+
const status = [ActivityInstanceStatus.Draft]
|
|
120
|
+
|
|
121
|
+
return await getQueryBuilderFromListParams({
|
|
122
|
+
repository: getRepository(ActivityInstance),
|
|
123
|
+
params: {},
|
|
124
|
+
domain,
|
|
125
|
+
alias: 'ai',
|
|
126
|
+
searchables: ['name', 'description']
|
|
127
|
+
})
|
|
128
|
+
.andWhere('ai.state IN (:...status)', { status })
|
|
129
|
+
.andWhere('ai.creator = :user', { user: user.id })
|
|
130
|
+
.getCount()
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Field, ObjectType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
@ObjectType({ description: 'Object Type for My Activity Summary' })
|
|
4
|
+
export class ActivitySummary {
|
|
5
|
+
@Field({ nullable: true })
|
|
6
|
+
numberOfToDos?: number
|
|
7
|
+
|
|
8
|
+
@Field({ nullable: true })
|
|
9
|
+
numberOfApprovalWaitings?: number
|
|
10
|
+
|
|
11
|
+
@Field({ nullable: true })
|
|
12
|
+
numberOfPicks?: number
|
|
13
|
+
|
|
14
|
+
@Field({ nullable: true })
|
|
15
|
+
numberOfDrafts?: number
|
|
16
|
+
}
|