Merge "Handle checks summary chip clicks by filtering the tab accordingly"
diff --git a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
index 4af51a9..beec0a4 100644
--- a/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-summary/gr-change-summary.ts
@@ -56,7 +56,7 @@
 import {notUndefined} from '../../../types/types';
 import {uniqueDefinedAvatar} from '../../../utils/account-util';
 import {PrimaryTab} from '../../../constants/constants';
-import {CommentTabState} from '../../../types/events';
+import {ChecksTabState, CommentTabState} from '../../../types/events';
 
 export enum SummaryChipStyles {
   INFO = 'info',
@@ -229,19 +229,13 @@
     const chipClass = `checksChip font-small ${this.icon}`;
     const grIcon = `gr-icons:${this.icon}`;
     return html`
-      <div class="${chipClass}" role="button" @click="${this.handleClick}">
+      <div class="${chipClass}" role="button">
         <iron-icon icon="${grIcon}"></iron-icon>
         <div class="text">${this.text}</div>
         <slot></slot>
       </div>
     `;
   }
-
-  private handleClick(e: MouseEvent) {
-    e.stopPropagation();
-    e.preventDefault();
-    fireShowPrimaryTab(this, PrimaryTab.CHECKS);
-  }
 }
 
 /** What is the maximum number of expanded checks chips? */
@@ -325,7 +319,7 @@
     const icon = iconForCategory(category);
     const runs = this.runs.filter(run => hasResultsOf(run, category));
     const count = (run: CheckRun) => getResultsOf(run, category);
