First steps towards a pull request review dialog

This commit is contained in:
Sergio Padrino 2022-03-01 18:23:56 +01:00
parent e6a5089169
commit d24923a5f6
4 changed files with 183 additions and 1 deletions

View file

@ -495,8 +495,10 @@ export interface IAPIPullRequest {
/** Information about a pull request review as returned by the GitHub API. */
export interface IAPIPullRequestReview {
readonly id: number
readonly user: IAPIIdentity
readonly body: string
readonly html_url: string
readonly state:
| 'APPROVED'
| 'DISMISSED'

View file

@ -20,6 +20,7 @@ import { ICommitMessage } from './commit-message'
import { IAuthor } from './author'
import { IRefCheck } from '../lib/ci-checks/ci-checks'
import { GitHubRepository } from './github-repository'
import { IAPIPullRequestReview } from '../lib/api'
export enum PopupType {
RenameBranch = 1,
@ -81,6 +82,7 @@ export enum PopupType {
CICheckRunRerun,
WarnForcePush,
DiscardChangesRetry,
PullRequestReview,
}
export type Popup =
@ -335,3 +337,10 @@ export type Popup =
type: PopupType.DiscardChangesRetry
retryAction: RetryAction
}
| {
type: PopupType.PullRequestReview
repository: RepositoryWithGitHubRepository
pullRequest: PullRequest
review: IAPIPullRequestReview
needsSelectRepository: boolean
}

View file

@ -152,6 +152,7 @@ import * as ipcRenderer from '../lib/ipc-renderer'
import { showNotification } from '../lib/stores/helpers/show-notification'
import { DiscardChangesRetryDialog } from './discard-changes/discard-changes-retry-dialog'
import { getReleaseSummary } from '../lib/release-notes'
import { PullRequestReview } from './notifications/pull-request-review'
const MinuteInMilliseconds = 1000 * 60
const HourInMilliseconds = MinuteInMilliseconds * 60
@ -2027,7 +2028,7 @@ export class App extends React.Component<IAppProps, IAppState> {
<PullRequestChecksFailed
key="pull-request-checks-failed"
dispatcher={this.props.dispatcher}
shouldChangeRepository={popup.needsSelectRepository}
shouldChangeRepository={popup.shouldChangeRepository}
repository={popup.repository}
pullRequest={popup.pullRequest}
commitMessage={popup.commitMessage}
@ -2080,6 +2081,22 @@ export class App extends React.Component<IAppProps, IAppState> {
/>
)
}
case PopupType.PullRequestReview: {
return (
<PullRequestReview
key="pull-request-checks-failed"
dispatcher={this.props.dispatcher}
shouldChangeRepository={popup.shouldChangeRepository}
repository={popup.repository}
pullRequest={popup.pullRequest}
review={popup.review}
emoji={this.state.emoji}
accounts={this.state.accounts}
onSubmit={onPopupDismissedFn}
onDismissed={onPopupDismissedFn}
/>
)
}
default:
return assertNever(popup, `Unknown popup type: ${popup}`)
}

View file

@ -0,0 +1,154 @@
import * as React from 'react'
import { Dialog, DialogContent, DialogFooter } from '../dialog'
import { Row } from '../lib/row'
import { OkCancelButtonGroup } from '../dialog/ok-cancel-button-group'
import { PullRequest } from '../../models/pull-request'
import { Dispatcher } from '../dispatcher'
import { Account } from '../../models/account'
import { IAPIPullRequestReview } from '../../lib/api'
import { Octicon } from '../octicons'
import * as OcticonSymbol from '../octicons/octicons.generated'
import { RepositoryWithGitHubRepository } from '../../models/repository'
import { SandboxedMarkdown } from '../lib/sandboxed-markdown'
interface IPullRequestReviewProps {
readonly dispatcher: Dispatcher
readonly shouldChangeRepository: boolean
readonly accounts: ReadonlyArray<Account>
readonly repository: RepositoryWithGitHubRepository
readonly pullRequest: PullRequest
readonly review: IAPIPullRequestReview
/** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */
readonly emoji: Map<string, string>
readonly onSubmit: () => void
readonly onDismissed: () => void
}
interface IPullRequestReviewState {
readonly switchingToPullRequest: boolean
}
/**
* Dialog to show the result of a CI check run.
*/
export class PullRequestReview extends React.Component<
IPullRequestReviewProps,
IPullRequestReviewState
> {
public constructor(props: IPullRequestReviewProps) {
super(props)
this.state = {
switchingToPullRequest: false,
}
}
public render() {
let okButtonTitle = __DARWIN__
? 'Switch to Pull Request'
: 'Switch to pull request'
if (this.props.shouldChangeRepository) {
okButtonTitle = __DARWIN__
? 'Switch to Repository and Pull Request'
: 'Switch to repository and pull request'
}
const { title, pullRequestNumber, base } = this.props.pullRequest
const header = (
<div className="ci-check-run-dialog-header">
<Octicon symbol={OcticonSymbol.xCircleFill} />
<div className="title-container">
<div className="summary">
@{this.props.review.user.login} requested changes on your pull
request
</div>
<span className="pr-title">
<span className="pr-title">{title}</span>{' '}
<span className="pr-number">#{pullRequestNumber}</span>{' '}
</span>
</div>
</div>
)
return (
<Dialog
id="pull-request-checks-failed"
type="normal"
title={header}
dismissable={false}
onSubmit={this.props.onSubmit}
onDismissed={this.props.onDismissed}
loading={this.state.switchingToPullRequest}
>
<DialogContent>
<Row>
<SandboxedMarkdown
markdown={this.props.review.body}
emoji={this.props.emoji}
baseHref={base.gitHubRepository.htmlURL}
repository={base.gitHubRepository}
onMarkdownLinkClicked={this.onMarkdownLinkClicked}
/>
</Row>
</DialogContent>
<DialogFooter>
<Row>
{this.renderSummary()}
<OkCancelButtonGroup
onCancelButtonClick={this.props.onDismissed}
cancelButtonText="Dismiss"
okButtonText={okButtonTitle}
okButtonDisabled={this.state.switchingToPullRequest}
onOkButtonClick={this.onSubmit}
/>
</Row>
</DialogFooter>
</Dialog>
)
}
private onMarkdownLinkClicked = (url: string) => {
this.props.dispatcher.openInBrowser(url)
}
private renderSummary() {
return (
<div className="footer-question">
<span>
Do you want to switch to that Pull Request now and start working on
the requested changes?
</span>
</div>
)
}
// private onViewOnGitHub = (checkRun: IRefCheck) => {
// const { repository, pullRequest, dispatcher, review } = this.props
// // Some checks do not provide htmlURLS like ones for the legacy status
// // object as they do not have a view in the checks screen. In that case we
// // will just open the PR and they can navigate from there... a little
// // dissatisfying tho more of an edgecase anyways.
// const url =
// review.html_url ||
// `${repository.gitHubRepository.htmlURL}/pull/${pullRequest.pullRequestNumber}#pullrequestreview-${review.id}`
// if (url === null) {
// // The repository should have a htmlURL.
// return
// }
// dispatcher.openInBrowser(url)
// }
private onSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault()
const { dispatcher, repository, pullRequest } = this.props
this.setState({ switchingToPullRequest: true })
await dispatcher.selectRepository(repository)
await dispatcher.checkoutPullRequest(repository, pullRequest)
this.setState({ switchingToPullRequest: false })
this.props.onDismissed()
}
}