@raclettejs/workbench 0.1.17 → 0.1.18

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 CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [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>
11
+
12
+ ### Removed
13
+
14
+ - Removed redundand authTokenExpiryDays config
15
+
16
+ ### Added
17
+
18
+ - Interaction Links can now have a trigger in the appbar
19
+ - possibility to restore items
20
+ - possibility to add prepend and append actions to base table row items
21
+ - added project configuration interface
22
+
10
23
  ## [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
24
 
12
25
  ### Added
@@ -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: "interactionLink",
49
- de: "interactionLink",
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: "users",
82
- de: "users",
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: "tags",
115
- de: "tags",
114
+ default: "Tags",
115
+ de: "Tags",
116
116
  },
117
- sortOrder: 2,
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: "plugins",
149
- de: "plugins",
148
+ default: "Plugins",
149
+ de: "Plugins",
150
150
  },
151
- sortOrder: 2,
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.17",
3
+ "version": "0.1.18",
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.17",
34
+ "@raclettejs/core": "^0.1.18",
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.17",
40
+ "@raclettejs/types": "^0.1.18",
41
41
  "@sinclair/typebox": "0.34.41",
42
42
  "@types/ramda": "0.31.1",
43
43
  "@vueuse/core": "13.9.0",
@@ -38,6 +38,20 @@
38
38
  size="x-large"
39
39
  />
40
40
  </template>
41
+ <template #prepend-row-actions="{ item }">
42
+ <v-icon
43
+ v-if="showDeleted"
44
+ color="green"
45
+ class="mr-2"
46
+ @click.stop.prevent="restore(item._id)"
47
+ :title="
48
+ $t('workbench.baseDataTable.restoreDataTitle', {
49
+ dataName: item.title,
50
+ })
51
+ "
52
+ icon="mdi-delete-restore"
53
+ />
54
+ </template>
41
55
  </BaseDataTable>
42
56
  </template>
43
57
 
@@ -91,7 +105,6 @@ const {
91
105
  execute,
92
106
  isLoading: compositionsLoading,
93
107
  } = $data.composition.getAll()
94
-
95
108
  const { data: tags, isLoading: tagsLoading } = $data.tag.getAll({
96
109
  options: { immediate: true },
97
110
  })
