Skip to content
Permalink
Browse files

New workshops site

  • Loading branch information...
lachlanjc committed Jan 28, 2018
1 parent dc262ca commit e0bc726c308e94c350c556490fbc248106acbbcc
Showing with 367 additions and 2 deletions.
  1. +63 −2 gatsby-node.js
  2. +1 −0 package.json
  3. +129 −0 src/pages/workshops/index.js
  4. +174 −0 src/pages/workshops/page.js
@@ -1,3 +1,64 @@
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage, createRedirect } = boundActionCreators
const path = require('path')

exports.onCreateNode = ({ node, boundActionCreators, getNode }) => {
const { createNodeField } = boundActionCreators
if (node.internal.type === 'MarkdownRemark') {
const fileNode = getNode(node.parent)
const parsedFilePath = path.parse(fileNode.relativePath)
if (!!parsedFilePath.dir) {
const value = `/workshops/${parsedFilePath.dir}`
createNodeField({ node, name: 'slug', value })
}
}
}

exports.createPages = ({ graphql, boundActionCreators }) => {
const { createPage } = boundActionCreators

return new Promise((resolve, reject) => {
const component = path.resolve('src/pages/workshops/page.js')
resolve(
graphql(
`
{
allMarkdownRemark(filter: { frontmatter: { name: { ne: null } } }) {
edges {
node {
frontmatter {
name
description
group
order
}
fields {
slug
}
}
}
}
}
`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}

const groupSet = new Set()
result.data.allMarkdownRemark.edges.forEach(edge => {
if (edge.node.frontmatter.category) {
groupSet.add(edge.node.frontmatter.group)
}

createPage({
path: edge.node.fields.slug,
component,
context: {
slug: edge.node.fields.slug
}
})
})
})
)
})
}
@@ -27,6 +27,7 @@
"gatsby-plugin-styled-components": "^2.0.5",
"gatsby-source-filesystem": "^1.5.15",
"gatsby-transformer-remark": "^1.7.30",
"lodash": "^4.17.4",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
@@ -0,0 +1,129 @@
import React, { Fragment } from 'react'
import {
ThemeProvider,
Box,
Button,
Card,
Container,
BackgroundImage,
Flex,
Heading,
LargeButton,
Link as A,
Section,
Text
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Link from 'gatsby-link'
import Nav from 'components/Nav'
import Footer from 'components/Footer'
import {
groupBy,
orderBy,
capitalize,
camelCase,
map,
fromPairs,
reverse,
toPairs
} from 'lodash'

const Header = Section.extend`
padding-top: 0 !important;
position: relative;
background-color: ${props => props.theme.colors.red[5]};
background-image: linear-gradient(
-16deg,
${props => props.theme.colors.orange[4]} 0%,
${props => props.theme.colors.red[5]} 50%,
${props => props.theme.colors.red[6]} 100%
);
`

const Group = Box.withComponent('section')

Button.link = Button.withComponent(Link)
A.link = A.withComponent(Link)
Card.img = Card.withComponent(BackgroundImage).extend`
text-shadow: 0 1px 2px rgba(0,0,0,.16);
`

const Grid = Box.withComponent('article').extend`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
grid-gap: ${props => props.theme.space[3]}px;
`

const WorkshopCard = ({ data, ...props }) => (
<A.link to={data.fields.slug} {...props}>
<Card.img
p={3}
boxShadowSize="md"
image={`https://splattered.now.sh/${camelCase(data.frontmatter.name)}`}
>
<Heading.h3 color="white" f={3} children={data.frontmatter.name} />
<Text color="snow" f={2} children={data.frontmatter.description} />
</Card.img>
</A.link>
)

export default ({ data: { allMarkdownRemark: { edges } } }) => {
let groups = groupBy(edges, 'node.frontmatter.group')
// hack to reverse sorting order of groups
groups = fromPairs(reverse(toPairs(groups)))
return (
<ThemeProvider>
<Helmet title="Workshops – Hack Club" />
<Header>
<Nav />
<Heading.h1 align="center" mt={3} mb={2}>
<Text f={4} caps>
Hack Club
</Text>
<Text f={6}>Workshops</Text>
</Heading.h1>
<Heading.h2 f={3} regular>
Learn to code through building projects.
</Heading.h2>
</Header>
<Container maxWidth={56} px={3} pb={5}>
{map(groups, (edges, name) => (
<Group>
<Heading.h2 f={4} mt={4} mb={2} caps>
{capitalize(name)}
</Heading.h2>
<Grid>
{map(edges, (edge, i) => (
<WorkshopCard data={edge.node} key={`workshops-${name}-${i}`} />
))}
</Grid>
</Group>
))}
</Container>
</ThemeProvider>
)
}

export const pageQuery = graphql`
query IndexQuery {
allMarkdownRemark(
filter: { frontmatter: { name: { ne: null } } }
sort: { fields: [frontmatter___order], order: ASC }
limit: 1024
) {
edges {
node {
fields {
slug
}
frontmatter {
name
description
group
order
}
}
}
}
}
`
@@ -0,0 +1,174 @@
import React, { Component, Fragment } from 'react'
import {
ThemeProvider,
Box,
Button,
Container,
Flex,
Heading,
Link as A,
Section
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Link from 'gatsby-link'
import Nav from 'components/Nav'
import Footer from 'components/Footer'
import { camelCase, join, map, range } from 'lodash'

const Header = Section.extend`
padding-top: 0 !important;
background-image: url(//splattered.now.sh/${props => camelCase(props.name)});
h1 {
mix-blend-mode: screen;
background-color: ${props => props.theme.colors.white};
color: ${props => props.theme.colors.black};
padding-left: ${props => props.theme.space[4]}px;
padding-right: ${props => props.theme.space[4]}px;
clip-path: polygon(4% 0%, 100% 0%, 96% 100%, 0% 100%);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16);
}
h2 {
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.16);
}
`

const Body = Box.extend`
color: ${props => props.theme.colors.black};
font-size: ${props => props.theme.fontSizes[2]};
a {
color: ${props => props.theme.colors.info};
}
h1:first-child {
display: none;
}
h1,
h2 {
padding-bottom: ${props => props.theme.space[2]}px;
border-bottom: 1px solid ${props => props.theme.colors.smoke};
}
hr {
border: 0;
height: 4px;
background-color: ${props => props.theme.colors.primary};
max-width: ${props => props.theme.space[7]}px;
margin: ${props => props.theme.space[4]}px auto;
border-radius: 4px;
}
pre,
code,
kbd {
font-family: ${props => props.theme.mono};
background-color: ${props => props.theme.colors.smoke};
color: ${props => props.theme.colors.black};
font-size: inherit;
br {
display: none;
}
}
del code {
text-decoration: inherit;
}
code {
border-radius: 2px;
padding-left: ${props => props.theme.space[1]}px;
padding-right: ${props => props.theme.space[1]}px;
}
pre {
word-wrap: normal;
padding: ${props => props.theme.space[3]}px;
border-radius: ${props => props.theme.radius};
> code {
padding: 0;
margin: 0;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
}
.highlight {
margin-bottom: ${props => props.theme.space[3]}px;
pre {
margin-bottom: 0;
word-break: normal;
}
}
.highlight pre,
pre {
overflow: auto;
font-size: 85%;
line-height: 1.45;
}
pre code,
pre tt {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
${props =>
join(
map(
range(1, 6),
level =>
`h${level} { font-size: ${props.theme.fontSizes[6 - level]}px; }`
),
''
)};
`

Button.home = Button.withComponent(Link)

export default ({
data: { markdownRemark: { frontmatter: { name, description, group }, html } }
}) => {
return (
<ThemeProvider>
<Helmet title={`${name} – Hack Club`} />
<Header name={name}>
<Nav />
<Heading.h1 f={[5, 6]} mt={[3, 4]} mb={2} children={name} />
<Heading.h2 f={[3, 4]} regular children={description} />
<Button.home to="/workshops" mt={[3, 4]} mb={2} inverted>
Get More Workshops
</Button.home>
</Header>
<Container maxWidth={42} p={3}>
<Body dangerouslySetInnerHTML={{ __html: html }} />
</Container>
<Footer />
</ThemeProvider>
)
}

export const pageQuery = graphql`
query WorkshopBySlug($path: String!) {
markdownRemark(fields: { slug: { eq: $path } }) {
html
frontmatter {
name
description
group
}
}
}
`

0 comments on commit e0bc726

Please sign in to comment.
You can’t perform that action at this time.