mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
feat(documents): pick documents from Paperless-ngx or Papra in the vault and wherever documents are linked
A settings card under Integrations connects either system and tests it before saving. An import button beside Upload in Documents, on a condition's documents card, and beside Add in the visit and vaccination document pickers opens a sheet that searches by name with tag and date filters, shows what HealthLog already holds, and imports the ticked documents one at a time with a result per row. The buttons appear only for a person in their own record with a connection; strings in all seven languages.
This commit is contained in:
1 parent
92f2cc729f
commit
d109d67889
21 files changed
+2200
-20
No files matched your search
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* The document picker's error codes (#1038), as sentences. One place for the
|
||||
* sheet and the settings card, so the same refusal reads the same on both.
|
||||
* Every branch names its key literally so the i18n coverage guard can see it.
|
||||
*/
|
||||
import { ApiError } from "@/lib/api/api-fetch";
|
||||
|
||||
type T = (key: string, params?: Record<string, string | number>) => string;
|
||||
|
||||
/** The `meta.errorCode` a failed request carried, if any. */
|
||||
export function errorCodeOf(err: unknown): string | undefined {
|
||||
if (err instanceof ApiError) {
|
||||
const code = err.meta?.errorCode;
|
||||
if (typeof code === "string") return code;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Is this a refusal that will not change on the next document? */
|
||||
export function isStoppingError(code: string | undefined): boolean {
|
||||
return (
|
||||
code === "documents.inbound.rateLimited" ||
|
||||
code === "documents.inbound.quotaExceeded" ||
|
||||
code === "documents.sources.authRefused" ||
|
||||
code === "documents.sources.unreachable" ||
|
||||
code === "documents.sources.originNotAllowed" ||
|
||||
code === "documents.sources.notConnected" ||
|
||||
code === "documents.sources.unavailable" ||
|
||||
code === "documents.sources.browserOnly" ||
|
||||
code === "documents.sources.linkTargetNotFound"
|
||||
);
|
||||
}
|
||||
|
||||
export function sourceErrorMessage(t: T, code: string | undefined): string {
|
||||
switch (code) {
|
||||
case "documents.sources.unavailable":
|
||||
return t("documents.sourcePicker.errors.unavailable");
|
||||
case "documents.sources.notConnected":
|
||||
return t("documents.sourcePicker.errors.notConnected");
|
||||
case "documents.sources.originNotAllowed":
|
||||
return t("documents.sourcePicker.errors.originNotAllowed");
|
||||
case "documents.sources.unreachable":
|
||||
return t("documents.sourcePicker.errors.unreachable");
|
||||
case "documents.sources.redirected":
|
||||
return t("documents.sourcePicker.errors.redirected");
|
||||
case "documents.sources.authRefused":
|
||||
return t("documents.sourcePicker.errors.authRefused");
|
||||
case "documents.sources.versionTooOld":
|
||||
return t("documents.sourcePicker.errors.versionTooOld");
|
||||
case "documents.sources.badResponse":
|
||||
return t("documents.sourcePicker.errors.badResponse");
|
||||
case "documents.sources.notFound":
|
||||
return t("documents.sourcePicker.errors.notFound");
|
||||
case "documents.sources.linkTargetNotFound":
|
||||
return t("documents.sourcePicker.errors.linkTargetNotFound");
|
||||
case "documents.sources.rateLimited":
|
||||
return t("documents.sourcePicker.errors.rateLimited");
|
||||
case "documents.sources.browserOnly":
|
||||
return t("documents.sourcePicker.errors.browserOnly");
|
||||
case "documents.sources.invalidAddress":
|
||||
return t("documents.sourcePicker.errors.invalidAddress");
|
||||
case "documents.sources.organizationRequired":
|
||||
return t("documents.sourcePicker.errors.organizationRequired");
|
||||
case "documents.sources.tokenRequired":
|
||||
return t("documents.sourcePicker.errors.tokenRequired");
|
||||
case "documents.inbound.fileTooLarge":
|
||||
return t("documents.sourcePicker.errors.fileTooLarge");
|
||||
case "documents.inbound.quotaExceeded":
|
||||
return t("documents.sourcePicker.errors.quotaExceeded");
|
||||
case "documents.inbound.fileType":
|
||||
return t("documents.sourcePicker.errors.fileType");
|
||||
case "documents.inbound.rateLimited":
|
||||
return t("documents.sourcePicker.errors.uploadLimit");
|
||||
case "documents.inbound.uploadBusy":
|
||||
return t("documents.sourcePicker.errors.uploadBusy");
|
||||
case "module.disabled":
|
||||
return t("documents.sourcePicker.errors.moduleDisabled");
|
||||
default:
|
||||
return t("documents.sourcePicker.errors.generic");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user