Add support for viewing other users' dashboards

The PolyGerrit router already accepts URLs like /dashboard/USER, but we
didn't respect the parameter. This change replaces all occurrences of
"self" that were hard-coded in the dashboard section queries with a
${user} placeholder.

We also eliminate redundant set of search query requests that are
emitted when navigating away from the dashboard view.

Feature: Issue 6982
Change-Id: I7baad12a02e0e9e53b74537215ddbf21c7b2d006
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index 69550b9..da31bc1 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -17,20 +17,22 @@
   const DEFAULT_SECTIONS = [
     {
       name: 'Work in progress',
-      query: 'is:open owner:self is:wip',
+      query: 'is:open owner:${user} is:wip',
+      selfOnly: true,
     },
     {
       name: 'Outgoing reviews',
-      query: 'is:open owner:self -is:wip',
+      query: 'is:open owner:${user} -is:wip',
     },
     {
       name: 'Incoming reviews',
-      query: 'is:open ((reviewer:self -owner:self -is:ignored) OR ' +
-          'assignee:self) -is:wip',
+      query: 'is:open ((reviewer:${user} -owner:${user} -is:ignored) OR ' +
+          'assignee:${user}) -is:wip',
     },
     {
       name: 'Recently closed',
-      query: 'is:closed (owner:self OR reviewer:self OR assignee:self)',
+      query: 'is:closed (owner:${user} OR reviewer:${user} OR ' +
+          'assignee:${user})',
       suffixForDashboard: '-age:4w limit:10',
     },
   ];
@@ -53,11 +55,10 @@
       viewState: Object,
       params: {
         type: Object,
-        observer: '_paramsChanged',
       },
 
       _results: Array,
-      sectionMetadata: {
+      _sectionMetadata: {
         type: Array,
         value() { return DEFAULT_SECTIONS; },
       },
@@ -71,6 +72,10 @@
       },
     },
 
+    observers: [
+      '_userChanged(params.user)',
+    ],
+
     behaviors: [
       Gerrit.RESTClientBehavior,
     ],
@@ -90,31 +95,37 @@
     /**
      * Allows a refresh if menu item is selected again.
      */
-    _paramsChanged() {
+    _userChanged(user) {
+      if (!user) { return; }
       this._loading = true;
-      this._getChanges().then(results => {
-        this._results = results;
-        this._loading = false;
-      }).catch(err => {
-        this._loading = false;
-        console.warn(err.message);
-      });
+      const sections = this._sectionMetadata.filter(
+          section => (user === 'self' || !section.selfOnly));
+      const queries =
+          sections.map(
+              section => this._dashboardQueryForSection(section, user));
+      this.$.restAPI.getChanges(null, queries, null, this.options)
+          .then(results => {
+            this._results = sections.map((section, i) => {
+              return {
+                sectionName: section.name,
+                query: queries[i],
+                results: results[i],
+              };
+            });
+            this._loading = false;
+          }).catch(err => {
+            this._loading = false;
+            console.warn(err.message);
+          });
     },
 
-    _getChanges() {
-      return this.$.restAPI.getChanges(
-          null,
-          this.sectionMetadata.map(
-              section => this._dashboardQueryForSection(section)),
-          null,
-          this.options);
+    _dashboardQueryForSection(section, user) {
+      const query =
+          section.suffixForDashboard ?
+          section.query + ' ' + section.suffixForDashboard :
+          section.query;
+      return query.replace(/\$\{user\}/g, user);
     },
 
-    _dashboardQueryForSection(section) {
-      if (section.suffixForDashboard) {
-        return section.query + ' ' + section.suffixForDashboard;
-      }
-      return section.query;
-    },
   });
 })();