From 9feeb80cf3ca2f178e80dc84184b3c96af516c74 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 9 Jul 2022 14:35:11 -0700 Subject: [PATCH 1/4] Allow fetching original content This is useful when debugging --- packages/api/package.json | 2 + packages/api/src/elastic/pages.ts | 5 +- packages/api/src/resolvers/article/index.ts | 9 ++- .../useGetArticleOriginalHtmlQuery.tsx | 77 +++++++++++++++++++ .../web/pages/[username]/[slug]/original.tsx | 62 +++++++++++++++ 5 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx create mode 100644 packages/web/pages/[username]/[slug]/original.tsx diff --git a/packages/api/package.json b/packages/api/package.json index 79e1cd854..29e154a8d 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -53,6 +53,7 @@ "firebase-admin": "^10.0.2", "googleapis": "^105.0.0", "graphql": "^15.3.0", + "graphql-fields": "^2.0.3", "graphql-middleware": "^6.0.10", "graphql-shield": "^7.5.0", "highlightjs": "^9.16.2", @@ -95,6 +96,7 @@ "@types/cookie-parser": "^1.4.2", "@types/dompurify": "^2.0.4", "@types/express": "^4.17.7", + "@types/graphql-fields": "^1.3.4", "@types/highlightjs": "^9.12.2", "@types/intercom-client": "^2.11.8", "@types/jsonwebtoken": "^8.5.0", diff --git a/packages/api/src/elastic/pages.ts b/packages/api/src/elastic/pages.ts index 2b53c9509..d503e83a1 100644 --- a/packages/api/src/elastic/pages.ts +++ b/packages/api/src/elastic/pages.ts @@ -274,7 +274,8 @@ export const deletePage = async ( } export const getPageByParam = async ( - param: Record + param: Record, + includeOriginalHtml = false ): Promise => { try { const params = { @@ -291,7 +292,7 @@ export const getPageByParam = async ( }, size: 1, _source: { - excludes: ['originalHtml'], + excludes: includeOriginalHtml ? [] : ['originalHtml'], }, } diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index 013cab0d1..f514e86d8 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -69,6 +69,7 @@ import { parseSearchQuery } from '../../utils/search' import { createPageSaveRequest } from '../../services/create_page_save_request' import { analytics } from '../../utils/analytics' import { env } from '../../env' +import graphqlFields from 'graphql-fields' import { ArticleSavingRequestStatus, @@ -397,12 +398,14 @@ export const getArticleResolver: ResolverFn< Record, WithDataSourcesContext, QueryArticleArgs -> = async (_obj, { slug }, { claims, pubsub }) => { +> = async (_obj, { slug }, { claims, pubsub }, info) => { try { if (!claims?.uid) { return { errorCodes: [ArticleErrorCode.Unauthorized] } } + const includeOriginalHtml = !!(graphqlFields(info).article.originalHtml) + analytics.track({ userId: claims?.uid, event: 'link_fetched', @@ -414,8 +417,8 @@ export const getArticleResolver: ResolverFn< // We allow the backend to use the ID instead of a slug to fetch the article const page = - (await getPageByParam({ userId: claims.uid, slug })) || - (await getPageByParam({ userId: claims.uid, _id: slug })) + (await getPageByParam({ userId: claims.uid, slug }, includeOriginalHtml)) || + (await getPageByParam({ userId: claims.uid, _id: slug }, includeOriginalHtml)) if (!page) { return { errorCodes: [ArticleErrorCode.NotFound] } diff --git a/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx new file mode 100644 index 000000000..12bd0965e --- /dev/null +++ b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx @@ -0,0 +1,77 @@ +import { gql } from 'graphql-request' +import useSWRImmutable, { Cache } from 'swr' +import { makeGqlFetcher, RequestContext, ssrFetcher } from '../networkHelpers' +import { ScopedMutator } from 'swr/dist/types' +import { LibraryItems } from './useGetLibraryItemsQuery' + +type ArticleQueryInput = { + username?: string + slug?: string + includeFriendsHighlights?: boolean +} + +type ArticleData = { + article: NestedArticleData +} + +type NestedArticleData = { + article: ArticleAttributes + errorCodes?: string[] +} + +export type ArticleAttributes = { + id: string + originalHtml: string +} + +const query = gql` + query GetArticle( + $username: String! + $slug: String! + ) { + article(username: $username, slug: $slug) { + ... on ArticleSuccess { + article { + id + originalHtml + } + } + ... on ArticleError { + errorCodes + } + } + } +` + +export function useGetArticleOriginalHtmlQuery({ + username, + slug, +}: ArticleQueryInput): string | undefined { + const variables = { + username, + slug, + } + + const { data } = useSWRImmutable( + slug ? [query, username, slug] : null, + makeGqlFetcher(variables) + ) + + let resultData: ArticleData | undefined = data as ArticleData + console.log("RESULT", JSON.stringify(data)) + + return resultData?.article.article.originalHtml +} + +export async function originalHtmlQuery( + context: RequestContext, + input: ArticleQueryInput +): Promise { + const resultData = (await ssrFetcher(context, query, input, false)) as ArticleData + console.log(JSON.stringify(resultData)) + // if (resultData?.article.article.originalHtml) { + // return resultData?.article.article.originalHtml + // } + + return Promise.reject() +} diff --git a/packages/web/pages/[username]/[slug]/original.tsx b/packages/web/pages/[username]/[slug]/original.tsx new file mode 100644 index 000000000..82d1a412d --- /dev/null +++ b/packages/web/pages/[username]/[slug]/original.tsx @@ -0,0 +1,62 @@ +import { PrimaryLayout } from '../../../components/templates/PrimaryLayout' +import { LoadingView } from '../../../components/patterns/LoadingView' +import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery' +import { removeItemFromCache, useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery' +import { useRouter } from 'next/router' +import { Box, VStack } from './../../../components/elements/LayoutPrimitives' +import { ArticleContainer } from './../../../components/templates/article/ArticleContainer' +import { PdfArticleContainerProps } from './../../../components/templates/article/PdfArticleContainer' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts' +import { articleKeyboardCommands, navigationCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts' +import dynamic from 'next/dynamic' +import { webBaseURL } from '../../../lib/appConfig' +import { Toaster } from 'react-hot-toast' +import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' +import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' +import { mergeHighlightMutation } from '../../../lib/networking/mutations/mergeHighlightMutation' +import { articleReadingProgressMutation } from '../../../lib/networking/mutations/articleReadingProgressMutation' +import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation' +import { userPersonalizationMutation } from '../../../lib/networking/mutations/userPersonalizationMutation' +import Script from 'next/script' +import { theme } from '../../../components/tokens/stitches.config' +import { ArticleActionsMenu } from '../../../components/templates/article/ArticleActionsMenu' +import { setLinkArchivedMutation } from '../../../lib/networking/mutations/setLinkArchivedMutation' +import { Label } from '../../../lib/networking/fragments/labelFragment' +import { useSWRConfig } from 'swr' +import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' +import { SetLabelsModal } from '../../../components/templates/article/SetLabelsModal' +import { DisplaySettingsModal } from '../../../components/templates/article/DisplaySettingsModal' +import { useReaderSettings } from '../../../lib/hooks/useReaderSettings' +import { SkeletonArticleContainer } from '../../../components/templates/article/SkeletonArticleContainer' +import { useGetArticleOriginalHtmlQuery } from '../../../lib/networking/queries/useGetArticleOriginalHtmlQuery' + + +const PdfArticleContainerNoSSR = dynamic( + () => import('./../../../components/templates/article/PdfArticleContainer'), + { ssr: false } +) + +export default function Home(): JSX.Element { + const router = useRouter() + const originalHtml = useGetArticleOriginalHtmlQuery({ + username: router.query.username as string, + slug: router.query.slug as string, + includeFriendsHighlights: false, + }) + + if (!originalHtml) { + return
error
+ } + + return ( + + ) +} From 2858dd68d2e61ac50e71854c21d6aedf5751bfd4 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 9 Jul 2022 14:38:59 -0700 Subject: [PATCH 2/4] Display in a textarea --- .../web/pages/[username]/[slug]/original.tsx | 47 ++----------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/packages/web/pages/[username]/[slug]/original.tsx b/packages/web/pages/[username]/[slug]/original.tsx index 82d1a412d..507c493b3 100644 --- a/packages/web/pages/[username]/[slug]/original.tsx +++ b/packages/web/pages/[username]/[slug]/original.tsx @@ -1,42 +1,6 @@ -import { PrimaryLayout } from '../../../components/templates/PrimaryLayout' -import { LoadingView } from '../../../components/patterns/LoadingView' -import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery' -import { removeItemFromCache, useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery' import { useRouter } from 'next/router' -import { Box, VStack } from './../../../components/elements/LayoutPrimitives' -import { ArticleContainer } from './../../../components/templates/article/ArticleContainer' -import { PdfArticleContainerProps } from './../../../components/templates/article/PdfArticleContainer' -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts' -import { articleKeyboardCommands, navigationCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts' -import dynamic from 'next/dynamic' -import { webBaseURL } from '../../../lib/appConfig' -import { Toaster } from 'react-hot-toast' -import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' -import { mergeHighlightMutation } from '../../../lib/networking/mutations/mergeHighlightMutation' -import { articleReadingProgressMutation } from '../../../lib/networking/mutations/articleReadingProgressMutation' -import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation' -import { userPersonalizationMutation } from '../../../lib/networking/mutations/userPersonalizationMutation' -import Script from 'next/script' -import { theme } from '../../../components/tokens/stitches.config' -import { ArticleActionsMenu } from '../../../components/templates/article/ArticleActionsMenu' -import { setLinkArchivedMutation } from '../../../lib/networking/mutations/setLinkArchivedMutation' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { useSWRConfig } from 'swr' -import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' -import { SetLabelsModal } from '../../../components/templates/article/SetLabelsModal' -import { DisplaySettingsModal } from '../../../components/templates/article/DisplaySettingsModal' -import { useReaderSettings } from '../../../lib/hooks/useReaderSettings' -import { SkeletonArticleContainer } from '../../../components/templates/article/SkeletonArticleContainer' import { useGetArticleOriginalHtmlQuery } from '../../../lib/networking/queries/useGetArticleOriginalHtmlQuery' - -const PdfArticleContainerNoSSR = dynamic( - () => import('./../../../components/templates/article/PdfArticleContainer'), - { ssr: false } -) - export default function Home(): JSX.Element { const router = useRouter() const originalHtml = useGetArticleOriginalHtmlQuery({ @@ -50,13 +14,8 @@ export default function Home(): JSX.Element { } return ( - + ) } From 56f843142a78ec196107f6a4d99c22c9c5738608 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 9 Jul 2022 15:28:33 -0700 Subject: [PATCH 3/4] Linting --- .../lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx index 12bd0965e..bfb4c4e14 100644 --- a/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx +++ b/packages/web/lib/networking/queries/useGetArticleOriginalHtmlQuery.tsx @@ -57,7 +57,7 @@ export function useGetArticleOriginalHtmlQuery({ makeGqlFetcher(variables) ) - let resultData: ArticleData | undefined = data as ArticleData + const resultData: ArticleData | undefined = data as ArticleData console.log("RESULT", JSON.stringify(data)) return resultData?.article.article.originalHtml From e153966eeeae3eb30c90dc7d361a27ede6f9b16f Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 9 Jul 2022 15:38:09 -0700 Subject: [PATCH 4/4] Linting --- packages/api/src/resolvers/article/index.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index f514e86d8..679757f33 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -404,7 +404,7 @@ export const getArticleResolver: ResolverFn< return { errorCodes: [ArticleErrorCode.Unauthorized] } } - const includeOriginalHtml = !!(graphqlFields(info).article.originalHtml) + const includeOriginalHtml = !!graphqlFields(info).article.originalHtml analytics.track({ userId: claims?.uid, @@ -417,8 +417,14 @@ export const getArticleResolver: ResolverFn< // We allow the backend to use the ID instead of a slug to fetch the article const page = - (await getPageByParam({ userId: claims.uid, slug }, includeOriginalHtml)) || - (await getPageByParam({ userId: claims.uid, _id: slug }, includeOriginalHtml)) + (await getPageByParam( + { userId: claims.uid, slug }, + includeOriginalHtml + )) || + (await getPageByParam( + { userId: claims.uid, _id: slug }, + includeOriginalHtml + )) if (!page) { return { errorCodes: [ArticleErrorCode.NotFound] }