Skip to content

Commit

Permalink
feat(ui): configure category for new article form
Browse files Browse the repository at this point in the history
  • Loading branch information
ncarlier committed Jan 15, 2020
1 parent 6b908bd commit 58a2541
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 27 deletions.
30 changes: 20 additions & 10 deletions ui/src/articles/AddArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,44 @@ import ButtonIcon from '../components/ButtonIcon'
import { URLRegExp } from '../helpers'
import Page from '../layout/Page'
import AddArticleForm from './components/AddArticleForm'
import { Article } from './models'
import { Category } from '../categories/models'

type AllProps = RouteComponentProps
interface Props {
category?: Category
}

const Actions = () => <ButtonIcon as={Link} to="/unread" icon="arrow_back" title="back to the list" />
type AllProps = Props & RouteComponentProps

export default ({ location, history }: AllProps) => {
const params = new URLSearchParams(location.search)
const Actions = () => <ButtonIcon as={Link} to="/unread" icon="arrow_back" title="back to the list" />

let value = ''
const extractURLFromParams = (qs: string) => {
const params = new URLSearchParams(qs)
if (params.has('url')) {
value = params.get('url')!
return params.get('url')!
} else if (params.has('text') || params.has('title')) {
const text = params.get('text') || params.get('title')!
if (URLRegExp.test(text)) {
value = text
return text
} else {
const matches = text.match(/\bhttps?:\/\/\S+/gi)
if (matches && URLRegExp.test(matches[0])) {
value = matches[0]
return matches[0]
}
}
}
return undefined
}

export default ({ category, location, history }: AllProps) => {
const url = extractURLFromParams(location.search)

const redirect = () => history.replace('/unread')
const onSuccess = (article: Article) => history.replace(`/unread/${article.id}`)
const onCancel = () => history.replace('/unread')

return (
<Page title="Add new article" actions={<Actions />}>
<AddArticleForm value={value} onCancel={redirect} onSuccess={redirect} />
<AddArticleForm value={url} category={category} onCancel={onCancel} onSuccess={onSuccess} />
</Page>
)
}
12 changes: 6 additions & 6 deletions ui/src/articles/ArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ export default ({ category, match, history }: AllProps) => {
let title = 'Articles to read'
if (category) {
title = category.title
}
if (match.path === '/history/:id') {
} else if (match.path === '/history/:id') {
title = 'History'
}

// useKeyboard('backspace', () => history.push(redirect))
useKeyboard('backspace', () => history.goBack())
const goBack = () => history.goBack()

useKeyboard('backspace', goBack)

const { data, error, loading } = useQuery<GetArticleResponse>(GetArticle, {
variables: { id }
Expand All @@ -58,7 +58,7 @@ export default ({ category, match, history }: AllProps) => {
<ArticleMenu article={article} keyboard />
</ArticleHeader>
<ArticleContent article={article} />
<MarkAsButton article={article} floating onSuccess={() => history.goBack()} keyboard />
<MarkAsButton article={article} floating onSuccess={goBack} keyboard />
</>
)
}
Expand All @@ -71,7 +71,7 @@ export default ({ category, match, history }: AllProps) => {
<Page
title={title}
subtitle={data && data.article ? data.article.title : ''}
actions={<ButtonIcon onClick={history.goBack} icon="arrow_back" title="back to the list" />}
actions={<ButtonIcon onClick={goBack} icon="arrow_back" title="back to the list" />}
>
<Panel style={{ flex: '1 1 auto' }}>{render(data, error, loading)}</Panel>
</Page>
Expand Down
24 changes: 19 additions & 5 deletions ui/src/articles/components/AddArticleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import Loader from '../../components/Loader'
import Panel from '../../components/Panel'
import { MessageContext } from '../../context/MessageContext'
import ErrorPanel from '../../error/ErrorPanel'
import { getGQLError, isValidForm } from '../../helpers'
import { getGQLError, isValidForm, isValidInput } from '../../helpers'
import useOnMountInputValidator from '../../hooks/useOnMountInputValidator'
import { AddNewArticleRequest, AddNewArticleResponse, Article } from '../models'
import { AddNewArticle } from '../queries'
import FormSelectField from '../../components/FormSelectField'
import CategoriesOptions from '../../components/CategoriesOptions'

interface AddArticleFormFields {
url: string
category?: number
}

interface Props {
Expand All @@ -29,15 +32,17 @@ export default ({ value, category, onSuccess, onCancel }: Props) => {
const [loading, setLoading] = useState(false)
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const { showMessage } = useContext(MessageContext)
const [formState, { url }] = useFormState<AddArticleFormFields>({ url: value })
const [formState, { url, select }] = useFormState<AddArticleFormFields>({
url: value,
category: category ? category.id : undefined
})
const onMountValidator = useOnMountInputValidator(formState.validity)
const addArticleMutation = useMutation<AddNewArticleResponse, AddNewArticleRequest>(AddNewArticle)

const addArticle = async (form: AddArticleFormFields) => {
setLoading(true)
try {
const categoryID = category ? category.id : undefined
const variables = { ...form, category: categoryID }
const variables = { ...form }
const res = await addArticleMutation({ variables })
setLoading(false)
if (res.data) {
Expand Down Expand Up @@ -75,11 +80,20 @@ export default ({ value, category, onSuccess, onCancel }: Props) => {
<FormInputField
label="URL"
{...url('url')}
error={!formState.validity.url}
error={!isValidInput(formState, onMountValidator, 'url')}
required
autoFocus
ref={onMountValidator.bind}
/>
<FormSelectField
label="Category"
{...select('category')}
error={!isValidInput(formState, onMountValidator, 'category')}
ref={onMountValidator.bind}
>
<option>Optional category</option>
<CategoriesOptions />
</FormSelectField>
</form>
</section>
<footer>
Expand Down
14 changes: 8 additions & 6 deletions ui/src/articles/components/NewArticlesAvailable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import Panel from '../../components/Panel'
import { GetArticlesResponse } from '../models'
import { GetNbNewArticles } from '../queries'

const renderLabel = (nb: number) => {
const NewArticlesLabel = ({ nb }: { nb: number }) => {
switch (true) {
case nb > 1:
return `View ${nb} new articles`
return <>View {nb} new articles</>
case nb === 1:
return 'View new article'
return <>View new article</>
case nb < 0:
return 'Refresh'
return <>Refresh</>
default:
return ''
return null
}
}

Expand Down Expand Up @@ -75,7 +75,9 @@ export default ({ current, category, refresh }: Props) => {
case nbItems != 0:
return (
<Panel style={{ flex: '0 0 auto' }}>
<Button onClick={reload}>{renderLabel(nbItems)}</Button>
<Button onClick={reload}>
<NewArticlesLabel nb={nbItems} />
</Button>
</Panel>
)
default:
Expand Down

0 comments on commit 58a2541

Please sign in to comment.