mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
refactor(admin): split the backups section
The section becomes a composer over backups/: the restore dialog with its preview, the refusal, skip and schedule notices, the restore jobs and their request, the upload flow, the run and download actions, and the two row layouts sharing one action pair. The upload total is a pure function and tested as one. The read-failure guard's 250-character window had stopped reaching the restore preview's own failure lines; the preview now sits in a smaller component, the guard sees it, and it is listed as a deliberate exception with its reason.
This commit is contained in:
1 parent
c9917d2de0
commit
5eafed8dd5
19 files changed
+1533
-1348
No files matched your search
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 113,
|
||||
"total": 130546,
|
||||
"count": 112,
|
||||
"total": 129084,
|
||||
"entries": {
|
||||
"app/api/dashboard/summary/route.ts": 1032,
|
||||
"app/api/documents/inbound/route.ts": 811,
|
||||
@@ -12,7 +12,6 @@
|
||||
"app/api/medications/intake/bulk/route.ts": 1044,
|
||||
"app/api/workouts/batch/route.ts": 958,
|
||||
"app/medications/page-client.tsx": 839,
|
||||
"components/admin/backups-section.tsx": 1462,
|
||||
"components/charts/mood-chart.tsx": 1166,
|
||||
"components/cycle/log-day-sheet.tsx": 1639,
|
||||
"components/insights/coach-panel/chat-bubble.tsx": 888,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 401,
|
||||
"total": 137456,
|
||||
"count": 399,
|
||||
"total": 136612,
|
||||
"entries": {
|
||||
"app/achievements/page.tsx :: AchievementsPage": 206,
|
||||
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 314,
|
||||
@@ -80,8 +80,6 @@
|
||||
"components/admin/admin-shell.tsx :: AdminShell": 254,
|
||||
"components/admin/api-token-overview-section.tsx :: ApiTokenOverviewSection": 212,
|
||||
"components/admin/app-log-preview-section.tsx :: AppLogPreviewSection": 341,
|
||||
"components/admin/backups-section.tsx :: BackupsSection": 618,
|
||||
"components/admin/backups-section.tsx :: RestoreRowDialog": 226,
|
||||
"components/admin/central-codex-section.tsx :: CentralCodexSection": 241,
|
||||
"components/admin/encryption-section.tsx :: EncryptionSection": 303,
|
||||
"components/admin/general-settings-section.tsx :: GeneralSettingsSection": 220,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.",
|
||||
"count": 2946,
|
||||
"total": 10225,
|
||||
"count": 2945,
|
||||
"total": 10221,
|
||||
"entries": {
|
||||
"__tests__/account-payload-consumer-guard.test.ts": 2,
|
||||
"__tests__/acting-account-boundary-guard.test.ts": 7,
|
||||
@@ -714,7 +714,6 @@
|
||||
"components/admin/api-token-overview-section.tsx": 5,
|
||||
"components/admin/app-log-preview-section.tsx": 1,
|
||||
"components/admin/assistant-section.tsx": 1,
|
||||
"components/admin/backups-section.tsx": 4,
|
||||
"components/admin/coach-feedback-section.tsx": 1,
|
||||
"components/admin/danger-zone-section.tsx": 1,
|
||||
"components/admin/general-settings-section.tsx": 1,
|
||||
|
||||
@@ -84,7 +84,7 @@ const INVENTORY: Readonly<Record<string, Poll>> = {
|
||||
shape: "until-done",
|
||||
cadence: "2 s until the job reports a terminal status",
|
||||
},
|
||||
"components/admin/backups-section.tsx": {
|
||||
"components/admin/backups/use-backup-restores.ts": {
|
||||
sites: 1,
|
||||
shape: "until-done",
|
||||
cadence: "2 s until no restore is active",
|
||||
|
||||
@@ -107,6 +107,18 @@ function framedRowsInCards(source: string): number[] {
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read failures that draw their own markup on purpose, each with its reason.
|
||||
* Keyed by file, and held live by the case below: an entry whose file no
|
||||
* longer hand-rolls a branch fails rather than lingering as a blind spot.
|
||||
*/
|
||||
const HAND_ROLLED_BY_DESIGN = new Map<string, string>([
|
||||
[
|
||||
"components/admin/backups/restore-dialog.tsx",
|
||||
"the restore preview never blocks the restore: a failed preview states its own absence in the dialog, and names the missing key when that is why",
|
||||
],
|
||||
]);
|
||||
|
||||
const files = walk(SRC).map((file) => ({
|
||||
file: relative(SRC, file),
|
||||
source: readFileSync(file, "utf8"),
|
||||
@@ -143,12 +155,24 @@ describe("read failures render through a primitive", () => {
|
||||
|
||||
it("never hand-rolls one beside a read", () => {
|
||||
const offenders = files.flatMap(({ file, source }) =>
|
||||
readErrorBranches(source)
|
||||
.filter((b) => b.handRolled)
|
||||
.map((b) => `${file}:${b.line}`),
|
||||
HAND_ROLLED_BY_DESIGN.has(file)
|
||||
? []
|
||||
: readErrorBranches(source)
|
||||
.filter((b) => b.handRolled)
|
||||
.map((b) => `${file}:${b.line}`),
|
||||
);
|
||||
expect(offenders).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps every deliberate exception live", () => {
|
||||
const stale = [...HAND_ROLLED_BY_DESIGN.keys()].filter((name) => {
|
||||
const entry = files.find(({ file }) => file === name);
|
||||
return (
|
||||
!entry || !readErrorBranches(entry.source).some((b) => b.handRolled)
|
||||
);
|
||||
});
|
||||
expect(stale).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("an error row inside a card draws no frame of its own", () => {
|
||||
|
||||
@@ -319,7 +319,7 @@ function findGatedWebCalls(): GatedCall[] {
|
||||
const PRECHECKED = new Set<string>([
|
||||
// `upload.mutationFn` asks first, then calls `uploadOnce`, so a large file
|
||||
// is not sent once only to be refused.
|
||||
"components/admin/backups-section.tsx -> POST /api/admin/backups/upload",
|
||||
"components/admin/backups/use-backup-upload.ts -> POST /api/admin/backups/upload",
|
||||
]);
|
||||
|
||||
describe("fresh-proof gates on the web", () => {
|
||||
|
||||
@@ -97,7 +97,10 @@ const PINNED_AFFORDANCES: Record<
|
||||
"src/components/admin/assistant-section.tsx": { "toast.success": 1 },
|
||||
// v1.43 — the AI usage bounds: a settings save, not a write with counts.
|
||||
"src/components/admin/ai-usage-section.tsx": { "toast.success": 1 },
|
||||
"src/components/admin/backups-section.tsx": { "toast.success": 4 },
|
||||
// The run, the download, the upload and the finished restore, one toast each.
|
||||
"src/components/admin/backups/use-backup-actions.ts": { "toast.success": 2 },
|
||||
"src/components/admin/backups/use-backup-restores.ts": { "toast.success": 1 },
|
||||
"src/components/admin/backups/use-backup-upload.ts": { "toast.success": 1 },
|
||||
"src/components/admin/central-codex-section.tsx": { "toast.success": 2 },
|
||||
"src/components/admin/danger-zone-section.tsx": { "text-success": 1 },
|
||||
"src/components/admin/encryption-section.tsx": {
|
||||
|
||||
Reference in new issue
Block a user