1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-12-22 09:13:19 +01:00

refactor header & footer, add github token auth

This commit is contained in:
Matthias Kretschmann 2019-11-10 13:17:13 +01:00
parent cc4c256824
commit fda8949627
Signed by: m
GPG Key ID: 606EEEF3C479A91F
11 changed files with 101 additions and 152 deletions

1
.env.example Normal file
View File

@ -0,0 +1 @@
#GITHUB_TOKEN=

View File

@ -35,7 +35,12 @@ async function getGithubRepos(data) {
const repoName = item.split('/')[1] const repoName = item.split('/')[1]
const repo = await axios.get( const repo = await axios.get(
`https://api.github.com/repos/${user}/${repoName}`, `https://api.github.com/repos/${user}/${repoName}`,
{ headers: { 'User-Agent': 'kremalicious/portfolio' } } {
headers: {
'User-Agent': 'kremalicious/portfolio',
Authorization: `token ${process.env.GITHUB_TOKEN}`
}
}
) )
holder.name = repo.data.name holder.name = repo.data.name

View File

@ -25,7 +25,6 @@
}, },
"dependencies": { "dependencies": {
"axios": "^0.19.0", "axios": "^0.19.0",
"classnames": "^2.2.6",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",
"gatsby": "^2.17.10", "gatsby": "^2.17.10",
"gatsby-image": "^2.2.30", "gatsby-image": "^2.2.30",

View File

@ -1,8 +1,7 @@
import React, { PureComponent } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Link, StaticQuery, graphql } from 'gatsby' import { Link, graphql, useStaticQuery } from 'gatsby'
import posed from 'react-pose' import posed from 'react-pose'
import classNames from 'classnames'
import { moveInBottom } from '../atoms/Transitions' import { moveInBottom } from '../atoms/Transitions'
import { ReactComponent as Logo } from '../../images/logo.svg' import { ReactComponent as Logo } from '../../images/logo.svg'
import styles from './LogoUnit.module.scss' import styles from './LogoUnit.module.scss'
@ -16,40 +15,24 @@ const query = graphql`
} }
` `
export default class LogoUnit extends PureComponent { LogoUnit.propTypes = {
static propTypes = { minimal: PropTypes.bool
minimal: PropTypes.bool }
}
export default function LogoUnit({ minimal }) {
Animation = posed.div(moveInBottom) const data = useStaticQuery(query)
const Animation = posed.div(moveInBottom)
nameClasses = classNames('p-name', [styles.title]) const { title, tagline } = data.metaYaml
descriptionClasses = classNames('p-job-title', [styles.description])
return (
render() { <Animation>
const wrapClasses = classNames([styles.logounit], { <Link className={minimal ? styles.minimal : styles.logounit} to={'/'}>
[styles.minimal]: this.props.minimal <Logo className={styles.logo} />
}) <h1 className={`p-name ${styles.title}`}>{title.toLowerCase()}</h1>
<p className={`p-job-title ${styles.description}`}>
return ( {tagline.toLowerCase()}
<StaticQuery </p>
query={query} </Link>
render={data => { </Animation>
const { title, tagline } = data.metaYaml )
return (
<this.Animation>
<Link className={wrapClasses} to={'/'}>
<Logo className={styles.logo} />
<h1 className={this.nameClasses}>{title.toLowerCase()}</h1>
<p className={this.descriptionClasses}>
{tagline.toLowerCase()}
</p>
</Link>
</this.Animation>
)
}}
/>
)
}
} }

View File

@ -48,8 +48,8 @@
} }
.minimal { .minimal {
composes: logounit;
pointer-events: all; pointer-events: all;
width: auto;
&, &,
&:hover, &:hover,

View File

@ -1,45 +1,35 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import posed from 'react-pose' import posed from 'react-pose'
import classNames from 'classnames'
import { moveInTop } from '../atoms/Transitions' import { moveInTop } from '../atoms/Transitions'
import LinkIcon from '../atoms/LinkIcon' import LinkIcon from '../atoms/LinkIcon'
import { useMeta } from '../../hooks/use-meta' import { useMeta } from '../../hooks/use-meta'
import icons from '../atoms/Icons.module.scss' import icons from '../atoms/Icons.module.scss'
import styles from './Networks.module.scss' import styles from './Networks.module.scss'
const Animation = posed.aside(moveInTop) export default function Networks({ small, hide }) {
const linkClasses = key =>
classNames({
'u-url': key !== 'Email',
'u-email': key === 'Email',
[styles.link]: true
})
const Networks = ({ small, hide }) => {
const { social } = useMeta() const { social } = useMeta()
if (hide) return null
const wrapClasses = classNames([styles.networks], { const Animation = posed.aside(moveInTop)
[styles.small]: small
}) const linkClasses = key =>
key === 'Email' ? `u-email ${styles.link}` : `u-url ${styles.link}`
return ( return (
!hide && ( <Animation className={small ? styles.small : styles.networks}>
<Animation className={wrapClasses}> {Object.keys(social).map((key, i) => (
{Object.keys(social).map((key, i) => ( <a
<a className={linkClasses(key)}
className={linkClasses(key)} href={social[key]}
href={social[key]} key={i}
key={i} data-testid={`network-${key.toLowerCase()}`}
data-testid={`network-${key.toLowerCase()}`} >
> <LinkIcon title={key} className={icons.icon} />
<LinkIcon title={key} className={icons.icon} /> <span className={styles.title}>{key}</span>
<span className={styles.title}>{key}</span> </a>
</a> ))}
))} </Animation>
</Animation>
)
) )
} }
@ -47,5 +37,3 @@ Networks.propTypes = {
small: PropTypes.bool, small: PropTypes.bool,
hide: PropTypes.bool hide: PropTypes.bool
} }
export default Networks

View File

@ -52,6 +52,8 @@
} }
.small { .small {
composes: networks;
.link { .link {
padding: $spacer / 4; padding: $spacer / 4;
margin-left: $spacer / 4; margin-left: $spacer / 4;

View File

@ -1,7 +1,6 @@
import React, { PureComponent } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { StaticQuery, graphql } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import classNames from 'classnames'
import Vcard from '../atoms/Vcard' import Vcard from '../atoms/Vcard'
import LogoUnit from '../molecules/LogoUnit' import LogoUnit from '../molecules/LogoUnit'
import Networks from '../molecules/Networks' import Networks from '../molecules/Networks'
@ -22,34 +21,29 @@ const query = graphql`
} }
` `
const FooterMarkup = ({ pkg, meta, year }) => { const FooterMarkup = ({ pkg, meta, year }) => (
const classes = classNames('h-card', [styles.footer]) <footer className={`h-card ${styles.footer}`}>
<LogoUnit minimal />
<Networks minimal />
return ( <p className={styles.actions}>
<footer className={classes}> <Vcard />
<LogoUnit minimal /> <a className="u-key" href={meta.gpg}>
PGP/GPG key
<Networks minimal /> </a>
<a href={pkg.bugs}>Found a bug?</a>
<p className={styles.actions}> </p>
<Vcard /> <p className={styles.copyright}>
<a className="u-key" href={meta.gpg}> <small>
PGP/GPG key &copy; {year}{' '}
</a> <a className="u-url" href={meta.url}>
<a href={pkg.bugs}>Found a bug?</a> {meta.title}
</p> </a>{' '}
<p className={styles.copyright}> &mdash; All Rights Reserved
<small> </small>
&copy; {year}{' '} </p>
<a className="u-url" href={meta.url}> </footer>
{meta.title} )
</a>{' '}
&mdash; All Rights Reserved
</small>
</p>
</footer>
)
}
FooterMarkup.propTypes = { FooterMarkup.propTypes = {
pkg: PropTypes.object.isRequired, pkg: PropTypes.object.isRequired,
@ -57,20 +51,11 @@ FooterMarkup.propTypes = {
year: PropTypes.number.isRequired year: PropTypes.number.isRequired
} }
export default class Footer extends PureComponent { export default function Footer() {
state = { year: new Date().getFullYear() } const data = useStaticQuery(query)
const pkg = data.portfolioJson
const meta = data.metaYaml
const year = new Date().getFullYear()
render() { return <FooterMarkup year={year} pkg={pkg} meta={meta} />
return (
<StaticQuery
query={query}
render={data => {
const pkg = data.portfolioJson
const meta = data.metaYaml
return <FooterMarkup year={this.state.year} pkg={pkg} meta={meta} />
}}
/>
)
}
} }

View File

@ -1,7 +1,6 @@
import React, { PureComponent } from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { StaticQuery, graphql } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import classNames from 'classnames'
import Networks from '../molecules/Networks' import Networks from '../molecules/Networks'
import Availability from '../molecules/Availability' import Availability from '../molecules/Availability'
import ThemeSwitch from '../molecules/ThemeSwitch' import ThemeSwitch from '../molecules/ThemeSwitch'
@ -18,33 +17,19 @@ const query = graphql`
} }
` `
export default class Header extends PureComponent { Header.propTypes = {
static propTypes = { minimal: PropTypes.bool
minimal: PropTypes.bool }
}
export default function Header({ minimal }) {
render() { const { metaYaml } = useStaticQuery(query)
const { minimal } = this.props
return (
return ( <header className={minimal ? styles.minimal : styles.header}>
<StaticQuery <ThemeSwitch />
query={query} <LogoUnit minimal={minimal} />
render={data => { <Networks hide={minimal} />
const meta = data.metaYaml <Availability hide={minimal && !metaYaml.availability.status} />
const headerClasses = classNames([styles.header], { </header>
[styles.minimal]: minimal )
})
return (
<header className={headerClasses}>
<ThemeSwitch />
<LogoUnit minimal={minimal} />
<Networks hide={minimal} />
<Availability hide={minimal && !meta.availability.status} />
</header>
)
}}
/>
)
}
} }

View File

@ -13,6 +13,7 @@
} }
.minimal { .minimal {
composes: header;
min-height: 0; min-height: 0;
padding-top: $spacer * 2; padding-top: $spacer * 2;
padding-bottom: 0; padding-bottom: 0;

View File

@ -13,7 +13,7 @@ describe('Header', () => {
it('renders correctly', () => { it('renders correctly', () => {
const { container } = render( const { container } = render(
<Context.Provider value={{ dark: false, toggleDark: () => null }}> <Context.Provider value={{ darkMode: false, toggleDark: () => null }}>
<Header /> <Header />
</Context.Provider> </Context.Provider>
) )
@ -22,7 +22,7 @@ describe('Header', () => {
it('Availability can be hidden', () => { it('Availability can be hidden', () => {
const { container } = render( const { container } = render(
<Context.Provider value={{ dark: false, toggleDark: () => null }}> <Context.Provider value={{ darkMode: false, toggleDark: () => null }}>
<Header minimal={true} /> <Header minimal={true} />
</Context.Provider> </Context.Provider>
) )