feat(taiga): Ticket-Stand im Knoten-Fenster — gelesen, nie geschrieben (D91-Nachtrag 6, SPEC §9)
Wo eine Ref steht und ein `&taiga.<slug>` gilt, zeigt das Knoten-Fenster
Betreff, Status und Zuständigen des Tickets; Taigas Statusname steht neben
der Statusbox der Notation (`In progress → [~]`).
- Proxy: zwei benannte Lese-Endpunkte (`GET /taiga/userstories/{ref}` und
`…/tasks/{ref}`, je `?slug=`) — das Präfix der Ref trägt den Typ, Taiga
hat getrennte `by_ref`-Endpunkte. Erst `/projects/by_slug`, dann `by_ref`
(eine Ref ist nur je Projekt eindeutig); der Slug wird kodiert angehängt.
- Die Abbildung Status → Statusbox liegt im Editor (`mapTaigaStatus`,
headless): Statuscodes sind Notation, das Backend parst sie nicht (D14).
Unbekannte Namen bleiben unabgebildet — Raten hieße, dem Knoten eine
Aussage zu geben, die niemand gemacht hat.
- Geholt wird erst nach 400 ms Verweilen und je Ticket einmal je Sitzung
(↻ holt neu); ohne Anmeldung gar nicht — der Knopf meldet erst an.
- Nichts wird geschrieben: kein Text, keine Statusbox (das bleibt
`#trk.write`).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e58f71bf90
commit
842e89795a
+43
-3
@@ -9,10 +9,20 @@
|
||||
zeigt nur die Nummer. */
|
||||
|
||||
import { gateOf, isDone, isRealized } from './model.js';
|
||||
import { STATUS_BY_CODE } from './parser.js';
|
||||
|
||||
/* Das Tracker-Muster (SPEC §11): `US-\d+` (Story) und `T-\d+` (Task). */
|
||||
export const TICKET_ID_RE = /^(?:US|T)-\d+$/;
|
||||
|
||||
/* Zerlegt eine Ref in Typ und nackte Nummer: `US-123` -> {kind:'US', nr:123}.
|
||||
Das Präfix trägt den Typ (SPEC §11) — daran hängen der Frontend-Pfad
|
||||
(unten), Taigas getrennte `by_ref`-Endpunkte und damit auch der Proxy-Pfad.
|
||||
Ungültiges ergibt null; geraten wird nirgends. */
|
||||
export function refParts(ref){
|
||||
const m = /^(US|T)-(\d+)$/.exec(ref || '');
|
||||
return m ? {kind: m[1], nr: m[2]} : null;
|
||||
}
|
||||
|
||||
/* Trägt die Zeile eines Knotens schon eine Ticket-Referenz? Das ist der
|
||||
Idempotenz-Marker (D91-Nachtrag 2): So ein Knoten wird nicht erneut
|
||||
angelegt. Die Ref ist entweder die Knoten-ID selbst (erstes `#`-Token,
|
||||
@@ -29,9 +39,39 @@ export function ticketRefOf(n){
|
||||
genau dafür schreibt Werkbaum es (SPEC §11). Ohne Web-Basis, Projekt-Slug
|
||||
oder gültige Ref gibt es keine Adresse (null). */
|
||||
export function ticketUrl(web, slug, ref){
|
||||
const m = /^(US|T)-(\d+)$/.exec(ref || '');
|
||||
if(!m || !web || !slug) return null;
|
||||
return web + '/project/' + slug + '/' + (m[1] === 'US' ? 'us' : 'task') + '/' + m[2];
|
||||
const p = refParts(ref);
|
||||
if(!p || !web || !slug) return null;
|
||||
return web + '/project/' + slug + '/' + (p.kind === 'US' ? 'us' : 'task') + '/' + p.nr;
|
||||
}
|
||||
|
||||
/* Der Pfad am Backend-Proxy zum LESEN eines Tickets (D91-Nachtrag 6),
|
||||
relativ zu `/api/v1/taiga`: zwei benannte Endpunkte statt eines mit
|
||||
Typ-Parameter, weil Taiga getrennte `by_ref`-Endpunkte hat. Der Slug
|
||||
kommt als Query dazu (eine Ref ist nur je Projekt eindeutig). */
|
||||
export function ticketApiPath(ref, slug){
|
||||
const p = refParts(ref);
|
||||
if(!p || !slug) return null;
|
||||
return '/' + (p.kind === 'US' ? 'userstories' : 'tasks') + '/' + p.nr +
|
||||
'?slug=' + encodeURIComponent(slug);
|
||||
}
|
||||
|
||||
/* Taiga-Workflow -> Statusbox der Notation (SPEC §4/§9, D91-Nachtrag 6).
|
||||
Die Vorgabe steht in backend/CLAUDE.md; abgebildet wird im **Editor**, denn
|
||||
die Statuscodes sind Notations-Vokabular und das Backend parst die Notation
|
||||
nicht (D14). Groß-/Kleinschreibung und Leerraum sind egal; ein Name
|
||||
außerhalb der Liste bleibt unabgebildet (null) — geraten wird nicht, und
|
||||
Taigas Workflows sind je Projekt frei benennbar. */
|
||||
export const TAIGA_STATUS_CODE = {
|
||||
'new': ' ',
|
||||
'in progress': '~',
|
||||
'ready for test': '/',
|
||||
'done': 'x',
|
||||
'archived': '^',
|
||||
};
|
||||
export function mapTaigaStatus(name){
|
||||
if(typeof name !== 'string') return null;
|
||||
const code = TAIGA_STATUS_CODE[name.trim().toLowerCase().replace(/\s+/g, ' ')];
|
||||
return code ? STATUS_BY_CODE[code] : null;
|
||||
}
|
||||
|
||||
/* Die Ticket-Referenz unter der Schreibmarke (Strg+Klick im Text,
|
||||
|
||||
Reference in New Issue
Block a user