Merge changes Id2d46f55,I820173fa,I2043efb1,Iebaa8387,Ife290c4c, ...

* changes:
  Hide "Assignee" related components when disabled in config
  Add a blurred attribute to account-label
  Add attention icon to account components
  Add reviewers column to dashboard
  Add comments column to dashboard
  Show reviewers next to each other
  Use display name in account label
diff --git a/plugins/download-commands b/plugins/download-commands
index 47b783e..e26ed31 160000
--- a/plugins/download-commands
+++ b/plugins/download-commands
@@ -1 +1 @@
-Subproject commit 47b783ea75036664dd591d2d3f1bcd06b68cdd5e
+Subproject commit e26ed31aaf070ff884e96b9a09d39c20437de6cb
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
index d12b279..0a3da6e 100644
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.js
@@ -29,6 +29,8 @@
           'Status',
           'Owner',
           'Assignee',
+          'Reviewers',
+          'Comments',
           'Repo',
           'Branch',
           'Updated',
@@ -61,6 +63,35 @@
     },
 
     /**
+     * Is the column disabled by a server config or experiment? For example the
+     * assignee feature might be disabled and thus the corresponding column is
+     * also disabled.
+     *
+     * @param {string} column
+     * @param {Object} config
+     * @param {!Array<string>} experiments
+     * @return {boolean}
+     */
+    isColumnEnabled(column, config, experiments) {
+      if (!config || !config.change) return true;
+      if (column === 'Assignee') return !!config.change.enable_assignee;
+      if (column === 'Comments') return experiments.includes('comments-column');
+      if (column === 'Reviewers') return !!config.change.enable_attention_set;
+      return true;
+    },
+
+    /**
+     * @param {!Array<string>} columns
+     * @param {Object} config
+     * @param {!Array<string>} experiments
+     * @return {!Array<string>} enabled columns, see isColumnEnabled().
+     */
+    getEnabledColumns(columns, config, experiments) {
+      return columns.filter(
+          col => this.isColumnEnabled(col, config, experiments));
+    },
+
+    /**
      * The Project column was renamed to Repo, but some users may have
      * preferences that use its old name. If that column is found, rename it
      * before use.
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
index 2889371..8036ff0 100644
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
@@ -65,6 +65,8 @@
       'Status',
       'Owner',
       'Assignee',
+      'Reviewers',
+      'Comments',
       'Repo',
       'Branch',
       'Updated',
@@ -76,6 +78,8 @@
       'Subject',
       'Status',
       'Assignee',
+      'Reviewers',
+      'Comments',
       'Repo',
       'Branch',
       'Size',
diff --git a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.js b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.js
index 2e7f5d4..af3ce64 100644
--- a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.js
+++ b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.js
@@ -29,6 +29,10 @@
       return GrDisplayNameUtils.getUserName(config, account);
     },
 
+    getDisplayName(config, account) {
+      return GrDisplayNameUtils.getDisplayName(config, account);
+    },
+
     getGroupDisplayName(group) {
       return GrDisplayNameUtils.getGroupDisplayName(group);
     },
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index 3605e15..69f2a44 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -26,6 +26,7 @@
 import '../../shared/gr-change-star/gr-change-star.js';
 import '../../shared/gr-change-status/gr-change-status.js';
 import '../../shared/gr-date-formatter/gr-date-formatter.js';
+import '../../shared/gr-icons/gr-icons.js';
 import '../../shared/gr-limited-text/gr-limited-text.js';
 import '../../shared/gr-tooltip-content/gr-tooltip-content.js';
 import '../../../styles/shared-styles.js';
@@ -208,6 +209,11 @@
     }
   }
 
+  _computeComments(unresolved_comment_count) {
+    if (!unresolved_comment_count || unresolved_comment_count < 1) return '';
+    return `${unresolved_comment_count} unresolved`;
+  }
+
   /**
    * TShirt sizing is based on the following paper:
    * http://dirkriehle.com/wp-content/uploads/2008/09/hicss-42-csdistr-final-web.pdf
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
index f76189c..aed0077 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
@@ -52,6 +52,10 @@
         white-space: nowrap;
         width: 100%;
       }
+      .comments,
+      .reviewers {
+        white-space: nowrap;
+      }
       .spacer {
         height: 0;
         overflow: hidden;
@@ -101,6 +105,9 @@
       .cell.label {
         font-weight: var(--font-weight-normal);
       }
+      .lastChildHidden:last-of-type {
+        display: none;
+      }
       @media only screen and (max-width: 50em) {
         :host {
           display: flex;
@@ -150,6 +157,18 @@
         <span class="placeholder">--</span>
       </template>
     </td>
+    <td class="cell reviewers" hidden\$="[[isColumnHidden('Reviewers', visibleChangeTableColumns)]]">
+      <div>
+        <template is="dom-repeat" items="[[change.reviewers.REVIEWER]]" as="reviewer">
+          <gr-account-link hide-avatar="" hide-status="" account="[[reviewer]]"></gr-account-link><!--
+       --><span class="lastChildHidden">, </span>
+        </template>
+      </div>
+    </td>
+    <td class="cell comments" hidden\$="[[isColumnHidden('Comments', visibleChangeTableColumns)]]">
+      <iron-icon hidden\$="[[!change.unresolved_comment_count]]" icon="gr-icons:comment"></iron-icon>
+      <span>[[_computeComments(change.unresolved_comment_count)]]</span>
+    </td>
     <td class="cell repo" hidden\$="[[isColumnHidden('Repo', visibleChangeTableColumns)]]">
       <a class="fullRepo" href\$="[[_computeRepoUrl(change)]]">
         [[_computeRepoDisplay(change)]]
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
index d26fc17..b1479b6 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
@@ -124,6 +124,8 @@
       'Status',
       'Owner',
       'Assignee',
+      'Reviewers',
+      'Comments',
       'Repo',
       'Branch',
       'Updated',
@@ -148,6 +150,8 @@
       'Status',
       'Owner',
       'Assignee',
+      'Reviewers',
+      'Comments',
       'Branch',
       'Updated',
       'Size',
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index ba7b366..a72faea 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -24,6 +24,7 @@
 import '../../../styles/gr-change-list-styles.js';
 import '../../core/gr-navigation/gr-navigation.js';
 import '../../shared/gr-cursor-manager/gr-cursor-manager.js';
+import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
 import '../gr-change-list-item/gr-change-list-item.js';
 import '../../../styles/shared-styles.js';
 import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
@@ -34,6 +35,7 @@
 import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
 import {PolymerElement} from '@polymer/polymer/polymer-element.js';
 import {htmlTemplate} from './gr-change-list_html.js';
+import {flags} from '../../../services/flags';
 import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
 
 const NUMBER_FIXED_COLUMNS = 3;
@@ -131,13 +133,14 @@
       changeTableColumns: Array,
       visibleChangeTableColumns: Array,
       preferences: Object,
+      _config: Object,
     };
   }
 
   static get observers() {
     return [
       '_sectionsChanged(sections.*)',
-      '_computePreferences(account, preferences)',
+      '_computePreferences(account, preferences, _config)',
     ];
   }
 
@@ -165,6 +168,9 @@
   ready() {
     super.ready();
     this._ensureAttribute('tabindex', 0);
+    this.$.restAPI.getConfig().then(config => {
+      this._config = config;
+    });
   }
 
   /** @override */
