@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.
@@ -1,28 +1,54 @@
1
- import _ from 'lodash';
2
-
3
1
  export default {
4
2
  methods: {
5
3
  dataFields(screen, definition) {
6
- this.variables.filter(v => (!v.name.startsWith('_parent') && !v.name.includes('._parent.') && !this.isComputedVariable(v.name, definition)))
7
- .forEach(v => {
8
- let component = _.get(v, 'element.component');
9
- let dataFormat = _.get(v, 'config.dataFormat', null);
10
- this.addData(screen, v.name, `
4
+ const localVariables = this.variables.filter(
5
+ (v) => !this.isComputedVariable(v.name, definition)
6
+ );
7
+ localVariables.forEach((v) => {
8
+ const { component } = v.element;
9
+ const dataFormat = v.config.dataFormat || null;
10
+ const safeDotName = this.safeDotName(v.name);
11
+ this.addData(
12
+ screen,
13
+ safeDotName,
14
+ `
11
15
  this.getValue(${JSON.stringify(v.name)}, this.vdata) ||
12
16
  this.getValue(${JSON.stringify(v.name)}, data) ||
13
- this.initialValue('${component}', '${dataFormat}', ${JSON.stringify(v.config)})
14
- `);
15
- this.addWatch(screen, v.name, `this.setValue(${JSON.stringify(v.name)}, value, this.vdata);this.setValue(${JSON.stringify(v.name)}, value, this.schema);`);
16
- this.addWatch(screen, `vdata.${v.name}`, `this.setValue(${JSON.stringify(v.name)}, value, this);`);
17
- });
18
- screen.props.vdata = null;
17
+ this.initialValue(
18
+ '${component}',
19
+ '${dataFormat}',
20
+ ${JSON.stringify(v.config)})
21
+ `,
22
+ v.name
23
+ );
24
+ this.addWatch(
25
+ screen,
26
+ `vdata.${v.name}`,
27
+ `if (this.canUpdate("${safeDotName}")) {
28
+ this.${safeDotName} = value;
29
+ }`
30
+ );
31
+ });
32
+ this.addProp(screen, "vdata", null);
19
33
  },
34
+ /**
35
+ * Replace `.` by `_DOT_` in a variable name
36
+ * @param {string} name
37
+ * @returns {string}
38
+ */
39
+ safeDotName(name) {
40
+ // if starts with _parent returns as is
41
+ if (name.startsWith("_parent")) {
42
+ return name;
43
+ }
44
+ return name.replace(/\./g, "_DOT_");
45
+ }
20
46
  },
21
47
  mounted() {
22
48
  this.extensions.push({
23
49
  onbuild({ screen, definition }) {
24
50
  this.dataFields(screen, definition);
25
- },
51
+ }
26
52
  });
27
- },
53
+ }
28
54
  };
@@ -25,8 +25,8 @@ export default {
25
25
  });
26
26
  },
