Skip to content

Commit

Permalink
(merge, genoswitch#18): Add a footer
Browse files Browse the repository at this point in the history
Merge pull request genoswitch#18 from genoswitch/feat/footer-att2
  • Loading branch information
jcxldn authored Jul 3, 2023
2 parents dc89a44 + c53ba8f commit 83f3f76
Show file tree
Hide file tree
Showing 14 changed files with 343 additions and 0 deletions.
8 changes: 8 additions & 0 deletions data/sponsor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- name: John Carpenter Club
logoPath: logos/john-carpenter-club-transparent.png

- name: Roger Counter Foundation
logoPath: logos/roger-counter-foundation-transparent.png

- name: Barbers Livery Company
logoPath: logos/barbers-company-barber-surgeons-crest.png
4 changes: 4 additions & 0 deletions gatsby-config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { GatsbyConfig } from "gatsby";

import childProcess from "child_process";

const config: GatsbyConfig = {
siteMetadata: {
siteUrl: process.env.SITE_URL || "https://2023.igem.wiki/city-of-london-uk/",
assetBasePath: process.env.ASSET_BASE_PATH || "https://static.igem.wiki/teams/4642/wiki/",
// Use the git cli to get the latest commit hash.
sha: childProcess.execSync("git rev-parse --verify HEAD").toString().trim(),
},
pathPrefix: process.env.PATH_PREFIX || "/city-of-london-uk",
// More easily incorporate content into your pages through automatic TypeScript type generation and better GraphQL IntelliSense.
Expand Down
18 changes: 18 additions & 0 deletions src/components/footer/components/copyright.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from "react";

import { Grid, Link, Typography } from "@mui/material";

const Copyright = () => {
return (
<Grid item>
<Typography>
© 2023 - Content on this site is licensed under a{" "}
<Link underline="hover" target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
Creative Commons Attribution 4.0 International license.
</Link>
</Typography>
</Grid>
);
};

export default Copyright;
30 changes: 30 additions & 0 deletions src/components/footer/components/schoolLogos.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from "react";

import { Grid } from "@mui/material";

type SchoolLogoProps = {
assetPath: string;
size: number;
containerSx: object;
};

const SchoolLogos = ({ assetPath, size, containerSx }: SchoolLogoProps) => {
return (
<Grid item container spacing={0} sx={containerSx}>
<Grid item xs={size}>
<img
style={{ maxWidth: "100%", maxHeight: "100%" }}
src={assetPath + "logos/clsg-transparent.png"}
/>
</Grid>
<Grid item xs={size}>
<img
style={{ maxWidth: "100%", maxHeight: "100%" }}
src={assetPath + "logos/clsb-transparent.png"}
/>
</Grid>
</Grid>
);
};

export default SchoolLogos;
37 changes: 37 additions & 0 deletions src/components/footer/components/sourceAndSha.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from "react";

import { Button, Grid, Typography } from "@mui/material";

type SourceAndShaProps = {
longSha: string;
shortSha: string;
};

const SourceAndSha = ({ longSha, shortSha }: SourceAndShaProps) => {
return (
<Grid item xs={12} display="flex" alignItems="end">
{/** Source Code Button */}
<Button
variant="contained"
target="_blank"
href="https://gitlab.igem.org/2023/city-of-london-uk"
>
Source Code
</Button>
{/** SHA Text / Button */}
<Typography sx={{ paddingLeft: 2, color: "white" }}>
(SHA:{" "}
<Button
variant="text"
target="_blank"
href={`https://gitlab.igem.org/2023/city-of-london-uk/-/commit/${longSha}`}
>
{shortSha}
</Button>
)
</Typography>
</Grid>
);
};

export default SourceAndSha;
28 changes: 28 additions & 0 deletions src/components/footer/components/sponsorLogos.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from "react";

import { Grid } from "@mui/material";
import { SponsorNode } from "../../../types/graphql/sponsorNode";

type SponsorLogoProps = {
nodes: SponsorNode[];
assetPath: string;
containerSx: object;
elementSx: object;
size: number;
};

const SponsorLogos = ({ nodes, assetPath, containerSx, elementSx, size }: SponsorLogoProps) => {
return (
<Grid item container spacing={2} sx={containerSx}>
{nodes.map(node => {
return (
<Grid item xs={size} sx={elementSx}>
<img style={{ maxWidth: "100%", maxHeight: "100%" }} src={assetPath + node.logoPath} />
</Grid>
);
})}
</Grid>
);
};

export default SponsorLogos;
53 changes: 53 additions & 0 deletions src/components/footer/desktop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Grid, Paper } from "@mui/material";

import * as React from "react";

import SchoolLogos from "./components/schoolLogos";
import SponsorLogos from "./components/sponsorLogos";
import SourceAndSha from "./components/sourceAndSha";
import Copyright from "./components/copyright";

const DesktopFooter = ({ data }) => {
const assetPath = data.site.siteMetadata.assetBasePath;
const longSha = data.site.siteMetadata.sha;
const shortSha = longSha.substring(0, 8);

return (
<>
<Paper square sx={{ backgroundColor: "#0a1628", color: "white" }}>
{/** Root grid. Size: 12 columns (default) */}
<Grid container spacing={2}>
{/** Left side */}
<Grid container item xs={6}>
{/** Left: Source code */}
<SourceAndSha longSha={longSha} shortSha={shortSha} />
<Grid item xs={12}>
<Copyright />
</Grid>
</Grid>

{/** Right side */}
<Grid container xs={6}>
{/** Top Right: School Logos */}
<SchoolLogos
containerSx={{ justifyContent: "flex-end" }}
size={3}
assetPath={assetPath}
/>

{/** Bottom Right: Sponsor Logos */}
<SponsorLogos
containerSx={{ justifyContent: "flex-end" }}
elementSx={{ display: "flex", alignItems: "center" }}
size={2}
nodes={data.allSponsorYaml.nodes}
assetPath={assetPath}
/>
</Grid>
</Grid>
</Paper>
</>
);
};

export default DesktopFooter;
43 changes: 43 additions & 0 deletions src/components/footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from "react";

import useWindowDimensions from "../../hooks/useWindowDimensions";
import Widths from "../../widths";

import DesktopFooter from "./desktop";
import MobileFooter from "./mobile";

import { graphql } from "gatsby";

export const query = graphql`
# Split into fragments that can be added to other pages' queries.
# See team.tsx
fragment FooterSponsorYamlFragment on SponsorYamlConnection {
nodes {
name
logoPath
}
}
fragment FooterSiteFragment on Site {
siteMetadata {
sha
assetBasePath
}
}
`;

type FooterProps = {
data: Queries.Query;
};

const Footer = ({ data }: FooterProps) => {
const { width } = useWindowDimensions();
return (
<>
{/** iGEM 2022 Vilnius Lithuania: Use widths to determine which footer to display. */}
{width && width >= Widths.MD ? <DesktopFooter data={data} /> : <MobileFooter data={data} />}
</>
);
};

export default Footer;
45 changes: 45 additions & 0 deletions src/components/footer/mobile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as React from "react";

import { Grid, Paper } from "@mui/material";

import SponsorLogos from "./components/sponsorLogos";
import SchoolLogos from "./components/schoolLogos";
import SourceAndSha from "./components/sourceAndSha";
import Copyright from "./components/copyright";

const MobileFooter = ({ data }) => {
const assetPath = data.site.siteMetadata.assetBasePath;
const longSha = data.site.siteMetadata.sha;
const shortSha = longSha.substring(0, 8);

return (
<>
<Paper square sx={{ backgroundColor: "#0a1628", color: "white" }}>
{/** Root grid. Size: 12 columns (default) */}
<Grid container spacing={2}>
{/** Desktop: Top left (nothing yet) */}

{/** School Logos */}
<SchoolLogos containerSx={{}} size={6} assetPath={assetPath} />

{/** Sponsors */}
<SponsorLogos
containerSx={{}}
elementSx={{ display: "flex", alignItems: "center" }}
size={4}
nodes={data.allSponsorYaml.nodes}
assetPath={assetPath}
/>

{/** Source code button and SHA */}
<SourceAndSha longSha={longSha} shortSha={shortSha} />

{/** Copyright */}
<Copyright />
</Grid>
</Paper>
</>
);
};

export default MobileFooter;
16 changes: 16 additions & 0 deletions src/components/mdxPageTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import * as React from "react";
import NavBar from "./navbar";
import { Container } from "@mui/material";
import Footer from "./footer";
import { graphql, useStaticQuery } from "gatsby";

// GraphQL query containing fragments (sub-queries) for the footer
export const query = graphql`
query MdxPageData {
site {
...FooterSiteFragment
}
allSponsorYaml {
...FooterSponsorYamlFragment
}
}
`;

// Define a custom type so TypeScript understands what is being passed to the function
// Without a type, the "any" type is implicitly set.
Expand All @@ -10,11 +24,13 @@ type MdxPageTemplatePropTypes = {
};

const MdxPageTemplate = ({ children }: MdxPageTemplatePropTypes) => {
const data = useStaticQuery(query);
return (
<>
<NavBar />
<br />
<Container>{children}</Container>
<Footer data={data} />
</>
);
};
Expand Down
34 changes: 34 additions & 0 deletions src/hooks/useWindowDimensions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// useWindowDimensions.ts
// Sourced, unmodified from iGEM 2022 Vilnius Lithuania
// https://gitlab.igem.org/2022/vilnius-lithuania/-/blob/main/src/hooks/useWindowDimensions.ts

import { useState, useEffect } from "react";

function getWindowDimensions() {
if (typeof window !== `undefined`) {
const { innerWidth: width, innerHeight: height } = window;
return {
width,
height,
};
}
return {
width: undefined,
height: undefined,
};
}

export default function useWindowDimensions() {
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}

window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);