-    return this.renderChecksChip(icon, runs, count);
+    return this.renderChecksChip(icon, runs, category, count);
   }
 
   renderChecksChipForStatus(
@@ -334,12 +328,13 @@
   ) {
     const icon = iconForStatus(status);
     const runs = this.runs.filter(filter);
-    return this.renderChecksChip(icon, runs, () => []);
+    return this.renderChecksChip(icon, runs, status, () => []);
   }
 
   renderChecksChip(
     icon: string,
     runs: CheckRun[],
+    statusOrCategory: RunStatus | Category,
     resultFilter: (run: CheckRun) => CheckResult[]
   ) {
     if (runs.length === 0) {
@@ -359,9 +354,10 @@
           class="${icon}"
           .icon="${icon}"
           .text="${text}"
+          @click="${() => this.onChipClick({checkName: run.checkName})}"
           >${links.map(
             link => html`
-              <a href="${link.url}" target="_blank" @click="${this.onClick}"
+              <a href="${link.url}" target="_blank" @click="${this.onLinkClick}"
                 ><iron-icon class="launch" icon="gr-icons:launch"></iron-icon
               ></a>
             `
@@ -380,11 +376,18 @@
       class="${icon}"
       .icon="${icon}"
       .text="${sum}"
+      @click="${() => this.onChipClick({statusOrCategory})}"
     ></gr-checks-chip>`;
   }
 
-  private onClick(e: MouseEvent) {
-    // Prevents handleClick() from reacting to <a> link clicks.
+  private onChipClick(state: ChecksTabState) {
+    fireShowPrimaryTab(this, PrimaryTab.CHECKS, true, {
+      checksTab: state,
+    });
+  }
+
+  private onLinkClick(e: MouseEvent) {
+    // Prevents onChipClick() from reacting to <a> link clicks.
     e.stopPropagation();
   }
 
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index f3fb860..08c04e8 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -690,7 +690,10 @@
         is="dom-if"
         if="[[_isTabActive(_constants.PrimaryTab.CHECKS, _activeTabs)]]"
       >
-        <gr-checks-tab id="checksTab"></gr-checks-tab>
+        <gr-checks-tab
+          id="checksTab"
+          tab-state="[[_tabState.checksTab]]"
+        ></gr-checks-tab>
       </template>
       <template
         is="dom-if"
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index b9fd48f..1b49f8a 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -41,7 +41,7 @@
   fakeRun4,
   updateStateSetResults,
 } from '../../services/checks/checks-model';
-import {assertIsDefined, toggleSetMembership} from '../../utils/common-util';
+import {assertIsDefined} from '../../utils/common-util';
 import {whenVisible} from '../../utils/dom-util';
 
 export interface RunSelectedEventDetail {
@@ -239,7 +239,8 @@
   @property()
   runs: CheckRun[] = [];
 
-  private selectedRuns = new Set<string>();
+  @property()
+  selectedRuns: string[] = [];
 
   private isSectionExpanded = new Map<RunStatus, boolean>();
 
@@ -390,20 +391,14 @@
   }
 
   renderRun(run: CheckRun) {
-    const selected = this.selectedRuns.has(run.checkName);
-    const deselected = !selected && this.selectedRuns.size > 0;
+    const selected = this.selectedRuns.includes(run.checkName);
+    const deselected = !selected && this.selectedRuns.length > 0;
     return html`<gr-checks-run
       .run="${run}"
       .selected="${selected}"
       .deselected="${deselected}"
-      @run-selected="${this.handleRunSelected}"
     ></gr-checks-run>`;
   }
-
-  handleRunSelected(e: RunSelectedEvent) {
-    toggleSetMembership(this.selectedRuns, e.detail.checkName);
-    this.requestUpdate();
-  }
 }
 
 declare global {
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
index 0ce81ed..ad4f2ae 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-tab.ts
@@ -15,7 +15,13 @@
  * limitations under the License.
  */
 import {html} from 'lit-html';
-import {css, customElement, property} from 'lit-element';
+import {
+  css,
+  customElement,
+  internalProperty,
+  property,
+  PropertyValues,
+} from 'lit-element';
 import {GrLitElement} from '../lit/gr-lit-element';
 import {Action, CheckResult, CheckRun} from '../../api/checks';
 import {
@@ -32,11 +38,9 @@
   ActionTriggeredEvent,
   fireActionTriggered,
 } from '../../services/checks/checks-util';
-import {
-  checkRequiredProperty,
-  toggleSetMembership,
-} from '../../utils/common-util';
+import {checkRequiredProperty} from '../../utils/common-util';
 import {RunSelectedEvent} from './gr-checks-runs';
+import {ChecksTabState} from '../../types/events';
 
 /**
  * The "Checks" tab on the Gerrit change page. Gets its data from plugins that
@@ -52,12 +56,16 @@
   actions: Action[] = [];
 
   @property()
+  tabState?: ChecksTabState;
+
+  @property()
   currentPatchNum: PatchSetNum | undefined = undefined;
 
   @property()
   changeNum: NumericChangeId | undefined = undefined;
 
-  private selectedRuns = new Set<string>();
+  @internalProperty()
+  selectedRuns: string[] = [];
 
   constructor() {
     super();
@@ -107,7 +115,9 @@
   render() {
     const ps = `Patchset ${this.currentPatchNum} (Latest)`;
     const filteredRuns = this.runs.filter(
-      r => this.selectedRuns.size === 0 || this.selectedRuns.has(r.checkName)
+      r =>
+        this.selectedRuns.length === 0 ||
+        this.selectedRuns.includes(r.checkName)
     );
     return html`
       <div class="header">
@@ -130,6 +140,7 @@
         <gr-checks-runs
           class="runs"
           .runs="${this.runs}"
+          .selectedRuns="${this.selectedRuns}"
           @run-selected="${this.handleRunSelected}"
         ></gr-checks-runs>
         <gr-checks-results
@@ -140,6 +151,16 @@
     `;
   }
 
+  protected updated(changedProperties: PropertyValues) {
+    super.updated(changedProperties);
+    if (changedProperties.has('tabState')) {
+      const check = this.tabState?.checkName;
+      if (check) {
+        this.selectedRuns = [check];
+      }
+    }
+  }
+
   renderAction(action: Action) {
     return html`<gr-checks-top-level-action
       .action="${action}"
@@ -163,8 +184,15 @@
   }
 
   handleRunSelected(e: RunSelectedEvent) {
-    toggleSetMembership(this.selectedRuns, e.detail.checkName);
-    this.requestUpdate();
+    this.toggleSelected(e.detail.checkName);
+  }
+
+  toggleSelected(checkName: string) {
+    if (this.selectedRuns.includes(checkName)) {
+      this.selectedRuns = this.selectedRuns.filter(r => r !== checkName);
+    } else {
+      this.selectedRuns = [...this.selectedRuns, checkName];
+    }
   }
 }
 
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index 6b05fad..5965453 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -19,6 +19,7 @@
 import {UIComment} from '../utils/comment-util';
 import {FetchRequest} from './types';
 import {MovedLinkClickedEventDetail} from '../api/diff';
+import {Category, RunStatus} from '../api/checks';
 
 export interface TitleChangeEventDetail {
   title: string;
@@ -152,6 +153,7 @@
 
 export interface TabState {
   commentTab?: CommentTabState;
+  checksTab?: ChecksTabState;
 }
 
 export enum CommentTabState {
@@ -160,6 +162,11 @@
   SHOW_ALL = 'show all',
 }
 
+export interface ChecksTabState {
+  statusOrCategory?: RunStatus | Category;
+  checkName?: string;
+}
+
 export type SwitchTabEvent = CustomEvent<SwitchTabEventDetail>;
 
 declare global {