blob: eaa74f47004668554cd48d65675ce70835f4d1f8 [file] [log] [blame]
Dave Borowitz8cdc76b2018-03-26 10:04:27 -04001/**
2 * @license
Ben Rohlfs94fcbbc2022-05-27 10:45:03 +02003 * Copyright 2017 Google LLC
4 * SPDX-License-Identifier: Apache-2.0
Dave Borowitz8cdc76b2018-03-26 10:04:27 -04005 */
Dmitrii Filippov782f0552020-08-14 13:28:34 +02006import '../gr-tooltip-content/gr-tooltip-content';
Frank Bordenfb3f9792021-05-14 13:20:58 +02007import '../gr-icons/gr-icons';
Dmitrii Filippov782f0552020-08-14 13:28:34 +02008import '../../../styles/shared-styles';
Frank Bordenfb3f9792021-05-14 13:20:58 +02009import {
10 GeneratedWebLink,
11 GerritNav,
12} from '../../core/gr-navigation/gr-navigation';
Dhruv Srivastava36158ca2021-03-16 13:53:29 +010013import {ChangeInfo} from '../../../types/common';
14import {ParsedChangeInfo} from '../../../types/types';
paladox01a91f82022-03-13 16:45:49 +000015import {sharedStyles} from '../../../styles/shared-styles';
16import {LitElement, PropertyValues, html, css} from 'lit';
17import {customElement, property} from 'lit/decorators';
Becky Siegel53a184a2017-10-24 17:23:42 -070018
Dhruv Srivastava69a51732021-04-14 18:23:00 +020019export enum ChangeStates {
Dmitrii Filippov782f0552020-08-14 13:28:34 +020020 ABANDONED = 'Abandoned',
Frank Borden88603372021-06-02 16:50:51 +020021 ACTIVE = 'Active',
Dmitrii Filippov782f0552020-08-14 13:28:34 +020022 MERGE_CONFLICT = 'Merge Conflict',
Frank Borden88603372021-06-02 16:50:51 +020023 MERGED = 'Merged',
Dmitrii Filippov782f0552020-08-14 13:28:34 +020024 PRIVATE = 'Private',
Frank Borden88603372021-06-02 16:50:51 +020025 READY_TO_SUBMIT = 'Ready to submit',
Dhruv Srivastava36158ca2021-03-16 13:53:29 +010026 REVERT_CREATED = 'Revert Created',
Dhruv Srivastava69a51732021-04-14 18:23:00 +020027 REVERT_SUBMITTED = 'Revert Submitted',
Frank Borden88603372021-06-02 16:50:51 +020028 WIP = 'WIP',
Dmitrii Filippov782f0552020-08-14 13:28:34 +020029}
Becky Siegel53a184a2017-10-24 17:23:42 -070030
Dhruv Srivastava9c8386d2021-12-06 17:40:47 +010031export const WIP_TOOLTIP =
Dmitrii Filippov782f0552020-08-14 13:28:34 +020032 "This change isn't ready to be reviewed or submitted. " +
Dhruv Srivastava9c8386d2021-12-06 17:40:47 +010033 "It will not appear on dashboards unless you are CC'ed, " +
Dmitrii Filippov782f0552020-08-14 13:28:34 +020034 'and email notifications will be silenced until the review is started.';
Dhruv Srivastava319ce412019-11-12 08:41:10 -080035
Dhruv Srivastava3a052172021-02-19 13:55:01 +010036export const MERGE_CONFLICT_TOOLTIP =
Dmitrii Filippov782f0552020-08-14 13:28:34 +020037 'This change has merge conflicts. ' +
Dhruv Srivastava3a052172021-02-19 13:55:01 +010038 'Download the patch and run "git rebase". ' +
Dmitrii Filippov782f0552020-08-14 13:28:34 +020039 'Upload a new patchset after resolving all merge conflicts.';
Becky Siegel53a184a2017-10-24 17:23:42 -070040
Dmitrii Filippov782f0552020-08-14 13:28:34 +020041const PRIVATE_TOOLTIP =
42 'This change is only visible to its owner and ' +
43 'current reviewers (or anyone with "View Private Changes" permission).';
Becky Siegel53a184a2017-10-24 17:23:42 -070044
Dmitrii Filippov782f0552020-08-14 13:28:34 +020045@customElement('gr-change-status')
paladox01a91f82022-03-13 16:45:49 +000046export class GrChangeStatus extends LitElement {
47 @property({type: Boolean, reflect: true})
Dmitrii Filippov782f0552020-08-14 13:28:34 +020048 flat = false;
49
Dhruv Srivastava36158ca2021-03-16 13:53:29 +010050 @property({type: Object})
51 change?: ChangeInfo | ParsedChangeInfo;
52
paladox01a91f82022-03-13 16:45:49 +000053 @property({type: String})
Dmitrii Filippov782f0552020-08-14 13:28:34 +020054 status?: ChangeStates;
55
56 @property({type: String})
57 tooltipText = '';
58
Dhruv Srivastava69a51732021-04-14 18:23:00 +020059 @property({type: Object})
Dhruv Srivastavab61cd442021-04-21 14:54:29 +020060 revertedChange?: ChangeInfo;
Dhruv Srivastava69a51732021-04-14 18:23:00 +020061
Frank Bordenfb3f9792021-05-14 13:20:58 +020062 @property({type: Object})
63 resolveWeblinks?: GeneratedWebLink[] = [];
64
paladox01a91f82022-03-13 16:45:49 +000065 static override get styles() {
66 return [
67 sharedStyles,
68 css`
69 .chip {
70 border-radius: var(--border-radius);
71 background-color: var(--chip-background-color);
72 padding: 0 var(--spacing-m);
73 white-space: nowrap;
74 }
75 :host(.merged) .chip {
76 background-color: var(--status-merged);
77 color: var(--status-merged);
78 }
79 :host(.abandoned) .chip {
80 background-color: var(--status-abandoned);
81 color: var(--status-abandoned);
82 }
83 :host(.wip) .chip {
84 background-color: var(--status-wip);
85 color: var(--status-wip);
86 }
87 :host(.private) .chip {
88 background-color: var(--status-private);
89 color: var(--status-private);
90 }
91 :host(.merge-conflict) .chip {
92 background-color: var(--status-conflict);
93 color: var(--status-conflict);
94 }
95 :host(.active) .chip {
96 background-color: var(--status-active);
97 color: var(--status-active);
98 }
99 :host(.ready-to-submit) .chip {
100 background-color: var(--status-ready);
101 color: var(--status-ready);
102 }
103 :host(.revert-created) .chip {
104 background-color: var(--status-revert-created);
105 color: var(--status-revert-created);
106 }
107 :host(.revert-submitted) .chip {
108 background-color: var(--status-revert-created);
109 color: var(--status-revert-created);
110 }
111 .status-link {
112 text-decoration: none;
113 }
114 :host(.custom) .chip {
115 background-color: var(--status-custom);
116 color: var(--status-custom);
117 }
118 :host([flat]) .chip {
119 background-color: transparent;
120 padding: 0;
121 }
122 :host(:not([flat])) .chip,
123 .icon {
124 color: var(--status-text-color);
125 }
126 .icon {
127 --iron-icon-height: 18px;
128 --iron-icon-width: 18px;
129 }
130 `,
131 ];
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100132 }
133
paladox01a91f82022-03-13 16:45:49 +0000134 override render() {
135 return html`
136 <gr-tooltip-content
137 has-tooltip
138 position-below
139 .title=${this.tooltipText}
140 .maxWidth=${'40em'}
141 >
142 ${this.renderStatusLink()}
143 </gr-tooltip-content>
144 `;
145 }
146
147 private renderStatusLink() {
148 if (!this.hasStatusLink()) {
149 return html`
150 <div class="chip" aria-label="Label: ${this.status}">
151 ${this.computeStatusString()}
152 </div>
153 `;
154 }
155
156 return html`
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200157 <a class="status-link" href=${this.getStatusLink()}>
paladox01a91f82022-03-13 16:45:49 +0000158 <div class="chip" aria-label="Label: ${this.status}">
159 ${this.computeStatusString()}
160 ${this.showResolveIcon()
161 ? html`<iron-icon class="icon" icon="gr-icons:edit"></iron-icon>`
162 : ''}
163 </div>
164 </a>
165 `;
166 }
167
168 override willUpdate(changedProperties: PropertyValues) {
169 if (changedProperties.has('status')) {
170 this.updateChipDetails(changedProperties.get('status') as ChangeStates);
171 }
172 }
173
174 private computeStatusString() {
175 if (this.status === ChangeStates.WIP && !this.flat) {
176 return 'Work in Progress';
177 }
178 return this.status ?? '';
179 }
180
181 private toClassName(str?: ChangeStates) {
Dmitrii Filippov782f0552020-08-14 13:28:34 +0200182 return str ? str.toLowerCase().replace(/\s/g, '-') : '';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100183 }
184
paladox01a91f82022-03-13 16:45:49 +0000185 // private but used in test
186 hasStatusLink(): boolean {
Dhruv Srivastava324f69e2021-06-07 17:28:59 +0200187 const isRevertCreatedOrSubmitted =
paladox01a91f82022-03-13 16:45:49 +0000188 (this.status === ChangeStates.REVERT_SUBMITTED ||
189 this.status === ChangeStates.REVERT_CREATED) &&
190 this.revertedChange !== undefined;
Frank Bordenfb3f9792021-05-14 13:20:58 +0200191 return (
Dhruv Srivastava324f69e2021-06-07 17:28:59 +0200192 isRevertCreatedOrSubmitted ||
paladox01a91f82022-03-13 16:45:49 +0000193 !!(
194 this.status === ChangeStates.MERGE_CONFLICT &&
195 this.resolveWeblinks?.length
196 )
Frank Bordenfb3f9792021-05-14 13:20:58 +0200197 );
Dhruv Srivastava36158ca2021-03-16 13:53:29 +0100198 }
199
paladox01a91f82022-03-13 16:45:49 +0000200 // private but used in test
201 getStatusLink(): string {
202 if (this.revertedChange) {
203 return GerritNav.getUrlForSearchQuery(`${this.revertedChange._number}`);
Frank Bordenfb3f9792021-05-14 13:20:58 +0200204 }
paladox01a91f82022-03-13 16:45:49 +0000205 if (
206 this.status === ChangeStates.MERGE_CONFLICT &&
207 this.resolveWeblinks?.length
208 ) {
209 return this.resolveWeblinks[0].url ?? '';
Frank Bordenfb3f9792021-05-14 13:20:58 +0200210 }
Paladox nonef517ea62021-07-29 02:35:29 +0000211 return '';
Frank Bordenfb3f9792021-05-14 13:20:58 +0200212 }
213
paladox01a91f82022-03-13 16:45:49 +0000214 // private but used in test
215 showResolveIcon(): boolean {
216 return (
217 this.status === ChangeStates.MERGE_CONFLICT &&
218 !!this.resolveWeblinks?.length
219 );
Dhruv Srivastava36158ca2021-03-16 13:53:29 +0100220 }
221
paladox01a91f82022-03-13 16:45:49 +0000222 private updateChipDetails(previousStatus?: ChangeStates) {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100223 if (previousStatus) {
paladox01a91f82022-03-13 16:45:49 +0000224 this.classList.remove(this.toClassName(previousStatus));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100225 }
paladox01a91f82022-03-13 16:45:49 +0000226 this.classList.add(this.toClassName(this.status));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100227
paladox01a91f82022-03-13 16:45:49 +0000228 switch (this.status) {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100229 case ChangeStates.WIP:
230 this.tooltipText = WIP_TOOLTIP;
231 break;
232 case ChangeStates.PRIVATE:
233 this.tooltipText = PRIVATE_TOOLTIP;
234 break;
235 case ChangeStates.MERGE_CONFLICT:
236 this.tooltipText = MERGE_CONFLICT_TOOLTIP;
237 break;
238 default:
239 this.tooltipText = '';
240 break;
241 }
242 }
243}
244
Dmitrii Filippov782f0552020-08-14 13:28:34 +0200245declare global {
246 interface HTMLElementTagNameMap {
247 'gr-change-status': GrChangeStatus;
248 }
249}