Skip to content

fix(task-refactor)migrate widgets to SDK state-machine-driven uiControls#668

Open
akulakum wants to merge 1 commit intowebex:task-refactorfrom
akulakum:TASK_REFACTOR_IMPLEMENTATION
Open

fix(task-refactor)migrate widgets to SDK state-machine-driven uiControls#668
akulakum wants to merge 1 commit intowebex:task-refactorfrom
akulakum:TASK_REFACTOR_IMPLEMENTATION

Conversation

@akulakum
Copy link
Copy Markdown
Contributor

@akulakum akulakum commented Apr 7, 2026

COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7779

This pull request addresses

The CC Widgets currently compute button visibility and enablement on the widget side using a complex combination of deviceType, featureFlags, conferenceEnabled, task state flags, and ~22 visibility functions in getControlsVisibility(). This approach duplicates logic that the SDK now handles internally through its state-machine-driven task.uiControls — a property on the ITask object where each of the 17 controls has { isVisible: boolean, isEnabled: boolean } computed from TaskState and TaskContext. This PR migrates all task widgets to consume task.uiControls as the single source of truth, eliminating widget-side control computation and aligning with the SDK's new architecture.

by making the following changes

Core migration — SDK uiControls as single source of truth:

  • Replaced the legacy getControlsVisibility() / ControlVisibility pattern in useCallControl hook with direct consumption of task.uiControls (type: TaskUIControls)
  • All button isVisible and isEnabled properties in buildCallControlButtons(), createConsultButtons(), and extractIncomingTaskData() / extractTaskListItemData() now read from controls..isVisible / controls..isEnabled
  • Subscribe to TASK_EVENTS.TASK_UI_CONTROLS_UPDATED for reactive re-renders when SDK recomputes controls after state transitions

Props removed (SDK handles internally):

  • deviceType — SDK uses UIControlConfig internally
  • featureFlags — SDK gates via config.isEndTaskEnabled, config.isEndConsultEnabled, config.isRecordingEnabled

Props restored (application-level overrides, not feature flags):

  • conferenceEnabled — application-level configuration from consumer apps (e.g., App.tsx) that controls whether conference-related buttons (merge, exit conference) are available. Applied directly at button builder level: isVisible: conferenceEnabled && (controls?.mergeToConference?.isVisible ?? false). Defaults to true. Exposed as r2wc boolean prop on WebCallControl and WebCallControlCAD
  • isDeclineButtonEnabled — store-level flag for auto-answer scenarios that overrides SDK's decline.isEnabled. Threaded through IncomingTask and TaskList component hierarchies

Hold state handling:

  • Introduced isHeld state in useCallControl hook, initialized from isInteractionOnHold(currentTask) and updated by TASK_HOLD / TASK_RESUME event callbacks
  • buildCallControlButtons() uses isHeld to toggle hold/resume icon and tooltip (not controls.hold.isEnabled, which is an action flag)

Transfer button mapping fix:

  • transferConsult button now correctly maps to controls.consultTransfer (not controls.transfer) to prevent duplicate "Transfer" buttons when SDK sets transfer: visible and consultTransfer: hidden

Type and Web Component updates:

  • Updated ControlProps, CallControlComponentProps, CallControlConsultComponentsProps, IncomingTaskComponentProps, TaskListComponentProps in task.types.ts
  • Updated CallControlProps and useCallControlProps in task/src/task.types.ts
  • Added conferenceEnabled: 'boolean' to r2wc prop definitions in wc.ts

Migration documentation:

  • Updated call-control-hook-migration.md, component-layer-migration.md, and store-task-utils-migration.md with fix logs for all restored props, corrected "Props removed" tables, and documented design decisions

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

  • The testing is done with the amplify link
    < ENUMERATE TESTS PERFORMED, WHETHER MANUAL OR AUTOMATED >

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

Checklist before merging

  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the testing document
  • I have tested the functionality with amplify link

Make sure to have followed the contributing guidelines before submitting.

@akulakum akulakum requested a review from a team as a code owner April 7, 2026 16:21
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2227d693dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +588 to +590
if (lastWrapupAuxCodeIdRef.current) {
const wrapUpReason = store.wrapupCodes.find((code) => code.id === lastWrapupAuxCodeIdRef.current)?.name;
if (onWrapUp) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore onWrapUp callback for SDK-driven wrapups

wrapupCallCallback now emits onWrapUp only when lastWrapupAuxCodeIdRef.current is present, but that ref is only set in wrapupCall(). As a result, wrapups triggered outside this path (for example auto-wrapup or other SDK-driven/task-synced wrapup events) will fire TASK_WRAPPEDUP but never notify consumers via onWrapUp, which breaks callback-based integrations such as analytics or workflow hooks.

Useful? React with 👍 / 👎.

</div>
</>
)}
{!controls?.wrapup?.isVisible && isInteractionOnHold(currentTask) && (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep consult-state gating for the CAD hold indicator

The hold badge now depends only on isInteractionOnHold(currentTask), which becomes true when either the main leg or consult leg is held. During consult/conference flows one leg is often intentionally held while the agent is active on the other, so this change can incorrectly show an ON HOLD status. The previous logic gated this by consult-state flags, and removing that gating regresses status accuracy.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant