feat(apollo-react): add uipath.case.stage manifest and drive StageNode handles from it [MST-12554]#947
feat(apollo-react): add uipath.case.stage manifest and drive StageNode handles from it [MST-12554]#947kittyyueli wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency License Review
License distribution
Excluded packages
|
a742c6f to
d839a7a
Compare
📊 Coverage + size by packagePer-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.
"Coverage" is each package's own |
There was a problem hiding this comment.
Pull request overview
Adds a Case Management stage node manifest (uipath.case.stage) and updates the existing StageNode handle rendering so the standard canvas “add” button can be driven from manifest metadata (opt-in via callbacks), aligning Stage behavior with the manifest-based canvas node system.
Changes:
- Introduces
caseManagementStageManifestand acase-stagecategory, and registers both trigger + stage manifests in the combinedcaseFlowManifest. - Updates
StageNodeHandlesto derive rendered handle groups from the stage manifest (while preserving legacy instance-scoped handle ids and the bottom target anchor). - Adds optional
StageNodehandle callbacks and tests/story coverage to verify add-button rendering and behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx | Derives handle groups from caseManagementStageManifest, preserves legacy handle ids/anchors, wires handle callbacks into useButtonHandles. |
| packages/apollo-react/src/canvas/components/StageNode/StageNode.types.ts | Adds optional onHandleAction / onHandleMouseEnter / onHandleMouseLeave props for opt-in add-button behavior. |
| packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx | Threads the new optional handle callbacks through to StageNodeHandles. |
| packages/apollo-react/src/canvas/components/StageNode/StageNode.test.tsx | Exercises real handle rendering (stubs xyflow Handle) and verifies add-button presence/behavior + legacy bottom target anchor. |
| packages/apollo-react/src/canvas/components/StageNode/StageNode.stories.tsx | Adds a Storybook story demonstrating the manifest-driven “add next stage” button via onHandleAction. |
| packages/apollo-react/src/canvas/components/CaseFlow/index.ts | Exports caseManagementStageManifest. |
| packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts | Adds the case-stage category and defines caseManagementStageManifest; registers it in caseFlowManifest. |
| packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.test.ts | Validates trigger + stage manifests/categories against schemas and checks key cross-references/uniqueness/button visibility rules. |
| const manifestGroups = (caseManagementStageManifest.handleConfiguration ?? []) | ||
| .filter((group) => RENDERED_POSITIONS.has(group.position)) | ||
| .map((group) => ({ | ||
| position: group.position, | ||
| handles: group.handles.map((handle) => ({ | ||
| id: `${id}____${handle.type}____${group.position}`, | ||
| type: handle.type, | ||
| handleType: handle.handleType, | ||
| showButton: handle.showButton, | ||
| })), |
There was a problem hiding this comment.
Accurate description of the usePreviewNode lookup, but this is intentional and not a regression: the instance-scoped ids are the pre-existing StageNode scheme, and stage edges in existing case documents already anchor to them — switching the DOM ids to the manifest ids (input/next/reentry) would orphan those edges. The usePreviewNode/AddNodePanel flow also isn't used by the case canvas today (PO.Frontend has its own preview pipeline; this PR's add button goes through the new onHandleAction prop, not AddNodePanel). Documented this as a known limitation in the code comment here, with id unification deferred to the unified-schema edge migration, which has to migrate existing documents' edges anyway.
Generated by Claude Code
There was a problem hiding this comment.
I'd rather move completely to using flow unified schema so I want to follow that as strictly as possible
There was a problem hiding this comment.
Done — reworked to follow the flow unified schema strictly: StageNodeHandles now uses the manifest handle ids verbatim (input/next/reentry, same pattern as the trigger's output), no instance-scoped rewriting, and the legacy bottom target anchor is removed. onHandleAction now emits the manifest id. Follow-ups this implies on the PO.Frontend side (will handle in #6373): stage edge generation must emit the manifest ids like it already does for the v24 trigger, and pre-unified-schema documents' stage edges (e.g. stage-1____target____bottom in existing case JSON) will need the edge migration to render again.
Generated by Claude Code
| /** | ||
| * Fired when the manifest-driven add button on a source handle is clicked | ||
| * (the `next` handle of `caseManagementStageManifest`). The add button only | ||
| * renders when this callback is provided. | ||
| */ |
d839a7a to
e994699
Compare
| // Legacy re-entry anchor: not part of the manifest, but existing edges | ||
| // target `${id}____target____bottom`, so it must keep rendering. | ||
| { | ||
| position: Position.Bottom, | ||
| handles: [ | ||
| { | ||
| id: `${id}____target____bottom`, | ||
| type: 'target' as const, | ||
| handleType: 'input' as const, | ||
| }, |
There was a problem hiding this comment.
why do we need to keep the legacy one?
There was a problem hiding this comment.
Removed. It was there because existing case documents' re-entry edges anchor to it ("targetHandle": "stage-1____target____bottom" in e.g. PO.Frontend's example.case.json), but per your call to follow the flow schema strictly, those edges are now covered by the unified-schema edge migration instead. The reentry manifest handle is the only bottom handle now.
Generated by Claude Code
e994699 to
16ec773
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:73
- Handle ids are derived as
${id}____${handle.type}____${group.position}. This collapses multiple manifest handles that share the same position+type into the same DOM id (the manifest schema allows multiple handles per group, includingrepeat). That will produce duplicate handle ids and make edges/connected-handle visibility ambiguous if the stage manifest ever adds a second handle on the same side.
Consider preserving the legacy ids for the existing anchors, but disambiguating any additional handles by appending the manifest handle id.
handles: group.handles.map((handle) => ({
id: `${id}____${handle.type}____${group.position}`,
type: handle.type,
handleType: handle.handleType,
showButton: handle.showButton,
})),
| * Scope (this file): trigger and stage nodes. Exception stages are regular stages | ||
| * with `isSecondary` instance metadata (the two node types were combined), so they | ||
| * share the stage manifest. Task, condition, and edge manifests are intentionally | ||
| * out of scope. |
16ec773 to
1bca828
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:46
- StageNodeHandles now renders handles with manifest ids (
input/next/reentry). However, this package still includes StageNode edge examples that reference the legacy instance-scoped handle ids (e.g.0____source____right/1____target____leftinStageNode.stories.tsx:600+), which will no longer anchor correctly. Those fixtures (and any downstream consumers still emitting legacy handle ids) need to be migrated to the new ids as part of this change, otherwise Storybook examples and existing graphs can regress.
const handleConfigurations: HandleGroupManifest[] = useMemo(() => {
if (isException) return [];
const visible = selected || isHovered || isConnecting;
return (caseManagementStageManifest.handleConfiguration ?? []).map((group) => ({
packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:72
- The PR description mentions that a “legacy bottom target anchor still renders”, but StageNodeHandles now derives handles exclusively from the manifest, and the stage manifest defines only
input(left target),next(right source), andreentry(bottom source) with no bottom target handle. Please update the PR description (or reintroduce the legacy anchor if it’s still required) to avoid confusion for reviewers/consumers.
const handleElements = useButtonHandles({
handleConfigurations,
shouldShowHandles,
nodeId: id,
selected,
hovered: isHovered,
showAddButton: !isReadOnly,
handleAction: onHandleAction,
handleMouseEnter: onHandleMouseEnter,
handleMouseLeave: onHandleMouseLeave,
});
| // Handle groups come straight from `caseManagementStageManifest` (ids included, | ||
| // per the unified flow schema); the runtime contributes only hover visibility | ||
| // and the header-aligned notch offsets. Edges reference the manifest handle ids | ||
| // (`input` / `next` / `reentry`); pre-unified-schema documents are migrated. |
| onHandleAction: () => { | ||
| window.alert('Add next stage: this would append a new stage after Intake'); | ||
| }, |
1bca828 to
c297874
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:60
- StageNodeHandles is meant to be manifest-driven, but the mapping currently rebuilds each handle with only {id,type,handleType,showButton}. This drops other manifest fields that are already defined on the stage manifest (e.g.
constraints,isDefaultForType, and any future handle/group metadata likeboundary,connectionPosition,labelVisibility). That makes the rendered handle config diverge from the manifest and can silently disable constraint/behavior metadata.
Consider preserving the manifest objects and only overriding the few runtime-controlled fields (visibility + left/right notch offsets).
return (caseManagementStageManifest.handleConfiguration ?? []).map((group) => ({
position: group.position,
handles: group.handles.map((handle) => ({
id: handle.id,
type: handle.type,
handleType: handle.handleType,
showButton: handle.showButton,
})),
visible,
customPositionAndOffsets:
group.position === Position.Left || group.position === Position.Right
? { top: 0, height: HANDLE_LANE_HEIGHT }
: undefined,
}));
…e handles from it
Adds caseManagementStageManifest per the Case unified-schema onboarding doc
(MST-12554), with two corrections against the doc's draft: display.shape is
'container' ('group' is not a valid NodeShape), and the top source handle is
'exitConditions' (the doc lists 'entryConditions' twice). Category ids follow
the ones already landed here.
StageNodeHandles now derives its handle groups from the manifest instead of
an inline hardcoded list, keeping the per-instance handle id scheme existing
edges anchor to, plus the legacy bottom target anchor. The manifest's next
handle carries showButton: true, so StageNode gains optional onHandleAction /
onHandleMouseEnter / onHandleMouseLeave props that light up the standard
canvas add button, the same affordance BaseNode-driven nodes (e.g. the case
trigger) already use.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012dGQD9cuKGicUg426htYEy
c297874 to
5a7b088
Compare
CLAUDE BUG BURN-DOWN
https://claude.ai/code/session_012dGQD9cuKGicUg426htYEy
Description
Follow-up to MST-12554 (add-stage handle on trigger vs. stages is inconsistent), taking the direction from the Case unified-schema onboarding doc: the stage node adopts the apollo manifest system rather than PO.Frontend keeping a custom add button.
What's in here:
caseManagementStageManifest(uipath.case.stage) inCaseFlow/case-flow.manifest.ts, per the onboarding doc's stage manifest, adjusted per review:display.shape: 'container'(the doc's'group'is not a validNodeShape); iconsquare-plus.input(left target),next(right source,showButton: true),reentry(bottom source).inputDefinitionmirrors the current stage node data model:name,tasks,entryConditions,exitConditions,slaRules,stageType('secondary'= exception stage, the combined node type).case-stagecategory is added, which also makes the trigger manifest's existingallowedTargetCategories: ['case-stage']constraint resolvable. Category ids follow the ones already landed here (case-management-trigger).StageNodeHandlesfollows the unified flow schema strictly: handle groups and ids come straight from the manifest (input/next/reentry, same pattern as the trigger'soutput). No instance-scoped id rewriting and no legacy bottom target anchor. Runtime contributes only hover visibility and header-aligned notch offsets.StageNodepropsonHandleAction/onHandleMouseEnter/onHandleMouseLeave, threaded to the handles.onHandleActionemits the manifest handle id (next). The add button renders only whenonHandleActionis provided, so existing consumers see no change until they opt in.Consumer side (PO.Frontend, will be handled in UiPath/PO.Frontend#6373):
Stage.tsxpasses the new callbacks (replacing the custom circularStageNodeAddNodeButtonComponent).outputhandle."targetHandle": "stage-1____target____bottom") need the unified-schema edge migration to render against the new handle ids.Testing
case-flow.manifest.test.ts: both manifests parse againstnodeManifestSchema, categories parse, category cross-references resolve, handle ids unique, onlynextshows the button.StageNode.test.tsx: add button renders and firesonHandleActionwith the manifestnexthandle id; hidden withoutonHandleAction, in read-only, and on exception stages; manifest handle ids (input/next/reentry) render. Un-mockeduseButtonHandles(was stubbed tonull) and stubbed xyflow'sHandleso handle rendering is actually exercised.apollo-reactsuite green locally;tsc --noEmitclean; package build passes; Biome lint/format clean.StageNode / Manifest Add Next Stageshowing the opt-in add button.Checklist