From 7dec8fbaff3ea0afcc8d6d157dc4652e1b7f4606 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:51:15 +0100 Subject: [PATCH] Add embedded Swagger UI page with auto-injected JWT auth - New /swagger route with lazy-loaded SwaggerPage that initializes swagger-ui-dist and injects the session JWT via requestInterceptor - Move API link from primary nav to navRight utility area (pill style) - Code-split swagger chunk (~1.4 MB) so main bundle stays lean Co-Authored-By: Claude Opus 4.6 (1M context) --- ui/package-lock.json | 17 ++++++++++++ ui/package.json | 1 + ui/src/components/layout/TopNav.module.css | 24 +++++++++++++++++ ui/src/components/layout/TopNav.tsx | 8 +++--- ui/src/pages/swagger/SwaggerPage.module.css | 5 ++++ ui/src/pages/swagger/SwaggerPage.tsx | 29 +++++++++++++++++++++ ui/src/router.tsx | 4 +++ ui/src/swagger-ui-dist.d.ts | 10 +++++++ 8 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 ui/src/pages/swagger/SwaggerPage.module.css create mode 100644 ui/src/pages/swagger/SwaggerPage.tsx create mode 100644 ui/src/swagger-ui-dist.d.ts diff --git a/ui/package-lock.json b/ui/package-lock.json index 66bac5fb..66ae4b88 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -14,6 +14,7 @@ "react": "^19.2.4", "react-dom": "^19.2.4", "react-router": "^7.13.1", + "swagger-ui-dist": "^5.32.0", "uplot": "^1.6.32", "zustand": "^5.0.11" }, @@ -941,6 +942,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, "node_modules/@tanstack/query-core": { "version": "5.90.20", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz", @@ -3027,6 +3035,15 @@ "node": ">=8" } }, + "node_modules/swagger-ui-dist": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.0.tgz", + "integrity": "sha512-nKZB0OuDvacB0s/lC2gbge+RigYvGRGpLLMWMFxaTUwfM+CfndVk9Th2IaTinqXiz6Mn26GK2zriCpv6/+5m3Q==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", diff --git a/ui/package.json b/ui/package.json index 5841cc02..96718422 100644 --- a/ui/package.json +++ b/ui/package.json @@ -18,6 +18,7 @@ "react": "^19.2.4", "react-dom": "^19.2.4", "react-router": "^7.13.1", + "swagger-ui-dist": "^5.32.0", "uplot": "^1.6.32", "zustand": "^5.0.11" }, diff --git a/ui/src/components/layout/TopNav.module.css b/ui/src/components/layout/TopNav.module.css index cac7dd1f..d87c9cb0 100644 --- a/ui/src/components/layout/TopNav.module.css +++ b/ui/src/components/layout/TopNav.module.css @@ -61,6 +61,30 @@ gap: 16px; } +.utilLink { + font-family: var(--font-mono); + font-size: 11px; + font-weight: 500; + color: var(--text-muted); + text-decoration: none; + padding: 4px 10px; + border-radius: 99px; + border: 1px solid var(--border); + transition: all 0.15s; +} + +.utilLink:hover { + color: var(--text-primary); + border-color: var(--text-muted); +} + +.utilLinkActive { + composes: utilLink; + color: var(--amber); + border-color: rgba(245, 158, 11, 0.3); + background: var(--amber-glow); +} + .envBadge { font-family: var(--font-mono); font-size: 11px; diff --git a/ui/src/components/layout/TopNav.tsx b/ui/src/components/layout/TopNav.tsx index e2e86d94..89f27dfa 100644 --- a/ui/src/components/layout/TopNav.tsx +++ b/ui/src/components/layout/TopNav.tsx @@ -28,11 +28,6 @@ export function TopNav() { Applications -
  • - - API - -
  • {roles.includes('ADMIN') && (
  • isActive ? styles.navLinkActive : styles.navLink}> @@ -43,6 +38,9 @@ export function TopNav() {
    + isActive ? styles.utilLinkActive : styles.utilLink} title="API Documentation"> + API + {import.meta.env.VITE_ENV_NAME || 'DEV'}