[AM] Add support for alert owners in am.skia.org

Highlights:

* If an alert has an owner specified in the labels then:
  * An "Assign to Owner" button shows up- https://screenshot.googleplex.com/gzgshv6z5S2.png
  * In the "Assign" popup, the alert owner's email has an indication next to the email- https://screenshot.googleplex.com/XpvgNsoESyi.png
* The alert's owner has the alert show up in the Mine tab (even if it is not assigned to them yet)- https://screenshot.googleplex.com/e9OYnQS3aP3.png
* The alert's owner has the active alert favicon set (even if it is not assigned to them yet)- https://screenshot.googleplex.com/xA2zDoXVqVG.png

Change-Id: I73ca5506a75664f14546bc5881f9e25c2c284987
Bug: skia:8645
Reviewed-on: https://skia-review.googlesource.com/c/179524
Commit-Queue: Ravi Mistry <rmistry@google.com>
Reviewed-by: Joe Gregorio <jcgregorio@google.com>
diff --git a/am/modules/alert-manager-sk/alert-manager-sk.js b/am/modules/alert-manager-sk/alert-manager-sk.js
index 74a5bbc..3dac5a1 100644
--- a/am/modules/alert-manager-sk/alert-manager-sk.js
+++ b/am/modules/alert-manager-sk/alert-manager-sk.js
@@ -163,7 +163,7 @@
   </tabs-sk>
   <tabs-panel-sk>
     <section class=mine>
-      ${incidentList(ele, ele._incidents.filter(i => i.active && ((ele._user === ele._trooper && (i.params.__silence_state !== 'silenced')) || (i.params.assigned_to === ele._user))))}
+      ${incidentList(ele, ele._incidents.filter(i => i.active && ((ele._user === ele._trooper && (i.params.__silence_state !== 'silenced')) || (i.params.assigned_to === ele._user) || (i.params.owner === ele._user))))}
     </section>
     <section class=incidents>
       ${incidentList(ele, ele._incidents)}
@@ -241,6 +241,7 @@
     this.addEventListener('del-note', e => this._delNote(e));
     this.addEventListener('take', e => this._take(e));
     this.addEventListener('assign', e => this._assign(e));
+    this.addEventListener('assign-to-owner', e => this._assignToOwner(e));
 
     this._render();
     this._busy = $$('#busy', this);
@@ -436,7 +437,8 @@
   }
 
   _assign(e) {
-    $$('#chooser', this).open(this._emails).then(email => {
+    const owner = this._selected && this._selected.params.owner;
+    $$('#chooser', this).open(this._emails, owner).then(email => {
       let detail = {
         key: e.detail.key,
         email: email,
@@ -445,6 +447,15 @@
     });
   }
 
+  _assignToOwner(e) {
+    const owner = this._selected && this._selected.params.owner;
+    let detail = {
+      key: e.detail.key,
+      email: owner,
+    }
+    this._doImpl('/_/assign', detail);
+  }
+
   _take(e) {
     this._doImpl('/_/take', e.detail);
   }
@@ -576,6 +587,7 @@
       && (
         (isTrooper && !incident.params.assigned_to)
         || (incident.params.assigned_to == this._user)
+        || (incident.params.owner == this._user)
       )
     ) {
       return true
diff --git a/am/modules/email-chooser-sk/email-chooser-sk.js b/am/modules/email-chooser-sk/email-chooser-sk.js
index 6bdd504..6b250cb 100644
--- a/am/modules/email-chooser-sk/email-chooser-sk.js
+++ b/am/modules/email-chooser-sk/email-chooser-sk.js
@@ -20,7 +20,7 @@
   <h2>Assign</h2>
   <select size=10 @input=${ele._input}>
     <option value='' selected>(un-assign)</option>
-    ${ele._emails.map(email => html`<option value=${email}>${email}</option>`)}
+    ${ele._emails.map(email => displayEmail(email, ele._owner))}
   </select>
   <div class=buttons>
     <button @click=${ele._dismiss}>Cancel</button>
@@ -28,12 +28,21 @@
   </div>
 </dialog-sk>`;
 
+function displayEmail(email, owner) {
+  if (owner === email) {
+    return html`<option value=${email}>${email} (alert owner)</option>`;
+  } else {
+    return html`<option value=${email}>${email}</option>`;
+  }
+}
+
 window.customElements.define('email-chooser-sk', class extends HTMLElement {
   constructor() {
     super();
     this._resolve = null;
     this._reject = null;
     this._emails = [];
+    this._owner = '';
     this._selected = '';
   }
 
@@ -46,11 +55,13 @@
    * Display the dialog.
    *
    * @param emails {Array} List of emails to choose from.
+   * @param owner {String} The owner of this incident if available. Optional.
    * @returns {Promise} Returns a Promise that resolves on OK, and rejects on Cancel.
    *
    */
-  open(emails) {
+  open(emails, owner) {
     this._emails = emails;
+    this._owner = owner;
     this._render();
     this._dialog.shown = true;
     $$('select', this).focus();
diff --git a/am/modules/incident-sk/incident-sk.js b/am/modules/incident-sk/incident-sk.js
index 033b7c6..d8caaae 100644
--- a/am/modules/incident-sk/incident-sk.js
+++ b/am/modules/incident-sk/incident-sk.js
@@ -80,8 +80,13 @@
 
 function actionButtons(ele) {
   if (ele._state.active) {
+    let assignToOwnerButton = '';
+    if (ele._state.params.owner) {
+      assignToOwnerButton = html`<button @click=${ele._assignToOwner}>Assign to Owner</button>`;
+    }
     return html`<section class=assign>
       <button @click=${ele._take}>Take</button>
+      ${assignToOwnerButton}
       <button @click=${ele._assign}>Assign</button>
     </section>`;
   } else {
@@ -189,6 +194,13 @@
     this.dispatchEvent(new CustomEvent('take', { detail: detail, bubbles: true }));
   }
 
+  _assignToOwner(e) {
+    let detail = {
+      key: this._state.key,
+    };
+    this.dispatchEvent(new CustomEvent('assign-to-owner', { detail: detail, bubbles: true }));
+  }
+
   _assign(e) {
     let detail = {
       key: this._state.key,