import type { ReactIsland } from "@ethicdevs/react-monolith";
import React from "react";
import type {
RepositoryFileDiff,
RepositoryFileDiffChunk,
WithThemeSchemeProp,
} from "../types";
import { AppRoute } from "../routes.defs";
import { Const } from "../const";
import { Card } from "../components/Card.styled";
import { Chip } from "../components/Chip";
import { Grid } from "../components/Grid";
import { NamedColors } from "../utils/style";
import { buildRouteLink } from "../utils/shared";
import Code, { getThemedCodeCss } from "../islands/Code";
export interface RepositoryFilesDiffsList {
filesDiffs: RepositoryFileDiff[];
orgSlug: string;
repoSlug: string;
commitHash: string;
}
const getChunkContent = (chunk: RepositoryFileDiffChunk): string => {
let sb = [] as string[];
sb.push(chunk.content);
chunk.changes.forEach((change) => sb.push(change.content));
return `${sb.join("\n")}\n`;
};
const RepositoryFilesDiffsList: ReactIsland<
RepositoryFilesDiffsList & WithThemeSchemeProp
> = ({ commitHash, filesDiffs, orgSlug, repoSlug, themeScheme }) => {
let codeCounter = 0;
return (
<>
{getThemedCodeCss(themeScheme)}
<Grid.Col fluid>
{filesDiffs.map(({ chunks, ...diff }, idx) => (
<Card
key={[diff.from, diff.to].join(":")}
style={{ marginTop: idx > 0 ? 16 : 0, width: "100%", padding: 8 }}
themeScheme={themeScheme}
>
<Grid.Col fluid nowrap>
<Grid.Row fluid nowrap gap={12} alignItems={"center"}>
{diff.from === "/dev/null" ? (
<Chip color={"rgb(43, 176, 90)"}>new file</Chip>
) : diff.to !== "/dev/null" ? (
<strong>{diff.from}</strong>
) : null}
{diff.to !== diff.from && (
<>
{diff.to !== "/dev/null" && diff.from !== "/dev/null" && (
<span>{" -> "}</span>
)}
{diff.to === "/dev/null" ? (
<>
<Chip color={"rgb(215, 44, 44)"}>file deleted</Chip>
<strong>{diff.from}</strong>
</>
) : (
<strong>{diff.to}</strong>
)}
</>
)}
</Grid.Row>
<Grid.Row
fluid
nowrap
alignItems={"center"}
style={{ marginTop: 8 }}
gap={16}
>
<div style={{ color: "rgb(43, 176, 90)" }}>
<strong>+</strong> <span>{diff.additions}</span>
</div>
<div style={{ color: "rgb(215, 44, 44)" }}>
<strong>-</strong> <span>{diff.deletions}</span>
</div>
<div>
<a
href={buildRouteLink(
AppRoute.REPOSITORY_BROWSER_WITH_PATH,
{
orgSlug,
repoSlug,
currentRef: commitHash,
"*": diff.to === "/dev/null" ? diff.from : diff.to,
}
)}
>
View file (current ref)
</a>
<a
href={buildRouteLink(
AppRoute.REPOSITORY_BROWSER_WITH_PATH,
{
orgSlug,
repoSlug,
currentRef: Const.PRIMARY_BRANCH_REF,
"*": diff.to === "/dev/null" ? diff.from : diff.to,
}
)}
style={{ marginLeft: 16 }}
>
View file (${Const.PRIMARY_BRANCH_REF})
</a>
</div>
</Grid.Row>
</Grid.Col>
<Grid.Col fluid style={{ marginTop: 8 }}>
{chunks.map((chunk, subIdx) => (
<div
data-islandid={`${Code.name}$$${codeCounter++}`}
key={[idx, subIdx, chunk.content].join(":")}
style={{ width: "100%" }}
>
<Code
code={getChunkContent(chunk)}
language={"diff"}
themeScheme={themeScheme}
style={{
borderTopLeftRadius: subIdx === 0 ? 8 : 0,
borderTopRightRadius: subIdx === 0 ? 8 : 0,
borderBottomLeftRadius:
subIdx === chunks.length - 1 ? 8 : 0,
borderBottomRightRadius:
subIdx === chunks.length - 1 ? 8 : 0,
}}
/>
{subIdx < chunks.length - 1 && (
<Grid.Row
fluid
alignItems={"center"}
style={{
height: 30,
width: "100%",
border: `1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]}`,
padding: "0 10px",
opacity: 0.7,
}}
>
...
</Grid.Row>
)}
</div>
))}
</Grid.Col>
</Card>
))}
</Grid.Col>
</>
);
};
RepositoryFilesDiffsList.displayName = "RepositoryFilesDiffsList";
export default RepositoryFilesDiffsList;