From 9f20920ddc751b717a747830348341bbe1e169c2 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 16:50:39 +0800 Subject: [PATCH 01/22] Initial work on the recent emails feature --- .../networking/queries/useGetRecentEmails.tsx | 78 ++++++ packages/web/pages/settings/emails/index.tsx | 234 ++++++++++++++++++ packages/web/pages/settings/emails/recent.tsx | 196 +++++++++++++++ 3 files changed, 508 insertions(+) create mode 100644 packages/web/lib/networking/queries/useGetRecentEmails.tsx create mode 100644 packages/web/pages/settings/emails/index.tsx create mode 100644 packages/web/pages/settings/emails/recent.tsx diff --git a/packages/web/lib/networking/queries/useGetRecentEmails.tsx b/packages/web/lib/networking/queries/useGetRecentEmails.tsx new file mode 100644 index 000000000..a8b10aee8 --- /dev/null +++ b/packages/web/lib/networking/queries/useGetRecentEmails.tsx @@ -0,0 +1,78 @@ +import { gql } from 'graphql-request' +import useSWR from 'swr' +import { publicGqlFetcher } from '../networkHelpers' + +export interface RecentEmail { + id: string + from: string + to: string + subject: string + type: string + text: string + createdAt: string +} + +interface RecentEmailsResponse { + isValidating: boolean + recentEmails: RecentEmail[] + revalidate: () => void +} + +interface RecentEmailsResponseData { + recentEmails: RecentEmailsData +} + +interface RecentEmailsData { + recentEmails: RecentEmail[] +} + +export function useGetRecentEmailsQuery(): RecentEmailsResponse { + const query = gql` + query GetRecentEmails { + recentEmails { + ... on RecentEmailsSuccess { + recentEmails { + id + from + to + subject + type + text + createdAt + } + } + ... on RecentEmailsError { + errorCodes + } + } + } + ` + + const { data, mutate, error, isValidating } = useSWR(query, publicGqlFetcher) + + try { + if (error) { + throw error + } + + if (data) { + const result = data as RecentEmailsResponseData + const recentEmails = result.recentEmails.recentEmails as RecentEmail[] + return { + isValidating, + recentEmails, + revalidate: () => { + mutate() + }, + } + } + } catch (error) { + console.log('error', error) + } + return { + isValidating: false, + recentEmails: [], + // eslint-disable-next-line @typescript-eslint/no-empty-function + revalidate: () => {}, + } +} diff --git a/packages/web/pages/settings/emails/index.tsx b/packages/web/pages/settings/emails/index.tsx new file mode 100644 index 000000000..4f064d53e --- /dev/null +++ b/packages/web/pages/settings/emails/index.tsx @@ -0,0 +1,234 @@ +import { Button } from '../../../components/elements/Button' +import { useGetNewsletterEmailsQuery } from '../../../lib/networking/queries/useGetNewsletterEmailsQuery' +import { createNewsletterEmailMutation } from '../../../lib/networking/mutations/createNewsletterEmailMutation' +import { deleteNewsletterEmailMutation } from '../../../lib/networking/mutations/deleteNewsletterEmailMutation' +import { MoreOptionsIcon } from '../../../components/elements/images/MoreOptionsIcon' +import { Trash, Copy } from 'phosphor-react' +import { + Dropdown, + DropdownOption, +} from '../../../components/elements/DropdownElements' +import { theme, styled } from '../../../components/tokens/stitches.config' +import { Box, HStack } from '../../../components/elements/LayoutPrimitives' +import { useCopyLink } from '../../../lib/hooks/useCopyLink' +import { useCallback, useMemo, useState } from 'react' +import { StyledText } from '../../../components/elements/StyledText' +import { applyStoredTheme } from '../../../lib/themeUpdater' +import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' +import { formattedShortDate } from '../../../lib/dateFormatting' +import Link from 'next/link' +import { + EmptySettingsRow, + SettingsTable, + SettingsTableRow, +} from '../../../components/templates/settings/SettingsTable' +import { ConfirmationModal } from '../../../components/patterns/ConfirmationModal' + +enum TextType { + EmailAddress, + ConfirmationCode, +} + +type CopyTextButtonProps = { + text: string + type: TextType +} + +const CopyTextBtnWrapper = styled(Box, { + background: '$grayBgActive', + borderRadius: '6px', + border: '1px solid rgba(0, 0, 0, 0.06)', + width: '32px', + height: '32px', + + display: 'flex', + + color: '#3D3D3D', + + alignItems: 'center', + justifyContent: 'center', +}) + +function CopyTextButton(props: CopyTextButtonProps): JSX.Element { + const { copyLink, isLinkCopied } = useCopyLink( + props.text, + 'newsletter_' + + (props.type == TextType.EmailAddress + ? 'email_address' + : 'confirmation_code') + ) + + const copy = useCallback(() => { + copyLink() + showSuccessToast( + props.type == TextType.EmailAddress + ? 'Email Address Copied' + : 'Confirmation Code Copied' + ) + }, []) + + return ( + + ) +} + +export default function EmailsPage(): JSX.Element { + const { emailAddresses, revalidate, isValidating } = + useGetNewsletterEmailsQuery() + const [confirmDeleteEmailId, setConfirmDeleteEmailId] = useState< + undefined | string + >(undefined) + + applyStoredTheme(false) + + async function createEmail(): Promise { + const email = await createNewsletterEmailMutation() + if (!email) { + showErrorToast('Error Creating Email') + return + } + showSuccessToast('Email Created') + revalidate() + } + + async function deleteEmail(id: string): Promise { + const result = await deleteNewsletterEmailMutation(id) + if (!result) { + showErrorToast('Error Deleting Email') + return + } + revalidate() + showSuccessToast('Email Deleted') + } + + const sortedEmailAddresses = useMemo(() => { + if (!emailAddresses) { + return [] + } + return emailAddresses.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) + }, [emailAddresses]) + + return ( + <> + + {sortedEmailAddresses.length > 0 ? ( + sortedEmailAddresses.map((email, i) => { + return ( + setConfirmDeleteEmailId(email.id)} + deleteTitle="Delete" + sublineElement={ + + {`created ${formattedShortDate(email.createdAt)}, `} + {`${email.subscriptionCount} subscriptions`} + + } + titleElement={ + + + + } + extraElement={ + email.confirmationCode ? ( + + <> + + {`Gmail: ${email.confirmationCode}`} + + + + + + + + + ) : ( + <> + ) + } + /> + ) + }) + ) : ( + + )} + + + {confirmDeleteEmailId ? ( + { + await deleteEmail(confirmDeleteEmailId) + setConfirmDeleteEmailId(undefined) + }} + onOpenChange={() => setConfirmDeleteEmailId(undefined)} + /> + ) : null} + + ) +} diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx new file mode 100644 index 000000000..d5eec181c --- /dev/null +++ b/packages/web/pages/settings/emails/recent.tsx @@ -0,0 +1,196 @@ +import { useEffect, useMemo, useState } from 'react' +import { useRouter } from 'next/router' + +import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' +import { applyStoredTheme } from '../../../lib/themeUpdater' + +import { FormInputProps } from '../../../components/elements/FormElements' +import { + EmptySettingsRow, + SettingsTable, + SettingsTableRow, +} from '../../../components/templates/settings/SettingsTable' +import { StyledText } from '../../../components/elements/StyledText' +import { formattedShortDate } from '../../../lib/dateFormatting' +import { + RecentEmail, + useGetRecentEmailsQuery, +} from '../../../lib/networking/queries/useGetRecentEmails' +import Link from 'next/link' + +export default function RecentEmails(): JSX.Element { + const { recentEmails, revalidate, isValidating } = useGetRecentEmailsQuery() + const [onDeleteId, setOnDeleteId] = useState('') + const [addModalOpen, setAddModalOpen] = useState(false) + const [name, setName] = useState('') + const [value, setValue] = useState('') + const [expiresAt, setExpiresAt] = useState(new Date()) + const [formInputs, setFormInputs] = useState([]) + const [apiKeyGenerated, setApiKeyGenerated] = useState('') + const neverExpiresDate = new Date(8640000000000000) + const defaultExpiresAt = 'Never' + + applyStoredTheme(false) + + // async function onDelete(id: string): Promise { + // const result = await revokeApiKeyMutation(id) + // if (result) { + // showSuccessToast('API Key deleted', { position: 'bottom-right' }) + // } else { + // showErrorToast('Failed to delete', { position: 'bottom-right' }) + // } + // revalidate() + // } + + // async function onCreate(): Promise { + // const result = await generateApiKeyMutation({ name, expiresAt }) + // if (result) { + // setApiKeyGenerated(result) + // showSuccessToast('API key generated', { position: 'bottom-right' }) + // } else { + // showErrorToast('Failed to add', { position: 'bottom-right' }) + // } + // revalidate() + // } + + // function onAdd() { + // return setFormInputs([ + // { + // label: 'Name', + // onChange: setName, + // name: 'name', + // value: value, + // required: true, + // }, + // { + // label: 'Expires', + // name: 'expiredAt', + // required: true, + // onChange: (e) => { + // console.log('onChange: ', e) + // let additionalDays = 0 + // switch (e.target.value) { + // case 'in 7 days': + // additionalDays = 7 + // break + // case 'in 30 days': + // additionalDays = 30 + // break + // case 'in 90 days': + // additionalDays = 90 + // break + // case 'in 1 year': + // additionalDays = 365 + // break + // case 'Never': + // break + // } + // const newExpires = additionalDays ? new Date() : neverExpiresDate + // if (additionalDays) { + // newExpires.setDate(newExpires.getDate() + additionalDays) + // } + // setExpiresAt(newExpires) + // }, + // type: 'select', + // options: [ + // 'in 7 days', + // 'in 30 days', + // 'in 90 days', + // 'in 1 year', + // 'Never', + // ], + // value: defaultExpiresAt, + // }, + // ]) + // } + + const sortedRecentEmails = useMemo(() => { + if (!recentEmails) { + return [] + } + return recentEmails.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) + }, [recentEmails]) + + return ( + + {sortedRecentEmails.length > 0 ? ( + sortedRecentEmails.map((recentEmail: RecentEmail, i) => { + return ( + { + console.log('onDelete triggered: ', recentEmail.id) + setOnDeleteId(recentEmail.id) + }} + deleteTitle="Delete" + sublineElement={ + + {`From ${formattedShortDate(recentEmail.from)},`} + {`Received ${formattedShortDate(recentEmail.createdAt)} at `} + + {recentEmail.to} + + + } + /> + ) + }) + ) : ( + + )} + {/* + {addModalOpen && ( + + )} + + {apiKeyGenerated && ( + { + await navigator.clipboard.writeText(apiKeyGenerated) + setApiKeyGenerated('') + }} + onOpenChange={() => setApiKeyGenerated('')} + /> + )} + + {onDeleteId && ( + { + await onDelete(onDeleteId) + setOnDeleteId('') + }} + onOpenChange={() => setOnDeleteId('')} + /> + )} */} + + ) +} From b711efea382c7ab6718996b48d65f2461b70dddc Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 17:10:37 +0800 Subject: [PATCH 02/22] Fix formatting of recent emails byline --- packages/web/pages/settings/emails.tsx | 233 ------------------ packages/web/pages/settings/emails/recent.tsx | 9 +- 2 files changed, 6 insertions(+), 236 deletions(-) delete mode 100644 packages/web/pages/settings/emails.tsx diff --git a/packages/web/pages/settings/emails.tsx b/packages/web/pages/settings/emails.tsx deleted file mode 100644 index ab432fdb4..000000000 --- a/packages/web/pages/settings/emails.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import { Button } from '../../components/elements/Button' -import { useGetNewsletterEmailsQuery } from '../../lib/networking/queries/useGetNewsletterEmailsQuery' -import { createNewsletterEmailMutation } from '../../lib/networking/mutations/createNewsletterEmailMutation' -import { deleteNewsletterEmailMutation } from '../../lib/networking/mutations/deleteNewsletterEmailMutation' -import { MoreOptionsIcon } from '../../components/elements/images/MoreOptionsIcon' -import { Trash, Copy } from 'phosphor-react' -import { - Dropdown, - DropdownOption, -} from '../../components/elements/DropdownElements' -import { theme, styled } from '../../components/tokens/stitches.config' -import { Box, HStack } from '../../components/elements/LayoutPrimitives' -import { useCopyLink } from '../../lib/hooks/useCopyLink' -import { useCallback, useMemo, useState } from 'react' -import { StyledText } from '../../components/elements/StyledText' -import { applyStoredTheme } from '../../lib/themeUpdater' -import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers' -import { formattedShortDate } from '../../lib/dateFormatting' -import Link from 'next/link' -import { - EmptySettingsRow, - SettingsTable, - SettingsTableRow, -} from '../../components/templates/settings/SettingsTable' -import { ConfirmationModal } from '../../components/patterns/ConfirmationModal' - -enum TextType { - EmailAddress, - ConfirmationCode, -} - -type CopyTextButtonProps = { - text: string - type: TextType -} - -const CopyTextBtnWrapper = styled(Box, { - background: '$grayBgActive', - borderRadius: '6px', - border: '1px solid rgba(0, 0, 0, 0.06)', - width: '32px', - height: '32px', - - display: 'flex', - - color: '#3D3D3D', - - alignItems: 'center', - justifyContent: 'center', -}) - -function CopyTextButton(props: CopyTextButtonProps): JSX.Element { - const { copyLink, isLinkCopied } = useCopyLink( - props.text, - 'newsletter_' + - (props.type == TextType.EmailAddress - ? 'email_address' - : 'confirmation_code') - ) - - const copy = useCallback(() => { - copyLink() - showSuccessToast( - props.type == TextType.EmailAddress - ? 'Email Address Copied' - : 'Confirmation Code Copied' - ) - }, []) - - return ( - - ) -} - -export default function EmailsPage(): JSX.Element { - const { emailAddresses, revalidate, isValidating } = - useGetNewsletterEmailsQuery() - const [confirmDeleteEmailId, setConfirmDeleteEmailId] = - useState(undefined) - - applyStoredTheme(false) - - async function createEmail(): Promise { - const email = await createNewsletterEmailMutation() - if (!email) { - showErrorToast('Error Creating Email') - return - } - showSuccessToast('Email Created') - revalidate() - } - - async function deleteEmail(id: string): Promise { - const result = await deleteNewsletterEmailMutation(id) - if (!result) { - showErrorToast('Error Deleting Email') - return - } - revalidate() - showSuccessToast('Email Deleted') - } - - const sortedEmailAddresses = useMemo(() => { - if (!emailAddresses) { - return [] - } - return emailAddresses.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) - }, [emailAddresses]) - - return ( - <> - - {sortedEmailAddresses.length > 0 ? ( - sortedEmailAddresses.map((email, i) => { - return ( - setConfirmDeleteEmailId(email.id)} - deleteTitle="Delete" - sublineElement={ - - {`created ${formattedShortDate(email.createdAt)}, `} - {`${email.subscriptionCount} subscriptions`} - - } - titleElement={ - - - - } - extraElement={ - email.confirmationCode ? ( - - <> - - {`Gmail: ${email.confirmationCode}`} - - - - - - - - - ) : ( - <> - ) - } - /> - ) - }) - ) : ( - - )} - - - {confirmDeleteEmailId ? ( - { - await deleteEmail(confirmDeleteEmailId) - setConfirmDeleteEmailId(undefined) - }} - onOpenChange={() => setConfirmDeleteEmailId(undefined)} - /> - ) : null} - - ) -} diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index d5eec181c..eb7641077 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -120,10 +120,11 @@ export default function RecentEmails(): JSX.Element { > {sortedRecentEmails.length > 0 ? ( sortedRecentEmails.map((recentEmail: RecentEmail, i) => { + console.log('recent email: ', recentEmail) return ( { console.log('onDelete triggered: ', recentEmail.id) @@ -140,8 +141,10 @@ export default function RecentEmails(): JSX.Element { }, }} > - {`From ${formattedShortDate(recentEmail.from)},`} - {`Received ${formattedShortDate(recentEmail.createdAt)} at `} + {recentEmail.subject} + {`, Received ${formattedShortDate( + recentEmail.createdAt + )} at `} {recentEmail.to} From de971bb027c8db19036cff038be9d087193e33ee Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 17:22:47 +0800 Subject: [PATCH 03/22] More formatting for recent emails --- packages/web/pages/settings/emails/recent.tsx | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index eb7641077..6991022ca 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -17,6 +17,7 @@ import { useGetRecentEmailsQuery, } from '../../../lib/networking/queries/useGetRecentEmails' import Link from 'next/link' +import { HStack } from '../../../components/elements/LayoutPrimitives' export default function RecentEmails(): JSX.Element { const { recentEmails, revalidate, isValidating } = useGetRecentEmailsQuery() @@ -132,23 +133,37 @@ export default function RecentEmails(): JSX.Element { }} deleteTitle="Delete" sublineElement={ - - {recentEmail.subject} - {`, Received ${formattedShortDate( - recentEmail.createdAt - )} at `} - - {recentEmail.to} - - + + + {recentEmail.subject} + + + + {recentEmail.to} + + + + {formattedShortDate(recentEmail.createdAt)} + + } /> ) From 2ae920f36d97efd2fe0f40b97f77fbdf5d122b39 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 17:25:08 +0800 Subject: [PATCH 04/22] Display type for recentEmail --- packages/web/pages/settings/emails/recent.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 6991022ca..1082a19db 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -161,7 +161,9 @@ export default function RecentEmails(): JSX.Element { }, }} > - {formattedShortDate(recentEmail.createdAt)} + {`${formattedShortDate( + recentEmail.createdAt + )}, classfied as: ${recentEmail.type}`} } From 23944e2d62c09287748b01df6ef30d0f4a12b3bc Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 17:32:04 +0800 Subject: [PATCH 05/22] Use VStack for email layout --- packages/web/pages/settings/emails/recent.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 1082a19db..4453f3f22 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -17,7 +17,7 @@ import { useGetRecentEmailsQuery, } from '../../../lib/networking/queries/useGetRecentEmails' import Link from 'next/link' -import { HStack } from '../../../components/elements/LayoutPrimitives' +import { HStack, VStack } from '../../../components/elements/LayoutPrimitives' export default function RecentEmails(): JSX.Element { const { recentEmails, revalidate, isValidating } = useGetRecentEmailsQuery() @@ -133,7 +133,7 @@ export default function RecentEmails(): JSX.Element { }} deleteTitle="Delete" sublineElement={ - + - + } /> ) From 52d32d4f24e78a6a479440b6e6367873f7a83253 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:10:42 +0800 Subject: [PATCH 06/22] Allow viewing text of recently received emails --- .../templates/settings/SettingsTable.tsx | 69 ++-- packages/web/pages/settings/api.tsx | 1 - packages/web/pages/settings/emails/recent.tsx | 300 +++++++++--------- packages/web/pages/settings/subscriptions.tsx | 6 +- 4 files changed, 200 insertions(+), 176 deletions(-) diff --git a/packages/web/components/templates/settings/SettingsTable.tsx b/packages/web/components/templates/settings/SettingsTable.tsx index 705b34252..6222c0fac 100644 --- a/packages/web/components/templates/settings/SettingsTable.tsx +++ b/packages/web/components/templates/settings/SettingsTable.tsx @@ -12,7 +12,6 @@ import { PrimaryLayout } from '../PrimaryLayout' type SettingsTableProps = { pageId: string - pageHeadline: string pageInfoLink: string headerTitle: string @@ -35,13 +34,16 @@ type SettingsTableRowProps = { titleElement?: JSX.Element extraElement?: JSX.Element - deleteTitle: string - onDelete: () => void + deleteTitle?: string + onDelete?: () => void + + dropdownItems?: JSX.Element } type MoreOptionsProps = { - title: string - onDelete: () => void + title?: string + onDelete?: () => void + dropdownItems?: JSX.Element } const MoreOptions = (props: MoreOptionsProps) => ( @@ -63,29 +65,32 @@ const MoreOptions = (props: MoreOptionsProps) => ( } > - { - props.onDelete() - }} - > - - - { + props.onDelete && props.onDelete() + }} + > + + + - {props.title} - - - + '&:hover': { + border: 'none', + backgroundColor: 'transparent', + }, + }} + > + {props.title} + + + + )} + {props.dropdownItems && props.dropdownItems} ) @@ -183,7 +188,11 @@ export const SettingsTableRow = (props: SettingsTableRowProps): JSX.Element => { }, }} > - + {props.extraElement} @@ -198,7 +207,11 @@ export const SettingsTableRow = (props: SettingsTableRowProps): JSX.Element => { }, }} > - + diff --git a/packages/web/pages/settings/api.tsx b/packages/web/pages/settings/api.tsx index a258505ed..43d0d20ee 100644 --- a/packages/web/pages/settings/api.tsx +++ b/packages/web/pages/settings/api.tsx @@ -114,7 +114,6 @@ export default function Api(): JSX.Element { return ( { + const backgroundColor = props.type == 'article' ? '$omnivoreCtaYellow' : 'red' + return ( + + {props.type} + + ) +} + +type MoreOptionItemProps = { + text: string + action: () => void +} + +const MoreOptionItem = (props: MoreOptionItemProps): JSX.Element => { + return ( + { + props.action() + }} + > + + + {props.text} + + + + ) +} + +type ViewRecentEmailModalProps = { + recentEmail: RecentEmail + onOpenChange: (open: boolean) => void +} + +const ViewRecentEmailModal = ( + props: ViewRecentEmailModalProps +): JSX.Element => { + return ( + + + { + // remove focus from modal + ;(document.activeElement as HTMLElement).blur() + }} + > + + + + {props.recentEmail.text} + + + + + ) +} export default function RecentEmails(): JSX.Element { - const { recentEmails, revalidate, isValidating } = useGetRecentEmailsQuery() - const [onDeleteId, setOnDeleteId] = useState('') - const [addModalOpen, setAddModalOpen] = useState(false) - const [name, setName] = useState('') - const [value, setValue] = useState('') - const [expiresAt, setExpiresAt] = useState(new Date()) - const [formInputs, setFormInputs] = useState([]) - const [apiKeyGenerated, setApiKeyGenerated] = useState('') - const neverExpiresDate = new Date(8640000000000000) - const defaultExpiresAt = 'Never' + const { recentEmails, isValidating } = useGetRecentEmailsQuery() + const [viewingEmail, setViewingEmail] = useState( + undefined + ) applyStoredTheme(false) - // async function onDelete(id: string): Promise { - // const result = await revokeApiKeyMutation(id) - // if (result) { - // showSuccessToast('API Key deleted', { position: 'bottom-right' }) - // } else { - // showErrorToast('Failed to delete', { position: 'bottom-right' }) - // } - // revalidate() - // } - - // async function onCreate(): Promise { - // const result = await generateApiKeyMutation({ name, expiresAt }) - // if (result) { - // setApiKeyGenerated(result) - // showSuccessToast('API key generated', { position: 'bottom-right' }) - // } else { - // showErrorToast('Failed to add', { position: 'bottom-right' }) - // } - // revalidate() - // } - - // function onAdd() { - // return setFormInputs([ - // { - // label: 'Name', - // onChange: setName, - // name: 'name', - // value: value, - // required: true, - // }, - // { - // label: 'Expires', - // name: 'expiredAt', - // required: true, - // onChange: (e) => { - // console.log('onChange: ', e) - // let additionalDays = 0 - // switch (e.target.value) { - // case 'in 7 days': - // additionalDays = 7 - // break - // case 'in 30 days': - // additionalDays = 30 - // break - // case 'in 90 days': - // additionalDays = 90 - // break - // case 'in 1 year': - // additionalDays = 365 - // break - // case 'Never': - // break - // } - // const newExpires = additionalDays ? new Date() : neverExpiresDate - // if (additionalDays) { - // newExpires.setDate(newExpires.getDate() + additionalDays) - // } - // setExpiresAt(newExpires) - // }, - // type: 'select', - // options: [ - // 'in 7 days', - // 'in 30 days', - // 'in 90 days', - // 'in 1 year', - // 'Never', - // ], - // value: defaultExpiresAt, - // }, - // ]) - // } - const sortedRecentEmails = useMemo(() => { + const stub = { + createdAt: '2023-01-25T09:00:02.000Z', + from: 'Jackson Harper from 😜 Jackson’s Newsletter ', + id: 'a7210b62-9c8e-11ed-bac2-7321761ada92', + subject: 'This is a test post i just created', + text: 'View this post on the web at https://jacksonharper.substack.com/p/this-is-a-test-post-i-just-created\n\nThis is a test post created on substack. You can read it in your recent emails.\n\nUnsubscribe https://substack.com/redirect/2/eyJlIjoiaHR0cHM6Ly9qYWNrc29uaGFycGVyLnN1YnN0YWNrLmNvbS9hY3Rpb24vZGlzYWJsZV9lbWFpbD90b2tlbj1leUoxYzJWeVgybGtJam8zTWpVMU16RXlNQ3dpY0c5emRGOXBaQ0k2T1RnNE5EYzFNRE1zSW1saGRDSTZNVFkzTkRZek56RTVOU3dpWlhod0lqb3hOamMzTWpJNU1UazFMQ0pwYzNNaU9pSndkV0l0Tmpnek1Ea3hJaXdpYzNWaUlqb2laR2x6WVdKc1pWOWxiV0ZwYkNKOS5SenJLc1RUcXQ5VTlXbFliY250ZmR1anFjeW80Mk5mUDFSNjRLMXBoRVJZIiwicCI6OTg4NDc1MDMsInMiOjY4MzA5MSwiZiI6dHJ1ZSwidSI6NzI1NTMxMjAsImlhdCI6MTY3NDYzNzE5NSwiZXhwIjoxNjc3MjI5MTk1LCJpc3MiOiJwdWItMCIsInN1YiI6ImxpbmstcmVkaXJlY3QifQ.bQzDxlIPeV1K2lMXAFkBrFkSiAxEJWOC-9VLw372kME?', + to: 'jacksonh-eEMfQepve@inbox-demo.omnivore.app', + type: 'article', + } + return [stub] if (!recentEmails) { return [] } @@ -115,23 +158,16 @@ export default function RecentEmails(): JSX.Element { return ( {sortedRecentEmails.length > 0 ? ( sortedRecentEmails.map((recentEmail: RecentEmail, i) => { - console.log('recent email: ', recentEmail) return ( { - console.log('onDelete triggered: ', recentEmail.id) - setOnDeleteId(recentEmail.id) - }} - deleteTitle="Delete" sublineElement={ - - {recentEmail.to} - - - - {`${formattedShortDate( - recentEmail.createdAt - )}, classfied as: ${recentEmail.type}`} + } + dropdownItems={ + <> + { + console.log('viewing text: ', recentEmail) + setViewingEmail(recentEmail) + }} + /> + { + console.log('marking as email', recentEmail) + }} + /> + + } /> ) }) @@ -175,42 +216,13 @@ export default function RecentEmails(): JSX.Element { text={isValidating ? '-' : 'No recent emails Found'} /> )} - {/* - {addModalOpen && ( - setViewingEmail(undefined)} /> )} - - {apiKeyGenerated && ( - { - await navigator.clipboard.writeText(apiKeyGenerated) - setApiKeyGenerated('') - }} - onOpenChange={() => setApiKeyGenerated('')} - /> - )} - - {onDeleteId && ( - { - await onDelete(onDeleteId) - setOnDeleteId('') - }} - onOpenChange={() => setOnDeleteId('')} - /> - )} */} ) } diff --git a/packages/web/pages/settings/subscriptions.tsx b/packages/web/pages/settings/subscriptions.tsx index ee0bab5f4..7a7826053 100644 --- a/packages/web/pages/settings/subscriptions.tsx +++ b/packages/web/pages/settings/subscriptions.tsx @@ -15,8 +15,9 @@ import { formattedShortDate } from '../../lib/dateFormatting' export default function SubscriptionsPage(): JSX.Element { const { subscriptions, revalidate, isValidating } = useGetSubscriptionsQuery() - const [confirmUnsubscribeName, setConfirmUnsubscribeName] = - useState(null) + const [confirmUnsubscribeName, setConfirmUnsubscribeName] = useState< + string | null + >(null) applyStoredTheme(false) @@ -40,7 +41,6 @@ export default function SubscriptionsPage(): JSX.Element { return ( From 69388148aa7b2d6bfffdb899a5d0e79773bbd43b Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:15:27 +0800 Subject: [PATCH 07/22] Set fontSize of email viewer --- packages/web/pages/settings/emails/recent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 7e1331502..a44acfeef 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -118,7 +118,7 @@ const ViewRecentEmailModal = ( css={{ width: '100%', height: '100%', - py: '16px', + fontSize: '12px', overflowY: 'scroll', }} > From b872c33ba91cc8b4c41cc472a613d1183de803f9 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:29:19 +0800 Subject: [PATCH 08/22] Allow marking recent emails as library items --- .../mutations/markEmailAsItemMutation.ts | 35 +++++++++++++++++++ packages/web/pages/settings/emails/index.tsx | 1 - packages/web/pages/settings/emails/recent.tsx | 13 ++++++- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 packages/web/lib/networking/mutations/markEmailAsItemMutation.ts diff --git a/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts b/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts new file mode 100644 index 000000000..9f8fb8d9b --- /dev/null +++ b/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts @@ -0,0 +1,35 @@ +import { gqlFetcher } from '../networkHelpers' + +type MarkEmailAsItemDataResponseData = { + markEmailAsItem?: MarkEmailAsItemData +} + +type MarkEmailAsItemData = { + success: Boolean + errorCodes?: unknown[] +} + +export async function markEmailAsItemMutation( + recentEmailId: String +): Promise { + const mutation = ` + mutation MarkRecentEmailAsItem($recentEmailId: ID!) { + markEmailAsItem(recentEmailId:$recentEmailId) { + ... on MarkEmailAsItemError { + errorCodes + } + ... on MarkEmailAsItemSuccess { + success + } + } + }` + + const data = await gqlFetcher(mutation, { recentEmailId }) + console.log('recentEmailId: ', data) + const output = data as MarkEmailAsItemDataResponseData | undefined + const error = output?.markEmailAsItem?.errorCodes?.find(() => true) + console.log('error: ', error) + if (error) { + throw error + } +} diff --git a/packages/web/pages/settings/emails/index.tsx b/packages/web/pages/settings/emails/index.tsx index 4f064d53e..c6381f007 100644 --- a/packages/web/pages/settings/emails/index.tsx +++ b/packages/web/pages/settings/emails/index.tsx @@ -118,7 +118,6 @@ export default function EmailsPage(): JSX.Element { <> { + action={async () => { console.log('marking as email', recentEmail) + showSuccessToast('Marking email as article') + try { + await markEmailAsItemMutation(recentEmail.id) + } catch (err) { + console.log('error marking as article: ', err) + showErrorToast('Error marking item as article') + return + } + showSuccessToast('Email added to library') }} /> From 948fa78ab5e40936be278457ee841e82f7f4b39a Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:34:01 +0800 Subject: [PATCH 09/22] Fix types --- .../web/lib/networking/mutations/markEmailAsItemMutation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts b/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts index 9f8fb8d9b..fc6e60690 100644 --- a/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts +++ b/packages/web/lib/networking/mutations/markEmailAsItemMutation.ts @@ -5,12 +5,12 @@ type MarkEmailAsItemDataResponseData = { } type MarkEmailAsItemData = { - success: Boolean + success: boolean errorCodes?: unknown[] } export async function markEmailAsItemMutation( - recentEmailId: String + recentEmailId: string ): Promise { const mutation = ` mutation MarkRecentEmailAsItem($recentEmailId: ID!) { From 2b3a519ebbda2ad7c3afe90255dc0acb3fe9b5ef Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:40:53 +0800 Subject: [PATCH 10/22] Set validating to false if there is an error fetching emails --- packages/web/lib/networking/queries/useGetRecentEmails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/lib/networking/queries/useGetRecentEmails.tsx b/packages/web/lib/networking/queries/useGetRecentEmails.tsx index a8b10aee8..71d68f886 100644 --- a/packages/web/lib/networking/queries/useGetRecentEmails.tsx +++ b/packages/web/lib/networking/queries/useGetRecentEmails.tsx @@ -70,7 +70,7 @@ export function useGetRecentEmailsQuery(): RecentEmailsResponse { console.log('error', error) } return { - isValidating: false, + isValidating: true, recentEmails: [], // eslint-disable-next-line @typescript-eslint/no-empty-function revalidate: () => {}, From c9054bc166f0ca7baf988c6f15828c99fb4ae65d Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 19:59:17 +0800 Subject: [PATCH 11/22] Add some debugging on invalid email handler --- packages/api/src/routers/svc/emails.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/routers/svc/emails.ts b/packages/api/src/routers/svc/emails.ts index 10a7d949f..07af0ae38 100644 --- a/packages/api/src/routers/svc/emails.ts +++ b/packages/api/src/routers/svc/emails.ts @@ -70,7 +70,7 @@ export function emailsServiceRouter() { try { const data = JSON.parse(message) as unknown if (!isEmailMessage(data)) { - logger.error('Invalid message') + logger.error('Invalid message', data) res.status(400).send('Bad Request') return } @@ -153,7 +153,7 @@ export function emailsServiceRouter() { } if (!isEmailMessage(req.body)) { - logger.error('Invalid message') + logger.error('Invalid message', req.body) return res.status(400).send('Bad Request') } From 8c722f9e57c41e80ead0a2c4a3ac9bda6783963b Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 20:29:33 +0800 Subject: [PATCH 12/22] Remove debug code --- packages/web/pages/settings/emails/recent.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 3e3c7f9e5..9e21bd14c 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -1,7 +1,6 @@ import { useMemo, useState } from 'react' import { applyStoredTheme } from '../../../lib/themeUpdater' -import { FormInputProps } from '../../../components/elements/FormElements' import { EmptySettingsRow, SettingsTable, @@ -26,8 +25,6 @@ import { ModalRoot, ModalTitleBar, } from '../../../components/elements/ModalPrimitives' -import TextArea from 'antd/lib/input/TextArea' -import { StyledTextArea } from '../../../components/elements/StyledTextArea' import { markEmailAsItemMutation } from '../../../lib/networking/mutations/markEmailAsItemMutation' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' @@ -141,19 +138,6 @@ export default function RecentEmails(): JSX.Element { applyStoredTheme(false) const sortedRecentEmails = useMemo(() => { - const stub = { - createdAt: '2023-01-25T09:00:02.000Z', - from: 'Jackson Harper from 😜 Jackson’s Newsletter ', - id: 'a7210b62-9c8e-11ed-bac2-7321761ada92', - subject: 'This is a test post i just created', - text: 'View this post on the web at https://jacksonharper.substack.com/p/this-is-a-test-post-i-just-created\n\nThis is a test post created on substack. You can read it in your recent emails.\n\nUnsubscribe https://substack.com/redirect/2/eyJlIjoiaHR0cHM6Ly9qYWNrc29uaGFycGVyLnN1YnN0YWNrLmNvbS9hY3Rpb24vZGlzYWJsZV9lbWFpbD90b2tlbj1leUoxYzJWeVgybGtJam8zTWpVMU16RXlNQ3dpY0c5emRGOXBaQ0k2T1RnNE5EYzFNRE1zSW1saGRDSTZNVFkzTkRZek56RTVOU3dpWlhod0lqb3hOamMzTWpJNU1UazFMQ0pwYzNNaU9pSndkV0l0Tmpnek1Ea3hJaXdpYzNWaUlqb2laR2x6WVdKc1pWOWxiV0ZwYkNKOS5SenJLc1RUcXQ5VTlXbFliY250ZmR1anFjeW80Mk5mUDFSNjRLMXBoRVJZIiwicCI6OTg4NDc1MDMsInMiOjY4MzA5MSwiZiI6dHJ1ZSwidSI6NzI1NTMxMjAsImlhdCI6MTY3NDYzNzE5NSwiZXhwIjoxNjc3MjI5MTk1LCJpc3MiOiJwdWItMCIsInN1YiI6ImxpbmstcmVkaXJlY3QifQ.bQzDxlIPeV1K2lMXAFkBrFkSiAxEJWOC-9VLw372kME?', - to: 'jacksonh-eEMfQepve@inbox-demo.omnivore.app', - type: 'article', - } - return [stub] - if (!recentEmails) { - return [] - } return recentEmails.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) }, [recentEmails]) From a2f88a628844f788013addb29670d8366309d9e6 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 20:40:24 +0800 Subject: [PATCH 13/22] Sort recent emails descending --- packages/web/pages/settings/emails/recent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 9e21bd14c..d470debea 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -138,7 +138,7 @@ export default function RecentEmails(): JSX.Element { applyStoredTheme(false) const sortedRecentEmails = useMemo(() => { - return recentEmails.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) + return recentEmails.sort((a, b) => b.createdAt.localeCompare(a.createdAt)) }, [recentEmails]) return ( From 2168b73c67a15666e244c37dfc6fb26695dcf566 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 20:47:40 +0800 Subject: [PATCH 14/22] Always reserve space for create button so the table doesnt move when navigating between settings views --- packages/web/components/templates/settings/SettingsTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web/components/templates/settings/SettingsTable.tsx b/packages/web/components/templates/settings/SettingsTable.tsx index 6222c0fac..ed63058f1 100644 --- a/packages/web/components/templates/settings/SettingsTable.tsx +++ b/packages/web/components/templates/settings/SettingsTable.tsx @@ -274,6 +274,7 @@ export const SettingsTable = (props: SettingsTableProps): JSX.Element => { display: 'flex', alignItems: 'center', marginBottom: '10px', + height: '60px', }} > {props.createAction && props.createTitle && ( From d9adf7f3761c3c6aff32300896e0b3e228af0c0c Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 20:47:51 +0800 Subject: [PATCH 15/22] Add link to recently received emails --- packages/web/pages/settings/emails/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/web/pages/settings/emails/index.tsx b/packages/web/pages/settings/emails/index.tsx index c6381f007..e14e0d968 100644 --- a/packages/web/pages/settings/emails/index.tsx +++ b/packages/web/pages/settings/emails/index.tsx @@ -214,6 +214,9 @@ export default function EmailsPage(): JSX.Element { text={isValidating ? '-' : 'No Email Addresses Found'} /> )} + + View recently received emails + {confirmDeleteEmailId ? ( From d94bff32f0168f9ae9f98c1e6726dc25a6a55d22 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 20:57:22 +0800 Subject: [PATCH 16/22] Revert API debug line --- packages/api/src/routers/svc/emails.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/routers/svc/emails.ts b/packages/api/src/routers/svc/emails.ts index 07af0ae38..10a7d949f 100644 --- a/packages/api/src/routers/svc/emails.ts +++ b/packages/api/src/routers/svc/emails.ts @@ -70,7 +70,7 @@ export function emailsServiceRouter() { try { const data = JSON.parse(message) as unknown if (!isEmailMessage(data)) { - logger.error('Invalid message', data) + logger.error('Invalid message') res.status(400).send('Bad Request') return } @@ -153,7 +153,7 @@ export function emailsServiceRouter() { } if (!isEmailMessage(req.body)) { - logger.error('Invalid message', req.body) + logger.error('Invalid message') return res.status(400).send('Bad Request') } From af6813f6af1fb1ef351a7667fa285f381c1089ec Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 21:04:45 +0800 Subject: [PATCH 17/22] Move link to recents to the right side --- packages/web/pages/settings/emails/index.tsx | 29 +++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/packages/web/pages/settings/emails/index.tsx b/packages/web/pages/settings/emails/index.tsx index e14e0d968..bf1ec30b4 100644 --- a/packages/web/pages/settings/emails/index.tsx +++ b/packages/web/pages/settings/emails/index.tsx @@ -2,14 +2,13 @@ import { Button } from '../../../components/elements/Button' import { useGetNewsletterEmailsQuery } from '../../../lib/networking/queries/useGetNewsletterEmailsQuery' import { createNewsletterEmailMutation } from '../../../lib/networking/mutations/createNewsletterEmailMutation' import { deleteNewsletterEmailMutation } from '../../../lib/networking/mutations/deleteNewsletterEmailMutation' -import { MoreOptionsIcon } from '../../../components/elements/images/MoreOptionsIcon' -import { Trash, Copy } from 'phosphor-react' -import { - Dropdown, - DropdownOption, -} from '../../../components/elements/DropdownElements' +import { Copy } from 'phosphor-react' import { theme, styled } from '../../../components/tokens/stitches.config' -import { Box, HStack } from '../../../components/elements/LayoutPrimitives' +import { + Box, + HStack, + SpanBox, +} from '../../../components/elements/LayoutPrimitives' import { useCopyLink } from '../../../lib/hooks/useCopyLink' import { useCallback, useMemo, useState } from 'react' import { StyledText } from '../../../components/elements/StyledText' @@ -214,9 +213,19 @@ export default function EmailsPage(): JSX.Element { text={isValidating ? '-' : 'No Email Addresses Found'} /> )} - - View recently received emails - + + + View recently received emails + + {confirmDeleteEmailId ? ( From 5aee465deec3a931752307b7bd415a5b5ed7fcb1 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 21:21:21 +0800 Subject: [PATCH 18/22] Make the email viewer larger --- packages/web/pages/settings/emails/recent.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index d470debea..429cf0c67 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -105,6 +105,7 @@ const ViewRecentEmailModal = ( overflowY: 'auto', height: '100%', width: '100%', + maxWidth: '650px', }} onInteractOutside={() => { // remove focus from modal From 284b9bc0036db8344074579119e40fa7d5c790cd Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 21:34:30 +0800 Subject: [PATCH 19/22] Use findOneBy to query for newsletter email --- packages/api/src/resolvers/recent_emails/index.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/api/src/resolvers/recent_emails/index.ts b/packages/api/src/resolvers/recent_emails/index.ts index 58fccb865..f3c66256c 100644 --- a/packages/api/src/resolvers/recent_emails/index.ts +++ b/packages/api/src/resolvers/recent_emails/index.ts @@ -82,15 +82,12 @@ export const markEmailAsItemResolver = authorized< } } - const newsletterEmail = await getRepository(NewsletterEmail).findOne({ - where: { - address: recentEmail.to, - user: { id: claims.uid }, - }, - relations: ['user'], + const newsletterEmail = await getRepository(NewsletterEmail).findOneBy({ + address: recentEmail.to, + user: { id: claims.uid }, }) if (!newsletterEmail) { - log.info('no newsletter email', recentEmail.to) + log.info('no newsletter email', { to: recentEmail.to }) return { errorCodes: [MarkEmailAsItemErrorCode.NotFound], From 699e7e6879f58f6d8f46acbcb8f0f8dbbfed5515 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 22:14:32 +0800 Subject: [PATCH 20/22] Remove query change --- packages/api/src/resolvers/recent_emails/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/api/src/resolvers/recent_emails/index.ts b/packages/api/src/resolvers/recent_emails/index.ts index f3c66256c..58fccb865 100644 --- a/packages/api/src/resolvers/recent_emails/index.ts +++ b/packages/api/src/resolvers/recent_emails/index.ts @@ -82,12 +82,15 @@ export const markEmailAsItemResolver = authorized< } } - const newsletterEmail = await getRepository(NewsletterEmail).findOneBy({ - address: recentEmail.to, - user: { id: claims.uid }, + const newsletterEmail = await getRepository(NewsletterEmail).findOne({ + where: { + address: recentEmail.to, + user: { id: claims.uid }, + }, + relations: ['user'], }) if (!newsletterEmail) { - log.info('no newsletter email', { to: recentEmail.to }) + log.info('no newsletter email', recentEmail.to) return { errorCodes: [MarkEmailAsItemErrorCode.NotFound], From 80e6062c1e0ad2991d3909b748b24066c8e9fb24 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Wed, 25 Jan 2023 22:20:31 +0800 Subject: [PATCH 21/22] Make font a little smaller for recents link --- packages/web/pages/settings/emails/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web/pages/settings/emails/index.tsx b/packages/web/pages/settings/emails/index.tsx index bf1ec30b4..2db4a11ad 100644 --- a/packages/web/pages/settings/emails/index.tsx +++ b/packages/web/pages/settings/emails/index.tsx @@ -216,6 +216,7 @@ export default function EmailsPage(): JSX.Element { Date: Fri, 27 Jan 2023 17:54:45 +0800 Subject: [PATCH 22/22] Only show mark as article if the email is not an article --- packages/web/pages/settings/emails/recent.tsx | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/web/pages/settings/emails/recent.tsx b/packages/web/pages/settings/emails/recent.tsx index 429cf0c67..c842937d0 100644 --- a/packages/web/pages/settings/emails/recent.tsx +++ b/packages/web/pages/settings/emails/recent.tsx @@ -187,21 +187,23 @@ export default function RecentEmails(): JSX.Element { setViewingEmail(recentEmail) }} /> - { - console.log('marking as email', recentEmail) - showSuccessToast('Marking email as article') - try { - await markEmailAsItemMutation(recentEmail.id) - } catch (err) { - console.log('error marking as article: ', err) - showErrorToast('Error marking item as article') - return - } - showSuccessToast('Email added to library') - }} - /> + {recentEmail.type != 'article' && ( + { + console.log('marking as email', recentEmail) + showSuccessToast('Marking email as article') + try { + await markEmailAsItemMutation(recentEmail.id) + } catch (err) { + console.log('error marking as article: ', err) + showErrorToast('Error marking item as article') + return + } + showSuccessToast('Email added to library') + }} + /> + )} } />