@@ -101,6 +114,9 @@ const { data: users } = $data.user.getAll({
101
114
  const { execute: executeDelete } = await $data.composition.delete({
102
115
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
103
116
  })
117
+ const { execute: executeRestore } = await $data.composition.updateRestore({
118
+ options: { cb: () => execute({ isDeleted: showDeleted.value }) },
119
+ })
104
120
  const { execute: executeHardDelete } = await $data.composition.deleteHard({
105
121
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
106
122
  })
@@ -154,7 +170,9 @@ const deleteComposition = async (composition: Composition) => {
154
170
  await executeDelete({ _id: composition._id })
155
171
  }
156
172
  }
157
-
173
+ const restore = (_id: string) => {
174
+ executeRestore({ _id })
175
+ }
158
176
  $socket.on("compositionCreated", () =>
159
177
  execute({ isDeleted: showDeleted.value }),
160
178
  )
@@ -37,6 +37,20 @@
37
37
  <v-icon icon="mdi-link" />
38
38
  </span>
39
39
  </template>
40
+ <template #prepend-row-actions="{ item }">
41
+ <v-icon
42
+ v-if="showDeleted"
43
+ color="green"
44
+ class="mr-2"
45
+ @click="restore(item._id)"
46
+ :title="
47
+ $t('workbench.baseDataTable.restoreDataTitle', {
48
+ dataName: item.title,
49
+ })
50
+ "
51
+ icon="mdi-delete-restore"
52
+ />
53
+ </template>
40
54
  </BaseDataTable>
41
55
  </template>
42
56
 
@@ -105,6 +119,7 @@ const { data: users } = $data.user.getAll({
105
119
  })
106
120
 
107
121
  const { data: compositions } = $data.composition.getAll({
122
+ params: { isDeleted: false },
108
123
  options: { immediate: true },
109
124
  })
110
125
 
@@ -114,6 +129,9 @@ const { execute: executeDelete } = $data.interactionLink.delete({
114
129
  const { execute: executeHardDelete } = await $data.interactionLink.deleteHard({
115
130
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
116
131
  })
132
+ const { execute: executeRestore } = await $data.interactionLink.updateRestore({
133
+ options: { cb: () => execute({ isDeleted: showDeleted.value }) },
134
+ })
117
135
  const parsedInteractionLinks = computed(() => {
118
136
  if (interactionLinks.value && tags.value) {
119
137
  return Object.values(
@@ -140,7 +158,9 @@ const parsedInteractionLinks = computed(() => {
140
158
 
141
159
  return []
142
160
  })
143
-
161
+ const restore = async (_id: string) => {
162
+ executeRestore({ _id })
163
+ }
144
164
  const deleteInteractionLink = async (interactionLink: InteractionLink) => {
145
165
  if (showDeleted.value) {
146
166
  await executeHardDelete({ _id: interactionLink._id })
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <StepNavigator
3
+ :steps
4
+ :is-saving="disabled"
5
+ :show-save-button="isEditing"
6
+ @save="$emit('save')"
7
+ @save-and-finish="$emit('save-and-finish')"
8
+ >
9
+ <!-- @vue-generic {ProjectUpdate} -->
10
+ <DynamicForm
11
+ ref="dynamicFormRef"
12
+ v-model="project"
13
+ :data="projectInputFields"
14
+ :disabled
15
+ :title="$t('workbench.project.formtitle')"
16
+ />
17
+ <DynamicForm
18
+ ref="dynamicFormRef"
19
+ v-model="project.config"
20
+ :data="configInputFields"
21
+ :disabled
22
+ />
23
+ </StepNavigator>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import type { ProjectUpdate } from "@raclettejs/core"
28
+ import DynamicForm from "@app/components/dynamicForm/DynamicForm.vue"
29
+ import type { DynamicFormItem } from "@app/components/dynamicForm/DynamicFormTypes"
30
+ import { useI18n } from "vue-i18n"
31
+ import { computed, useTemplateRef } from "vue"
32
+ import { Step } from "@app/components/stepNavigator/StepNavigatorTypes"
33
+ import StepNavigator from "@app/components/stepNavigator/StepNavigator.vue"
34
+
35
+ defineProps<{ disabled?: boolean; isEditing?: boolean }>()
36
+
37
+ defineEmits<{
38
+ (e: "save"): void
39
+ (e: "save-and-finish"): void
40
+ }>()
41
+
42
+ const project = defineModel<ProjectUpdate>({ required: true })
43
+
44
+ const dynamicFormRef = useTemplateRef("dynamicFormRef")
45
+
46
+ const { t } = useI18n()
47
+
48
+ const projectInputFields = computed<DynamicFormItem<ProjectUpdate>[]>(() => [
49
+ { divider: t("workbench.project.dividers.general") },
50
+ {
51
+ title: t("workbench.project.title.title"),
52
+ description: t("workbench.project.title.description"),
53
+ inputType: "textarea",
54
+ field: "title",
55
+ prependIcon: "text",
56
+ },
57
+ {
58
+ title: t("workbench.project.description.title"),
59
+ description: t("workbench.project.description.description"),
60
+ inputType: "textarea",
61
+ field: "description",
62
+ prependIcon: "text",
63
+ },
64
+ /* {
65
+ title: t("workbench.interactionLinkConfiguration.tags.title"),
66
+ description: t("workbench.project.tags.description"),
67
+ inputType: "tags",
68
+ field: "tags",
69
+ prependIcon: "tag-multiple",
70
+ },*/
71
+ ])
72
+ const configInputFields = computed<DynamicFormItem<ProjectUpdate["config"]>[]>(
73
+ () => [
74
+ { divider: t("workbench.project.dividers.config") },
75
+ {
76
+ title: t("workbench.project.railPageNavigation.title"),
77
+ description: t("workbench.project.railPageNavigation.description"),
78
+ inputType: "switch",
79
+ field: "railPageNavigation",
80
+ },
81
+ /*{
82
+ title: t("workbench.project.tags.title"),
83
+ description: t("workbench.project.tags.description"),
84
+ inputType: "tags",
85
+ field: "tags",
86
+ prependIcon: "tag-multiple",
87
+ },*/
88
+ ],
89
+ )
90
+ const validateForm = (): boolean => {
91
+ const validateAllFields = dynamicFormRef.value?.validateAllFields
92
+
93
+ if (validateAllFields) {
94
+ const isValid = !!validateAllFields()
95
+
96
+ return isValid
97
+ }
98
+ return true
99
+ }
100
+
101
+ const steps = computed<Step[]>(() => [
102
+ {
103
+ id: "config",
104
+ validator: validateForm,
105
+ },
106
+ ])
107
+ </script>
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <ProjectConfiguration
3
+ v-if="editableProject"
4
+ v-model="editableProject"
5
+ :disabled="isLoading"
6
+ is-editing
7
+ @save="onSubmit"
8
+ />
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { clone } from "ramda"
13
+ import type { Project } from "@raclettejs/core"
14
+ import { usePluginApi } from "@raclettejs/core/orchestrator/composables"
15
+ import { onMounted, ref, toRaw } from "vue"
16
+ import ProjectConfiguration from "../components/ProjectConfiguration.vue"
17
+
18
+ const props = defineProps<{
19
+ uuid: string
20
+ }>()
21
+
22
+ const { $data } = usePluginApi("raclette__core")
23
+ const { $store } = usePluginApi()
24
+ const project = $store.get(["project"])
25
+
26
+ const { execute: executeUpdate, isLoading } = $data.project.update()
27
+
28
+ const editableProject = ref<Project>()
29
+
30
+ const onSubmit = async () => await executeUpdate(toRaw(editableProject.value))
31
+ onMounted(() => {
32
+ editableProject.value = clone({ config: {}, ...project.value })
33
+ })
34
+ </script>
@@ -0,0 +1,8 @@
1
+ export default {
2
+ name: "project",
3
+ author: "pacifico",
4
+ version: "0.0.1",
5
+ description: "A plugin for project configuration",
6
+ // Specify where the main frontend and backend entry points are
7
+ frontendDir: "./frontend",
8
+ }
@@ -30,6 +30,20 @@
30
30
  </template>
31
31
  </v-tooltip>
32
32
  </template>
33
+ <template #prepend-row-actions="{ item }">
34
+ <v-icon
35
+ v-if="showDeleted"
36
+ color="green"
37
+ class="mr-2"
38
+ @click="restore(item._id)"
39
+ :title="
40
+ $t('workbench.baseDataTable.restoreDataTitle', {
41
+ dataName: item.title,
42
+ })
43
+ "
44
+ icon="mdi-delete-restore"
45
+ />
46
+ </template>
33
47
  </BaseDataTable>
34
48
  </template>
35
49
 
@@ -83,6 +97,9 @@ const { execute: executeDelete } = $data.tag.delete({
83
97
  const { execute: executeHardDelete } = await $data.tag.deleteHard({
84
98
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
85
99
  })
100
+ const { execute: executeRestore } = await $data.tag.updateRestore({
101
+ options: { cb: () => execute({ isDeleted: showDeleted.value }) },
102
+ })
86
103
  const parsedTags = computed(() => {
87
104
  if (tags.value) {
88
105
  return Object.values(tags.value as { [key: string]: Tag }).map((tag) => ({
@@ -101,7 +118,9 @@ const deleteTag = async (tag: Tag) => {
101
118
  await executeDelete({ _id: tag._id })
102
119
  }
103
120
  }
104
-
121
+ const restore = async (_id: string) => {
122
+ executeRestore({ _id })
123
+ }
105
124
  $socket.on("tagCreated", () => execute({ isDeleted: showDeleted.value }))
106
125
  watch(
107
126
  showDeleted,
@@ -31,6 +31,20 @@
31
31
  </template>
32
32
  </v-tooltip>
33
33
  </template>
34
+ <template #prepend-row-actions="{ item }">
35
+ <v-icon
36
+ v-if="showDeleted"
37
+ color="green"
38
+ class="mr-2"
39
+ @click.stop.prevent="restore(item._id)"
40
+ :title="
41
+ $t('workbench.baseDataTable.restoreDataTitle', {
42
+ dataName: item.title,
43
+ })
44
+ "
45
+ icon="mdi-delete-restore"
46
+ />
47
+ </template>
34
48
  </BaseDataTable>
35
49
  </template>
36
50
 
@@ -79,13 +93,15 @@ const { data: users, execute, isLoading: usersLoading } = $data.user.getAll()
79
93
  const { data: tags, isLoading: tagsLoading } = $data.tag.getAll({
80
94
  options: { immediate: true },
81
95
  })
82
-
83
96
  const { execute: executeDelete } = $data.user.delete({
84
97
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
85
98
  })
86
99
  const { execute: executeHardDelete } = await $data.user.deleteHard({
87
100
  options: { cb: () => execute({ isDeleted: showDeleted.value }) },
88
101
  })
102
+ const { execute: executeRestore } = await $data.user.updateRestore({
103
+ options: { cb: () => execute({ isDeleted: showDeleted.value }) },
104
+ })
89
105
  const parsedUsers = computed(() => {
90
106
  if (users.value && tags.value) {
91
107
  return Object.values(users.value as { [key: string]: User }).map(
@@ -105,7 +121,9 @@ const deleteUser = async (user: User) => {
105
121
  await executeDelete({ _id: user._id })
106
122
  }
107
123
  }
108
-
124
+ const restore = async (_id: string) => {
125
+ executeRestore({ _id })
126
+ }
109
127
  $socket.on("userCreated", () => execute({ isDeleted: showDeleted.value }))
110
128
  watch(
111
129
  showDeleted,
@@ -62,9 +62,6 @@ export default defineRacletteConfig({
62
62
  },
63
63
  production: {},
64
64
  },
65
- global: {
66
- authTokenExpiryDays: 1,
67
- },
68
65
  frontend: {
69
66
  meta: {
70
67
  title: "Workbench",
@@ -81,6 +81,7 @@
81
81
 
82
82
  <!-- Actions column template -->
83
83
  <template #item.actions="{ item }" v-if="showActionsColumn">
84
+ <slot name="prepend-row-actions" :item="item"> </slot>
84
85
  <slot name="row-actions" :item="item">
85
86
  <!-- Default delete action -->
86
87
  <v-icon
@@ -96,6 +97,7 @@
96
97
  icon="mdi-delete"
97
98
  />
98
99
  </slot>
100
+ <slot name="append-row-actions" :item="item"> </slot>
99
101
  </template>
100
102
 
101
103
  <!-- Loading template -->
@@ -296,5 +298,6 @@ const isDeleteDisabled = (item: T): boolean => {
296
298
  <style lang="css">
297
299
  .itemsDeleted .v-data-table__tr {
298
300
  background-color: rgb(233, 190, 190);
301
+ color: #000;
299
302
  }
300
303
  </style>
@@ -25,6 +25,7 @@ const modelValue = defineModel<string | null>({ required: true })
25
25
  const { $data } = usePluginApi("raclette__core")
26
26
 
27
27
  const { data, query } = $data.composition.getAll({
28
+ params: { isDeleted: false },
28
29
  options: { immediate: true },
29
30
  })
30
31
 
@@ -23,9 +23,7 @@
23
23
  <div class="tw:grid tw:gap-2 tw:p-2">
24
24
  <template
25
25
  v-if="
26
- ['top-navigation', 'page-navigation', 'user-menu'].includes(
27
- trigger.type,
28
- )
26
+ ['app-bar', 'page-navigation', 'user-menu'].includes(trigger.type)
29
27
  "
30
28
  >
31
29
  <IconInput v-model="trigger.settings.icon" v-bind="$attrs" />
@@ -96,8 +94,8 @@ defineOptions({
96
94
 
97
95
  const modelValue = defineModel<Trigger[]>({ required: true })
98
96
 
99
- // TODO readd "top-navigation", "shortcut" once they are implemented
100
- const triggerTypes = ["page-navigation", "user-menu"] as const
97
+ // TODO readd "shortcut" once they are implemented
98
+ const triggerTypes = ["page-navigation", "user-menu", "app-bar"] as const
101
99
  const pageNavigationTypes = ["footerItem", "navItem"] as const
102
100
  const virtualTrigger = ref<Trigger>({
103
101
  type: "",
@@ -123,7 +121,7 @@ const createSettingsObject = (
123
121
  ): Trigger["settings"] => {
124
122
  if (
125
123
  triggerType === "page-navigation" ||
126
- triggerType === "top-navigation" ||
124
+ triggerType === "app-bar" ||
127
125
  triggerType === "user-menu"
128
126
  ) {
129
127
  const clickLink = {
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@0.1.17":
480
- version "0.1.17"
481
- resolved "https://registry.yarnpkg.com/@raclettejs/core/-/core-0.1.17.tgz#36712a73791a5115b09c50fcbe8856793dd9ed9c"
482
- integrity sha512-dMUW+/TikBRbZ4gOEvmSlwKJyRtvvGyJ9VFvhTbvYPMTjmnT/OzOIN9WMj6wG8b2tYFSNWtq+RNSQuc/G/nLxw==
479
+ "@raclettejs/core@^0.1.18":
480
+ version "0.1.18"
481
+ resolved "https://registry.yarnpkg.com/@raclettejs/core/-/core-0.1.18.tgz#6bf2a7de62996b3e2bc038b35e572467d2871130"
482
+ integrity sha512-jftqZLGoUm3CxG8UZ8nsF0vrQiZ+mhFdOglu+AdECEqi0Jr+2MbStEkHsz5RRKau6TXiT4Prmtv9/x1ZS8aGbQ==
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.17":
496
- version "0.1.17"
497
- resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.17.tgz#ced377e5fa8879a5790b1c0c838f621917032690"
498
- integrity sha512-WBhi6Nf/XJPlisF1stEB0KGo5TWw+EMaTuYt39fJKc+Vtyf/SFmZqP2D3BKlssE5N/8bo2DFgf2qUeKowo0onA==
495
+ "@raclettejs/types@^0.1.18":
496
+ version "0.1.18"
497
+ resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.18.tgz#7df0eb1b86db015694fabfafa089a277e654b350"
498
+ integrity sha512-mvQI2sO48z6+QKj/s5A5JMBKnY8piE+8D8N0soctfsU7tAKg8nEwlxOiQHZiqJyR1k+gX2p+VBMRGbxHCYAGFw==
499
499
  dependencies:
500
500
  "@types/node" "24.5.2"
501
501
  fastify "5.6.0"