Scouting App: Add Request all data RPC

Create a requestor that contains methods to fetch and parse all
notes, stats, and driver rankings.

Signed-off-by: Filip Kujawa <filip.j.kujawa@gmail.com>
Change-Id: I5988666619d1089e4e2d3a59ae2fb947cd4d094d
diff --git a/scouting/www/rpc/BUILD b/scouting/www/rpc/BUILD
index 581a7b8..954b3fb 100644
--- a/scouting/www/rpc/BUILD
+++ b/scouting/www/rpc/BUILD
@@ -4,6 +4,7 @@
     name = "rpc",
     srcs = [
         "match_list_requestor.ts",
+        "view_data_requestor.ts",
     ],
     compiler = "//tools:tsc_wrapped_with_angular",
     target_compatible_with = ["@platforms//cpu:x86_64"],
@@ -11,8 +12,14 @@
     visibility = ["//visibility:public"],
     deps = [
         "//scouting/webserver/requests/messages:error_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_all_driver_rankings_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_all_driver_rankings_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_matches_response_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_matches_ts_fbs",
+        "//scouting/webserver/requests/messages:request_all_notes_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_all_notes_ts_fbs",
+        "//scouting/webserver/requests/messages:request_data_scouting_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_data_scouting_ts_fbs",
         "@com_github_google_flatbuffers//ts:flatbuffers_ts",
         "@npm//@angular/core",
     ],
diff --git a/scouting/www/rpc/view_data_requestor.ts b/scouting/www/rpc/view_data_requestor.ts
new file mode 100644
index 0000000..5eee3ec
--- /dev/null
+++ b/scouting/www/rpc/view_data_requestor.ts
@@ -0,0 +1,99 @@
+import {Injectable} from '@angular/core';
+import {Builder, ByteBuffer} from 'flatbuffers';
+import {ErrorResponse} from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
+import {RequestAllNotes} from 'org_frc971/scouting/webserver/requests/messages/request_all_notes_generated';
+import {
+  Note,
+  RequestAllNotesResponse,
+} from 'org_frc971/scouting/webserver/requests/messages/request_all_notes_response_generated';
+import {RequestAllDriverRankings} from 'org_frc971/scouting/webserver/requests/messages/request_all_driver_rankings_generated';
+import {
+  Ranking,
+  RequestAllDriverRankingsResponse,
+} from 'org_frc971/scouting/webserver/requests/messages/request_all_driver_rankings_response_generated';
+import {RequestDataScouting} from 'org_frc971/scouting/webserver/requests/messages/request_data_scouting_generated';
+import {
+  Stats,
+  RequestDataScoutingResponse,
+} from 'org_frc971/scouting/webserver/requests/messages/request_data_scouting_response_generated';
+
+@Injectable({providedIn: 'root'})
+export class ViewDataRequestor {
+  async fetchFromServer(start: Function, end: Function, path: string) {
+    const builder = new Builder();
+    start(builder);
+    builder.finish(end(builder));
+    const buffer = builder.asUint8Array();
+    const res = await fetch(path, {
+      method: 'POST',
+      body: buffer,
+    });
+
+    const resBuffer = await res.arrayBuffer();
+    const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+
+    if (!res.ok) {
+      const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
+      const errorMessage = parsedResponse.errorMessage();
+      throw `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
+    }
+
+    return fbBuffer;
+  }
+
+  // Returns all notes from the database.
+  async fetchNoteList(): Promise<Note[]> {
+    let fbBuffer = await this.fetchFromServer(
+      RequestAllNotes.startRequestAllNotes,
+      RequestAllNotes.endRequestAllNotes,
+      '/requests/request/all_notes'
+    );
+    const parsedResponse =
+      RequestAllNotesResponse.getRootAsRequestAllNotesResponse(fbBuffer);
+    // Convert the flatbuffer list into an array. That's more useful.
+    const noteList = [];
+    for (let i = 0; i < parsedResponse.noteListLength(); i++) {
+      noteList.push(parsedResponse.noteList(i));
+    }
+    return noteList;
+  }
+  // Returns all driver ranking entries from the database.
+  async fetchDriverRankingList(): Promise<Ranking[]> {
+    let fbBuffer = await this.fetchFromServer(
+      RequestAllDriverRankings.startRequestAllDriverRankings,
+      RequestAllDriverRankings.endRequestAllDriverRankings,
+      '/requests/request/all_driver_rankings'
+    );
+
+    const parsedResponse =
+      RequestAllDriverRankingsResponse.getRootAsRequestAllDriverRankingsResponse(
+        fbBuffer
+      );
+    // Convert the flatbuffer list into an array. That's more useful.
+    const driverRankingList = [];
+    for (let i = 0; i < parsedResponse.driverRankingListLength(); i++) {
+      driverRankingList.push(parsedResponse.driverRankingList(i));
+    }
+    return driverRankingList;
+  }
+  // Returns all data scouting entries from the database.
+  async fetchStatsList(): Promise<Stats[]> {
+    let fbBuffer = await this.fetchFromServer(
+      RequestDataScouting.startRequestDataScouting,
+      RequestDataScouting.endRequestDataScouting,
+      '/requests/request/all_statss'
+    );
+
+    const parsedResponse =
+      RequestDataScoutingResponse.getRootAsRequestDataScoutingResponse(
+        fbBuffer
+      );
+
+    // Convert the flatbuffer list into an array. That's more useful.
+    const statList = [];
+    for (let i = 0; i < parsedResponse.statsListLength(); i++) {
+      statList.push(parsedResponse.statsList(i));
+    }
+    return statList;
+  }
+}