Add API req to create new app/section
This commit is contained in:
parent
59027c9ba6
commit
57d1156425
Binary file not shown.
@ -1,24 +1,26 @@
|
||||
- name: Gitea
|
||||
url: https://git.dvirlabs.com
|
||||
icon: http://192.168.10.118:1111/icons/gitea.svg
|
||||
description: Git server
|
||||
|
||||
- name: Grafana
|
||||
url: https://grafana.dvirlabs.com
|
||||
sections:
|
||||
- apps:
|
||||
- description: Dashboards
|
||||
icon: http://192.168.10.118:1111/icons/grafana.svg
|
||||
description: Dashboards
|
||||
|
||||
- name: Prometheus
|
||||
url: https://prometheus.dvirlabs.com
|
||||
name: Grafana
|
||||
url: https://grafana.dvirlabs.com
|
||||
- description: Monitoring
|
||||
icon: http://192.168.10.118:1111/icons/prometheus.svg
|
||||
description: Monitoring
|
||||
|
||||
- name: Harbor
|
||||
url: https://harbor.dvirlabs.com
|
||||
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
|
||||
description: Container registry
|
||||
|
||||
- name: Woodpecker
|
||||
url: https://woodpecker.dvirlabs.com
|
||||
name: Harbor
|
||||
url: https://harbor.dvirlabs.com
|
||||
- description: CI/CD
|
||||
icon: http://192.168.10.118:1111/icons/woodpecker-ci.svg
|
||||
description: CI/CD
|
||||
name: Woodpecker
|
||||
url: https://woodpecker.dvirlabs.com
|
||||
name: Dev-tools
|
||||
|
||||
|
||||
@ -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
|
||||
@ -27,6 +29,47 @@ def get_apps():
|
||||
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
|
||||
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
||||
@ -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 (
|
||||
<div className="App">
|
||||
<h1 className="main-title">🔷 Navix</h1>
|
||||
<AppGrid apps={apps} />
|
||||
{sections.map((section) => (
|
||||
<SectionGrid key={section.name} section={section} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
13
frontend/src/components/SectionGrid.jsx
Normal file
13
frontend/src/components/SectionGrid.jsx
Normal file
@ -0,0 +1,13 @@
|
||||
import AppGrid from './AppGrid';
|
||||
import '../style/SectionGrid.css';
|
||||
|
||||
function SectionGrid({ section }) {
|
||||
return (
|
||||
<div className="section">
|
||||
<h2 className="section-title">{section.name}</h2>
|
||||
<AppGrid apps={section.apps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SectionGrid;
|
||||
14
frontend/src/style/SectionGrid.css
Normal file
14
frontend/src/style/SectionGrid.css
Normal file
@ -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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user