From 898c619c0d8cc02c49b5dba33eba26c1eef65356 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Wed, 13 Aug 2025 21:18:14 +0000 Subject: [PATCH] Organize backup, NocoDB, and database debug tools into a single utilities menu Consolidate backup, NocoDB configuration, and database debug functionalities into a new "Utilities" section, accessible via tabs within a single page. This refactors routing to redirect previous paths to the new utilities page and updates the sidebar navigation accordingly. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7c468936-2a88-4686-ac0a-84921a45222d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/7c468936-2a88-4686-ac0a-84921a45222d/XNPzpuo --- attached_assets/image_1755119737827.png | Bin 0 -> 11107 bytes client/src/components/RouterProduction.tsx | 11 +- client/src/components/Sidebar.tsx | 21 +--- client/src/pages/Utilities.tsx | 121 +++++++++++++++++++++ 4 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 attached_assets/image_1755119737827.png create mode 100644 client/src/pages/Utilities.tsx diff --git a/attached_assets/image_1755119737827.png b/attached_assets/image_1755119737827.png new file mode 100644 index 0000000000000000000000000000000000000000..78633b02d1d39660dccedaf0528301c5badde26c GIT binary patch literal 11107 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 YDyG - + - - + + {/* Routes de compatibilité - redirection vers utilities */} + + + + diff --git a/client/src/components/Sidebar.tsx b/client/src/components/Sidebar.tsx index 0675126..516881e 100644 --- a/client/src/components/Sidebar.tsx +++ b/client/src/components/Sidebar.tsx @@ -21,7 +21,8 @@ import { ListTodo, ChevronLeft, ChevronRight, - X + X, + Settings } from "lucide-react"; export default function Sidebar() { @@ -147,21 +148,9 @@ export default function Sidebar() { roles: ["admin"] }, { - path: "/backup", - label: "Sauvegardes", - icon: Database, - roles: ["admin"] - }, - { - path: "/nocodb-config", - label: "Configuration NocoDB", - icon: Database, - roles: ["admin"] - }, - { - path: "/database-debug", - label: "Debug Base de Données", - icon: Database, + path: "/utilities", + label: "Utilitaires", + icon: Settings, roles: ["admin"] }, ]; diff --git a/client/src/pages/Utilities.tsx b/client/src/pages/Utilities.tsx new file mode 100644 index 0000000..3b9cc19 --- /dev/null +++ b/client/src/pages/Utilities.tsx @@ -0,0 +1,121 @@ +import { useState } from "react"; +import { useAuthUnified } from "@/hooks/useAuthUnified"; +import { hasPermission } from "@/lib/permissions"; +import { + Settings, + Database, + Server, + Bug +} from "lucide-react"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { AlertTriangle } from "lucide-react"; + +// Import des composants existants +import BackupManager from "./BackupManager"; +import NocoDBConfig from "./NocoDBConfig"; +import DatabaseDebug from "./DatabaseDebug"; + +export default function Utilities() { + const { user } = useAuthUnified(); + // Détecter l'onglet actif basé sur l'URL pour la compatibilité + const [activeTab, setActiveTab] = useState(() => { + const path = window.location.pathname; + if (path === '/backup') return 'backups'; + if (path === '/nocodb-config') return 'nocodb'; + if (path === '/database-debug') return 'debug'; + return 'backups'; + }); + + // Vérification des permissions pour chaque onglet + const canManageBackups = hasPermission(user?.role || '', 'backups', 'manage'); + const canManageNocoDB = user?.role === 'admin'; + const canDebugDatabase = user?.role === 'admin'; + + // Si l'utilisateur n'a aucune permission, afficher le message d'accès refusé + if (!canManageBackups && !canManageNocoDB && !canDebugDatabase) { + return ( +
+ + + + Accès refusé + + Vous n'avez pas les permissions nécessaires pour accéder aux utilitaires d'administration. + + + +
+ ); + } + + return ( +
+ {/* Header */} +
+
+ +
+

+ Utilitaires d'Administration +

+

+ Outils de gestion et de maintenance du système +

+
+
+
+ + {/* Content avec onglets */} +
+ + + {canManageBackups && ( + + + Sauvegardes + + )} + {canManageNocoDB && ( + + + Configuration NocoDB + + )} + {canDebugDatabase && ( + + + Debug Base de Données + + )} + + + {/* Contenu des onglets */} + {canManageBackups && ( + +
+ +
+
+ )} + + {canManageNocoDB && ( + +
+ +
+
+ )} + + {canDebugDatabase && ( + +
+ +
+
+ )} +
+
+
+ ); +} \ No newline at end of file