@processmaker/screen-builder 2.20.1 → 2.23.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 +6904 -4686
- package/dist/vue-form-builder.common.js.map +1 -1
- package/dist/vue-form-builder.umd.js +6904 -4686
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/dist/vue-form-builder.umd.min.js +9 -9
- package/dist/vue-form-builder.umd.min.js.map +1 -1
- package/package-lock.json +19334 -0
- package/package.json +3 -3
- package/src/DataProvider.js +6 -2
- package/src/ValidationsFactory.js +76 -21
- package/src/components/.DS_Store +0 -0
- package/src/components/renderer/form-record-list.vue +38 -6
- package/src/components/screen-renderer.vue +9 -5
- package/src/components/task.vue +25 -9
- package/src/form-control-common-properties.js +2 -1
- package/src/main.js +11 -1
- package/src/mixins/Json2Vue.js +40 -11
- package/src/mixins/ScreenBase.js +9 -1
- package/src/mixins/ValidationRules.js +3 -0
- package/src/mixins/extensions/LoadFieldComponents.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@processmaker/screen-builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"serve": "vue-cli-service serve",
|
|
6
6
|
"build": "vue-cli-service build",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@cypress/code-coverage": "^3.8.1",
|
|
45
45
|
"@fortawesome/fontawesome-free": "^5.6.1",
|
|
46
46
|
"@panter/vue-i18next": "^0.15.2",
|
|
47
|
-
"@processmaker/vue-form-elements": "0.28.
|
|
47
|
+
"@processmaker/vue-form-elements": "0.28.6",
|
|
48
48
|
"@processmaker/vue-multiselect": "^2.2.0",
|
|
49
49
|
"@vue/cli-plugin-babel": "^3.6.0",
|
|
50
50
|
"@vue/cli-plugin-e2e-cypress": "^4.0.3",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
87
|
"@panter/vue-i18next": "^0.15.0",
|
|
88
|
-
"@processmaker/vue-form-elements": "0.28.
|
|
88
|
+
"@processmaker/vue-form-elements": "0.28.6",
|
|
89
89
|
"i18next": "^15.0.8",
|
|
90
90
|
"vue": "^2.6.12",
|
|
91
91
|
"vuex": "^3.1.1"
|
package/src/DataProvider.js
CHANGED
|
@@ -88,10 +88,14 @@ export default {
|
|
|
88
88
|
}
|
|
89
89
|
else {
|
|
90
90
|
const endpoint = _.get(window, 'PM4ConfigOverrides.getScreenEndpoint', '/screens');
|
|
91
|
-
|
|
91
|
+
|
|
92
|
+
const screensCacheHit = this.screensCache.find(screen => screen.id == id);
|
|
93
|
+
if (screensCacheHit) {
|
|
94
|
+
return Promise.resolve({data: screensCacheHit});
|
|
95
|
+
}
|
|
92
96
|
|
|
93
97
|
let screenPromise = new Promise((resolve, reject) => {
|
|
94
|
-
|
|
98
|
+
this.get(endpoint + `/${id}${query}`)
|
|
95
99
|
.then(response => {
|
|
96
100
|
if (response.data.nested) {
|
|
97
101
|
this.addNestedScreenCache(response.data.nested);
|
|
@@ -34,7 +34,7 @@ class Validations {
|
|
|
34
34
|
isVisible() {
|
|
35
35
|
// Disable validations if field is hidden
|
|
36
36
|
let visible = true;
|
|
37
|
-
if (this.element.config.conditionalHide) {
|
|
37
|
+
if (!this.data.noData && this.element.config.conditionalHide) {
|
|
38
38
|
try {
|
|
39
39
|
visible = !!Parser.evaluate(this.element.config.conditionalHide, this.data);
|
|
40
40
|
} catch (error) {
|
|
@@ -51,7 +51,7 @@ class Validations {
|
|
|
51
51
|
class ArrayOfFieldsValidations extends Validations {
|
|
52
52
|
async addValidations(validations) {
|
|
53
53
|
for (const item of this.element) {
|
|
54
|
-
await ValidationsFactory(item, { screen: this.screen, data: this.data }).addValidations(validations);
|
|
54
|
+
await ValidationsFactory(item, { screen: this.screen, data: this.data, parentVisibilityRule: this.parentVisibilityRule }).addValidations(validations);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -81,8 +81,9 @@ class FormNestedScreenValidations extends Validations {
|
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
const definition = await this.loadScreen(this.element.config.screen);
|
|
84
|
+
let parentVisibilityRule = this.parentVisibilityRule ? this.parentVisibilityRule : this.element.config.conditionalHide;
|
|
84
85
|
if (definition && definition[0] && definition[0].items) {
|
|
85
|
-
await ValidationsFactory(definition[0].items, { screen: this.screen, data: this.data }).addValidations(validations);
|
|
86
|
+
await ValidationsFactory(definition[0].items, { screen: this.screen, data: this.data, parentVisibilityRule }).addValidations(validations);
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -112,8 +113,7 @@ class FormLoopValidations extends Validations {
|
|
|
112
113
|
set(validations, this.element.config.name, {});
|
|
113
114
|
const loopField = get(validations, this.element.config.name);
|
|
114
115
|
loopField['$each'] = {};
|
|
115
|
-
|
|
116
|
-
await ValidationsFactory(this.element.items, { screen: this.screen, data: {_parent: this.data, ...firstRow } }).addValidations(loopField['$each']);
|
|
116
|
+
await ValidationsFactory(this.element.items, { screen: this.screen, data: {_parent: this.data, noData:true }, parentVisibilityRule: this.element.config.conditionalHide }).addValidations(loopField['$each']);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -126,7 +126,7 @@ class FormMultiColumnValidations extends Validations {
|
|
|
126
126
|
if (!this.isVisible()) {
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
|
-
await ValidationsFactory(this.element.items, { screen: this.screen, data: this.data }).addValidations(validations);
|
|
129
|
+
await ValidationsFactory(this.element.items, { screen: this.screen, data: this.data, parentVisibilityRule: this.element.config.conditionalHide }).addValidations(validations);
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -167,19 +167,8 @@ class FormElementValidations extends Validations {
|
|
|
167
167
|
}
|
|
168
168
|
const fieldName = this.element.config.name;
|
|
169
169
|
const validationConfig = this.element.config.validation;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (this.element.config.conditionalHide) {
|
|
173
|
-
let visible = true;
|
|
174
|
-
try {
|
|
175
|
-
visible = !!Parser.evaluate(this.element.config.conditionalHide, this.data);
|
|
176
|
-
} catch (error) {
|
|
177
|
-
visible = false;
|
|
178
|
-
}
|
|
179
|
-
if (!visible) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
170
|
+
const conditionalHide = this.element.config.conditionalHide;
|
|
171
|
+
const parentVisibilityRule = this.parentVisibilityRule;
|
|
183
172
|
|
|
184
173
|
set(validations, fieldName, get(validations, fieldName, {}));
|
|
185
174
|
const fieldValidation = get(validations, fieldName);
|
|
@@ -203,7 +192,40 @@ class FormElementValidations extends Validations {
|
|
|
203
192
|
params.push(fieldName);
|
|
204
193
|
validationFn = validationFn(...params);
|
|
205
194
|
}
|
|
206
|
-
fieldValidation[rule] =
|
|
195
|
+
fieldValidation[rule] = function(...props) {
|
|
196
|
+
const data = props[1];
|
|
197
|
+
let dataWithParent = this.addReferenceToParents(data);
|
|
198
|
+
const nestedDataWithParent = this.addReferenceToParents(this.findParent(data));
|
|
199
|
+
if (nestedDataWithParent) {
|
|
200
|
+
dataWithParent = Object.assign(nestedDataWithParent, dataWithParent);
|
|
201
|
+
}
|
|
202
|
+
// Check Parent Visibility
|
|
203
|
+
if (parentVisibilityRule) {
|
|
204
|
+
let isParentVisible = true;
|
|
205
|
+
try {
|
|
206
|
+
isParentVisible = !!Parser.evaluate(parentVisibilityRule, dataWithParent);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
isParentVisible = false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!isParentVisible ) {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Check Field Visibility
|
|
216
|
+
let visible = true;
|
|
217
|
+
if (conditionalHide) {
|
|
218
|
+
try {
|
|
219
|
+
visible = !!Parser.evaluate(conditionalHide, dataWithParent);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
visible = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!visible) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
return validationFn.apply(this,props);
|
|
228
|
+
};
|
|
207
229
|
});
|
|
208
230
|
} else if (typeof validationConfig === 'string' && validationConfig) {
|
|
209
231
|
let validationFn = validators[validationConfig];
|
|
@@ -212,7 +234,40 @@ class FormElementValidations extends Validations {
|
|
|
212
234
|
console.error(`Undefined validation rule "${validationConfig}"`);
|
|
213
235
|
return;
|
|
214
236
|
}
|
|
215
|
-
fieldValidation[validationConfig] =
|
|
237
|
+
fieldValidation[validationConfig] = function(...props) {
|
|
238
|
+
const data = props[1];
|
|
239
|
+
let dataWithParent = this.addReferenceToParents(data);
|
|
240
|
+
const nestedDataWithParent = this.addReferenceToParents(this.findParent(data));
|
|
241
|
+
if (nestedDataWithParent) {
|
|
242
|
+
dataWithParent = Object.assign(nestedDataWithParent, dataWithParent);
|
|
243
|
+
}
|
|
244
|
+
// Check Parent Visibility
|
|
245
|
+
if (parentVisibilityRule) {
|
|
246
|
+
let isParentVisible = true;
|
|
247
|
+
try {
|
|
248
|
+
isParentVisible = !!Parser.evaluate(parentVisibilityRule, dataWithParent);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
isParentVisible = false;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!isParentVisible) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Check Field Visibility
|
|
258
|
+
let visible = true;
|
|
259
|
+
if (conditionalHide) {
|
|
260
|
+
try {
|
|
261
|
+
visible = !!Parser.evaluate(conditionalHide, dataWithParent);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
visible = false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (!visible) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return validationFn.apply(this,props);
|
|
270
|
+
};
|
|
216
271
|
}
|
|
217
272
|
if (this.element.items) {
|
|
218
273
|
ValidationsFactory(this.element.items, { screen: this.screen, data: this.data }).addValidations(validations);
|
|
Binary file
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
:css="css"
|
|
25
25
|
:empty-text="$t('No Data Available')"
|
|
26
26
|
:current-page="currentPage"
|
|
27
|
+
@sort-changed="sortChanged"
|
|
28
|
+
@input="onInput"
|
|
27
29
|
data-cy="table"
|
|
28
30
|
>
|
|
29
31
|
<template #cell()="{index,field,item}">
|
|
@@ -74,6 +76,7 @@
|
|
|
74
76
|
:title="$t('Add')"
|
|
75
77
|
header-close-content="×"
|
|
76
78
|
data-cy="modal-add"
|
|
79
|
+
@shown="emitShownEvent"
|
|
77
80
|
>
|
|
78
81
|
<vue-form-renderer
|
|
79
82
|
:page="0"
|
|
@@ -99,6 +102,7 @@
|
|
|
99
102
|
:title="$t('Edit Record')"
|
|
100
103
|
header-close-content="×"
|
|
101
104
|
data-cy="modal-edit"
|
|
105
|
+
@shown="emitShownEvent"
|
|
102
106
|
>
|
|
103
107
|
<vue-form-renderer
|
|
104
108
|
:page="0"
|
|
@@ -161,7 +165,7 @@ const jsonOptionsActionsColumn = {
|
|
|
161
165
|
|
|
162
166
|
export default {
|
|
163
167
|
mixins: [mustacheEvaluation],
|
|
164
|
-
props: ['name', 'label', 'fields', 'value', 'editable', '_config', 'form', 'validationData', 'formConfig', 'formComputed', 'formWatchers'],
|
|
168
|
+
props: ['name', 'label', 'fields', 'value', 'editable', '_config', 'form', 'validationData', 'formConfig', 'formComputed', 'formWatchers', '_perPage'],
|
|
165
169
|
data() {
|
|
166
170
|
return {
|
|
167
171
|
editFormVersion: 0,
|
|
@@ -192,6 +196,11 @@ export default {
|
|
|
192
196
|
initFormValues: {},
|
|
193
197
|
};
|
|
194
198
|
},
|
|
199
|
+
mounted() {
|
|
200
|
+
if (this._perPage) {
|
|
201
|
+
this.perPage = this._perPage;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
195
204
|
computed: {
|
|
196
205
|
popupConfig() {
|
|
197
206
|
const config = [];
|
|
@@ -240,6 +249,7 @@ export default {
|
|
|
240
249
|
from,
|
|
241
250
|
to: value.length,
|
|
242
251
|
data: value,
|
|
252
|
+
lastSortConfig: false,
|
|
243
253
|
};
|
|
244
254
|
return data;
|
|
245
255
|
},
|
|
@@ -258,7 +268,28 @@ export default {
|
|
|
258
268
|
return this.form && this.form === this.$parent.currentPage;
|
|
259
269
|
},
|
|
260
270
|
},
|
|
271
|
+
watch: {
|
|
272
|
+
'tableData.total': {
|
|
273
|
+
deep: true,
|
|
274
|
+
handler(total) {
|
|
275
|
+
let totalPages = Math.ceil(total / this.perPage);
|
|
276
|
+
this.currentPage = (this.currentPage > totalPages ? totalPages : this.currentPage);
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
261
280
|
methods: {
|
|
281
|
+
sortChanged(payload) {
|
|
282
|
+
this.lastSortConfig = payload;
|
|
283
|
+
this.tableData.data = _.orderBy(this.tableData.data, [payload.sortBy], [(payload.sortDesc ? 'desc' : 'asc')]);
|
|
284
|
+
},
|
|
285
|
+
onInput() {
|
|
286
|
+
if (this.lastSortConfig) {
|
|
287
|
+
this.tableData.data = _.orderBy(this.tableData.data, [this.lastSortConfig.sortBy], [(this.lastSortConfig.sortDesc ? 'desc' : 'asc')]);
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
emitShownEvent() {
|
|
291
|
+
window.ProcessMaker.EventBus.$emit('modal-shown');
|
|
292
|
+
},
|
|
262
293
|
formatIfDate(string) {
|
|
263
294
|
return dateUtils.formatIfDate(string);
|
|
264
295
|
},
|
|
@@ -339,7 +370,7 @@ export default {
|
|
|
339
370
|
showEditForm(index) {
|
|
340
371
|
let pageIndex = ((this.paginatorPage-1) * this.perPage) + index;
|
|
341
372
|
// Reset edit to be a copy of our data model item
|
|
342
|
-
this.editItem = JSON.parse(JSON.stringify(this.
|
|
373
|
+
this.editItem = JSON.parse(JSON.stringify(this.tableData.data[pageIndex]));
|
|
343
374
|
this.editIndex = pageIndex;
|
|
344
375
|
// rebuild the edit screen to avoid
|
|
345
376
|
this.editFormVersion++;
|
|
@@ -349,13 +380,13 @@ export default {
|
|
|
349
380
|
});
|
|
350
381
|
},
|
|
351
382
|
edit(event) {
|
|
352
|
-
if (this.$refs.editRenderer.$refs.renderer.$refs.component.$v.$invalid) {
|
|
383
|
+
if (this.$refs.editRenderer.$refs.renderer.$refs.component.$v.vdata.$invalid) {
|
|
353
384
|
event.preventDefault();
|
|
354
385
|
return;
|
|
355
386
|
}
|
|
356
387
|
|
|
357
388
|
// Edit the item in our model and emit change
|
|
358
|
-
let data = this.
|
|
389
|
+
let data = this.tableData.data ? JSON.parse(JSON.stringify(this.tableData.data)) : [];
|
|
359
390
|
data[this.editIndex] = JSON.parse(JSON.stringify(this.editItem));
|
|
360
391
|
|
|
361
392
|
// Remove the parent object
|
|
@@ -382,7 +413,7 @@ export default {
|
|
|
382
413
|
handleOk(bvModalEvt) {
|
|
383
414
|
bvModalEvt.preventDefault();
|
|
384
415
|
|
|
385
|
-
if (this.$refs.addRenderer.$refs.renderer.$refs.component.$v.$invalid) {
|
|
416
|
+
if (this.$refs.addRenderer.$refs.renderer.$refs.component.$v.vdata.$invalid) {
|
|
386
417
|
return;
|
|
387
418
|
}
|
|
388
419
|
|
|
@@ -442,7 +473,7 @@ export default {
|
|
|
442
473
|
remove() {
|
|
443
474
|
// Add the item to our model and emit change
|
|
444
475
|
// @todo Also check that value is an array type, if not, reset it to an array
|
|
445
|
-
let data = this.
|
|
476
|
+
let data = this.tableData.data ? JSON.parse(JSON.stringify(this.tableData.data)) : [];
|
|
446
477
|
let recordData = data[this.deleteIndex];
|
|
447
478
|
// Remove item from data array
|
|
448
479
|
data.splice(this.deleteIndex, 1);
|
|
@@ -459,3 +490,4 @@ export default {
|
|
|
459
490
|
max-width: 300px;
|
|
460
491
|
}
|
|
461
492
|
</style>
|
|
493
|
+
|
|
@@ -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
|
@@ -242,6 +242,11 @@ export default {
|
|
|
242
242
|
.then((response) => {
|
|
243
243
|
this.task = response.data;
|
|
244
244
|
this.checkTaskStatus();
|
|
245
|
+
if (window.PM4ConfigOverrides.getScreenEndpoint && window.PM4ConfigOverrides.getScreenEndpoint.includes('tasks/')) {
|
|
246
|
+
const screenPath = window.PM4ConfigOverrides.getScreenEndpoint.split('/');
|
|
247
|
+
screenPath[1] = this.task.id;
|
|
248
|
+
window.PM4ConfigOverrides.getScreenEndpoint = screenPath.join('/');
|
|
249
|
+
}
|
|
245
250
|
})
|
|
246
251
|
.catch(() => {
|
|
247
252
|
this.hasErrors = true;
|
|
@@ -279,19 +284,19 @@ export default {
|
|
|
279
284
|
}
|
|
280
285
|
this.prepareTask();
|
|
281
286
|
},
|
|
282
|
-
closeTask() {
|
|
287
|
+
closeTask(parentRequestId = null) {
|
|
283
288
|
if (this.hasErrors) {
|
|
284
289
|
this.$emit('error', this.requestId);
|
|
285
290
|
return;
|
|
286
291
|
}
|
|
287
292
|
|
|
288
293
|
if (this.task.process_request.status === 'COMPLETED') {
|
|
289
|
-
this.
|
|
294
|
+
this.loadNextAssignedTask(parentRequestId);
|
|
290
295
|
|
|
291
296
|
} else if (this.task.allow_interstitial) {
|
|
292
297
|
this.task.interstitial_screen['_interstitial'] = true;
|
|
293
298
|
this.screen = this.task.interstitial_screen;
|
|
294
|
-
this.loadNextAssignedTask();
|
|
299
|
+
this.loadNextAssignedTask(parentRequestId);
|
|
295
300
|
|
|
296
301
|
} else {
|
|
297
302
|
this.$emit('closed', this.task.id);
|
|
@@ -313,11 +318,18 @@ export default {
|
|
|
313
318
|
}
|
|
314
319
|
this.unsubscribeSocketListeners();
|
|
315
320
|
this.redirecting = task.process_request_id;
|
|
316
|
-
this.$emit('redirect', task);
|
|
321
|
+
this.$emit('redirect', task.id, true);
|
|
317
322
|
return;
|
|
323
|
+
} else {
|
|
324
|
+
// Only emit completed after getting the subprocess tasks and there are no tasks and process is completed
|
|
325
|
+
if (requestId == this.task.process_request_id && this.parentRequest && this.task.process_request.status === 'COMPLETED') {
|
|
326
|
+
this.$emit('completed', this.parentRequest);
|
|
327
|
+
}
|
|
318
328
|
}
|
|
319
329
|
this.taskId = task.id;
|
|
320
330
|
this.nodeId = task.element_id;
|
|
331
|
+
} else {
|
|
332
|
+
this.$emit('completed', (this.parentRequest ? this.parentRequest : requestId));
|
|
321
333
|
}
|
|
322
334
|
});
|
|
323
335
|
},
|
|
@@ -361,9 +373,8 @@ export default {
|
|
|
361
373
|
// This may no longer be needed
|
|
362
374
|
},
|
|
363
375
|
processCompleted() {
|
|
364
|
-
if (this.parentRequest
|
|
365
|
-
|
|
366
|
-
return;
|
|
376
|
+
if (this.parentRequest) {
|
|
377
|
+
this.$emit('completed', this.parentRequest);
|
|
367
378
|
}
|
|
368
379
|
this.$emit('completed', this.requestId);
|
|
369
380
|
},
|
|
@@ -412,8 +423,13 @@ export default {
|
|
|
412
423
|
`ProcessMaker.Models.ProcessRequest.${this.parentRequest}`,
|
|
413
424
|
'.ProcessUpdated',
|
|
414
425
|
(data) => {
|
|
415
|
-
if (['
|
|
416
|
-
this.
|
|
426
|
+
if (['ACTIVITY_ACTIVATED'].includes(data.event)) {
|
|
427
|
+
this.closeTask(this.parentRequest);
|
|
428
|
+
}
|
|
429
|
+
if (['ACTIVITY_COMPLETED'].includes(data.event)) {
|
|
430
|
+
if (this.task.process_request.status === 'COMPLETED') {
|
|
431
|
+
this.processCompleted();
|
|
432
|
+
}
|
|
417
433
|
}
|
|
418
434
|
if (data.event === 'ACTIVITY_EXCEPTION') {
|
|
419
435
|
this.$emit('error', this.requestId);
|
|
@@ -96,7 +96,8 @@ export const keyNameProperty = {
|
|
|
96
96
|
config: {
|
|
97
97
|
label: 'Variable Name',
|
|
98
98
|
name: 'Variable Name',
|
|
99
|
-
|
|
99
|
+
// Update tests/e2e/specs/Builder.spec.js when changing this
|
|
100
|
+
validation: 'regex:/^([a-zA-Z]([a-zA-Z0-9_]?)+\\.?)+(?<!\\.)$/|required|not_in:' + javascriptReservedKeywords,
|
|
100
101
|
helper: 'A variable name is a symbolic name to reference information.',
|
|
101
102
|
},
|
|
102
103
|
};
|
package/src/main.js
CHANGED
|
@@ -152,7 +152,7 @@ window.ProcessMaker = {
|
|
|
152
152
|
{value: 2, content: 'John'},
|
|
153
153
|
{value: 3, content: 'Mary'},
|
|
154
154
|
{value: 4, content: 'Patricia'},
|
|
155
|
-
],
|
|
155
|
+
],
|
|
156
156
|
}});
|
|
157
157
|
break;
|
|
158
158
|
default:
|
|
@@ -201,6 +201,16 @@ window.Echo = {
|
|
|
201
201
|
}, 1000);
|
|
202
202
|
});
|
|
203
203
|
},
|
|
204
|
+
eventMocks(event, response) {
|
|
205
|
+
this.listeners.forEach((listener) => {
|
|
206
|
+
setTimeout(() => {
|
|
207
|
+
listener.callback({
|
|
208
|
+
type: event,
|
|
209
|
+
response,
|
|
210
|
+
});
|
|
211
|
+
}, 1000);
|
|
212
|
+
});
|
|
213
|
+
},
|
|
204
214
|
private() {
|
|
205
215
|
return {
|
|
206
216
|
notification(callback) {
|
package/src/mixins/Json2Vue.js
CHANGED
|
@@ -2,7 +2,7 @@ import extensions from './extensions';
|
|
|
2
2
|
import ScreenBase from './ScreenBase';
|
|
3
3
|
import CountElements from '../CountElements';
|
|
4
4
|
import ValidationsFactory from '../ValidationsFactory';
|
|
5
|
-
import _ from 'lodash';
|
|
5
|
+
import _, { debounce, isEqual } from 'lodash';
|
|
6
6
|
|
|
7
7
|
let screenRenderer;
|
|
8
8
|
|
|
@@ -214,7 +214,12 @@ export default {
|
|
|
214
214
|
return name && typeof name === 'string' && name.match(/^[a-zA-Z_][0-9a-zA-Z_.]*$/);
|
|
215
215
|
},
|
|
216
216
|
isComputedVariable(name, definition) {
|
|
217
|
-
return definition.computed && definition.computed.
|
|
217
|
+
return definition.computed && definition.computed.some(computed => {
|
|
218
|
+
// Check if the first part of an element's name (up to the first `.`)
|
|
219
|
+
// matches the name of a computed property.
|
|
220
|
+
const regex = new RegExp(`^${computed.property}(\\.|$)`, 'i');
|
|
221
|
+
return regex.test(name);
|
|
222
|
+
});
|
|
218
223
|
},
|
|
219
224
|
registerVariable(name, element = {}) {
|
|
220
225
|
if (!this.validVariableName(name)) {
|
|
@@ -336,19 +341,43 @@ export default {
|
|
|
336
341
|
},
|
|
337
342
|
addValidationRulesLoader(component, definition) {
|
|
338
343
|
const firstPage = parseInt(this.currentPage) || 0;
|
|
344
|
+
function getKeys(input) {
|
|
345
|
+
if (input instanceof Array) {
|
|
346
|
+
const response = [];
|
|
347
|
+
input.forEach((item) => {
|
|
348
|
+
response.push(getKeys(item));
|
|
349
|
+
});
|
|
350
|
+
return response;
|
|
351
|
+
}
|
|
352
|
+
if (!(input instanceof Object)) {
|
|
353
|
+
return typeof input;
|
|
354
|
+
}
|
|
355
|
+
const keys = Object.keys(input);
|
|
356
|
+
const response = {};
|
|
357
|
+
keys.forEach((key) => {
|
|
358
|
+
response[key] = getKeys(input[key]);
|
|
359
|
+
});
|
|
360
|
+
return response;
|
|
361
|
+
}
|
|
362
|
+
let updateValidationRules = function(screenComponent, validations) {
|
|
363
|
+
const a = getKeys(screenComponent.ValidationRules__);
|
|
364
|
+
const b = getKeys(validations);
|
|
365
|
+
if (isEqual(a, b)) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
screenComponent.ValidationRules__ = validations;
|
|
369
|
+
screenComponent.$nextTick(() => {
|
|
370
|
+
if (screenComponent.$v) {
|
|
371
|
+
screenComponent.$v.$touch();
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
};
|
|
375
|
+
updateValidationRules = debounce(updateValidationRules, 25);
|
|
339
376
|
component.methods.loadValidationRules = function() {
|
|
340
377
|
// Asynchronous loading of validations
|
|
341
378
|
const validations = {};
|
|
342
379
|
ValidationsFactory(definition, { screen: definition, firstPage, data: {_parent: this._parent, ...this.vdata} }).addValidations(validations).then(() => {
|
|
343
|
-
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
this.ValidationRules__ = validations;
|
|
347
|
-
this.$nextTick(() => {
|
|
348
|
-
if (this.$v) {
|
|
349
|
-
this.$v.$touch();
|
|
350
|
-
}
|
|
351
|
-
});
|
|
380
|
+
updateValidationRules(this, validations);
|
|
352
381
|
});
|
|
353
382
|
};
|
|
354
383
|
component.mounted.push('this.loadValidationRules()');
|
package/src/mixins/ScreenBase.js
CHANGED
|
@@ -102,7 +102,15 @@ export default {
|
|
|
102
102
|
},
|
|
103
103
|
mustache(text) {
|
|
104
104
|
try {
|
|
105
|
-
const data =
|
|
105
|
+
const data = new Proxy(this, {
|
|
106
|
+
get(target, name) {
|
|
107
|
+
if (name === '_parent') {
|
|
108
|
+
return target._parent;
|
|
109
|
+
} else {
|
|
110
|
+
return target.vdata[name];
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
106
114
|
return text && Mustache.render(text, data);
|
|
107
115
|
} catch (e) {
|
|
108
116
|
return 'MUSTACHE: ' + e.message;
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
and,
|
|
24
24
|
maxItems,
|
|
25
25
|
minItems,
|
|
26
|
+
type,
|
|
26
27
|
} from 'vuelidate/lib/validators';
|
|
27
28
|
|
|
28
29
|
export const ValidationMsg = {
|
|
@@ -59,6 +60,7 @@ export const ValidationMsg = {
|
|
|
59
60
|
regex: 'Invalid value',
|
|
60
61
|
maxItems: 'Should NOT have more than {max} items',
|
|
61
62
|
minItems: 'Must have at least {min}',
|
|
63
|
+
type: 'Invalid type',
|
|
62
64
|
};
|
|
63
65
|
|
|
64
66
|
export const custom_date = (date) => {
|
|
@@ -231,4 +233,5 @@ export const validators = {
|
|
|
231
233
|
afterOrEqual: after_or_equal,
|
|
232
234
|
maxItems,
|
|
233
235
|
minItems,
|
|
236
|
+
type,
|
|
234
237
|
};
|
|
@@ -69,7 +69,7 @@ export default {
|
|
|
69
69
|
properties[':form-computed'] = JSON.stringify(definition.computed);
|
|
70
70
|
properties[':form-watchers'] = JSON.stringify(definition.watchers);
|
|
71
71
|
// Check if control is assigned to a calculated property
|
|
72
|
-
const isCalcProp =
|
|
72
|
+
const isCalcProp = this.isComputedVariable(element.config.name, definition);
|
|
73
73
|
properties[':readonly'] = isCalcProp || element.config.readonly;
|
|
74
74
|
properties[':disabled'] = isCalcProp || element.config.disabled;
|
|
75
75
|
// Events
|