@motor-cms/ui-admin 4.1.0 → 4.2.1

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.
@@ -0,0 +1,235 @@
1
+ <script setup lang="ts">
2
+ const props = defineProps<{
3
+ configurableType: string
4
+ configurableId: number | string
5
+ }>()
6
+
7
+ const { t } = useI18n()
8
+ const client = useSanctumClient()
9
+ const { success: notifySuccess, error: notifyError } = useNotify()
10
+
11
+ interface ConfigVariable {
12
+ id: number
13
+ package: string
14
+ group: string
15
+ name: string
16
+ value: string
17
+ }
18
+
19
+ interface EntityConfiguration {
20
+ id: number
21
+ configurable_type: string
22
+ configurable_id: number
23
+ config_variable_id: number
24
+ config_variable?: ConfigVariable
25
+ value: string | null
26
+ }
27
+
28
+ const configurations = ref<EntityConfiguration[]>([])
29
+ const configVariables = ref<ConfigVariable[]>([])
30
+ const loading = ref(false)
31
+ const saving = ref(false)
32
+ const removing = ref<number | null>(null)
33
+
34
+ const newConfigVariableId = ref<number | null>(null)
35
+ const newValue = ref('')
36
+
37
+ async function loadConfigurations() {
38
+ loading.value = true
39
+ try {
40
+ const response = await client<{ data: EntityConfiguration[] }>('/api/v2/entity-configurations', {
41
+ query: {
42
+ configurable_type: props.configurableType,
43
+ configurable_id: props.configurableId,
44
+ per_page: 100
45
+ }
46
+ })
47
+ configurations.value = response.data ?? []
48
+ } catch {
49
+ configurations.value = []
50
+ } finally {
51
+ loading.value = false
52
+ }
53
+ }
54
+
55
+ async function loadConfigVariables() {
56
+ try {
57
+ const response = await client<{ data: ConfigVariable[] }>('/api/v2/config-variables', {
58
+ query: { per_page: 200 }
59
+ })
60
+ configVariables.value = response.data ?? []
61
+ } catch {
62
+ configVariables.value = []
63
+ }
64
+ }
65
+
66
+ const availableConfigVariables = computed(() => {
67
+ const usedIds = new Set(configurations.value.map(c => c.config_variable_id))
68
+ return configVariables.value
69
+ .filter(v => !usedIds.has(v.id))
70
+ .map(v => ({
71
+ label: `${v.package}.${v.group}.${v.name}`,
72
+ value: v.id
73
+ }))
74
+ })
75
+
76
+ const canAdd = computed(() => newConfigVariableId.value !== null)
77
+
78
+ async function addConfiguration() {
79
+ if (!canAdd.value) return
80
+ saving.value = true
81
+ try {
82
+ await client('/api/v2/entity-configurations', {
83
+ method: 'POST',
84
+ body: {
85
+ configurable_type: props.configurableType,
86
+ configurable_id: props.configurableId,
87
+ config_variable_id: newConfigVariableId.value,
88
+ value: newValue.value || null
89
+ }
90
+ })
91
+ newConfigVariableId.value = null
92
+ newValue.value = ''
93
+ await loadConfigurations()
94
+ notifySuccess(
95
+ t('motor-admin.entity_configurations.title'),
96
+ t('motor-admin.entity_configurations.saved')
97
+ )
98
+ } catch (e) {
99
+ notifyError(
100
+ t('motor-admin.entity_configurations.title'),
101
+ (e as Error).message
102
+ )
103
+ } finally {
104
+ saving.value = false
105
+ }
106
+ }
107
+
108
+ async function removeConfiguration(config: EntityConfiguration) {
109
+ removing.value = config.id
110
+ try {
111
+ await client(`/api/v2/entity-configurations/${config.id}`, {
112
+ method: 'DELETE'
113
+ })
114
+ await loadConfigurations()
115
+ notifySuccess(
116
+ t('motor-admin.entity_configurations.title'),
117
+ t('motor-admin.entity_configurations.removed')
118
+ )
119
+ } catch (e) {
120
+ notifyError(
121
+ t('motor-admin.entity_configurations.title'),
122
+ (e as Error).message
123
+ )
124
+ } finally {
125
+ removing.value = null
126
+ }
127
+ }
128
+
129
+ function formatVariableName(cv: ConfigVariable | undefined): string {
130
+ if (!cv) return '—'
131
+ return `${cv.package}.${cv.group}.${cv.name}`
132
+ }
133
+
134
+ onMounted(() => {
135
+ loadConfigurations()
136
+ loadConfigVariables()
137
+ })
138
+ </script>
139
+
140
+ <template>
141
+ <UCard>
142
+ <template #header>
143
+ <div class="flex items-center justify-between">
144
+ <h3 class="text-base font-semibold">
145
+ {{ t('motor-admin.entity_configurations.title') }}
146
+ </h3>
147
+ <span
148
+ v-if="configurations.length > 0"
149
+ class="text-xs text-[var(--ui-text-muted)]"
150
+ >
151
+ {{ configurations.length }}
152
+ </span>
153
+ </div>
154
+ </template>
155
+
156
+ <div
157
+ v-if="loading"
158
+ class="flex items-center justify-center py-6"
159
+ >
160
+ <UIcon
161
+ name="i-lucide-loader-2"
162
+ class="size-5 animate-spin text-[var(--ui-text-muted)]"
163
+ />
164
+ </div>
165
+
166
+ <div v-else>
167
+ <!-- Existing configurations -->
168
+ <div
169
+ v-if="configurations.length > 0"
170
+ class="mb-4 space-y-2"
171
+ >
172
+ <div
173
+ v-for="config in configurations"
174
+ :key="config.id"
175
+ class="flex items-center gap-4 py-2.5 px-3 rounded-lg ring-1 ring-[var(--ui-border)] group"
176
+ >
177
+ <UIcon
178
+ name="i-lucide-link"
179
+ class="size-3.5 text-emerald-500 shrink-0"
180
+ />
181
+ <div class="min-w-0 flex-1">
182
+ <p class="text-sm font-medium truncate">
183
+ {{ formatVariableName(config.config_variable) }}
184
+ </p>
185
+ </div>
186
+ <div class="shrink-0 max-w-xs">
187
+ <span class="text-sm text-[var(--ui-text-muted)] font-mono truncate">
188
+ {{ config.value ?? '—' }}
189
+ </span>
190
+ </div>
191
+ <UButton
192
+ icon="i-lucide-unlink"
193
+ variant="ghost"
194
+ color="error"
195
+ size="xs"
196
+ :loading="removing === config.id"
197
+ class="opacity-0 group-hover:opacity-100 transition-opacity shrink-0"
198
+ @click="removeConfiguration(config)"
199
+ />
200
+ </div>
201
+ </div>
202
+
203
+ <p
204
+ v-else
205
+ class="text-sm text-[var(--ui-text-muted)] mb-4"
206
+ >
207
+ {{ t('motor-admin.entity_configurations.no_configurations') }}
208
+ </p>
209
+
210
+ <!-- Add new configuration -->
211
+ <div class="flex items-start gap-3">
212
+ <USelect
213
+ v-model="newConfigVariableId"
214
+ :items="availableConfigVariables"
215
+ :placeholder="t('motor-admin.entity_configurations.select_variable')"
216
+ class="flex-1"
217
+ />
218
+ <UInput
219
+ v-model="newValue"
220
+ :placeholder="t('motor-admin.entity_configurations.value')"
221
+ class="flex-1"
222
+ @keydown.enter.prevent="addConfiguration"
223
+ />
224
+ <UButton
225
+ icon="i-lucide-plus"
226
+ variant="outline"
227
+ :disabled="!canAdd"
228
+ :loading="saving"
229
+ class="shrink-0"
230
+ @click="addConfiguration"
231
+ />
232
+ </div>
233
+ </div>
234
+ </UCard>
235
+ </template>
@@ -0,0 +1,12 @@
1
+ {
2
+ "title": "Entity-Konfigurationen",
3
+ "config_variable": "Konfigurationsvariable",
4
+ "value": "Wert",
5
+ "add": "Konfiguration hinzufügen",
6
+ "save": "Speichern",
7
+ "saved": "Konfiguration gespeichert",
8
+ "removed": "Konfiguration entfernt",
9
+ "no_configurations": "Noch keine Konfigurationen zugeordnet.",
10
+ "select_variable": "Konfigurationsvariable auswählen",
11
+ "confirm_remove": "Diese Konfiguration entfernen?"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "title": "Entity Configurations",
3
+ "config_variable": "Config Variable",
4
+ "value": "Value",
5
+ "add": "Add Configuration",
6
+ "save": "Save",
7
+ "saved": "Configuration saved",
8
+ "removed": "Configuration removed",
9
+ "no_configurations": "No configurations assigned yet.",
10
+ "select_variable": "Select a config variable",
11
+ "confirm_remove": "Remove this configuration?"
12
+ }
@@ -22,6 +22,9 @@ const mergedSelectOptions = computed(() => ({
22
22
  ...selectOptions?.value,
23
23
  protocol: domainProtocolOptions
24
24
  }))
25
+
26
+ const { can } = usePermissions()
27
+ const showEntityConfigs = computed(() => can('entity-configurations.read'))
25
28
  </script>
26
29
 
27
30
  <template>
@@ -49,6 +52,16 @@ const mergedSelectOptions = computed(() => ({
49
52
  @submit="onSubmit"
50
53
  @save-and-continue="onSaveAndContinue"
51
54
  @save-and-new="onSaveAndNew"
52
- />
55
+ >
56
+ <template
57
+ v-if="showEntityConfigs"
58
+ #after-fields
59
+ >
60
+ <FormInputsEntityConfigurationsPanel
61
+ configurable-type="Motor\Admin\Models\Domain"
62
+ :configurable-id="Number(route.params.id)"
63
+ />
64
+ </template>
65
+ </FormBase>
53
66
  </FormPage>
54
67
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-cms/ui-admin",
3
- "version": "4.1.0",
3
+ "version": "4.2.1",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [