Skip to content

Commit

Permalink
#379 network node filter with signals
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarc committed Mar 27, 2024
1 parent 24b85ad commit 623de27
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 174 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WritableSignal } from '@angular/core';
import { SurveyDateInfo } from '@api/common';
import { TimeInfo } from '@api/common';
import { NetworkNodeRow } from '@api/common/network';
Expand All @@ -8,119 +9,97 @@ import { SurveyDateFilter } from '@app/kpn/filter';
import { SurveyDateFilterKind } from '@app/kpn/filter';
import { TimestampFilter } from '@app/kpn/filter';
import { TimestampFilterKind } from '@app/kpn/filter';
import { BehaviorSubject } from 'rxjs';
import { NetworkNodeFilterCriteria } from './network-node-filter-criteria';

export class NetworkNodeFilter {
private readonly proposedFilter = new BooleanFilter<NetworkNodeRow>(
'proposed',
this.criteria.proposed,
this.criteria().proposed,
(row) => row.detail.proposed,
this.update({ ...this.criteria, proposed: null }),
this.update({ ...this.criteria, proposed: true }),
this.update({ ...this.criteria, proposed: false })
() => this.criteria.update((c) => ({ ...c, proposed: null })),
() => this.criteria.update((c) => ({ ...c, proposed: true })),
() => this.criteria.update((c) => ({ ...c, proposed: false }))
);

private readonly definedInNetworkRelationFilter = new BooleanFilter<NetworkNodeRow>(
'definedInNetworkRelation',
this.criteria.definedInNetworkRelation,
this.criteria().definedInNetworkRelation,
(row) => row.detail.definedInRelation,
this.update({ ...this.criteria, definedInNetworkRelation: null }),
this.update({ ...this.criteria, definedInNetworkRelation: true }),
this.update({ ...this.criteria, definedInNetworkRelation: false })
() => this.criteria.update((c) => ({ ...c, definedInNetworkRelation: null })),
() => this.criteria.update((c) => ({ ...c, definedInNetworkRelation: true })),
() => this.criteria.update((c) => ({ ...c, definedInNetworkRelation: false }))
);

private readonly referencedInRouteFilter = new BooleanFilter<NetworkNodeRow>(
'referencedInRoute',
this.criteria.referencedInRoute,
this.criteria().referencedInRoute,
(row) => row.routeReferences.length > 0,
this.update({ ...this.criteria, referencedInRoute: null }),
this.update({ ...this.criteria, referencedInRoute: true }),
this.update({ ...this.criteria, referencedInRoute: false })
() => this.criteria.update((c) => ({ ...c, referencedInRoute: null })),
() => this.criteria.update((c) => ({ ...c, referencedInRoute: true })),
() => this.criteria.update((c) => ({ ...c, referencedInRoute: false }))
);

private readonly connectionFilter = new BooleanFilter<NetworkNodeRow>(
'connection',
this.criteria.connection,
this.criteria().connection,
(row) => row.detail.connection,
this.update({ ...this.criteria, connection: null }),
this.update({ ...this.criteria, connection: true }),
this.update({ ...this.criteria, connection: false })
() => this.criteria.update((c) => ({ ...c, connection: null })),
() => this.criteria.update((c) => ({ ...c, connection: true })),
() => this.criteria.update((c) => ({ ...c, connection: false }))
);

private readonly roleConnectionFilter = new BooleanFilter<NetworkNodeRow>(
'roleConnection',
this.criteria.roleConnection,
this.criteria().roleConnection,
(row) => row.detail.roleConnection,
this.update({ ...this.criteria, roleConnection: null }),
this.update({ ...this.criteria, roleConnection: true }),
this.update({ ...this.criteria, roleConnection: false })
() => this.criteria.update((c) => ({ ...c, roleConnection: null })),
() => this.criteria.update((c) => ({ ...c, roleConnection: true })),
() => this.criteria.update((c) => ({ ...c, roleConnection: false }))
);

private readonly integrityCheckFilter = new BooleanFilter<NetworkNodeRow>(
'integrityCheck',
this.criteria.integrityCheck,
this.criteria().integrityCheck,
(row) => !!row.detail.expectedRouteCount,
this.update({ ...this.criteria, integrityCheck: null }),
this.update({ ...this.criteria, integrityCheck: true }),
this.update({ ...this.criteria, integrityCheck: false })
() => this.criteria.update((c) => ({ ...c, integrityCheck: null })),
() => this.criteria.update((c) => ({ ...c, integrityCheck: true })),
() => this.criteria.update((c) => ({ ...c, integrityCheck: false }))
);

private readonly integrityCheckFailedFilter = new BooleanFilter<NetworkNodeRow>(
'integrityCheckFailed',
this.criteria.integrityCheckFailed,
this.criteria().integrityCheckFailed,
(row) =>
row.detail.expectedRouteCount
? +row.detail.expectedRouteCount !== row.routeReferences.length
: false,
this.update({ ...this.criteria, integrityCheckFailed: null }),
this.update({ ...this.criteria, integrityCheckFailed: true }),
this.update({ ...this.criteria, integrityCheckFailed: false })
() => this.criteria.update((c) => ({ ...c, integrityCheckFailed: null })),
() => this.criteria.update((c) => ({ ...c, integrityCheckFailed: true })),
() => this.criteria.update((c) => ({ ...c, integrityCheckFailed: false }))
);

private readonly lastUpdatedFilter = new TimestampFilter<NetworkNodeRow>(
this.criteria.lastUpdated,
this.criteria().lastUpdated,
(row) => row.detail.timestamp,
this.timeInfo,
this.update({ ...this.criteria, lastUpdated: TimestampFilterKind.all }),
this.update({
...this.criteria,
lastUpdated: TimestampFilterKind.lastWeek,
}),
this.update({
...this.criteria,
lastUpdated: TimestampFilterKind.lastMonth,
}),
this.update({
...this.criteria,
lastUpdated: TimestampFilterKind.lastYear,
}),
this.update({ ...this.criteria, lastUpdated: TimestampFilterKind.older })
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.all })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastWeek })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastMonth })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastYear })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.older }))
);

private readonly lastSurveyFilter = new SurveyDateFilter<NetworkNodeRow>(
this.criteria.lastSurvey,
this.criteria().lastSurvey,
(row) => row.detail.lastSurvey,
this.surveyDateInfo,
this.update({ ...this.criteria, lastSurvey: SurveyDateFilterKind.all }),
this.update({ ...this.criteria, lastSurvey: SurveyDateFilterKind.unknown }),
this.update({
...this.criteria,
lastSurvey: SurveyDateFilterKind.lastMonth,
}),
this.update({
...this.criteria,
lastSurvey: SurveyDateFilterKind.lastHalfYear,
}),
this.update({
...this.criteria,
lastSurvey: SurveyDateFilterKind.lastYear,
}),
this.update({
...this.criteria,
lastSurvey: SurveyDateFilterKind.lastTwoYears,
}),
this.update({ ...this.criteria, lastSurvey: SurveyDateFilterKind.older })
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.all })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.unknown })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.lastMonth })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.lastHalfYear })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.lastYear })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.lastTwoYears })),
() => this.criteria.update((c) => ({ ...c, lastSurvey: SurveyDateFilterKind.older }))
);

private readonly allFilters = new Filters<NetworkNodeRow>(
Expand All @@ -136,10 +115,9 @@ export class NetworkNodeFilter {
);

constructor(
private readonly timeInfo: TimeInfo,
private readonly criteria: WritableSignal<NetworkNodeFilterCriteria>,
private readonly surveyDateInfo: SurveyDateInfo,
private readonly criteria: NetworkNodeFilterCriteria,
private readonly filterCriteria: BehaviorSubject<NetworkNodeFilterCriteria>
private readonly timeInfo: TimeInfo
) {}

filter(nodes: NetworkNodeRow[]): NetworkNodeRow[] {
Expand All @@ -151,7 +129,6 @@ export class NetworkNodeFilter {
const filteredCount = nodes.filter((node) => this.allFilters.passes(node)).length;

const proposed = this.proposedFilter.filterOptions(this.allFilters, nodes);

const definedInNetworkRelation = this.definedInNetworkRelationFilter.filterOptions(
this.allFilters,
nodes
Expand Down Expand Up @@ -181,8 +158,4 @@ export class NetworkNodeFilter {

return new FilterOptions(filteredCount, totalCount, groups);
}

private update(criteria: NetworkNodeFilterCriteria) {
return () => this.filterCriteria.next(criteria);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { effect } from '@angular/core';
import { viewChild } from '@angular/core';
import { computed } from '@angular/core';
import { inject } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { ChangeDetectionStrategy } from '@angular/core';
import { Component } from '@angular/core';
import { OnInit } from '@angular/core';
Expand All @@ -20,18 +20,10 @@ import { Util } from '@app/components/shared';
import { DayComponent } from '@app/components/shared/day';
import { DayPipe } from '@app/components/shared/format';
import { LinkNodeComponent } from '@app/components/shared/link';
import { FilterOptions } from '@app/kpn/filter';
import { BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';
import { delay } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { ActionButtonNodeComponent } from '../../../components/action/action-button-node.component';
import { NetworkNodesPageService } from '../network-nodes-page.service';
import { NetworkNodeAnalysisComponent } from './network-node-analysis.component';
import { NetworkNodeFilter } from './network-node-filter';
import { NetworkNodeFilterCriteria } from './network-node-filter-criteria';
import { NetworkNodeRoutesComponent } from './network-node-routes.component';
import { NetworkNodesService } from './network-nodes.service';

@Component({
selector: 'kpn-network-node-table',
Expand Down Expand Up @@ -183,7 +175,7 @@ import { NetworkNodesService } from './network-nodes.service';
ActionButtonNodeComponent,
],
})
export class NetworkNodeTableComponent implements OnInit, OnDestroy {
export class NetworkNodeTableComponent implements OnInit {
networkType = input.required<NetworkType>();
networkScope = input.required<NetworkScope>();
timeInfo = input.required<TimeInfo>();
Expand All @@ -193,7 +185,6 @@ export class NetworkNodeTableComponent implements OnInit, OnDestroy {
private readonly editAndPaginator = viewChild(EditAndPaginatorComponent);

private readonly pageWidthService = inject(PageWidthService);
private readonly networkNodesService = inject(NetworkNodesService);
private readonly editService = inject(EditService);
protected readonly service = inject(NetworkNodesPageService);

Expand Down Expand Up @@ -238,32 +229,14 @@ export class NetworkNodeTableComponent implements OnInit, OnDestroy {
return ['nr', 'analysis', 'node'];
});

private readonly filterCriteria$: BehaviorSubject<NetworkNodeFilterCriteria> =
new BehaviorSubject(new NetworkNodeFilterCriteria());
constructor() {
effect(() => {
this.dataSource.data = this.service.filteredNodes();
});
}

ngOnInit(): void {
this.dataSource.paginator = this.editAndPaginator().paginator().matPaginator();
this.filterCriteria$
.pipe(
map(
(criteria) =>
new NetworkNodeFilter(
this.timeInfo(),
this.surveyDateInfo(),
criteria,
this.filterCriteria$
)
),
tap((filter) => (this.dataSource.data = filter.filter(this.nodes()))),
delay(0)
)
.subscribe((filter) => {
this.networkNodesService.setFilterOptions(filter.filterOptions(this.nodes()));
});
}

ngOnDestroy() {
this.networkNodesService.setFilterOptions(FilterOptions.empty());
}

rowNumber(index: number): number {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { AsyncPipe } from '@angular/common';
import { inject } from '@angular/core';
import { ChangeDetectionStrategy } from '@angular/core';
import { Component } from '@angular/core';
import { FilterComponent } from '@app/analysis/components/filter';
import { SidebarComponent } from '@app/components/shared/sidebar';
import { NetworkNodesService } from './network-nodes.service';
import { NetworkNodesPageService } from '../network-nodes-page.service';

@Component({
selector: 'kpn-network-nodes-sidebar',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<kpn-sidebar>
<kpn-filter [filterOptions]="networkNodesService.filterOptions$ | async" />
<kpn-filter [filterOptions]="service.filterOptions()" />
</kpn-sidebar>
`,
standalone: true,
imports: [SidebarComponent, FilterComponent, AsyncPipe],
imports: [SidebarComponent, FilterComponent],
})
export class NetworkNodesSidebarComponent {
protected readonly networkNodesService = inject(NetworkNodesService);
protected readonly service = inject(NetworkNodesPageService);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { computed } from '@angular/core';
import { signal } from '@angular/core';
import { inject } from '@angular/core';
import { NetworkNodesPage } from '@api/common/network';
Expand All @@ -6,6 +7,8 @@ import { PreferencesService } from '@app/core';
import { ApiService } from '@app/services';
import { RouterService } from '../../../shared/services/router.service';
import { NetworkService } from '../network.service';
import { NetworkNodeFilter } from './components/network-node-filter';
import { NetworkNodeFilterCriteria } from './components/network-node-filter-criteria';

export class NetworkNodesPageService {
private readonly apiService = inject(ApiService);
Expand All @@ -18,6 +21,22 @@ export class NetworkNodesPageService {

readonly pageSize = this.preferencesService.pageSize;

private readonly timeInfo = computed(() => this.response()?.result?.timeInfo);
private readonly surveyDateInfo = computed(() => this.response()?.result?.surveyDateInfo);
private readonly nodes = computed(() => this.response()?.result?.nodes ?? []);

private readonly filterCriteria = signal<NetworkNodeFilterCriteria>(
new NetworkNodeFilterCriteria()
);

private readonly filter = computed(
() => new NetworkNodeFilter(this.filterCriteria, this.surveyDateInfo(), this.timeInfo())
);

readonly filteredNodes = computed(() => this.filter().filter(this.nodes()));

readonly filterOptions = computed(() => this.filter().filterOptions(this.nodes()));

onInit(): void {
this.networkService.initPage(this.routerService);
this.load();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,11 @@ export class SubsetOrphanNodeFilter {
this.criteria().lastUpdated,
(row) => row.lastUpdated,
this.timeInfo,
this.update({ ...this.criteria(), lastUpdated: TimestampFilterKind.all }),
this.update({
...this.criteria(),
lastUpdated: TimestampFilterKind.lastWeek,
}),
this.update({
...this.criteria(),
lastUpdated: TimestampFilterKind.lastMonth,
}),
this.update({
...this.criteria(),
lastUpdated: TimestampFilterKind.lastYear,
}),
this.update({ ...this.criteria(), lastUpdated: TimestampFilterKind.older })
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.all })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastWeek })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastMonth })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.lastYear })),
() => this.criteria.update((c) => ({ ...c, lastUpdated: TimestampFilterKind.older }))
);

private readonly allFilters = new Filters<OrphanNodeInfo>(this.lastUpdatedFilter);
Expand All @@ -46,8 +37,4 @@ export class SubsetOrphanNodeFilter {
const groups = [lastUpdated].filter((g) => g !== null);
return new FilterOptions(filteredCount, totalCount, groups);
}

private update(updatedCriteria: SubsetOrphanNodeFilterCriteria) {
return () => this.criteria.set(updatedCriteria);
}
}
Loading

0 comments on commit 623de27

Please sign in to comment.