Merge "Ensure existing reviewers are removed as part of ReviewInput"
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 318d53c..eb979a1 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -274,6 +274,7 @@
 const SKIP_ACTION_KEYS: string[] = [
   ChangeActions.REVIEWED,
   ChangeActions.UNREVIEWED,
+  ChangeActions.REVERT_SUBMISSION,
 ];
 
 export function assertUIActionInfo(action?: ActionInfo): UIActionInfo {
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-attempt.ts b/polygerrit-ui/app/elements/checks/gr-checks-attempt.ts
new file mode 100644
index 0000000..6dce9bc
--- /dev/null
+++ b/polygerrit-ui/app/elements/checks/gr-checks-attempt.ts
@@ -0,0 +1,83 @@
+/**
+ * @license
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {html} from 'lit-html';
+import {css, customElement, property} from 'lit-element';
+import {GrLitElement} from '../lit/gr-lit-element';
+import {CheckRun} from '../../services/checks/checks-model';
+
+@customElement('gr-checks-attempt')
+class GrChecksAttempt extends GrLitElement {
+  @property()
+  run?: CheckRun;
+
+  static get styles() {
+    return [
+      css`
+        .attempt {
+          display: inline-block;
+          height: var(--line-height-normal);
+          vertical-align: top;
+          font-size: var(--font-size-small);
+          position: relative;
+        }
+        .attempt .box,
+        .attempt .angle {
+          box-sizing: border-box;
+          height: calc(var(--line-height-normal) - 2px);
+          line-height: calc(var(--line-height-normal) - 2px);
+          border-radius: 2px;
+        }
+        .attempt .box {
+          margin-left: 2px;
+          margin-bottom: 2px;
+          border: 1px solid var(--deemphasized-text-color);
+          padding: 0 var(--spacing-s);
+        }
+        .attempt .angle {
+          position: absolute;
+          top: 2px;
+          /* The text in the .angle div just ensures the correct width. */
+          color: transparent;
+          border-left: 1px solid var(--deemphasized-text-color);
+          border-bottom: 1px solid var(--deemphasized-text-color);
+          /* 1px for the border of the .box div. */
+          padding: 0 calc(var(--spacing-s) + 1px);
+        }
+      `,
+    ];
+  }
+
+  render() {
+    if (!this.run) return undefined;
+    if (this.run.isSingleAttempt) return undefined;
+    if (!this.run.attempt) return undefined;
+    const attempt = this.run.attempt;
+
+    return html`
+      <span class="attempt">
+        <div class="box">${attempt}</div>
+        <div class="angle">${attempt}</div>
+      </span>
+    `;
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'gr-checks-attempt': GrChecksAttempt;
+  }
+}
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index c74f6f9..6f35c49 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -27,6 +27,7 @@
   TemplateResult,
 } from 'lit-element';
 import {GrLitElement} from '../lit/gr-lit-element';
+import './gr-checks-attempt';
 import '@polymer/paper-tooltip/paper-tooltip';
 import {
   Action,
@@ -113,16 +114,6 @@
           overflow: hidden;
           text-overflow: ellipsis;
         }
-        .nameCol .attempt {
-          display: inline-block;
-          background-color: var(--tag-gray);
-          border-radius: var(--line-height-normal);
-          height: var(--line-height-normal);
-          width: var(--line-height-normal);
-          text-align: center;
-          vertical-align: top;
-          font-size: var(--font-size-small);
-        }
         .summaryCol {
           /* Forces this column to get the remaining space that is left over by
              the other columns. */
@@ -263,9 +254,7 @@
         <td class="nameCol" @click="${this.toggleExpanded}">
           <div>
             <span>${this.result.checkName}</span>
-            <span class="attempt" ?hidden="${this.result.isSingleAttempt}"
-              >${this.result.attempt}</span
-            >
+            <gr-checks-attempt .run="${this.result}"></gr-checks-attempt>
           </div>
         </td>
         <td class="summaryCol">
@@ -874,7 +863,8 @@
     const filtered = selected.filter(
       result =>
         this.filterRegExp.test(result.checkName) ||
-        this.filterRegExp.test(result.summary)
+        this.filterRegExp.test(result.summary) ||
+        this.filterRegExp.test(result.message ?? '')
     );
     let expanded = this.isSectionExpanded.get(category);
     const expandedByUser = this.isSectionExpandedByUser.get(category) ?? false;
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index 8ff42ee..1d65546 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -26,6 +26,7 @@
   state,
 } from 'lit-element';
 import {GrLitElement} from '../lit/gr-lit-element';
+import './gr-checks-attempt';
 import {Action, Link, RunStatus} from '../../api/checks';
 import {sharedStyles} from '../../styles/shared-styles';
 import {
@@ -85,16 +86,6 @@
         .name {
           font-weight: var(--font-weight-bold);
         }
-        .attempt {
-          display: inline-block;
-          background-color: var(--tag-gray);
-          border-radius: var(--line-height-normal);
-          height: var(--line-height-normal);
-          width: var(--line-height-normal);
-          text-align: center;
-          vertical-align: top;
-          font-size: var(--font-size-small);
-        }
         .chip.error {
           border-left: var(--thick-border) solid var(--error-foreground);
         }
@@ -233,9 +224,7 @@
           <iron-icon class="${icon}" icon="gr-icons:${icon}"></iron-icon>
           ${this.renderAdditionalIcon()}
           <span class="name">${this.run.checkName}</span>
-          <span class="attempt" ?hidden="${this.run.isSingleAttempt}"
-            >${this.run.attempt}</span
-          >
+          <gr-checks-attempt .run="${this.run}"></gr-checks-attempt>
         </div>
         <div class="right">
           ${action