mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
Merge branch 'fix/v1437-data' into release/v1.43.7
This commit is contained in:
commit
dee6a27ae4
100 files changed
+2314
-506
No files matched your search
@@ -22,6 +22,8 @@ import {
|
||||
resolveBulkShareDocuments,
|
||||
SHARE_LINK_MAX_DOCUMENTS,
|
||||
vaultFiltersToSearch,
|
||||
STAGED_ATTACHMENT_POLL_MS,
|
||||
stagedAttachmentPollInterval,
|
||||
} from "../vault-utils";
|
||||
|
||||
function doc(overrides: Partial<InboundDocumentDto> = {}): InboundDocumentDto {
|
||||
@@ -541,3 +543,36 @@ describe("buildProcedureChoices", () => {
|
||||
expect(buildProcedureChoices([], null, labels)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("stagedAttachmentPollInterval", () => {
|
||||
const now = Date.parse("2026-10-20T10:00:00Z");
|
||||
const at = (msAgo: number) => new Date(now - msAgo).toISOString();
|
||||
|
||||
it("polls a fresh upload until its index lands", () => {
|
||||
expect(
|
||||
stagedAttachmentPollInterval(
|
||||
{ createdAt: at(30_000), hasContentIndex: false },
|
||||
now,
|
||||
),
|
||||
).toBe(STAGED_ATTACHMENT_POLL_MS);
|
||||
expect(
|
||||
stagedAttachmentPollInterval(
|
||||
{ createdAt: at(30_000), hasContentIndex: true },
|
||||
now,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("stops polling a document that is never indexed once the window passes", () => {
|
||||
expect(
|
||||
stagedAttachmentPollInterval(
|
||||
{ createdAt: at(RECENT_UPLOAD_WINDOW_MS + 1), hasContentIndex: false },
|
||||
now,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("does not poll before the detail has loaded", () => {
|
||||
expect(stagedAttachmentPollInterval(undefined, now)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -167,6 +167,26 @@ export function isDocumentProcessing(
|
||||
return !doc.hasContentIndex && isRecentlyUploaded(doc.createdAt, now);
|
||||
}
|
||||
|
||||
/**
|
||||
* How often the Coach polls a staged attachment for its content index.
|
||||
*
|
||||
* The same "still processing" question the vault list asks, so the same
|
||||
* bounded window answers it: a document that will never be indexed (an
|
||||
* unsupported format, indexing disabled) used to be polled every 2.5 s for as
|
||||
* long as the Coach stayed open. `false` once the index exists or the window
|
||||
* has passed.
|
||||
*/
|
||||
export const STAGED_ATTACHMENT_POLL_MS = 2_500;
|
||||
|
||||
export function stagedAttachmentPollInterval(
|
||||
doc: Pick<InboundDocumentDto, "createdAt" | "hasContentIndex"> | undefined,
|
||||
now: number = Date.now(),
|
||||
): number | false {
|
||||
return doc && isDocumentProcessing(doc, now)
|
||||
? STAGED_ATTACHMENT_POLL_MS
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether ANY document in the list is still inside its processing window —
|
||||
* drives the vault list query's poll-while-indexing `refetchInterval`.
|
||||
|
||||
@@ -21,7 +21,10 @@ import type { CoachLaunchScope } from "@/lib/insights/coach-launch-context";
|
||||
import type { InboundDocumentDetailDto } from "@/lib/validations/inbound-documents";
|
||||
import { MAX_COACH_ATTACHMENTS } from "@/lib/validations/inbound-documents";
|
||||
import { useModuleEnabled } from "@/hooks/use-module-enabled";
|
||||
import { parseUploadResponse } from "@/components/documents/vault-utils";
|
||||
import {
|
||||
parseUploadResponse,
|
||||
stagedAttachmentPollInterval,
|
||||
} from "@/components/documents/vault-utils";
|
||||
import {
|
||||
metricScopeLabelFallback,
|
||||
scopeSourceMetricLabelKey,
|
||||
@@ -399,10 +402,11 @@ export function CoachConversation({
|
||||
queryFn: async () =>
|
||||
apiGet<InboundDocumentDetailDto>(`/api/documents/inbound/${id}`),
|
||||
staleTime: 15_000,
|
||||
// Bounded by the upload processing window, like the vault list: a
|
||||
// document that is never indexed stops being polled.
|
||||
refetchInterval: (query: {
|
||||
state: { data?: InboundDocumentDetailDto };
|
||||
}) =>
|
||||
query.state.data && !query.state.data.hasContentIndex ? 2500 : false,
|
||||
}) => stagedAttachmentPollInterval(query.state.data),
|
||||
})),
|
||||
});
|
||||
const stagedDetailById = new Map<
|
||||
|
||||
@@ -368,7 +368,12 @@ export function AccountSection() {
|
||||
setFieldErrors(describeRejectedProfileFields(json?.details?.issues, t));
|
||||
if (errorCode === "profile.update.nothingSaved" && field) {
|
||||
setSaveMsg({ key: "settings.profileNothingSaved", params: { field } });
|
||||
} else if (errorCode) {
|
||||
} else if (
|
||||
errorCode &&
|
||||
t(`apiErrors.${errorCode}`) !== `apiErrors.${errorCode}`
|
||||
) {
|
||||
// Only a code with a sentence of its own: every refusal carries a
|
||||
// code now, and the generic `http.*` family has no translation.
|
||||
setSaveMsg({ key: `apiErrors.${errorCode}` });
|
||||
} else {
|
||||
setSaveMsg({ key: "settings.savingError" });
|
||||
|
||||
Reference in new issue
Block a user