Skip to content

feat(cc): add campaign preview#684

Open
cmullenx wants to merge 5 commits into
webex:nextfrom
cmullenx:chrmulle/campaignPrev
Open

feat(cc): add campaign preview#684
cmullenx wants to merge 5 commits into
webex:nextfrom
cmullenx:chrmulle/campaignPrev

Conversation

@cmullenx
Copy link
Copy Markdown
Contributor

@cmullenx cmullenx commented May 11, 2026

COMPLETES #https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7660 and https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7662

This pull request addresses

Adds the UI for the campaign preview functionality

by making the following changes

creates new components for campaign preview
creates global variable component to share between call control cad and campaign components
makes changes to call control cad to render campaign preview ui
adds campaign preview to task list only when flag is enabled

Figma: https://www.figma.com/design/JvnDPHRIXlvZEiSSCBwtjk/WxCC-6242---Preview-Campaign?node-id=6473-173114&m=dev

Vidcast: https://app.vidcast.io/share/72f03823-417d-4417-8a5a-35032943f3d3

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 >

  • Can accept campaign previews

  • Can skip campaign previews

  • Can remove campaign previews

  • Can disable skip/remove buttons based on campaign settings

  • Campaign auto action fires when campaign times out

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 - Windsurf
  • 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.

@cmullenx cmullenx requested a review from a team as a code owner May 11, 2026 20:32
@cmullenx cmullenx added validated Indicates that the PR is ready for actions run_e2e Add this label to run E2E test for meeting and CC widgets labels May 11, 2026
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: c3cda98967

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +58 to +62
// Campaign preview handling: render only the active one, skip stale duplicates
if (hasCampaignPreviewEnabled && isCampaignPreviewTask(task) && hasAgentJoinedTask(task, agentId)) {
if (task.data.interactionId !== activeCampaignId) {
return null; // skip stale campaign preview
}
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 Filter dismissed campaign previews before rendering

When Skip or Remove succeeds, dismissAndSkip/dismissAndRemove add the interaction to dismissedCampaignIds, but this render branch never checks that set. If the SDK keeps returning the same task until the backend sends the follow-up update/end event, the skipped or removed preview remains visible with disabled controls instead of being hidden immediately, which defeats the dismissal tracking added in the store.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed

Comment on lines +34 to +36

if (!participants) return undefined;

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 Use the agent participant for handle time

For accepted campaign previews with multiple joined participants, this returns the first joined participant in object iteration order rather than the logged-in agent. If the customer or another participant appears first, the CampaignTask handle-time timer is initialized from that participant's joinTimestamp, so the displayed handle time can be wrong after acceptance or hydration; pass/use the agent id and read that participant specifically.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed

@aws-amplify-us-east-2
Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-684.d1b38q61t1z947.amplifyapp.com

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: 9a2feebe73

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +87 to +90
const globalVariablesRef = useRef(latestGlobalVariables);
if (latestGlobalVariables.length > 0) {
globalVariablesRef.current = latestGlobalVariables;
}
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 Reset CAD variables when task changes

When currentTask changes to a different interaction whose snapshot has no callAssociatedData, this ref is not cleared because it only updates for non-empty arrays. GlobalVariablesPanel will then keep rendering the previous task's global variables, which can show stale or wrong customer CAD on the next call; key/reset the ref by interactionId before preserving missing snapshots for the same task.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed

Comment on lines +755 to +756
if (this.onIncomingTask && !this.taskList[task.data.interactionId]) {
this.onIncomingTask({task});
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 Do not enqueue campaign previews as incoming tasks

For campaign preview reservations, invoking onIncomingTask sends the preview through the existing IncomingTask UI path; that hook's Accept/Decline buttons call task.accept()/task.decline(), while the preview flow added here requires cc.acceptPreviewContact/skipPreviewContact/removePreviewContact from CampaignTask. In apps that render IncomingTask from this callback (including the sample app), a preview offer can therefore expose duplicate controls and let users take the wrong SDK action.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is intended and is consistent with agent desktop the flow is:

  1. handleIncomingCampaignPreview → onIncomingTask → IncomingTask UI renders (Accept/Decline)
    2)Agent clicks Accept → task.accept() → enters RESERVED
  2. handleCampaignPreviewReservation → refreshTaskList → CampaignTask renders (Accept/Skip/Remove the contact)

The IncomingTask and CampaignTask never render simultaneously — IncomingTask handles the initial task offer, and CampaignTask only renders after the agent has accepted and hasAgentJoinedTask() returns true. The onIncomingTask call is required for the agent to accept the initial task to be in the reserved state so that they can determine what they want to do with the campaign.

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: 003596fba6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +91 to +94
const globalVariablesRef = useRef(latestGlobalVariables);
if (latestGlobalVariables.length > 0) {
globalVariablesRef.current = latestGlobalVariables;
}
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 Reset campaign CAD when a new preview contact arrives

When Skip/Remove advances the same campaign task to another contact and the SDK update omits or empties callAssociatedData, this ref never clears because it only writes non-empty values. The component already detects new contacts via timeoutTimestamp below, but GlobalVariablesPanel will keep showing the previous contact's global variables on the next preview; reset/key the ref when the offer changes, and mirror the same fix in the popover path.

Useful? React with 👍 / 👎.

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: 97c2c9dd1a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// The agent has joined the telephony reservation but hasn't accepted the
// campaign preview yet (Accept/Skip/Remove buttons still showing).
// CallControl should only render after the preview is explicitly accepted.
if (task && this.isCampaignPreview(task) && task.data.interaction.state === 'new') return;
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 Honor accepted campaign IDs when selecting current task

When a campaign preview accept is confirmed via handleCampaignPreviewReservation, this change records the interaction in acceptedCampaignIds and immediately refreshes the task list, but this guard still rejects any campaign snapshot whose interaction.state is still 'new'. In that transient accepted-but-not-yet-state-updated case, the accepted preview is never assigned to currentTask, so CallControl/CallControlCAD stay hidden until another SDK update arrives; use the accepted-campaign set here as well before treating the preview as pending.

Useful? React with 👍 / 👎.

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

Labels

run_e2e Add this label to run E2E test for meeting and CC widgets validated Indicates that the PR is ready for actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant