Merge pull request #4324 from omnivore-app/fix/web-text-issues
Move text utils into single place
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import { styled } from './../tokens/stitches.config'
|
||||
import { Root, Image, Fallback } from '@radix-ui/react-avatar'
|
||||
import { Root, Fallback } from '@radix-ui/react-avatar'
|
||||
|
||||
type AvatarProps = {
|
||||
imageURL?: string
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
import { NavigationLayout } from '../templates/NavigationLayout'
|
||||
import { Box, HStack, VStack } from '../elements/LayoutPrimitives'
|
||||
import { useFetchMore } from '../../lib/hooks/useFetchMoreScroll'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useGetHighlights } from '../../lib/networking/queries/useGetHighlights'
|
||||
import { Highlight } from '../../lib/networking/fragments/highlightFragment'
|
||||
import { NextRouter, useRouter } from 'next/router'
|
||||
import {
|
||||
UserBasicData,
|
||||
useGetViewerQuery,
|
||||
} from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { SetHighlightLabelsModalPresenter } from '../templates/article/SetLabelsModalPresenter'
|
||||
import { TrashIcon } from '../elements/icons/TrashIcon'
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { ConfirmationModal } from '../patterns/ConfirmationModal'
|
||||
import { deleteHighlightMutation } from '../../lib/networking/mutations/deleteHighlightMutation'
|
||||
import { LabelChip } from '../elements/LabelChip'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import { timeAgo } from '../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { timeAgo } from '../../lib/textFormatting'
|
||||
import { HighlightHoverActions } from '../patterns/HighlightHoverActions'
|
||||
import {
|
||||
autoUpdate,
|
||||
|
||||
@ -16,7 +16,7 @@ import { ArchiveActionIcon } from '../elements/icons/home/ArchiveActionIcon'
|
||||
import { RemoveActionIcon } from '../elements/icons/home/RemoveActionIcon'
|
||||
import { ShareActionIcon } from '../elements/icons/home/ShareActionIcon'
|
||||
import Pagination from '../elements/Pagination'
|
||||
import { timeAgo } from '../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { timeAgo } from '../../lib/textFormatting'
|
||||
import { theme } from '../tokens/stitches.config'
|
||||
import { useApplyLocalTheme } from '../../lib/hooks/useApplyLocalTheme'
|
||||
import { useGetHiddenHomeSection } from '../../lib/networking/queries/useGetHiddenHomeSection'
|
||||
@ -33,7 +33,6 @@ import {
|
||||
useGetSubscriptionsQuery,
|
||||
} from '../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { Box, HStack, SpanBox, VStack } from '../elements/LayoutPrimitives'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import useLibraryItemActions from '../../lib/hooks/useLibraryItemActions'
|
||||
import { SyncLoader } from 'react-spinners'
|
||||
import { useGetLibraryItems } from '../../lib/networking/library_items/useLibraryItems'
|
||||
@ -423,7 +422,6 @@ export function HomeContainer(): JSX.Element {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toaster />
|
||||
<VStack
|
||||
distribution="start"
|
||||
css={{
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Box, StyledLink } from './../elements/LayoutPrimitives'
|
||||
import { StyledText } from './../../components/elements/StyledText'
|
||||
import { formattedLongDate } from './../../lib/dateFormatting'
|
||||
import { shouldHideUrl } from '../../lib/textFormatting'
|
||||
|
||||
type SubtitleStyle = 'footnote' | 'shareSubtitle'
|
||||
|
||||
@ -67,15 +68,6 @@ export function ReaderSavedInfo(props: ReaderSavedInfoProps): JSX.Element {
|
||||
)
|
||||
}
|
||||
|
||||
function shouldHideUrl(url: string): boolean {
|
||||
const origin = new URL(url).origin
|
||||
const hideHosts = ['https://storage.googleapis.com', 'https://omnivore.app']
|
||||
if (hideHosts.indexOf(origin) != -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function articleSubtitle(url: string, author?: string): string | undefined {
|
||||
const origin = new URL(url).origin
|
||||
const hideUrl = shouldHideUrl(url)
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { useMemo } from 'react'
|
||||
import { LibraryItemNode } from '../../../lib/networking/library_items/useLibraryItems'
|
||||
import { HStack, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { RecommendedFlairIcon } from '../../elements/icons/RecommendedFlairIcon'
|
||||
@ -9,8 +6,7 @@ import { FavoriteFlairIcon } from '../../elements/icons/FavoriteFlairIcon'
|
||||
import { NewsletterFlairIcon } from '../../elements/icons/NewsletterFlairIcon'
|
||||
import { FeedFlairIcon } from '../../elements/icons/FeedFlairIcon'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
import { timeAgo } from '../../../lib/textFormatting'
|
||||
|
||||
export const MenuStyle = {
|
||||
display: 'flex',
|
||||
@ -69,26 +65,6 @@ export const AuthorInfoStyle = {
|
||||
textOverflow: 'ellipsis',
|
||||
}
|
||||
|
||||
export const timeAgo = (date: string | undefined): string => {
|
||||
if (!date) {
|
||||
return ''
|
||||
}
|
||||
return dayjs(date).fromNow()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
export const FLAIR_ICON_NAMES = [
|
||||
'favorite',
|
||||
'pinned',
|
||||
@ -148,27 +124,6 @@ export function FlairIcon(props: FlairIconProps): JSX.Element {
|
||||
)
|
||||
}
|
||||
|
||||
export const siteName = (
|
||||
originalArticleUrl: string,
|
||||
itemUrl: string,
|
||||
siteName?: string
|
||||
): string => {
|
||||
if (siteName) {
|
||||
return siteName
|
||||
}
|
||||
|
||||
if (shouldHideUrl(originalArticleUrl)) {
|
||||
return ''
|
||||
}
|
||||
try {
|
||||
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
|
||||
} catch {}
|
||||
try {
|
||||
return new URL(itemUrl).hostname.replace(/^www\./, '')
|
||||
} catch {}
|
||||
return ''
|
||||
}
|
||||
|
||||
type LibraryItemMetadataProps = {
|
||||
item: LibraryItemNode
|
||||
showProgress?: boolean
|
||||
|
||||
@ -10,11 +10,11 @@ import {
|
||||
CardCheckbox,
|
||||
LibraryItemMetadata,
|
||||
MetaStyle,
|
||||
siteName,
|
||||
TitleStyle,
|
||||
MenuStyle,
|
||||
FLAIR_ICON_NAMES,
|
||||
} from './LibraryCardStyles'
|
||||
import { siteName } from '../../../lib/textFormatting'
|
||||
import { sortedLabels } from '../../../lib/labelsSort'
|
||||
import { LibraryHoverActions } from './LibraryHoverActions'
|
||||
import {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { CaretDown, CaretUp } from '@phosphor-icons/react'
|
||||
import { MetaStyle, timeAgo, TitleStyle } from './LibraryCardStyles'
|
||||
import { MetaStyle, TitleStyle } from './LibraryCardStyles'
|
||||
import { styled } from '@stitches/react'
|
||||
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { LibraryItemNode } from '../../../lib/networking/library_items/useLibraryItems'
|
||||
@ -12,6 +12,7 @@ import { HighlightView } from '../HighlightView'
|
||||
import { useRouter } from 'next/router'
|
||||
import { showErrorToast } from '../../../lib/toastHelpers'
|
||||
import { sortHighlights } from '../../../lib/highlights/sortHighlights'
|
||||
import { timeAgo } from '../../../lib/textFormatting'
|
||||
|
||||
export const GridSeparator = styled(Box, {
|
||||
height: '1px',
|
||||
|
||||
@ -7,11 +7,11 @@ import {
|
||||
CardCheckbox,
|
||||
LibraryItemMetadata,
|
||||
MetaStyle,
|
||||
siteName,
|
||||
TitleStyle,
|
||||
MenuStyle,
|
||||
FLAIR_ICON_NAMES,
|
||||
} from './LibraryCardStyles'
|
||||
import { siteName } from '../../../lib/textFormatting'
|
||||
import { sortedLabels } from '../../../lib/labelsSort'
|
||||
import { LIBRARY_LEFT_MENU_WIDTH } from '../../templates/navMenu/LibraryMenu'
|
||||
import { LibraryHoverActions } from './LibraryHoverActions'
|
||||
|
||||
@ -1,258 +0,0 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { PageMetaData } from '../patterns/PageMetaData'
|
||||
import { VStack, HStack, Box } from '../elements/LayoutPrimitives'
|
||||
import { OmnivoreNameLogo } from '../elements/images/OmnivoreNameLogo'
|
||||
import { StyledText } from '../elements/StyledText'
|
||||
import { Button } from '../elements/Button'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
|
||||
const TOTAL_ONBOARDING_PAGES = 6
|
||||
|
||||
type OnboardingLayoutProps = {
|
||||
pageNumber: number
|
||||
title: string
|
||||
subTitle: string
|
||||
description?: string
|
||||
children: ReactNode
|
||||
image?: ReactNode
|
||||
nextPage?: string
|
||||
reduceSpace?: boolean
|
||||
onNext?: () => void | Promise<void>
|
||||
}
|
||||
|
||||
export const OnboardingLayout = ({
|
||||
pageNumber,
|
||||
title,
|
||||
subTitle,
|
||||
description,
|
||||
image,
|
||||
children,
|
||||
nextPage,
|
||||
reduceSpace,
|
||||
onNext,
|
||||
}: OnboardingLayoutProps) => {
|
||||
const router = useRouter()
|
||||
|
||||
const NextButton = () => {
|
||||
const handleNext = async () => {
|
||||
onNext && (await onNext())
|
||||
router.push(nextPage ?? `/onboarding/0${pageNumber + 1}`)
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
style="ctaDarkYellow"
|
||||
css={{
|
||||
width: '111px',
|
||||
height: '44px',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
textDecoration: 'none',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
onClick={handleNext}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageMetaData
|
||||
path={`/onboarding/0${pageNumber}`}
|
||||
title={`Onboarding - ${pageNumber}`}
|
||||
/>
|
||||
<Toaster />
|
||||
<Box
|
||||
css={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr',
|
||||
minHeight: '100vh',
|
||||
'@lgDown': {
|
||||
gridTemplateRows: reduceSpace ? 0 : 'initial',
|
||||
},
|
||||
'@lg': {
|
||||
gridTemplateColumns: '1fr 2fr',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<VStack
|
||||
css={{
|
||||
background: '#FFFFFF',
|
||||
padding: '21px 19px 0 19px',
|
||||
position: 'relative',
|
||||
'@lg': {
|
||||
padding: '116px 32px 14px 48px',
|
||||
},
|
||||
}}
|
||||
distribution="between"
|
||||
>
|
||||
<Box
|
||||
css={{
|
||||
backgroundColor: '#FFD234',
|
||||
width: `${Math.floor(
|
||||
(pageNumber * 100) / TOTAL_ONBOARDING_PAGES
|
||||
)}%`,
|
||||
height: '4px',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
'@lg': {
|
||||
top: '$1',
|
||||
},
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
css={{
|
||||
width: '100%',
|
||||
'@sm': { textAlign: 'center' },
|
||||
'@lg': { textAlign: 'left' },
|
||||
}}
|
||||
>
|
||||
<HStack
|
||||
distribution="start"
|
||||
css={{
|
||||
justifyContent: 'center',
|
||||
'@lg': { justifyContent: 'flex-start' },
|
||||
}}
|
||||
alignment="center"
|
||||
>
|
||||
<OmnivoreNameLogo href="/login" />
|
||||
<StyledText
|
||||
style="logoTitle"
|
||||
css={{ color: '#0A080666', paddingLeft: '9px', fontSize: 15 }}
|
||||
>
|
||||
Omnivore
|
||||
</StyledText>
|
||||
</HStack>
|
||||
<Box
|
||||
css={{
|
||||
marginTop: '24px',
|
||||
fontWeight: '700',
|
||||
fontSize: 32,
|
||||
'@lgDown': {
|
||||
marginTop: '5px',
|
||||
fontSize: 28,
|
||||
},
|
||||
lineHeight: '125%',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Box>
|
||||
<Box
|
||||
css={{
|
||||
marginTop: '24px',
|
||||
fontWeight: '400',
|
||||
fontSize: 16,
|
||||
lineHeight: '125%',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
}}
|
||||
>
|
||||
{subTitle}
|
||||
</Box>
|
||||
{image && (
|
||||
<Box
|
||||
css={{
|
||||
height: '295px',
|
||||
position: 'relative',
|
||||
marginTop: '24px',
|
||||
display: 'none',
|
||||
'@lg': { display: 'block' },
|
||||
}}
|
||||
>
|
||||
{image}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<HStack
|
||||
distribution="end"
|
||||
css={{
|
||||
width: '100%',
|
||||
justifyContent: 'end',
|
||||
'@lgDown': { display: 'none' },
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
style="ctaSecondary"
|
||||
css={{
|
||||
width: '111px',
|
||||
height: '44px',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
}}
|
||||
>
|
||||
Skip
|
||||
</Button>
|
||||
<NextButton />
|
||||
</HStack>
|
||||
</VStack>
|
||||
<VStack
|
||||
css={{
|
||||
background: 'White',
|
||||
'@sm': { alignItems: 'center' },
|
||||
padding: '2vw 2vw 0 2vw',
|
||||
'@lg': {
|
||||
background: '#F5F5F4',
|
||||
padding: '30px 71px 0 30px',
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
'@xl': {
|
||||
padding: '58px 71px 0 58px',
|
||||
},
|
||||
}}
|
||||
distribution="start"
|
||||
>
|
||||
{description && (
|
||||
<Box
|
||||
css={{
|
||||
position: 'relative',
|
||||
fontWeight: 600,
|
||||
fontSize: 16,
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
'@lgDown': { paddingLeft: '11px' },
|
||||
}}
|
||||
>
|
||||
{description}
|
||||
</Box>
|
||||
)}
|
||||
{children}
|
||||
</VStack>
|
||||
</Box>
|
||||
<HStack
|
||||
css={{
|
||||
position: 'fixed',
|
||||
bottom: '0',
|
||||
width: '100%',
|
||||
padding: '20px',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#ffffff',
|
||||
|
||||
'@lg': { display: 'none' },
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
style="ctaSecondary"
|
||||
css={{
|
||||
width: '111px',
|
||||
height: '44px',
|
||||
textAlign: 'left',
|
||||
color: 'rgba(10, 8, 6, 0.8)',
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
}}
|
||||
>
|
||||
Skip
|
||||
</Button>
|
||||
<NextButton />
|
||||
</HStack>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -1,13 +1,12 @@
|
||||
import { HStack, VStack } from "../../../elements/LayoutPrimitives"
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { HStack, VStack } from '../../../elements/LayoutPrimitives'
|
||||
import { LayoutType } from '../../homeFeed/HomeFeedContainer'
|
||||
import { UserBasicData } from '../../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { DiscoverItems } from '../DiscoverItems/DiscoverItems'
|
||||
import { SaveDiscoverArticleOutput } from "../../../../lib/networking/mutations/saveDiscoverArticle"
|
||||
import { HeaderText } from "../DiscoverHeader/HeaderText"
|
||||
import React from "react"
|
||||
import { TopicTabData } from "../DiscoverContainer"
|
||||
import { DiscoverFeedItem } from "../../../../lib/networking/queries/useGetDiscoverFeedItems"
|
||||
import { SaveDiscoverArticleOutput } from '../../../../lib/networking/mutations/saveDiscoverArticle'
|
||||
import { HeaderText } from '../DiscoverHeader/HeaderText'
|
||||
import React from 'react'
|
||||
import { TopicTabData } from '../DiscoverContainer'
|
||||
import { DiscoverFeedItem } from '../../../../lib/networking/queries/useGetDiscoverFeedItems'
|
||||
|
||||
type DiscoverItemFeedProps = {
|
||||
items: DiscoverFeedItem[]
|
||||
@ -33,7 +32,6 @@ export const DiscoverItemFeed = (props: DiscoverItemFeedProps) => {
|
||||
minHeight: '100vh',
|
||||
}}
|
||||
>
|
||||
<Toaster />
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution={'start'}
|
||||
|
||||
@ -19,9 +19,9 @@ import { CoverImage } from '../../../elements/CoverImage'
|
||||
import {
|
||||
AuthorInfoStyle,
|
||||
MetaStyle,
|
||||
siteName,
|
||||
TitleStyle,
|
||||
} from '../../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { siteName } from '../../../../lib/textFormatting'
|
||||
import {
|
||||
DiscoverItemCardProps,
|
||||
DiscoverItemSubCardProps,
|
||||
|
||||
@ -20,9 +20,9 @@ import { CoverImage } from '../../../elements/CoverImage'
|
||||
import {
|
||||
AuthorInfoStyle,
|
||||
MetaStyle,
|
||||
siteName,
|
||||
TitleStyle,
|
||||
} from '../../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { siteName } from '../../../../lib/textFormatting'
|
||||
import { CheckCircle, Circle } from '@phosphor-icons/react'
|
||||
import {
|
||||
DiscoverItemCardProps,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { HStack } from '../../../elements/LayoutPrimitives'
|
||||
import { timeAgo } from '../../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { DiscoverFeedItem } from "../../../../lib/networking/queries/useGetDiscoverFeedItems"
|
||||
import { DiscoverFeedItem } from '../../../../lib/networking/queries/useGetDiscoverFeedItems'
|
||||
import { timeAgo } from '../../../../lib/textFormatting'
|
||||
|
||||
type DiscoverItemMetadataProps = {
|
||||
item: DiscoverFeedItem
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import { HighlighterCircle } from '@phosphor-icons/react'
|
||||
import { useCallback, useEffect, useReducer, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
|
||||
import {
|
||||
LibraryItem,
|
||||
@ -13,10 +12,8 @@ import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { MenuTrigger } from '../../elements/MenuTrigger'
|
||||
import {
|
||||
MetaStyle,
|
||||
timeAgo,
|
||||
} from '../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { MetaStyle } from '../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { timeAgo } from '../../../lib/textFormatting'
|
||||
import { LibraryHighlightGridCard } from '../../patterns/LibraryCards/LibraryHighlightGridCard'
|
||||
import { NotebookContent } from '../article/Notebook'
|
||||
import { EmptyHighlights } from './EmptyHighlights'
|
||||
@ -36,9 +33,8 @@ type HighlightItemsLayoutProps = {
|
||||
export function HighlightItemsLayout(
|
||||
props: HighlightItemsLayoutProps
|
||||
): JSX.Element {
|
||||
const [currentItem, setCurrentItem] = useState<LibraryItem | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [currentItem, setCurrentItem] =
|
||||
useState<LibraryItem | undefined>(undefined)
|
||||
|
||||
const listReducer = (
|
||||
state: LibraryItem[],
|
||||
@ -131,7 +127,6 @@ export function HighlightItemsLayout(
|
||||
distribution="start"
|
||||
alignment="start"
|
||||
>
|
||||
<Toaster />
|
||||
<HStack
|
||||
css={{
|
||||
flexGrow: '0',
|
||||
|
||||
@ -1,317 +0,0 @@
|
||||
import { LayoutType } from './HomeFeedContainer'
|
||||
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { LibraryItem } from '../../../lib/networking/library_items/useLibraryItems'
|
||||
import { HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import TopBarProgress from 'react-topbar-progress-indicator'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { ArchiveIcon } from '../../elements/icons/ArchiveIcon'
|
||||
import { TrashIcon } from '../../elements/icons/TrashIcon'
|
||||
import { BrowserIcon } from '../../elements/icons/BrowserIcon'
|
||||
import { styled } from '@stitches/react'
|
||||
import { siteName } from '../../patterns/LibraryCards/LibraryCardStyles'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { DotsThree } from '@phosphor-icons/react'
|
||||
import { useState } from 'react'
|
||||
|
||||
type TLDRLayoutProps = {
|
||||
layout: LayoutType
|
||||
viewer?: UserBasicData
|
||||
|
||||
items: LibraryItem[]
|
||||
isValidating: boolean
|
||||
|
||||
hasMore: boolean
|
||||
totalItems: number
|
||||
|
||||
loadMore: () => void
|
||||
}
|
||||
|
||||
const SiteIcon = styled('img', {
|
||||
width: '22px',
|
||||
height: '22px',
|
||||
borderRadius: '100px',
|
||||
})
|
||||
|
||||
export function TLDRLayout(props: TLDRLayoutProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{
|
||||
mt: '30px',
|
||||
gap: '50px',
|
||||
height: '100%',
|
||||
minHeight: '100vh',
|
||||
px: '0px',
|
||||
width: '100%',
|
||||
maxWidth: '800px',
|
||||
'@mdDown': {
|
||||
p: '10px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toaster />
|
||||
|
||||
{props.isValidating && props.items.length == 0 && <TopBarProgress />}
|
||||
|
||||
{props.items.map((item) => {
|
||||
const sourceName = siteName(
|
||||
item.node.originalArticleUrl,
|
||||
item.node.url,
|
||||
item.node.siteName
|
||||
)
|
||||
const source =
|
||||
sourceName == item.node.author ? undefined : item.node.author
|
||||
|
||||
return (
|
||||
<VStack key={`tldr-${item.node.id}`} css={{ gap: '10px' }}>
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="start"
|
||||
css={{
|
||||
gap: '5px',
|
||||
width: '100%',
|
||||
height: '25px',
|
||||
pb: 'red',
|
||||
}}
|
||||
>
|
||||
<VStack
|
||||
distribution="center"
|
||||
alignment="center"
|
||||
css={{
|
||||
mr: '5px',
|
||||
display: 'flex',
|
||||
w: '22px',
|
||||
h: '22px',
|
||||
borderRadius: '100px',
|
||||
bg: '$ctaBlue',
|
||||
color: '$thTextSubtle',
|
||||
}}
|
||||
>
|
||||
<SiteIcon src={item.node.siteIcon} />
|
||||
</VStack>
|
||||
{source && (
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'flex',
|
||||
fontFamily: '$inter',
|
||||
fontSize: '16px',
|
||||
maxWidth: '150px',
|
||||
maxLines: '1',
|
||||
textOverflow: 'ellipsis',
|
||||
'@mdDown': {
|
||||
fontSize: '12px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.node.siteName}
|
||||
</SpanBox>
|
||||
)}
|
||||
{source && item.node.author && (
|
||||
<SpanBox
|
||||
css={{
|
||||
maxLines: '1',
|
||||
display: 'flex',
|
||||
fontFamily: '$inter',
|
||||
maxWidth: '150px',
|
||||
textOverflow: 'ellipsis',
|
||||
'@mdDown': {
|
||||
fontSize: '12px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
•
|
||||
</SpanBox>
|
||||
)}
|
||||
{item.node.author && (
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'flex',
|
||||
fontFamily: '$inter',
|
||||
fontSize: '16px',
|
||||
maxWidth: '120px',
|
||||
maxLines: '1',
|
||||
textOverflow: 'ellipsis',
|
||||
'@mdDown': {
|
||||
fontSize: '12px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.node.author}
|
||||
</SpanBox>
|
||||
)}
|
||||
<SpanBox css={{ ml: 'auto' }}>
|
||||
<DotsThree
|
||||
size={20}
|
||||
color={theme.colors.thTextSubtle.toString()}
|
||||
/>
|
||||
</SpanBox>
|
||||
</HStack>
|
||||
<HStack
|
||||
css={{
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{ gap: '10px' }}
|
||||
>
|
||||
<SpanBox
|
||||
css={{
|
||||
fontFamily: '$inter',
|
||||
fontWeight: '700',
|
||||
fontSize: '20px',
|
||||
wordBreak: 'break-all',
|
||||
textDecoration: 'underline',
|
||||
a: {
|
||||
color: '$thTLDRText',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<a href={``}>{item.node.title}</a>
|
||||
</SpanBox>
|
||||
<SpanBox
|
||||
css={{
|
||||
fontFamily: '$inter',
|
||||
fontWeight: '500',
|
||||
fontSize: '14px',
|
||||
lineHeight: '30px',
|
||||
color: '$thTLDRText',
|
||||
}}
|
||||
>
|
||||
{item.node.aiSummary}
|
||||
</SpanBox>
|
||||
<HStack css={{ gap: '15px', pt: '5px' }}>
|
||||
<ArchiveButton />
|
||||
<RemoveButton />
|
||||
<OpenOriginalButton />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
})}
|
||||
|
||||
<HStack
|
||||
distribution="center"
|
||||
css={{ width: '100%', mt: '$2', mb: '$4' }}
|
||||
>
|
||||
{props.hasMore ? (
|
||||
<Button
|
||||
style="ctaGray"
|
||||
css={{
|
||||
cursor: props.isValidating ? 'not-allowed' : 'pointer',
|
||||
}}
|
||||
onClick={props.loadMore}
|
||||
disabled={props.isValidating}
|
||||
>
|
||||
{props.isValidating ? 'Loading' : 'Load More'}
|
||||
</Button>
|
||||
) : (
|
||||
<StyledText style="caption"></StyledText>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const ArchiveButton = (): JSX.Element => {
|
||||
const [foreground, setForegroundColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
return (
|
||||
<Button
|
||||
title="Archive"
|
||||
style="tldr"
|
||||
css={{
|
||||
'&:hover': {
|
||||
bg: '$ctaBlue',
|
||||
opacity: 1.0,
|
||||
},
|
||||
}}
|
||||
onMouseEnter={(event) => {
|
||||
setForegroundColor('white')
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseLeave={(event) => {
|
||||
setForegroundColor(theme.colors.thTextContrast2.toString())
|
||||
event.preventDefault()
|
||||
}}
|
||||
onClick={(e) => {
|
||||
// props.setShowConfirmDelete(true)
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<ArchiveIcon size={20} color={foreground} />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const RemoveButton = (): JSX.Element => {
|
||||
const [foreground, setForegroundColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
return (
|
||||
<Button
|
||||
title="Remove"
|
||||
style="tldr"
|
||||
css={{
|
||||
'&:hover': {
|
||||
bg: '$ctaBlue',
|
||||
opacity: 1.0,
|
||||
},
|
||||
}}
|
||||
onMouseEnter={(event) => {
|
||||
setForegroundColor('white')
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseLeave={(event) => {
|
||||
setForegroundColor(theme.colors.thTextContrast2.toString())
|
||||
event.preventDefault()
|
||||
}}
|
||||
onClick={(e) => {
|
||||
// props.setShowConfirmDelete(true)
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<TrashIcon size={20} color={foreground} />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const OpenOriginalButton = (): JSX.Element => {
|
||||
const [foreground, setForegroundColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
return (
|
||||
<Button
|
||||
title="Open original"
|
||||
style="tldr"
|
||||
css={{
|
||||
'&:hover': {
|
||||
bg: '$ctaBlue',
|
||||
opacity: 1.0,
|
||||
},
|
||||
}}
|
||||
onMouseEnter={(event) => {
|
||||
setForegroundColor('white')
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseLeave={(event) => {
|
||||
setForegroundColor(theme.colors.thTextContrast2.toString())
|
||||
event.preventDefault()
|
||||
}}
|
||||
onClick={(e) => {
|
||||
// props.setShowConfirmDelete(true)
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<BrowserIcon size={20} color={foreground} />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@ -44,7 +44,6 @@ export function Webhooks(): JSX.Element {
|
||||
return webhooksList
|
||||
}, [webhooks])
|
||||
|
||||
console.log('webhooksList', webhooksList)
|
||||
return (
|
||||
<VStack
|
||||
distribution={'start'}
|
||||
|
||||
@ -2,7 +2,6 @@ import { Action, createAction, useKBar, useRegisterActions } from 'kbar'
|
||||
import debounce from 'lodash/debounce'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import TopBarProgress from 'react-topbar-progress-indicator'
|
||||
import { useFetchMore } from '../../../lib/hooks/useFetchMoreScroll'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
@ -1044,8 +1043,6 @@ export function LibraryItemsLayout(
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Toaster />
|
||||
|
||||
<SpanBox
|
||||
css={{
|
||||
alignSelf: 'flex-start',
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Pencil, Trash } from '@phosphor-icons/react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { Dropdown, DropdownOption } from '../../elements/DropdownElements'
|
||||
import { MoreOptionsIcon } from '../../elements/images/MoreOptionsIcon'
|
||||
@ -282,11 +281,6 @@ const CreateButton = (props: CreateButtonProps): JSX.Element => {
|
||||
export const SettingsTable = (props: SettingsTableProps): JSX.Element => {
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<HStack css={{ width: '100%' }} alignment="center">
|
||||
<VStack
|
||||
alignment="start"
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Action } from 'kbar'
|
||||
import type { KeyboardCommand } from './useKeyboardShortcuts'
|
||||
import type { NextRouter } from 'next/router'
|
||||
import { DEFAULT_HOME_PATH } from '../navigations'
|
||||
|
||||
export function navigationCommands(router: NextRouter | undefined): Action[] {
|
||||
return [
|
||||
|
||||
45
packages/web/lib/textFormatting.ts
Normal file
45
packages/web/lib/textFormatting.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
export const timeAgo = (date: string | undefined): string => {
|
||||
if (!date) {
|
||||
return ''
|
||||
}
|
||||
return dayjs(date).fromNow()
|
||||
}
|
||||
|
||||
export 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
|
||||
}
|
||||
|
||||
export const siteName = (
|
||||
originalArticleUrl: string,
|
||||
itemUrl: string,
|
||||
siteName?: string
|
||||
): string => {
|
||||
if (siteName) {
|
||||
return shouldHideUrl(siteName) ? '' : siteName
|
||||
}
|
||||
|
||||
if (shouldHideUrl(originalArticleUrl)) {
|
||||
return ''
|
||||
}
|
||||
try {
|
||||
return new URL(originalArticleUrl).hostname.replace(/^www\./, '')
|
||||
} catch {}
|
||||
try {
|
||||
return new URL(itemUrl).hostname.replace(/^www\./, '')
|
||||
} catch {}
|
||||
return ''
|
||||
}
|
||||
@ -1,16 +1,11 @@
|
||||
import { PrimaryLayout } from '../../../components/templates/PrimaryLayout'
|
||||
import { LoadingView } from '../../../components/patterns/LoadingView'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { useRouter } from 'next/router'
|
||||
import { VStack } from './../../../components/elements/LayoutPrimitives'
|
||||
import {
|
||||
ArticleContainer,
|
||||
UpdateTitleEvent,
|
||||
} from './../../../components/templates/article/ArticleContainer'
|
||||
import { ArticleContainer } from './../../../components/templates/article/ArticleContainer'
|
||||
import { PdfArticleContainerProps } from './../../../components/templates/article/PdfArticleContainer'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import Script from 'next/script'
|
||||
import { ArticleActionsMenu } from '../../../components/templates/article/ArticleActionsMenu'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
@ -505,8 +500,6 @@ export default function Reader(): JSX.Element {
|
||||
id="MathJax-script"
|
||||
src="/static/mathjax/tex-mml-chtml.js"
|
||||
/>
|
||||
<Toaster />
|
||||
|
||||
<ReaderHeader
|
||||
hideDisplaySettings={false}
|
||||
showDisplaySettingsModal={
|
||||
|
||||
@ -29,6 +29,7 @@ import { QueryClient } from '@tanstack/react-query'
|
||||
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
||||
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
|
||||
import React from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@ -107,6 +108,7 @@ export function OmnivoreApp({ Component, pageProps }: AppProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<ConditionalCaptchaProvider>
|
||||
<Toaster />
|
||||
<PersistQueryClientProvider
|
||||
client={queryClient}
|
||||
persistOptions={{ persister: asyncStoragePersister }}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
/* eslint-disable functional/no-class */
|
||||
import NextDocument, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import { getCssText, globalStyles } from '../components/tokens/stitches.config'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
|
||||
export default class Document extends NextDocument {
|
||||
render() {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { PageMetaData } from '../../components/patterns/PageMetaData'
|
||||
import { AuthLayout } from '../../components/templates/AuthLayout'
|
||||
import { EmailForgotPassword } from '../../components/templates/auth/EmailForgotPassword'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
|
||||
export default function ForgotPassword(): JSX.Element {
|
||||
return (
|
||||
@ -10,11 +9,6 @@ export default function ForgotPassword(): JSX.Element {
|
||||
title="Reset your password - Omnivore"
|
||||
path="/auth-forgot-password"
|
||||
/>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<EmailForgotPassword />
|
||||
<div data-testid="auth-forgot-password-page-tag" />
|
||||
</AuthLayout>
|
||||
|
||||
@ -1,33 +1,8 @@
|
||||
import { styled } from '@stitches/react'
|
||||
import { AddToLibraryActionIcon } from '../../components/elements/icons/home/AddToLibraryActionIcon'
|
||||
import { ArchiveActionIcon } from '../../components/elements/icons/home/ArchiveActionIcon'
|
||||
import { CommentActionIcon } from '../../components/elements/icons/home/CommentActionIcon'
|
||||
import { RemoveActionIcon } from '../../components/elements/icons/home/RemoveActionIcon'
|
||||
import { ShareActionIcon } from '../../components/elements/icons/home/ShareActionIcon'
|
||||
import { useApplyLocalTheme } from '../../lib/hooks/useApplyLocalTheme'
|
||||
import {
|
||||
HStack,
|
||||
SpanBox,
|
||||
VStack,
|
||||
} from './../../components/elements/LayoutPrimitives'
|
||||
|
||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||
import { SpanBox, VStack } from './../../components/elements/LayoutPrimitives'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import {
|
||||
HomeItem,
|
||||
HomeItemSource,
|
||||
HomeItemSourceType,
|
||||
HomeSection,
|
||||
useGetHomeItems,
|
||||
} from '../../lib/networking/queries/useGetHome'
|
||||
import { timeAgo } from '../../components/patterns/LibraryCards/LibraryCardStyles'
|
||||
import { theme } from '../../components/tokens/stitches.config'
|
||||
import { useRouter } from 'next/router'
|
||||
import {
|
||||
SubscriptionType,
|
||||
useGetSubscriptionsQuery,
|
||||
} from '../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useGetHomeItems } from '../../lib/networking/queries/useGetHome'
|
||||
import { useCallback } from 'react'
|
||||
import { refreshHomeMutation } from '../../lib/networking/mutations/refreshHome'
|
||||
|
||||
export default function DebugHome(): JSX.Element {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import {
|
||||
Box,
|
||||
@ -224,12 +223,6 @@ export default function Account(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
|
||||
<VStack
|
||||
css={{ width: '100%', height: '100%' }}
|
||||
distribution="start"
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { applyStoredTheme } from '../../lib/themeUpdater'
|
||||
@ -48,11 +47,6 @@ export default function DeleteMyAccount(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<VStack
|
||||
css={{ width: '100%', height: '100%' }}
|
||||
distribution="start"
|
||||
|
||||
@ -1,34 +1,12 @@
|
||||
import { Spinner } from '@phosphor-icons/react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Button } from '../../../components/elements/Button'
|
||||
import { HStack, VStack } from '../../../components/elements/LayoutPrimitives'
|
||||
import { StyledText } from '../../../components/elements/StyledText'
|
||||
import { VStack } from '../../../components/elements/LayoutPrimitives'
|
||||
import { SettingsLayout } from '../../../components/templates/SettingsLayout'
|
||||
import { styled } from '../../../components/tokens/stitches.config'
|
||||
import { userHasFeature } from '../../../lib/featureFlag'
|
||||
import { optInFeature } from '../../../lib/networking/mutations/optIntoFeatureMutation'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { applyStoredTheme } from '../../../lib/themeUpdater'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
|
||||
const StyledLabel = styled('label', {
|
||||
fontWeight: 600,
|
||||
fontSize: '16px',
|
||||
marginBottom: '5px',
|
||||
})
|
||||
|
||||
export default function BetaFeatures(): JSX.Element {
|
||||
applyStoredTheme()
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
|
||||
<VStack
|
||||
css={{ width: '100%', height: '100%', mt: '80px' }}
|
||||
distribution="start"
|
||||
|
||||
@ -3,7 +3,6 @@ import Image from 'next/image'
|
||||
import { useRouter } from 'next/router'
|
||||
import { DownloadSimple, Link, Spinner } from '@phosphor-icons/react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import {
|
||||
Dropdown,
|
||||
@ -27,9 +26,7 @@ import {
|
||||
Integration,
|
||||
useGetIntegrationsQuery,
|
||||
} from '../../lib/networking/queries/useGetIntegrationsQuery'
|
||||
import { useGetViewerQuery } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { useGetViewer } from '../../lib/networking/viewer/useGetViewer'
|
||||
// Styles
|
||||
const Header = styled(Box, {
|
||||
color: '$utilityTextDefault',
|
||||
@ -327,12 +324,6 @@ export default function Integrations(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
|
||||
<VStack css={{ width: '100%', height: '100%' }}>
|
||||
<Header css={{ textAlign: 'center', width: '100%' }}>
|
||||
Integrations
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
HStack,
|
||||
VStack,
|
||||
} from '../../components/elements/LayoutPrimitives'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { applyStoredTheme, isDarkTheme } from '../../lib/themeUpdater'
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { Label, LabelColor } from '../../lib/networking/fragments/labelFragment'
|
||||
@ -156,9 +155,8 @@ export default function LabelsPage(): JSX.Element {
|
||||
const [descriptionInputText, setDescriptionInputText] = useState<string>('')
|
||||
const [isCreateMode, setIsCreateMode] = useState<boolean>(false)
|
||||
const [windowWidth, setWindowWidth] = useState<number>(0)
|
||||
const [confirmRemoveLabelId, setConfirmRemoveLabelId] = useState<
|
||||
string | null
|
||||
>(null)
|
||||
const [confirmRemoveLabelId, setConfirmRemoveLabelId] =
|
||||
useState<string | null>(null)
|
||||
const [showLabelPageHelp, setShowLabelPageHelp] = usePersistedState<boolean>({
|
||||
key: `--settings-labels-show-help`,
|
||||
initialValue: true,
|
||||
@ -262,11 +260,6 @@ export default function LabelsPage(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<HStack css={{ width: '100%', height: '100%' }}>
|
||||
<VStack
|
||||
css={{
|
||||
|
||||
@ -5,7 +5,6 @@ import React, {
|
||||
useMemo,
|
||||
useReducer,
|
||||
} from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import {
|
||||
Box,
|
||||
HStack,
|
||||
@ -144,11 +143,6 @@ export default function PinnedSearches(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<VStack
|
||||
css={{ width: '100%', height: '100%' }}
|
||||
distribution="start"
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Button, Form, Input, Modal, Select, Space, Table, Tag } from 'antd'
|
||||
import 'antd/dist/antd.compact.css'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { Box, HStack } from '../../components/elements/LayoutPrimitives'
|
||||
import { SettingsLayout } from '../../components/templates/SettingsLayout'
|
||||
import { Label } from '../../lib/networking/fragments/labelFragment'
|
||||
@ -181,9 +180,8 @@ const CreateActionModal = (props: CreateActionModalProps): JSX.Element => {
|
||||
}
|
||||
}
|
||||
|
||||
const [actionType, setActionType] = useState<RuleActionType | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [actionType, setActionType] =
|
||||
useState<RuleActionType | undefined>(undefined)
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -304,9 +302,8 @@ export default function Rules(): JSX.Element {
|
||||
const { rules, revalidate } = useGetRulesQuery()
|
||||
const { data: labels } = useGetLabels()
|
||||
const [isCreateRuleModalOpen, setIsCreateRuleModalOpen] = useState(false)
|
||||
const [createActionRule, setCreateActionRule] = useState<Rule | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [createActionRule, setCreateActionRule] =
|
||||
useState<Rule | undefined>(undefined)
|
||||
|
||||
const dataSource = useMemo(() => {
|
||||
return rules.map((rule: Rule) => {
|
||||
@ -435,12 +432,6 @@ export default function Rules(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
|
||||
<CreateRuleModal
|
||||
revalidate={revalidate}
|
||||
isModalOpen={isCreateRuleModalOpen}
|
||||
|
||||
@ -15,7 +15,6 @@ import {
|
||||
HStack,
|
||||
VStack,
|
||||
} from '../../components/elements/LayoutPrimitives'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { applyStoredTheme, isDarkTheme } from '../../lib/themeUpdater'
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { StyledText } from '../../components/elements/StyledText'
|
||||
@ -162,14 +161,14 @@ export default function SavedSearchesPage(): JSX.Element {
|
||||
const [editingId, setEditingId] = useState<string | null>(null)
|
||||
const [isCreateMode, setIsCreateMode] = useState<boolean>(false)
|
||||
const [windowWidth, setWindowWidth] = useState<number>(0)
|
||||
const [confirmRemoveSavedSearchId, setConfirmRemoveSavedSearchId] = useState<
|
||||
string | null
|
||||
>(null)
|
||||
const [confirmRemoveSavedSearchId, setConfirmRemoveSavedSearchId] =
|
||||
useState<string | null>(null)
|
||||
const [draggedElementId, setDraggedElementId] = useState<string | null>(null)
|
||||
const [draggedElementPosition, setDraggedElementPosition] = useState<{
|
||||
x: number
|
||||
y: number
|
||||
} | null>(null)
|
||||
const [draggedElementPosition, setDraggedElementPosition] =
|
||||
useState<{
|
||||
x: number
|
||||
y: number
|
||||
} | null>(null)
|
||||
const [sortedSavedSearch, setSortedSavedSearch] = useState<SavedSearch[]>([])
|
||||
|
||||
// Some theming stuff here.
|
||||
@ -330,11 +329,6 @@ export default function SavedSearchesPage(): JSX.Element {
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<HStack css={{ width: '100%', height: '100%' }}>
|
||||
<VStack
|
||||
css={{
|
||||
@ -592,14 +586,15 @@ function GenericTableCard(
|
||||
const iconColor = isDarkTheme() ? '#D8D7D5' : '#5F5E58'
|
||||
const DEFAULT_STYLE = { position: null }
|
||||
const updateSavedSearchFunc = useUpdateSavedSearch()
|
||||
const [style, setStyle] = useState<
|
||||
Partial<{
|
||||
position: string | null
|
||||
top: string
|
||||
left: string
|
||||
maxWidth: string
|
||||
}>
|
||||
>(DEFAULT_STYLE)
|
||||
const [style, setStyle] =
|
||||
useState<
|
||||
Partial<{
|
||||
position: string | null
|
||||
top: string
|
||||
left: string
|
||||
maxWidth: string
|
||||
}>
|
||||
>(DEFAULT_STYLE)
|
||||
const handleEdit = () => {
|
||||
editingId && updateSavedSearch(editingId)
|
||||
setEditingId(null)
|
||||
|
||||
@ -1,18 +1,6 @@
|
||||
import {
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useReducer,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { applyStoredTheme } from '../../lib/themeUpdater'
|
||||
|
||||
import { useCallback, useEffect, useMemo, useReducer } from 'react'
|
||||
import { SettingsLayout } from '../../components/templates/SettingsLayout'
|
||||
import { NavigationLayout } from '../../components/templates/NavigationLayout'
|
||||
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { styled } from '../../components/tokens/stitches.config'
|
||||
import {
|
||||
Box,
|
||||
VStack,
|
||||
@ -20,36 +8,23 @@ import {
|
||||
SpanBox,
|
||||
Separator,
|
||||
} from '../../components/elements/LayoutPrimitives'
|
||||
import { LabelChip } from '../../components/elements/LabelChip'
|
||||
import { StyledText } from '../../components/elements/StyledText'
|
||||
import {
|
||||
Subscription,
|
||||
SubscriptionType,
|
||||
useGetSubscriptionsQuery,
|
||||
} from '../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { DragIcon } from '../../components/elements/icons/DragIcon'
|
||||
import { SubscriptionType } from '../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { CoverImage } from '../../components/elements/CoverImage'
|
||||
import { Label } from '../../lib/networking/fragments/labelFragment'
|
||||
import { usePersistedState } from '../../lib/hooks/usePersistedState'
|
||||
import { CheckSquare, Square, Tag } from '@phosphor-icons/react'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import { styled } from '@stitches/react'
|
||||
import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment'
|
||||
import { escapeQuotes } from '../../utils/helper'
|
||||
import { useGetLabels } from '../../lib/networking/labels/useLabels'
|
||||
import { useGetSavedSearches } from '../../lib/networking/savedsearches/useSavedSearches'
|
||||
import {
|
||||
Shortcut,
|
||||
ShortcutType,
|
||||
useGetShortcuts,
|
||||
useResetShortcuts,
|
||||
useSetShortcuts,
|
||||
} from '../../lib/networking/shortcuts/useShortcuts'
|
||||
import * as Switch from '@radix-ui/react-switch'
|
||||
import { useGetSubscriptions } from '../../lib/networking/subscriptions/useGetSubscriptions'
|
||||
import { NewsletterIcon } from '../../components/elements/icons/NewsletterIcon'
|
||||
import { FollowingIcon } from '../../components/elements/icons/FollowingIcon'
|
||||
import { LIBRARY_LEFT_MENU_WIDTH } from '../../components/templates/navMenu/NavigationMenu'
|
||||
import { escapeQuotes } from '../../utils/helper'
|
||||
import { Tag } from '@phosphor-icons/react'
|
||||
|
||||
function flattenShortcuts(shortcuts: Shortcut[]): string[] {
|
||||
let result: string[] = []
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { SettingsLayout } from '../../components/templates/SettingsLayout'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { VStack } from '../../components/elements/LayoutPrimitives'
|
||||
import Link from 'next/link'
|
||||
import { StyledText } from '../../components/elements/StyledText'
|
||||
@ -7,11 +6,6 @@ import { StyledText } from '../../components/elements/StyledText'
|
||||
export default function Webhooks(): JSX.Element {
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: '5rem',
|
||||
}}
|
||||
/>
|
||||
<VStack
|
||||
css={{ width: '100%', height: '100%' }}
|
||||
distribution="start"
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react'
|
||||
import { Toaster, ToastPosition } from 'react-hot-toast'
|
||||
import { showErrorToast, showSuccessToast } from '../lib/toastHelpers'
|
||||
import { Button } from '../components/elements/Button'
|
||||
|
||||
export default {
|
||||
title: 'Components/Snackbar',
|
||||
component: Toaster,
|
||||
argTypes: {
|
||||
position: {
|
||||
description: 'The position of the snackbar',
|
||||
options: [
|
||||
'top-left',
|
||||
'top-center',
|
||||
'top-right',
|
||||
'bottom-right',
|
||||
'bottom-center',
|
||||
'bottom-left',
|
||||
],
|
||||
control: { type: 'select' },
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof Toaster>
|
||||
|
||||
const Template = ({ showToast, position }: { showToast: () => void; position?: ToastPosition }) => (
|
||||
<div>
|
||||
<Toaster position={position} />
|
||||
<div
|
||||
style={{
|
||||
height: '15rem',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Button style='ctaGray' onClick={showToast}>
|
||||
Show Toast
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const SuccessSnackbar: ComponentStory<typeof Toaster> = (args: any) => {
|
||||
return (
|
||||
<Template {...args} showToast={() => showSuccessToast('Success Message')} />
|
||||
)
|
||||
}
|
||||
|
||||
export const ErrorSnackbar: ComponentStory<typeof Toaster> = (args: any) => {
|
||||
return (
|
||||
<Template {...args} showToast={() => showErrorToast('Error Message!')} />
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user