@raclettejs/workbench 0.1.11 → 0.1.12
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/CHANGELOG.md +20 -1
- package/i18n/de-DE.json +7 -1
- package/i18n/en-EU.json +9 -3
- package/i18n/sk-SK.json +4 -3
- package/package.json +5 -4
- package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/CompositionConfiguration.vue +10 -0
- package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetSettings.vue +13 -3
- package/plugins/pacifico__compositions/frontend/widgets/CompositionCreateWidget.vue +1 -0
- package/plugins/pacifico__interactionLinks/frontend/components/InteractionLinkConfiguration.vue +6 -1
- package/plugins/pacifico__tags/frontend/widgets/TagListWidget.vue +4 -0
- package/services/frontend/src/app/components/BaseDataTable.vue +10 -0
- package/services/frontend/src/app/components/dynamicForm/DynamicFormTypes.ts +8 -3
- package/services/frontend/src/app/components/dynamicForm/DynamicInput.vue +13 -2
- package/services/frontend/src/app/components/dynamicForm/ObjectListInput.vue +193 -0
- package/services/frontend/src/app/components/dynamicForm/typedInputs/UserInput.vue +0 -1
- package/services/frontend/src/orchestrator/WelcomeScreen.vue +32 -34
- package/yarn.lock +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [0.1.11] - 19.09.2025 <a href="https://gitlab.com/raclettejs/
|
|
10
|
+
## [0.1.11] - 19.09.2025 <a href="https://gitlab.com/raclettejs/workbench/-/compare/v0.1.11...v0.1.12" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
|
+
|
|
12
|
+
### Updated
|
|
13
|
+
|
|
14
|
+
- updated versions to latest core
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Added color column to tagList
|
|
19
|
+
- new field "slotLayout" for composition
|
|
20
|
+
- default set of settings per widget – temporary solution
|
|
21
|
+
- added datePicker option for dynamic form renderer
|
|
22
|
+
- added objectList for dynamic form renderer
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- removed v-container from welcome screen
|
|
27
|
+
- fixed i18n
|
|
28
|
+
|
|
29
|
+
## [0.1.11] - 19.09.2025 <a href="https://gitlab.com/raclettejs/workbench/-/compare/v0.1.10...v0.1.11" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
30
|
|
|
12
31
|
### Security
|
|
13
32
|
|
package/i18n/de-DE.json
CHANGED
|
@@ -77,7 +77,8 @@
|
|
|
77
77
|
},
|
|
78
78
|
"divider": {
|
|
79
79
|
"general": "Allgemein",
|
|
80
|
-
"navigation": "Navigation"
|
|
80
|
+
"navigation": "Navigation",
|
|
81
|
+
"styling": "Styling"
|
|
81
82
|
},
|
|
82
83
|
"title": {
|
|
83
84
|
"title": "Bezeichnung / Titel",
|
|
@@ -94,6 +95,10 @@
|
|
|
94
95
|
"pathname": {
|
|
95
96
|
"title": "Pfadname",
|
|
96
97
|
"description": "Beschreibt den technischen Titel, der entweder als URL-Pfad, Query-Parameter und andersweitige Referenzierung genutzt wird. Darf keine Leerzeichen enthalten."
|
|
98
|
+
},
|
|
99
|
+
"slotLayout": {
|
|
100
|
+
"title": "Slot Layout",
|
|
101
|
+
"description": "Beschreibt das Zusammenspiel der einzelnen Widgets auf der Seite (Abstände sowie Rahmen pro Widget)"
|
|
97
102
|
}
|
|
98
103
|
},
|
|
99
104
|
"interactionLinkList": {
|
|
@@ -193,6 +198,7 @@
|
|
|
193
198
|
"dataArticle": "den",
|
|
194
199
|
"tableHeaders": {
|
|
195
200
|
"title": "Bezeichnung",
|
|
201
|
+
"color": "Farbe",
|
|
196
202
|
"type": "Typ",
|
|
197
203
|
"tags": "Tags",
|
|
198
204
|
"updatedAt": "Zuletzt geändert"
|
package/i18n/en-EU.json
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
"save_finish": "Save & Finish"
|
|
8
8
|
},
|
|
9
9
|
"loginScreen": {
|
|
10
|
-
"title": "Welcome to the Raclette
|
|
10
|
+
"title": "Welcome to the Raclette Workbench!",
|
|
11
11
|
"eMail": "Email",
|
|
12
12
|
"password": "Password",
|
|
13
13
|
"login": "Login"
|
|
14
14
|
},
|
|
15
15
|
"welcomeScreen": {
|
|
16
|
-
"title": "Welcome to the Raclette
|
|
16
|
+
"title": "Welcome to the Raclette Workbench!",
|
|
17
17
|
"whatIsWhat": "What is what?",
|
|
18
18
|
"compositionInfo": "Create compositions to define the layout of your pages or modals",
|
|
19
19
|
"interactionLinkInfo": "Create InteractionLinks to define how users can access pages or modals",
|
|
@@ -77,7 +77,8 @@
|
|
|
77
77
|
},
|
|
78
78
|
"divider": {
|
|
79
79
|
"general": "General",
|
|
80
|
-
"navigation": "Navigation"
|
|
80
|
+
"navigation": "Navigation",
|
|
81
|
+
"styling": "Styling"
|
|
81
82
|
},
|
|
82
83
|
"title": {
|
|
83
84
|
"title": "Title",
|
|
@@ -94,6 +95,10 @@
|
|
|
94
95
|
"pathname": {
|
|
95
96
|
"title": "Pathname",
|
|
96
97
|
"description": "Describes the technical title used as a URL path, query parameter, or other reference. Must not contain spaces."
|
|
98
|
+
},
|
|
99
|
+
"slotLayout": {
|
|
100
|
+
"title": "Slot Layout",
|
|
101
|
+
"description": "Describes the interaction of the individual widgets on the page (spacing and borders per widget)"
|
|
97
102
|
}
|
|
98
103
|
},
|
|
99
104
|
"interactionLinkList": {
|
|
@@ -193,6 +198,7 @@
|
|
|
193
198
|
"dataArticle": "the",
|
|
194
199
|
"tableHeaders": {
|
|
195
200
|
"title": "Title",
|
|
201
|
+
"color": "Color",
|
|
196
202
|
"type": "Type",
|
|
197
203
|
"tags": "Tags",
|
|
198
204
|
"updatedAt": "Last Modified"
|
package/i18n/sk-SK.json
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
"save_finish": "Uložiť a dokončiť"
|
|
8
8
|
},
|
|
9
9
|
"loginScreen": {
|
|
10
|
-
"title": "Vitajte v Raclette
|
|
10
|
+
"title": "Vitajte v Raclette Workbench",
|
|
11
11
|
"eMail": "Email",
|
|
12
12
|
"password": "Heslo",
|
|
13
13
|
"login": "Prihlásiť sa"
|
|
14
14
|
},
|
|
15
15
|
"welcomeScreen": {
|
|
16
|
-
"title": "Vitajte v Raclette
|
|
16
|
+
"title": "Vitajte v Raclette Workbench!",
|
|
17
17
|
"whatIsWhat": "Čo je čo?",
|
|
18
18
|
"compositionInfo": "Vytvorte kompozície na definovanie rozloženia vašich stránok alebo modálov",
|
|
19
19
|
"interactionLinkInfo": "Vytvorte InteractionLinks na definovanie, ako môžu používatelia pristupovať k stránkam alebo modálom",
|
|
@@ -193,6 +193,7 @@
|
|
|
193
193
|
"dataArticle": "",
|
|
194
194
|
"tableHeaders": {
|
|
195
195
|
"title": "Názov",
|
|
196
|
+
"color": "Farba",
|
|
196
197
|
"type": "Typ",
|
|
197
198
|
"tags": "Značky",
|
|
198
199
|
"updatedAt": "Naposledy upravené"
|
|
@@ -242,4 +243,4 @@
|
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
}
|
|
245
|
-
}
|
|
246
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raclettejs/workbench",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "racletteJS Workbench - used to configure your application, for dev and prod",
|
|
6
6
|
"repository": "https://gitlab.com/raclettejs/workbench",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
".": "./index.ts"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@raclettejs/core": "0.1.
|
|
34
|
+
"@raclettejs/core": "0.1.12",
|
|
35
35
|
"three": "0.180.0",
|
|
36
36
|
"vanta": "0.5.24"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@eslint/js": "9.35.0",
|
|
40
|
-
"@raclettejs/types": "0.1.
|
|
40
|
+
"@raclettejs/types": "0.1.12",
|
|
41
41
|
"@sinclair/typebox": "0.34.41",
|
|
42
42
|
"@types/ramda": "0.31.1",
|
|
43
43
|
"@vueuse/core": "13.9.0",
|
|
@@ -62,5 +62,6 @@
|
|
|
62
62
|
"vue-eslint-parser": "10.2.0",
|
|
63
63
|
"vue-i18n": "11.1.12",
|
|
64
64
|
"vuetify": "3.10.2"
|
|
65
|
-
}
|
|
65
|
+
},
|
|
66
|
+
"packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
|
|
66
67
|
}
|
|
@@ -110,6 +110,16 @@ const inputFields = computed<
|
|
|
110
110
|
required: true,
|
|
111
111
|
},
|
|
112
112
|
},
|
|
113
|
+
{ divider: t("workbench.compositionConfiguration.divider.styling") },
|
|
114
|
+
{
|
|
115
|
+
title: t("workbench.compositionConfiguration.slotLayout.title"),
|
|
116
|
+
description: t("workbench.compositionConfiguration.slotLayout.description"),
|
|
117
|
+
inputType: "select",
|
|
118
|
+
field: "slotLayout",
|
|
119
|
+
selectItems: ["default", "spaced", "card", "border", "full"],
|
|
120
|
+
prependIcon: "view-grid",
|
|
121
|
+
default: "default",
|
|
122
|
+
},
|
|
113
123
|
])
|
|
114
124
|
|
|
115
125
|
const validateConfigStep = (): boolean => {
|
|
@@ -69,9 +69,19 @@ const { findWidgetByName } = useWidgets()
|
|
|
69
69
|
|
|
70
70
|
const widget = computed(() => findWidgetByName(selectedWigdetModel.value.name))
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
// TOOD: find more suitable place, should be affected by theme
|
|
73
|
+
const defaultConfigurabelParameters = {
|
|
74
|
+
allowPaddingOverride: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: true,
|
|
77
|
+
inputType: "checkbox",
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const configurableParameteters = computed(() => ({
|
|
82
|
+
...defaultConfigurabelParameters,
|
|
83
|
+
...widget.value?.configurableParameters,
|
|
84
|
+
}))
|
|
75
85
|
|
|
76
86
|
const getConfigValue = (key: string) => {
|
|
77
87
|
const config = selectedWigdetModel.value.config
|
package/plugins/pacifico__interactionLinks/frontend/components/InteractionLinkConfiguration.vue
CHANGED
|
@@ -35,6 +35,7 @@ import { Step } from "@app/components/stepNavigator/StepNavigatorTypes"
|
|
|
35
35
|
import StepNavigator from "@app/components/stepNavigator/StepNavigator.vue"
|
|
36
36
|
import {
|
|
37
37
|
DEFAULT_SLOT_NAME,
|
|
38
|
+
DEFAULT_INLINE_SLOT_NAME,
|
|
38
39
|
DEFAULT_MODAL_SLOT_NAME,
|
|
39
40
|
} from "@raclettejs/core/orchestrator/router/routeParserHelper"
|
|
40
41
|
|
|
@@ -93,7 +94,11 @@ const inputFields = computed<
|
|
|
93
94
|
),
|
|
94
95
|
inputType: "select",
|
|
95
96
|
field: "slotType",
|
|
96
|
-
selectItems: [
|
|
97
|
+
selectItems: [
|
|
98
|
+
DEFAULT_SLOT_NAME,
|
|
99
|
+
DEFAULT_MODAL_SLOT_NAME,
|
|
100
|
+
DEFAULT_INLINE_SLOT_NAME,
|
|
101
|
+
],
|
|
97
102
|
prependIcon: "dock-window",
|
|
98
103
|
validation: {
|
|
99
104
|
required: true,
|
|
@@ -26,6 +26,10 @@ const headers = computed<{ title: string; key: keyof Tag }[]>(() => [
|
|
|
26
26
|
title: t("workbench.tagList.tableHeaders.title"),
|
|
27
27
|
key: "title",
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
title: t("workbench.tagList.tableHeaders.color"),
|
|
31
|
+
key: "color",
|
|
32
|
+
},
|
|
29
33
|
{
|
|
30
34
|
title: t("workbench.tagList.tableHeaders.type"),
|
|
31
35
|
key: "type",
|
|
@@ -48,6 +48,16 @@
|
|
|
48
48
|
:loading="loading"
|
|
49
49
|
@click:row="handleRowClick"
|
|
50
50
|
>
|
|
51
|
+
<template
|
|
52
|
+
#item.color="{ item }"
|
|
53
|
+
v-if="!customSlots.includes('item.color')"
|
|
54
|
+
>
|
|
55
|
+
<div class="tw:flex tw:gap-2" v-if="item.color?.length">
|
|
56
|
+
<v-chip :color="item.color" label variant="outlined" size="small">
|
|
57
|
+
{{ item.color }}
|
|
58
|
+
</v-chip>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
51
61
|
<!-- Built-in tags column -->
|
|
52
62
|
<template #item.tags="{ item }" v-if="!customSlots.includes('item.tags')">
|
|
53
63
|
<div class="tw:flex tw:gap-2" v-if="item.tags?.length">
|
|
@@ -8,6 +8,7 @@ export type DynamicInputType =
|
|
|
8
8
|
| "triggers"
|
|
9
9
|
| "record"
|
|
10
10
|
| "list"
|
|
11
|
+
| "objectList"
|
|
11
12
|
| "text"
|
|
12
13
|
| "textarea"
|
|
13
14
|
| "number"
|
|
@@ -33,7 +34,6 @@ export interface InputAttributes {
|
|
|
33
34
|
appendInnerIcon?: MdiIcon
|
|
34
35
|
prefix?: string
|
|
35
36
|
suffix?: string
|
|
36
|
-
// click handlers
|
|
37
37
|
onClickPrepend?: (event: PointerEvent) => void
|
|
38
38
|
onClickPrependInner?: (event: PointerEvent) => void
|
|
39
39
|
onClickAppend?: (event: PointerEvent) => void
|
|
@@ -49,7 +49,11 @@ export interface ValidationProps {
|
|
|
49
49
|
minLength?: number
|
|
50
50
|
maxLength?: number
|
|
51
51
|
pattern?: RegExp
|
|
52
|
-
customValidator?: (value: any) => string | null
|
|
52
|
+
customValidator?: (value: any) => string | null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ObjectListProps {
|
|
56
|
+
fields?: DynamicFormField<any>[]
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
export interface DynamicFormDivider {
|
|
@@ -58,6 +62,7 @@ export interface DynamicFormDivider {
|
|
|
58
62
|
|
|
59
63
|
export type DynamicFormField<T> = DynamicFormItemBase<T> &
|
|
60
64
|
InputAttributes &
|
|
61
|
-
SelectionProps &
|
|
65
|
+
SelectionProps &
|
|
66
|
+
ObjectListProps & { validation?: ValidationProps }
|
|
62
67
|
|
|
63
68
|
export type DynamicFormItem<T> = DynamicFormField<T> | DynamicFormDivider
|
|
@@ -82,6 +82,15 @@
|
|
|
82
82
|
/>
|
|
83
83
|
</template>
|
|
84
84
|
|
|
85
|
+
<template v-else-if="inputType === 'objectList'">
|
|
86
|
+
<ObjectListInput
|
|
87
|
+
v-model="objectArrayModel"
|
|
88
|
+
:fields="value.fields"
|
|
89
|
+
:disabled="!!disabled"
|
|
90
|
+
@validate="$emit('validate')"
|
|
91
|
+
/>
|
|
92
|
+
</template>
|
|
93
|
+
|
|
85
94
|
<template v-else-if="inputType === 'triggers'">
|
|
86
95
|
<TriggerInput
|
|
87
96
|
v-model="triggerModel"
|
|
@@ -212,6 +221,7 @@ import { computed, useAttrs, useId, WritableComputedRef } from "vue"
|
|
|
212
221
|
import LocalizedInput from "./typedInputs/LocalizedInput.vue"
|
|
213
222
|
import CompositionInput from "./typedInputs/CompositionInput.vue"
|
|
214
223
|
import ListInput from "./typedInputs/ListInput.vue"
|
|
224
|
+
import ObjectListInput from "./ObjectListInput.vue"
|
|
215
225
|
import PasswordInput from "./typedInputs/PasswordInput.vue"
|
|
216
226
|
import RecordInput from "./typedInputs/RecordInput.vue"
|
|
217
227
|
import TagsInput from "./typedInputs/TagsInput.vue"
|
|
@@ -240,6 +250,7 @@ type DynamicModelType =
|
|
|
240
250
|
| string[]
|
|
241
251
|
| number
|
|
242
252
|
| Record<string, string>
|
|
253
|
+
| Record<string, any>[]
|
|
243
254
|
| Trigger[]
|
|
244
255
|
| boolean
|
|
245
256
|
|
|
@@ -252,7 +263,6 @@ const attrs = useAttrs()
|
|
|
252
263
|
|
|
253
264
|
const inputId = computed(() => `dynamic-input-${id}`)
|
|
254
265
|
|
|
255
|
-
// make dynamic typed model to true type
|
|
256
266
|
const createTypedModel = <T extends DynamicModelType>(
|
|
257
267
|
types: DynamicInputType[],
|
|
258
268
|
): WritableComputedRef<T> =>
|
|
@@ -286,6 +296,8 @@ const stringArrayModel = createTypedModel<string[]>([
|
|
|
286
296
|
"list",
|
|
287
297
|
])
|
|
288
298
|
|
|
299
|
+
const objectArrayModel = createTypedModel<Record<string, any>[]>(["objectList"])
|
|
300
|
+
|
|
289
301
|
const recordModel = createTypedModel<Record<string, string>>([
|
|
290
302
|
"record",
|
|
291
303
|
"localized",
|
|
@@ -329,7 +341,6 @@ const additionalInputBindings = computed(() => {
|
|
|
329
341
|
appendInnerIcon: appendInnerIcon ? `mdi-${appendInnerIcon}` : undefined,
|
|
330
342
|
}
|
|
331
343
|
|
|
332
|
-
// add click handlers if they exist
|
|
333
344
|
if (onClickPrepend) result["onClick:prepend"] = onClickPrepend
|
|
334
345
|
if (onClickPrependInner) result["onClick:prependInner"] = onClickPrependInner
|
|
335
346
|
if (onClickAppend) result["onClick:append"] = onClickAppend
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="tw:grid tw:gap-4">
|
|
3
|
+
<v-expansion-panels v-model="openPanels" multiple>
|
|
4
|
+
<v-expansion-panel
|
|
5
|
+
v-for="(item, index) in internalItems"
|
|
6
|
+
:key="index"
|
|
7
|
+
:value="index"
|
|
8
|
+
>
|
|
9
|
+
<v-expansion-panel-title class="tw:flex tw:items-center tw:gap-2">
|
|
10
|
+
<span class="tw:flex-1">
|
|
11
|
+
{{ getPanelTitle(item, index) }}
|
|
12
|
+
</span>
|
|
13
|
+
<v-btn
|
|
14
|
+
icon="mdi-minus"
|
|
15
|
+
size="small"
|
|
16
|
+
variant="text"
|
|
17
|
+
:disabled="disabled"
|
|
18
|
+
@click.stop="removeItem(index)"
|
|
19
|
+
/>
|
|
20
|
+
</v-expansion-panel-title>
|
|
21
|
+
|
|
22
|
+
<v-expansion-panel-text>
|
|
23
|
+
<div class="tw:grid tw:gap-4 tw:pt-4">
|
|
24
|
+
<DynamicInput
|
|
25
|
+
v-for="field in fields"
|
|
26
|
+
:key="field.field as string"
|
|
27
|
+
v-model="internalItems[index][field.field]"
|
|
28
|
+
:input-type="field.inputType"
|
|
29
|
+
:value="field"
|
|
30
|
+
:disabled="disabled"
|
|
31
|
+
@update:model-value="onItemChange(index)"
|
|
32
|
+
@validate="$emit('validate')"
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
</v-expansion-panel-text>
|
|
36
|
+
</v-expansion-panel>
|
|
37
|
+
</v-expansion-panels>
|
|
38
|
+
|
|
39
|
+
<v-btn
|
|
40
|
+
v-if="canAddNewItem"
|
|
41
|
+
color="primary"
|
|
42
|
+
variant="outlined"
|
|
43
|
+
prepend-icon="mdi-plus"
|
|
44
|
+
:disabled="disabled"
|
|
45
|
+
@click="addNewItem"
|
|
46
|
+
>
|
|
47
|
+
Add Entry
|
|
48
|
+
</v-btn>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<script setup lang="ts" generic="T extends Record<string, any>">
|
|
53
|
+
import { ref, watch, computed } from "vue"
|
|
54
|
+
import DynamicInput from "./DynamicInput.vue"
|
|
55
|
+
import type { DynamicFormField } from "./DynamicFormTypes"
|
|
56
|
+
|
|
57
|
+
const props = defineProps<{
|
|
58
|
+
fields?: DynamicFormField<T>[]
|
|
59
|
+
disabled?: boolean
|
|
60
|
+
}>()
|
|
61
|
+
|
|
62
|
+
defineEmits<{
|
|
63
|
+
validate: []
|
|
64
|
+
}>()
|
|
65
|
+
|
|
66
|
+
const modelValue = defineModel<T[]>({ required: true, default: () => [] })
|
|
67
|
+
|
|
68
|
+
const internalItems = ref<T[]>([])
|
|
69
|
+
const openPanels = ref<number[]>([0])
|
|
70
|
+
|
|
71
|
+
const initializeEmptyItem = (): T => {
|
|
72
|
+
const item: any = {}
|
|
73
|
+
props.fields?.forEach((field) => {
|
|
74
|
+
const fieldKey = field.field as string
|
|
75
|
+
|
|
76
|
+
switch (field.inputType) {
|
|
77
|
+
case "text":
|
|
78
|
+
case "textarea":
|
|
79
|
+
case "select":
|
|
80
|
+
case "password":
|
|
81
|
+
case "composition":
|
|
82
|
+
case "color":
|
|
83
|
+
case "user":
|
|
84
|
+
item[fieldKey] = ""
|
|
85
|
+
break
|
|
86
|
+
case "number":
|
|
87
|
+
item[fieldKey] = 0
|
|
88
|
+
break
|
|
89
|
+
case "checkbox":
|
|
90
|
+
case "switch":
|
|
91
|
+
item[fieldKey] = false
|
|
92
|
+
break
|
|
93
|
+
case "tags":
|
|
94
|
+
case "multiselect":
|
|
95
|
+
case "list":
|
|
96
|
+
case "objectList":
|
|
97
|
+
item[fieldKey] = []
|
|
98
|
+
break
|
|
99
|
+
case "record":
|
|
100
|
+
case "localized":
|
|
101
|
+
item[fieldKey] = {}
|
|
102
|
+
break
|
|
103
|
+
case "triggers":
|
|
104
|
+
item[fieldKey] = []
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
item[fieldKey] = null
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
return item as T
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const isItemEmpty = (item: T): boolean => {
|
|
114
|
+
return !props.fields?.some((field) => {
|
|
115
|
+
const value = item[field.field]
|
|
116
|
+
|
|
117
|
+
if (value === null || value === undefined) return false
|
|
118
|
+
if (typeof value === "string") return value.trim() !== ""
|
|
119
|
+
if (Array.isArray(value)) return value.length > 0
|
|
120
|
+
if (typeof value === "object") return Object.keys(value).length > 0
|
|
121
|
+
if (typeof value === "boolean") return value === true
|
|
122
|
+
if (typeof value === "number") return value !== 0
|
|
123
|
+
|
|
124
|
+
return false
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const getPanelTitle = (item: T, index: number): string => {
|
|
129
|
+
if (!props.fields || props.fields.length === 0) {
|
|
130
|
+
return `Entry ${index + 1}`
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const firstField = props.fields[0]
|
|
134
|
+
const firstValue = item[firstField.field]
|
|
135
|
+
|
|
136
|
+
if (firstValue && String(firstValue).trim() !== "") {
|
|
137
|
+
return String(firstValue)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return `Entry ${index + 1}`
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const syncToModelValue = () => {
|
|
144
|
+
const nonEmptyItems = internalItems.value.filter((item) => !isItemEmpty(item))
|
|
145
|
+
modelValue.value = nonEmptyItems
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const onItemChange = (index: number) => {
|
|
149
|
+
syncToModelValue()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const addNewItem = () => {
|
|
153
|
+
const newItem = initializeEmptyItem()
|
|
154
|
+
internalItems.value.push(newItem)
|
|
155
|
+
openPanels.value.push(internalItems.value.length - 1)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const removeItem = (index: number) => {
|
|
159
|
+
internalItems.value.splice(index, 1)
|
|
160
|
+
openPanels.value = openPanels.value
|
|
161
|
+
.filter((panelIndex) => panelIndex !== index)
|
|
162
|
+
.map((panelIndex) => (panelIndex > index ? panelIndex - 1 : panelIndex))
|
|
163
|
+
|
|
164
|
+
syncToModelValue()
|
|
165
|
+
|
|
166
|
+
if (internalItems.value.length === 0) {
|
|
167
|
+
internalItems.value.push(initializeEmptyItem())
|
|
168
|
+
openPanels.value = [0]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const canAddNewItem = computed(() => {
|
|
173
|
+
if (internalItems.value.length === 0) return true
|
|
174
|
+
const lastItem = internalItems.value[internalItems.value.length - 1]
|
|
175
|
+
return !isItemEmpty(lastItem)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
watch(
|
|
179
|
+
() => modelValue.value,
|
|
180
|
+
(newVal) => {
|
|
181
|
+
if (newVal.length === 0 && internalItems.value.length === 0) {
|
|
182
|
+
internalItems.value = [initializeEmptyItem()]
|
|
183
|
+
} else if (newVal.length > 0) {
|
|
184
|
+
internalItems.value = [...newVal]
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
{ immediate: true, deep: true },
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if (internalItems.value.length === 0) {
|
|
191
|
+
internalItems.value.push(initializeEmptyItem())
|
|
192
|
+
}
|
|
193
|
+
</script>
|
|
@@ -1,40 +1,38 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-
|
|
3
|
-
<v-
|
|
4
|
-
<v-
|
|
5
|
-
<v-card
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<v-
|
|
12
|
-
<v-list
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
>
|
|
2
|
+
<v-row>
|
|
3
|
+
<v-col cols="12">
|
|
4
|
+
<v-card flat>
|
|
5
|
+
<v-card-title>
|
|
6
|
+
🧀
|
|
7
|
+
{{ $t("workbench.welcomeScreen.title") }}
|
|
8
|
+
</v-card-title>
|
|
9
|
+
</v-card>
|
|
10
|
+
<v-card-text>
|
|
11
|
+
<v-list density="compact" disabled>
|
|
12
|
+
<v-list-subheader
|
|
13
|
+
><h3>
|
|
14
|
+
{{ $t("workbench.welcomeScreen.whatIsWhat") }}
|
|
15
|
+
</h3></v-list-subheader
|
|
16
|
+
>
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
<v-list-item
|
|
19
|
+
v-for="(item, i) in whatIsWhatItems"
|
|
20
|
+
:key="i"
|
|
21
|
+
:value="item"
|
|
22
|
+
color="primary"
|
|
23
|
+
>
|
|
24
|
+
<template #prepend>
|
|
25
|
+
<v-icon :icon="item.icon"></v-icon>
|
|
26
|
+
</template>
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</v-container>
|
|
28
|
+
<v-list-item-title>
|
|
29
|
+
{{ $t("workbench.welcomeScreen." + item.i18nKey) }}
|
|
30
|
+
</v-list-item-title>
|
|
31
|
+
</v-list-item>
|
|
32
|
+
</v-list>
|
|
33
|
+
</v-card-text>
|
|
34
|
+
</v-col>
|
|
35
|
+
</v-row>
|
|
38
36
|
</template>
|
|
39
37
|
|
|
40
38
|
<script setup lang="ts">
|
package/yarn.lock
CHANGED
|
@@ -476,10 +476,10 @@
|
|
|
476
476
|
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b"
|
|
477
477
|
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
|
|
478
478
|
|
|
479
|
-
"@raclettejs/core
|
|
480
|
-
version "0.1.
|
|
481
|
-
resolved "https://registry.yarnpkg.com/@raclettejs/core/-/core-0.1.
|
|
482
|
-
integrity sha512-
|
|
479
|
+
"@raclettejs/core@^0.1.12":
|
|
480
|
+
version "0.1.12"
|
|
481
|
+
resolved "https://registry.yarnpkg.com/@raclettejs/core/-/core-0.1.12.tgz#7b48b29af4512c67e6b922a063b6b0007d74ba1d"
|
|
482
|
+
integrity sha512-AQ60ZfINVy9d9xNpCQK0V295GkZFQD5+Lv2yOyTqrTvYosvNiDo0REIOS82plUJCsL2ORaQVNGVRlaxi9cV+PA==
|
|
483
483
|
dependencies:
|
|
484
484
|
chalk "5.6.2"
|
|
485
485
|
chokidar "3.6.0"
|
|
@@ -492,10 +492,10 @@
|
|
|
492
492
|
ramda "0.31.3"
|
|
493
493
|
tsc-alias "1.8.16"
|
|
494
494
|
|
|
495
|
-
"@raclettejs/types@0.1.
|
|
496
|
-
version "0.1.
|
|
497
|
-
resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.
|
|
498
|
-
integrity sha512-
|
|
495
|
+
"@raclettejs/types@0.1.12":
|
|
496
|
+
version "0.1.12"
|
|
497
|
+
resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.12.tgz#5b8ddf2ff70333494abf96be2a3af118b3ca8afc"
|
|
498
|
+
integrity sha512-hN+mfnv23JMPDwcHodDoVGnM4tVsMyfS5BcUL/vxohYROp2xfBpIFnN7k9WbFbhLeGJhUackjRN/2EfWQi76eQ==
|
|
499
499
|
dependencies:
|
|
500
500
|
"@types/node" "24.5.2"
|
|
501
501
|
fastify "5.6.0"
|