@simitgroup/simpleapp-generator 1.1.11 → 1.1.12
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/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +3 -2
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +5 -2
- package/dist/generate.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/framework.ts +3 -2
- package/src/generate.ts +7 -3
- package/src/index.ts +1 -1
- package/templates/basic/nest/controller.ts.eta +19 -17
- package/templates/basic/nest/service.ts.eta +39 -2
- package/templates/basic/nuxt/pages.form.vue.eta +117 -84
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +7 -4
- package/templates/nest/.env._eta +7 -1
- package/templates/nest/remoteapi/cloudapi.yaml.eta +768 -0
- package/templates/nest/src/app.module.ts.eta +2 -2
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +0 -19
- package/templates/nest/src/simpleapp/services/autoinc.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/services/branch.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/services/docno.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/services/org.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/services/perm.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/services/tenant.service.ts.eta +1 -1
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +6 -3
- package/templates/nest/src/simpleapp/workflow/appDelegate.ts.eta +194 -0
- package/templates/nest/src/simpleapp/workflow/bpmn/suspendcustomer.bpmn.eta +53 -0
- package/templates/nest/src/simpleapp/workflow/configuration.ts.eta +46 -0
- package/templates/nest/src/simpleapp/workflow/delegates/customer.ts._eta +8 -0
- package/templates/nest/src/simpleapp/workflow/delegates/hello.ts._eta +5 -0
- package/templates/nest/src/simpleapp/workflow/delegates/index.ts._eta +5 -0
- package/templates/nest/src/simpleapp/workflow/delegates/invoice.delegates.ts._eta +9 -0
- package/templates/nest/src/simpleapp/workflow/delegates/usertask.ts._eta +3 -0
- package/templates/nest/src/simpleapp/workflow/formschema/SimpleApproveReject.ts.eta +8 -0
- package/templates/nest/src/simpleapp/workflow/formschema/index.ts.eta +1 -0
- package/templates/nest/src/simpleapp/workflow/workflow.apischema.ts.eta +135 -0
- package/templates/nest/src/simpleapp/workflow/workflow.controller.ts.eta +407 -0
- package/templates/nest/src/simpleapp/workflow/workflow.service.ts.eta +430 -0
- package/templates/nest/src/simpleapp/workflow/workflow.type.ts.eta +56 -0
- package/templates/nuxt/assets/primevue/passthrough.ts._eta +2 -1
- package/templates/nuxt/components/event/EventDecision.vue.eta +1 -1
- package/templates/nuxt/components/event/EventNotification.vue.eta +1 -1
- package/templates/nuxt/components/header/HeaderBar.vue.eta +3 -1
- package/templates/nuxt/components/header/button/task/HeaderButtonTaskItem.vue.eta +21 -0
- package/templates/nuxt/components/header/button/task/HeaderButtonTaskList.vue.eta +126 -0
- package/templates/nuxt/components/simpleApp/SimpleAppJsonSchemaForm.vue.eta +133 -0
- package/templates/nuxt/composables/getOpenApi.generate.ts.eta +27 -8
- package/templates/nuxt/composables/workflow.generate.ts.eta +16 -0
- package/templates/nuxt/lang/df.ts.eta +2 -0
- package/templates/nuxt/pages/[xorg]/index.vue._eta +5 -3
- package/templates/nuxt/types/index.ts.eta +2 -1
- package/templates/nuxt/types/schema.ts.eta +1 -0
- package/templates/nuxt/types/workflow.ts.eta +20 -0
- package/templates/project/jsonschemas/customer.json._eta +13 -9
- package/templates/project/jsonschemas/invoice.json._eta +10 -6
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bpmn microservices
|
|
3
|
+
* require endpoints
|
|
4
|
+
* 3. get list of proccess
|
|
5
|
+
*
|
|
6
|
+
* user method
|
|
7
|
+
* 1. start new process *
|
|
8
|
+
* 2. update existing process
|
|
9
|
+
* 3. cancel process *
|
|
10
|
+
* 4. find my process *
|
|
11
|
+
* 5. find all proccess by filter in current tenant *
|
|
12
|
+
* 6. invoke process (approve, accept and reject)
|
|
13
|
+
* 7.getproccessbyid
|
|
14
|
+
*
|
|
15
|
+
* supply callback
|
|
16
|
+
* 1. send messaging
|
|
17
|
+
* 2. obtain dynamic users, candidate users/groups
|
|
18
|
+
* 3.
|
|
19
|
+
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
BadRequestException,
|
|
24
|
+
Injectable,
|
|
25
|
+
InternalServerErrorException,
|
|
26
|
+
Logger,
|
|
27
|
+
NotFoundException,
|
|
28
|
+
} from '@nestjs/common';
|
|
29
|
+
import {
|
|
30
|
+
WorkflowSettingApiSchema,
|
|
31
|
+
WorkflowDataApiSchema,
|
|
32
|
+
WorkflowProcess,
|
|
33
|
+
WorkflowTask,
|
|
34
|
+
UserTaskActors,
|
|
35
|
+
UserTaskType
|
|
36
|
+
} from './workflow.type';
|
|
37
|
+
import { BPMNServer, Logger as bpmnlogger } from 'bpmn-server';
|
|
38
|
+
import { configuration } from './configuration';
|
|
39
|
+
import { UserContext } from '../generate/commons/user.context';
|
|
40
|
+
import * as formschemas from './formschema'
|
|
41
|
+
export {
|
|
42
|
+
WorkflowSettingApiSchema,
|
|
43
|
+
WorkflowDataApiSchema,
|
|
44
|
+
} from './workflow.type';
|
|
45
|
+
|
|
46
|
+
@Injectable()
|
|
47
|
+
export class WorkflowService {
|
|
48
|
+
protected bpmnServer: BPMNServer;
|
|
49
|
+
private readonly logger = new Logger();
|
|
50
|
+
constructor() {
|
|
51
|
+
this.bpmnServer = new BPMNServer(configuration);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* get all workflow userTask for specific uid (uuid)
|
|
56
|
+
* @param appuser
|
|
57
|
+
* @returns array of usertask
|
|
58
|
+
*/
|
|
59
|
+
async getActorUserTask(appuser: UserContext, uid: string) {
|
|
60
|
+
const tmp: any[] = await this.bpmnServer.dataStore.findItems({
|
|
61
|
+
'items.status': 'wait',
|
|
62
|
+
'data.tenantId': appuser.getTenantId(),
|
|
63
|
+
//filter uid properties base on function
|
|
64
|
+
$or: [
|
|
65
|
+
{ 'items.assignee': appuser.getUname() },
|
|
66
|
+
{ 'items.candidateUsers': appuser.getUname() },
|
|
67
|
+
{ 'items.candidateGroups': appuser.getGroup() },
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
const result:UserTaskType[] = tmp.map((proc) => {
|
|
71
|
+
const subitem:UserTaskType = {
|
|
72
|
+
id: proc.instanceId,
|
|
73
|
+
taskId: proc.id,
|
|
74
|
+
elementId: proc.elementId,
|
|
75
|
+
name: proc.name,
|
|
76
|
+
processName: proc.processName,
|
|
77
|
+
assignee: proc.assignee,
|
|
78
|
+
candidateUsers: proc.candidateUsers,
|
|
79
|
+
candidateGroups: proc.candidateGroups,
|
|
80
|
+
data: proc.data,
|
|
81
|
+
vars: proc.vars,
|
|
82
|
+
startedAt: proc.startedAt,
|
|
83
|
+
followUpDate: proc.followUpDate,
|
|
84
|
+
dueDate: proc.dueDate,
|
|
85
|
+
priority: proc.priority,
|
|
86
|
+
type: proc.type,
|
|
87
|
+
userId: proc.userId,
|
|
88
|
+
}
|
|
89
|
+
return subitem
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
// throw new BadRequestException(`getActorUserTask is not supported yet`)
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* get all workflow userTask for my uid (uuid)
|
|
96
|
+
* @param appuser
|
|
97
|
+
* @returns array of usertask
|
|
98
|
+
*/
|
|
99
|
+
async getMyUserTask(appuser: UserContext) {
|
|
100
|
+
return await this.getActorUserTask(appuser, appuser.getUid());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* !! waiting founder
|
|
105
|
+
* deveploper method
|
|
106
|
+
* create new process definitions
|
|
107
|
+
*/
|
|
108
|
+
async newWorkflowDefinitions(
|
|
109
|
+
appuser: UserContext,
|
|
110
|
+
workflowName: string,
|
|
111
|
+
xml: string,
|
|
112
|
+
) {
|
|
113
|
+
throw new BadRequestException(
|
|
114
|
+
`newWorkflowDefinitions "${workflowName}" is not supported yet`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async getWorkflowDefinitions(appuser: UserContext) {
|
|
119
|
+
throw new BadRequestException(
|
|
120
|
+
`getWorkflowDefinitions is not supported yet`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async readWorkflowDefinition(appuser: UserContext, workflowname: string) {
|
|
125
|
+
throw new BadRequestException(
|
|
126
|
+
`readWorkflowDefinition is not supported yet`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async deleteWorkflowDefinition(appuser: UserContext, workflowname: string) {
|
|
131
|
+
throw new BadRequestException(
|
|
132
|
+
`deleteWorkflowDefinition is not supported yet`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async updateWorkflowDefinition(
|
|
137
|
+
appuser: UserContext,
|
|
138
|
+
workflowname: string,
|
|
139
|
+
xml: string,
|
|
140
|
+
) {
|
|
141
|
+
throw new BadRequestException(
|
|
142
|
+
`updateWorkflowDefinition is not supported yet`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* admin workflow service, obtain all active workflows and it's pending task from all tenant
|
|
148
|
+
* status: done
|
|
149
|
+
* @param appuser
|
|
150
|
+
* @returns array of workflow process and it's waiting task
|
|
151
|
+
*/
|
|
152
|
+
async getAllActiveProcesses(appuser: UserContext) {
|
|
153
|
+
const alldata = await this.bpmnServer.dataStore.findInstances(
|
|
154
|
+
{ status: 'running' },
|
|
155
|
+
'summary',
|
|
156
|
+
);
|
|
157
|
+
const result = this.workflowProcessArrayMaping(alldata);
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* delete a workflow process from database
|
|
163
|
+
* @param appuser
|
|
164
|
+
* @param id
|
|
165
|
+
* @returns
|
|
166
|
+
*/
|
|
167
|
+
async deleteWorkflowById(appuser: UserContext, id: string) {
|
|
168
|
+
if (await this.getWorkflowById(appuser, id)) {
|
|
169
|
+
const result = await this.bpmnServer.dataStore.deleteInstances({
|
|
170
|
+
id: id,
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
status: 'ok',
|
|
174
|
+
deletedCount: result['deletedCount'],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* invoke workflow process to next step
|
|
181
|
+
* @param appuser
|
|
182
|
+
* @param id
|
|
183
|
+
* @param taskId
|
|
184
|
+
* @param data
|
|
185
|
+
* @returns
|
|
186
|
+
*/
|
|
187
|
+
async invokeWorkflowUserTask(
|
|
188
|
+
appuser: UserContext,
|
|
189
|
+
taskId: string,
|
|
190
|
+
data: any,
|
|
191
|
+
) {
|
|
192
|
+
try {
|
|
193
|
+
const response = await this.bpmnServer.engine.invoke(
|
|
194
|
+
{ 'items.id': taskId, 'items.status': 'wait' },
|
|
195
|
+
data,
|
|
196
|
+
);
|
|
197
|
+
return Object.keys(response);
|
|
198
|
+
} catch (e) {
|
|
199
|
+
throw new NotFoundException(e);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* !! waiting founder
|
|
205
|
+
* use in adhoc situation override bpmn assignee/candidateUsers/Groups with data
|
|
206
|
+
* status: draft
|
|
207
|
+
* @param appuser
|
|
208
|
+
* @param id
|
|
209
|
+
* @param taskId
|
|
210
|
+
* @param data
|
|
211
|
+
*/
|
|
212
|
+
async updateWorkflowUserTask(
|
|
213
|
+
appuser: UserContext,
|
|
214
|
+
id: string,
|
|
215
|
+
taskId: string,
|
|
216
|
+
data: UserTaskActors,
|
|
217
|
+
) {
|
|
218
|
+
try {
|
|
219
|
+
const result = await this.bpmnServer.dataStore.findInstance(
|
|
220
|
+
{ id: id },
|
|
221
|
+
{},
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const usertask = result.items.find((item) => item.id == taskId);
|
|
225
|
+
if (usertask) {
|
|
226
|
+
const result = await this.bpmnServer.engine.assign(
|
|
227
|
+
{ id: id, 'items.id': taskId },
|
|
228
|
+
{ newData: 1 },
|
|
229
|
+
appuser.getUid(),
|
|
230
|
+
data,
|
|
231
|
+
);
|
|
232
|
+
return 'OK'; //Object.keys(result)
|
|
233
|
+
} else {
|
|
234
|
+
throw new NotFoundException(`user task id:${taskId} not found`);
|
|
235
|
+
}
|
|
236
|
+
} catch (e) {
|
|
237
|
+
throw new NotFoundException(e);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// throw new BadRequestException(`updateWorkflowUserTask is not supported yet`)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
*
|
|
245
|
+
* @param appuser search all workflow in current tenant
|
|
246
|
+
* @param filter
|
|
247
|
+
* @returns
|
|
248
|
+
*/
|
|
249
|
+
async searchRunningWorkflowProcesses(appuser: UserContext, filter: any) {
|
|
250
|
+
// filter['data.tenantId']= appuser.getTenantId() //tmp disabled waiting
|
|
251
|
+
filter['status'] = 'running';
|
|
252
|
+
return await this.searchWorkflowProcesses(appuser, filter);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
*
|
|
257
|
+
* @param appuser search all workflow in current tenant
|
|
258
|
+
* @param filter
|
|
259
|
+
* @returns
|
|
260
|
+
*/
|
|
261
|
+
async searchWorkflowProcesses(appuser: UserContext, filter: any) {
|
|
262
|
+
filter['data.tenantId'] = appuser.getTenantId(); //tmp disabled waiting
|
|
263
|
+
const alldata = await this.bpmnServer.dataStore.findInstances(
|
|
264
|
+
filter,
|
|
265
|
+
'summary',
|
|
266
|
+
);
|
|
267
|
+
const result = this.workflowProcessArrayMaping(alldata);
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async getPendingProcess(appuser: UserContext) {
|
|
272
|
+
const tmp: any[] = await this.bpmnServer.dataStore.findItems({
|
|
273
|
+
'items.status': 'wait',
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const result = tmp.map((proc) => ({
|
|
277
|
+
id: proc.instanceId,
|
|
278
|
+
assignee: proc.assignee,
|
|
279
|
+
candidateUsers: proc.candidateUsers,
|
|
280
|
+
candidateGroups: proc.candidateGroups,
|
|
281
|
+
data: proc.data,
|
|
282
|
+
processName: proc.processName,
|
|
283
|
+
startedAt: proc.startedAt,
|
|
284
|
+
type: proc.type,
|
|
285
|
+
taskName: proc.name,
|
|
286
|
+
userId: proc.userId,
|
|
287
|
+
}));
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* initialise new workflow process
|
|
293
|
+
* status: done
|
|
294
|
+
* @param appuser
|
|
295
|
+
* @param workflowName
|
|
296
|
+
* @param data
|
|
297
|
+
* @returns workflowsummary
|
|
298
|
+
*/
|
|
299
|
+
async startWorkflow(appuser: UserContext, workflowName: string, data?: any) {
|
|
300
|
+
try {
|
|
301
|
+
data.tenantId = appuser.getTenantId();
|
|
302
|
+
data.orgId = appuser.getOrgId();
|
|
303
|
+
data.branchId = appuser.getBranchId();
|
|
304
|
+
const result = await this.bpmnServer.engine.start(
|
|
305
|
+
workflowName,
|
|
306
|
+
data,
|
|
307
|
+
null,
|
|
308
|
+
appuser.getUid(),
|
|
309
|
+
);
|
|
310
|
+
return {
|
|
311
|
+
id: result.id,
|
|
312
|
+
name: result.name,
|
|
313
|
+
status: result.status,
|
|
314
|
+
userId: result.userId,
|
|
315
|
+
startedAt: result.item.startedAt,
|
|
316
|
+
};
|
|
317
|
+
} catch (e) {
|
|
318
|
+
throw new BadRequestException(e, JSON.stringify(data));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* read single process full property
|
|
324
|
+
* @param appuser
|
|
325
|
+
* @param id
|
|
326
|
+
* @returns
|
|
327
|
+
*/
|
|
328
|
+
async getWorkflowById(appuser: UserContext, id: string) {
|
|
329
|
+
try {
|
|
330
|
+
const data = await this.bpmnServer.dataStore.findInstance({ id: id }, {}); // .findInstances({id:id},'full')
|
|
331
|
+
const result = this.workflowProcessMaping(data);
|
|
332
|
+
return result;
|
|
333
|
+
} catch (e) {
|
|
334
|
+
throw new NotFoundException(e);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async getPendingWorkflows(appuser: UserContext) {
|
|
338
|
+
const tmp: any[] = await this.bpmnServer.dataStore.findItems({
|
|
339
|
+
'items.status': 'wait',
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const result = tmp.map((proc) => ({
|
|
343
|
+
id: proc.instanceId,
|
|
344
|
+
assignee: proc.assignee,
|
|
345
|
+
candidateUsers: proc.candidateUsers,
|
|
346
|
+
candidateGroups: proc.candidateGroups,
|
|
347
|
+
data: proc.data,
|
|
348
|
+
processName: proc.processName,
|
|
349
|
+
startedAt: proc.startedAt,
|
|
350
|
+
type: proc.type,
|
|
351
|
+
taskName: proc.name,
|
|
352
|
+
userId: proc.userId,
|
|
353
|
+
}));
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* obtain specific bpmn task camunda:formKey
|
|
359
|
+
* @param appuser
|
|
360
|
+
* @param processName
|
|
361
|
+
* @param elementId
|
|
362
|
+
* @returns properties
|
|
363
|
+
*/
|
|
364
|
+
async getWorkflowUserTaskFormKey(
|
|
365
|
+
appuser,
|
|
366
|
+
processName: string,
|
|
367
|
+
elementId: string,
|
|
368
|
+
) {
|
|
369
|
+
try{
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
let definition = await this.bpmnServer.definitions.load(processName);
|
|
373
|
+
let node = definition.getNodeById(elementId);
|
|
374
|
+
if(node){
|
|
375
|
+
const formKey = node.def.formKey
|
|
376
|
+
let schema:string =''
|
|
377
|
+
if(formKey.includes('jsonschema://')){
|
|
378
|
+
const keyname = formKey.replace('jsonschema://','')
|
|
379
|
+
schema = formschemas[keyname]
|
|
380
|
+
}else if(formKey.includes('custom://')){
|
|
381
|
+
schema=formKey
|
|
382
|
+
}else{
|
|
383
|
+
//others implementation like http://, https:// and etc
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if(schema){
|
|
387
|
+
return {
|
|
388
|
+
processName: processName,
|
|
389
|
+
elementId: elementId,
|
|
390
|
+
schema: schema
|
|
391
|
+
}
|
|
392
|
+
}else{
|
|
393
|
+
throw new InternalServerErrorException(`Cannot resolve schema from invalid formKey '${formKey}', example: 'jsonschema://SimpleApproveReject' or 'custom://your-custom-key'`)
|
|
394
|
+
}
|
|
395
|
+
}else{
|
|
396
|
+
throw new NotFoundException(`Element ${elementId} not found in process ${processName}`)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
}catch(e){
|
|
400
|
+
throw new InternalServerErrorException(e)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// helper
|
|
405
|
+
workflowProcessArrayMaping(alldata: any[]) {
|
|
406
|
+
const result = alldata.map((data) => this.workflowProcessMaping(data));
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
workflowProcessMaping(data: any) {
|
|
410
|
+
const result: WorkflowProcess = {
|
|
411
|
+
id: data.id,
|
|
412
|
+
name: data.name,
|
|
413
|
+
status: data.status,
|
|
414
|
+
startedAt: data.startedAt,
|
|
415
|
+
items: data.items
|
|
416
|
+
.filter((item) => item.type != 'bpmn:SequenceFlow')
|
|
417
|
+
.map((item) => ({
|
|
418
|
+
taskId: item.id,
|
|
419
|
+
name: item.name,
|
|
420
|
+
status: item.status,
|
|
421
|
+
assignee: item.assignee,
|
|
422
|
+
candidateUsers: item.candidateUsers,
|
|
423
|
+
candidateGroups: item.candidateGroups,
|
|
424
|
+
type: item.type,
|
|
425
|
+
})),
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
return result;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { UserService } from './../services/user.service';
|
|
2
|
+
export type WorkflowSettingApiSchema = {
|
|
3
|
+
userServiceUrl: string;
|
|
4
|
+
callBackUrl?: string;
|
|
5
|
+
assignee?: string;
|
|
6
|
+
candidateUsers?: string[];
|
|
7
|
+
candidategroups?: string[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type WorkflowDataApiSchema = {
|
|
11
|
+
data: any;
|
|
12
|
+
workflowSetting: WorkflowSettingApiSchema;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type WorkflowTask = {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
assignee: string;
|
|
19
|
+
candidateUsers: string[];
|
|
20
|
+
candidateGroups: string[];
|
|
21
|
+
type: string;
|
|
22
|
+
};
|
|
23
|
+
export type WorkflowProcess = {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
status: string;
|
|
27
|
+
startedAt: string;
|
|
28
|
+
items: WorkflowTask[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type UserTaskActors = {
|
|
32
|
+
assignee: string;
|
|
33
|
+
candidateUsers: string[];
|
|
34
|
+
candidateGroups: string[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export type UserTaskType = {
|
|
39
|
+
|
|
40
|
+
id: string
|
|
41
|
+
taskId: string
|
|
42
|
+
elementId: string
|
|
43
|
+
name: string
|
|
44
|
+
processName: string
|
|
45
|
+
assignee: string
|
|
46
|
+
candidateUsers: string[]
|
|
47
|
+
candidateGroups: string[]
|
|
48
|
+
data: any
|
|
49
|
+
vars: any
|
|
50
|
+
startedAt: string
|
|
51
|
+
followUpDate: string
|
|
52
|
+
dueDate: string
|
|
53
|
+
priority: string
|
|
54
|
+
type: string
|
|
55
|
+
userId: string
|
|
56
|
+
}
|
|
@@ -40,7 +40,8 @@ const CustomTailwind = usePassThrough(
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
sidebar:{
|
|
43
|
-
root:{class:'w-1/2
|
|
43
|
+
root:{class:'w-full md:w-1/2 xl:w-1/4 bg-white dark:bg-gray-800 border p-0 h-full'},
|
|
44
|
+
content:{class:'p-0 pt-0 h-full w-full grow overflow-y-auto'}
|
|
44
45
|
},
|
|
45
46
|
panel: {
|
|
46
47
|
root:{class:['border']},
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* author: Ks Tan
|
|
7
7
|
*/
|
|
8
8
|
import {Notification, EventType} from '~/types'
|
|
9
|
-
import { useToast, } from 'primevue/usetoast';
|
|
9
|
+
//import { useToast, } from 'primevue/usetoast';
|
|
10
10
|
import type { ToastMessageOptions } from 'primevue/toast';
|
|
11
11
|
import Toast from 'primevue/toast';
|
|
12
12
|
import { stringify } from 'ajv';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* author: Ks Tan
|
|
7
7
|
*/
|
|
8
8
|
import {Notification, NotificationStatus} from '~/types'
|
|
9
|
-
import { useToast, } from 'primevue/usetoast';
|
|
9
|
+
//import { useToast, } from 'primevue/usetoast';
|
|
10
10
|
import type { ToastMessageOptions } from 'primevue/toast';
|
|
11
11
|
import Toast from 'primevue/toast';
|
|
12
12
|
import { stringify } from 'ajv';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col border cursor-pointer p-2" @click="$emit('click',task)">
|
|
3
|
+
<!-- <span v-else class="text-gray-400 text-sm">{{ value[f] }}</span> -->
|
|
4
|
+
<!-- <div>{{ task.data }}</div> -->
|
|
5
|
+
<div class="flex flex-row">
|
|
6
|
+
<span class="flex-1">{{task.name}}</span><span class="flex-1 text-right">{{ task.startedAt }}</span>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="text text-sm text-gray-400">{{task.processName}}</div>
|
|
9
|
+
<!-- <div class="text text-xs text-gray-300">{{task.taskId}}</div> -->
|
|
10
|
+
<div v-if="task.dueDate" class="text text-xs text-gray-200">{{ task.dueDate }}</div>
|
|
11
|
+
<div v-if="task.priority" class="text text-xs text-gray-200">{{ task.priority }}</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
defineEmits(['click'])
|
|
16
|
+
const props = defineProps<{
|
|
17
|
+
task:any
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button class="text-center border-none cursor-pointer p-1" @click="visible=true" >
|
|
3
|
+
<i class="pi pi-bell"></i>
|
|
4
|
+
<Sidebar v-model:visible="visible" position="right" :modal="false" :dismissable="false">
|
|
5
|
+
<template #header>
|
|
6
|
+
<div class="text text-lg font-bold">{{ t('mytasks') }}</div>
|
|
7
|
+
</template>
|
|
8
|
+
<HeaderButtonTaskItem v-for="task in tasklist" :task="task" @click="viewTask"></HeaderButtonTaskItem>
|
|
9
|
+
</Sidebar>
|
|
10
|
+
<Dialog v-model:visible="dialogvisible"
|
|
11
|
+
@update:visible="closeDialog"
|
|
12
|
+
:pt="{root:{class:'w-1/2 h-5/6'}}"
|
|
13
|
+
:modal="true"
|
|
14
|
+
:close-on-escape="false" >
|
|
15
|
+
<template #header>
|
|
16
|
+
<div class="text text-lg font-bold">
|
|
17
|
+
{{ selectedtask.processName }} / {{ selectedtask.name }}
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
<template #default>
|
|
21
|
+
<div >
|
|
22
|
+
|
|
23
|
+
<div>
|
|
24
|
+
<pre>{{ selectedtask.data}}</pre>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="border ">
|
|
27
|
+
<Card>
|
|
28
|
+
<template #header>Response</template>
|
|
29
|
+
<template #content>
|
|
30
|
+
<div v-if="formSchema">
|
|
31
|
+
|
|
32
|
+
<SimpleAppJsonSchemaForm :schema="formSchema" #default="o">
|
|
33
|
+
<div v-for="field in Object.keys(formSchema.properties)" class="border p-2">
|
|
34
|
+
<SimpleAppInput :setting="o.getField(`#/properties/${field}`)"
|
|
35
|
+
:input-type="autoPickInput(formSchema.properties[field])"
|
|
36
|
+
v-model="data[field]" />
|
|
37
|
+
</div>
|
|
38
|
+
</SimpleAppJsonSchemaForm>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
<template #footer>
|
|
42
|
+
<Button class="btn-primary" @click="invokeTask()">{{ t('submit') }}</Button>
|
|
43
|
+
|
|
44
|
+
</template>
|
|
45
|
+
</Card>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
</Dialog>
|
|
50
|
+
</button>
|
|
51
|
+
</template>
|
|
52
|
+
<script setup lang="ts">
|
|
53
|
+
import {UserTaskType,SimpleAppInputType} from '~/types'
|
|
54
|
+
import { useDialog } from 'primevue/usedialog';
|
|
55
|
+
const dialog = useDialog()
|
|
56
|
+
const dialogvisible = ref(false)
|
|
57
|
+
const visible = ref(false)
|
|
58
|
+
const selectedtask = ref()
|
|
59
|
+
const tasklist = ref<UserTaskType[]>([])
|
|
60
|
+
const formSchema = ref()
|
|
61
|
+
const data = ref<any>({})
|
|
62
|
+
//computed(async ()=>await getTaskList())
|
|
63
|
+
|
|
64
|
+
onMounted(async ()=> syncTask())
|
|
65
|
+
watch(visible,(newvalue)=>{
|
|
66
|
+
if(newvalue){
|
|
67
|
+
syncTask()
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
const syncTask = async ()=>{
|
|
71
|
+
tasklist.value = await getTaskList()
|
|
72
|
+
if(tasklist.value.length==0){
|
|
73
|
+
visible.value=false
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const closeDialog = ()=>{
|
|
77
|
+
console.log('close dialog')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const invokeTask = async ()=>{
|
|
81
|
+
const res = await invokeUserTask(selectedtask.value.taskId,data)
|
|
82
|
+
syncTask()
|
|
83
|
+
dialogvisible.value=false
|
|
84
|
+
}
|
|
85
|
+
const viewTask = async (task:UserTaskType)=>{
|
|
86
|
+
selectedtask.value=task
|
|
87
|
+
dialogvisible.value=true
|
|
88
|
+
const formsettings:any = await getTaskForm(task.processName, task.elementId)
|
|
89
|
+
formSchema.value = formsettings.schema
|
|
90
|
+
Object.keys(formsettings.schema.properties).forEach((key)=>{
|
|
91
|
+
data.value[key]=null
|
|
92
|
+
})
|
|
93
|
+
console.log("data,data",data)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const autoPickInput = (setting:any) =>{
|
|
97
|
+
if(setting.type=='boolean'){
|
|
98
|
+
return SimpleAppInputType.checkbox
|
|
99
|
+
}if(setting.type=='number'){
|
|
100
|
+
return SimpleAppInputType.number
|
|
101
|
+
}
|
|
102
|
+
else if(setting.enum){
|
|
103
|
+
return SimpleAppInputType.select
|
|
104
|
+
}
|
|
105
|
+
else if(setting.type=='string'){
|
|
106
|
+
return pickStringInput(setting)
|
|
107
|
+
}else{
|
|
108
|
+
return SimpleAppInputType.text
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const pickStringInput = (setting:any) =>{
|
|
113
|
+
switch(setting.format){
|
|
114
|
+
case 'date':
|
|
115
|
+
return SimpleAppInputType.date
|
|
116
|
+
break;
|
|
117
|
+
case 'textarea':
|
|
118
|
+
return SimpleAppInputType.textarea
|
|
119
|
+
break;
|
|
120
|
+
case 'text':
|
|
121
|
+
default:
|
|
122
|
+
return SimpleAppInputType.text
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
</script>
|