@5minds/node-red-dashboard-2-processcube-dynamic-form 1.1.2-develop-f834c0-m5z4zfc5 → 1.1.2-develop-231918-m7na5yab

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