RBAC #346 - Interface Admin : Gestion des Rôles (Frontend) #5
@@ -32,6 +32,12 @@ return [
|
|||||||
'icon' => 'mdi:cog-outline',
|
'icon' => 'mdi:cog-outline',
|
||||||
'module' => 'core',
|
'module' => 'core',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'label' => 'sidebar.core.roles',
|
||||||
|
'to' => '/admin/roles',
|
||||||
|
'icon' => 'mdi:shield-account-outline',
|
||||||
|
'module' => 'core',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'label' => 'sidebar.general.logout',
|
'label' => 'sidebar.general.logout',
|
||||||
'to' => '/logout',
|
'to' => '/logout',
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
"commercial": {
|
"commercial": {
|
||||||
"section": "Commercial",
|
"section": "Commercial",
|
||||||
"suppliers": "Répertoire fournisseurs"
|
"suppliers": "Répertoire fournisseurs"
|
||||||
|
},
|
||||||
|
"core": {
|
||||||
|
"roles": "Gestion des roles"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
@@ -56,5 +59,41 @@
|
|||||||
"auth": {
|
"auth": {
|
||||||
"logout": "Deconnexion reussie"
|
"logout": "Deconnexion reussie"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"roles": {
|
||||||
|
"title": "Gestion des roles",
|
||||||
|
"newRole": "Nouveau role",
|
||||||
|
"editRole": "Modifier le role",
|
||||||
|
"createRole": "Creer un role",
|
||||||
|
"noRoles": "Aucun role configure",
|
||||||
|
"table": {
|
||||||
|
"label": "Libelle",
|
||||||
|
"code": "Code",
|
||||||
|
"permissions": "Permissions",
|
||||||
|
"system": "Systeme",
|
||||||
|
"actions": "Actions"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"label": "Libelle",
|
||||||
|
"code": "Code",
|
||||||
|
"description": "Description",
|
||||||
|
"permissions": "Permissions"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"title": "Supprimer le role",
|
||||||
|
"message": "Etes-vous sur de vouloir supprimer le role \"{label}\" ? Cette action est irreversible.",
|
||||||
|
"systemTooltip": "Role systeme non supprimable"
|
||||||
|
},
|
||||||
|
"toast": {
|
||||||
|
"created": "Role cree avec succes",
|
||||||
|
"updated": "Role mis a jour avec succes",
|
||||||
|
"deleted": "Role supprime avec succes"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"selectAll": "Tout selectionner",
|
||||||
|
"noPermissions": "Aucune permission disponible"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
72
frontend/modules/core/components/PermissionGroup.vue
Normal file
72
frontend/modules/core/components/PermissionGroup.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div class="rounded-lg border border-neutral-200 overflow-hidden">
|
||||||
|
<!-- En-tete du groupe avec checkbox "tout selectionner" -->
|
||||||
|
<div class="flex items-center gap-3 bg-neutral-50 px-4 py-3 border-b border-neutral-200">
|
||||||
|
<MalioCheckbox
|
||||||
|
:id="`group-${module}`"
|
||||||
|
:label="moduleLabel"
|
||||||
|
:model-value="allSelected"
|
||||||
|
label-class="font-semibold text-sm text-neutral-700 capitalize"
|
||||||
|
@update:model-value="toggleAll"
|
||||||
|
/>
|
||||||
|
<span class="ml-auto text-xs text-neutral-400">
|
||||||
|
{{ selectedCount }}/{{ permissions.length }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Liste des permissions individuelles -->
|
||||||
|
<div class="grid grid-cols-1 gap-1 p-3 sm:grid-cols-2">
|
||||||
|
<MalioCheckbox
|
||||||
|
v-for="perm in permissions"
|
||||||
|
:key="perm.id"
|
||||||
|
:id="`perm-${perm.id}`"
|
||||||
|
:label="perm.label"
|
||||||
|
:model-value="selectedIds.has(perm.id)"
|
||||||
|
label-class="text-sm text-neutral-600"
|
||||||
|
@update:model-value="(val: boolean) => togglePermission(perm.id, val)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface Permission {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
module: string
|
||||||
|
orphan: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
module: string
|
||||||
|
moduleLabel: string
|
||||||
|
permissions: Permission[]
|
||||||
|
selectedIds: Set<number>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
toggle: [permissionId: number, selected: boolean]
|
||||||
|
toggleAll: [module: string, selected: boolean]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// Nombre de permissions selectionnees dans ce groupe
|
||||||
|
const selectedCount = computed(() =>
|
||||||
|
props.permissions.filter(p => props.selectedIds.has(p.id)).length
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vrai si toutes les permissions du groupe sont selectionnees
|
||||||
|
const allSelected = computed(() =>
|
||||||
|
props.permissions.length > 0 && selectedCount.value === props.permissions.length
|
||||||
|
)
|
||||||
|
|
||||||
|
// Emet l'evenement de bascule pour une permission individuelle
|
||||||
|
function togglePermission(id: number, selected: boolean) {
|
||||||
|
emit('toggle', id, selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emet l'evenement de bascule pour toutes les permissions du groupe
|
||||||
|
function toggleAll(selected: boolean) {
|
||||||
|
emit('toggleAll', props.module, selected)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
69
frontend/modules/core/components/RoleDeleteModal.vue
Normal file
69
frontend/modules/core/components/RoleDeleteModal.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<Teleport to="body">
|
||||||
|
<Transition name="fade">
|
||||||
|
<div
|
||||||
|
v-if="modelValue"
|
||||||
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
|
||||||
|
@click.self="cancel"
|
||||||
|
>
|
||||||
|
<div class="w-full max-w-md rounded-lg bg-white p-6 shadow-xl">
|
||||||
|
<h3 class="text-lg font-semibold text-neutral-900">
|
||||||
|
{{ t('admin.roles.delete.title') }}
|
||||||
|
</h3>
|
||||||
|
<p class="mt-3 text-sm text-neutral-600">
|
||||||
|
{{ t('admin.roles.delete.message', { label: roleLabel }) }}
|
||||||
|
</p>
|
||||||
|
<div class="mt-6 flex justify-end gap-3">
|
||||||
|
<MalioButton
|
||||||
|
:label="t('common.cancel')"
|
||||||
|
variant="secondary"
|
||||||
|
@click="cancel"
|
||||||
|
/>
|
||||||
|
<MalioButton
|
||||||
|
:label="t('common.delete')"
|
||||||
|
variant="danger"
|
||||||
|
:disabled="loading"
|
||||||
|
@click="confirm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
modelValue: boolean
|
||||||
|
roleLabel: string
|
||||||
|
loading: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: boolean]
|
||||||
|
confirm: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// Ferme la modale sans confirmer
|
||||||
|
function cancel() {
|
||||||
|
emit('update:modelValue', false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emet l'evenement de confirmation de suppression
|
||||||
|
function confirm() {
|
||||||
|
emit('confirm')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
224
frontend/modules/core/components/RoleDrawer.vue
Normal file
224
frontend/modules/core/components/RoleDrawer.vue
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
<template>
|
||||||
|
<MalioDrawer
|
||||||
|
:model-value="modelValue"
|
||||||
|
:title="isEditMode ? t('admin.roles.editRole') : t('admin.roles.createRole')"
|
||||||
|
drawer-class="w-full max-w-lg"
|
||||||
|
@update:model-value="emit('update:modelValue', $event)"
|
||||||
|
>
|
||||||
|
<form class="flex flex-col gap-6 p-4" @submit.prevent="handleSave">
|
||||||
|
<!-- Champs du role -->
|
||||||
|
<MalioInputText
|
||||||
|
v-model="form.label"
|
||||||
|
:label="t('admin.roles.form.label')"
|
||||||
|
input-class="w-full"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MalioInputText
|
||||||
|
v-model="form.code"
|
||||||
|
:label="t('admin.roles.form.code')"
|
||||||
|
input-class="w-full"
|
||||||
|
required
|
||||||
|
:readonly="isEditMode && role?.isSystem"
|
||||||
|
:hint="isEditMode && role?.isSystem ? t('admin.roles.delete.systemTooltip') : ''"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MalioInputTextArea
|
||||||
|
v-model="form.description"
|
||||||
|
:label="t('admin.roles.form.description')"
|
||||||
|
input-class="w-full"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Permissions groupees par module -->
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-3 text-sm font-semibold text-neutral-700">
|
||||||
|
{{ t('admin.roles.form.permissions') }}
|
||||||
|
</h4>
|
||||||
|
<div v-if="permissionsByModule.length === 0" class="text-sm text-neutral-400">
|
||||||
|
{{ t('admin.roles.permissions.noPermissions') }}
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<PermissionGroup
|
||||||
|
v-for="group in permissionsByModule"
|
||||||
|
:key="group.module"
|
||||||
|
:module="group.module"
|
||||||
|
:module-label="group.module"
|
||||||
|
:permissions="group.permissions"
|
||||||
|
:selected-ids="selectedPermissionIds"
|
||||||
|
@toggle="handleTogglePermission"
|
||||||
|
@toggle-all="handleToggleAll"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Boutons -->
|
||||||
|
<div class="flex justify-end gap-3 border-t border-neutral-200 pt-4">
|
||||||
|
<MalioButton
|
||||||
|
:label="t('common.cancel')"
|
||||||
|
variant="secondary"
|
||||||
|
@click="emit('update:modelValue', false)"
|
||||||
|
/>
|
||||||
|
<MalioButton
|
||||||
|
:label="t('common.save')"
|
||||||
|
variant="primary"
|
||||||
|
:disabled="saving"
|
||||||
|
@click="handleSave"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</MalioDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface Permission {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
module: string
|
||||||
|
orphan: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Role {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
description: string | null
|
||||||
|
isSystem: boolean
|
||||||
|
permissions: (Permission | string)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PermissionModule {
|
||||||
|
module: string
|
||||||
|
permissions: Permission[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: boolean
|
||||||
|
role: Role | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: boolean]
|
||||||
|
saved: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const saving = ref(false)
|
||||||
|
const allPermissions = ref<Permission[]>([])
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
label: '',
|
||||||
|
code: '',
|
||||||
|
description: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedPermissionIds = ref(new Set<number>())
|
||||||
|
|
||||||
|
const isEditMode = computed(() => props.role !== null)
|
||||||
|
|
||||||
|
// Grouper les permissions par module
|
||||||
|
const permissionsByModule = computed<PermissionModule[]>(() => {
|
||||||
|
const groups = new Map<string, Permission[]>()
|
||||||
|
for (const perm of allPermissions.value) {
|
||||||
|
if (perm.orphan) continue
|
||||||
|
const list = groups.get(perm.module) || []
|
||||||
|
list.push(perm)
|
||||||
|
groups.set(perm.module, list)
|
||||||
|
}
|
||||||
|
return Array.from(groups.entries())
|
||||||
|
.map(([module, permissions]) => ({ module, permissions }))
|
||||||
|
.sort((a, b) => a.module.localeCompare(b.module))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Charger les permissions au montage
|
||||||
|
async function loadPermissions() {
|
||||||
|
const data = await api.get<{ member: Permission[] }>(
|
||||||
|
'/permissions',
|
||||||
|
{ 'orphan': false, itemsPerPage: 200 },
|
||||||
|
{ toast: false },
|
||||||
|
)
|
||||||
|
allPermissions.value = data.member
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remplir le formulaire quand le role change
|
||||||
|
watch(() => props.role, (role) => {
|
||||||
|
if (role) {
|
||||||
|
form.value.label = role.label
|
||||||
|
form.value.code = role.code
|
||||||
|
form.value.description = role.description || ''
|
||||||
|
selectedPermissionIds.value = new Set(role.permissions.map(p => {
|
||||||
|
// L'API peut retourner des objets Permission ou des IRIs string
|
||||||
|
if (typeof p === 'string') {
|
||||||
|
return Number(p.split('/').pop())
|
||||||
|
}
|
||||||
|
return p.id
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
form.value.label = ''
|
||||||
|
form.value.code = ''
|
||||||
|
form.value.description = ''
|
||||||
|
selectedPermissionIds.value = new Set()
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
// Charger les permissions quand le drawer s'ouvre
|
||||||
|
watch(() => props.modelValue, (open) => {
|
||||||
|
if (open) loadPermissions()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Basculer une permission individuelle
|
||||||
|
function handleTogglePermission(id: number, selected: boolean) {
|
||||||
|
const ids = new Set(selectedPermissionIds.value)
|
||||||
|
if (selected) {
|
||||||
|
ids.add(id)
|
||||||
|
} else {
|
||||||
|
ids.delete(id)
|
||||||
|
}
|
||||||
|
selectedPermissionIds.value = ids
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basculer toutes les permissions d'un module
|
||||||
|
function handleToggleAll(module: string, selected: boolean) {
|
||||||
|
const ids = new Set(selectedPermissionIds.value)
|
||||||
|
const group = permissionsByModule.value.find(g => g.module === module)
|
||||||
|
if (!group) return
|
||||||
|
for (const perm of group.permissions) {
|
||||||
|
if (selected) {
|
||||||
|
ids.add(perm.id)
|
||||||
|
} else {
|
||||||
|
ids.delete(perm.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedPermissionIds.value = ids
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sauvegarder le role (creation ou edition)
|
||||||
|
async function handleSave() {
|
||||||
|
saving.value = true
|
||||||
|
try {
|
||||||
|
const body = {
|
||||||
|
label: form.value.label,
|
||||||
|
code: form.value.code,
|
||||||
|
description: form.value.description || null,
|
||||||
|
permissions: Array.from(selectedPermissionIds.value).map(id => `/api/permissions/${id}`),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEditMode.value && props.role) {
|
||||||
|
await api.patch(`/roles/${props.role.id}`, body, {
|
||||||
|
toastSuccessMessage: t('admin.roles.toast.updated'),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await api.post('/roles', body, {
|
||||||
|
toastSuccessMessage: t('admin.roles.toast.created'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('saved')
|
||||||
|
emit('update:modelValue', false)
|
||||||
|
} finally {
|
||||||
|
saving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
193
frontend/modules/core/pages/admin/roles.vue
Normal file
193
frontend/modules/core/pages/admin/roles.vue
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- En-tete -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h1 class="text-xl font-bold text-primary-500 sm:text-2xl">
|
||||||
|
{{ t('admin.roles.title') }}
|
||||||
|
</h1>
|
||||||
|
<MalioButton
|
||||||
|
v-if="can('core.roles.manage')"
|
||||||
|
:label="t('admin.roles.newRole')"
|
||||||
|
icon-name="mdi:plus"
|
||||||
|
@click="openCreateDrawer"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Table des roles -->
|
||||||
|
<MalioDataTable
|
||||||
|
class="mt-6"
|
||||||
|
:columns="columns"
|
||||||
|
:items="roleItems"
|
||||||
|
:total-items="roles.length"
|
||||||
|
:row-clickable="true"
|
||||||
|
:empty-message="t('admin.roles.noRoles')"
|
||||||
|
@row-click="onRowClick"
|
||||||
|
>
|
||||||
|
<template #cell-code="{ item }">
|
||||||
|
<span class="font-mono text-xs">{{ item.code }}</span>
|
||||||
|
</template>
|
||||||
|
<template #cell-permissions="{ item }">
|
||||||
|
{{ item.permissions }}
|
||||||
|
</template>
|
||||||
|
<template #cell-system="{ item }">
|
||||||
|
<span
|
||||||
|
v-if="item.isSystem"
|
||||||
|
class="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800"
|
||||||
|
>
|
||||||
|
{{ t('admin.roles.table.system') }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #cell-actions="{ item }">
|
||||||
|
<div class="flex items-center justify-end gap-2" @click.stop>
|
||||||
|
<MalioButtonIcon
|
||||||
|
v-if="can('core.roles.manage')"
|
||||||
|
icon="mdi:pencil-outline"
|
||||||
|
:aria-label="t('common.edit')"
|
||||||
|
variant="ghost"
|
||||||
|
@click="openEditDrawer(getRoleById(item.id as number)!)"
|
||||||
|
/>
|
||||||
|
<MalioButtonIcon
|
||||||
|
v-if="can('core.roles.manage')"
|
||||||
|
icon="mdi:delete-outline"
|
||||||
|
:aria-label="t('common.delete')"
|
||||||
|
variant="ghost"
|
||||||
|
:disabled="item.isSystem as boolean"
|
||||||
|
@click="confirmDelete(getRoleById(item.id as number)!)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</MalioDataTable>
|
||||||
|
|
||||||
|
<!-- Drawer creation/edition -->
|
||||||
|
<RoleDrawer
|
||||||
|
v-model="drawerOpen"
|
||||||
|
:role="selectedRole"
|
||||||
|
@saved="onRoleSaved"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Modale de suppression -->
|
||||||
|
<RoleDeleteModal
|
||||||
|
v-model="deleteModalOpen"
|
||||||
|
:role-label="roleToDelete?.label ?? ''"
|
||||||
|
:loading="deleting"
|
||||||
|
@confirm="handleDelete"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface Permission {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
module: string
|
||||||
|
orphan: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Role {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
description: string | null
|
||||||
|
isSystem: boolean
|
||||||
|
permissions: (Permission | string)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const api = useApi()
|
||||||
|
const { can } = usePermissions()
|
||||||
|
|
||||||
|
useHead({ title: t('admin.roles.title') })
|
||||||
|
|
||||||
|
const roles = ref<Role[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ key: 'label', label: t('admin.roles.table.label') },
|
||||||
|
{ key: 'code', label: t('admin.roles.table.code') },
|
||||||
|
{ key: 'permissions', label: t('admin.roles.table.permissions') },
|
||||||
|
{ key: 'system', label: t('admin.roles.table.system') },
|
||||||
|
{ key: 'actions', label: t('admin.roles.table.actions') },
|
||||||
|
]
|
||||||
|
|
||||||
|
// Transformer les roles en items compatibles MalioDataTable
|
||||||
|
const roleItems = computed(() =>
|
||||||
|
roles.value.map(role => ({
|
||||||
|
id: role.id,
|
||||||
|
label: role.label,
|
||||||
|
code: role.code,
|
||||||
|
permissions: role.permissions.length,
|
||||||
|
isSystem: role.isSystem,
|
||||||
|
system: '', // colonne geree par le slot
|
||||||
|
actions: '', // colonne geree par le slot
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
function getRoleById(id: number): Role | undefined {
|
||||||
|
return roles.value.find(r => r.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRowClick(item: Record<string, unknown>) {
|
||||||
|
const role = getRoleById(item.id as number)
|
||||||
|
if (role) openEditDrawer(role)
|
||||||
|
}
|
||||||
|
const drawerOpen = ref(false)
|
||||||
|
const selectedRole = ref<Role | null>(null)
|
||||||
|
const deleteModalOpen = ref(false)
|
||||||
|
const roleToDelete = ref<Role | null>(null)
|
||||||
|
const deleting = ref(false)
|
||||||
|
|
||||||
|
// Charger la liste des roles
|
||||||
|
async function loadRoles() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const data = await api.get<{ member: Role[] }>(
|
||||||
|
'/roles',
|
||||||
|
{},
|
||||||
|
{ toast: false },
|
||||||
|
)
|
||||||
|
roles.value = data.member
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openCreateDrawer() {
|
||||||
|
selectedRole.value = null
|
||||||
|
drawerOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function openEditDrawer(role: Role) {
|
||||||
|
selectedRole.value = role
|
||||||
|
drawerOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmDelete(role: Role) {
|
||||||
|
if (role.isSystem) return
|
||||||
|
roleToDelete.value = role
|
||||||
|
deleteModalOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
if (!roleToDelete.value) return
|
||||||
|
deleting.value = true
|
||||||
|
try {
|
||||||
|
await api.delete(`/roles/${roleToDelete.value.id}`, {}, {
|
||||||
|
toastSuccessMessage: t('admin.roles.toast.deleted'),
|
||||||
|
})
|
||||||
|
deleteModalOpen.value = false
|
||||||
|
roleToDelete.value = null
|
||||||
|
await loadRoles()
|
||||||
|
} finally {
|
||||||
|
deleting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRoleSaved() {
|
||||||
|
loadRoles()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadRoles()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
79
frontend/package-lock.json
generated
79
frontend/package-lock.json
generated
@@ -7,7 +7,7 @@
|
|||||||
"name": "coltura-frontend",
|
"name": "coltura-frontend",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@malio/layer-ui": "^1.2.3",
|
"@malio/layer-ui": "^1.3.0",
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/i18n": "^10.2.3",
|
"@nuxtjs/i18n": "^10.2.3",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
@@ -83,7 +83,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
||||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.29.0",
|
"@babel/code-frame": "^7.29.0",
|
||||||
"@babel/generator": "^7.29.0",
|
"@babel/generator": "^7.29.0",
|
||||||
@@ -581,6 +580,27 @@
|
|||||||
"integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==",
|
"integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@emnapi/core": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.2.1",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emnapi/wasi-threads": {
|
"node_modules/@emnapi/wasi-threads": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
||||||
@@ -1819,9 +1839,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@malio/layer-ui": {
|
"node_modules/@malio/layer-ui": {
|
||||||
"version": "1.2.3",
|
"version": "1.3.0",
|
||||||
"resolved": "https://gitea.malio.fr/api/packages/MALIO-DEV/npm/%40malio%2Flayer-ui/-/1.2.3/layer-ui-1.2.3.tgz",
|
"resolved": "https://gitea.malio.fr/api/packages/MALIO-DEV/npm/%40malio%2Flayer-ui/-/1.3.0/layer-ui-1.3.0.tgz",
|
||||||
"integrity": "sha512-5nRnBzRkXfs3PfKwKl6sH2ikrmSK7lTifcd0TX1QZP3rFRVRTgcT6mrsrpsbR9PwI27OeCNm0X6d0Ii92Rq7Yg==",
|
"integrity": "sha512-Gs4pnlWTWrhoF3QQKxYBu4IxN65O9B4bls7s+ONm05qvI2Y2x7N4VNFGjWvT+rNQ4BzHFCxSCzN4V3o6p0Q7uw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
@@ -2166,7 +2186,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.4.2.tgz",
|
||||||
"integrity": "sha512-5+IPRNX2CjkBhuWUwz0hBuLqiaJPRoKzQ+SvcdrQDbAyE+VDeFt74VpSFr5/R0ujrK4b+XnSHUJWdS72w6hsog==",
|
"integrity": "sha512-5+IPRNX2CjkBhuWUwz0hBuLqiaJPRoKzQ+SvcdrQDbAyE+VDeFt74VpSFr5/R0ujrK4b+XnSHUJWdS72w6hsog==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"c12": "^3.3.3",
|
"c12": "^3.3.3",
|
||||||
"consola": "^3.4.2",
|
"consola": "^3.4.2",
|
||||||
@@ -2269,7 +2288,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.2.tgz",
|
||||||
"integrity": "sha512-/q6C7Qhiricgi+PKR7ovBnJlKTL0memCbA1CzRT+itCW/oeYzUfeMdQ35mGntlBoyRPNrMXbzuSUhfDbSCU57w==",
|
"integrity": "sha512-/q6C7Qhiricgi+PKR7ovBnJlKTL0memCbA1CzRT+itCW/oeYzUfeMdQ35mGntlBoyRPNrMXbzuSUhfDbSCU57w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/shared": "^3.5.30",
|
"@vue/shared": "^3.5.30",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
@@ -4610,7 +4628,6 @@
|
|||||||
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
|
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.19.0"
|
"undici-types": "~7.19.0"
|
||||||
}
|
}
|
||||||
@@ -4673,7 +4690,6 @@
|
|||||||
"integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==",
|
"integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.58.2",
|
"@typescript-eslint/scope-manager": "8.58.2",
|
||||||
"@typescript-eslint/types": "8.58.2",
|
"@typescript-eslint/types": "8.58.2",
|
||||||
@@ -4818,7 +4834,6 @@
|
|||||||
"integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==",
|
"integrity": "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.9.1",
|
"@eslint-community/eslint-utils": "^4.9.1",
|
||||||
"@typescript-eslint/scope-manager": "8.58.2",
|
"@typescript-eslint/scope-manager": "8.58.2",
|
||||||
@@ -5454,7 +5469,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz",
|
||||||
"integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==",
|
"integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.29.2",
|
"@babel/parser": "^7.29.2",
|
||||||
"@vue/compiler-core": "3.5.32",
|
"@vue/compiler-core": "3.5.32",
|
||||||
@@ -5698,7 +5712,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
|
||||||
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -6086,7 +6099,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
|
||||||
"integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
|
"integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"bare-abort-controller": "*"
|
"bare-abort-controller": "*"
|
||||||
},
|
},
|
||||||
@@ -6284,7 +6296,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.10.12",
|
"baseline-browser-mapping": "^2.10.12",
|
||||||
"caniuse-lite": "^1.0.30001782",
|
"caniuse-lite": "^1.0.30001782",
|
||||||
@@ -6399,7 +6410,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||||
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -6594,8 +6604,7 @@
|
|||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz",
|
||||||
"integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==",
|
"integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/clean-regexp": {
|
"node_modules/clean-regexp": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -6671,17 +6680,6 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/commander": {
|
|
||||||
"version": "10.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
|
||||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/comment-parser": {
|
"node_modules/comment-parser": {
|
||||||
"version": "1.4.6",
|
"version": "1.4.6",
|
||||||
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
|
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
|
||||||
@@ -7449,6 +7447,16 @@
|
|||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/editorconfig/node_modules/commander": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/editorconfig/node_modules/minimatch": {
|
"node_modules/editorconfig/node_modules/minimatch": {
|
||||||
"version": "9.0.9",
|
"version": "9.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||||
@@ -7649,7 +7657,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
|
||||||
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
|
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -8808,7 +8815,6 @@
|
|||||||
"integrity": "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==",
|
"integrity": "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": ">=20.0.0",
|
"@types/node": ">=20.0.0",
|
||||||
"@types/whatwg-mimetype": "^3.0.2",
|
"@types/whatwg-mimetype": "^3.0.2",
|
||||||
@@ -11199,7 +11205,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.4.2.tgz",
|
||||||
"integrity": "sha512-iWVFpr/YEqVU/CenqIHMnIkvb2HE/9f+q8oxZ+pj2et+60NljGRClCgnmbvGPdmNFE0F1bEhoBCYfqbDOCim3Q==",
|
"integrity": "sha512-iWVFpr/YEqVU/CenqIHMnIkvb2HE/9f+q8oxZ+pj2et+60NljGRClCgnmbvGPdmNFE0F1bEhoBCYfqbDOCim3Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dxup/nuxt": "^0.4.0",
|
"@dxup/nuxt": "^0.4.0",
|
||||||
"@nuxt/cli": "^3.34.0",
|
"@nuxt/cli": "^3.34.0",
|
||||||
@@ -12258,7 +12263,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deep-is": "^0.1.3",
|
"deep-is": "^0.1.3",
|
||||||
"fast-levenshtein": "^2.0.6",
|
"fast-levenshtein": "^2.0.6",
|
||||||
@@ -12310,7 +12314,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.112.0.tgz",
|
"resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.112.0.tgz",
|
||||||
"integrity": "sha512-7rQ3QdJwobMQLMZwQaPuPYMEF2fDRZwf51lZ//V+bA37nejjKW5ifMHbbCwvA889Y4RLhT+/wLJpPRhAoBaZYw==",
|
"integrity": "sha512-7rQ3QdJwobMQLMZwQaPuPYMEF2fDRZwf51lZ//V+bA37nejjKW5ifMHbbCwvA889Y4RLhT+/wLJpPRhAoBaZYw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oxc-project/types": "^0.112.0"
|
"@oxc-project/types": "^0.112.0"
|
||||||
},
|
},
|
||||||
@@ -12577,7 +12580,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz",
|
||||||
"integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==",
|
"integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/devtools-api": "^7.7.7"
|
"@vue/devtools-api": "^7.7.7"
|
||||||
},
|
},
|
||||||
@@ -12656,7 +12658,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.11",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@@ -13200,7 +13201,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
|
||||||
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
|
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
"util-deprecate": "^1.0.2"
|
"util-deprecate": "^1.0.2"
|
||||||
@@ -13820,7 +13820,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
|
||||||
"integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
|
"integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.8"
|
"@types/estree": "1.0.8"
|
||||||
},
|
},
|
||||||
@@ -14718,7 +14717,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
|
||||||
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
|
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alloc/quick-lru": "^5.2.0",
|
"@alloc/quick-lru": "^5.2.0",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
@@ -15374,7 +15372,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"napi-postinstall": "^0.3.0"
|
"napi-postinstall": "^0.3.0"
|
||||||
},
|
},
|
||||||
@@ -15641,7 +15638,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
|
||||||
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
|
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -16560,7 +16556,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz",
|
||||||
"integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==",
|
"integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.32",
|
"@vue/compiler-dom": "3.5.32",
|
||||||
"@vue/compiler-sfc": "3.5.32",
|
"@vue/compiler-sfc": "3.5.32",
|
||||||
@@ -16605,7 +16600,6 @@
|
|||||||
"integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
|
"integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"eslint-scope": "^8.2.0 || ^9.0.0",
|
"eslint-scope": "^8.2.0 || ^9.0.0",
|
||||||
@@ -16642,7 +16636,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.3.1.tgz",
|
||||||
"integrity": "sha512-azq8fhVnCwJAw0iXW7i44h9P+Bj+snNuevBAaJ9bxn0I3YVsRU3deVFPNnTfZ2uxVJefGp83JUmL68ddCPw5Pw==",
|
"integrity": "sha512-azq8fhVnCwJAw0iXW7i44h9P+Bj+snNuevBAaJ9bxn0I3YVsRU3deVFPNnTfZ2uxVJefGp83JUmL68ddCPw5Pw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/core-base": "11.3.1",
|
"@intlify/core-base": "11.3.1",
|
||||||
"@intlify/devtools-types": "11.3.1",
|
"@intlify/devtools-types": "11.3.1",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"test:watch": "vitest"
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@malio/layer-ui": "^1.2.3",
|
"@malio/layer-ui": "^1.3.0",
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/i18n": "^10.2.3",
|
"@nuxtjs/i18n": "^10.2.3",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user