11import { Pipe , PipeTransform } from '@angular/core' ;
2- import { cloneArray } from '../../core/utils' ;
2+ import { cloneArray , cloneValue } from '../../core/utils' ;
33import { DataUtil } from '../../data-operations/data-util' ;
44import { FilteringExpressionsTree , IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree' ;
55import { IFilteringStrategy } from '../../data-operations/filtering-strategy' ;
6- import { IGroupingExpression } from '../../data-operations/grouping-expression.interface' ;
7- import { SortingDirection } from '../../data-operations/sorting-expression.interface' ;
8- import { DefaultSortingStrategy } from '../../data-operations/sorting-strategy' ;
9- import { GridBaseAPIService } from '../api.service' ;
10- import { IgxPivotGridComponent } from './pivot-grid.component' ;
116import { IPivotDimension , IPivotValue } from './pivot-grid.interface' ;
127
138/**
@@ -19,60 +14,22 @@ import { IPivotDimension, IPivotValue } from './pivot-grid.interface';
1914} )
2015export class IgxPivotRowPipe implements PipeTransform {
2116
22- constructor ( private gridAPI : GridBaseAPIService < IgxPivotGridComponent > ) { }
17+ constructor ( ) { }
2318
2419 public transform (
2520 collection : any ,
2621 rows : IPivotDimension [ ] ,
2722 values ?: IPivotValue [ ]
2823 ) : any [ ] {
2924
30- const result : any [ ] = collection . slice ( ) ;
31- let groupingExpressions : IGroupingExpression [ ] = [ ] ;
3225
33- // group the data in a way using the rows.member declarations in a groupingComparer
34- for ( const row of rows ) {
35- groupingExpressions = groupingExpressions . concat ( this . buildGroupingExpressions ( row ) ) ;
36- }
37-
38- // need to extend the grouping and improve the groupingComparer function capabilities
39- const sorted = DataUtil . sort ( result , groupingExpressions ) ;
40- const groupResult = DataUtil
41- . group ( sorted , { defaultExpanded : true , expansion : [ ] , expressions : groupingExpressions } ) ;
42-
43- // go around the data and aggregate by the specified values, aggregations should be
44- // stored into the groups
45- for ( const val of values ) {
46- this . applyAggregation ( groupResult . data , val ) ;
47- }
48-
49- return groupResult . data ;
50- }
51-
52- private buildGroupingExpressions ( row : IPivotDimension ) : IGroupingExpression [ ] {
53- let groupingExpressions : IGroupingExpression [ ] = [ {
54- fieldName : row . name ,
55- dir : SortingDirection . Asc ,
56- groupingComparer : ( a , b ) => DefaultSortingStrategy . instance ( )
57- . compareValues ( row . member . call ( this , a ) , row . member . call ( this , b ) )
58- } ] ;
59- if ( row . childLevels ) {
60- for ( const childRow of row . childLevels ) {
61- groupingExpressions = groupingExpressions . concat ( this . buildGroupingExpressions ( childRow ) ) ;
62- }
63- }
64- return groupingExpressions ;
65- }
66-
67- private applyAggregation ( data : any [ ] , val : IPivotValue ) : void {
68- for ( const record of data ) {
69- if ( record . groups ) {
70- this . applyAggregation ( record . groups , val ) ;
71- record [ val . member ] = val . aggregate ( record . records . map ( r => r [ val . member ] ) ) ;
72- } else if ( record . records ) {
73- record [ val . member ] = val . aggregate ( record . records . map ( r => r [ val . member ] ) ) ;
74- }
75- }
26+ // build hierarchies - groups and subgroups
27+ const hierarchies = PivotUtil . getFieldsHierarchy ( collection , rows ) ;
28+ // apply aggregations based on the created groups
29+ PivotUtil . applyAggregations ( hierarchies , values ) ;
30+ // generate flat data from the hierarchies
31+ const data = PivotUtil . flattenHierarchy ( hierarchies , collection [ 0 ] ?? [ ] ) ;
32+ return data ;
7633 }
7734}
7835
@@ -85,15 +42,21 @@ export class IgxPivotRowPipe implements PipeTransform {
8542} )
8643export class IgxPivotColumnPipe implements PipeTransform {
8744
88- constructor ( private gridAPI : GridBaseAPIService < IgxPivotGridComponent > ) { }
89-
9045 public transform (
9146 collection : any ,
9247 columns : IPivotDimension [ ] ,
9348 values ?: IPivotValue [ ]
9449 ) : any [ ] {
95- return collection ;
50+ // build hierarchies - groups and subgroups
51+ const hierarchies = PivotUtil . getFieldsHierarchy ( collection , columns ) ;
52+ // apply aggregations based on the created groups
53+ PivotUtil . applyAggregations ( hierarchies , values ) ;
54+ // generate column fields based on the hierarchies
55+
56+ return [ ] ;
9657 }
58+
59+
9760}
9861
9962/**
@@ -105,8 +68,6 @@ export class IgxPivotColumnPipe implements PipeTransform {
10568} )
10669export class IgxPivotGridFilterPipe implements PipeTransform {
10770
108- constructor ( private gridAPI : GridBaseAPIService < IgxPivotGridComponent > ) { }
109-
11071 public transform ( collection : any [ ] ,
11172 expressionsTree : IFilteringExpressionsTree ,
11273 filterStrategy : IFilteringStrategy ,
@@ -127,3 +88,107 @@ export class IgxPivotGridFilterPipe implements PipeTransform {
12788 return result ;
12889 }
12990}
91+
92+ export class PivotUtil {
93+ public static getFieldsHierarchy ( data : any [ ] , columns : IPivotDimension [ ] ) : Map < string , any > {
94+ const hierarchy = new Map < string , any > ( ) ;
95+ for ( const rec of data ) {
96+ const vals = this . extractValuesFromDimension ( columns , rec ) ;
97+ for ( const val of vals ) { // this should go in depth also vals.children
98+ if ( hierarchy . get ( val . value ) != null && val . children ) {
99+ this . applyHierarchyChildren ( hierarchy , val , rec ) ;
100+ } else {
101+ hierarchy . set ( val . value , cloneValue ( val ) ) ;
102+ hierarchy . get ( val . value ) . children = new Map < string , any > ( ) ;
103+ this . applyHierarchyChildren ( hierarchy , val , rec ) ;
104+ }
105+ }
106+ }
107+ return hierarchy ;
108+ }
109+
110+ public static extractValueFromDimension ( dim : IPivotDimension , recData : any ) {
111+ return typeof dim . member === 'string' ? recData [ dim . member ] : dim . member . call ( this , recData ) ;
112+ }
113+
114+ public static extractValuesFromDimension ( dims : IPivotDimension [ ] , recData : any ) {
115+ const vals = [ ] ;
116+ let i = 0 ;
117+ for ( const col of dims ) {
118+ const value = this . extractValueFromDimension ( col , recData ) ;
119+ vals . push ( { value } ) ;
120+ if ( col . childLevels != null && col . childLevels . length > 0 ) {
121+ const childValues = this . extractValuesFromDimension ( col . childLevels , recData ) ;
122+ vals [ i ] . children = childValues ;
123+ }
124+ i ++ ;
125+ }
126+ return vals ;
127+ }
128+
129+ public static applyAggregations ( hierarchies , values ) {
130+ hierarchies . forEach ( ( hierarchy ) => {
131+ const children = hierarchy [ 'children' ] ;
132+ if ( children ) {
133+ this . applyAggregations ( children , values ) ;
134+ const childrenAggregations = this . collectAggregations ( children ) ;
135+ hierarchy [ 'aggregations' ] = this . aggregate ( childrenAggregations , values ) ;
136+ } else if ( hierarchy [ 'records' ] ) {
137+ hierarchy [ 'aggregations' ] = this . aggregate ( hierarchy [ 'records' ] , values ) ;
138+ }
139+ } ) ;
140+ }
141+
142+ public static aggregate ( records , values : IPivotValue [ ] ) {
143+ const result = { } ;
144+ for ( const pivotValue of values ) {
145+ result [ pivotValue . member ] = pivotValue . aggregate ( records . map ( r => r [ pivotValue . member ] ) ) ;
146+ }
147+
148+ return result ;
149+ }
150+
151+ public static flattenHierarchy ( hierarchies , rec ) {
152+ let flatData = [ ] ;
153+ const field = this . generateFieldValue ( rec ) ;
154+ hierarchies . forEach ( ( h , key ) => {
155+ let obj = { } ;
156+ obj [ field ] = key ;
157+ obj [ 'records' ] = h [ 'records' ] ;
158+ obj = { ...obj , ...h [ 'aggregations' ] } ;
159+ flatData . push ( obj ) ;
160+ if ( h [ 'children' ] ) {
161+ flatData = [ ...flatData , ...this . flattenHierarchy ( h [ 'children' ] , rec ) ] ;
162+ }
163+ } ) ;
164+
165+ return flatData ;
166+ }
167+
168+ private static generateFieldValue ( rec ) {
169+ let i = 0 ;
170+ while ( Object . keys ( rec ) . indexOf ( 'field' + ++ i ) !== - 1 ) { }
171+ return 'field' + i ;
172+ }
173+
174+ private static collectAggregations ( children ) {
175+ const result = [ ] ;
176+ children . forEach ( value => result . push ( value [ 'aggregations' ] ) ) ;
177+
178+ return result ;
179+ }
180+
181+ private static applyHierarchyChildren ( hierarchy , val , rec , recordsKey = 'records' ) {
182+ for ( const child of val . children ) {
183+ if ( ! hierarchy . get ( val . value ) . children . get ( child . value ) ) {
184+ hierarchy . get ( val . value ) . children . set ( child . value , child ) ;
185+ }
186+
187+ if ( hierarchy . get ( val . value ) . children . get ( child . value ) [ recordsKey ] ) {
188+ hierarchy . get ( val . value ) . children . get ( child . value ) [ recordsKey ] . push ( rec ) ;
189+ } else {
190+ hierarchy . get ( val . value ) . children . get ( child . value ) [ recordsKey ] = [ rec ] ;
191+ }
192+ }
193+ }
194+ }
0 commit comments