mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
fix(documents): report picker and card results through the shared outcome line, and register the disconnect as a destructive control
This commit is contained in:
1 parent
d109d67889
commit
9e38ee3a99
4 files changed
+46
-14
No files matched your search
@@ -579,6 +579,13 @@ const REGISTRY: DestructiveEntry[] = [
|
||||
recovery: "permanent",
|
||||
confirm: ["AlertDialog"],
|
||||
})),
|
||||
{
|
||||
file: "components/settings/integrations/document-sources-card.tsx",
|
||||
destroys:
|
||||
"the stored Paperless-ngx or Papra address and API token; documents already imported stay in the vault — reconnecting means typing the token again",
|
||||
recovery: "permanent",
|
||||
confirm: ["AlertDialog"],
|
||||
},
|
||||
];
|
||||
|
||||
// ── Detectors ─────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -161,6 +161,13 @@ const PINNED_AFFORDANCES: Record<
|
||||
"src/components/documents/document-card.tsx": { "text-success": 1 },
|
||||
"src/components/documents/document-detail-sheet.tsx": { "toast.success": 2 },
|
||||
"src/components/documents/documents-view.tsx": { "toast.success": 3 },
|
||||
// The document picker's per-row result: tinted only for the `imported` /
|
||||
// `duplicate` outcome the import route returned for that one document, i.e.
|
||||
// a document the vault now holds. The run's headline goes through
|
||||
// WrittenOutcomeLine; a row sits inside a button, where its <p> cannot.
|
||||
"src/components/documents/sources/document-source-picker.tsx": {
|
||||
"text-success": 1,
|
||||
},
|
||||
"src/components/error-details.tsx": { CheckCircle2: 2, "text-success": 1 },
|
||||
"src/components/illness/episode-menu.tsx": {
|
||||
CheckCircle2: 2,
|
||||
|
||||
@@ -69,6 +69,9 @@ import { invalidateKeys, queryKeys } from "@/lib/query-keys";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { InboundDocumentKindValue } from "@/lib/validations/inbound-documents";
|
||||
|
||||
import { WrittenOutcomeLine } from "@/components/outcome/written-outcome-line";
|
||||
import type { WrittenOutcome } from "@/lib/outcome/written-outcome";
|
||||
|
||||
import { formatBytes } from "../vault-utils";
|
||||
import {
|
||||
errorCodeOf,
|
||||
@@ -306,7 +309,7 @@ export function DocumentSourcePicker({
|
||||
data-slot="document-source-selection"
|
||||
>
|
||||
{finished
|
||||
? t("documents.sourcePicker.summary", counts)
|
||||
? null
|
||||
: running
|
||||
? t("documents.sourcePicker.importing")
|
||||
: t("documents.sourcePicker.selectedCount", {
|
||||
@@ -469,6 +472,14 @@ export function DocumentSourcePicker({
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
{finished ? (
|
||||
<WrittenOutcomeLine
|
||||
outcome={runOutcome(counts)}
|
||||
message={t("documents.sourcePicker.summary", counts)}
|
||||
testId="document-source-summary"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{stopMessage ? (
|
||||
<p
|
||||
role="alert"
|
||||
@@ -597,6 +608,17 @@ export function DocumentSourcePicker({
|
||||
);
|
||||
}
|
||||
|
||||
/** How the run went, in the shared outcome vocabulary. */
|
||||
function runOutcome(counts: {
|
||||
imported: number;
|
||||
present: number;
|
||||
failed: number;
|
||||
}): WrittenOutcome {
|
||||
const held = counts.imported + counts.present;
|
||||
if (counts.failed === 0) return held > 0 ? "success" : "empty";
|
||||
return held > 0 ? "partial" : "failed";
|
||||
}
|
||||
|
||||
/** One row's progress or result, under its title. */
|
||||
function RunLine({ run }: { run: RowRun }) {
|
||||
const { t } = useTranslations();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* (UI standards §12).
|
||||
*/
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Archive, CheckCircle2, Loader2, Unlink } from "lucide-react";
|
||||
import { Archive, Check, Loader2, Unlink } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
import {
|
||||
@@ -38,6 +38,7 @@ import { PasswordInput } from "@/components/ui/password-input";
|
||||
import { SettingsCardActions } from "@/components/settings/_card-actions";
|
||||
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
||||
import { SettingsCard } from "@/components/settings/settings-card";
|
||||
import { WrittenOutcomeLine } from "@/components/outcome/written-outcome-line";
|
||||
import {
|
||||
errorCodeOf,
|
||||
sourceErrorMessage,
|
||||
@@ -111,8 +112,8 @@ export function DocumentSourcesCard() {
|
||||
>
|
||||
{systemName(option)}
|
||||
{isConnected ? (
|
||||
<CheckCircle2
|
||||
className="text-success size-3.5"
|
||||
<Check
|
||||
className="size-3.5"
|
||||
aria-label={t("settings.documentSources.statusConnected")}
|
||||
/>
|
||||
) : null}
|
||||
@@ -328,16 +329,11 @@ function SourceForm({
|
||||
</div>
|
||||
|
||||
{outcome ? (
|
||||
<p
|
||||
role={outcome.tone === "error" ? "alert" : "status"}
|
||||
data-slot="document-sources-outcome"
|
||||
className={cn(
|
||||
"text-sm",
|
||||
outcome.tone === "error" ? "text-destructive" : "text-success",
|
||||
)}
|
||||
>
|
||||
{outcome.message}
|
||||
</p>
|
||||
<WrittenOutcomeLine
|
||||
outcome={outcome.tone === "error" ? "failed" : "success"}
|
||||
message={outcome.message}
|
||||
testId="document-sources-outcome"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<SettingsCardActions>
|
||||
|
||||
Reference in new issue
Block a user