feat(pull_requests): make it possible to see a Pull Request and its diff@@ -1,5 +1,5 @@
{
- "_generatedAtUnix": 1665674159579,
+ "_generatedAtUnix": 1665676834248,
"_hashAlgorithm": "sha1",
"_version": 2,
"islands": {
@@ -134,7 +134,7 @@
"pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestCreateView.tsx"
},
"RepositoryPullRequestDetailsView": {
- "hash": "1ecb2513fa8cee3e027d71aea376466657bb1d56",
+ "hash": "6c311e13f7cbbc00b502e0d4c1af30493433eb65",
"pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestDetailsView.tsx"
},
"RepositoryPullRequestsView": {
@@ -2,6 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
+import type { RepositoryFileDiff } from "../../types";
import { AppRoute, AppRoutesParams } from "../../routes";
// app services
import { makeOrganizationService } from "../../services/organization";
@@ -25,47 +26,104 @@ const getRepositoryPullRequestDetailsView: ReqHandler = async (
const repoService = makeRepositoryService({ request });
const usersService = makeUsersService({ request });
+ const pullRequest = await prService.getPullRequestByUid(
+ orgSlug,
+ repoSlug,
+ pullUid
+ );
+
+ if (pullRequest == null) {
+ return reply.status(404).callNotFound();
+ }
+
const currentUser =
request.session.data.authenticated &&
request.session.data.curr_user_uid != null
? await usersService.getUserById(request.session.data.curr_user_uid)
: null;
- const parentOrg = await orgService.getOrganizationBySlug(orgSlug);
+ const sourceRepo = await repoService.getRepositoryById(
+ pullRequest.sourceRepositoryId
+ );
+ const targetRepo = await repoService.getRepositoryById(
+ pullRequest.targetRepositoryId
+ );
- if (parentOrg == null) {
+ if (sourceRepo == null || targetRepo == null) {
return reply.status(404).callNotFound();
}
- const repo = await repoService.getRepository(orgSlug, repoSlug);
+ const sourceParentOrg = await orgService.getOrganizationById(
+ sourceRepo.organizationId
+ );
- if (repo == null) {
+ const targetParentOrg = await orgService.getOrganizationById(
+ targetRepo.organizationId
+ );
+
+ if (sourceParentOrg == null || targetParentOrg == null) {
return reply.status(404).callNotFound();
}
- if (repo.visibility === ResourceVisibility.PRIVATE) {
+ if (sourceRepo.visibility === ResourceVisibility.PRIVATE) {
if (currentUser == null) {
return reply.status(404).callNotFound();
} else if (
- (await repoService.canUserAccessRepository(currentUser, repo)) === false
+ (await repoService.canUserAccessRepository(currentUser, sourceRepo)) ===
+ false
) {
return reply.status(404).callNotFound();
}
}
- const pullRequest = await prService.getPullRequestByUid(
- orgSlug,
- repoSlug,
- pullUid
+ if (targetRepo.visibility === ResourceVisibility.PRIVATE) {
+ if (currentUser == null) {
+ return reply.status(404).callNotFound();
+ } else if (
+ (await repoService.canUserAccessRepository(currentUser, targetRepo)) ===
+ false
+ ) {
+ return reply.status(404).callNotFound();
+ }
+ }
+
+ const commitLogs = await repoService.getRepositoryCommitLog(
+ sourceRepo,
+ "",
+ pullRequest.sourceBranch,
+ true
);
+ const lastCommit = commitLogs.length >= 1 ? commitLogs[0] : null;
+
+ let filesDiffs = [] as RepositoryFileDiff[];
+
+ if (sourceParentOrg.slug === targetParentOrg.slug) {
+ filesDiffs = await repoService.getRepositoryRefDiff(
+ sourceRepo,
+ pullRequest.targetBranch,
+ pullRequest.sourceBranch
+ );
+ } else {
+ filesDiffs = await repoService.getRepositoryRemoteRefDiff(
+ sourceRepo,
+ pullRequest.sourceBranch,
+ targetRepo,
+ pullRequest.targetBranch
+ );
+ }
+
const reqHandler = reply.makeRequestHandler(request, reply);
return reqHandler<RepositoryPullRequestDetailsViewProps>(
RepositoryPullRequestDetailsView.name,
{
- parentOrg,
+ filesDiffs,
+ lastCommit,
pullRequest,
- repo,
+ sourceParentOrg,
+ sourceRepo,
+ targetParentOrg,
+ targetRepo,
}
);
};
@@ -0,0 +1,44 @@
+// 1st-party
+import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
+// app
+import { RepositoryWithForkedFromRepo } from "../../types";
+// service
+import type { RepositoryServiceDeps } from "./types";
+
+const makeGetRepositoryById: ServiceMethodFactory<
+ RepositoryServiceDeps,
+ [string],
+ Promise<RepositoryWithForkedFromRepo | null>
+> = ({ request }) => {
+ return async (repoId) => {
+ const repository = await request.prisma.repository.findFirst({
+ include: {
+ forkedFromRepo: {
+ select: {
+ id: true,
+ slug: true,
+ displayName: true,
+ organization: {
+ select: {
+ id: true,
+ slug: true,
+ displayName: true,
+ },
+ },
+ },
+ },
+ forks: {
+ select: {
+ _count: true,
+ },
+ },
+ },
+ where: {
+ id: repoId,
+ },
+ });
+ return repository;
+ };
+};
+
+export default makeGetRepositoryById;
@@ -9,6 +9,7 @@ import { default as makeForkRepository } from "./forkRepository";
import { default as makeGetCurrentUserRepositoryForks } from "./getCurrentUserRepositoryForks";
import { default as makeGetRepository } from "./getRepository";
import { default as makeGetRepositoryBranches } from "./getRepositoryBranches";
+import { default as makeGetRepositoryById } from "./getRepositoryById";
import { default as makeGetRepositoryCommitLog } from "./getRepositoryCommitLog";
import { default as makeGetRepositoryExploreCollection } from "./getRepositoryExploreCollection";
import { default as makeGetRepositoryFileContent } from "./getRepositoryFileContent";
@@ -33,6 +34,7 @@ export const makeRepositoryService = makeService<
getCurrentUserRepositoryForks: makeGetCurrentUserRepositoryForks,
getRepository: makeGetRepository,
getRepositoryBranches: makeGetRepositoryBranches,
+ getRepositoryById: makeGetRepositoryById,
getRepositoryCommitLog: makeGetRepositoryCommitLog,
getRepositoryExploreCollection: makeGetRepositoryExploreCollection,
getRepositoryFileContent: makeGetRepositoryFileContent,
@@ -51,17 +51,20 @@ export interface RepositoryServiceAPI extends ServiceApiContract {
canUserAccessRepository(user: User, repo: Repository): Promise<boolean>;
createRepository(dto: CreateRepositoryDTO): Promise<Repository>;
forkRepository(dto: ForkRepositoryDTO): Promise<Repository>;
+ getCurrentUserRepositoryForks(
+ repository: Repository
+ ): Promise<RepositoryWithParentAndForkedFromRepos[]>;
getRepository(
orgSlug: string,
repoSlug: string
): Promise<RepositoryWithForkedFromRepo | null>;
- getCurrentUserRepositoryForks(
- repository: Repository
- ): Promise<RepositoryWithParentAndForkedFromRepos[]>;
getRepositoryBranches(
repository: Repository,
onlyLocalBranches?: boolean
): Promise<string[]>;
+ getRepositoryById(
+ repoId: string
+ ): Promise<RepositoryWithForkedFromRepo | null>;
getRepositoryCommitLog(
repository: Repository,
path?: string,
@@ -5,25 +5,46 @@ import React from "react";
// generated via script[generate:prisma]
import type { Organization, PullRequest } from "@prisma/client";
// app
-import type { CommonProps, RepositoryWithForkedFromRepo } from "../../types";
+import type {
+ CommonProps,
+ RepositoryFileDiff,
+ RepositoryObject,
+ RepositoryWithForkedFromRepo,
+} from "../../types";
import {
+ Card,
Grid,
InlineCode,
IslandWrapper,
Layout,
+ MarkdownToJsx,
PageWrapper,
} from "../../components";
// app islands
+import RepositoryFilesDiffsList from "../../islands/RepositoryFilesDiffsList";
import RepositoryHero from "../../islands/RepositoryHero";
export interface RepositoryPullRequestDetailsViewProps extends CommonProps {
- parentOrg: Organization;
+ filesDiffs: RepositoryFileDiff[];
+ lastCommit: RepositoryObject | null;
pullRequest: PullRequest;
- repo: RepositoryWithForkedFromRepo;
+ sourceParentOrg: Organization;
+ sourceRepo: RepositoryWithForkedFromRepo;
+ targetParentOrg: Organization;
+ targetRepo: RepositoryWithForkedFromRepo;
}
const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsViewProps> =
- ({ commonProps, parentOrg, pullRequest: pr, repo }) => {
+ ({
+ commonProps,
+ filesDiffs,
+ lastCommit,
+ pullRequest: pr,
+ sourceParentOrg,
+ sourceRepo,
+ targetParentOrg: parentOrg,
+ targetRepo: repo,
+ }) => {
return (
<Layout {...commonProps}>
<PageWrapper>
@@ -49,7 +70,7 @@ const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsVi
<span style={{ opacity: 0.67, marginTop: 8 }}>
wants to merge{" "}
<InlineCode themeScheme={commonProps.themeScheme}>
- {pr.sourceBranch}
+ {`${sourceParentOrg.slug}/${sourceRepo.slug}@${pr.sourceBranch}`}
</InlineCode>{" "}
into{" "}
<InlineCode themeScheme={commonProps.themeScheme}>
@@ -97,10 +118,33 @@ const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsVi
Delete PR
</a>
</Grid.Col>
- <Grid.Col fluid>
- <pre>
- <code>{JSON.stringify(pr, null, 2)}</code>
- </pre>
+ <Grid.Col fluid style={{ marginTop: 24 }}>
+ <Card
+ style={{ width: "100%" }}
+ themeScheme={commonProps.themeScheme}
+ >
+ <MarkdownToJsx
+ markdown={
+ pr.textMd == null || pr.textMd.trim() === ""
+ ? "> <no_description_yet />"
+ : pr.textMd
+ }
+ themeScheme={commonProps.themeScheme}
+ />
+ </Card>
+ </Grid.Col>
+ <Grid.Col
+ fluid
+ data-islandid={`${RepositoryFilesDiffsList.name}$$0`}
+ style={{ marginTop: 24 }}
+ >
+ <RepositoryFilesDiffsList
+ filesDiffs={filesDiffs}
+ themeScheme={commonProps.themeScheme}
+ orgSlug={parentOrg.slug}
+ repoSlug={repo.slug}
+ commitHash={lastCommit != null ? lastCommit.commit : "HEAD"}
+ />
</Grid.Col>
</Grid.Col>
</PageWrapper>