import React from "react";
import styled, { css } from "styled-components";
import { Const } from "../const";
import { Colors, NamedColors } from "../utils/style";
import {
type RepositoryCountersDTO,
type CommonViewProps,
type WithThemeSchemeProp,
} from "../types";
import { useMediaQuery } from "../utils/hooks/useMediaQuery";
import { buildRouteLink } from "../utils/shared";
import { AppRoute } from "../routes.defs";
import { Chip } from "./Chip";
import { TextEllipsis } from "./TextEllipsis.styled";
import { SupportIcon } from "./icons/SupportIcon";
import { SettingsIcon } from "./icons/SettingsIcon";
import { FolderIcon } from "./icons/FolderIcon";
import { CommentIcon } from "./icons/CommentIcon";
import { Grid } from "./Grid";
import { GitForkIcon } from "./icons/GitForkIcon";
import { GitPullIcon } from "./icons/GitPullIcon";
import { LikeIcon } from "./icons/LikeIcon";
export const DrawerPrimary = ({
visible = false,
commonProps,
themeScheme,
orgSlug,
repoSlug,
currentRef = Const.DEFAULT_HEAD_REF,
path = "/",
counters = {
pulls: 0,
tests: 0,
builds: 0,
issues: 0,
apiRefSymbols: 0,
},
}: WithThemeSchemeProp & {
visible: boolean;
commonProps: CommonViewProps;
orgSlug: string;
repoSlug: string;
currentRef?: string;
path?: string;
counters?: RepositoryCountersDTO;
}) => {
const pathRepo = buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
orgSlug: orgSlug,
repoSlug: repoSlug,
});
const pathRepoTrailing = buildRouteLink(
AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH,
{
orgSlug: orgSlug,
repoSlug: repoSlug,
},
);
const pathFiles = buildRouteLink(AppRoute.REPOSITORY_BROWSER, {
orgSlug: orgSlug,
repoSlug: repoSlug,
currentRef: currentRef,
"*": path,
});
const pathPulls = buildRouteLink(AppRoute.REPOSITORY_PULL_REQUESTS, {
orgSlug: orgSlug,
repoSlug: repoSlug,
});
if (visible === false) {
return null;
}
return (
<StyledDrawerPrimary id="drawer" themeScheme={themeScheme}>
<StyledDrawerHeader>
<StyledLogoArea themeScheme={themeScheme}>
<a href={"/"}>
<h1>{Const.APP_NAME}</h1>
</a>
</StyledLogoArea>
</StyledDrawerHeader>
<StyledDrawerContent>
<StyledDrawerListHeader style={{ margin: 0 }}>
<a href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, { orgSlug })}>
@{orgSlug}
</a>
<span>{" / "}</span>
<a
href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
orgSlug,
repoSlug,
})}
>
<TextEllipsis>{repoSlug}</TextEllipsis>
</a>
</StyledDrawerListHeader>
<StyledDrawerListHeader style={{ height: 32 }}>
<Grid.Row
fluid
nowrap
gap={8}
justifyContent={"center"}
alignItems={"center"}
>
<Grid.Row nowrap gap={4} alignItems={"center"}>
<GitPullIcon
color={NamedColors.TEXT_MUTED[themeScheme]}
size={16}
/>
<span style={{ fontSize: 11 }}>Watchers</span>
<Chip
themeScheme={themeScheme}
color={NamedColors.TEXT_MUTED[themeScheme]}
style={{
padding: "2px 6px",
backgroundColor: "rgba(0,0,0,0.1)",
fontSize: 11,
color: NamedColors.TEXT_MUTED[themeScheme],
}}
>
{counters.watchers || "0"}
</Chip>
</Grid.Row>
<Grid.Row nowrap gap={4} alignItems={"center"}>
<LikeIcon color={NamedColors.TEXT_MUTED[themeScheme]} size={16} />
<span style={{ fontSize: 11 }}>Likes</span>
<Chip
themeScheme={themeScheme}
color={NamedColors.TEXT_MUTED[themeScheme]}
style={{
padding: "2px 6px",
backgroundColor: "rgba(0,0,0,0.1)",
fontSize: 11,
color: NamedColors.TEXT_MUTED[themeScheme],
}}
>
{counters.likes || "0"}
</Chip>
</Grid.Row>
<Grid.Row nowrap gap={4} alignItems={"center"}>
<GitForkIcon color={Colors.WHITE_01} size={16} />
<span style={{ fontSize: 11 }}>Forks</span>
<Chip
themeScheme={themeScheme}
color={NamedColors.TEXT_MUTED[themeScheme]}
style={{
padding: "2px 6px",
backgroundColor: "rgba(0,0,0,0.1)",
fontSize: 11,
color: NamedColors.TEXT_MUTED[themeScheme],
}}
>
{counters.forks || "0"}
</Chip>
</Grid.Row>
</Grid.Row>
</StyledDrawerListHeader>
<StyledDrawerList>
<StyledDrawerListItem
themeScheme={themeScheme}
href={pathFiles}
className={
(commonProps.path!.startsWith(pathFiles) ||
[pathFiles, pathRepo, pathRepoTrailing].some(
(p) =>
commonProps.path === p || commonProps.path!.startsWith(p),
)) &&
commonProps.path!.startsWith(pathPulls) === false
? "active"
: undefined
}
style={{ paddingRight: 16 }}
>
<span>Files</span>
<FolderIcon
color={
(commonProps.path!.startsWith(pathFiles) ||
[pathFiles, pathRepo, pathRepoTrailing].some(
(p) =>
commonProps.path === p || commonProps.path!.startsWith(p),
)) &&
commonProps.path!.startsWith(pathPulls) === false
? NamedColors.TEXT_DEFAULT[themeScheme]
: NamedColors.TEXT_MUTED[themeScheme]
}
size={16}
/>
</StyledDrawerListItem>
<StyledDrawerListItem
themeScheme={themeScheme}
href={pathPulls}
className={
commonProps.path! === pathPulls ||
commonProps.path!.startsWith(pathPulls)
? "active"
: undefined
}
>
<span>Pull Requests</span>
<Chip themeScheme={themeScheme}>{counters.pulls || 0}</Chip>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Tests & Coverage</span>
<Chip themeScheme={themeScheme}>{counters.tests || 0}</Chip>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Builds</span>
<Chip themeScheme={themeScheme}>{counters.builds || 0}</Chip>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Issues</span>
<Chip themeScheme={themeScheme}>{counters.issues || 0}</Chip>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>API Reference</span>
<Chip themeScheme={themeScheme}>{counters.apiRefSymbols || 0}</Chip>
</StyledDrawerListItem>
</StyledDrawerList>
<StyledDrawerListHeader></StyledDrawerListHeader>
<StyledDrawerList></StyledDrawerList>
</StyledDrawerContent>
<StyledDrawerFooter>
<StyledDrawerList>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Feedback</span>
<CommentIcon
color={NamedColors.TEXT_MUTED[themeScheme]}
size={20}
/>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Help Center</span>
<span style={{ flex: 1 }}></span>
{counters.helpCenterNotifs! > 0 && (
<Chip themeScheme={themeScheme}>{counters.helpCenterNotifs}</Chip>
)}
<SupportIcon
color={NamedColors.TEXT_MUTED[themeScheme]}
size={20}
/>
</StyledDrawerListItem>
<StyledDrawerListItem themeScheme={themeScheme} disabled>
<span>Settings</span>
<SettingsIcon
color={NamedColors.TEXT_MUTED[themeScheme]}
size={20}
/>
</StyledDrawerListItem>
</StyledDrawerList>
</StyledDrawerFooter>
</StyledDrawerPrimary>
);
};
const StyledDrawerPrimary = styled.aside<
WithThemeSchemeProp & { color?: string }
>`
${({ themeScheme }) => css`
min-width: 300px;
max-width: 320px;
height: 100vh;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
position: sticky;
top: 0;
left: 0;
bottom: 0;
background: ${NamedColors.HEADER[themeScheme]};
border-right: 1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]};
@media only screen and (max-width: 386px) {
display: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 1000;
width: 85vw;
max-width: 320px;
transform: translateX(-100%);
&:target {
transform: translateX(0);
transition: transform 0.3s ease-in-out;
}
}
`};
`;
const StyledDrawerHeader = styled.header`
width: 100%;
height: 64px;
display: flex;
justify-content: center;
align-items: center;
`;
const StyledLogoArea = styled.div<WithThemeSchemeProp>`
@media only screen and (max-width: 768px) {
& > a > h1 {
font-size: 22px;
}
}
& > a {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
${({ themeScheme }) => css`
color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
`};
h1 {
margin: 0;
}
}
`;
const StyledDrawerContent = styled.main`
width: 100%;
max-width: 100%;
min-width: 100%;
height: 100%;
flex: 1;
padding: 12px;
overflow-y: auto;
`;
const StyledDrawerListHeader = styled.section`
width: 100%;
min-height: 40px;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
font-weight: bold;
margin-bottom: 12px;
& > span {
margin: 0 4px;
}
`;
const StyledDrawerList = styled.section`
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: center;
gap: 2px;
`;
const StyledDrawerListItem = styled.a<
WithThemeSchemeProp & { disabled?: boolean }
>`
${({ disabled, themeScheme }) => css`
width: 100%;
height: 40px;
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
padding: 0 12px;
font-weight: normal;
font-size: 14px;
color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
border-radius: 20px;
text-decoration: none;
& > span:nth-child(1) {
flex: 1;
}
& > ${Chip} {
color: ${NamedColors.TEXT_MUTED[themeScheme]};
background-color: ${NamedColors.CARD_OVERLAY[themeScheme]};
}
${(disabled == null || disabled === false) &&
css`
&.active,
&:not(:disabled):hover {
color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
background-color: ${NamedColors.CARD[themeScheme]};
font-weight: bold;
font-family: monospace;
}
`};
&:hover {
text-decoration: none;
}
&:disabled {
color: ${NamedColors.TEXT_MUTED[themeScheme]};
}
${disabled &&
css`
color: ${NamedColors.TEXT_MUTED[themeScheme]};
& > ${Chip} {
color: ${NamedColors.TEXT_MUTED[themeScheme]};
opacity: 0.3;
}
`}
`}
`;
const StyledDrawerFooter = styled.footer`
width: 100%;
height: 128px;
display: flex;
justify-content: flex-start;
align-items: center;
margin: 16px 0;
padding: 0 12px;
`;