Files
Webklar-Kundenbereich/server/services/projectInsights.js
T
ClaudeandClaude Opus 5.5 ba9916cfe6 Projektdetails und Fortschritt kundenverständlich
Der Server bereitet Commits, Tickets und Arbeitseinträge für Kunden auf
(server/services/customerProjectView.js), die Rohdaten bleiben intern:
- keine Co-Authored-By-/Signed-off-by-Zeilen und KI-Hinweise, keine
  Commit-Kürzel, Kontonamen, Git-Links oder Branch
- technische Commits (Preview-Config, Merges) ausgeblendet, bekannte
  Automatik-Texte übersetzt, "fix"/"upload" -> "Website aktualisiert"
- Ticketstatus und Arbeitsarten auf Deutsch (Open -> Eingegangen,
  Remote -> Online erledigt, ...), Fortschritt in 4 Schritten
- Akquise-Tickets auch in den Projektdetails verborgen
- /api/projects ohne Gitea-URL, Repo- und Vorlagennamen

Darstellung: Auftragskarte mit Status und Fortschrittsleiste, Zeitleiste
"Letzte Änderungen" nach Tagen, Arbeiten mit Farbe/Symbol je Art und
Arbeitszeit; der Tab "Fortschritt" nutzt dieselben Bausteine. In der
App-Ansicht öffnen sich die Projektdetails als eigene Seite mit Zurück
zu "Projekte".

Tests: npm test (node --test, 22 Fälle).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 18:46:22 +00:00

49 lines
1.7 KiB
JavaScript

import { getRepoInfo, listRepoCommits, getRepoTreeSummary } from './giteaAdmin.js'
// In-Memory-Cache fuer Gitea-Abfragen (Commits/Groesse/Dateibaum) pro Repo.
// Wird vom Gitea-Webhook nach jedem Push invalidiert.
const cache = new Map() // key: `${repoFullName}:${kind}` -> { data, expiresAt }
const TTL_MS = 5 * 60 * 1000
async function cached(repoFullName, kind, loader) {
const key = `${repoFullName}:${kind}`
const hit = cache.get(key)
if (hit && hit.expiresAt > Date.now()) return hit.data
const data = await loader()
cache.set(key, { data, expiresAt: Date.now() + TTL_MS })
return data
}
export function invalidateProjectCache(repoFullName) {
for (const key of cache.keys()) {
if (key.startsWith(`${repoFullName}:`)) cache.delete(key)
}
}
/** Repo-Info + letzte Commits fuer die Projekt-Detailansicht im Kundenportal. */
export async function getProjectGitInsights(project) {
const repoFullName = project?.repoFullName
if (!repoFullName) return { repo: null, commits: [] }
return cached(repoFullName, 'git', async () => {
const repo = await getRepoInfo(repoFullName)
const commits = await listRepoCommits(repoFullName, {
branch: repo?.defaultBranch || 'main',
// Technische Commits blendet die Kundenansicht aus - etwas mehr holen, damit genug bleiben
limit: 30,
})
return { repo, commits }
})
}
/** Aggregierte Datei-Uebersicht (Top-Level + Groessensummen). */
export async function getProjectFileOverview(project) {
const repoFullName = project?.repoFullName
if (!repoFullName) return null
return cached(repoFullName, 'files', async () => {
const repo = await getRepoInfo(repoFullName)
return getRepoTreeSummary(repoFullName, repo?.defaultBranch || 'main')
})
}