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:
Matthieu
2026-04-16 10:45:21 +02:00
parent 580ea01941
commit d49c317c49
9 changed files with 70 additions and 103 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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') })

View File

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

View 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[]
}