import Column , { IColumnDesc , IDataRow , Ranking , defaultGroup , IndicesArray , IOrderedGroup } from '../model' ; import ACommonDataProvider from './ACommonDataProvider' ; import type { IDataProviderOptions } from './interfaces' ; import { DirectRenderTasks } from './DirectRenderTasks' ; import type { IRenderTasks } from '../renderer' ; /**
 * interface what the server side has to provide
 */ export interface IServerData { param ranking sort ( ranking ) : Promise < IndicesArray > ; param indices view ( indices ) : Promise < any [ ] > ; param column mappingSample ( column ) : Promise < number [ ] > ; param search param column search ( search , column ) : Promise < number [ ] > ; } export interface IRemoteDataProviderOptions { /**
     * maximal cache size (unused at the moment)
     */ maxCacheSize : number ; } function createIndex2Pos ( order ) { const index2pos = [ ] ; for ( let i = 0 ; i < order . length ; ++ i ) { index2pos [ order [ i ] ] = i + 1 ; } return index2pos ; } /**
 * a remote implementation of the data provider
 */ export default class RemoteDataProvider extends ACommonDataProvider { private readonly ooptions : IRemoteDataProviderOptions = { maxCacheSize : 1000 , } ; private readonly cache = new Map < number , Promise < IDataRow > > ( ) ; constructor ( private server , columns = [ ] , options = { } ) { super ( columns , options ) ; Object . assign ( this . ooptions , options ) ; } getTotalNumberOfRows ( ) { return this . cache . size ; } getTaskExecutor ( ) { return new DirectRenderTasks ( ) ; } sort ( ranking ) { return this . server . sort ( ranking ) . then ( ( order ) => ( { groups : [ Object . assign ( { order } , defaultGroup ) ] , index2pos : createIndex2Pos ( order ) } ) ) ; } private loadFromServer ( indices ) { return this . server . view ( indices ) . then ( ( view ) => { return view . map ( ( v , i ) => { const dataIndex = indices [ i ] ; return { v , dataIndex } ; } ) ; } ) ; } view ( indices ) { if ( indices . length === 0 ) { return Promise . resolve ( [ ] ) ; } const base = this . fetch ( [ indices ] ) [ 0 ] ; return Promise . all ( base ) . then ( ( rows ) => rows . map ( ( d ) => d . v ) ) ; } private computeMissing ( orders ) { const union = new Set < number > ( ) ; const unionAdd = union . add . bind ( union ) ; orders . forEach ( ( order ) => order . forEach ( unionAdd ) ) ; this . cache . forEach ( ( _v , k ) => union . delete ( k ) ) ; if ( this . cache . size + union . size > this . ooptions . maxCacheSize ) { } return Array . from ( union ) ; } private loadInCache ( missing ) { if ( missing . length === 0 ) { return ; } const v = this . loadFromServer ( missing ) ; missing . forEach ( ( _m , i ) => { const dataIndex = missing [ i ] ; this . cache . set ( dataIndex , v . then ( ( loaded ) => ( { v : loaded [ i ] , i : dataIndex } ) ) ) ; } ) ; } fetch ( orders ) { const toLoad = this . computeMissing ( orders ) ; this . loadInCache ( toLoad ) ; return orders . map ( ( order ) => order . map ( ( i ) => this . cache . get ( i ) ! ) ) ; } getRow ( index ) { if ( this . cache . has ( index ) ) { return this . cache . get ( index ) ! ; } this . loadInCache ( [ index ] ) ; return this . cache . get ( index ) ! ; } mappingSample ( col ) { return this . server . mappingSample ( ( col as any ) . desc . column ) ; } searchAndJump ( search , col ) { this . server . search ( search , ( col as any ) . desc . column ) . then ( ( indices ) => { this . jumpToNearest ( indices ) ; } ) ; } }