@processmaker/screen-builder 2.18.1 → 2.21.0
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/vue-form-builder.common.js +10236 -10109
- package/dist/vue-form-builder.common.js.map +1 -1
- package/dist/vue-form-builder.css +1 -1
- package/dist/vue-form-builder.umd.js +10236 -10109
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/dist/vue-form-builder.umd.min.js +36 -36
- package/dist/vue-form-builder.umd.min.js.map +1 -1
- package/package.json +3 -3
- package/src/DataProvider.js +41 -16
- package/src/components/inspector/options-list.vue +1 -1
- package/src/components/renderer/add-loop-row.vue +19 -10
- package/src/components/renderer/file-download.vue +139 -229
- package/src/components/renderer/file-upload.vue +189 -170
- package/src/components/screen-renderer.vue +9 -5
- package/src/components/task.vue +61 -15
- package/src/components/vue-form-builder.vue +1 -1
- package/src/mixins/Json2Vue.js +41 -12
- package/src/mixins/ScreenBase.js +10 -2
- package/src/mixins/ValidationRules.js +6 -0
- package/src/mixins/VisibilityRule.js +4 -15
- package/src/mixins/computedFields.js +7 -8
- package/src/mixins/extensions/DataManager.js +1 -1
- package/src/mixins/extensions/DefaultValues.js +4 -2
- package/src/mixins/extensions/LoadFieldComponents.js +15 -3
- package/src/mixins/extensions/LoopContainer.js +1 -0
|
@@ -33,28 +33,19 @@
|
|
|
33
33
|
<span v-if="validation === 'required' && !value" class="required">{{ $t('Required') }}</span>
|
|
34
34
|
</uploader-drop>
|
|
35
35
|
<uploader-list>
|
|
36
|
-
<template
|
|
37
|
-
<ul
|
|
38
|
-
<li v-for="
|
|
39
|
-
<div class="
|
|
40
|
-
<div class="
|
|
41
|
-
<div
|
|
42
|
-
<uploader-file :file="
|
|
36
|
+
<template>
|
|
37
|
+
<ul>
|
|
38
|
+
<li v-for="(file, i) in files " :key="i" :data-cy="file.id">
|
|
39
|
+
<div class="">
|
|
40
|
+
<div class="" style="display:flex; background:rgb(226 238 255)">
|
|
41
|
+
<div v-if="nativeFiles[file.id]" style="flex: 1" :data-cy="file.file_name.replace(/[^0-9a-zA-Z\-]/g, '-')">
|
|
42
|
+
<uploader-file :file="nativeFiles[file.id]" :list="true" />
|
|
43
43
|
</div>
|
|
44
|
-
<div
|
|
45
|
-
<
|
|
46
|
-
<i class="fas fa-trash-alt"/>
|
|
47
|
-
</b-btn>
|
|
44
|
+
<div v-else style="flex: 1">
|
|
45
|
+
<i class="fas fa-paperclip"/> {{ file.file_name }}
|
|
48
46
|
</div>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div v-else class="container-fluid border-bottom pl-3 pr-3">
|
|
52
|
-
<div class="row">
|
|
53
|
-
<div class="col-11 pr-0 pl-0 my-auto">
|
|
54
|
-
<i class="fas fa-paperclip"/> {{ displayNameFor(fileId) }}
|
|
55
|
-
</div>
|
|
56
|
-
<div class="col-1 my-auto">
|
|
57
|
-
<b-btn variant="outline" @click="removeFile(fileId)" v-b-tooltip.hover :title="$t('Delete')">
|
|
47
|
+
<div class="pt-1">
|
|
48
|
+
<b-btn variant="outline" @click="removeFile(file)" v-b-tooltip.hover :title="$t('Delete')">
|
|
58
49
|
<i class="fas fa-trash-alt"/>
|
|
59
50
|
</b-btn>
|
|
60
51
|
</div>
|
|
@@ -62,16 +53,6 @@
|
|
|
62
53
|
</div>
|
|
63
54
|
</li>
|
|
64
55
|
</ul>
|
|
65
|
-
<ul v-else>
|
|
66
|
-
<li v-if="fileList.length === 0 && value">
|
|
67
|
-
<div class="border-bottom py-2">
|
|
68
|
-
<i class="fas fa-paperclip"/> {{ displayName }}
|
|
69
|
-
</div>
|
|
70
|
-
</li>
|
|
71
|
-
<li v-for="file in fileList" :key="file.id" :data-cy="file.name.replace(/[^0-9a-zA-Z\-]/g, '-')" :nada="JSON.stringify(file)" >
|
|
72
|
-
<uploader-file :file="file" :list="true"/>
|
|
73
|
-
</li>
|
|
74
|
-
</ul>
|
|
75
56
|
</template>
|
|
76
57
|
</uploader-list>
|
|
77
58
|
<div class="invalid-feedback" :class="{'d-block': required && !value}">
|
|
@@ -107,9 +88,6 @@ export default {
|
|
|
107
88
|
components: uploader,
|
|
108
89
|
mixins: [uniqIdsMixin],
|
|
109
90
|
props: ['label', 'error', 'helper', 'name', 'value', 'controlClass', 'endpoint', 'accept', 'validation', 'parent', 'config', 'multipleUpload'],
|
|
110
|
-
beforeMount() {
|
|
111
|
-
this.getFileType();
|
|
112
|
-
},
|
|
113
91
|
updated() {
|
|
114
92
|
this.removeDefaultClasses();
|
|
115
93
|
},
|
|
@@ -140,6 +118,43 @@ export default {
|
|
|
140
118
|
}
|
|
141
119
|
},
|
|
142
120
|
computed: {
|
|
121
|
+
filesFromGlobalRequestFiles() {
|
|
122
|
+
if (!this.value) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
return _.get(window, `PM4ConfigOverrides.requestFiles["${this.fileDataName}"]`, []).filter(file => {
|
|
126
|
+
// Filter any requestFiles that don't exist in this component's value. This can happen if
|
|
127
|
+
// a file is uploaded but the task is not saved.
|
|
128
|
+
if (this.multipleUpload) {
|
|
129
|
+
return this.value.some(valueFile => valueFile.file === file.id);
|
|
130
|
+
} else {
|
|
131
|
+
return file.id === this.value;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
filesFromCollection() {
|
|
136
|
+
if (!this.value) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
return this.filesFromCollectionValue(this.value);
|
|
140
|
+
},
|
|
141
|
+
collection() {
|
|
142
|
+
const collectionIdNode = document.head.querySelector('meta[name="collection-id"]');
|
|
143
|
+
if (collectionIdNode) {
|
|
144
|
+
return collectionIdNode.content;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
},
|
|
148
|
+
filesData() {
|
|
149
|
+
if (this.collection) {
|
|
150
|
+
return this.filesFromCollection;
|
|
151
|
+
} else {
|
|
152
|
+
return this.filesFromGlobalRequestFiles;
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
fileIds() {
|
|
156
|
+
return this.files.map(f => f.id);
|
|
157
|
+
},
|
|
143
158
|
nativeButtonAttrs() {
|
|
144
159
|
const attrs = { 'data-cy':'file-upload-button' };
|
|
145
160
|
if (this.disabled) {
|
|
@@ -157,15 +172,6 @@ export default {
|
|
|
157
172
|
inPreviewMode() {
|
|
158
173
|
return ((this.mode === 'preview' && !window.exampleScreens) || this.mode === 'editor');
|
|
159
174
|
},
|
|
160
|
-
displayName() {
|
|
161
|
-
const requestFiles = _.get(window, 'PM4ConfigOverrides.requestFiles', {});
|
|
162
|
-
const fileInfo = requestFiles[this.fileDataName];
|
|
163
|
-
let id = this.uploaderId;
|
|
164
|
-
if (fileInfo && id >= 0) {
|
|
165
|
-
return fileInfo.file_name;
|
|
166
|
-
}
|
|
167
|
-
return this.value.name ? this.value.name : this.value;
|
|
168
|
-
},
|
|
169
175
|
mode() {
|
|
170
176
|
return this.$root.$children[0].mode;
|
|
171
177
|
},
|
|
@@ -195,6 +201,22 @@ export default {
|
|
|
195
201
|
},
|
|
196
202
|
},
|
|
197
203
|
watch: {
|
|
204
|
+
filesData: {
|
|
205
|
+
handler() {
|
|
206
|
+
this.setFiles();
|
|
207
|
+
},
|
|
208
|
+
immediate: true,
|
|
209
|
+
deep: true,
|
|
210
|
+
},
|
|
211
|
+
files: {
|
|
212
|
+
handler() {
|
|
213
|
+
if (!this.collection) {
|
|
214
|
+
this.setRequestFiles();
|
|
215
|
+
}
|
|
216
|
+
this.$emit('input', this.valueToSend());
|
|
217
|
+
},
|
|
218
|
+
deep: true,
|
|
219
|
+
},
|
|
198
220
|
name: {
|
|
199
221
|
handler() {
|
|
200
222
|
this.options.query.data_name = this.fileDataName;
|
|
@@ -232,7 +254,6 @@ export default {
|
|
|
232
254
|
return {
|
|
233
255
|
uploaderId: 1,
|
|
234
256
|
content: '',
|
|
235
|
-
fileType: null,
|
|
236
257
|
validator: {
|
|
237
258
|
errorCount: 0,
|
|
238
259
|
errors: [],
|
|
@@ -261,32 +282,66 @@ export default {
|
|
|
261
282
|
accept: this.accept,
|
|
262
283
|
},
|
|
263
284
|
disabled: false,
|
|
285
|
+
files: [],
|
|
286
|
+
nativeFiles: {},
|
|
264
287
|
};
|
|
265
288
|
},
|
|
266
289
|
methods: {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// has just one file, we must return the object, in other case a search by id is done.
|
|
271
|
-
const requestFiles = _.get(window, 'PM4ConfigOverrides.requestFiles', {});
|
|
272
|
-
const files = requestFiles[this.fileDataName];
|
|
273
|
-
if (files) {
|
|
274
|
-
return Array.isArray(files)
|
|
275
|
-
? files.find(x => x.id === id)
|
|
276
|
-
: files;
|
|
290
|
+
setFiles() {
|
|
291
|
+
if (_.isEqual(this.filesData, this.files)) {
|
|
292
|
+
return;
|
|
277
293
|
}
|
|
278
|
-
|
|
294
|
+
this.files = this.filesData;
|
|
279
295
|
},
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
|
|
283
|
-
|
|
296
|
+
filesFromCollectionValue(value) {
|
|
297
|
+
if (!value) {
|
|
298
|
+
return [];
|
|
299
|
+
}
|
|
300
|
+
if (this.multipleUpload) {
|
|
301
|
+
return this.filesFromCollectionMulti(value);
|
|
302
|
+
} else {
|
|
303
|
+
return this.filesFromCollectionSingle(value);
|
|
284
304
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
305
|
+
},
|
|
306
|
+
filesFromCollectionSingle(value) {
|
|
307
|
+
return [{ id: value.id, file_name: value.name }];
|
|
308
|
+
},
|
|
309
|
+
filesFromCollectionMulti(value) {
|
|
310
|
+
return value.map(v => {
|
|
311
|
+
return { id: v.file.id, file_name: v.file.name };
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
setRequestFiles() {
|
|
315
|
+
_.set(window, `PM4ConfigOverrides.requestFiles["${this.fileDataName}"]`, this.files);
|
|
316
|
+
this.$emit('input', this.valueToSend());
|
|
317
|
+
},
|
|
318
|
+
valueToSend() {
|
|
319
|
+
if (this.multipleUpload) {
|
|
320
|
+
return this.valueForMulti();
|
|
321
|
+
} else {
|
|
322
|
+
return this.valueForSingle();
|
|
288
323
|
}
|
|
289
324
|
},
|
|
325
|
+
valueForMulti() {
|
|
326
|
+
return this.files.map(file => {
|
|
327
|
+
return { file: this.formatForType(file) };
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
valueForSingle() {
|
|
331
|
+
if (this.files.length > 0) {
|
|
332
|
+
return this.formatForType(this.files[0]);
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
},
|
|
336
|
+
formatForType(file) {
|
|
337
|
+
if (this.collection) {
|
|
338
|
+
return { id: file.id, name: file.file_name };
|
|
339
|
+
}
|
|
340
|
+
return file.id;
|
|
341
|
+
},
|
|
342
|
+
hasFileId(id) {
|
|
343
|
+
return this.fileIds.includes(id);
|
|
344
|
+
},
|
|
290
345
|
listenRemovedLoop(loop, removed) {
|
|
291
346
|
this.deleteAssociatedFiles(removed);
|
|
292
347
|
},
|
|
@@ -297,40 +352,62 @@ export default {
|
|
|
297
352
|
}
|
|
298
353
|
this.deleteAssociatedFiles(record);
|
|
299
354
|
},
|
|
300
|
-
deleteAssociatedFiles(object) {
|
|
355
|
+
async deleteAssociatedFiles(object) {
|
|
301
356
|
for (const prop in object) {
|
|
302
|
-
if (prop === this.name) {
|
|
303
|
-
this.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
357
|
+
if (prop === this.name && object[prop]) {
|
|
358
|
+
const idsInRemoved = this.idsFromValue(object[prop]);
|
|
359
|
+
|
|
360
|
+
for (const id of idsInRemoved) {
|
|
361
|
+
if (this.hasFileId(id)) {
|
|
362
|
+
// In record lists, delete can be called twice on the same file.
|
|
363
|
+
// Catch and igore the error.
|
|
364
|
+
// eslint-disable-next-line no-unused-vars
|
|
365
|
+
await this.$dataProvider.deleteFile(id).catch(e => {});
|
|
366
|
+
this.removeFromFiles(id);
|
|
367
|
+
}
|
|
308
368
|
}
|
|
309
369
|
}
|
|
310
370
|
}
|
|
311
371
|
},
|
|
312
|
-
|
|
313
|
-
if (this.
|
|
314
|
-
this.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
372
|
+
idsFromValue(value) {
|
|
373
|
+
if (this.collection) {
|
|
374
|
+
return this.filesFromCollectionValue(value).map(f => f.id);
|
|
375
|
+
} else {
|
|
376
|
+
if (this.multipleUpload) {
|
|
377
|
+
return value.map(v => v.file);
|
|
378
|
+
} else {
|
|
379
|
+
return [value];
|
|
380
|
+
}
|
|
320
381
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
382
|
+
},
|
|
383
|
+
async removeFile(file) {
|
|
384
|
+
const id = file.id;
|
|
385
|
+
const token = file.token ? file.token : null;
|
|
386
|
+
|
|
387
|
+
// If it's not a web entry start event
|
|
388
|
+
if (!isNaN(id)) {
|
|
389
|
+
await this.$dataProvider.deleteFile(id, token);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
this.removeFromFiles(id);
|
|
393
|
+
},
|
|
394
|
+
removeFromFiles(id) {
|
|
395
|
+
const idx = this.files.findIndex(f => f.id === id);
|
|
396
|
+
this.$delete(this.files, idx);
|
|
397
|
+
|
|
398
|
+
if (this.nativeFiles[id]) {
|
|
399
|
+
if (this.$refs.uploader) {
|
|
400
|
+
this.$refs.uploader.uploader.removeFile(this.nativeFiles[id]);
|
|
401
|
+
}
|
|
402
|
+
this.$delete(this.nativeFiles, id);
|
|
325
403
|
}
|
|
404
|
+
|
|
326
405
|
},
|
|
327
|
-
|
|
328
|
-
if (
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
/** ignore exception **/
|
|
333
|
-
});
|
|
406
|
+
addToFiles(fileInfo) {
|
|
407
|
+
if (this.multipleUpload) {
|
|
408
|
+
this.files.push(fileInfo);
|
|
409
|
+
} else {
|
|
410
|
+
this.files = [fileInfo];
|
|
334
411
|
}
|
|
335
412
|
},
|
|
336
413
|
listenRecordList(recordList, index, id) {
|
|
@@ -339,15 +416,6 @@ export default {
|
|
|
339
416
|
return;
|
|
340
417
|
}
|
|
341
418
|
this.row_id = (parent !== null) ? id : null;
|
|
342
|
-
//update id to refresh computed values
|
|
343
|
-
this.uploaderId =new Date().getTime();
|
|
344
|
-
if (this.$refs.uploader) {
|
|
345
|
-
this.$refs.uploader.files = [];
|
|
346
|
-
this.$refs.uploader.fileList = [];
|
|
347
|
-
this.$refs.uploader.uploader.files = [];
|
|
348
|
-
this.$refs.uploader.uploader.fileList = [];
|
|
349
|
-
}
|
|
350
|
-
this.$forceUpdate();
|
|
351
419
|
},
|
|
352
420
|
setPrefix() {
|
|
353
421
|
let parent = this.$parent;
|
|
@@ -412,70 +480,28 @@ export default {
|
|
|
412
480
|
e.target.click();
|
|
413
481
|
}
|
|
414
482
|
},
|
|
415
|
-
getFileType() {
|
|
416
|
-
if (document.head.querySelector('meta[name="collection-id"]')) {
|
|
417
|
-
this.fileType = 'collection';
|
|
418
|
-
} else {
|
|
419
|
-
this.fileType = 'request';
|
|
420
|
-
}
|
|
421
|
-
},
|
|
422
483
|
fileUploaded(rootFile, file, message) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const msg = JSON.parse(message);
|
|
427
|
-
if (!_.has(window, 'PM4ConfigOverrides')) {
|
|
428
|
-
window.PM4ConfigOverrides = {};
|
|
429
|
-
}
|
|
430
|
-
if (!_.has(window, 'PM4ConfigOverrides.requestFiles')) {
|
|
431
|
-
window.PM4ConfigOverrides.requestFiles = {};
|
|
432
|
-
}
|
|
433
|
-
if (typeof (window.PM4ConfigOverrides.requestFiles[this.fileDataName]) == 'undefined') {
|
|
434
|
-
window.PM4ConfigOverrides.requestFiles[this.fileDataName] = this.multipleUpload ? [] : {};
|
|
435
|
-
}
|
|
436
|
-
if (this.multipleUpload) {
|
|
437
|
-
const filesData = this.asArray(JSON.parse(JSON.stringify(window.PM4ConfigOverrides.requestFiles[this.fileDataName])));
|
|
438
|
-
filesData.push({id: msg.fileUploadId, file_name: file.name, new:true});
|
|
439
|
-
window.PM4ConfigOverrides.requestFiles[this.fileDataName] = filesData;
|
|
440
|
-
} else {
|
|
441
|
-
window.PM4ConfigOverrides.requestFiles[this.fileDataName] = {id: msg.fileUploadId, file_name: file.name, new:true};
|
|
442
|
-
}
|
|
443
|
-
id = msg.fileUploadId;
|
|
444
|
-
}
|
|
445
|
-
const valueToSend = this.multipleUpload
|
|
446
|
-
? this.asArray(this.value).concat(id)
|
|
447
|
-
: id;
|
|
448
|
-
this.$emit('input', valueToSend);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
if (this.fileType == 'collection') {
|
|
452
|
-
message = JSON.parse(message);
|
|
453
|
-
const uploadedObject = {
|
|
454
|
-
id: message.id,
|
|
455
|
-
name: message.file_name,
|
|
456
|
-
};
|
|
484
|
+
let name = file.name;
|
|
485
|
+
if (message) {
|
|
486
|
+
const msg = JSON.parse(message);
|
|
457
487
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
this.$emit('input', currentVal);
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
this.$emit('input', uploadedObject);
|
|
488
|
+
let id = msg.fileUploadId;
|
|
489
|
+
if (this.collection) {
|
|
490
|
+
id = msg.id;
|
|
465
491
|
}
|
|
492
|
+
|
|
493
|
+
const fileInfo = {
|
|
494
|
+
id,
|
|
495
|
+
file_name: name,
|
|
496
|
+
mime_type: rootFile.fileType,
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
this.$set(this.nativeFiles, id, rootFile);
|
|
500
|
+
this.addToFiles(fileInfo);
|
|
501
|
+
} else {
|
|
502
|
+
this.$emit('input', name);
|
|
466
503
|
}
|
|
467
504
|
},
|
|
468
|
-
asArray(value) {
|
|
469
|
-
if (value === null || value === undefined) {
|
|
470
|
-
return [];
|
|
471
|
-
}
|
|
472
|
-
return Array.isArray(value) ? value : [value];
|
|
473
|
-
},
|
|
474
|
-
getFileId(value) {
|
|
475
|
-
return (typeof value === 'object' && value.id)
|
|
476
|
-
? value.id
|
|
477
|
-
: value;
|
|
478
|
-
},
|
|
479
505
|
removed() {
|
|
480
506
|
if (!this.inProgress) {
|
|
481
507
|
this.complete();
|
|
@@ -515,25 +541,18 @@ export default {
|
|
|
515
541
|
return this.endpoint;
|
|
516
542
|
}
|
|
517
543
|
|
|
518
|
-
if (this.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
return requestIDNode
|
|
522
|
-
? `/api/1.0/requests/${requestIDNode.content}/files`
|
|
523
|
-
: null;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
if (this.fileType == 'collection') {
|
|
527
|
-
const collectionIdNode = document.head.querySelector('meta[name="collection-id"]');
|
|
528
|
-
|
|
529
|
-
return collectionIdNode
|
|
530
|
-
? '/api/1.0/files' +
|
|
544
|
+
if (this.collection) {
|
|
545
|
+
return '/api/1.0/files' +
|
|
531
546
|
'?model=' +
|
|
532
547
|
'ProcessMaker\\Plugins\\Collections\\Models\\Collection' +
|
|
533
548
|
'&model_id=' +
|
|
534
|
-
|
|
549
|
+
this.collection +
|
|
535
550
|
'&collection=' +
|
|
536
|
-
'collection'
|
|
551
|
+
'collection';
|
|
552
|
+
} else {
|
|
553
|
+
const requestIDNode = document.head.querySelector('meta[name="request-id"]');
|
|
554
|
+
return requestIDNode
|
|
555
|
+
? `/api/1.0/requests/${requestIDNode.content}/files`
|
|
537
556
|
: null;
|
|
538
557
|
}
|
|
539
558
|
},
|
|
@@ -26,7 +26,7 @@ import Json2Vue from '../mixins/Json2Vue';
|
|
|
26
26
|
import CurrentPageProperty from '../mixins/CurrentPageProperty';
|
|
27
27
|
import WatchersSynchronous from '@/components/watchers-synchronous';
|
|
28
28
|
import ScreenRendererError from '../components/renderer/screen-renderer-error';
|
|
29
|
-
import { cloneDeep, isEqual } from 'lodash';
|
|
29
|
+
import { cloneDeep, isEqual, debounce } from 'lodash';
|
|
30
30
|
|
|
31
31
|
export default {
|
|
32
32
|
name: 'screen-renderer',
|
|
@@ -43,19 +43,23 @@ export default {
|
|
|
43
43
|
mounted() {
|
|
44
44
|
this.currentDefinition = cloneDeep(this.definition);
|
|
45
45
|
this.component = this.buildComponent(this.currentDefinition);
|
|
46
|
+
this.rebuildScreen = debounce(this.rebuildScreen, 25);
|
|
46
47
|
},
|
|
47
48
|
watch: {
|
|
48
49
|
definition: {
|
|
49
50
|
deep: true,
|
|
50
51
|
handler(definition) {
|
|
51
|
-
|
|
52
|
-
this.currentDefinition = cloneDeep(definition);
|
|
53
|
-
this.component = this.buildComponent(this.currentDefinition);
|
|
54
|
-
}
|
|
52
|
+
this.rebuildScreen(definition);
|
|
55
53
|
},
|
|
56
54
|
},
|
|
57
55
|
},
|
|
58
56
|
methods: {
|
|
57
|
+
rebuildScreen(definition) {
|
|
58
|
+
if (!isEqual(definition, this.currentDefinition)) {
|
|
59
|
+
this.currentDefinition = cloneDeep(definition);
|
|
60
|
+
this.component = this.buildComponent(this.currentDefinition);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
59
63
|
onAsyncWatcherOn() {
|
|
60
64
|
this.displayAsyncLoading = typeof this._parent === 'undefined';
|
|
61
65
|
},
|
package/src/components/task.vue
CHANGED
|
@@ -91,6 +91,7 @@ export default {
|
|
|
91
91
|
requestData: {},
|
|
92
92
|
hasErrors: false,
|
|
93
93
|
refreshScreen: 0,
|
|
94
|
+
redirecting: null,
|
|
94
95
|
};
|
|
95
96
|
},
|
|
96
97
|
watch: {
|
|
@@ -157,6 +158,7 @@ export default {
|
|
|
157
158
|
handler() {
|
|
158
159
|
this.taskId = this.task.id;
|
|
159
160
|
this.nodeId = this.task.element_id;
|
|
161
|
+
this.listenForParentChanges();
|
|
160
162
|
},
|
|
161
163
|
},
|
|
162
164
|
|
|
@@ -205,6 +207,9 @@ export default {
|
|
|
205
207
|
const screenType = this.screen.type;
|
|
206
208
|
return screenType.toLowerCase() + '-screen';
|
|
207
209
|
},
|
|
210
|
+
parentRequest() {
|
|
211
|
+
return _.get(this.task, 'process_request.parent_request_id', null);
|
|
212
|
+
},
|
|
208
213
|
},
|
|
209
214
|
methods: {
|
|
210
215
|
loadScreen(id) {
|
|
@@ -227,7 +232,7 @@ export default {
|
|
|
227
232
|
loadTask() {
|
|
228
233
|
const url = `/${this.taskId}?include=data,user,requestor,processRequest,component,screen,requestData,bpmnTagName,interstitial,definition,nested`;
|
|
229
234
|
// For Vocabularies
|
|
230
|
-
if (window.ProcessMaker && window.ProcessMaker.packages && window.ProcessMaker.packages.
|
|
235
|
+
if (window.ProcessMaker && window.ProcessMaker.packages && window.ProcessMaker.packages.includes('package-vocabularies')) {
|
|
231
236
|
window.ProcessMaker.VocabulariesSchemaUrl = `vocabularies/task_schema/${this.taskId}`;
|
|
232
237
|
}
|
|
233
238
|
|
|
@@ -252,6 +257,7 @@ export default {
|
|
|
252
257
|
|
|
253
258
|
if (this.task.process_request.status === 'ERROR') {
|
|
254
259
|
this.hasErrors = true;
|
|
260
|
+
this.$emit('error', this.requestId);
|
|
255
261
|
} else {
|
|
256
262
|
this.hasErrors = false;
|
|
257
263
|
}
|
|
@@ -291,12 +297,25 @@ export default {
|
|
|
291
297
|
this.$emit('closed', this.task.id);
|
|
292
298
|
}
|
|
293
299
|
},
|
|
294
|
-
loadNextAssignedTask() {
|
|
295
|
-
|
|
300
|
+
loadNextAssignedTask(requestId = null) {
|
|
301
|
+
if (!requestId) {
|
|
302
|
+
requestId = this.requestId;
|
|
303
|
+
}
|
|
304
|
+
const url = `?user_id=${this.userId}&status=ACTIVE&process_request_id=${requestId}&include_sub_tasks=1`;
|
|
296
305
|
return this.$dataProvider
|
|
297
306
|
.getTasks(url).then((response) => {
|
|
298
307
|
if (response.data.data.length > 0) {
|
|
299
308
|
let task = response.data.data[0];
|
|
309
|
+
if (task.process_request_id !== this.requestId) {
|
|
310
|
+
// Next task is in a subprocess, do a hard redirect
|
|
311
|
+
if (this.redirecting === task.process_request_id) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
this.unsubscribeSocketListeners();
|
|
315
|
+
this.redirecting = task.process_request_id;
|
|
316
|
+
this.$emit('redirect', task);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
300
319
|
this.taskId = task.id;
|
|
301
320
|
this.nodeId = task.element_id;
|
|
302
321
|
}
|
|
@@ -336,29 +355,32 @@ export default {
|
|
|
336
355
|
},
|
|
337
356
|
onUpdate(data) {
|
|
338
357
|
this.$emit('input', data);
|
|
339
|
-
window.ProcessMaker.EventBus.$emit('form-data-updated', data);
|
|
340
358
|
},
|
|
341
359
|
|
|
342
360
|
activityAssigned() {
|
|
343
361
|
// This may no longer be needed
|
|
344
362
|
},
|
|
345
363
|
processCompleted() {
|
|
364
|
+
if (this.parentRequest && this.task.allow_interstitial) {
|
|
365
|
+
// There could be another task in the parent, so don't emit completed
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
346
368
|
this.$emit('completed', this.requestId);
|
|
347
369
|
},
|
|
348
|
-
processUpdated(data) {
|
|
370
|
+
processUpdated: _.debounce(function(data) {
|
|
349
371
|
if (
|
|
350
372
|
data.event === 'ACTIVITY_COMPLETED' ||
|
|
351
373
|
data.event === 'ACTIVITY_ACTIVATED'
|
|
352
374
|
) {
|
|
353
375
|
this.reload();
|
|
354
376
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (this.socketListeners.length > 0) {
|
|
358
|
-
return;
|
|
377
|
+
if (data.event === 'ACTIVITY_EXCEPTION') {
|
|
378
|
+
this.$emit('error', this.requestId);
|
|
359
379
|
}
|
|
360
|
-
|
|
380
|
+
}, 300),
|
|
381
|
+
initSocketListeners() {
|
|
361
382
|
this.addSocketListener(
|
|
383
|
+
`completed-${this.requestId}`,
|
|
362
384
|
`ProcessMaker.Models.ProcessRequest.${this.requestId}`,
|
|
363
385
|
'.ProcessCompleted',
|
|
364
386
|
(data) => {
|
|
@@ -367,6 +389,7 @@ export default {
|
|
|
367
389
|
);
|
|
368
390
|
|
|
369
391
|
this.addSocketListener(
|
|
392
|
+
`updated-${this.requestId}`,
|
|
370
393
|
`ProcessMaker.Models.ProcessRequest.${this.requestId}`,
|
|
371
394
|
'.ProcessUpdated',
|
|
372
395
|
(data) => {
|
|
@@ -380,18 +403,41 @@ export default {
|
|
|
380
403
|
this.reload();
|
|
381
404
|
}
|
|
382
405
|
},
|
|
383
|
-
|
|
384
|
-
this.
|
|
406
|
+
listenForParentChanges() {
|
|
407
|
+
if (!this.parentRequest) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
this.addSocketListener(
|
|
411
|
+
`parent-${this.requestId}`,
|
|
412
|
+
`ProcessMaker.Models.ProcessRequest.${this.parentRequest}`,
|
|
413
|
+
'.ProcessUpdated',
|
|
414
|
+
(data) => {
|
|
415
|
+
if (['ACTIVITY_COMPLETED', 'ACTIVITY_ACTIVATED'].includes(data.event)) {
|
|
416
|
+
this.loadNextAssignedTask(this.parentRequest);
|
|
417
|
+
}
|
|
418
|
+
if (data.event === 'ACTIVITY_EXCEPTION') {
|
|
419
|
+
this.$emit('error', this.requestId);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
},
|
|
424
|
+
addSocketListener(key, channel, event, callback) {
|
|
425
|
+
if (key in this.socketListeners) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
this.socketListeners[key] = {
|
|
385
429
|
channel,
|
|
386
430
|
event,
|
|
431
|
+
};
|
|
432
|
+
window.Echo.private(channel).listen(event, (data) => {
|
|
433
|
+
callback(data);
|
|
387
434
|
});
|
|
388
|
-
window.Echo.private(channel).listen(event, callback);
|
|
389
435
|
},
|
|
390
436
|
unsubscribeSocketListeners() {
|
|
391
|
-
this.socketListeners.forEach(
|
|
437
|
+
Object.values(this.socketListeners).forEach(element => {
|
|
392
438
|
window.Echo.private(element.channel).stopListening(element.event);
|
|
393
439
|
});
|
|
394
|
-
this.socketListeners =
|
|
440
|
+
this.socketListeners = {};
|
|
395
441
|
},
|
|
396
442
|
obtainPayload(url) {
|
|
397
443
|
return new Promise((resolve) => {
|