1+ import { Ref , ref , provide , inject , computed , ComputedRef } from 'vue'
2+ import type { PivotData , PivotDataProps } from '@/helper/utilities.d'
3+ import { PivotData as PivotDataClass } from '@/helper/utilities.js'
4+
5+ const PIVOT_DATA_KEY = Symbol ( 'pivotData' )
6+
7+ interface ProvidePivotDataProps extends Partial < PivotDataProps > {
8+ heatmapMode ?: 'full' | 'row' | 'col'
9+ tableColorScaleGenerator : ( values : any [ ] ) => ( value : any ) => any
10+ }
11+
12+ export interface PivotDataContext {
13+ pivotData : ComputedRef < PivotData | null >
14+ rowKeys : ComputedRef < any [ ] [ ] >
15+ colKeys : ComputedRef < any [ ] [ ] >
16+ colAttrs : ComputedRef < string [ ] >
17+ rowAttrs : ComputedRef < string [ ] >
18+ getAggregator : ( rowKey : any [ ] , colKey : any [ ] ) => any
19+ grandTotalAggregator : ComputedRef < any >
20+ spanSize : ( arr : any [ ] [ ] , i : number , j : number ) => number
21+ valueCellColors : ( rowKey : any [ ] , colKey : any [ ] , value : any ) => any
22+ rowTotalColors : ( value : any ) => any
23+ colTotalColors : ( value : any ) => any
24+ error : Ref < string | null >
25+ }
26+
27+ export function providePivotData ( props : ProvidePivotDataProps ) : PivotDataContext {
28+ const error = ref < string | null > ( null )
29+
30+ const pivotData = computed < PivotData | null > ( ( ) => {
31+ try {
32+ return new PivotDataClass ( props ) as PivotData
33+ } catch ( err : any ) {
34+ console . error ( err . stack )
35+ error . value = 'An error occurred computing the PivotTable results.'
36+ return null
37+ }
38+ } )
39+
40+ const rowKeys = computed < any [ ] [ ] > ( ( ) => pivotData . value ?. getRowKeys ( ) || [ ] )
41+ const colKeys = computed < any [ ] [ ] > ( ( ) => pivotData . value ?. getColKeys ( ) || [ ] )
42+ const colAttrs = computed < string [ ] > ( ( ) => pivotData . value ?. props . cols || [ ] )
43+ const rowAttrs = computed < string [ ] > ( ( ) => pivotData . value ?. props . rows || [ ] )
44+ const colorScaleGenerator = props . tableColorScaleGenerator
45+ const getAggregator = ( rowKey : any [ ] , colKey : any [ ] ) =>
46+ pivotData . value ?. getAggregator ( rowKey , colKey ) || {
47+ value : ( ) => null ,
48+ format : ( ) => ''
49+ }
50+
51+ const grandTotalAggregator = computed ( ( ) => {
52+ return pivotData . value
53+ ? getAggregator ( [ ] , [ ] )
54+ : {
55+ value : ( ) => null ,
56+ format : ( ) => ''
57+ }
58+ } )
59+
60+ const allColorScales = computed ( ( ) => {
61+ const values = rowKeys . value . reduce ( ( acc : any [ ] , r : any [ ] ) => acc . concat ( colKeys . value . map ( ( c : any [ ] ) => getAggregator ( r , c ) . value ( ) ) ) , [ ] )
62+ return colorScaleGenerator ( values )
63+ } )
64+ const rowColorScales = computed ( ( ) =>
65+ rowKeys . value . reduce ( ( scales : Record < string , any > , r : any [ ] ) => {
66+ const key = JSON . stringify ( r )
67+ scales [ key ] = colorScaleGenerator (
68+ colKeys . value . map ( ( x : any [ ] ) => getAggregator ( r , x ) . value ( ) )
69+ )
70+ return scales
71+ } , { } as Record < string , any > )
72+ )
73+ const colColorScales = computed ( ( ) =>
74+ colKeys . value . reduce ( ( scales : Record < string , any > , c : any [ ] ) => {
75+ const key = JSON . stringify ( c )
76+ scales [ key ] = colorScaleGenerator (
77+ rowKeys . value . map ( ( x : any [ ] ) => getAggregator ( x , c ) . value ( ) )
78+ )
79+ return scales
80+ } , { } as Record < string , any > )
81+ )
82+
83+ const valueCellColors = ( rowKey : any [ ] , colKey : any [ ] , value : any ) => {
84+ if ( props . heatmapMode === 'full' ) {
85+ return allColorScales . value ( value )
86+ } else if ( props . heatmapMode === 'row' ) {
87+ return rowColorScales . value [ JSON . stringify ( rowKey ) ] ?.( value )
88+ } else if ( props . heatmapMode === 'col' ) {
89+ return colColorScales . value [ JSON . stringify ( colKey ) ] ?.( value )
90+ }
91+ return { }
92+ }
93+ const rowTotalValues = computed ( ( ) => colKeys . value . map ( ( x : any [ ] ) => getAggregator ( [ ] , x ) . value ( ) ) )
94+ const rowTotalColors = ( value : any ) => {
95+ if ( ! props . heatmapMode ) return { }
96+ return colorScaleGenerator ( rowTotalValues . value ) ( value )
97+ }
98+ const colTotalValues = computed ( ( ) => rowKeys . value . map ( ( x : any [ ] ) => getAggregator ( x , [ ] ) . value ( ) ) )
99+ const colTotalColors = ( value : any ) => {
100+ if ( ! props . heatmapMode ) return { }
101+ return colorScaleGenerator ( colTotalValues . value ) ( value )
102+ }
103+
104+ const spanSize = ( arr : any [ ] [ ] , i : number , j : number ) : number => {
105+ let x
106+ if ( i !== 0 ) {
107+ let noDraw = true
108+ for ( x = 0 ; x <= j ; x ++ ) {
109+ if ( arr [ i - 1 ] [ x ] !== arr [ i ] [ x ] ) {
110+ noDraw = false
111+ }
112+ }
113+ if ( noDraw ) {
114+ return - 1
115+ }
116+ }
117+
118+ let len = 0
119+ while ( i + len < arr . length ) {
120+ let stop = false
121+ for ( x = 0 ; x <= j ; x ++ ) {
122+ if ( arr [ i ] [ x ] !== arr [ i + len ] [ x ] ) {
123+ stop = true
124+ }
125+ }
126+ if ( stop ) {
127+ break
128+ }
129+ len ++
130+ }
131+ return len
132+ }
133+
134+ const pivotDataContext : PivotDataContext = {
135+ pivotData,
136+ rowKeys,
137+ colKeys,
138+ colAttrs,
139+ rowAttrs,
140+ getAggregator,
141+ grandTotalAggregator,
142+ spanSize,
143+ valueCellColors,
144+ rowTotalColors,
145+ colTotalColors,
146+ error
147+ }
148+
149+ provide ( PIVOT_DATA_KEY , pivotDataContext )
150+ return pivotDataContext
151+ }
152+
153+ export function useProvidePivotData ( ) : PivotDataContext | undefined {
154+ return inject < PivotDataContext > ( PIVOT_DATA_KEY )
155+ }
0 commit comments