@processmaker/screen-builder 2.90.0 → 2.92.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/README.md +5 -4
- package/dist/vue-form-builder.css +1 -1
- package/dist/vue-form-builder.es.js +7897 -7488
- package/dist/vue-form-builder.es.js.map +1 -1
- package/dist/vue-form-builder.umd.js +76 -59
- package/dist/vue-form-builder.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/DataProvider.js +31 -11
- package/src/assets/icons/Bypass.svg +5 -0
- package/src/assets/icons/Unbypass.svg +5 -0
- package/src/components/accordions.js +1 -0
- package/src/components/computed-properties.vue +211 -110
- package/src/components/index.js +2 -0
- package/src/components/inspector/options-list.vue +1 -1
- package/src/components/renderer/form-list-table.vue +11 -2
- package/src/components/renderer/form-requests.vue +13 -26
- package/src/components/renderer/form-tasks.vue +5 -3
- package/src/components/renderer/index.js +1 -0
- package/src/components/renderer/link-button.vue +30 -0
- package/src/components/sortable/Sortable.vue +95 -13
- package/src/components/sortable/sortable.scss +5 -0
- package/src/components/sortable/sortableList/SortableList.vue +103 -36
- package/src/components/sortable/sortableList/sortableList.scss +63 -22
- package/src/components/task.vue +256 -59
- package/src/components/vue-form-builder.vue +19 -10
- package/src/components/watchers-form.vue +4 -3
- package/src/components/watchers-list.vue +46 -100
- package/src/components/watchers-popup.vue +89 -16
- package/src/customLogs.js +26 -0
- package/src/form-builder-controls.js +42 -0
- package/src/main.js +26 -1
- package/src/mixins/Json2Vue.js +5 -3
- package/src/mixins/computedFields.js +25 -7
- package/src/mixins/extensions/ComputedFields.js +26 -5
- package/src/mixins/extensions/Watchers.js +4 -0
- package/src/mixins/watchers.js +5 -2
- package/src/stories/Sortable.stories.js +58 -11
|
@@ -1,67 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
<Sortable
|
|
3
|
+
:fields="fields"
|
|
4
|
+
:items="value"
|
|
5
|
+
disable-key="byPass"
|
|
6
|
+
:inline-edit="false"
|
|
7
|
+
:data-test-actions="{
|
|
8
|
+
tableBox: { 'data-cy': 'watchers-table' },
|
|
9
|
+
btnNew: { 'data-cy': 'watchers-add-watcher' },
|
|
10
|
+
btnEdit: { 'data-cy': 'watchers-table-edit' },
|
|
11
|
+
btnDelete: { 'data-cy': 'watchers-table-remove' },
|
|
12
|
+
}"
|
|
13
|
+
@item-edit="editProperty"
|
|
14
|
+
@item-delete="deleteProperty"
|
|
15
|
+
@add-page="displayFormProperty"
|
|
16
|
+
@ordered="$emit('ordered', $event)"
|
|
17
|
+
:searchProperties= "searchProperties"
|
|
18
|
+
>
|
|
19
|
+
<template #options="{ item }">
|
|
20
|
+
<button
|
|
21
|
+
v-b-tooltip="{ customClass: 'bypass-btn-tooltip' }"
|
|
22
|
+
:title="item.byPass ? $t('Unbypass Watcher') : $t('Bypass Watcher')"
|
|
23
|
+
class="btn"
|
|
24
|
+
data-test="watchers-bypass"
|
|
25
|
+
@click.prevent="$emit('toggle-bypass', item.uid)"
|
|
23
26
|
>
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<b-btn
|
|
28
|
-
variant="link"
|
|
29
|
-
@click="editProperty(item)"
|
|
30
|
-
v-b-tooltip.hover
|
|
31
|
-
:title="$t('Edit')"
|
|
32
|
-
data-cy="watchers-table-edit"
|
|
33
|
-
>
|
|
34
|
-
<i class="fas fa-edit fa-lg fa-fw"/>
|
|
35
|
-
</b-btn>
|
|
36
|
-
<b-btn
|
|
37
|
-
variant="link"
|
|
38
|
-
@click="deleteProperty(item)"
|
|
39
|
-
v-b-tooltip.hover
|
|
40
|
-
:title="$t('Delete')"
|
|
41
|
-
data-cy="watchers-table-remove"
|
|
42
|
-
>
|
|
43
|
-
<i class="fas fa-trash-alt fa-lg fa-fw"/>
|
|
44
|
-
</b-btn>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
</template>
|
|
48
|
-
</b-table>
|
|
49
|
-
</div>
|
|
50
|
-
<template slot="modal-footer">
|
|
51
|
-
<span />
|
|
27
|
+
<img :src="getByPassIcon(item)" alt="Bypass" width="24" />
|
|
28
|
+
</button>
|
|
29
|
+
<div class="sortable-item-vr"></div>
|
|
52
30
|
</template>
|
|
53
|
-
</
|
|
31
|
+
</Sortable>
|
|
54
32
|
</template>
|
|
55
33
|
|
|
56
34
|
<script>
|
|
57
35
|
import BasicSearch from './basic-search';
|
|
58
36
|
import { FormInput, FormTextArea } from '@processmaker/vue-form-elements';
|
|
37
|
+
import Sortable from './sortable/Sortable.vue';
|
|
59
38
|
|
|
60
39
|
export default {
|
|
61
40
|
components: {
|
|
62
41
|
BasicSearch,
|
|
63
42
|
FormInput,
|
|
64
43
|
FormTextArea,
|
|
44
|
+
Sortable,
|
|
65
45
|
},
|
|
66
46
|
props: {
|
|
67
47
|
value: {
|
|
@@ -90,7 +70,6 @@ export default {
|
|
|
90
70
|
{
|
|
91
71
|
label: this.$t('Name'),
|
|
92
72
|
key: 'name',
|
|
93
|
-
tdClass: 'break-word',
|
|
94
73
|
},
|
|
95
74
|
{
|
|
96
75
|
label: this.$t('Watching Variable'),
|
|
@@ -99,39 +78,16 @@ export default {
|
|
|
99
78
|
{
|
|
100
79
|
label: this.$t('Output Variable'),
|
|
101
80
|
key: 'output_variable',
|
|
102
|
-
tdClass: 'break-word',
|
|
103
81
|
},
|
|
104
82
|
{
|
|
105
83
|
label: this.$t('Source'),
|
|
106
84
|
key: 'script.title',
|
|
107
85
|
},
|
|
108
|
-
{
|
|
109
|
-
key: 'actions',
|
|
110
|
-
label: '',
|
|
111
|
-
},
|
|
112
86
|
],
|
|
87
|
+
searchProperties: ['name', 'output_variable', 'watching', 'script.title'],
|
|
113
88
|
};
|
|
114
89
|
},
|
|
115
|
-
computed: {
|
|
116
|
-
filtered() {
|
|
117
|
-
const list = this.getValuesWithOutputVarsNames(this.value);
|
|
118
|
-
|
|
119
|
-
if (!this.filter) {
|
|
120
|
-
return list;
|
|
121
|
-
}
|
|
122
|
-
const filtered = [];
|
|
123
|
-
list.forEach(item => {
|
|
124
|
-
if (Object.keys(item).find(key => typeof item[key] === 'string' ? item[key].indexOf(this.filter)>=0 : false)) {
|
|
125
|
-
filtered.push(item);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
return filtered;
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
90
|
methods: {
|
|
132
|
-
search() {
|
|
133
|
-
|
|
134
|
-
},
|
|
135
91
|
displayFormProperty() {
|
|
136
92
|
this.$emit('display-form');
|
|
137
93
|
},
|
|
@@ -141,36 +97,26 @@ export default {
|
|
|
141
97
|
deleteProperty(item) {
|
|
142
98
|
this.$emit('delete-form', item);
|
|
143
99
|
},
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
let scriptConfig = JSON.parse(newItem.script_configuration);
|
|
150
|
-
let vars = (scriptConfig && scriptConfig.dataMapping)
|
|
151
|
-
? scriptConfig.dataMapping.map(mapping => mapping.key).join(', ')
|
|
152
|
-
: '';
|
|
153
|
-
|
|
154
|
-
// var names string won't have more than 50 characters to avoid distorting the UI
|
|
155
|
-
const maxLen = 50;
|
|
156
|
-
newItem.output_variable = vars.length > maxLen
|
|
157
|
-
? vars.substr(0, maxLen) + '...'
|
|
158
|
-
: vars;
|
|
159
|
-
}
|
|
160
|
-
return newItem;
|
|
161
|
-
});
|
|
162
|
-
return list;
|
|
100
|
+
getByPassIcon(item) {
|
|
101
|
+
return new URL(
|
|
102
|
+
`../assets/icons/${item.byPass ? 'Unbypass' : 'Bypass'}.svg`,
|
|
103
|
+
import.meta.url,
|
|
104
|
+
).href;
|
|
163
105
|
},
|
|
164
106
|
},
|
|
165
107
|
};
|
|
166
108
|
</script>
|
|
167
109
|
|
|
168
|
-
<style>
|
|
169
|
-
.
|
|
170
|
-
|
|
171
|
-
|
|
110
|
+
<style lang="scss" scoped>
|
|
111
|
+
.bypass-btn-tooltip::v-deep {
|
|
112
|
+
& .tooltip-inner {
|
|
113
|
+
background-color: #EBEEF2 !important;
|
|
114
|
+
color: #444444 !important;
|
|
115
|
+
}
|
|
172
116
|
|
|
173
|
-
|
|
174
|
-
|
|
117
|
+
& .arrow:before {
|
|
118
|
+
border-top-color: #EBEEF2 !important;
|
|
119
|
+
border-bottom-color: #EBEEF2 !important;
|
|
120
|
+
}
|
|
175
121
|
}
|
|
176
122
|
</style>
|
|
@@ -1,17 +1,41 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<b-modal
|
|
3
3
|
ref="modal"
|
|
4
|
-
size="
|
|
4
|
+
:size="modalSize"
|
|
5
5
|
id="watchers-popup"
|
|
6
|
-
:title="$t('Watchers')"
|
|
7
6
|
@hidden="displayList"
|
|
8
7
|
hide-footer
|
|
9
8
|
header-close-content="×"
|
|
10
9
|
no-close-on-backdrop
|
|
11
10
|
data-cy="watchers-modal"
|
|
12
11
|
>
|
|
12
|
+
<template #modal-title>
|
|
13
|
+
{{ $t('Watchers') }}
|
|
14
|
+
<small class="d-block my-2 modal-subtitle">
|
|
15
|
+
{{ $t('Manage your active watchers for this screen') }}
|
|
16
|
+
</small>
|
|
17
|
+
</template>
|
|
13
18
|
<template v-if="enableList">
|
|
14
|
-
<watchers-list
|
|
19
|
+
<watchers-list
|
|
20
|
+
v-model="current"
|
|
21
|
+
@display-form="displayForm"
|
|
22
|
+
@edit-form="edit"
|
|
23
|
+
@delete-form="confirmRemoval"
|
|
24
|
+
@toggle-bypass="toggleBypass"
|
|
25
|
+
@ordered="$emit('input', $event)"
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<div class="d-flex justify-content-end mt-3 mr-1">
|
|
29
|
+
<div class="d-flex align-items-end">
|
|
30
|
+
<button
|
|
31
|
+
class="btn btn-secondary ml-3 text-uppercase"
|
|
32
|
+
data-cy="calcs-button-close"
|
|
33
|
+
@click="$refs.modal.hide()"
|
|
34
|
+
>
|
|
35
|
+
{{ $t("Done") }}
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
15
39
|
</template>
|
|
16
40
|
<template v-else>
|
|
17
41
|
<required />
|
|
@@ -37,34 +61,75 @@ export default {
|
|
|
37
61
|
WatchersList,
|
|
38
62
|
WatchersForm,
|
|
39
63
|
},
|
|
40
|
-
props:
|
|
64
|
+
props: {
|
|
65
|
+
value: {
|
|
66
|
+
type: Array,
|
|
67
|
+
required: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
41
70
|
data() {
|
|
42
71
|
return {
|
|
43
72
|
enableList: true,
|
|
44
73
|
current: [],
|
|
45
74
|
add: {
|
|
46
|
-
uid:'',
|
|
47
|
-
name:'',
|
|
48
|
-
variable:'',
|
|
49
|
-
script_id:'',
|
|
50
|
-
script_key:'',
|
|
51
|
-
input_data:'',
|
|
52
|
-
script_configuration:'',
|
|
53
|
-
synchronous:false,
|
|
75
|
+
uid: '',
|
|
76
|
+
name: '',
|
|
77
|
+
variable: '',
|
|
78
|
+
script_id: '',
|
|
79
|
+
script_key: '',
|
|
80
|
+
input_data: '',
|
|
81
|
+
script_configuration: '',
|
|
82
|
+
synchronous: false,
|
|
83
|
+
byPass: false,
|
|
54
84
|
},
|
|
55
85
|
};
|
|
56
86
|
},
|
|
87
|
+
computed: {
|
|
88
|
+
modalSize() {
|
|
89
|
+
return "xl";
|
|
90
|
+
},
|
|
91
|
+
},
|
|
57
92
|
watch: {
|
|
58
93
|
value: {
|
|
59
94
|
handler(value) {
|
|
60
|
-
this.current = value;
|
|
95
|
+
this.current = this.getValuesWithOutputVarsNames(value);
|
|
61
96
|
},
|
|
62
97
|
},
|
|
63
|
-
},
|
|
64
|
-
computed: {
|
|
65
|
-
|
|
66
98
|
},
|
|
67
99
|
methods: {
|
|
100
|
+
getValuesWithOutputVarsNames(values) {
|
|
101
|
+
const list = values.map((watcher) => {
|
|
102
|
+
const newItem = { ...watcher };
|
|
103
|
+
|
|
104
|
+
if (!Object.hasOwn(newItem, 'byPass')) {
|
|
105
|
+
newItem.byPass = false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// If watcher is a data source, extract the output vars
|
|
109
|
+
if (newItem?.script?.id?.substr(0, 11) === 'data_source') {
|
|
110
|
+
const scriptConfig = JSON.parse(newItem.script_configuration);
|
|
111
|
+
const vars = scriptConfig?.dataMapping
|
|
112
|
+
? scriptConfig.dataMapping.map((mapping) => mapping.key).join(', ')
|
|
113
|
+
: '';
|
|
114
|
+
|
|
115
|
+
// var names string won't have more than 50 characters to avoid distorting the UI
|
|
116
|
+
const maxLen = 50;
|
|
117
|
+
newItem.output_variable =
|
|
118
|
+
vars.length > maxLen ? `${vars.substr(0, maxLen)}...` : vars;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return newItem;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return list;
|
|
125
|
+
},
|
|
126
|
+
toggleBypass(itemUid) {
|
|
127
|
+
this.current = this.current.map((item) =>
|
|
128
|
+
item.uid === itemUid ? { ...item, byPass: !item.byPass } : item,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
this.$emit('input', this.current);
|
|
132
|
+
},
|
|
68
133
|
show() {
|
|
69
134
|
this.$refs.modal.show();
|
|
70
135
|
},
|
|
@@ -118,3 +183,11 @@ export default {
|
|
|
118
183
|
},
|
|
119
184
|
};
|
|
120
185
|
</script>
|
|
186
|
+
|
|
187
|
+
<style lang="scss" scoped>
|
|
188
|
+
.modal-subtitle {
|
|
189
|
+
color: #556271;
|
|
190
|
+
font-size: 1rem;
|
|
191
|
+
font-weight: 400;
|
|
192
|
+
}
|
|
193
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default class CustomLog {
|
|
2
|
+
static logWithStyle(icon, type, name, status, message, color) {
|
|
3
|
+
const baseColor = color === '255, 0, 0' ? 'red' : 'green';
|
|
4
|
+
const style = `background-color: rgba(${color}, 0.1); color: ${baseColor}; padding: 2px 4px; border-radius: 3px;`;
|
|
5
|
+
const transparentStyle = 'background-color: transparent';
|
|
6
|
+
|
|
7
|
+
const logPrefix = `%c${icon} %c${type} "${name}" has`;
|
|
8
|
+
const logStatus = `%c${status}`;
|
|
9
|
+
|
|
10
|
+
if (status === 'RUN') {
|
|
11
|
+
console.log(`${logPrefix} ${logStatus}`, style, transparentStyle, style);
|
|
12
|
+
} else if (status === 'FAILED') {
|
|
13
|
+
console.groupCollapsed(`${logPrefix} ${logStatus}`, style, transparentStyle, style);
|
|
14
|
+
console.log(`%c${message}`, style);
|
|
15
|
+
console.groupEnd();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static success(type, name) {
|
|
20
|
+
this.logWithStyle('\u2705', type, name, 'RUN', '', '0, 128, 0');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static error(type, name, message) {
|
|
24
|
+
this.logWithStyle('\u274C', type, name, 'FAILED', message, '255, 0, 0');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
BWrapperComponent,
|
|
24
24
|
} from '@processmaker/vue-form-elements';
|
|
25
25
|
import { dataSourceValues } from '@/components/inspector/data-source-types';
|
|
26
|
+
import LinkButton from "./components/renderer/link-button.vue";
|
|
26
27
|
|
|
27
28
|
import {
|
|
28
29
|
bgcolorProperty,
|
|
@@ -990,5 +991,46 @@ export default [
|
|
|
990
991
|
}
|
|
991
992
|
]
|
|
992
993
|
}
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
editorComponent: LinkButton,
|
|
997
|
+
editorBinding: 'LinkButton',
|
|
998
|
+
rendererComponent: LinkButton,
|
|
999
|
+
rendererBinding: "LinkButton",
|
|
1000
|
+
|
|
1001
|
+
control: {
|
|
1002
|
+
popoverContent: "Add a URL where this link should redirect",
|
|
1003
|
+
group: 'Content Fields',
|
|
1004
|
+
order: 6.0,
|
|
1005
|
+
label: "Link URL",
|
|
1006
|
+
component: "LinkButton",
|
|
1007
|
+
"editor-component": "LinkButton",
|
|
1008
|
+
"editor-control": "LinkButton",
|
|
1009
|
+
config: {
|
|
1010
|
+
label: "New Link",
|
|
1011
|
+
icon: "fas fa-link",
|
|
1012
|
+
variant: "primary",
|
|
1013
|
+
event: "link",
|
|
1014
|
+
},
|
|
1015
|
+
inspector: [
|
|
1016
|
+
{
|
|
1017
|
+
type: 'FormInput',
|
|
1018
|
+
field: 'label',
|
|
1019
|
+
config: {
|
|
1020
|
+
label: 'Label',
|
|
1021
|
+
helper: 'The label describes the button\'s text',
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
type: 'FormInput',
|
|
1026
|
+
field: 'linkUrl',
|
|
1027
|
+
config: {
|
|
1028
|
+
label: 'Link URL',
|
|
1029
|
+
helper: 'Type here the URL link. Mustache syntax is supported.',
|
|
1030
|
+
},
|
|
1031
|
+
},
|
|
1032
|
+
buttonVariantStyleProperty
|
|
1033
|
+
]
|
|
1034
|
+
}
|
|
993
1035
|
}
|
|
994
1036
|
];
|
package/src/main.js
CHANGED
|
@@ -270,8 +270,8 @@ window.Echo = {
|
|
|
270
270
|
}
|
|
271
271
|
};
|
|
272
272
|
|
|
273
|
+
// Setup axios
|
|
273
274
|
window.axios = axios.create({
|
|
274
|
-
baseURL: "/api/1.0/",
|
|
275
275
|
adapter: cacheAdapterEnhancer(axios.getAdapter(axios.defaults.adapter), {
|
|
276
276
|
enabledByDefault: window.ProcessMaker.screen.cacheEnabled,
|
|
277
277
|
cacheFlag: "useCache",
|
|
@@ -282,6 +282,31 @@ window.axios = axios.create({
|
|
|
282
282
|
})
|
|
283
283
|
});
|
|
284
284
|
|
|
285
|
+
// Setup api versions
|
|
286
|
+
const apiVersionConfig = [
|
|
287
|
+
{ version: "1.0", baseURL: "/api/1.0/" },
|
|
288
|
+
{ version: "1.1", baseURL: "/api/1.1/" },
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
window.axios.defaults.baseURL = apiVersionConfig[0].baseURL;
|
|
292
|
+
window.axios.interceptors.request.use((config) => {
|
|
293
|
+
if (typeof config.url !== "string" || !config.url) {
|
|
294
|
+
throw new Error("Invalid URL in the request configuration");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
apiVersionConfig.forEach(({ version, baseURL }) => {
|
|
298
|
+
const versionPrefix = `/api/${version}/`;
|
|
299
|
+
if (config.url.startsWith(versionPrefix)) {
|
|
300
|
+
// eslint-disable-next-line no-param-reassign
|
|
301
|
+
config.baseURL = baseURL;
|
|
302
|
+
// eslint-disable-next-line no-param-reassign
|
|
303
|
+
config.url = config.url.replace(versionPrefix, "");
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
return config;
|
|
308
|
+
});
|
|
309
|
+
|
|
285
310
|
const searchParams = new URLSearchParams(window.location.search);
|
|
286
311
|
|
|
287
312
|
const scenario = searchParams?.get("scenario");
|
package/src/mixins/Json2Vue.js
CHANGED
|
@@ -236,9 +236,11 @@ export default {
|
|
|
236
236
|
return name && typeof name === 'string' && name.match(/^[a-zA-Z_][0-9a-zA-Z_.]*$/);
|
|
237
237
|
},
|
|
238
238
|
isComputedVariable(name, definition) {
|
|
239
|
-
return definition
|
|
240
|
-
//
|
|
241
|
-
|
|
239
|
+
return definition?.computed?.some(computed => {
|
|
240
|
+
// add byPass computed property validation
|
|
241
|
+
if (computed?.byPass) return false;
|
|
242
|
+
// Check if the first part of an element'ßs name (up to the first `.`)
|
|
243
|
+
// matches the name of a computed propertåy.
|
|
242
244
|
const regex = new RegExp(`^${computed.property}(\\.|$)`, 'i');
|
|
243
245
|
return regex.test(name);
|
|
244
246
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Parser } from "expr-eval";
|
|
2
|
+
import CustomLog from '../customLogs';
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
methods: {
|
|
@@ -9,7 +10,6 @@ export default {
|
|
|
9
10
|
// Monitor if variable belongs to data (defined variables) or
|
|
10
11
|
// vdata (external variables)in this way the event is not
|
|
11
12
|
// executed again when the variable is update
|
|
12
|
-
|
|
13
13
|
const data = this.getDataReference(null, () => {
|
|
14
14
|
throw new Error(
|
|
15
15
|
"You are not allowed to set properties from inside an expression"
|
|
@@ -19,18 +19,36 @@ export default {
|
|
|
19
19
|
if (type === "expression") {
|
|
20
20
|
value = Parser.evaluate(expression, data);
|
|
21
21
|
} else {
|
|
22
|
+
// Create a new function with the expression and bind the data context
|
|
22
23
|
// eslint-disable-next-line no-new-func
|
|
23
|
-
value = new Function(expression).bind(data)
|
|
24
|
+
value = new Function(expression).bind(data);
|
|
25
|
+
return { result: value(), error: null };
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
if (value instanceof Date) {
|
|
27
29
|
value = value.toISOString();
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
return { result: value, error: null };
|
|
32
|
+
} catch (error) {
|
|
33
|
+
// Catch any errors and return them
|
|
34
|
+
return { result: null, error };
|
|
33
35
|
}
|
|
34
|
-
}
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Logs an error message with a custom format.
|
|
39
|
+
* @param {string} name - The name of the calculation.
|
|
40
|
+
* @param {string} message - The error message.
|
|
41
|
+
*/
|
|
42
|
+
customErrorLog(name, message) {
|
|
43
|
+
CustomLog.error('Calc', name, message);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Logs a success message with a custom format.
|
|
48
|
+
* @param {string} name - The name of the calculation.
|
|
49
|
+
*/
|
|
50
|
+
customSuccessLog(name) {
|
|
51
|
+
CustomLog.success('Calc', name);
|
|
52
|
+
},
|
|
35
53
|
}
|
|
36
54
|
};
|
|
@@ -9,18 +9,39 @@ export default {
|
|
|
9
9
|
* this.setValueAsync("calcProperty", value, this.vdata);
|
|
10
10
|
* }
|
|
11
11
|
*/
|
|
12
|
-
computedFields(screen, definition) {
|
|
12
|
+
computedFields(screen, definition, logsEnabled = true) {
|
|
13
13
|
// For each computed field defined
|
|
14
14
|
definition.computed.forEach((computed) => {
|
|
15
|
+
if (computed.byPass) {
|
|
16
|
+
// If the computed field has bypass set to true, skip it
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
15
19
|
const formula = JSON.stringify(computed.formula);
|
|
16
20
|
const type = JSON.stringify(computed.type);
|
|
17
21
|
const name = JSON.stringify(computed.property);
|
|
18
22
|
const safeDotName = this.safeDotName(computed.property);
|
|
19
23
|
const code = `
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
const evaluatedExpression = this.evaluateExpression(${formula}, ${type});
|
|
25
|
+
// Handle errors if any
|
|
26
|
+
if (evaluatedExpression.error) {
|
|
27
|
+
if (${logsEnabled}) {
|
|
28
|
+
this.customErrorLog(${name}, evaluatedExpression.error);
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
// Add non-defined computed attributes
|
|
32
|
+
const value = this.addNonDefinedComputedAttributes(evaluatedExpression.result);
|
|
33
|
+
// Set the value
|
|
34
|
+
this.setValue(${name}, value, this.vdata);
|
|
35
|
+
|
|
36
|
+
// Log the successful calculation if logging is enabled
|
|
37
|
+
if (${logsEnabled}) {
|
|
38
|
+
this.customSuccessLog(${name});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Return the result
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
24
45
|
this.addComputed(screen, safeDotName, code, "");
|
|
25
46
|
// required to enable reactivity of computed field
|
|
26
47
|
this.addWatch(screen, safeDotName, "");
|
|
@@ -20,6 +20,10 @@ export default {
|
|
|
20
20
|
if (definition.watchers) {
|
|
21
21
|
screen.mixins.push(watchersMixin);
|
|
22
22
|
definition.watchers.filter(this.filterWatchers).forEach((watcher) => {
|
|
23
|
+
if (watcher?.byPass) {
|
|
24
|
+
// If the watcher has bypass set to true, skip it
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
23
27
|
this.addMounted(screen, `
|
|
24
28
|
this.$nextTick(() => this.$watch('vdata.${watcher.watching}', (newValue) => {
|
|
25
29
|
if (typeof newValue !== 'undefined') {
|
package/src/mixins/watchers.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Mustache from 'mustache';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
+
import CustomLog from '../customLogs';
|
|
3
4
|
|
|
4
5
|
const broadcastEvent = '.Illuminate\\\\Notifications\\\\Events\\\\BroadcastNotificationCreated';
|
|
5
6
|
|
|
@@ -44,7 +45,7 @@ export default {
|
|
|
44
45
|
// Data Source
|
|
45
46
|
const requestId = _.get(this.vdata, '_request.id', null);
|
|
46
47
|
const params = { config: JSON.parse(config), data: this.vdata };
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
this.$dataProvider.postDataSource(scriptId, requestId, params).then(response => {
|
|
49
50
|
this.$emit('asyncWatcherCompleted');
|
|
50
51
|
complete(response.data);
|
|
@@ -67,6 +68,7 @@ export default {
|
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
}).then((response) => {
|
|
71
|
+
CustomLog.success('Watcher', watcher.name);
|
|
70
72
|
// If watcher has an output variable and is a script
|
|
71
73
|
if (watcher.output_variable && (watcher.script_key || '').length === 0) {
|
|
72
74
|
this.setValue(watcher.output_variable, response, this.vdata);
|
|
@@ -94,6 +96,7 @@ export default {
|
|
|
94
96
|
}
|
|
95
97
|
return response;
|
|
96
98
|
}).catch(error => {
|
|
99
|
+
CustomLog.error('Watcher', watcher.name, error.message);
|
|
97
100
|
const message = _.get(error, 'response.data.message', error.message);
|
|
98
101
|
if (watcher.synchronous) {
|
|
99
102
|
this.$parent.$refs.watchersSynchronous.error(message);
|
|
@@ -135,4 +138,4 @@ export default {
|
|
|
135
138
|
destroyed() {
|
|
136
139
|
this.cleanEchoListeners();
|
|
137
140
|
},
|
|
138
|
-
};
|
|
141
|
+
};
|