Complete assisted intake provenance UI

This commit is contained in:
2026-08-24 14:03:35 +02:00
parent cc15233a44
commit c4dd146505
12 changed files with 413 additions and 43 deletions
+7
View File
@@ -62,6 +62,10 @@ Runtime form submissions for validation, drafts, attachments, signatures, status
channel, affected and represented party references, authority basis, purpose,
notice, responsible function, language, accessibility needs, and field-level
source/confidence provenance on the same exact Form revision used digitally
- a responsive operator source editor that classifies each populated field
independently, including its confidence and optional governed declaring-party,
document, or source-system reference; it restores the current revision's
retained source map instead of flattening mixed provenance
- append-only assisted read-back outcomes bound to the exact current Form
revision, normalized values, attachments, and signatures; draft corrections
invalidate earlier confirmation evidence and submission fails closed until a
@@ -157,6 +161,9 @@ The immutable outcome identifies the confirming party and operator. Corrections
are saved as a new Form revision and require a new read-back. When confirmation
cannot be obtained, the operator must choose that outcome and record the
exception; policy or downstream review may still stop or escalate the case.
Newly started assisted sessions may be saved as their first ordinary draft;
this is required before read-back whenever the operator entered or corrected
values, attachments, or acknowledgements.
## Approved Intake And Evidence Profiles
+4 -1
View File
@@ -30,4 +30,7 @@ instance revisions, validation, receipts, and handoff evidence.
Native controls preserve keyboard order, shared dialogs manage focus, changed
values use the global unsaved-draft guard, and bounded list/detail regions keep
their existing responsive scrolling. English and German catalogues cover
module-owned copy; definition content uses its own published localization.
module-owned copy; definition content uses its own published localization. The
assisted read-back dialog uses one responsive fieldset per populated value so
mixed person, representative, document, system, and derived provenance remains
legible and independently editable at desktop and mobile widths.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@govoplan/forms-runtime",
"version": "0.1.19",
"version": "0.1.20",
"private": true,
"description": "Definition-aware form submissions and service launch for GovOPlaN.",
"type": "module",
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "govoplan-forms-runtime"
version = "0.1.19"
version = "0.1.20"
description = "Definition-aware form submissions and service launch for GovOPlaN."
readme = "README.md"
requires-python = ">=3.12"
@@ -65,7 +65,7 @@ from govoplan_forms_runtime.backend.status_access import FormStatusAccessService
MODULE_ID = "forms_runtime"
MODULE_NAME = "Forms Runtime"
MODULE_VERSION = "0.1.19"
MODULE_VERSION = "0.1.20"
PARTICIPATE_SCOPE = "forms_runtime:submission:participate"
ASSIST_SCOPE = "forms_runtime:submission:assist"
READ_SCOPE = "forms_runtime:workspace:read"
@@ -674,7 +674,7 @@ manifest = ModuleManifest(
"stable idempotency key. Rejected effects may be retried. Unknown outcomes must be reconciled before retry to avoid a "
"duplicate target. Administrative compensation records verified absence and never deletes a remote target. "
"When Records is enabled, only immutable submitted revisions can be resolved for filing; current Forms Runtime access is rechecked and editable drafts fail closed."
" Assisted intake begins with an authenticated, purpose-bound session. The operator records the channel, party and representation references, authority basis, notice, responsible function, language, accessibility support, and per-field sources. Read-back outcomes are append-only and bind the exact current payload. Corrections must first be saved as a new draft revision and confirmed again; an unavailable confirmation requires an explicit exception note."
" Assisted intake begins with an authenticated, purpose-bound session. The operator records the channel, party and representation references, authority basis, notice, responsible function, language, accessibility support, and per-field sources. The operator interface classifies every populated value independently and restores source, confidence, and declaring-party references retained for the current revision. A newly started assisted session can be saved as its first draft before read-back. Read-back outcomes are append-only and bind the exact current payload. Corrections must first be saved as a new draft revision and confirmed again; an unavailable confirmation requires an explicit exception note."
" Applicant status policies are attached to one exact published Form revision. Authenticated access is object-bound to the applicant account; assisted intake can bind it only from an explicit account party reference. Email-link mode compares the submitted email without revealing whether it matched, revokes the earlier link on resend, and delegates delivery to Notifications. Permanent-link mode deliberately trades authentication and expiry for possession of a stable high-entropy URL. Disabling a policy immediately suspends all grants issued under it; changing policy fields affects future submissions while existing grants retain their issued access profile."
),
layer="configured",
@@ -745,7 +745,10 @@ manifest = ModuleManifest(
"unveränderliche eingereichte Revisionen für die Ablage aufgelöst werden; der aktuelle Zugriff in Forms Runtime "
"wird erneut geprüft und bearbeitbare Entwürfe werden abgewiesen. Assistierte Erfassung beginnt mit einer "
"authentifizierten zweckgebundenen Sitzung. Bearbeitende erfassen Kanal, Partei- und Vertretungsverweise, "
"Befugnisgrundlage, Hinweis, zuständige Funktion, Sprache, Barrierefreiheit und Quellen je Feld. "
"Befugnisgrundlage, Hinweis, zuständige Funktion, Sprache, Barrierefreiheit und Quellen je Feld. Die "
"Bearbeitungsoberfläche klassifiziert jeden ausgefüllten Wert unabhängig und stellt für die aktuelle Revision "
"bewahrte Quellen-, Vertrauens- und Erklärendenreferenzen wieder her. Eine neu begonnene assistierte Sitzung "
"kann vor dem Rücklesen als erster Entwurf gespeichert werden. "
"Rückleseergebnisse werden nur angefügt und binden die exakten aktuellen Nutzdaten. Korrekturen müssen zuerst "
"als neue Entwurfsrevision gespeichert und erneut bestätigt werden; eine nicht mögliche Bestätigung erfordert "
"einen ausdrücklichen Ausnahmevermerk. Regeln für Antragstellerstatus sind an eine exakte veröffentlichte "
@@ -789,7 +792,6 @@ manifest = ModuleManifest(
test_ref="tests/test_forms_runtime.py",
known_limits=(
"External advanced or qualified signature providers, scheduled expiry cleanup, and target kinds beyond native Case/Workflow handoffs remain adapter depth. Public links intentionally cannot substitute the native authenticated acknowledgement profile.",
"The assisted-intake API retains per-field provenance, while the first operator dialog applies one selected source/confidence profile to all populated values; mixed-source field editing remains UI depth.",
"Status policy field changes apply to future submissions; existing grants retain their issued mode and limits, while disabling the policy suspends all of them immediately. Scheduled token cleanup and per-IP throttling remain operations depth.",
),
supported_authority_modes=("native_authoritative",),
@@ -38,6 +38,11 @@ class FormsRuntimeInterfaceDocumentationContractTests(unittest.TestCase):
)
self.assertIn("submit", reference.metadata["consequence_classes"])
self.assertIn("compensate", reference.metadata["consequence_classes"])
self.assertIn("every populated value independently", reference.body)
self.assertFalse(any(
"mixed-source field editing remains" in limit
for limit in manifest.architecture.known_limits
))
if __name__ == "__main__":
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@govoplan/forms-runtime-webui",
"version": "0.1.19",
"version": "0.1.20",
"private": true,
"type": "module",
"main": "src/index.ts",
+160 -31
View File
@@ -89,8 +89,7 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
const [assistedOutcome, setAssistedOutcome] = useState<AssistedConfirmation["outcome"]>("confirmed");
const [assistedMethod, setAssistedMethod] = useState<AssistedConfirmation["method"]>("spoken_readback");
const [assistedConfirmedBy, setAssistedConfirmedBy] = useState("");
const [assistedSource, setAssistedSource] = useState<AssistedIntakeContext["field_sources"][string]["source"]>("person_statement");
const [assistedConfidence, setAssistedConfidence] = useState<AssistedIntakeContext["field_sources"][string]["confidence"]>("stated");
const [assistedFieldSources, setAssistedFieldSources] = useState<AssistedIntakeContext["field_sources"]>({});
const [assistedNote, setAssistedNote] = useState("");
const load = useCallback(async (signal?: AbortSignal) => {
@@ -115,6 +114,11 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
setHandoffs(nextHandoffs.handoffs);
setAssistedConfirmations(nextConfirmations.confirmations);
setAssistedConfirmedBy((current) => current || assisted?.affected_party_ref || "");
setAssistedFieldSources(assistedSourcesForRevision(
nextInstance,
assisted,
nextConfirmations.confirmations
));
setValues(nextInstance.values);
setAttachmentRefs(nextInstance.attachment_refs);
setSignatureRefs(nextInstance.signature_refs);
@@ -147,7 +151,7 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
const canAdmin = hasScope(auth, "forms_runtime:workspace:admin");
const canEditPermission = canParticipate || canWrite;
const editable = Boolean(editableLifecycle && canEditPermission);
const canSave = Boolean(instance?.status === "draft" && definition?.allow_drafts && canEditPermission);
const canSave = Boolean(editableLifecycle && definition?.allow_drafts && canEditPermission);
const changed = useMemo(
() => Boolean(instance && (
JSON.stringify(values) !== JSON.stringify(instance.values)
@@ -248,11 +252,9 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
fieldSources: Object.fromEntries(
Object.entries(values)
.filter(([, value]) => value !== null && value !== undefined && value !== "")
.map(([key]) => [key, {
source: assistedSource,
confidence: assistedConfidence,
declared_by_ref: assistedConfirmedBy.trim()
}])
.map(([key]) => [key, assistedFieldSources[key] ?? defaultAssistedFieldSource(
assistedConfirmedBy.trim() || assisted.affected_party_ref
)])
),
correctionNote: assistedNote
}
@@ -277,6 +279,21 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
setSignatureRefs([]);
}
function changeAssistedFieldSource(
fieldKey: string,
patch: Partial<AssistedIntakeContext["field_sources"][string]>
) {
setAssistedFieldSources((current) => ({
...current,
[fieldKey]: {
...(current[fieldKey] ?? defaultAssistedFieldSource(
assistedConfirmedBy.trim() || assisted?.affected_party_ref || ""
)),
...patch
}
}));
}
async function uploadAttachments(files: File[]) {
if (!instance || !definition) return;
const available = Math.max(0, definition.max_attachments - attachmentRefs.length);
@@ -385,14 +402,14 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
refreshable
reloadAction={{ onReload: () => void load(), loading }}
className="form-instance-toolbar"
contextActions={<>
contextActions={<span className="form-instance-toolbar-context">
<Button onClick={() => navigate("/forms-runtime")}>
<ArrowLeft size={16} aria-hidden="true" />
Forms
</Button>
{definition && <strong>{localized.title}</strong>}
{instance && <StatusBadge status={editableLifecycle ? "active" : "inactive"} label={stateLabel(instance.status)} />}
</>}
</span>}
primaryActions={instance && recordsAvailable && !editableLifecycle ?
<Button onClick={() => navigate(recordFilingPath(instance))}>
<Archive size={16} aria-hidden="true" />
@@ -437,8 +454,10 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
<div className="form-evidence-heading">
<h2>Assisted intake context</h2>
<StatusBadge
status={assistedConfirmationCurrent ? "active" : "inactive"}
label={assistedConfirmationCurrent ? "Read-back current" : "Read-back required"}
status={assistedConfirmationCurrent || (!editableLifecycle && assistedConfirmations.length > 0) ? "active" : "inactive"}
label={editableLifecycle
? assistedConfirmationCurrent ? "Read-back current" : "Read-back required"
: assistedConfirmations.length > 0 ? "Read-back recorded" : "No read-back evidence"}
/>
</div>
<DescriptionList columns={3} collapseAt="workspace" density="compact">
@@ -697,26 +716,70 @@ export default function FormInstancePage({ settings, auth }: PlatformRouteContex
<CoreFormField label="Confirming party reference">
<input value={assistedConfirmedBy} onChange={(event) => setAssistedConfirmedBy(event.target.value)} disabled={saving} required />
</CoreFormField>
<CoreFormField label="Value source" help="Applied to each populated field in this first assisted-intake slice.">
<select value={assistedSource} onChange={(event) => setAssistedSource(event.target.value as typeof assistedSource)} disabled={saving}>
<option value="person_statement">Person statement</option>
<option value="representative_statement">Representative statement</option>
<option value="document">Document</option>
<option value="system">Existing system</option>
<option value="derived">Derived by operator</option>
</select>
</CoreFormField>
<CoreFormField label="Source confidence">
<select value={assistedConfidence} onChange={(event) => setAssistedConfidence(event.target.value as typeof assistedConfidence)} disabled={saving}>
<option value="stated">Stated</option>
<option value="verified">Verified</option>
<option value="uncertain">Uncertain</option>
</select>
</CoreFormField>
<CoreFormField label={assistedOutcome === "confirmed" ? "Note (optional)" : "Correction or exception note"}>
<textarea rows={3} value={assistedNote} onChange={(event) => setAssistedNote(event.target.value)} disabled={saving} required={assistedOutcome !== "confirmed"} />
</CoreFormField>
</FormGrid>
<section className="form-assisted-field-sources" aria-labelledby="assisted-field-sources-heading">
<header>
<h3 id="assisted-field-sources-heading">Source of each populated value</h3>
<p>Classify every value independently. Use a governed party, document, or system reference instead of repeating sensitive evidence in free text.</p>
</header>
<div className="form-assisted-field-source-list">
{Object.entries(values)
.filter(([, value]) => value !== null && value !== undefined && value !== "")
.map(([fieldKey]) => {
const source = assistedFieldSources[fieldKey] ?? defaultAssistedFieldSource(
assistedConfirmedBy.trim() || assisted?.affected_party_ref || ""
);
const fieldLabel = localized.fieldLabels[fieldKey]
?? definition?.fields.find((field) => field.key === fieldKey)?.label
?? humanize(fieldKey);
return (
<fieldset key={fieldKey} className="form-assisted-field-source">
<legend>{fieldLabel}</legend>
<FormGrid columns={3} gap="small" collapseAt="workspace">
<CoreFormField label="Value source">
<select
value={source.source}
onChange={(event) => changeAssistedFieldSource(fieldKey, {
source: event.target.value as typeof source.source
})}
disabled={saving}>
<option value="person_statement">Person statement</option>
<option value="representative_statement">Representative statement</option>
<option value="document">Document</option>
<option value="system">Existing system</option>
<option value="derived">Derived by operator</option>
</select>
</CoreFormField>
<CoreFormField label="Source confidence">
<select
value={source.confidence}
onChange={(event) => changeAssistedFieldSource(fieldKey, {
confidence: event.target.value as typeof source.confidence
})}
disabled={saving}>
<option value="stated">Stated</option>
<option value="verified">Verified</option>
<option value="uncertain">Uncertain</option>
</select>
</CoreFormField>
<CoreFormField label="Declared by or source reference" help="Optional for derived values; otherwise identify the governed party, document, or source system.">
<input
value={source.declared_by_ref ?? ""}
onChange={(event) => changeAssistedFieldSource(fieldKey, {
declared_by_ref: event.target.value || null
})}
disabled={saving}
/>
</CoreFormField>
</FormGrid>
</fieldset>
);
})}
</div>
</section>
</Dialog>
<ConfirmDialog
open={confirmingAcknowledgement}
@@ -955,6 +1018,70 @@ function intakeContext(instance: FormInstance | null): AssistedIntakeContext | n
};
}
function defaultAssistedFieldSource(
declaredByRef: string
): AssistedIntakeContext["field_sources"][string] {
return {
source: "person_statement",
confidence: "stated",
declared_by_ref: declaredByRef || null
};
}
function assistedSourcesForRevision(
instance: FormInstance,
assisted: AssistedIntakeContext | null,
confirmations: AssistedConfirmation[]
): AssistedIntakeContext["field_sources"] {
const currentConfirmation = confirmations.find(
(confirmation) => confirmation.instance_revision === instance.revision
);
const confirmedSources = currentConfirmation?.metadata?.field_sources;
return normalizeAssistedFieldSources(confirmedSources)
?? assisted?.field_sources
?? {};
}
function normalizeAssistedFieldSources(
value: unknown
): AssistedIntakeContext["field_sources"] | null {
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
const result: AssistedIntakeContext["field_sources"] = {};
for (const [fieldKey, candidate] of Object.entries(value)) {
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
const source = (candidate as Record<string, unknown>).source;
const confidence = (candidate as Record<string, unknown>).confidence;
const declaredByRef = (candidate as Record<string, unknown>).declared_by_ref;
if (!isAssistedSource(source) || !isAssistedConfidence(confidence)) continue;
result[fieldKey] = {
source,
confidence,
declared_by_ref: typeof declaredByRef === "string" && declaredByRef.trim()
? declaredByRef
: null
};
}
return result;
}
function isAssistedSource(
value: unknown
): value is AssistedIntakeContext["field_sources"][string]["source"] {
return [
"person_statement",
"representative_statement",
"document",
"system",
"derived"
].includes(String(value));
}
function isAssistedConfidence(
value: unknown
): value is AssistedIntakeContext["field_sources"][string]["confidence"] {
return ["stated", "verified", "uncertain"].includes(String(value));
}
function statusAccessMessage(mode: "authenticated" | "email_link" | "permanent_link"): string {
if (mode === "authenticated") return "Only the bound applicant account can open this status page.";
if (mode === "email_link") return "The applicant uses this tracking ID and linked email address to request an expiring link.";
@@ -989,9 +1116,11 @@ export function visibleGroups(definition: FormDefinition, values: Record<string,
}
function evaluateCondition(condition: NonNullable<FormFieldDefinition["visibility_condition"]>, values: Record<string, unknown>): boolean {
if (condition.kind === "all") return condition.conditions.every((item) => evaluateCondition(item, values));
if (condition.kind === "any") return condition.conditions.some((item) => evaluateCondition(item, values));
if (condition.kind === "not") return !evaluateCondition(condition.conditions[0], values);
if ("conditions" in condition) {
if (condition.kind === "all") return condition.conditions.every((item) => evaluateCondition(item, values));
if (condition.kind === "any") return condition.conditions.some((item) => evaluateCondition(item, values));
return !evaluateCondition(condition.conditions[0], values);
}
const actual = values[condition.field_key];
const expected = condition.value;
switch (condition.operator) {
@@ -19,7 +19,7 @@ import { Button,
type PlatformRouteContext
} from "@govoplan/core-webui";
import { listFormInstances, type FormInstance } from "../../api/formsRuntime";
import { FORMS_RUNTIME_DOCUMENTATION, FORMS_RUNTIME_I18N } from "./interfacePatterns";
import { FORMS_RUNTIME_DOCUMENTATION } from "./interfacePatterns";
import IntakeProfilesDialog from "./IntakeProfilesDialog";
import AssistedIntakeDialog from "./AssistedIntakeDialog";
import StatusAccessPoliciesDialog from "./StatusAccessPoliciesDialog";
+158 -2
View File
@@ -120,7 +120,85 @@ const en = {
"Submission received": "Submission received",
"Receipt": "Receipt",
"Submit Form": "Submit Form",
"Submit this Form? The values and managed attachment references become an immutable submission revision.": "Submit this Form? The values and managed attachment references become an immutable submission revision."
"Submit this Form? The values and managed attachment references become an immutable submission revision.": "Submit this Form? The values and managed attachment references become an immutable submission revision.",
"Assisted intake": "Assisted intake",
"Start assisted intake": "Start assisted intake",
"Capture who is acting, for whom, through which channel, and for what purpose before entering Form values.": "Capture who is acting, for whom, through which channel, and for what purpose before entering Form values.",
"Cancel": "Cancel",
"Start session": "Start session",
"Loading assisted intake profiles": "Loading assisted intake profiles",
"No assisted intake profile is enabled. Ask a Forms Runtime administrator to add one for the published Form.": "No assisted intake profile is enabled. Ask a Forms Runtime administrator to add one for the published Form.",
"Intake channel": "Intake channel",
"Service counter": "Service counter",
"Telephone": "Telephone",
"Paper": "Paper",
"Email": "Email",
"Mobile service": "Mobile service",
"Representative": "Representative",
"Offline import": "Offline import",
"Affected party reference": "Affected party reference",
"Use the governed person or organization reference; do not enter a display name only.": "Use the governed person or organization reference; do not enter a display name only.",
"Represented party reference": "Represented party reference",
"Optional when the affected party is acting directly.": "Optional when the affected party is acting directly.",
"Authority basis": "Authority basis",
"Acting for self": "Acting for self",
"Documented representation": "Documented representation",
"Legal guardianship": "Legal guardianship",
"Statutory authority": "Statutory authority",
"Responsible function reference": "Responsible function reference",
"Purpose": "Purpose",
"Legal basis reference": "Legal basis reference",
"Consent basis": "Consent basis",
"Accessibility or communication support": "Accessibility or communication support",
"Separate multiple needs with commas.": "Separate multiple needs with commas.",
"Privacy and procedural notice was provided": "Privacy and procedural notice was provided",
"Record the fact of notice here; retain any separately required evidence through its owning module.": "Record the fact of notice here; retain any separately required evidence through its owning module.",
"Assisted intake context": "Assisted intake context",
"Read-back current": "Read-back current",
"Read-back required": "Read-back required",
"Read-back recorded": "Read-back recorded",
"No read-back evidence": "No read-back evidence",
"Channel": "Channel",
"Affected party": "Affected party",
"Represented party": "Represented party",
"Authority": "Authority",
"Responsible function": "Responsible function",
"Notice": "Notice",
"Provided": "Provided",
"Not recorded": "Not recorded",
"Language": "Language",
"Communication support": "Communication support",
"This context records provenance and does not bypass the published Form rules. Any saved correction invalidates the earlier read-back for submission.": "This context records provenance and does not bypass the published Form rules. Any saved correction invalidates the earlier read-back for submission.",
"Read back and submit": "Read back and submit",
"Record assisted read-back": "Record assisted read-back",
"Make the exact values and managed evidence available to the confirming party. Record corrections before continuing; the server binds this evidence to the current revision and submission payload.": "Make the exact values and managed evidence available to the confirming party. Record corrections before continuing; the server binds this evidence to the current revision and submission payload.",
"Record and continue": "Record and continue",
"Outcome": "Outcome",
"Confirmed without correction": "Confirmed without correction",
"Corrected and confirmed": "Corrected and confirmed",
"Confirmation unavailable": "Confirmation unavailable",
"Confirmation method": "Confirmation method",
"Spoken read-back": "Spoken read-back",
"Written preview": "Written preview",
"Accessible copy": "Accessible copy",
"Unavailable": "Unavailable",
"Confirming party reference": "Confirming party reference",
"Note (optional)": "Note (optional)",
"Correction or exception note": "Correction or exception note",
"Source of each populated value": "Source of each populated value",
"Classify every value independently. Use a governed party, document, or system reference instead of repeating sensitive evidence in free text.": "Classify every value independently. Use a governed party, document, or system reference instead of repeating sensitive evidence in free text.",
"Value source": "Value source",
"Person statement": "Person statement",
"Representative statement": "Representative statement",
"Document": "Document",
"Existing system": "Existing system",
"Derived by operator": "Derived by operator",
"Source confidence": "Source confidence",
"Stated": "Stated",
"Verified": "Verified",
"Uncertain": "Uncertain",
"Declared by or source reference": "Declared by or source reference",
"Optional for derived values; otherwise identify the governed party, document, or source system.": "Optional for derived values; otherwise identify the governed party, document, or source system."
} as const;
const de: Record<keyof typeof en, string> = {
@@ -243,7 +321,85 @@ const de: Record<keyof typeof en, string> = {
"Submission received": "Übermittlung eingegangen",
"Receipt": "Beleg",
"Submit Form": "Formular absenden",
"Submit this Form? The values and managed attachment references become an immutable submission revision.": "Dieses Formular absenden? Die Werte und Referenzen auf verwaltete Anhänge werden zu einer unveränderlichen Übermittlungsrevision."
"Submit this Form? The values and managed attachment references become an immutable submission revision.": "Dieses Formular absenden? Die Werte und Referenzen auf verwaltete Anhänge werden zu einer unveränderlichen Übermittlungsrevision.",
"Assisted intake": "Assistierte Erfassung",
"Start assisted intake": "Assistierte Erfassung starten",
"Capture who is acting, for whom, through which channel, and for what purpose before entering Form values.": "Erfassen Sie vor den Formularwerten, wer für wen, über welchen Kanal und zu welchem Zweck handelt.",
"Cancel": "Abbrechen",
"Start session": "Sitzung starten",
"Loading assisted intake profiles": "Profile für die assistierte Erfassung werden geladen",
"No assisted intake profile is enabled. Ask a Forms Runtime administrator to add one for the published Form.": "Es ist kein Profil für die assistierte Erfassung aktiviert. Bitten Sie die Formularadministration, eines für das veröffentlichte Formular einzurichten.",
"Intake channel": "Erfassungskanal",
"Service counter": "Serviceschalter",
"Telephone": "Telefon",
"Paper": "Papier",
"Email": "E-Mail",
"Mobile service": "Mobiler Dienst",
"Representative": "Vertretung",
"Offline import": "Offline-Import",
"Affected party reference": "Referenz der betroffenen Partei",
"Use the governed person or organization reference; do not enter a display name only.": "Verwenden Sie die geregelte Personen- oder Organisationsreferenz, nicht nur einen Anzeigenamen.",
"Represented party reference": "Referenz der vertretenen Partei",
"Optional when the affected party is acting directly.": "Optional, wenn die betroffene Partei selbst handelt.",
"Authority basis": "Befugnisgrundlage",
"Acting for self": "Handelt für sich selbst",
"Documented representation": "Dokumentierte Vertretung",
"Legal guardianship": "Gesetzliche Betreuung",
"Statutory authority": "Gesetzliche Befugnis",
"Responsible function reference": "Referenz der zuständigen Funktion",
"Purpose": "Zweck",
"Legal basis reference": "Referenz der Rechtsgrundlage",
"Consent basis": "Einwilligungsgrundlage",
"Accessibility or communication support": "Barrierefreiheits- oder Kommunikationsunterstützung",
"Separate multiple needs with commas.": "Trennen Sie mehrere Bedarfe durch Kommas.",
"Privacy and procedural notice was provided": "Datenschutz- und Verfahrenshinweis wurde erteilt",
"Record the fact of notice here; retain any separately required evidence through its owning module.": "Erfassen Sie hier die Erteilung; gesondert erforderliche Nachweise verbleiben im zuständigen Modul.",
"Assisted intake context": "Kontext der assistierten Erfassung",
"Read-back current": "Rücklesen aktuell",
"Read-back required": "Rücklesen erforderlich",
"Read-back recorded": "Rücklesen erfasst",
"No read-back evidence": "Kein Rücklesenachweis",
"Channel": "Kanal",
"Affected party": "Betroffene Partei",
"Represented party": "Vertretene Partei",
"Authority": "Befugnis",
"Responsible function": "Zuständige Funktion",
"Notice": "Hinweis",
"Provided": "Erteilt",
"Not recorded": "Nicht erfasst",
"Language": "Sprache",
"Communication support": "Kommunikationsunterstützung",
"This context records provenance and does not bypass the published Form rules. Any saved correction invalidates the earlier read-back for submission.": "Dieser Kontext erfasst die Herkunft und umgeht die Regeln des veröffentlichten Formulars nicht. Jede gespeicherte Korrektur macht das frühere Rücklesen für die Einreichung ungültig.",
"Read back and submit": "Rücklesen und absenden",
"Record assisted read-back": "Assistiertes Rücklesen erfassen",
"Make the exact values and managed evidence available to the confirming party. Record corrections before continuing; the server binds this evidence to the current revision and submission payload.": "Stellen Sie der bestätigenden Partei die exakten Werte und verwalteten Nachweise bereit. Erfassen Sie Korrekturen vor dem Fortfahren; der Server bindet diesen Nachweis an die aktuelle Revision und die Einreichungsnutzdaten.",
"Record and continue": "Erfassen und fortfahren",
"Outcome": "Ergebnis",
"Confirmed without correction": "Ohne Korrektur bestätigt",
"Corrected and confirmed": "Korrigiert und bestätigt",
"Confirmation unavailable": "Bestätigung nicht verfügbar",
"Confirmation method": "Bestätigungsmethode",
"Spoken read-back": "Mündliches Rücklesen",
"Written preview": "Schriftliche Vorschau",
"Accessible copy": "Barrierefreie Kopie",
"Unavailable": "Nicht verfügbar",
"Confirming party reference": "Referenz der bestätigenden Partei",
"Note (optional)": "Notiz (optional)",
"Correction or exception note": "Korrektur- oder Ausnahmenotiz",
"Source of each populated value": "Quelle jedes ausgefüllten Werts",
"Classify every value independently. Use a governed party, document, or system reference instead of repeating sensitive evidence in free text.": "Klassifizieren Sie jeden Wert einzeln. Verwenden Sie eine geregelte Partei-, Dokument- oder Systemreferenz, statt sensible Nachweise im Freitext zu wiederholen.",
"Value source": "Wertquelle",
"Person statement": "Angabe der Person",
"Representative statement": "Angabe der Vertretung",
"Document": "Dokument",
"Existing system": "Bestehendes System",
"Derived by operator": "Durch Bearbeitung abgeleitet",
"Source confidence": "Quellenvertrauen",
"Stated": "Angegeben",
"Verified": "Geprüft",
"Uncertain": "Unsicher",
"Declared by or source reference": "Erklärende Partei oder Quellenreferenz",
"Optional for derived values; otherwise identify the governed party, document, or source system.": "Bei abgeleiteten Werten optional; sonst die geregelte Partei, das Dokument oder Quellsystem angeben."
};
export const generatedTranslations: PlatformTranslations = { en, de };
+1 -1
View File
@@ -15,7 +15,7 @@ const routeScopes = [
export const formsRuntimeModule: PlatformWebModule = {
id: "forms_runtime",
label: "i18n:govoplan-forms-runtime.forms",
version: "0.1.19",
version: "0.1.20",
dependencies: ["access", "forms"],
optionalDependencies: ["files", "approvals", "workflow_engine", "portal", "cases", "records", "policy", "audit"],
translations: generatedTranslations,
+68
View File
@@ -21,6 +21,21 @@
margin-left: auto;
}
.form-instance-toolbar-context {
display: flex;
min-width: 0;
max-width: 100%;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.form-instance-toolbar-context > strong {
min-width: 0;
flex: 1 1 180px;
overflow-wrap: anywhere;
}
.forms-runtime-list-viewport,
.form-instance-viewport {
flex: 1;
@@ -278,6 +293,46 @@
font-size: 0.78rem;
}
.form-assisted-field-sources {
display: grid;
gap: 12px;
margin-top: 18px;
padding-top: 16px;
border-top: 1px solid var(--border);
}
.form-assisted-field-sources > header h3,
.form-assisted-field-sources > header p {
margin: 0;
}
.form-assisted-field-sources > header p {
margin-top: 5px;
color: var(--text-soft);
font-size: 0.8rem;
}
.form-assisted-field-source-list {
display: grid;
gap: 10px;
}
.form-assisted-field-source {
min-width: 0;
margin: 0;
padding: 12px;
border: 1px solid var(--border);
border-radius: var(--radius-compact);
background: var(--surface-subtle);
}
.form-assisted-field-source legend {
padding-inline: 5px;
color: var(--text-strong);
font-size: 0.84rem;
font-weight: 700;
}
.form-status-policy-save {
display: flex;
justify-content: flex-end;
@@ -557,6 +612,19 @@
}
@media (max-width: 900px) {
.form-instance-toolbar .page-action-slot-context {
max-width: 100%;
flex: 1 1 100%;
}
.form-instance-toolbar-context {
width: 100%;
}
.form-instance-toolbar-context .status-badge {
margin-left: 0;
}
.form-instance-content {
grid-template-columns: 1fr;
}