Skip to content

Commit b857885

Browse files
IllusionMHRachel Macfarlane
authored andcommitted
Improve visibility of PR controls to take into account user write permission, fixes #1408, fixes #1065
1 parent f21a3b0 commit b857885

4 files changed

Lines changed: 27 additions & 20 deletions

File tree

preview-src/cache.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export interface PullRequest {
2424
labels: ILabel[];
2525
commitsCount: number;
2626
repositoryDefaultBranch: any;
27+
/**
28+
* User can edit PR title and description (author or user with push access)
29+
*/
2730
canEdit: boolean;
2831
/**
2932
* Users with push access to repo have rights to merge/close PRs,

preview-src/merge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export const PrActions = (pr: PullRequest) => {
133133

134134
return isDraft
135135
// Only PR author and users with push rights can mark draft as ready for review
136-
? hasWritePermission || canEdit
136+
? canEdit
137137
? <ReadyForReview/>
138138
: null
139139
: mergeable === PullRequestMergeability.Mergeable && hasWritePermission

preview-src/sidebar.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,62 +7,66 @@ import PullRequestContext from './context';
77
import { ReviewState, ILabel } from '../src/github/interface';
88
import { nbsp } from './space';
99

10-
export default function Sidebar({ reviewers, labels }: PullRequest) {
10+
export default function Sidebar({ reviewers, labels, hasWritePermission }: PullRequest) {
1111
const { addReviewers, addLabels, updatePR, pr } = useContext(PullRequestContext);
1212

1313
return <div id='sidebar'>
1414
<div id='reviewers' className='section'>
1515
<div className='section-header'>
1616
<div>Reviewers</div>
17-
<button title='Add Reviewers' onClick={async () => {
18-
const newReviewers = await addReviewers();
19-
updatePR({reviewers: pr.reviewers.concat(newReviewers.added)});
20-
}}>{plusIcon}</button>
17+
{ hasWritePermission ? (
18+
<button title='Add Reviewers' onClick={async () => {
19+
const newReviewers = await addReviewers();
20+
updatePR({reviewers: pr.reviewers.concat(newReviewers.added)});
21+
}}>{plusIcon}</button>
22+
) : null }
2123
</div>
2224
{
2325
reviewers.map(state =>
24-
<Reviewer key={state.reviewer.login} {...state} />
26+
<Reviewer key={state.reviewer.login} {...state} canDelete={hasWritePermission} />
2527
)
2628
}
2729
</div>
2830
<div id='labels' className='section'>
2931
<div className='section-header'>
3032
<div>Labels</div>
31-
<button title='Add Labels' onClick={async () => {
32-
const newLabels = await addLabels();
33-
updatePR({ labels: pr.labels.concat(newLabels.added)});
34-
}}>{plusIcon}</button>
33+
{ hasWritePermission ? (
34+
<button title='Add Labels' onClick={async () => {
35+
const newLabels = await addLabels();
36+
updatePR({ labels: pr.labels.concat(newLabels.added)});
37+
}}>{plusIcon}</button>
38+
) : null }
3539
</div>
3640
{
37-
labels.map(label => <Label key={label.name} {...label} />)
41+
labels.map(label => <Label key={label.name} {...label} canDelete={hasWritePermission} />)
3842
}
3943
</div>
4044
</div>;
4145
}
4246

43-
function Reviewer(reviewState: ReviewState) {
44-
const { reviewer, state } = reviewState;
47+
function Reviewer(reviewState: ReviewState & { canDelete: boolean }) {
48+
const { reviewer, state, canDelete } = reviewState;
4549
const [ showDelete, setShowDelete ] = useState(false);
4650
const { removeReviewer } = useContext(PullRequestContext);
4751
return <div className='section-item reviewer'
4852
onMouseEnter={state === 'REQUESTED' ? () => setShowDelete(true) : null}
4953
onMouseLeave={state === 'REQUESTED' ? () => setShowDelete(false) : null}>
5054
<Avatar for={reviewer} />
5155
<AuthorLink for={reviewer} />
52-
{ showDelete ? <>{nbsp}<a className='remove-item' onClick={() => removeReviewer(reviewState.reviewer.login)}>{deleteIcon}</a></> : null}
56+
{ canDelete && showDelete ? <>{nbsp}<a className='remove-item' onClick={() => removeReviewer(reviewState.reviewer.login)}>{deleteIcon}</a></> : null}
5357
{REVIEW_STATE[state]}
5458
</div>;
5559
}
5660

57-
function Label(label: ILabel) {
58-
const { name } = label;
61+
function Label(label: ILabel & { canDelete: boolean }) {
62+
const { name, canDelete } = label;
5963
const [ showDelete, setShowDelete ] = useState(false);
6064
const { removeLabel } = useContext(PullRequestContext);
6165
return <div className='section-item label'
6266
onMouseEnter={() => setShowDelete(true)}
6367
onMouseLeave={() => setShowDelete(false)}>
6468
{name}
65-
{ showDelete ? <>{nbsp}<a className='push-right remove-item' onClick={() => removeLabel(name)}>{deleteIcon}</a>{nbsp}</> : null}
69+
{ canDelete && showDelete ? <>{nbsp}<a className='push-right remove-item' onClick={() => removeLabel(name)}>{deleteIcon}</a>{nbsp}</> : null}
6670
</div>;
6771
}
6872

@@ -71,4 +75,4 @@ const REVIEW_STATE: { [state: string]: React.ReactElement } = {
7175
COMMENTED: cloneElement(commentIcon, { className: 'push-right', Root: 'div', title: 'Left review comments' }),
7276
APPROVED: cloneElement(checkIcon, { className: 'push-right', title: 'Approved these changes' }),
7377
CHANGES_REQUESTED: cloneElement(diffIcon, { className: 'push-right', title: 'Requested changes' }),
74-
};
78+
};

src/github/pullRequestOverview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export class PullRequestOverviewPanel {
226226
this._panel.title = `Pull Request #${pullRequestModel.prNumber.toString()}`;
227227

228228
const isCurrentlyCheckedOut = pullRequestModel.equals(this._pullRequestManager.activePullRequest);
229-
const canEdit = this._pullRequestManager.canEditPullRequest(this._pullRequest);
229+
const canEdit = hasWritePermission || this._pullRequestManager.canEditPullRequest(this._pullRequest);
230230
const preferredMergeMethod = vscode.workspace.getConfiguration('githubPullRequests').get<MergeMethod>('defaultMergeMethod');
231231
const supportsGraphQl = pullRequestModel.githubRepository.supportsGraphQl;
232232
const defaultMergeMethod = getDetaultMergeMethod(mergeMethodsAvailability, preferredMergeMethod);

0 commit comments

Comments
 (0)