From f3e87186609680cdc90deb07b6f045347fae8d61 Mon Sep 17 00:00:00 2001 From: 9qeklajc <9qeklajc> Date: Fri, 24 Oct 2025 15:55:48 +0200 Subject: [PATCH] fix icon --- routstr/core/main.py | 31 +++++++++++++++++++++---------- ui/.gitignore | 3 +++ ui/app/layout.tsx | 3 +++ ui/components/app-sidebar.tsx | 12 +++++++++++- ui/public/icon.ico | Bin 0 -> 15406 bytes 5 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 ui/public/icon.ico diff --git a/routstr/core/main.py b/routstr/core/main.py index f900e541..9ffba19a 100644 --- a/routstr/core/main.py +++ b/routstr/core/main.py @@ -192,48 +192,59 @@ UI_DIST_PATH = Path(__file__).parent.parent.parent / "ui" / "out" if UI_DIST_PATH.exists() and UI_DIST_PATH.is_dir(): logger.info(f"Serving static UI from {UI_DIST_PATH}") - + app.mount("/_next", StaticFiles(directory=UI_DIST_PATH / "_next", check_dir=True), name="next-static") - + @app.get("/", include_in_schema=False) async def serve_root_ui() -> FileResponse: return FileResponse(UI_DIST_PATH / "index.html") - + @app.get("/dashboard", include_in_schema=False) @app.get("/dashboard/{path:path}", include_in_schema=False) async def serve_dashboard_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "index.html") - + @app.get("/login", include_in_schema=False) @app.get("/login/{path:path}", include_in_schema=False) async def serve_login_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "login" / "index.html") - + @app.get("/models", include_in_schema=False) @app.get("/models/{path:path}", include_in_schema=False) async def serve_models_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "models" / "index.html") - + @app.get("/providers", include_in_schema=False) @app.get("/providers/{path:path}", include_in_schema=False) async def serve_providers_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "providers" / "index.html") - + @app.get("/settings", include_in_schema=False) @app.get("/settings/{path:path}", include_in_schema=False) async def serve_settings_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "settings" / "index.html") - + @app.get("/transactions", include_in_schema=False) @app.get("/transactions/{path:path}", include_in_schema=False) async def serve_transactions_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "transactions" / "index.html") - + @app.get("/unauthorized", include_in_schema=False) @app.get("/unauthorized/{path:path}", include_in_schema=False) async def serve_unauthorized_ui(path: str = "") -> FileResponse: return FileResponse(UI_DIST_PATH / "unauthorized" / "index.html") - + + @app.get("/favicon.ico", include_in_schema=False) + async def serve_favicon() -> FileResponse: + icon_path = UI_DIST_PATH / "icon.ico" + if icon_path.exists(): + return FileResponse(icon_path) + return FileResponse(UI_DIST_PATH / "favicon.ico") + + @app.get("/icon.ico", include_in_schema=False) + async def serve_icon() -> FileResponse: + return FileResponse(UI_DIST_PATH / "icon.ico") + app.mount("/static", StaticFiles(directory=UI_DIST_PATH, check_dir=True), name="ui-static") else: logger.warning(f"UI dist directory not found at {UI_DIST_PATH}, skipping static file serving") diff --git a/ui/.gitignore b/ui/.gitignore index 01435d73..80cef375 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -38,3 +38,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# favicon conflicts +/app/favicon.ico diff --git a/ui/app/layout.tsx b/ui/app/layout.tsx index a20063b3..6f388724 100644 --- a/ui/app/layout.tsx +++ b/ui/app/layout.tsx @@ -16,6 +16,9 @@ const geistMono = Geist_Mono({ export const metadata: Metadata = { title: 'Routstr', description: 'Routstr model management', + icons: { + icon: '/icon.ico', + }, }; export default function RootLayout({ diff --git a/ui/components/app-sidebar.tsx b/ui/components/app-sidebar.tsx index 4a11c709..a8af2e9f 100644 --- a/ui/components/app-sidebar.tsx +++ b/ui/components/app-sidebar.tsx @@ -7,6 +7,7 @@ import { ServerIcon, SettingsIcon, } from 'lucide-react'; +import Image from 'next/image'; import { NavSecondary } from '@/components/nav-secondary'; import { @@ -82,7 +83,16 @@ export function AppSidebar({ ...props }: React.ComponentProps) { asChild className='data-[slot=sidebar-menu-button]:!p-1.5' > - Routstr +
+ Routstr + Routstr +
diff --git a/ui/public/icon.ico b/ui/public/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c4591ac495f46b175370b9591e9e8aa4195424dd GIT binary patch literal 15406 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