docs(ai-docs): task refactor migration — widget hooks (PR 3/4)#647
docs(ai-docs): task refactor migration — widget hooks (PR 3/4)#647akulakum wants to merge 8 commits intowebex:nextfrom
Conversation
Add widget layer migration documentation: - 004: CallControl hook migration (largest hook, timer utils, recording cleanup) - 005: IncomingTask migration (isBrowser → task.uiControls.accept/decline) - 006: TaskList migration (per-task accept/decline rendering) - 007: OutdialCall migration (no changes needed — CC-level, not task-level) - 010: Component layer migration (cc-components: call-control.utils.ts, call-control-cad.tsx, props) Made-with: Cursor
|
This pull request is automatically being deployed by Amplify Hosting (learn more). |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e36142c785
ℹ️ 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".
| | `isConsultInitiatedAndAccepted` | Removed — SDK handles | | ||
| | `isConsultReceived` | Removed — SDK handles | | ||
| | `isConsultInitiatedOrAccepted` | `controls.endConsult.isVisible` | | ||
| | `isHeld` | `controls.hold` state (visible + disabled = held) | |
There was a problem hiding this comment.
Derive held state from task media, not control disablement
This mapping says isHeld should come from controls.hold being visible+disabled, but that will misclassify non-held calls during consult/conference transitions where hold is intentionally disabled for other reasons (see current getHoldResumeButtonVisibility logic in task-util.ts, where isEnabled depends on consult/conference state, not only hold state). Following this guidance can invert Hold/Resume behavior in the migration; the doc should point readers to participant/media hold status (e.g., findHoldStatus) instead.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b62e700eb0
ℹ️ 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".
| return ( | ||
| <div className="call-control"> | ||
| {controls.hold.isVisible && ( | ||
| <Button onClick={() => onToggleHold(!controls.hold.isEnabled)} disabled={!controls.hold.isEnabled}> |
There was a problem hiding this comment.
Derive hold toggles from media hold state, not enablement
This example still infers held state from controls.hold.isEnabled by calling onToggleHold(!controls.hold.isEnabled), which can invert Hold/Resume actions during consult/conference transitions where hold is disabled for reasons unrelated to held status. In the current logic (getHoldResumeButtonVisibility in task/src/Utils/task-util.ts), isEnabled depends on consult/conference predicates, so using it as a held proxy will issue the wrong SDK action in valid call states; the guidance should use actual media/participant hold status (for example findHoldStatus) for this decision.
Useful? React with 👍 / 👎.
| store.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, () => { | ||
| if (onAccepted) onAccepted({task: incomingTask}); | ||
| }, incomingTask.data.interactionId); |
There was a problem hiding this comment.
Reuse a named TASK_ASSIGNED callback for removable cleanup
The migrated snippet still registers TASK_ASSIGNED with an inline function, while the documented “same as before” cleanup pattern removes TASK_ASSIGNED via taskAssignCallback; because removeTaskCallback ultimately calls task.off(event, callback) (which requires the exact same function reference), this pattern leaves stale listeners attached across task changes/unmounts and can duplicate onAccepted executions.
Useful? React with 👍 / 👎.
Move widget-layer migration docs to packages/contact-center/ai-docs/migration/. Delete 007-outdial-call-migration.md (no task-refactor changes needed). Made-with: Cursor
Made-with: Cursor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42936f20c1
ℹ️ 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".
| | Old Flag | New Approach | | ||
| |----------|-------------| | ||
| | `isConferenceInProgress` | `controls.exitConference.isVisible` | | ||
| | `isConsultInitiated` | `controls.endConsult.isVisible` | |
There was a problem hiding this comment.
Preserve consult-initiating state separately from consulting
Mapping isConsultInitiated to controls.endConsult.isVisible collapses two distinct consult phases into one signal, because end-consult visibility represents both initiated and accepted consult states (the current getEndConsultButtonVisibility already gates on initiated-or-accepted). Any migration code that uses this mapping for consult labels or branching will misclassify active consulting as “consult requested,” which changes button filtering and status text behavior in valid call flows.
Useful? React with 👍 / 👎.
| | `controlVisibility.consultTransfer.isEnabled` | `controls.consultTransfer.isEnabled` | | ||
| | `controlVisibility.consultTransfer.isVisible` | `controls.consultTransfer.isVisible` | |
There was a problem hiding this comment.
Use transfer controls instead of hidden consultTransfer control
This migration row rewires consultTransfer to controls.consultTransfer, but the same docs describe the new model as splitting transfer actions across controls.transfer and controls.transferConference while consultTransfer is hidden. Implementing this row as written will bind consult/conference transfer UI to a control that never surfaces, causing transfer actions to disappear in consult/conference scenarios.
Useful? React with 👍 / 👎.
Removed serial numbers from filenames. Added migration gotchas to call-control-hook doc. Fixed isHeld State Flag mapping. Moved task-list and component-layer docs to PR 4. Made-with: Cursor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3918b09b17
ℹ️ 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".
| | `mergeConference` | `controls.mergeToConference` | **Renamed** + nested | | ||
| | `consult` | `controls.consult` | Nested | | ||
| | `endConsult` | `controls.endConsult` | Nested | | ||
| | `consultTransfer` | `controls.consultTransfer` | Nested (always hidden in new) | |
There was a problem hiding this comment.
Map consult transfer UI to active transfer controls
This row maps consultTransfer to controls.consultTransfer while simultaneously documenting that this new control is always hidden, which would remove consult/conference transfer actions when teams follow the table literally. The existing CallControl button builder currently renders transfer-in-consult from controlVisibility.consultTransfer, so wiring that path to an always-hidden control makes the transfer button disappear in active consult/conference flows; this mapping should instead point to the visible transfer controls (transfer / transferConference) used for those states.
Useful? React with 👍 / 👎.
| | `isConsultReceived` | Removed — SDK handles | | ||
| | `isConsultInitiatedOrAccepted` | `controls.endConsult.isVisible` | | ||
| | `isHeld` | **Do NOT derive from `controls.hold.isEnabled`** — use `findHoldStatus(task, 'mainCall', agentId)` from task data | | ||
| | `consultCallHeld` | `controls.switchToConsult.isVisible` | |
There was a problem hiding this comment.
Derive consult-held state from media hold status
Mapping consultCallHeld to controls.switchToConsult.isVisible loses real held-state information because switch-button visibility is gated by additional UI conditions (e.g. !isBeingConsulted in getSwitchToConsultButtonVisibility) that are unrelated to whether the consult leg is actually on hold. Using this mapping will misclassify consult hold state in valid flows and can skew downstream timer/status logic that depends on consultCallHeld; it should continue to come from participant/media hold data (for example findHoldStatus(task, 'consult', agentId)).
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3918b09b17
ℹ️ 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".
| store.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, () => { | ||
| if (onAccepted) onAccepted({task: incomingTask}); | ||
| }, incomingTask.data.interactionId); |
There was a problem hiding this comment.
Reuse one TASK_ASSIGNED callback for add/remove
The migrated useIncomingTask example still registers TASK_EVENTS.TASK_ASSIGNED with an inline arrow function, but cleanup is described as unchanged; that pattern cannot reliably unsubscribe because removeTaskCallback ultimately calls task.off(event, callback) and requires the same function reference used in setTaskCallback (packages/contact-center/store/src/storeEventsWrapper.ts). If this guidance is followed, changing/unmounting incomingTask can leave stale listeners behind and trigger duplicate onAccepted executions on later assignments.
Useful? React with 👍 / 👎.
…ation docs - useCallControl: use TASK_RECORDING_PAUSED/RESUMED in removeTaskCallback so cleanup matches setTaskCallback (fixes listener leak) - remove console.log from toggleMute - tests: invoke recording callbacks via TASK_RECORDING_* to match registration - call-control-hook-migration: document recording event alignment, add helper.ts code-location table, retain deviceType/featureFlags/conferenceEnabled for applyFeatureGates Made-with: Cursor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2538c8a2fa
ℹ️ 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".
| const onControlsUpdated = (updatedControls: TaskUIControls) => { | ||
| setControls(updatedControls); | ||
| }; | ||
| task.on(TASK_EVENTS.TASK_UI_CONTROLS_UPDATED, onControlsUpdated); |
There was a problem hiding this comment.
Replace undefined TASK_UI_CONTROLS_UPDATED enum usage
This migration example subscribes with TASK_EVENTS.TASK_UI_CONTROLS_UPDATED, but that enum member does not exist in packages/contact-center/store/src/store.types.ts (the enum currently ends at TASK_OUTDIAL_FAILED). If teams follow this snippet during the refactor, TypeScript compilation fails and the uiControls update listener cannot be wired, so the guidance should either use the literal 'task:ui-controls-updated' event name or add the enum constant first.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5cec293ab3
ℹ️ 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".
| if (!incomingTask) return; | ||
| store.setTaskCallback(TASK_EVENTS.TASK_ASSIGNED, taskAssignCallback, incomingTask.data.interactionId); | ||
| store.setTaskCallback(TASK_EVENTS.TASK_CONSULT_ACCEPTED, taskAssignCallback, incomingTask?.data.interactionId); | ||
| store.setTaskCallback(TASK_EVENTS.TASK_END, taskRejectCallback, incomingTask?.data.interactionId); |
There was a problem hiding this comment.
Declare taskRejectCallback in migrated useIncomingTask example
The “After (migrated)” snippet calls taskRejectCallback in setTaskCallback/removeTaskCallback and includes it in the effect dependency list, but the callback is never defined in the example. Because this section is presented as the full hook migration, teams copying it will get a TypeScript Cannot find name 'taskRejectCallback' error and incomplete reject/end wiring unless they guess the missing code.
Useful? React with 👍 / 👎.
COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7714
This pull request addresses
This is PR 3 of 4 in the task refactor migration documentation series. It covers the widget hooks layer —
useCallControlanduseIncomingTaskrefactoring to consumetask.uiControlsinstead ofgetControlsVisibility().by making the following changes
Added 2 widget hook migration documents under
packages/contact-center/ai-docs/migration/:call-control-hook-migration.md: Refactors
useCallControl(the largest hook) to consumetask.uiControls:{isVisible, isEnabled}structurecalculateStateTimerData,calculateConsultTimerData)incoming-task-migration.md: Replaces local
isBrowser/isDeclineButtonEnabledlogic withtask.uiControls.accept/decline— includes before/after for hook and componentNote:
task-list-migration.mdandcomponent-layer-migration.mdmoved to PR 4 to balance PR size.CC SDK Task-Refactor Branch Reference
Change Type
Related PRs
The following scenarios were tested
The GAI Coding Policy And Copyright Annotation Best Practices
Checklist before merging