Skip to content

Commit

Permalink
social icons and better author links (#1375)
Browse files Browse the repository at this point in the history
* Change Author links to an Array

This just loosely adapts the new schema to the existing template.

- Changed all author content files

- Updated schema

- Removed some dead data imports

Cherry-picked from the author page branch

* Add example content to work off of

* Enable viewboxes in SVGR components

This is next to no data (a few bytes per SVG max) and allows SVGR-based
components to be resized via CSS.

* Make Twitter icon color-neutral

Also update its current usage in the hamburger menu so it looks the same despite
the change.

* Overhaul Author Link schema

Author Links are now objects with a sort of subtype defined by their `site`
field. The node parser recognizes certain strings provided to the `links` field
and converts them to these objects pre-filled with the correct info (right now
it's Twitter, LinkedIn, and GitHub).

These objects can then be queried all throughout the site, whether it be for
social icons or a more detailed list.

Also worth noting that since `links` is an array, its order is maintained.

* Adapt FeedMeta to links and add a SocialIcon component

* Improve TS fix and move SocialIcon SVGs

* Remake string link processors

The string processors now have their own file with an object that links hostname
strings to processor functions that take a specific set of URL info gathered via
regex and return an object describing Author link represented by the string.

Now they're made of re-usable functional blocks, allowing for quick additions to
recognize other site types. This allows us to easily re-use common patterns like
"the username is the pathname with slashes stripped" while also being flexible
enough to accomodate any special case, as there will always be exceptions.

There's also tests for the new link parser.

* Combine link parser into one file

It can always be split later if additions make it cumbersome.

* Embed processStringLink and move WrongTypeError closer to where it's used.

* Improve LinkedIn handling

Change urls to include `www.` like canonical, and make it not a function chain
since we handle everything differently.

* Embed and simplify trimSlashes and fix LinkedIn test
  • Loading branch information
rogermparent authored May 31, 2020
1 parent 845d7b5 commit 6007482
Show file tree
Hide file tree
Showing 24 changed files with 358 additions and 42 deletions.
4 changes: 3 additions & 1 deletion content/authors/dmitry_petrov.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
name: Dmitry Petrov
avatar: dmitry_petrov.png
link: https://twitter.com/fullstackml
links:
- https://twitter.com/fullstackml
- https://www.linkedin.com/in/dmitryleopetrov
---

Creator of [http://dvc.org](http://dvc.org) — Git for ML. Ex-Data Scientist
Expand Down
3 changes: 2 additions & 1 deletion content/authors/elle_obrien.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: Elle O'Brien
avatar: elle_obrien.jpg
link: https://twitter.com/andronovhopf
links:
- https://twitter.com/andronovhopf
---

Data scientist at [http://dvc.org](http://dvc.org)
3 changes: 2 additions & 1 deletion content/authors/george_vyshnya.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: George Vyshnya
avatar: george_vyshnya.jpeg
link: https://www.linkedin.com/in/gvyshnya
links:
- https://www.linkedin.com/in/gvyshnya
---

Seasoned Data Scientist / Software Developer with blended experience in software
Expand Down
3 changes: 2 additions & 1 deletion content/authors/jorge_orpinel.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: Jorge Orpinel Pérez
avatar: jorge.jpg
link: https://www.linkedin.com/in/jorgeorpinel
links:
- https://www.linkedin.com/in/jorgeorpinel
---

Technical writer and developer at [dvc.org](http://dvc.org/)
3 changes: 2 additions & 1 deletion content/authors/marcel_rd.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: Marcel Ribeiro-Dantas
avatar: marcel.jpg
link: https://twitter.com/mribeirodantas
links:
- https://twitter.com/mribeirodantas
---

Early Stage Researcher at [Institut Curie](https://intstitut-curie.org) with
Expand Down
3 changes: 2 additions & 1 deletion content/authors/marija_ilic.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: Marija Ilić
avatar: marija_ilic.png
link: https://www.linkedin.com/in/marija-ili%C4%87-65b8a53
links:
- https://www.linkedin.com/in/marija-ili%C4%87-65b8a53
---

Data scientist at Njuškalo, Croatia.
3 changes: 2 additions & 1 deletion content/authors/svetlana_grinchenko.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
name: Svetlana Grinchenko
avatar: svetlana_grinchenko.jpeg
link: https://twitter.com/a142hr
links:
- https://twitter.com/a142hr
---

Head of developer relations at [http://dvc.org](http://dvc.org)
5 changes: 4 additions & 1 deletion gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ const plugins = [
{
resolve: 'gatsby-plugin-svgr',
options: {
ref: true
ref: true,
svgoConfig: {
plugins: [{ removeViewBox: false }]
}
}
},
'gatsby-transformer-sharp',
Expand Down
9 changes: 8 additions & 1 deletion src/components/Blog/Feed/Item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { graphql } from 'gatsby'
import Link from '../../../Link'
import Image, { FixedObject, FluidObject } from 'gatsby-image'
import cn from 'classnames'
import { ISocialIcon } from '../../../SocialIcon'

import FeedMeta from '../../FeedMeta'

Expand All @@ -28,6 +29,7 @@ export interface IBlogPostData {
avatar: {
fixed: FixedObject
}
links: Array<ISocialIcon>
}
}

Expand All @@ -40,7 +42,7 @@ const Item: React.FC<IBlogFeedItemProps> = ({
big,
feedPost: { title, description, date, picture, author, slug, timeToRead }
}) => {
const { avatar, name } = author
const { avatar, name, links } = author
const bodyRef = useRef<HTMLDivElement>(null)
const { width } = useWindowSize()
const [isOverflown, setIsOverflown] = useRafState(true)
Expand Down Expand Up @@ -84,6 +86,7 @@ const Item: React.FC<IBlogFeedItemProps> = ({
name={name}
avatar={avatar}
date={date}
links={links}
timeToRead={timeToRead}
/>
</div>
Expand Down Expand Up @@ -120,6 +123,10 @@ export const query = graphql`
}
author {
name
links {
url
site
}
avatar {
fixed(width: 40, height: 40, quality: 50, cropFocus: CENTER) {
...GatsbyImageSharpFixed_withWebp
Expand Down
23 changes: 12 additions & 11 deletions src/components/Blog/FeedMeta/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Link from '../../Link'
import { pluralizeComments } from '../../../utils/front/i18n'

import styles from './styles.module.css'
import SocialIcon, { ISocialIcon } from '../../SocialIcon'

interface IBlogFeedMetaProps {
avatar: {
Expand All @@ -15,7 +16,7 @@ interface IBlogFeedMetaProps {
date: string
name: string
timeToRead: string
link?: string
links: Array<ISocialIcon>
}

const FeedMeta: React.FC<IBlogFeedMetaProps> = ({
Expand All @@ -25,21 +26,21 @@ const FeedMeta: React.FC<IBlogFeedMetaProps> = ({
date,
name,
timeToRead,
link
links
}) => {
return (
<div className={styles.wrapper}>
<Image fixed={avatar.fixed} className={styles.avatar} />
<ul className={styles.list}>
<li className={styles.item}>
{link ? (
<Link href={link} className={styles.link}>
{name}
</Link>
) : (
name
)}
</li>
<li className={styles.segment}>{name}</li>
{links && (
<li className={styles.linkIcons}>
{links.map(({ site, url }, i) => (
<SocialIcon site={site} url={url} key={i} />
))}
</li>
)}

<li className={styles.item}>
{date}{timeToRead} min read
</li>
Expand Down
35 changes: 31 additions & 4 deletions src/components/Blog/FeedMeta/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,20 @@
padding: 0;
}

.item {
.segment {
@mixin text-secondary;

position: relative;
display: inline-block;
margin-right: 14px;
white-space: nowrap;
line-height: 20px;
color: var(--color-gray);
vertical-align: middle;
}

.item {
composes: segment;
white-space: nowrap;
position: relative;
margin-right: 14px;

&::before {
content: '• ';
Expand All @@ -38,6 +43,28 @@
}
}

.linkIcons {
composes: segment;
padding: 0 10px 0 0.1rem;
display: inline-block;

a {
display: inline-block;
box-sizing: border-box;
vertical-align: middle;
color: inherit;
width: 26px;
height: 26px;
padding: 0.2rem;
}

img,
svg {
width: 100%;
height: 100%;
}
}

.link {
@mixin link;
}
4 changes: 2 additions & 2 deletions src/components/Blog/Post/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Post: React.FC<IBlogPostData> = ({
descriptionLong,
commentsUrl,
tags,
author: { name, avatar, link },
author: { name, avatar, links },
slug
}) => {
const wrapperRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -79,7 +79,7 @@ const Post: React.FC<IBlogPostData> = ({
avatar={avatar}
date={date}
timeToRead={timeToRead}
link={link}
links={links}
/>
</div>
</div>
Expand Down
14 changes: 4 additions & 10 deletions src/components/HamburgerMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Link from '../Link'
import { logEvent } from '../../utils/front/ga'
import { getFirstPage } from '../../utils/shared/sidebar'
import { ReactComponent as LogoSVG } from '../../../static/img/logo-white.svg'
import { ReactComponent as TwitterIcon } from '../SocialIcon/twitter.svg'
import { ReactComponent as GithubIcon } from '../SocialIcon/github.svg'

import styles from './styles.module.css'

Expand Down Expand Up @@ -180,11 +182,7 @@ const HamburgerMenu: React.FC = () => {
onClick={itemClick('github')}
target="_blank"
>
<img
className={styles.subSectionLinkImage}
src="/img/community/icon-github.svg"
alt=""
/>
<GithubIcon className={styles.subSectionLinkImage} />
<span className={styles.subSectionLinkTitle}>GitHub</span>
</Link>
</li>
Expand All @@ -210,11 +208,7 @@ const HamburgerMenu: React.FC = () => {
onClick={itemClick('twitter')}
target="_blank"
>
<img
className={styles.subSectionLinkImage}
src="/img/community/icon-twitter.svg"
alt=""
/>
<TwitterIcon className={styles.subSectionLinkImage} />
<span className={styles.subSectionLinkTitle}>Twitter</span>
</Link>
</li>
Expand Down
1 change: 1 addition & 0 deletions src/components/HamburgerMenu/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
.subSectionLinkImage {
display: block;
margin: 0 auto 5px;
color: #fff;
}

.subSectionLinkTitle {
Expand Down
File renamed without changes
43 changes: 43 additions & 0 deletions src/components/SocialIcon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'
import Link from '../Link'
import { ReactComponent as TwitterIcon } from './twitter.svg'
import { ReactComponent as GithubIcon } from './github.svg'
import { ReactComponent as LinkedInIcon } from './linkedin.svg'

const icons: { [site: string]: JSX.Element } = {
linkedin: <LinkedInIcon />,
github: <GithubIcon />,
twitter: <TwitterIcon viewBox="5 5 30 30" />
}

export interface ISocialIcon {
url: string
site?: string
}

export interface ISocialIconProps extends ISocialIcon {
className?: string
}

/*
Returns a link containing an icon corresponding to the provided site
Given the situation where either the given link has no site or we don't have
an icon for it, we return null such that nothing is rendered in map
functions.
*/
const SocialIcon: React.FC<ISocialIconProps> = ({
site,
url,
className
}): JSX.Element | null => {
/* eslint-disable-next-line */
const icon: JSX.Element = icons[site!]
return icon ? (
<Link href={url} className={className} aria-label={site}>
{icon}
</Link>
) : null
}

export default SocialIcon
1 change: 1 addition & 0 deletions src/components/SocialIcon/linkedin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/SocialIcon/twitter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion src/gatsby/models/authors/createSchemaCustomization.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ async function createAuthorSchemaCustomization(api) {
schema: { buildObjectType }
} = api
const typeDefs = [
buildObjectType({
name: 'AuthorLink',
fields: {
url: 'String!',
site: 'String',
username: 'String'
}
}),
buildObjectType({
name: 'AuthorPosts',
fields: {
Expand All @@ -19,7 +27,8 @@ async function createAuthorSchemaCustomization(api) {
interfaces: ['Node'],
fields: {
...markdownParentFields,
link: 'String',
links: '[AuthorLink]',
slug: 'String',
avatar: {
type: 'ImageSharp',
resolve: resolveAuthorAvatar
Expand Down
6 changes: 4 additions & 2 deletions src/gatsby/models/authors/onCreateMarkdownContentNode.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
const parseLink = require('./parse-link.js')

async function createMarkdownAuthorNode(api, { parentNode, createChildNode }) {
if (parentNode.relativeDirectory.split('/')[0] !== 'authors') return
const { node, createNodeId, createContentDigest } = api
const { frontmatter, rawMarkdownBody } = node
const { path, name, avatar, link } = frontmatter
const { path, name, avatar, links } = frontmatter
const { relativePath } = parentNode

const fieldData = {
sourcePath: relativePath,
rawMarkdownBody,
path,
name,
link,
links: links.map(parseLink),
avatar
}

Expand Down
Loading

0 comments on commit 6007482

Please sign in to comment.