Clean up card types, remove old code

This commit is contained in:
Jackson Harper 2023-03-08 17:02:52 +08:00
parent 818a9a66ad
commit c9d48c5f35
8 changed files with 180 additions and 629 deletions

View file

@ -19,6 +19,5 @@ export type LinkedItemCardProps = {
item: LibraryItemNode
layout: LayoutType
viewer: UserBasicData
originText?: string
handleAction: (action: LinkedItemCardAction) => void
}

View file

@ -1,190 +0,0 @@
import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { CoverImage } from '../../elements/CoverImage'
import { StyledText } from '../../elements/StyledText'
import { authoredByText } from '../ArticleSubtitle'
import { MoreOptionsIcon } from '../../elements/images/MoreOptionsIcon'
import { theme } from '../../tokens/stitches.config'
import { CardMenu } from '../CardMenu'
import { LabelChip } from '../../elements/LabelChip'
import { ProgressBar } from '../../elements/ProgressBar'
import type { LinkedItemCardProps } from './CardTypes'
export function GridLinkedItemCard(props: LinkedItemCardProps): JSX.Element {
return (
<VStack
css={{
p: '$2',
pr: '8px',
height: '100%',
width: '100%',
maxWidth: '100%',
borderRadius: '6px',
cursor: 'pointer',
wordBreak: 'break-word',
overflow: 'clip',
border: '1px solid $grayBorder',
boxShadow: '0px 3px 11px rgba(32, 31, 29, 0.04)',
position: 'relative',
}}
alignment="start"
distribution="start"
onClick={() => {
props.handleAction('showDetail')
}}
>
<Box
css={{
position: 'absolute',
top: '1px',
left: '1px',
width: 'calc(100% - 2px)',
'& > div': {
borderRadius: '100vmax 100vmax 0 0',
},
}}
>
<ProgressBar
fillPercentage={props.item.readingProgressPercent}
fillColor={theme.colors.highlight.toString()}
backgroundColor="transparent"
borderRadius={
props.item.readingProgressPercent === 100 ? '0' : '0px 8px 8px 0px'
}
/>
</Box>
<VStack
distribution="start"
alignment="start"
css={{
px: '0px',
width: '100%',
pl: '$1',
}}
>
<HStack
alignment="start"
distribution="between"
css={{
width: '100%',
p: '0px',
mr: '-12px',
mt: '15px',
display: 'grid',
gridTemplateColumns: '1fr 24px',
gridTemplateRows: '1fr',
}}
>
<CardTitle title={props.item.title} />
<Box
css={{ alignSelf: 'end', alignItems: 'start', height: '100%' }}
onClick={(e) => {
// This is here to prevent menu click events from bubbling
// up and causing us to "click" on the link item.
e.stopPropagation()
}}
>
<CardMenu
item={props.item}
viewer={props.viewer}
triggerElement={
<MoreOptionsIcon
size={24}
strokeColor={theme.colors.grayTextContrast.toString()}
orientation="horizontal"
/>
}
actionHandler={props.handleAction}
/>
</Box>
</HStack>
<HStack alignment="start" distribution="between">
<StyledText style="caption" css={{ my: '0', mt: '-$2' }}>
{props.item.author && (
<SpanBox css={{ mr: '8px' }}>
{authoredByText(props.item.author)}
</SpanBox>
)}
<SpanBox css={{ textDecorationLine: 'underline' }}>
{props.originText}
</SpanBox>
</StyledText>
</HStack>
</VStack>
<HStack
alignment="start"
distribution="between"
css={{
width: '100%',
pt: '$2',
px: '$1',
pr: '12px',
mt: '7px',
flexGrow: '1',
}}
>
<StyledText
css={{
m: 0,
py: '0px',
mr: '$2',
fontStyle: 'normal',
fontWeight: '400',
fontSize: '14px',
lineHeight: '125%',
color: '$grayTextContrast',
flexGrow: '4',
overflow: 'hidden',
display: '-webkit-box',
WebkitLineClamp: 5,
WebkitBoxOrient: 'vertical',
}}
data-testid="listDesc"
>
{props.item.description}
</StyledText>
{props.item.image && (
<CoverImage
src={props.item.image}
alt="Link Preview Image"
width={135}
height={90}
css={{ ml: '10px', mb: '8px', borderRadius: '3px' }}
onError={(e) => {
;(e.target as HTMLElement).style.display = 'none'
}}
/>
)}
</HStack>
<Box css={{ display: 'block', mt: '8px' }}>
{props.item.labels?.map(({ name, color }, index) => (
<LabelChip key={index} text={name || ''} color={color} />
))}
</Box>
</VStack>
)
}
type CardTitleProps = {
title: string
}
function CardTitle(props: CardTitleProps): JSX.Element {
return (
<StyledText
style="listTitle"
data-testid="listTitle"
css={{
mt: '0',
mb: '0',
fontWeight: '700',
textAlign: 'left',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
width: '100%',
overflow: 'hidden',
}}
>
{props.title}
</StyledText>
)
}

