feat(taiga): Status zurückschreiben — zwei Knöpfe, niemand gewinnt von selbst (D91-Nachtrag 8, SPEC §9)
Weicht der Ticket-Status von der Statusbox ab, markiert das Knoten-Fenster
die Abweichung und bietet beide Richtungen ausdrücklich an.
- „nach Taiga schreiben": Spalte des Projekts suchen (Taiga schreibt nach Id,
die Namen sind je Projekt frei) und mit der zuletzt GELESENEN `version`
patchen — hat jemand dazwischen geändert, lehnt Taiga ab und der Text steht
im Fenster, statt dass etwas überschrieben wird.
- „aus Taiga übernehmen": `setStatusBox()` schreibt die Box in die Textzeile,
undo-fähig wie jede andere Änderung.
- Schreibbar sind nur die fünf abgebildeten Zustände; `[?]`, `[!]`, `[-]` und
der neutrale Knoten lassen das Ticket unangetastet — mit Begründung im
Fenster.
- Proxy: zwei Spaltenlisten (`/taiga/{userstory,task}-statuses?slug=`) und
zwei Schreib-Endpunkte (`PATCH …/{ref}/status?slug=`); die Zielspalte wählt
der Editor, das Backend parst die Notation nicht (D14).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4e6f98bbee
commit
323e8fe0ba
+40
-1
@@ -70,9 +70,48 @@ export const TAIGA_STATUS_CODE = {
|
||||
};
|
||||
export function mapTaigaStatus(name){
|
||||
if(typeof name !== 'string') return null;
|
||||
const code = TAIGA_STATUS_CODE[name.trim().toLowerCase().replace(/\s+/g, ' ')];
|
||||
const code = TAIGA_STATUS_CODE[normName(name)];
|
||||
return code ? STATUS_BY_CODE[code] : null;
|
||||
}
|
||||
const normName = s => s.trim().toLowerCase().replace(/\s+/g, ' ');
|
||||
|
||||
/* Die Gegenrichtung (D91-Nachtrag 7/8): Zu welcher Taiga-Spalte gehört eine
|
||||
Statusbox? Nur die fünf abgebildeten Zustände haben eine — `[?]`, `[!]`,
|
||||
`[-]` und der neutrale Knoten (code null) haben keine Entsprechung und
|
||||
lassen das Ticket unangetastet; erfunden wird nichts. */
|
||||
export const TAIGA_STATUS_NAME = Object.fromEntries(
|
||||
Object.entries(TAIGA_STATUS_CODE).map(([name, code]) => [code, name]));
|
||||
export function taigaStatusName(code){
|
||||
const name = code ? TAIGA_STATUS_NAME[code] : null;
|
||||
/* Zurück in die Schreibweise, in der Taiga die Spalten führt — gesucht wird
|
||||
ohnehin normalisiert (`pickStatus`), aber gemeldet wird sie im Klartext. */
|
||||
return name ? name.replace(/^./, c => c.toUpperCase()) : null;
|
||||
}
|
||||
|
||||
/* Die Spalte des Projekts zu einem Namen — Taiga schreibt nach **Id**, und
|
||||
die Namen sind je Projekt frei. Verglichen wird mit derselben
|
||||
Normalisierung wie beim Lesen; findet sich nichts, wird nicht geschrieben
|
||||
(der Aufrufer sagt, welche Spalte fehlte). */
|
||||
export function pickStatus(list, name){
|
||||
if(!Array.isArray(list) || typeof name !== 'string') return null;
|
||||
const gesucht = normName(name);
|
||||
return list.find(s => s && typeof s.name === 'string' && normName(s.name) === gesucht) || null;
|
||||
}
|
||||
|
||||
/* Die beiden Schreib-Pfade am Proxy: der Status des Tickets und die Spalten
|
||||
des Projekts — je Typ ein eigener Endpunkt, wie beim Lesen. */
|
||||
export function statusApiPath(ref, slug){
|
||||
const p = ticketApiPath(ref, slug);
|
||||
if(!p) return null;
|
||||
const [pfad, query] = p.split('?');
|
||||
return pfad + '/status?' + query;
|
||||
}
|
||||
export function statusListPath(ref, slug){
|
||||
const p = refParts(ref);
|
||||
if(!p || !slug) return null;
|
||||
return '/' + (p.kind === 'US' ? 'userstory-statuses' : 'task-statuses') +
|
||||
'?slug=' + encodeURIComponent(slug);
|
||||
}
|
||||
|
||||
/* Die Ticket-Referenz unter der Schreibmarke (Strg+Klick im Text,
|
||||
D91-Nachtrag 5): ein FREISTEHENDES `#US-123`/`#T-1234`-Token im Baumteil.
|
||||
|
||||
Reference in New Issue
Block a user