add loading and set labels ui

This commit is contained in:
Hongbo Wu 2022-02-24 12:35:42 +08:00
parent 276205d52a
commit 6482d280f7
5 changed files with 94 additions and 48 deletions

View file

@ -1,9 +1,9 @@
import {
ModalRoot,
ModalContent,
ModalOverlay,
ModalRoot,
} from '../../elements/ModalPrimitives'
import { HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { HStack, VStack } from '../../elements/LayoutPrimitives'
import { Button } from '../../elements/Button'
import { StyledText } from '../../elements/StyledText'
import { CrossIcon } from '../../elements/images/CrossIcon'
@ -15,36 +15,33 @@ import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticle
import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation'
type EditLabelsModalProps = {
labels: string[]
article: ArticleAttributes
onOpenChange: (open: boolean) => void
}
export function EditLabelsModal(
props: EditLabelsModalProps
): JSX.Element {
const [selectedLabels, setSelectedLabels] = useState(props.labels)
export function EditLabelsModal(props: EditLabelsModalProps): JSX.Element {
const [selectedLabels, setSelectedLabels] = useState(
props.article.labels?.map((l) => l.id) || []
)
const { labels, revalidate, isValidating } = useGetLabelsQuery()
const saveAndExit = useCallback(async () => {
if (selectedLabels.length > 0) {
const result = await setLabelsMutation(
props.article.id,
selectedLabels,
)
console.log('result of setting labels', result)
}
const result = await setLabelsMutation(props.article.linkId, selectedLabels)
console.log('result of setting labels', result)
props.onOpenChange(false)
}, [selectedLabels, props.onOpenChange])
const handleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
const label = event.target.value
if (event.target.checked) {
setSelectedLabels([...selectedLabels, label])
} else {
setSelectedLabels(selectedLabels.filter((l) => l !== label))
}
}, [selectedLabels, setSelectedLabels])
const handleChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
const label = event.target.value
if (event.target.checked) {
setSelectedLabels([...selectedLabels, label])
} else {
setSelectedLabels(selectedLabels.filter((l) => l !== label))
}
},
[selectedLabels, setSelectedLabels]
)
return (
<ModalRoot defaultOpen onOpenChange={saveAndExit}>
@ -61,7 +58,9 @@ export function EditLabelsModal(
alignment="center"
css={{ width: '100%' }}
>
<StyledText style="modalHeadline" css={{ p: '16px' }}>Edit Labels</StyledText>
<StyledText style="modalHeadline" css={{ p: '16px' }}>
Edit Labels
</StyledText>
<Button
css={{ pt: '16px', pr: '16px' }}
style="ghost"
@ -75,25 +74,34 @@ export function EditLabelsModal(
/>
</Button>
</HStack>
{labels && labels.map((label) => (
<HStack key={label.id} css={{ height: '50px', verticalAlign: 'middle' }} onClick={() => {
if (selectedLabels.includes(label.id)) {
setSelectedLabels(selectedLabels.filter((id) => id !== label.id))
} else {
setSelectedLabels([...selectedLabels, label.id])
}
}}>
<Label color={label.color} text={label.name} />
<input
type="checkbox"
value={label.id}
onChange={handleChange}
checked={selectedLabels.includes(label.id)}
/>
</HStack>
))}
{labels &&
labels.map((label) => (
<HStack
key={label.id}
css={{ height: '50px', verticalAlign: 'middle' }}
onClick={() => {
if (selectedLabels.includes(label.id)) {
setSelectedLabels(
selectedLabels.filter((id) => id !== label.id)
)
} else {
setSelectedLabels([...selectedLabels, label.id])
}
}}
>
<Label color={label.color} text={label.name} />
<input
type="checkbox"
value={label.id}
onChange={handleChange}
checked={selectedLabels.includes(label.id)}
/>
</HStack>
))}
<HStack css={{ width: '100%', mb: '16px' }} alignment="center">
<Button style="ctaDarkYellow" onClick={saveAndExit}>Save</Button>
<Button style="ctaDarkYellow" onClick={saveAndExit}>
Save
</Button>
</HStack>
</VStack>
</ModalContent>

View file

@ -17,6 +17,7 @@ export const articleFragment = gql`
slug
isArchived
description
linkId
}
`
@ -38,4 +39,5 @@ export type ArticleFragmentData = {
slug: string
isArchived: boolean
description: string
linkId?: string
}

View file

@ -0,0 +1,18 @@
import { gql } from 'graphql-request'
export const labelFragment = gql`
fragment LabelFields on Label {
id
name
color
description
}
`
export type Label = {
id: string
name: string
color: string
description?: string
createdAt: string
}

View file

@ -1,9 +1,10 @@
import { gql } from 'graphql-request'
import useSWRImmutable, { useSWRConfig } from 'swr'
import useSWRImmutable from 'swr'
import { makeGqlFetcher, RequestContext, ssrFetcher } from '../networkHelpers'
import { articleFragment, ContentReader } from '../fragments/articleFragment'
import { highlightFragment, Highlight } from '../fragments/highlightFragment'
import { Highlight, highlightFragment } from '../fragments/highlightFragment'
import { ScopedMutator } from 'swr/dist/types'
import { Label, labelFragment } from '../fragments/labelFragment'
type ArticleQueryInput = {
username?: string
@ -46,6 +47,8 @@ export type ArticleAttributes = {
content: string
shareInfo?: ArticleShareInfo
highlights: Highlight[]
linkId: string
labels?: Label[]
}
type ArticleShareInfo = {
@ -73,6 +76,9 @@ const query = gql`
highlights(input: { includeFriends: $includeFriendsHighlights }) {
...HighlightFields
}
labels {
...LabelFields
}
}
}
... on ArticleError {
@ -82,10 +88,16 @@ const query = gql`
}
${articleFragment}
${highlightFragment}
${labelFragment}
`
export const cacheArticle = (mutate: ScopedMutator, username: string, article: ArticleAttributes, includeFriendsHighlights = false) => {
export const cacheArticle = (
mutate: ScopedMutator,
username: string,
article: ArticleAttributes,
includeFriendsHighlights = false
) => {
mutate([query, username, article.slug, includeFriendsHighlights], {
article: { article: {...article, cached: true} }
article: { article: { ...article, cached: true } },
})
}
@ -134,4 +146,3 @@ export async function articleQuery(
return Promise.reject()
}

View file

@ -1,11 +1,12 @@
import { gql } from 'graphql-request'
import useSWRInfinite from 'swr/infinite'
import { gqlFetcher } from '../networkHelpers'
import { articleFragment } from '../fragments/articleFragment'
import type { ArticleFragmentData } from '../fragments/articleFragment'
import { articleFragment } from '../fragments/articleFragment'
import { setLinkArchivedMutation } from '../mutations/setLinkArchivedMutation'
import { deleteLinkMutation } from '../mutations/deleteLinkMutation'
import { articleReadingProgressMutation } from '../mutations/articleReadingProgressMutation'
import { labelFragment } from '../fragments/labelFragment'
export type LibraryItemsQueryInput = {
limit: number
@ -89,6 +90,9 @@ export function useGetLibraryItemsQuery({
cursor
node {
...ArticleFields
labels {
...LabelFields
}
originalArticleUrl
}
}
@ -106,6 +110,7 @@ export function useGetLibraryItemsQuery({
}
}
${articleFragment}
${labelFragment}
`
const variables = {
@ -132,7 +137,9 @@ export function useGetLibraryItemsQuery({
limit,
sortDescending,
searchQuery,
pageIndex === 0 ? undefined : previousResult.articles.pageInfo.endCursor,
pageIndex === 0
? undefined
: previousResult.articles.pageInfo.endCursor,
]
},
(query, _l, _s, _sq, cursor: string) => {