Compare commits

..

No commits in common. "fdc412bf15cc33fb339b1040bbf2c138dec2346b" and "0d2074f1d43d8a183b5ed73825c48b7adbdd334f" have entirely different histories.

22 changed files with 318 additions and 512 deletions

View File

@ -17,8 +17,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-helmet": "^5.2.1",
"styled-components": "^5.2.1",
"zustand": "^3.3.1"
"styled-components": "^5.2.1"
},
"scripts": {
"build": "gatsby build",

View File

@ -1,50 +0,0 @@
import React from 'react';
import styled from 'styled-components';
import useStore from '../store';
import Emoji from './Emoji';
const bgs = {
green: {
light: 'beige',
dark: 'darkolivegreen'
},
blue: {
light: 'aliceblue',
dark: 'steelblue',
},
orange: {
light: 'linen',
dark: 'sienna'
},
red: {
light: 'lightpink',
dark: 'mediumvioletred'
},
white: {
light: 'floralwhite',
dark: 'darkslategrey'
},
}
const StyledAlert = styled.div`
margin: 30px 0px;
padding: 10px;
border-radius: 3px;
background-color: ${p => bgs[p.colour][p.theme]};
color: ${p => p.theme === 'dark' ? 'white' : null};
h3{
margin-top: 0px;
}
`;
const Alert = ({ emoji, title, colour, children }) => {
const theme = useStore(s => s.theme);
return (
<StyledAlert colour={colour} theme={theme}>
<h3>{emoji && <Emoji e={emoji} />} {title}</h3>
{children}
</StyledAlert>
);
}
export default Alert;

View File

@ -2,20 +2,16 @@ import React from 'react'
import { Link } from 'gatsby'
import moment from 'moment';
import Emoji from './Emoji';
import Alert from './Alert';
import Tag from './Tag';
const BlogPostHeader = ({ post }) => (
<Alert
colour='white'
title={<span><Emoji e='📝' /> <Link to={post.fields.slug}>{post.frontmatter.title}</Link> <small>{moment(post.frontmatter.date).format('D MMMM YYYY')}</small></span>}
>
<div>
<div style={{marginBottom: '1.45rem', background: 'floralwhite', padding: 3, borderRadius: 3}}>
<h3><Emoji e='📝' /> <Link to={post.fields.slug}>{post.frontmatter.title}</Link> <small>{moment(post.frontmatter.date).format('D MMMM YYYY')}</small></h3>
<p><em>{post.excerpt}</em></p>
{post.frontmatter.tags && post.frontmatter.tags.map(tag => <Tag key={tag} tag={tag} />)}
{post.frontmatter.tags && post.frontmatter.tags.map(tag =>
<Link style={{marginRight: 10}} to={`/tags/${tag}`}><Emoji e="🏷️" /> #{tag}</Link>
)}
</div>
</Alert>
)
export default BlogPostHeader;

View File

@ -3,8 +3,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'
const ExternalLink = (props) => {
const isExternal = props.href.indexOf('http') === 0 && props.href.indexOf('wilw.dev') === -1;
return (
<a {...props} href={props.href} target="_blank" rel="noopener noreferrer">{props.children} <FontAwesomeIcon icon={faExternalLinkAlt} /></a>
<a {...props} href={props.href} target="_blank" rel="noopener noreferrer">{props.children} {isExternal && <FontAwesomeIcon icon={faExternalLinkAlt} />}</a>
);
}

View File

@ -2,10 +2,8 @@ import React from 'react'
import { Link } from 'gatsby'
import styled from 'styled-components';
import Emoji from './Emoji';
import useStore from '../store';
import { themes } from '../components/Layout/Layout'
import Will from '../images/will.jpeg';
import Will from '../images/will.jpg';
const StyledHeader = styled.header`
text-align: left;
@ -55,23 +53,8 @@ const StyledNavBar = styled.div`
font-size: 20px;
}
`;
const StyledThemeSelector = styled.select`
padding: 4px;
background: white;
border: 1px solid gray;
border-radius: 5px;
cursor: pointer;
`;
const Header = () => {
const store = useStore();
const switchTheme = themeName => {
store.setTheme(themeName);
localStorage.setItem('theme', themeName);
};
return (
const Header = () => (
<StyledHeader>
<StyledHeaderArea>
<Link to='/'><StyledAvatar /></Link>
@ -88,14 +71,8 @@ const Header = () => {
<Link to='/notes' activeClassName='active-link'>notes</Link>
<Link to='/projects' activeClassName='active-link'>projects</Link>
<Link to='/research' activeClassName='active-link'>research</Link>
<StyledThemeSelector value={store.theme} onChange={e => switchTheme(e.target.value)}>
{Object.keys(themes).map(themeName =>
<option key={themeName} value={themeName}>{themes[themeName].name}</option>
)}
</StyledThemeSelector>
</StyledNavBar>
</StyledHeader>
);
}
)
export default Header

View File

@ -12,6 +12,19 @@ html {
overflow-y: scroll;
}
a {
color: #01BAEF;
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active,
a:hover {
outline-width: 0;
}
a.active-link{
color:rgb(50,50,50);
}
body {
margin: 0;
font-family: 'Recursive', monospace;
@ -71,14 +84,6 @@ h4 {
line-height: 1.3;
}
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active, a:hover {
outline-width: 0;
}
p {
margin: 0px 0px 15px 0px;
}

View File

@ -1,47 +1,11 @@
import React, { useEffect } from 'react'
import React from 'react'
import Helmet from 'react-helmet'
import styled, { createGlobalStyle } from 'styled-components'
import styled from 'styled-components'
import Header from '../Header'
import Footer from '../Footer';
import useStore from '../../store';
import Will from '../../images/will.png';
import './Layout.css';
export const themes = {
light: {
name: '☀️ Light Theme',
background: 'white',
text: 'black',
links: '#01BAEF',
activeLinks: 'rgb(50,50,50)',
},
dark: {
name: '🌒 Dark Theme',
background: '#0f0e17',
text: '#a7a9be',
headers: '#fffffe',
links: '#ff8906',
activeLinks: 'rgb(200,200,200)',
}
}
const GlobalStyle = createGlobalStyle`
body{
background-color: ${({ theme }) => theme.background};
color: ${({ theme }) => theme.text};
transition: background-color 0.25s, color 0.25s;
}
h1,h2,h3,h4 {
color: ${({ theme }) => theme.headers};
}
a {
color: ${({ theme }) => theme.links};
&.active-link {
color: ${({ theme }) => theme.activeLinks};
}
}
`;
import './Layout.css'
const StyledMain = styled.div`
margin: 0px auto;
@ -49,23 +13,8 @@ const StyledMain = styled.div`
padding: 0px 1.1rem 1.45rem;
`;
const TemplateWrapper = ({ children }) => {
const theme = useStore(s => s.theme);
const setTheme = useStore(s => s.setTheme);
useEffect(() => {
const rememberedTheme = localStorage.getItem('theme');
if (rememberedTheme && themes[rememberedTheme]) {
setTheme(rememberedTheme);
} else {
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if (isDarkMode) setTheme('dark');
}
}, [setTheme]);
return (
const TemplateWrapper = ({ children }) => (
<div>
<GlobalStyle theme={themes[theme]} />
<Helmet titleTemplate="%s | Will Webberley" defaultTitle="Will Webberley">
<link rel="icon" type="image/png" href={Will} />
</Helmet>
@ -73,7 +22,6 @@ const TemplateWrapper = ({ children }) => {
<StyledMain>{children}</StyledMain>
<Footer />
</div>
);
}
)
export default TemplateWrapper

View File

@ -2,15 +2,16 @@ import React from 'react'
import { Link } from 'gatsby'
import moment from 'moment';
import Emoji from './Emoji';
import Alert from './Alert';
import Tag from './Tag';
const NoteHeader = ({ post }) => (
<Alert colour='blue'
title={<span><Emoji e='📔' /> <Link to={post.fields.slug}>{post.frontmatter.title}</Link> <small>(last updated {moment(post.frontmatter.date).format('D MMMM YYYY')})</small></span>}>
<div style={{marginBottom: '1.45rem', background: 'aliceblue', padding: 3, borderRadius: 3}}>
<h3><Emoji e='📔' /> <Link to={post.fields.slug}>{post.frontmatter.title}</Link> <small>(last updated {moment(post.frontmatter.date).format('D MMMM YYYY')})</small></h3>
<p>{post.frontmatter.description}</p>
{post.frontmatter.tags && post.frontmatter.tags.map(tag => <Tag key={tag} tag={tag} />)}
</Alert>
);
{post.frontmatter.tags && post.frontmatter.tags.map(tag =>
<Link style={{marginRight: 10}} to={`/tags/${tag}`}><Emoji e="🏷️" /> #{tag}</Link>
)}
</div>
)
export default NoteHeader;

