import type { ReactView } from "@ethicdevs/react-monolith";
import React from "react";
import type { Organization, User } from "@prisma/client";
import type {
CommonProps,
LinguistFileInfos,
RepositoryFileContent,
RepositoryLog,
RepositoryWithForkedFromRepo,
} from "../../types";
import { buildRouteLink } from "../../utils/shared";
import { AppRoute } from "../../routes.defs";
import { Const } from "../../const";
import { NamedColors } from "../../utils/style";
import {
Card,
Grid,
IslandWrapper,
Layout,
PageWrapper,
Select,
TextEllipsis,
} from "../../components";
import Code, { getThemedCodeCss } from "../../islands/Code";
import RepositoryCommitSummaryLine from "../../islands/RepositoryCommitSummaryLine";
import RepositoryHero from "../../islands/RepositoryHero";
export interface RepositoryBrowserViewProps extends CommonProps {
branches: string[];
currentRef: string;
currentUser: null | User;
fileContent: RepositoryFileContent;
lastCommit: null | RepositoryLog;
linguistInfos: LinguistFileInfos;
parentOrg: Organization;
path: string;
repo: RepositoryWithForkedFromRepo;
}
const RepositoryBrowserView: ReactView<RepositoryBrowserViewProps> = ({
branches,
commonProps,
currentRef,
fileContent,
lastCommit,
linguistInfos,
parentOrg,
path,
repo,
}) => {
const currPathParts = path.split("/");
const shouldShowRootPath = path !== "/";
console.log("currentRef:", currentRef);
return (
<Layout {...commonProps}>
<PageWrapper>
<IslandWrapper data-islandid={`${RepositoryHero.name}$$0`}>
<RepositoryHero
forkedFromRepo={repo.forkedFromRepo}
forksCount={repo.forks.length}
parentOrg={parentOrg}
repo={repo}
/>
</IslandWrapper>
<Grid.Col fluid style={{ marginTop: 32 }}>
{lastCommit && (
<Card
data-islandid={`${RepositoryCommitSummaryLine.name}$$0`}
style={{ width: "100%", padding: 8 }}
themeScheme={commonProps.themeScheme}
>
<RepositoryCommitSummaryLine
commit={lastCommit}
currentRef={currentRef}
orgSlug={parentOrg.slug}
repoSlug={repo.slug}
/>
</Card>
)}
<Card
style={{
width: "100%",
marginTop: lastCommit != null ? 8 : 0,
padding: 8,
backdropFilter: "blur(8px)",
backgroundColor:
NamedColors.CARD_ALPHA_01[commonProps.themeScheme],
position: "sticky",
top: 80,
zIndex: 9000,
borderRadius: 8,
}}
themeScheme={commonProps.themeScheme}
>
<Grid.Row fluid nowrap alignItems={"center"} gap={8}>
<Select
themeScheme={commonProps.themeScheme}
title={"Branch"}
onChange={(e) => {
console.log("branch changed to: ", e.currentTarget.value);
window.__router.push(
buildRouteLink(AppRoute.REPOSITORY_BROWSER_WITH_PATH, {
orgSlug: parentOrg.slug,
repoSlug: repo.slug,
currentRef: e.currentTarget.value,
"*": path,
}),
);
}}
style={{
height: 32,
width: "auto",
minWidth: 80,
padding: "0 8px",
}}
>
{branches.map(
(branch, idx) =>
branch.trim() != "" && (
<option
key={branch}
value={branch}
selected={
branches.findIndex((b) => b === currentRef) === idx ||
(currentRef === Const.DEFAULT_HEAD_REF &&
branch === Const.PRIMARY_BRANCH_REF)
? true
: undefined
}
>
{branch}
</option>
),
)}
</Select>
{shouldShowRootPath && (
<a
title={`Go to root`}
href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
orgSlug: parentOrg.slug,
repoSlug: repo.slug,
})}
>
~
</a>
)}
{currPathParts.map(
(pathPart, idx, self) =>
pathPart.trim() !== "" &&
pathPart !== "/" && (
<a
key={[idx, pathPart].join(":")}
title={`Go to "${currPathParts
.slice(0, idx + 1)
.join("/")}${
idx === self.length - 1 && path.endsWith("/") === false
? '" file'
: '/" folder'
}`}
href={buildRouteLink(
AppRoute.REPOSITORY_BROWSER_WITH_PATH,
{
orgSlug: parentOrg.slug,
repoSlug: repo.slug,
currentRef,
"*": `${currPathParts.slice(0, idx + 1).join("/")}${
idx === self.length - 1 &&
path.endsWith("/") === false
? ""
: "/"
}`,
},
)}
>
<TextEllipsis>
{pathPart}
{idx === self.length - 1 && path.endsWith("/") === false
? ""
: "/"}
</TextEllipsis>
</a>
),
)}
</Grid.Row>
<div
style={{
height: 1,
margin: "8px 0",
background: NamedColors.BORDER_CARD[commonProps.themeScheme],
}}
/>
<Grid.Row
nowrap
gap={12}
alignItems={"center"}
style={{ width: "100%" }}
>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: 24,
width: 24,
background: linguistInfos.color,
borderRadius: 4,
color: "white",
fontSize:
linguistInfos.extensions.length > 0 &&
linguistInfos.extensions[0].slice(1).length <= 4
? linguistInfos.extensions[0].slice(1).length <= 2
? 12
: 9
: 6,
}}
>
{linguistInfos.extensions.length > 0
? linguistInfos.extensions[0]
: ""}
</div>
<div>
<strong>
{linguistInfos.languageDisplayName ||
`lang: ${linguistInfos.language}`}
</strong>
</div>
<div>
<span>({linguistInfos.mimeType})</span>
</div>
</Grid.Row>
</Card>
{linguistInfos.type === "image" ? (
<Card
style={{ width: "100%", marginTop: 8 }}
themeScheme={commonProps.themeScheme}
>
<img
src={fileContent.content}
style={{ width: "100%", height: "auto" }}
/>
</Card>
) : (
<>
{getThemedCodeCss(commonProps.themeScheme)}
<Card
data-islandid={`${Code.name}$$0`}
style={{
width: "100%",
marginTop: 8,
padding: 0,
border: "none",
}}
themeScheme={commonProps.themeScheme}
>
<Code
code={fileContent.content}
language={linguistInfos.language}
themeScheme={commonProps.themeScheme}
/>
</Card>
</>
)}
</Grid.Col>
</PageWrapper>
</Layout>
);
};
RepositoryBrowserView.displayName = "RepositoryBrowserView";
export default RepositoryBrowserView;