-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor custom directory components for reusability, override worker…
… directory (#430)
- Loading branch information
Showing
17 changed files
with
561 additions
and
382 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
156 changes: 156 additions & 0 deletions
156
...late-v2/src/feature-library/custom-transfer-directory/custom-components/DirectoryItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import * as React from 'react'; | ||
import { TaskHelper, ITask, templates } from '@twilio/flex-ui'; | ||
import { Box } from '@twilio-paste/core/box'; | ||
import { ButtonGroup } from '@twilio-paste/core/button-group'; | ||
import { Button } from '@twilio-paste/core/button'; | ||
import { Flex } from '@twilio-paste/core/flex'; | ||
import { Tooltip } from '@twilio-paste/core/tooltip'; | ||
import { Text } from '@twilio-paste/core/text'; | ||
import { AgentIcon } from '@twilio-paste/icons/esm/AgentIcon'; | ||
import { ProductContactCenterTeamsIcon } from '@twilio-paste/icons/esm/ProductContactCenterTeamsIcon'; | ||
import { ProductPhoneNumbersIcon } from '@twilio-paste/icons/esm/ProductPhoneNumbersIcon'; | ||
import { CallTransferIcon } from '@twilio-paste/icons/esm/CallTransferIcon'; | ||
import { CallOutgoingIcon } from '@twilio-paste/icons/esm/CallOutgoingIcon'; | ||
import { SendIcon } from '@twilio-paste/icons/esm/SendIcon'; | ||
import { ChatIcon } from '@twilio-paste/icons/esm/ChatIcon'; | ||
|
||
import { DirectoryEntry } from '../types/DirectoryEntry'; | ||
import { StringTemplates } from '../flex-hooks/strings/CustomTransferDirectory'; | ||
|
||
export interface DirectoryItemProps { | ||
entry: DirectoryEntry; | ||
task: ITask; | ||
onTransferClick: (options: any) => void; | ||
} | ||
|
||
const DirectoryItem = (props: DirectoryItemProps) => { | ||
const { entry, task, onTransferClick } = props; | ||
|
||
const onWarmTransferClick = () => { | ||
onTransferClick({ mode: 'WARM' }); | ||
}; | ||
|
||
const onColdTransferClick = () => { | ||
onTransferClick({ mode: 'COLD' }); | ||
}; | ||
|
||
const renderIcon = (): React.JSX.Element => { | ||
if (entry.icon) { | ||
return entry.icon; | ||
} | ||
|
||
switch (entry.type) { | ||
case 'number': | ||
return <ProductPhoneNumbersIcon decorative={true} />; | ||
case 'queue': | ||
return <ProductContactCenterTeamsIcon decorative={true} />; | ||
default: | ||
return <AgentIcon decorative={true} />; | ||
} | ||
}; | ||
|
||
const renderLabel = (): React.JSX.Element => ( | ||
<Box key={`directory-item-label-${entry.type}-${entry.address}`} element="TRANSFER_DIR_COMMON_ROW_LABEL"> | ||
{entry.labelComponent || ( | ||
<Text as="div" className="Twilio" element="TRANSFER_DIR_COMMON_ROW_NAME"> | ||
{entry.label} | ||
</Text> | ||
)} | ||
</Box> | ||
); | ||
|
||
return ( | ||
<Flex | ||
element="TRANSFER_DIR_COMMON_HORIZONTAL_ROW_CONTAINER" | ||
vertical={false} | ||
vAlignContent="center" | ||
key={`directory-item-container-${entry.type}-${entry.address}`} | ||
> | ||
<Box key={`directory-item-icon-${entry.type}-${entry.address}`} element="TRANSFER_DIR_COMMON_ROW_ICON"> | ||
{renderIcon()} | ||
</Box> | ||
{entry.tooltip ? ( | ||
<Tooltip | ||
key={`directory-item-label-tooltip-${entry.type}-${entry.address}`} | ||
element="TRANSFER_DIR_COMMON_TOOLTIP" | ||
text={entry.tooltip} | ||
> | ||
{renderLabel()} | ||
</Tooltip> | ||
) : ( | ||
renderLabel() | ||
)} | ||
|
||
<ButtonGroup | ||
element="TRANSFER_DIR_COMMON_ROW_BUTTONGROUP" | ||
key={`directory-item-buttongroup-${entry.type}-${entry.address}`} | ||
attached | ||
> | ||
{entry.warm_transfer_enabled ? ( | ||
<Tooltip | ||
key={`directory-item-buttons-warm-transfer-tooltip-${entry.type}-${entry.address}`} | ||
element="TRANSFER_DIR_COMMON_TOOLTIP" | ||
text={templates[StringTemplates.WarmTransfer]()} | ||
> | ||
<Button | ||
element="TRANSFER_DIR_COMMON_ROW_BUTTON" | ||
key={`directory-item-warm-transfer-button-${entry.type}-${entry.address}`} | ||
variant="secondary_icon" | ||
size="circle" | ||
onClick={onWarmTransferClick} | ||
> | ||
{task && TaskHelper.isChatBasedTask(task) ? ( | ||
<ChatIcon | ||
key={`directory-item-warm-transfer-icon-${entry.type}-${entry.address}`} | ||
decorative={false} | ||
title="" | ||
/> | ||
) : ( | ||
<CallTransferIcon | ||
key={`directory-item-warm-transfer-icon-${entry.type}-${entry.address}`} | ||
decorative={false} | ||
title="" | ||
/> | ||
)} | ||
</Button> | ||
</Tooltip> | ||
) : ( | ||
<div></div> | ||
)} | ||
{entry.cold_transfer_enabled ? ( | ||
<Tooltip | ||
key={`directory-item-buttons-cold-transfer-tooltip-${entry.type}-${entry.address}`} | ||
element="TRANSFER_DIR_COMMON_TOOLTIP" | ||
text={templates[StringTemplates.ColdTransfer]()} | ||
> | ||
<Button | ||
element="TRANSFER_DIR_COMMON_ROW_BUTTON" | ||
key={`directory-item-warm-transfer-button-${entry.type}-${entry.address}`} | ||
variant="secondary_icon" | ||
size="circle" | ||
onClick={onColdTransferClick} | ||
> | ||
{task && TaskHelper.isChatBasedTask(task) ? ( | ||
<SendIcon | ||
key={`directory-item-cold-transfer-icon-${entry.type}-${entry.address}`} | ||
decorative={false} | ||
title="" | ||
/> | ||
) : ( | ||
<CallOutgoingIcon | ||
key={`directory-item-cold-transfer-icon-${entry.type}-${entry.address}`} | ||
decorative={false} | ||
title="" | ||
/> | ||
)} | ||
</Button> | ||
</Tooltip> | ||
) : ( | ||
<div></div> | ||
)} | ||
</ButtonGroup> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default DirectoryItem; |
95 changes: 95 additions & 0 deletions
95
...plate-v2/src/feature-library/custom-transfer-directory/custom-components/DirectoryTab.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { Alert } from '@twilio-paste/core/alert'; | ||
import { Flex } from '@twilio-paste/core/flex'; | ||
import { Spinner } from '@twilio-paste/core/spinner'; | ||
import { withTaskContext, ITask, Actions, Template, templates } from '@twilio/flex-ui'; | ||
import { useState, useRef, useEffect } from 'react'; | ||
import debounce from 'lodash/debounce'; | ||
|
||
import DirectoryItem from './DirectoryItem'; | ||
import SearchBox from './SearchBox'; | ||
import { StringTemplates } from '../flex-hooks/strings/CustomTransferDirectory'; | ||
import { DirectoryEntry } from '../types/DirectoryEntry'; | ||
|
||
export interface TransferClickPayload { | ||
mode: 'WARM' | 'COLD'; | ||
} | ||
|
||
export interface OwnProps { | ||
task: ITask; | ||
entries: Array<DirectoryEntry>; | ||
isLoading: boolean; | ||
noEntriesMessage?: string; | ||
onTransferClick: (entry: DirectoryEntry, transferOptions: TransferClickPayload) => void; | ||
} | ||
|
||
const DirectoryTab = (props: OwnProps) => { | ||
const [filteredDirectory, setFilteredDirectory] = useState([] as Array<DirectoryEntry>); | ||
|
||
const searchInputRef = useRef<HTMLInputElement>(null); | ||
|
||
// takes the input in the search box and applies it to filter the entry list | ||
const onQueueSearchInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
// eslint-disable-next-line no-eq-null, eqeqeq | ||
if (event.target != null) { | ||
filterDirectoryDebounce(); | ||
} | ||
}; | ||
|
||
// function to filter the entries and trigger a re-render | ||
const filterDirectory = () => { | ||
const tempDir = props.entries.filter((entry) => { | ||
const searchString = searchInputRef.current?.value.toLocaleLowerCase() || ''; | ||
return entry.label.toLocaleLowerCase().includes(searchString); | ||
}); | ||
|
||
setFilteredDirectory(tempDir); | ||
}; | ||
|
||
const filterDirectoryDebounce = debounce(filterDirectory, 500, { maxWait: 1000 }); | ||
|
||
const onTransferEntryClick = (entry: DirectoryEntry) => async (transferOptions: TransferClickPayload) => { | ||
props.onTransferClick(entry, transferOptions); | ||
Actions.invokeAction('HideDirectory'); | ||
}; | ||
|
||
useEffect(() => { | ||
filterDirectory(); | ||
}, [props.entries]); | ||
|
||
return ( | ||
<Flex key="external-directory-tab-list" vertical wrap={false} grow={1} shrink={1}> | ||
<SearchBox key="key-tab-search-box" onInputChange={onQueueSearchInputChange} inputRef={searchInputRef} /> | ||
<Flex key="external-tab-results" vertical element="TRANSFER_DIR_COMMON_ROWS_CONTAINER"> | ||
{props.isLoading && ( | ||
<Flex hAlignContent="center"> | ||
<Spinner decorative size="sizeIcon90" /> | ||
</Flex> | ||
)} | ||
{filteredDirectory.length === 0 && !props.isLoading ? ( | ||
<Alert variant="neutral"> | ||
<Template | ||
source={ | ||
props.noEntriesMessage && !searchInputRef.current?.value | ||
? props.noEntriesMessage | ||
: templates[StringTemplates.NoItemsFound] | ||
} | ||
/> | ||
</Alert> | ||
) : ( | ||
Array.from(filteredDirectory).map((entry: DirectoryEntry) => { | ||
return ( | ||
<DirectoryItem | ||
task={props.task} | ||
entry={entry} | ||
key={`dir-item-${entry.type}-${entry.address}`} | ||
onTransferClick={onTransferEntryClick(entry)} | ||
/> | ||
); | ||
}) | ||
)} | ||
</Flex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default withTaskContext(DirectoryTab); |
Oops, something went wrong.