Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/elements/issue-list/mr-grid-page/mr-grid-page.js b/static_src/elements/issue-list/mr-grid-page/mr-grid-page.js
new file mode 100644
index 0000000..d96e566
--- /dev/null
+++ b/static_src/elements/issue-list/mr-grid-page/mr-grid-page.js
@@ -0,0 +1,180 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(juliacordero): Handle pRPC errors with a FE page
+
+import {LitElement, html, css} from 'lit-element';
+import {store, connectStore} from 'reducers/base.js';
+import {shouldWaitForDefaultQuery} from 'shared/helpers.js';
+import * as issueV0 from 'reducers/issueV0.js';
+import * as projectV0 from 'reducers/projectV0.js';
+import * as sitewide from 'reducers/sitewide.js';
+import 'elements/framework/links/mr-issue-link/mr-issue-link.js';
+import './mr-grid-controls.js';
+import './mr-grid.js';
+
+/**
+ * <mr-grid-page>
+ *
+ * Grid page view containing mr-grid and mr-grid-controls.
+ * @extends {LitElement}
+ */
+export class MrGridPage extends connectStore(LitElement) {
+ /** @override */
+ render() {
+ const displayedProgress = this.progress || 0.02;
+ const doneLoading = this.progress === 1;
+ const noMatches = this.totalIssues === 0 && doneLoading;
+ return html`
+ <div id="grid-area">
+ <mr-grid-controls
+ .projectName=${this.projectName}
+ .queryParams=${this._queryParams}
+ .issueCount=${this.issues.length}>
+ </mr-grid-controls>
+ ${noMatches ? html`
+ <div class="empty-search">
+ Your search did not generate any results.
+ </div>` : html`
+ <progress
+ title="${Math.round(displayedProgress * 100)}%"
+ value=${displayedProgress}
+ ?hidden=${doneLoading}
+ ></progress>`}
+ <br>
+ <mr-grid
+ .issues=${this.issues}
+ .xField=${this._queryParams.x}
+ .yField=${this._queryParams.y}
+ .cellMode=${this._queryParams.cells ? this._queryParams.cells : 'tiles'}
+ .queryParams=${this._queryParams}
+ .projectName=${this.projectName}
+ ></mr-grid>
+ </div>
+ `;
+ }
+
+ /** @override */
+ static get properties() {
+ return {
+ projectName: {type: String},
+ _queryParams: {type: Object},
+ userDisplayName: {type: String},
+ issues: {type: Array},
+ fields: {type: Array},
+ progress: {type: Number},
+ totalIssues: {type: Number},
+ _presentationConfigLoaded: {type: Boolean},
+ /**
+ * The current search string the user is querying for.
+ * Project default if not specified.
+ */
+ _currentQuery: {type: String},
+ /**
+ * The current canned query the user is searching for.
+ * Project default if not specified.
+ */
+ _currentCan: {type: String},
+ };
+ };
+
+ /** @override */
+ constructor() {
+ super();
+ this.issues = [];
+ this.progress = 0;
+ /** @type {string} */
+ this.projectName;
+ this._queryParams = {};
+ this._presentationConfigLoaded = false;
+ };
+
+ /** @override */
+ updated(changedProperties) {
+ if (changedProperties.has('userDisplayName')) {
+ store.dispatch(issueV0.fetchStarredIssues());
+ }
+ // TODO(zosha): Abort sets of calls to ListIssues when
+ // queryParams.q is changed.
+ if (this._shouldFetchMatchingIssues(changedProperties)) {
+ this._fetchMatchingIssues();
+ }
+ }
+
+ /**
+ * Computes whether to fetch matching issues based on changedProperties
+ * @param {Map} changedProperties
+ * @return {boolean}
+ */
+ _shouldFetchMatchingIssues(changedProperties) {
+ const wait = shouldWaitForDefaultQuery(this._queryParams);
+ if (wait && !this._presentationConfigLoaded) {
+ return false;
+ } else if (wait && this._presentationConfigLoaded &&
+ changedProperties.has('_presentationConfigLoaded')) {
+ return true;
+ } else if (changedProperties.has('projectName') ||
+ changedProperties.has('_currentQuery') ||
+ changedProperties.has('_currentCan')) {
+ return true;
+ }
+ return false;
+ }
+
+ /** @private */
+ _fetchMatchingIssues() {
+ store.dispatch(issueV0.fetchIssueList(this.projectName, {
+ ...this._queryParams,
+ q: this._currentQuery,
+ can: this._currentCan,
+ maxItems: 500, // 500 items * 12 calls = max of 6,000 issues.
+ maxCalls: 12,
+ }));
+ }
+
+ /** @override */
+ stateChanged(state) {
+ this.projectName = projectV0.viewedProjectName(state);
+ this.issues = (issueV0.issueList(state) || []);
+ this.progress = (issueV0.issueListProgress(state) || 0);
+ this.totalIssues = (issueV0.totalIssues(state) || 0);
+ this._queryParams = sitewide.queryParams(state);
+ this._currentQuery = sitewide.currentQuery(state);
+ this._currentCan = sitewide.currentCan(state);
+ this._presentationConfigLoaded =
+ projectV0.viewedPresentationConfigLoaded(state);
+ }
+
+ /** @override */
+ static get styles() {
+ return css `
+ :host {
+ display: block;
+ box-sizing: border-box;
+ width: 100%;
+ padding: 0.5em 8px;
+ }
+ progress {
+ background-color: var(--chops-white);
+ border: 1px solid var(--chops-gray-500);
+ width: 40%;
+ margin-left: 1%;
+ margin-top: 0.5em;
+ visibility: visible;
+ }
+ ::-webkit-progress-bar {
+ background-color: var(--chops-white);
+ }
+ progress::-webkit-progress-value {
+ transition: width 1s;
+ background-color: var(--chops-blue-700);
+ }
+ .empty-search {
+ text-align: center;
+ padding-top: 2em;
+ }
+ `;
+ }
+};
+customElements.define('mr-grid-page', MrGridPage);