Extract results table to separate component

This commit is contained in:
Jim Martens 2023-08-11 19:46:51 +02:00
parent 3a6892bc34
commit 641bba55e0
7 changed files with 121 additions and 42 deletions

View File

@ -0,0 +1,15 @@
<table mat-table [dataSource]="dataSource" [hidden]="electedCandidates == null" matSort (matSortChange)="announceSortChange($event)">
<ng-container matColumnDef="party">
<th mat-header-cell mat-sort-header *matHeaderCellDef i18n
i18n-sortActionDescription sortActionDescription="Sort by party">Party</th>
<td mat-cell *matCellDef="let row">{{row.party}}</td>
</ng-container>
<ng-container matColumnDef="seats">
<th mat-header-cell mat-sort-header i18n-sortActionDescription sortActionDescription="Sort by seats"
*matHeaderCellDef i18n>Seats</th>
<td mat-cell *matCellDef="let row">{{row.seats}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="resultColumns"></tr>
<tr mat-row *matRowDef="let row; columns: resultColumns"></tr>
</table>

View File

@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ElectionResultComponent } from './election-result.component';
describe('ElectionResultComponent', () => {
let component: ElectionResultComponent;
let fixture: ComponentFixture<ElectionResultComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ElectionResultComponent]
});
fixture = TestBed.createComponent(ElectionResultComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,64 @@
import {AfterViewInit, Component, Input, ViewChild} from '@angular/core';
import {Party} from "../model/party";
import {ElectedCandidates} from "../model/elected-candidates";
import {MatSort, Sort} from "@angular/material/sort";
import {LiveAnnouncer} from "@angular/cdk/a11y";
import {MatTableDataSource} from "@angular/material/table";
export interface PartySeats {
party: string;
seats: number;
}
@Component({
selector: 'app-election-result',
templateUrl: './election-result.component.html',
styleUrls: ['./election-result.component.scss']
})
export class ElectionResultComponent implements AfterViewInit {
@ViewChild(MatSort) sort: MatSort|null = null;
resultColumns: string[] = ['party', 'seats'];
seatsPerParty: PartySeats[] = [];
dataSource: MatTableDataSource<PartySeats> = new MatTableDataSource<PartySeats>();
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
@Input() parties: Map<string, Party> = new Map<string, Party>();
private _electedCandidates: ElectedCandidates | null = null;
get electedCandidates(): ElectedCandidates | null {
return this._electedCandidates;
}
@Input() set electedCandidates(value: ElectedCandidates | null) {
this._electedCandidates = value;
if (value != null) {
const newSeatAllocations = [];
for (const partyAbbreviation in value.seatAllocation) {
if (!this.parties.has(partyAbbreviation)) {
continue;
}
newSeatAllocations.push({
party: this.parties.get(partyAbbreviation)!.abbreviation,
seats: value.seatAllocation[partyAbbreviation]
})
}
this.seatsPerParty = newSeatAllocations;
this.dataSource.data = this.seatsPerParty;
}
}
constructor(private liveAnnouncer: LiveAnnouncer) {
}
announceSortChange(sortState: Sort) {
if (sortState.direction) {
this.liveAnnouncer.announce($localize`Sorted ${sortState.direction}ending`)
} else {
this.liveAnnouncer.announce($localize`Sorting cleared`)
}
}
}

View File

@ -1,18 +1,6 @@
<h1 class="mat-headline-5">{{viewModel.election.name}}</h1>
<table mat-table [dataSource]="seatsPerParty" *ngIf="electedCandidates != null">
<ng-container matColumnDef="party">
<th mat-header-cell *matHeaderCellDef i18n>Party</th>
<td mat-cell *matCellDef="let row">{{row.party.abbreviation}}</td>
</ng-container>
<ng-container matColumnDef="seats">
<th mat-header-cell *matHeaderCellDef i18n>Seats</th>
<td mat-cell *matCellDef="let row">{{row.seats}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="resultColumns"></tr>
<tr mat-row *matRowDef="let row; columns: resultColumns"></tr>
</table>
<app-election-result [electedCandidates]="electedCandidates" [parties]="viewModel.parties"></app-election-result>
<button mat-raised-button i18n #calculateButton (keyup.enter)="onCalculate()" (click)="onCalculate()">
<mat-spinner class="spinner" *ngIf="showSpinner"></mat-spinner>

View File

@ -4,7 +4,7 @@ import {KeyValue} from "@angular/common";
import {Party} from "../model/party";
import {VotingResult} from "../model/voting-result";
import {Constituency} from "../model/constituency";
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
import {FormBuilder, FormGroup} from '@angular/forms';
import {
DEFAULT_MODIFIED_RESULT,
ModifiedElectionResult,
@ -25,8 +25,6 @@ export class ElectionComponent implements OnInit {
form: FormGroup;
overallResults: FormGroup;
constituencyResults: FormGroup;
resultColumns: string[] = ['party', 'seats'];
seatsPerParty: { party: Party, seats: number }[] = [];
showSpinner = false;
constituencyToId: Map<number, Constituency> = new Map<number, Constituency>();
constituencyNumberToName: Map<string, string> = new Map<string, string>();
@ -60,17 +58,6 @@ export class ElectionComponent implements OnInit {
@Input() set electedCandidates(value: ElectedCandidates | null) {
this._electedCandidates = value;
if (value != null) {
const newSeatAllocations = [];
for (const partyAbbreviation in value.seatAllocation) {
if (!this.viewModel.parties.has(partyAbbreviation)) {
continue;
}
newSeatAllocations.push({
party: this.viewModel.parties.get(partyAbbreviation)!,
seats: value.seatAllocation[partyAbbreviation]
})
}
this.seatsPerParty = newSeatAllocations;
this.showSpinner = false;
if (this.calculateButton != undefined) {
this.calculateButton.disabled = false;

View File

@ -15,28 +15,32 @@ import {MatInputModule} from "@angular/material/input";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import { ElectionContainerComponent } from './election-container/election-container.component';
import {MatButtonModule} from "@angular/material/button";
import { ElectionResultComponent } from './election-result/election-result.component';
import {MatSortModule} from "@angular/material/sort";
@NgModule({
declarations: [
LandingPageComponent,
ElectionComponent,
ElectionContainerComponent
ElectionContainerComponent,
ElectionResultComponent
],
imports: [
CommonModule,
ElectionsRoutingModule,
StoreModule.forFeature(featureStateName, electionsReducers),
EffectsModule.forFeature([ElectionsEffects]),
MatTableModule,
MatProgressSpinnerModule,
MatFormFieldModule,
MatTabsModule,
MatInputModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatSortModule,
],
imports: [
CommonModule,
ElectionsRoutingModule,
StoreModule.forFeature(featureStateName, electionsReducers),
EffectsModule.forFeature([ElectionsEffects]),
MatTableModule,
MatProgressSpinnerModule,
MatFormFieldModule,
MatTabsModule,
MatInputModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
],
exports: [
LandingPageComponent
]