-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor of enrollment report to deal with weird paging issues.
- Loading branch information
1 parent
92eb039
commit 18ca491
Showing
9 changed files
with
292 additions
and
270 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
...orts/enrollment-report/enrollment-report-summary/enrollment-report-summary.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
<ng-container *ngIf="ctx"> | ||
<div class="results"> | ||
<table class="report-table table-hover gameboard-report"> | ||
<colgroup span="3"></colgroup> | ||
<colgroup span="5"></colgroup> | ||
|
||
<thead class="thead-light"> | ||
<tr class="headers super-headers-row"> | ||
<th scope="col" colSpan="3" class="group-header">Enrollment</th> | ||
<th scope="col" colSpan="5" class="group-header">Performance</th> | ||
</tr> | ||
</thead> | ||
|
||
<tbody> | ||
<tr class="headers headers-row"> | ||
<td>Player</td> | ||
<td>Enroll Date</td> | ||
<td>Game</td> | ||
<td>Cumulative Time</td> | ||
<td>Attempted</td> | ||
<td>Partially Solved</td> | ||
<td>Completely Solved</td> | ||
<td>Score</td> | ||
</tr> | ||
|
||
<tr class="data-row" *ngFor="let record of ctx.results.records"> | ||
<td> | ||
<div class="d-flex align-items-center"> | ||
<app-player-field class="d-block" | ||
[player]="{ userId: record.player.id, name: record.player.name, sponsor: record.player.sponsor, team: record.game.isTeamGame ? record.team : undefined }"></app-player-field> | ||
</div> | ||
</td> | ||
<td class="report-field date"> | ||
<ng-container *ngIf="record.player.enrollDate else noValue"> | ||
<p>{{ record.player.enrollDate | shortdate }}</p> | ||
<p class="subtle-info">{{ record.player.enrollDate | friendlyTime }}</p> | ||
</ng-container> | ||
</td> | ||
<td> | ||
<p class="game-name m-0">{{ record.game.name }}</p> | ||
<p class="game-info subtle-info"> | ||
<span *ngIf="record.game.series"> | ||
<app-parameter-change-link | ||
[config]="{ parameterChange: { series: record.game.series } }"> | ||
{{ record.game.series }} | ||
</app-parameter-change-link> | ||
:: | ||
</span> | ||
<span *ngIf="record.game.season"> | ||
<app-parameter-change-link | ||
[config]="{ parameterChange: { seasons: record.game.season }}"> | ||
{{ record.game.season }} | ||
</app-parameter-change-link> | ||
:: | ||
</span> | ||
<span *ngIf="record.game.track; else noValue"> | ||
<app-parameter-change-link [config]="{ parameterChange: { tracks: record.game.track }}"> | ||
{{ record.game.track }} | ||
</app-parameter-change-link> | ||
</span> | ||
</p> | ||
</td> | ||
<td class="report-field numerical"> | ||
<p class="report-field" *ngIf="record.playTime.durationMs; else noValue"> | ||
{{ record.playTime.durationMs | msToDuration }} | ||
</p> | ||
</td> | ||
<td class="report-field numerical"> | ||
<p class="challenges-deployed"> | ||
<span [class.tooltipped-value]="record.challenges.length" | ||
(click)="record.challenges && showChallengesDetail(record, 'deployed')"> | ||
{{ record.challenges | arrayToCount }} | ||
</span> | ||
</p> | ||
</td> | ||
<td class="report-field numerical"> | ||
<p class="count challenges-partial"> | ||
<span [class.tooltipped-value]="record.challengesPartiallySolvedCount" | ||
(click)="record.challengesPartiallySolvedCount && showChallengesDetail(record, 'partial')"> | ||
{{ record.challengesPartiallySolvedCount }} | ||
</span> | ||
</p> | ||
</td> | ||
<td class="report-field numerical"> | ||
<p class="count challenges-complete"> | ||
<span [class.tooltipped-value]="record.challengesCompletelySolvedCount" | ||
(click)="record.challengesCompletelySolvedCount && showChallengesDetail(record, 'complete')"> | ||
{{ record.challengesCompletelySolvedCount }} | ||
</span> | ||
</p> | ||
</td> | ||
<td class="report-field numerical"> | ||
<p> | ||
<span [class.tooltipped-value]="(record.score || 0) > 0" | ||
(click)="(record.score || 0) && showScoreBreakdown(record)"> | ||
{{ record.score }} | ||
</span> | ||
</p> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
|
||
<div class="pager-container d-flex justify-content-end mt-4"> | ||
<div class="flex-grow-1"></div> | ||
<app-select-pager [itemCount]="ctx.results.paging.itemCount" [pageSize]="ctx.results.paging.pageSize || 20" | ||
(change)="handlePagingChange($event)"></app-select-pager> | ||
</div> | ||
</div> | ||
</ng-container> | ||
|
||
<ng-template #noRecords> | ||
<app-no-report-records recordDescription="enrollments"></app-no-report-records> | ||
</ng-template> | ||
|
||
<ng-template #noValue> | ||
<app-report-field-no-value></app-report-field-no-value> | ||
</ng-template> |
Empty file.
93 changes: 93 additions & 0 deletions
93
...eports/enrollment-report/enrollment-report-summary/enrollment-report-summary.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; | ||
import { EnrollmentReportFlatParameters, EnrollmentReportRecord } from '../enrollment-report.models'; | ||
import { MarkdownHelpersService } from '@/services/markdown-helpers.service'; | ||
import { ModalConfirmService } from '@/services/modal-confirm.service'; | ||
import { ReportResults } from '@/reports/reports-models'; | ||
import { PagingArgs } from '@/api/models'; | ||
import { RouterService } from '@/services/router.service'; | ||
import { EnrollmentReportService } from '../enrollment-report.service'; | ||
import { firstValueFrom } from 'rxjs'; | ||
|
||
interface EnrollmentReportSummaryContext { | ||
results: ReportResults<EnrollmentReportRecord>; | ||
} | ||
|
||
@Component({ | ||
selector: 'app-enrollment-report-summary', | ||
templateUrl: './enrollment-report-summary.component.html', | ||
styleUrls: ['./enrollment-report-summary.component.scss'] | ||
}) | ||
export class EnrollmentReportSummaryComponent implements OnChanges { | ||
@Input() parameters: EnrollmentReportFlatParameters | null = null; | ||
|
||
protected ctx?: EnrollmentReportSummaryContext; | ||
protected isLoading = false; | ||
|
||
constructor( | ||
private enrollmentReportService: EnrollmentReportService, | ||
private markdownHelpersService: MarkdownHelpersService, | ||
private modalService: ModalConfirmService, | ||
private routerService: RouterService | ||
) { } | ||
|
||
async ngOnChanges(changes: SimpleChanges) { | ||
if (!changes.parameters) | ||
return; | ||
|
||
this.isLoading = true; | ||
this.ctx = { | ||
results: await firstValueFrom(this.enrollmentReportService.getReportData(this.parameters || {})) | ||
}; | ||
this.isLoading = false; | ||
} | ||
|
||
protected handlePagingChange(request: PagingArgs) { | ||
this.routerService.updateQueryParams({ parameters: { ...request } }); | ||
} | ||
|
||
protected showChallengesDetail(record: EnrollmentReportRecord, challengeStatus: "deployed" | "partial" | "complete") { | ||
let challenges: { name: string, score?: number, maxPossiblePoints: number }[] = []; | ||
|
||
switch (challengeStatus) { | ||
case "partial": | ||
challenges = record.challenges.filter(c => c.result == "partial"); | ||
break; | ||
case "complete": | ||
challenges = record.challenges.filter(c => c.result == "success"); | ||
break; | ||
default: | ||
challenges = record.challenges; | ||
} | ||
|
||
this.modalService.open({ | ||
bodyContent: this | ||
.markdownHelpersService | ||
.arrayToBulletList(challenges.map(c => `${c.name} (${c.score || "--"}/${c.maxPossiblePoints}) possible points`)), | ||
renderBodyAsMarkdown: true, | ||
title: `${record.player.name}: Challenges ${challengeStatus.substring(0, 1).toUpperCase()}${challengeStatus.substring(1)}`, | ||
}); | ||
} | ||
|
||
protected showScoreBreakdown(record: EnrollmentReportRecord) { | ||
const scoreItems: { points: number, source: string }[] = []; | ||
|
||
for (const challenge of record.challenges) { | ||
if (challenge.score) | ||
scoreItems.push({ points: challenge.score, source: `**${challenge.name}**, ${challenge.result.toString()} solve` }); | ||
|
||
if (challenge.manualChallengeBonuses?.length) { | ||
for (const bonus of challenge.manualChallengeBonuses) { | ||
scoreItems.push({ points: bonus.points, source: `**Manual bonus**, ${bonus.description}` }); | ||
} | ||
} | ||
} | ||
|
||
this.modalService.open({ | ||
bodyContent: this | ||
.markdownHelpersService | ||
.arrayToBulletList(scoreItems.map(i => `${i.points} (${i.source})`)), | ||
renderBodyAsMarkdown: true, | ||
title: `${record.player.name}: Score Breakdown` | ||
}); | ||
} | ||
} |
Oops, something went wrong.