blob: af018c3616d6269f6e6201df5e87438e8af6e1fe [file] [log] [blame]
Dave Borowitz8cdc76b2018-03-26 10:04:27 -04001/**
2 * @license
Ben Rohlfs94fcbbc2022-05-27 10:45:03 +02003 * Copyright 2015 Google LLC
4 * SPDX-License-Identifier: Apache-2.0
Dave Borowitz8cdc76b2018-03-26 10:04:27 -04005 */
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +02006import '../../shared/gr-account-chip/gr-account-chip';
7import '../../shared/gr-button/gr-button';
Chris Poucet1c713862022-07-25 13:12:24 +02008import '../../shared/gr-icon/gr-icon';
Milutin Kristoficc43c58a2021-08-12 16:12:08 +02009import '../../shared/gr-vote-chip/gr-vote-chip';
Dhruve4473ab2022-04-04 10:54:30 +020010import {LitElement, html} from 'lit';
Frank Borden42c1a452022-08-11 16:27:20 +020011import {customElement, property, state} from 'lit/decorators.js';
Dhruve4473ab2022-04-04 10:54:30 +020012
Ben Rohlfs669433f2020-08-14 17:09:25 +020013import {
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020014 ChangeInfo,
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020015 AccountInfo,
16 ApprovalInfo,
Dhruv Srivastavacded6de2021-04-12 18:51:40 +020017 AccountDetailInfo,
Milutin Kristoficc43c58a2021-08-12 16:12:08 +020018 isDetailedLabelInfo,
19 LabelInfo,
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020020} from '../../../types/common';
Milutin Kristoficd21f8602022-05-13 11:58:17 +020021import {getApprovalInfo, getCodeReviewLabel} from '../../../utils/label-util';
Milutin Kristofic85d3f912021-10-19 18:55:57 +020022import {sortReviewers} from '../../../utils/attention-set-util';
Dhruve4473ab2022-04-04 10:54:30 +020023import {sharedStyles} from '../../../styles/shared-styles';
24import {css} from 'lit';
25import {nothing} from 'lit';
Ben Rohlfs6bb90532023-02-17 18:55:56 +010026import {fire} from '../../../utils/event-util';
27import {ShowReplyDialogEvent} from '../../../types/events';
Milutin Kristofic308a4142023-05-10 17:38:02 +020028import {repeat} from 'lit/directives/repeat.js';
29import {accountKey} from '../../../utils/account-util';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010030
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020031@customElement('gr-reviewer-list')
Dhruve4473ab2022-04-04 10:54:30 +020032export class GrReviewerList extends LitElement {
Dhruve4473ab2022-04-04 10:54:30 +020033 @property({type: Object}) change?: ChangeInfo;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010034
Dhruve4473ab2022-04-04 10:54:30 +020035 @property({type: Object}) account?: AccountDetailInfo;
Dhruv Srivastavacded6de2021-04-12 18:51:40 +020036
Dhruve4473ab2022-04-04 10:54:30 +020037 @property({type: Boolean, reflect: true}) disabled = false;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020038
Dhruve4473ab2022-04-04 10:54:30 +020039 @property({type: Boolean}) mutable = false;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020040
Dhruve4473ab2022-04-04 10:54:30 +020041 @property({type: Boolean, attribute: 'reviewers-only'}) reviewersOnly = false;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020042
Dhruve4473ab2022-04-04 10:54:30 +020043 @property({type: Boolean, attribute: 'ccs-only'}) ccsOnly = false;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020044
Dhruve4473ab2022-04-04 10:54:30 +020045 @state() displayedReviewers: AccountInfo[] = [];
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020046
Dhruve4473ab2022-04-04 10:54:30 +020047 @state() reviewers: AccountInfo[] = [];
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020048
Dhruve4473ab2022-04-04 10:54:30 +020049 @state() hiddenReviewerCount?: number;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020050
Dhruve4473ab2022-04-04 10:54:30 +020051 @state() showAllReviewers = false;
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +020052
Dhruve4473ab2022-04-04 10:54:30 +020053 static override get styles() {
54 return [
55 sharedStyles,
56 css`
57 :host {
58 display: block;
59 }
60 :host([disabled]) {
61 opacity: 0.8;
62 pointer-events: none;
63 }
64 .container {
65 display: block;
66 /* line-height-normal for the chips, 2px for the chip border, spacing-s
67 for the gap between lines, negative bottom margin for eliminating the
68 gap after the last line */
69 line-height: calc(var(--line-height-normal) + 2px + var(--spacing-s));
70 margin-bottom: calc(0px - var(--spacing-s));
71 }
Chris Poucet1c713862022-07-25 13:12:24 +020072 .addReviewer gr-icon {
Dhruve4473ab2022-04-04 10:54:30 +020073 color: inherit;
Dhruve4473ab2022-04-04 10:54:30 +020074 }
75 .controlsContainer {
76 display: inline-block;
77 }
78 gr-button.addReviewer {
Dhruve4473ab2022-04-04 10:54:30 +020079 vertical-align: top;
Ben Rohlfsb1b0ac92022-08-01 14:33:02 +020080 --gr-button-padding: var(--spacing-s);
81 --margin: calc(0px - var(--spacing-s));
Dhruve4473ab2022-04-04 10:54:30 +020082 }
83 gr-button {
84 line-height: var(--line-height-normal);
85 --gr-button-padding: 0px;
86 }
87 gr-account-chip {
88 line-height: var(--line-height-normal);
89 vertical-align: top;
90 display: inline-block;
91 }
92 gr-vote-chip {
93 --gr-vote-chip-width: 14px;
94 --gr-vote-chip-height: 14px;
95 }
Frank Bordena6f871b2024-02-08 17:11:16 +010096 .reviewersAndControls {
97 text-wrap: pretty;
98 }
Dhruve4473ab2022-04-04 10:54:30 +020099 `,
100 ];
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100101 }
102
Dhruve4473ab2022-04-04 10:54:30 +0200103 override render() {
104 this.displayedReviewers = this.computeDisplayedReviewers() ?? [];
105 this.hiddenReviewerCount =
106 this.reviewers.length - this.displayedReviewers.length;
107 return html`
108 <div class="container">
Frank Bordena6f871b2024-02-08 17:11:16 +0100109 <div class="reviewersAndControls">
Milutin Kristofic308a4142023-05-10 17:38:02 +0200110 ${repeat(
111 this.displayedReviewers,
112 reviewer => accountKey(reviewer),
113 reviewer => this.renderAccountChip(reviewer)
Dhruve4473ab2022-04-04 10:54:30 +0200114 )}
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200115 <div class="controlsContainer" ?hidden=${!this.mutable}>
Dhruve4473ab2022-04-04 10:54:30 +0200116 <gr-button
117 link
118 id="addReviewer"
119 class="addReviewer"
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200120 @click=${this.handleAddTap}
121 title=${this.ccsOnly ? 'Add CC' : 'Add reviewer'}
Ben Rohlfsb1b0ac92022-08-01 14:33:02 +0200122 >
123 <div>
124 <gr-icon icon="edit" filled small></gr-icon>
125 </div>
Chris Poucetb8c06392022-07-08 16:35:43 +0200126 </gr-button>
Dhruve4473ab2022-04-04 10:54:30 +0200127 </div>
128 </div>
129 <gr-button
130 class="hiddenReviewers"
131 link=""
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200132 ?hidden=${!this.hiddenReviewerCount}
133 @click=${() => {
Dhruve4473ab2022-04-04 10:54:30 +0200134 this.showAllReviewers = true;
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200135 }}
Dhruve4473ab2022-04-04 10:54:30 +0200136 >and ${this.hiddenReviewerCount} more</gr-button
137 >
138 </div>
139 `;
140 }
141
142 private renderAccountChip(reviewer: AccountInfo) {
143 const change = this.change;
144 if (!change) return nothing;
145 return html`
146 <gr-account-chip
147 class="reviewer"
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200148 .account=${reviewer}
149 .change=${change}
Dhruve4473ab2022-04-04 10:54:30 +0200150 highlightAttention
Ben Rohlfs8003bd32022-04-05 18:24:42 +0200151 .vote=${this.computeVote(reviewer)}
152 .label=${this.computeCodeReviewLabel()}
Dhruve4473ab2022-04-04 10:54:30 +0200153 >
Milutin Kristoficd21f8602022-05-13 11:58:17 +0200154 <gr-vote-chip
155 slot="vote-chip"
156 .vote=${this.computeVote(reviewer)}
157 .label=${this.computeCodeReviewLabel()}
158 circle-shape
159 ></gr-vote-chip>
Dhruve4473ab2022-04-04 10:54:30 +0200160 </gr-account-chip>
161 `;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100162 }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500163
Dhruve4473ab2022-04-04 10:54:30 +0200164 private computeVote(reviewer: AccountInfo): ApprovalInfo | undefined {
165 const codeReviewLabel = this.computeCodeReviewLabel();
Milutin Kristoficc43c58a2021-08-12 16:12:08 +0200166 if (!codeReviewLabel || !isDetailedLabelInfo(codeReviewLabel)) return;
167 return getApprovalInfo(codeReviewLabel, reviewer);
168 }
169
Dhruve4473ab2022-04-04 10:54:30 +0200170 private computeCodeReviewLabel(): LabelInfo | undefined {
171 if (!this.change?.labels) return;
172 return getCodeReviewLabel(this.change.labels);
Milutin Kristoficc43c58a2021-08-12 16:12:08 +0200173 }
174
Dhruve4473ab2022-04-04 10:54:30 +0200175 private computeDisplayedReviewers() {
176 if (this.change?.owner === undefined) {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100177 return;
178 }
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +0200179 let result: AccountInfo[] = [];
Dhruve4473ab2022-04-04 10:54:30 +0200180 const reviewers = this.change.reviewers;
Ben Rohlfs7b71b112021-02-12 10:36:08 +0100181 for (const key of Object.keys(reviewers)) {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100182 if (this.reviewersOnly && key !== 'REVIEWER') {
183 continue;
184 }
185 if (this.ccsOnly && key !== 'CC') {
186 continue;
187 }
188 if (key === 'REVIEWER' || key === 'CC') {
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +0200189 result = result.concat(reviewers[key]!);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100190 }
191 }
Dhruve4473ab2022-04-04 10:54:30 +0200192 this.reviewers = result
193 .filter(
194 reviewer => reviewer._account_id !== this.change?.owner._account_id
195 )
Milutin Kristofic85d3f912021-10-19 18:55:57 +0200196 .sort((r1, r2) => sortReviewers(r1, r2, this.change, this.account));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100197
Dhruve4473ab2022-04-04 10:54:30 +0200198 if (this.reviewers.length > 8 && !this.showAllReviewers) {
199 return this.reviewers.slice(0, 6);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100200 } else {
Dhruve4473ab2022-04-04 10:54:30 +0200201 return this.reviewers;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100202 }
203 }
204
Dhruve4473ab2022-04-04 10:54:30 +0200205 // private but used in tests
206 handleAddTap(e: Event) {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100207 e.preventDefault();
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +0200208 const value = {
Ben Rohlfs6bb90532023-02-17 18:55:56 +0100209 reviewersOnly: this.reviewersOnly,
210 ccsOnly: this.ccsOnly,
Dhruv Srivastava4ac17f22020-09-10 16:21:41 +0200211 };
Ben Rohlfs6bb90532023-02-17 18:55:56 +0100212 fire(this, 'show-reply-dialog', {value});
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100213 }
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100214}
Dhruv Srivastava33a657a2021-04-12 20:10:11 +0200215
216declare global {
217 interface HTMLElementTagNameMap {
218 'gr-reviewer-list': GrReviewerList;
219 }
Ben Rohlfs6bb90532023-02-17 18:55:56 +0100220 interface HTMLElementEventMap {
221 /** Fired when the "Add reviewer..." button is tapped. */
222 'show-reply-dialog': ShowReplyDialogEvent;
223 }
Dhruv Srivastava33a657a2021-04-12 20:10:11 +0200224}