@raclettejs/workbench 0.1.17 → 0.1.19
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 +19 -0
- package/config/compositions.js +18 -14
- package/config/interactionLinks.js +30 -10
- package/i18n/de-DE.json +27 -1
- package/i18n/en-EU.json +27 -1
- package/i18n/sk-SK.json +26 -0
- package/package.json +3 -3
- package/plugins/pacifico__compositions/frontend/widgets/CompositionListWidget.vue +207 -45
- package/plugins/pacifico__interactionLinks/frontend/widgets/InteractionLinkListWidget.vue +226 -42
- package/plugins/pacifico__project/frontend/components/ProjectConfiguration.vue +107 -0
- package/plugins/pacifico__project/frontend/widgets/ProjectDetailWidget.vue +34 -0
- package/plugins/pacifico__project/raclette.plugin.ts +8 -0
- package/plugins/pacifico__tags/frontend/widgets/TagListWidget.vue +203 -34
- package/plugins/pacifico__users/frontend/widgets/UserListWidget.vue +20 -2
- package/raclette.config.js +0 -3
- package/services/frontend/src/app/components/BaseDataTable.vue +3 -0
- package/services/frontend/src/app/components/FileUpload.vue +98 -0
- package/services/frontend/src/app/components/SelectionDialog.vue +182 -0
- package/services/frontend/src/app/components/SummaryDialog.vue +140 -0
- package/services/frontend/src/app/components/dynamicForm/typedInputs/CompositionInput.vue +1 -0
- package/services/frontend/src/app/components/dynamicForm/typedInputs/TriggerInput.vue +4 -6
- package/services/frontend/src/app/lib/jsonTools.ts +81 -0
- package/yarn.lock +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.19] - 12.12.2025 <a href="https://gitlab.com/raclettejs/workbench/-/compare/v0.1.18...v0.1.19" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Compositions, interactionLinks and tags can now be imported and exported
|
|
15
|
+
|
|
16
|
+
## [0.1.18] - 05.12.2025 <a href="https://gitlab.com/raclettejs/workbench/-/compare/v0.1.17...v0.1.18" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
|
|
20
|
+
- Removed redundand authTokenExpiryDays config
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Interaction Links can now have a trigger in the appbar
|
|
25
|
+
- possibility to restore items
|
|
26
|
+
- possibility to add prepend and append actions to base table row items
|
|
27
|
+
- added project configuration interface
|
|
28
|
+
|
|
10
29
|
## [0.1.17] - 06.11.2025 <a href="https://gitlab.com/raclettejs/workbench/-/compare/v0.1.15...v0.1.17" target="_blank" rel="noopener"><b>Overview of all changes</b></a>
|
|
11
30
|
|
|
12
31
|
### Added
|
package/config/compositions.js
CHANGED
|
@@ -2,7 +2,6 @@ export default [
|
|
|
2
2
|
// composition administration
|
|
3
3
|
{
|
|
4
4
|
_id: "compositionList",
|
|
5
|
-
description: "Ein Test",
|
|
6
5
|
pathname: {
|
|
7
6
|
default: "composition-list",
|
|
8
7
|
},
|
|
@@ -21,7 +20,6 @@ export default [
|
|
|
21
20
|
},
|
|
22
21
|
{
|
|
23
22
|
_id: "compositionCreate",
|
|
24
|
-
description: "Ein Test",
|
|
25
23
|
pathname: {
|
|
26
24
|
default: "composition-create",
|
|
27
25
|
},
|
|
@@ -41,7 +39,6 @@ export default [
|
|
|
41
39
|
},
|
|
42
40
|
{
|
|
43
41
|
_id: "compositionEdit",
|
|
44
|
-
description: "Ein Test",
|
|
45
42
|
pathname: {
|
|
46
43
|
default: "composition-edit",
|
|
47
44
|
},
|
|
@@ -63,7 +60,6 @@ export default [
|
|
|
63
60
|
// interactionLinks administration
|
|
64
61
|
{
|
|
65
62
|
_id: "interactionLinkList",
|
|
66
|
-
description: "Ein Test",
|
|
67
63
|
pathname: {
|
|
68
64
|
default: "interactionLink-list",
|
|
69
65
|
},
|
|
@@ -82,7 +78,6 @@ export default [
|
|
|
82
78
|
},
|
|
83
79
|
{
|
|
84
80
|
_id: "interactionLinkCreate",
|
|
85
|
-
description: "Ein Test",
|
|
86
81
|
pathname: {
|
|
87
82
|
default: "interactionLink-create",
|
|
88
83
|
},
|
|
@@ -101,7 +96,6 @@ export default [
|
|
|
101
96
|
},
|
|
102
97
|
{
|
|
103
98
|
_id: "interactionLinkEdit",
|
|
104
|
-
description: "Ein Test",
|
|
105
99
|
pathname: {
|
|
106
100
|
default: "interactionLink-edit",
|
|
107
101
|
},
|
|
@@ -123,7 +117,6 @@ export default [
|
|
|
123
117
|
// users administration
|
|
124
118
|
{
|
|
125
119
|
_id: "userList",
|
|
126
|
-
description: "Ein Test",
|
|
127
120
|
pathname: {
|
|
128
121
|
default: "user-list",
|
|
129
122
|
},
|
|
@@ -142,7 +135,6 @@ export default [
|
|
|
142
135
|
},
|
|
143
136
|
{
|
|
144
137
|
_id: "userCreate",
|
|
145
|
-
description: "Ein Test",
|
|
146
138
|
pathname: {
|
|
147
139
|
default: "user-create",
|
|
148
140
|
},
|
|
@@ -161,7 +153,6 @@ export default [
|
|
|
161
153
|
},
|
|
162
154
|
{
|
|
163
155
|
_id: "userEdit",
|
|
164
|
-
description: "Ein Test",
|
|
165
156
|
pathname: {
|
|
166
157
|
default: "user-edit",
|
|
167
158
|
},
|
|
@@ -182,7 +173,6 @@ export default [
|
|
|
182
173
|
// tags administration
|
|
183
174
|
{
|
|
184
175
|
_id: "tagList",
|
|
185
|
-
description: "Ein Test",
|
|
186
176
|
pathname: {
|
|
187
177
|
default: "tag-list",
|
|
188
178
|
},
|
|
@@ -201,7 +191,6 @@ export default [
|
|
|
201
191
|
},
|
|
202
192
|
{
|
|
203
193
|
_id: "tagCreate",
|
|
204
|
-
description: "Ein Test",
|
|
205
194
|
pathname: {
|
|
206
195
|
default: "tag-create",
|
|
207
196
|
},
|
|
@@ -220,7 +209,6 @@ export default [
|
|
|
220
209
|
},
|
|
221
210
|
{
|
|
222
211
|
_id: "tagEdit",
|
|
223
|
-
description: "Ein Test",
|
|
224
212
|
pathname: {
|
|
225
213
|
default: "tag-edit",
|
|
226
214
|
},
|
|
@@ -242,7 +230,6 @@ export default [
|
|
|
242
230
|
// plugins configuration
|
|
243
231
|
{
|
|
244
232
|
_id: "pluginList",
|
|
245
|
-
description: "Ein Test",
|
|
246
233
|
pathname: {
|
|
247
234
|
default: "plugin-list",
|
|
248
235
|
},
|
|
@@ -261,7 +248,6 @@ export default [
|
|
|
261
248
|
},
|
|
262
249
|
{
|
|
263
250
|
_id: "pluginDetail",
|
|
264
|
-
description: "Ein Test",
|
|
265
251
|
pathname: {
|
|
266
252
|
default: "plugin-detail",
|
|
267
253
|
},
|
|
@@ -279,4 +265,22 @@ export default [
|
|
|
279
265
|
],
|
|
280
266
|
queryParameters: ["id"],
|
|
281
267
|
},
|
|
268
|
+
{
|
|
269
|
+
_id: "projectDetail",
|
|
270
|
+
pathname: {
|
|
271
|
+
default: "project-detail",
|
|
272
|
+
},
|
|
273
|
+
widgetsLayout: [
|
|
274
|
+
[
|
|
275
|
+
{
|
|
276
|
+
column: 12,
|
|
277
|
+
widget: {
|
|
278
|
+
uuid: "ProjectDetail",
|
|
279
|
+
name: "ProjectDetail",
|
|
280
|
+
pluginKey: "pacifico__project",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
],
|
|
285
|
+
},
|
|
282
286
|
] //satisfies Composition[]
|
|
@@ -45,8 +45,8 @@ export default [
|
|
|
45
45
|
settings: {
|
|
46
46
|
icon: "mdi-link-box-variant",
|
|
47
47
|
title: {
|
|
48
|
-
default: "
|
|
49
|
-
de: "
|
|
48
|
+
default: "Interaction Links",
|
|
49
|
+
de: "Interaktionslinks",
|
|
50
50
|
},
|
|
51
51
|
sortOrder: 1,
|
|
52
52
|
navigationBarType: "navItem",
|
|
@@ -78,8 +78,8 @@ export default [
|
|
|
78
78
|
settings: {
|
|
79
79
|
icon: "mdi-account-details",
|
|
80
80
|
title: {
|
|
81
|
-
default: "
|
|
82
|
-
de: "
|
|
81
|
+
default: "Users",
|
|
82
|
+
de: "Nutzer",
|
|
83
83
|
},
|
|
84
84
|
sortOrder: 2,
|
|
85
85
|
navigationBarType: "navItem",
|
|
@@ -111,10 +111,10 @@ export default [
|
|
|
111
111
|
settings: {
|
|
112
112
|
icon: "mdi-tag",
|
|
113
113
|
title: {
|
|
114
|
-
default: "
|
|
115
|
-
de: "
|
|
114
|
+
default: "Tags",
|
|
115
|
+
de: "Tags",
|
|
116
116
|
},
|
|
117
|
-
sortOrder:
|
|
117
|
+
sortOrder: 3,
|
|
118
118
|
navigationBarType: "navItem",
|
|
119
119
|
},
|
|
120
120
|
},
|
|
@@ -145,10 +145,10 @@ export default [
|
|
|
145
145
|
settings: {
|
|
146
146
|
icon: "mdi-puzzle",
|
|
147
147
|
title: {
|
|
148
|
-
default: "
|
|
149
|
-
de: "
|
|
148
|
+
default: "Plugins",
|
|
149
|
+
de: "Plugins",
|
|
150
150
|
},
|
|
151
|
-
sortOrder:
|
|
151
|
+
sortOrder: 4,
|
|
152
152
|
navigationBarType: "navItem",
|
|
153
153
|
},
|
|
154
154
|
},
|
|
@@ -161,4 +161,24 @@ export default [
|
|
|
161
161
|
triggers: [],
|
|
162
162
|
queryParameters: ["pluginKey"],
|
|
163
163
|
},
|
|
164
|
+
// project configuration
|
|
165
|
+
{
|
|
166
|
+
_id: "projectDetailInteractionLink",
|
|
167
|
+
composition: compositions[14]._id,
|
|
168
|
+
slotType: "page",
|
|
169
|
+
triggers: [
|
|
170
|
+
{
|
|
171
|
+
type: "page-navigation",
|
|
172
|
+
settings: {
|
|
173
|
+
icon: "mdi-application-cog",
|
|
174
|
+
title: {
|
|
175
|
+
default: "Project",
|
|
176
|
+
de: "Projekt",
|
|
177
|
+
},
|
|
178
|
+
sortOrder: 0,
|
|
179
|
+
navigationBarType: "footerItem",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
},
|
|
164
184
|
] // satisfies Partial<InteractionLink>[]
|
package/i18n/de-DE.json
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"searchPlaceholder": "{dataName} durchsuchen",
|
|
43
43
|
"createDataButton": "{dataName} erstellen",
|
|
44
44
|
"deleteDataTitle": "{dataName} löschen",
|
|
45
|
+
"restoreDataTitle": "{dataName} widerherstellen",
|
|
45
46
|
"deleteDataConfirmMessage": "Bist du sicher, dass du {article} {dataName} <strong>{value}</strong> löschen willst?",
|
|
46
47
|
"deleteDataConfirmButton": "Löschen",
|
|
47
48
|
"deleteDataConfirmCancel": "Abbrechen"
|
|
@@ -246,6 +247,31 @@
|
|
|
246
247
|
"invalidEmail": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
|
247
248
|
"invalidUrl": "Bitte geben Sie eine gültige URL ein"
|
|
248
249
|
}
|
|
250
|
+
},
|
|
251
|
+
"project": {
|
|
252
|
+
"formtitle": "Projekt bearbeiten",
|
|
253
|
+
"dataName": "Projekt",
|
|
254
|
+
"dividers": {
|
|
255
|
+
"general": "Allgemein",
|
|
256
|
+
"config": "Konfiguration"
|
|
257
|
+
},
|
|
258
|
+
"title": {
|
|
259
|
+
"title": "Projekt name",
|
|
260
|
+
"description": "Der Name des Projekts"
|
|
261
|
+
},
|
|
262
|
+
"tags": {
|
|
263
|
+
"title": "Tags",
|
|
264
|
+
"description": "Dieses Feld dient nur der internen Zuordnung der Komposition und wird nicht im Produkt angezeigt."
|
|
265
|
+
},
|
|
266
|
+
"description": {
|
|
267
|
+
"title": "Projekt Beschreibung",
|
|
268
|
+
"description": "Die Beschreibung des Portal/Platform Inhalts"
|
|
269
|
+
},
|
|
270
|
+
"config": "Projekt Konfiguration",
|
|
271
|
+
"railPageNavigation": {
|
|
272
|
+
"title": "Ausklappbare Navigation",
|
|
273
|
+
"description": "Wenn aktiviert wird die Seitennavigation automatisch ein- und aufgeklappt"
|
|
274
|
+
}
|
|
249
275
|
}
|
|
250
276
|
}
|
|
251
|
-
}
|
|
277
|
+
}
|
package/i18n/en-EU.json
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"searchPlaceholder": "Search {dataName}",
|
|
43
43
|
"createDataButton": "Create {dataName}",
|
|
44
44
|
"deleteDataTitle": "Delete {dataName}",
|
|
45
|
+
"restoreDataTitle": "Restore {dataName}",
|
|
45
46
|
"deleteDataConfirmMessage": "Are you sure you want to delete {article} {dataName} <strong>{value}</strong>?",
|
|
46
47
|
"deleteDataConfirmButton": "Delete",
|
|
47
48
|
"deleteDataConfirmCancel": "Cancel"
|
|
@@ -246,6 +247,31 @@
|
|
|
246
247
|
"invalidEmail": "Please enter a valid email address",
|
|
247
248
|
"invalidUrl": "Please enter a valid URL"
|
|
248
249
|
}
|
|
250
|
+
},
|
|
251
|
+
"project": {
|
|
252
|
+
"formtitle": "Edit Project",
|
|
253
|
+
"dataName": "Project",
|
|
254
|
+
"dividers": {
|
|
255
|
+
"general": "General",
|
|
256
|
+
"config": "Configuration"
|
|
257
|
+
},
|
|
258
|
+
"title": {
|
|
259
|
+
"title": "Project Name",
|
|
260
|
+
"description": "The name of the project"
|
|
261
|
+
},
|
|
262
|
+
"tags": {
|
|
263
|
+
"title": "Tags",
|
|
264
|
+
"description": "This field is only used for internal categorization of the composition and is not displayed in the product."
|
|
265
|
+
},
|
|
266
|
+
"description": {
|
|
267
|
+
"title": "Project Description",
|
|
268
|
+
"description": "The description of the portal/platform content"
|
|
269
|
+
},
|
|
270
|
+
"config": "Project Configuration",
|
|
271
|
+
"railPageNavigation": {
|
|
272
|
+
"title": "Collapsible Navigation",
|
|
273
|
+
"description": "When enabled, the page navigation is automatically collapsed and expanded"
|
|
274
|
+
}
|
|
249
275
|
}
|
|
250
276
|
}
|
|
251
|
-
}
|
|
277
|
+
}
|
package/i18n/sk-SK.json
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"searchPlaceholder": "Hľadať {dataName}",
|
|
43
43
|
"createDataButton": "Vytvoriť {dataName}",
|
|
44
44
|
"deleteDataTitle": "Odstrániť {dataName}",
|
|
45
|
+
"restoreDataTitle": "Obnoviť {dataName}",
|
|
45
46
|
"deleteDataConfirmMessage": "Naozaj chcete odstrániť {article} {dataName} <strong>{value}</strong>?",
|
|
46
47
|
"deleteDataConfirmButton": "Odstrániť",
|
|
47
48
|
"deleteDataConfirmCancel": "Zrušiť"
|
|
@@ -241,6 +242,31 @@
|
|
|
241
242
|
"invalidEmail": "Zadajte platnú emailovú adresu",
|
|
242
243
|
"invalidUrl": "Zadajte platnú URL adresu"
|
|
243
244
|
}
|
|
245
|
+
},
|
|
246
|
+
"project": {
|
|
247
|
+
"formtitle": "Upraviť projekt",
|
|
248
|
+
"dataName": "Projekt",
|
|
249
|
+
"dividers": {
|
|
250
|
+
"general": "Všeobecné",
|
|
251
|
+
"config": "Konfigurácia"
|
|
252
|
+
},
|
|
253
|
+
"title": {
|
|
254
|
+
"title": "Názov projektu",
|
|
255
|
+
"description": "Názov projektu"
|
|
256
|
+
},
|
|
257
|
+
"description": {
|
|
258
|
+
"title": "Popis projektu",
|
|
259
|
+
"description": "Popis obsahu portálu/platformy"
|
|
260
|
+
},
|
|
261
|
+
"config": "Projekt Konfigurácia",
|
|
262
|
+
"railPageNavigation": {
|
|
263
|
+
"title": "Sklopná navigácia",
|
|
264
|
+
"description": "Ak je povolená, stránková navigácia sa automaticky sklopí a rozbalí"
|
|
265
|
+
},
|
|
266
|
+
"tags": {
|
|
267
|
+
"title": "Značky",
|
|
268
|
+
"description": "Toto pole slúži len na internú kategorizáciu kompozície a nezobrazuje sa v produkte."
|
|
269
|
+
}
|
|
244
270
|
}
|
|
245
271
|
}
|
|
246
272
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raclettejs/workbench",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
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.19",
|
|
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.19",
|
|
41
41
|
"@sinclair/typebox": "0.34.41",
|
|
42
42
|
"@types/ramda": "0.31.1",
|
|
43
43
|
"@vueuse/core": "13.9.0",
|
|
@@ -1,56 +1,151 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<v-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<v-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
2
|
+
<div>
|
|
3
|
+
<BaseDataTable
|
|
4
|
+
:items="parsedCompositions"
|
|
5
|
+
:loading="compositionsLoading || tagsLoading"
|
|
6
|
+
:headers="headers"
|
|
7
|
+
create-interaction-link-id="compositionCreateInteractionLink"
|
|
8
|
+
edit-interaction-link-id="compositionEditInteractionLink"
|
|
9
|
+
:data-name="$t('workbench.compositionList.dataName')"
|
|
10
|
+
:data-article="$t('workbench.compositionList.dataArticle')"
|
|
11
|
+
@delete="deleteComposition"
|
|
12
|
+
:itemsDeleted="showDeleted"
|
|
13
|
+
>
|
|
14
|
+
<template #actions>
|
|
15
|
+
<v-tooltip
|
|
16
|
+
:text="showDeleted ? $t('core.hideDeleted') : $t('core.showDeleted')"
|
|
17
|
+
>
|
|
18
|
+
<template v-slot:activator="{ props }">
|
|
19
|
+
<v-btn-toggle
|
|
20
|
+
density="compact"
|
|
21
|
+
v-bind="props"
|
|
22
|
+
v-model="showDeleted"
|
|
23
|
+
mandatory
|
|
24
|
+
:color="showDeleted ? 'error' : 'success'"
|
|
25
|
+
>
|
|
26
|
+
<v-btn :value="true">
|
|
27
|
+
<v-icon>mdi-table-eye-off</v-icon>
|
|
28
|
+
</v-btn>
|
|
29
|
+
<v-btn :value="false"><v-icon>mdi-table-eye</v-icon></v-btn>
|
|
30
|
+
</v-btn-toggle>
|
|
31
|
+
</template>
|
|
32
|
+
</v-tooltip>
|
|
33
|
+
<v-btn-group density="compact">
|
|
34
|
+
<v-tooltip :text="$t('core.export')">
|
|
35
|
+
<template v-slot:activator="{ props }">
|
|
36
|
+
<v-btn color="info" v-bind="props" flat @click="openExportDialog">
|
|
37
|
+
<v-icon>mdi-database-export</v-icon>
|
|
38
|
+
</v-btn>
|
|
39
|
+
</template>
|
|
40
|
+
</v-tooltip>
|
|
41
|
+
<v-tooltip :text="$t('core.import')">
|
|
42
|
+
<template v-slot:activator="{ props }">
|
|
43
|
+
<v-btn v-bind="props" color="warning">
|
|
44
|
+
<FileUpload
|
|
45
|
+
ref="uploadRef"
|
|
46
|
+
:onFileLoaded="handleFileUpload"
|
|
47
|
+
accept=".json"
|
|
48
|
+
readAs="text"
|
|
49
|
+
/></v-btn>
|
|
50
|
+
</template>
|
|
51
|
+
</v-tooltip>
|
|
52
|
+
</v-btn-group>
|
|
53
|
+
</template>
|
|
54
|
+
<!-- Custom status column -->
|
|
55
|
+
<template #item.status="{ item }">
|
|
56
|
+
<v-icon
|
|
57
|
+
:icon="item.statusIcon"
|
|
58
|
+
:color="item.statusColor"
|
|
59
|
+
size="x-large"
|
|
60
|
+
/>
|
|
61
|
+
</template>
|
|
62
|
+
<template #prepend-row-actions="{ item }">
|
|
63
|
+
<v-icon
|
|
64
|
+
v-if="showDeleted"
|
|
65
|
+
color="green"
|
|
66
|
+
class="mr-2"
|
|
67
|
+
@click.stop.prevent="restore(item._id)"
|
|
68
|
+
:title="
|
|
69
|
+
$t('workbench.baseDataTable.restoreDataTitle', {
|
|
70
|
+
dataName: item.title,
|
|
71
|
+
})
|
|
72
|
+
"
|
|
73
|
+
icon="mdi-delete-restore"
|
|
74
|
+
/>
|
|
75
|
+
</template>
|
|
76
|
+
</BaseDataTable>
|
|
77
|
+
<!-- Export Selection Dialog -->
|
|
78
|
+
<SelectionDialog
|
|
79
|
+
v-model="showExportDialog"
|
|
80
|
+
:items="exportableItems"
|
|
81
|
+
display-attribute="title"
|
|
82
|
+
:title="$t('core.selectItemsToExport')"
|
|
83
|
+
:confirm-text="$t('core.export')"
|
|
84
|
+
@confirm="handleExportConfirm"
|
|
85
|
+
/>
|
|
86
|
+
|
|
87
|
+
<!-- Import Selection Dialog -->
|
|
88
|
+
<SelectionDialog
|
|
89
|
+
v-model="showImportDialog"
|
|
90
|
+
:items="importableItems"
|
|
91
|
+
display-attribute="title"
|
|
92
|
+
:title="$t('core.selectItemsToImport')"
|
|
93
|
+
:confirm-text="$t('core.import')"
|
|
94
|
+
@confirm="handleImportConfirm"
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
<!-- Export Summary Dialog -->
|
|
98
|
+
<SummaryDialog
|
|
99
|
+
v-model="showExportSummary"
|
|
100
|
+
display-attribute="title"
|
|
101
|
+
:items="exportedItems"
|
|
102
|
+
:title="$t('core.exportSummary')"
|
|
103
|
+
:message="$t('core.exportSuccessMessage')"
|
|
104
|
+
type="success"
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
<!-- Import Summary Dialog -->
|
|
108
|
+
<SummaryDialog
|
|
109
|
+
v-model="showImportSummary"
|
|
110
|
+
display-attribute="title"
|
|
111
|
+
:items="importedItems"
|
|
112
|
+
:title="$t('core.importSummary')"
|
|
113
|
+
:message="$t('core.importSuccessMessage')"
|
|
114
|
+
type="success"
|
|
115
|
+
:show-confirm="true"
|
|
116
|
+
:confirm-text="$t('core.saveImported')"
|
|
117
|
+
@confirm="finalizeImport"
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
42
120
|
</template>
|
|
43
121
|
|
|
44
122
|
<script setup lang="ts">
|
|
45
123
|
import { usePluginApi } from "@raclettejs/core/orchestrator/composables"
|
|
46
|
-
import { computed, watch, ref } from "vue"
|
|
124
|
+
import { computed, watch, ref, useTemplateRef } from "vue"
|
|
47
125
|
import type { Composition } from "@raclettejs/core"
|
|
48
126
|
import { formatDistance } from "date-fns"
|
|
49
127
|
import BaseDataTable from "@app/components/BaseDataTable.vue"
|
|
50
128
|
import { useI18n } from "vue-i18n"
|
|
51
|
-
|
|
129
|
+
import { downloadJson, mapJsonValues } from "@app/lib/jsonTools"
|
|
130
|
+
import FileUpload from "@app/components/FileUpload.vue"
|
|
131
|
+
import SelectionDialog from "@app/components/SelectionDialog.vue"
|
|
132
|
+
import SummaryDialog from "@app/components/SummaryDialog.vue"
|
|
52
133
|
|
|
53
134
|
const { t } = useI18n()
|
|
135
|
+
const showDeleted = ref(false)
|
|
136
|
+
// Dialog states
|
|
137
|
+
const showExportDialog = ref(false)
|
|
138
|
+
const showImportDialog = ref(false)
|
|
139
|
+
const showExportSummary = ref(false)
|
|
140
|
+
const showImportSummary = ref(false)
|
|
141
|
+
|
|
142
|
+
// Data for dialogs
|
|
143
|
+
const exportableItems = ref<any[]>([])
|
|
144
|
+
const importableItems = ref<any[]>([])
|
|
145
|
+
const exportedItems = ref<any[]>([])
|
|
146
|
+
const importedItems = ref<any[]>([])
|
|
147
|
+
const pendingImportData = ref<any>(null)
|
|
148
|
+
const uploadRef = useTemplateRef("uploadRef")
|
|
54
149
|
|
|
55
150
|
const headers = computed<
|
|
56
151
|
{ title: string; key: keyof Composition | "actions" }[]
|
|
@@ -85,13 +180,12 @@ const props = defineProps<{
|
|
|
85
180
|
uuid: string
|
|
86
181
|
}>()
|
|
87
182
|
|
|
88
|
-
const { $data, $socket } = usePluginApi("raclette__core")
|
|
183
|
+
const { $data, $socket, $user } = usePluginApi("raclette__core")
|
|
89
184
|
const {
|
|
90
185
|
data: compositions,
|
|
91
186
|
execute,
|
|
92
187
|
isLoading: compositionsLoading,
|
|
93
188
|
} = $data.composition.getAll()
|
|
94
|
-
|
|
95
189
|
const { data: tags, isLoading: tagsLoading } = $data.tag.getAll({
|
|
96
190
|
options: { immediate: true },
|
|
97
191
|
})
|
|
@@ -101,6 +195,12 @@ const { data: users } = $data.user.getAll({
|
|
|
101
195
|
const { execute: executeDelete } = await $data.composition.delete({
|
|
102
196
|
options: { cb: () => execute({ isDeleted: showDeleted.value }) },
|
|
103
197
|
})
|
|
198
|
+
const { execute: executeBulkCreate } = await $data.composition.createBulk({
|
|
199
|
+
options: { notify: false, cb: () => execute() },
|
|
200
|
+
})
|
|
201
|
+
const { execute: executeRestore } = await $data.composition.updateRestore({
|
|
202
|
+
options: { cb: () => execute({ isDeleted: showDeleted.value }) },
|
|
203
|
+
})
|
|
104
204
|
const { execute: executeHardDelete } = await $data.composition.deleteHard({
|
|
105
205
|
options: { cb: () => execute({ isDeleted: showDeleted.value }) },
|
|
106
206
|
})
|
|
@@ -146,7 +246,67 @@ const getStatusColor = (status: string) => {
|
|
|
146
246
|
return "#B66218"
|
|
147
247
|
}
|
|
148
248
|
}
|
|
249
|
+
// Export functions
|
|
250
|
+
const openExportDialog = () => {
|
|
251
|
+
exportableItems.value = Object.values(compositions.value || {})
|
|
252
|
+
showExportDialog.value = true
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const handleExportConfirm = (selectedIds: string[]) => {
|
|
256
|
+
const dataToExport = selectedIds.reduce((acc, id) => {
|
|
257
|
+
if (compositions.value?.[id]) {
|
|
258
|
+
acc[id] = compositions.value[id]
|
|
259
|
+
}
|
|
260
|
+
return acc
|
|
261
|
+
}, {} as any)
|
|
262
|
+
|
|
263
|
+
exportedItems.value = Object.values(dataToExport)
|
|
264
|
+
downloadJson(dataToExport, "compositions")
|
|
265
|
+
showExportSummary.value = true
|
|
266
|
+
}
|
|
149
267
|
|
|
268
|
+
// Import functions
|
|
269
|
+
const handleFileUpload = (content: string, file: File) => {
|
|
270
|
+
try {
|
|
271
|
+
const parsedData = JSON.parse(content)
|
|
272
|
+
const itemsArray = Object.values(parsedData)
|
|
273
|
+
|
|
274
|
+
importableItems.value = itemsArray
|
|
275
|
+
pendingImportData.value = parsedData
|
|
276
|
+
showImportDialog.value = true
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error("Failed to parse JSON:", error)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const handleImportConfirm = (selectedIds: string[]) => {
|
|
283
|
+
const selectedItems = selectedIds.map((id) => pendingImportData.value[id])
|
|
284
|
+
importedItems.value = selectedItems
|
|
285
|
+
showImportSummary.value = true
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const finalizeImport = async () => {
|
|
289
|
+
const mapping = {
|
|
290
|
+
owner: $user.value._id,
|
|
291
|
+
lastEditor: $user.value._id,
|
|
292
|
+
createdBy: $user.value._id,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const dataToImport = importedItems.value.reduce((acc, item) => {
|
|
296
|
+
const mappedItem = mapJsonValues(item, mapping)
|
|
297
|
+
acc[item._id] = mappedItem
|
|
298
|
+
return acc
|
|
299
|
+
}, {} as any)
|
|
300
|
+
|
|
301
|
+
await executeBulkCreate(Object.values(dataToImport))
|
|
302
|
+
// TODO: Add your actual import logic here
|
|
303
|
+
// e.g., call an API endpoint to save the imported compositions
|
|
304
|
+
|
|
305
|
+
// Reset states
|
|
306
|
+
pendingImportData.value = null
|
|
307
|
+
importableItems.value = []
|
|
308
|
+
importedItems.value = []
|
|
309
|
+
}
|
|
150
310
|
const deleteComposition = async (composition: Composition) => {
|
|
151
311
|
if (showDeleted.value) {
|
|
152
312
|
await executeHardDelete({ _id: composition._id })
|
|
@@ -154,7 +314,9 @@ const deleteComposition = async (composition: Composition) => {
|
|
|
154
314
|
await executeDelete({ _id: composition._id })
|
|
155
315
|
}
|
|
156
316
|
}
|
|
157
|
-
|
|
317
|
+
const restore = (_id: string) => {
|
|
318
|
+
executeRestore({ _id })
|
|
319
|
+
}
|
|
158
320
|
$socket.on("compositionCreated", () =>
|
|
159
321
|
execute({ isDeleted: showDeleted.value }),
|
|
160
322
|
)
|