Merge "Scouting App: Add test for note scouting"
diff --git a/scouting/scouting_test.ts b/scouting/scouting_test.ts
index e54a237..15a0509 100644
--- a/scouting/scouting_test.ts
+++ b/scouting/scouting_test.ts
@@ -241,7 +241,6 @@
 
     expect(await getHeadingText()).toEqual('Climb');
     await element(by.id('high')).click();
-    await setTextboxByIdTo('comment', 'A very useful comment here.');
     await element(by.buttonText('Next')).click();
 
     expect(await getHeadingText()).toEqual('Other');
@@ -249,6 +248,7 @@
     await adjustNthSliderBy(1, 1);
     await element(by.id('no_show')).click();
     await element(by.id('mechanically_broke')).click();
+    await setTextboxByIdTo('comment', 'A very useful comment here.');
     await element(by.buttonText('Next')).click();
 
     expect(await getHeadingText()).toEqual('Review and Submit');
@@ -273,7 +273,6 @@
 
     // Validate Climb.
     await expectReviewFieldToBe('Climb Level', 'High');
-    await expectReviewFieldToBe('Comments', 'A very useful comment here.');
 
     // Validate Other.
     await expectReviewFieldToBe('Defense Played On Rating', '3');
@@ -282,6 +281,7 @@
     await expectReviewFieldToBe('Never moved', 'false');
     await expectReviewFieldToBe('Battery died', 'false');
     await expectReviewFieldToBe('Broke (mechanically)', 'true');
+    await expectReviewFieldToBe('Comments', 'A very useful comment here.');
 
     await element(by.buttonText('Submit')).click();
     await browser.wait(
diff --git a/scouting/www/entry/entry.component.css b/scouting/www/entry/entry.component.css
index 6d13657..a78a00a 100644
--- a/scouting/www/entry/entry.component.css
+++ b/scouting/www/entry/entry.component.css
@@ -8,8 +8,8 @@
 }
 
 textarea {
-  width: 300px;
-  height: 150px;
+  width: 350px;
+  height: 180px;
 }
 
 button {
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
index 9be8db7..e73cfb0 100644
--- a/scouting/www/entry/entry.ng.html
+++ b/scouting/www/entry/entry.ng.html
@@ -254,10 +254,6 @@
       </label>
       <br />
     </form>
-    <div class="row">
-      <h4>Comments</h4>
-      <textarea [(ngModel)]="comment" id="comment"></textarea>
-    </div>
     <div class="buttons">
       <button class="btn btn-primary" (click)="prevSection()">Back</button>
       <button class="btn btn-primary" (click)="nextSection()">Next</button>
@@ -360,6 +356,15 @@
       </form>
     </div>
 
+    <div class="row">
+      <h4>General Comments About Match</h4>
+      <textarea
+        [(ngModel)]="comment"
+        id="comment"
+        placeholder="optional"
+      ></textarea>
+    </div>
+
     <div class="buttons">
       <button class="btn btn-primary" (click)="prevSection()">Back</button>
       <button class="btn btn-primary" (click)="nextSection()">Next</button>
@@ -398,7 +403,6 @@
     <h4>Climb</h4>
     <ul>
       <li>Climb Level: {{level | levelToString}}</li>
-      <li>Comments: {{comment}}</li>
     </ul>
 
     <h4>Other</h4>
@@ -410,6 +414,7 @@
       <li>Battery died: {{batteryDied}}</li>
       <li>Broke (mechanically): {{mechanicallyBroke}}</li>
       <li>Lost coms: {{lostComs}}</li>
+      <li>Comments: {{comment}}</li>
     </ul>
 
     <span class="error_message">{{ errorMessage }}</span>
diff --git a/scouting/www/notes/notes.component.ts b/scouting/www/notes/notes.component.ts
index 86df425..00faddd 100644
--- a/scouting/www/notes/notes.component.ts
+++ b/scouting/www/notes/notes.component.ts
@@ -1,4 +1,4 @@
-import {Component} from '@angular/core';
+import {Component, HostListener} 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';
@@ -83,6 +83,29 @@
   // Includes the team number, notes, and keyword selection.
   newData: Input[] = [];
 
+  // Keyboard shortcuts to switch between text areas.
+  // Listens for Ctrl + number and focuses on the
+  // corresponding textbox.
+  // More Info: https://angular.io/api/core/HostListener
+
+  @HostListener('window:keyup', ['$event'])
+  onEvent(event: KeyboardEvent) {
+    if (event.ctrlKey) {
+      if (event.code.includes('Digit')) {
+        this.handleFocus(event.key);
+      }
+    }
+  }
+
+  handleFocus(digit: string) {
+    let textArea = <HTMLInputElement>(
+      document.getElementById('text-input-' + digit)
+    );
+    if (textArea != null) {
+      textArea.focus();
+    }
+  }
+
   setTeamNumber() {
     let data: Input = {
       teamNumber: this.teamNumberSelection,
diff --git a/scouting/www/notes/notes.ng.html b/scouting/www/notes/notes.ng.html
index 8170801..b51a7ce 100644
--- a/scouting/www/notes/notes.ng.html
+++ b/scouting/www/notes/notes.ng.html
@@ -31,10 +31,19 @@
           <div><h3 id="team-key-{{i+1}}">{{team.teamNumber}}</h3></div>
         </div>
         <div class="">
+          <!--
+          Note Input Text Areas.
+          ID property is used for keyboard shorcuts to focus
+          on the corresponding text area.
+          The data-toggle and title properties are
+          used for bootstrap tooltips.
+          -->
           <textarea
             class="text-input"
             id="text-input-{{i+1}}"
             [(ngModel)]="newData[i].notesData"
+            data-toggle="tooltip"
+            title="Ctrl + {{i+1}}"
           ></textarea>
         </div>
         <!--Key Word Checkboxes-->