@rytass/bpm-core-client 0.5.0 → 0.5.1
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/CHANGELOG.md +11 -0
- package/package.json +3 -2
- package/src/index.js +8 -0
- package/src/index.js.map +1 -0
- package/src/lib/api-auth-client.d.ts +73 -0
- package/src/lib/api-auth-client.js +129 -0
- package/src/lib/api-auth-client.js.map +1 -0
- package/src/lib/client-config.d.ts +81 -0
- package/src/lib/client-config.js +63 -0
- package/src/lib/client-config.js.map +1 -0
- package/src/lib/form/form-api.d.ts +54 -0
- package/src/lib/form/form-api.js +240 -0
- package/src/lib/form/form-api.js.map +1 -0
- package/src/lib/form/form-rendering.d.ts +52 -0
- package/src/lib/form/form-rendering.js +341 -0
- package/src/lib/form/form-rendering.js.map +1 -0
- package/src/lib/form/index.js +6 -0
- package/src/lib/form/index.js.map +1 -0
- package/src/lib/graphql-client.d.ts +45 -0
- package/src/lib/graphql-client.js +101 -0
- package/src/lib/graphql-client.js.map +1 -0
- package/src/lib/member-api.d.ts +49 -0
- package/src/lib/member-api.js +72 -0
- package/src/lib/member-api.js.map +1 -0
- package/src/lib/organization/index.js +5 -0
- package/src/lib/organization/index.js.map +1 -0
- package/src/lib/organization/organization-api.d.ts +173 -0
- package/src/lib/organization/organization-api.js +394 -0
- package/src/lib/organization/organization-api.js.map +1 -0
- package/src/lib/template/index.js +5 -0
- package/src/lib/template/index.js.map +1 -0
- package/src/lib/template/template-api.d.ts +174 -0
- package/src/lib/template/template-api.js +469 -0
- package/src/lib/template/template-api.js.map +1 -0
- package/src/lib/workflow/index.js +5 -0
- package/src/lib/workflow/index.js.map +1 -0
- package/src/lib/workflow/workflow-api.d.ts +517 -0
- package/src/lib/workflow/workflow-api.js +1068 -0
- package/src/lib/workflow/workflow-api.js.map +1 -0
- package/eslint.config.mjs +0 -19
- package/jest.config.cts +0 -10
- package/project.json +0 -66
- package/src/lib/api-auth-client.ts +0 -182
- package/src/lib/client-config.ts +0 -99
- package/src/lib/form/form-api.spec.ts +0 -81
- package/src/lib/form/form-api.ts +0 -402
- package/src/lib/form/form-rendering.ts +0 -580
- package/src/lib/graphql-client.spec.ts +0 -65
- package/src/lib/graphql-client.ts +0 -128
- package/src/lib/member-api.ts +0 -129
- package/src/lib/organization/organization-api.spec.ts +0 -90
- package/src/lib/organization/organization-api.ts +0 -711
- package/src/lib/template/template-api.spec.ts +0 -88
- package/src/lib/template/template-api.ts +0 -894
- package/src/lib/workflow/workflow-api.spec.ts +0 -132
- package/src/lib/workflow/workflow-api.ts +0 -2124
- package/tsconfig.json +0 -27
- package/tsconfig.lib.json +0 -16
- package/tsconfig.spec.json +0 -16
- /package/src/{index.ts → index.d.ts} +0 -0
- /package/src/lib/form/{index.ts → index.d.ts} +0 -0
- /package/src/lib/organization/{index.ts → index.d.ts} +0 -0
- /package/src/lib/template/{index.ts → index.d.ts} +0 -0
- /package/src/lib/workflow/{index.ts → index.d.ts} +0 -0
|
@@ -1,2124 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FormDefinitionSchema,
|
|
3
|
-
FormFieldDefinition,
|
|
4
|
-
FormFieldValue,
|
|
5
|
-
FormUiSchema,
|
|
6
|
-
SelectFieldDefinition,
|
|
7
|
-
} from '@rytass/bpm-core-shared/form';
|
|
8
|
-
import { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
|
|
9
|
-
import { requestGraphQl } from '../graphql-client';
|
|
10
|
-
|
|
11
|
-
export type ApprovalInstanceState =
|
|
12
|
-
| 'APPROVED'
|
|
13
|
-
| 'CANCELLED'
|
|
14
|
-
| 'DRAFT'
|
|
15
|
-
| 'EXPIRED'
|
|
16
|
-
| 'REJECTED'
|
|
17
|
-
| 'RETURNED'
|
|
18
|
-
| 'RUNNING';
|
|
19
|
-
|
|
20
|
-
export type TaskStatus =
|
|
21
|
-
| 'CANCELLED'
|
|
22
|
-
| 'COMPLETED'
|
|
23
|
-
| 'IN_PROGRESS'
|
|
24
|
-
| 'PENDING'
|
|
25
|
-
| 'TRANSFERRED';
|
|
26
|
-
|
|
27
|
-
export type TaskAssignmentType = 'CANDIDATE_GROUP' | 'DIRECT_MEMBER';
|
|
28
|
-
|
|
29
|
-
export type TaskDecisionAction =
|
|
30
|
-
| 'APPROVED'
|
|
31
|
-
| 'REJECTED'
|
|
32
|
-
| 'RETURNED'
|
|
33
|
-
| 'TRANSFERRED';
|
|
34
|
-
|
|
35
|
-
export type AdhocDirectiveType =
|
|
36
|
-
| 'COMPLETION_NOTIFY'
|
|
37
|
-
| 'COUNTERSIGN'
|
|
38
|
-
| 'PRE_APPROVAL'
|
|
39
|
-
| 'STAGE_NOTIFY';
|
|
40
|
-
|
|
41
|
-
export type AdhocDirectiveStatus = 'CANCELLED' | 'CONSUMED' | 'PENDING';
|
|
42
|
-
|
|
43
|
-
export type AdhocTargetKind =
|
|
44
|
-
| 'MEMBER'
|
|
45
|
-
| 'ORG_UNIT_MEMBER'
|
|
46
|
-
| 'POSITION'
|
|
47
|
-
| 'WEBHOOK';
|
|
48
|
-
|
|
49
|
-
export type AdhocPreApprovalRejectBehavior =
|
|
50
|
-
| 'REJECT_INSTANCE'
|
|
51
|
-
| 'RETURN_TO_ORIGIN';
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Polymorphic target of an ad-hoc directive. Set exactly the fields matching
|
|
55
|
-
* `kind`:
|
|
56
|
-
*
|
|
57
|
-
* - `MEMBER` → `memberIds`
|
|
58
|
-
* - `POSITION` → `positionId`
|
|
59
|
-
* - `ORG_UNIT_MEMBER` → `orgUnitId` (+ optional `includeDescendants`)
|
|
60
|
-
* - `WEBHOOK` → `webhookUrl` (+ optional `webhookHeaders`); only valid for
|
|
61
|
-
* the notification directives, never as countersign / pre-approval signers.
|
|
62
|
-
*/
|
|
63
|
-
export interface AdhocTargetOptions {
|
|
64
|
-
readonly includeDescendants?: boolean;
|
|
65
|
-
readonly kind: AdhocTargetKind;
|
|
66
|
-
readonly memberIds?: readonly string[];
|
|
67
|
-
readonly orgUnitId?: string;
|
|
68
|
-
readonly positionId?: string;
|
|
69
|
-
readonly webhookHeaders?: Readonly<Record<string, string>>;
|
|
70
|
-
readonly webhookUrl?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* An instance-scoped ad-hoc directive recorded by a stage approver. Directives
|
|
75
|
-
* never modify the workflow template — they only affect the single approval
|
|
76
|
-
* instance they were created on. `status` lifecycle: `PENDING` (waiting for
|
|
77
|
-
* its trigger) → `CONSUMED` (effect applied / notification sent) or
|
|
78
|
-
* `CANCELLED` (withdrawn, or dropped by a return / reject / cancel).
|
|
79
|
-
*/
|
|
80
|
-
export interface AdhocDirectiveRecord {
|
|
81
|
-
readonly channels: readonly NotificationChannel[] | null;
|
|
82
|
-
readonly comment: string | null;
|
|
83
|
-
readonly consumedAt: string | null;
|
|
84
|
-
readonly createdAt: string;
|
|
85
|
-
readonly createdByMemberId: string;
|
|
86
|
-
readonly id: string;
|
|
87
|
-
readonly instanceId: string;
|
|
88
|
-
readonly onReject: AdhocPreApprovalRejectBehavior | null;
|
|
89
|
-
readonly originNodeId: string;
|
|
90
|
-
readonly originTaskId: string;
|
|
91
|
-
readonly status: AdhocDirectiveStatus;
|
|
92
|
-
readonly targetKind: AdhocTargetKind;
|
|
93
|
-
readonly targetValueJson: string;
|
|
94
|
-
readonly type: AdhocDirectiveType;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface ApprovalInstanceRecord {
|
|
98
|
-
readonly completedAt: string | null;
|
|
99
|
-
readonly formData: WorkflowFormData;
|
|
100
|
-
readonly formDataJson: string;
|
|
101
|
-
readonly formDefinitionSnapshot: FormDefinitionSnapshot;
|
|
102
|
-
readonly formDefinitionSnapshotJson: string;
|
|
103
|
-
readonly id: string;
|
|
104
|
-
readonly initiatorMemberId: string;
|
|
105
|
-
readonly startedAt: string;
|
|
106
|
-
readonly state: ApprovalInstanceState;
|
|
107
|
-
readonly templateId: string;
|
|
108
|
-
readonly templateVersionId: string;
|
|
109
|
-
readonly title: string;
|
|
110
|
-
readonly workflowSnapshot: WorkflowDefinition;
|
|
111
|
-
readonly workflowSnapshotJson: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface FormDefinitionSnapshot {
|
|
115
|
-
readonly formDefinitionVersionId?: string;
|
|
116
|
-
readonly schema?: FormDefinitionSchema;
|
|
117
|
-
readonly uiSchema?: FormUiSchema;
|
|
118
|
-
readonly version?: number;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export type WorkflowFormData = Readonly<
|
|
122
|
-
Record<string, FormFieldValue | undefined>
|
|
123
|
-
>;
|
|
124
|
-
|
|
125
|
-
export interface TaskRecord {
|
|
126
|
-
readonly adhocDirectiveId: string | null;
|
|
127
|
-
readonly adhocOriginTaskId: string | null;
|
|
128
|
-
readonly adhocType: AdhocDirectiveType | null;
|
|
129
|
-
readonly assigneeMemberId: string | null;
|
|
130
|
-
readonly assignmentType: TaskAssignmentType;
|
|
131
|
-
readonly candidateMemberIds: readonly string[];
|
|
132
|
-
readonly completedAt: string | null;
|
|
133
|
-
readonly createdAt: string;
|
|
134
|
-
readonly decisionPolicySnapshotJson: string;
|
|
135
|
-
readonly delegationChainJson: string;
|
|
136
|
-
readonly id: string;
|
|
137
|
-
readonly instanceId: string;
|
|
138
|
-
readonly isAdhoc: boolean;
|
|
139
|
-
readonly nodeId: string;
|
|
140
|
-
readonly openedAt: string | null;
|
|
141
|
-
readonly originalAssigneeMemberId: string | null;
|
|
142
|
-
readonly slaDueAt: string | null;
|
|
143
|
-
readonly status: TaskStatus;
|
|
144
|
-
readonly tokenId: string;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export interface TaskCandidateRecord {
|
|
148
|
-
readonly claimedAt: string | null;
|
|
149
|
-
readonly createdAt: string;
|
|
150
|
-
readonly decidedAt: string | null;
|
|
151
|
-
readonly delegationChainJson: string;
|
|
152
|
-
readonly id: string;
|
|
153
|
-
readonly memberId: string;
|
|
154
|
-
readonly originalMemberId: string;
|
|
155
|
-
readonly sourceType: string;
|
|
156
|
-
readonly status: string;
|
|
157
|
-
readonly taskId: string;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export interface WorkflowTokenRecord {
|
|
161
|
-
readonly consumedAt: string | null;
|
|
162
|
-
readonly createdAt: string;
|
|
163
|
-
readonly currentNodeId: string;
|
|
164
|
-
readonly id: string;
|
|
165
|
-
readonly instanceId: string;
|
|
166
|
-
readonly parentTokenId: string | null;
|
|
167
|
-
readonly status: 'ACTIVE' | 'CONSUMED' | 'WAITING';
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export interface TaskDecisionRecord {
|
|
171
|
-
readonly action: TaskDecisionAction;
|
|
172
|
-
readonly comment: string | null;
|
|
173
|
-
readonly decidedAt: string;
|
|
174
|
-
readonly decidedByMemberId: string;
|
|
175
|
-
readonly id: string;
|
|
176
|
-
readonly returnToNodeId: string | null;
|
|
177
|
-
readonly signatureId: string | null;
|
|
178
|
-
readonly taskId: string;
|
|
179
|
-
readonly transferToMemberId: string | null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export interface ActivityLogRecord {
|
|
183
|
-
readonly actorMemberId: string | null;
|
|
184
|
-
readonly createdAt: string;
|
|
185
|
-
readonly eventType: string;
|
|
186
|
-
readonly id: string;
|
|
187
|
-
readonly nodeId: string | null;
|
|
188
|
-
readonly payloadJson: string;
|
|
189
|
-
readonly taskId: string | null;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export interface MemberProfileRecord {
|
|
193
|
-
readonly email: string;
|
|
194
|
-
readonly memberId: string;
|
|
195
|
-
readonly name: string;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export interface MemberDirectoryPage {
|
|
199
|
-
readonly members: readonly MemberProfileRecord[];
|
|
200
|
-
readonly totalCount: number;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export type DelegationScopeType = 'ALL' | 'CONDITION_BASED' | 'TEMPLATE_LIST';
|
|
204
|
-
|
|
205
|
-
export type DelegationRuleStatus = 'ACTIVE' | 'EXPIRED' | 'REVOKED';
|
|
206
|
-
|
|
207
|
-
export type NotificationChannel = 'EMAIL' | 'IN_APP' | 'WEBHOOK';
|
|
208
|
-
|
|
209
|
-
export type NotificationDigestMode = 'DAILY' | 'INSTANT';
|
|
210
|
-
|
|
211
|
-
export type NotificationStatus = 'FAILED' | 'PENDING' | 'READ' | 'SENT';
|
|
212
|
-
|
|
213
|
-
export type NotificationType =
|
|
214
|
-
| 'INSTANCE_COMPLETED'
|
|
215
|
-
| 'SLA_OVERDUE'
|
|
216
|
-
| 'SLA_WARNING'
|
|
217
|
-
| 'TASK_ASSIGNED'
|
|
218
|
-
| 'TASK_TRANSFERRED';
|
|
219
|
-
|
|
220
|
-
export type NotificationResolution =
|
|
221
|
-
| 'APPROVED'
|
|
222
|
-
| 'REJECTED'
|
|
223
|
-
| 'RETURNED'
|
|
224
|
-
| 'SUPERSEDED'
|
|
225
|
-
| 'TRANSFERRED';
|
|
226
|
-
|
|
227
|
-
export interface NotificationRecord {
|
|
228
|
-
/**
|
|
229
|
-
* Whether the recipient can still act on this notification (an unresolved
|
|
230
|
-
* task assignment). Server-derived; drives the inline 同意/拒絕 actions.
|
|
231
|
-
*/
|
|
232
|
-
readonly actionable: boolean;
|
|
233
|
-
readonly attemptCount: number;
|
|
234
|
-
readonly body: string;
|
|
235
|
-
readonly channel: NotificationChannel;
|
|
236
|
-
readonly createdAt: string;
|
|
237
|
-
readonly deliveredAt: string | null;
|
|
238
|
-
readonly deliveryError: string | null;
|
|
239
|
-
readonly deliveryTarget: string | null;
|
|
240
|
-
readonly id: string;
|
|
241
|
-
readonly instanceId: string | null;
|
|
242
|
-
readonly lastAttemptAt: string | null;
|
|
243
|
-
readonly nextRetryAt: string | null;
|
|
244
|
-
readonly payloadJson: string;
|
|
245
|
-
readonly readAt: string | null;
|
|
246
|
-
readonly recipientMemberId: string;
|
|
247
|
-
/** How an actionable notification was resolved; `null` while still open. */
|
|
248
|
-
readonly resolution: NotificationResolution | null;
|
|
249
|
-
readonly resolvedAt: string | null;
|
|
250
|
-
readonly sentAt: string | null;
|
|
251
|
-
readonly status: NotificationStatus;
|
|
252
|
-
readonly taskId: string | null;
|
|
253
|
-
readonly title: string;
|
|
254
|
-
readonly type: NotificationType;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export interface NotificationPreferenceRecord {
|
|
258
|
-
readonly emailDigestMode: NotificationDigestMode;
|
|
259
|
-
readonly emailEnabled: boolean;
|
|
260
|
-
readonly inAppEnabled: boolean;
|
|
261
|
-
readonly memberId: string;
|
|
262
|
-
readonly quietHoursEnd: string | null;
|
|
263
|
-
readonly quietHoursStart: string | null;
|
|
264
|
-
readonly updatedAt: string;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export interface DelegationRuleRecord {
|
|
268
|
-
readonly agentMemberId: string;
|
|
269
|
-
readonly createdAt: string;
|
|
270
|
-
readonly createdByMemberId: string | null;
|
|
271
|
-
readonly endAt: string | null;
|
|
272
|
-
readonly id: string;
|
|
273
|
-
readonly principalMemberId: string;
|
|
274
|
-
readonly priority: number;
|
|
275
|
-
readonly requiresConfirmation: boolean;
|
|
276
|
-
readonly revokedAt: string | null;
|
|
277
|
-
readonly revokedByMemberId: string | null;
|
|
278
|
-
readonly scopeConditionCel: string | null;
|
|
279
|
-
readonly scopeTemplateIds: readonly string[];
|
|
280
|
-
readonly scopeType: DelegationScopeType;
|
|
281
|
-
readonly startAt: string;
|
|
282
|
-
readonly status: DelegationRuleStatus;
|
|
283
|
-
readonly updatedAt: string;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export interface AttachmentRecord {
|
|
287
|
-
readonly checksumSha256: string;
|
|
288
|
-
readonly createdAt: string;
|
|
289
|
-
readonly filename: string;
|
|
290
|
-
readonly formFieldPath: string | null;
|
|
291
|
-
readonly id: string;
|
|
292
|
-
readonly instanceId: string | null;
|
|
293
|
-
readonly mimeType: string;
|
|
294
|
-
readonly sizeBytes: string;
|
|
295
|
-
readonly storageKey: string;
|
|
296
|
-
readonly storageProvider: string;
|
|
297
|
-
readonly taskId: string | null;
|
|
298
|
-
readonly uploaderMemberId: string;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
export interface SignatureRecord {
|
|
302
|
-
readonly algorithm: string;
|
|
303
|
-
readonly id: string;
|
|
304
|
-
readonly instanceId: string;
|
|
305
|
-
readonly keyVersion: number;
|
|
306
|
-
readonly previousSignatureHash: string | null;
|
|
307
|
-
readonly signature: string;
|
|
308
|
-
readonly signedAt: string;
|
|
309
|
-
readonly signedPayloadHash: string;
|
|
310
|
-
readonly signedPayloadJson: string;
|
|
311
|
-
readonly signerMemberId: string;
|
|
312
|
-
readonly taskId: string | null;
|
|
313
|
-
readonly timestampTokenBase64: string | null;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export interface SignatureVerificationRecord {
|
|
317
|
-
readonly checkedCount: number;
|
|
318
|
-
readonly errors: readonly string[];
|
|
319
|
-
readonly instanceId: string;
|
|
320
|
-
readonly valid: boolean;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
export interface ApprovalTemplateRecord {
|
|
324
|
-
readonly currentVersionId: string | null;
|
|
325
|
-
readonly id: string;
|
|
326
|
-
readonly name: string;
|
|
327
|
-
readonly updatedAt?: string;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
export interface ApprovalTemplateVersionRecord {
|
|
331
|
-
readonly formDefinitionVersionId: string | null;
|
|
332
|
-
readonly id: string;
|
|
333
|
-
readonly status: 'ARCHIVED' | 'DRAFT' | 'PUBLISHED';
|
|
334
|
-
readonly version: number;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export interface LaunchContext {
|
|
338
|
-
readonly formVersion: {
|
|
339
|
-
readonly id: string;
|
|
340
|
-
readonly schema: FormDefinitionSchema;
|
|
341
|
-
readonly uiSchema: FormUiSchema;
|
|
342
|
-
readonly version: number;
|
|
343
|
-
};
|
|
344
|
-
readonly template: ApprovalTemplateRecord;
|
|
345
|
-
readonly templateVersion: ApprovalTemplateVersionRecord;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
export interface LaunchableTemplateRecord {
|
|
349
|
-
readonly currentVersionId: string;
|
|
350
|
-
readonly formDefinitionVersionId: string;
|
|
351
|
-
readonly id: string;
|
|
352
|
-
readonly name: string;
|
|
353
|
-
readonly updatedAt: string;
|
|
354
|
-
readonly version: number;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
export type ApprovalInstanceView = 'ALL' | 'CC' | 'SENT';
|
|
358
|
-
|
|
359
|
-
export interface ApprovalInstancesPageInput {
|
|
360
|
-
readonly page: number;
|
|
361
|
-
readonly pageSize: number;
|
|
362
|
-
readonly searchText: string | null;
|
|
363
|
-
readonly state: ApprovalInstanceState | null;
|
|
364
|
-
readonly templateId: string | null;
|
|
365
|
-
readonly view: ApprovalInstanceView;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export interface ApprovalInstancesPageResult {
|
|
369
|
-
readonly instances: readonly ApprovalInstanceRecord[];
|
|
370
|
-
readonly pageInfo: ApprovalInstancePageInfoRecord;
|
|
371
|
-
readonly totalCount: number;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
export interface ApprovalInstancePageInfoRecord {
|
|
375
|
-
readonly hasNextPage: boolean;
|
|
376
|
-
readonly hasPreviousPage: boolean;
|
|
377
|
-
readonly page: number;
|
|
378
|
-
readonly pageSize: number;
|
|
379
|
-
readonly totalCount: number;
|
|
380
|
-
readonly totalPages: number;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
export interface WorkflowDashboardSummaryRecord {
|
|
384
|
-
readonly activeInstanceCount: number;
|
|
385
|
-
readonly completedInstanceCount: number;
|
|
386
|
-
readonly overdueTaskCount: number;
|
|
387
|
-
readonly pendingTaskCount: number;
|
|
388
|
-
readonly rejectedInstanceCount: number;
|
|
389
|
-
readonly totalInstanceCount: number;
|
|
390
|
-
readonly unreadNotificationCount: number;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
interface ApprovalInstancesQueryData {
|
|
394
|
-
readonly approvalInstances: readonly InstanceJsonRecord[];
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
interface ApprovalInstancePageInfoQueryData {
|
|
398
|
-
readonly approvalInstancePageInfo: ApprovalInstancePageInfoRecord;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
interface WorkflowDashboardSummaryQueryData {
|
|
402
|
-
readonly workflowDashboardSummary: Omit<
|
|
403
|
-
WorkflowDashboardSummaryRecord,
|
|
404
|
-
'unreadNotificationCount'
|
|
405
|
-
>;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
interface ApprovalInstanceQueryData {
|
|
409
|
-
readonly approvalInstance: InstanceJsonRecord;
|
|
410
|
-
readonly activityLogs: readonly ActivityLogRecord[];
|
|
411
|
-
readonly tasks: readonly TaskRecord[];
|
|
412
|
-
readonly workflowTokens: readonly WorkflowTokenRecord[];
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
interface InboxTasksQueryData {
|
|
416
|
-
readonly inboxTasks: readonly TaskRecord[];
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
interface ApprovalHistoryTasksQueryData {
|
|
420
|
-
readonly approvalHistoryTasks: readonly TaskRecord[];
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
interface TaskDecisionsQueryData {
|
|
424
|
-
readonly taskDecisions: readonly TaskDecisionRecord[];
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
interface AttachmentsQueryData {
|
|
428
|
-
readonly attachments: readonly AttachmentRecord[];
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
interface AttachmentDownloadUrlQueryData {
|
|
432
|
-
readonly attachmentDownloadUrl: string;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
interface AttachmentPreviewUrlQueryData {
|
|
436
|
-
readonly attachmentPreviewUrl: string;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
interface SignaturesQueryData {
|
|
440
|
-
readonly signatures: readonly SignatureRecord[];
|
|
441
|
-
readonly verifySignatureChain: SignatureVerificationRecord;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
interface UploadAttachmentMutationData {
|
|
445
|
-
readonly uploadAttachment: AttachmentRecord;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
interface MembersQueryData {
|
|
449
|
-
readonly members: readonly MemberProfileRecord[];
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
interface SearchMembersQueryData {
|
|
453
|
-
readonly searchMembers: readonly MemberProfileRecord[];
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
interface MemberDirectoryPageQueryData {
|
|
457
|
-
readonly memberCount: number;
|
|
458
|
-
readonly searchMembers: readonly MemberProfileRecord[];
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
interface DelegationRulesQueryData {
|
|
462
|
-
readonly delegationRules: readonly DelegationRuleRecord[];
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
interface DelegationRulesPageQueryData extends DelegationRulesQueryData {
|
|
466
|
-
readonly delegationRuleCount: number;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
interface NotificationsQueryData {
|
|
470
|
-
readonly notificationCount: number;
|
|
471
|
-
readonly notifications: readonly NotificationRecord[];
|
|
472
|
-
readonly unreadNotificationCount: number;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
interface NotificationPreferenceQueryData {
|
|
476
|
-
readonly notificationPreference: NotificationPreferenceRecord;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
interface CreateDelegationRuleMutationData {
|
|
480
|
-
readonly createDelegationRule: DelegationRuleRecord;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
interface RevokeDelegationRuleMutationData {
|
|
484
|
-
readonly revokeDelegationRule: DelegationRuleRecord;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
interface MarkNotificationReadMutationData {
|
|
488
|
-
readonly markNotificationRead: Pick<
|
|
489
|
-
NotificationRecord,
|
|
490
|
-
'id' | 'readAt' | 'status'
|
|
491
|
-
>;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
interface UpdateNotificationPreferenceMutationData {
|
|
495
|
-
readonly updateNotificationPreference: NotificationPreferenceRecord;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
interface SubmitApprovalInstanceMutationData {
|
|
499
|
-
readonly submitApprovalInstance: Pick<ApprovalInstanceRecord, 'id'>;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
interface DecideTaskMutationData {
|
|
503
|
-
readonly decideTask: TaskDecisionRecord;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
interface CancelApprovalInstanceMutationData {
|
|
507
|
-
readonly cancelApprovalInstance: Pick<ApprovalInstanceRecord, 'id' | 'state'>;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
interface ResubmitApprovalInstanceMutationData {
|
|
511
|
-
readonly resubmitApprovalInstance: Pick<
|
|
512
|
-
ApprovalInstanceRecord,
|
|
513
|
-
'id' | 'state'
|
|
514
|
-
>;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
interface LaunchTemplateQueryData {
|
|
518
|
-
readonly approvalTemplate: ApprovalTemplateRecord & {
|
|
519
|
-
readonly updatedAt: string;
|
|
520
|
-
};
|
|
521
|
-
readonly approvalTemplateVersions: readonly ApprovalTemplateVersionRecord[];
|
|
522
|
-
readonly launchableApprovalTemplates?: readonly (ApprovalTemplateRecord & {
|
|
523
|
-
readonly updatedAt: string;
|
|
524
|
-
})[];
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
interface LaunchTemplatesQueryData {
|
|
528
|
-
readonly approvalTemplates?: readonly (ApprovalTemplateRecord & {
|
|
529
|
-
readonly updatedAt: string;
|
|
530
|
-
})[];
|
|
531
|
-
readonly launchableApprovalTemplates?: readonly (ApprovalTemplateRecord & {
|
|
532
|
-
readonly updatedAt: string;
|
|
533
|
-
})[];
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
interface LaunchTemplateVersionsQueryData {
|
|
537
|
-
readonly approvalTemplateVersions: readonly ApprovalTemplateVersionRecord[];
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
interface LaunchFormVersionQueryData {
|
|
541
|
-
readonly formDefinitionVersion: {
|
|
542
|
-
readonly id: string;
|
|
543
|
-
readonly schemaJson: string;
|
|
544
|
-
readonly uiSchemaJson: string;
|
|
545
|
-
readonly version: number;
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
interface InstanceJsonRecord extends Omit<
|
|
550
|
-
ApprovalInstanceRecord,
|
|
551
|
-
'formData' | 'formDefinitionSnapshot' | 'workflowSnapshot'
|
|
552
|
-
> {
|
|
553
|
-
readonly formDataJson: string;
|
|
554
|
-
readonly formDefinitionSnapshotJson: string;
|
|
555
|
-
readonly workflowSnapshotJson: string;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
export async function listApprovalInstances(): Promise<
|
|
559
|
-
readonly ApprovalInstanceRecord[]
|
|
560
|
-
> {
|
|
561
|
-
const data = await requestGraphQl<ApprovalInstancesQueryData>(
|
|
562
|
-
`query ApprovalInstances {
|
|
563
|
-
approvalInstances {
|
|
564
|
-
completedAt
|
|
565
|
-
formDataJson
|
|
566
|
-
formDefinitionSnapshotJson
|
|
567
|
-
id
|
|
568
|
-
initiatorMemberId
|
|
569
|
-
startedAt
|
|
570
|
-
state
|
|
571
|
-
templateId
|
|
572
|
-
templateVersionId
|
|
573
|
-
title
|
|
574
|
-
workflowSnapshotJson
|
|
575
|
-
}
|
|
576
|
-
}`,
|
|
577
|
-
);
|
|
578
|
-
|
|
579
|
-
return data.approvalInstances.map(parseInstanceJson);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
export async function listApprovalInstancesPage({
|
|
583
|
-
page,
|
|
584
|
-
pageSize,
|
|
585
|
-
searchText,
|
|
586
|
-
state,
|
|
587
|
-
templateId,
|
|
588
|
-
view,
|
|
589
|
-
}: ApprovalInstancesPageInput): Promise<ApprovalInstancesPageResult> {
|
|
590
|
-
const variables = {
|
|
591
|
-
page,
|
|
592
|
-
pageSize,
|
|
593
|
-
searchText: searchText?.trim() || null,
|
|
594
|
-
state: state ? [state] : null,
|
|
595
|
-
templateId: templateId?.trim() || null,
|
|
596
|
-
view,
|
|
597
|
-
};
|
|
598
|
-
const [pageData, pageInfoData] = await Promise.all([
|
|
599
|
-
requestGraphQl<ApprovalInstancesQueryData>(
|
|
600
|
-
`query ApprovalInstancesPage(
|
|
601
|
-
$view: ApprovalInstanceListView
|
|
602
|
-
$searchText: String
|
|
603
|
-
$state: [ApprovalInstanceState!]
|
|
604
|
-
$templateId: String
|
|
605
|
-
$page: Int
|
|
606
|
-
$pageSize: Int
|
|
607
|
-
) {
|
|
608
|
-
approvalInstances(
|
|
609
|
-
view: $view
|
|
610
|
-
searchText: $searchText
|
|
611
|
-
state: $state
|
|
612
|
-
templateId: $templateId
|
|
613
|
-
page: $page
|
|
614
|
-
pageSize: $pageSize
|
|
615
|
-
) {
|
|
616
|
-
completedAt
|
|
617
|
-
formDataJson
|
|
618
|
-
formDefinitionSnapshotJson
|
|
619
|
-
id
|
|
620
|
-
initiatorMemberId
|
|
621
|
-
startedAt
|
|
622
|
-
state
|
|
623
|
-
templateId
|
|
624
|
-
templateVersionId
|
|
625
|
-
title
|
|
626
|
-
workflowSnapshotJson
|
|
627
|
-
}
|
|
628
|
-
}`,
|
|
629
|
-
variables,
|
|
630
|
-
),
|
|
631
|
-
requestGraphQl<ApprovalInstancePageInfoQueryData>(
|
|
632
|
-
`query ApprovalInstancePageInfo(
|
|
633
|
-
$view: ApprovalInstanceListView
|
|
634
|
-
$searchText: String
|
|
635
|
-
$state: [ApprovalInstanceState!]
|
|
636
|
-
$templateId: String
|
|
637
|
-
$page: Int
|
|
638
|
-
$pageSize: Int
|
|
639
|
-
) {
|
|
640
|
-
approvalInstancePageInfo(
|
|
641
|
-
view: $view
|
|
642
|
-
searchText: $searchText
|
|
643
|
-
state: $state
|
|
644
|
-
templateId: $templateId
|
|
645
|
-
page: $page
|
|
646
|
-
pageSize: $pageSize
|
|
647
|
-
) {
|
|
648
|
-
hasNextPage
|
|
649
|
-
hasPreviousPage
|
|
650
|
-
page
|
|
651
|
-
pageSize
|
|
652
|
-
totalCount
|
|
653
|
-
totalPages
|
|
654
|
-
}
|
|
655
|
-
}`,
|
|
656
|
-
variables,
|
|
657
|
-
),
|
|
658
|
-
]);
|
|
659
|
-
const pageInfo = pageInfoData.approvalInstancePageInfo;
|
|
660
|
-
|
|
661
|
-
return {
|
|
662
|
-
instances: pageData.approvalInstances.map(parseInstanceJson),
|
|
663
|
-
pageInfo,
|
|
664
|
-
totalCount: pageInfo.totalCount,
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
export async function readLaunchContext(
|
|
669
|
-
templateId: string,
|
|
670
|
-
): Promise<LaunchContext> {
|
|
671
|
-
const templateData = await requestGraphQl<LaunchTemplateQueryData>(
|
|
672
|
-
`query LaunchTemplate($id: String!) {
|
|
673
|
-
approvalTemplate(id: $id) {
|
|
674
|
-
currentVersionId
|
|
675
|
-
id
|
|
676
|
-
name
|
|
677
|
-
}
|
|
678
|
-
approvalTemplateVersions(templateId: $id) {
|
|
679
|
-
formDefinitionVersionId
|
|
680
|
-
id
|
|
681
|
-
status
|
|
682
|
-
version
|
|
683
|
-
}
|
|
684
|
-
launchableApprovalTemplates {
|
|
685
|
-
currentVersionId
|
|
686
|
-
id
|
|
687
|
-
name
|
|
688
|
-
updatedAt
|
|
689
|
-
}
|
|
690
|
-
}`,
|
|
691
|
-
{ id: templateId },
|
|
692
|
-
);
|
|
693
|
-
const templateVersion = templateData.approvalTemplateVersions.find(
|
|
694
|
-
(version) => version.id === templateData.approvalTemplate.currentVersionId,
|
|
695
|
-
);
|
|
696
|
-
|
|
697
|
-
if (!templateVersion || templateVersion.status !== 'PUBLISHED') {
|
|
698
|
-
throw new Error('模板尚未發布,無法發起簽核。');
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
if (!templateVersion.formDefinitionVersionId) {
|
|
702
|
-
throw new Error('模板尚未綁定表單版本,無法發起簽核。');
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
const launchableApprovalTemplates =
|
|
706
|
-
templateData.launchableApprovalTemplates ?? [templateData.approvalTemplate];
|
|
707
|
-
|
|
708
|
-
if (
|
|
709
|
-
!launchableApprovalTemplates.some((template) => template.id === templateId)
|
|
710
|
-
) {
|
|
711
|
-
throw new Error('目前登入者沒有此模板的發起權限。');
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
const formData = await requestGraphQl<LaunchFormVersionQueryData>(
|
|
715
|
-
`query LaunchFormVersion($id: String!) {
|
|
716
|
-
formDefinitionVersion(id: $id) {
|
|
717
|
-
id
|
|
718
|
-
schemaJson
|
|
719
|
-
uiSchemaJson
|
|
720
|
-
version
|
|
721
|
-
}
|
|
722
|
-
}`,
|
|
723
|
-
{ id: templateVersion.formDefinitionVersionId },
|
|
724
|
-
);
|
|
725
|
-
|
|
726
|
-
return {
|
|
727
|
-
formVersion: {
|
|
728
|
-
id: formData.formDefinitionVersion.id,
|
|
729
|
-
schema: JSON.parse(
|
|
730
|
-
formData.formDefinitionVersion.schemaJson,
|
|
731
|
-
) as FormDefinitionSchema,
|
|
732
|
-
uiSchema: JSON.parse(
|
|
733
|
-
formData.formDefinitionVersion.uiSchemaJson,
|
|
734
|
-
) as FormUiSchema,
|
|
735
|
-
version: formData.formDefinitionVersion.version,
|
|
736
|
-
},
|
|
737
|
-
template: templateData.approvalTemplate,
|
|
738
|
-
templateVersion,
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
export async function listLaunchableTemplates(): Promise<
|
|
743
|
-
readonly LaunchableTemplateRecord[]
|
|
744
|
-
> {
|
|
745
|
-
const templateData = await requestGraphQl<LaunchTemplatesQueryData>(
|
|
746
|
-
`query ApprovalTemplates {
|
|
747
|
-
launchableApprovalTemplates {
|
|
748
|
-
currentVersionId
|
|
749
|
-
id
|
|
750
|
-
name
|
|
751
|
-
updatedAt
|
|
752
|
-
}
|
|
753
|
-
}`,
|
|
754
|
-
);
|
|
755
|
-
const launchableApprovalTemplates =
|
|
756
|
-
templateData.launchableApprovalTemplates ??
|
|
757
|
-
templateData.approvalTemplates ??
|
|
758
|
-
[];
|
|
759
|
-
const versionLists = await Promise.all(
|
|
760
|
-
launchableApprovalTemplates.map((template) =>
|
|
761
|
-
requestGraphQl<LaunchTemplateVersionsQueryData>(
|
|
762
|
-
`query LaunchTemplateVersions($templateId: String!) {
|
|
763
|
-
approvalTemplateVersions(templateId: $templateId) {
|
|
764
|
-
formDefinitionVersionId
|
|
765
|
-
id
|
|
766
|
-
status
|
|
767
|
-
version
|
|
768
|
-
}
|
|
769
|
-
}`,
|
|
770
|
-
{ templateId: template.id },
|
|
771
|
-
),
|
|
772
|
-
),
|
|
773
|
-
);
|
|
774
|
-
|
|
775
|
-
return launchableApprovalTemplates.flatMap((template, index) => {
|
|
776
|
-
const currentVersion = versionLists[index]?.approvalTemplateVersions.find(
|
|
777
|
-
(version) => version.id === template.currentVersionId,
|
|
778
|
-
);
|
|
779
|
-
|
|
780
|
-
return currentVersion?.status === 'PUBLISHED' &&
|
|
781
|
-
currentVersion.formDefinitionVersionId
|
|
782
|
-
? [
|
|
783
|
-
{
|
|
784
|
-
currentVersionId: currentVersion.id,
|
|
785
|
-
formDefinitionVersionId: currentVersion.formDefinitionVersionId,
|
|
786
|
-
id: template.id,
|
|
787
|
-
name: template.name,
|
|
788
|
-
updatedAt: template.updatedAt,
|
|
789
|
-
version: currentVersion.version,
|
|
790
|
-
},
|
|
791
|
-
]
|
|
792
|
-
: [];
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
export async function readApprovalInstance(instanceId: string): Promise<{
|
|
797
|
-
readonly activityLogs: readonly ActivityLogRecord[];
|
|
798
|
-
readonly instance: ApprovalInstanceRecord;
|
|
799
|
-
readonly tasks: readonly TaskRecord[];
|
|
800
|
-
readonly workflowTokens: readonly WorkflowTokenRecord[];
|
|
801
|
-
}> {
|
|
802
|
-
const data = await requestGraphQl<ApprovalInstanceQueryData>(
|
|
803
|
-
`query ApprovalInstance($id: String!) {
|
|
804
|
-
approvalInstance(id: $id) {
|
|
805
|
-
completedAt
|
|
806
|
-
formDataJson
|
|
807
|
-
formDefinitionSnapshotJson
|
|
808
|
-
id
|
|
809
|
-
initiatorMemberId
|
|
810
|
-
startedAt
|
|
811
|
-
state
|
|
812
|
-
templateId
|
|
813
|
-
templateVersionId
|
|
814
|
-
title
|
|
815
|
-
workflowSnapshotJson
|
|
816
|
-
}
|
|
817
|
-
tasks(instanceId: $id) {
|
|
818
|
-
adhocDirectiveId
|
|
819
|
-
adhocOriginTaskId
|
|
820
|
-
adhocType
|
|
821
|
-
assigneeMemberId
|
|
822
|
-
assignmentType
|
|
823
|
-
candidateMemberIds
|
|
824
|
-
completedAt
|
|
825
|
-
createdAt
|
|
826
|
-
decisionPolicySnapshotJson
|
|
827
|
-
delegationChainJson
|
|
828
|
-
id
|
|
829
|
-
instanceId
|
|
830
|
-
isAdhoc
|
|
831
|
-
nodeId
|
|
832
|
-
openedAt
|
|
833
|
-
originalAssigneeMemberId
|
|
834
|
-
slaDueAt
|
|
835
|
-
status
|
|
836
|
-
tokenId
|
|
837
|
-
}
|
|
838
|
-
workflowTokens(instanceId: $id) {
|
|
839
|
-
consumedAt
|
|
840
|
-
createdAt
|
|
841
|
-
currentNodeId
|
|
842
|
-
id
|
|
843
|
-
instanceId
|
|
844
|
-
parentTokenId
|
|
845
|
-
status
|
|
846
|
-
}
|
|
847
|
-
activityLogs(instanceId: $id) {
|
|
848
|
-
actorMemberId
|
|
849
|
-
createdAt
|
|
850
|
-
eventType
|
|
851
|
-
id
|
|
852
|
-
nodeId
|
|
853
|
-
payloadJson
|
|
854
|
-
taskId
|
|
855
|
-
}
|
|
856
|
-
}`,
|
|
857
|
-
{ id: instanceId },
|
|
858
|
-
);
|
|
859
|
-
|
|
860
|
-
return {
|
|
861
|
-
activityLogs: data.activityLogs,
|
|
862
|
-
instance: parseInstanceJson(data.approvalInstance),
|
|
863
|
-
tasks: normalizeTaskRecords(data.tasks),
|
|
864
|
-
workflowTokens: data.workflowTokens,
|
|
865
|
-
};
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
export async function listInboxTasks(
|
|
869
|
-
assigneeMemberId: string,
|
|
870
|
-
): Promise<readonly TaskRecord[]> {
|
|
871
|
-
const data = await requestGraphQl<InboxTasksQueryData>(
|
|
872
|
-
`query InboxTasks($assigneeMemberId: String!) {
|
|
873
|
-
inboxTasks(assigneeMemberId: $assigneeMemberId) {
|
|
874
|
-
adhocDirectiveId
|
|
875
|
-
adhocOriginTaskId
|
|
876
|
-
adhocType
|
|
877
|
-
assigneeMemberId
|
|
878
|
-
assignmentType
|
|
879
|
-
candidateMemberIds
|
|
880
|
-
completedAt
|
|
881
|
-
createdAt
|
|
882
|
-
decisionPolicySnapshotJson
|
|
883
|
-
delegationChainJson
|
|
884
|
-
id
|
|
885
|
-
instanceId
|
|
886
|
-
isAdhoc
|
|
887
|
-
nodeId
|
|
888
|
-
openedAt
|
|
889
|
-
originalAssigneeMemberId
|
|
890
|
-
slaDueAt
|
|
891
|
-
status
|
|
892
|
-
tokenId
|
|
893
|
-
}
|
|
894
|
-
}`,
|
|
895
|
-
{ assigneeMemberId },
|
|
896
|
-
);
|
|
897
|
-
|
|
898
|
-
return normalizeTaskRecords(data.inboxTasks);
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
export async function listApprovalHistoryTasks(
|
|
902
|
-
assigneeMemberId: string,
|
|
903
|
-
): Promise<readonly TaskRecord[]> {
|
|
904
|
-
const data = await requestGraphQl<ApprovalHistoryTasksQueryData>(
|
|
905
|
-
`query ApprovalHistoryTasks($assigneeMemberId: String!) {
|
|
906
|
-
approvalHistoryTasks(assigneeMemberId: $assigneeMemberId) {
|
|
907
|
-
adhocDirectiveId
|
|
908
|
-
adhocOriginTaskId
|
|
909
|
-
adhocType
|
|
910
|
-
assigneeMemberId
|
|
911
|
-
assignmentType
|
|
912
|
-
candidateMemberIds
|
|
913
|
-
completedAt
|
|
914
|
-
createdAt
|
|
915
|
-
decisionPolicySnapshotJson
|
|
916
|
-
delegationChainJson
|
|
917
|
-
id
|
|
918
|
-
instanceId
|
|
919
|
-
isAdhoc
|
|
920
|
-
nodeId
|
|
921
|
-
openedAt
|
|
922
|
-
originalAssigneeMemberId
|
|
923
|
-
slaDueAt
|
|
924
|
-
status
|
|
925
|
-
tokenId
|
|
926
|
-
}
|
|
927
|
-
}`,
|
|
928
|
-
{ assigneeMemberId },
|
|
929
|
-
);
|
|
930
|
-
|
|
931
|
-
return normalizeTaskRecords(data.approvalHistoryTasks);
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
export async function readWorkflowDashboardSummary({
|
|
935
|
-
currentMemberId,
|
|
936
|
-
from,
|
|
937
|
-
to,
|
|
938
|
-
}: {
|
|
939
|
-
readonly currentMemberId: string;
|
|
940
|
-
readonly from: string | null;
|
|
941
|
-
readonly to: string | null;
|
|
942
|
-
}): Promise<WorkflowDashboardSummaryRecord> {
|
|
943
|
-
const [summaryData, notificationResult] = await Promise.all([
|
|
944
|
-
requestGraphQl<WorkflowDashboardSummaryQueryData>(
|
|
945
|
-
`query WorkflowDashboardSummary($from: DateTime, $to: DateTime) {
|
|
946
|
-
workflowDashboardSummary(from: $from, to: $to) {
|
|
947
|
-
activeInstanceCount
|
|
948
|
-
completedInstanceCount
|
|
949
|
-
overdueTaskCount
|
|
950
|
-
pendingTaskCount
|
|
951
|
-
rejectedInstanceCount
|
|
952
|
-
totalInstanceCount
|
|
953
|
-
}
|
|
954
|
-
}`,
|
|
955
|
-
{ from, to },
|
|
956
|
-
),
|
|
957
|
-
listNotifications({
|
|
958
|
-
includeRead: true,
|
|
959
|
-
page: 1,
|
|
960
|
-
pageSize: 1,
|
|
961
|
-
recipientMemberId: currentMemberId,
|
|
962
|
-
}),
|
|
963
|
-
]);
|
|
964
|
-
|
|
965
|
-
return {
|
|
966
|
-
...summaryData.workflowDashboardSummary,
|
|
967
|
-
unreadNotificationCount: notificationResult.unreadCount,
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
function normalizeTaskRecords(
|
|
972
|
-
tasks: readonly TaskRecord[],
|
|
973
|
-
): readonly TaskRecord[] {
|
|
974
|
-
return tasks.map((task) => ({
|
|
975
|
-
...task,
|
|
976
|
-
adhocDirectiveId: task.adhocDirectiveId ?? null,
|
|
977
|
-
adhocOriginTaskId: task.adhocOriginTaskId ?? null,
|
|
978
|
-
adhocType: task.adhocType ?? null,
|
|
979
|
-
assignmentType: task.assignmentType ?? 'DIRECT_MEMBER',
|
|
980
|
-
candidateMemberIds: task.candidateMemberIds ?? [],
|
|
981
|
-
decisionPolicySnapshotJson:
|
|
982
|
-
task.decisionPolicySnapshotJson ?? JSON.stringify({ type: 'SINGLE' }),
|
|
983
|
-
isAdhoc: task.isAdhoc ?? false,
|
|
984
|
-
}));
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
export async function listTaskDecisions(
|
|
988
|
-
taskId: string,
|
|
989
|
-
): Promise<readonly TaskDecisionRecord[]> {
|
|
990
|
-
const data = await requestGraphQl<TaskDecisionsQueryData>(
|
|
991
|
-
`query TaskDecisions($taskId: String!) {
|
|
992
|
-
taskDecisions(taskId: $taskId) {
|
|
993
|
-
action
|
|
994
|
-
comment
|
|
995
|
-
decidedAt
|
|
996
|
-
decidedByMemberId
|
|
997
|
-
id
|
|
998
|
-
returnToNodeId
|
|
999
|
-
signatureId
|
|
1000
|
-
taskId
|
|
1001
|
-
transferToMemberId
|
|
1002
|
-
}
|
|
1003
|
-
}`,
|
|
1004
|
-
{ taskId },
|
|
1005
|
-
);
|
|
1006
|
-
|
|
1007
|
-
return data.taskDecisions;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
export async function listAttachments(
|
|
1011
|
-
instanceId: string,
|
|
1012
|
-
): Promise<readonly AttachmentRecord[]> {
|
|
1013
|
-
const data = await requestGraphQl<AttachmentsQueryData>(
|
|
1014
|
-
`query InstanceAttachments($instanceId: String!) {
|
|
1015
|
-
attachments(instanceId: $instanceId) {
|
|
1016
|
-
checksumSha256
|
|
1017
|
-
createdAt
|
|
1018
|
-
filename
|
|
1019
|
-
formFieldPath
|
|
1020
|
-
id
|
|
1021
|
-
instanceId
|
|
1022
|
-
mimeType
|
|
1023
|
-
sizeBytes
|
|
1024
|
-
storageKey
|
|
1025
|
-
storageProvider
|
|
1026
|
-
taskId
|
|
1027
|
-
uploaderMemberId
|
|
1028
|
-
}
|
|
1029
|
-
}`,
|
|
1030
|
-
{ instanceId },
|
|
1031
|
-
);
|
|
1032
|
-
|
|
1033
|
-
return data.attachments ?? [];
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
export async function uploadAttachment({
|
|
1037
|
-
file,
|
|
1038
|
-
formFieldPath,
|
|
1039
|
-
}: {
|
|
1040
|
-
readonly file: File;
|
|
1041
|
-
readonly formFieldPath: string;
|
|
1042
|
-
}): Promise<AttachmentRecord> {
|
|
1043
|
-
const contentBase64 = await readFileBase64(file);
|
|
1044
|
-
const checksumSha256 = await hashFileSha256(file);
|
|
1045
|
-
const data = await requestGraphQl<UploadAttachmentMutationData>(
|
|
1046
|
-
`mutation UploadAttachment($input: UploadAttachmentInput!) {
|
|
1047
|
-
uploadAttachment(input: $input) {
|
|
1048
|
-
checksumSha256
|
|
1049
|
-
createdAt
|
|
1050
|
-
filename
|
|
1051
|
-
formFieldPath
|
|
1052
|
-
id
|
|
1053
|
-
instanceId
|
|
1054
|
-
mimeType
|
|
1055
|
-
sizeBytes
|
|
1056
|
-
storageKey
|
|
1057
|
-
storageProvider
|
|
1058
|
-
taskId
|
|
1059
|
-
uploaderMemberId
|
|
1060
|
-
}
|
|
1061
|
-
}`,
|
|
1062
|
-
{
|
|
1063
|
-
input: {
|
|
1064
|
-
checksumSha256,
|
|
1065
|
-
contentBase64,
|
|
1066
|
-
filename: file.name,
|
|
1067
|
-
formFieldPath,
|
|
1068
|
-
instanceId: null,
|
|
1069
|
-
mimeType: file.type || 'application/octet-stream',
|
|
1070
|
-
sizeBytes: file.size,
|
|
1071
|
-
taskId: null,
|
|
1072
|
-
},
|
|
1073
|
-
},
|
|
1074
|
-
);
|
|
1075
|
-
|
|
1076
|
-
return data.uploadAttachment;
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
export async function readAttachmentDownloadUrl({
|
|
1080
|
-
id,
|
|
1081
|
-
}: {
|
|
1082
|
-
readonly id: string;
|
|
1083
|
-
}): Promise<string> {
|
|
1084
|
-
const data = await requestGraphQl<AttachmentDownloadUrlQueryData>(
|
|
1085
|
-
`query AttachmentDownloadUrl($id: String!) {
|
|
1086
|
-
attachmentDownloadUrl(id: $id)
|
|
1087
|
-
}`,
|
|
1088
|
-
{ id },
|
|
1089
|
-
);
|
|
1090
|
-
|
|
1091
|
-
return data.attachmentDownloadUrl;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
export async function readAttachmentPreviewUrl({
|
|
1095
|
-
id,
|
|
1096
|
-
}: {
|
|
1097
|
-
readonly id: string;
|
|
1098
|
-
}): Promise<string> {
|
|
1099
|
-
const data = await requestGraphQl<AttachmentPreviewUrlQueryData>(
|
|
1100
|
-
`query AttachmentPreviewUrl($id: String!) {
|
|
1101
|
-
attachmentPreviewUrl(id: $id)
|
|
1102
|
-
}`,
|
|
1103
|
-
{ id },
|
|
1104
|
-
);
|
|
1105
|
-
|
|
1106
|
-
return data.attachmentPreviewUrl;
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
export async function readInstanceSignatures(instanceId: string): Promise<{
|
|
1110
|
-
readonly signatures: readonly SignatureRecord[];
|
|
1111
|
-
readonly verification: SignatureVerificationRecord;
|
|
1112
|
-
}> {
|
|
1113
|
-
const data = await requestGraphQl<SignaturesQueryData>(
|
|
1114
|
-
`query InstanceSignatures($instanceId: String!) {
|
|
1115
|
-
signatures(instanceId: $instanceId) {
|
|
1116
|
-
algorithm
|
|
1117
|
-
id
|
|
1118
|
-
instanceId
|
|
1119
|
-
keyVersion
|
|
1120
|
-
previousSignatureHash
|
|
1121
|
-
signature
|
|
1122
|
-
signedAt
|
|
1123
|
-
signedPayloadHash
|
|
1124
|
-
signedPayloadJson
|
|
1125
|
-
signerMemberId
|
|
1126
|
-
taskId
|
|
1127
|
-
timestampTokenBase64
|
|
1128
|
-
}
|
|
1129
|
-
verifySignatureChain(instanceId: $instanceId) {
|
|
1130
|
-
checkedCount
|
|
1131
|
-
errors
|
|
1132
|
-
instanceId
|
|
1133
|
-
valid
|
|
1134
|
-
}
|
|
1135
|
-
}`,
|
|
1136
|
-
{ instanceId },
|
|
1137
|
-
);
|
|
1138
|
-
|
|
1139
|
-
return {
|
|
1140
|
-
signatures: data.signatures ?? [],
|
|
1141
|
-
verification: data.verifySignatureChain ?? {
|
|
1142
|
-
checkedCount: 0,
|
|
1143
|
-
errors: [],
|
|
1144
|
-
instanceId,
|
|
1145
|
-
valid: true,
|
|
1146
|
-
},
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
export async function resolveMemberProfiles(
|
|
1151
|
-
memberIds: readonly string[],
|
|
1152
|
-
): Promise<readonly MemberProfileRecord[]> {
|
|
1153
|
-
if (memberIds.length === 0) {
|
|
1154
|
-
return [];
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
const data = await requestGraphQl<MembersQueryData>(
|
|
1158
|
-
`query InstanceMembers($memberIds: [String!]!) {
|
|
1159
|
-
members(memberIds: $memberIds) {
|
|
1160
|
-
email
|
|
1161
|
-
memberId
|
|
1162
|
-
name
|
|
1163
|
-
}
|
|
1164
|
-
}`,
|
|
1165
|
-
{ memberIds },
|
|
1166
|
-
);
|
|
1167
|
-
|
|
1168
|
-
return data.members;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
export async function searchMembers(
|
|
1172
|
-
searchText: string,
|
|
1173
|
-
): Promise<readonly MemberProfileRecord[]> {
|
|
1174
|
-
const data = await requestGraphQl<SearchMembersQueryData>(
|
|
1175
|
-
`query SearchMembers($searchText: String!) {
|
|
1176
|
-
searchMembers(searchText: $searchText) {
|
|
1177
|
-
email
|
|
1178
|
-
memberId
|
|
1179
|
-
name
|
|
1180
|
-
}
|
|
1181
|
-
}`,
|
|
1182
|
-
{ searchText },
|
|
1183
|
-
);
|
|
1184
|
-
|
|
1185
|
-
return data.searchMembers;
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
export async function listMemberDirectoryPage({
|
|
1189
|
-
page,
|
|
1190
|
-
pageSize,
|
|
1191
|
-
searchText = '',
|
|
1192
|
-
}: {
|
|
1193
|
-
readonly page: number;
|
|
1194
|
-
readonly pageSize: number;
|
|
1195
|
-
readonly searchText?: string;
|
|
1196
|
-
}): Promise<MemberDirectoryPage> {
|
|
1197
|
-
const data = await requestGraphQl<MemberDirectoryPageQueryData>(
|
|
1198
|
-
`query MemberDirectoryPage($page: Int, $pageSize: Int, $searchText: String!) {
|
|
1199
|
-
searchMembers(page: $page, pageSize: $pageSize, searchText: $searchText) {
|
|
1200
|
-
email
|
|
1201
|
-
memberId
|
|
1202
|
-
name
|
|
1203
|
-
}
|
|
1204
|
-
memberCount(searchText: $searchText)
|
|
1205
|
-
}`,
|
|
1206
|
-
{ page, pageSize, searchText },
|
|
1207
|
-
);
|
|
1208
|
-
|
|
1209
|
-
return {
|
|
1210
|
-
members: data.searchMembers,
|
|
1211
|
-
totalCount: data.memberCount,
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
export async function listDelegationRules({
|
|
1216
|
-
includeInactive = true,
|
|
1217
|
-
principalMemberId = null,
|
|
1218
|
-
}: {
|
|
1219
|
-
readonly includeInactive?: boolean;
|
|
1220
|
-
readonly principalMemberId?: string | null;
|
|
1221
|
-
} = {}): Promise<readonly DelegationRuleRecord[]> {
|
|
1222
|
-
const data = await requestGraphQl<DelegationRulesQueryData>(
|
|
1223
|
-
`query DelegationRules($includeInactive: Boolean, $principalMemberId: String) {
|
|
1224
|
-
delegationRules(
|
|
1225
|
-
includeInactive: $includeInactive
|
|
1226
|
-
principalMemberId: $principalMemberId
|
|
1227
|
-
) {
|
|
1228
|
-
agentMemberId
|
|
1229
|
-
createdAt
|
|
1230
|
-
createdByMemberId
|
|
1231
|
-
endAt
|
|
1232
|
-
id
|
|
1233
|
-
principalMemberId
|
|
1234
|
-
priority
|
|
1235
|
-
requiresConfirmation
|
|
1236
|
-
revokedAt
|
|
1237
|
-
revokedByMemberId
|
|
1238
|
-
scopeConditionCel
|
|
1239
|
-
scopeTemplateIds
|
|
1240
|
-
scopeType
|
|
1241
|
-
startAt
|
|
1242
|
-
status
|
|
1243
|
-
updatedAt
|
|
1244
|
-
}
|
|
1245
|
-
}`,
|
|
1246
|
-
{ includeInactive, principalMemberId },
|
|
1247
|
-
);
|
|
1248
|
-
|
|
1249
|
-
return data.delegationRules;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
export async function listDelegationRulesPage({
|
|
1253
|
-
agentMemberId = null,
|
|
1254
|
-
includeInactive = true,
|
|
1255
|
-
page = 1,
|
|
1256
|
-
pageSize = 10,
|
|
1257
|
-
principalMemberId = null,
|
|
1258
|
-
scopeType = null,
|
|
1259
|
-
status = null,
|
|
1260
|
-
}: {
|
|
1261
|
-
readonly agentMemberId?: string | null;
|
|
1262
|
-
readonly includeInactive?: boolean;
|
|
1263
|
-
readonly page?: number;
|
|
1264
|
-
readonly pageSize?: number;
|
|
1265
|
-
readonly principalMemberId?: string | null;
|
|
1266
|
-
readonly scopeType?: DelegationScopeType | null;
|
|
1267
|
-
readonly status?: DelegationRuleStatus | null;
|
|
1268
|
-
} = {}): Promise<{
|
|
1269
|
-
readonly rules: readonly DelegationRuleRecord[];
|
|
1270
|
-
readonly totalCount: number;
|
|
1271
|
-
}> {
|
|
1272
|
-
const data = await requestGraphQl<DelegationRulesPageQueryData>(
|
|
1273
|
-
`query DelegationRulesPage(
|
|
1274
|
-
$includeInactive: Boolean
|
|
1275
|
-
$page: Int
|
|
1276
|
-
$pageSize: Int
|
|
1277
|
-
$principalMemberId: String
|
|
1278
|
-
$agentMemberId: String
|
|
1279
|
-
$scopeType: DelegationScopeType
|
|
1280
|
-
$status: DelegationRuleStatus
|
|
1281
|
-
) {
|
|
1282
|
-
delegationRules(
|
|
1283
|
-
agentMemberId: $agentMemberId
|
|
1284
|
-
includeInactive: $includeInactive
|
|
1285
|
-
page: $page
|
|
1286
|
-
pageSize: $pageSize
|
|
1287
|
-
principalMemberId: $principalMemberId
|
|
1288
|
-
scopeType: $scopeType
|
|
1289
|
-
status: $status
|
|
1290
|
-
) {
|
|
1291
|
-
agentMemberId
|
|
1292
|
-
createdAt
|
|
1293
|
-
createdByMemberId
|
|
1294
|
-
endAt
|
|
1295
|
-
id
|
|
1296
|
-
principalMemberId
|
|
1297
|
-
priority
|
|
1298
|
-
requiresConfirmation
|
|
1299
|
-
revokedAt
|
|
1300
|
-
revokedByMemberId
|
|
1301
|
-
scopeConditionCel
|
|
1302
|
-
scopeTemplateIds
|
|
1303
|
-
scopeType
|
|
1304
|
-
startAt
|
|
1305
|
-
status
|
|
1306
|
-
updatedAt
|
|
1307
|
-
}
|
|
1308
|
-
delegationRuleCount(
|
|
1309
|
-
agentMemberId: $agentMemberId
|
|
1310
|
-
includeInactive: $includeInactive
|
|
1311
|
-
principalMemberId: $principalMemberId
|
|
1312
|
-
scopeType: $scopeType
|
|
1313
|
-
status: $status
|
|
1314
|
-
)
|
|
1315
|
-
}`,
|
|
1316
|
-
{
|
|
1317
|
-
agentMemberId,
|
|
1318
|
-
includeInactive,
|
|
1319
|
-
page,
|
|
1320
|
-
pageSize,
|
|
1321
|
-
principalMemberId,
|
|
1322
|
-
scopeType,
|
|
1323
|
-
status,
|
|
1324
|
-
},
|
|
1325
|
-
);
|
|
1326
|
-
|
|
1327
|
-
return {
|
|
1328
|
-
rules: data.delegationRules,
|
|
1329
|
-
totalCount: data.delegationRuleCount,
|
|
1330
|
-
};
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
export async function createDelegationRule(input: {
|
|
1334
|
-
readonly agentMemberId: string;
|
|
1335
|
-
readonly createdByMemberId: string | null;
|
|
1336
|
-
readonly endAt: string | null;
|
|
1337
|
-
readonly principalMemberId: string;
|
|
1338
|
-
readonly priority: number;
|
|
1339
|
-
readonly requiresConfirmation: boolean;
|
|
1340
|
-
readonly scopeConditionCel: string | null;
|
|
1341
|
-
readonly scopeTemplateIds: readonly string[];
|
|
1342
|
-
readonly scopeType: DelegationScopeType;
|
|
1343
|
-
readonly startAt: string | null;
|
|
1344
|
-
}): Promise<DelegationRuleRecord> {
|
|
1345
|
-
const data = await requestGraphQl<CreateDelegationRuleMutationData>(
|
|
1346
|
-
`mutation CreateDelegationRule($input: CreateDelegationRuleInput!) {
|
|
1347
|
-
createDelegationRule(input: $input) {
|
|
1348
|
-
agentMemberId
|
|
1349
|
-
createdAt
|
|
1350
|
-
createdByMemberId
|
|
1351
|
-
endAt
|
|
1352
|
-
id
|
|
1353
|
-
principalMemberId
|
|
1354
|
-
priority
|
|
1355
|
-
requiresConfirmation
|
|
1356
|
-
revokedAt
|
|
1357
|
-
revokedByMemberId
|
|
1358
|
-
scopeConditionCel
|
|
1359
|
-
scopeTemplateIds
|
|
1360
|
-
scopeType
|
|
1361
|
-
startAt
|
|
1362
|
-
status
|
|
1363
|
-
updatedAt
|
|
1364
|
-
}
|
|
1365
|
-
}`,
|
|
1366
|
-
{ input },
|
|
1367
|
-
);
|
|
1368
|
-
|
|
1369
|
-
return data.createDelegationRule;
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
export async function revokeDelegationRule({
|
|
1373
|
-
id,
|
|
1374
|
-
revokedByMemberId,
|
|
1375
|
-
}: {
|
|
1376
|
-
readonly id: string;
|
|
1377
|
-
readonly revokedByMemberId: string | null;
|
|
1378
|
-
}): Promise<DelegationRuleRecord> {
|
|
1379
|
-
const data = await requestGraphQl<RevokeDelegationRuleMutationData>(
|
|
1380
|
-
`mutation RevokeDelegationRule($id: String!, $revokedByMemberId: String) {
|
|
1381
|
-
revokeDelegationRule(id: $id, revokedByMemberId: $revokedByMemberId) {
|
|
1382
|
-
agentMemberId
|
|
1383
|
-
createdAt
|
|
1384
|
-
createdByMemberId
|
|
1385
|
-
endAt
|
|
1386
|
-
id
|
|
1387
|
-
principalMemberId
|
|
1388
|
-
priority
|
|
1389
|
-
requiresConfirmation
|
|
1390
|
-
revokedAt
|
|
1391
|
-
revokedByMemberId
|
|
1392
|
-
scopeConditionCel
|
|
1393
|
-
scopeTemplateIds
|
|
1394
|
-
scopeType
|
|
1395
|
-
startAt
|
|
1396
|
-
status
|
|
1397
|
-
updatedAt
|
|
1398
|
-
}
|
|
1399
|
-
}`,
|
|
1400
|
-
{ id, revokedByMemberId },
|
|
1401
|
-
);
|
|
1402
|
-
|
|
1403
|
-
return data.revokeDelegationRule;
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
export async function listNotifications({
|
|
1407
|
-
includeRead = true,
|
|
1408
|
-
page = 1,
|
|
1409
|
-
pageSize = 10,
|
|
1410
|
-
recipientMemberId,
|
|
1411
|
-
}: {
|
|
1412
|
-
readonly includeRead?: boolean;
|
|
1413
|
-
readonly page?: number;
|
|
1414
|
-
readonly pageSize?: number;
|
|
1415
|
-
readonly recipientMemberId: string;
|
|
1416
|
-
}): Promise<{
|
|
1417
|
-
readonly notifications: readonly NotificationRecord[];
|
|
1418
|
-
readonly totalCount: number;
|
|
1419
|
-
readonly unreadCount: number;
|
|
1420
|
-
}> {
|
|
1421
|
-
const data = await requestGraphQl<NotificationsQueryData>(
|
|
1422
|
-
`query Notifications(
|
|
1423
|
-
$recipientMemberId: String!
|
|
1424
|
-
$includeRead: Boolean
|
|
1425
|
-
$page: Int
|
|
1426
|
-
$pageSize: Int
|
|
1427
|
-
) {
|
|
1428
|
-
notifications(
|
|
1429
|
-
includeRead: $includeRead
|
|
1430
|
-
page: $page
|
|
1431
|
-
pageSize: $pageSize
|
|
1432
|
-
recipientMemberId: $recipientMemberId
|
|
1433
|
-
) {
|
|
1434
|
-
actionable
|
|
1435
|
-
attemptCount
|
|
1436
|
-
body
|
|
1437
|
-
channel
|
|
1438
|
-
createdAt
|
|
1439
|
-
deliveredAt
|
|
1440
|
-
deliveryError
|
|
1441
|
-
deliveryTarget
|
|
1442
|
-
id
|
|
1443
|
-
instanceId
|
|
1444
|
-
lastAttemptAt
|
|
1445
|
-
nextRetryAt
|
|
1446
|
-
payloadJson
|
|
1447
|
-
readAt
|
|
1448
|
-
recipientMemberId
|
|
1449
|
-
resolution
|
|
1450
|
-
resolvedAt
|
|
1451
|
-
sentAt
|
|
1452
|
-
status
|
|
1453
|
-
taskId
|
|
1454
|
-
title
|
|
1455
|
-
type
|
|
1456
|
-
}
|
|
1457
|
-
notificationCount(
|
|
1458
|
-
includeRead: $includeRead
|
|
1459
|
-
recipientMemberId: $recipientMemberId
|
|
1460
|
-
)
|
|
1461
|
-
unreadNotificationCount(recipientMemberId: $recipientMemberId)
|
|
1462
|
-
}`,
|
|
1463
|
-
{ includeRead, page, pageSize, recipientMemberId },
|
|
1464
|
-
);
|
|
1465
|
-
|
|
1466
|
-
return {
|
|
1467
|
-
notifications: data.notifications,
|
|
1468
|
-
totalCount: data.notificationCount,
|
|
1469
|
-
unreadCount: data.unreadNotificationCount,
|
|
1470
|
-
};
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
export async function readUnreadNotificationCount(
|
|
1474
|
-
recipientMemberId: string,
|
|
1475
|
-
): Promise<number> {
|
|
1476
|
-
const data = await requestGraphQl<{
|
|
1477
|
-
readonly unreadNotificationCount: number;
|
|
1478
|
-
}>(
|
|
1479
|
-
`query UnreadNotificationCount($recipientMemberId: String!) {
|
|
1480
|
-
unreadNotificationCount(recipientMemberId: $recipientMemberId)
|
|
1481
|
-
}`,
|
|
1482
|
-
{ recipientMemberId },
|
|
1483
|
-
);
|
|
1484
|
-
|
|
1485
|
-
return data.unreadNotificationCount;
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
export async function markNotificationRead({
|
|
1489
|
-
id,
|
|
1490
|
-
readerMemberId,
|
|
1491
|
-
}: {
|
|
1492
|
-
readonly id: string;
|
|
1493
|
-
readonly readerMemberId: string;
|
|
1494
|
-
}): Promise<Pick<NotificationRecord, 'id' | 'readAt' | 'status'>> {
|
|
1495
|
-
const data = await requestGraphQl<MarkNotificationReadMutationData>(
|
|
1496
|
-
`mutation MarkNotificationRead($id: String!, $readerMemberId: String) {
|
|
1497
|
-
markNotificationRead(id: $id, readerMemberId: $readerMemberId) {
|
|
1498
|
-
id
|
|
1499
|
-
readAt
|
|
1500
|
-
status
|
|
1501
|
-
}
|
|
1502
|
-
}`,
|
|
1503
|
-
{ id, readerMemberId },
|
|
1504
|
-
);
|
|
1505
|
-
|
|
1506
|
-
return data.markNotificationRead;
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
export async function markAllNotificationsRead({
|
|
1510
|
-
recipientMemberId,
|
|
1511
|
-
}: {
|
|
1512
|
-
readonly recipientMemberId: string;
|
|
1513
|
-
}): Promise<number> {
|
|
1514
|
-
const data = await requestGraphQl<{
|
|
1515
|
-
readonly markAllNotificationsRead: number;
|
|
1516
|
-
}>(
|
|
1517
|
-
`mutation MarkAllNotificationsRead($recipientMemberId: String) {
|
|
1518
|
-
markAllNotificationsRead(recipientMemberId: $recipientMemberId)
|
|
1519
|
-
}`,
|
|
1520
|
-
{ recipientMemberId },
|
|
1521
|
-
);
|
|
1522
|
-
|
|
1523
|
-
return data.markAllNotificationsRead;
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
|
-
export async function readNotificationPreference(
|
|
1527
|
-
memberId: string,
|
|
1528
|
-
): Promise<NotificationPreferenceRecord> {
|
|
1529
|
-
const data = await requestGraphQl<NotificationPreferenceQueryData>(
|
|
1530
|
-
`query NotificationPreference($memberId: String!) {
|
|
1531
|
-
notificationPreference(memberId: $memberId) {
|
|
1532
|
-
emailDigestMode
|
|
1533
|
-
emailEnabled
|
|
1534
|
-
inAppEnabled
|
|
1535
|
-
memberId
|
|
1536
|
-
quietHoursEnd
|
|
1537
|
-
quietHoursStart
|
|
1538
|
-
updatedAt
|
|
1539
|
-
}
|
|
1540
|
-
}`,
|
|
1541
|
-
{ memberId },
|
|
1542
|
-
);
|
|
1543
|
-
|
|
1544
|
-
return data.notificationPreference;
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
export async function updateNotificationPreference(input: {
|
|
1548
|
-
readonly emailDigestMode: NotificationDigestMode;
|
|
1549
|
-
readonly emailEnabled: boolean;
|
|
1550
|
-
readonly inAppEnabled: boolean;
|
|
1551
|
-
readonly memberId: string;
|
|
1552
|
-
readonly quietHoursEnd: string | null;
|
|
1553
|
-
readonly quietHoursStart: string | null;
|
|
1554
|
-
}): Promise<NotificationPreferenceRecord> {
|
|
1555
|
-
const data = await requestGraphQl<UpdateNotificationPreferenceMutationData>(
|
|
1556
|
-
`mutation UpdateNotificationPreference($input: UpdateNotificationPreferenceInput!) {
|
|
1557
|
-
updateNotificationPreference(input: $input) {
|
|
1558
|
-
emailDigestMode
|
|
1559
|
-
emailEnabled
|
|
1560
|
-
inAppEnabled
|
|
1561
|
-
memberId
|
|
1562
|
-
quietHoursEnd
|
|
1563
|
-
quietHoursStart
|
|
1564
|
-
updatedAt
|
|
1565
|
-
}
|
|
1566
|
-
}`,
|
|
1567
|
-
{ input },
|
|
1568
|
-
);
|
|
1569
|
-
|
|
1570
|
-
return data.updateNotificationPreference;
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
export async function submitApprovalInstance({
|
|
1574
|
-
formData,
|
|
1575
|
-
initiatorMemberId,
|
|
1576
|
-
templateId,
|
|
1577
|
-
title,
|
|
1578
|
-
}: {
|
|
1579
|
-
readonly formData: Readonly<Record<string, unknown>>;
|
|
1580
|
-
readonly initiatorMemberId: string;
|
|
1581
|
-
readonly templateId: string;
|
|
1582
|
-
readonly title: string | null;
|
|
1583
|
-
}): Promise<string> {
|
|
1584
|
-
const data = await requestGraphQl<SubmitApprovalInstanceMutationData>(
|
|
1585
|
-
`mutation SubmitApprovalInstance($input: SubmitApprovalInstanceInput!) {
|
|
1586
|
-
submitApprovalInstance(input: $input) {
|
|
1587
|
-
id
|
|
1588
|
-
}
|
|
1589
|
-
}`,
|
|
1590
|
-
{
|
|
1591
|
-
input: {
|
|
1592
|
-
formDataJson: JSON.stringify(formData),
|
|
1593
|
-
initiatorMemberId,
|
|
1594
|
-
initiatorMetadataSnapshotJson: null,
|
|
1595
|
-
templateId,
|
|
1596
|
-
title,
|
|
1597
|
-
},
|
|
1598
|
-
},
|
|
1599
|
-
);
|
|
1600
|
-
|
|
1601
|
-
return data.submitApprovalInstance.id;
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
export async function decideTask({
|
|
1605
|
-
action,
|
|
1606
|
-
comment,
|
|
1607
|
-
decidedByMemberId,
|
|
1608
|
-
returnToNodeId = null,
|
|
1609
|
-
taskId,
|
|
1610
|
-
transferToMemberId = null,
|
|
1611
|
-
}: {
|
|
1612
|
-
readonly action: TaskDecisionAction;
|
|
1613
|
-
readonly comment: string | null;
|
|
1614
|
-
readonly decidedByMemberId: string;
|
|
1615
|
-
readonly returnToNodeId?: string | null;
|
|
1616
|
-
readonly taskId: string;
|
|
1617
|
-
readonly transferToMemberId?: string | null;
|
|
1618
|
-
}): Promise<TaskDecisionRecord> {
|
|
1619
|
-
const data = await requestGraphQl<DecideTaskMutationData>(
|
|
1620
|
-
`mutation DecideTask($input: DecideTaskInput!) {
|
|
1621
|
-
decideTask(input: $input) {
|
|
1622
|
-
action
|
|
1623
|
-
comment
|
|
1624
|
-
decidedAt
|
|
1625
|
-
decidedByMemberId
|
|
1626
|
-
id
|
|
1627
|
-
returnToNodeId
|
|
1628
|
-
signatureId
|
|
1629
|
-
taskId
|
|
1630
|
-
transferToMemberId
|
|
1631
|
-
}
|
|
1632
|
-
}`,
|
|
1633
|
-
{
|
|
1634
|
-
input: {
|
|
1635
|
-
action,
|
|
1636
|
-
comment,
|
|
1637
|
-
decidedByMemberId,
|
|
1638
|
-
returnToNodeId,
|
|
1639
|
-
taskId,
|
|
1640
|
-
transferToMemberId,
|
|
1641
|
-
},
|
|
1642
|
-
},
|
|
1643
|
-
);
|
|
1644
|
-
|
|
1645
|
-
return data.decideTask;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
export async function cancelApprovalInstance({
|
|
1649
|
-
cancelledByMemberId,
|
|
1650
|
-
comment,
|
|
1651
|
-
instanceId,
|
|
1652
|
-
}: {
|
|
1653
|
-
readonly cancelledByMemberId: string;
|
|
1654
|
-
readonly comment: string | null;
|
|
1655
|
-
readonly instanceId: string;
|
|
1656
|
-
}): Promise<void> {
|
|
1657
|
-
await requestGraphQl<CancelApprovalInstanceMutationData>(
|
|
1658
|
-
`mutation CancelApprovalInstance($input: CancelApprovalInstanceInput!) {
|
|
1659
|
-
cancelApprovalInstance(input: $input) {
|
|
1660
|
-
id
|
|
1661
|
-
state
|
|
1662
|
-
}
|
|
1663
|
-
}`,
|
|
1664
|
-
{
|
|
1665
|
-
input: {
|
|
1666
|
-
cancelledByMemberId,
|
|
1667
|
-
comment,
|
|
1668
|
-
instanceId,
|
|
1669
|
-
},
|
|
1670
|
-
},
|
|
1671
|
-
);
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
export async function resubmitApprovalInstance({
|
|
1675
|
-
formData,
|
|
1676
|
-
initiatorMemberId,
|
|
1677
|
-
instanceId,
|
|
1678
|
-
title,
|
|
1679
|
-
}: {
|
|
1680
|
-
readonly formData: Readonly<Record<string, unknown>>;
|
|
1681
|
-
readonly initiatorMemberId: string;
|
|
1682
|
-
readonly instanceId: string;
|
|
1683
|
-
readonly title: string | null;
|
|
1684
|
-
}): Promise<void> {
|
|
1685
|
-
await requestGraphQl<ResubmitApprovalInstanceMutationData>(
|
|
1686
|
-
`mutation ResubmitApprovalInstance($input: ResubmitApprovalInstanceInput!) {
|
|
1687
|
-
resubmitApprovalInstance(input: $input) {
|
|
1688
|
-
id
|
|
1689
|
-
state
|
|
1690
|
-
}
|
|
1691
|
-
}`,
|
|
1692
|
-
{
|
|
1693
|
-
input: {
|
|
1694
|
-
formDataJson: JSON.stringify(formData),
|
|
1695
|
-
initiatorMemberId,
|
|
1696
|
-
instanceId,
|
|
1697
|
-
title,
|
|
1698
|
-
},
|
|
1699
|
-
},
|
|
1700
|
-
);
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
const ADHOC_DIRECTIVE_FIELDS = `
|
|
1704
|
-
channels
|
|
1705
|
-
comment
|
|
1706
|
-
consumedAt
|
|
1707
|
-
createdAt
|
|
1708
|
-
createdByMemberId
|
|
1709
|
-
id
|
|
1710
|
-
instanceId
|
|
1711
|
-
onReject
|
|
1712
|
-
originNodeId
|
|
1713
|
-
originTaskId
|
|
1714
|
-
status
|
|
1715
|
-
targetKind
|
|
1716
|
-
targetValueJson
|
|
1717
|
-
type
|
|
1718
|
-
`;
|
|
1719
|
-
|
|
1720
|
-
const ADHOC_TASK_FIELDS = `
|
|
1721
|
-
adhocDirectiveId
|
|
1722
|
-
adhocOriginTaskId
|
|
1723
|
-
adhocType
|
|
1724
|
-
assigneeMemberId
|
|
1725
|
-
assignmentType
|
|
1726
|
-
candidateMemberIds
|
|
1727
|
-
completedAt
|
|
1728
|
-
createdAt
|
|
1729
|
-
decisionPolicySnapshotJson
|
|
1730
|
-
delegationChainJson
|
|
1731
|
-
id
|
|
1732
|
-
instanceId
|
|
1733
|
-
isAdhoc
|
|
1734
|
-
nodeId
|
|
1735
|
-
openedAt
|
|
1736
|
-
originalAssigneeMemberId
|
|
1737
|
-
slaDueAt
|
|
1738
|
-
status
|
|
1739
|
-
tokenId
|
|
1740
|
-
`;
|
|
1741
|
-
|
|
1742
|
-
interface RequestAdhocCountersignMutationData {
|
|
1743
|
-
readonly requestAdhocCountersign: AdhocDirectiveRecord;
|
|
1744
|
-
}
|
|
1745
|
-
|
|
1746
|
-
interface RequestAdhocPreApprovalMutationData {
|
|
1747
|
-
readonly requestAdhocPreApproval: TaskRecord;
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
interface ConfigureAdhocStageNotificationMutationData {
|
|
1751
|
-
readonly configureAdhocStageNotification: AdhocDirectiveRecord;
|
|
1752
|
-
}
|
|
1753
|
-
|
|
1754
|
-
interface ConfigureAdhocCompletionNotificationMutationData {
|
|
1755
|
-
readonly configureAdhocCompletionNotification: AdhocDirectiveRecord;
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
interface CancelAdhocDirectiveMutationData {
|
|
1759
|
-
readonly cancelAdhocDirective: AdhocDirectiveRecord;
|
|
1760
|
-
}
|
|
1761
|
-
|
|
1762
|
-
interface AdhocDirectivesQueryData {
|
|
1763
|
-
readonly adhocDirectives: readonly AdhocDirectiveRecord[];
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
function buildAdhocTargetInput(
|
|
1767
|
-
target: AdhocTargetOptions,
|
|
1768
|
-
): Readonly<Record<string, unknown>> {
|
|
1769
|
-
return {
|
|
1770
|
-
includeDescendants: target.includeDescendants ?? null,
|
|
1771
|
-
kind: target.kind,
|
|
1772
|
-
memberIds: target.memberIds ? [...target.memberIds] : null,
|
|
1773
|
-
orgUnitId: target.orgUnitId ?? null,
|
|
1774
|
-
positionId: target.positionId ?? null,
|
|
1775
|
-
webhookHeadersJson: target.webhookHeaders
|
|
1776
|
-
? JSON.stringify(target.webhookHeaders)
|
|
1777
|
-
: null,
|
|
1778
|
-
webhookUrl: target.webhookUrl ?? null,
|
|
1779
|
-
};
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
/**
|
|
1783
|
-
* Ad-hoc countersign (臨時會簽): asks the given target to co-sign the NEXT
|
|
1784
|
-
* stage of this instance. When the next user task is created, a parallel
|
|
1785
|
-
* ad-hoc task is spawned for the target, and the flow only advances past
|
|
1786
|
-
* that stage once BOTH the original task and every countersign task are
|
|
1787
|
-
* approved. A countersigner's rejection rejects the whole instance.
|
|
1788
|
-
*
|
|
1789
|
-
* Only the current task's assignee/candidate may call this, and only on
|
|
1790
|
-
* nodes whose template sets `allowAddSigner: true`. Returns the recorded
|
|
1791
|
-
* directive (`PENDING` until the next user task consumes it; withdrawable
|
|
1792
|
-
* via {@link cancelAdhocDirective} while pending). Never alters the
|
|
1793
|
-
* workflow template.
|
|
1794
|
-
*/
|
|
1795
|
-
export async function requestAdhocCountersign({
|
|
1796
|
-
comment = null,
|
|
1797
|
-
target,
|
|
1798
|
-
taskId,
|
|
1799
|
-
}: {
|
|
1800
|
-
readonly comment?: string | null;
|
|
1801
|
-
readonly target: AdhocTargetOptions;
|
|
1802
|
-
readonly taskId: string;
|
|
1803
|
-
}): Promise<AdhocDirectiveRecord> {
|
|
1804
|
-
const data = await requestGraphQl<RequestAdhocCountersignMutationData>(
|
|
1805
|
-
`mutation RequestAdhocCountersign($taskId: ID!, $target: AdhocTargetInput!, $comment: String) {
|
|
1806
|
-
requestAdhocCountersign(taskId: $taskId, target: $target, comment: $comment) {
|
|
1807
|
-
${ADHOC_DIRECTIVE_FIELDS}
|
|
1808
|
-
}
|
|
1809
|
-
}`,
|
|
1810
|
-
{ comment, target: buildAdhocTargetInput(target), taskId },
|
|
1811
|
-
);
|
|
1812
|
-
|
|
1813
|
-
return data.requestAdhocCountersign;
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
/**
|
|
1817
|
-
* Ad-hoc pre-approval (臨時加簽): immediately spawns a blocking ad-hoc task
|
|
1818
|
-
* for the given target on the CURRENT stage. Even after the original
|
|
1819
|
-
* approver approves, the flow stays on this stage until the pre-approver
|
|
1820
|
-
* also approves. `onReject` decides what happens when the pre-approver
|
|
1821
|
-
* rejects: `REJECT_INSTANCE` rejects the whole instance;
|
|
1822
|
-
* `RETURN_TO_ORIGIN` hands the decision back to the original approver
|
|
1823
|
-
* (re-opening their task if they had already approved).
|
|
1824
|
-
*
|
|
1825
|
-
* Only the current task's assignee/candidate may call this, and only on
|
|
1826
|
-
* nodes whose template sets `allowAddSigner: true`. Returns the spawned
|
|
1827
|
-
* ad-hoc task. Never alters the workflow template.
|
|
1828
|
-
*/
|
|
1829
|
-
export async function requestAdhocPreApproval({
|
|
1830
|
-
comment = null,
|
|
1831
|
-
onReject,
|
|
1832
|
-
target,
|
|
1833
|
-
taskId,
|
|
1834
|
-
}: {
|
|
1835
|
-
readonly comment?: string | null;
|
|
1836
|
-
readonly onReject: AdhocPreApprovalRejectBehavior;
|
|
1837
|
-
readonly target: AdhocTargetOptions;
|
|
1838
|
-
readonly taskId: string;
|
|
1839
|
-
}): Promise<TaskRecord> {
|
|
1840
|
-
const data = await requestGraphQl<RequestAdhocPreApprovalMutationData>(
|
|
1841
|
-
`mutation RequestAdhocPreApproval($taskId: ID!, $target: AdhocTargetInput!, $onReject: AdhocPreApprovalRejectBehavior!, $comment: String) {
|
|
1842
|
-
requestAdhocPreApproval(taskId: $taskId, target: $target, onReject: $onReject, comment: $comment) {
|
|
1843
|
-
${ADHOC_TASK_FIELDS}
|
|
1844
|
-
}
|
|
1845
|
-
}`,
|
|
1846
|
-
{
|
|
1847
|
-
comment,
|
|
1848
|
-
onReject,
|
|
1849
|
-
target: buildAdhocTargetInput(target),
|
|
1850
|
-
taskId,
|
|
1851
|
-
},
|
|
1852
|
-
);
|
|
1853
|
-
|
|
1854
|
-
return data.requestAdhocPreApproval;
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
/**
|
|
1858
|
-
* Ad-hoc stage notification (臨時階段通知): notifies the target once the
|
|
1859
|
-
* CURRENT stage ends — regardless of outcome (approved, rejected, or
|
|
1860
|
-
* returned). Targets may be members, a position, an org unit, or a webhook
|
|
1861
|
-
* URL. `channels` defaults to in-app notification.
|
|
1862
|
-
*
|
|
1863
|
-
* Available to the current task's assignee/candidate on any user-task node
|
|
1864
|
-
* (no `allowAddSigner` requirement). Returns the recorded directive
|
|
1865
|
-
* (withdrawable via {@link cancelAdhocDirective} while pending). Never
|
|
1866
|
-
* alters the workflow template.
|
|
1867
|
-
*/
|
|
1868
|
-
export async function configureAdhocStageNotification({
|
|
1869
|
-
channels = null,
|
|
1870
|
-
target,
|
|
1871
|
-
taskId,
|
|
1872
|
-
}: {
|
|
1873
|
-
readonly channels?: readonly NotificationChannel[] | null;
|
|
1874
|
-
readonly target: AdhocTargetOptions;
|
|
1875
|
-
readonly taskId: string;
|
|
1876
|
-
}): Promise<AdhocDirectiveRecord> {
|
|
1877
|
-
const data =
|
|
1878
|
-
await requestGraphQl<ConfigureAdhocStageNotificationMutationData>(
|
|
1879
|
-
`mutation ConfigureAdhocStageNotification($taskId: ID!, $input: AdhocNotificationInput!) {
|
|
1880
|
-
configureAdhocStageNotification(taskId: $taskId, input: $input) {
|
|
1881
|
-
${ADHOC_DIRECTIVE_FIELDS}
|
|
1882
|
-
}
|
|
1883
|
-
}`,
|
|
1884
|
-
{
|
|
1885
|
-
input: {
|
|
1886
|
-
channels: channels ? [...channels] : null,
|
|
1887
|
-
target: buildAdhocTargetInput(target),
|
|
1888
|
-
},
|
|
1889
|
-
taskId,
|
|
1890
|
-
},
|
|
1891
|
-
);
|
|
1892
|
-
|
|
1893
|
-
return data.configureAdhocStageNotification;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
/**
|
|
1897
|
-
* Ad-hoc completion notification (臨時完成通知): notifies the target once
|
|
1898
|
-
* the WHOLE instance reaches a terminal state (`APPROVED`, `REJECTED`, or
|
|
1899
|
-
* `CANCELLED`). Targets may be members, a position, an org unit, or a
|
|
1900
|
-
* webhook URL. `channels` defaults to in-app notification.
|
|
1901
|
-
*
|
|
1902
|
-
* Available to the current task's assignee/candidate on any user-task node
|
|
1903
|
-
* (no `allowAddSigner` requirement). Returns the recorded directive
|
|
1904
|
-
* (withdrawable via {@link cancelAdhocDirective} while pending). Never
|
|
1905
|
-
* alters the workflow template.
|
|
1906
|
-
*/
|
|
1907
|
-
export async function configureAdhocCompletionNotification({
|
|
1908
|
-
channels = null,
|
|
1909
|
-
target,
|
|
1910
|
-
taskId,
|
|
1911
|
-
}: {
|
|
1912
|
-
readonly channels?: readonly NotificationChannel[] | null;
|
|
1913
|
-
readonly target: AdhocTargetOptions;
|
|
1914
|
-
readonly taskId: string;
|
|
1915
|
-
}): Promise<AdhocDirectiveRecord> {
|
|
1916
|
-
const data =
|
|
1917
|
-
await requestGraphQl<ConfigureAdhocCompletionNotificationMutationData>(
|
|
1918
|
-
`mutation ConfigureAdhocCompletionNotification($taskId: ID!, $input: AdhocNotificationInput!) {
|
|
1919
|
-
configureAdhocCompletionNotification(taskId: $taskId, input: $input) {
|
|
1920
|
-
${ADHOC_DIRECTIVE_FIELDS}
|
|
1921
|
-
}
|
|
1922
|
-
}`,
|
|
1923
|
-
{
|
|
1924
|
-
input: {
|
|
1925
|
-
channels: channels ? [...channels] : null,
|
|
1926
|
-
target: buildAdhocTargetInput(target),
|
|
1927
|
-
},
|
|
1928
|
-
taskId,
|
|
1929
|
-
},
|
|
1930
|
-
);
|
|
1931
|
-
|
|
1932
|
-
return data.configureAdhocCompletionNotification;
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
/**
|
|
1936
|
-
* Withdraws a still-`PENDING` ad-hoc directive (countersign / stage-notify /
|
|
1937
|
-
* completion-notify) before it takes effect. Only the directive's creator
|
|
1938
|
-
* may withdraw it; pre-approval directives are consumed immediately on
|
|
1939
|
-
* creation and therefore cannot be withdrawn.
|
|
1940
|
-
*/
|
|
1941
|
-
export async function cancelAdhocDirective(
|
|
1942
|
-
directiveId: string,
|
|
1943
|
-
): Promise<AdhocDirectiveRecord> {
|
|
1944
|
-
const data = await requestGraphQl<CancelAdhocDirectiveMutationData>(
|
|
1945
|
-
`mutation CancelAdhocDirective($directiveId: ID!) {
|
|
1946
|
-
cancelAdhocDirective(directiveId: $directiveId) {
|
|
1947
|
-
${ADHOC_DIRECTIVE_FIELDS}
|
|
1948
|
-
}
|
|
1949
|
-
}`,
|
|
1950
|
-
{ directiveId },
|
|
1951
|
-
);
|
|
1952
|
-
|
|
1953
|
-
return data.cancelAdhocDirective;
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
/**
|
|
1957
|
-
* Lists every ad-hoc directive recorded on one approval instance, ordered by
|
|
1958
|
-
* creation time. Use the `status` field to find directives that are still
|
|
1959
|
-
* pending (withdrawable) versus already consumed or cancelled.
|
|
1960
|
-
*/
|
|
1961
|
-
export async function listAdhocDirectives(
|
|
1962
|
-
instanceId: string,
|
|
1963
|
-
): Promise<readonly AdhocDirectiveRecord[]> {
|
|
1964
|
-
const data = await requestGraphQl<AdhocDirectivesQueryData>(
|
|
1965
|
-
`query AdhocDirectives($instanceId: String!) {
|
|
1966
|
-
adhocDirectives(instanceId: $instanceId) {
|
|
1967
|
-
${ADHOC_DIRECTIVE_FIELDS}
|
|
1968
|
-
}
|
|
1969
|
-
}`,
|
|
1970
|
-
{ instanceId },
|
|
1971
|
-
);
|
|
1972
|
-
|
|
1973
|
-
// Tolerate hosts (and test mocks) whose GraphQL layer does not answer the
|
|
1974
|
-
// adhocDirectives query yet.
|
|
1975
|
-
return data.adhocDirectives ?? [];
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
|
-
export function readApprovalInstanceCaseTitle(
|
|
1979
|
-
instance: ApprovalInstanceRecord,
|
|
1980
|
-
): string {
|
|
1981
|
-
return readFormDataCaseTitle({
|
|
1982
|
-
fallbackTitle: instance.title || instance.id,
|
|
1983
|
-
formData: instance.formData,
|
|
1984
|
-
schema: instance.formDefinitionSnapshot.schema ?? null,
|
|
1985
|
-
uiSchema: instance.formDefinitionSnapshot.uiSchema ?? null,
|
|
1986
|
-
});
|
|
1987
|
-
}
|
|
1988
|
-
|
|
1989
|
-
export function readFormDataCaseTitle({
|
|
1990
|
-
fallbackTitle,
|
|
1991
|
-
formData,
|
|
1992
|
-
schema,
|
|
1993
|
-
uiSchema,
|
|
1994
|
-
}: {
|
|
1995
|
-
readonly fallbackTitle: string;
|
|
1996
|
-
readonly formData: WorkflowFormData;
|
|
1997
|
-
readonly schema: FormDefinitionSchema | null;
|
|
1998
|
-
readonly uiSchema: FormUiSchema | null;
|
|
1999
|
-
}): string {
|
|
2000
|
-
const firstField = readFirstCaseTitleField(schema, uiSchema);
|
|
2001
|
-
|
|
2002
|
-
if (!firstField) {
|
|
2003
|
-
return fallbackTitle;
|
|
2004
|
-
}
|
|
2005
|
-
|
|
2006
|
-
const valueLabel = readFieldValueLabel(
|
|
2007
|
-
firstField,
|
|
2008
|
-
formData[firstField.fieldKey],
|
|
2009
|
-
);
|
|
2010
|
-
|
|
2011
|
-
return valueLabel ? `${firstField.label}:${valueLabel}` : fallbackTitle;
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
function parseInstanceJson(record: InstanceJsonRecord): ApprovalInstanceRecord {
|
|
2015
|
-
return {
|
|
2016
|
-
...record,
|
|
2017
|
-
formData: JSON.parse(record.formDataJson) as WorkflowFormData,
|
|
2018
|
-
formDefinitionSnapshot: JSON.parse(
|
|
2019
|
-
record.formDefinitionSnapshotJson,
|
|
2020
|
-
) as FormDefinitionSnapshot,
|
|
2021
|
-
workflowSnapshot: JSON.parse(
|
|
2022
|
-
record.workflowSnapshotJson,
|
|
2023
|
-
) as WorkflowDefinition,
|
|
2024
|
-
};
|
|
2025
|
-
}
|
|
2026
|
-
|
|
2027
|
-
async function readFileBase64(file: File): Promise<string> {
|
|
2028
|
-
const buffer = await file.arrayBuffer();
|
|
2029
|
-
const bytes = new Uint8Array(buffer);
|
|
2030
|
-
const chunkSize = 0x8000;
|
|
2031
|
-
const chunks = Array.from(
|
|
2032
|
-
{ length: Math.ceil(bytes.length / chunkSize) },
|
|
2033
|
-
(_, index): string =>
|
|
2034
|
-
String.fromCharCode(
|
|
2035
|
-
...bytes.slice(index * chunkSize, (index + 1) * chunkSize),
|
|
2036
|
-
),
|
|
2037
|
-
);
|
|
2038
|
-
|
|
2039
|
-
return btoa(chunks.join(''));
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
async function hashFileSha256(file: File): Promise<string> {
|
|
2043
|
-
const digest = await crypto.subtle.digest(
|
|
2044
|
-
'SHA-256',
|
|
2045
|
-
await file.arrayBuffer(),
|
|
2046
|
-
);
|
|
2047
|
-
const bytes = Array.from(new Uint8Array(digest));
|
|
2048
|
-
|
|
2049
|
-
return bytes.map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
function readFirstCaseTitleField(
|
|
2053
|
-
schema: FormDefinitionSchema | null,
|
|
2054
|
-
uiSchema: FormUiSchema | null,
|
|
2055
|
-
): FormFieldDefinition | null {
|
|
2056
|
-
if (!schema?.fields.length) {
|
|
2057
|
-
return null;
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
const fieldsByKey = new Map(
|
|
2061
|
-
schema.fields.map((field) => [field.fieldKey, field]),
|
|
2062
|
-
);
|
|
2063
|
-
const firstLayoutField = uiSchema?.layout
|
|
2064
|
-
.map((layoutItem) => fieldsByKey.get(layoutItem.fieldKey) ?? null)
|
|
2065
|
-
.find((field): field is FormFieldDefinition => Boolean(field));
|
|
2066
|
-
|
|
2067
|
-
return firstLayoutField ?? schema.fields[0] ?? null;
|
|
2068
|
-
}
|
|
2069
|
-
|
|
2070
|
-
function readFieldValueLabel(
|
|
2071
|
-
field: FormFieldDefinition,
|
|
2072
|
-
value: FormFieldValue | undefined,
|
|
2073
|
-
): string | null {
|
|
2074
|
-
if (typeof value === 'undefined' || value === null) {
|
|
2075
|
-
return null;
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
if (Array.isArray(value)) {
|
|
2079
|
-
return readArrayFieldValueLabel(field, value);
|
|
2080
|
-
}
|
|
2081
|
-
|
|
2082
|
-
if (field.type === 'boolean') {
|
|
2083
|
-
return value === true ? '是' : '否';
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
if (isSelectFieldDefinition(field) && typeof value === 'string') {
|
|
2087
|
-
return readSelectOptionLabel(field, value);
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
const valueLabel = String(value).trim();
|
|
2091
|
-
|
|
2092
|
-
return valueLabel || null;
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
function readArrayFieldValueLabel(
|
|
2096
|
-
field: FormFieldDefinition,
|
|
2097
|
-
value: readonly string[],
|
|
2098
|
-
): string | null {
|
|
2099
|
-
const labels = isSelectFieldDefinition(field)
|
|
2100
|
-
? value.map((item) => readSelectOptionLabel(field, item))
|
|
2101
|
-
: value;
|
|
2102
|
-
const label = labels.filter((item) => item.trim()).join('、');
|
|
2103
|
-
|
|
2104
|
-
return label || null;
|
|
2105
|
-
}
|
|
2106
|
-
|
|
2107
|
-
function readSelectOptionLabel(
|
|
2108
|
-
field: SelectFieldDefinition,
|
|
2109
|
-
value: string,
|
|
2110
|
-
): string {
|
|
2111
|
-
return (
|
|
2112
|
-
field.options.find((option) => option.value === value)?.label ?? value
|
|
2113
|
-
).trim();
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
function isSelectFieldDefinition(
|
|
2117
|
-
field: FormFieldDefinition,
|
|
2118
|
-
): field is SelectFieldDefinition {
|
|
2119
|
-
return (
|
|
2120
|
-
field.type === 'select' ||
|
|
2121
|
-
field.type === 'radio' ||
|
|
2122
|
-
field.type === 'checkbox'
|
|
2123
|
-
);
|
|
2124
|
-
}
|