1- import { Component , OnInit , ElementRef , ViewChild } from '@angular/core' ;
1+ import { Component , OnInit , ElementRef , ViewChild , signal , computed } from '@angular/core' ;
22import { FormControl } from '@angular/forms' ;
3- import { MatTableDataSource , MatTableModule } from '@angular/material/table' ;
3+ import { MatTableModule } from '@angular/material/table' ;
44import { Router , NavigationExtras } from '@angular/router' ;
55import { LoaderService } from 'src/app/service/loader/data-loader.service' ;
66import { Activity , ActivityStore , Data } from 'src/app/model/activity-store' ;
77import { UntilDestroy } from '@ngneat/until-destroy' ;
88import { MatChipListbox , MatChipSelectionChange , MatChipsModule } from '@angular/material/chips' ;
9- import { deepCopy } from 'src/app/util/util' ;
109import { DataStore } from 'src/app/model/data-store' ;
1110import { perfNow } from 'src/app/util/util' ;
1211import { SettingsService } from 'src/app/service/settings/settings.service' ;
@@ -50,14 +49,52 @@ export class MatrixComponent implements OnInit {
5049 Routing : string = '/activity-description' ;
5150 dataStore : DataStore = new DataStore ( ) ;
5251 data : Data = { } ;
53- levels : Partial < Record < LevelKey , string > > = { } ;
54- filtersTag : Record < string , boolean > = { } ;
55- filtersDim : Record < string , boolean > = { } ;
56- columnNames : string [ ] = [ ] ;
57- allCategoryNames : string [ ] = [ ] ;
58- allDimensionNames : string [ ] = [ ] ;
59- MATRIX_DATA : MatrixRow [ ] = [ ] ;
60- dataSource : any = new MatTableDataSource < MatrixRow > ( this . MATRIX_DATA ) ;
52+ levels = signal < Partial < Record < LevelKey , string > > > ( { } ) ;
53+ filtersTag = signal < Record < string , boolean > > ( { } ) ;
54+ filtersDim = signal < Record < string , boolean > > ( { } ) ;
55+ columnNames = signal < string [ ] > ( [ ] ) ;
56+ MATRIX_DATA = signal < MatrixRow [ ] > ( [ ] ) ;
57+
58+ dataSource = computed ( ( ) : MatrixRow [ ] => {
59+ const hasDimFilter = Object . values ( this . filtersDim ( ) ) . some ( v => v === true ) ;
60+ const hasTagFilter = Object . values ( this . filtersTag ( ) ) . some ( v => v === true ) ;
61+
62+ if ( ! hasTagFilter && ! hasDimFilter ) {
63+ return this . MATRIX_DATA ( ) ;
64+ }
65+
66+ let itemsStage1 : MatrixRow [ ] ;
67+ if ( ! hasDimFilter ) {
68+ itemsStage1 = this . MATRIX_DATA ( ) ;
69+ } else {
70+ itemsStage1 = this . MATRIX_DATA ( ) . filter ( srcItem => this . filtersDim ( ) [ srcItem . Dimension ] ) ;
71+ }
72+
73+ if ( ! hasTagFilter ) {
74+ return itemsStage1 ;
75+ }
76+
77+ const itemsStage2 : MatrixRow [ ] = [ ] ;
78+ for ( const srcItem of itemsStage1 ) {
79+ let hasContent = false ;
80+ const trgItem : Partial < MatrixRow > = { } ;
81+
82+ for ( const lvl of Object . keys ( this . levels ( ) ) as LevelKey [ ] ) {
83+ const tmp = srcItem [ lvl ] . filter ( activity => this . hasTag ( activity ) ) ;
84+ if ( tmp . length > 0 ) {
85+ trgItem [ lvl ] = tmp ;
86+ hasContent = true ;
87+ }
88+ }
89+
90+ if ( hasContent ) {
91+ trgItem . Category = srcItem . Category ;
92+ trgItem . Dimension = srcItem . Dimension ;
93+ itemsStage2 . push ( trgItem as MatrixRow ) ;
94+ }
95+ }
96+ return itemsStage2 ;
97+ } ) ;
6198
6299 /* eslint-disable */
63100 constructor (
@@ -69,13 +106,8 @@ export class MatrixComponent implements OnInit {
69106 /* eslint-enable */
70107
71108 reset ( ) {
72- for ( let dim in this . filtersDim ) {
73- this . filtersDim [ dim ] = false ;
74- }
75- for ( let tag in this . filtersTag ) {
76- this . filtersTag [ tag ] = false ;
77- }
78- this . updateActivitiesBeingDisplayed ( ) ;
109+ this . filtersDim . set ( Object . fromEntries ( Object . keys ( this . filtersDim ( ) ) . map ( k => [ k , false ] ) ) ) ;
110+ this . filtersTag . set ( Object . fromEntries ( Object . keys ( this . filtersTag ( ) ) . map ( k => [ k , false ] ) ) ) ;
79111 }
80112
81113 ngOnInit ( ) : void {
@@ -99,18 +131,15 @@ export class MatrixComponent implements OnInit {
99131 if ( ! dataStore . activityStore ) {
100132 return ;
101133 }
102- // this.data = this.activities.getData();
103- this . allCategoryNames = dataStore ?. activityStore ?. getAllCategoryNames ( ) || [ ] ;
104- this . allDimensionNames = dataStore ?. activityStore ?. getAllDimensionNames ( ) || [ ] ;
105-
106- this . MATRIX_DATA = this . buildMatrixData ( dataStore . activityStore ) ;
107- this . levels = this . buildLevels ( dataStore . getLevelTitles ( this . settings . getMaxLevel ( ) ) ) ; // eslint-disable-line
108- this . filtersTag = this . buildFiltersForTag ( dataStore . activityStore . getAllActivities ( ) ) ; // eslint-disable-line
109- this . filtersDim = this . buildFiltersForDim ( this . MATRIX_DATA ) ;
110- this . columnNames = [ 'Category' , 'Dimension' ] ;
111- this . columnNames . push ( ...Object . keys ( this . levels ) ) ;
112-
113- this . dataSource . data = deepCopy ( this . MATRIX_DATA ) ;
134+ const allCategoryNames = dataStore ?. activityStore ?. getAllCategoryNames ( ) || [ ] ;
135+ const allDimensionNames = dataStore ?. activityStore ?. getAllDimensionNames ( ) || [ ] ;
136+
137+ this . MATRIX_DATA . set ( this . buildMatrixData ( dataStore . activityStore , allDimensionNames ) ) ;
138+ const levelsObj = this . buildLevels ( dataStore . getLevelTitles ( this . settings . getMaxLevel ( ) ) ) ; // eslint-disable-line
139+ this . levels . set ( levelsObj ) ;
140+ this . filtersTag . set ( this . buildFiltersForTag ( dataStore . activityStore . getAllActivities ( ) ) ) ; // eslint-disable-line
141+ this . filtersDim . set ( this . buildFiltersForDim ( this . MATRIX_DATA ( ) ) ) ;
142+ this . columnNames . set ( [ 'Category' , 'Dimension' , ...Object . keys ( levelsObj ) ] ) ;
114143 }
115144
116145 buildFiltersForTag ( activities : Activity [ ] ) : Record < string , boolean > {
@@ -145,9 +174,9 @@ export class MatrixComponent implements OnInit {
145174 return levels ;
146175 }
147176
148- buildMatrixData ( activityStore : ActivityStore ) : MatrixRow [ ] {
177+ buildMatrixData ( activityStore : ActivityStore , allDimensionNames : string [ ] ) : MatrixRow [ ] {
149178 let matrixData : MatrixRow [ ] = [ ] ;
150- for ( let dim of this . allDimensionNames ) {
179+ for ( let dim of allDimensionNames ) {
151180 let matrixRow : Partial < MatrixRow > = { } ;
152181 for ( let level = 1 ; level <= activityStore . getMaxLevel ( ) ; level ++ ) {
153182 let activities : Activity [ ] = activityStore . getActivities ( dim , level ) ;
@@ -174,9 +203,8 @@ export class MatrixComponent implements OnInit {
174203 const selected = event . selected ;
175204
176205 setTimeout ( ( ) => {
177- this . filtersTag [ value ] = selected ;
206+ this . filtersTag . update ( f => ( { ... f , [ value ] : selected } ) ) ;
178207 console . log ( `${ perfNow ( ) } : Matrix: Chip flip Tag '${ value } : ${ selected } ` ) ;
179- this . updateActivitiesBeingDisplayed ( ) ;
180208 } ) ;
181209 }
182210
@@ -187,77 +215,18 @@ export class MatrixComponent implements OnInit {
187215 const selected = event . selected ;
188216
189217 setTimeout ( ( ) => {
190- this . filtersDim [ value ] = selected ;
218+ this . filtersDim . update ( f => ( { ... f , [ value ] : selected } ) ) ;
191219 console . log ( `${ perfNow ( ) } : Matrix: Chip flip Dim '${ value } : ${ selected } ` ) ;
192- this . updateActivitiesBeingDisplayed ( ) ;
193220 } ) ;
194221 }
195222
196223 @ViewChild ( 'rowInput' ) rowInput ! : ElementRef < HTMLInputElement > ;
197224 @ViewChild ( 'activityInput' ) activityInput ! : ElementRef < HTMLInputElement > ;
198225
199- updateActivitiesBeingDisplayed ( ) : void {
200- let hasDimFilter = Object . values ( this . filtersDim ) . some ( v => v === true ) ;
201- let hasTagFilter = Object . values ( this . filtersTag ) . some ( v => v === true ) ;
202-
203- if ( ! hasTagFilter && ! hasDimFilter ) {
204- this . dataSource . data = this . MATRIX_DATA ;
205- return ;
206- }
207-
208- // Apply dimension filters
209- let itemsStage1 : MatrixRow [ ] = [ ] ;
210- if ( ! hasDimFilter ) {
211- itemsStage1 = this . MATRIX_DATA ;
212- } else {
213- for ( let srcItem of this . MATRIX_DATA ) {
214- if ( this . filtersDim [ srcItem . Dimension ] ) {
215- itemsStage1 . push ( srcItem as MatrixRow ) ;
216- }
217- }
218- }
219-
220- // Apply tag filters
221- let itemsStage2 : MatrixRow [ ] ;
222- if ( ! hasTagFilter ) {
223- itemsStage2 = itemsStage1 ;
224- } else {
225- itemsStage2 = [ ] ;
226- for ( let srcItem of itemsStage1 ) {
227- let hasContent = false ;
228-
229- let trgItem : Partial < MatrixRow > = { } ;
230- if ( hasTagFilter ) {
231- // Include activities withing each level, that match the tag filter
232-
233- // If tag filter is active, filter activities by tags
234- for ( let lvl of Object . keys ( this . levels ) as LevelKey [ ] ) {
235- let tmp : Activity [ ] ;
236- tmp = srcItem [ lvl ] . filter ( activity => this . hasTag ( activity ) ) ;
237- if ( tmp . length > 0 ) {
238- trgItem [ lvl ] = tmp ;
239- hasContent = true ;
240- }
241- }
242-
243- // Only include the row if it has any activities after tag filtering
244- if ( hasContent ) {
245- // Copy metadata, since the element has remaining activities after filtering
246- trgItem . Category = srcItem . Category ;
247- trgItem . Dimension = srcItem . Dimension ;
248-
249- itemsStage2 . push ( trgItem as MatrixRow ) ;
250- }
251- }
252- }
253- }
254- this . dataSource . data = itemsStage2 ;
255- }
256-
257226 hasTag ( activity : Activity ) : boolean {
258227 if ( activity . tags ) {
259228 for ( let tagName of activity . tags ) {
260- if ( this . filtersTag [ tagName ] ) return true ;
229+ if ( this . filtersTag ( ) [ tagName ] ) return true ;
261230 }
262231 }
263232 return false ;
0 commit comments