Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bookmark notes #647

Merged
merged 5 commits into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/static/img/avatar-small.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/static/img/avatar.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/static/img/overthought/2019-in-review.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 18 additions & 3 deletions src/components/Bookmarks/AddBookmark.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { GET_BOOKMARKS } from '~/graphql/queries'
import { Small } from '~/components/Typography'
import Input from '~/components/Input'
import Grid from '../Grid'
import Textarea from '../Textarea'

export default function AddBookmark() {
const [url, setUrl] = React.useState('')
const [notes, setNotes] = React.useState('')
const [error, setError] = React.useState('')
const query = GET_BOOKMARKS

Expand All @@ -18,6 +20,7 @@ export default function AddBookmark() {
id: url,
title: 'Saving...',
url,
notes,
host: url,
reactions: 0,
},
Expand All @@ -41,24 +44,36 @@ export default function AddBookmark() {

function onSubmit(e) {
e.preventDefault()
return handleAddBookmark({ variables: { url } })
return handleAddBookmark({ variables: { url, notes } })
}

function onChange(e) {
function onUrlChange(e) {
error && setError('')
return setUrl(e.target.value)
}

function onNotesChange(e) {
return setNotes(e.target.value)
}

return (
<Grid gap={12} as={'form'} onSubmit={onSubmit}>
<Input
autoFocus
type="text"
placeholder="Add a url..."
value={url}
onChange={onChange}
onChange={onUrlChange}
style={{ width: '100%' }}
/>
{url.length > 0 && (
<React.Fragment>
<Textarea placeholder="Notes..." onChange={onNotesChange} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

<Small style={{ cursor: 'pointer' }} onClick={onSubmit}>
Save
</Small>
</React.Fragment>
)}
{error && <Small style={{ color: 'var(--accent-red)' }}>{error}</Small>}
</Grid>
)
Expand Down
15 changes: 13 additions & 2 deletions src/components/Bookmarks/BookmarkListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react'
import { Bookmark } from '~/graphql/types.generated'
import { Small, A } from '~/components/Typography'

import Grid from '~/components/Grid'
import EditingBookmarkListItem from './EditingBookmarkListItem'
import BookmarkReaction from './BookmarkReaction'
Expand All @@ -25,14 +24,26 @@ export default function BookmarkListItem(props: Props) {
}

return (
<Grid gap={4}>
<Grid gap={bookmark.notes ? 8 : 4}>
<A
href={`${bookmark.url}?ref=brianlovin.com`}
target="_blank"
rel="noopener noreferrer"
>
{bookmark.title || bookmark.url}
</A>
{bookmark.notes && (
<Grid style={{ alignItems: 'start' }} columns={'1fr'}>
<Small
style={{
borderLeft: '2px solid var(--border-primary)',
paddingLeft: '12px',
}}
>
{bookmark.notes}
</Small>
</Grid>
)}
<Grid columns={`repeat(5, min-content)`} gap={16}>
<BookmarkReaction bookmark={bookmark} />

Expand Down
38 changes: 30 additions & 8 deletions src/components/Bookmarks/EditingBookmarkListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { Small } from '~/components/Typography'
import { GET_BOOKMARKS } from '~/graphql/queries'
import Input from '~/components/Input'
import Textarea from '~/components/Textarea'
import Grid from '~/components/Grid'

interface Props {
Expand All @@ -20,16 +21,23 @@ export default function EditingBookmarkListItem(props: Props) {
const initialState = {
error: '',
title: bookmark.title,
notes: bookmark.notes || '',
}

function reducer(state, action) {
switch (action.type) {
case 'edit': {
case 'edit-title': {
return {
error: '',
title: action.value,
}
}
case 'edit-notes': {
return {
...state,
notes: action.value,
}
}
case 'error': {
return {
...state,
Expand All @@ -43,14 +51,15 @@ export default function EditingBookmarkListItem(props: Props) {

const [state, dispatch] = React.useReducer(reducer, initialState)

const [saveBookmark] = useEditBookmarkMutation({
variables: { title: state.title, id: bookmark.id },
const [editBookmark] = useEditBookmarkMutation({
variables: { title: state.title, id: bookmark.id, notes: state.notes },
optimisticResponse: {
__typename: 'Mutation',
editBookmark: {
__typename: 'Bookmark',
...bookmark,
title: state.title,
notes: state.notes,
},
},
onError({ message }) {
Expand All @@ -75,8 +84,12 @@ export default function EditingBookmarkListItem(props: Props) {
},
})

function onChange(e) {
dispatch({ type: 'edit', value: e.target.value })
function onTitleChange(e) {
dispatch({ type: 'edit-title', value: e.target.value })
}

function onNotesChange(e) {
dispatch({ type: 'edit-notes', value: e.target.value })
}

function handleSave(e) {
Expand All @@ -86,14 +99,23 @@ export default function EditingBookmarkListItem(props: Props) {
return dispatch({ type: 'error', value: 'Bookmark must have a title' })
}

saveBookmark()
editBookmark()
return onDone()
}

return (
<Grid gap={12} as={'form'} onSubmit={handleSave}>
<Input value={state.title} onChange={onChange} />

<Input
autoFocus
placeholder="Title"
value={state.title}
onChange={onTitleChange}
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

<Textarea
placeholder="Notes..."
value={state.notes}
onChange={onNotesChange}
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

{state.error && (
<Small style={{ color: 'var(--accent-red)' }}>{state.error}</Small>
)}
Expand Down
4 changes: 2 additions & 2 deletions src/components/DesignDetailView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ export default function DesignDetailView(props: Props) {
>
<Grid gap={32}>
<Picture
width={'64px'}
height={'64px'}
style={{
borderRadius: '16px',
overflow: 'hidden',
width: '64px',
height: '64px',
}}
srcset={[
`/static/img/design-details/${post.slug}.webp`,
Expand Down
7 changes: 6 additions & 1 deletion src/components/DesignDetailsCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ export default function DesignDetailsCard(props: Props) {
<a>
<Container onMouseEnter={play} onMouseLeave={pause}>
<ImageContainer>
<Picture alt={'Design Details'} srcset={srcset} />
<Picture
width={'56px'}
height={'56px'}
alt={'Design Details'}
srcset={srcset}
/>
</ImageContainer>
<CardContent>
<Title>{title}</Title>
Expand Down
11 changes: 2 additions & 9 deletions src/components/Overthought/Feedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,8 @@ import { Post } from '~/graphql/types.generated'
import { PrimaryButton } from '~/components/Button'
import { H5, P } from '~/components/Typography'
import Input from '~/components/Input'
import {
InputGrid,
Container,
Form,
Textarea,
Success,
Error,
Label,
} from './style'
import Textarea from '~/components/Textarea'
import { InputGrid, Container, Form, Success, Error, Label } from './style'

interface Props {
post: Post
Expand Down
15 changes: 0 additions & 15 deletions src/components/Overthought/Feedback/style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,6 @@ export const Form = styled.form`
}
`

export const Textarea = styled.textarea`
padding: ${theme.space[3]};
border: 1px solid var(--border-primary);
color: var(--text-primary);
border-radius: ${theme.space[2]};
font-size: 16px;
background: var(--bg-primary);
resize: vertical;

&:focus {
border: 1px solid var(--accent-blue);
background: var(--bg-secondary);
}
`

export const InputGrid = styled.div`
display: grid;
grid-gap: ${theme.space[3]};
Expand Down
4 changes: 1 addition & 3 deletions src/components/Overthought/Post/SEO.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ export default function SEO({ post }: Props) {
description: post.custom_excerpt || post.excerpt,
images: [
{
url: post.feature_image
? post.feature_image
: 'https://brianlovin.com/static/meta/overthought.png',
url: `https://brianlovin.com/static/img/overthought/${post.slug}.png`,
alt: post.title,
},
],
Expand Down
12 changes: 7 additions & 5 deletions src/components/Picture/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@ interface Props {
srcset: string[]
alt: string
style?: object
width: string
height: string
}

export default function Picture({ srcset, alt, style = {} }: Props) {
export default function Picture({ srcset, alt, ...rest }: Props) {
const assets = []

srcset.map((src, i) => {
const key = `${src}-${i}`
if (src.endsWith('webp'))
assets.push(<source type="image/webp" srcSet={src} key={key} />)
assets.push(<source type="image/webp" srcSet={src} key={key} {...rest} />)
if (src.endsWith('jpg') || src.endsWith('jpeg'))
assets.push(<source type="image/jpeg" srcSet={src} key={key} />)
assets.push(<source type="image/jpeg" srcSet={src} key={key} {...rest} />)
if (src.endsWith('png'))
assets.push(<source type="image/png" srcSet={src} key={key} />)
assets.push(<source type="image/png" srcSet={src} key={key} {...rest} />)
})

const fallback = srcset.find((src) => !src.endsWith('webp'))

assets.push(<img style={style} src={fallback} key={fallback} alt={alt} />)
assets.push(<img src={fallback} key={fallback} alt={alt} {...rest} />)

return <picture>{assets}</picture>
}
2 changes: 1 addition & 1 deletion src/components/Providers/Fathom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function Fathom() {
tracker.defer = true
tracker.setAttribute('site', process.env.FATHOM_SITE_ID)
tracker.setAttribute('spa', 'auto')
tracker.setAttribute('excluded-domains', 'localhost')
tracker.setAttribute('excluded-domains', 'localhost,now.sh')
tracker.setAttribute('included-domains', 'brianlovin.com')
tracker.src = process.env.FATHOM_CUSTOM_URL
firstScript.parentNode.insertBefore(tracker, firstScript)
Expand Down
19 changes: 19 additions & 0 deletions src/components/Textarea/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styled from 'styled-components'
import theme from '~/components/Theme'

export default styled.textarea`
padding: ${theme.space[3]};
border: 1px solid var(--border-primary);
color: var(--text-primary);
border-radius: ${theme.space[2]};
font-size: 16px;
background: var(--bg-primary);
resize: vertical;
width: 100%;
line-height: ${theme.lineHeights.body};

&:focus {
border: 1px solid var(--accent-blue);
background: var(--bg-secondary);
}
`
1 change: 1 addition & 0 deletions src/graphql/fragments/bookmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const BookmarkInfoFragment = gql`
url
host
reactions
notes
}
`
8 changes: 4 additions & 4 deletions src/graphql/mutations/bookmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { gql } from '@apollo/client'
import { BookmarkInfoFragment } from '../fragments'

export const EDIT_BOOKMARK = gql`
mutation editBookmark($id: ID!, $title: String!) {
editBookmark(id: $id, title: $title) {
mutation editBookmark($id: ID!, $title: String!, $notes: String) {
editBookmark(id: $id, title: $title, notes: $notes) {
...BookmarkInfo
}
}
Expand All @@ -17,8 +17,8 @@ export const DELETE_BOOKMARK = gql`
`

export const ADD_BOOKMARK = gql`
mutation addBookmark($url: String!) {
addBookmark(url: $url) {
mutation addBookmark($url: String!, $notes: String) {
addBookmark(url: $url, notes: $notes) {
...BookmarkInfo
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/graphql/resolvers/mutations/bookmarks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ function isValidUrl(string) {
}
}

export async function editBookmark(_, { id, title }) {
export async function editBookmark(_, { id, title, notes }) {
if (!title || title.length === 0)
throw new UserInputError('Bookmark must have a title')

await firebase.collection('bookmarks').doc(id).update({ title })
await firebase.collection('bookmarks').doc(id).update({ title, notes })

return await firebase
.collection('bookmarks')
Expand All @@ -25,7 +25,7 @@ export async function editBookmark(_, { id, title }) {
.then((doc) => doc.data())
}

export async function addBookmark(_, { url }) {
export async function addBookmark(_, { url, notes }) {
if (!isValidUrl(url)) throw new UserInputError('URL was invalid')

const existingRef = await firebase
Expand All @@ -43,6 +43,7 @@ export async function addBookmark(_, { url }) {
.add({
createdAt: new Date(),
...metadata,
notes,
reactions: 0,
})
.then(({ id }) => id)
Expand Down
Loading