Bereich Datenbank geht in Workspaces auf (Reiter Workspaces und Vorlagen)
Workspace-Liste unter /admin/workspaces/liste, Merkmale, Kategorien, Webapp-Vorlagen und Distro-Abdeckung (frühere Flottenmatrix) unter /admin/workspaces/vorlagen. Gemeinsame Unternavigation, Menüpunkt Datenbank entfällt, alte /admin/technik-Adressen leiten weiter (POST mit 307). Workspace-Creator neu, Schritt B. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf1470a3ff
commit
3c7a7e49f3
13 files changed
+125
-112
No files matched your search
@@ -62,6 +62,7 @@ app.include_router(installationsmedium.router)
|
||||
app.include_router(webapps.router)
|
||||
app.include_router(admin_technik.router)
|
||||
app.include_router(admin_workspaces.router)
|
||||
app.include_router(admin_workspaces.technik_weiterleitung)
|
||||
app.include_router(admin_geraete.router)
|
||||
app.include_router(admin_flows.router)
|
||||
app.include_router(admin_kunden.router)
|
||||
|
||||
+27
-32
@@ -6,17 +6,12 @@ from auth import require_admin
|
||||
from templating import templates
|
||||
|
||||
|
||||
router = APIRouter(prefix="/admin/technik")
|
||||
|
||||
|
||||
@router.get("")
|
||||
def index(user: dict = Depends(require_admin)):
|
||||
return RedirectResponse("/admin/technik/merkmale", status_code=303)
|
||||
router = APIRouter(prefix="/admin/workspaces")
|
||||
|
||||
|
||||
# --- Merkmale ---
|
||||
|
||||
@router.get("/merkmale")
|
||||
@router.get("/vorlagen/merkmale")
|
||||
def merkmale_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
merkmale_result = anode_request("GET", "/api/v1/merkmale")
|
||||
merkmale = merkmale_result.get("merkmale", []) if merkmale_result.get("success") else []
|
||||
@@ -31,7 +26,7 @@ def merkmale_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
)
|
||||
|
||||
|
||||
@router.post("/merkmale")
|
||||
@router.post("/vorlagen/merkmale")
|
||||
def merkmal_anlegen(
|
||||
key: str = Form(...), name: str = Form(...), description: str = Form(default=""),
|
||||
user: dict = Depends(require_admin),
|
||||
@@ -41,10 +36,10 @@ def merkmal_anlegen(
|
||||
json={"key": key, "name": name, "description": description or None},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/merkmale", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/merkmale", status_code=303)
|
||||
|
||||
|
||||
@router.post("/merkmale/{merkmal_id}")
|
||||
@router.post("/vorlagen/merkmale/{merkmal_id}")
|
||||
def merkmal_aktualisieren(
|
||||
merkmal_id: str,
|
||||
name: str = Form(...),
|
||||
@@ -63,12 +58,12 @@ def merkmal_aktualisieren(
|
||||
},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/merkmale", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/merkmale", status_code=303)
|
||||
|
||||
|
||||
# --- Kategorien ---
|
||||
|
||||
@router.get("/kategorien")
|
||||
@router.get("/vorlagen/kategorien")
|
||||
def kategorien_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
result = anode_request("GET", "/api/v1/kategorien")
|
||||
kategorien = result.get("kategorien", []) if result.get("success") else []
|
||||
@@ -78,7 +73,7 @@ def kategorien_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
)
|
||||
|
||||
|
||||
@router.post("/kategorien")
|
||||
@router.post("/vorlagen/kategorien")
|
||||
def kategorie_anlegen(
|
||||
key: str = Form(...), name: str = Form(...), description: str = Form(default=""),
|
||||
sort_order: int = Form(default=0), art: str = Form(default="app"), user: dict = Depends(require_admin),
|
||||
@@ -88,12 +83,12 @@ def kategorie_anlegen(
|
||||
json={"key": key, "name": name, "description": description or None, "sort_order": sort_order, "art": art},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/kategorien", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/kategorien", status_code=303)
|
||||
|
||||
|
||||
# --- Workspaces ---
|
||||
|
||||
@router.get("/workspaces")
|
||||
@router.get("/liste")
|
||||
def workspaces_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
result = anode_request("GET", "/api/v1/workspaces")
|
||||
workspaces = result.get("workspaces", []) if result.get("success") else []
|
||||
@@ -108,7 +103,7 @@ def workspaces_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
)
|
||||
|
||||
|
||||
@router.post("/workspaces")
|
||||
@router.post("/liste")
|
||||
def workspace_anlegen(
|
||||
key: str = Form(...), name: str = Form(...), description: str = Form(default=""),
|
||||
organization_id: str = Form(default=""), user: dict = Depends(require_admin),
|
||||
@@ -121,7 +116,7 @@ def workspace_anlegen(
|
||||
},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/workspaces", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/liste", status_code=303)
|
||||
|
||||
|
||||
def gruppiere_merkmale_nach_kategorie(alle_merkmale: list[dict], komponierte_ids: set[str]) -> dict[str, list[dict]]:
|
||||
@@ -143,7 +138,7 @@ def gruppiere_merkmale_nach_kategorie(alle_merkmale: list[dict], komponierte_ids
|
||||
return kategorien
|
||||
|
||||
|
||||
@router.get("/workspaces/{workspace_id}")
|
||||
@router.get("/liste/{workspace_id}")
|
||||
def workspace_detail(request: Request, workspace_id: str, user: dict = Depends(require_admin)):
|
||||
result = anode_request("GET", f"/api/v1/workspaces/{workspace_id}")
|
||||
workspace = result.get("workspace") if result.get("success") else None
|
||||
@@ -170,7 +165,7 @@ def workspace_detail(request: Request, workspace_id: str, user: dict = Depends(r
|
||||
)
|
||||
|
||||
|
||||
@router.post("/workspaces/{workspace_id}/merkmale")
|
||||
@router.post("/liste/{workspace_id}/merkmale")
|
||||
async def workspace_merkmale_speichern(request: Request, workspace_id: str, user: dict = Depends(require_admin)):
|
||||
"""
|
||||
Ersetzt die alte "ein Merkmal pro Formular"-Zuordnung: die
|
||||
@@ -194,7 +189,7 @@ async def workspace_merkmale_speichern(request: Request, workspace_id: str, user
|
||||
for merkmal_id in aktuell - ausgewaehlt:
|
||||
anode_request("DELETE", f"/api/v1/workspaces/{workspace_id}/merkmale/{merkmal_id}")
|
||||
|
||||
return RedirectResponse(f"/admin/technik/workspaces/{workspace_id}", status_code=303)
|
||||
return RedirectResponse(f"/admin/workspaces/liste/{workspace_id}", status_code=303)
|
||||
|
||||
|
||||
# --- Webapps (Phase 2, 09.09.2026) ---
|
||||
@@ -207,7 +202,7 @@ async def workspace_merkmale_speichern(request: Request, workspace_id: str, user
|
||||
# OE-/Gruppen-Ebene umziehen (analog zu oe_merkmale) statt Workspace-Ebene -
|
||||
# bewusst nicht unilateral entschieden.
|
||||
|
||||
@router.post("/workspaces/{workspace_id}/webapps")
|
||||
@router.post("/liste/{workspace_id}/webapps")
|
||||
def workspace_webapp_hinzufuegen(
|
||||
workspace_id: str, name: str = Form(...), url: str = Form(...), user: dict = Depends(require_admin)
|
||||
):
|
||||
@@ -216,16 +211,16 @@ def workspace_webapp_hinzufuegen(
|
||||
json={"name": name, "url": url},
|
||||
)
|
||||
|
||||
return RedirectResponse(f"/admin/technik/workspaces/{workspace_id}", status_code=303)
|
||||
return RedirectResponse(f"/admin/workspaces/liste/{workspace_id}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/workspaces/{workspace_id}/webapps/{webapp_id}/entfernen")
|
||||
@router.post("/liste/{workspace_id}/webapps/{webapp_id}/entfernen")
|
||||
def workspace_webapp_entfernen(
|
||||
workspace_id: str, webapp_id: str, user: dict = Depends(require_admin)
|
||||
):
|
||||
anode_request("DELETE", f"/api/v1/workspaces/{workspace_id}/webapps/{webapp_id}")
|
||||
|
||||
return RedirectResponse(f"/admin/technik/workspaces/{workspace_id}", status_code=303)
|
||||
return RedirectResponse(f"/admin/workspaces/liste/{workspace_id}", status_code=303)
|
||||
|
||||
|
||||
@router.get("/webapp-icons/{filename}")
|
||||
@@ -284,7 +279,7 @@ def _blueprint_matrix(backends: list[dict], merkmale: list[dict], blueprints: li
|
||||
]
|
||||
|
||||
|
||||
@router.get("/backends")
|
||||
@router.get("/vorlagen/distros")
|
||||
def backends_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
backends_result = anode_request("GET", "/api/v1/backends")
|
||||
backends = backends_result.get("backends", []) if backends_result.get("success") else []
|
||||
@@ -308,7 +303,7 @@ def backends_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
|
||||
# --- Webapp-Vorlagen (Phase 2, 09.09.2026) ---
|
||||
|
||||
@router.get("/webapp-templates")
|
||||
@router.get("/vorlagen/webapp-vorlagen")
|
||||
def webapp_templates_liste(request: Request, user: dict = Depends(require_admin)):
|
||||
result = anode_request("GET", "/api/v1/webapp-templates")
|
||||
webapp_templates = result.get("webapp_templates", []) if result.get("success") else []
|
||||
@@ -327,7 +322,7 @@ def webapp_templates_liste(request: Request, user: dict = Depends(require_admin)
|
||||
)
|
||||
|
||||
|
||||
@router.post("/webapp-templates")
|
||||
@router.post("/vorlagen/webapp-vorlagen")
|
||||
def webapp_template_anlegen(
|
||||
name: str = Form(...), url: str = Form(...), description: str = Form(default=""),
|
||||
kategorie_id: str = Form(default=""), user: dict = Depends(require_admin),
|
||||
@@ -337,10 +332,10 @@ def webapp_template_anlegen(
|
||||
json={"name": name, "url": url, "description": description or None, "kategorie_id": kategorie_id or None},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/webapp-templates", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/webapp-vorlagen", status_code=303)
|
||||
|
||||
|
||||
@router.post("/webapp-templates/{template_id}")
|
||||
@router.post("/vorlagen/webapp-vorlagen/{template_id}")
|
||||
def webapp_template_bearbeiten(
|
||||
template_id: str, name: str = Form(...), url: str = Form(...), description: str = Form(default=""),
|
||||
kategorie_id: str = Form(default=""), user: dict = Depends(require_admin),
|
||||
@@ -350,11 +345,11 @@ def webapp_template_bearbeiten(
|
||||
json={"name": name, "url": url, "description": description or None, "kategorie_id": kategorie_id or None},
|
||||
)
|
||||
|
||||
return RedirectResponse("/admin/technik/webapp-templates", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/webapp-vorlagen", status_code=303)
|
||||
|
||||
|
||||
@router.post("/webapp-templates/{template_id}/loeschen")
|
||||
@router.post("/vorlagen/webapp-vorlagen/{template_id}/loeschen")
|
||||
def webapp_template_loeschen(template_id: str, user: dict = Depends(require_admin)):
|
||||
anode_request("DELETE", f"/api/v1/webapp-templates/{template_id}")
|
||||
|
||||
return RedirectResponse("/admin/technik/webapp-templates", status_code=303)
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/webapp-vorlagen", status_code=303)
|
||||
@@ -74,7 +74,7 @@ def katalog_aufbauen(
|
||||
for m in merkmale:
|
||||
eintrag = _eintrag(
|
||||
m["name"], m.get("description"),
|
||||
f"/admin/technik{m['icon_path']}" if m.get("icon_path") else None,
|
||||
f"/admin/workspaces{m['icon_path']}" if m.get("icon_path") else None,
|
||||
distro_liste(distros_je_merkmal.get(m["key"], set())),
|
||||
)
|
||||
ziel = richtlinien if art_je_kategorie.get(m.get("kategorie_id")) == "richtlinie" else apps
|
||||
@@ -86,7 +86,7 @@ def katalog_aufbauen(
|
||||
t.get("kategorie_id"),
|
||||
_eintrag(
|
||||
t["name"], t.get("description"),
|
||||
f"/admin/technik/webapp-icons/{t['icon_path'].split('/')[-1]}" if t.get("icon_path") else None,
|
||||
f"/admin/workspaces/webapp-icons/{t['icon_path'].split('/')[-1]}" if t.get("icon_path") else None,
|
||||
distro_liste(alle_distros),
|
||||
),
|
||||
)
|
||||
@@ -113,6 +113,44 @@ def index(user: dict = Depends(require_admin)):
|
||||
return RedirectResponse("/admin/workspaces/katalog", status_code=303)
|
||||
|
||||
|
||||
@router.get("/vorlagen")
|
||||
def vorlagen(user: dict = Depends(require_admin)):
|
||||
return RedirectResponse("/admin/workspaces/vorlagen/merkmale", status_code=303)
|
||||
|
||||
|
||||
# Bereich "Datenbank" (/admin/technik) ist in "Workspaces" aufgegangen
|
||||
# (Schritt B, 07.10.2026) - alte Lesezeichen und Links leiten weiter.
|
||||
# Bewusst 307/308 statt 303 für POST, damit ein noch offenes altes Formular
|
||||
# nicht stillschweigend zu einem GET wird.
|
||||
ALTE_TECHNIK_PFADE = [
|
||||
("webapp-templates", "vorlagen/webapp-vorlagen"),
|
||||
("webapp-icons", "webapp-icons"),
|
||||
("merkmal-icons", "merkmal-icons"),
|
||||
("merkmale", "vorlagen/merkmale"),
|
||||
("kategorien", "vorlagen/kategorien"),
|
||||
("backends", "vorlagen/distros"),
|
||||
("workspaces", "liste"),
|
||||
]
|
||||
|
||||
|
||||
def neuer_pfad_fuer_technik(rest: str) -> str:
|
||||
rest = rest.strip("/")
|
||||
for alt, neu in ALTE_TECHNIK_PFADE:
|
||||
if rest == alt or rest.startswith(alt + "/"):
|
||||
return "/admin/workspaces/" + neu + rest[len(alt):]
|
||||
return "/admin/workspaces"
|
||||
|
||||
|
||||
technik_weiterleitung = APIRouter(prefix="/admin/technik")
|
||||
|
||||
|
||||
@technik_weiterleitung.api_route("", methods=["GET", "POST"])
|
||||
@technik_weiterleitung.api_route("/{rest:path}", methods=["GET", "POST"])
|
||||
def alte_technik_adresse(request: Request, rest: str = ""):
|
||||
status = 303 if request.method == "GET" else 307
|
||||
return RedirectResponse(neuer_pfad_fuer_technik(rest), status_code=status)
|
||||
|
||||
|
||||
@router.get("/katalog")
|
||||
def katalog(request: Request, user: dict = Depends(require_admin)):
|
||||
kategorien = _liste(anode_request("GET", "/api/v1/kategorien"), "kategorien")
|
||||
|
||||
@@ -13,7 +13,7 @@ router = APIRouter()
|
||||
# Workspace-Creator kundenseitig gesperrt (07.10.2026, Nutzer-Entscheidung):
|
||||
# Der Creator ist noch nicht verständlich genug bedienbar, Workspaces von
|
||||
# Kunden-Organisationen richtet bis auf Weiteres nur der root-admin über
|
||||
# Admin → Datenbank → Workspaces-Vorlagen ein (Organisation im
|
||||
# Admin → Workspaces → Workspaces ein (Organisation im
|
||||
# Anlege-Formular wählen). Die Zuweisung eines fertigen Workspace an eine
|
||||
# Gerätegruppe (routers/gruppen.py) bleibt für Kunden offen - das ist reine
|
||||
# Auswahl, kein Zusammenstellen. Freischalten: True setzen.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{# Unterseiten von Workspaces → Vorlagen: Pflege dessen, woraus Workspaces
|
||||
zusammengestellt werden. #}
|
||||
{% set vl_pfad = request.url.path %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/workspaces/vorlagen/merkmale">{% if vl_pfad.startswith("/admin/workspaces/vorlagen/merkmale") %}<strong>Merkmale</strong>{% else %}Merkmale{% endif %}</a></li>
|
||||
<li><a href="/admin/workspaces/vorlagen/kategorien">{% if vl_pfad.startswith("/admin/workspaces/vorlagen/kategorien") %}<strong>Kategorien</strong>{% else %}Kategorien{% endif %}</a></li>
|
||||
<li><a href="/admin/workspaces/vorlagen/webapp-vorlagen">{% if vl_pfad.startswith("/admin/workspaces/vorlagen/webapp-vorlagen") %}<strong>Webapp-Vorlagen</strong>{% else %}Webapp-Vorlagen{% endif %}</a></li>
|
||||
<li><a href="/admin/workspaces/vorlagen/distros">{% if vl_pfad.startswith("/admin/workspaces/vorlagen/distros") %}<strong>Distro-Abdeckung</strong>{% else %}Distro-Abdeckung{% endif %}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -1,11 +1,15 @@
|
||||
{# Unterreiter des Bereichs "Workspaces" (Workspace-Creator neu, 07.10.2026).
|
||||
"Workspaces" und "Vorlagen" zeigen bis Schritt B auf die bisherigen
|
||||
Seiten unter /admin/technik. #}
|
||||
{# Unterreiter des Bereichs "Workspaces" (Workspace-Creator neu, 07.10.2026):
|
||||
Katalog (Übersicht), Workspaces (Liste/Verwaltung), Vorlagen (Pflege des
|
||||
Katalogs, nur root). Ersetzt den früheren Bereich "Datenbank". #}
|
||||
{% set ws_pfad = request.url.path %}
|
||||
<nav>
|
||||
{% set ws_reiter = "katalog" if ws_pfad.startswith("/admin/workspaces/katalog")
|
||||
else "liste" if ws_pfad.startswith("/admin/workspaces/liste")
|
||||
else "vorlagen" if ws_pfad.startswith("/admin/workspaces/vorlagen")
|
||||
else "" %}
|
||||
<nav class="sekundaer-nav" aria-label="Workspaces-Unterseiten">
|
||||
<ul>
|
||||
<li><a href="/admin/workspaces/katalog">{% if ws_pfad.startswith("/admin/workspaces/katalog") %}<strong>Katalog</strong>{% else %}Katalog{% endif %}</a></li>
|
||||
<li><a href="/admin/technik/workspaces">Workspaces</a></li>
|
||||
<li><a href="/admin/technik/merkmale">Vorlagen</a></li>
|
||||
<li><a href="/admin/workspaces/katalog" {% if ws_reiter == "katalog" %}class="active"{% endif %}>Katalog</a></li>
|
||||
<li><a href="/admin/workspaces/liste" {% if ws_reiter == "liste" %}class="active"{% endif %}>Workspaces</a></li>
|
||||
<li><a href="/admin/workspaces/vorlagen" {% if ws_reiter == "vorlagen" %}class="active"{% endif %}>Vorlagen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -1,17 +1,10 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}Flottenmatrix — Tuxflotte Admin{% endblock %}
|
||||
{% block title %}Distro-Abdeckung — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/technik/merkmale">Merkmale</a></li>
|
||||
<li><a href="/admin/technik/kategorien">App-Kategorien</a></li>
|
||||
<li><a href="/admin/technik/workspaces">Workspaces-Vorlagen</a></li>
|
||||
<li><a href="/admin/technik/backends"><strong>Flottenmatrix</strong></a></li>
|
||||
<li><a href="/admin/technik/webapp-templates">Webapp-Vorlagen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h2>Flottenmatrix</h2>
|
||||
<p><small>Nur Anzeige — Änderungen brauchen echten Ansible-Rollen-Code, nicht nur einen Datenbankeintrag. Ein Haken zeigt, dass für dieses Merkmal auf diesem Backend eine Ansible-Rolle hinterlegt ist (Mauszeiger drüber zeigt den Rollennamen) — eine leere Zeile heißt, das Merkmal ist auf keinem Backend umgesetzt.</small></p>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
{% include "admin/_vorlagen_nav.html" %}
|
||||
<h2>Distro-Abdeckung</h2>
|
||||
<p><small>Nur Anzeige — Änderungen brauchen echten Ansible-Rollen-Code, nicht nur einen Datenbankeintrag. Ein Haken zeigt, dass für dieses Merkmal auf dieser Distro eine Ansible-Rolle hinterlegt ist (Mauszeiger drüber zeigt den Rollennamen) — eine leere Zeile heißt, das Merkmal ist auf keiner Distro umgesetzt.</small></p>
|
||||
|
||||
<input type="search" placeholder="Suche nach Merkmal …" data-table-search="#blueprint-matrix" style="max-width: 24rem">
|
||||
|
||||
@@ -29,7 +22,7 @@
|
||||
{% for zeile in matrix %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if zeile.merkmal.icon_path %}<img src="/admin/technik{{ zeile.merkmal.icon_path }}" alt="" width="18" height="18" style="vertical-align:middle;margin-right:0.35rem">{% endif %}
|
||||
{% if zeile.merkmal.icon_path %}<img src="/admin/workspaces{{ zeile.merkmal.icon_path }}" alt="" width="18" height="18" style="vertical-align:middle;margin-right:0.35rem">{% endif %}
|
||||
<code>{{ zeile.merkmal.key }}</code> {{ zeile.merkmal.name }}
|
||||
</td>
|
||||
{% for ansible_role in zeile.zellen %}
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}App-Kategorien — Tuxflotte Admin{% endblock %}
|
||||
{% block title %}Kategorien — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/technik/merkmale">Merkmale</a></li>
|
||||
<li><a href="/admin/technik/kategorien"><strong>App-Kategorien</strong></a></li>
|
||||
<li><a href="/admin/technik/workspaces">Workspaces-Vorlagen</a></li>
|
||||
<li><a href="/admin/technik/backends">Flottenmatrix</a></li>
|
||||
<li><a href="/admin/technik/webapp-templates">Webapp-Vorlagen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h2>App-Kategorien</h2>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
{% include "admin/_vorlagen_nav.html" %}
|
||||
<h2>Kategorien</h2>
|
||||
<p><small>Kategorien ordnen Apps und Webapps (Art „App“) bzw. Konfigurationsrichtlinien (Art „Richtlinie“) im Katalog und im Assistenten.</small></p>
|
||||
|
||||
<figure>
|
||||
<table>
|
||||
@@ -30,7 +24,7 @@
|
||||
|
||||
<details>
|
||||
<summary role="button" class="secondary outline">Neue Kategorie anlegen</summary>
|
||||
<form method="post" action="/admin/technik/kategorien">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/kategorien">
|
||||
<label>Key<input type="text" name="key" required></label>
|
||||
<label>Name<input type="text" name="name" required></label>
|
||||
<label>Beschreibung<input type="text" name="description"></label>
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}Merkmale — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/technik/merkmale"><strong>Merkmale</strong></a></li>
|
||||
<li><a href="/admin/technik/kategorien">App-Kategorien</a></li>
|
||||
<li><a href="/admin/technik/workspaces">Workspaces-Vorlagen</a></li>
|
||||
<li><a href="/admin/technik/backends">Flottenmatrix</a></li>
|
||||
<li><a href="/admin/technik/webapp-templates">Webapp-Vorlagen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
{% include "admin/_vorlagen_nav.html" %}
|
||||
<h2>Merkmale</h2>
|
||||
|
||||
<input type="search" placeholder="Suche nach Key, Name, Kategorie …" data-table-search="#merkmale-tabelle" style="max-width: 24rem">
|
||||
@@ -28,7 +21,7 @@
|
||||
<tr>
|
||||
<td><code>{{ m.key }}</code></td>
|
||||
<td>
|
||||
{% if m.icon_path %}<img src="/admin/technik{{ m.icon_path }}" alt="" width="20" height="20" style="vertical-align:middle;margin-right:0.35rem">{% endif %}
|
||||
{% if m.icon_path %}<img src="/admin/workspaces{{ m.icon_path }}" alt="" width="20" height="20" style="vertical-align:middle;margin-right:0.35rem">{% endif %}
|
||||
{{ m.name }}
|
||||
{% if m.description %}<br><small>{{ m.description }}</small>{% endif %}
|
||||
</td>
|
||||
@@ -37,7 +30,7 @@
|
||||
<td>
|
||||
<details>
|
||||
<summary role="button" class="outline">Bearbeiten</summary>
|
||||
<form method="post" action="/admin/technik/merkmale/{{ m.id }}">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/merkmale/{{ m.id }}">
|
||||
<label>Name<input type="text" name="name" value="{{ m.name }}" required></label>
|
||||
<label>Beschreibung<input type="text" name="description" value="{{ m.description or '' }}"></label>
|
||||
<label>Kategorie
|
||||
@@ -64,7 +57,7 @@
|
||||
|
||||
<details>
|
||||
<summary role="button" class="secondary outline">Neues Merkmal anlegen</summary>
|
||||
<form method="post" action="/admin/technik/merkmale">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/merkmale">
|
||||
<label>Key<input type="text" name="key" required></label>
|
||||
<label>Name<input type="text" name="name" required></label>
|
||||
<label>Beschreibung<input type="text" name="description"></label>
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}Webapp-Vorlagen — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/technik/merkmale">Merkmale</a></li>
|
||||
<li><a href="/admin/technik/kategorien">App-Kategorien</a></li>
|
||||
<li><a href="/admin/technik/workspaces">Workspaces-Vorlagen</a></li>
|
||||
<li><a href="/admin/technik/backends">Flottenmatrix</a></li>
|
||||
<li><a href="/admin/technik/webapp-templates"><strong>Webapp-Vorlagen</strong></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
{% include "admin/_vorlagen_nav.html" %}
|
||||
<h2>Webapp-Vorlagen</h2>
|
||||
<p><small>Global wiederverwendbare Webapp-Vorschläge, die Kunden für ihre eigenen Workspaces aktivieren können (zusätzlich zu ihren eigenen freien Einträgen).</small></p>
|
||||
|
||||
@@ -21,7 +14,7 @@
|
||||
<tr>
|
||||
<td style="width:2rem">
|
||||
{% if t.icon_path %}
|
||||
<img src="/admin/technik/webapp-icons/{{ t.icon_path.split('/')[-1] }}" alt="" width="24" height="24">
|
||||
<img src="/admin/workspaces/webapp-icons/{{ t.icon_path.split('/')[-1] }}" alt="" width="24" height="24">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ t.name }}{% if t.description %}<br><small>{{ t.description }}</small>{% endif %}</td>
|
||||
@@ -30,7 +23,7 @@
|
||||
<td>
|
||||
<details>
|
||||
<summary role="button" class="outline">Bearbeiten</summary>
|
||||
<form method="post" action="/admin/technik/webapp-templates/{{ t.id }}">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/webapp-vorlagen/{{ t.id }}">
|
||||
<label>Name<input type="text" name="name" value="{{ t.name }}" required></label>
|
||||
<label>URL<input type="url" name="url" value="{{ t.url }}" required></label>
|
||||
<label>Beschreibung<input type="text" name="description" value="{{ t.description or '' }}"></label>
|
||||
@@ -45,7 +38,7 @@
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
</details>
|
||||
<form method="post" action="/admin/technik/webapp-templates/{{ t.id }}/loeschen">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/webapp-vorlagen/{{ t.id }}/loeschen">
|
||||
<button type="submit" class="secondary outline">Löschen</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -57,7 +50,7 @@
|
||||
|
||||
<details>
|
||||
<summary role="button" class="secondary outline">Neue Vorlage anlegen</summary>
|
||||
<form method="post" action="/admin/technik/webapp-templates">
|
||||
<form method="post" action="/admin/workspaces/vorlagen/webapp-vorlagen">
|
||||
<label>Name<input type="text" name="name" required placeholder="z.B. Wikipedia"></label>
|
||||
<label>URL<input type="url" name="url" required placeholder="https://..."></label>
|
||||
<label>Beschreibung<input type="text" name="description"></label>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}{{ workspace.name if workspace else workspace_id }} — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<p><a href="/admin/technik/workspaces">← Workspaces-Vorlagen</a></p>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
<p><a href="/admin/workspaces/liste">← Workspaces</a></p>
|
||||
{% if not workspace %}
|
||||
<p><mark>Workspace wurde nicht gefunden.</mark></p>
|
||||
{% else %}
|
||||
@@ -20,7 +21,7 @@
|
||||
{% if not kategorien %}
|
||||
<p>Keine katalogfähigen Merkmale vorhanden.</p>
|
||||
{% else %}
|
||||
<form method="post" action="/admin/technik/workspaces/{{ workspace_id }}/merkmale">
|
||||
<form method="post" action="/admin/workspaces/liste/{{ workspace_id }}/merkmale">
|
||||
{% for kategorie_name, eintraege in kategorien.items() %}
|
||||
<fieldset>
|
||||
<legend><strong>{{ kategorie_name }}</strong></legend>
|
||||
@@ -49,12 +50,12 @@
|
||||
<tr>
|
||||
<td style="width:2rem">
|
||||
{% if w.icon_path %}
|
||||
<img src="/admin/technik/webapp-icons/{{ w.icon_path.split('/')[-1] }}" alt="" width="24" height="24">
|
||||
<img src="/admin/workspaces/webapp-icons/{{ w.icon_path.split('/')[-1] }}" alt="" width="24" height="24">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ w.name }}<br><small><a href="{{ w.url }}" target="_blank" rel="noopener">{{ w.url }}</a></small></td>
|
||||
<td>
|
||||
<form method="post" action="/admin/technik/workspaces/{{ workspace_id }}/webapps/{{ w.id }}/entfernen">
|
||||
<form method="post" action="/admin/workspaces/liste/{{ workspace_id }}/webapps/{{ w.id }}/entfernen">
|
||||
<button type="submit" class="secondary outline">Entfernen</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -65,7 +66,7 @@
|
||||
</figure>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/admin/technik/workspaces/{{ workspace_id }}/webapps">
|
||||
<form method="post" action="/admin/workspaces/liste/{{ workspace_id }}/webapps">
|
||||
<label>Name
|
||||
<input type="text" name="name" required placeholder="z.B. Schulportal">
|
||||
</label>
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% block title %}Workspaces-Vorlagen — Tuxflotte Admin{% endblock %}
|
||||
{% block title %}Workspaces — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/admin/technik/merkmale">Merkmale</a></li>
|
||||
<li><a href="/admin/technik/kategorien">App-Kategorien</a></li>
|
||||
<li><a href="/admin/technik/workspaces"><strong>Workspaces-Vorlagen</strong></a></li>
|
||||
<li><a href="/admin/technik/backends">Flottenmatrix</a></li>
|
||||
<li><a href="/admin/technik/webapp-templates">Webapp-Vorlagen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h2>Workspaces-Vorlagen</h2>
|
||||
{% include "admin/_workspaces_nav.html" %}
|
||||
<h2>Workspaces</h2>
|
||||
|
||||
<figure>
|
||||
<table>
|
||||
@@ -21,7 +13,7 @@
|
||||
<td><code>{{ w.key }}</code></td>
|
||||
<td>{{ w.name }}</td>
|
||||
<td>{{ w.organization_name or "Global" }}</td>
|
||||
<td><a href="/admin/technik/workspaces/{{ w.id }}" role="button" class="outline">Zusammensetzung</a></td>
|
||||
<td><a href="/admin/workspaces/liste/{{ w.id }}" role="button" class="outline">Zusammensetzung</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -30,7 +22,7 @@
|
||||
|
||||
<details>
|
||||
<summary role="button" class="secondary outline">Neuen Workspace anlegen</summary>
|
||||
<form method="post" action="/admin/technik/workspaces">
|
||||
<form method="post" action="/admin/workspaces/liste">
|
||||
<label>Key<input type="text" name="key" required></label>
|
||||
<label>Name<input type="text" name="name" required></label>
|
||||
<label>Beschreibung<input type="text" name="description"></label>
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
else "installationsmedium" if pfad.startswith("/installationsmedium")
|
||||
else "admin_dashboard" if pfad.startswith("/admin/dashboard")
|
||||
else "admin_kunden" if pfad.startswith("/admin/kunden")
|
||||
else "admin_technik" if pfad.startswith("/admin/technik")
|
||||
else "admin_workspaces" if pfad.startswith("/admin/workspaces")
|
||||
else "admin_geraete" if pfad.startswith("/admin/geraete")
|
||||
else "admin_flows" if pfad.startswith("/admin/flows")
|
||||
@@ -165,7 +164,6 @@
|
||||
<li><a href="/admin/dashboard" {% if aktiver_bereich == "admin_dashboard" %}class="active"{% endif %}>📊 Dashboard</a></li>
|
||||
<li><a href="/admin/kunden" {% if aktiver_bereich == "admin_kunden" %}class="active"{% endif %}>🏢 Organisationen</a></li>
|
||||
<li><a href="/admin/workspaces" {% if aktiver_bereich == "admin_workspaces" %}class="active"{% endif %}>🧩 Workspaces</a></li>
|
||||
<li><a href="/admin/technik" {% if aktiver_bereich == "admin_technik" %}class="active"{% endif %}>🗄️ Datenbank</a></li>
|
||||
<li><a href="/admin/geraete" {% if aktiver_bereich == "admin_geraete" %}class="active"{% endif %}>🖥️ Flotte</a></li>
|
||||
<li><a href="/admin/accounts" {% if aktiver_bereich == "admin_accounts" %}class="active"{% endif %}>🔑 Admin-Accounts</a></li>
|
||||
{% else %}
|
||||
|
||||
Reference in new issue
Block a user