import m from "mithril" /** * Datenmodell für einen Tag (hierarchische Taxonomie). * Die Feldnamen entsprechen den serverseitigen ORM-Spalten (snake_case). * Tags koennen beliebig verschachtelt werden (parent_id -> tags.id). */ export interface iTag { id: number name: string description: string color: string parent_id: number | null is_parent: boolean /** True = Kontakt gilt als erledigt, wenn dieser Tag zugewiesen wird. */ is_erledigend: boolean /** True = Tag löst eine Wiedervorlage aus. */ loest_wiedervorlage_aus: boolean /** Tage bis zur Wiedervorlage (nur relevant, wenn loest_wiedervorlage_aus True). */ wiedervorlage_abstand_tage: number | null } /** * Tag mit verschachtelten Kindern für die Hierarchie-Darstellung. * Das children-Array wird serverseitig im Hierarchie-Endpunkt befüllt. */ export interface iTagWithChildren extends iTag { children: iTagWithChildren[] } /* ------------------------------------------------------------------ */ /* REST-API-Aufrufe (Client-Seite) */ /* ------------------------------------------------------------------ */ /* Die folgenden Funktionen kapseln die Kommunikation mit den */ /* serverseitigen REST-Endpunkten (/xhr/tag/*). */ /* ------------------------------------------------------------------ */ /** * Basis-Pfad der Tag-REST-Endpunkte. */ const TAG_REST_BASE = "/xhr/tag" /** * Lädt alle Tags als flache Liste vom Server. * Ist parentId gesetzt, werden nur die direkten Kinder dieses Tags * geliefert (serverseitige Filterung). */ export function fetchTags(parentId?: number): Promise { const params: Record = {} if (parentId !== undefined) { params.parent_id = parentId } return m.request({ method: "GET", url: TAG_REST_BASE + "/list", params: params }).then((result) => result as iTag[]) } /** * Lädt die vollständige Tag-Hierarchie als verschachtelte Struktur vom Server. * Jeder Tag enthält ein children-Array mit seinen rekursiv eingebetteten Kindern. */ export function fetchTagHierarchy(): Promise { return m.request({ method: "GET", url: TAG_REST_BASE + "/hierarchy" }).then((result) => result as iTagWithChildren[]) } /** * Lädt einen einzelnen Tag anhand seiner ID vom Server. */ export function fetchTagById(id: number): Promise { return m.request({ method: "GET", url: TAG_REST_BASE + "/get", params: {id: id} }).then((result) => result as iTag) } /** * Legt einen neuen Tag serverseitig an. Die ID wird vom Server * vergeben und im zurückgegebenen Tag-Objekt gesetzt. */ export function createTagREST(tag: iTag): Promise { return m.request({ method: "POST", url: TAG_REST_BASE + "/create", body: tag }).then((result) => result as iTag) } /** * Aktualisiert einen bestehenden Tag serverseitig. */ export function updateTagREST(tag: iTag): Promise { return m.request({ method: "PUT", url: TAG_REST_BASE + "/update", body: tag }).then((result) => result as iTag) } /** * Löscht einen Tag inkl. aller Nachfahren serverseitig anhand seiner ID. */ export function deleteTagREST(id: number): Promise { return m.request({ method: "DELETE", url: TAG_REST_BASE + "/delete", params: {id: id} }).then(() => undefined) } /* ------------------------------------------------------------------ */ /* Fachliche Hilfsfunktionen */ /* ------------------------------------------------------------------ */ /** * Berechnet das Wiedervorlage-Datum automatisch aus den ausgewählten * Tags. Basis ist das übergebene Basisdatum (z.B. das Datum der Notiz * oder heute). Aus allen ausgewählten Tags mit * loest_wiedervorlage_aus=True wird das Minimum von * wiedervorlage_abstand_tage ermittelt und zum Basisdatum addiert. * Liefert einen leeren String, wenn kein Tag mit * loest_wiedervorlage_aus=True ausgewählt ist. * * Wird von der Call_Log-Maske und der Tages-Workflow-Maske genutzt, * damit die Berechnungslogik nur an einer Stelle gepflegt wird. */ export function berechneWiedervorlageDatum(tagIds: number[], tagListe: iTag[], basisdatum: string): string { const wvTags = tagListe.filter((t: iTag) => tagIds.includes(t.id) && t.loest_wiedervorlage_aus && t.wiedervorlage_abstand_tage != null ) if (wvTags.length === 0) return "" const minAbstand = Math.min(...wvTags.map(t => t.wiedervorlage_abstand_tage as number)) const basisDate = new Date(basisdatum) basisDate.setDate(basisDate.getDate() + minAbstand) return basisDate.toISOString().split('T')[0] }