Merge "Expose the TokenHighlightLayer to embedders"
diff --git a/polygerrit-ui/app/api/checks.ts b/polygerrit-ui/app/api/checks.ts
index fdb785c..658a97e 100644
--- a/polygerrit-ui/app/api/checks.ts
+++ b/polygerrit-ui/app/api/checks.ts
@@ -82,6 +82,13 @@
* Will be shown as buttons in the header of the Checks tab.
*/
actions?: Action[];
+
+ /**
+ * Top-level links that are not associated with a specific run or result.
+ * Will be shown as icons in the header of the Checks tab.
+ */
+ links?: Link[];
+
runs?: CheckRun[];
}
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.ts b/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.ts
index ba089f6..98d21f9 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.ts
@@ -25,9 +25,6 @@
color: var(--deemphasized-text-color);
content: ' *';
}
- .inputUpdateBtn {
- margin-top: var(--spacing-s);
- }
</style>
<style include="gr-form-styles">
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
index 69f2954..3d55097 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
@@ -140,7 +140,7 @@
change?: ParsedChangeInfo;
@property({type: Object})
- revertSubmittedChange?: ChangeInfo;
+ revertedChange?: ChangeInfo;
@property({type: Object, notify: true})
labels?: LabelNameToInfoMap;
@@ -584,9 +584,11 @@
_getRevertSectionTitle(
_change?: ParsedChangeInfo,
- revertSubmittedChange?: ChangeInfo
+ revertedChange?: ChangeInfo
) {
- return revertSubmittedChange ? 'Revert Submitted As' : 'Revert Created As';
+ return revertedChange?.status === ChangeStatus.MERGED
+ ? 'Revert Submitted As'
+ : 'Revert Created As';
}
_showRevertCreatedAs(change?: ParsedChangeInfo) {
@@ -594,18 +596,12 @@
return getRevertCreatedChangeIds(change.messages).length > 0;
}
- _computeRevertCommit(
- change?: ParsedChangeInfo,
- revertSubmittedChange?: ChangeInfo
- ) {
- if (
- revertSubmittedChange?.current_revision &&
- revertSubmittedChange?.revisions
- ) {
+ _computeRevertCommit(change?: ParsedChangeInfo, revertedChange?: ChangeInfo) {
+ if (revertedChange?.current_revision && revertedChange?.revisions) {
return {
commit: this._computeMergedCommitInfo(
- revertSubmittedChange.current_revision,
- revertSubmittedChange.revisions
+ revertedChange.current_revision,
+ revertedChange.revisions
),
};
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
index 50bb5ac..9f0c780 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
@@ -356,12 +356,12 @@
class$="[[_computeDisplayState(_showAllSections, change, _SECTION.REVERT_CREATED_AS)]]"
>
<span class="title"
- >[[_getRevertSectionTitle(change, revertSubmittedChange)]]</span
+ >[[_getRevertSectionTitle(change, revertedChange)]]</span
>
<span class="value">
<gr-commit-info
change="[[change]]"
- commit-info="[[_computeRevertCommit(change, revertSubmittedChange)]]"
+ commit-info="[[_computeRevertCommit(change, revertedChange)]]"
server-config="[[serverConfig]]"
></gr-commit-info>
</span>
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 2db74dbb..f56209b 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
@@ -515,7 +515,7 @@
_tabState?: TabState;
@property({type: Object})
- revertSubmittedChange?: ChangeInfo;
+ revertedChange?: ChangeInfo;
restApiService = appContext.restApiService;
@@ -1864,14 +1864,15 @@
change => change?.status !== ChangeStatus.ABANDONED
);
if (!changes.length) return;
- const change = changes.find(
+ const submittedRevert = changes.find(
change => change?.status === ChangeStatus.MERGED
);
if (!this._changeStatuses) return;
- if (change) {
- this.revertSubmittedChange = change;
+ if (submittedRevert) {
+ this.revertedChange = submittedRevert;
this.push('_changeStatuses', ChangeStates.REVERT_SUBMITTED);
} else {
+ if (changes[0]) this.revertedChange = changes[0];
this.push('_changeStatuses', ChangeStates.REVERT_CREATED);
}
});
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index ac43c59..132833f 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -113,8 +113,7 @@
--collapsed-max-height: 300px;
}
.changeStatuses,
- .commitActions,
- .statusText {
+ .commitActions {
align-items: center;
display: flex;
}
@@ -324,7 +323,7 @@
<template is="dom-repeat" items="[[_changeStatuses]]" as="status">
<gr-change-status
change="[[_change]]"
- revert-submitted-change="[[revertSubmittedChange]]"
+ reverted-change="[[revertedChange]]"
max-width="100"
status="[[status]]"
></gr-change-status>
@@ -386,7 +385,7 @@
<gr-change-metadata
id="metadata"
change="{{_change}}"
- revert-submitted-change="[[revertSubmittedChange]]"
+ reverted-change="[[revertedChange]]"
account="[[_account]]"
revision="[[_selectedRevision]]"
commit-info="[[_commitInfo]]"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
index 8ebb029..878caea 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
@@ -21,9 +21,6 @@
.prefsButton {
float: right;
}
- .collapseToggleButton {
- text-decoration: none;
- }
.patchInfoOldPatchSet.patchInfo-header {
background-color: var(--emphasis-color);
}
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
index 64179f7..da91095 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
@@ -44,10 +44,6 @@
border-top: 1px solid var(--border-color);
margin-top: var(--spacing-xl);
}
- .resolved-comments-message {
- color: var(--link-color);
- cursor: pointer;
- }
.show-resolved-comments {
box-shadow: none;
padding-left: var(--spacing-m);
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index 03d50cc..57bed1c 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -24,6 +24,7 @@
property,
PropertyValues,
query,
+ TemplateResult,
} from 'lit-element';
import {GrLitElement} from '../lit/gr-lit-element';
import '@polymer/paper-tooltip/paper-tooltip';
@@ -42,6 +43,7 @@
someProvidersAreLoading$,
RunResult,
CheckRun,
+ allLinks$,
} from '../../services/checks/checks-model';
import {
allResults,
@@ -457,6 +459,12 @@
}
}
+const SHOW_ALL_THRESHOLDS: Map<Category | 'SUCCESS', number> = new Map();
+SHOW_ALL_THRESHOLDS.set(Category.ERROR, 20);
+SHOW_ALL_THRESHOLDS.set(Category.WARNING, 20);
+SHOW_ALL_THRESHOLDS.set(Category.INFO, 5);
+SHOW_ALL_THRESHOLDS.set('SUCCESS', 5);
+
@customElement('gr-checks-results')
export class GrChecksResults extends GrLitElement {
@query('#filterInput')
@@ -480,6 +488,9 @@
actions: Action[] = [];
@property()
+ links: Link[] = [];
+
+ @property()
tabState?: ChecksTabState;
@property()
@@ -498,6 +509,10 @@
number | undefined
>();
+ /** Maintains the state of which result sections should show all results. */
+ @internalProperty()
+ isShowAll: Map<Category | 'SUCCESS', boolean> = new Map();
+
/**
* This is the current state of whether a section is expanded or not. As long
* as isSectionExpandedByUser is false this will be computed by a default rule
@@ -517,6 +532,7 @@
constructor() {
super();
this.subscribe('actions', allActions$);
+ this.subscribe('links', allLinks$);
this.subscribe('checksPatchsetNumber', checksPatchsetNumber$);
this.subscribe('latestPatchsetNumber', latestPatchNum$);
this.subscribe('someProvidersAreLoading', someProvidersAreLoading$);
@@ -555,6 +571,10 @@
display: flex;
align-items: center;
}
+ .headerBottomRow .links iron-icon {
+ color: var(--link-color);
+ margin-right: var(--spacing-l);
+ }
#moreActions iron-icon {
color: var(--link-color);
}
@@ -645,6 +665,12 @@
font-weight: var(--font-weight-bold);
padding: var(--spacing-s);
}
+ gr-button.showAll {
+ margin: var(--spacing-m);
+ }
+ tr {
+ border-top: 1px solid var(--border-color);
+ }
`,
];
}
@@ -697,7 +723,7 @@
</div>
<div class="headerBottomRow">
<div class="left">${this.renderFilter()}</div>
- <div class="right">${this.renderActions()}</div>
+ <div class="right">${this.renderLinks()}${this.renderActions()}</div>
</div>
</div>
<div class="body">
@@ -708,6 +734,24 @@
`;
}
+ private renderLinks() {
+ const links = (this.links ?? []).slice(0, 4);
+ if (links.length === 0) return;
+ return html`<div class="links">${links.map(this.renderLink)}</div>`;
+ }
+
+ private renderLink(link: Link) {
+ const tooltipText = link.tooltip ?? tooltipForLink(link.icon);
+ return html`<a href="${link.url}" target="_blank"
+ ><iron-icon
+ aria-label="${tooltipText}"
+ class="link"
+ icon="gr-icons:${iconForLink(link.icon)}"
+ ></iron-icon
+ ><paper-tooltip offset="5">${tooltipText}</paper-tooltip></a
+ >`;
+ }
+
private renderActions() {
const overflowItems = this.actions.slice(2).map(action => {
return {...action, id: action.name};
@@ -843,6 +887,16 @@
}
const expandedClass = expanded ? 'expanded' : 'collapsed';
const icon = expanded ? 'gr-icons:expand-less' : 'gr-icons:expand-more';
+ const isShowAll = this.isShowAll.get(category) ?? false;
+ const showAllThreshold = SHOW_ALL_THRESHOLDS.get(category) ?? 5;
+ const resultCount = filtered.length;
+ const resultLimit = isShowAll ? 1000 : showAllThreshold;
+ const showAllButton = this.renderShowAllButton(
+ category,
+ isShowAll,
+ showAllThreshold,
+ resultCount
+ );
return html`
<div class="${expandedClass}">
<h3
@@ -859,15 +913,49 @@
>${this.renderCount(all, selected, filtered)}</span
>
</h3>
- ${this.renderResults(all, selected, filtered)}
+ ${this.renderResults(
+ all,
+ selected,
+ filtered,
+ resultLimit,
+ showAllButton
+ )}
</div>
`;
}
+ renderShowAllButton(
+ category: Category | 'SUCCESS',
+ isShowAll: boolean,
+ showAllThreshold: number,
+ resultCount: number
+ ) {
+ if (resultCount <= showAllThreshold) return;
+ const message = isShowAll ? 'Show Less' : `Show All (${resultCount})`;
+ const handler = () => this.toggleShowAll(category);
+ return html`
+ <tr class="showAllRow">
+ <td colspan="4">
+ <gr-button class="showAll" link @click="${handler}"
+ >${message}</gr-button
+ >
+ </td>
+ </tr>
+ `;
+ }
+
+ toggleShowAll(category: Category | 'SUCCESS') {
+ const current = this.isShowAll.get(category) ?? false;
+ this.isShowAll.set(category, !current);
+ this.requestUpdate();
+ }
+
renderResults(
all: RunResult[],
selected: RunResult[],
- filtered: RunResult[]
+ filtered: RunResult[],
+ limit: number,
+ showAll: TemplateResult | undefined
) {
if (all.length === 0) {
return html`<div class="noResultsMessage">No results</div>`;
@@ -882,6 +970,7 @@
No results match the regular expression
</div>`;
}
+ filtered = filtered.slice(0, limit);
return html`
<table class="resultsTable">
<thead>
@@ -903,6 +992,7 @@
></gr-result-row>
`
)}
+ ${showAll}
</tbody>
</table>
`;
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index dc09479..de9c5fb 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -26,7 +26,7 @@
query,
} from 'lit-element';
import {GrLitElement} from '../lit/gr-lit-element';
-import {Action, RunStatus} from '../../api/checks';
+import {Action, Link, RunStatus} from '../../api/checks';
import {sharedStyles} from '../../styles/shared-styles';
import {
AttemptDetail,
@@ -50,6 +50,7 @@
fakeRun4_3,
fakeRun4_4,
updateStateSetResults,
+ fakeLinks,
} from '../../services/checks/checks-model';
import {assertIsDefined} from '../../utils/common-util';
import {whenVisible} from '../../utils/dom-util';
@@ -436,7 +437,8 @@
<gr-button link @click="${this.none}">none</gr-button>
<gr-button
link
- @click="${() => this.toggle('f0', [fakeRun0], fakeActions)}"
+ @click="${() =>
+ this.toggle('f0', [fakeRun0], fakeActions, fakeLinks)}"
>0</gr-button
>
<gr-button link @click="${() => this.toggle('f1', [fakeRun1])}"
@@ -474,7 +476,7 @@
}
all() {
- updateStateSetResults('f0', [fakeRun0], fakeActions);
+ updateStateSetResults('f0', [fakeRun0], fakeActions, fakeLinks);
updateStateSetResults('f1', [fakeRun1]);
updateStateSetResults('f2', [fakeRun2]);
updateStateSetResults('f3', [fakeRun3]);
@@ -486,9 +488,14 @@
]);
}
- toggle(plugin: string, runs: CheckRun[], actions: Action[] = []) {
+ toggle(
+ plugin: string,
+ runs: CheckRun[],
+ actions: Action[] = [],
+ links: Link[] = []
+ ) {
const newRuns = this.runs.includes(runs[0]) ? [] : runs;
- updateStateSetResults(plugin, newRuns, actions);
+ updateStateSetResults(plugin, newRuns, actions, links);
}
renderSection(status: RunStatus) {
diff --git a/polygerrit-ui/app/elements/checks/gr-hovercard-run.ts b/polygerrit-ui/app/elements/checks/gr-hovercard-run.ts
index 5ebd05c..ae6408d 100644
--- a/polygerrit-ui/app/elements/checks/gr-hovercard-run.ts
+++ b/polygerrit-ui/app/elements/checks/gr-hovercard-run.ts
@@ -20,8 +20,14 @@
import {htmlTemplate} from './gr-hovercard-run_html';
import {customElement, property} from '@polymer/decorators';
import {CheckRun} from '../../services/checks/checks-model';
-import {iconForRun} from '../../services/checks/checks-util';
-import {fromNow} from '../../utils/date-util';
+import {
+ iconForCategory,
+ iconForStatus,
+ runActions,
+ worstCategory,
+} from '../../services/checks/checks-util';
+import {durationString, fromNow} from '../../utils/date-util';
+import {RunStatus} from '../../api/checks';
@customElement('gr-hovercard-run')
export class GrHovercardRun extends hovercardBehaviorMixin(PolymerElement) {
@@ -32,13 +38,78 @@
@property({type: Object})
run?: CheckRun;
- computeIcon(run: CheckRun) {
- return iconForRun(run);
+ computeIcon(run?: CheckRun) {
+ if (!run) return '';
+ const category = worstCategory(run);
+ if (category) return iconForCategory(category);
+ return run.status === RunStatus.COMPLETED
+ ? iconForStatus(RunStatus.COMPLETED)
+ : '';
}
- computeDuration(date: Date) {
+ computeActions(run?: CheckRun) {
+ return runActions(run);
+ }
+
+ computeChipIcon(run?: CheckRun) {
+ if (run?.status === RunStatus.COMPLETED) return 'check';
+ if (run?.status === RunStatus.RUNNING) return 'timelapse';
+ return '';
+ }
+
+ computeCompletionDuration(run?: CheckRun) {
+ if (!run?.finishedTimestamp || !run?.startedTimestamp) return '';
+ return durationString(run.startedTimestamp, run.finishedTimestamp, true);
+ }
+
+ computeDuration(date?: Date) {
return date ? fromNow(date) : '';
}
+
+ computeHostName(link?: string) {
+ return link ? new URL(link).hostname : '';
+ }
+
+ hideChip(run?: CheckRun) {
+ return !run || run.status === RunStatus.RUNNABLE;
+ }
+
+ hideHeaderSectionIcon(run?: CheckRun) {
+ return this.computeIcon(run).length === 0;
+ }
+
+ hideStatusSection(run?: CheckRun) {
+ if (!run) return true;
+ return !run.statusLink && !run.statusDescription;
+ }
+
+ hideAttemptSection(run?: CheckRun) {
+ if (!run) return true;
+ return (
+ !run.startedTimestamp &&
+ !run.scheduledTimestamp &&
+ !run.finishedTimestamp &&
+ this.hideAttempts(run)
+ );
+ }
+
+ hideAttempts(run?: CheckRun) {
+ const attemptCount = run?.attemptDetails?.length;
+ return attemptCount === undefined || attemptCount < 2;
+ }
+
+ hideScheduled(run?: CheckRun) {
+ return !run?.scheduledTimestamp || !!run?.startedTimestamp;
+ }
+
+ hideCompletion(run?: CheckRun) {
+ return !run?.startedTimestamp || !run?.finishedTimestamp;
+ }
+
+ hideDescriptionSection(run?: CheckRun) {
+ if (!run) return true;
+ return !run.checkLink && !run.checkDescription;
+ }
}
declare global {
diff --git a/polygerrit-ui/app/elements/checks/gr-hovercard-run_html.ts b/polygerrit-ui/app/elements/checks/gr-hovercard-run_html.ts
index cb7e464..08ceefe 100644
--- a/polygerrit-ui/app/elements/checks/gr-hovercard-run_html.ts
+++ b/polygerrit-ui/app/elements/checks/gr-hovercard-run_html.ts
@@ -22,74 +22,187 @@
</style>
<style include="gr-hovercard-shared-style">
#container {
- padding: var(--spacing-xl);
- }
- h3 iron-icon {
- position: relative;
- top: 2px;
+ min-width: 356px;
+ max-width: 356px;
+ padding: var(--spacing-xl) 0 var(--spacing-m) 0;
}
.row {
+ display: flex;
margin-top: var(--spacing-s);
}
+ .chipRow {
+ display: flex;
+ margin-top: var(--spacing-s);
+ }
+ .chip {
+ background: var(--gray-background);
+ color: var(--gray-foreground);
+ border-radius: 20px;
+ padding: var(--spacing-xs) var(--spacing-m) var(--spacing-xs)
+ var(--spacing-s);
+ }
.title {
color: var(--deemphasized-text-color);
- margin-right: var(--spacing-s);
+ margin-right: var(--spacing-m);
}
- iron-icon.launch {
+ div.section {
+ margin: 0 var(--spacing-xl) var(--spacing-m) var(--spacing-xl);
+ display: flex;
+ }
+ div.sectionIcon {
+ flex: 0 0 30px;
+ }
+ div.chip iron-icon {
+ width: 16px;
+ height: 16px;
+ /* Positioning of a 16px icon in the middle of a 20px line. */
+ position: relative;
+ top: 2px;
+ }
+ div.sectionIcon iron-icon {
+ position: relative;
+ top: 2px;
+ width: 20px;
+ height: 20px;
+ }
+ div.sectionIcon iron-icon.small {
+ position: relative;
+ top: 6px;
+ width: 16px;
+ height: 16px;
+ }
+ div.sectionContent iron-icon.link {
color: var(--link-color);
}
+ div.sectionContent .attemptIcon iron-icon,
+ div.sectionContent iron-icon.small {
+ width: 16px;
+ height: 16px;
+ margin-right: var(--spacing-s);
+ /* Positioning of a 16px icon in the middle of a 20px line. */
+ position: relative;
+ top: 2px;
+ }
+ .attemptNumber {
+ margin-right: var(--spacing-s);
+ color: var(--deemphasized-text-color);
+ text-align: center;
+ }
+ div.action {
+ border-top: 1px solid var(--border-color);
+ margin-top: var(--spacing-m);
+ padding: var(--spacing-m) var(--spacing-xl) 0;
+ }
</style>
<div id="container" role="tooltip" tabindex="-1">
- <h3 class="name heading-3">
- <iron-icon
- class$="[[computeIcon(run)]]"
- icon="gr-icons:[[computeIcon(run)]]"
- ></iron-icon>
- <span>[[run.checkName]]</span>
- </h3>
- <div hidden$="[[!run.checkDescription]]" class="row">
- <span class="title">Description</span>
- <span>[[run.checkDescription]]</span>
+ <div class="section">
+ <div hidden$="[[hideChip(run)]]" class="chipRow">
+ <div class="chip">
+ <iron-icon icon="gr-icons:[[computeChipIcon(run)]]"></iron-icon>
+ <span>[[run.status]]</span>
+ </div>
+ </div>
</div>
- <div hidden$="[[!run.checkLink]]" class="row">
- <span class="title">Documentation</span>
- <a href="[[run.checkLink]]" target="_blank">
+ <div class="section">
+ <div class="sectionIcon" hidden$="[[hideHeaderSectionIcon(run)]]">
<iron-icon
- aria-label="external link to check documentation"
- class="launch"
- icon="gr-icons:launch"
+ class$="[[computeIcon(run)]]"
+ icon="gr-icons:[[computeIcon(run)]]"
></iron-icon>
- </a>
+ </div>
+ <div class="sectionContent">
+ <h3 class="name heading-3">
+ <span>[[run.checkName]]</span>
+ </h3>
+ </div>
</div>
- <div hidden$="[[!run.statusDescription]]" class="row">
- <span class="title">Status</span>
- <span>[[run.statusDescription]]</span>
+ <div class="section" hidden$="[[hideStatusSection(run)]]">
+ <div class="sectionIcon">
+ <iron-icon class="small" icon="gr-icons:info-outline"></iron-icon>
+ </div>
+ <div class="sectionContent">
+ <div hidden$="[[!run.statusLink]]" class="row">
+ <div class="title">Status</div>
+ <div>
+ <a href="[[run.statusLink]]" target="_blank"
+ ><iron-icon
+ aria-label="external link to check status"
+ class="small link"
+ icon="gr-icons:launch"
+ ></iron-icon
+ >[[computeHostName(run.statusLink)]]
+ </a>
+ </div>
+ </div>
+ <div hidden$="[[!run.statusDescription]]" class="row">
+ <div class="title">Message</div>
+ <div>[[run.statusDescription]]</div>
+ </div>
+ </div>
</div>
- <div hidden$="[[!run.statusLink]]" class="row">
- <span class="title">Status Link</span>
- <a href="[[run.statusLink]]" target="_blank">
- <iron-icon
- aria-label="external link to check status"
- class="launch"
- icon="gr-icons:launch"
- ></iron-icon>
- </a>
+ <div class="section" hidden$="[[hideAttemptSection(run)]]">
+ <div class="sectionIcon">
+ <iron-icon class="small" icon="gr-icons:schedule"></iron-icon>
+ </div>
+ <div class="sectionContent">
+ <div hidden$="[[hideAttempts(run)]]" class="row">
+ <div class="title">Attempt</div>
+ <template is="dom-repeat" items="[[run.attemptDetails]]">
+ <div>
+ <div class="attemptIcon">
+ <iron-icon
+ class$="[[item.icon]]"
+ icon="gr-icons:[[item.icon]]"
+ ></iron-icon>
+ </div>
+ <div class="attemptNumber">[[item.attempt]]</div>
+ </div>
+ </template>
+ </div>
+ <div hidden$="[[hideScheduled(run)]]" class="row">
+ <div class="title">Scheduled</div>
+ <div>[[computeDuration(run.scheduledTimestamp)]]</div>
+ </div>
+ <div hidden$="[[!run.startedTimestamp]]" class="row">
+ <div class="title">Started</div>
+ <div>[[computeDuration(run.startedTimestamp)]]</div>
+ </div>
+ <div hidden$="[[!run.finishedTimestamp]]" class="row">
+ <div class="title">Ended</div>
+ <div>[[computeDuration(run.finishedTimestamp)]]</div>
+ </div>
+ <div hidden$="[[hideCompletion(run)]]" class="row">
+ <div class="title">Completion</div>
+ <div>[[computeCompletionDuration(run)]]</div>
+ </div>
+ </div>
</div>
- <div hidden$="[[!run.attempt]]" class="row">
- <span class="title">Attempt</span>
- <span>[[run.attempt]]</span>
+ <div class="section" hidden$="[[hideDescriptionSection(run)]]">
+ <div class="sectionIcon">
+ <iron-icon class="small" icon="gr-icons:link"></iron-icon>
+ </div>
+ <div class="sectionContent">
+ <div hidden$="[[!run.checkDescription]]" class="row">
+ <div class="title">Description</div>
+ <div>[[run.checkDescription]]</div>
+ </div>
+ <div hidden$="[[!run.checkLink]]" class="row">
+ <div class="title">Documentation</div>
+ <div>
+ <a href="[[run.checkLink]]" target="_blank"
+ ><iron-icon
+ aria-label="external link to check documentation"
+ class="small link"
+ icon="gr-icons:launch"
+ ></iron-icon
+ >[[computeHostName(run.checkLink)]]
+ </a>
+ </div>
+ </div>
+ </div>
</div>
- <div hidden$="[[!run.scheduledTimestamp]]" class="row">
- <span class="title">Scheduled</span>
- <span>[[computeDuration(run.scheduledTimestamp)]]</span>
- </div>
- <div hidden$="[[!run.startedTimestamp]]" class="row">
- <span class="title">Started</span>
- <span>[[computeDuration(run.startedTimestamp)]]</span>
- </div>
- <div hidden$="[[!run.finishedTimestamp]]" class="row">
- <span class="title">Finished</span>
- <span>[[computeDuration(run.finishedTimestamp)]]</span>
- </div>
+ <template is="dom-repeat" items="[[computeActions(run)]]">
+ <div class="action"><gr-button link>[[item.name]]</gr-button></div>
+ </template>
</div>
`;
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_html.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_html.ts
index 2fb1fa0..b0716dd 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_html.ts
@@ -31,10 +31,6 @@
background-color: var(--background-color-secondary);
border-bottom: 1px solid var(--border-color);
}
- .fixActions {
- display: flex;
- justify-content: flex-end;
- }
gr-button {
margin-left: var(--spacing-m);
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
index 30c6f49..0412779 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_html.ts
@@ -112,10 +112,6 @@
.prefsButton {
text-align: right;
}
- .noOverflow {
- display: block;
- overflow: auto;
- }
.editMode .hideOnEdit {
display: none;
}
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
index 69ac702..ab24168 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
@@ -31,14 +31,6 @@
padding: var(--spacing-xxl);
width: 50em;
}
- .publicKey {
- font-family: var(--monospace-font-family);
- font-size: var(--font-size-mono);
- line-height: var(--line-height-mono);
- overflow-x: scroll;
- overflow-wrap: break-word;
- width: 30em;
- }
.closeButton {
bottom: 2em;
position: absolute;
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
index 89cab8a..71c1add 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.ts
@@ -20,7 +20,6 @@
import {htmlTemplate} from './gr-change-status_html';
import {customElement, property} from '@polymer/decorators';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
-import {getRevertCreatedChangeIds} from '../../../utils/message-util';
import {ChangeInfo} from '../../../types/common';
import {ParsedChangeInfo} from '../../../types/types';
@@ -67,7 +66,7 @@
tooltipText = '';
@property({type: Object})
- revertSubmittedChange?: ChangeInfo;
+ revertedChange?: ChangeInfo;
_computeStatusString(status: ChangeStates) {
if (status === ChangeStates.WIP && !this.flat) {
@@ -80,26 +79,15 @@
return str ? str.toLowerCase().replace(/\s/g, '-') : '';
}
- hasStatusLink(status: ChangeStates) {
- return (
- status === ChangeStates.REVERT_CREATED ||
- status === ChangeStates.REVERT_SUBMITTED
- );
+ hasStatusLink(revertedChange?: ChangeInfo) {
+ return revertedChange !== undefined;
}
- getStatusLink(change?: ParsedChangeInfo, status?: ChangeStates) {
- if (!change?.messages) return;
- if (status === ChangeStates.REVERT_CREATED) {
- const revertChangeId = getRevertCreatedChangeIds(change.messages)?.[0];
- if (!revertChangeId) return;
- return GerritNav.getUrlForSearchQuery(revertChangeId);
- }
- if (this.revertSubmittedChange) {
- return GerritNav.getUrlForSearchQuery(
- `${this.revertSubmittedChange._number}`
- );
- }
- return;
+ getStatusLink(revertedChange?: ChangeInfo) {
+ return (
+ revertedChange &&
+ GerritNav.getUrlForSearchQuery(`${revertedChange._number}`)
+ );
}
_updateChipDetails(status?: ChangeStates, previousStatus?: ChangeStates) {
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_html.ts b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_html.ts
index 2a96cdf..3d227a9 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_html.ts
@@ -81,14 +81,14 @@
title="[[tooltipText]]"
max-width="40em"
>
- <template is="dom-if" if="[[hasStatusLink(status)]]">
- <a class="status-link" href="[[getStatusLink(change, status)]]">
+ <template is="dom-if" if="[[!!hasStatusLink(revertedChange)]]">
+ <a class="status-link" href="[[getStatusLink(revertedChange)]]">
<div class="chip" aria-label$="Label: [[status]]">
[[_computeStatusString(status)]]
</div>
</a>
</template>
- <template is="dom-if" if="[[!hasStatusLink(status)]]">
+ <template is="dom-if" if="[[!hasStatusLink(revertedChange)]]">
<div class="chip" aria-label$="Label: [[status]]">
[[_computeStatusString(status)]]
</div>
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
index a1644e7..1f0ce3d 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_html.ts
@@ -80,10 +80,6 @@
justify-content: space-between;
padding: 0 var(--spacing-s) var(--spacing-s);
}
- .descriptionText {
- margin-left: var(--spacing-m);
- font-style: italic;
- }
.fileName {
padding: var(--spacing-m) var(--spacing-s) var(--spacing-m);
}
diff --git a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
index 2957320..e324cf25 100644
--- a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
+++ b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.ts
@@ -140,8 +140,10 @@
<g id="download"><path d="M0 0h24v24H0z" fill="none"/><path d="M5,20h14v-2H5V20z M19,9h-4V3H9v6H5l7,7L19,9z"/></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#system_update-->
<g id="system-update"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14zm-1-6h-3V8h-2v5H8l4 4 4-4z"/></g>
- <!-- This SVG is a copy from material.io https://fonts.google.com/icons?selected=Material%20Icons%3Aswap_horiz-->
+ <!-- This SVG is a copy from material.io https://material.io/icons/#swap_horiz-->
<g id="swapHoriz"><path d="M0 0h24v24H0z" fill="none"/><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"/></g>
+ <!-- This SVG is a copy from material.io https://material.io/icons/#link-->
+ <g id="link"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g>
</defs>
</svg>
</iron-iconset-svg>`;
diff --git a/polygerrit-ui/app/services/checks/checks-model.ts b/polygerrit-ui/app/services/checks/checks-model.ts
index b7b8bda..ecd56cb 100644
--- a/polygerrit-ui/app/services/checks/checks-model.ts
+++ b/polygerrit-ui/app/services/checks/checks-model.ts
@@ -22,6 +22,7 @@
CheckResult as CheckResultApi,
CheckRun as CheckRunApi,
ChecksApiConfig,
+ Link,
LinkIcon,
RunStatus,
} from '../../api/checks';
@@ -76,6 +77,7 @@
config?: ChecksApiConfig;
runs: CheckRun[];
actions: Action[];
+ links: Link[];
}
interface ChecksState {
@@ -148,6 +150,18 @@
)
);
+export const allLinks$ = checksProviderState$.pipe(
+ map(state =>
+ Object.values(state).reduce(
+ (allActions: Link[], providerState: ChecksProviderState) => [
+ ...allActions,
+ ...providerState.links,
+ ],
+ []
+ )
+ )
+);
+
export const allRuns$ = checksProviderState$.pipe(
map(state =>
Object.values(state).reduce(
@@ -208,6 +222,7 @@
config,
runs: [],
actions: [],
+ links: [],
};
privateState$.next(nextState);
}
@@ -303,9 +318,35 @@
export const fakeRun2: CheckRun = {
internalRunId: 'f2',
checkName: 'FAKE Mega Analysis',
+ statusDescription: 'This run is nearly completed, but not quite.',
+ statusLink: 'https://www.google.com/',
+ checkDescription:
+ 'From what the title says you can tell that this check analyses.',
+ checkLink: 'https://www.google.com/',
+ scheduledTimestamp: new Date('2021-04-01T03:14:15'),
+ startedTimestamp: new Date('2021-04-01T04:24:25'),
+ finishedTimestamp: new Date('2021-04-01T04:44:44'),
isSingleAttempt: true,
isLatestAttempt: true,
attemptDetails: [],
+ actions: [
+ {
+ name: 'Re-Run',
+ tooltip: 'More powerful run than before',
+ primary: true,
+ callback: () => undefined,
+ },
+ {
+ name: 'Monetize',
+ primary: true,
+ callback: () => undefined,
+ },
+ {
+ name: 'Delete',
+ primary: true,
+ callback: () => undefined,
+ },
+ ],
results: [
{
internalResultId: 'f2r0',
@@ -380,8 +421,15 @@
export const fakeRun4_4: CheckRun = {
internalRunId: 'f4',
checkName: 'FAKE Elimination',
+ checkDescription: 'Shows you the possible eliminations.',
+ checkLink: 'https://www.google.com',
status: RunStatus.RUNNING,
+ statusDescription: 'Everything was eliminated already.',
+ statusLink: 'https://www.google.com',
attempt: 4,
+ scheduledTimestamp: new Date('2021-04-02T03:14:15'),
+ startedTimestamp: new Date('2021-04-02T04:24:25'),
+ finishedTimestamp: new Date('2021-04-02T04:25:44'),
isSingleAttempt: false,
isLatestAttempt: true,
attemptDetails: [],
@@ -424,6 +472,21 @@
},
];
+export const fakeLinks: Link[] = [
+ {
+ url: 'https://www.google.com',
+ primary: false,
+ tooltip: 'Tooltip for Bug Report Fake Link',
+ icon: LinkIcon.REPORT_BUG,
+ },
+ {
+ url: 'https://www.google.com',
+ primary: false,
+ tooltip: 'Tooltip for External Fake Link',
+ icon: LinkIcon.EXTERNAL,
+ },
+];
+
export function updateStateSetLoading(pluginName: string) {
const nextState = {...privateState$.getValue()};
nextState.providerNameToState = {...nextState.providerNameToState};
@@ -468,7 +531,8 @@
export function updateStateSetResults(
pluginName: string,
runs: CheckRunApi[],
- actions: Action[] = []
+ actions: Action[] = [],
+ links: Link[] = []
) {
const attemptMap = createAttemptMap(runs);
for (const attemptInfo of attemptMap.values()) {
@@ -502,6 +566,7 @@
};
}),
actions: [...actions],
+ links: [...links],
};
privateState$.next(nextState);
}
diff --git a/polygerrit-ui/app/services/checks/checks-service.ts b/polygerrit-ui/app/services/checks/checks-service.ts
index c7e42ba..250cea5 100644
--- a/polygerrit-ui/app/services/checks/checks-service.ts
+++ b/polygerrit-ui/app/services/checks/checks-service.ts
@@ -176,7 +176,8 @@
updateStateSetResults(
pluginName,
response.runs ?? [],
- response.actions
+ response.actions ?? [],
+ response.links ?? []
);
break;
}
diff --git a/polygerrit-ui/app/services/checks/checks-util.ts b/polygerrit-ui/app/services/checks/checks-util.ts
index 27da2a8..15841f3 100644
--- a/polygerrit-ui/app/services/checks/checks-util.ts
+++ b/polygerrit-ui/app/services/checks/checks-util.ts
@@ -128,9 +128,14 @@
}
export function primaryRunAction(run: CheckRun): Action | undefined {
- return (run.actions ?? [])
- .map(action => toCanonicalAction(action, run.status))
- .filter(action => action.name === primaryActionName(run.status))[0];
+ return runActions(run).filter(
+ action => action.name === primaryActionName(run.status)
+ )[0];
+}
+
+export function runActions(run?: CheckRun): Action[] {
+ if (!run?.actions) return [];
+ return run.actions.map(action => toCanonicalAction(action, run.status));
}
export function iconForRun(run: CheckRun) {