@5minds/node-red-dashboard-2-processcube-dynamic-form 1.1.1-feature-735e79-m734z5f9 → 1.1.1-feature-22e391-m79a6gn4

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,770 +1,757 @@
1
1
  <template>
2
- <!-- Component must be wrapped in a block so props such as className and style can be passed in from parent -->
3
- <div className="ui-dynamic-form-wrapper">
4
- <p v-if="hasFields()">
5
- <v-form ref="form" v-model="form" :class="dynamicClass">
6
- <h3 style="padding: 16px">{{ this.props.name }}</h3>
7
- <div style="padding: 16px; max-height: 550px; overflow-y: auto">
8
- <FormKit type="group" id="form">
9
- <v-row v-for="(field, index) in fields()" :key="field">
10
- <v-col cols="12">
11
- <component
12
- v-if="createComponent(field).innerText"
13
- :is="createComponent(field).type"
14
- v-bind="createComponent(field).props"
15
- v-model="formData[field.id]"
16
- >
17
- {{ createComponent(field).innerText }}
18
- </component>
19
- <div v-else-if="createComponent(field).type == 'v-slider'">
20
- <p class="formkit-label">{{ field.label }}</p>
21
- <component
22
- :is="createComponent(field).type"
23
- v-bind="createComponent(field).props"
24
- v-model="field.defaultValue"
25
- />
26
- <p class="formkit-help">
27
- {{ field.customForm ? JSON.parse(field.customForm).hint : undefined }}
28
- </p>
29
- </div>
30
- <component
31
- v-else
32
- :is="createComponent(field).type"
33
- v-bind="createComponent(field).props"
34
- v-model="formData[field.id]"
35
- />
36
- </v-col>
37
- </v-row>
38
- </FormKit>
2
+ <div className="ui-dynamic-form-external-sizing-wrapper" :style="props.card_size_styling">
3
+ <!-- Component must be wrapped in a block so props such as className and style can be passed in from parent -->
4
+ <UIDynamicFormTitleText v-if="props.title_style === 'outside' && hasUserTask()" :style="props.title_style" :title="props.title_text" :customStyles="props.title_custom_text_styling" :titleIcon="props.title_icon" />
5
+ <div className="ui-dynamic-form-wrapper">
6
+ <p v-if="hasUserTask()" style="margin-bottom: 0px;">
7
+ <v-form ref="form" v-model="form" :class="dynamicClass">
8
+ <UIDynamicFormTitleText v-if="props.title_style != 'outside'" :style="props.title_style" :title="props.title_text" :customStyles="props.title_custom_text_styling" :titleIcon="props.title_icon" />
9
+ <div className="ui-dynamic-form-formfield-positioner">
10
+ <v-row v-for="(field, index) in fields()" :key="field" :style="getRowWidthStyling(field, index)">
11
+ <v-col cols="12">
12
+ <component
13
+ :is="createComponent(field).type"
14
+ v-if="createComponent(field).innerText"
15
+ v-bind="createComponent(field).props"
16
+ v-model="formData[field.id]"
17
+ >
18
+ {{ createComponent(field).innerText }}
19
+ </component>
20
+ <div v-else-if="createComponent(field).type == 'v-slider'">
21
+ <p class="formkit-label">{{ field.label }}</p>
22
+ <component
23
+ :is="createComponent(field).type"
24
+ v-bind="createComponent(field).props"
25
+ v-model="field.defaultValue"
26
+ />
27
+ <p class="formkit-help">
28
+ {{ field.customForm ? JSON.parse(field.customForm).hint : undefined }}
29
+ </p>
30
+ </div>
31
+ <component
32
+ :is="createComponent(field).type"
33
+ v-else
34
+ v-bind="createComponent(field).props"
35
+ v-model="formData[field.id]"
36
+ />
37
+ </v-col>
38
+ </v-row>
39
+ </div>
40
+ <v-row :class="dynamicFooterClass">
41
+ <v-row v-if="error" style="padding: 12px">
42
+ <v-alert v-if="error" type="error">Error: {{ errorMsg }}</v-alert>
43
+ </v-row>
44
+ <UIDynamicFormFooterAction v-if="props.actions_inside_card && actions.length > 0" :actions="actions" :actionCallback="actionFn" style="padding: 16px; padding-top: 0px;" />
45
+ </v-row>
46
+ </v-form>
47
+ </p>
48
+ <p v-else>
49
+ <v-alert :text="waiting_info" :title="waiting_title" />
50
+ </p>
39
51
  </div>
40
- <v-row :class="dynamicFooterClass">
41
- <v-row v-if="error" style="padding: 12px">
42
- <v-alert v-if="error" type="error">Error: {{ errorMsg }}</v-alert>
43
- </v-row>
44
- <div style="display: flex; gap: 8px">
45
- <div v-for="(action, index) in actions" :key="index" style="flex-grow: 1">
46
- <v-btn :key="index" style="width: 100% !important; min-height: 36px" @click="actionFn(action)">
47
- {{ action.label }}
48
- </v-btn>
49
- </div>
50
- </div>
51
- </v-row>
52
- </v-form>
53
- </p>
54
- <p v-else>
55
- <v-alert :text="waiting_info" :title="waiting_title" />
56
- </p>
57
- </div>
52
+ <div v-if="!props.actions_inside_card && actions.length > 0 && hasUserTask()" style="padding-top: 32px;">
53
+ <UIDynamicFormFooterAction :actions="actions" :actionCallback="actionFn" />
54
+ </div>
55
+ </div>
58
56
  </template>
59
57
 
58
+ <!-- eslint-disable no-case-declarations -->
60
59
  <script>
61
- import { markRaw, h, getCurrentInstance } from 'vue';
62
- import { mapState } from 'vuex';
63
- import { plugin, defaultConfig } from '@formkit/vue';
64
- import '@formkit/themes/genesis';
65
- import { FormKit } from '@formkit/vue';
66
- import { getNode } from '@formkit/core';
60
+ import { FormKit, defaultConfig, plugin } from '@formkit/vue'
61
+ import { getCurrentInstance, markRaw } from 'vue'
62
+ import { mapState } from 'vuex'
63
+
64
+ // eslint-disable-next-line import/no-unresolved
65
+ import '@formkit/themes/genesis'
66
+ import UIDynamicFormFooterAction from './FooterActions.vue'
67
+ import UIDynamicFormTitleText from './TitleText.vue'
67
68
 
