Merge "scouting: Enable strict template checking"
diff --git a/scouting/www/app/app.ts b/scouting/www/app/app.ts
index 1a70b6f..645c224 100644
--- a/scouting/www/app/app.ts
+++ b/scouting/www/app/app.ts
@@ -1,5 +1,7 @@
import {Component, ElementRef, ViewChild, isDevMode} from '@angular/core';
+import {CompLevel} from '@org_frc971/scouting/www/entry';
+
type Tab =
| 'MatchList'
| 'Notes'
@@ -17,7 +19,7 @@
teamNumber: string;
matchNumber: number;
setNumber: number;
- compLevel: string;
+ compLevel: CompLevel;
};
@Component({
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
index b1d84b7..d2c922e 100644
--- a/scouting/www/entry/entry.component.ts
+++ b/scouting/www/entry/entry.component.ts
@@ -41,7 +41,7 @@
// TODO(phil): Deduplicate with match_list.component.ts.
const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
-type CompLevel = typeof COMP_LEVELS[number];
+export type CompLevel = typeof COMP_LEVELS[number];
// TODO(phil): Deduplicate with match_list.component.ts.
const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
@@ -141,7 +141,12 @@
errorMessage: string = '';
autoPhase: boolean = true;
mobilityCompleted: boolean = false;
+ // TODO(phil): Come up with a better name here.
selectedValue = 0;
+ endGameAction: StageType = StageType.kMISSING;
+ noteIsTrapped: boolean = false;
+ endGameSpotlight: boolean = false;
+
nextTeamNumber = '';
preScouting: boolean = false;
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
index 553fa1e..233d63a 100644
--- a/scouting/www/entry/entry.ng.html
+++ b/scouting/www/entry/entry.ng.html
@@ -91,7 +91,7 @@
type="radio"
name="radio-group"
[value]="i"
- (change)="selectedValue = $event.target.value"
+ [(ngModel)]="selectedValue"
/>
{{ i }}
</label>
@@ -311,21 +311,19 @@
<div class="button_row">
<label>
<input
- #park
type="radio"
- id="option1"
name="endgameaction"
- value="park"
+ [value]="StageType.kPARK"
+ [(ngModel)]="endGameAction"
/>
Park
</label>
<label>
<input
- #onStage
type="radio"
- id="option2"
name="endgameaction"
- value="onStage"
+ [value]="StageType.kON_STAGE"
+ [(ngModel)]="endGameAction"
/>
On Stage
</label>
@@ -333,42 +331,32 @@
<div class="button_row">
<label>
<input
- #harmony
type="radio"
- id="option3"
name="endgameaction"
- value="harmony"
+ [value]="StageType.kHARMONY"
+ [(ngModel)]="endGameAction"
/>
Harmony
</label>
<label>
<input
- #na
type="radio"
- id="option2"
name="endgameaction"
- value="na"
+ [value]="StageType.kMISSING"
+ [(ngModel)]="endGameAction"
/>
N/A
</label>
</div>
<label>
- <input
- #trapNote
- type="checkbox"
- id="trapnote"
- name="trapnote"
- value="trapNote"
- />
+ <input type="checkbox" name="trapnote" [(ngModel)]="noteIsTrapped" />
Trap Note
</label>
<label>
<input
- #spotlight
type="checkbox"
- id="spotlight"
name="spotlight"
- value="spotlight"
+ [(ngModel)]="endGameSpotlight"
/>
Spotlight
</label>
@@ -394,7 +382,7 @@
<button
*ngIf="!autoPhase"
class="btn btn-info"
- (click)="changeSectionTo('Review and Submit'); addPenalties(); addAction({type: 'endMatchAction', stageType: (park.checked ? StageType.kPARK : onStage.checked ? StageType.kON_STAGE : harmony.checked ? StageType.kHARMONY : StageType.kMISSING), trapNote: trapNote.checked, spotlight: spotlight.checked});"
+ (click)="changeSectionTo('Review and Submit'); addPenalties(); addAction({type: 'endMatchAction', stageType: endGameAction, trapNote: noteIsTrapped, spotlight: endGameSpotlight});"
>
End Match
</button>
@@ -430,7 +418,7 @@
</button>
<button
class="btn btn-info"
- (click)="changeSectionTo('Review and Submit'); addPenalties(); addAction({type: 'endMatchAction', stageType: (park.checked ? StageType.kPARK : onStage.checked ? StageType.kON_STAGE : harmony.checked ? StageType.kHARMONY : StageType.kMISSING), trapNote: trapNote.checked, spotlight: spotlight.checked});"
+ (click)="changeSectionTo('Review and Submit'); addPenalties(); addAction({type: 'endMatchAction', stageType: endGameAction, trapNote: noteIsTrapped, spotlight: endGameSpotlight});"
>
End Match
</button>
@@ -439,35 +427,30 @@
<div *ngSwitchCase="'Review and Submit'" id="Review" class="container-fluid">
<div class="row">
<ul id="review_data">
- <li
- *ngFor="let action of actionList"
- [ngValue]="action"
- style="display: flex"
- >
+ <li *ngFor="let action of actionList" style="display: flex">
<div [ngSwitch]="action.type" style="padding: 0px">
<span *ngSwitchCase="'startMatchAction'">
- Started match at position {{action.position}}
+ Started match at position {{$any(action).position}}
</span>
<span *ngSwitchCase="'pickupNoteAction'">Picked up Note</span>
<span *ngSwitchCase="'placeNoteAction'">
- Placed at {{stringifyScoreType(action.scoreType)}}
+ Placed at {{stringifyScoreType($any(action).scoreType)}}
</span>
<span *ngSwitchCase="'endAutoPhase'">Ended auto phase</span>
<span *ngSwitchCase="'endMatchAction'">
- Ended Match; stageType: {{(action.stageType === 0 ? "kON_STAGE" :
- action.stageType === 1 ? "kPARK" : action.stageType === 2 ?
- "kHARMONY" : "kMISSING")}}, trapNote: {{action.trapNote}},
- spotlight: {{action.spotlight}}
+ Ended Match; stageType:
+ {{stringifyStageType($any(action).stageType)}}, trapNote:
+ {{$any(action).trapNote}}, spotlight: {{$any(action).spotlight}}
</span>
<span *ngSwitchCase="'robotDeathAction'">
- Robot dead: {{action.robotDead}}
+ Robot dead: {{$any(action).robotDead}}
</span>
<span *ngSwitchCase="'mobilityAction'">
- Mobility: {{action.mobility}}
+ Mobility: {{$any(action).mobility}}
</span>
<span *ngSwitchDefault>{{action.type}}</span>
<span *ngSwitchCase="'penaltyAction'">
- Penalties: {{action.penalties}}
+ Penalties: {{$any(action).penalties}}
</span>
</div>
</li>
diff --git a/scouting/www/match_list/match_list.component.ts b/scouting/www/match_list/match_list.component.ts
index 35165d5..08120b3 100644
--- a/scouting/www/match_list/match_list.component.ts
+++ b/scouting/www/match_list/match_list.component.ts
@@ -9,11 +9,15 @@
import {MatchListRequestor} from '@org_frc971/scouting/www/rpc';
+// TODO(phil): Deduplicate with entry.component.ts.
+const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
+export type CompLevel = typeof COMP_LEVELS[number];
+
type TeamInMatch = {
teamNumber: string;
matchNumber: number;
setNumber: number;
- compLevel: string;
+ compLevel: CompLevel;
};
@Component({
@@ -23,6 +27,7 @@
})
export class MatchListComponent implements OnInit {
@Output() selectedTeamEvent = new EventEmitter<TeamInMatch>();
+
progressMessage: string = '';
errorMessage: string = '';
matchList: Match[] = [];
@@ -30,6 +35,14 @@
constructor(private readonly matchListRequestor: MatchListRequestor) {}
+ // Validates that the specified string is a proper comp level.
+ validateCompLevel(compLevel: string): CompLevel {
+ if (COMP_LEVELS.indexOf(compLevel as any) !== -1) {
+ return compLevel as CompLevel;
+ }
+ throw new Error(`Could not parse "${compLevel}" as a valid comp level.`);
+ }
+
// Returns true if the match is fully scouted. Returns false otherwise.
matchIsFullyScouted(match: Match): boolean {
const scouted = match.dataScouted();
diff --git a/scouting/www/match_list/match_list.ng.html b/scouting/www/match_list/match_list.ng.html
index 0ebbe4c..fe26d09 100644
--- a/scouting/www/match_list/match_list.ng.html
+++ b/scouting/www/match_list/match_list.ng.html
@@ -22,7 +22,7 @@
teamNumber: team.teamNumber,
matchNumber: match.matchNumber(),
setNumber: match.setNumber(),
- compLevel: match.compLevel()
+ compLevel: validateCompLevel(match.compLevel()),
})"
class="match-item"
[ngClass]="team.color"
diff --git a/tsconfig.json b/tsconfig.json
index bd23965..3999b5c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,5 +17,10 @@
},
"bazelOptions": {
"workspaceName": "971-Robot-Code"
+ },
+ "angularCompilerOptions": {
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true
}
}