import callDirections from '@ringcentral-integration/commons/enums/callDirections'; import { callResults } from '@ringcentral-integration/commons/enums/callResults'; import type { TelephonyStatus } from '@ringcentral-integration/commons/enums/telephonyStatus'; import telephonyStatuses from '@ringcentral-integration/commons/enums/telephonyStatus'; import type { Call } from '@ringcentral-integration/commons/interfaces/Call.interface'; import { isMissed } from '@ringcentral-integration/commons/lib/callLogHelpers'; import { formatDuration } from '@ringcentral-integration/commons/lib/formatDuration'; import { RcIcon, RcLink, RcText, RcTooltip } from '@ringcentral/juno'; import { Hold, ResendFax, Team } from '@ringcentral/juno-icon'; import clsx from 'clsx'; import { isEmpty } from 'ramda'; import type { FunctionComponent } from 'react'; import React from 'react'; import dynamicsFont from '../../assets/DynamicsFont/DynamicsFont.scss'; import { DurationCounter } from '../DurationCounter'; import { RecordingIndicator } from '../RecordingIndicator'; import { CallIcon } from './CallIcon'; import { ShinyBar } from './ShinyBar'; import i18n from './i18n'; import { StyledSide, StyledSubRecordingIndicator, StyledSubSide, StyledTransferSwitchButton, StyleSubBox, SubInfoName, SubInfoWrapper, StyledParticipantsButton, } from './styles'; import styles from './styles.scss'; const callIconMap = { [callResults.missed]: dynamicsFont.missed, [callDirections.inbound]: dynamicsFont.inbound, [callDirections.outbound]: dynamicsFont.outbound, [telephonyStatuses.ringing]: dynamicsFont.callHover, conferenceCall: dynamicsFont.conference, }; function getInfoStatus(status?: TelephonyStatus) { switch (status) { case telephonyStatuses.onHold: return 'onHold'; case telephonyStatuses.callConnected: case telephonyStatuses.ringing: return 'active'; default: return 'callEnd'; } } interface ILogInfo { call?: Call; logName?: string; subContactNameDisplay?: string; entityDetailLinkId?: string; } type LogBasicInfoProps = { currentLocale?: string; formatPhone?: (...args: any[]) => string; currentLog?: ILogInfo; subCallLog?: ILogInfo; dataSign?: string; disableLinks?: boolean; dateTimeFormatter: (...args: any[]) => any; isWide?: boolean; className?: string; showRecordingIndicator?: boolean; openEntityDetailLinkTrack?: (...args: any[]) => any; openEntityDetailLink: (entityDetailLinkId: string) => any; onSwitchWarmTransferSession?: () => any; disabledSwitchButton: boolean; toggleConference: (open: boolean) => any; conferenceParticipantsIsOpen: boolean; }; type CallInfoProps = Omit & { displayCallLog: ILogInfo; }; const SubCallInfoSection: FunctionComponent = ({ displayCallLog: { call, logName, subContactNameDisplay, entityDetailLinkId }, disabledSwitchButton, currentLocale, disableLinks, isWide, showRecordingIndicator, openEntityDetailLink, openEntityDetailLinkTrack, onSwitchWarmTransferSession, }) => { if (!call) return null; const { startTime, offset, duration, telephonyStatus, isRecording } = call; function getDurationElm() { let durationElement = null; if (typeof duration === 'undefined') { durationElement = disableLinks ? ( // TODO: should find what is that key, this unavailable is not exist // i18n.getString('unavailable', currentLocale) 'unavailable' ) : ( ); } else { durationElement = formatDuration(duration); } return durationElement; } const durationElement = getDurationElm(); const infoStatus = getInfoStatus(telephonyStatus); const switchButtonDisabled = disableLinks || disabledSwitchButton; return (
{entityDetailLinkId ? ( { openEntityDetailLink?.(entityDetailLinkId); openEntityDetailLinkTrack?.('call log page'); }} > {logName} ) : ( logName )} {subContactNameDisplay && ( {` ${subContactNameDisplay}`} )}

{durationElement}

{showRecordingIndicator && isRecording && ( )}
); }; const ActiveCallInfoSection: FunctionComponent = ({ displayCallLog: { call, logName, subContactNameDisplay, entityDetailLinkId }, formatPhone, currentLocale, dataSign, disableLinks, dateTimeFormatter, isWide, className, showRecordingIndicator, openEntityDetailLinkTrack, openEntityDetailLink, toggleConference, conferenceParticipantsIsOpen, }) => { if (!call) return null; const { direction, to, from, startTime, offset, duration, result, telephonyStatus, isRecording, isConferenceCall, conferenceParticipants, } = call; function getDurationElm() { let durationElement = null; if (typeof duration === 'undefined') { durationElement = disableLinks ? ( // TODO: should find what is that key, this unavailable is not exist // i18n.getString('unavailable', currentLocale) 'unavailable' ) : ( ); } else { durationElement = formatDuration(duration); } return durationElement; } const number = direction === callDirections.outbound ? to && (to.phoneNumber || to.extensionNumber) : from && (from.phoneNumber || from.extensionNumber); const formatNumber = formatPhone?.(number); const missed = isMissed(call); const durationElement = getDurationElm(); const status = result || telephonyStatus; // @ts-expect-error TS(2345): Argument of type 'string | undefined' is not assig... Remove this comment to see the full error message const statusI18n = i18n.getString(status, currentLocale); const isRinging = status === telephonyStatuses.ringing; // @ts-expect-error TS(2345): Argument of type '"NoCall" | "OnHold" | "Ringing" ... Remove this comment to see the full error message const infoStatus = getInfoStatus(status); return (
  • {entityDetailLinkId ? ( { openEntityDetailLink?.(entityDetailLinkId); openEntityDetailLinkTrack?.('call log page'); }} > {logName} ) : ( logName )} {subContactNameDisplay && ( {` ${subContactNameDisplay}`} )}

    {isConferenceCall ? null : ( {formatNumber} )} {statusI18n}

  • {!call.result && isConferenceCall && (
  • toggleConference(true)} > {conferenceParticipants?.length}
  • )}
  • {isWide ? (
  • {durationElement} {showRecordingIndicator && isRecording && ( )}

    {dateTimeFormatter({ utcTimestamp: startTime, locale: currentLocale, })}

  • ) : (
  • {durationElement}

    {dateTimeFormatter({ utcTimestamp: startTime, locale: currentLocale, })}

    {showRecordingIndicator && isRecording && ( )}
  • )}
); }; const LogBasicInfo: React.FC = React.memo( (props) => { const { currentLog, subCallLog, ...rest } = props; // @ts-expect-error TS(2532): Object is possibly 'undefined'. const status = currentLog?.call.result || currentLog?.call.telephonyStatus; const disabledCtrl = status === telephonyStatuses.ringing; return ( <> {subCallLog && ( )} {/* @ts-expect-error TS(2322): Type 'ILogInfo | undefined' is not */} ); }, (prevProps, nextProps) => { // current call will be {} temporally when the call is ended // will not update log info component at that time if ( nextProps.currentLog?.call !== prevProps.currentLog?.call && isEmpty(nextProps.currentLog?.call) ) { return true; } return false; }, ); LogBasicInfo.defaultProps = { formatPhone: (value) => value, currentLog: {}, dataSign: undefined, disableLinks: false, isWide: true, currentLocale: 'en', className: undefined, showRecordingIndicator: false, }; export default LogBasicInfo;