Add notes scouting page to scouting app.
Change-Id: Ie2c60ba4a69ae68f407cb2a0c0fb6e90b7bfe1c5
Signed-off-by: Alex Perry <alex.perry96@gmail.com>
diff --git a/scouting/www/notes/BUILD b/scouting/www/notes/BUILD
new file mode 100644
index 0000000..39a97ef
--- /dev/null
+++ b/scouting/www/notes/BUILD
@@ -0,0 +1,29 @@
+load("@npm//@bazel/typescript:index.bzl", "ts_library")
+
+ts_library(
+ name = "notes",
+ srcs = [
+ "notes.component.ts",
+ "notes.module.ts",
+ ],
+ angular_assets = [
+ "notes.component.css",
+ "notes.ng.html",
+ "//scouting/www:common_css",
+ ],
+ compiler = "//tools:tsc_wrapped_with_angular",
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+ use_angular_plugin = True,
+ visibility = ["//visibility:public"],
+ deps = [
+ "//scouting/webserver/requests/messages:error_response_ts_fbs",
+ "//scouting/webserver/requests/messages:request_notes_for_team_response_ts_fbs",
+ "//scouting/webserver/requests/messages:request_notes_for_team_ts_fbs",
+ "//scouting/webserver/requests/messages:submit_notes_response_ts_fbs",
+ "//scouting/webserver/requests/messages:submit_notes_ts_fbs",
+ "@com_github_google_flatbuffers//ts:flatbuffers_ts",
+ "@npm//@angular/common",
+ "@npm//@angular/core",
+ "@npm//@angular/forms",
+ ],
+)
diff --git a/scouting/www/notes/notes.component.css b/scouting/www/notes/notes.component.css
new file mode 100644
index 0000000..869bdab
--- /dev/null
+++ b/scouting/www/notes/notes.component.css
@@ -0,0 +1,12 @@
+.error {
+ color: red;
+}
+
+.text-input {
+ width: calc(100% - 20px);
+}
+
+.buttons {
+ display: flex;
+ justify-content: space-between;
+}
diff --git a/scouting/www/notes/notes.component.ts b/scouting/www/notes/notes.component.ts
new file mode 100644
index 0000000..09178f8
--- /dev/null
+++ b/scouting/www/notes/notes.component.ts
@@ -0,0 +1,90 @@
+import {Component} from '@angular/core';
+import {Builder, ByteBuffer} from 'flatbuffers';
+import {ErrorResponse} from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
+import {RequestNotesForTeam} from 'org_frc971/scouting/webserver/requests/messages/request_notes_for_team_generated';
+import {Note as NoteFb, RequestNotesForTeamResponse} from 'org_frc971/scouting/webserver/requests/messages/request_notes_for_team_response_generated';
+import {SubmitNotes} from 'org_frc971/scouting/webserver/requests/messages/submit_notes_generated';
+import {SubmitNotesResponse} from 'org_frc971/scouting/webserver/requests/messages/submit_notes_response_generated';
+
+type Section = 'TeamSelection'|'Data';
+
+interface Note {
+ readonly data: string;
+}
+
+@Component({
+ selector: 'frc971-notes',
+ templateUrl: './notes.ng.html',
+ styleUrls: ['../common.css', './notes.component.css']
+})
+export class Notes {
+ section: Section = 'TeamSelection';
+ notes: Note[] = [];
+
+ errorMessage = '';
+
+ teamNumber: number = 971;
+ newData = '';
+
+ async setTeamNumber() {
+ const builder = new Builder();
+ RequestNotesForTeam.startRequestNotesForTeam(builder);
+ RequestNotesForTeam.addTeam(builder, this.teamNumber);
+ builder.finish(RequestNotesForTeam.endRequestNotesForTeam(builder));
+
+ const buffer = builder.asUint8Array();
+ const res = await fetch(
+ '/requests/request/notes_for_team', {method: 'POST', body: buffer});
+
+ const resBuffer = await res.arrayBuffer();
+ const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+
+ if (res.ok) {
+ this.notes = [];
+ const parsedResponse =
+ RequestNotesForTeamResponse.getRootAsRequestNotesForTeamResponse(
+ fbBuffer);
+ for (let i = 0; i < parsedResponse.notesLength(); i++) {
+ const fbNote = parsedResponse.notes(i);
+ this.notes.push({data: fbNote.data()});
+ }
+ this.section = 'Data';
+ } else {
+ const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
+
+ const errorMessage = parsedResponse.errorMessage();
+ this.errorMessage =
+ `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
+ }
+ }
+
+ changeTeam() {
+ this.section = "TeamSelection";
+ }
+
+ async submitData() {
+ const builder = new Builder();
+ const dataFb = builder.createString(this.newData);
+ builder.finish(
+ SubmitNotes.createSubmitNotes(builder, this.teamNumber, dataFb));
+
+ const buffer = builder.asUint8Array();
+ const res = await fetch(
+ '/requests/submit/submit_notes', {method: 'POST', body: buffer});
+
+ if (res.ok) {
+ this.newData = '';
+ this.errorMessage = '';
+ await this.setTeamNumber();
+ } else {
+ const resBuffer = await res.arrayBuffer();
+ const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+ const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
+
+ const errorMessage = parsedResponse.errorMessage();
+ this.errorMessage =
+ `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
+ }
+ }
+}
+
diff --git a/scouting/www/notes/notes.module.ts b/scouting/www/notes/notes.module.ts
new file mode 100644
index 0000000..c537550
--- /dev/null
+++ b/scouting/www/notes/notes.module.ts
@@ -0,0 +1,14 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {FormsModule} from '@angular/forms';
+
+import {Notes} from './notes.component';
+
+@NgModule({
+ declarations: [Notes],
+ exports: [Notes],
+ imports: [CommonModule, FormsModule],
+})
+export class NotesModule {
+}
+
diff --git a/scouting/www/notes/notes.ng.html b/scouting/www/notes/notes.ng.html
new file mode 100644
index 0000000..90f004a
--- /dev/null
+++ b/scouting/www/notes/notes.ng.html
@@ -0,0 +1,26 @@
+<h2>Notes</h2>
+
+<ng-container [ngSwitch]="section">
+ <div *ngSwitchCase="'TeamSelection'">
+ <label for="team_number_notes">Team Number</label>
+ <input [(ngModel)]="teamNumber" type="number" id="team_number_notes" min="1" max="9999">
+ <button class="btn btn-primary" (click)="setTeamNumber()">Select</button>
+ </div>
+
+ <div *ngSwitchCase="'Data'">
+ <h3> Scouting team: {{teamNumber}}</h3>
+ <ul *ngFor="let note of notes">
+ <li class="note">
+ {{ note.data }}
+ </li>
+ </ul>
+ <textarea class="text-input" [(ngModel)]="newData"></textarea>
+ <div class="buttons">
+ <button class="btn btn-primary" (click)="changeTeam()">Change team</button>
+ <button class="btn btn-primary" (click)="submitData()">Submit</button>
+ </div>
+ </div>
+ <div class="error">
+ {{errorMessage}}
+ </div>
+</ng-container>