Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/github/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,15 @@ export interface PullRequest extends Issue {
suggestedReviewers: SuggestedReviewerResponse[];
additions?: number;
deletions?: number;
closingIssuesReferences?: {
Comment thread
alexr00 marked this conversation as resolved.
nodes: {
id: number,
title: string,
number: number,
state: 'CLOSED' | 'OPEN',
url: string,
}[];
};
}

export enum DefaultCommitTitle {
Expand Down
9 changes: 9 additions & 0 deletions src/github/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,14 @@ export interface Issue {
reactions: Reaction[];
}

export interface IssueReference {
id: number;
number: number;
title: string;
state: GithubItemStateEnum;
url: string;
}

export interface PullRequest extends Issue {
isDraft?: boolean;
isRemoteHeadDeleted?: boolean;
Expand All @@ -242,6 +250,7 @@ export interface PullRequest extends Issue {
mergeCommitMeta?: { title: string, description: string };
squashCommitMeta?: { title: string, description: string };
suggestedReviewers?: ISuggestedReviewer[];
closingIssues?: IssueReference[]
hasComments?: boolean;
additions?: number;
deletions?: number;
Expand Down
4 changes: 3 additions & 1 deletion src/github/pullRequestModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
IGitTreeItem,
IRawFileChange,
IRawFileContent,
IssueReference,
ISuggestedReviewer,
ITeam,
MergeMethod,
Expand Down Expand Up @@ -137,6 +138,7 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
public conflicts?: string[];
public suggestedReviewers?: ISuggestedReviewer[];
public hasChangesSinceLastReview?: boolean;
public closingIssues: IssueReference[] = [];
private _showChangesSinceReview: boolean;
private _hasPendingReview: boolean = false;
private _onDidChangePendingReviewState: vscode.EventEmitter<boolean> = this._register(new vscode.EventEmitter<boolean>());
Expand Down Expand Up @@ -265,7 +267,7 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
}

this.suggestedReviewers = item.suggestedReviewers;

this.closingIssues = item.closingIssues ?? [];
if (item.isRemoteHeadDeleted != null) {
this.isRemoteHeadDeleted = item.isRemoteHeadDeleted;
}
Expand Down
3 changes: 2 additions & 1 deletion src/github/pullRequestOverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,8 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel<PullRequestMode
currentUserReviewState: reviewState,
revertable: pullRequest.state === GithubItemStateEnum.Merged,
isCopilotOnMyBehalf: await isCopilotOnMyBehalf(pullRequest, currentUser, coAuthors),
generateDescriptionTitle: this.getGenerateDescriptionTitle()
generateDescriptionTitle: this.getGenerateDescriptionTitle(),
closingIssues: pullRequest.closingIssues,
};
this._postMessage({
command: 'pr.initialize',
Expand Down
9 changes: 9 additions & 0 deletions src/github/queries.gql
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@ fragment PullRequestFragment on PullRequest {
mergeCommitMessage
mergeCommitTitle
}
closingIssuesReferences(first: 50) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs to be added in queriesExtra.gql and queriesLimited.gql.

nodes {
id
number
title
state
url
}
}
merged
mergeable
mergeQueueEntry {
Expand Down
17 changes: 17 additions & 0 deletions src/github/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,7 @@ export async function parseGraphQLPullRequest(
commentCount: graphQLPullRequest.comments.totalCount,
additions: graphQLPullRequest.additions,
deletions: graphQLPullRequest.deletions,
closingIssues: parseClosingIssuesReferences(graphQLPullRequest.closingIssuesReferences?.nodes),
};
pr.mergeCommitMeta = parseCommitMeta(graphQLPullRequest.baseRepository.mergeCommitTitle, graphQLPullRequest.baseRepository.mergeCommitMessage, pr);
pr.squashCommitMeta = parseCommitMeta(graphQLPullRequest.baseRepository.squashMergeCommitTitle, graphQLPullRequest.baseRepository.squashMergeCommitMessage, pr);
Expand Down Expand Up @@ -1068,6 +1069,22 @@ function parseSuggestedReviewers(
return ret.sort(loginComparator);
}

function parseClosingIssuesReferences(
closingIssuesReferences: Array<{ id: number, number: number, title: string, state: string, url: string }> | undefined
): Array<{ id: number, number: number, title: string, state: GithubItemStateEnum, url: string }> {
if (!closingIssuesReferences) {
return [];
}

return closingIssuesReferences.map(issue => ({
id: issue.id,
number: issue.number,
title: issue.title,
state: issue.state === 'OPEN' ? GithubItemStateEnum.Open : GithubItemStateEnum.Closed,
url: issue.url,
}));
}

/**
* Used for case insensitive sort by login
*/
Expand Down
8 changes: 8 additions & 0 deletions src/github/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export enum ReviewType {
RequestChanges = 'requestChanges',
}

export interface IssueReference {
number: number;
title: string;
state: GithubItemStateEnum;
url: string;
}

export interface DisplayLabel extends ILabel {
displayName: string;
}
Expand Down Expand Up @@ -112,6 +119,7 @@ export interface PullRequest extends Issue {
busy?: boolean;
loadingCommit?: string;
generateDescriptionTitle?: string;
closingIssues: IssueReference[];
}

export interface ProjectItemsReply {
Expand Down
8 changes: 8 additions & 0 deletions webviews/common/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,14 @@ body img.avatar {
fill: var(--vscode-issues-open);
}

.section-icon.issue-open svg path {
fill: var(--vscode-issues-open);
}

.section-icon.issue-closed svg path {
fill: var(--vscode-issues-closed);
}

.reviewer-icons {
display: flex;
gap: 4px;
Expand Down
2 changes: 2 additions & 0 deletions webviews/components/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const outputIcon = <Icon src={require('../../resources/icons/codicons/out
export const skipIcon = <Icon src={require('../../resources/icons/codicons/skip.svg')} className='skip' />;

// Other icons
export const issueIcon = <Icon src={require('../../resources/icons/issue_webview.svg')} />;
export const issueClosedIcon = <Icon src={require('../../resources/icons/codicons/pass.svg')} />;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add another export here, pass is already exported above.

export const copilotErrorIcon = <Icon className='copilot-icon' src={require('../../resources/icons/copilot-error.svg')} />;
export const copilotInProgressIcon = <Icon className='copilot-icon' src={require('../../resources/icons/copilot-in-progress.svg')} />;
export const copilotSuccessIcon = <Icon className='copilot-icon' src={require('../../resources/icons/copilot-success.svg')} />;
37 changes: 33 additions & 4 deletions webviews/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*--------------------------------------------------------------------------------------------*/

import React, { useContext, useEffect, useRef, useState } from 'react';
import { closeIcon, copilotIcon, settingsIcon } from './icon';
import { closeIcon, copilotIcon, issueClosedIcon, issueIcon, settingsIcon } from './icon';
import { Reviewer } from './reviewer';
import { COPILOT_LOGINS } from '../../src/common/copilot';
import { gitHubLabelColor } from '../../src/common/utils';
import { IAccount, IMilestone, IProjectItem, isITeam, reviewerId, reviewerLabel, ReviewState } from '../../src/github/interface';
import { ChangeReviewersReply, PullRequest } from '../../src/github/views';
import { GithubItemStateEnum, IAccount, IMilestone, IProjectItem, isITeam, reviewerId, reviewerLabel, ReviewState } from '../../src/github/interface';
import { ChangeReviewersReply, IssueReference, PullRequest } from '../../src/github/views';
import PullRequestContext from '../common/context';
import { Label } from '../common/label';
import { AuthorLink, Avatar } from '../components/user';
Expand Down Expand Up @@ -53,7 +53,7 @@ function Section({
);
}

export default function Sidebar({ reviewers, labels, hasWritePermission, isIssue, projectItems: projects, milestone, assignees, canAssignCopilot, canRequestCopilotReview }: PullRequest) {
export default function Sidebar({ reviewers, labels, closingIssues, hasWritePermission, isIssue, projectItems: projects, milestone, assignees, canAssignCopilot, canRequestCopilotReview }: PullRequest) {
const {
addReviewers,
addReviewerCopilot,
Expand Down Expand Up @@ -268,6 +268,22 @@ export default function Sidebar({ reviewers, labels, hasWritePermission, isIssue
<div className="section-placeholder">No milestone</div>
)}
</Section>

<Section
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are no closing issues, let's just not show this section. It's not actionable when there's nothing in it.

id="closingIssues"
title="Linked Issues"
hasWritePermission={false}
>
{closingIssues.length ? (
closingIssues.map(issue => (
<div key={issue.number} className="section-item">
<IssueItem issue={issue} />
</div>
))
) : (
<div className="section-placeholder">None yet</div>
)}
</Section>
</div>
);
}
Expand Down Expand Up @@ -577,3 +593,16 @@ function ConvertToDraft() {
</div>
);
}

function IssueItem({ issue }: { issue: IssueReference }) {
const isOpen = issue.state === GithubItemStateEnum.Open;
return (
<div className="avatar-with-author">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a weird class to use here, as there's no avatar with author in the div.

<span className={`section-icon ${isOpen ? 'issue-open' : 'issue-closed'}`}>
{isOpen ? issueIcon : issueClosedIcon}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use issuescon (looks like there's a typo in the icon variable, but that's the correct icon) instead of issueIcon.

</span>
<a href={issue.url} title={issue.url}>#{issue.number} {issue.title}</a>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the styling of this be improved?

  • not blue
  • overflow shouldn't wrap to the next line, and instead end with ...
  • would also be nice to use the same colors as GH for the icon.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What it currently looks like:
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, when it's clicked it should open the issue webview, rather than issue in your browser.

</div>
);
}

1 change: 1 addition & 0 deletions webviews/editorWebview/test/builder/pullRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const PullRequestBuilder = createBuilderClass<PullRequest>()({
hasReviewDraft: { default: false },
busy: { default: undefined },
lastReviewType: { default: undefined },
closingIssues: { default: [] },
canAssignCopilot: { default: false },
canRequestCopilotReview: { default: false },
isCopilotOnMyBehalf: { default: false },
Expand Down