68
69
  export default {
69
- name: 'UIDynamicForm',
70
- inject: ['$socket'],
71
- props: {
72
- /* do not remove entries from this - Dashboard's Layout Manager's will pass this data to your component */
73
- id: { type: String, required: true },
74
- props: { type: Object, default: () => ({}) },
75
- state: {
76
- type: Object,
77
- default: () => ({ enabled: false, visible: false }),
70
+ name: 'UIDynamicForm',
71
+ components: {
72
+ FormKit, UIDynamicFormFooterAction, UIDynamicFormTitleText
73
+ },
74
+ inject: ['$socket'],
75
+ props: {
76
+ /* do not remove entries from this - Dashboard's Layout Manager's will pass this data to your component */
77
+ id: { type: String, required: true },
78
+ props: { type: Object, default: () => ({}) },
79
+ state: {
80
+ type: Object,
81
+ default: () => ({ enabled: false, visible: false })
82
+ }
78
83
  },
79
- },
80
- setup(props) {
81
- console.info('UIDynamicForm setup with:', props);
82
- console.debug('Vue function loaded correctly', markRaw);
83
- const instance = getCurrentInstance();
84
- const app = instance.appContext.app;
85
- const formkitConfig = defaultConfig({
86
- theme: 'genesis',
87
- });
88
- app.use(plugin, formkitConfig);
89
- },
90
- data() {
91
- return {
92
- actions: [],
93
- form: {},
94
- formData: {},
95
- taskInput: {},
96
- theme: '',
97
- error: false,
98
- errorMsg: '',
99
- };
100
- },
101
- created() {
102
- const currentPath = window.location.pathname;
103
- const lastPart = currentPath.substring(currentPath.lastIndexOf('/'));
84
+ setup (props) {
85
+ console.info('UIDynamicForm setup with:', props)
86
+ console.debug('Vue function loaded correctly', markRaw)
87
+ const instance = getCurrentInstance()
88
+ const app = instance.appContext.app
89
+ const formkitConfig = defaultConfig({
90
+ theme: 'genesis'
91
+ })
92
+ app.use(plugin, formkitConfig)
93
+ },
94
+ data () {
95
+ return {
96
+ actions: [],
97
+ form: {},
98
+ formData: {},
99
+ taskInput: {},
100
+ theme: '',
101
+ error: false,
102
+ errorMsg: ''
103
+ }
104
+ },
105
+ computed: {
106
+ ...mapState('data', ['messages']),
107
+ waiting_title () {
108
+ return this.props.waiting_title || 'Warten auf den Usertask...'
109
+ },
110
+ waiting_info () {
111
+ return (
112
+ this.props.waiting_info ||
113
+ 'Der Usertask wird automatisch angezeigt, wenn ein entsprechender Task vorhanden ist.'
114
+ )
115
+ },
104
116
 
105
- const store = this.$store.state;
117
+ dynamicClass () {
118
+ return `ui-dynamic-form-${this.theme} ui-dynamic-form-common`
119
+ },
106
120
 
107
- for (let key in store.ui.pages) {
108
- if (store.ui.pages[key].path === lastPart) {
109
- const theme = store.ui.pages[key].theme;
110
- if (store.ui.themes[theme].name === 'ProcessCube Lightmode') {
111
- this.theme = 'light';
112
- } else if (store.ui.themes[theme].name === 'ProcessCube Darkmode') {
113
- this.theme = 'dark';
114
- } else {
115
- this.theme = 'default';
121
+ dynamicFooterClass () {
122
+ return `ui-dynamic-form-footer-${this.theme} ui-dynamic-form-footer-common`
116
123
  }
117
- break;
118
- }
119
- }
120
- },
121
- computed: {
122
- ...mapState('data', ['messages']),
123
- waiting_title() {
124
- return this.props.waiting_title || 'Warten auf den Usertask...';
125
124
  },
126
- waiting_info() {
127
- return (
128
- this.props.waiting_info ||
129
- 'Der Usertask wird automatisch angezeigt, wenn ein entsprechender Task vorhanden ist.'
130
- );
125
+ watch: {
126
+ formData: {
127
+ handler (newData, oldData) {
128
+ if (this.props.trigger_on_change) {
129
+ const res = { payload: { formData: newData, userTask: this.taskInput } }
130
+ this.send(res, this.actions.length)
131
+ }
132
+ },
133
+ deep: true
134
+ }
131
135
  },
136
+ created () {
137
+ const currentPath = window.location.pathname
138
+ const lastPart = currentPath.substring(currentPath.lastIndexOf('/'))
132
139
 
133
- dynamicClass() {
134
- return `ui-dynamic-form-${this.theme}`;
135
- },
140
+ const store = this.$store.state
136
141
 
137
- dynamicFooterClass() {
138
- return `ui-dynamic-form-footer-${this.theme}`;
142
+ for (const key in store.ui.pages) {
143
+ if (store.ui.pages[key].path === lastPart) {
144
+ const theme = store.ui.pages[key].theme
145
+ if (store.ui.themes[theme].name === 'ProcessCube Lightmode') {
146
+ this.theme = 'light'
147
+ } else if (store.ui.themes[theme].name === 'ProcessCube Darkmode') {
148
+ this.theme = 'dark'
149
+ } else {
150
+ this.theme = 'default'
151
+ }
152
+ break
153
+ }
154
+ }
139
155
  },
140
- },
141
- mounted() {
142
- const elements = document.querySelectorAll('.formkit-input');
143
-
144
- elements.forEach((element) => {
145
- element.classList.add('test');
146
- });
156
+ mounted () {
157
+ const elements = document.querySelectorAll('.formkit-input')
147
158
 
148
- this.$socket.on('widget-load:' + this.id, (msg) => {
149
- this.init();
150
- this.$store.commit('data/bind', {
151
- widgetId: this.id,
152
- msg,
153
- });
154
- });
155
- this.$socket.on('msg-input:' + this.id, (msg) => {
156
- // store the latest message in our client-side vuex store when we receive a new message
157
- this.init();
159
+ elements.forEach((element) => {
160
+ element.classList.add('test')
161
+ })
158
162
 
159
- this.messages[this.id] = msg;
163
+ this.$socket.on('widget-load:' + this.id, (msg) => {
164
+ this.init()
165
+ this.$store.commit('data/bind', {
166
+ widgetId: this.id,
167
+ msg
168
+ })
169
+ })
170
+ this.$socket.on('msg-input:' + this.id, (msg) => {
171
+ // store the latest message in our client-side vuex store when we receive a new message
172
+ this.init()
160
173
 
161
- const hasTask = msg.payload && msg.payload.userTask;
162
- const defaultValues = msg.payload.userTask.userTaskConfig.formFields;
163
- const initialValues = msg.payload.userTask.startToken;
174
+ this.messages[this.id] = msg
164
175
 
165
- if (hasTask) {
166
- this.taskInput = msg.payload.userTask;
167
- }
176
+ const hasTask = msg.payload && msg.payload.userTask
177
+ const formFields = msg.payload.userTask.userTaskConfig.formFields
178
+ const formFieldIds = formFields.map(ff => ff.id)
179
+ const initialValues = msg.payload.userTask.startToken
168
180
 
169
- if (hasTask && defaultValues) {
170
- defaultValues.forEach((field) => {
171
- this.formData[field.id] = field.defaultValue;
172
- });
173
- }
181
+ if (hasTask) {
182
+ this.taskInput = msg.payload.userTask
183
+ }
174
184
 
175
- if (hasTask && initialValues) {
176
- Object.keys(initialValues).forEach((key) => {
177
- this.formData[key] = initialValues[key];
178
- });
179
- }
185
+ if (hasTask && formFields) {
186
+ formFields.forEach((field) => {
187
+ this.formData[field.id] = field.defaultValue
188
+ })
189
+ }
180
190
 
181
- this.$store.commit('data/bind', {
182
- widgetId: this.id,
183
- msg,
184
- });
185
- });
186
- // tell Node-RED that we're loading a new instance of this widget
187
- this.$socket.emit('widget-load', this.id);
188
- },
189
- unmounted() {
190
- /* Make sure, any events you subscribe to on SocketIO are unsubscribed to here */
191
- this.$socket?.off('widget-load' + this.id);
192
- this.$socket?.off('msg-input:' + this.id);
193
- },
194
- components: {
195
- FormKit,
196
- },
197
- methods: {
198
- createComponent(field) {
199
- const hint = field.customForm ? JSON.parse(field.customForm).hint : undefined;
200
- const placeholder = field.customForm ? JSON.parse(field.customForm).placeholder : undefined;
201
- const validation = field.customForm ? JSON.parse(field.customForm).validation : undefined;
202
- const name = field.id;
191
+ if (hasTask && initialValues) {
192
+ Object.keys(initialValues).filter(key => formFieldIds.includes(key)).forEach((key) => {
193
+ this.formData[key] = initialValues[key]
194
+ })
195
+ }
203
196
 
204
- switch (field.type) {
205
- case 'long':
206
- return {
207
- type: 'FormKit',
208
- props: {
209
- type: 'number',
210
- id: field.id,
211
- name: name,
212
- label: field.label,
213
- required: field.required,
214
- value: field.defaultValue,
215
- number: 'integer',
216
- help: hint,
217
- wrapperClass: '$remove:formkit-wrapper',
218
- inputClass: `input-${this.theme}`,
219
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
220
- validation: validation,
221
- validationVisibility: 'live',
222
- },
223
- };
224
- case 'number':
225
- const step = field.customForm ? JSON.parse(field.customForm).step : undefined;
226
- return {
227
- type: 'FormKit',
228
- props: {
229
- type: 'number',
230
- id: field.id,
231
- name: name,
232
- label: field.label,
233
- required: field.required,
234
- value: field.defaultValue,
235
- step: step,
236
- help: hint,
237
- wrapperClass: '$remove:formkit-wrapper',
238
- inputClass: `input-${this.theme}`,
239
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
240
- validation: validation,
241
- validationVisibility: 'live',
242
- },
243
- };
244
- case 'date':
245
- return {
246
- type: 'FormKit',
247
- props: {
248
- type: 'date',
249
- id: field.id,
250
- name: name,
251
- label: field.label,
252
- required: field.required,
253
- value: field.defaultValue,
254
- help: hint,
255
- wrapperClass: '$remove:formkit-wrapper',
256
- inputClass: `input-${this.theme}`,
257
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
258
- validation: validation,
259
- validationVisibility: 'live',
260
- },
261
- };
262
- case 'enum':
263
- const enums = field.enumValues.map((obj) => {
264
- return { value: obj.id, label: obj.name };
265
- });
266
- return {
267
- type: 'FormKit',
268
- props: {
269
- type: 'select', // JSON.parse(field.customForm).displayAs
270
- id: field.id,
271
- name: name,
272
- label: field.label,
273
- required: field.required,
274
- value: field.defaultValue,
275
- options: enums,
276
- help: hint,
277
- wrapperClass: '$remove:formkit-wrapper',
278
- inputClass: `input-${this.theme}`,
279
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
280
- validation: validation,
281
- validationVisibility: 'live',
282
- },
283
- };
284
- case 'select':
285
- const selections = JSON.parse(field.customForm).entries.map((obj) => {
286
- return { value: obj.key, label: obj.value };
287
- });
288
- return {
289
- type: 'FormKit',
290
- props: {
291
- type: 'select', // JSON.parse(field.customForm).displayAs
292
- id: field.id,
293
- name: name,
294
- label: field.label,
295
- required: field.required,
296
- value: field.defaultValue,
297
- options: selections,
298
- placeholder: placeholder,
299
- help: hint,
300
- wrapperClass: '$remove:formkit-wrapper',
301
- inputClass: `input-${this.theme}`,
302
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
303
- validation: validation,
304
- validationVisibility: 'live',
305
- },
306
- };
307
- case 'string':
308
- return {
309
- type: 'FormKit',
310
- props: {
311
- type: 'text',
312
- id: field.id,
313
- name: name,
314
- label: field.label,
315
- required: field.required,
316
- value: field.defaultValue,
317
- help: hint,
318
- placeholder: placeholder,
319
- wrapperClass: '$remove:formkit-wrapper',
320
- inputClass: `input-${this.theme}`,
321
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
322
- validation: validation,
323
- validationVisibility: 'live',
324
- },
325
- };
326
- case 'boolean':
327
- return {
328
- type: 'FormKit',
329
- props: {
330
- type: 'checkbox',
331
- id: field.id,
332
- name: name,
333
- label: field.label,
334
- required: field.required,
335
- value: field.defaultValue,
336
- help: hint,
337
- inputClass: `input-${this.theme}`,
338
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
339
- validation: validation,
340
- validationVisibility: 'live',
341
- },
342
- };
343
- case 'file':
344
- return {
345
- type: 'FormKit',
346
- props: {
347
- type: 'file',
348
- id: field.id,
349
- name: name,
350
- label: field.label,
351
- required: field.required,
352
- value: field.defaultValue,
353
- help: hint,
354
- innerClass: 'reset-background',
355
- wrapperClass: '$remove:formkit-wrapper',
356
- inputClass: `input-${this.theme}`,
357
- // innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
358
- validation: validation,
359
- validationVisibility: 'live',
360
- },
361
- };
362
- case 'checkbox':
363
- const options = JSON.parse(field.customForm).entries.map((obj) => {
364
- return { value: obj.key, label: obj.value };
365
- });
366
- return {
367
- type: 'FormKit',
368
- props: {
369
- type: 'checkbox',
370
- id: field.id,
371
- name: name,
372
- label: field.label,
373
- required: field.required,
374
- value: field.defaultValue,
375
- options: options,
376
- help: hint,
377
- fieldsetClass: 'custom-fieldset',
378
- inputClass: `input-${this.theme}`,
379
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
380
- validation: validation,
381
- validationVisibility: 'live',
382
- },
383
- };
384
- case 'color':
385
- return {
386
- type: 'FormKit',
387
- props: {
388
- type: 'color',
389
- id: field.id,
390
- name: name,
391
- label: field.label,
392
- required: field.required,
393
- value: field.defaultValue,
394
- help: hint,
395
- validation: validation,
396
- validationVisibility: 'live',
397
- },
398
- };
399
- case 'datetime-local':
400
- return {
401
- type: 'FormKit',
402
- props: {
403
- type: 'datetime-local',
404
- id: field.id,
405
- name: name,
406
- label: field.label,
407
- required: field.required,
408
- value: field.defaultValue,
409
- help: hint,
410
- wrapperClass: '$remove:formkit-wrapper',
411
- inputClass: `input-${this.theme}`,
412
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
413
- validation: validation,
414
- validationVisibility: 'live',
415
- },
416
- };
417
- case 'email':
418
- return {
419
- type: 'FormKit',
420
- props: {
421
- type: 'email',
422
- id: field.id,
423
- name: name,
424
- label: field.label,
425
- required: field.required,
426
- value: field.defaultValue,
427
- help: hint,
428
- validation: 'email',
429
- validationVisibility: 'live',
430
- placeholder: placeholder,
431
- wrapperClass: '$remove:formkit-wrapper',
432
- inputClass: `input-${this.theme}`,
433
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
434
- validation: validation,
435
- validationVisibility: 'live',
436
- },
437
- };
438
- case 'header':
439
- let typeToUse = 'h1';
440
- if (field.customForm && JSON.parse(field.customForm).style == 'heading_2') {
441
- typeToUse = 'h2';
442
- }
443
- if (field.customForm && JSON.parse(field.customForm).style == 'heading_3') {
444
- typeToUse = 'h3';
445
- }
446
- return {
447
- type: typeToUse,
448
- innerText: field.defaultValue,
449
- };
450
- case 'hidden':
451
- return {
452
- type: 'input',
453
- props: {
454
- type: 'hidden',
455
- value: field.defaultValue,
456
- },
457
- };
458
- case 'month':
459
- return {
460
- type: 'FormKit',
461
- props: {
462
- type: 'month',
463
- id: field.id,
464
- name: name,
465
- label: field.label,
466
- required: field.required,
467
- value: field.defaultValue,
468
- help: hint,
469
- wrapperClass: '$remove:formkit-wrapper',
470
- inputClass: `input-${this.theme}`,
471
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
472
- validation: validation,
473
- validationVisibility: 'live',
474
- },
475
- };
476
- case 'paragraph':
477
- return {
478
- type: 'p',
479
- innerText: field.defaultValue,
480
- };
481
- case 'password':
482
- return {
483
- type: 'FormKit',
484
- props: {
485
- type: 'password',
486
- id: field.id,
487
- name: name,
488
- label: field.label,
489
- required: field.required,
490
- value: field.defaultValue,
491
- help: hint,
492
- placeholder: placeholder,
493
- wrapperClass: '$remove:formkit-wrapper',
494
- inputClass: `input-${this.theme}`,
495
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
496
- validation: validation,
497
- validationVisibility: 'live',
498
- },
499
- };
500
- case 'radio':
501
- const radioOptions = JSON.parse(field.customForm).entries.map((obj) => {
502
- return { value: obj.key, label: obj.value };
503
- });
504
- return {
505
- type: 'FormKit',
506
- props: {
507
- type: 'radio',
508
- id: field.id,
509
- name: name,
510
- label: field.label,
511
- required: field.required,
512
- value: field.defaultValue,
513
- options: radioOptions,
514
- help: hint,
515
- fieldsetClass: 'custom-fieldset',
516
- inputClass: `input-${this.theme}`,
517
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
518
- validation: validation,
519
- validationVisibility: 'live',
520
- },
521
- };
522
- case 'range':
523
- const customForm = JSON.parse(field.customForm);
524
- return {
525
- type: 'v-slider',
526
- props: {
527
- id: field.id,
528
- name: name,
529
- // label: field.label,
530
- required: field.required,
531
- // value: field.defaultValue,
532
- // help: hint,
533
- min: customForm.min,
534
- max: customForm.max,
535
- step: customForm.step,
536
- thumbLabel: true,
537
- // wrapperClass: '$remove:formkit-wrapper',
538
- // inputClass: `input-${this.theme}`,
539
- // innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
540
- validation: validation,
541
- validationVisibility: 'live',
542
- },
543
- };
544
- case 'tel':
545
- return {
546
- type: 'FormKit',
547
- props: {
548
- type: 'tel' /* with pro component mask more good */,
549
- id: field.id,
550
- name: name,
551
- label: field.label,
552
- required: field.required,
553
- value: field.defaultValue,
554
- help: hint,
555
- placeholder: placeholder,
556
- wrapperClass: '$remove:formkit-wrapper',
557
- inputClass: `input-${this.theme}`,
558
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
559
- validation: validation,
560
- validationVisibility: 'live',
561
- },
562
- };
563
- case 'textarea':
564
- const rows = field.customForm ? JSON.parse(field.customForm).rows : undefined;
565
- return {
566
- type: 'FormKit',
567
- props: {
568
- type: 'textarea' /* with pro component mask more good */,
569
- id: field.id,
570
- name: name,
571
- label: field.label,
572
- required: field.required,
573
- value: field.defaultValue,
574
- rows: rows,
575
- help: hint,
576
- placeholder: placeholder,
577
- wrapperClass: '$remove:formkit-wrapper',
578
- inputClass: `input-${this.theme}`,
579
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
580
- validation: validation,
581
- validationVisibility: 'live',
582
- },
583
- };
584
- case 'time':
585
- return {
586
- type: 'FormKit',
587
- props: {
588
- type: 'time' /* with pro component mask more good */,
589
- id: field.id,
590
- name: name,
591
- label: field.label,
592
- required: field.required,
593
- value: field.defaultValue,
594
- help: hint,
595
- placeholder: placeholder,
596
- wrapperClass: '$remove:formkit-wrapper',
597
- inputClass: `input-${this.theme}`,
598
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
599
- validation: validation,
600
- validationVisibility: 'live',
601
- },
602
- };
603
- case 'url':
604
- return {
605
- type: 'FormKit',
606
- props: {
607
- type: 'url',
608
- id: field.id,
609
- name: name,
610
- label: field.label,
611
- required: field.required,
612
- value: field.defaultValue,
613
- help: hint,
614
- placeholder: placeholder,
615
- validation: 'url',
616
- validationVisibility: 'live',
617
- wrapperClass: '$remove:formkit-wrapper',
618
- inputClass: `input-${this.theme}`,
619
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
620
- validation: validation,
621
- validationVisibility: 'live',
622
- },
623
- };
624
- case 'week':
625
- return {
626
- type: 'FormKit',
627
- props: {
628
- type: 'week',
629
- id: field.id,
630
- name: name,
631
- label: field.label,
632
- required: field.required,
633
- value: field.defaultValue,
634
- help: hint,
635
- placeholder: placeholder,
636
- wrapperClass: '$remove:formkit-wrapper',
637
- inputClass: `input-${this.theme}`,
638
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
639
- validation: validation,
640
- validationVisibility: 'live',
641
- },
642
- };
643
- default:
644
- return {
645
- type: 'FormKit',
646
- props: {
647
- type: field.type,
648
- id: field.id,
649
- name: name,
650
- label: field.label,
651
- required: field.required,
652
- value: field.defaultValue,
653
- help: hint,
654
- inputClass: `input-${this.theme}`,
655
- innerClass: `${this.theme == 'dark' ? '$remove:formkit-inner' : ''}`,
656
- validation: validation,
657
- validationVisibility: 'live',
658
- },
659
- };
660
- }
197
+ this.$store.commit('data/bind', {
198
+ widgetId: this.id,
199
+ msg
200
+ })
201
+ })
202
+ // tell Node-RED that we're loading a new instance of this widget
203
+ this.$socket.emit('widget-load', this.id)
661
204
  },
662
- checkFormState(state) {
663
- // const field = this.$formkit.get('field_01');
664
- // console.info(field.context.state.valid);
205
+ unmounted () {
206
+ /* Make sure, any events you subscribe to on SocketIO are unsubscribed to here */
207
+ this.$socket?.off('widget-load' + this.id)
208
+ this.$socket?.off('msg-input:' + this.id)
209
+ },
210
+ methods: {
211
+ createComponent (field) {
212
+ const hint = field.customForm ? JSON.parse(field.customForm).hint : undefined
213
+ const placeholder = field.customForm ? JSON.parse(field.customForm).placeholder : undefined
214
+ switch (field.type) {
215
+ case 'long':
216
+ return {
217
+ type: 'FormKit',
218
+ props: {
219
+ type: 'number',
220
+ id: field.id,
221
+ label: field.label,
222
+ required: field.required,
223
+ value: field.defaultValue,
224
+ number: 'integer',
225
+ help: hint,
226
+ wrapperClass: '$remove:formkit-wrapper',
227
+ labelClass: 'ui-dynamic-form-input-label',
228
+ inputClass: `input-${this.theme}`,
229
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
230
+ readonly: this.props.readonly ? 'true' : undefined
231
+ }
232
+ }
233
+ case 'number':
234
+ const step = field.customForm ? JSON.parse(field.customForm).step : undefined
235
+ return {
236
+ type: 'FormKit',
237
+ props: {
238
+ type: 'number',
239
+ id: field.id,
240
+ label: field.label,
241
+ required: field.required,
242
+ value: field.defaultValue,
243
+ step,
244
+ help: hint,
245
+ wrapperClass: '$remove:formkit-wrapper',
246
+ labelClass: 'ui-dynamic-form-input-label',
247
+ inputClass: `input-${this.theme}`,
248
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
249
+ readonly: this.props.readonly ? 'true' : undefined
250
+ }
251
+ }
252
+ case 'date':
253
+ return {
254
+ type: 'FormKit',
255
+ props: {
256
+ type: 'date',
257
+ id: field.id,
258
+ label: field.label,
259
+ required: field.required,
260
+ value: field.defaultValue,
261
+ help: hint,
262
+ wrapperClass: '$remove:formkit-wrapper',
263
+ labelClass: 'ui-dynamic-form-input-label',
264
+ inputClass: `input-${this.theme}`,
265
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
266
+ readonly: this.props.readonly ? 'true' : undefined
267
+ }
268
+ }
269
+ case 'enum':
270
+ const enums = field.enumValues.map((obj) => {
271
+ return { value: obj.id, label: obj.name }
272
+ })
273
+ return {
274
+ type: 'FormKit',
275
+ props: {
276
+ type: 'select', // JSON.parse(field.customForm).displayAs
277
+ id: field.id,
278
+ label: field.label,
279
+ required: field.required,
280
+ value: field.defaultValue,
281
+ options: enums,
282
+ help: hint,
283
+ wrapperClass: '$remove:formkit-wrapper',
284
+ labelClass: 'ui-dynamic-form-input-label',
285
+ inputClass: `input-${this.theme}`,
286
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
287
+ readonly: this.props.readonly ? 'true' : undefined,
288
+ disabled: this.props.readonly ? 'true' : undefined
289
+ }
290
+ }
291
+ case 'select':
292
+ const selections = JSON.parse(field.customForm).entries.map((obj) => {
293
+ return { value: obj.key, label: obj.value }
294
+ })
295
+ return {
296
+ type: 'FormKit',
297
+ props: {
298
+ type: 'select', // JSON.parse(field.customForm).displayAs
299
+ id: field.id,
300
+ label: field.label,
301
+ required: field.required,
302
+ value: field.defaultValue,
303
+ options: selections,
304
+ placeholder,
305
+ help: hint,
306
+ wrapperClass: '$remove:formkit-wrapper',
307
+ labelClass: 'ui-dynamic-form-input-label',
308
+ inputClass: `input-${this.theme}`,
309
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
310
+ readonly: this.props.readonly ? 'true' : undefined,
311
+ disabled: this.props.readonly ? 'true' : undefined
312
+ }
313
+ }
314
+ case 'string':
315
+ return {
316
+ type: 'FormKit',
317
+ props: {
318
+ type: 'text',
319
+ id: field.id,
320
+ label: field.label,
321
+ required: field.required,
322
+ value: field.defaultValue,
323
+ help: hint,
324
+ placeholder,
325
+ wrapperClass: '$remove:formkit-wrapper',
326
+ labelClass: 'ui-dynamic-form-input-label',
327
+ inputClass: `input-${this.theme}`,
328
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
329
+ readonly: this.props.readonly ? 'true' : undefined
330
+ }
331
+ }
332
+ case 'boolean':
333
+ return {
334
+ type: 'FormKit',
335
+ props: {
336
+ type: 'checkbox',
337
+ id: field.id,
338
+ label: field.label,
339
+ required: field.required,
340
+ value: field.defaultValue,
341
+ help: hint,
342
+ labelClass: 'ui-dynamic-form-input-label',
343
+ inputClass: `input-${this.theme}`,
344
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
345
+ readonly: this.props.readonly ? 'true' : undefined,
346
+ disabled: this.props.readonly ? 'true' : undefined
347
+ }
348
+ }
349
+ case 'file':
350
+ return {
351
+ type: 'FormKit',
352
+ props: {
353
+ type: 'file',
354
+ id: field.id,
355
+ label: field.label,
356
+ required: field.required,
357
+ value: field.defaultValue,
358
+ help: hint,
359
+ innerClass: 'reset-background',
360
+ wrapperClass: '$remove:formkit-wrapper',
361
+ labelClass: 'ui-dynamic-form-input-label',
362
+ inputClass: `input-${this.theme}`,
363
+ // innerClass: ui-dynamic-form-input-outlines `${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
364
+ readonly: this.props.readonly ? 'true' : undefined,
365
+ disabled: this.props.readonly ? 'true' : undefined
366
+ }
367
+ }
368
+ case 'checkbox':
369
+ const options = JSON.parse(field.customForm).entries.map((obj) => {
370
+ return { value: obj.key, label: obj.value }
371
+ })
372
+ return {
373
+ type: 'FormKit',
374
+ props: {
375
+ type: 'checkbox',
376
+ id: field.id,
377
+ label: field.label,
378
+ required: field.required,
379
+ value: field.defaultValue,
380
+ options,
381
+ help: hint,
382
+ fieldsetClass: 'custom-fieldset',
383
+ labelClass: 'ui-dynamic-form-input-label',
384
+ inputClass: `input-${this.theme}`,
385
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
386
+ readonly: this.props.readonly ? 'true' : undefined,
387
+ disabled: this.props.readonly ? 'true' : undefined
388
+ }
389
+ }
390
+ case 'color':
391
+ return {
392
+ type: 'FormKit',
393
+ props: {
394
+ type: 'color',
395
+ id: field.id,
396
+ label: field.label,
397
+ required: field.required,
398
+ value: field.defaultValue,
399
+ help: hint,
400
+ readonly: this.props.readonly ? 'true' : undefined,
401
+ disabled: this.props.readonly ? 'true' : undefined
402
+ }
403
+ }
404
+ case 'datetime-local':
405
+ return {
406
+ type: 'FormKit',
407
+ props: {
408
+ type: 'datetime-local',
409
+ id: field.id,
410
+ label: field.label,
411
+ required: field.required,
412
+ value: field.defaultValue,
413
+ help: hint,
414
+ wrapperClass: '$remove:formkit-wrapper',
415
+ labelClass: 'ui-dynamic-form-input-label',
416
+ inputClass: `input-${this.theme}`,
417
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
418
+ readonly: this.props.readonly ? 'true' : undefined
419
+ }
420
+ }
421
+ case 'email':
422
+ return {
423
+ type: 'FormKit',
424
+ props: {
425
+ type: 'email',
426
+ id: field.id,
427
+ label: field.label,
428
+ required: field.required,
429
+ value: field.defaultValue,
430
+ help: hint,
431
+ validation: 'email',
432
+ validationVisibility: 'live',
433
+ placeholder,
434
+ wrapperClass: '$remove:formkit-wrapper',
435
+ labelClass: 'ui-dynamic-form-input-label',
436
+ inputClass: `input-${this.theme}`,
437
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
438
+ readonly: this.props.readonly ? 'true' : undefined
439
+ }
440
+ }
441
+ case 'header':
442
+ let typeToUse = 'h1'
443
+ if (field.customForm && JSON.parse(field.customForm).style === 'heading_2') {
444
+ typeToUse = 'h2'
445
+ }
446
+ if (field.customForm && JSON.parse(field.customForm).style === 'heading_3') {
447
+ typeToUse = 'h3'
448
+ }
449
+ return {
450
+ type: typeToUse,
451
+ innerText: field.defaultValue
452
+ }
453
+ case 'hidden':
454
+ return {
455
+ type: 'input',
456
+ props: {
457
+ type: 'hidden',
458
+ value: field.defaultValue
459
+ }
460
+ }
461
+ case 'month':
462
+ return {
463
+ type: 'FormKit',
464
+ props: {
465
+ type: 'month',
466
+ id: field.id,
467
+ label: field.label,
468
+ required: field.required,
469
+ value: field.defaultValue,
470
+ help: hint,
471
+ wrapperClass: '$remove:formkit-wrapper',
472
+ labelClass: 'ui-dynamic-form-input-label',
473
+ inputClass: `input-${this.theme}`,
474
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
475
+ readonly: this.props.readonly ? 'true' : undefined
476
+ }
477
+ }
478
+ case 'paragraph':
479
+ return {
480
+ type: 'p',
481
+ innerText: field.defaultValue
482
+ }
483
+ case 'password':
484
+ return {
485
+ type: 'FormKit',
486
+ props: {
487
+ type: 'password',
488
+ id: field.id,
489
+ label: field.label,
490
+ required: field.required,
491
+ value: field.defaultValue,
492
+ help: hint,
493
+ placeholder,
494
+ wrapperClass: '$remove:formkit-wrapper',
495
+ labelClass: 'ui-dynamic-form-input-label',
496
+ inputClass: `input-${this.theme}`,
497
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
498
+ readonly: this.props.readonly ? 'true' : undefined
499
+ }
500
+ }
501
+ case 'radio':
502
+ const radioOptions = JSON.parse(field.customForm).entries.map((obj) => {
503
+ return { value: obj.key, label: obj.value }
504
+ })
505
+ return {
506
+ type: 'FormKit',
507
+ props: {
508
+ type: 'radio',
509
+ id: field.id,
510
+ label: field.label,
511
+ required: field.required,
512
+ value: field.defaultValue,
513
+ options: radioOptions,
514
+ help: hint,
515
+ fieldsetClass: 'custom-fieldset',
516
+ labelClass: 'ui-dynamic-form-input-label',
517
+ inputClass: `input-${this.theme}`,
518
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
519
+ readonly: this.props.readonly ? 'true' : undefined,
520
+ disabled: this.props.readonly ? 'true' : undefined
521
+ }
522
+ }
523
+ case 'range':
524
+ const customForm = JSON.parse(field.customForm)
525
+ return {
526
+ type: 'v-slider',
527
+ props: {
528
+ id: field.id,
529
+ // label: field.label,
530
+ required: field.required,
531
+ // value: field.defaultValue,
532
+ // help: hint,
533
+ min: customForm.min,
534
+ max: customForm.max,
535
+ step: customForm.step,
536
+ thumbLabel: true,
537
+ // wrapperClass: '$remove:formkit-wrapper',
538
+ labelClass: 'ui-dynamic-form-input-label',
539
+ // inputClass: `input-${this.theme}`,
540
+ // innerClass: ui-dynamic-form-input-outlines `${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
541
+ readonly: this.props.readonly ? 'true' : undefined,
542
+ disabled: this.props.readonly ? 'true' : undefined
543
+ }
544
+ }
545
+ case 'tel':
546
+ return {
547
+ type: 'FormKit',
548
+ props: {
549
+ type: 'tel' /* with pro component mask more good */,
550
+ id: field.id,
551
+ label: field.label,
552
+ required: field.required,
553
+ value: field.defaultValue,
554
+ help: hint,
555
+ placeholder,
556
+ wrapperClass: '$remove:formkit-wrapper',
557
+ labelClass: 'ui-dynamic-form-input-label',
558
+ inputClass: `input-${this.theme}`,
559
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
560
+ readonly: this.props.readonly ? 'true' : undefined
561
+ }
562
+ }
563
+ case 'textarea':
564
+ const rows = field.customForm ? JSON.parse(field.customForm).rows : undefined
565
+ return {
566
+ type: 'FormKit',
567
+ props: {
568
+ type: 'textarea' /* with pro component mask more good */,
569
+ id: field.id,
570
+ label: field.label,
571
+ required: field.required,
572
+ value: field.defaultValue,
573
+ rows,
574
+ help: hint,
575
+ placeholder,
576
+ wrapperClass: '$remove:formkit-wrapper',
577
+ labelClass: 'ui-dynamic-form-input-label',
578
+ inputClass: `input-${this.theme}`,
579
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
580
+ readonly: this.props.readonly ? 'true' : undefined
581
+ }
582
+ }
583
+ case 'time':
584
+ return {
585
+ type: 'FormKit',
586
+ props: {
587
+ type: 'time' /* with pro component mask more good */,
588
+ id: field.id,
589
+ label: field.label,
590
+ required: field.required,
591
+ value: field.defaultValue,
592
+ help: hint,
593
+ placeholder,
594
+ wrapperClass: '$remove:formkit-wrapper',
595
+ labelClass: 'ui-dynamic-form-input-label',
596
+ inputClass: `input-${this.theme}`,
597
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
598
+ readonly: this.props.readonly ? 'true' : undefined
599
+ }
600
+ }
601
+ case 'url':
602
+ return {
603
+ type: 'FormKit',
604
+ props: {
605
+ type: 'url',
606
+ id: field.id,
607
+ label: field.label,
608
+ required: field.required,
609
+ value: field.defaultValue,
610
+ help: hint,
611
+ placeholder,
612
+ validation: 'url',
613
+ validationVisibility: 'live',
614
+ wrapperClass: '$remove:formkit-wrapper',
615
+ labelClass: 'ui-dynamic-form-input-label',
616
+ inputClass: `input-${this.theme}`,
617
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
618
+ readonly: this.props.readonly ? 'true' : undefined
619
+ }
620
+ }
621
+ case 'week':
622
+ return {
623
+ type: 'FormKit',
624
+ props: {
625
+ type: 'week',
626
+ id: field.id,
627
+ label: field.label,
628
+ required: field.required,
629
+ value: field.defaultValue,
630
+ help: hint,
631
+ placeholder,
632
+ wrapperClass: '$remove:formkit-wrapper',
633
+ labelClass: 'ui-dynamic-form-input-label',
634
+ inputClass: `input-${this.theme}`,
635
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
636
+ readonly: this.props.readonly ? 'true' : undefined
637
+ }
638
+ }
639
+ default:
640
+ return {
641
+ type: 'FormKit',
642
+ props: {
643
+ type: field.type,
644
+ id: field.id,
645
+ label: field.label,
646
+ required: field.required,
647
+ value: field.defaultValue,
648
+ help: hint,
649
+ labelClass: 'ui-dynamic-form-input-label',
650
+ inputClass: `input-${this.theme}`,
651
+ innerClass: `ui-dynamic-form-input-outlines ${this.theme === 'dark' ? '$remove:formkit-inner' : ''}`,
652
+ readonly: this.props.readonly ? 'true' : undefined
653
+ }
654
+ }
655
+ }
656
+ },
657
+ checkFormState (state) {
658
+ // const field = this.$formkit.get('field_01');
659
+ // console.info(field.context.state.valid);
665
660
 
666
- return true;
661
+ return true
667
662
 
668
- // loop over fields then this.$formkit.get(this.id) -> check error state if all ok return true else return false
669
- // ?? wie unterscheiden wir welche actions dieser validierungsfehler betrifft ??
670
- // ?? wie machen wir formkit validierung auch im Studio available ??
671
- // \_ vllt macht es sinn das schema von formkit zu übernehmen oder alternativ nur unsere validierung zu nutzen.
672
- },
673
- hasUserTask() {
674
- return this.messages && this.messages[this.id] && this.messages[this.id].payload.userTask;
675
- },
676
- userTask() {
677
- return this.hasUserTask() ? this.messages[this.id].payload.userTask : {};
678
- },
679
- fields() {
680
- const aFields = this.hasUserTask() ? this.userTask().userTaskConfig.formFields : [];
681
- const fieldMap = aFields.map((field) => ({
682
- ...field,
683
- items: mapItems(field.type, field),
684
- }));
663
+ // loop over fields then this.$formkit.get(this.id) -> check error state if all ok return true else return false
664
+ // ?? wie unterscheiden wir welche actions dieser validierungsfehler betrifft ??
665
+ // ?? wie machen wir formkit validierung auch im Studio available ??
666
+ // \_ vllt macht es sinn das schema von formkit zu übernehmen oder alternativ nur unsere validierung zu nutzen.
667
+ },
668
+ hasUserTask () {
669
+ return this.messages && this.messages[this.id] && this.messages[this.id].payload?.userTask
670
+ },
671
+ userTask () {
672
+ return this.hasUserTask() ? this.messages[this.id].payload.userTask : {}
673
+ },
674
+ getRowWidthStyling (field, index) {
675
+ let style = ''
676
+ if (index === 0) {
677
+ style += 'margin-top: 12px;'
678
+ }
679
+ if (field.type === 'header') {
680
+ style += 'flex-basis: 100%;'
681
+ } else {
682
+ style += `flex-basis: ${1 / this.props.form_columns * 100}%;`
683
+ }
684
+ return style
685
+ },
686
+ fields () {
687
+ const aFields = this.userTask()?.userTaskConfig?.formFields ?? []
688
+ const fieldMap = aFields.map((field) => ({
689
+ ...field,
690
+ items: mapItems(field.type, field)
691
+ }))
685
692
 
686
- return fieldMap;
687
- },
688
- hasFields() {
689
- return this.messages && this.messages[this.id] && this.messages[this.id].payload.userTask !== undefined;
690
- },
691
- /*
693
+ return fieldMap
694
+ },
695
+ /*
692
696
  widget-action just sends a msg to Node-RED, it does not store the msg state server-side
693
697
  alternatively, you can use widget-change, which will also store the msg in the Node's datastore
694
698
  */
695
- send(msg, index) {
696
- const msgArr = [];
697
- msgArr[index] = msg;
698
- this.$socket.emit('widget-action', this.id, msgArr);
699
- },
700
- init() {
701
- this.actions = this.props.options;
702
- },
703
- actionFn(action) {
704
- // this.checkFormState();
705
-
706
- if (action.label === 'Speichern' || action.label === 'Speichern und nächster') {
707
- const formkitInputs = this.$refs.form.$el.querySelectorAll('.formkit-outer');
708
- let allComplete = true;
709
-
710
- formkitInputs.forEach((input) => {
711
- const dataComplete = input.getAttribute('data-complete');
712
- const dataInvalid = input.getAttribute('data-invalid')
713
-
714
- if (dataComplete == null && dataInvalid === "true") {
715
- allComplete = false;
699
+ send (msg, index) {
700
+ const msgArr = []
701
+ msgArr[index] = msg
702
+ this.$socket.emit('widget-action', this.id, msgArr)
703
+ },
704
+ init () {
705
+ this.actions = this.props.options
706
+ },
707
+ actionFn (action) {
708
+ // this.checkFormState();
709
+ if (this.checkCondition(action.condition)) {
710
+ this.showError(false, '')
711
+ // TODO: MM - begin
712
+ // this.send(
713
+ // { payload: { formData: this.formData, userTask: this.userTask() } },
714
+ // this.actions.findIndex((element) => element.label === action.label)
715
+ // );
716
+ const msg = this.messages[this.id] || {}
717
+ msg.payload = { formData: this.formData, userTask: this.userTask() }
718
+ this.send(
719
+ msg,
720
+ this.actions.findIndex((element) => element.label === action.label)
721
+ )
722
+ // TODO: mm - end
723
+ } else {
724
+ this.showError(true, action.errorMessage)
716
725
  }
717
- });
718
-
719
- if (!allComplete) return;
720
- }
721
-
722
- if (this.checkCondition(action.condition)) {
723
- this.showError(false, '');
724
- // TODO: MM - begin
725
- // this.send(
726
- // { payload: { formData: this.formData, userTask: this.userTask() } },
727
- // this.actions.findIndex((element) => element.label === action.label)
728
- // );
729
- const msg = this.messages[this.id] || {};
730
- msg.payload = { formData: this.formData, userTask: this.userTask() };
731
- this.send(
732
- msg,
733
- this.actions.findIndex((element) => element.label === action.label)
734
- );
735
- // TODO: mm - end
736
- } else {
737
- this.showError(true, action.errorMessage);
738
- }
739
- },
740
- checkCondition(condition) {
741
- if (condition == '') return true;
742
- try {
743
- const func = Function('fields', 'userTask', 'msg', '"use strict"; return (' + condition + ')');
744
- const result = func(this.formData, this.taskInput, this.messages[this.id]);
745
- console.log(this.formData, result);
746
- return Boolean(result);
747
- } catch (err) {
748
- console.error('Error while evaluating condition: ' + err);
749
- return false;
750
- }
751
- },
752
- showError(bool, errMsg) {
753
- this.error = bool;
754
- this.errorMsg = errMsg;
755
- },
756
- },
757
- };
726
+ },
727
+ checkCondition (condition) {
728
+ if (condition === '') return true
729
+ try {
730
+ // eslint-disable-next-line no-new-func
731
+ const func = Function('fields', 'userTask', 'msg', '"use strict"; return (' + condition + ')')
732
+ const result = func(this.formData, this.taskInput, this.messages[this.id])
733
+ return Boolean(result)
734
+ } catch (err) {
735
+ console.error('Error while evaluating condition: ' + err)
736
+ return false
737
+ }
738
+ },
739
+ showError (bool, errMsg) {
740
+ this.error = bool
741
+ this.errorMsg = errMsg
742
+ }
743
+ }
744
+ }
758
745
 
759
- function mapItems(type, field) {
760
- if (type === 'enum') {
761
- return field.enumValues.map((enumValue) => ({
762
- title: enumValue.name,
763
- value: enumValue.id,
764
- }));
765
- } else {
766
- return null;
767
- }
746
+ function mapItems (type, field) {
747
+ if (type === 'enum') {
748
+ return field.enumValues.map((enumValue) => ({
749
+ title: enumValue.name,
750
+ value: enumValue.id
751
+ }))
752
+ } else {
753
+ return null
754
+ }
768
755
  }
769
756
  </script>
770
757