diff --git a/packages/contact-center/cc-components/src/components/task/CallControlCAD/call-control-cad.tsx b/packages/contact-center/cc-components/src/components/task/CallControlCAD/call-control-cad.tsx index b2f31072a..2a8234f50 100644 --- a/packages/contact-center/cc-components/src/components/task/CallControlCAD/call-control-cad.tsx +++ b/packages/contact-center/cc-components/src/components/task/CallControlCAD/call-control-cad.tsx @@ -69,6 +69,9 @@ const CallControlCADComponent: React.FC = (props) => //@ts-expect-error To be fixed in SDK - https://jira-eng-sjc12.cisco.com/jira/browse/CAI-6762 const dn = currentTask?.data?.interaction?.callAssociatedDetails?.dn; + // Check if this is an outdial call - for outdial, show dialed number instead of entrypoint + const isOutdial = currentTask?.data?.interaction?.outboundType === 'OUTDIAL'; + // Create unique IDs for tooltips const customerNameTriggerId = `customer-name-trigger-${currentTask.data.interaction.interactionId}`; const customerNameTooltipId = `customer-name-tooltip-${currentTask.data.interaction.interactionId}`; @@ -76,7 +79,11 @@ const CallControlCADComponent: React.FC = (props) => const phoneNumberTooltipId = `phone-number-tooltip-${currentTask.data.interaction.interactionId}`; const renderCustomerName = () => { - const customerText = isSocial ? customerName || NO_CUSTOMER_NAME : ani || NO_CALLER_ID; + const customerText = isSocial + ? customerName || NO_CUSTOMER_NAME + : isOutdial + ? dn || ani || NO_CALLER_ID + : ani || NO_CALLER_ID; const textComponent = ( { }); }); + describe('Outdial tasks', () => { + it('should use dn (dialed number) as title for outdial telephony tasks', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + ronaTimeout: '30', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('+14155559876'); // Should show dn, not ani + expect(result.ani).toBe('+18005551234'); + expect(result.isTelephony).toBe(true); + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should fall back to ani when dn is not available for outdial tasks', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('+18005551234'); // Falls back to ani + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should use ani as title for non-outdial telephony tasks', () => { + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Inbound Customer', + virtualTeamName: 'Support Team', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('+18005551234'); // Should show ani for inbound + + // Restore + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + }); + + it('should fall back to ani when dn is empty string for outdial tasks', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('+18005551234'); // Empty dn falls back to ani + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should use ani for CALLBACK outboundType (not OUTDIAL)', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'CALLBACK'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Callback Customer', + virtualTeamName: 'Callback Team', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('+18005551234'); // CALLBACK uses ani, not dn + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should still use customerName for social media outdial tasks', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.SOCIAL; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: 'social-ani', + dn: 'social-dn', + customerName: 'Social Outdial Customer', + virtualTeamName: 'Social Team', + }; + + const result = extractIncomingTaskData(mockTask, true); + + expect(result.title).toBe('Social Outdial Customer'); // Social always uses customerName + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should extract correct button states for outdial telephony on non-browser', () => { + const originalMediaType = mockTask.data.interaction.mediaType; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalOutboundType = mockTask.data.interaction.outboundType; + const originalWrapUpRequired = mockTask.data.wrapUpRequired; + + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.wrapUpRequired = false; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + ronaTimeout: '30', + }; + + const result = extractIncomingTaskData(mockTask, false); + + expect(result.title).toBe('+14155559876'); + expect(result.acceptText).toBe('Ringing...'); + expect(result.declineText).toBeUndefined(); + expect(result.disableAccept).toBe(true); + + // Restore + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.outboundType = originalOutboundType; + mockTask.data.wrapUpRequired = originalWrapUpRequired; + }); + }); + describe('Edge cases', () => { it('should handle missing call association details', () => { const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; diff --git a/packages/contact-center/cc-components/tests/components/task/TaskList/task-list.utils.tsx b/packages/contact-center/cc-components/tests/components/task/TaskList/task-list.utils.tsx index ac93a7a84..a9bb2c65d 100644 --- a/packages/contact-center/cc-components/tests/components/task/TaskList/task-list.utils.tsx +++ b/packages/contact-center/cc-components/tests/components/task/TaskList/task-list.utils.tsx @@ -243,6 +243,205 @@ describe('task-list.utils', () => { mockTask.data.interaction.mediaType = originalMediaType; }); }); + + describe('Outdial tasks', () => { + it('should use dn (dialed number) as title for outdial telephony tasks', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('+14155559876'); // Should show dn, not ani + expect(result.ani).toBe('+18005551234'); + expect(result.isTelephony).toBe(true); + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should fall back to ani when dn is not available for outdial tasks', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('+18005551234'); // Falls back to ani + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should use ani as title for non-outdial telephony tasks even when dn is present', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Inbound Customer', + virtualTeamName: 'Support Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('+18005551234'); // Should show ani for inbound + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + }); + + it('should fall back to ani when dn is empty string for outdial tasks', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('+18005551234'); // Empty dn falls back to ani + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should use ani for CALLBACK outboundType (not OUTDIAL)', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'CALLBACK'; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Callback Customer', + virtualTeamName: 'Callback Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('+18005551234'); // CALLBACK uses ani, not dn + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should still use customerName for social media outdial tasks', () => { + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + + mockTask.data.interaction.state = 'connected'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.SOCIAL; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.interaction.callAssociatedDetails = { + ani: 'social-ani', + dn: 'social-dn', + customerName: 'Social Outdial Customer', + virtualTeamName: 'Social Team', + }; + + const result = extractTaskListItemData(mockTask, true, mockTask.data.agentId); + + expect(result.title).toBe('Social Outdial Customer'); // Social always uses customerName + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + }); + + it('should extract correct button states for incoming outdial telephony on non-browser', () => { + // Mock isIncomingTask to return true for this test + (isIncomingTask as jest.Mock).mockReturnValueOnce(true); + + const originalState = mockTask.data.interaction.state; + const originalCallAssociatedDetails = mockTask.data.interaction.callAssociatedDetails; + const originalMediaType = mockTask.data.interaction.mediaType; + const originalOutboundType = mockTask.data.interaction.outboundType; + const originalWrapUpRequired = mockTask.data.wrapUpRequired; + + mockTask.data.interaction.state = 'new'; + mockTask.data.interaction.mediaType = MEDIA_CHANNEL.TELEPHONY; + mockTask.data.interaction.outboundType = 'OUTDIAL'; + mockTask.data.wrapUpRequired = false; + mockTask.data.interaction.callAssociatedDetails = { + ani: '+18005551234', + dn: '+14155559876', + customerName: 'Outdial Customer', + virtualTeamName: 'Outbound Team', + ronaTimeout: '30', + }; + + const result = extractTaskListItemData(mockTask, false, mockTask.data.agentId); + + expect(result.title).toBe('+14155559876'); + expect(result.acceptText).toBe('Ringing...'); + expect(result.declineText).toBeUndefined(); + expect(result.disableAccept).toBe(true); + + // Restore + mockTask.data.interaction.state = originalState; + mockTask.data.interaction.callAssociatedDetails = originalCallAssociatedDetails; + mockTask.data.interaction.mediaType = originalMediaType; + mockTask.data.interaction.outboundType = originalOutboundType; + mockTask.data.wrapUpRequired = originalWrapUpRequired; + }); + }); }); describe('isTaskSelectable', () => {