View File

@ -1,15 +0,0 @@
import React from 'react';
import { Link } from 'gatsby';
import styled from 'styled-components';
import Emoji from '../components/Emoji';
const StlyedTag = styled(Link)`
margin-left: 10px;
`;
const Tag = ({ tag }) => (
<StlyedTag key={tag} to={`/tags/${tag}`}><Emoji e="🏷️" /> #{tag}</StlyedTag>
);
export default Tag;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -4,8 +4,8 @@ import Layout from '../components/Layout/Layout.js';
const ErrorPage = () => (
<Layout>
<h2>Not found</h2>
<p>The requested file could not be found.</p>
<h2 style={{fontFamily:'Courier, Monospace'}}>~/errors/404</h2>
<p>The requested file was not found.</p>
</Layout>
)

View File

@ -1,18 +1,12 @@
import React from "react";
import { graphql, Link } from 'gatsby';
import Helmet from 'react-helmet';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faRss } from '@fortawesome/free-solid-svg-icons';
import styled from 'styled-components';
import Helmet from 'react-helmet'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faRss } from '@fortawesome/free-solid-svg-icons'
import Layout from '../../components/Layout/Layout.js';
import BlogPostHeader from '../../components/BlogPostHeader';
const StyledHeader = styled.h2`
display: flex;
justify-content: space-between;
`;
export default class Blog extends React.Component {
render() {
@ -21,15 +15,12 @@ export default class Blog extends React.Component {
<Helmet title='Blog'>
<meta name="description" content="Blog post entries and articles" />
</Helmet>
<StyledHeader>
<span>Blog posts</span>
<small>
<FontAwesomeIcon icon={faRss} /> <Link to='/feeds'>RSS feeds</Link>
</small>
</StyledHeader>
<h2>Blog posts
<small style={{float: 'right'}}><FontAwesomeIcon icon={faRss} /> <Link to='/feeds'>RSS feeds</Link></small>
</h2>
{this.props.data.allMarkdownRemark.edges.map(({ node }) => {
if (node.fields.slug.includes('/blog/')) {
return <BlogPostHeader key={node.fields.slug} post={node} />;
return <BlogPostHeader post={node} />;
} else return null;
})}

View File

@ -7,7 +7,6 @@ import styled from 'styled-components';
import Layout from '../components/Layout/Layout.js';
import ExternalLink from '../components/ExternalLink';
import Emoji from '../components/Emoji';
import Alert from '../components/Alert';
const StyledButton = styled(ExternalLink)`
display: inline-block;
@ -65,20 +64,25 @@ const FeedsPage = () => {
<p>RSS lets you subscribe to receive new articles (blog posts, notes, etc.) as they are published.</p>
<p>My site has a number of different RSS feeds you can subscribe to, so you can choose the one(s) you want and avoid the content you're not interested in.</p>
<Alert colour='orange' title='Do you need an RSS reader?'>
<div style={{background: 'linen', padding: 10, borderRadius: 3, margin: '20px 0px'}}>
<h3>Do you need an RSS reader?</h3>
<p>There are lots of good ones. Just <ExternalLink href="https://duckduckgo.com/?q=rss+reader">search</ExternalLink> for one for your device.
I use <ExternalLink href="https://www.reederapp.com/">Reeder 5</ExternalLink> on my <ExternalLink href="https://itunes.apple.com/app/id1529448980">Mac</ExternalLink> and <ExternalLink href="https://apps.apple.com/app/id1529445840">iPhone</ExternalLink>.</p>
</Alert>
</div>
<h3><Emoji e='🌍' /> Recommended: enter <code>wilw.dev <StyledCopyButton onClick={copyFeedsUrl}><FontAwesomeIcon icon={faCopy} /></StyledCopyButton></code> into your RSS reader &amp; it should list the available feeds</h3>
<p>Alternatively you can choose a feed from the options below.</p>
<div style={{marginTop: 20}}>
{feeds.map(feed =>
<Alert key={feed.url} colour='green' title={<span><FontAwesomeIcon icon={faRssSquare} /> {feed.name}</span>}>
<div style={{background: 'whitesmoke', padding: 10, borderRadius: 3, margin: '20px 0px'}}>
<h3><FontAwesomeIcon icon={faRssSquare} /> {feed.name}</h3>
<p>{feed.description}</p>
<StyledButton href={feed.url}>Subscribe</StyledButton>
</Alert>
</div>
)}
</div>
</Layout>
);
}

View File

@ -6,7 +6,6 @@ import { faRss } from '@fortawesome/free-solid-svg-icons'
import Layout from '../components/Layout/Layout.js';
import Emoji from '../components/Emoji';
import Alert from '../components/Alert';
import ArticleHeader from '../components/ArticleHeader';
import ExternalLink from '../components/ExternalLink';
@ -18,12 +17,11 @@ const IndexPage = (props) => (
<p><Emoji n="Live long" e='🖖' /> Hello and welcome. I'm a tech lead/enthusiast based in Wales, UK. My main interests are indie and open-source projects, web and mobile technologies, serverless, IoT and automation.</p>
<Alert colour='green'
title={<span><Emoji e='💯' /> 100 Days to Offload</span>}
>
<div style={{background: 'beige', padding: '2px', borderRadius: 3, margin: '40px 0px'}}>
<h3><Emoji e='💯' /> 100 Days to Offload</h3>
<p>I'm taking part in the <ExternalLink href="https://100daystooffload.com/">100 Days to Offload challenge</ExternalLink> in 2021.</p>
<p><Link to='/blog/2021/01/29/100-days-to-offload'>Read more about it</Link> and <Link to='/tags/100daystooffload'>see what I've written so far</Link> for this challenge.</p>
</Alert>
</div>
<h3>Quick background</h3>
<p><Emoji e='💡' /> Since 2016 I have been Chief Technology Officer at enterprise SaaS company <ExternalLink href="https://simplydo.co.uk">Simply Do Ideas</ExternalLink>. Before this I was a software engineer at <ExternalLink href="https://www.chaserhq.com">Chaser</ExternalLink>.</p>
@ -48,7 +46,7 @@ const IndexPage = (props) => (
<h3>Recent posts</h3>
{props.data.recentPosts.edges
.map(({ node }) => node.fields.slug.indexOf('blog') > -1 ? <ArticleHeader key={node.fields.slug} post={node} /> : null)}
.map(({ node }) => node.fields.slug.indexOf('blog') > -1 ? <ArticleHeader post={node} /> : null)}
<p><Link to='/blog'>See more</Link></p>
</Layout>
)

View File

@ -17,7 +17,7 @@ export default class Notes extends React.Component {
<p>These are notes that I try and keep up-to-date. View <Link to='/blog'>my blog</Link> to see a post stream.</p>
{this.props.data.notesQuery.edges.map(({ node }) => {
if (node.fields.slug.includes('/notes/')) {
return <NoteHeader key={node.fields.slug} post={node} />;
return <NoteHeader post={node} />;
} else return null;
})}

View File

@ -1,16 +1,16 @@
import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faLaptop } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faLaptop } from '@fortawesome/free-solid-svg-icons'
import { faLinux, faApple, faAndroid, faGithub } from '@fortawesome/free-brands-svg-icons';
import Helmet from 'react-helmet';
import styled from 'styled-components';
import Helmet from 'react-helmet'
import Layout from '../components/Layout/Layout.js';
import treadlIcon from '../images/treadl.png';
import dottyIcon from '../images/dotty.png';
import ssotoolsIcon from '../images/ssotools.png';
const projects = [
const ProjectsPage = () => {
const projects = [
{
name: 'Treadl',
logo: treadlIcon,
@ -41,9 +41,9 @@ const projects = [
{ name: 'Web', icon: faLaptop }, { name: 'Android', icon: faAndroid, url: 'https://play.google.com/store/apps/details?id=app.trilo' }, { name: 'iOS', icon: faApple, url: 'https://itunes.apple.com/gb/app/trilo/id1460738681' }
]
},*/
];
];
const otherProjects = [
const otherProjects = [
{
name: 'Gower Tides',
description: 'An Android app for displaying daily tidal patterns, along with weather and surf conditions, for the sea around the Gower Peninsula in South Wales. The app was aimed at surfers and other sea-users, and was available for several years on Google Play, but is now discontinued.',
@ -77,53 +77,30 @@ const otherProjects = [
description: 'A project that supported simultaneous audio output (e.g. for music) across devices on a network. The project hooked into PulseAudio and made uss of RTP to broadcast sound to low-powered devices (such as a Raspberry Pi). Whilst I used to use this fairly frequently, the project is no longer being maintained.',
source: 'https://github.com/willwebberley/CasaStream'
}
];
];
const StyledProjects = styled.div`
display: grid;
grid-column-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
`;
const StyledProject = styled.div`
display: flex;
flex-direction: row;
margin-bottom: 30px;
border-bottom: 1px solid rgba(150,150,150,0.2);
`;
const StyledProjectImage = styled.div`
padding-right: 30px;
padding-top: 30px;
img{
width: 100px;
}
`;
const StyledPlatform = styled.a`
text-decoration: none;
margin-right: 15px;
`;
const ProjectsPage = () => (
return (
<Layout>
<Helmet title='Projects'>
<meta name="description" content="Projects I'm working on now and in the past" />
</Helmet>
<h2>Projects</h2>
<StyledProjects>
<div style={{display:'grid', gridColumnGap: 20, gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))'}}>
<div>
<p>Some of the things I am currently working on. Please <a href='https://twitter.com/willwebberley' target='_blank' rel='noopener noreferrer'>get in touch</a> if you are interested in finding out more about these (or if you'd like to help out or get involved!).</p>
{projects.map((p, i) =>
<StyledProject key={i}>
<StyledProjectImage>
<img alt={p.name} src={p.logo} />
</StyledProjectImage>
<div key={i} style={{display: 'flex', flexDirection: 'row', marginBottom: 30, borderBottom: '1px solid rgb(250,250,250)'}}>
<div style={{paddingRight: 30, paddingTop: 30}}>
<img alt={p.name} src={p.logo} style={{width: 100}} />
</div>
<div>
<h3><a href={p.url} target='_blank' rel='noopener noreferrer'>{p.name}</a></h3>
<p>{p.description}</p>
<p>{p.availableFor && p.availableFor.map((a, j) =>
<StyledPlatform key={j} href={a.url || p.url} target="_blank" rel="noopener noreferrer">{a.icon && <FontAwesomeIcon icon={a.icon} />} {a.name}</StyledPlatform>
<a key={j} href={a.url || p.url} target="_blank" rel="noopener noreferrer" style={{textDecoration: 'none', marginRight: 15}}>{a.icon && <FontAwesomeIcon icon={a.icon} />} {a.name}</a>
)}</p>
</div>
</StyledProject>
</div>
)}
</div>
<div>
@ -136,8 +113,9 @@ const ProjectsPage = () => (
</div>
)}
</div>
</StyledProjects>
</div>
</Layout>
);
)
}
export default ProjectsPage

View File

@ -1,10 +1,10 @@
import React from 'react';
import Helmet from 'react-helmet';
import styled from 'styled-components';
import React from 'react'
import Helmet from 'react-helmet'
import Layout from '../components/Layout/Layout.js';
const outputs = [
const ProjectsPage = () => {
const outputs = [
{
name: 'Retweeting: A Study of Message-Forwarding in Twitter',
date: '2011',
@ -102,39 +102,17 @@ const outputs = [
journal: 'IEEE Transactions on Computational Social Systems',
url: 'https://ieeexplore.ieee.org/iel7/6570650/6780646/08232468.pdf'
}
];
];
const StyledResearch = styled.div`
display: grid;
grid-column-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
`;
const StyledPublication = styled.div`
display: flex;
flex-direction: row;
margin-bottom: 10px;
border-bottom: 1px solid rgba(150,150,150,0.2);
`;
const PublicationTitle = styled.h4`
margin-top: 0px;
`;
const PublicationAuthors = styled.p`
margin-bottom: 0px;
font-size: 15px;
`;
const PublicationAttribution = styled.p`
font-size: 13px;
`;
const ProjectsPage = () => (
return (
<Layout>
<Helmet title='Research'>
<meta name="description" content="Research work papers and outputs" />
</Helmet>
<h2>Research</h2>
<StyledResearch>
<div style={{display:'grid', gridColumnGap: 20, gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))'}}>
<div>
<h3>Projects</h3>
<h3 style={{marginTop: 0}}>Projects</h3>
<p>I have been involved in a number of research projects.</p>
<h4>NIS/DAIS-ITA project</h4>
@ -145,19 +123,20 @@ const ProjectsPage = () => (
</div>
<div>
<h3>Publications</h3>
<h3 style={{marginTop: 0}}>Publications</h3>
{outputs.reverse().map((o, i) =>
<StyledPublication key={i}>
<div key={i} style={{display: 'flex', flexDirection: 'row', marginBottom: 10, borderBottom: '1px solid rgb(250,250,250)'}}>
<div>
<PublicationTitle><a href={o.url} target='_blank' rel='noopener noreferrer'>{o.name}</a></PublicationTitle>
<PublicationAuthors>{o.authors}</PublicationAuthors>
<PublicationAttribution>{o.journal}, {o.date}</PublicationAttribution>
<h4 style={{marginTop:0}}><a href={o.url} target='_blank' rel='noopener noreferrer'>{o.name}</a></h4>
<p style={{marginBottom:0, fontSize:15}}>{o.authors}</p>
<p style={{fontSize: 13}}>{o.journal}, {o.date}</p>
</div>
</div>
</StyledPublication>
)}
</div>
</StyledResearch>
</div>
</Layout>
);
)
}
export default ProjectsPage

View File

@ -29,8 +29,7 @@ const ThisPage = () => {
<p>This is a static site built using <ExternalLink href="https://www.gatsbyjs.com">GatsbyJS</ExternalLink> - an open-source generator that leverages React to build performant websites.</p>
<p>I deploy the site using <ExternalLink href="https://vercel.com">Vercel</ExternalLink>, which uses its network of CDN nodes to serve the static site assets.</p>
<p>I use the <ExternalLink href="https://www.recursive.design/">Recursive</ExternalLink> font.</p>
<p><ExternalLink href="https://www.happyhues.co">Happy Hues</ExternalLink> provides the inspiration for some of the colour themes.</p>
<p>The content and layout is hand-made by me. You can check out <ExternalLink href="https://git.wilw.dev/wilw/wilw.dev">the source code</ExternalLink> if you're interested.</p>
<p>The content and layout/theming is hand-made by me. You can check out <ExternalLink href="https://git.wilw.dev/wilw/wilw.dev">the source code</ExternalLink> if you're interested.</p>
<h2><Emoji e='' /> Other remarks</h2>
<p>The content on this site represents my own thoughts and opinions, and does not necessarily reflect the opinions of the people and companies I work with and for.</p>

View File

@ -1,6 +0,0 @@
import create from 'zustand'
export default create(set => ({
theme: 'light',
setTheme: theme => set({ theme }),
}));

View File

@ -8,8 +8,7 @@ import { config } from "@fortawesome/fontawesome-svg-core"
import "@fortawesome/fontawesome-svg-core/styles.css"
import Layout from '../components/Layout/Layout.js';
import Tag from '../components/Tag';
import Alert from '../components/Alert';
import Emoji from '../components/Emoji';
import ExternalLink from '../components/ExternalLink';
config.autoAddCss = false;
@ -27,30 +26,35 @@ export default class BlogPost extends React.Component {
<h1>{post.frontmatter.title}</h1>
<h4>{moment(post.frontmatter.date).format('D MMMM YYYY')} <i><small>({moment(post.frontmatter.date).fromNow()})</small></i>
{post.frontmatter.tags && post.frontmatter.tags.map(tag => <Tag tag={tag} key={tag} />)}
{post.frontmatter.tags && post.frontmatter.tags.map(tag =>
<Link style={{marginLeft: 10}} to={`/tags/${tag}`}><Emoji e="🏷️" /> #{tag}</Link>
)}
</h4>
{post.frontmatter.tags && post.frontmatter.tags.indexOf('100daystooffload') > -1 &&
<Alert colour='green' emoji='💯' title='100 Days to Offload'>
<div style={{background: 'beige', padding: 4, borderRadius: 3, margin: '20px 0px'}}>
<h3><Emoji e='💯' /> 100 Days to Offload</h3>
<p><b>This article is one of a series of posts in the <ExternalLink href="https://100daystooffload.com">100 Days to Offload challenge</ExternalLink></b>.
The challenge focuses on writing <strong>frequency</strong> rather than <strong>quality</strong>, and so posts may not always be fully planned out. They are simply a way to offload thoughts.</p>
<p><Link to='/tags/100daystooffload'>View other articles in this series</Link></p>
</Alert>
</div>
}
{post.frontmatter.tags && post.frontmatter.tags.indexOf('book') > -1 &&
<Alert colour='orange' emoji='📚' title='This article is about a book'>
<div style={{background: 'linen', padding: 4, borderRadius: 3, margin: '20px 0px'}}>
<h3><Emoji e='📚' /> This article is about a book</h3>
<p>A quick warning: I always try to avoid giving away spoilers but be careful if you're worried about finding out too much.</p>
</Alert>
</div>
}
{moment(post.frontmatter.date).isBefore(moment().subtract(12, 'months')) &&
<Alert colour='pink' emoji='🕰️' title='This is an old post'>
<div style={{background: 'lightpink', padding: 4, borderRadius: 3, margin: '20px 0px'}}>
<h3><Emoji e='🕰️' /> This is an old post</h3>
<p>Please note that this article was posted quite a while ago and may now be out-of-date or inaccurate.</p>
</Alert>
</div>
}
<article>
<article className='post' style={{marginTop: 10}}>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
@ -62,15 +66,17 @@ export default class BlogPost extends React.Component {
}
{post.frontmatter.tags && post.frontmatter.tags.indexOf('book') > -1 &&
<Alert colour='orange' emoji='📚' title='I try and read a wide variety of books'>
<div style={{background: 'linen', padding: 4, borderRadius: 3, margin: '20px 0px'}}>
<h3><Emoji e='📚' /> I try and read a wide variety of books</h3>
<p>If you're interested in seeing what else I read you can <a href="https://www.goodreads.com/user/show/22390023-will" target="_blank" rel="noopener noreferrer">check out my Goodreads profile</a>.</p>
</Alert>
</div>
}
<Alert colour='blue' emoji='📲' title='Enjoyed this article? Subscribe to updates!'>
<div style={{background: 'honeydew', padding: 4, borderRadius: 3, marginTop: 10}}>
<h3><Emoji e='📲' /> Enjoyed this article? Subscribe to updates!</h3>
<p>If you would like to read more posts like this, then you can subscribe via RSS.</p>
<p><FontAwesomeIcon icon={faRss} /> <Link to='/feeds'>Subscribe to an RSS feed</Link></p>
</Alert>
</div>
</Layout>
);
}

View File

@ -7,8 +7,6 @@ import { faArrowLeft } from '@fortawesome/free-solid-svg-icons'
import Layout from '../components/Layout/Layout.js';
import Emoji from '../components/Emoji';
import Alert from '../components/Alert';
import Tag from '../components/Tag';
export default class Note extends React.Component {
@ -23,17 +21,19 @@ export default class Note extends React.Component {
<h1>{note.frontmatter.title}</h1>
<h4>Last updated {moment(note.frontmatter.date).format('D MMMM YYYY')} <i><small>({moment(note.frontmatter.date).fromNow()})</small></i>
{note.frontmatter.tags && note.frontmatter.tags.map(tag => <Tag key={tag} tag={tag} />)}
{note.frontmatter.tags && note.frontmatter.tags.map(tag =>
<Link style={{marginLeft: 10}} to={`/tags/${tag}`}><Emoji e="🏷️" /> #{tag}</Link>
)}
</h4>
{moment(note.frontmatter.date).isBefore(moment().subtract(12, 'months')) &&
<Alert colour='pink' emoji='🕰️' title='This is an old note'>
<div style={{background: 'lightpink', padding: 4, borderRadius: 3, margin: '20px 0px'}}>
<h3><Emoji e='🕰️' /> This is an old note</h3>
<p>Please note that this article was last updated quite a while ago and may now be out-of-date or inaccurate.</p>
</Alert>
</div>
}
<article>
<article className='post' style={{marginTop: 10}}>
<div dangerouslySetInnerHTML={{ __html: note.html }} />
</article>
</Layout>

View File

@ -12378,11 +12378,6 @@ yurnalist@^2.1.0:
read "^1.0.7"
strip-ansi "^5.2.0"
zustand@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.3.1.tgz#de5c4b51112b84e0f819d8b3f336fbfbc087d758"
integrity sha512-o0rgrBsi29nCkPHdhtkAHisCIlmRUoXOV+1AmDMeCgkGG0i5edFSpGU0KiZYBvFmBYycnck4Z07JsLYDjSET9g==
zwitch@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"