feat(tickets): Rückfragen-Dialog, Verlinkungen, Entwurfssicherung + PWA-Vorbereitung
- Feedback: fixNote (Changelog), agentContext (intern), thread (Q&A-Verlauf); 3 gefilterte Ansichten (Rückfragen/Offen/Geschlossen) - Tickets-Text: klickbare Tier-Links (ID→Name), Ticket→Ticket-Links (?focus=), Markdown-Links; Antwort-Entwurf pro Ticket in localStorage - "Fehler melden": Entwurf übersteht App-Wechsel/Schließen (ein gemeinsamer Entwurf) - entityName als Hyperlink zum referenzierten Datensatz Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -412,6 +412,9 @@ export async function installMockApi(page: Page): Promise<MockDb> {
|
||||
question: null,
|
||||
answer: null,
|
||||
answeredAt: null,
|
||||
fixNote: null,
|
||||
agentContext: null,
|
||||
thread: [],
|
||||
}
|
||||
db.feedback.push(created)
|
||||
return json(route, 201, created)
|
||||
@@ -433,19 +436,34 @@ export async function installMockApi(page: Page): Promise<MockDb> {
|
||||
status?: string
|
||||
question?: string
|
||||
answer?: string
|
||||
fixNote?: string
|
||||
agentContext?: string
|
||||
}
|
||||
const row = db.feedback[idx]
|
||||
if (typeof body.message === 'string') {
|
||||
if (!body.message.trim()) return json(route, 400, 'Message darf nicht leer sein.')
|
||||
row.message = body.message.trim()
|
||||
}
|
||||
// Rückfrage anhängen → NeedsInfo (außer bereits Resolved).
|
||||
// Rückfrage anhängen → NeedsInfo (außer bereits Resolved). Eine vorhandene
|
||||
// Frage/Antwort-Runde wird zuerst in den Verlauf (thread) verschoben.
|
||||
if (typeof body.question === 'string') {
|
||||
const q = body.question.trim()
|
||||
row.question = q.length === 0 ? null : q
|
||||
if (row.question && row.status !== 'Resolved') {
|
||||
row.status = 'NeedsInfo'
|
||||
row.resolvedAt = null
|
||||
if (q.length > 0) {
|
||||
const thread = (row.thread as Record<string, unknown>[] | undefined) ?? []
|
||||
if (typeof row.question === 'string' && row.question)
|
||||
thread.push({ role: 'maintainer', text: row.question, at: row.createdAt ?? null })
|
||||
if (typeof row.answer === 'string' && row.answer)
|
||||
thread.push({ role: 'breeder', text: row.answer, at: row.answeredAt ?? null })
|
||||
row.thread = thread
|
||||
row.answer = null
|
||||
row.answeredAt = null
|
||||
row.question = q
|
||||
if (row.status !== 'Resolved') {
|
||||
row.status = 'NeedsInfo'
|
||||
row.resolvedAt = null
|
||||
}
|
||||
} else {
|
||||
row.question = null
|
||||
}
|
||||
}
|
||||
// Antwort der Züchterin → Answered + answeredAt.
|
||||
@@ -471,6 +489,16 @@ export async function installMockApi(page: Page): Promise<MockDb> {
|
||||
: 'Open'
|
||||
row.resolvedAt = resolved ? (row.resolvedAt ?? new Date().toISOString()) : null
|
||||
}
|
||||
// Changelog (fixNote) — laienverständlich, sichtbar.
|
||||
if (typeof body.fixNote === 'string') {
|
||||
const note = body.fixNote.trim()
|
||||
row.fixNote = note.length === 0 ? null : note
|
||||
}
|
||||
// Internes Agenten-Arbeitsgedächtnis — ändert den Status nicht.
|
||||
if (typeof body.agentContext === 'string') {
|
||||
const c = body.agentContext.trim()
|
||||
row.agentContext = c.length === 0 ? null : c
|
||||
}
|
||||
return json(route, 200, row)
|
||||
}
|
||||
if (method === 'DELETE') {
|
||||
|
||||
Reference in New Issue
Block a user