View file

@ -1,35 +1,10 @@
import {
Box,
VStack,
HStack,
SpanBox,
Blockquote,
} from '../../elements/LayoutPrimitives'
import { LabelChip } from '../../elements/LabelChip'
import { Fragment, useMemo, useState } from 'react'
import { CaretDown, CaretUp, DotsThreeVertical } from 'phosphor-react'
import Link from 'next/link'
import { CardMenu } from '../CardMenu'
import {
AuthorInfoStyle,
DescriptionStyle,
MenuStyle,
MetaStyle,
timeAgo,
TitleStyle,
} from './LibraryCardStyles'
import { Separator } from '../../elements/Separator'
import { Box, VStack, HStack } from '../../elements/LayoutPrimitives'
import { useState } from 'react'
import { CaretDown, CaretUp } from 'phosphor-react'
import { MetaStyle, timeAgo, TitleStyle } from './LibraryCardStyles'
import { styled } from '@stitches/react'
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
import { StyledText } from '../../elements/StyledText'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import {
LibraryItem,
LibraryItemNode,
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { useRouter } from 'next/router'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { LibraryItemNode } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { Button } from '../../elements/Button'
import { theme } from '../../tokens/stitches.config'
import { HighlightItem } from '../../templates/homeFeed/HighlightItem'
@ -45,7 +20,6 @@ type LibraryHighlightGridCardProps = {
item: LibraryItemNode
}
// Component
export function LibraryHighlightGridCard(
props: LibraryHighlightGridCardProps
): JSX.Element {

View file

@ -14,7 +14,6 @@ import {
TitleStyle,
} from './LibraryCardStyles'
// Component
export function LibraryListCard(props: LinkedItemCardProps): JSX.Element {
const [isHovered, setIsHovered] = useState(false)
const [menuOpen, setMenuOpen] = useState(false)

View file

@ -1,48 +1,11 @@
import { GridLinkedItemCard } from './GridLinkedItemCard'
import { ListLinkedItemCard } from './ListLinkedItemCard'
import type { LinkedItemCardProps } from './CardTypes'
import { HighlightItemCard } from './HighlightItemCard'
import { PageType } from '../../../lib/networking/fragments/articleFragment'
import { LibraryGridCard } from './LibraryGridCard'
import { LibraryListCard } from './LibraryListCard'
import { LibraryHighlightGridCard } from './LibraryHighlightGridCard'
const shouldHideUrl = (url: string): boolean => {
try {
const origin = new URL(url).origin
const hideHosts = ['https://storage.googleapis.com', 'https://omnivore.app']
if (hideHosts.indexOf(origin) != -1) {
return true
}
} catch {
console.log('invalid url item', url)
}
return false
}
const siteName = (originalArticleUrl: string, itemUrl: string): string => {
if (shouldHideUrl(originalArticleUrl)) {
return ''
}
try {
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
} catch {}
try {
return new URL(itemUrl).hostname.replace(/^www\./, '')
} catch {}
return ''
}
export function LinkedItemCard(props: LinkedItemCardProps): JSX.Element {
const originText =
props.item.siteName ||
siteName(props.item.originalArticleUrl, props.item.url)
if (props.layout == 'LIST_LAYOUT') {
return <LibraryListCard {...props} originText={originText} />
// return <ListLinkedItemCard {...props} originText={originText} />
return <LibraryListCard {...props} />
} else {
return <LibraryGridCard {...props} originText={originText} />
// return <GridLinkedItemCard {...props} originText={originText} />
return <LibraryGridCard {...props} />
}
}

View file

@ -1,215 +0,0 @@
import {
Box,
HStack,
VStack,
MediumBreakpointBox,
} from '../../elements/LayoutPrimitives'
import { StyledText } from '../../elements/StyledText'
import { authoredByText } from '../ArticleSubtitle'
import { MoreOptionsIcon } from '../../elements/images/MoreOptionsIcon'
import { theme } from '../../tokens/stitches.config'
import { CardMenu } from '../CardMenu'
import type { LinkedItemCardProps } from './CardTypes'
import { ProgressBar } from '../../elements/ProgressBar'
export function ListLinkedItemCard(props: LinkedItemCardProps): JSX.Element {
return (
<MediumBreakpointBox
smallerLayoutNode={<ListLinkedItemCardNarrow {...props} />}
largerLayoutNode={<ListLinkedItemCardWide {...props} />}
/>
)
}
export function ListLinkedItemCardNarrow(
props: LinkedItemCardProps
): JSX.Element {
return (
<Box
css={{
p: '$3',
height: '100%',
width: '100%',
maxWidth: '100%',
borderRadius: 0,
cursor: 'pointer',
wordBreak: 'break-word',
border: '1px solid $grayBorder',
borderBottom: 'none',
alignItems: 'center',
display: 'grid',
gridTemplateColumns: '1fr 24px',
gridTemplateRows: '1fr',
}}
onClick={() => {
props.handleAction('showDetail')
}}
>
<HStack
distribution="start"
alignment="end"
css={{
px: '$2',
pl: '0px',
}}
>
<VStack>
<StyledText
style="listTitle"
data-testid="listTitle"
css={{
mt: '0px',
mb: '$1',
textAlign: 'left',
lineHeight: 'normal',
}}
>
{props.item.title}
</StyledText>
<HStack>
{props.item.author && (
<StyledText style="caption" css={{ my: '$1' }}>
{authoredByText(props.item.author)}
</StyledText>
)}
<StyledText
style="caption"
css={{
my: '$1',
ml: props.item.author ? '8px' : 0,
textDecorationLine: 'underline',
}}
>
{props.originText}
</StyledText>
</HStack>
</VStack>
</HStack>
<Box
css={{
alignSelf: 'end',
alignItems: 'center',
display: 'grid',
placeItems: 'center',
}}
onClick={(e) => {
// This is here to prevent menu click events from bubbling
// up and causing us to "click" on the link item.
e.stopPropagation()
}}
>
<CardMenu
item={props.item}
viewer={props.viewer}
triggerElement={
<MoreOptionsIcon
size={24}
strokeColor={theme.colors.grayTextContrast.toString()}
orientation="horizontal"
/>
}
actionHandler={props.handleAction}
/>
</Box>
</Box>
)
}
export function ListLinkedItemCardWide(
props: LinkedItemCardProps
): JSX.Element {
return (
<HStack
css={{
p: '$3',
height: '100%',
width: '100%',
maxWidth: '100%',
borderRadius: 0,
cursor: 'pointer',
wordBreak: 'break-word',
border: '1px solid $grayBorder',
borderBottom: 'none',
alignItems: 'center',
}}
onClick={() => {
props.handleAction('showDetail')
}}
>
<HStack
distribution="start"
alignment="end"
css={{
px: '$2',
flexGrow: 1,
pl: '0px',
}}
>
<StyledText
style="listTitle"
data-testid="listTitle"
css={{ mt: '0px', mb: '$1', textAlign: 'left', lineHeight: 'normal' }}
>
{props.item.title}
</StyledText>
{props.item.author && (
<StyledText style="caption" css={{ my: '$1', ml: '8px' }}>
{authoredByText(props.item.author)}
</StyledText>
)}
<StyledText
style="caption"
css={{ my: '$1', ml: '8px', textDecorationLine: 'underline' }}
>
{props.originText}
</StyledText>
</HStack>
<Box
css={{
width: '40px',
height: '8px',
mr: '$2',
backgroundColor: '$grayBase',
display: 'grid',
placeItems: 'center',
borderRadius: '6px',
border: '1px solid $grayBorder',
px: '1px',
}}
>
<ProgressBar
fillPercentage={props.item.readingProgressPercent}
fillColor={theme.colors.highlight.toString()}
backgroundColor={theme.colors.grayTextContrast.toString()}
borderRadius={'8px'}
/>
</Box>
<Box
css={{
alignSelf: 'end',
alignItems: 'center',
display: 'grid',
placeItems: 'center',
}}
onClick={(e) => {
// This is here to prevent menu click events from bubbling
// up and causing us to "click" on the link item.
e.stopPropagation()
}}
>
<CardMenu
item={props.item}
viewer={props.viewer}
triggerElement={
<MoreOptionsIcon
size={24}
strokeColor={theme.colors.grayTextContrast.toString()}
orientation="horizontal"
/>
}
actionHandler={props.handleAction}
/>
</Box>
</HStack>
)
}

View file

@ -0,0 +1,173 @@
import { styled } from '@stitches/react'
import { useRouter } from 'next/router'
import { DotsThreeVertical } from 'phosphor-react'
import { Fragment, useMemo, useState } from 'react'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import {
LibraryItem,
LibraryItemNode,
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
import { LabelChip } from '../../elements/LabelChip'
import {
Blockquote,
Box,
HStack,
SpanBox,
VStack,
} from '../../elements/LayoutPrimitives'
import { StyledText } from '../../elements/StyledText'
type HighlightItemProps = {
highlight: Highlight
viewer: UserBasicData | undefined
item: LibraryItemNode
}
const StyledQuote = styled(Blockquote, {
margin: '0px',
fontSize: '16px',
fontFamily: '$inter',
fontWeight: '500',
lineHeight: '1.50',
color: '$thHighContrast',
paddingLeft: '15px',
borderLeft: '2px solid $omnivoreCtaYellow',
})
export function HighlightItem(props: HighlightItemProps): JSX.Element {
const router = useRouter()
const [hover, setHover] = useState(false)
const [isEditing, setIsEditing] = useState(false)
const lines = useMemo(
() => props.highlight.quote.split('\n'),
[props.highlight.quote]
)
return (
<HStack
css={{ width: '100%', py: '20px', cursor: 'pointer' }}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<VStack
css={{
gap: '10px',
height: '100%',
width: '100%',
wordBreak: 'break-word',
overflow: 'clip',
}}
alignment="start"
distribution="start"
onClick={(event) => {
if (router && props.viewer) {
const dest = `/${props.viewer}/${props.item.slug}#${props.highlight.id}`
router.push(dest)
}
event.preventDefault()
}}
>
<StyledQuote>
<SpanBox css={{ p: '1px', borderRadius: '2px' }}>
{lines.map((line: string, index: number) => (
<Fragment key={index}>
{line}
{index !== lines.length - 1 && (
<>
<br />
<br />
</>
)}
</Fragment>
))}
</SpanBox>
<Box css={{ display: 'block', pt: '16px' }}>
{props.highlight.labels?.map((label: Label, index: number) => (
<LabelChip
key={index}
text={label.name || ''}
color={label.color}
/>
))}
</Box>
</StyledQuote>
<StyledText
css={{
borderRadius: '6px',
bg: '#EBEBEB',
p: '10px',
width: '100%',
marginTop: '5px',
color: '#3D3D3D',
}}
onClick={() => setIsEditing(true)}
>
{props.highlight.annotation
? props.highlight.annotation
: 'Add your notes...'}
</StyledText>
</VStack>
<SpanBox
css={{
marginLeft: 'auto',
width: '20px',
visibility: hover ? 'unset' : 'hidden',
'@media (hover: none)': {
visibility: 'unset',
},
}}
>
<HighlightsMenu />
</SpanBox>
</HStack>
)
}
function HighlightsMenu(): JSX.Element {
return (
<Dropdown
triggerElement={
<Box
css={{
display: 'flex',
height: '20px',
width: '20px',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '1000px',
'&:hover': {
bg: '#898989',
},
}}
>
<DotsThreeVertical size={20} color="#EBEBEB" weight="bold" />
</Box>
}
>
<DropdownOption
onSelect={() => {
console.log('copy')
}}
title="Copy"
/>
<DropdownOption
onSelect={() => {
console.log('labels')
}}
title="Labels"
/>
<DropdownOption
onSelect={() => {
console.log('delete')
}}
title="Delete"
/>
</Dropdown>
)
}

View file

@ -291,115 +291,6 @@ function HighlightList(props: HighlightListProps): JSX.Element {
)
}
// const StyledQuote = styled(Blockquote, {
// margin: '0px',
// fontSize: '16px',
// fontFamily: '$inter',
// fontWeight: '500',
// lineHeight: '1.50',
// color: '$thHighContrast',
// paddingLeft: '15px',
// borderLeft: '2px solid $omnivoreCtaYellow',
// })
// type HighlightItemCardProps = {
// highlight: Highlight
// viewer: UserBasicData | undefined
// item: LibraryItem
// }
// function HighlightItemCard(props: HighlightItemCardProps): JSX.Element {
// const router = useRouter()
// const [hover, setHover] = useState(false)
// const [isEditing, setIsEditing] = useState(false)
// const lines = useMemo(
// () => props.highlight.quote.split('\n'),
// [props.highlight.quote]
// )
// return (
// <HStack
// css={{ width: '100%', py: '20px', cursor: 'pointer' }}
// onMouseEnter={() => setHover(true)}
// onMouseLeave={() => setHover(false)}
// >
// <VStack
// css={{
// gap: '10px',
// height: '100%',
// width: '100%',
// wordBreak: 'break-word',
// overflow: 'clip',
// }}
// alignment="start"
// distribution="start"
// onClick={(event) => {
// if (router && props.viewer) {
// const dest = `/${props.viewer}/${props.item.node.slug}#${props.highlight.id}`
// router.push(dest)
// }
// event.preventDefault()
// }}
// >
// <StyledQuote>
// <SpanBox css={{ p: '1px', borderRadius: '2px' }}>
// {lines.map((line: string, index: number) => (
// <Fragment key={index}>
// {line}
// {index !== lines.length - 1 && (
// <>
// <br />
// <br />
// </>
// )}
// </Fragment>
// ))}
// </SpanBox>
// <Box css={{ display: 'block', pt: '16px' }}>
// {props.highlight.labels?.map((label: Label, index: number) => (
// <LabelChip
// key={index}
// text={label.name || ''}
// color={label.color}
// />
// ))}
// </Box>
// </StyledQuote>
// <StyledText
// css={{
// borderRadius: '6px',
// bg: '#EBEBEB',
// p: '10px',
// width: '100%',
// marginTop: '5px',
// color: '#3D3D3D',
// }}
// onClick={() => setIsEditing(true)}
// >
// {props.highlight.annotation
// ? props.highlight.annotation
// : 'Add your notes...'}
// </StyledText>
// </VStack>
// <SpanBox
// css={{
// marginLeft: 'auto',
// width: '20px',
// visibility: hover ? 'unset' : 'hidden',
// '@media (hover: none)': {
// visibility: 'unset',
// },
// }}
// >
// <HighlightsMenu />
// </SpanBox>
// </HStack>
// )
// }
type HighlightCountChipProps = {
count: number
selected: boolean
@ -433,46 +324,3 @@ function HighlightCountChip(props: HighlightCountChipProps): JSX.Element {
</HStack>
)
}
// function HighlightsMenu(): JSX.Element {
// return (
// <Dropdown
// triggerElement={
// <Box
// css={{
// display: 'flex',
// height: '20px',
// width: '20px',
// alignItems: 'center',
// justifyContent: 'center',
// borderRadius: '1000px',
// '&:hover': {
// bg: '#898989',
// },
// }}
// >
// <DotsThreeVertical size={20} color="#EBEBEB" weight="bold" />
// </Box>
// }
// >
// <DropdownOption
// onSelect={() => {
// console.log('copy')
// }}
// title="Copy"
// />
// <DropdownOption
// onSelect={() => {
// console.log('labels')
// }}
// title="Labels"
// />
// <DropdownOption
// onSelect={() => {
// console.log('delete')
// }}
// title="Delete"
// />
// </Dropdown>
// )
// }