fix: add missing onError handlers on RBAC mutations

- deleteMutation onError in AdminRoles and AdminPolicies
- revokeMutation onError in AdminRoleAssign
- handleExport error handling in AdminAuditLog
- add missing i18n keys: deleteFailed, revokeFailed, exportError
This commit is contained in:
Fringg
2026-02-25 03:17:12 +03:00
parent 874ee2682e
commit c4e3211baa
8 changed files with 60 additions and 23 deletions

View File

@@ -2990,7 +2990,8 @@
"loadFailed": "Failed to load roles",
"createFailed": "Failed to create role",
"updateFailed": "Failed to update role",
"nameRequired": "Role name is required"
"nameRequired": "Role name is required",
"deleteFailed": "Failed to delete role"
}
},
"roleAssign": {
@@ -3041,7 +3042,8 @@
"errors": {
"userRequired": "Please select a user",
"roleRequired": "Please select a role",
"assignFailed": "Failed to assign role"
"assignFailed": "Failed to assign role",
"revokeFailed": "Failed to revoke role"
}
},
"policies": {
@@ -3117,7 +3119,8 @@
"updateFailed": "Failed to update policy",
"nameRequired": "Policy name is required",
"resourceRequired": "Please select a resource",
"actionsRequired": "Please select at least one action"
"actionsRequired": "Please select at least one action",
"deleteFailed": "Failed to delete policy"
}
},
"auditLog": {
@@ -3125,6 +3128,7 @@
"subtitle": "Review system activity and access history",
"back": "Back",
"exportCsv": "Export CSV",
"exportError": "Failed to export",
"exporting": "Exporting...",
"refresh": "Refresh",
"unknownUser": "Unknown user",

View File

@@ -2850,7 +2850,8 @@
"loadFailed": "بارگذاری نقش‌ها ناموفق بود",
"createFailed": "ایجاد نقش ناموفق بود",
"updateFailed": "به‌روزرسانی نقش ناموفق بود",
"nameRequired": "نام نقش الزامی است"
"nameRequired": "نام نقش الزامی است",
"deleteFailed": "حذف نقش ناموفق بود"
}
},
"roleAssign": {
@@ -2900,7 +2901,8 @@
"errors": {
"userRequired": "لطفاً یک کاربر انتخاب کنید",
"roleRequired": "لطفاً یک نقش انتخاب کنید",
"assignFailed": "تخصیص نقش ناموفق بود"
"assignFailed": "تخصیص نقش ناموفق بود",
"revokeFailed": "لغو نقش ناموفق بود"
}
},
"policies": {
@@ -2975,7 +2977,8 @@
"updateFailed": "به‌روزرسانی سیاست ناموفق بود",
"nameRequired": "نام سیاست الزامی است",
"resourceRequired": "لطفاً یک منبع انتخاب کنید",
"actionsRequired": "لطفاً حداقل یک عملیات انتخاب کنید"
"actionsRequired": "لطفاً حداقل یک عملیات انتخاب کنید",
"deleteFailed": "حذف سیاست ناموفق بود"
}
},
"auditLog": {
@@ -2983,6 +2986,7 @@
"subtitle": "بررسی فعالیت سیستم و تاریخچه دسترسی",
"back": "بازگشت",
"exportCsv": "خروجی CSV",
"exportError": "خطا در خروجی",
"exporting": "در حال خروجی...",
"refresh": "بازخوانی",
"unknownUser": "کاربر ناشناخته",

View File

@@ -3545,7 +3545,8 @@
"loadFailed": "Не удалось загрузить роли",
"createFailed": "Не удалось создать роль",
"updateFailed": "Не удалось обновить роль",
"nameRequired": "Укажите название роли"
"nameRequired": "Укажите название роли",
"deleteFailed": "Не удалось удалить роль"
}
},
"roleAssign": {
@@ -3597,7 +3598,8 @@
"errors": {
"userRequired": "Выберите пользователя",
"roleRequired": "Выберите роль",
"assignFailed": "Не удалось назначить роль"
"assignFailed": "Не удалось назначить роль",
"revokeFailed": "Не удалось отозвать роль"
}
},
"policies": {
@@ -3674,7 +3676,8 @@
"updateFailed": "Не удалось обновить политику",
"nameRequired": "Укажите название политики",
"resourceRequired": "Выберите ресурс",
"actionsRequired": "Выберите хотя бы одно действие"
"actionsRequired": "Выберите хотя бы одно действие",
"deleteFailed": "Не удалось удалить политику"
}
},
"auditLog": {
@@ -3682,6 +3685,7 @@
"subtitle": "Просмотр активности системы и истории доступа",
"back": "Назад",
"exportCsv": "Экспорт CSV",
"exportError": "Ошибка экспорта",
"exporting": "Экспорт...",
"refresh": "Обновить",
"unknownUser": "Неизвестный пользователь",

View File

@@ -2876,7 +2876,8 @@
"loadFailed": "加载角色失败",
"createFailed": "创建角色失败",
"updateFailed": "更新角色失败",
"nameRequired": "请输入角色名称"
"nameRequired": "请输入角色名称",
"deleteFailed": "删除角色失败"
}
},
"roleAssign": {
@@ -2926,7 +2927,8 @@
"errors": {
"userRequired": "请选择用户",
"roleRequired": "请选择角色",
"assignFailed": "角色分配失败"
"assignFailed": "角色分配失败",
"revokeFailed": "角色撤销失败"
}
},
"policies": {
@@ -3001,7 +3003,8 @@
"updateFailed": "更新策略失败",
"nameRequired": "请输入策略名称",
"resourceRequired": "请选择资源",
"actionsRequired": "请至少选择一个操作"
"actionsRequired": "请至少选择一个操作",
"deleteFailed": "删除策略失败"
}
},
"auditLog": {
@@ -3009,6 +3012,7 @@
"subtitle": "查看系统活动和访问历史",
"back": "返回",
"exportCsv": "导出CSV",
"exportError": "导出失败",
"exporting": "导出中...",
"refresh": "刷新",
"unknownUser": "未知用户",

View File

@@ -381,6 +381,7 @@ export default function AdminAuditLog() {
const [expandedIds, setExpandedIds] = useState<Set<number>>(new Set());
const [autoRefresh, setAutoRefresh] = useState(false);
const [exporting, setExporting] = useState(false);
const [exportError, setExportError] = useState<string | null>(null);
// Auto-refresh interval ref
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
@@ -479,10 +480,12 @@ export default function AdminAuditLog() {
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch {
setExportError(t('admin.auditLog.exportError'));
} finally {
setExporting(false);
}
}, [appliedFilters]);
}, [appliedFilters, t]);
const handlePageSizeChange = useCallback((newSize: number) => {
setPageSize(newSize);
@@ -552,16 +555,22 @@ export default function AdminAuditLog() {
{/* Export */}
<PermissionGate permission="audit_log:export">
<button
onClick={handleExport}
disabled={exporting}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
>
<DownloadIcon />
<span className="hidden sm:inline">
{exporting ? t('admin.auditLog.exporting') : t('admin.auditLog.exportCsv')}
</span>
</button>
<div className="flex items-center gap-2">
{exportError && <p className="text-sm text-error-400">{exportError}</p>}
<button
onClick={() => {
setExportError(null);
handleExport();
}}
disabled={exporting}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
>
<DownloadIcon />
<span className="hidden sm:inline">
{exporting ? t('admin.auditLog.exporting') : t('admin.auditLog.exportCsv')}
</span>
</button>
</div>
</PermissionGate>
</div>
</div>

View File

@@ -379,6 +379,10 @@ export default function AdminPolicies() {
queryClient.invalidateQueries({ queryKey: ['admin-policies'] });
setDeleteConfirm(null);
},
onError: () => {
setDeleteConfirm(null);
setFormError(t('admin.policies.errors.deleteFailed'));
},
});
// Derived data

View File

@@ -330,6 +330,10 @@ export default function AdminRoleAssign() {
queryClient.invalidateQueries({ queryKey: ['admin-roles'] });
setRevokeConfirm(null);
},
onError: () => {
setRevokeConfirm(null);
setFormError(t('admin.roleAssign.errors.revokeFailed'));
},
});
// Handlers

View File

@@ -350,6 +350,10 @@ export default function AdminRoles() {
queryClient.invalidateQueries({ queryKey: ['admin-roles'] });
setDeleteConfirm(null);
},
onError: () => {
setDeleteConfirm(null);
setFormError(t('admin.roles.errors.deleteFailed'));
},
});
// Handlers