Compare commits
No commits in common. "fdc412bf15cc33fb339b1040bbf2c138dec2346b" and "0d2074f1d43d8a183b5ed73825c48b7adbdd334f" have entirely different histories.
fdc412bf15
...
0d2074f1d4
@ -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",
|
||||
|
@ -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;
|
@ -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;
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 |
@ -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>
|
||||
)
|
||||
|
||||
|
@ -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;
|
||||
})}
|
||||
|
||||
|
@ -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 & 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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
)
|
||||
|
@ -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;
|
||||
})}
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
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 ProjectsPage = () => {
|
||||
const projects = [
|
||||
{
|
||||
name: 'Treadl',
|
||||
@ -79,51 +79,28 @@ const otherProjects = [
|
||||
}
|
||||
];
|
||||
|
||||
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
|
||||
|
@ -1,9 +1,9 @@
|
||||
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 ProjectsPage = () => {
|
||||
const outputs = [
|
||||
{
|
||||
name: 'Retweeting: A Study of Message-Forwarding in Twitter',
|
||||
@ -104,37 +104,15 @@ const outputs = [
|
||||
}
|
||||
];
|
||||
|
||||
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
|
||||
|
@ -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>
|
||||
|
@ -1,6 +0,0 @@
|
||||
import create from 'zustand'
|
||||
|
||||
export default create(set => ({
|
||||
theme: 'light',
|
||||
setTheme: theme => set({ theme }),
|
||||
}));
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user