diff --git a/pyproject.toml b/pyproject.toml index e674f29..a691779 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-workflow" -version = "0.1.19" +version = "0.1.20" description = "Optional visual authoring and inspection workspace for GovOPlaN Workflow Engine." readme = "README.md" requires-python = ">=3.12" license = "AGPL-3.0-or-later" authors = [{ name = "GovOPlaN" }] dependencies = [ - "govoplan-core>=0.1.18", - "govoplan-workflow-engine>=0.1.18", + "govoplan-core>=0.1.28", + "govoplan-workflow-engine>=0.1.19", ] [tool.setuptools.packages.find] diff --git a/src/govoplan_workflow/backend/manifest.py b/src/govoplan_workflow/backend/manifest.py index 4915f1f..788f16e 100644 --- a/src/govoplan_workflow/backend/manifest.py +++ b/src/govoplan_workflow/backend/manifest.py @@ -2,6 +2,7 @@ from __future__ import annotations from govoplan_core.core.modules import ( CapabilityDocumentation, + DocumentationCondition, DocumentationLink, DocumentationTopic, FrontendModule, @@ -34,7 +35,7 @@ from govoplan_workflow_engine.backend.manifest import ( MODULE_ID = "workflow" MODULE_NAME = "Workflow" -MODULE_VERSION = "0.1.19" +MODULE_VERSION = "0.1.20" SEMANTIC_SUBJECT_CAPABILITY = semantic_documentation_subject_capability(MODULE_ID) @@ -139,6 +140,49 @@ manifest = ModuleManifest( ), ), documentation=( + DocumentationTopic( + id="workflow.external-handoff-inspection", + title="Inspect and return to external work hand-offs", + summary=( + "Follow the exact linked module work while Workflow retains " + "its durable position and immutable reference." + ), + body=( + "The runs dialog shows the current external hand-off state, exact " + "revision reference, safe linked-work action, timeout, and the " + "immutable Workflow evidence trail. Leaving the dialog or linked " + "Campaign page does not complete the step. Declared Campaign events " + "drive acceptance, reassignment, completion, rejection, and " + "cancellation without browser polling. A configured focused View " + "narrows the available surfaces while the step is active. If Views " + "is absent, the linked Campaign action remains available and the " + "dialog explains the reduced presentation. Missing optional Tasks or " + "Notifications is also shown without changing the hand-off outcome." + ), + layer="available", + documentation_types=("admin", "user"), + audience=("operator", "workflow_designer", "campaign_manager"), + related_modules=( + "workflow_engine", + "campaigns", + "views", + "tasks", + "notifications", + ), + conditions=( + DocumentationCondition( + any_scopes=(INSTANCE_READ_SCOPE, ADMIN_SCOPE), + ), + ), + metadata={ + "kind": "workflow", + "help_contexts": [ + "workflow.external-handoff", + "workflow.instances", + ], + }, + order=74, + ), DocumentationTopic( id="workflow.semantic-documentation", title="Document configured workflow and step meaning", diff --git a/webui/package.json b/webui/package.json index b6c8c91..8dc00f1 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/workflow-webui", - "version": "0.1.19", + "version": "0.1.20", "private": true, "type": "module", "main": "src/index.ts", diff --git a/webui/src/features/workflow/WorkflowRunsDialog.tsx b/webui/src/features/workflow/WorkflowRunsDialog.tsx index 1b9f23c..8d24140 100644 --- a/webui/src/features/workflow/WorkflowRunsDialog.tsx +++ b/webui/src/features/workflow/WorkflowRunsDialog.tsx @@ -285,6 +285,13 @@ export default function WorkflowRunsDialog({ const actionUrl = typeof currentStep?.handoff.action_url === "string" ? currentStep.handoff.action_url : ""; + const unavailableOptionalCapabilities = Array.isArray( + currentStep?.handoff.unavailable_optional_capabilities + ) + ? currentStep.handoff.unavailable_optional_capabilities.filter( + (value): value is string => typeof value === "string" && Boolean(value) + ) + : []; const close = () => { dispatchWorkflowViewChanged(null); onClose(); @@ -390,6 +397,15 @@ export default function WorkflowRunsDialog({ {selected.error} ) : null} + {selected.view_context && !viewsRuntime ? ( + + The focused View is unavailable. Workflow position is preserved; + use the linked module action or ask an administrator to enable Views. + + ) : null} {currentStep ? (
@@ -417,9 +433,18 @@ export default function WorkflowRunsDialog({ && currentStep.handoff.instructions ? (

{currentStep.handoff.instructions}

) : null} + {unavailableOptionalCapabilities.length ? ( + + Optional integration unavailable: {unavailableOptionalCapabilities.join(", ")}. + The hand-off remains valid and resumable. + + ) : null} {actionUrl ? ( - Open linked Dataflow result + Open linked work ) : null} {allowedActions.some((action) => action !== "cancel") ? (