diff --git a/preview-src/cache.ts b/preview-src/cache.ts index 8ef811c573..a994c95dbd 100644 --- a/preview-src/cache.ts +++ b/preview-src/cache.ts @@ -27,6 +27,7 @@ export interface PullRequest { pendingCommentText?: string; pendingCommentDrafts?: { [key: string]: string; }; status: ReposGetCombinedStatusForRefResponse; + mergeable; boolean; } export function getState(): PullRequest { diff --git a/preview-src/index.css b/preview-src/index.css index ba1cf3f69b..c658f2a36e 100644 --- a/preview-src/index.css +++ b/preview-src/index.css @@ -125,6 +125,16 @@ body .comment-container .review-comment-header a { margin-left: 15px; } +.status-item { + display: flex; + padding-top: 12px; +} + +.status-item a { + margin-left: 10px; + cursor: pointer; +} + #status-checks { margin-top: 5px; } diff --git a/preview-src/index.ts b/preview-src/index.ts index 13bf0cf68e..815611f557 100644 --- a/preview-src/index.ts +++ b/preview-src/index.ts @@ -61,7 +61,7 @@ function renderPullRequest(pr: PullRequest): void { renderTimelineEvents(pr); setTitleHTML(pr); setTextArea(); - renderStatusChecks(pr.status); + renderStatusChecks(pr); updateCheckoutButton(pr.isCurrentlyCheckedOut); updatePullRequestState(pr.state); diff --git a/preview-src/pullRequestOverviewRenderer.ts b/preview-src/pullRequestOverviewRenderer.ts index 40047a00f0..870992823f 100644 --- a/preview-src/pullRequestOverviewRenderer.ts +++ b/preview-src/pullRequestOverviewRenderer.ts @@ -8,7 +8,7 @@ import { TimelineEvent, CommitEvent, ReviewEvent, CommentEvent, EventType, isCom import { PullRequestStateEnum } from '../src/github/interface'; import md from './mdRenderer'; import { MessageHandler } from './message'; -import { getState, updateState } from './cache'; +import { getState, updateState, PullRequest } from './cache'; import { Comment } from '../src/common/comment'; const commitIconSvg = require('../resources/icons/commit_icon.svg'); @@ -82,46 +82,77 @@ function getStateIcon(state: string) { } } -export function renderStatusChecks(statusInfo: any) { - const statusContainer: HTMLDetailsElement = document.getElementById('status-checks') as HTMLDetailsElement; +export function renderStatusChecks(pr: PullRequest) { + const statusContainer = document.getElementById('status-checks') as HTMLDivElement; statusContainer.innerHTML = ''; - if (!statusInfo.statuses.length) { - statusContainer.classList.add('hidden'); - return; - } else { - statusContainer.classList.remove('hidden'); - } + const { status, mergeable } = pr; - statusContainer.open = statusInfo.state !== 'success'; + const statusCheckInformationContainer = document.createElement('div'); - const statusSummary = document.createElement('summary'); - const statusSummaryIcon = document.createElement('span'); - const statusSummaryText = document.createElement('span'); - statusSummaryIcon.innerHTML = getStateIcon(statusInfo.state); + const statusSummary = document.createElement('div'); + statusSummary.classList.add('status-item'); + const statusSummaryIcon = document.createElement('div'); + const statusSummaryText = document.createElement('div'); + statusSummaryIcon.innerHTML = getStateIcon(status.state); statusSummary.appendChild(statusSummaryIcon); - statusSummaryText.textContent = getSummaryLabel(statusInfo.statuses); + statusSummaryText.textContent = getSummaryLabel(status.statuses); statusSummary.appendChild(statusSummaryText); - statusContainer.appendChild(statusSummary); + statusCheckInformationContainer.appendChild(statusSummary); + + const statusesToggle = document.createElement('a'); + statusesToggle.textContent = status.state === 'success' ? 'Show' : 'Hide'; + statusesToggle.addEventListener('click', () => { + if (statusList.classList.contains('hidden')) { + statusList.classList.remove('hidden'); + statusesToggle.textContent = 'Hide'; + } else { + statusList.classList.add('hidden'); + statusesToggle.textContent = 'Show'; + } + }); + + statusSummary.appendChild(statusesToggle); - statusInfo.statuses.forEach(status => { + if (!status.statuses.length) { + statusCheckInformationContainer.classList.add('hidden'); + } + + const statusList = document.createElement('div'); + if (status.state === 'success') { + statusList.classList.add('hidden'); + } + statusCheckInformationContainer.appendChild(statusList); + statusContainer.appendChild(statusCheckInformationContainer); + + status.statuses.forEach(s => { const statusElement: HTMLDivElement = document.createElement('div'); statusElement.className = 'status-check'; const state: HTMLSpanElement = document.createElement('span'); - state.innerHTML = getStateIcon(status.state); + state.innerHTML = getStateIcon(s.state); statusElement.appendChild(state); - const statusIcon = renderUserIcon(status.url, status.avatar_url); + const statusIcon = renderUserIcon(s.url, s.avatar_url); statusElement.appendChild(statusIcon); const statusDescription = document.createElement('span'); - statusDescription.textContent = `${status.context} - ${status.description}`; + statusDescription.textContent = `${s.context} - ${s.description}`; statusElement.appendChild(statusDescription); - statusContainer.appendChild(statusElement); + statusList.appendChild(statusElement); }); + + const mergeableSummary = document.createElement('div'); + mergeableSummary.classList.add('status-item'); + const mergeableSummaryIcon = document.createElement('div'); + const mergeableSummaryText = document.createElement('div'); + mergeableSummaryIcon.innerHTML = mergeable ? checkIcon : deleteIcon; + mergeableSummary.appendChild(mergeableSummaryIcon); + mergeableSummaryText.textContent = mergeable ? 'This branch has no conflicts with the base branch' : 'This branch has conflicts that must be resolved'; + mergeableSummary.appendChild(mergeableSummaryText); + statusContainer.appendChild(mergeableSummary); } function renderUserIcon(iconLink: string, iconSrc: string): HTMLElement { diff --git a/src/github/interface.ts b/src/github/interface.ts index 61141dd47a..c0f3b77540 100644 --- a/src/github/interface.ts +++ b/src/github/interface.ts @@ -67,6 +67,7 @@ export type PullRequest = Pick< | 'commits' | 'head' | 'base' + | 'mergeable' >; export interface IRawFileChange { @@ -103,6 +104,7 @@ export interface IPullRequestModel { userAvatarUri: vscode.Uri; body: string; labels: string[]; + prItem: PullRequest; update(prItem: Github.PullRequestsGetResponse): void; equals(other: IPullRequestModel): boolean; } diff --git a/src/github/pullRequestOverview.ts b/src/github/pullRequestOverview.ts index 9c0be87929..3184f3fb4f 100644 --- a/src/github/pullRequestOverview.ts +++ b/src/github/pullRequestOverview.ts @@ -174,7 +174,8 @@ export class PullRequestOverviewPanel { commitsCount: this._pullRequest.commitCount, repositoryDefaultBranch: defaultBranch, canEdit: canEdit, - status: status + status: status, + mergeable: this._pullRequest.prItem.mergeable } }); }).catch(e => { @@ -476,7 +477,7 @@ export class PullRequestOverviewPanel {
-