diff --git a/README.md b/README.md index 4932b11..1a1e186 100644 --- a/README.md +++ b/README.md @@ -1,219 +1,209 @@ -# 🗂️ Projekt-Dashboard +# 🗂️ Gitea Projekt-Dashboard -Ein selbst gehostetes Dashboard zur zentralen Verwaltung aller persönlichen Projekte – technische wie nicht-technische. +Ein selbst gehostetes Dashboard, das automatisch alle Gitea-Repositories anzeigt, die mit einem bestimmten **Topic-Tag** versehen sind. --- -## 💡 Was ist ein Projekt? +## 🏷️ Funktionsprinzip: Tag-basierte Projektanzeige -Ein Projekt ist **alles, woran aktiv gearbeitet wird oder wurde** – unabhängig davon, ob es einen Code-Repository hat oder nicht. +Jedes Repository, das auf dieser Gitea-Instanz mit dem Topic-Tag `dashboard` versehen ist, wird automatisch im Dashboard angezeigt. -Beispiele: +### So funktioniert es: -- 🖥️ **Softwareprojekt** – eine selbst gehostete App, ein CLI-Tool, ein Backend-Service -- 🔧 **Hardware-Projekt** – Aufbau eines zweiten PCs, Einrichten eines Homelab-Servers -- 🏗️ **Infrastruktur** – Umstrukturierung des Heimnetzwerks, Migration zu Docker Compose -- 📋 **Organisatorisches** – Dokumentation aufräumen, Backupstrategie planen -- 🌱 **Persönliches** – Lernprojekte, Kurse, Ziele ohne technischen Bezug +1. Du setzt in einem Gitea-Repository unter **Settings → Topics** das Tag `dashboard` +2. Der Backend-Service pollt regelmäßig (oder per Webhook) die Gitea API nach allen Repos mit diesem Tag +3. Die gefundenen Repos werden in der PostgreSQL-Datenbank gespeichert und gecacht +4. Das Frontend zeigt alle getaggten Repos als Projektkarten mit Live-Daten an -Ein Projekt **kann** mit einer Gitea-Repository verknüpft sein, **muss es aber nicht**. - ---- - -## 🏷️ Repo-Verknüpfung (optional) - -Wenn ein Projekt eine zugehörige Gitea-Repository hat, kann diese durch das Topic-Tag `projekt` markiert werden. Das Dashboard erkennt diese Repos automatisch und zeigt zugehörige Metadaten an (letzter Commit, offene Issues, Sprache etc.). - -Repos **ohne** das Tag `projekt` erscheinen nicht im Dashboard – sie sind keine verwalteten Projekte. - -Projekte **ohne** Repository existieren nur in der Datenbank des Dashboards und werden manuell angelegt. +> **Beispiel:** Repo `mein-projekt` bekommt das Topic `dashboard` → erscheint sofort im Dashboard mit Issues, letztem Commit, Status und Beschreibung. --- ## 🧱 Architektur ``` -┌─────────────────────┐ Gitea REST API v1 ┌──────────────────────┐ -│ Gitea Server │ ◄─────────────────────────────► │ Backend Service │ -│ (Repos + Topics) │ (nur wenn Repo verknüpft) │ (Go, net/http) │ -└─────────────────────┘ └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ PostgreSQL DB │ - │ (Projekte, Tasks, │ - │ Milestones, Notizen) │ - └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ Frontend │ - │ (SvelteKit) │ - └──────────────────────┘ - ``` +┌─────────────────┐ Gitea REST API v1 ┌──────────────────────┐ +│ Gitea Server │ ◄────────────────────────► │ Backend Service │ +│ (Repos + Topics)│ │ (Go, net/http) │ +└─────────────────┘ └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ PostgreSQL DB │ + │ (Repos, Issues, │ + │ Milestones, Cache) │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ Frontend │ + │ (SvelteKit) │ + └──────────────────────┘ +``` - --- +--- - ## 🖥️ Frontend: SvelteKit +## 🖥️ Frontend: **SvelteKit** - Warum SvelteKit? +**Warum SvelteKit?** +- Leichtgewichtig und schnell – ideal für ein internes Dashboard +- Server-Side Rendering (SSR) out of the box – kein Flackern beim Laden +- Einfache Reaktivität ohne Overhead +- Perfekt für datengetriebene Dashboards mit Echtzeit-Updates via SSE oder WebSocket - - Leichtgewichtig und schnell – ideal für ein internes Dashboard - - Server-Side Rendering (SSR) out of the box – kein Flackern beim Laden - - Einfache Reaktivität ohne Overhead - - Perfekt für datengetriebene Übersichten mit Echtzeit-Updates +**Features im Frontend:** +- Projektkarten mit Repo-Name, Beschreibung, letztem Commit, offenen Issues +- Filterfunktion nach Topics, Sprache, Aktivität +- Detailansicht: Issues & Milestones direkt im Dashboard bearbeiten (bi-direktional) +- Live-Updates via Webhook-Events (Server-Sent Events) +- Dark Mode, responsive Design - Features im Frontend: +--- - - Projektkarten mit Name, Beschreibung, Status und offenen Tasks - - Unterscheidung zwischen repo-gebundenen und freien Projekten - - Filterfunktion nach Kategorie, Status, Aktivität - - Detailansicht: Tasks, Milestones, Notizen pro Projekt - - Live-Updates via Server-Sent Events (bei repo-gebundenen Projekten) - - Dark Mode, responsive Design +## ⚙️ Backend: **Go (net/http + pgx)** - --- +Go eignet sich hervorragend als Backend-Sprache – die Standardbibliothek ist so vollständig, dass kein Web-Framework nötig ist. `net/http` liefert alles was gebraucht wird: Routing, Handler, Middleware. Das Ergebnis ist eine dependency-arme, gut lesbare Codebasis. - ## ⚙️ Backend: Go (net/http + pgx) +**Warum kein Framework?** +- `net/http` aus der Standardbibliothek reicht für ~6 Endpoints vollständig aus +- Kein Framework-Overhead, keine Breaking Changes durch externe Dependencies +- Go-typischer Ansatz: explizit, simpel, lesbar +- Kompiliert zu einer einzigen statischen Binary – minimaler Docker-Footprint - Go eignet sich hervorragend als Backend-Sprache – die Standardbibliothek ist so vollständig, dass kein Web-Framework nötig ist. `net/http` liefert alles was gebraucht wird: Routing, Handler, Middleware. +**Externe Dependencies (minimal):** +- `pgx` – PostgreSQL-Treiber (direktes SQL, kein ORM) +- `godotenv` – `.env`-Datei laden +- `golang.org/x/oauth2` – OAuth2-Flow für Gitea-Login - **Warum kein Framework?** +**Backend-Aufgaben:** +- `GET /api/projects` – alle getaggten Repos aus der DB zurückgeben +- `POST /api/webhook` – Gitea Webhook-Listener für Push, Issue, Tag-Events +- `GET /api/projects/{id}/issues` – Issues eines Repos live aus Gitea holen +- Hintergrund-Goroutine: alle 5 Minuten Gitea API nach Repos mit Tag `dashboard` abfragen +- Repo-Daten in PostgreSQL cachen (inkl. Topics, letzter Aktivität, Issue-Count) - - `net/http` aus der Standardbibliothek reicht für die benötigten Endpoints vollständig aus - - Kein Framework-Overhead, keine Breaking Changes durch externe Dependencies - - Go-typischer Ansatz: explizit, simpel, lesbar - - Kompiliert zu einer einzigen statischen Binary – minimaler Docker-Footprint +**Beispiel – HTTP-Server ohne Framework:** +```go +mux := http.NewServeMux() +mux.HandleFunc("GET /api/projects", h.listProjects) +mux.HandleFunc("POST /api/webhook", h.handleWebhook) +mux.HandleFunc("GET /api/projects/{id}/issues", h.listIssues) - **Externe Dependencies (minimal):** +log.Fatal(http.ListenAndServe(":8080", mux)) +``` - - `pgx` – PostgreSQL-Treiber (direktes SQL, kein ORM) - - `godotenv` – `.env`-Datei laden - - `golang.org/x/oauth2` – OAuth2-Flow für Gitea-Login (optional) +--- - **Backend-Aufgaben:** +## 🔐 Auth: **Gitea OAuth2** - - `GET /api/projects` – alle Projekte aus der DB zurückgeben - - `POST /api/projects` – neues Projekt anlegen (mit oder ohne Repo-Verknüpfung) - - `GET /api/projects/{id}/tasks` – Tasks eines Projekts abrufen - - `POST /api/webhook` – Gitea Webhook-Listener für repo-gebundene Projekte - - Hintergrund-Goroutine: Gitea API nach Repos mit Tag `projekt` abfragen und DB synchronisieren +Gitea kann selbst als OAuth2-Provider fungieren – Nutzer loggen sich mit ihrem Gitea-Account im Dashboard ein, genau wie "Login with GitHub". - --- +### Setup in Gitea: - ## 🔐 Auth: Gitea OAuth2 +1. In Gitea unter **Settings → Applications → OAuth2 Applications** eine neue App registrieren +2. `Client ID` und `Client Secret` in die `.env` eintragen +3. Redirect URI auf `https://dashboard.example.com/auth/callback` setzen - Gitea fungiert als OAuth2-Provider – Nutzer loggen sich mit ihrem Gitea-Account im Dashboard ein. +### Flow: - **Flow:** +``` +Nutzer klickt "Login mit Gitea" + → Weiterleitung zur Gitea-Instanz (Authorization Endpoint) + → Nutzer bestätigt Zugriff + → Gitea leitet mit Authorization Code zurück + → Backend tauscht Code gegen Access Token + → Nutzer ist eingeloggt, Gitea-Identität bekannt +``` - Nutzer klickt "Login mit Gitea" → Weiterleitung zur Gitea-Instanz → Nutzer bestätigt Zugriff → Gitea leitet mit Authorization Code zurück → Backend tauscht Code gegen Access Token → Nutzer ist eingeloggt +**Vorteile:** +- Kein eigenes Auth-System nötig – Gitea übernimmt Passwörter und Sessions +- Nutzeridentität direkt bekannt → Repos und Issues können nutzerbasiert gefiltert werden +- Schreibrechte (Issues erstellen/schließen) nur für den jeweiligen Repo-Owner +- Implementiert mit `golang.org/x/oauth2` – offizielles Go-Paket, keine Drittanbieter-Lib nötig - **Vorteile:** +--- - - Kein eigenes Auth-System nötig - - Nutzeridentität direkt bekannt - - Implementiert mit `golang.org/x/oauth2` +## 🗄️ Datenbank: **PostgreSQL** - --- +**Schema-Übersicht:** - ## 🗄️ Datenbank: PostgreSQL +```sql +-- Gecachte Repo-Informationen +CREATE TABLE projects ( + id SERIAL PRIMARY KEY, + gitea_id INTEGER UNIQUE NOT NULL, + name VARCHAR(255) NOT NULL, + full_name VARCHAR(255) NOT NULL, + description TEXT, + html_url TEXT, + topics TEXT[], -- z.B. ["dashboard", "freelancer"] + language VARCHAR(100), + open_issues INTEGER DEFAULT 0, + last_push TIMESTAMPTZ, + is_private BOOLEAN DEFAULT false, + synced_at TIMESTAMPTZ DEFAULT NOW() +); - **Schema-Übersicht:** +-- Gemanagte Issues / Aufgaben +CREATE TABLE issues ( + id SERIAL PRIMARY KEY, + gitea_id INTEGER NOT NULL, + project_id INTEGER REFERENCES projects(id), + title TEXT NOT NULL, + state VARCHAR(20), -- open / closed + assignee VARCHAR(100), + milestone TEXT, + updated_at TIMESTAMPTZ +); - ```sql - -- Alle Projekte (mit oder ohne Repo-Verknüpfung) - CREATE TABLE projects ( - id SERIAL PRIMARY KEY, - name VARCHAR(255) NOT NULL, - description TEXT, - status VARCHAR(50) DEFAULT 'active', -- active / paused / done - category VARCHAR(100), -- z.B. "software", "hardware", "infra", "personal" - gitea_repo TEXT, -- optional: voller Repo-Name (z.B. "Jannis/mein-projekt") - gitea_id INTEGER, -- optional: Gitea-interne Repo-ID - html_url TEXT, -- optional: Link zur Repo - language VARCHAR(100), -- optional: Hauptsprache der Repo - open_tasks INTEGER DEFAULT 0, - last_activity TIMESTAMPTZ, - created_at TIMESTAMPTZ DEFAULT NOW(), - synced_at TIMESTAMPTZ -- NULL wenn kein Gitea-Sync - ); +-- Webhook-Event-Log +CREATE TABLE webhook_events ( + id SERIAL PRIMARY KEY, + event_type VARCHAR(50), + payload JSONB, + received_at TIMESTAMPTZ DEFAULT NOW() +); +``` - -- Tasks / Aufgaben pro Projekt - CREATE TABLE tasks ( - id SERIAL PRIMARY KEY, - project_id INTEGER REFERENCES projects(id), - gitea_issue_id INTEGER, -- optional: verknüpftes Gitea-Issue - title TEXT NOT NULL, - body TEXT, - state VARCHAR(20) DEFAULT 'open', -- open / closed - priority VARCHAR(20), -- low / medium / high - milestone TEXT, - assignee VARCHAR(100), - updated_at TIMESTAMPTZ DEFAULT NOW() - ); +--- - -- Milestones pro Projekt - CREATE TABLE milestones ( - id SERIAL PRIMARY KEY, - project_id INTEGER REFERENCES projects(id), - title TEXT NOT NULL, - description TEXT, - due_date TIMESTAMPTZ, - closed BOOLEAN DEFAULT false - ); +## 🚀 Roadmap - -- Webhook-Event-Log (nur für repo-gebundene Projekte) - CREATE TABLE webhook_events ( - id SERIAL PRIMARY KEY, - event_type VARCHAR(50), - project_id INTEGER REFERENCES projects(id), - payload JSONB, - received_at TIMESTAMPTZ DEFAULT NOW() - ); - ``` +- [ ] **v0.1** – Repo-Listing via Tag `dashboard`, Polling alle 5 min +- [ ] **v0.2** – Webhook-Listener für Echtzeit-Updates +- [ ] **v0.3** – Issues & Milestones im Dashboard anzeigen +- [ ] **v0.4** – Issues direkt aus dem Dashboard erstellen/schließen (bi-direktional) +- [ ] **v0.5** – Gitea OAuth2 Login +- [ ] **v0.6** – Verknüpfung mit Freelancer-Dashboard (Repos = Projekte) +- [ ] **v1.0** – Multi-User, öffentliche Projektsseiten - --- +--- - ## 🚀 Roadmap +## 🔧 Tech Stack - - **v0.1** – Projekt-Listing: manuelle Projekte anlegen, Repos mit Tag `projekt` automatisch einlesen - - **v0.2** – Webhook-Listener für Echtzeit-Sync bei repo-gebundenen Projekten - - **v0.3** – Tasks & Milestones im Dashboard anzeigen und verwalten - - **v0.4** – Tasks direkt aus dem Dashboard erstellen/schließen (bi-direktional mit Gitea) - - **v0.5** – Gitea OAuth2 Login - - **v0.6** – Kategorien, Filter, Status-Verwaltung für alle Projekttypen - - **v1.0** – Multi-User, öffentliche Projektseiten +| Schicht | Technologie | +|--------------|--------------------------------| +| Frontend | SvelteKit + TailwindCSS | +| Backend | Go + net/http (Standardlib) | +| Datenbank | PostgreSQL + pgx | +| Auth | Gitea OAuth2 + golang.org/x/oauth2 | +| API | Gitea REST API v1 | +| Deployment | Docker Compose | - --- +--- - ## 🔧 Tech Stack +## 📦 Getting Started - | Schicht | Technologie | - |-------------|-------------------------------------| - | Frontend | SvelteKit + TailwindCSS | - | Backend | Go + net/http (Standardlib) | - | Datenbank | PostgreSQL + pgx | - | Auth | Gitea OAuth2 + golang.org/x/oauth2 | - | API | Gitea REST API v1 (optional) | - | Deployment | Docker Compose | +```bash +# Repo klonen +git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard - --- +# Umgebungsvariablen setzen +cp .env.example .env +# GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG eintragen - ## 📦 Getting Started +# Mit Docker starten +docker compose up -d +``` - ```bash - # Repo klonen - git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard +--- - # Umgebungsvariablen setzen - cp .env.example .env - # GITEA_URL, GITEA_TOKEN, DATABASE_URL, PROJEKT_TAG eintragen - - # Mit Docker starten - docker compose up -d - ``` - - --- - - Dieses Projekt ist Teil der persönlichen Projekt-Ideen-Sammlung. - Zugehöriges Übersichts-Repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen) - \ No newline at end of file +*Dieses Projekt ist Teil der persönlichen Projekt-Ideen-Sammlung. Zugehöriges Übersichts-Repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen)* \ No newline at end of file