import { timeFormat , timeParse } from 'd3-time-format' ; import { median , min , max , IEventListener } from '../internal' ; import { dialogAddons , toolbar } from './annotations' ; import ArrayColumn , { IArrayColumnDesc } from './ArrayColumn' ; import type { widthChanged , labelChanged , metaDataChanged , dirty , dirtyHeader , dirtyValues , rendererTypeChanged , groupRendererChanged , summaryRendererChanged , visibilityChanged , dirtyCaches , } from './Column' ; import type Column from './Column' ; import type { dataLoaded } from './ValueColumn' ; import type ValueColumn from './ValueColumn' ; import type { IDateDesc , IDatesColumn , IDateFilter } from './IDateColumn' ; import { IDataRow , ECompareValueType , ITypeFactory } from './interfaces' ; import { isMissingValue } from './missing' ; import DateColumn from './DateColumn' ; import { noDateFilter , isDummyDateFilter , restoreDateFilter } from './internalDate' ; import { chooseUIntByDataLength , integrateDefaults } from './internal' ; export enum EDateSort { min = 'min' , max = 'max' , median = 'median' } export interface IDatesDesc extends IDateDesc { sort ? : EDateSort ; } export declare type IDatesColumnDesc = IDatesDesc & IArrayColumnDesc < Date > ; asMemberOf event export declare function sortMethodChanged_DCS ( previous , current ) ; asMemberOf event export declare function filterChanged_DCS ( previous , current ) ; @ toolbar ( 'rename' , 'clone' , 'sort' , 'sortBy' , 'filterDate' ) @ dialogAddons ( 'sort' , 'sortDates' ) export default class DatesColumn extends ArrayColumn < Date | null > implements IDatesColumn { static readonly EVENT_SORTMETHOD_CHANGED = 'sortMethodChanged' ; static readonly EVENT_FILTER_CHANGED = DateColumn . EVENT_FILTER_CHANGED ; private readonly format : ( date : Date | null ) => string ; private readonly parse : ( date : string ) => Date | null ; private sort : EDateSort ; private currentFilter : IDateFilter = noDateFilter ( ) ; constructor ( id , desc ) { super ( id , integrateDefaults ( desc , { renderer : 'datehistogram' , groupRenderer : 'datehistogram' , summaryRenderer : 'datehistogram' , } ) ) ; const f = timeFormat ( desc . dateFormat || DateColumn . DEFAULT_DATE_FORMAT ) ; this . format = ( v ) => ( v instanceof Date ? f ( v ) : '' ) ; this . parse = desc . dateParse ? timeParse ( desc . dateParse ) : timeParse ( desc . dateFormat || DateColumn . DEFAULT_DATE_FORMAT ) ; this . sort = desc . sort || EDateSort . median ; } getFormatter ( ) { return this . format ; } protected createEventList ( ) { return super . createEventList ( ) . concat ( [ DatesColumn . EVENT_SORTMETHOD_CHANGED , DatesColumn . EVENT_FILTER_CHANGED ] ) ; } on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) { return super . on ( type as any , listener ) ; } getValue ( row ) { const r = this . getDates ( row ) ; return r . every ( ( d ) => d == null ) ? null : r ; } getLabels ( row ) { return this . getDates ( row ) . map ( ( v ) => ( v instanceof Date ? this . format ( v ) : '' ) ) ; } getDates ( row ) { return super . getValues ( row ) . map ( ( v ) => { if ( isMissingValue ( v ) ) { return null ; } if ( v instanceof Date ) { return v ; } return this . parse ( String ( v ) ) ; } ) ; } getDate ( row ) { const av = this . getDates ( row ) . filter ( Boolean ) ; if ( av . length === 0 ) { return null ; } return new Date ( compute ( av , this . sort ) ) ; } iterDate ( row ) { return this . getDates ( row ) ; } getSortMethod ( ) { return this . sort ; } setSortMethod ( sort ) { if ( this . sort === sort ) { return ; } this . fire ( [ DatesColumn . EVENT_SORTMETHOD_CHANGED ] , this . sort , ( this . sort = sort ) ) ; if ( ! this . isSortedByMe ( ) . asc ) { this . sortByMe ( ) ; } } dump ( toDescRef ) { const r = super . dump ( toDescRef ) ; r . sortMethod = this . getSortMethod ( ) ; r . filter = ! isDummyDateFilter ( this . currentFilter ) ? this . currentFilter : null ; return r ; } restore ( dump , factory ) { super . restore ( dump , factory ) ; if ( dump . sortMethod ) { this . sort = dump . sortMethod ; } if ( dump . filter ) { this . currentFilter = restoreDateFilter ( dump . filter ) ; } } toCompareValue ( row ) { const vs = this . getDates ( row ) . filter ( Boolean ) ; if ( ! vs ) { return [ 0 , 0 ] ; } return [ vs . length , compute ( vs , this . sort ) ] ; } toCompareValueType ( ) { return [ chooseUIntByDataLength ( this . dataLength ) , ECompareValueType . DOUBLE_ASC ] ; } isFiltered ( ) { return DateColumn . prototype . isFiltered . call ( this ) ; } getFilter ( ) { return DateColumn . prototype . getFilter . call ( this ) ; } setFilter ( value ) { DateColumn . prototype . setFilter . call ( this , value ) ; } filter ( row ) { return DateColumn . prototype . filter . call ( this , row ) ; } clearFilter ( ) { return DateColumn . prototype . clearFilter . call ( this ) ; } } function compute ( arr , sort ) { switch ( sort ) { case EDateSort . min : return min ( arr , ( d ) => d . getTime ( ) ) ! ; case EDateSort . max : return max ( arr , ( d ) => d . getTime ( ) ) ! ; case EDateSort . median : return median ( arr , ( d ) => d . getTime ( ) ) ! ; } }