return windowDimensions;
}
6 changes: 6 additions & 0 deletions src/pages/team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import teamEntryFilter from "../filters/teamEntryFilter";
import Navbar from "../components/navbar";
import FilterMenu from "../components/team/filterMenu";
import LoadingPage from "../components/loadingPage";
import Footer from "../components/footer";

// TypeScript type def for the component state
// https://stackoverflow.com/questions/46987816/using-state-in-react-with-typescript
Expand Down Expand Up @@ -264,6 +265,7 @@ export default class TeamPage extends React.PureComponent<
this.state.filterChip,
this.state.shouldIncludeTagsInSearch
)}
<Footer data={this.data} />
</ThemeProvider>
);
}
Expand Down Expand Up @@ -310,6 +312,10 @@ export const query = graphql`
siteMetadata {
assetBasePath
}
...FooterSiteFragment
}
allSponsorYaml {
...FooterSponsorYamlFragment
}
}
`;
6 changes: 6 additions & 0 deletions src/types/graphql/sponsorNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { NodeUnneededKeys } from "./nodeUnneededKeys";

/**
* {@link Queries.SponsorYaml} without GraphQL specific keys
*/
export type SponsorNode = Omit<Queries.SponsorYaml, keyof NodeUnneededKeys>;
Loading

0 comments on commit 83f3f76

Please sign in to comment.