Add manual 'Save result' to all tools — replaces auto-save

All tool results can now be saved to My Case manually. Users click
'Save result', type a description, and confirm. This replaces the
previous silent auto-save on barnevernet/timeline/etc., giving users
control over what stays and what it's called (supports multiple runs
of the same tool with different titles).

- CaseResults: extend ELIGIBLE_TOOLS to include summarize, ask, redact,
  transcribe; add toolLabel/toolIcon entries; support explicit title
  via meta['title'] in save()
- api/case/save-result.php: new client-initiated save endpoint;
  accepts tool + title + input_payload + output_payload + meta
- Remove CaseResults::save() auto-save from barnevernet, deep-research,
  discrepancy, korrespond, timeline API endpoints
- tools.js: add showSaveResultButton() (exposed as window.dbnShowSaveResultButton);
  wire for ask, redact, timeline, transcribe (both file-upload and
  stored-audio paths)
- barnevernet.js: wire save button after final result render
- summarize.js: wire save button after renderFinal(); passes sumResults
  container so widget appears in the correct #sumResults div
- case-result.php: rich tool-specific rendering for summarize, ask,
  redact, transcribe, timeline; update re-run link map to include all
  new tools
- tools.css: styles for .save-result-widget and its states (idle,
  prompt, done, error)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 01:27:26 +02:00
parent 0fcfed1a86
commit 2013648ee0
12 changed files with 473 additions and 80 deletions
+94
View File
@@ -9173,3 +9173,97 @@ body.lt-landing {
.account-survey-cta span { font-size: 0.8rem; opacity: 0.85; }
.account-survey-cta:hover { background: #fde68a; }
/* ── Save result widget ────────────────────────────────────────────────────── */
.save-result-widget {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.55rem 0.75rem;
margin-bottom: 1rem;
background: #f0f4ff;
border: 1px solid #c7d3f5;
border-radius: 8px;
font-size: 0.85rem;
}
.save-result-btn {
background: none;
border: 1px solid var(--dbn-blue, #00205b);
color: var(--dbn-blue, #00205b);
border-radius: 6px;
padding: 0.3rem 0.75rem;
font-size: 0.82rem;
font-weight: 500;
cursor: pointer;
transition: background 0.15s, color 0.15s;
white-space: nowrap;
}
.save-result-btn:hover {
background: var(--dbn-blue, #00205b);
color: #fff;
}
.save-result-prompt {
display: flex;
align-items: center;
gap: 0.4rem;
width: 100%;
flex-wrap: wrap;
}
.save-result-input {
flex: 1 1 240px;
min-width: 0;
border: 1px solid var(--line, #d8dde7);
border-radius: 6px;
padding: 0.3rem 0.6rem;
font-size: 0.82rem;
color: var(--dbn-ink, #16130f);
background: #fff;
}
.save-result-input:focus {
outline: 2px solid var(--dbn-blue, #00205b);
outline-offset: 1px;
}
.save-result-confirm {
background: var(--dbn-blue, #00205b);
color: #fff;
border: none;
border-radius: 6px;
padding: 0.3rem 0.75rem;
font-size: 0.82rem;
font-weight: 600;
cursor: pointer;
}
.save-result-confirm:disabled { opacity: 0.55; cursor: default; }
.save-result-cancel {
background: none;
border: 1px solid var(--line, #d8dde7);
border-radius: 6px;
padding: 0.3rem 0.6rem;
font-size: 0.82rem;
cursor: pointer;
color: var(--muted, #667085);
}
.save-result-cancel:hover { border-color: #aaa; }
.save-result-done {
width: 100%;
}
.save-result-link {
color: var(--dbn-teal, #0f766e);
font-weight: 600;
text-decoration: none;
font-size: 0.85rem;
}
.save-result-link:hover { text-decoration: underline; }
.save-result-error {
color: var(--coral, #c2410c);
margin: 0;
font-size: 0.82rem;
width: 100%;
}