import { assoc , converge , flip , identity , keys , mergeWith , pick , useWith , } from 'ramda' ; import { Module } from '@ringcentral-integration/commons/lib/di' ; import { proxify } from '@ringcentral-integration/commons/lib/proxy/proxify' ; import { HistoryCall } from '@ringcentral-integration/commons/modules/CallHistoryV2' ; import { action , computed , RcModuleV2 , state , storage , } from '@ringcentral-integration/core' ; import { Mapping } from '../../typings' ; import { AddLogHandlerFunctions , CallLogSectionCallStatus , CallLogStatus , CallsMappingType , Deps , } from './CallLogSection.interface' ; @ Module ( { deps : [ 'Storage' , 'CallHistory' , 'CallMonitor' , { dep : 'CallLogSectionOptions' , optional : true , } , ] , } ) export class CallLogSection < T extends Deps = Deps > extends RcModuleV2 < T > { _notSyncOpenState : boolean ; _storageKey : string ; private _readyCheckFunction : AddLogHandlerFunctions [ 'readyCheckFunction' ] ; private _logFunction : AddLogHandlerFunctions [ 'logFunction' ] ; private _onSuccess : AddLogHandlerFunctions [ 'onSuccess' ] ; private _onUpdate : AddLogHandlerFunctions [ 'onUpdate' ] ; private _onError : AddLogHandlerFunctions [ 'onError' ] ; constructor ( deps ) { super ( { deps , storageKey : 'callLogSection' , enableCache : true , } ) ; this . _notSyncOpenState = ! ! this . _deps . callLogSectionOptions ?. notSyncOpenState ; } @ state callsSavingStatus : Record < string , boolean > = { } ; @ storage @ state callsMappingState : CallsMappingType = { } ; @ storage @ state identifyList : Array < string > = [ ] ; @ state stateCurrentIdentify : string = null ; @ storage @ state storageCurrentIdentify : string = null ; @ state stateCurrentNotificationIdentify : string = null ; @ storage @ state storageCurrentNotificationIdentify : string = null ; @ state stateNotificationIsExpand : boolean = false ; @ storage @ state storageNotificationIsExpand : boolean = false ; _shouldInit ( ) { return super . _shouldInit ( ) && this . _readyCheckFunction ( ) ; } _shouldReset ( ) { return super . _shouldReset ( ) || ( this . ready && ! this . _readyCheckFunction ( ) ) ; } @ action update ( identify , newValue , callsSavingStatus ) { this . callsSavingStatus [ identify ] = callsSavingStatus ; const originalState = this . callsMappingState [ identify ] ; this . callsMappingState [ identify ] = { ... originalState , ... newValue , } ; this . identifyList = Array . from ( new Set ( [ ... this . identifyList , identify ] ) ) ; } @ proxify async saveSuccess ( identify ) { const originalState = this . callsMappingState [ identify ] ; this . update ( identify , { isSucceed : true , isEdited : ! ! ( originalState ?. latestUpdateTime && originalState ?. latestSaveTime && originalState ?. latestSaveTime < originalState ?. latestUpdateTime ) , } , false ) ; } @ proxify async saving ( identify ) { this . update ( identify , { latestSaveTime : Date . now ( ) , } , true ) ; } @ proxify async saveError ( identify ) { this . update ( identify , { isEdited : true , isSucceed : false , } , false ) ; } @ proxify async _handleSuccess ( identify , ... args ) { this . saveSuccess ( identify ) ; if ( typeof this . _onSuccess === 'function' ) this . _onSuccess ( identify , ... args ) ; } @ proxify async _handleError ( identify , ... args ) { this . saveError ( identify ) ; if ( typeof this . _onError === 'function' ) { await this . _onError ( identify , ... args ) ; } } @ proxify async showLogSection ( identify ) { if ( ! this . show || identify !== this . currentIdentify ) { this . setLogSectionIdentify ( identify ) ; } } @ action setLogSectionIdentify ( identify ) { if ( this . _notSyncOpenState ) { this . stateCurrentIdentify = identify ; } else { this . storageCurrentIdentify = identify ; } } @ action setLogNotificationIdentify ( identify ) { if ( this . _notSyncOpenState ) { this . stateCurrentNotificationIdentify = identify ; } else { this . storageCurrentNotificationIdentify = identify ; } } @ proxify async showLogNotification ( identify ) { if ( ! this . showNotification || identify !== this . currentNotificationIdentify ) { this . setLogNotificationIdentify ( identify ) ; } } addLogHandler ( { logFunction , readyCheckFunction , onUpdate , onSuccess , onError , } ) { if ( typeof logFunction !== 'function' ) { throw new Error ( 'CallLogSection: "logFunction" must be a function.' ) ; } if ( typeof readyCheckFunction !== 'function' ) { throw new Error ( 'CallLogSection: "readyCheckFunction" must be a function.' ) ; } this . _logFunction = logFunction ; this . _readyCheckFunction = readyCheckFunction ; this . _onUpdate = onUpdate ; this . _onSuccess = onSuccess ; this . _onError = onError ; } @ proxify async updateCallLog ( identify , ... args ) { this . update ( identify , { latestUpdateTime : Date . now ( ) , isEdited : true , } , this . callsSavingStatus [ identify ] ) ; await this . _onUpdate ( identify , ... args ) ; } @ proxify async saveCallLog ( identify , ... args ) { if ( identify && ( ! this . callsMapping [ identify ] || ! this . callsMapping [ identify ] . isSaving ) ) { this . saving ( identify ) ; try { const result = await this . _logFunction ( identify , ... args ) ; if ( ! result ) { throw new Error ( 'Result is empty' ) ; } this . _handleSuccess ( identify , { ... args , result } ) ; return result ; } catch ( e ) { await this . _handleError ( identify , ... args ) ; console . warn ( e ) ; } } } @ proxify async handleLogSection ( identify ) { if ( ! this . show ) { await this . showLogSection ( identify ) ; } else if ( ! this . notificationIsExpand && this . currentIdentify !== identify ) { await this . showLogNotification ( identify ) ; } } @ proxify async closeLogSection ( ) { if ( this . show ) { this . setLogSectionIdentify ( null ) ; } } @ proxify async discardAndHandleNotification ( ) { const currentNotificationIdentify = this . currentNotificationIdentify ; await this . closeLogNotification ( ) ; await this . closeLogSection ( ) ; await this . showLogSection ( currentNotificationIdentify ) ; } @ proxify async saveAndHandleNotification ( ) { const currentNotificationIdentify = this . currentNotificationIdentify ; const currentIdentify = this . currentIdentify ; await this . saveCallLog ( currentIdentify ) ; await this . closeLogNotification ( ) ; await this . closeLogSection ( ) ; await this . showLogSection ( currentNotificationIdentify ) ; } @ proxify async closeLogNotification ( ) { if ( this . showNotification ) { this . setLogNotificationIdentify ( null ) ; this . setNotificationIsExpand ( false ) ; } } @ action setNotificationIsExpand ( isExpand ) { if ( this . _notSyncOpenState ) { this . stateNotificationIsExpand = isExpand ; } else { this . storageNotificationIsExpand = isExpand ; } } @ proxify async shrinkNotification ( ) { if ( this . notificationIsExpand ) { this . setNotificationIsExpand ( false ) ; } } @ proxify async expandNotification ( ) { if ( ! this . notificationIsExpand ) { this . setNotificationIsExpand ( true ) ; } } @ proxify async expandLogNotification ( ) { if ( ! this . show ) { await this . showLogSection ( this . currentNotificationIdentify ) ; await this . closeLogNotification ( ) ; } await this . expandNotification ( ) ; } @ computed ( ( that ) => [ that . identifyList , that . callsMappingState , ] ) get calls ( ) { const calls = this . identifyList . map ( ( identify ) => this . callsMappingState [ identify ] ) ; return calls ; } /**
     * Merge isSaving property from reducer to callsMapping
     */ @ computed ( ( that ) => [ that . callsMappingState , that . callsSavingStatus , ] ) get callsMapping ( ) : Mapping < CallLogSectionCallStatus > { return converge ( mergeWith ( flip ( assoc ( 'isSaving' ) ) ) , [ identity , useWith ( pick , [ keys , identity ] ) , ] ) as any ; } @ computed ( ( that ) => [ that . currentIdentify , that . callsMappingState , ] ) get currentCallLogStatus ( ) { return ( this . callsMappingState [ this . currentIdentify ] || ( { } as CallLogStatus ) ) ; } @ computed ( ( that ) => [ that . currentIdentify , that . _deps . callHistory . calls , that . _deps . callMonitor . calls , ] ) get currentCall ( ) : HistoryCall { return ( [ ... this . _deps . callMonitor . calls , ... this . _deps . callHistory . calls ] . find ( ( call ) => call . sessionId === this . currentIdentify ) || { } ) ; } @ computed ( ( that ) => [ that . currentNotificationIdentify , that . _deps . callMonitor . calls , ] ) get currentNotificationCall ( ) { return ( this . _deps . callMonitor . calls . find ( ( call ) => call . sessionId === this . currentNotificationIdentify ) || { } ) ; } get currentIdentify ( ) { return this . _notSyncOpenState ? this . stateCurrentIdentify : this . storageCurrentIdentify ; } get show ( ) { return ! ! this . currentIdentify ; } get currentNotificationIdentify ( ) { return this . _notSyncOpenState ? this . stateCurrentNotificationIdentify : this . storageCurrentNotificationIdentify ; } get showNotification ( ) { return ! ! this . currentNotificationIdentify ; } get notificationIsExpand ( ) { return this . _notSyncOpenState ? this . stateNotificationIsExpand : this . storageNotificationIsExpand ; } get currentCallSavingStatus ( ) { return this . callsSavingStatus [ this . currentIdentify ] ; } }