Add conditional localized form definitions

This commit is contained in:
2026-08-01 20:57:26 +02:00
parent 343a208894
commit e2033640a1
11 changed files with 1346 additions and 33 deletions
+82
View File
@@ -3,6 +3,11 @@ import { apiFetch, apiPath, type ApiSettings } from "@govoplan/core-webui";
export type FormValueType = "text" | "multiline_text" | "integer" | "number" | "boolean" | "date" | "datetime" | "email" | "choice" | "multi_choice" | "object" | "list";
export type FormCondition =
| { kind: "predicate"; field_key: string; operator: "eq" | "neq" | "lt" | "lte" | "gt" | "gte" | "in" | "not_in" | "contains" | "is_empty" | "is_not_empty"; value?: unknown }
| { kind: "all" | "any"; conditions: FormCondition[] }
| { kind: "not"; conditions: [FormCondition] };
export type FormFieldDefinition = {
key: string;
label: string;
@@ -12,6 +17,35 @@ export type FormFieldDefinition = {
options: string[];
constraints: Record<string, unknown>;
default_value?: unknown;
visibility_condition?: FormCondition | null;
accessibility?: Record<string, unknown>;
};
export type FormSectionDefinition = {
key: string;
title: string;
description?: string | null;
field_keys: string[];
visibility_condition?: FormCondition | null;
};
export type FormPageDefinition = {
key: string;
title: string;
description?: string | null;
sections: FormSectionDefinition[];
visibility_condition?: FormCondition | null;
};
export type FormLocalization = {
locale: string;
title?: string | null;
description?: string | null;
field_labels: Record<string, string>;
field_help_texts: Record<string, string>;
option_labels: Record<string, Record<string, string>>;
page_titles: Record<string, string>;
section_titles: Record<string, string>;
};
export type FormDefinition = {
@@ -40,9 +74,21 @@ export type FormDefinition = {
signature_requirement: "none" | "optional" | "required";
policy_refs: string[];
handoff_kinds: string[];
pages?: FormPageDefinition[];
fallback_locale?: string | null;
localizations?: FormLocalization[];
accessibility?: Record<string, unknown>;
metadata: Record<string, unknown>;
};
export type FormPackageFragment = {
kind: "govoplan.forms.definition";
contract_version: "0.1.0";
definition: FormDefinition;
definition_sha256: string;
provenance: Record<string, unknown>;
};
export function listFormDefinitions(
settings: ApiSettings,
options: { query?: string; states?: string[]; offset?: number; limit?: number } = {},
@@ -69,3 +115,39 @@ export function saveFormDefinition(
})
});
}
export function exportFormDefinitionPackage(
settings: ApiSettings,
formId: string,
revision: string
): Promise<FormPackageFragment> {
return apiFetch(settings, apiPath(`/api/v1/forms/definitions/${encodeURIComponent(formId)}/package`, { revision }));
}
export function assessFormDefinitionPackage(
settings: ApiSettings,
fragment: FormPackageFragment
): Promise<{ outcome: string; requires_remap: boolean; current_revision?: string | null }> {
return apiFetch(settings, "/api/v1/forms/packages/assess", {
method: "POST",
body: JSON.stringify({ fragment })
});
}
export function importFormDefinitionPackage(
settings: ApiSettings,
fragment: FormPackageFragment,
options: { targetFormId?: string; targetKey?: string; expectedRevision?: string; changeReason: string }
): Promise<FormDefinition> {
return apiFetch(settings, "/api/v1/forms/packages/import", {
method: "POST",
body: JSON.stringify({
fragment,
target_form_id: options.targetFormId || null,
target_key: options.targetKey || null,
expected_revision: options.expectedRevision || null,
change_reason: options.changeReason,
recorded_at: new Date().toISOString()
})
});
}