@raclettejs/workbench 0.1.18 → 0.1.20

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.
Files changed (35) hide show
  1. package/.raclette/backend/raclette.config.js +519 -0
  2. package/{yarn.lock → .raclette/backend/yarn.lock} +1014 -796
  3. package/.raclette/frontend/raclette.config.js +47 -0
  4. package/.raclette/frontend/yarn.lock +3428 -0
  5. package/.raclette/raclette.config.js +643 -0
  6. package/.raclette/virtual/backend/README.md +172 -0
  7. package/.raclette/virtual/backend/raclette.config.js +519 -0
  8. package/.raclette/virtual/backend/yarn.lock +3773 -0
  9. package/.raclette/virtual/frontend/README.md +511 -0
  10. package/.raclette/virtual/frontend/raclette.config.js +47 -0
  11. package/.raclette/virtual/frontend/src/core/lib/eggs/readme.md +75 -0
  12. package/.raclette/virtual/frontend/yarn.lock +3428 -0
  13. package/CHANGELOG.md +11 -0
  14. package/i18n/de-DE.json +17 -1
  15. package/i18n/en-EU.json +17 -1
  16. package/i18n/sk-SK.json +17 -1
  17. package/package.json +6 -4
  18. package/packages.json +3 -1
  19. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/CompositionWidgetsLayout.vue +8 -3
  20. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetContextMenu.vue +60 -0
  21. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetIcon.vue +4 -7
  22. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetList.vue +34 -117
  23. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetListFlat.vue +20 -0
  24. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetListGrouped.vue +50 -0
  25. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetListHeader.vue +213 -0
  26. package/plugins/pacifico__compositions/frontend/components/compositionConfiguration/widgetsLayout/WidgetListItem.vue +56 -0
  27. package/plugins/pacifico__compositions/frontend/composables/useWidgetList.ts +288 -0
  28. package/plugins/pacifico__compositions/frontend/widgets/CompositionListWidget.vue +201 -57
  29. package/plugins/pacifico__interactionLinks/frontend/widgets/InteractionLinkListWidget.vue +219 -55
  30. package/plugins/pacifico__tags/frontend/widgets/TagListWidget.vue +198 -48
  31. package/raclette.config.js +4 -1
  32. package/services/frontend/src/app/components/FileUpload.vue +98 -0
  33. package/services/frontend/src/app/components/SelectionDialog.vue +182 -0
  34. package/services/frontend/src/app/components/SummaryDialog.vue +140 -0
  35. package/services/frontend/src/app/lib/jsonTools.ts +81 -0
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <!-- Dialog overlay -->
3
+ <div
4
+ v-if="dialog"
5
+ class="tw:fixed tw:inset-0 tw:flex tw:items-center tw:justify-center tw:bg-black/50 tw:z-50"
6
+ >
7
+ <!-- Dialog panel -->
8
+ <div
9
+ class="tw:bg-white tw:rounded-lg tw:shadow-xl tw:max-w-md tw:w-full tw:overflow-auto tw:h-[80%]"
10
+ >
11
+ <!-- Title bar -->
12
+ <div
13
+ class="tw:flex tw:justify-between tw:items-center tw:px-4 tw:py-3 tw:border-b tw:border-gray-200"
14
+ >
15
+ <span class="tw:text-lg tw:font-semibold">{{ title }}</span>
16
+
17
+ <button
18
+ @click="close"
19
+ class="tw:text-gray-500 hover:tw:text-gray-700 tw:p-1 tw:rounded tw:hover:bg-gray-100"
20
+ >
21
+ <i class="mdi mdi-close tw:text-xl"></i>
22
+ </button>
23
+ </div>
24
+
25
+ <!-- Content -->
26
+ <div class="tw:px-4 tw:py-4">
27
+ <!-- Alert -->
28
+ <div
29
+ :class="[
30
+ 'tw:rounded tw:p-4 tw:mb-4',
31
+ type === 'error' && 'tw:bg-red-50 tw:text-red-700',
32
+ type === 'warning' && 'tw:bg-yellow-50 tw:text-yellow-700',
33
+ type === 'info' && 'tw:bg-blue-50 tw:text-blue-700',
34
+ type === 'success' && 'tw:bg-green-50 tw:text-green-700',
35
+ ]"
36
+ >
37
+ <div class="tw:text-lg tw:font-medium tw:mb-2">
38
+ {{ message }}
39
+ </div>
40
+
41
+ <div class="tw:text-sm">
42
+ {{ $t("core.itemsCount") }}:
43
+ <strong>{{ itemCount }}</strong>
44
+ </div>
45
+ </div>
46
+
47
+ <!-- List -->
48
+ <div v-if="showItems && items.length > 0" class="tw:mt-4">
49
+ <div
50
+ class="tw:text-xs tw:uppercase tw:font-semibold tw:text-gray-500 tw:mb-2"
51
+ >
52
+ {{ $t("core.selectedItems") }}
53
+ </div>
54
+
55
+ <ul class="tw:space-y-1">
56
+ <li
57
+ v-for="item in items"
58
+ :key="item._id"
59
+ class="tw:px-3 tw:py-2 tw:bg-gray-50 tw:rounded tw:text-sm tw:text-gray-700"
60
+ >
61
+ {{ getDisplayValue(item) }}
62
+ </li>
63
+ </ul>
64
+ </div>
65
+ </div>
66
+
67
+ <!-- Actions -->
68
+ <div
69
+ class="tw:flex tw:justify-end tw:space-x-2 tw:px-4 tw:py-3 tw:border-t tw:border-gray-200"
70
+ >
71
+ <button
72
+ @click="close"
73
+ class="tw:px-4 tw:py-2 tw:text-sm tw:text-gray-700 hover:tw:bg-gray-100 tw:rounded"
74
+ >
75
+ {{ cancelText || $t("core.close") }}
76
+ </button>
77
+
78
+ <button
79
+ v-if="showConfirm"
80
+ @click="confirm"
81
+ :class="[
82
+ 'tw:px-4 tw:py-2 tw:text-sm tw:rounded tw:text-white',
83
+ type === 'error' && 'tw:bg-red-600 hover:tw:bg-red-700',
84
+ type === 'warning' && 'tw:bg-yellow-600 hover:tw:bg-yellow-700',
85
+ type === 'info' && 'tw:bg-blue-600 hover:tw:bg-blue-700',
86
+ type === 'success' && 'tw:bg-green-600 hover:tw:bg-green-700',
87
+ ]"
88
+ >
89
+ {{ confirmText }}
90
+ </button>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </template>
95
+
96
+ <script setup lang="ts">
97
+ import { computed } from "vue"
98
+
99
+ interface Props {
100
+ modelValue: boolean
101
+ items: any[]
102
+ title: string
103
+ message: string
104
+ type?: "info" | "success" | "warning" | "error"
105
+ showItems?: boolean
106
+ showConfirm?: boolean
107
+ displayAttribute: string
108
+ confirmText?: string
109
+ cancelText?: string
110
+ }
111
+
112
+ const props = withDefaults(defineProps<Props>(), {
113
+ type: "info",
114
+ showItems: true,
115
+ showConfirm: false,
116
+ })
117
+
118
+ const emit = defineEmits<{
119
+ "update:modelValue": [value: boolean]
120
+ confirm: []
121
+ }>()
122
+
123
+ const dialog = computed({
124
+ get: () => props.modelValue,
125
+ set: (value) => emit("update:modelValue", value),
126
+ })
127
+
128
+ const itemCount = computed(() => props.items.length)
129
+
130
+ const close = () => {
131
+ dialog.value = false
132
+ }
133
+ const getDisplayValue = (item: any) => {
134
+ return item[props.displayAttribute] || item._id
135
+ }
136
+ const confirm = () => {
137
+ emit("confirm")
138
+ close()
139
+ }
140
+ </script>
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Downloads a JSON object as a .json file
3
+ * @param {Object|Array} data - The data to be downloaded as JSON
4
+ * @param {string} filename - The name of the file (without .json extension)
5
+ * @throws {Error} If data cannot be serialized to JSON
6
+ */
7
+ export function downloadJson(data, filename = "download") {
8
+ try {
9
+ // Convert data to JSON string with pretty formatting
10
+ const jsonString = JSON.stringify(data, null, 2)
11
+
12
+ // Create blob from JSON string
13
+ const blob = new Blob([jsonString], { type: "application/json" })
14
+
15
+ // Create download link
16
+ const url = URL.createObjectURL(blob)
17
+ const link = document.createElement("a")
18
+
19
+ // Ensure filename has .json extension
20
+ const normalizedFilename = filename.endsWith(".json")
21
+ ? filename
22
+ : `${filename}.json`
23
+
24
+ link.href = url
25
+ link.download = normalizedFilename
26
+
27
+ // Trigger download
28
+ document.body.appendChild(link)
29
+ link.click()
30
+
31
+ // Cleanup
32
+ document.body.removeChild(link)
33
+ URL.revokeObjectURL(url)
34
+ } catch (error) {
35
+ console.error("Failed to download JSON:", error)
36
+ throw new Error(`Unable to download JSON file: ${error.message}`)
37
+ }
38
+ }
39
+ /**
40
+ * Recursively maps values in a JSON object based on a mapping configuration
41
+ * @param {Object|Array} data - The source JSON data to transform
42
+ * @param {Object} mapping - Mapping object where keys are attribute names and values are replacement values
43
+ * @returns {Object|Array} New object with mapped values
44
+ * @throws {Error} If data cannot be processed
45
+ *
46
+ * @example
47
+ * const data = { owner: 'user123', name: 'Project A', lastEditor: 'user123' };
48
+ * const mapping = { owner: 'user456', lastEditor: 'user789' };
49
+ * const result = mapJsonValues(data, mapping);
50
+ * // Result: { owner: 'user456', name: 'Project A', lastEditor: 'user789' }
51
+ */
52
+ export function mapJsonValues(data, mapping = {}) {
53
+ if (!data || typeof data !== "object") {
54
+ return data
55
+ }
56
+
57
+ // Handle arrays
58
+ if (Array.isArray(data)) {
59
+ return data.map((item) => mapJsonValues(item, mapping))
60
+ }
61
+
62
+ // Handle objects
63
+ const result = {}
64
+
65
+ for (const [key, value] of Object.entries(data)) {
66
+ // If this key exists in mapping, use the mapped value
67
+ if (key in mapping) {
68
+ result[key] = mapping[key]
69
+ }
70
+ // If value is an object or array, recursively process it
71
+ else if (value && typeof value === "object") {
72
+ result[key] = mapJsonValues(value, mapping)
73
+ }
74
+ // Otherwise keep the original value
75
+ else {
76
+ result[key] = value
77
+ }
78
+ }
79
+
80
+ return result
81
+ }