diff --git a/README.md b/README.md index dca674b..571cc4c 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,94 @@ -# πŸ—‚οΈ Gitea Projekt-Dashboard +# πŸ—‚οΈ Gitea Project Dashboard > [!WARNING] -> **⏸️ Projekt pausiert** +> **⏸️ Project paused** > -> Dieses Projekt ist aktuell pausiert. Ich entwickle eine eigene LΓΆsung weiter, die Beego ersetzen soll. -> Sobald mein eigenes Web-Framework weit genug ist, wird dieses Projekt damit neu aufgesetzt. +> This project is currently paused. I am continuing to develop my own solution to replace Beego. Once my own web framework is far enough along, this project will be rebuilt with it. > -> πŸ‘‰ **Eigene LΓΆsung in Entwicklung:** [go-webframework](https://gitea.starfour.de/Jannis/go-webframework) +> πŸ‘‰ **Own solution in development:** [go-webframework](https://gitea.starfour.de/Jannis/go-webframework) - -Ein selbst gehostetes Dashboard zur zentralen Verwaltung aller persΓΆnlichen Projekte – technische wie nicht-technische. Projekte kΓΆnnen mit einer Gitea-Repository verknΓΌpft sein, mΓΌssen es aber nicht. +A self-hosted dashboard for centrally managing all personal projects – technical and non-technical alike. Projects can be linked to a Gitea repository, but don't have to be. --- -## 🏷️ Funktionsprinzip: Tag-basierte Projektanzeige +## 🏷️ How It Works: Tag-Based Project Display -Jedes Repository, das auf dieser Gitea-Instanz mit dem Topic-Tag `dashboard` versehen ist, wird automatisch im Dashboard angezeigt. +Every repository on this Gitea instance that has the topic tag `dashboard` is automatically shown in the dashboard. -### So funktioniert es: +### How it works: +1. In a Gitea repository, go to **Settings β†’ Topics** and add the tag `dashboard` +2. The backend service polls the Gitea API regularly (or via webhook) for all repos with this tag +3. The found repos are stored and cached in the PostgreSQL database +4. The frontend displays all tagged repos as project cards with live data -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 - -> **Beispiel:** Repo `mein-projekt` bekommt das Topic `dashboard` β†’ erscheint sofort im Dashboard mit Issues, letztem Commit, Status und Beschreibung. +> **Example:** Repo `my-project` gets the topic `dashboard` β†’ immediately appears in the dashboard with issues, last commit, status, and description. --- -## 🧱 Architektur +## 🧱 Architecture ``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” Gitea REST API v1 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Gitea Server β”‚ ◄────────────────────────► β”‚ Backend Service β”‚ -β”‚ (Repos + Topics)β”‚ β”‚ (Go, net/http) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ PostgreSQL DB β”‚ - β”‚ (Repos, Issues, β”‚ - β”‚ Milestones, Cache) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ 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** +**Why 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 +- Lightweight and fast – ideal for an internal dashboard +- Server-Side Rendering (SSR) out of the box – no flickering on load +- Simple reactivity without overhead +- Perfect for data-driven dashboards with real-time updates via SSE or WebSocket -**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 +**Frontend features:** ---- +- Project cards with repo name, description, last commit, open issues +- Filter function by topics, language, activity +- Detail view: edit issues & milestones directly in the dashboard (bi-directional) +- Live updates via webhook events (Server-Sent Events) +- Dark mode, responsive design -## βš™οΈ Backend: **Go (net/http + pgx)** +## βš™οΈ 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. +Go is an excellent backend language – the standard library is so complete that no web framework is needed. `net/http` provides everything required: routing, handlers, middleware. The result is a dependency-light, readable codebase. -**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 +**Why no framework?** -**Externe Dependencies (minimal):** -- `pgx` – PostgreSQL-Treiber (direktes SQL, kein ORM) -- `godotenv` – `.env`-Datei laden -- `golang.org/x/oauth2` – OAuth2-Flow fΓΌr Gitea-Login +- `net/http` from the standard library is fully sufficient for ~6 endpoints +- No framework overhead, no breaking changes from external dependencies +- The Go-typical approach: explicit, simple, readable +- Compiles to a single static binary – minimal Docker footprint -**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) +**External dependencies (minimal):** + +- `pgx` – PostgreSQL driver (direct SQL, no ORM) +- `godotenv` – load `.env` file +- `golang.org/x/oauth2` – OAuth2 flow for Gitea login + +**Backend tasks:** + +- `GET /api/projects` – return all tagged repos from the DB +- `POST /api/webhook` – Gitea webhook listener for push, issue, tag events +- `GET /api/projects/{id}/issues` – fetch issues for a repo live from Gitea +- Background goroutine: query Gitea API every 5 minutes for repos with tag `dashboard` +- Cache repo data in PostgreSQL (incl. topics, last activity, issue count) + +**Example – HTTP server without a framework:** -**Beispiel – HTTP-Server ohne Framework:** ```go mux := http.NewServeMux() mux.HandleFunc("GET /api/projects", h.listProjects) @@ -99,120 +98,104 @@ mux.HandleFunc("GET /api/projects/{id}/issues", h.listIssues) log.Fatal(http.ListenAndServe(":8080", mux)) ``` ---- +## πŸ” Auth: Gitea OAuth2 -## πŸ” Auth: **Gitea OAuth2** +Gitea can act as its own OAuth2 provider – users log into the dashboard with their Gitea account, just like "Login with GitHub". -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:** +1. In Gitea under **Settings β†’ Applications β†’ OAuth2 Applications**, register a new app +2. Enter Client ID and Client Secret in the `.env` file +3. Set the Redirect URI to `https://dashboard.example.com/auth/callback` -### Setup in Gitea: +**Flow:** +- User clicks "Login with Gitea" +- β†’ Redirect to Gitea instance (Authorization Endpoint) +- β†’ User confirms access +- β†’ Gitea redirects back with Authorization Code +- β†’ Backend exchanges code for Access Token +- β†’ User is logged in, Gitea identity is known -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 +**Advantages:** -### Flow: +- No custom auth system needed – Gitea handles passwords and sessions +- User identity directly available β†’ repos and issues can be filtered per user +- Write permissions (create/close issues) only for the respective repo owner +- Implemented with `golang.org/x/oauth2` – official Go package, no third-party lib needed -``` -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 -``` +## πŸ—„οΈ Database: PostgreSQL -**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 - ---- - -## πŸ—„οΈ Datenbank: **PostgreSQL** - -**Schema-Übersicht:** +**Schema overview:** ```sql --- Gecachte Repo-Informationen +-- Cached repo information 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() + 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[], -- e.g. ["dashboard", "freelancer"] + language VARCHAR(100), + open_issues INTEGER DEFAULT 0, + last_push TIMESTAMPTZ, + is_private BOOLEAN DEFAULT false, + synced_at TIMESTAMPTZ DEFAULT NOW() ); --- Gemanagte Issues / Aufgaben +-- Managed issues / tasks 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 + 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 ); --- Webhook-Event-Log +-- Webhook event log CREATE TABLE webhook_events ( - id SERIAL PRIMARY KEY, - event_type VARCHAR(50), - payload JSONB, - received_at TIMESTAMPTZ DEFAULT NOW() + id SERIAL PRIMARY KEY, + event_type VARCHAR(50), + payload JSONB, + received_at TIMESTAMPTZ DEFAULT NOW() ); ``` ---- - ## πŸš€ Roadmap - -- [ ] **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 - ---- +- v0.1 – Repo listing via tag `dashboard`, polling every 5 min +- v0.2 – Webhook listener for real-time updates +- v0.3 – Display issues & milestones in the dashboard +- v0.4 – Create/close issues directly from the dashboard (bi-directional) +- v0.5 – Gitea OAuth2 login +- v0.6 – Integration with freelancer dashboard (repos = projects) +- v1.0 – Multi-user, public project pages ## πŸ”§ Tech Stack -| 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 | - ---- +| Layer | Technology | +|----------|-------------------------------------| +| Frontend | SvelteKit + TailwindCSS | +| Backend | Go + net/http (standard lib) | +| Database | PostgreSQL + pgx | +| Auth | Gitea OAuth2 + golang.org/x/oauth2 | +| API | Gitea REST API v1 | +| Deploy | Docker Compose | ## πŸ“¦ Getting Started ```bash -# Repo klonen +# Clone the repo git clone https://gitea.starfour.de/Jannis/gitea-projekt-dashboard -# Umgebungsvariablen setzen +# Set environment variables cp .env.example .env -# GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG eintragen +# Fill in GITEA_URL, GITEA_TOKEN, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, DATABASE_URL, DASHBOARD_TAG -# Mit Docker starten +# Start with Docker 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 +This project is part of the personal project ideas collection. Related overview repo: [projekt-ideen](https://gitea.starfour.de/Jannis/projekt-ideen) \ No newline at end of file