@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>
|