Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {DEFAULT_PAGE_SIZE} from '../../constants';
* @param logger - Optional logger instance for diagnostics.
* @returns An object containing the transformed data (U[]), pagination state and helpers.
*/
export const usePaginatedData = <T, U>(
export const usePaginatedData = <T, U extends {name?: string}>(
fetchFunction: FetchPaginatedList<T> | undefined,
transformFunction: TransformPaginatedData<T, U>,
categoryName: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import {
getAgentsForDisplay,
} from './call-control-custom.utils';
import {useConsultTransferPopover} from './consult-transfer-popover-hooks';
import {
isAgentsTabVisible,
isEntryPointTabVisible,
isQueuesTabVisible,
ConsultTransferAction,
} from './consult-transfer-tab.utils';

import {
SEARCH_PLACEHOLDER,
Expand All @@ -34,12 +40,26 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
onDialNumberSelect,
onEntryPointSelect,
allowConsultToQueue,
accessQueue,
accessEntryPoint,
accessBuddyTeam,
interactionContext,
isTelephony = true,
consultTransferOptions,
isConferenceInProgress,
logger,
}) => {
const {showDialNumberTab = true, showEntryPointTab = true} = consultTransferOptions || {};
const isEntryPointTabVisible = showEntryPointTab && heading === 'Consult';
const action: ConsultTransferAction = heading === 'Transfer' ? 'Transfer' : 'Consult';
const isQueueTabVisible = isQueuesTabVisible(
action,
allowConsultToQueue,
accessQueue,
interactionContext ?? {},
isTelephony
);
const isAgentsTabVisibleFlag = isAgentsTabVisible(accessBuddyTeam);
const isEntryPointTabVisibleFlag = isEntryPointTabVisible(showEntryPointTab, accessEntryPoint, isTelephony);
const {
selectedCategory,
searchQuery,
Expand All @@ -61,7 +81,7 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
handleReload,
} = useConsultTransferPopover({
showDialNumberTab,
showEntryPointTab: isEntryPointTabVisible,
showEntryPointTab: isEntryPointTabVisibleFlag,
getAddressBookEntries,
getEntryPoints,
getQueues,
Expand Down Expand Up @@ -92,13 +112,13 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
</ListNext>
);

const noQueues = !allowConsultToQueue || queuesData.length === 0;
const noQueues = !isQueueTabVisible || queuesData.length === 0;
const noDialNumbers = !showDialNumberTab || dialNumbers.length === 0;
const noEntryPoints = !isEntryPointTabVisible || entryPoints.length === 0;
const noEntryPoints = !isEntryPointTabVisibleFlag || entryPoints.length === 0;

const consultTransferManualAction = shouldAddConsultTransferAction(
selectedCategory,
isEntryPointTabVisible,
isEntryPointTabVisibleFlag,
allowParticipantsToInteract,
searchQuery,
entryPoints,
Expand Down Expand Up @@ -180,17 +200,19 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
</div>

<div className="consult-category-buttons">
<Button
variant={selectedCategory === CATEGORY_AGENTS ? 'primary' : 'secondary'}
size="small"
onClick={handleAgentsClick}
className={`consult-category-button-standard ${
selectedCategory === CATEGORY_AGENTS ? 'consult-category-button-active' : ''
}`}
>
{CATEGORY_AGENTS}
</Button>
{allowConsultToQueue && (
{isAgentsTabVisibleFlag && (

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 Select a visible category when Agents is hidden

When accessBuddyTeam is NONE, this removes the Agents button but the hook still initializes selectedCategory to Agents and the list rendering at line 254 is not gated by isAgentsTabVisibleFlag. The popover therefore opens with no visible active tab and can still display/select any preloaded buddy agents despite the profile restriction; initialize the selection to the first permitted category and gate the Agents content as well.

Useful? React with 👍 / 👎.

<Button
variant={selectedCategory === CATEGORY_AGENTS ? 'primary' : 'secondary'}
size="small"
onClick={handleAgentsClick}
className={`consult-category-button-standard ${
selectedCategory === CATEGORY_AGENTS ? 'consult-category-button-active' : ''
}`}
>
{CATEGORY_AGENTS}
</Button>
)}
{isQueueTabVisible && (
<Button
variant={selectedCategory === CATEGORY_QUEUES ? 'primary' : 'secondary'}
size="small"
Expand All @@ -214,7 +236,7 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
{CATEGORY_DIAL_NUMBER}
</Button>
)}
{isEntryPointTabVisible && (
{isEntryPointTabVisibleFlag && (
<Button
variant={selectedCategory === CATEGORY_ENTRY_POINT ? 'primary' : 'secondary'}
size="small"
Expand Down Expand Up @@ -309,7 +331,7 @@ const ConsultTransferPopoverComponent: React.FC<ConsultTransferPopoverComponentP
</div>
))}

{isEntryPointTabVisible &&
{isEntryPointTabVisibleFlag &&
selectedCategory === CATEGORY_ENTRY_POINT &&
(loadingEntryPoints && entryPoints.length === 0 ? (
<div className="consult-loading-spinner">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export type ConsultTransferAction = 'Consult' | 'Transfer';

export type ConsultTransferInteractionContext = {
contactDirectionType?: string;
outdialTransferToQueueEnabled?: boolean;
mediaType?: string;
};

export const isCollaborationAccessEnabled = (access?: string): boolean => access?.toLowerCase() !== 'none';

export const isQueueEnabled = (
action: ConsultTransferAction,
allowConsultToQueue: boolean,
interaction: ConsultTransferInteractionContext,
isTelephony: boolean
): boolean => {
if (!isTelephony) {
return true;
}

if (action === 'Consult') {
return allowConsultToQueue;
}

const direction = interaction.contactDirectionType?.toUpperCase();
if (direction === 'INBOUND') {
return true;
}
if (direction === 'OUTBOUND') {
return interaction.outdialTransferToQueueEnabled === true;
}

return true;
};

export const isAgentsTabVisible = (accessBuddyTeam?: string): boolean => isCollaborationAccessEnabled(accessBuddyTeam);

export const isQueuesTabVisible = (
action: ConsultTransferAction,
allowConsultToQueue: boolean,
accessQueue: string | undefined,
interaction: ConsultTransferInteractionContext,
isTelephony: boolean
): boolean =>
isCollaborationAccessEnabled(accessQueue) && isQueueEnabled(action, allowConsultToQueue, interaction, isTelephony);

export const isEntryPointTabVisible = (
showEntryPointTab: boolean,
accessEntryPoint: string | undefined,
isTelephony: boolean
): boolean => showEntryPointTab && isTelephony && isCollaborationAccessEnabled(accessEntryPoint);
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ function CallControlComponent(props: CallControlComponentProps) {
callControlAudio,
setConsultAgentName,
allowConsultToQueue,
accessQueue,
accessEntryPoint,
accessBuddyTeam,
interactionContext,
setLastTargetType,
controls,
logger,
Expand Down Expand Up @@ -242,6 +246,11 @@ function CallControlComponent(props: CallControlComponentProps) {
handleTargetSelect(dialNumber, dialNumber, 'dialNumber', allowParticipantsToInteract)
}
allowConsultToQueue={allowConsultToQueue}
accessQueue={accessQueue}
accessEntryPoint={accessEntryPoint}
accessBuddyTeam={accessBuddyTeam}
interactionContext={interactionContext}
isTelephony={isTelephony}
consultTransferOptions={
isTelephony
? consultTransferOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,18 @@ export interface ControlProps {
*/
allowConsultToQueue: boolean;

/** Desktop Profile collaboration access for queues */
accessQueue?: string;

/** Desktop Profile collaboration access for entry points */
accessEntryPoint?: string;

/** Desktop Profile collaboration access for buddy teams */
accessBuddyTeam?: string;
Comment on lines +471 to +478

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 Update the owning cc-components spec

This adds collaboration-access props and changes Consult/Transfer tab behavior in cc-components, but the commit updates only the store and task specs; packages/contact-center/cc-components/ai-docs/cc-components-spec.md remains unchanged. Document the new props, visibility rules, and access behavior in the owning module spec in this change.

AGENTS.md reference: AGENTS.md:L68-L68

Useful? React with 👍 / 👎.


/** Interaction context for Consult/Transfer tab visibility */
interactionContext?: ConsultTransferInteractionContext;

/**
* Flag to enable or disable conference feature
*/
Expand Down Expand Up @@ -553,6 +565,10 @@ export type CallControlComponentProps = Pick<
| 'consultTimerLabel'
| 'consultTimerTimestamp'
| 'allowConsultToQueue'
| 'accessQueue'
| 'accessEntryPoint'
| 'accessBuddyTeam'
| 'interactionContext'
| 'lastTargetType'
| 'setLastTargetType'
| 'controls'
Expand Down Expand Up @@ -665,6 +681,15 @@ export interface ConsultTransferDialNumberComponentProps {
logger: ILogger;
}

/**
* Interaction fields used for Consult/Transfer tab visibility (Agent Desktop parity).
*/
export type ConsultTransferInteractionContext = {
contactDirectionType?: string;
outdialTransferToQueueEnabled?: boolean;
mediaType?: string;
};

/**
* Interface representing the properties for ConsultTransferPopover component.
*/
Expand All @@ -682,6 +707,11 @@ export interface ConsultTransferPopoverComponentProps {
onEntryPointSelect: (entryPointId: string, entryPointName: string, allowParticipantsToInteract: boolean) => void;
onDialNumberSelect: (dialNumber: string, allowParticipantsToInteract: boolean) => void;
allowConsultToQueue: boolean;
accessQueue?: string;
accessEntryPoint?: string;
accessBuddyTeam?: string;
interactionContext?: ConsultTransferInteractionContext;
isTelephony?: boolean;
/** Options governing popover visibility/behavior */
consultTransferOptions?: ConsultTransferOptions;
isConferenceInProgress?: boolean;
Expand Down
Loading
Loading