diff --git a/lang/default.json b/lang/default.json index 38bcd5729d..08791bfae7 100644 --- a/lang/default.json +++ b/lang/default.json @@ -468,6 +468,9 @@ "defaultMessage": "Followed", "description": "src/components/Buttons/FollowUser/Unfollow.tsx" }, + "99OtWT": { + "defaultMessage": "Pending..." + }, "9Fpc9S": { "defaultMessage": "Bug Report" }, diff --git a/lang/en.json b/lang/en.json index 128b4f33da..b4139fd5ab 100644 --- a/lang/en.json +++ b/lang/en.json @@ -468,6 +468,9 @@ "defaultMessage": "Followed", "description": "src/components/Buttons/FollowUser/Unfollow.tsx" }, + "99OtWT": { + "defaultMessage": "Pending..." + }, "9Fpc9S": { "defaultMessage": "Bug Report" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 08a8f3d7f9..c384a584a6 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -468,6 +468,9 @@ "defaultMessage": "已追踪", "description": "src/components/Buttons/FollowUser/Unfollow.tsx" }, + "99OtWT": { + "defaultMessage": "写入中…" + }, "9Fpc9S": { "defaultMessage": "漏洞报告" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index a16729fbe3..90f92d482e 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -468,6 +468,9 @@ "defaultMessage": "已追蹤", "description": "src/components/Buttons/FollowUser/Unfollow.tsx" }, + "99OtWT": { + "defaultMessage": "寫入中…" + }, "9Fpc9S": { "defaultMessage": "漏洞提報" }, diff --git a/src/common/utils/route.ts b/src/common/utils/route.ts index dfaa36c694..fe4c9da09c 100644 --- a/src/common/utils/route.ts +++ b/src/common/utils/route.ts @@ -45,6 +45,7 @@ type ToPathArgs = page: 'articleDetail' article: ArticleArgs collectionId?: string + versionId?: string } | { page: @@ -116,7 +117,9 @@ export const toPath = ( mediaHash ? '-' + mediaHash : '' }` } - if (!!args.collectionId) { + if (!!args.versionId) { + href = `${href}/revision?version=${args.versionId}` + } else if (!!args.collectionId) { href = `${href}?collection=${args.collectionId}` } } catch (err) { diff --git a/src/views/ArticleDetail/Content/index.tsx b/src/views/ArticleDetail/Content/index.tsx index 265eaad54f..ee7894cf71 100644 --- a/src/views/ArticleDetail/Content/index.tsx +++ b/src/views/ArticleDetail/Content/index.tsx @@ -6,7 +6,7 @@ import { useContext, useEffect, useRef, useState } from 'react' import { TEST_ID } from '~/common/enums' import { captureClicks, initAudioPlayers, optimizeEmbed } from '~/common/utils' import { useMutation, ViewerContext } from '~/components' -import { ContentArticleFragment, ReadArticleMutation } from '~/gql/graphql' +import { ReadArticleMutation } from '~/gql/graphql' import styles from './styles.module.css' @@ -19,11 +19,11 @@ const READ_ARTICLE = gql` ` const Content = ({ - article, + articleId, content, translating, }: { - article: ContentArticleFragment + articleId: string content: string translating?: boolean }) => { @@ -88,12 +88,12 @@ const Content = ({ // if user is logged in, ReadArticle mutation will be invoked multiple times if (viewer.isAuthed && isReading()) { - read({ variables: { id: article.id } }) + read({ variables: { id: articleId } }) } // if visitor, invoke ReadArticle mutation only once if (!viewer.isAuthed && !visitorReadRef.current) { - read({ variables: { id: article.id } }) + read({ variables: { id: articleId } }) visitorReadRef.current = true } return heartbeat @@ -125,15 +125,4 @@ const Content = ({ ) } -Content.fragments = { - article: gql` - fragment ContentArticle on Article { - id - contents { - html - } - } - `, -} - export default Content diff --git a/src/views/ArticleDetail/MetaInfo/gql.ts b/src/views/ArticleDetail/MetaInfo/gql.ts index 9f8511a528..c53f83ec61 100644 --- a/src/views/ArticleDetail/MetaInfo/gql.ts +++ b/src/views/ArticleDetail/MetaInfo/gql.ts @@ -9,6 +9,13 @@ export const fragments = { access { type } + language + slug + mediaHash + author { + id + userName + } ...FingerprintArticle } ${FingerprintButton.fragments.article} diff --git a/src/views/ArticleDetail/MetaInfo/index.tsx b/src/views/ArticleDetail/MetaInfo/index.tsx index 3b8fd67883..ddf986baae 100644 --- a/src/views/ArticleDetail/MetaInfo/index.tsx +++ b/src/views/ArticleDetail/MetaInfo/index.tsx @@ -14,7 +14,7 @@ import { UserDigest, ViewerContext, } from '~/components' -import { ArticleDetailPublicQuery } from '~/gql/graphql' +import { MetaInfoArticleFragment } from '~/gql/graphql' import FingerprintButton from './FingerprintButton' import { fragments } from './gql' @@ -22,7 +22,7 @@ import styles from './styles.module.css' import TranslationButton from './TranslationButton' type MetaInfoProps = { - article: NonNullable + article: MetaInfoArticleFragment translated: boolean canTranslate: boolean toggleTranslate: () => any diff --git a/src/views/ArticleDetail/Revision/InfoHeader/gql.ts b/src/views/ArticleDetail/Revision/InfoHeader/gql.ts index e9701acdc8..72f1fd0706 100644 --- a/src/views/ArticleDetail/Revision/InfoHeader/gql.ts +++ b/src/views/ArticleDetail/Revision/InfoHeader/gql.ts @@ -4,20 +4,28 @@ import { UserDigest } from '~/components' export const fragments = { article: gql` - fragment InfoHeader on Article { + fragment InfoHeaderArticle on Article { id author { id ...UserDigestMiniUser } - mediaHash - dataHash iscnId - createdAt access { type + secret } } ${UserDigest.Mini.fragments.user} `, + articleVersion: gql` + fragment InfoHeaderArticleVersion on ArticleVersion { + id + dataHash + mediaHash + summary + createdAt + description + } + `, } diff --git a/src/views/ArticleDetail/Revision/InfoHeader/index.tsx b/src/views/ArticleDetail/Revision/InfoHeader/index.tsx index f425237fd5..836ff5ece0 100644 --- a/src/views/ArticleDetail/Revision/InfoHeader/index.tsx +++ b/src/views/ArticleDetail/Revision/InfoHeader/index.tsx @@ -13,9 +13,13 @@ import { Tooltip, UserDigest, } from '~/components' -import { GatewaysQuery } from '~/gql/graphql' -import { MOCK_ARTILCE, MOCK_USER } from '~/stories/mocks' +import { + GatewaysQuery, + InfoHeaderArticleFragment, + InfoHeaderArticleVersionFragment, +} from '~/gql/graphql' +import { fragments } from './gql' import styles from './styles.module.css' const GATEWAYS = gql` @@ -36,7 +40,13 @@ function iscnLinkUrl(iscnId: string) { return `${iscnLinkPrefix}/${encodeURIComponent(iscnId)}` } -export const InfoHeader = () => { +const InfoHeader = ({ + article, + version, +}: { + article: InfoHeaderArticleFragment + version: InfoHeaderArticleVersionFragment +}) => { const intl = useIntl() const { data } = useQuery(GATEWAYS) @@ -47,7 +57,7 @@ export const InfoHeader = () => {
{
-

- 這個版本調整了引用文字、出處,以及部分連結資料也一併更新了 -

+ {version.description && ( +

{version.description}

+ )}

@@ -95,82 +105,8 @@ export const InfoHeader = () => {
- - - - - - {/* gateways */} -
-
- -
-
- {gateways.slice(0, 3).map((url) => { - const gatewayUrl = url.replace(':hash', MOCK_ARTILCE.dataHash) - const hostname = url.replace(/(https:\/\/|\/ipfs\/|:hash.?)/g, '') - - return ( - - {hostname} - - ) - })} -
-
- - {/* ISCN */} -
-
ISCN
- -
- - } - color="greyDarker" - size="xs" - spacing="xxtight" - textPlacement="left" - > - {truncate(MOCK_ARTILCE.iscnId, 4, 4)} - - -
-
- - {/* Secret */} -
-
- -
- -
- + {version.dataHash && ( + -
+ )} + {!version.dataHash && ( + + + + )}
+ + {/* gateways */} + {version.dataHash && ( +
+
+ +
+
+ {gateways.slice(0, 3).map((url) => { + const gatewayUrl = url.replace(':hash', version.dataHash!) + const hostname = url.replace( + /(https:\/\/|\/ipfs\/|:hash.?)/g, + '' + ) + + return ( + + {hostname} + + ) + })} +
+
+ )} + + {/* ISCN */} + {article.iscnId && ( +
+
ISCN
+ +
+ + } + color="greyDarker" + size="xs" + spacing="xxtight" + textPlacement="left" + > + {truncate(article.iscnId, 4, 4)} + + +
+
+ )} + + {/* Secret */} + {article.access.secret && ( +
+
+ +
+ +
+ + + +
+
+ )} ) } + +InfoHeader.fragments = fragments + +export default InfoHeader diff --git a/src/views/ArticleDetail/Revision/VersionsDropdown/index.tsx b/src/views/ArticleDetail/Revision/Versions/VersionsDropdown/index.tsx similarity index 82% rename from src/views/ArticleDetail/Revision/VersionsDropdown/index.tsx rename to src/views/ArticleDetail/Revision/Versions/VersionsDropdown/index.tsx index d35555ed1e..f362d71cf7 100644 --- a/src/views/ArticleDetail/Revision/VersionsDropdown/index.tsx +++ b/src/views/ArticleDetail/Revision/Versions/VersionsDropdown/index.tsx @@ -4,16 +4,11 @@ import { FormattedMessage } from 'react-intl' import { Z_INDEX } from '~/common/enums' import { Dropdown, IconDown20, Label, Menu } from '~/components' +import { VersionsArticleFragment } from '~/gql/graphql' import versionStyles from '../VersionsSidebar/styles.module.css' import styles from './styles.module.css' -const versions = [ - { id: 'UmV2aXNvbjox', createdAt: '2021-01-03T00:00:00Z' }, - { id: 'UmV2aXNvbjoy', createdAt: '2021-01-02T00:00:00Z' }, - { id: 'UmV2aXNvbjoz', createdAt: '2021-01-01T00:00:00Z' }, -] - const Version = ({ version, active, @@ -49,13 +44,18 @@ const Version = ({ ) } -export const VersionsDropdown = () => { - // TODO - if (versions.length === 1) { +const VersionsDropdown = ({ + article, +}: { + article: VersionsArticleFragment +}) => { + const versions = article.versions.edges.map((edge) => edge?.node!) + + if (versions.length < 1) { return null } - const SelectContent = ({ dropdown }: { dropdown?: boolean }) => { + const SelectContent = () => { return ( {versions.map((version, index) => ( @@ -72,7 +72,7 @@ export const VersionsDropdown = () => {
} + content={} zIndex={Z_INDEX.OVER_DIALOG} > {({ openDropdown, ref }) => ( @@ -91,3 +91,5 @@ export const VersionsDropdown = () => {
) } + +export default VersionsDropdown diff --git a/src/views/ArticleDetail/Revision/VersionsDropdown/styles.module.css b/src/views/ArticleDetail/Revision/Versions/VersionsDropdown/styles.module.css similarity index 100% rename from src/views/ArticleDetail/Revision/VersionsDropdown/styles.module.css rename to src/views/ArticleDetail/Revision/Versions/VersionsDropdown/styles.module.css diff --git a/src/views/ArticleDetail/Revision/VersionsSidebar/index.tsx b/src/views/ArticleDetail/Revision/Versions/VersionsSidebar/index.tsx similarity index 83% rename from src/views/ArticleDetail/Revision/VersionsSidebar/index.tsx rename to src/views/ArticleDetail/Revision/Versions/VersionsSidebar/index.tsx index 419a4292c7..dbf391dc91 100644 --- a/src/views/ArticleDetail/Revision/VersionsSidebar/index.tsx +++ b/src/views/ArticleDetail/Revision/Versions/VersionsSidebar/index.tsx @@ -3,18 +3,14 @@ import format from 'date-fns/format' import { FormattedMessage } from 'react-intl' import { Label } from '~/components' +import { VersionsArticleFragment } from '~/gql/graphql' import styles from './styles.module.css' -const versions = [ - { id: 'UmV2aXNvbjox', createdAt: '2021-01-03T00:00:00Z' }, - { id: 'UmV2aXNvbjoy', createdAt: '2021-01-02T00:00:00Z' }, - { id: 'UmV2aXNvbjoz', createdAt: '2021-01-01T00:00:00Z' }, -] +const VersionsSidebar = ({ article }: { article: VersionsArticleFragment }) => { + const versions = article.versions.edges.map((edge) => edge?.node!) -export const VersionsSidebar = () => { - // TODO - if (versions.length === 1) { + if (versions.length < 1) { return null } @@ -59,3 +55,5 @@ export const VersionsSidebar = () => { ) } + +export default VersionsSidebar diff --git a/src/views/ArticleDetail/Revision/VersionsSidebar/styles.module.css b/src/views/ArticleDetail/Revision/Versions/VersionsSidebar/styles.module.css similarity index 100% rename from src/views/ArticleDetail/Revision/VersionsSidebar/styles.module.css rename to src/views/ArticleDetail/Revision/Versions/VersionsSidebar/styles.module.css diff --git a/src/views/ArticleDetail/Revision/Versions/gql.ts b/src/views/ArticleDetail/Revision/Versions/gql.ts new file mode 100644 index 0000000000..37537e41cd --- /dev/null +++ b/src/views/ArticleDetail/Revision/Versions/gql.ts @@ -0,0 +1,19 @@ +import gql from 'graphql-tag' + +// import { MAX_ARTICLE_REVISION_COUNT } from '~/common/enums' + +export const fragments = { + article: gql` + fragment VersionsArticle on Article { + id + versions(input: { first: 5 }) { + edges { + node { + id + createdAt + } + } + } + } + `, +} diff --git a/src/views/ArticleDetail/Revision/Versions/index.tsx b/src/views/ArticleDetail/Revision/Versions/index.tsx new file mode 100644 index 0000000000..579aa4aabb --- /dev/null +++ b/src/views/ArticleDetail/Revision/Versions/index.tsx @@ -0,0 +1,11 @@ +import { fragments } from './gql' +import VersionsDropdown from './VersionsDropdown' +import VersionsSidebar from './VersionsSidebar' + +const Versions = { + fragments, + Dropdown: VersionsDropdown, + Sidebar: VersionsSidebar, +} + +export default Versions diff --git a/src/views/ArticleDetail/Revision/gql.ts b/src/views/ArticleDetail/Revision/gql.ts new file mode 100644 index 0000000000..76ce06bbc5 --- /dev/null +++ b/src/views/ArticleDetail/Revision/gql.ts @@ -0,0 +1,153 @@ +import gql from 'graphql-tag' + +import { UserDigest } from '~/components/UserDigest' + +import { fragments as circleWallFragments } from '../Wall/Circle/gql' +import InfoHeader from './InfoHeader' +import Versions from './Versions' + +const articleRevisionPublicFragment = gql` + fragment ArticleRevisionPublicArticle on Article { + id + title + slug + mediaHash + state + cover + summaryCustomized + language + author { + id + ...UserDigestRichUserPublic + ...UserDigestRichUserPrivate + } + access { + type + circle { + id + ...CircleWallCirclePublic + ...CircleWallCirclePrivate + } + } + license + sensitiveByAuthor + sensitiveByAdmin + requestForDonation + replyToDonator + availableTranslations + ...InfoHeaderArticle + ...VersionsArticle + } + ${UserDigest.Rich.fragments.user.public} + ${UserDigest.Rich.fragments.user.private} + ${circleWallFragments.circle.public} + ${circleWallFragments.circle.private} + ${InfoHeader.fragments.article} + ${Versions.fragments.article} +` + +const articleVersionFragment = gql` + fragment ArticleVersion on ArticleVersion { + id + mediaHash + summary + # translation(input: TranslationArgs): ArticleTranslation + createdAt + description + contents { + html + } + ...InfoHeaderArticleVersion + } + ${InfoHeader.fragments.articleVersion} +` + +export const ARTICLE_REVISION_DETAIL_PUBLIC = gql` + query ArticleRevisionDetailPublic($mediaHash: String!, $version: ID!) { + article(input: { mediaHash: $mediaHash }) { + ...ArticleRevisionPublicArticle + } + version: node(input: { id: $version }) { + ... on ArticleVersion { + ...ArticleVersion + } + } + } + ${articleRevisionPublicFragment} + ${articleVersionFragment} +` + +export const ARTICLE_REVISION_DETAIL_PUBLIC_BY_NODE_ID = gql` + query ArticleRevisionDetailPublicByNodeId($id: ID!, $version: ID!) { + article: node(input: { id: $id }) { + ... on Article { + ...ArticleRevisionPublicArticle + } + } + version: node(input: { id: $version }) { + ... on ArticleVersion { + ...ArticleVersion + } + } + } + ${articleRevisionPublicFragment} + ${articleVersionFragment} +` + +export const ARTICLE_REVISION_DETAIL_PRIVATE = gql` + query ArticleRevisionDetailPrivate($id: ID!, $version: ID!) { + article: node(input: { id: $id }) { + ... on Article { + id + access { + circle { + id + ...CircleWallCirclePrivate + } + } + } + } + version: node(input: { id: $version }) { + id + ... on ArticleVersion { + contents { + html + } + } + } + } + ${UserDigest.Rich.fragments.user.private} + ${circleWallFragments.circle.private} +` + +export const ARTICLE_LATEST_VERSION = gql` + query ArticleLatestVersion($mediaHash: String!) { + article(input: { mediaHash: $mediaHash }) { + id + versions(input: { first: 1 }) { + edges { + node { + id + } + } + } + } + } +` + +export const ARTICLE_LATEST_VERSION_BY_NODE_ID = gql` + query ArticleLatestVersionByNodeId($id: ID!) { + article: node(input: { id: $id }) { + ... on Article { + id + versions(input: { first: 1 }) { + edges { + node { + id + } + } + } + } + } + } +` diff --git a/src/views/ArticleDetail/Revision/index.tsx b/src/views/ArticleDetail/Revision/index.tsx index eac0c0d062..8318d1f3ec 100644 --- a/src/views/ArticleDetail/Revision/index.tsx +++ b/src/views/ArticleDetail/Revision/index.tsx @@ -1,8 +1,7 @@ -import formatISO from 'date-fns/formatISO' import dynamic from 'next/dynamic' import { useContext, useEffect, useState } from 'react' -import { normalizeTag, toGlobalId, toPath } from '~/common/utils' +import { toGlobalId, toPath } from '~/common/utils' import { BackToHomeButton, EmptyLayout, @@ -21,29 +20,27 @@ import { } from '~/components' import { ArticleAccessType, - ArticleAvailableTranslationsQuery, - ArticleDetailPublicQuery, - UserLanguage, + ArticleLatestVersionByNodeIdQuery, + ArticleLatestVersionQuery, + ArticleRevisionDetailPublicQuery, } from '~/gql/graphql' import Content from '../Content' import CustomizedSummary from '../CustomizedSummary' -import { - ARTICLE_AVAILABLE_TRANSLATIONS, - ARTICLE_AVAILABLE_TRANSLATIONS_BY_NODE_ID, - ARTICLE_DETAIL_PRIVATE, - ARTICLE_DETAIL_PUBLIC, - ARTICLE_DETAIL_PUBLIC_BY_NODE_ID, -} from '../gql' import License from '../License' -import MetaInfo from '../MetaInfo' +// import MetaInfo from '../MetaInfo' import Placeholder from '../Placeholder' import StickyTopBanner from '../StickyTopBanner' import styles from '../styles.module.css' -import TagList from '../TagList' -import { InfoHeader } from './InfoHeader' -import { VersionsDropdown } from './VersionsDropdown' -import { VersionsSidebar } from './VersionsSidebar' +import { + ARTICLE_LATEST_VERSION, + ARTICLE_LATEST_VERSION_BY_NODE_ID, + ARTICLE_REVISION_DETAIL_PRIVATE, + ARTICLE_REVISION_DETAIL_PUBLIC, + ARTICLE_REVISION_DETAIL_PUBLIC_BY_NODE_ID, +} from './gql' +import InfoHeader from './InfoHeader' +import Versions from './Versions' const DynamicCircleWall = dynamic(() => import('../Wall/Circle'), { ssr: true, // enable for first screen @@ -70,8 +67,10 @@ const isMediaHashPossiblyValid = (mediaHash?: string | null) => { const BaseArticleDetailRevision = ({ article, + version, }: { - article: NonNullable + article: NonNullable + version: NonNullable }) => { const viewer = useContext(ViewerContext) @@ -80,7 +79,6 @@ const BaseArticleDetailRevision = ({ ) const authorId = article.author?.id - const paymentPointer = article.author?.paymentPointer const isAuthor = viewer.id === authorId const circle = article.access.circle const canReadFullContent = !!( @@ -90,41 +88,25 @@ const BaseArticleDetailRevision = ({ article.access.type === ArticleAccessType.Public ) + version = (version.__typename === 'ArticleVersion' ? version : undefined)! const title = article.title - const summary = article.summary - const content = article.contents.html - const keywords = (article.tags || []).map(({ content: c }) => normalizeTag(c)) - const lock = article.state !== 'active' + const summary = version.summary + const content = version.contents.html return ( - }> + }> @@ -132,22 +114,22 @@ const BaseArticleDetailRevision = ({
- + - +
{title} - {}} + toggleTranslate={() => {}} // TODO canReadFullContent={canReadFullContent} - disabled={lock} - /> + disabled + /> */}
{article?.summaryCustomized && } @@ -162,7 +144,7 @@ const BaseArticleDetailRevision = ({ {!isSensitive && ( <> - + {circle && !canReadFullContent && ( @@ -170,8 +152,6 @@ const BaseArticleDetailRevision = ({ )} - -
@@ -179,11 +159,11 @@ const BaseArticleDetailRevision = ({ } const ArticleDetailRevision = ({ - includeTranslation, + latestVersion, }: { - includeTranslation: boolean + latestVersion: string }) => { - const { getQuery, router, routerLang } = useRoute() + const { getQuery, router } = useRoute() const [needRefetchData, setNeedRefetchData] = useState(false) const mediaHash = getQuery('mediaHash') const articleId = @@ -203,24 +183,22 @@ const ArticleDetailRevision = ({ // - `/:username:/:articleId:-:slug:-:mediaHash` // - `/:username:/:articleId:` // - `/:username:/:slug:-:mediaHash:` - const resultByHash = usePublicQuery( - ARTICLE_DETAIL_PUBLIC, + const resultByHash = usePublicQuery( + ARTICLE_REVISION_DETAIL_PUBLIC, { variables: { mediaHash, - language: routerLang || UserLanguage.ZhHant, - includeTranslation, + version: latestVersion, }, skip: !isQueryByHash, } ) - const resultByNodeId = usePublicQuery( - ARTICLE_DETAIL_PUBLIC_BY_NODE_ID, + const resultByNodeId = usePublicQuery( + ARTICLE_REVISION_DETAIL_PUBLIC_BY_NODE_ID, { variables: { id: toGlobalId({ type: 'Article', id: articleId }), - language: routerLang || UserLanguage.ZhHant, - includeTranslation, + version: latestVersion, }, skip: isQueryByHash, } @@ -234,7 +212,7 @@ const ArticleDetailRevision = ({ const loading = resultByHash.loading || resultByNodeId.loading const error = resultByHash.error || resultByNodeId.error - const article = data?.article + const { article, version } = data || {} const authorId = article?.author?.id const isAuthor = viewer.id === authorId @@ -247,11 +225,10 @@ const ArticleDetailRevision = ({ } await client.query({ - query: ARTICLE_DETAIL_PRIVATE, + query: ARTICLE_REVISION_DETAIL_PRIVATE, fetchPolicy: 'network-only', variables: { id: article?.id, - includeCanSuperLike: viewer.isCivicLiker, }, }) } @@ -268,47 +245,6 @@ const ArticleDetailRevision = ({ })() }, [mediaHash]) - // fetch private data when mediaHash of public data is changed - useEffect(() => { - loadPrivate() - }, [article?.mediaHash, viewer.id]) - - // shadow replace URL - // const latestHash = article?.drafts?.filter( - // (d) => d.publishState === 'published' - // )[0]?.mediaHash - // useEffect(() => { - // if (!article || !latestHash) { - // return - // } - - // const newPath = toPath({ - // page: 'articleDetail', - // article: { ...article, mediaHash: latestHash }, - // }) - - // // parse current URL: router.asPath - // const u = new URL( - // `https://${process.env.NEXT_PUBLIC_SITE_DOMAIN}${router.asPath}` - // ) - // const n = new URL( - // `https://${process.env.NEXT_PUBLIC_SITE_DOMAIN}${newPath.href}` - // ) - - // // hide all utm_ tracking code parameters - // // copy all others - // const rems = [ - // ...u.searchParams, // uses .entries() - // ...n.searchParams, - // ].filter(([k, v]) => !k?.startsWith('utm_')) - // const nsearch = rems.length > 0 ? `?${new URLSearchParams(rems)}` : '' - // const nhref = `${n.pathname}${nsearch}${n.hash || u.hash}` - - // if (nhref !== router.asPath || routerLang) { - // router.replace(nhref, undefined, { shallow: true, locale: false }) - // } - // }, [latestHash]) - /** * Render:Loading */ @@ -334,7 +270,7 @@ const ArticleDetailRevision = ({ /** * Render:404 */ - if (!article) { + if (!article || !version || version.__typename !== 'ArticleVersion') { return ( @@ -374,11 +310,11 @@ const ArticleDetailRevision = ({ /** * Render:Article */ - return + return } const ArticleDetailRevisionOuter = () => { - const { getQuery, router, routerLang } = useRoute() + const { getQuery, router } = useRoute() const mediaHash = getQuery('mediaHash') const articleId = (router.query.mediaHash as string)?.match(/^(\d+)/)?.[1] || '' @@ -389,12 +325,12 @@ const ArticleDetailRevisionOuter = () => { !articleId ) - const resultByHash = usePublicQuery( - ARTICLE_AVAILABLE_TRANSLATIONS, + const resultByHash = usePublicQuery( + ARTICLE_LATEST_VERSION, { variables: { mediaHash }, skip: !isQueryByHash } ) - const resultByNodeId = usePublicQuery( - ARTICLE_AVAILABLE_TRANSLATIONS_BY_NODE_ID, + const resultByNodeId = usePublicQuery( + ARTICLE_LATEST_VERSION_BY_NODE_ID, { variables: { id: toGlobalId({ type: 'Article', id: articleId }) }, skip: isQueryByHash, @@ -402,9 +338,9 @@ const ArticleDetailRevisionOuter = () => { ) const { data } = resultByHash.data ? resultByHash : resultByNodeId const loading = resultByHash.loading || resultByNodeId.loading - const includeTranslation = - !!routerLang && - (data?.article?.availableTranslations || []).includes(routerLang) + const latestVersion = + data?.article?.__typename === 'Article' && + data.article.versions.edges[0]?.node.id /** * Rendering @@ -417,7 +353,15 @@ const ArticleDetailRevisionOuter = () => { ) } - return + if (!latestVersion) { + return ( + + + + ) + } + + return } export default ArticleDetailRevisionOuter diff --git a/src/views/ArticleDetail/gql.ts b/src/views/ArticleDetail/gql.ts index 92c8e5cfa0..7b81f402d7 100644 --- a/src/views/ArticleDetail/gql.ts +++ b/src/views/ArticleDetail/gql.ts @@ -5,7 +5,6 @@ import { UserDigest } from '~/components/UserDigest' import { AuthorSidebar } from './AuthorSidebar' import { FromAuthor } from './AuthorSidebar/FromAuthor' import { RelatedArticles } from './AuthorSidebar/RelatedArticles' -import Content from './Content' import MetaInfo from './MetaInfo' import StickyTopBanner from './StickyTopBanner' import { fragments as supportWidgetFragments } from './SupportWidget/gql' @@ -64,9 +63,11 @@ const articlePublicFragment = gql` language } availableTranslations + contents { + html + } ...AuthorSidebarArticle ...MetaInfoArticle - ...ContentArticle ...TagListArticle ...AuthorSidebarRelatedArticles ...AuthorSidebarFromAuthor @@ -78,7 +79,6 @@ const articlePublicFragment = gql` } ${AuthorSidebar.fragments.article} ${MetaInfo.fragments.article} - ${Content.fragments.article} ${TagList.fragments.article} ${RelatedArticles.fragments.article} ${FromAuthor.fragments.article} @@ -158,13 +158,14 @@ export const ARTICLE_DETAIL_PRIVATE = gql` ...CircleWallCirclePrivate } } - ...ContentArticle + contents { + html + } ...ToolbarArticlePrivate ...SupportWidgetArticlePrivate } } } - ${Content.fragments.article} ${UserDigest.Rich.fragments.user.private} ${Toolbar.fragments.article.private} ${supportWidgetFragments.article.private} diff --git a/src/views/ArticleDetail/index.tsx b/src/views/ArticleDetail/index.tsx index b4418f9d8b..5e7a67f027 100644 --- a/src/views/ArticleDetail/index.tsx +++ b/src/views/ArticleDetail/index.tsx @@ -361,7 +361,7 @@ const BaseArticleDetail = ({ {!isSensitive && ( <> @@ -396,6 +396,7 @@ const BaseArticleDetail = ({ translatedLanguage={translatedLanguage} privateFetched={privateFetched} hasFingerprint={canReadFullContent} + // hasReport // TODO: lock={lock} toggleDrawer={toggleDrawer} />