Merge "Replace "RESET VIEW" in results panel by "UNSELECT ALL" in runs panel"
diff --git a/polygerrit-ui/app/api/diff.ts b/polygerrit-ui/app/api/diff.ts
index f6b3aa0..8e1ffef 100644
--- a/polygerrit-ui/app/api/diff.ts
+++ b/polygerrit-ui/app/api/diff.ts
@@ -302,6 +302,15 @@
buttonType: ContextButtonType;
}
+/**
+ * Details to be externally accessed when hovering context
+ * expansion buttons
+ */
+export declare interface DiffContextButtonHoveredDetail {
+ linesToExpand: number;
+ buttonType: ContextButtonType;
+}
+
export declare type ImageDiffAction =
| {type: 'overview-image-clicked'}
| {type: 'overview-frame-dragged'}
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index ea5339e..2086270 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -108,6 +108,8 @@
private readonly restApiService = appContext.restApiService;
+ private reporting = appContext.reportingService;
+
constructor() {
super();
this.addEventListener('next-page', () => this._handleNextPage());
@@ -272,6 +274,9 @@
}
_handleToggleStar(e: CustomEvent<ChangeStarToggleStarDetail>) {
+ if (e.detail.starred) {
+ this.reporting.reportInteraction('change-starred-from-change-list');
+ }
this.restApiService.saveChangeStarred(
e.detail.change._number,
e.detail.starred
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index bde7d77..e93b293 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -372,6 +372,9 @@
e.detail.change._number,
e.detail.starred
);
+ if (e.detail.starred) {
+ this.reporting.reportInteraction('change-starred-from-dashboard');
+ }
// When a change is updated the same change may appear elsewhere in the
// dashboard (but is not the same object), so we must update other
// occurrences of the same change.
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index f05d665..a11b142 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -2527,6 +2527,7 @@
_handleToggleStar(e: CustomEvent<{change: ChangeInfo; starred: boolean}>) {
if (e.detail.starred) {
+ this.reporting.reportInteraction('change-starred-from-change-view');
this.lastStarredTimestamp = Date.now();
} else {
if (
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index e98ab61..a4ac01d 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -165,8 +165,8 @@
tr.collapsed td .summary-cell .actions {
display: none;
}
- tr.collapsed:hover .summary-cell .tags,
- tr.collapsed:hover .summary-cell .label {
+ tr.collapsed:hover .summary-cell .hoverHide.tags,
+ tr.collapsed:hover .summary-cell .hoverHide.label {
display: none;
}
td .summary-cell .tags .tag {
@@ -255,6 +255,7 @@
<div>
<span>${this.result.checkName}</span>
<gr-checks-attempt .run="${this.result}"></gr-checks-attempt>
+ <gr-hovercard-run .run="${this.result}"></gr-hovercard-run>
</div>
</td>
<td class="summaryCol">
@@ -264,7 +265,7 @@
<div class="message" @click="${this.toggleExpanded}">
${this.isExpanded ? '' : this.result.message}
</div>
- <div class="tags">
+ <div class="tags ${this.hasLinksOrActions() ? 'hoverHide' : ''}">
${(this.result.tags ?? []).map(t => this.renderTag(t))}
</div>
${this.renderLabel()} ${this.renderLinks()} ${this.renderActions()}
@@ -294,6 +295,13 @@
`;
}
+ private hasLinksOrActions() {
+ const linkCount = this.result?.links?.length ?? 0;
+ const actionCount = this.result?.actions?.length ?? 0;
+ // The primary link is rendered somewhere else, so it does not count here.
+ return linkCount > 1 || actionCount > 0;
+ }
+
private renderExpanded() {
if (!this.isExpanded) return;
return html`<gr-result-expanded
@@ -323,7 +331,11 @@
renderLabel() {
const label = this.result?.labelName;
if (!label) return;
- return html`<div class="label">${label}</div>`;
+ return html`
+ <div class="label ${this.hasLinksOrActions() ? 'hoverHide' : ''}">
+ ${label}
+ </div>
+ `;
}
renderLinks() {
@@ -455,6 +467,21 @@
SHOW_ALL_THRESHOLDS.set(Category.INFO, 5);
SHOW_ALL_THRESHOLDS.set(Category.SUCCESS, 5);
+const CATEGORY_TOOLTIPS: Map<Category, string> = new Map();
+CATEGORY_TOOLTIPS.set(Category.ERROR, 'Must be fixed and is blocking submit');
+CATEGORY_TOOLTIPS.set(
+ Category.WARNING,
+ 'Should be checked but is not blocking submit'
+);
+CATEGORY_TOOLTIPS.set(
+ Category.INFO,
+ 'Does not have to be checked, for your information only'
+);
+CATEGORY_TOOLTIPS.set(
+ Category.SUCCESS,
+ 'Successful runs without results and individual successful results'
+);
+
@customElement('gr-checks-results')
export class GrChecksResults extends GrLitElement {
@query('#filterInput')
@@ -601,6 +628,9 @@
height: var(--line-height-h3);
margin-right: var(--spacing-s);
}
+ .categoryHeader .statusIconWrapper {
+ display: inline-block;
+ }
.categoryHeader .statusIcon {
position: relative;
top: 2px;
@@ -867,11 +897,16 @@
@click="${() => this.toggleExpanded(category)}"
>
<iron-icon class="expandIcon" icon="${icon}"></iron-icon>
- <iron-icon
- icon="gr-icons:${iconForCategory(category)}"
- class="statusIcon ${catString}"
- ></iron-icon>
- <span class="title">${catString}</span>
+ <div class="statusIconWrapper">
+ <iron-icon
+ icon="gr-icons:${iconForCategory(category)}"
+ class="statusIcon ${catString}"
+ ></iron-icon>
+ <span class="title">${catString}</span>
+ <paper-tooltip offset="5"
+ >${CATEGORY_TOOLTIPS.get(category)}</paper-tooltip
+ >
+ </div>
<span class="count"
>${this.renderCount(all, selected, filtered)}</span
>
diff --git a/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls.ts b/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls.ts
index 41a448e..dec5111 100644
--- a/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls.ts
+++ b/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls.ts
@@ -23,6 +23,8 @@
import '@polymer/paper-item/paper-item';
import '@polymer/paper-listbox/paper-listbox';
import '@polymer/paper-tooltip/paper-tooltip.js';
+import {of, EMPTY, Subject} from 'rxjs';
+import {switchMap, delay, takeUntil} from 'rxjs/operators';
import '../../shared/gr-button/gr-button';
import {pluralize} from '../../../utils/string-util';
@@ -40,12 +42,19 @@
import {
ContextButtonType,
+ DiffContextButtonHoveredDetail,
RenderPreferences,
SyntaxBlock,
} from '../../../api/diff';
import {GrDiffGroup, hideInContextControl} from '../gr-diff/gr-diff-group';
+declare global {
+ interface HTMLElementEventMap {
+ 'diff-context-button-hovered': CustomEvent<DiffContextButtonHoveredDetail>;
+ }
+}
+
const PARTIAL_CONTEXT_AMOUNT = 10;
/**
@@ -88,6 +97,14 @@
@property({type: Boolean}) showBelow = false;
+ private expandButtonsHover = new Subject<{
+ eventType: 'enter' | 'leave';
+ buttonType: ContextButtonType;
+ linesToExpand: number;
+ }>();
+
+ private disconnected$ = new Subject();
+
static styles = css`
:host {
display: flex;
@@ -106,6 +123,26 @@
/* First button needs to claim width to display without text wrapping. */
position: relative;
}
+
+ paper-button {
+ text-transform: none;
+ align-items: center;
+ background-color: var(--background-color);
+ font-family: inherit;
+ margin: var(--margin, 0);
+ min-width: var(--border, 0);
+ color: var(--diff-context-control-color);
+ border: solid var(--border-color);
+ border-width: 1px;
+ border-radius: var(--border-radius);
+ padding: var(--spacing-s) var(--spacing-l);
+ }
+
+ paper-button:hover {
+ /* same as defined in gr-button */
+ background: rgba(0, 0, 0, 0.12);
+ }
+
.centeredButton {
/* Center over divider. */
top: 50%;
@@ -124,74 +161,52 @@
.aboveButton {
/* Display over preceding content / background placeholder. */
transform: translateY(-100%);
+ border-bottom-width: 1px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ padding: var(--spacing-xxs) var(--spacing-l);
}
.belowButton {
top: calc(100% + var(--divider-border));
+ border-top-width: 0;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ padding: var(--spacing-xxs) var(--spacing-l);
}
.breadcrumbTooltip {
white-space: nowrap;
}
`;
- // To pass CSS mixins for @apply to Polymer components, they need to be
- // wrapped in a <custom-style>.
- static customStyles = html`
- <custom-style>
- <style>
- .centeredButton {
- --gr-button: {
- color: var(--diff-context-control-color);
- border-style: solid;
- border-color: var(--border-color);
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px;
+ connectedCallback() {
+ super.connectedCallback();
+ this.setupButtonHoverHandler();
+ }
- border-top-left-radius: var(--border-radius);
- border-top-right-radius: var(--border-radius);
- border-bottom-right-radius: var(--border-radius);
- border-bottom-left-radius: var(--border-radius);
- padding: var(--spacing-s) var(--spacing-l);
- }
- }
- .aboveButton {
- --gr-button: {
- color: var(--diff-context-control-color);
- border-style: solid;
- border-color: var(--border-color);
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 0;
- border-left-width: 1px;
+ disconnectedCallback() {
+ this.disconnected$.next();
+ }
- border-top-left-radius: var(--border-radius);
- border-top-right-radius: var(--border-radius);
- border-bottom-right-radius: 0;
- border-bottom-left-radius: var(--border-radius);
- padding: var(--spacing-xxs) var(--spacing-l);
+ setupButtonHoverHandler() {
+ this.expandButtonsHover
+ .pipe(
+ switchMap(e => {
+ if (e.eventType === 'leave') {
+ // cancel any previous delay
+ // for mouse enter
+ return EMPTY;
}
- }
- .belowButton {
- --gr-button: {
- color: var(--diff-context-control-color);
- border-style: solid;
- border-color: var(--border-color);
- border-top-width: 0;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px;
-
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- border-bottom-right-radius: var(--border-radius);
- border-bottom-left-radius: var(--border-radius);
- padding: var(--spacing-xxs) var(--spacing-l);
- }
- }
- </style>
- </custom-style>
- `;
+ return of(e).pipe(delay(500));
+ }),
+ takeUntil(this.disconnected$)
+ )
+ .subscribe(({buttonType, linesToExpand}) => {
+ fire(this, 'diff-context-button-hovered', {
+ buttonType,
+ linesToExpand,
+ });
+ });
+ }
private numLines() {
const {leftStart, leftEnd} = this.contextRange();
@@ -276,16 +291,24 @@
groups
);
- const button = html` <gr-button
+ const mouseHandler = (eventType: 'enter' | 'leave') => {
+ this.expandButtonsHover.next({
+ eventType,
+ buttonType: type,
+ linesToExpand,
+ });
+ };
+
+ const button = html` <paper-button
class="${classes}"
- link="true"
- no-uppercase="true"
aria-label="${ariaLabel}"
@click="${expandHandler}"
+ @mouseenter="${() => mouseHandler('enter')}"
+ @mouseleave="${() => mouseHandler('leave')}"
>
<span class="showContext">${text}</span>
${tooltip}
- </gr-button>`;
+ </paper-button>`;
return button;
}
@@ -468,7 +491,7 @@
return html`<p>invalid properties</p>`;
}
return html`
- ${GrContextControls.customStyles} ${this.createExpandAllButtonContainer()}
+ ${this.createExpandAllButtonContainer()}
${this.createPartialExpansionButtons()}
${this.createBlockExpansionButtons()}
`;
diff --git a/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls_test.ts b/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls_test.ts
index f59b19d..4e75c82 100644
--- a/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-context-controls/gr-context-controls_test.ts
@@ -60,7 +60,7 @@
await flush();
const buttons = element.shadowRoot!.querySelectorAll(
- 'gr-button.showContext'
+ 'paper-button.showContext'
);
assert.equal(buttons.length, 1);
assert.equal(buttons[0].textContent!.trim(), '+10 common lines');
@@ -73,7 +73,7 @@
await flush();
const buttons = element.shadowRoot!.querySelectorAll(
- 'gr-button.showContext'
+ 'paper-button.showContext'
);
assert.equal(buttons.length, 2);
@@ -92,7 +92,7 @@
await flush();
const buttons = element.shadowRoot!.querySelectorAll(
- 'gr-button.showContext'
+ 'paper-button.showContext'
);
assert.equal(buttons.length, 3);
@@ -112,7 +112,7 @@
await flush();
const buttons = element.shadowRoot!.querySelectorAll(
- 'gr-button.showContext'
+ 'paper-button.showContext'
);
assert.equal(buttons.length, 2);
@@ -138,13 +138,13 @@
await flush();
const fullExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.fullExpansion gr-button'
+ '.fullExpansion paper-button'
);
const partialExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.partialExpansion gr-button'
+ '.partialExpansion paper-button'
);
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(fullExpansionButtons.length, 1);
assert.equal(partialExpansionButtons.length, 1);
@@ -168,13 +168,13 @@
await flush();
const fullExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.fullExpansion gr-button'
+ '.fullExpansion paper-button'
);
const partialExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.partialExpansion gr-button'
+ '.partialExpansion paper-button'
);
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(fullExpansionButtons.length, 1);
assert.equal(partialExpansionButtons.length, 2);
@@ -205,13 +205,13 @@
await flush();
const fullExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.fullExpansion gr-button'
+ '.fullExpansion paper-button'
);
const partialExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.partialExpansion gr-button'
+ '.partialExpansion paper-button'
);
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(fullExpansionButtons.length, 1);
assert.equal(partialExpansionButtons.length, 1);
@@ -246,7 +246,7 @@
await flush();
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(
blockExpansionButtons[0]
@@ -299,7 +299,7 @@
await flush();
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(
blockExpansionButtons[0]
@@ -345,7 +345,7 @@
await flush();
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
assert.equal(
blockExpansionButtons[0]
@@ -364,7 +364,7 @@
await flush();
const blockExpansionButtons = element.shadowRoot!.querySelectorAll(
- '.blockExpansion gr-button'
+ '.blockExpansion paper-button'
);
const tooltipAbove = blockExpansionButtons[0].querySelector(
'paper-tooltip'