diff --git a/src/github/graphql.ts b/src/github/graphql.ts index 8959383941..fc46c41e7c 100644 --- a/src/github/graphql.ts +++ b/src/github/graphql.ts @@ -557,6 +557,15 @@ export interface Issue { title: string; titleHTML: string; assignees?: { + closingIssuesReferences?: { + nodes: { + id: string; + databaseId: number; + number: number; + title: string; + state: 'OPEN' | 'CLOSED' | 'MERGED'; + }[]; + }; nodes: Account[]; }; author: Account; diff --git a/src/github/interface.ts b/src/github/interface.ts index 71e4f156be..b85d42cbe6 100644 --- a/src/github/interface.ts +++ b/src/github/interface.ts @@ -223,6 +223,7 @@ export interface PullRequest extends Issue { mergeCommitMeta?: { title: string, description: string }; squashCommitMeta?: { title: string, description: string }; suggestedReviewers?: ISuggestedReviewer[]; + closingIssuesReferences?: Pick[] hasComments?: boolean; } diff --git a/src/github/pullRequestModel.ts b/src/github/pullRequestModel.ts index a11d43e7af..b6e701c59d 100644 --- a/src/github/pullRequestModel.ts +++ b/src/github/pullRequestModel.ts @@ -56,6 +56,7 @@ import { IAccount, IGitTreeItem, IRawFileChange, + Issue, IRawFileContent, ISuggestedReviewer, ITeam, @@ -121,6 +122,8 @@ export class PullRequestModel extends IssueModel implements IPullRe public conflicts?: string[]; public suggestedReviewers?: ISuggestedReviewer[]; public hasChangesSinceLastReview?: boolean; + public issues: Partial[]; + private _showChangesSinceReview: boolean; private _hasPendingReview: boolean = false; private _onDidChangePendingReviewState: vscode.EventEmitter = new vscode.EventEmitter(); @@ -144,7 +147,6 @@ export class PullRequestModel extends IssueModel implements IPullRe private _comments: readonly IComment[] | undefined; private _onDidChangeComments: vscode.EventEmitter = new vscode.EventEmitter(); public readonly onDidChangeComments: vscode.Event = this._onDidChangeComments.event; - // Whether the pull request is currently checked out locally private _isActive: boolean; public get isActive(): boolean { @@ -248,6 +250,7 @@ export class PullRequestModel extends IssueModel implements IPullRe super.update(item); this.isDraft = item.isDraft; this.suggestedReviewers = item.suggestedReviewers; + this.issues = item.closingIssuesReferences ?? []; if (item.isRemoteHeadDeleted != null) { this.isRemoteHeadDeleted = item.isRemoteHeadDeleted; diff --git a/src/github/queriesExtra.gql b/src/github/queriesExtra.gql index 513d7bf4df..5bbec3a84f 100644 --- a/src/github/queriesExtra.gql +++ b/src/github/queriesExtra.gql @@ -179,6 +179,15 @@ fragment PullRequestFragment on PullRequest { } } } + closingIssuesReferences(first: 50) { + nodes { + id + databaseId + body + number + title + } + } comments(first: 1) { totalCount diff --git a/src/github/utils.ts b/src/github/utils.ts index 2ea17e052c..92f3e0a9e7 100644 --- a/src/github/utils.ts +++ b/src/github/utils.ts @@ -778,6 +778,7 @@ export function parseGraphQLPullRequest( milestone: parseMilestone(graphQLPullRequest.milestone), assignees: graphQLPullRequest.assignees?.nodes.map(assignee => parseAccount(assignee, githubRepository)), commits: parseCommits(graphQLPullRequest.commits.nodes), + closingIssuesReferences: parseIssues(graphQLPullRequest.closingIssuesReferences?.nodes), reactionCount: graphQLPullRequest.reactions.totalCount, commentCount: graphQLPullRequest.comments.totalCount, }; @@ -867,6 +868,35 @@ function parseComments(comments: GraphQL.AbbreviatedIssueComment[] | undefined, return parsedComments; } +function parseIssues(issues: Pick[] | undefined): { + id: number; + number: number; + title: string; + state: 'OPEN' | 'CLOSED' | 'MERGED'; +}[] | undefined { + if (!issues) { + return undefined; + } + + const parsedIssues: { + id: number; + number: number; + title: string; + state: 'OPEN' | 'CLOSED' | 'MERGED'; + }[] = []; + + for (const issue of issues) { + parsedIssues.push({ + id: issue.databaseId, + number: issue.number, + title: issue.title, + state: issue.state, + }); + } + + return parsedIssues; +} + export function parseGraphQLIssue(issue: GraphQL.Issue, githubRepository: GitHubRepository): Issue { return { id: issue.databaseId, diff --git a/src/github/views.ts b/src/github/views.ts index 0f261208f2..9f4a774e25 100644 --- a/src/github/views.ts +++ b/src/github/views.ts @@ -10,6 +10,7 @@ import { ILabel, IMilestone, IProjectItem, + Issue, MergeMethod, MergeMethodsAvailability, MergeQueueState, @@ -40,6 +41,7 @@ export interface Issue { assignees: IAccount[]; projectItems: IProjectItem[] | undefined; milestone: IMilestone | undefined; + issues: Partial[]; /** * User can edit PR title and description (author or user with push access) */ diff --git a/webviews/components/sidebar.tsx b/webviews/components/sidebar.tsx index eeb5d6cf24..810dcc9d9f 100644 --- a/webviews/components/sidebar.tsx +++ b/webviews/components/sidebar.tsx @@ -14,7 +14,7 @@ import { AuthorLink, Avatar } from '../components/user'; import { closeIcon, copilotIcon, settingsIcon } from './icon'; import { Reviewer } from './reviewer'; -export default function Sidebar({ reviewers, labels, hasWritePermission, isIssue, projectItems: projects, milestone, assignees, canAssignCopilot }: PullRequest) { +export default function Sidebar({ reviewers, labels, issues, hasWritePermission, isIssue, projectItems: projects, milestone, assignees, canAssignCopilot }: PullRequest) { const { addReviewers, addAssignees, @@ -202,6 +202,30 @@ export default function Sidebar({ reviewers, labels, hasWritePermission, isIssue
No milestone
)} +
+
{ + const newMilestone = await addMilestone(); + updatePR({ milestone: newMilestone.added }); + }}> +
Linked issues
+ {hasWritePermission ? ( + + ) : null} +
+ {issues.length ? ( +
+ {issues.map(issue => ( + + ))} +
+ ) : ( +
None yet
+ )} +
); } @@ -273,3 +297,14 @@ function Project(project: IProjectItem & { canDelete: boolean }) { ); } + +function Issue(issue: any) { + return ( +
+
+

{issue.title}

+ {/* Add more details about the issue as needed */} +
+
+ ); +} diff --git a/webviews/editorWebview/test/builder/pullRequest.ts b/webviews/editorWebview/test/builder/pullRequest.ts index af776ab9a2..d23b5ac329 100644 --- a/webviews/editorWebview/test/builder/pullRequest.ts +++ b/webviews/editorWebview/test/builder/pullRequest.ts @@ -57,5 +57,6 @@ export const PullRequestBuilder = createBuilderClass()({ hasReviewDraft: { default: false }, busy: { default: undefined }, lastReviewType: { default: undefined }, + issues: { default: [] }, canAssignCopilot: { default: false }, });