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