@processmaker/screen-builder 2.60.3 → 2.61.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 +8418 -5953
- 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 +8418 -5953
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/dist/vue-form-builder.umd.min.js +17 -17
- package/dist/vue-form-builder.umd.min.js.map +1 -1
- package/package.json +3 -3
- package/src/.DS_Store +0 -0
- package/src/App.vue +3 -0
- package/src/components/index.js +23 -0
- package/src/components/renderer/add-loop-row.vue +3 -1
- package/src/components/renderer/form-button.vue +4 -13
- package/src/components/renderer/form-image.vue +3 -1
- package/src/components/renderer/form-masked-input.vue +6 -0
- package/src/components/renderer/form-record-list.vue +2 -2
- package/src/mixins/DataReference.js +12 -2
- package/src/mixins/Json2Vue.js +67 -10
- package/src/mixins/ScreenBase.js +92 -5
- package/src/mixins/VisibilityRule.js +4 -21
- package/src/mixins/extensions/ComputedFields.js +27 -31
- package/src/mixins/extensions/DataManager.js +41 -15
- package/src/mixins/extensions/DefaultValues.js +5 -5
- package/src/mixins/extensions/LoadFieldComponents.js +60 -36
- package/src/mixins/extensions/LoopContainer.js +3 -11
- package/src/mixins/extensions/ValidationRules.js +26 -2
- package/src/mixins/extensions/Watchers.js +1 -1
- package/src/mixins/watchers.js +3 -3
- package/src/store/modules/globalErrorsModule.js +19 -4
- package/src/mixins/LoopControl.js +0 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@processmaker/screen-builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.61.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"serve": "vue-cli-service serve",
|
|
6
6
|
"build": "vue-cli-service build",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@cypress/code-coverage": "^3.8.1",
|
|
40
40
|
"@fortawesome/fontawesome-free": "^5.6.1",
|
|
41
41
|
"@panter/vue-i18next": "^0.15.2",
|
|
42
|
-
"@processmaker/vue-form-elements": "0.
|
|
42
|
+
"@processmaker/vue-form-elements": "0.42.0",
|
|
43
43
|
"@processmaker/vue-multiselect": "^2.2.0",
|
|
44
44
|
"@vue/cli-plugin-babel": "^3.6.0",
|
|
45
45
|
"@vue/cli-plugin-e2e-cypress": "^4.0.3",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
90
|
"@panter/vue-i18next": "^0.15.0",
|
|
91
|
-
"@processmaker/vue-form-elements": "0.
|
|
91
|
+
"@processmaker/vue-form-elements": "0.42.0",
|
|
92
92
|
"i18next": "^15.0.8",
|
|
93
93
|
"vue": "^2.6.12",
|
|
94
94
|
"vuex": "^3.1.1"
|
package/src/.DS_Store
CHANGED
|
Binary file
|
package/src/App.vue
CHANGED
|
@@ -218,6 +218,7 @@ import VueFormRenderer from './components/vue-form-renderer.vue';
|
|
|
218
218
|
import MonacoEditor from 'vue-monaco';
|
|
219
219
|
import canOpenJsonFile from './mixins/canOpenJsonFile';
|
|
220
220
|
import { cloneDeep, debounce } from 'lodash';
|
|
221
|
+
import { mapMutations } from 'vuex';
|
|
221
222
|
|
|
222
223
|
// Bring in our initial set of controls
|
|
223
224
|
import controlConfig from './form-builder-controls';
|
|
@@ -420,6 +421,7 @@ export default {
|
|
|
420
421
|
this.loadFromLocalStorage();
|
|
421
422
|
},
|
|
422
423
|
methods: {
|
|
424
|
+
...mapMutations("globalErrorsModule", { setStoreMode: "setMode" }),
|
|
423
425
|
// eslint-disable-next-line func-names
|
|
424
426
|
updateDataInput: debounce(function () {
|
|
425
427
|
this.updateDataInputNow();
|
|
@@ -456,6 +458,7 @@ export default {
|
|
|
456
458
|
} else {
|
|
457
459
|
this.$refs.builder.refreshContent();
|
|
458
460
|
}
|
|
461
|
+
this.setStoreMode(this.mode);
|
|
459
462
|
this.mode = mode;
|
|
460
463
|
},
|
|
461
464
|
loadFromLocalStorage() {
|
package/src/components/index.js
CHANGED
|
@@ -43,6 +43,22 @@ export {
|
|
|
43
43
|
Task,
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Gets the screen parent or null if don't have
|
|
48
|
+
* @returns {object|null}
|
|
49
|
+
*/
|
|
50
|
+
function findScreenOwner(control) {
|
|
51
|
+
let owner = control.$parent;
|
|
52
|
+
while (owner) {
|
|
53
|
+
const isScreen = owner.$options.name === "ScreenContent";
|
|
54
|
+
if (isScreen) {
|
|
55
|
+
return owner;
|
|
56
|
+
}
|
|
57
|
+
owner = owner.$parent;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
// Export our Vue plugin as our default
|
|
47
63
|
export default {
|
|
48
64
|
install(Vue) {
|
|
@@ -87,6 +103,13 @@ export default {
|
|
|
87
103
|
}
|
|
88
104
|
});
|
|
89
105
|
Vue.mixin({ store });
|
|
106
|
+
|
|
107
|
+
//Helper to access data reference.
|
|
108
|
+
Vue.mixin({ methods:{ getScreenDataReference(customProperties = null, setter = null) {
|
|
109
|
+
const control = this;
|
|
110
|
+
const screen = findScreenOwner(control);
|
|
111
|
+
return screen.getDataReference(customProperties, setter);
|
|
112
|
+
}}});
|
|
90
113
|
}
|
|
91
114
|
};
|
|
92
115
|
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
22
|
<script>
|
|
23
|
+
import { mapActions } from "vuex";
|
|
24
|
+
|
|
23
25
|
export default {
|
|
24
26
|
props: {
|
|
25
27
|
value: Array,
|
|
@@ -27,7 +29,7 @@ export default {
|
|
|
27
29
|
error: String,
|
|
28
30
|
},
|
|
29
31
|
methods: {
|
|
30
|
-
add() {
|
|
32
|
+
async add() {
|
|
31
33
|
this.value.push({});
|
|
32
34
|
},
|
|
33
35
|
remove() {
|
|
@@ -8,17 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import Mustache from 'mustache';
|
|
11
|
+
import { mapActions, mapState } from "vuex";
|
|
11
12
|
import { getValidPath } from '@/mixins';
|
|
12
|
-
|
|
13
|
+
|
|
13
14
|
|
|
14
15
|
export default {
|
|
15
16
|
mixins: [getValidPath],
|
|
16
17
|
props: ['variant', 'label', 'event', 'eventData', 'name', 'fieldValue', 'value', 'tooltip', 'transientData'],
|
|
17
|
-
watch: {
|
|
18
|
-
valid(valid) {
|
|
19
|
-
this.isInvalid = !valid;
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
18
|
computed: {
|
|
23
19
|
...mapState('globalErrorsModule', ['valid']),
|
|
24
20
|
classList() {
|
|
@@ -26,7 +22,7 @@ export default {
|
|
|
26
22
|
return {
|
|
27
23
|
btn: true,
|
|
28
24
|
['btn-' + variant]: true,
|
|
29
|
-
disabled: this.event === 'submit' && this.
|
|
25
|
+
disabled: this.event === 'submit' && !this.valid
|
|
30
26
|
};
|
|
31
27
|
},
|
|
32
28
|
options() {
|
|
@@ -49,11 +45,6 @@ export default {
|
|
|
49
45
|
};
|
|
50
46
|
},
|
|
51
47
|
},
|
|
52
|
-
data() {
|
|
53
|
-
return {
|
|
54
|
-
isInvalid: false,
|
|
55
|
-
};
|
|
56
|
-
},
|
|
57
48
|
methods: {
|
|
58
49
|
setValue(parent, name, value) {
|
|
59
50
|
if (parent) {
|
|
@@ -64,7 +55,7 @@ export default {
|
|
|
64
55
|
}
|
|
65
56
|
}
|
|
66
57
|
},
|
|
67
|
-
click() {
|
|
58
|
+
async click() {
|
|
68
59
|
if (this.event === 'script') {
|
|
69
60
|
const trueValue = this.fieldValue || '1';
|
|
70
61
|
const value = (this.value == trueValue) ? null : trueValue;
|
|
@@ -18,7 +18,9 @@ export default {
|
|
|
18
18
|
},
|
|
19
19
|
computed: {
|
|
20
20
|
imageUrl() {
|
|
21
|
-
|
|
21
|
+
if (this.mode !== 'editor') {
|
|
22
|
+
return get(this.getScreenDataReference(), this.variableName || this.imageName);
|
|
23
|
+
}
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
26
|
};
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
class="form-control"
|
|
12
12
|
:class="classList"
|
|
13
13
|
type="text"
|
|
14
|
+
@change="onChange"
|
|
14
15
|
/>
|
|
15
16
|
<input v-else
|
|
16
17
|
v-model="localValue"
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
:class="classList"
|
|
22
23
|
:type="dataType"
|
|
23
24
|
:maxlength="maxlength"
|
|
25
|
+
@change="onChange"
|
|
24
26
|
>
|
|
25
27
|
<template v-if="validator && validator.errorCount">
|
|
26
28
|
<div class="invalid-feedback" v-for="(errors, index) in validator.errors.all()" :key="index">
|
|
@@ -41,6 +43,7 @@ import { TheMask } from 'vue-the-mask';
|
|
|
41
43
|
import { getUserDateFormat, getUserDateTimeFormat } from '@processmaker/vue-form-elements/src/dateUtils';
|
|
42
44
|
import ValidationMixin from '@processmaker/vue-form-elements/src/components/mixins/validation';
|
|
43
45
|
import moment from 'moment';
|
|
46
|
+
import debounce from "lodash/debounce";
|
|
44
47
|
|
|
45
48
|
const uniqIdsMixin = createUniqIdsMixin();
|
|
46
49
|
const componentTypes = {
|
|
@@ -210,6 +213,9 @@ export default {
|
|
|
210
213
|
}
|
|
211
214
|
},
|
|
212
215
|
methods: {
|
|
216
|
+
onChange() {
|
|
217
|
+
this.$emit("change", this.convertToData(this.localValue));
|
|
218
|
+
},
|
|
213
219
|
getUserConfig() {
|
|
214
220
|
return (window.ProcessMaker && window.ProcessMaker.user) || {};
|
|
215
221
|
},
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
import mustacheEvaluation from '../../mixins/mustacheEvaluation';
|
|
157
157
|
import _ from 'lodash';
|
|
158
158
|
import { dateUtils } from '@processmaker/vue-form-elements';
|
|
159
|
-
|
|
159
|
+
import { mapActions, mapState } from "vuex";
|
|
160
160
|
|
|
161
161
|
const jsonOptionsActionsColumn = {
|
|
162
162
|
key: '__actions',
|
|
@@ -411,7 +411,7 @@ export default {
|
|
|
411
411
|
let {_parent, ...result} = this.addItem;
|
|
412
412
|
this.initFormValues = _.cloneDeep(result);
|
|
413
413
|
},
|
|
414
|
-
handleOk(bvModalEvt) {
|
|
414
|
+
async handleOk(bvModalEvt) {
|
|
415
415
|
bvModalEvt.preventDefault();
|
|
416
416
|
|
|
417
417
|
if (this.$refs.addRenderer.$refs.renderer.$refs.component.$v.vdata.$invalid) {
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Gets the screen parent or null if don't have
|
|
3
3
|
* @returns {object|null}
|
|
4
4
|
*/
|
|
5
|
-
function findScreenOwner(control) {
|
|
5
|
+
function findScreenOwner(control, lastScreenContentIfNull = false) {
|
|
6
6
|
let owner = control;
|
|
7
7
|
let level = 1;
|
|
8
|
+
let lastScreenContent = null;
|
|
8
9
|
while (owner) {
|
|
9
10
|
const isScreen = owner.$options.name === "ScreenContent";
|
|
10
11
|
const isNested = owner.$options.name === "FormNestedScreen";
|
|
11
12
|
if (isScreen) {
|
|
13
|
+
lastScreenContent = owner;
|
|
12
14
|
level--;
|
|
13
15
|
}
|
|
14
16
|
if (isNested) {
|
|
@@ -19,7 +21,7 @@ function findScreenOwner(control) {
|
|
|
19
21
|
}
|
|
20
22
|
owner = owner.$parent;
|
|
21
23
|
}
|
|
22
|
-
return null;
|
|
24
|
+
return lastScreenContentIfNull ? lastScreenContent : null;
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
27
|
* Wrap the data of a control using a Proxy
|
|
@@ -83,3 +85,11 @@ export default {
|
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Gets the root screen or same element if couldn't find
|
|
91
|
+
* @returns {object|null}
|
|
92
|
+
*/
|
|
93
|
+
export function findRootScreen(element) {
|
|
94
|
+
return findScreenOwner(element, true) || element;
|
|
95
|
+
}
|
package/src/mixins/Json2Vue.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import _ from "lodash";
|
|
1
2
|
import extensions from './extensions';
|
|
2
3
|
import ScreenBase from './ScreenBase';
|
|
3
4
|
import CountElements from '../CountElements';
|
|
4
5
|
import ValidationsFactory from '../ValidationsFactory';
|
|
5
|
-
import _, { isEqual } from 'lodash';
|
|
6
6
|
|
|
7
7
|
let screenRenderer;
|
|
8
8
|
|
|
@@ -184,12 +184,26 @@ export default {
|
|
|
184
184
|
return reference;
|
|
185
185
|
},
|
|
186
186
|
loadItems(items, component, screen, definition, formIndex) {
|
|
187
|
-
items.forEach(element => {
|
|
187
|
+
items.forEach((element) => {
|
|
188
188
|
const componentName = element[this.nodeNameProperty];
|
|
189
189
|
const nodeName = this.alias[componentName] || componentName;
|
|
190
190
|
const properties = { ...element.config };
|
|
191
191
|
// Extensions.onloadproperties
|
|
192
|
-
this.extensions.forEach(
|
|
192
|
+
this.extensions.forEach(
|
|
193
|
+
(ext) =>
|
|
194
|
+
ext.onloadproperties instanceof Function &&
|
|
195
|
+
ext.onloadproperties.bind(this)({
|
|
196
|
+
properties,
|
|
197
|
+
element,
|
|
198
|
+
component,
|
|
199
|
+
items,
|
|
200
|
+
nodeName,
|
|
201
|
+
componentName,
|
|
202
|
+
screen,
|
|
203
|
+
definition,
|
|
204
|
+
formIndex
|
|
205
|
+
})
|
|
206
|
+
);
|
|
193
207
|
// Create component
|
|
194
208
|
const node = this.createComponent(nodeName, properties);
|
|
195
209
|
// Create wrapper
|
|
@@ -291,6 +305,7 @@ export default {
|
|
|
291
305
|
props: {},
|
|
292
306
|
computed: {},
|
|
293
307
|
methods: {},
|
|
308
|
+
created: [],
|
|
294
309
|
data: {},
|
|
295
310
|
watch: {},
|
|
296
311
|
mounted: [],
|
|
@@ -306,7 +321,27 @@ export default {
|
|
|
306
321
|
ext.onbuild instanceof Function ? ext.onbuild.bind(this)({ screen: component, definition }) : null;
|
|
307
322
|
});
|
|
308
323
|
// Build data
|
|
309
|
-
|
|
324
|
+
const hiddenVars = ["currentPage__"];
|
|
325
|
+
const dataCode = `let value;const data = {};
|
|
326
|
+
${Object.keys(component.data)
|
|
327
|
+
.map((key) => {
|
|
328
|
+
const { code, variable } = component.data[key];
|
|
329
|
+
return `value = ${code};
|
|
330
|
+
data.${this.safeDotName(key)} = value;
|
|
331
|
+
${
|
|
332
|
+
!variable ||
|
|
333
|
+
hiddenVars.includes(variable) ||
|
|
334
|
+
variable.endsWith("__")
|
|
335
|
+
? ""
|
|
336
|
+
: `this.setValue(${JSON.stringify(
|
|
337
|
+
variable
|
|
338
|
+
)}, value, this.vdata);`
|
|
339
|
+
}`;
|
|
340
|
+
})
|
|
341
|
+
.join("\n")};
|
|
342
|
+
return data;`;
|
|
343
|
+
// eslint-disable-next-line no-new-func
|
|
344
|
+
component.data = new Function(dataCode);
|
|
310
345
|
// Build watchers
|
|
311
346
|
Object.keys(component.watch).forEach((key) => {
|
|
312
347
|
const watch = { deep: true };
|
|
@@ -317,6 +352,8 @@ export default {
|
|
|
317
352
|
// Add validation rules
|
|
318
353
|
this.addValidationRulesLoader(component, definition);
|
|
319
354
|
// Build mounted
|
|
355
|
+
component.created = new Function(component.created.join('\n'));
|
|
356
|
+
// Build mounted
|
|
320
357
|
component.mounted = new Function(component.mounted.join('\n'));
|
|
321
358
|
return component;
|
|
322
359
|
} catch (error) {
|
|
@@ -331,8 +368,19 @@ export default {
|
|
|
331
368
|
};
|
|
332
369
|
}
|
|
333
370
|
},
|
|
334
|
-
|
|
335
|
-
screen.
|
|
371
|
+
addProp(screen, name, value) {
|
|
372
|
+
screen.props[name] = value;
|
|
373
|
+
},
|
|
374
|
+
addData(screen, name, code, variable = null) {
|
|
375
|
+
screen.data[name] = { code, variable };
|
|
376
|
+
},
|
|
377
|
+
addComputed(screen, name, getterCode, setterCode) {
|
|
378
|
+
screen.computed[name] = {
|
|
379
|
+
// eslint-disable-next-line no-new-func
|
|
380
|
+
get: new Function(getterCode),
|
|
381
|
+
// eslint-disable-next-line no-new-func
|
|
382
|
+
set: new Function("value", setterCode)
|
|
383
|
+
};
|
|
336
384
|
},
|
|
337
385
|
addWatch(screen, name, code, options = {}) {
|
|
338
386
|
if (screen.watch[name]) {
|
|
@@ -344,6 +392,9 @@ export default {
|
|
|
344
392
|
addMounted(screen, code) {
|
|
345
393
|
screen.mounted.push(code);
|
|
346
394
|
},
|
|
395
|
+
addCreated(screen, code) {
|
|
396
|
+
screen.created.push(code);
|
|
397
|
+
},
|
|
347
398
|
addEvent(properties, event, code) {
|
|
348
399
|
properties[`@${event}`] = code;
|
|
349
400
|
},
|
|
@@ -367,13 +418,19 @@ export default {
|
|
|
367
418
|
});
|
|
368
419
|
return response;
|
|
369
420
|
}
|
|
370
|
-
const updateValidationRules =
|
|
421
|
+
const updateValidationRules = (screenComponent, validations) => {
|
|
371
422
|
return new Promise((resolve) => {
|
|
372
423
|
screenComponent.ValidationRules__ = validations;
|
|
373
424
|
screenComponent.$nextTick(() => {
|
|
374
|
-
|
|
375
|
-
screenComponent.$v
|
|
376
|
-
|
|
425
|
+
try {
|
|
426
|
+
if (screenComponent.$v) {
|
|
427
|
+
screenComponent.$v.$touch();
|
|
428
|
+
resolve();
|
|
429
|
+
}
|
|
430
|
+
} catch (error) {
|
|
431
|
+
if (this.getMode() === "preview") {
|
|
432
|
+
console.warn("There was a problem rendering the screen", error);
|
|
433
|
+
}
|
|
377
434
|
}
|
|
378
435
|
});
|
|
379
436
|
});
|
package/src/mixins/ScreenBase.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { get, isEqual, set } from 'lodash';
|
|
1
|
+
import { get, isEqual, set, debounce } from 'lodash';
|
|
2
2
|
import Mustache from 'mustache';
|
|
3
3
|
import { mapActions, mapState } from 'vuex';
|
|
4
4
|
import { ValidationMsg } from './ValidationRules';
|
|
5
5
|
import DataReference from "./DataReference";
|
|
6
|
+
import computedFields from "./computedFields";
|
|
7
|
+
import { findRootScreen } from "./DataReference";
|
|
6
8
|
|
|
7
9
|
const stringFormats = ['string', 'datetime', 'date', 'password'];
|
|
8
10
|
const parentReference = [];
|
|
9
11
|
|
|
10
12
|
export default {
|
|
11
13
|
name: "ScreenContent",
|
|
12
|
-
mixins: [DataReference],
|
|
14
|
+
mixins: [DataReference, computedFields],
|
|
13
15
|
schema: [
|
|
14
16
|
function() {
|
|
15
17
|
if (window.ProcessMaker && window.ProcessMaker.packages && window.ProcessMaker.packages.includes('package-vocabularies')) {
|
|
@@ -45,7 +47,8 @@ export default {
|
|
|
45
47
|
computed: {
|
|
46
48
|
...mapState("globalErrorsModule", {
|
|
47
49
|
valid__: "valid",
|
|
48
|
-
message__: "message"
|
|
50
|
+
message__: "message",
|
|
51
|
+
locked__: "locked",
|
|
49
52
|
}),
|
|
50
53
|
references__() {
|
|
51
54
|
return this.$parent && this.$parent.references__;
|
|
@@ -134,14 +137,15 @@ export default {
|
|
|
134
137
|
},
|
|
135
138
|
mustache(text) {
|
|
136
139
|
try {
|
|
137
|
-
const data =
|
|
140
|
+
const data = this.getDataReference();
|
|
138
141
|
return text && Mustache.render(text, data);
|
|
139
142
|
} catch (e) {
|
|
140
143
|
return 'MUSTACHE: ' + e.message;
|
|
141
144
|
}
|
|
142
145
|
},
|
|
143
146
|
async submitForm() {
|
|
144
|
-
await this.validateNow(this);
|
|
147
|
+
await this.validateNow(findRootScreen(this));
|
|
148
|
+
console.log(this.valid__, this.message__);
|
|
145
149
|
if (!this.valid__) {
|
|
146
150
|
window.ProcessMaker.alert(this.message__, "danger");
|
|
147
151
|
// if the form is not valid the data is not emitted
|
|
@@ -149,6 +153,10 @@ export default {
|
|
|
149
153
|
}
|
|
150
154
|
this.$emit('submit', this.vdata);
|
|
151
155
|
},
|
|
156
|
+
resetValue(safeDotName, variableName) {
|
|
157
|
+
this.setValue(safeDotName, null);
|
|
158
|
+
this.updateScreenDataNow(safeDotName, variableName);
|
|
159
|
+
},
|
|
152
160
|
getValidationData() {
|
|
153
161
|
return this.vdata;
|
|
154
162
|
},
|
|
@@ -166,9 +174,44 @@ export default {
|
|
|
166
174
|
value = [];
|
|
167
175
|
} else if (component === 'FormSelectList' && !config.options.allowMultiSelect) {
|
|
168
176
|
value = null;
|
|
177
|
+
} else if (component === "FormLoop") {
|
|
178
|
+
value = this.emptyLoopValue(config);
|
|
169
179
|
}
|
|
170
180
|
return value;
|
|
171
181
|
},
|
|
182
|
+
emptyLoopValue(config) {
|
|
183
|
+
if (config.settings.type === "existing") {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
const times = Number(config.settings.times);
|
|
187
|
+
const loopVariable = [];
|
|
188
|
+
for (let i = 0; i < times; i++) {
|
|
189
|
+
loopVariable.push({});
|
|
190
|
+
}
|
|
191
|
+
return loopVariable;
|
|
192
|
+
},
|
|
193
|
+
updateScreenData(safeDotName, variable) {
|
|
194
|
+
this[`${safeDotName}_was_filled__`] = true;
|
|
195
|
+
this.blockUpdate(safeDotName, 210);
|
|
196
|
+
this.setValueDebounced(variable, this[safeDotName], this.vdata);
|
|
197
|
+
},
|
|
198
|
+
updateScreenDataNow(safeDotName, variable) {
|
|
199
|
+
this[`${safeDotName}_was_filled__`] = true;
|
|
200
|
+
this.setValue(variable, this[safeDotName], this.vdata);
|
|
201
|
+
this.unblockUpdate(safeDotName);
|
|
202
|
+
},
|
|
203
|
+
blockUpdate(safeDotName, time) {
|
|
204
|
+
this.blockedUpdates[safeDotName] = new Date().getTime() + time;
|
|
205
|
+
},
|
|
206
|
+
unblockUpdate(safeDotName) {
|
|
207
|
+
this.blockUpdate(safeDotName, 0);
|
|
208
|
+
},
|
|
209
|
+
canUpdate(safeDotName) {
|
|
210
|
+
return (
|
|
211
|
+
!this.blockedUpdates[safeDotName] ||
|
|
212
|
+
this.blockedUpdates[safeDotName] < new Date().getTime()
|
|
213
|
+
);
|
|
214
|
+
},
|
|
172
215
|
getValue(name, object = this) {
|
|
173
216
|
return object ? get(object, name) : undefined;
|
|
174
217
|
},
|
|
@@ -214,6 +257,32 @@ export default {
|
|
|
214
257
|
}
|
|
215
258
|
}
|
|
216
259
|
},
|
|
260
|
+
addNonDefinedComputedAttributes(value, key, owner = null) {
|
|
261
|
+
if (value instanceof Array) {
|
|
262
|
+
value.forEach((item, index) => {
|
|
263
|
+
this.addNonDefinedComputedAttributes(item, index, value);
|
|
264
|
+
});
|
|
265
|
+
} else if (value instanceof Object) {
|
|
266
|
+
Object.keys(value).forEach((k) => {
|
|
267
|
+
this.addNonDefinedComputedAttributes(value[k], k, value);
|
|
268
|
+
});
|
|
269
|
+
} else if (
|
|
270
|
+
owner &&
|
|
271
|
+
owner instanceof Object &&
|
|
272
|
+
!(value instanceof Array)
|
|
273
|
+
) {
|
|
274
|
+
// check if value is reactive using getOwnPropertyDescriptor
|
|
275
|
+
const descriptor = Object.getOwnPropertyDescriptor(owner, key);
|
|
276
|
+
const isReactive = descriptor && descriptor.get;
|
|
277
|
+
if (!isReactive) {
|
|
278
|
+
// remove static value
|
|
279
|
+
delete owner[key];
|
|
280
|
+
// add reactive value
|
|
281
|
+
this.$set(owner, key, value);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return value;
|
|
285
|
+
},
|
|
217
286
|
validationMessage(validation) {
|
|
218
287
|
const message = [];
|
|
219
288
|
Object.keys(ValidationMsg).forEach(key => {
|
|
@@ -234,8 +303,26 @@ export default {
|
|
|
234
303
|
setCurrentPage(page) {
|
|
235
304
|
this.currentPage__ = page;
|
|
236
305
|
},
|
|
306
|
+
setValueAsync(name, value, object = this, defaults = object) {}
|
|
237
307
|
},
|
|
238
308
|
validations() {
|
|
239
309
|
return { vdata: this.ValidationRules__ };
|
|
240
310
|
},
|
|
311
|
+
created() {
|
|
312
|
+
this.blockedUpdates = {};
|
|
313
|
+
const debouncedValuesQueue = [];
|
|
314
|
+
const setDebouncedValues = debounce(() => {
|
|
315
|
+
debouncedValuesQueue.forEach((args) => {
|
|
316
|
+
this.setValue(...args);
|
|
317
|
+
});
|
|
318
|
+
}, 210);
|
|
319
|
+
this.setValueDebounced = (...args) => {
|
|
320
|
+
debouncedValuesQueue.push(args);
|
|
321
|
+
setDebouncedValues();
|
|
322
|
+
};
|
|
323
|
+
this.setValueAsync = (name, value, object = this, defaults = object) =>
|
|
324
|
+
Promise.resolve().then(() => {
|
|
325
|
+
this.setValue(name, value, object, defaults);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
241
328
|
};
|
|
@@ -1,32 +1,15 @@
|
|
|
1
|
-
import { Parser } from
|
|
1
|
+
import { Parser } from "expr-eval";
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
methods: {
|
|
5
5
|
visibilityRuleIsVisible(rule) {
|
|
6
6
|
try {
|
|
7
|
-
const
|
|
8
|
-
const dataWithParent = new Proxy(
|
|
9
|
-
{},
|
|
10
|
-
{
|
|
11
|
-
get: (target, name) => {
|
|
12
|
-
if (name === "_parent") {
|
|
13
|
-
return that._parent;
|
|
14
|
-
}
|
|
15
|
-
return that.vdata[name];
|
|
16
|
-
},
|
|
17
|
-
has: (target, name) => {
|
|
18
|
-
if (name === "_parent") {
|
|
19
|
-
return that._parent !== undefined;
|
|
20
|
-
}
|
|
21
|
-
return that.vdata[name] !== undefined;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
);
|
|
7
|
+
const dataWithParent = this.getDataReference();
|
|
25
8
|
const isVisible = Boolean(Parser.evaluate(rule, dataWithParent));
|
|
26
9
|
return isVisible;
|
|
27
10
|
} catch (e) {
|
|
28
11
|
return false;
|
|
29
12
|
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
32
15
|
};
|
|
@@ -1,35 +1,31 @@
|
|
|
1
|
-
import computedFields from '../computedFields';
|
|
2
|
-
|
|
3
1
|
export default {
|
|
4
2
|
methods: {
|
|
3
|
+
/**
|
|
4
|
+
* Implements computed fields like this:
|
|
5
|
+
*
|
|
6
|
+
* calcProperty() {
|
|
7
|
+
* let value = this.evaluateExpression('return formula();', 'javascript');
|
|
8
|
+
* value = this.addNonDefinedComputedAttributes(value);
|
|
9
|
+
* this.setValueAsync("calcProperty", value, this.vdata);
|
|
10
|
+
* }
|
|
11
|
+
*/
|
|
5
12
|
computedFields(screen, definition) {
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.addWatch(
|
|
23
|
-
screen,
|
|
24
|
-
computed.property,
|
|
25
|
-
`this.setValue(${JSON.stringify(computed.property)}, value, this.vdata);`
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
this.addMounted(screen, `
|
|
29
|
-
this.setValue(${JSON.stringify(computed.property)}, this.getValue(${JSON.stringify(computed.property)}), this.vdata, this);
|
|
30
|
-
`);
|
|
31
|
-
}
|
|
32
|
-
},
|
|
13
|
+
// For each computed field defined
|
|
14
|
+
definition.computed.forEach((computed) => {
|
|
15
|
+
const formula = JSON.stringify(computed.formula);
|
|
16
|
+
const type = JSON.stringify(computed.type);
|
|
17
|
+
const name = JSON.stringify(computed.property);
|
|
18
|
+
const safeDotName = this.safeDotName(computed.property);
|
|
19
|
+
const code = `
|
|
20
|
+
let value = this.evaluateExpression(${formula}, ${type});
|
|
21
|
+
value = this.addNonDefinedComputedAttributes(value);
|
|
22
|
+
this.setValue(${name}, value, this.vdata);
|
|
23
|
+
return value;`;
|
|
24
|
+
this.addComputed(screen, safeDotName, code, "");
|
|
25
|
+
// required to enable reactivity of computed field
|
|
26
|
+
this.addWatch(screen, safeDotName, "");
|
|
27
|
+
});
|
|
28
|
+
}
|
|
33
29
|
},
|
|
34
30
|
mounted() {
|
|
35
31
|
this.extensions.push({
|
|
@@ -37,7 +33,7 @@ export default {
|
|
|
37
33
|
if (definition.computed) {
|
|
38
34
|
this.computedFields(screen, definition);
|
|
39
35
|
}
|
|
40
|
-
}
|
|
36
|
+
}
|
|
41
37
|
});
|
|
42
|
-
}
|
|
38
|
+
}
|
|
43
39
|
};
|