@@ -194,28 +200,26 @@
     return column.toLowerCase();
   }
 
-  _computePreferences(account, preferences) {
+  _computePreferences(account, preferences, config) {
     // Polymer 2: check for undefined
-    if ([account, preferences].some(arg => arg === undefined)) {
+    if ([account, preferences, config].some(arg => arg === undefined)) {
       return;
     }
 
     this.changeTableColumns = this.columnNames;
+    this.showNumber = false;
+    this.visibleChangeTableColumns = this.getEnabledColumns(this.columnNames,
+        config, flags.enabledExperiments);
 
     if (account) {
       this.showNumber = !!(preferences &&
           preferences.legacycid_in_change_table);
       if (preferences.change_table &&
           preferences.change_table.length > 0) {
-        this.visibleChangeTableColumns =
-          this.getVisibleColumns(preferences.change_table);
-      } else {
-        this.visibleChangeTableColumns = this.columnNames;
+        const prefColumns = this.getVisibleColumns(preferences.change_table);
+        this.visibleChangeTableColumns = this.getEnabledColumns(prefColumns,
+            config, flags.enabledExperiments);
       }
-    } else {
-      // Not logged in.
-      this.showNumber = false;
-      this.visibleChangeTableColumns = this.columnNames;
     }
   }
 
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
index ac37827..3309fb2 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_html.js
@@ -103,4 +103,5 @@
       </template>
     </table>
     <gr-cursor-manager id="cursor" index="{{selectedIndex}}" scroll-behavior="keep-visible" focus-on-move=""></gr-cursor-manager>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
 `;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
index d077f6b..3bc7032 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
@@ -69,6 +69,7 @@
       element = fixture('basic');
       element.account = null;
       element.preferences = null;
+      element._config = {};
     });
 
     test('show number disabled', () => {
@@ -85,6 +86,7 @@
         change_table: [],
       };
       element.account = {_account_id: 1001};
+      element._config = {};
       flushAsynchronousOperations();
     });
 
@@ -102,6 +104,7 @@
         change_table: [],
       };
       element.account = {_account_id: 1001};
+      element._config = {};
       flushAsynchronousOperations();
     });
 
@@ -334,6 +337,7 @@
         time_format: 'HHMM_12',
         change_table: [],
       };
+      element._config = {};
       flushAsynchronousOperations();
     });
 
@@ -367,12 +371,15 @@
           'Status',
           'Owner',
           'Assignee',
+          'Reviewers',
+          'Comments',
           'Repo',
           'Branch',
           'Updated',
           'Size',
         ],
       };
+      element._config = {};
       flushAsynchronousOperations();
     });
 
@@ -402,11 +409,14 @@
           'Status',
           'Owner',
           'Assignee',
+          'Reviewers',
+          'Comments',
           'Branch',
           'Updated',
           'Size',
         ],
       };
+      element._config = {};
       flushAsynchronousOperations();
     });
 
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 2c023752..fabcdad 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
@@ -105,14 +105,6 @@
     ];
   }
 
-  get options() {
-    return this.listChangesOptionsToHex(
-        this.ListChangesOption.LABELS,
-        this.ListChangesOption.DETAILED_ACCOUNTS,
-        this.ListChangesOption.REVIEWED
-    );
-  }
-
   /** @override */
   attached() {
     super.attached();
@@ -240,7 +232,7 @@
       queries.push('owner:self limit:1');
     }
 
-    return this.$.restAPI.getChanges(null, queries, null, this.options)
+    return this.$.restAPI.getChanges(null, queries)
         .then(changes => {
           if (checkForNewUser) {
             // Last set of results is not meant for dashboard display.
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
index 8a0cfa0..f94c896 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
@@ -206,8 +206,7 @@
       };
       return paramsChangedPromise.then(() => {
         assert.isTrue(
-            getChangesStub.calledWith(
-                null, ['1', '2', 'owner:self limit:1'], null, element.options));
+            getChangesStub.calledWith(null, ['1', '2', 'owner:self limit:1']));
       });
     });
 
@@ -221,9 +220,7 @@
         user: 'user',
       };
       return paramsChangedPromise.then(() => {
-        assert.isTrue(
-            getChangesStub.calledWith(
-                null, ['1'], null, element.options));
+        assert.isTrue(getChangesStub.calledWith(null, ['1']));
       });
     });
   });
@@ -239,8 +236,7 @@
     return paramsChangedPromise.then(() => {
       assert.isTrue(getChangesStub.calledOnce);
       assert.deepEqual(
-          getChangesStub.firstCall.args,
-          [null, ['1', '2 suffix'], null, element.options]);
+          getChangesStub.firstCall.args, [null, ['1', '2 suffix']]);
     });
   });
 
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
index 160b912..47e6a9a 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
@@ -46,7 +46,6 @@
   let element;
 
   const sectionSelectors = [
-    'section.assignee',
     'section.strategy',
     'section.topic',
   ];
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
index 2e9cdf9..28262be 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
@@ -188,7 +188,9 @@
   }
 
   _assigneeChanged(assigneeRecord) {
-    if (!this.change) { return; }
+    if (!this.change || !this._isAssigneeEnabled(this.serverConfig)) {
+      return;
+    }
     const assignee = assigneeRecord.base;
     if (assignee.length) {
       const acct = assignee[0];
@@ -225,6 +227,11 @@
     return weblinks.length ? weblinks : null;
   }
 
+  _isAssigneeEnabled(serverConfig) {
+    return serverConfig && serverConfig.change
+        && !!serverConfig.change.enable_assignee;
+  }
+
   _computeStrategy(change) {
     return SubmitTypeLabel[change.submit_type];
   }
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
index 786a118..059aa71 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
@@ -97,6 +97,9 @@
       .topic gr-linked-chip {
         --linked-chip-text-color: var(--link-color);
       }
+      gr-reviewer-list {
+        max-width: 200px;
+      }
     </style>
     <gr-external-style id="externalStyle" name="change-metadata">
       <section>
@@ -135,23 +138,25 @@
           <gr-account-link account="[[_getNonOwnerRole(change, _CHANGE_ROLE.COMMITTER)]]"></gr-account-link>
         </span>
       </section>
-      <section class="assignee">
-        <span class="title">Assignee</span>
-        <span class="value">
-          <gr-account-list id="assigneeValue" placeholder="Set assignee..." max-count="1" skip-suggest-on-empty="" accounts="{{_assignee}}" readonly="[[_computeAssigneeReadOnly(_mutable, change)]]" suggestions-provider="[[_getReviewerSuggestionsProvider(change)]]">
-          </gr-account-list>
-        </span>
-      </section>
+      <template is="dom-if" if="[[_isAssigneeEnabled(serverConfig)]]">
+        <section class="assignee">
+          <span class="title">Assignee</span>
+          <span class="value">
+            <gr-account-list id="assigneeValue" placeholder="Set assignee..." max-count="1" skip-suggest-on-empty="" accounts="{{_assignee}}" readonly="[[_computeAssigneeReadOnly(_mutable, change)]]" suggestions-provider="[[_getReviewerSuggestionsProvider(change)]]">
+            </gr-account-list>
+          </span>
+        </section>
+      </template>
       <section>
         <span class="title">Reviewers</span>
         <span class="value">
-          <gr-reviewer-list change="{{change}}" mutable="[[_mutable]]" reviewers-only="" max-reviewers-displayed="3"></gr-reviewer-list>
+          <gr-reviewer-list change="{{change}}" mutable="[[_mutable]]" reviewers-only="" server-config="[[serverConfig]]"></gr-reviewer-list>
         </span>
       </section>
       <section>
         <span class="title">CC</span>
         <span class="value">
-          <gr-reviewer-list change="{{change}}" mutable="[[_mutable]]" ccs-only="" max-reviewers-displayed="3"></gr-reviewer-list>
+          <gr-reviewer-list change="{{change}}" mutable="[[_mutable]]" ccs-only="" server-config="[[serverConfig]]"></gr-reviewer-list>
         </span>
       </section>
       <template is="dom-if" if="[[_computeShowRepoBranchTogether(change.project, change.branch)]]">
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
index 773e6ec..ce3770f 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
@@ -634,6 +634,11 @@
       setup(() => {
         deleteStub = sandbox.stub(element.$.restAPI, 'deleteAssignee');
         setStub = sandbox.stub(element.$.restAPI, 'setAssignee');
+        element.serverConfig = {
+          change: {
+            enable_assignee: true,
+          },
+        };
       });
 
       test('changing change recomputes _assignee', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
index 129cb01..0fcf81d 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
@@ -44,6 +44,7 @@
   static get properties() {
     return {
       change: Object,
+      serverConfig: Object,
       disabled: {
         type: Boolean,
         value: false,
@@ -61,7 +62,6 @@
         type: Boolean,
         value: false,
       },
-      maxReviewersDisplayed: Number,
 
       _displayedReviewers: {
         type: Array,
@@ -92,7 +92,7 @@
 
   static get observers() {
     return [
-      '_reviewersChanged(change.reviewers.*, change.owner)',
+      '_reviewersChanged(change.reviewers.*, change.owner, serverConfig)',
     ];
   }
 
@@ -179,9 +179,9 @@
     return maxScores.join(', ');
   }
 
-  _reviewersChanged(changeRecord, owner) {
+  _reviewersChanged(changeRecord, owner, serverConfig) {
     // Polymer 2: check for undefined
-    if ([changeRecord, owner].some(arg => arg === undefined)) {
+    if ([changeRecord, owner, serverConfig].some(arg => arg === undefined)) {
       return;
     }
 
@@ -201,12 +201,13 @@
     this._reviewers = result
         .filter(reviewer => reviewer._account_id != owner._account_id);
 
+    const isFirstNameConfigured = serverConfig.accounts
+        && serverConfig.accounts.default_display_name === 'FIRST_NAME';
+    const maxReviewers = isFirstNameConfigured ? 6 : 3;
     // If there is one or two more than the max reviewers, don't show the
     // 'show more' button, because it takes up just as much space.
-    if (this.maxReviewersDisplayed &&
-        this._reviewers.length > this.maxReviewersDisplayed + 2) {
-      this._displayedReviewers =
-        this._reviewers.slice(0, this.maxReviewersDisplayed);
+    if (this._reviewers.length > maxReviewers + 2) {
+      this._displayedReviewers = this._reviewers.slice(0, maxReviewers);
     } else {
       this._displayedReviewers = this._reviewers;
     }
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
index c5df61d..300e38a 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
@@ -27,26 +27,27 @@
       }
       .container {
         display: block;
-        /* This is a bit of a hack. We tried to use margin-top with
-           :not(:first-child) before, but :first-child does not understand
-           whether a child is visible or not. So adding a margin for every
-           child and then a negative one at the top does the trick. */
-        margin-top: calc(0px - var(--spacing-s));
-      }
-      .container > * {
-        margin-top: var(--spacing-s);
       }
       gr-button {
         --gr-button: {
           padding: 0px 0px;
         }
       }
+      gr-account-chip {
+        display: inline-block;
+      }
     </style>
     <div class="container">
-      <template is="dom-repeat" items="[[_displayedReviewers]]" as="reviewer">
-        <gr-account-chip class="reviewer" account="[[reviewer]]" on-remove="_handleRemove" voteable-text="[[_computeVoteableText(reviewer, change)]]" removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]">
-        </gr-account-chip>
-      </template>
+      <div>
+        <template is="dom-repeat" items="[[_displayedReviewers]]" as="reviewer">
+          <gr-account-chip class="reviewer"
+                           account="[[reviewer]]"
+                           on-remove="_handleRemove"
+                           voteable-text="[[_computeVoteableText(reviewer, change)]]"
+                           removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]">
+          </gr-account-chip>
+        </template>
+      </div>
       <gr-button class="hiddenReviewers" link="" hidden\$="[[!_hiddenReviewerCount]]" on-click="_handleViewAll">and [[_hiddenReviewerCount]] more</gr-button>
       <div class="controlsContainer" hidden\$="[[!mutable]]">
         <gr-button link="" id="addReviewer" class="addReviewer" on-click="_handleAddTap">[[_addLabel]]</gr-button>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
index d97bf6b..9e51d16 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
@@ -40,6 +40,7 @@
 
   setup(() => {
     element = fixture('basic');
+    element.serverConfig = {};
     sandbox = sinon.sandbox.create();
     stub('gr-rest-api-interface', {
       getConfig() { return Promise.resolve({}); },
@@ -198,9 +199,32 @@
         {value: {ccsOnly: true}});
   });
 
-  test('no show all reviewers button with 6 reviewers', () => {
+  test('dont show all reviewers button with 4 reviewers', () => {
     const reviewers = [];
-    element.maxReviewersDisplayed = 5;
+    element.maxReviewersDisplayed = 3;
+    for (let i = 0; i < 4; i++) {
+      reviewers.push(
+          {email: i+'reviewer@google.com', name: 'reviewer-' + i});
+    }
+    element.ccsOnly = true;
+
+    element.change = {
+      owner: {
+        _account_id: 1,
+      },
+      reviewers: {
+        CC: reviewers,
+      },
+    };
+    assert.equal(element._hiddenReviewerCount, 0);
+    assert.equal(element._displayedReviewers.length, 4);
+    assert.equal(element._reviewers.length, 4);
+    assert.isTrue(element.shadowRoot
+        .querySelector('.hiddenReviewers').hidden);
+  });
+
+  test('show all reviewers button with 6 reviewers', () => {
+    const reviewers = [];
     for (let i = 0; i < 6; i++) {
       reviewers.push(
           {email: i+'reviewer@google.com', name: 'reviewer-' + i});
@@ -215,63 +239,15 @@
         CC: reviewers,
       },
     };
-    assert.equal(element._hiddenReviewerCount, 0);
-    assert.equal(element._displayedReviewers.length, 6);
-    assert.equal(element._reviewers.length, 6);
-    assert.isTrue(element.shadowRoot
-        .querySelector('.hiddenReviewers').hidden);
-  });
-
-  test('show all reviewers button with 8 reviewers', () => {
-    const reviewers = [];
-    element.maxReviewersDisplayed = 5;
-    for (let i = 0; i < 8; i++) {
-      reviewers.push(
-          {email: i+'reviewer@google.com', name: 'reviewer-' + i});
-    }
-    element.ccsOnly = true;
-
-    element.change = {
-      owner: {
-        _account_id: 1,
-      },
-      reviewers: {
-        CC: reviewers,
-      },
-    };
     assert.equal(element._hiddenReviewerCount, 3);
-    assert.equal(element._displayedReviewers.length, 5);
-    assert.equal(element._reviewers.length, 8);
+    assert.equal(element._displayedReviewers.length, 3);
+    assert.equal(element._reviewers.length, 6);
     assert.isFalse(element.shadowRoot
         .querySelector('.hiddenReviewers').hidden);
   });
 
-  test('no maxReviewersDisplayed', () => {
-    const reviewers = [];
-    for (let i = 0; i < 7; i++) {
-      reviewers.push(
-          {email: i+'reviewer@google.com', name: 'reviewer-' + i});
-    }
-    element.ccsOnly = true;
-
-    element.change = {
-      owner: {
-        _account_id: 1,
-      },
-      reviewers: {
-        CC: reviewers,
-      },
-    };
-    assert.equal(element._hiddenReviewerCount, 0);
-    assert.equal(element._displayedReviewers.length, 7);
-    assert.equal(element._reviewers.length, 7);
-    assert.isTrue(element.shadowRoot
-        .querySelector('.hiddenReviewers').hidden);
-  });
-
   test('show all reviewers button', () => {
     const reviewers = [];
-    element.maxReviewersDisplayed = 5;
     for (let i = 0; i < 100; i++) {
       reviewers.push(
           {email: i+'reviewer@google.com', name: 'reviewer-' + i});
@@ -286,8 +262,8 @@
         CC: reviewers,
       },
     };
-    assert.equal(element._hiddenReviewerCount, 95);
-    assert.equal(element._displayedReviewers.length, 5);
+    assert.equal(element._hiddenReviewerCount, 97);
+    assert.equal(element._displayedReviewers.length, 3);
     assert.equal(element._reviewers.length, 100);
     assert.isFalse(element.shadowRoot
         .querySelector('.hiddenReviewers').hidden);
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
index 287ac3b..919be86 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
@@ -47,6 +47,8 @@
       'Status',
       'Owner',
       'Assignee',
+      'Reviewers',
+      'Comments',
       'Repo',
       'Branch',
       'Updated',
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
index c4f9119..274f270 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
@@ -61,6 +61,10 @@
         type: Boolean,
         value: false,
       },
+      showAttention: {
+        type: Boolean,
+        value: false,
+      },
       showAvatar: {
         type: Boolean,
         reflectToAttribute: true,
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
index 14bbd57..cfa0243 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
@@ -81,7 +81,9 @@
       }
     </style>
     <div class\$="container [[_getBackgroundClass(transparentBackground)]]">
-      <gr-account-link account="[[account]]" voteable-text="[[voteableText]]">
+      <gr-account-link account="[[account]]"
+                       show-attention="[[showAttention]]"
+                       voteable-text="[[voteableText]]">
       </gr-account-link>
       <gr-button id="remove" link="" hidden\$="[[!removable]]" hidden="" tabindex="-1" aria-label="Remove" class\$="remove [[_getBackgroundClass(transparentBackground)]]" on-click="_handleRemoveTap">
         <iron-icon icon="gr-icons:close"></iron-icon>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
index d279563..ef835f0 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
@@ -50,10 +50,18 @@
        */
       account: Object,
       voteableText: String,
+      showAttention: {
+        type: Boolean,
+        value: false,
+      },
       hideAvatar: {
         type: Boolean,
         value: false,
       },
+      hideStatus: {
+        type: Boolean,
+        value: false,
+      },
       _serverConfig: {
         type: Object,
         value: null,
@@ -69,7 +77,7 @@
   }
 
   _computeName(account, config) {
-    return this.getUserName(config, account);
+    return this.getDisplayName(config, account);
   }
 }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
index a7d01ae..f642af3 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
@@ -20,10 +20,23 @@
     <style include="shared-styles">
       :host {
         display: inline;
+        position: relative;
       }
       :host::after {
         content: var(--account-label-suffix);
       }
+      :host(:not([blurred])) .overlay {
+        display: none;
+      }
+      .overlay {
+        position: absolute;
+        pointer-events: none;
+        height: var(--line-height-normal);
+        right: 0;
+        left: 0;
+        background-color: var(--background-color-primary);
+        opacity: 0.5;
+      }
       gr-avatar {
         height: var(--line-height-normal);
         width: var(--line-height-normal);
@@ -35,7 +48,10 @@
       .text:hover {
         @apply --gr-account-label-text-hover-style;
       }
-      iron-icon {
+      iron-icon.attention {
+        vertical-align: top;
+      }
+      iron-icon.status {
         width: 14px;
         height: 14px;
         vertical-align: top;
@@ -43,16 +59,25 @@
         top: 2px;
       }
     </style>
+    <div class="overlay"></div>
     <span>
-      <gr-hovercard-account account="[[account]]" voteable-text="[[voteableText]]"></gr-hovercard-account>
-      <template is="dom-if" if="[[!hideAvatar]]">
-        <gr-avatar account="[[account]]" image-size="32"></gr-avatar>
+      <gr-hovercard-account attention="[[showAttention]]"
+                            account="[[account]]"
+                            voteable-text="[[voteableText]]">
+      </gr-hovercard-account>
+      <template is="dom-if" if="[[showAttention]]">
+        <iron-icon class="attention" icon="gr-icons:attention"></iron-icon><!--
+   --></template><!--
+   --><template is="dom-if" if="[[!hideAvatar]]"><!--
+     --><gr-avatar account="[[account]]" image-size="32"></gr-avatar>
       </template>
       <span class="text">
         <span class="name">
           [[_computeName(account, _serverConfig)]]</span>
-        <template is="dom-if" if="[[account.status]]">
-          <iron-icon icon="gr-icons:calendar"></iron-icon>
+        <template is="dom-if" if="[[!hideStatus]]">
+          <template is="dom-if" if="[[account.status]]">
+            <iron-icon class="status" icon="gr-icons:calendar"></iron-icon>
+          </template>
         </template>
       </span>
     </span>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
index a5738d1..ca37659 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
@@ -42,6 +42,18 @@
     return {
       voteableText: String,
       account: Object,
+      showAttention: {
+        type: Boolean,
+        value: false,
+      },
+      hideAvatar: {
+        type: Boolean,
+        value: false,
+      },
+      hideStatus: {
+        type: Boolean,
+        value: false,
+      },
     };
   }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
index 4f1ea44..5eb9ad5 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
@@ -33,7 +33,12 @@
     </style>
     <span>
       <a href\$="[[_computeOwnerLink(account)]]" tabindex="-1">
-        <gr-account-label account="[[account]]" voteable-text="[[voteableText]]"></gr-account-label>
+        <gr-account-label show-attention="[[showAttention]]" 
+                          hide-avatar="[[hideAvatar]]"
+                          hide-status="[[hideStatus]]"
+                          account="[[account]]"
+                          voteable-text="[[voteableText]]">
+        </gr-account-label>
       </a>
     </span>
 `;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 914a1ad..a4308c4 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -950,49 +950,50 @@
    *     changeInfos.
    */
   getChanges(opt_changesPerPage, opt_query, opt_offset, opt_options) {
-    const options = opt_options || this.listChangesOptionsToHex(
-        this.ListChangesOption.LABELS,
-        this.ListChangesOption.DETAILED_ACCOUNTS
-    );
-    // Issue 4524: respect legacy token with max sortkey.
-    if (opt_offset === 'n,z') {
-      opt_offset = 0;
-    }
-    const params = {
-      O: options,
-      S: opt_offset || 0,
-    };
-    if (opt_changesPerPage) { params.n = opt_changesPerPage; }
-    if (opt_query && opt_query.length > 0) {
-      params.q = opt_query;
-    }
-    const iterateOverChanges = arr => {
-      for (const change of (arr || [])) {
-        this._maybeInsertInLookup(change);
-      }
-    };
-    const req = {
-      url: '/changes/',
-      params,
-      reportUrlAsIs: true,
-    };
-    return this._restApiHelper.fetchJSON(req).then(response => {
-      // Response may be an array of changes OR an array of arrays of
-      // changes.
-      if (opt_query instanceof Array) {
-        // Normalize the response to look like a multi-query response
-        // when there is only one query.
-        if (opt_query.length === 1) {
-          response = [response];
-        }
-        for (const arr of response) {
-          iterateOverChanges(arr);
-        }
-      } else {
-        iterateOverChanges(response);
-      }
-      return response;
-    });
+    return this.getConfig(false)
+        .then(config => {
+          const options = opt_options || this._getChangesOptionsHex(config);
+          // Issue 4524: respect legacy token with max sortkey.
+          if (opt_offset === 'n,z') {
+            opt_offset = 0;
+          }
+          const params = {
+            O: options,
+            S: opt_offset || 0,
+          };
+          if (opt_changesPerPage) { params.n = opt_changesPerPage; }
+          if (opt_query && opt_query.length > 0) {
+            params.q = opt_query;
+          }
+          return {
+            url: '/changes/',
+            params,
+            reportUrlAsIs: true,
+          };
+        })
+        .then(req => this._restApiHelper.fetchJSON(req))
+        .then(response => {
+          const iterateOverChanges = arr => {
+            for (const change of (arr || [])) {
+              this._maybeInsertInLookup(change);
+            }
+          };
+          // Response may be an array of changes OR an array of arrays of
+          // changes.
+          if (opt_query instanceof Array) {
+            // Normalize the response to look like a multi-query response
+            // when there is only one query.
+            if (opt_query.length === 1) {
+              response = [response];
+            }
+            for (const arr of response) {
+              iterateOverChanges(arr);
+            }
+          } else {
+            iterateOverChanges(response);
+          }
+          return response;
+        });
   }
 
   /**
@@ -1034,6 +1035,20 @@
     });
   }
 
+  _getChangesOptionsHex(config) {
+    const options = [
+      this.ListChangesOption.LABELS,
+      this.ListChangesOption.DETAILED_ACCOUNTS,
+    ];
+    if (config && config.change && config.change.enable_attention_set) {
+      options.push(this.ListChangesOption.DETAILED_LABELS);
+    } else {
+      options.push(this.ListChangesOption.REVIEWED);
+    }
+
+    return this.listChangesOptionsToHex(...options);
+  }
+
   _getChangeOptionsHex(config) {
     if (window.DEFAULT_DETAIL_HEXES && window.DEFAULT_DETAIL_HEXES.changePage
         && !(config.receive && config.receive.enable_signed_push)) {
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index 814a474..5fd289e 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -332,10 +332,11 @@
     });
   });
 
-  test('legacy n,z key in change url is replaced', () => {
+  test('legacy n,z key in change url is replaced', async () => {
+    sandbox.stub(element, 'getConfig', async () => { return {}; });
     const stub = sandbox.stub(element._restApiHelper, 'fetchJSON')
         .returns(Promise.resolve([]));
-    element.getChanges(1, null, 'n,z');
+    await element.getChanges(1, null, 'n,z');
     assert.equal(stub.lastCall.args[0].params.S, 0);
   });
 
diff --git a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils.js b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils.js
index cefd254..20de3fb6 100644
--- a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils.js
+++ b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils.js
@@ -39,6 +39,24 @@
       return ANONYMOUS_NAME;
     }
 
+    static getDisplayName(config, account) {
+      if (account && account.display_name) {
+        return account.display_name;
+      }
+      if (!account || !account.name || !config || !config.accounts) {
+        return this.getUserName(config, account);
+      }
+      if (config.accounts.default_display_name === 'USERNAME'
+          && account.username) {
+        return account.username;
+      }
+      if (config.accounts.default_display_name === 'FIRST_NAME') {
+        return account.name.trim().split(' ')[0];
+      }
+      // Treat every other value as FULL_NAME.
+      return account.name;
+    }
+
     static getAccountDisplayName(config, account) {
       const reviewerName = this.getUserName(config, account);
       const reviewerEmail = this._accountEmail(account.email);
diff --git a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
index 262d53c..0ed5ec7 100644
--- a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
+++ b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
@@ -34,7 +34,77 @@
     },
   };
 
-  test('getUserName name only', () => {
+  test('getDisplayName name only', () => {
+    const account = {
+      name: 'test-name',
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'test-name');
+  });
+
+  test('getDisplayName prefer displayName', () => {
+    const account = {
+      name: 'test-name',
+      display_name: 'better-name',
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'better-name');
+  });
+
+  test('getDisplayName prefer username default', () => {
+    const account = {
+      name: 'test-name',
+      username: 'user-name',
+    };
+    const config = {
+      accounts: {
+        default_display_name: 'USERNAME',
+      },
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'user-name');
+  });
+
+  test('getDisplayName prefer first name default', () => {
+    const account = {
+      name: 'firstname lastname',
+    };
+    const config = {
+      accounts: {
+        default_display_name: 'FIRST_NAME',
+      },
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'firstname');
+  });
+
+  test('getDisplayName ignore leading whitespace for first name', () => {
+    const account = {
+      name: '   firstname lastname',
+    };
+    const config = {
+      accounts: {
+        default_display_name: 'FIRST_NAME',
+      },
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'firstname');
+  });
+
+  test('getDisplayName full name default', () => {
+    const account = {
+      name: 'firstname lastname',
+    };
+    const config = {
+      accounts: {
+        default_display_name: 'FULL_NAME',
+      },
+    };
+    assert.equal(GrDisplayNameUtils.getDisplayName(config, account),
+        'firstname lastname');
+  });
+
+  test('getDisplayName name only', () => {
     const account = {
       name: 'test-name',
     };
diff --git a/polygerrit-ui/app/styles/gr-change-list-styles.js b/polygerrit-ui/app/styles/gr-change-list-styles.js
index 148943b..4f4d7e3 100644
--- a/polygerrit-ui/app/styles/gr-change-list-styles.js
+++ b/polygerrit-ui/app/styles/gr-change-list-styles.js
@@ -89,6 +89,9 @@
       .star {
         width: 30px;
       }
+      .reviewers div {
+        overflow: hidden;
+      }
       .label, .endpoint {
         border-left: 1px solid var(--border-color);
       }
@@ -118,7 +121,8 @@
       @media only screen and (max-width: 100em) {
         .assignee,
         .branch,
-        .owner {
+        .owner,
+        .reviewers {
           max-width: 10rem;
         }
       }
diff --git a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.js b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.js
index 51cf6d3..aabdde5 100644
--- a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.js
+++ b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.js
@@ -34,6 +34,7 @@
       .title,
       .value {
         display: table-cell;
+        vertical-align: top;
       }
 
       .title {
@@ -43,10 +44,6 @@
         padding-right: var(--metadata-horizontal-padding);
         word-break: break-word;
       }
-
-      .value {
-        padding-right: var(--metadata-horizontal-padding);
-      }
     </style>
   </template>
 </dom-module>`;