diff --git a/clarity.controlplane/package-lock.json b/clarity.controlplane/package-lock.json
index a9a13ef..e973ec6 100644
--- a/clarity.controlplane/package-lock.json
+++ b/clarity.controlplane/package-lock.json
@@ -13,7 +13,8 @@
"highlight.js": "^11.11.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-multistep": "^7.0.0"
+ "react-multistep": "^7.0.0",
+ "react-router-dom": "^7.14.2"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
@@ -1710,6 +1711,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3043,6 +3057,44 @@
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
+ "node_modules/react-router": {
+ "version": "7.14.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.2.tgz",
+ "integrity": "sha512-yCqNne6I8IB6rVCH7XUvlBK7/QKyqypBFGv+8dj4QBFJiiRX+FG7/nkdAvGElyvVZ/HQP5N19wzteuTARXi5Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.14.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.14.2.tgz",
+ "integrity": "sha512-YZcM5ES8jJSM+KrJ9BdvHHqlnGTg5tH3sC5ChFRj4inosKctdyzBDhOyyHdGk597q2OT6NTrCA1OvB/YDwfekQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.14.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -3140,6 +3192,12 @@
"upper-case-first": "^2.0.2"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/clarity.controlplane/package.json b/clarity.controlplane/package.json
index d1d8d2d..34762ce 100644
--- a/clarity.controlplane/package.json
+++ b/clarity.controlplane/package.json
@@ -15,7 +15,8 @@
"highlight.js": "^11.11.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-multistep": "^7.0.0"
+ "react-multistep": "^7.0.0",
+ "react-router-dom": "^7.14.2"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
diff --git a/clarity.controlplane/src/App.tsx b/clarity.controlplane/src/App.tsx
index 90717f8..3e9cf7e 100644
--- a/clarity.controlplane/src/App.tsx
+++ b/clarity.controlplane/src/App.tsx
@@ -1,6 +1,6 @@
import '@blueprintjs/core/lib/css/blueprint.css';
import './App.css';
-import { useState } from 'react';
+import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
import DashboardPage from './pages/DashboardPage';
import PipelinesPage from './pages/PipelinesPage';
@@ -11,59 +11,44 @@ import OpcPage from './opc/OpcPage';
import InfraPage from './pages/InfraPage';
import ChangesetsPage from './pages/ChangesetsPage';
-function App() {
- const [activeNav, setActiveNav] = useState('opc');
+function Sidebar() {
+ const navigate = useNavigate();
+ const { pathname } = useLocation();
+ const at = (path: string) => pathname === path || pathname.startsWith(path + '/');
return (
-
- {/* ── Sidebar ── */}
-