diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 0000000..6c64840 --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,14 @@ +version: 1 + +update_configs: + - package_manager: javascript + directory: / + update_schedule: live + allowed_updates: + - match: + update_type: security + automerged_updates: + - match: + dependency_type: all + update_type: in_range + version_requirement_updates: widen_ranges \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a4aa37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Project dependencies +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules +.cache/ +# Build directory +public/ +static/admin/*.bundle.* +.DS_Store +yarn-error.log diff --git a/README.md b/README.md index b4147b6..58e8d59 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,35 @@ -# website -GatsbyJs Repository for AK Dev Alliance website +# Alaska Developer Alliance Website + +This is the repository for the https://akdevalliance.com/ + +## Development + +### Clone & Run Locally + +Make sure you have `node v8.2.0` or higher installed. + +Pull down a local copy of the Github repository + +``` +$ git clone git@github.com:akdevalliance/website.git +$ cd website +$ yarn add global gatsby-dev-cli +$ yarn +$ yarn start +``` + +## Contributing + +1. Fork this repository to your own github account +2. Run `git checkout epic/gatsbyjs-redesign` to switch to this epic +3. Run `git checkout -b feature/your-branch-name-here` to create a new branch +4. Run `git commit -a --alow-empty` and enter something like "Empty commit to open {Your Branch Name Here} PR" +5. Run `git push -u origin HEAD` to push that new branch to your github repo +6. Create a new Pull Request from your repo targeting this `akdevalliance/website#epic/gatsbyjs-redesign` branch using a good title / description (bonus points: you can create checklist items using `* [ ] Title of checklist item`) +7. Add the `WIP` label to indicate that you are still working on it +8. Code away! +9. When you are ready, remove the `WIP` label and add `Needs Review` and add one or more people under the "Reviewers" section +10. Make any changes requested during the review process +11. When you get one or more `LGTM 👍` reponses from reviewers, hit merge, and pat yourself on the back +12. Find a new task on Trello +13. Rinse & repeat! diff --git a/_headers b/_headers new file mode 100644 index 0000000..4c2f41f --- /dev/null +++ b/_headers @@ -0,0 +1,4 @@ +[[headers]] +for = "/static/*" +[headers.values] +Cache-Control = "public, max-age=360000" \ No newline at end of file diff --git a/gatsby-config.js b/gatsby-config.js new file mode 100644 index 0000000..8ace2ed --- /dev/null +++ b/gatsby-config.js @@ -0,0 +1,71 @@ +module.exports = { + siteMetadata: { + title: "Alaska Developer Alliance", + description: + "The Alaska Developers Alliance is an organization focused on bringing together all segments of programmers from video game development and virtual reality to web development and enterprise software tooling. It was built as a community to get students plugged in earlier, provide continued learning opportunities for professionals, and inspire and educate the community. The Alliance bridges the geography of Alaska with chapters in Juneau, Anchorage, and Fairbanks, along with specific groups like the VMWare users group joining under the umbrella. It currently has over 200 members and regularly has meetups digitally joining all three locations including more than 50 people and streaming live on facebook." + }, + plugins: [ + "gatsby-plugin-react-helmet", + "gatsby-plugin-sass", + { + // keep as first gatsby-source-filesystem plugin for gatsby image support + resolve: "gatsby-source-filesystem", + options: { + path: `${__dirname}/static/img`, + name: "uploads" + } + }, + { + resolve: "gatsby-source-filesystem", + options: { + path: `${__dirname}/src/pages`, + name: "pages" + } + }, + { + resolve: "gatsby-source-filesystem", + options: { + path: `${__dirname}/src/img`, + name: "images" + } + }, + "gatsby-plugin-sharp", + "gatsby-transformer-sharp", + { + resolve: "gatsby-transformer-remark", + options: { + plugins: [ + { + resolve: "gatsby-remark-relative-images", + options: { + name: "uploads" + } + }, + { + resolve: "gatsby-remark-images", + options: { + // It's important to specify the maxWidth (in pixels) of + // the content container as this plugin uses this as the + // base for generating different widths of each image. + maxWidth: 2048 + } + }, + { + resolve: "gatsby-remark-copy-linked-files", + options: { + destinationDir: "static" + } + } + ] + } + }, + { + resolve: "gatsby-plugin-purgecss", // purges all unused/unreferenced css rules + options: { + develop: true, // Activates purging in npm run develop + purgeOnly: ["/all.sass"] // applies purging only on the bulma css file + } + }, // must be after other CSS plugins + "gatsby-plugin-netlify" // make sure to keep it last in the array + ] +}; diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..119e7ee --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,63 @@ +const _ = require("lodash"); +const path = require("path"); +const { createFilePath } = require("gatsby-source-filesystem"); +const { fmImagesToRelative } = require("gatsby-remark-relative-images"); + +exports.createPages = ({ actions, graphql }) => { + const { createPage } = actions; + + return graphql(` + { + allMarkdownRemark(limit: 1000) { + edges { + node { + id + fields { + slug + } + frontmatter { + templateKey + } + } + } + } + } + `).then(result => { + if (result.errors) { + result.errors.forEach(e => console.error(e.toString())); + return Promise.reject(result.errors); + } + + const documents = result.data.allMarkdownRemark.edges; + + documents.forEach(edge => { + const id = edge.node.id; + const templateKey = String(edge.node.frontmatter.templateKey); + + if (templateKey === "partner") return; + + createPage({ + path: edge.node.fields.slug, + component: path.resolve(`src/templates/${templateKey}.js`), + // additional data can be passed via context + context: { + id + } + }); + }); + }); +}; + +exports.onCreateNode = ({ node, actions, getNode }) => { + const { createNodeField } = actions; + fmImagesToRelative(node); // convert image paths for gatsby images + + if (node.internal.type === `MarkdownRemark`) { + const value = createFilePath({ node, getNode }); + createNodeField({ + name: `slug`, + node, + value + }); + } +}; diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..95c4f73 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,6 @@ +[build] + publish = "public" + command = "yarn build" +[build.environment] + YARN_VERSION = "1.9.4" + YARN_FLAGS = "--no-ignore-optional" diff --git a/package.json b/package.json new file mode 100644 index 0000000..0ce89f7 --- /dev/null +++ b/package.json @@ -0,0 +1,45 @@ +{ + "name": "alaska-developer-alliance", + "description": "The Alaska Developer Alliance Website", + "version": "0.0.1", + "author": "The Alaska Developer Alliance", + "dependencies": { + "bulma": "^0.7.0", + "gatsby": "^2.13.31", + "gatsby-image": "^2.0.23", + "gatsby-plugin-netlify": "^2.0.6", + "gatsby-plugin-purgecss": "^4.0.0", + "gatsby-plugin-react-helmet": "^3.0.4", + "gatsby-plugin-sass": "^2.0.7", + "gatsby-plugin-sharp": "^2.2.9", + "gatsby-remark-copy-linked-files": "^2.0.7", + "gatsby-remark-images": "^3.1.6", + "gatsby-remark-relative-images": "^0.2.1", + "gatsby-source-filesystem": "^2.0.26", + "gatsby-transformer-remark": "^2.6.9", + "gatsby-transformer-sharp": "^2.1.9", + "lodash": "^4.17.15", + "lodash-webpack-plugin": "^0.11.4", + "node-sass": "^4.11.0", + "parcel-bundler": "^1.9.4", + "prop-types": "^15.6.0", + "react": "^16.8.4", + "react-dom": "^16.8.4", + "react-helmet": "^5.2.0", + "uuid": "^3.2.1" + }, + "keywords": [], + "license": "MIT", + "main": "n/a", + "scripts": { + "clean": "gatsby clean", + "start": "yarn develop", + "build": "yarn clean && gatsby build", + "develop": "yarn clean && gatsby develop", + "format": "prettier --trailing-comma es5 --no-semi --single-quote --write \"{gatsby-*.js,src/**/*.js}\"", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "prettier": "^1.15.3" + } +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..16cbccc --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "extends": ["github>netlify/renovate-config:netlify-cms-starter"] +} diff --git a/src/components/Content.js b/src/components/Content.js new file mode 100644 index 0000000..99b487d --- /dev/null +++ b/src/components/Content.js @@ -0,0 +1,19 @@ +import React from 'react' +import PropTypes from 'prop-types' + +export const HTMLContent = ({ content, className }) => ( +
+) + +const Content = ({ content, className }) => ( +
{content}
+) + +Content.propTypes = { + content: PropTypes.node, + className: PropTypes.string, +} + +HTMLContent.propTypes = Content.propTypes + +export default Content diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js new file mode 100644 index 0000000..4961b34 --- /dev/null +++ b/src/components/DocumentList.js @@ -0,0 +1,80 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Link, graphql, StaticQuery } from "gatsby"; + +class DocumentList extends React.Component { + render() { + const { data } = this.props; + const { edges: documents } = data.allMarkdownRemark; + + return ( +
+ {documents && + documents.map(({ node: document }) => ( +
+
+
+

+ + {document.frontmatter.title} + +

+
+

+ {document.excerpt} +
+
+ + Keep Reading → + +

+
+
+ ))} +
+ ); + } +} + +DocumentList.propTypes = { + data: PropTypes.shape({ + allMarkdownRemark: PropTypes.shape({ + edges: PropTypes.array + }) + }) +}; + +export default () => ( + } + /> +); diff --git a/src/components/Features.js b/src/components/Features.js new file mode 100644 index 0000000..53368d5 --- /dev/null +++ b/src/components/Features.js @@ -0,0 +1,36 @@ +import React from 'react' +import PropTypes from 'prop-types' +import PreviewCompatibleImage from '../components/PreviewCompatibleImage' + +const FeatureGrid = ({ gridItems }) => ( +
+ {gridItems.map(item => ( +
+
+
+
+ +
+
+

{item.text}

+
+
+ ))} +
+) + +FeatureGrid.propTypes = { + gridItems: PropTypes.arrayOf( + PropTypes.shape({ + image: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), + text: PropTypes.string, + }) + ), +} + +export default FeatureGrid diff --git a/src/components/Footer.js b/src/components/Footer.js new file mode 100644 index 0000000..c32d583 --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,79 @@ +import React from "react"; +import { Link } from "gatsby"; + +import logo from "../img/logo.svg"; +import facebook from "../img/social/facebook.svg"; +import twitter from "../img/social/twitter.svg"; + +const Footer = class extends React.Component { + render() { + return ( +
+
+ Codi the Yeti +
+
+
+
+
+
+
    +
  • + + Home + +
  • +
  • + + About + +
  • +
  • + + Form Examples + +
  • +
+
+
+
+
+
    +
  • + + Contact + +
  • +
+
+
+ +
+
+
+
+ ); + } +}; + +export default Footer; diff --git a/src/components/Layout.js b/src/components/Layout.js new file mode 100644 index 0000000..8a244aa --- /dev/null +++ b/src/components/Layout.js @@ -0,0 +1,58 @@ +import React from "react"; +import { Helmet } from "react-helmet"; +import Footer from "../components/Footer"; +import Navbar from "../components/Navbar"; +import "./all.sass"; +import useSiteMetadata from "./SiteMetadata"; +import { withPrefix } from "gatsby"; + +const TemplateWrapper = ({ children }) => { + const { title, description } = useSiteMetadata(); + return ( +
+ + + {title} + + + + + + + + + + + + + + + +
{children}
+
+
+ ); +}; + +export default TemplateWrapper; diff --git a/src/components/LeadershipList.js b/src/components/LeadershipList.js new file mode 100644 index 0000000..d6237d1 --- /dev/null +++ b/src/components/LeadershipList.js @@ -0,0 +1,98 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Link, graphql, StaticQuery } from "gatsby"; +import PreviewCompatibleImage from "./PreviewCompatibleImage"; + +class LeadershipList extends React.Component { + render() { + const { data } = this.props; + const { edges: leaders } = data.allMarkdownRemark; + + return ( +
+ {leaders && + leaders.map(({ node: leader }) => ( +
+
+
+ {!!leader.frontmatter.image ? ( +
+ +
+ ) : null} +

+ + {leader.frontmatter.name} + + + + {leader.frontmatter.role} + +

+
+

{leader.frontmatter.bio}

+
+
+ ))} +
+ ); + } +} + +LeadershipList.propTypes = { + data: PropTypes.shape({ + allMarkdownRemark: PropTypes.shape({ + edges: PropTypes.array + }) + }) +}; + +export default () => ( + } + /> +); diff --git a/src/components/Navbar.js b/src/components/Navbar.js new file mode 100644 index 0000000..8c7bfba --- /dev/null +++ b/src/components/Navbar.js @@ -0,0 +1,93 @@ +import React from "react"; +import { Link } from "gatsby"; +import logo from "../img/logo.svg"; + +const Navbar = class extends React.Component { + constructor(props) { + super(props); + this.state = { + active: false, + navBarActiveClass: "" + }; + } + + toggleHamburger = () => { + // toggle the active boolean in the state + this.setState( + { + active: !this.state.active + }, + // after state has been updated, + () => { + // set the class in state for the navbar accordingly + this.state.active + ? this.setState({ + navBarActiveClass: "is-active" + }) + : this.setState({ + navBarActiveClass: "" + }); + } + ); + }; + + render() { + return ( + + ); + } +}; + +export default Navbar; diff --git a/src/components/PartnerList.js b/src/components/PartnerList.js new file mode 100644 index 0000000..9f0c063 --- /dev/null +++ b/src/components/PartnerList.js @@ -0,0 +1,89 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { graphql, StaticQuery } from "gatsby"; +import PreviewCompatibleImage from "./PreviewCompatibleImage"; + +class PartnerList extends React.Component { + render() { + const { data } = this.props; + const { edges: partners } = data.allMarkdownRemark; + + return ( +
+ {partners && + partners.map(({ node: partner }) => ( +
+ +
+ ))} +
+ ); + } +} + +PartnerList.propTypes = { + data: PropTypes.shape({ + allMarkdownRemark: PropTypes.shape({ + edges: PropTypes.array + }) + }) +}; + +export default () => ( + } + /> +); diff --git a/src/components/PreviewCompatibleImage.js b/src/components/PreviewCompatibleImage.js new file mode 100644 index 0000000..aeb4f15 --- /dev/null +++ b/src/components/PreviewCompatibleImage.js @@ -0,0 +1,34 @@ +import React from "react"; +import PropTypes from "prop-types"; +import Img from "gatsby-image"; + +const PreviewCompatibleImage = ({ imageInfo, style }) => { + const imageStyle = { ...style, borderRadius: "5px" }; + const { alt = "", childImageSharp, image } = imageInfo; + + if (!!image && !!image.childImageSharp) { + return ( + {alt} + ); + } + + if (!!childImageSharp) { + return {alt}; + } + + if (!!image && typeof image === "string") + return {alt}; + + return null; +}; + +PreviewCompatibleImage.propTypes = { + imageInfo: PropTypes.shape({ + alt: PropTypes.string, + childImageSharp: PropTypes.object, + image: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired, + style: PropTypes.object + }).isRequired +}; + +export default PreviewCompatibleImage; diff --git a/src/components/SiteMetadata.js b/src/components/SiteMetadata.js new file mode 100644 index 0000000..60450a3 --- /dev/null +++ b/src/components/SiteMetadata.js @@ -0,0 +1,19 @@ +import { graphql, useStaticQuery } from 'gatsby' + +const useSiteMetadata = () => { + const { site } = useStaticQuery( + graphql` + query SITE_METADATA_QUERY { + site { + siteMetadata { + title + description + } + } + } + ` + ) + return site.siteMetadata +} + +export default useSiteMetadata diff --git a/src/components/all.sass b/src/components/all.sass new file mode 100644 index 0000000..fb5c208 --- /dev/null +++ b/src/components/all.sass @@ -0,0 +1,124 @@ +@import "~bulma/sass/utilities/initial-variables" + +// Config vars +$akdev-blue: #2C5DC6 +$akdev-blue-invert: #fff + +$primary: $akdev-blue +$primary-invert: $akdev-blue-invert +$body-color: #333 +$black: #222222 + +.navbar .navbar-menu + box-shadow:none !important + +// Helper Classes +.full-width-image-container + width: 100vw + height: 400px + position: relative + left: 50% + right: 50% + margin: 2em -50vw + background-size: cover + background-position: bottom + display: flex + justify-content: center + align-items: center + +.full-width-image + width: 100vw + height: 400px + background-size: cover + background-position: bottom + display: flex + justify-content: center + align-items: center + +.btn + display: inline-block + padding: 12px 16px 10px + font-size: 18px + font-size: 1rem + line-height: 1.25 + background-color: #fff + border-radius: .25rem + text-decoration: none + font-weight: 700 + color: #CC3700 + text-align: center + -webkit-box-shadow: inset 0 0 0 2px #CC3700 + box-shadow: inset 0 0 0 2px #f40 + -webkit-transition: all .15s ease + transition: all .15s ease + +.margin-top-0 + margin-top: 0 !important + +.navbar-item .icon + color: $primary +// Override for use of svg's from https://simpleicons.org/ +.icon svg + width: 1.5rem + height: 1.5rem + fill: currentColor +.navbar-brand .navbar-item.logo + padding: 0 1rem +footer.footer + padding: 3rem 0rem 0rem + background-color: transparent + +//Menu overrides +$menu-item-color: $white-ter +$menu-item-hover-color: $black !important +$menu-item-hover-background-color: $black +$menu-item-active-color: $akdev-blue-invert +$menu-item-active-background-color: $akdev-blue-invert +$menu-list-border-left: 1px solid $akdev-blue-invert +$menu-label-color: $white-ter + + +.menu-label + font-size: 1em !important + text-align: left +.menu-list + list-style: none !important + text-align: left +.social + padding: 2em +.social a + padding: .5em .5em .3em .5em + border-radius: 1em + background-color: $white-ter + margin: .5em + width: 1em + height: 1em + vertical-align: middle + display: inline + +// blog roll +.blog-list-item.is-featured + background-color: #FFF; +.blog-list-item header + display: flex; + margin-bottom: 1em; +.blog-list-item .featured-thumbnail + flex-basis: 35%; + margin: 0 1.5em 0 0; + + +@import "~bulma" + + +// responsiveness ++tablet-only + .blog-list-item .featured-thumbnail + flex-basis: 50%; + ++mobile + .blog-list-item header + display: block + .blog-list-item .featured-thumbnail + text-align: center; + max-width: 70%; + margin: 0 0 1em; diff --git a/src/img/github-icon.svg b/src/img/github-icon.svg new file mode 100644 index 0000000..cc9e70f --- /dev/null +++ b/src/img/github-icon.svg @@ -0,0 +1,5 @@ + + + + +