27
27
  setupDefaultValue(screen, name, value) {
28
- const splittedName = name.split('.').join('_DOT_');
29
- const defaultComputedName = `default_${splittedName}__`;
28
+ const safeDotName = this.safeDotName(name);
29
+ const defaultComputedName = `default_${safeDotName}__`;
30
30
  this.addData(screen, `${name}_was_filled__`, `!!this.getValue(${JSON.stringify(name)}, this.vdata) || !!this.getValue(${JSON.stringify(name)}, data)`);
31
31
  this.addMounted(screen, `if (!this.${name}) {
32
32
  this.tryFormField(${JSON.stringify(name)}, () => {this.${this.dot2bracket(name)} = ${value};});
@@ -35,7 +35,7 @@ export default {
35
35
  get: new Function(`return this.tryFormField(${JSON.stringify(name)}, () => ${value});`),
36
36
  set() {},
37
37
  };
38
- this.addWatch(screen, defaultComputedName, `!this.${name}_was_filled__ && this.setValue(${JSON.stringify(name)}, this.${defaultComputedName}, this.vdata, this);`);
38
+ this.addWatch(screen, defaultComputedName, `!this.${safeDotName}_was_filled__ && this.setValue(${JSON.stringify(name)}, this.${defaultComputedName}, this.vdata, this);`);
39
39
  },
40
40
  },
41
41
  mounted() {
@@ -47,8 +47,8 @@ export default {
47
47
  const name = element.config.name;
48
48
  if (this.isComputedVariable(name, definition)) return;
49
49
  if (element.config.defaultValue || element.config.initiallyChecked) {
50
- const splittedName = name.split('.').join('_DOT_');
51
- const event = `${name}_was_filled__ |= !!$event; !${name}_was_filled__ && (vdata.${this.dot2bracket(name)} = default_${splittedName}__)`;
50
+ const safeDotName = this.safeDotName(name);
51
+ const event = `${safeDotName}_was_filled__ |= !!$event; !${safeDotName}_was_filled__ && (vdata.${this.dot2bracket(name)} = default_${safeDotName}__)`;
52
52
  this.addEvent(properties, 'input', event);
53
53
  }
54
54
  },
@@ -1,80 +1,104 @@
1
+ /* eslint-disable no-param-reassign */
1
2
  export default {
2
3
  data() {
3
4
  return {
4
- popups: [],
5
+ popups: []
5
6
  };
6
7
  },
7
8
  methods: {
8
9
  searchForRecordList(items) {
9
- items.forEach(item => {
10
+ items.forEach((item) => {
10
11
  if (item instanceof Array) {
11
12
  this.searchForRecordList(item);
12
13
  }
13
14
  if (item.items) {
14
15
  this.searchForRecordList(item.items);
15
16
  }
16
- if (item.component === 'FormRecordList') {
17
+ if (item.component === "FormRecordList") {
17
18
  this.popups.push(parseInt(item.config.form));
18
19
  }
19
20
  });
20
21
  },
21
22
  loadFormPopups({ definition }) {
22
23
  this.popups = [];
23
- definition.config.forEach(page => {
24
+ definition.config.forEach((page) => {
24
25
  if (page && page.items) {
25
26
  this.searchForRecordList(page.items);
26
27
  }
27
28
  });
28
29
  },
29
- loadFieldProperties({ properties, element, componentName, definition , formIndex, screen}) {
30
+ loadFieldProperties({
31
+ properties,
32
+ element,
33
+ componentName,
34
+ definition,
35
+ formIndex,
36
+ screen
37
+ }) {
30
38
  properties.class = this.elementCssClass(element);
31
- properties[':validation-data'] = 'getValidationData()';
39
+ properties[":validation-data"] = "getValidationData()";
32
40
 
33
- //verify if component is defined in popup
41
+ // verify if component is defined in popup
34
42
  if (!this.popups.includes(formIndex)) {
35
- if (componentName === 'FormImage') {
43
+ if (componentName === "FormImage") {
36
44
  this.registerVariable(element.config.variableName, element);
37
45
  delete properties.image;
38
- properties[':image'] = this.byRef(element.config.image);
46
+ properties[":image"] = this.byRef(element.config.image);
39
47
  } else if (this.validVariableName(element.config.name)) {
40
48
  this.registerVariable(element.config.name, element);
41
49
  // v-model are not assigned directly to the field name, to prevent invalid references like:
42
50
  // `person.content` when `person`=null
43
- const computed_property = `computedProxy__${element.config.name.split('.').join('_DOT_')}`;
44
- properties['v-model'] = computed_property;
45
- screen.computed[computed_property] = {
46
- get() {
47
- return this.getValue(element.config.name);
48
- },
49
- set(value) {
50
- this.setValue(element.config.name, value);
51
- return true;
52
- },
53
- };
51
+ const safeDotName = this.safeDotName(element.config.name);
52
+ properties["v-model"] = safeDotName;
53
+ // Debounce input from FormTextArea and FormInput
54
+ if (
55
+ componentName === "FormTextArea" ||
56
+ componentName === "FormInput"
57
+ ) {
58
+ properties["@input"] = `updateScreenData('${safeDotName}', '${element.config.name}')`;
59
+ properties["@change"] = `updateScreenDataNow('${safeDotName}', '${element.config.name}')`;
60
+ } else {
61
+ properties["@input"] = `updateScreenDataNow('${safeDotName}', '${element.config.name}')`;
62
+ properties["@change"] = `updateScreenDataNow('${safeDotName}', '${element.config.name}')`;
63
+ }
64
+ // Process the FormSelectList@reset event
65
+ properties[
66
+ "@reset"
67
+ ] = `resetValue('${safeDotName}', '${element.config.name}')`;
54
68
  }
55
69
  }
56
70
  // Do not replace mustache in RichText control, it is replaced by the control
57
- if (componentName === 'FormHtmlViewer' || componentName === 'FormHtmlEditorStatic') {
71
+ if (
72
+ componentName === "FormHtmlViewer" ||
73
+ componentName === "FormHtmlEditorStatic"
74
+ ) {
58
75
  delete properties.content;
59
- properties[':content'] = this.byRef(element.config.content);
76
+ properties[":content"] = this.byRef(element.config.content);
60
77
  }
61
78
  if (componentName === "FormNestedScreen") {
62
79
  properties[":_parent"] = "_parent";
63
80
  }
64
81
  // Add cypress testing tags
65
82
  if (element.config.name) {
66
- properties['data-cy'] = `screen-field-${element.config.name}`;
83
+ properties["data-cy"] = `screen-field-${element.config.name}`;
67
84
  }
68
- properties[':ancestor-screens'] = '$parent && $parent.ancestorScreens';
69
- properties.name = element.config.name !== undefined ? element.config.name : null;
70
- properties.disabled = element.config.interactive || element.config.disabled;
71
- properties[':form-config'] = this.byRef(this.configRef || definition.config);
72
- properties[':form-computed'] = JSON.stringify(definition.computed);
73
- properties[':form-watchers'] = JSON.stringify(definition.watchers);
85
+ properties[":ancestor-screens"] = "$parent && $parent.ancestorScreens";
86
+ properties.name =
87
+ element.config.name !== undefined ? element.config.name : null;
88
+ properties.disabled =
89
+ element.config.interactive || element.config.disabled;
90
+ properties[":form-config"] = this.byRef(
91
+ this.configRef || definition.config
92
+ );
93
+ properties[":form-computed"] = JSON.stringify(definition.computed);
94
+ properties[":form-watchers"] = JSON.stringify(definition.watchers);
74
95
  // Check if control is assigned to a calculated property
75
- const isCalcProp = this.isComputedVariable(element.config.name, definition);
76
- properties[':readonly'] = isCalcProp || element.config.readonly;
77
- properties[':disabled'] = isCalcProp || element.config.disabled;
96
+ const isCalcProp = this.isComputedVariable(
97
+ element.config.name,
98
+ definition
99
+ );
100
+ properties[":readonly"] = isCalcProp || element.config.readonly;
101
+ properties[":disabled"] = isCalcProp || element.config.disabled;
78
102
  // Events
79
103
  properties['@submit'] = 'submitForm';
80
104
  },
@@ -86,9 +110,9 @@ export default {
86
110
  this.loadFormPopups(params);
87
111
  this.loadFieldProperties(params);
88
112
  }
89
- params.properties[':config'] = this.byRef(params.element.config);
90
- params.properties[':transientData'] = 'vdata';
91
- },
113
+ params.properties[":config"] = this.byRef(params.element.config);
114
+ params.properties[":transientData"] = "vdata";
115
+ }
92
116
  });
93
- },
117
+ }
94
118
  };
@@ -1,5 +1,3 @@
1
- import LoopControl from '../../mixins/LoopControl';
2
-
3
1
  export default {
4
2
  props: {
5
3
  configRef: null,
@@ -12,7 +10,7 @@ export default {
12
10
  },
13
11
  methods: {
14
12
  loadFormLoopProperties({ properties, element }) {
15
- this.registerVariable(element.config.settings.varname, {});
13
+ this.registerVariable(element.config.settings.varname, element);
16
14
  this.loops.push({ variable: element.config.settings.varname, element, properties });
17
15
  },
18
16
  loadFormLoopItems({ element, node, definition }) {
@@ -75,13 +73,7 @@ export default {
75
73
  if (params.element.container && params.componentName === 'FormLoop') {
76
74
  this.loadFormLoopItems(params);
77
75
  }
78
- },
79
- onbuild({ screen }) {
80
- screen.mixins.push(LoopControl);
81
- this.loops.forEach(({variable, element}) => {
82
- this.addMounted(screen, `this.initLoopVariable(${JSON.stringify(variable)}, ${JSON.stringify(element.config)});`);
83
- });
84
- },
76
+ }
85
77
  });
86
- },
78
+ }
87
79
  };
@@ -1,5 +1,7 @@
1
1
  import { validationMixin } from 'vuelidate';
2
+ import { mapGetters } from 'vuex';
2
3
  import VueVuelidateJsonschema from 'vue-vuelidate-jsonschema';
4
+ import { javascriptReservedKeywords } from '../../form-control-common-properties';
3
5
 
4
6
  export default {
5
7
  mounted() {
@@ -10,8 +12,14 @@ export default {
10
12
  delete properties[':validation'];
11
13
  delete properties['validation'];
12
14
  // Add validation class and error message
13
- properties[':class'] = `{ 'form-group--error': ${this.checkVariableExists('$v.vdata.' + element.config.name)} && $v.vdata.${element.config.name}.$invalid || ${this.checkVariableExists('$v.schema.' + element.config.name)} && $v.schema.${element.config.name}.$invalid }`;
14
- properties[':error'] = `${this.checkVariableExists('$v.vdata.' + element.config.name)} && validationMessage($v.vdata.${element.config.name}) || ${this.checkVariableExists('$v.schema.' + element.config.name)} && validationMessage($v.schema.${element.config.name})`;
15
+ if (!this.isValidVariableName(element.config.name)) {
16
+ if (this.getMode() === "preview") {
17
+ console.error("Invalid variable name");
18
+ }
19
+ } else {
20
+ properties[':class'] = `{ 'form-group--error': ${this.checkVariableExists('$v.vdata.' + element.config.name)} && $v.vdata.${element.config.name}.$invalid || ${this.checkVariableExists('$v.schema.' + element.config.name)} && $v.schema.${element.config.name}.$invalid }`;
21
+ properties[':error'] = `${this.checkVariableExists('$v.vdata.' + element.config.name)} && validationMessage($v.vdata.${element.config.name}) || ${this.checkVariableExists('$v.schema.' + element.config.name)} && validationMessage($v.schema.${element.config.name})`;
22
+ }
15
23
  }
16
24
  },
17
25
  onbuild({ screen }) {
@@ -21,6 +29,22 @@ export default {
21
29
  });
22
30
  },
23
31
  methods: {
32
+ ...mapGetters("globalErrorsModule", ["getMode"]),
33
+ isValidVariableName(name) {
34
+ const validVariableNameExp = RegExp('^[A-Za-z][0-9a-zA-Z_$]*$');
35
+ const nameParts = name.split(".");
36
+ let valid = true;
37
+ nameParts.forEach((item) => {
38
+ if (!validVariableNameExp.test(item)) {
39
+ valid = false;
40
+ }
41
+ if (javascriptReservedKeywords.split(",").includes(item)) {
42
+ valid = false;
43
+ }
44
+ });
45
+
46
+ return valid;
47
+ },
24
48
  checkVariableExists(name) {
25
49
  const check =name.split('.').reduce((check, el) => {
26
50
  check.variable = check.variable ? `${check.variable}.${el}` : el;
@@ -21,7 +21,7 @@ export default {
21
21
  screen.mixins.push(watchersMixin);
22
22
  definition.watchers.filter(this.filterWatchers).forEach((watcher) => {
23
23
  this.addMounted(screen, `
24
- this.$nextTick(() => this.$watch('${watcher.watching}', (newValue) => {
24
+ this.$nextTick(() => this.$watch('vdata.${watcher.watching}', (newValue) => {
25
25
  if (typeof newValue !== 'undefined') {
26
26
  this.queueWatcher(${JSON.stringify(watcher)});
27
27
  }
@@ -3,7 +3,7 @@ import _ from 'lodash';
3
3
 
4
4
  const broadcastEvent = '.Illuminate\\\\Notifications\\\\Events\\\\BroadcastNotificationCreated';
5
5
 
6
- const debounce_time = 1000;
6
+ const debounce_time = 500;
7
7
 
8
8
  export default {
9
9
  data() {
@@ -69,7 +69,7 @@ export default {
69
69
  }).then((response) => {
70
70
  // If watcher has an output variable and is a script
71
71
  if (watcher.output_variable && (watcher.script_key || '').length === 0) {
72
- this.setValue(watcher.output_variable, response);
72
+ this.setValue(watcher.output_variable, response, this.vdata);
73
73
  }
74
74
 
75
75
  //update mapped values
@@ -80,7 +80,7 @@ export default {
80
80
  if (typeof this.getValue(`${map.key}_was_filled__`) !== 'undefined') {
81
81
  // If the variable already exist it must be set as filled and updated
82
82
  this.setValue(`${map.key}_was_filled__`, true);
83
- this.setValue(map.key, response[map.key]);
83
+ this.setValue(map.key, response[map.key], this.vdata);
84
84
  }
85
85
  else {
86
86
  // If it is a new variable, the value is set directly
@@ -1,4 +1,5 @@
1
1
  import { debounce } from "lodash";
2
+ import { findRootScreen } from "../../mixins/DataReference";
2
3
 
3
4
  const namespaced = true;
4
5
 
@@ -30,8 +31,13 @@ function countErrors(obj) {
30
31
  return errors;
31
32
  }
32
33
 
33
- const updateValidationRules = async (mainScreen, commit) => {
34
- await mainScreen.loadValidationRules();
34
+ const updateValidationRules = async (screen, commit) => {
35
+ const mainScreen = findRootScreen(screen);
36
+ try {
37
+ await mainScreen.loadValidationRules();
38
+ } catch (error) {
39
+ console.warn("There was a problem rendering the screen", error);
40
+ }
35
41
  const validate = mainScreen.$v;
36
42
  // update the global error state used by submit buttons
37
43
  if (validate) {
@@ -56,14 +62,17 @@ const updateValidationRules = async (mainScreen, commit) => {
56
62
  });
57
63
  }
58
64
  };
65
+
59
66
  const updateValidationRulesDebounced = debounce(updateValidationRules, 1000);
60
67
 
61
68
  const globalErrorsModule = {
62
69
  namespaced,
63
70
  state: () => {
64
71
  return {
72
+ locked: false,
65
73
  valid: true,
66
- message: ""
74
+ message: "",
75
+ mode: ""
67
76
  };
68
77
  },
69
78
  getters: {
@@ -72,11 +81,17 @@ const globalErrorsModule = {
72
81
  },
73
82
  getErrorMessage(state) {
74
83
  return state.message;
84
+ },
85
+ getMode(state) {
86
+ return state.mode;
75
87
  }
76
88
  },
77
89
  mutations: {
78
90
  basic(state, payload) {
79
91
  state[payload.key] = payload.value;
92
+ },
93
+ setMode(state, mode) {
94
+ state.mode = mode;
80
95
  }
81
96
  },
82
97
  actions: {
@@ -88,7 +103,7 @@ const globalErrorsModule = {
88
103
  },
89
104
  close({ commit }) {
90
105
  commit("basic", { key: "valid", value: true });
91
- }
106
+ },
92
107
  }
93
108
  };
94
109
 
@@ -1,23 +0,0 @@
1
- export default {
2
- methods: {
3
- initLoopVariable(variable, config) {
4
- if (config.settings.type === 'existing') {
5
- // Do not initialize any variables if the loop is
6
- // configured to use existing data.
7
- // Unless it's null, then set it to an empty array
8
- if (this.getValue(variable) === null) {
9
- this.setValue(variable, []);
10
- }
11
- return;
12
- }
13
-
14
- let array = this.getValue(variable);
15
- if (!array) {
16
- const times = Number(config.settings.times);
17
- array = [];
18
- for (let i = 0; i < times; i++) array.push({});
19
- }
20
- this.setValue(variable, array);
21
- },
22
- },
23
- };