fix(frontend) : ERP-26/27 - review fixes: shared types, accents i18n, escape key, self-edit refresh, row-clickable guard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
"suppliers": "Répertoire fournisseurs"
|
"suppliers": "Répertoire fournisseurs"
|
||||||
},
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"roles": "Gestion des roles",
|
"roles": "Gestion des rôles",
|
||||||
"users": "Utilisateurs"
|
"users": "Utilisateurs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -63,33 +63,33 @@
|
|||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"roles": {
|
"roles": {
|
||||||
"title": "Gestion des roles",
|
"title": "Gestion des rôles",
|
||||||
"newRole": "Nouveau role",
|
"newRole": "Nouveau rôle",
|
||||||
"editRole": "Modifier le role",
|
"editRole": "Modifier le rôle",
|
||||||
"createRole": "Creer un role",
|
"createRole": "Créer un rôle",
|
||||||
"noRoles": "Aucun role configure",
|
"noRoles": "Aucun rôle configuré",
|
||||||
"table": {
|
"table": {
|
||||||
"label": "Libelle",
|
"label": "Libellé",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
"permissions": "Permissions",
|
"permissions": "Permissions",
|
||||||
"system": "Systeme",
|
"system": "Système",
|
||||||
"actions": "Actions"
|
"actions": "Actions"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"label": "Libelle",
|
"label": "Libellé",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"permissions": "Permissions"
|
"permissions": "Permissions"
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"title": "Supprimer le role",
|
"title": "Supprimer le rôle",
|
||||||
"message": "Etes-vous sur de vouloir supprimer le role \"{label}\" ? Cette action est irreversible.",
|
"message": "Êtes-vous sûr de vouloir supprimer le rôle \"{label}\" ? Cette action est irréversible.",
|
||||||
"systemTooltip": "Role systeme non supprimable"
|
"systemTooltip": "Rôle système non supprimable"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"created": "Role cree avec succes",
|
"created": "Rôle créé avec succès",
|
||||||
"updated": "Role mis a jour avec succes",
|
"updated": "Rôle mis à jour avec succès",
|
||||||
"deleted": "Role supprime avec succes"
|
"deleted": "Rôle supprimé avec succès"
|
||||||
},
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"selectAll": "Tout selectionner",
|
"selectAll": "Tout selectionner",
|
||||||
@@ -110,16 +110,16 @@
|
|||||||
"title": "Permissions de {username}",
|
"title": "Permissions de {username}",
|
||||||
"selfWarning": "Vous modifiez vos propres droits",
|
"selfWarning": "Vous modifiez vos propres droits",
|
||||||
"adminToggle": "Administrateur (bypass total)",
|
"adminToggle": "Administrateur (bypass total)",
|
||||||
"rolesSection": "Roles",
|
"rolesSection": "Rôles",
|
||||||
"directPermissionsSection": "Permissions directes",
|
"directPermissionsSection": "Permissions directes",
|
||||||
"summarySection": "Resume des permissions effectives",
|
"summarySection": "Résumé des permissions effectives",
|
||||||
"noEffectivePermissions": "Aucune permission effective",
|
"noEffectivePermissions": "Aucune permission effective",
|
||||||
"sourceRole": "via {role}",
|
"sourceRole": "via {role}",
|
||||||
"sourceDirect": "Direct",
|
"sourceDirect": "Direct",
|
||||||
"lastAdminWarning": "Impossible de retirer le statut administrateur du dernier admin"
|
"lastAdminWarning": "Impossible de retirer le statut administrateur du dernier admin"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"updated": "Permissions mises a jour avec succes"
|
"updated": "Permissions mises à jour avec succès"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,14 +40,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { t } = useI18n()
|
import type { EffectivePermission } from '~/shared/types/rbac'
|
||||||
|
|
||||||
interface EffectivePermission {
|
const { t } = useI18n()
|
||||||
code: string
|
|
||||||
label: string
|
|
||||||
module: string
|
|
||||||
sources: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
permissions: EffectivePermission[]
|
permissions: EffectivePermission[]
|
||||||
|
|||||||
@@ -30,13 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Permission {
|
import type { Permission } from '~/shared/types/rbac'
|
||||||
id: number
|
|
||||||
code: string
|
|
||||||
label: string
|
|
||||||
module: string
|
|
||||||
orphan: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
module: string
|
module: string
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ function cancel() {
|
|||||||
function confirm() {
|
function confirm() {
|
||||||
emit('confirm')
|
emit('confirm')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fermer la modale avec la touche Escape
|
||||||
|
function onKeydown(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'Escape') cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => document.addEventListener('keydown', onKeydown))
|
||||||
|
onUnmounted(() => document.removeEventListener('keydown', onKeydown))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -70,22 +70,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Permission {
|
import type { Permission, Role } from '~/shared/types/rbac'
|
||||||
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 {
|
interface PermissionModule {
|
||||||
module: string
|
module: string
|
||||||
|
|||||||
@@ -91,37 +91,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Permission {
|
import type { Permission, Role, UserListItem, EffectivePermission } from '~/shared/types/rbac'
|
||||||
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 UserListItem {
|
|
||||||
id: number
|
|
||||||
username: string
|
|
||||||
isAdmin: boolean
|
|
||||||
roles: string[]
|
|
||||||
directPermissions: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EffectivePermission {
|
|
||||||
code: string
|
|
||||||
label: string
|
|
||||||
module: string
|
|
||||||
sources: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PermissionModule {
|
interface PermissionModule {
|
||||||
module: string
|
module: string
|
||||||
@@ -276,6 +246,10 @@ async function handleSave() {
|
|||||||
}, {
|
}, {
|
||||||
toastSuccessMessage: t('admin.users.toast.updated'),
|
toastSuccessMessage: t('admin.users.toast.updated'),
|
||||||
})
|
})
|
||||||
|
// Rafraichir les donnees du user courant si auto-edition
|
||||||
|
if (isSelfEdit.value) {
|
||||||
|
await auth.refreshUser()
|
||||||
|
}
|
||||||
emit('saved')
|
emit('saved')
|
||||||
emit('update:modelValue', false)
|
emit('update:modelValue', false)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:items="roleItems"
|
:items="roleItems"
|
||||||
:total-items="roles.length"
|
:total-items="roles.length"
|
||||||
:row-clickable="true"
|
:row-clickable="canManage"
|
||||||
:empty-message="t('admin.roles.noRoles')"
|
:empty-message="t('admin.roles.noRoles')"
|
||||||
@row-click="onRowClick"
|
@row-click="onRowClick"
|
||||||
>
|
>
|
||||||
@@ -76,26 +76,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Permission {
|
import type { Role } from '~/shared/types/rbac'
|
||||||
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 { t } = useI18n()
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
const { can } = usePermissions()
|
const { can } = usePermissions()
|
||||||
|
const canManage = can('core.roles.manage')
|
||||||
|
|
||||||
useHead({ title: t('admin.roles.title') })
|
useHead({ title: t('admin.roles.title') })
|
||||||
|
|
||||||
|
|||||||
@@ -48,13 +48,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface UserListItem {
|
import type { UserListItem } from '~/shared/types/rbac'
|
||||||
id: number
|
|
||||||
username: string
|
|
||||||
isAdmin: boolean
|
|
||||||
roles: string[]
|
|
||||||
directPermissions: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|||||||
31
frontend/shared/types/rbac.ts
Normal file
31
frontend/shared/types/rbac.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
export interface Permission {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
module: string
|
||||||
|
orphan: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Role {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
description: string | null
|
||||||
|
isSystem: boolean
|
||||||
|
permissions: (Permission | string)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserListItem {
|
||||||
|
id: number
|
||||||
|
username: string
|
||||||
|
isAdmin: boolean
|
||||||
|
roles: string[]
|
||||||
|
directPermissions: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EffectivePermission {
|
||||||
|
code: string
|
||||||
|
label: string
|
||||||
|
module: string
|
||||||
|
sources: string[]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user