import type { ReactIsland } from "@ethicdevs/react-monolith";
import React, { useCallback } from "react";
import styled, { css } from "styled-components";
import type {
RepositoryFile,
RepositoryLog,
WithThemeSchemeProp,
} from "../types";
import { Grid, TextEllipsis } from "../components";
import { NamedColors } from "../utils/style";
export interface RepositoryTreeViewProps {
currentPath: string;
currentRef: string;
lastCommit: RepositoryLog;
orgSlug: string;
repoFiles: RepositoryFile[];
repoSlug: string;
}
const RepositoryTreeView: ReactIsland<
RepositoryTreeViewProps & WithThemeSchemeProp
> = ({
themeScheme,
currentPath,
currentRef,
orgSlug,
repoFiles,
repoSlug,
}) => {
const buildRepoFileLink = useCallback(
(file: RepositoryFile) => {
const fileName = `${file.name}${file.type === "tree" ? "/" : ""}`;
return {
text: fileName,
href:
currentPath === "/"
? `/${orgSlug}/${repoSlug}/${encodeURIComponent(
currentRef
)}/tree/${encodeURIComponent(fileName)}`
: `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
currentPath.endsWith("/") || currentPath === ""
? currentPath
: `${currentPath}/`
}${encodeURIComponent(fileName)}`,
};
},
[orgSlug, repoSlug, currentPath]
);
const currPathParts = currentPath.split("/");
let prevPath: string | null = currPathParts
.slice(0, currPathParts.length - 2)
.join("/");
prevPath = prevPath.trim() === "" ? null : prevPath;
prevPath = prevPath == null ? "/" : prevPath;
const prevPathLink =
prevPath === "/"
? `/${orgSlug}/${repoSlug}`
: `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
prevPath.endsWith("/") ? prevPath : `${prevPath}/`
}`;
const shouldShowPrevPath = currentPath !== "/";
return (
<StyledRepositoryTreeViewContainer>
<Grid.Col fluid>
<Grid.Row
gap={8}
alignItems={"center"}
justifyContent={"flex-end"}
style={{
marginTop: 8,
width: "100%",
padding: "0 8px 8px 8px",
borderBottom: "1px solid gray",
}}
>
<a
href={`/${orgSlug}/${repoSlug}/${encodeURIComponent(
currentRef
)}/commits`}
>
Commits History
</a>
</Grid.Row>
<Grid.Col fluid nowrap>
<ul style={{ listStyle: "none", padding: 0, width: "100%" }}>
{shouldShowPrevPath && (
<li key={"go-previous"}>
<StyledTreeViewAnchorItem
href={prevPathLink}
themeScheme={themeScheme}
>
..
</StyledTreeViewAnchorItem>
</li>
)}
{repoFiles.map((file) => {
const fileLink = buildRepoFileLink(file);
return (
<li key={[file.id, file.name].join(":")}>
<StyledTreeViewAnchorItem
href={fileLink.href}
themeScheme={themeScheme}
>
<span style={{ flex: "0 0 240px" }}>{fileLink.text}</span>
{file.lastCommit != null && (
<>
<span style={{ flex: 1, marginLeft: 16 }}>
<TextEllipsis>{file.lastCommit.subject}</TextEllipsis>
</span>
<span style={{ marginLeft: 16 }}>
{file.lastCommit.abbreviated_commit}
</span>
</>
)}
</StyledTreeViewAnchorItem>
</li>
);
})}
</ul>
</Grid.Col>
</Grid.Col>
</StyledRepositoryTreeViewContainer>
);
};
const StyledTreeViewAnchorItem = styled.a<WithThemeSchemeProp>`
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
height: 30px;
width: 100%;
padding: 0 8px;
${({ themeScheme }) => css`
border-bottom: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};
&:hover {
background-color: ${NamedColors.CARD_OVERLAY[themeScheme]};
}
`}
`;
const StyledRepositoryTreeViewContainer = styled.div`
width: 100%;
`;
RepositoryTreeView.displayName = "RepositoryTreeView";
export default RepositoryTreeView;