diff --git a/backend/__pycache__/main.cpython-313.pyc b/backend/__pycache__/main.cpython-313.pyc index 9e29e14..ac9fb77 100644 Binary files a/backend/__pycache__/main.cpython-313.pyc and b/backend/__pycache__/main.cpython-313.pyc differ diff --git a/backend/apps.yaml b/backend/apps.yaml index a8c6297..d21a950 100644 --- a/backend/apps.yaml +++ b/backend/apps.yaml @@ -1,24 +1,26 @@ -- name: Gitea - url: https://git.dvirlabs.com - icon: http://192.168.10.118:1111/icons/gitea.svg - description: Git server +sections: +- apps: + - description: Dashboards + icon: http://192.168.10.118:1111/icons/grafana.svg + name: Grafana + url: https://grafana.dvirlabs.com + - description: Monitoring + icon: http://192.168.10.118:1111/icons/prometheus.svg + name: Prometheus + url: https://prometheus.dvirlabs.com + name: Monitoring +- apps: + - description: Git server + icon: http://192.168.10.118:1111/icons/gitea.svg + name: Gitea + url: https://git.dvirlabs.com + - description: Container registry + icon: http://192.168.10.118:1111/icons/harbor.svg + name: Harbor + url: https://harbor.dvirlabs.com + - description: CI/CD + icon: http://192.168.10.118:1111/icons/woodpecker-ci.svg + name: Woodpecker + url: https://woodpecker.dvirlabs.com + name: Dev-tools -- name: Grafana - url: https://grafana.dvirlabs.com - icon: http://192.168.10.118:1111/icons/grafana.svg - description: Dashboards - -- name: Prometheus - url: https://prometheus.dvirlabs.com - icon: http://192.168.10.118:1111/icons/prometheus.svg - description: Monitoring - -- name: Harbor - url: https://harbor.dvirlabs.com - icon: http://192.168.10.118:1111/icons/harbor.svg - description: Container registry - -- name: Woodpecker - url: https://woodpecker.dvirlabs.com - icon: http://192.168.10.118:1111/icons/woodpecker-ci.svg - description: CI/CD \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 47f1e4f..d211f90 100644 --- a/backend/main.py +++ b/backend/main.py @@ -2,6 +2,8 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware import yaml from pathlib import Path +from pydantic import BaseModel + app = FastAPI() # Allow CORS for all origins @@ -26,6 +28,47 @@ def get_apps(): return {"error": "apps.yaml not found"} with open(APPS_FILE, "r") as f: return yaml.safe_load(f) + +class AppEntry(BaseModel): + section: str + name: str + icon: str + description: str + url: str + +@app.post("/add_app") +def add_app(entry: AppEntry): + if not APPS_FILE.exists(): + current = {"sections": []} + else: + with open(APPS_FILE, "r") as f: + current = yaml.safe_load(f) or {"sections": []} + + # Find or create section + for section in current["sections"]: + if section["name"] == entry.section: + section["apps"].append({ + "name": entry.name, + "icon": entry.icon, + "description": entry.description, + "url": entry.url, + }) + break + else: + current["sections"].append({ + "name": entry.section, + "apps": [{ + "name": entry.name, + "icon": entry.icon, + "description": entry.description, + "url": entry.url, + }] + }) + + with open(APPS_FILE, "w") as f: + yaml.safe_dump(current, f) + + return {"status": "added"} if __name__ == "__main__": import uvicorn diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 6b27168..ec486ef 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,20 +1,22 @@ import { useEffect, useState } from 'react'; import './App.css'; -import AppGrid from './components/AppGrid'; +import SectionGrid from './components/SectionGrid'; function App() { - const [apps, setApps] = useState([]); + const [sections, setSections] = useState([]); useEffect(() => { fetch('/apps') .then(res => res.json()) - .then(data => setApps(data)); + .then(data => setSections(data.sections || [])); }, []); return (

🔷 Navix

- + {sections.map((section) => ( + + ))}
); } diff --git a/frontend/src/components/SectionGrid.jsx b/frontend/src/components/SectionGrid.jsx new file mode 100644 index 0000000..2a79207 --- /dev/null +++ b/frontend/src/components/SectionGrid.jsx @@ -0,0 +1,13 @@ +import AppGrid from './AppGrid'; +import '../style/SectionGrid.css'; + +function SectionGrid({ section }) { + return ( +
+

{section.name}

+ +
+ ); +} + +export default SectionGrid; diff --git a/frontend/src/style/SectionGrid.css b/frontend/src/style/SectionGrid.css new file mode 100644 index 0000000..3235698 --- /dev/null +++ b/frontend/src/style/SectionGrid.css @@ -0,0 +1,14 @@ +.section { + margin-bottom: 3rem; + width: 100%; + max-width: 1000px; +} + +.section-title { + font-size: 1.5rem; + color: #ffffff; + margin-bottom: 1rem; + border-bottom: 1px solid #444; + padding-bottom: 0.5rem; + text-align: left; +}