Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa0bdde839 | ||
|
|
8e5415dfe7 |
+3
-3
@@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "govoplan-workflow"
|
name = "govoplan-workflow"
|
||||||
version = "0.1.19"
|
version = "0.1.21"
|
||||||
description = "Optional visual authoring and inspection workspace for GovOPlaN Workflow Engine."
|
description = "Optional visual authoring and inspection workspace for GovOPlaN Workflow Engine."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = [{ name = "GovOPlaN" }]
|
authors = [{ name = "GovOPlaN" }]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"govoplan-core>=0.1.18",
|
"govoplan-core>=0.1.28",
|
||||||
"govoplan-workflow-engine>=0.1.18",
|
"govoplan-workflow-engine>=0.1.19",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""Optional GovOPlaN Workflow editor and compatibility package."""
|
"""Optional GovOPlaN Workflow editor and compatibility package."""
|
||||||
|
|
||||||
__version__ = "0.1.18"
|
__version__ = "0.1.21"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from govoplan_core.core.modules import (
|
from govoplan_core.core.modules import (
|
||||||
CapabilityDocumentation,
|
CapabilityDocumentation,
|
||||||
|
DocumentationCondition,
|
||||||
DocumentationLink,
|
DocumentationLink,
|
||||||
DocumentationTopic,
|
DocumentationTopic,
|
||||||
FrontendModule,
|
FrontendModule,
|
||||||
@@ -34,7 +35,7 @@ from govoplan_workflow_engine.backend.manifest import (
|
|||||||
|
|
||||||
MODULE_ID = "workflow"
|
MODULE_ID = "workflow"
|
||||||
MODULE_NAME = "Workflow"
|
MODULE_NAME = "Workflow"
|
||||||
MODULE_VERSION = "0.1.19"
|
MODULE_VERSION = "0.1.21"
|
||||||
SEMANTIC_SUBJECT_CAPABILITY = semantic_documentation_subject_capability(MODULE_ID)
|
SEMANTIC_SUBJECT_CAPABILITY = semantic_documentation_subject_capability(MODULE_ID)
|
||||||
|
|
||||||
|
|
||||||
@@ -139,6 +140,61 @@ manifest = ModuleManifest(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
documentation=(
|
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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
translations={
|
||||||
|
"de": {
|
||||||
|
"title": "Externe Arbeitsübergaben prüfen und zu ihnen zurückkehren",
|
||||||
|
"summary": "Der genau verknüpften Arbeit im Zielmodul folgen, während Workflow seine dauerhafte Position und unveränderliche Referenz beibehält.",
|
||||||
|
"body": (
|
||||||
|
"Der Läufe-Dialog zeigt den aktuellen Zustand der externen Übergabe, die genaue Revisionsreferenz, die sichere Aktion zur verknüpften Arbeit, den Zeitablauf und die unveränderliche Workflow-Nachweisspur. "
|
||||||
|
"Das Verlassen des Dialogs oder der verknüpften Campaign-Seite schließt den Schritt nicht ab. Deklarierte Campaign-Ereignisse steuern Annahme, Neuzuweisung, Abschluss, Ablehnung und Abbruch ohne Browser-Abfragen. "
|
||||||
|
"Eine konfigurierte fokussierte View grenzt die verfügbaren Oberflächen ein, solange der Schritt aktiv ist. Fehlt Views, bleibt die verknüpfte Campaign-Aktion verfügbar und der Dialog erläutert die reduzierte Darstellung. "
|
||||||
|
"Auch fehlende optionale Module Tasks oder Notifications werden angezeigt, ohne das Ergebnis der Übergabe zu verändern."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
metadata={
|
||||||
|
"kind": "workflow",
|
||||||
|
"help_contexts": [
|
||||||
|
"workflow.external-handoff",
|
||||||
|
"workflow.instances",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
order=74,
|
||||||
|
),
|
||||||
DocumentationTopic(
|
DocumentationTopic(
|
||||||
id="workflow.semantic-documentation",
|
id="workflow.semantic-documentation",
|
||||||
title="Document configured workflow and step meaning",
|
title="Document configured workflow and step meaning",
|
||||||
@@ -183,6 +239,19 @@ manifest = ModuleManifest(
|
|||||||
kind="repository",
|
kind="repository",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
translations={
|
||||||
|
"de": {
|
||||||
|
"title": "Bedeutung konfigurierter Workflows und Schritte dokumentieren",
|
||||||
|
"summary": "Mandanteneigene semantische Hinweise einer berechtigten Workflow-Definition oder einem stabilen Schritt zuordnen, ohne die Ausführung zu verändern.",
|
||||||
|
"body": (
|
||||||
|
"Wenn Docs installiert ist, stellt Workflow dokumentationssichere Subjekte für jede Definition bereit, die der aktuelle Akteur sehen darf, sowie für jeden Schritt ihrer aktuellen unveränderlichen Revision. "
|
||||||
|
"Die Schrittidentität bleibt bei Änderungen von Bezeichnung und Position auf der Zeichenfläche erhalten. Wird ein Schritt entfernt und später mit derselben Graph-ID neu angelegt, entsteht eine neue Abstammung; frühere Dokumentation bleibt ausdrücklich verwaist. "
|
||||||
|
"Relevante Änderungen an Schritttyp, Bezeichnung, Hierarchie, sicherer Konfiguration oder der Semantik verbundener Flüsse ändern den Prüffingerabdruck; reine Layoutverschiebungen tun dies nicht. "
|
||||||
|
"Semantische Texte können Zweck, Nicht-Zweck, Ein- und Austrittsbedingungen, Übergaben, Ausnahmen, Verantwortung, Betreuung und Beispiele erläutern, aber weder Validierung, Aktivierung, Richtlinien noch die Ausführung durch Workflow Engine verändern. "
|
||||||
|
"Workflow prüft bei Ermittlung und direkter Auflösung erneut Mandantengrenze und aktuelle Governance-Entscheidung je Definition. Fehlt Docs, bleiben Bearbeitung und statische Hilfe verfügbar."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
metadata={
|
metadata={
|
||||||
"kind": "reference",
|
"kind": "reference",
|
||||||
"help_contexts": ["workflow.semantic-documentation"],
|
"help_contexts": ["workflow.semantic-documentation"],
|
||||||
@@ -214,6 +283,16 @@ manifest = ModuleManifest(
|
|||||||
kind="repository",
|
kind="repository",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
translations={
|
||||||
|
"de": {
|
||||||
|
"title": "Arbeitsbereich für Workflow-Bearbeitung und -Prüfung",
|
||||||
|
"summary": "Optionale Erstellung, Validierung, Revisionsprüfung und Betriebssteuerung für Workflow Engine.",
|
||||||
|
"body": (
|
||||||
|
"Workflow ergänzt den visuellen BPMN- und nativen Graph-Editor, den Definitionskatalog, den Vergleich unveränderlicher Revisionen, Aktivierungssteuerung, Instanzprüfung und gesteuerte Eingriffe zum Überschreiben oder Zurücksetzen. "
|
||||||
|
"Definitionen und Instanzen bleiben Eigentum des ohne eigene Bedienoberfläche betriebenen Moduls Workflow Engine und werden dort ausgeführt."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
order=76,
|
order=76,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class WorkflowManifestTests(unittest.TestCase):
|
|||||||
manifest = get_manifest()
|
manifest = get_manifest()
|
||||||
|
|
||||||
self.assertEqual("workflow", manifest.id)
|
self.assertEqual("workflow", manifest.id)
|
||||||
|
self.assertEqual("0.1.21", manifest.version)
|
||||||
self.assertEqual(("workflow_engine",), manifest.dependencies)
|
self.assertEqual(("workflow_engine",), manifest.dependencies)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{"workflow.definition_graph", "workflow.definition_catalogue", "workflow.bpmn_interchange"},
|
{"workflow.definition_graph", "workflow.definition_catalogue", "workflow.bpmn_interchange"},
|
||||||
@@ -38,6 +39,13 @@ class WorkflowManifestTests(unittest.TestCase):
|
|||||||
manifest.frontend.package_name if manifest.frontend else None,
|
manifest.frontend.package_name if manifest.frontend else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for topic in manifest.documentation:
|
||||||
|
german = topic.translations.get("de", {})
|
||||||
|
self.assertTrue(
|
||||||
|
all(german.get(field) for field in ("title", "summary", "body")),
|
||||||
|
topic.id,
|
||||||
|
)
|
||||||
|
|
||||||
def test_editor_exposes_semantic_help_without_replacing_static_help(self) -> None:
|
def test_editor_exposes_semantic_help_without_replacing_static_help(self) -> None:
|
||||||
root = Path(__file__).parents[1]
|
root = Path(__file__).parents[1]
|
||||||
page = (root / "webui/src/features/workflow/WorkflowPage.tsx").read_text()
|
page = (root / "webui/src/features/workflow/WorkflowPage.tsx").read_text()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/workflow-webui",
|
"name": "@govoplan/workflow-webui",
|
||||||
"version": "0.1.19",
|
"version": "0.1.21",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -285,6 +285,13 @@ export default function WorkflowRunsDialog({
|
|||||||
const actionUrl = typeof currentStep?.handoff.action_url === "string"
|
const actionUrl = typeof currentStep?.handoff.action_url === "string"
|
||||||
? currentStep.handoff.action_url
|
? 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 = () => {
|
const close = () => {
|
||||||
dispatchWorkflowViewChanged(null);
|
dispatchWorkflowViewChanged(null);
|
||||||
onClose();
|
onClose();
|
||||||
@@ -390,6 +397,15 @@ export default function WorkflowRunsDialog({
|
|||||||
{selected.error}
|
{selected.error}
|
||||||
</DismissibleAlert>
|
</DismissibleAlert>
|
||||||
) : null}
|
) : null}
|
||||||
|
{selected.view_context && !viewsRuntime ? (
|
||||||
|
<DismissibleAlert
|
||||||
|
tone="warning"
|
||||||
|
resetKey={`view-unavailable:${selected.id}:${selected.current_step_id ?? "none"}`}
|
||||||
|
>
|
||||||
|
The focused View is unavailable. Workflow position is preserved;
|
||||||
|
use the linked module action or ask an administrator to enable Views.
|
||||||
|
</DismissibleAlert>
|
||||||
|
) : null}
|
||||||
{currentStep ? (
|
{currentStep ? (
|
||||||
<section className="workflow-run-handoff">
|
<section className="workflow-run-handoff">
|
||||||
<div>
|
<div>
|
||||||
@@ -417,9 +433,18 @@ export default function WorkflowRunsDialog({
|
|||||||
&& currentStep.handoff.instructions ? (
|
&& currentStep.handoff.instructions ? (
|
||||||
<p>{currentStep.handoff.instructions}</p>
|
<p>{currentStep.handoff.instructions}</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
{unavailableOptionalCapabilities.length ? (
|
||||||
|
<DismissibleAlert
|
||||||
|
tone="info"
|
||||||
|
resetKey={`optional:${currentStep.id}:${unavailableOptionalCapabilities.join(",")}`}
|
||||||
|
>
|
||||||
|
Optional integration unavailable: {unavailableOptionalCapabilities.join(", ")}.
|
||||||
|
The hand-off remains valid and resumable.
|
||||||
|
</DismissibleAlert>
|
||||||
|
) : null}
|
||||||
{actionUrl ? (
|
{actionUrl ? (
|
||||||
<a href={actionUrl}>
|
<a href={actionUrl}>
|
||||||
Open linked Dataflow result <ExternalLink size={14} />
|
Open linked work <ExternalLink size={14} />
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
{allowedActions.some((action) => action !== "cancel") ? (
|
{allowedActions.some((action) => action !== "cancel") ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user