Improve the UX of the attention set section in the reply dialog
Before: https://imgur.com/a/WZBcxWO After: https://imgur.com/a/V9GSC71 - Add icons that link to documentation and bug template. - Add a bug icon. - List the names of users that will be added to the attention set. - Make the selection chips nicer. - Blue border and background. Change border-radius. - Remove 'blurred' concept. - Move the "click chips ..." hint to the bottom. - Hide CC row, if there are no CCs. - Move overflow/linebreak/width rules from account-link to -label. - Fixes layout problems with many reviewer chips. Change-Id: Id4147eeddae2f6a137517ff8ebabb9eff34ca031
This commit is contained in:
		@@ -39,6 +39,7 @@ import {SpecialFilePath} from '../../../constants/constants.js';
 | 
			
		||||
import {ExperimentIds} from '../../../services/flags.js';
 | 
			
		||||
import {fetchChangeUpdates} from '../../../utils/patch-set-util.js';
 | 
			
		||||
import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
 | 
			
		||||
import {getDisplayName} from '../../../utils/display-name-util.js';
 | 
			
		||||
 | 
			
		||||
const STORAGE_DEBOUNCE_INTERVAL_MS = 400;
 | 
			
		||||
 | 
			
		||||
@@ -773,6 +774,10 @@ class GrReplyDialog extends KeyboardShortcutMixin(GestureEventListeners(
 | 
			
		||||
 | 
			
		||||
  _handleAttentionModify() {
 | 
			
		||||
    this._attentionModified = true;
 | 
			
		||||
    // If the attention-detail section is expanded without dispatching this
 | 
			
		||||
    // event, then the dialog may expand beyond the screen's bottom border.
 | 
			
		||||
    this.dispatchEvent(new CustomEvent(
 | 
			
		||||
        'iron-resize', {composed: true, bubbles: true}));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _showAttentionSummary(config, attentionModified) {
 | 
			
		||||
@@ -813,6 +818,8 @@ class GrReplyDialog extends KeyboardShortcutMixin(GestureEventListeners(
 | 
			
		||||
            .map(id => parseInt(id)));
 | 
			
		||||
    const newAttention = new Set(this._currentAttentionSet);
 | 
			
		||||
    if (this._isOwner(user, change)) {
 | 
			
		||||
      // TODO(brohlfs): Do not add all reviewers, just the ones that are replied
 | 
			
		||||
      // to.
 | 
			
		||||
      reviewers.forEach(r => newAttention.add(r._account_id));
 | 
			
		||||
    } else {
 | 
			
		||||
      if (change.owner) {
 | 
			
		||||
@@ -823,6 +830,34 @@ class GrReplyDialog extends KeyboardShortcutMixin(GestureEventListeners(
 | 
			
		||||
    this._newAttentionSet = newAttention;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _isNewAttentionEmpty(config, currentAttentionSet, newAttentionSet) {
 | 
			
		||||
    return this._computeNewAttentionNames(
 | 
			
		||||
        config, currentAttentionSet, newAttentionSet).length === 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _computeNewAttentionNames(config, currentAttentionSet, newAttentionSet) {
 | 
			
		||||
    if ([currentAttentionSet, newAttentionSet].includes(undefined)) return '';
 | 
			
		||||
    const addedNames = [...newAttentionSet]
 | 
			
		||||
        .filter(id => !currentAttentionSet.has(id))
 | 
			
		||||
        .map(id => this._findAccountById(id))
 | 
			
		||||
        .filter(account => !!account)
 | 
			
		||||
        .map(account => getDisplayName(config, account))
 | 
			
		||||
        .sort();
 | 
			
		||||
    return addedNames.join(', ');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _findAccountById(accountId) {
 | 
			
		||||
    let allAccounts = [];
 | 
			
		||||
    if (this.change && this.change.owner) allAccounts.push(this.change.owner);
 | 
			
		||||
    if (this._reviewers) allAccounts = [...allAccounts, ...this._reviewers];
 | 
			
		||||
    if (this._ccs) allAccounts = [...allAccounts, ...this._ccs];
 | 
			
		||||
    return allAccounts.find(r => r._account_id === accountId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _computeShowAttentionCcs(ccs) {
 | 
			
		||||
    return !!ccs && ccs.length > 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _accountOrGroupKey(entry) {
 | 
			
		||||
    return entry.id || entry._account_id;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -150,15 +150,27 @@ export const htmlTemplate = html`
 | 
			
		||||
    .attention .edit-attention-button iron-icon {
 | 
			
		||||
      color: inherit;
 | 
			
		||||
    }
 | 
			
		||||
    .attention a,
 | 
			
		||||
    .attention-detail a {
 | 
			
		||||
      text-decoration: none;
 | 
			
		||||
    }
 | 
			
		||||
    .attentionSummary {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail .peopleList {
 | 
			
		||||
      margin-top: var(--spacing-s);
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail .peopleList .accountList {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-wrap: wrap;
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail gr-account-label {
 | 
			
		||||
      background-color: var(--background-color-tertiary);
 | 
			
		||||
      padding: 0 var(--spacing-m) 0 var(--spacing-s);
 | 
			
		||||
      display: inline-block;
 | 
			
		||||
      padding: var(--spacing-xs) var(--spacing-m);
 | 
			
		||||
      margin-right: var(--spacing-m);
 | 
			
		||||
      user-select: none;
 | 
			
		||||
      --label-border-radius: 10px;
 | 
			
		||||
      --label-border-radius: 4px;
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail gr-account-label:focus {
 | 
			
		||||
      outline: none;
 | 
			
		||||
@@ -168,7 +180,14 @@ export const htmlTemplate = html`
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail .attentionDetailsTitle {
 | 
			
		||||
      margin-bottom: var(--spacing-s);
 | 
			
		||||
      display: flex;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      margin-bottom: var(--spacing-m);
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail .attentionDetailsFooter {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      margin-top: var(--spacing-s);
 | 
			
		||||
    }
 | 
			
		||||
    .attention-detail .selectUsers {
 | 
			
		||||
      color: var(--deemphasized-text-color);
 | 
			
		||||
@@ -289,14 +308,27 @@ export const htmlTemplate = html`
 | 
			
		||||
      hidden$="[[!_showAttentionSummary(serverConfig, _attentionModified)]]"
 | 
			
		||||
      class="attention"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="attentionSummary">
 | 
			
		||||
        <div>
 | 
			
		||||
        <iron-icon class="attention-icon" icon="gr-icons:attention"></iron-icon>
 | 
			
		||||
        <span hidden$="[[_isOwner(_account, change)]]"
 | 
			
		||||
          >Bring to owner's attention.</span
 | 
			
		||||
          <iron-icon
 | 
			
		||||
            class="attention-icon"
 | 
			
		||||
            icon="gr-icons:attention"
 | 
			
		||||
          ></iron-icon>
 | 
			
		||||
          <template
 | 
			
		||||
            is="dom-if"
 | 
			
		||||
            if="[[_isNewAttentionEmpty(serverConfig, _currentAttentionSet, _newAttentionSet)]]"
 | 
			
		||||
          >
 | 
			
		||||
        <span hidden$="[[!_isOwner(_account, change)]]"
 | 
			
		||||
          >Bring to all reviewer's attention.</span
 | 
			
		||||
            <span>Do not add anyone to the attention set.</span>
 | 
			
		||||
          </template>
 | 
			
		||||
          <template
 | 
			
		||||
            is="dom-if"
 | 
			
		||||
            if="[[!_isNewAttentionEmpty(serverConfig, _currentAttentionSet, _newAttentionSet)]]"
 | 
			
		||||
          >
 | 
			
		||||
            <span
 | 
			
		||||
              >Bring to attention of [[_computeNewAttentionNames(serverConfig,
 | 
			
		||||
              _currentAttentionSet, _newAttentionSet)]].</span
 | 
			
		||||
            >
 | 
			
		||||
          </template>
 | 
			
		||||
          <gr-button
 | 
			
		||||
            class="edit-attention-button"
 | 
			
		||||
            on-click="_handleAttentionModify"
 | 
			
		||||
@@ -309,57 +341,111 @@ export const htmlTemplate = html`
 | 
			
		||||
            role="button"
 | 
			
		||||
            tabindex="0"
 | 
			
		||||
          >
 | 
			
		||||
          <iron-icon icon="gr-icons:edit" class=""></iron-icon>
 | 
			
		||||
            <iron-icon icon="gr-icons:edit"></iron-icon>
 | 
			
		||||
            Modify
 | 
			
		||||
          </gr-button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <a
 | 
			
		||||
            href="https://gerrit-review.googlesource.com/Documentation/user-attention-set.html"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
          >
 | 
			
		||||
            <iron-icon
 | 
			
		||||
              icon="gr-icons:info"
 | 
			
		||||
              title="read documentation"
 | 
			
		||||
            ></iron-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
          <a
 | 
			
		||||
            href="https://bugs.chromium.org/p/gerrit/issues/entry?template=Attention+Set"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
          >
 | 
			
		||||
            <iron-icon icon="gr-icons:bug" title="report a problem"></iron-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </section>
 | 
			
		||||
    <section
 | 
			
		||||
      hidden$="[[!_showAttentionDetails(serverConfig, _attentionModified)]]"
 | 
			
		||||
      class="attention-detail"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="attentionDetailsTitle">
 | 
			
		||||
        <iron-icon class="attention-icon" icon="gr-icons:attention"></iron-icon>
 | 
			
		||||
        <span>Bring to attention of ...</span>
 | 
			
		||||
        <span class="selectUsers">(click chips to select users)</span>
 | 
			
		||||
        <div>
 | 
			
		||||
          <span>Change attention set to:</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div></div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <a
 | 
			
		||||
            href="https://gerrit-review.googlesource.com/Documentation/user-attention-set.html"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
          >
 | 
			
		||||
            <iron-icon
 | 
			
		||||
              icon="gr-icons:info"
 | 
			
		||||
              title="read documentation"
 | 
			
		||||
            ></iron-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
          <a
 | 
			
		||||
            href="https://bugs.chromium.org/p/gerrit/issues/entry?template=Attention+Set"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
          >
 | 
			
		||||
            <iron-icon icon="gr-icons:bug" title="report a problem"></iron-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="peopleList">
 | 
			
		||||
        <div class="peopleListLabel">Owner</div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <gr-account-label
 | 
			
		||||
            account="[[_owner]]"
 | 
			
		||||
            force-attention="[[_computeHasNewAttention(_owner, _newAttentionSet)]]"
 | 
			
		||||
          blurred="[[!_computeHasNewAttention(_owner, _newAttentionSet)]]"
 | 
			
		||||
            selected$="[[_computeHasNewAttention(_owner, _newAttentionSet)]]"
 | 
			
		||||
            deselected$="[[!_computeHasNewAttention(_owner, _newAttentionSet)]]"
 | 
			
		||||
            hide-hovercard=""
 | 
			
		||||
            on-click="_handleAttentionClick"
 | 
			
		||||
          >
 | 
			
		||||
          </gr-account-label>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="peopleList">
 | 
			
		||||
        <div class="peopleListLabel">Reviewers</div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <template is="dom-repeat" items="[[_reviewers]]" as="account">
 | 
			
		||||
            <gr-account-label
 | 
			
		||||
              account="[[account]]"
 | 
			
		||||
              force-attention="[[_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
            blurred="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
              selected$="[[_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
              deselected$="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
              hide-hovercard=""
 | 
			
		||||
              on-click="_handleAttentionClick"
 | 
			
		||||
            >
 | 
			
		||||
            </gr-account-label>
 | 
			
		||||
          </template>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <template is="dom-if" if="[[_computeShowAttentionCcs(_ccs)]]">
 | 
			
		||||
        <div class="peopleList">
 | 
			
		||||
          <div class="peopleListLabel">CC</div>
 | 
			
		||||
          <div>
 | 
			
		||||
            <template is="dom-repeat" items="[[_ccs]]" as="account">
 | 
			
		||||
              <gr-account-label
 | 
			
		||||
                account="[[account]]"
 | 
			
		||||
                force-attention="[[_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
            blurred="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
                selected$="[[_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
                deselected$="[[!_computeHasNewAttention(account, _newAttentionSet)]]"
 | 
			
		||||
                hide-hovercard=""
 | 
			
		||||
                on-click="_handleAttentionClick"
 | 
			
		||||
              >
 | 
			
		||||
              </gr-account-label>
 | 
			
		||||
            </template>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <div class="attentionDetailsFooter">
 | 
			
		||||
        <div></div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <span class="selectUsers">(click chips to add and remove users)</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div></div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </section>
 | 
			
		||||
    <section
 | 
			
		||||
      class="draftsContainer"
 | 
			
		||||
 
 | 
			
		||||
@@ -74,6 +74,7 @@ suite('gr-reply-dialog tests', () => {
 | 
			
		||||
      _number: changeNum,
 | 
			
		||||
      owner: {
 | 
			
		||||
        _account_id: 999,
 | 
			
		||||
        display_name: 'Kermit',
 | 
			
		||||
      },
 | 
			
		||||
      labels: {
 | 
			
		||||
        'Verified': {
 | 
			
		||||
@@ -226,6 +227,25 @@ suite('gr-reply-dialog tests', () => {
 | 
			
		||||
    checkComputeAttention(1, [22, 33], 1, [22, 33], [22, 33]);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('computeNewAttentionNames', () => {
 | 
			
		||||
    element._reviewers = [
 | 
			
		||||
      {_account_id: 123, display_name: 'Ernie'},
 | 
			
		||||
      {_account_id: 321, display_name: 'Bert'},
 | 
			
		||||
    ];
 | 
			
		||||
    element._ccs = [
 | 
			
		||||
      {_account_id: 7, display_name: 'Elmo'},
 | 
			
		||||
    ];
 | 
			
		||||
    const compute = (currentAtt, newAtt) => element._computeNewAttentionNames(
 | 
			
		||||
        undefined, new Set(currentAtt), new Set(newAtt));
 | 
			
		||||
 | 
			
		||||
    assert.equal(compute([], []), '');
 | 
			
		||||
    assert.equal(compute([], [999]), 'Kermit');
 | 
			
		||||
    assert.equal(compute([999], []), '');
 | 
			
		||||
    assert.equal(compute([999], [999]), '');
 | 
			
		||||
    assert.equal(compute([123, 321], [999]), 'Kermit');
 | 
			
		||||
    assert.equal(compute([999], [7, 123, 999]), 'Elmo, Ernie');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('toggle resolved checkbox', done => {
 | 
			
		||||
    // Async tick is needed because iron-selector content is distributed and
 | 
			
		||||
    // distributed content requires an observer to be set up.
 | 
			
		||||
 
 | 
			
		||||
@@ -66,11 +66,6 @@ class GrAccountLabel extends GestureEventListeners(
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
        value: false,
 | 
			
		||||
      },
 | 
			
		||||
      blurred: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
        value: false,
 | 
			
		||||
        reflectToAttribute: true,
 | 
			
		||||
      },
 | 
			
		||||
      hideHovercard: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
        value: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -19,25 +19,26 @@ import {html} from '@polymer/polymer/lib/utils/html-tag';
 | 
			
		||||
export const htmlTemplate = html`
 | 
			
		||||
  <style include="shared-styles">
 | 
			
		||||
    :host {
 | 
			
		||||
      display: inline;
 | 
			
		||||
      position: relative;
 | 
			
		||||
      border-radius: var(--label-border-radius);
 | 
			
		||||
      /* Setting this really high, so all the following rules don't change
 | 
			
		||||
           anything, only if --account-max-length is actually set to something
 | 
			
		||||
           smaller like 20ch. */
 | 
			
		||||
      max-width: var(--account-max-length, 500px);
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
    }
 | 
			
		||||
    :host::after {
 | 
			
		||||
      content: var(--account-label-suffix);
 | 
			
		||||
    }
 | 
			
		||||
    :host(:not([blurred])) .overlay {
 | 
			
		||||
      display: none;
 | 
			
		||||
    :host([deselected]) {
 | 
			
		||||
      background-color: white;
 | 
			
		||||
      border: 1px solid #ddd;
 | 
			
		||||
    }
 | 
			
		||||
    .overlay {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
      height: var(--line-height-normal);
 | 
			
		||||
      right: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      background-color: var(--background-color-primary);
 | 
			
		||||
      opacity: 0.5;
 | 
			
		||||
      border-radius: var(--label-border-radius);
 | 
			
		||||
    :host([selected]) {
 | 
			
		||||
      background-color: #e8f0fe;
 | 
			
		||||
      border: 1px solid #174ea6;
 | 
			
		||||
    }
 | 
			
		||||
    gr-avatar {
 | 
			
		||||
      height: var(--line-height-normal);
 | 
			
		||||
@@ -65,7 +66,6 @@ export const htmlTemplate = html`
 | 
			
		||||
      top: 2px;
 | 
			
		||||
    }
 | 
			
		||||
  </style>
 | 
			
		||||
  <div class="overlay"></div>
 | 
			
		||||
  <span>
 | 
			
		||||
    <template is="dom-if" if="[[!hideHovercard]]">
 | 
			
		||||
      <gr-hovercard-account
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,7 @@ export const htmlTemplate = html`
 | 
			
		||||
  <style include="shared-styles">
 | 
			
		||||
    :host {
 | 
			
		||||
      display: inline-block;
 | 
			
		||||
      /* Setting this really high, so all the following rules don't change
 | 
			
		||||
           anything, only if --account-max-length is actually set to something
 | 
			
		||||
           smaller like 20ch. */
 | 
			
		||||
      max-width: var(--account-max-length, 500px);
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
      vertical-align: top;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
    }
 | 
			
		||||
    a {
 | 
			
		||||
      color: var(--primary-text-color);
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,8 @@ $_documentContainer.innerHTML = `<iron-iconset-svg name="gr-icons" size="24">
 | 
			
		||||
      <g id="ready"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g>
 | 
			
		||||
      <!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons -->
 | 
			
		||||
      <g id="schedule"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g>
 | 
			
		||||
      <!-- This SVG is a copy from material.io https://material.io/icons/#bug_report-->
 | 
			
		||||
      <g id="bug"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></g>
 | 
			
		||||
    </defs>
 | 
			
		||||
  </svg>
 | 
			
		||||
</iron-iconset-svg>`;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user