Complete assisted intake provenance UI
Module Package Release / publish-packages (push) Successful in 13s
Module Package Release / publish-packages (push) Successful in 13s
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user