import { observable , transaction } from 'mobx' ; import { ThrottleProcessor } from 'common/utils/throttle' ; import logger from 'common/logger' ; export interface IActivityController { getIsActive ( id ) : boolean ; setIsActive ( map ) : Promise < void > ; activate ( ids ) : Promise < void > ; deactivate ( ids ) : Promise < void > ; } type ItemType < TKey extends string > = { active : boolean ; } & { [ P in TKey ] : string ; } ; type Diff = Record < string , { active : boolean ; } > ; type DiffItem = { id : string ; active : boolean ; } ; export class ActivityController < T extends ItemType < TKey > , TKey extends string > implements IActivityController { @ observable private _activeById : Record < string , boolean > = { } ; private readonly _submitter : ThrottleProcessor < DiffItem > ; constructor ( readonly key , readonly submit ) { this . _submitter = new ThrottleProcessor ( this . _doSubmit ) ; } public setItems ( items ) { this . _activeById = { } ; items ?. forEach ( a => { this . _activeById [ a [ this . key ] ] = a . active ; } ) ; } getIsActive ( id ) { return this . _activeById [ id ] ; } async setIsActive ( map ) { transaction ( ( ) => { Object . keys ( map ) . forEach ( id => { this . _activeById [ id ] = map [ id ] ; this . _submitter . push ( { id , active : map [ id ] } ) ; } ) ; } ) ; } private _doSubmit = async ( diffs ) => { const resultDiff = { } ; diffs . forEach ( di => { resultDiff [ di . id ] = { active : di . active } ; } ) ; try { await this . submit ( resultDiff ) ; } catch ( err ) { transaction ( ( ) => { diffs . forEach ( di => { this . _activeById [ di . id ] = ! di . active ; } ) ; } ) ; logger . error ( err ) ; } } ; activate ( ids ) { if ( ! ids ?. length ) { return ; } const diff = { } ; ids . forEach ( id => diff [ id ] = true ) ; return this . setIsActive ( diff ) ; } deactivate ( ids ) { if ( ! ids ?. length ) { return ; } const diff = { } ; ids . forEach ( id => diff [ id ] = false ) ; return this . setIsActive ( diff ) ; } }