diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index a2aa747..0000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,5 +0,0 @@ -version: "2" -checks: - method-lines: - config: - threshold: 50 # Gatsby's StaticQuery makes render functions pretty long diff --git a/package.json b/package.json index 8181776..ff08668 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,11 @@ }, "dependencies": { "file-saver": "^1.3.8", - "gatsby": "^2.0.0-rc.11", + "gatsby": "^2.0.0-rc.13", "gatsby-image": "^2.0.0-rc.1", "gatsby-plugin-manifest": "^2.0.2-rc.1", "gatsby-plugin-matomo": "^0.5.0", - "gatsby-plugin-offline": "^2.0.0-rc.3", + "gatsby-plugin-offline": "^2.0.0-rc.4", "gatsby-plugin-react-helmet": "^3.0.0-rc.1", "gatsby-plugin-sass": "^2.0.0-rc.2", "gatsby-plugin-sharp": "^2.0.0-rc.3", diff --git a/src/components/atoms/LogoUnit.jsx b/src/components/atoms/LogoUnit.jsx index 26cc43e..9ff67f6 100644 --- a/src/components/atoms/LogoUnit.jsx +++ b/src/components/atoms/LogoUnit.jsx @@ -4,11 +4,20 @@ import { StaticQuery, graphql } from 'gatsby' import Logo from '../svg/Logo' import styles from './LogoUnit.module.scss' -class LogoUnit extends PureComponent { - constructor(props) { - super(props) +const query = graphql` + query { + dataYaml { + title + tagline + } + } +` - this.state = { minimal: false } +class LogoUnit extends PureComponent { + state = { minimal: false } + + static propTypes = { + minimal: PropTypes.bool } checkMinimal = () => { @@ -28,14 +37,7 @@ class LogoUnit extends PureComponent { render() { return ( { const meta = data.dataYaml const { minimal } = this.state @@ -58,8 +60,4 @@ class LogoUnit extends PureComponent { } } -LogoUnit.propTypes = { - minimal: PropTypes.bool -} - export default LogoUnit diff --git a/src/components/atoms/SEO.jsx b/src/components/atoms/SEO.jsx index bbdb75f..f7aa79e 100644 --- a/src/components/atoms/SEO.jsx +++ b/src/components/atoms/SEO.jsx @@ -15,35 +15,37 @@ function truncate(n, useWordBoundary) { ) } -const SEO = ({ project }) => ( - ( + { const meta = data.dataYaml diff --git a/src/components/atoms/Typekit.js b/src/components/atoms/Typekit.js index 768d764..a5899d5 100644 --- a/src/components/atoms/Typekit.js +++ b/src/components/atoms/Typekit.js @@ -17,15 +17,17 @@ const TypekitScript = typekitID => ( ) +const query = graphql` + query { + dataYaml { + typekitID + } + } +` + const Typekit = () => ( { const { typekitID } = data.dataYaml diff --git a/src/components/atoms/Vcard.jsx b/src/components/atoms/Vcard.jsx index 5046b62..e430685 100644 --- a/src/components/atoms/Vcard.jsx +++ b/src/components/atoms/Vcard.jsx @@ -3,88 +3,43 @@ import { StaticQuery, graphql } from 'gatsby' import FileSaver from 'file-saver' import vCard from 'vcf' -const Vcard = () => ( - ( + { const meta = data.dataYaml - const constructVcard = () => { - const contact = new vCard() - const photoSrc = meta.avatar.childImageSharp.original.src - - // first, convert the avatar to base64, - // then construct all vCard elements - toDataURL( - photoSrc, - dataUrl => { - // stripping this data out of base64 string is required - // for vcard to actually display the image for whatever reason - const dataUrlCleaned = dataUrl - .split('data:image/jpeg;base64,') - .join('') - contact.set('photo', dataUrlCleaned, { - encoding: 'b', - type: 'JPEG' - }) - contact.set('fn', meta.title) - contact.set('title', meta.tagline) - contact.set('email', meta.email) - contact.set('url', meta.url, { type: 'Portfolio' }) - contact.add('url', meta.social.Blog, { type: 'Blog' }) - contact.set('nickname', 'kremalicious') - contact.add('x-socialprofile', meta.social.Twitter, { - type: 'twitter' - }) - contact.add('x-socialprofile', meta.social.GitHub, { - type: 'GitHub' - }) - - const vcard = contact.toString('3.0') - - downloadVcard(vcard) - }, - 'image/jpeg' - ) - } - - // Construct the download from a blob of the just constructed vCard, - // and save it to user's file system - const downloadVcard = vcard => { - const name = meta.addressbook.split('/').join('') - const blob = new Blob([vcard], { type: 'text/x-vcard' }) - FileSaver.saveAs(blob, name) - } - const handleAddressbookClick = e => { e.preventDefault() - constructVcard() + constructVcard(meta) } return ( @@ -101,6 +56,43 @@ const Vcard = () => ( /> ) +// Construct the download from a blob of the just constructed vCard, +// and save it to user's file system +const downloadVcard = (vcard, meta) => { + const name = meta.addressbook.split('/').join('') + const blob = new Blob([vcard], { type: 'text/x-vcard' }) + FileSaver.saveAs(blob, name) +} + +const constructVcard = meta => { + const contact = new vCard() + const photoSrc = meta.avatar.childImageSharp.original.src + + // first, convert the avatar to base64, then construct all vCard elements + toDataURL( + photoSrc, + dataUrl => { + // stripping this data out of base64 string is required + // for vcard to actually display the image for whatever reason + const dataUrlCleaned = dataUrl.split('data:image/jpeg;base64,').join('') + contact.set('photo', dataUrlCleaned, { encoding: 'b', type: 'JPEG' }) + contact.set('fn', meta.title) + contact.set('title', meta.tagline) + contact.set('email', meta.email) + contact.set('url', meta.url, { type: 'Portfolio' }) + contact.add('url', meta.social.Blog, { type: 'Blog' }) + contact.set('nickname', 'kremalicious') + contact.add('x-socialprofile', meta.social.Twitter, { type: 'twitter' }) + contact.add('x-socialprofile', meta.social.GitHub, { type: 'GitHub' }) + + const vcard = contact.toString('3.0') + + downloadVcard(vcard, meta) + }, + 'image/jpeg' + ) +} + // Helper function to create base64 string from avatar image // without the need to read image file from file system const toDataURL = (src, callback, outputFormat) => { diff --git a/src/components/molecules/Availability.jsx b/src/components/molecules/Availability.jsx index 8023caf..56dfbea 100644 --- a/src/components/molecules/Availability.jsx +++ b/src/components/molecules/Availability.jsx @@ -4,25 +4,25 @@ import { StaticQuery, graphql } from 'gatsby' import { MoveIn } from '../atoms/Animations' import styles from './Availability.module.scss' -class Availability extends PureComponent { - constructor(props) { - super(props) +const query = graphql` + query { + dataYaml { + availability { + status + available + unavailable + } + } } +` + +export default class Availability extends PureComponent { + static propTypes = { hide: PropTypes.bool } render() { return ( { const { availability } = data.dataYaml const { status, available, unavailable } = availability @@ -53,9 +53,3 @@ class Availability extends PureComponent { ) } } - -Availability.propTypes = { - hide: PropTypes.bool -} - -export default Availability diff --git a/src/components/molecules/Head.jsx b/src/components/molecules/Head.jsx index e7482e5..e6e062b 100644 --- a/src/components/molecules/Head.jsx +++ b/src/components/molecules/Head.jsx @@ -4,16 +4,18 @@ import { StaticQuery, graphql } from 'gatsby' import SEO from '../atoms/SEO' import Typekit from '../atoms/Typekit' +const query = graphql` + query { + dataYaml { + title + tagline + } + } +` + const Head = () => ( { const { title, tagline } = data.dataYaml diff --git a/src/components/molecules/Networks.jsx b/src/components/molecules/Networks.jsx index 33fd395..5cb1d1f 100644 --- a/src/components/molecules/Networks.jsx +++ b/src/components/molecules/Networks.jsx @@ -12,6 +12,20 @@ import Dribbble from '../svg/Dribbble' import icons from '../atoms/Icons.module.scss' import styles from './Networks.module.scss' +const query = graphql` + query { + dataYaml { + social { + Email + Blog + Twitter + GitHub + Dribbble + } + } + } +` + const NetworkIcon = props => { switch (props.title) { case 'Email': @@ -29,13 +43,14 @@ const NetworkIcon = props => { } } -class Network extends PureComponent { - constructor(props) { - super(props) +export default class Network extends PureComponent { + static propTypes = { + minimal: PropTypes.bool, + hide: PropTypes.bool + } - this.state = { - classes: styles.networks - } + state = { + classes: styles.networks } componentDidMount() { @@ -57,19 +72,7 @@ class Network extends PureComponent { render() { return ( { const meta = data.dataYaml @@ -92,10 +95,3 @@ class Network extends PureComponent { ) } } - -Network.propTypes = { - minimal: PropTypes.bool, - hide: PropTypes.bool -} - -export default Network diff --git a/src/components/molecules/ProjectNav.jsx b/src/components/molecules/ProjectNav.jsx index c7c0f42..784b02a 100644 --- a/src/components/molecules/ProjectNav.jsx +++ b/src/components/molecules/ProjectNav.jsx @@ -5,6 +5,26 @@ import Img from 'gatsby-image' import FullWidth from '../atoms/FullWidth' import styles from './ProjectNav.module.scss' +const query = graphql` + query { + allProjectsYaml { + edges { + node { + title + slug + img { + childImageSharp { + fluid(maxWidth: 500, quality: 85) { + ...GatsbyImageSharpFluid_noBase64 + } + } + } + } + } + } + } +` + const ProjectLink = ({ node }) => ( ( ) -class ProjectNav extends Component { - constructor(props) { - super(props) - - this.state = { - scrolledToCurrent: false - } - - this.scrollToCurrent = this.scrollToCurrent.bind(this) +export default class ProjectNav extends Component { + state = { + scrolledToCurrent: false } componentDidMount() { @@ -54,25 +68,7 @@ class ProjectNav extends Component { return ( { const projects = data.allProjectsYaml.edges @@ -111,5 +107,3 @@ ProjectLink.propTypes = { ProjectNav.propTypes = { slug: PropTypes.string } - -export default ProjectNav diff --git a/src/components/molecules/ThemeSwitch.jsx b/src/components/molecules/ThemeSwitch.jsx index fbc8dcd..9bda3dc 100644 --- a/src/components/molecules/ThemeSwitch.jsx +++ b/src/components/molecules/ThemeSwitch.jsx @@ -5,20 +5,20 @@ import Day from '../svg/Day' import Night from '../svg/Night' import styles from './ThemeSwitch.module.scss' -const ThemeToggle = props => ( +const ThemeToggle = ({ dark }) => ( - + - + ) -class ThemeSwitch extends PureComponent { - constructor(props) { - super(props) +ThemeToggle.propTypes = { + dark: PropTypes.bool +} - this.state = { dark: null } - } +export default class ThemeSwitch extends PureComponent { + state = { dark: null } isDark = () => this.state.dark === true @@ -78,9 +78,3 @@ class ThemeSwitch extends PureComponent { ) } } - -ThemeToggle.propTypes = { - dark: PropTypes.bool -} - -export default ThemeSwitch diff --git a/src/components/organisms/Footer.jsx b/src/components/organisms/Footer.jsx index 8cdc9ab..4139d63 100644 --- a/src/components/organisms/Footer.jsx +++ b/src/components/organisms/Footer.jsx @@ -1,62 +1,66 @@ import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' import { StaticQuery, graphql } from 'gatsby' import Vcard from '../atoms/Vcard' import LogoUnit from '../atoms/LogoUnit' import Networks from '../molecules/Networks' import styles from './Footer.module.scss' -class Footer extends PureComponent { - constructor(props) { - super(props) +const query = graphql` + query { + # the package.json file + portfolioJson { + name + homepage + repository + bugs + } - this.state = { year: new Date().getFullYear() } + dataYaml { + title + gpg + } } +` + +const FooterMarkup = ({ meta, pkg, year }) => ( + +) + +FooterMarkup.propTypes = { + meta: PropTypes.object, + pkg: PropTypes.object, + year: PropTypes.number +} + +export default class Footer extends PureComponent { + state = { year: new Date().getFullYear() } render() { return ( { const pkg = data.portfolioJson const meta = data.dataYaml - return ( - - ) + return }} /> ) } } - -export default Footer diff --git a/src/components/organisms/Header.jsx b/src/components/organisms/Header.jsx index 5249bd5..cb6d18e 100644 --- a/src/components/organisms/Header.jsx +++ b/src/components/organisms/Header.jsx @@ -7,12 +7,18 @@ import ThemeSwitch from '../molecules/ThemeSwitch' import LogoUnit from '../atoms/LogoUnit' import styles from './Header.module.scss' -class Header extends PureComponent { - constructor(props) { - super(props) - - this.state = { minimal: false } +const query = graphql` + query { + dataYaml { + availability { + status + } + } } +` + +export default class Header extends PureComponent { + state = { minimal: false } checkMinimal = () => { const { isHomepage } = this.props @@ -34,15 +40,7 @@ class Header extends PureComponent { return ( { const meta = data.dataYaml @@ -68,5 +66,3 @@ class Header extends PureComponent { Header.propTypes = { isHomepage: PropTypes.bool } - -export default Header diff --git a/src/pages/404.jsx b/src/pages/404.jsx index c75e3f6..3ddb414 100644 --- a/src/pages/404.jsx +++ b/src/pages/404.jsx @@ -12,12 +12,11 @@ import './404.scss' const giphyClient = giphyAPI('LfXRwufRyt6PK414G2kKJBv3L8NdnxyR') const tag = 'fail-cat' -class NotFound extends Component { - constructor(props) { - super(props) - this.state = { gif: '' } +export default class NotFound extends Component { + state = { gif: '' } - this.handleClick = this.handleClick.bind(this) + static propTypes = { + location: PropTypes.object } componentDidMount() { @@ -36,7 +35,7 @@ class NotFound extends Component { }) } - handleClick(e) { + handleClick = e => { e.preventDefault() this.getRandomGif() } @@ -64,9 +63,3 @@ class NotFound extends Component { ) } } - -NotFound.propTypes = { - location: PropTypes.object -} - -export default NotFound