Skip to content

Commit

Permalink
feat: add a link to turn back to my apps page
Browse files Browse the repository at this point in the history
Closes #543.
  • Loading branch information
svedova committed Apr 5, 2024
1 parent 2b73e71 commit e3f9024
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 154 deletions.
39 changes: 9 additions & 30 deletions src/components/AppName/AppName.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@ import mockApp from "~/testing/data/mock_app";
import AppName from "./AppName";

interface Props {
displayName?: string;
withLinkToRepo?: boolean;
app: App;
}

describe("~/components/AppName/AppName.tsx", () => {
let wrapper: RenderResult;
let app: App;

const createWrapper = ({ displayName, withLinkToRepo }: Props) => {
const createWrapper = ({ app }: Props) => {
wrapper = render(
<MemoryRouter>
<AppName
repo={app.repo}
displayName={displayName}
withLinkToRepo={withLinkToRepo}
/>
<AppName app={app} />
</MemoryRouter>
);
};
Expand All @@ -28,33 +23,17 @@ describe("~/components/AppName/AppName.tsx", () => {
app = mockApp();
});

test("should display the app name without the display name", () => {
createWrapper({});
expect(wrapper.getByText("stormkit-io/frontend")).toBeTruthy();
expect(() => wrapper.getByText("app")).toThrow();
});
test("should display the app name with the display name and repo", () => {
createWrapper({ app });

test("should display the app name with the display name", () => {
createWrapper({ displayName: app.displayName });
expect(wrapper.getByText("stormkit-io/frontend")).toBeTruthy();
expect(wrapper.getByText("app")).toBeTruthy();
});

test("should contain a link to the repo", () => {
createWrapper({ withLinkToRepo: true });
const component = wrapper.getByLabelText("Repository URL");

expect(component.getAttribute("href")).toBe(
"https://gitlab.com/stormkit-io/frontend"
expect(wrapper.getByText("app").getAttribute("href")).toBe(
`/apps/${app.id}/environments`
);

expect(component.textContent).toBe("stormkit-io/frontend");
});

test("should contain a link to the repo", () => {
createWrapper({ withLinkToRepo: false });
expect(wrapper.getByText("stormkit-io/frontend")).toBeTruthy();
expect(wrapper.getByText("stormkit-io/frontend").getAttribute("href")).toBe(
null
"https://gitlab.com/stormkit-io/frontend"
);
});
});
96 changes: 28 additions & 68 deletions src/components/AppName/AppName.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import type { SxProps } from "@mui/material";
import Link from "@mui/material/Link";
import Box from "@mui/material/Box";
import githubLogo from "~/assets/logos/github-logo.svg";
import bitbucketLogo from "~/assets/logos/bitbucket-logo.svg";
import gitlabLogo from "~/assets/logos/gitlab-logo.svg";
import Typography from "@mui/material/Typography";
import { grey } from "@mui/material/colors";
import Dot from "~/components/Dot";
import { getLogoForProvider, parseRepo } from "~/utils/helpers/providers";

interface Props {
sx?: SxProps;
imageSx?: SxProps;
repo: string;
displayName?: string;
withLinkToRepo?: boolean;
wrapOnMobile?: boolean;
app: App;
imageSize?: number;
}

const providerHosts: Record<Provider, string> = {
Expand All @@ -20,79 +16,43 @@ const providerHosts: Record<Provider, string> = {
gitlab: "gitlab.com",
};

export default function AppName({
repo,
sx,
imageSx,
displayName,
withLinkToRepo,
wrapOnMobile,
}: Props) {
const pieces = repo.split("/") || [];
const provider = pieces.shift() as Provider;
const nameWithoutPrefix = pieces.join("/");
const logo =
provider === "github"
? githubLogo
: provider === "gitlab"
? gitlabLogo
: bitbucketLogo;
export default function AppName({ app, imageSize = 18 }: Props) {
const { repo, provider } = parseRepo(app.repo);
const providerLogo = getLogoForProvider(provider);
const linkToRepo = `https://${providerHosts[provider]}/${repo}`;

return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
...sx,
alignItems: "flex-start",
}}
>
<Box
component="img"
sx={{
display: "inline-block",
mr: 1,
width: 8,
...imageSx,
width: imageSize,
}}
src={logo}
src={providerLogo}
alt={provider}
/>
<Box>
{withLinkToRepo && (
<Link
href={`https://${providerHosts[provider]}/${nameWithoutPrefix}`}
aria-label="Repository URL"
target="_blank"
rel="noreferrer noopener"
sx={{ display: "block", ml: 1 }}
>
<Box
component="span"
sx={{
maxWidth: { xs: wrapOnMobile ? "150px" : "none", md: "none" },
whiteSpace: "nowrap",
overflow: "hidden",
display: "block",
textOverflow: "ellipsis",
}}
>
{nameWithoutPrefix}
</Box>
</Link>
)}
{!withLinkToRepo && nameWithoutPrefix}
{displayName && (
<Box
sx={{
fontSize: 12,
opacity: 0.7,
}}
>
{displayName}
</Box>
)}
</Box>

<Typography>
<Link href={`/apps/${app.id}/environments`}>{app.displayName}</Link>
</Typography>
<Dot />
<Typography>
<Link
href={linkToRepo}
target="_blank"
rel="noreferrer noopener"
sx={{ color: grey[500] }}
>
{repo}
</Link>
</Typography>
</Box>
);
}
45 changes: 24 additions & 21 deletions src/components/MenuLink/MenuLink.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Typography from "@mui/material/Typography";
import Link from "@mui/material/Link";

export interface Path {
Expand All @@ -13,27 +14,29 @@ interface Props {

export default function MenuLink({ item }: Props) {
return (
<Link
key={item.path}
href={item.path}
sx={{
cursor: "pointer",
color: "white",
px: { xs: 1, md: 2 },
py: 0.5,
display: "inline-flex",
position: "relative",
alignItems: "center",
borderRadius: 1,
bgcolor: item.isActive ? "rgba(255,255,255,0.05)" : undefined,
":hover": {
opacity: 1,
<Typography component="span">
<Link
key={item.path}
href={item.path}
sx={{
cursor: "pointer",
color: "white",
bgcolor: "rgba(255,255,255,0.1)",
},
}}
>
{item.text}
</Link>
px: { xs: 1, md: 2 },
py: 0.5,
display: "inline-flex",
position: "relative",
alignItems: "center",
borderRadius: 1,
bgcolor: item.isActive ? "rgba(255,255,255,0.05)" : undefined,
":hover": {
opacity: 1,
color: "white",
bgcolor: "rgba(255,255,255,0.1)",
},
}}
>
{item.text}
</Link>
</Typography>
);
}
6 changes: 6 additions & 0 deletions src/layouts/AppLayout/AppLayout.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ describe("~/layouts/AppLayout/Applayout.tsx", () => {
expect(links).toEqual([
"/", // Stormkit logo link
`/apps/${defaultApp.id}/usage`,
"/", // <- My apps Link
`/apps/${defaultApp.id}/environments`, // <- app display name link
"https://gitlab.com/stormkit-io/frontend",
`/apps/${defaultApp.id}/environments`,
`/apps/${defaultApp.id}/settings`,
Expand Down Expand Up @@ -99,6 +101,8 @@ describe("~/layouts/AppLayout/Applayout.tsx", () => {
expect(links).toEqual([
"/", // Stormkit logo link
`/apps/${defaultApp.id}/usage`,
"/", // <- My apps Link
`/apps/${defaultApp.id}/environments`, // <- app display name link
"https://gitlab.com/stormkit-io/frontend",
`/apps/${defaultApp.id}/environments`,
`/apps/${defaultApp.id}/settings`,
Expand Down Expand Up @@ -130,6 +134,8 @@ describe("~/layouts/AppLayout/Applayout.tsx", () => {
expect(links).toEqual([
"/", // Stormkit logo link
`/apps/${defaultApp.id}/usage`,
"/", // <- My apps Link
`/apps/${defaultApp.id}/environments`, // <- app display name link
"https://gitlab.com/stormkit-io/frontend",
`/apps/${defaultApp.id}/environments`,
`/apps/${defaultApp.id}/settings`,
Expand Down
10 changes: 7 additions & 3 deletions src/layouts/AppLayout/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import React, { useContext } from "react";
import { Route, Routes } from "react-router-dom";
import Box from "@mui/material/Box";
import AppContextProvider, { AppContext } from "~/pages/apps/[id]/App.context";
import { AuthContext } from "~/pages/auth/Auth.context";
import TopMenu from "../TopMenu";
import { useSelectedTeam } from "../TopMenu/Teams/actions";
import AppMenu from "./AppMenu";
import EnvMenu from "./EnvMenu";
import { routes } from "./routes";

export const AppLayout: React.FC = () => {
export function AppLayout() {
const { app, environments } = useContext(AppContext);
const { teams } = useContext(AuthContext);
const selectedTeam = useSelectedTeam({ teams, app });

if (environments.length === 0) {
return <></>;
Expand All @@ -23,7 +27,7 @@ export const AppLayout: React.FC = () => {
width: "100%",
}}
>
<TopMenu app={app} submenu={<AppMenu app={app} />} />
<TopMenu app={app} submenu={<AppMenu team={selectedTeam} app={app} />} />
<Box
sx={{
display: "flex",
Expand Down Expand Up @@ -55,7 +59,7 @@ export const AppLayout: React.FC = () => {
</Box>
</Box>
);
};
}

const WithAppProvider: React.FC = () => (
<AppContextProvider>
Expand Down
27 changes: 18 additions & 9 deletions src/layouts/AppLayout/AppMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { useMemo } from "react";
import { useLocation } from "react-router";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import ArrowBack from "@mui/icons-material/ArrowBack";
import AppName from "~/components/AppName";
import MenuLink from "~/components/MenuLink";
import { appMenuItems } from "./menu_items";

interface Props {
app: App;
team?: Team;
}

export default function AppMenu({ app }: Props) {
export default function AppMenu({ app, team }: Props) {
const { pathname } = useLocation();

const appMenu = useMemo(
Expand Down Expand Up @@ -37,14 +41,19 @@ export default function AppMenu({ app }: Props) {
alignItems: "center",
}}
>
<Box sx={{ mr: 2 }}>
<AppName
repo={app.repo}
withLinkToRepo
wrapOnMobile
sx={{ mr: 2 }}
imageSx={{ width: 28 }} // Same as Stormkit Icon
/>
<Box sx={{ mr: 2, display: "flex", alignItems: "center" }}>
<Button
variant="text"
sx={{ color: "white", mr: 2 }}
href={`/${team?.slug || ""}`}
size="small"
>
<ArrowBack sx={{ fontSize: 18, mr: 1 }} />
<Typography component="span">My Apps</Typography>
</Button>
<Box sx={{ pt: 0.25 /* fixes an alignment issue with buttons */ }}>
<AppName app={app} />
</Box>
</Box>
<Box>
{appMenu.map(item => (
Expand Down
25 changes: 2 additions & 23 deletions src/pages/apps/Apps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import SearchIcon from "@mui/icons-material/Search";
import ArrowForward from "@mui/icons-material/ArrowForwardIos";
import { AuthContext } from "~/pages/auth/Auth.context";
import ButtonDropdown from "~/components/ButtonDropdown";
import AppName from "~/components/AppName";
import Dot from "~/components/Dot";
import { parseRepo, getLogoForProvider } from "~/utils/helpers/providers";
import { useSelectedTeam } from "~/layouts/TopMenu/Teams/actions";
Expand Down Expand Up @@ -135,29 +136,7 @@ export default function Apps() {
</IconButton>
}
>
<Box
sx={{
display: "flex",
alignItems: "flex-start",
}}
>
<Box
component="img"
sx={{
display: "inline-block",
mr: 1,
width: 20,
}}
src={providerLogo}
alt={provider}
/>

<Typography>
<Link href={environmentsUrl}>{app.displayName}</Link>
</Typography>
<Dot />
<Typography color={grey[500]}>{repo}</Typography>
</Box>
<AppName app={app} />
</CardRow>
);
})}
Expand Down

0 comments on commit e3f9024

Please sign in to comment.