From 343b71defd02bbe999cb0847779d93e1ef3d5711 Mon Sep 17 00:00:00 2001 From: dufok Date: Tue, 24 Sep 2024 00:40:57 -0300 Subject: [PATCH 01/15] feat: renamed ArticalPage to component, added useParam for slug and reactivity --- src/routes/[slug]/[...tab].tsx | 177 ++++++++++++++++++++------------- 1 file changed, 108 insertions(+), 69 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index ef9fc842..a0d63feb 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,32 @@ -import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' +/** + * [slug].tsx + * + * # Dynamic Slug Route Handler + * + * ## Overview + * + * This file handles dynamic routing based on the `slug` parameter in the URL. Depending on the prefix of the slug, it renders different pages: + * + * - **Author Page**: If the `slug` starts with `@`, it renders the `AuthorPage` component for the specified author. + * - **Topic Page**: If the `slug` starts with `!`, it renders the `TopicPage` component for the specified topic. + * - **Article Page**: For all other slugs, it renders the `ArticlePageComponent`, displaying the full article details. + * + * ## Components + * + * - **SlugPage**: The main component that determines which page to render based on the `slug`. + * - **ArticlePageComponent**: Fetches and displays the detailed view of an article. + * - **AuthorPage**: Displays author-specific information (imported from `../author/[slug]/[...tab]`). + * - **TopicPage**: Displays topic-specific information (imported from `../topic/[slug]/[...tab]`). + * + * ## Data Fetching + * + * - **fetchShout**: Asynchronously fetches article data based on the `slug` using the `getShout` GraphQL query. + * - **createResource**: Utilized in `ArticlePageComponent` to fetch and manage article data reactively.**/ + + +import { RouteDefinition, RouteSectionProps, useLocation, useParams } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, onMount, createResource } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -16,7 +42,7 @@ import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]' import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]' const fetchShout = async (slug: string): Promise => { - if (slug.startsWith('@')) return + if (slug.startsWith('@') || slug.startsWith('!')) return const shoutLoader = getShout({ slug }) const result = await shoutLoader() return result @@ -43,90 +69,103 @@ export type SlugPageProps = { topics: Topic[] } -export default function ArticlePage(props: RouteSectionProps) { - if (props.params.slug.startsWith('@')) { +export default function SlugPage(props: RouteSectionProps) { + const { t } = useLocalize() + const loc = useLocation() + + const params = useParams() + const slug = createMemo(() => params.slug) + + if (slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { ...props, params: { ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) + slug: slug.slice(1) } } as RouteSectionProps return } - if (props.params.slug.startsWith('!')) { + if (slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') const patchedProps = { ...props, params: { ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) + slug: slug.slice(1) } } as RouteSectionProps return } - function ArticlePage(props: RouteSectionProps) { - const loc = useLocation() - const { t } = useLocalize() - const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) - - onMount(async () => { - if (gaIdentity && data()?.id) { - try { - await loadGAScript(gaIdentity) - initGA(gaIdentity) - } catch (error) { - console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) - } - } - }) - - createEffect( - on( - data, - (a?: Shout) => { - if (!a?.id) return - window?.gtag?.('event', 'page_view', { - page_title: a.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }) - }, - { defer: true } - ) - ) - - return ( - }> - }> - - - - - } - > - - - - - - - - - ) - } - return + // Pass slug as a prop to ArticlePageComponent + return +} + +function ArticlePageComponent(props: RouteSectionProps & { slug: string }) { + const loc = useLocation() + const { t } = useLocalize() + const { slug } = props + + // Define the fetcher function + const fetchArticle = async (slug: string): Promise => { + return await fetchShout(slug) + } + + // Create a resource that fetches the article based on slug + const [article, { refetch, mutate }] = createResource(slug, fetchArticle) + + // Handle Google Analytics + createEffect(() => { + const currentArticle = article() + if (gaIdentity && currentArticle?.id) { + loadGAScript(gaIdentity) + .then(() => initGA(gaIdentity)) + .catch((error) => { + console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) + }) + } + }) + + createEffect(() => { + const currentArticle = article() + if (currentArticle?.id) { + window?.gtag?.('event', 'page_view', { + page_title: currentArticle.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + } + }) + + return ( + }> + }> + + + + + } + > + + + + + + + + + ) } From ef7ceb5d33b08c99b9ee627fc463489fcfd7d82a Mon Sep 17 00:00:00 2001 From: dufok Date: Tue, 24 Sep 2024 20:51:32 -0300 Subject: [PATCH 02/15] debug: backed slug to dev code just rename ArticlePage inner function --- src/routes/[slug]/[...tab].tsx | 105 ++++++++++++++------------------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index a0d63feb..88cde259 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -14,19 +14,14 @@ * ## Components * * - **SlugPage**: The main component that determines which page to render based on the `slug`. - * - **ArticlePageComponent**: Fetches and displays the detailed view of an article. + * - **InnerArticlePage**: Fetches and displays the detailed view of an article. * - **AuthorPage**: Displays author-specific information (imported from `../author/[slug]/[...tab]`). * - **TopicPage**: Displays topic-specific information (imported from `../topic/[slug]/[...tab]`). - * - * ## Data Fetching - * - * - **fetchShout**: Asynchronously fetches article data based on the `slug` using the `getShout` GraphQL query. - * - **createResource**: Utilized in `ArticlePageComponent` to fetch and manage article data reactively.**/ + **/ - -import { RouteDefinition, RouteSectionProps, useLocation, useParams } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount, createResource } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -42,7 +37,7 @@ import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]' import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]' const fetchShout = async (slug: string): Promise => { - if (slug.startsWith('@') || slug.startsWith('!')) return + if (slug.startsWith('@')) return const shoutLoader = getShout({ slug }) const result = await shoutLoader() return result @@ -69,82 +64,70 @@ export type SlugPageProps = { topics: Topic[] } -export default function SlugPage(props: RouteSectionProps) { - const { t } = useLocalize() - const loc = useLocation() - - const params = useParams() - const slug = createMemo(() => params.slug) - - if (slug.startsWith('@')) { +export default function ArticlePage(props: RouteSectionProps) { + if (props.params.slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { ...props, params: { ...props.params, - slug: slug.slice(1) + slug: props.params.slug.slice(1, props.params.slug.length) } } as RouteSectionProps return } - if (slug.startsWith('!')) { + if (props.params.slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') const patchedProps = { ...props, params: { ...props.params, - slug: slug.slice(1) + slug: props.params.slug.slice(1, props.params.slug.length) } } as RouteSectionProps return } - // Pass slug as a prop to ArticlePageComponent - return + return } -function ArticlePageComponent(props: RouteSectionProps & { slug: string }) { +function InnerArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() - const { slug } = props + const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) - // Define the fetcher function - const fetchArticle = async (slug: string): Promise => { - return await fetchShout(slug) - } + onMount(async () => { + if (gaIdentity && data()?.id) { + try { + await loadGAScript(gaIdentity) + initGA(gaIdentity) + } catch (error) { + console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) + } + } + }) - // Create a resource that fetches the article based on slug - const [article, { refetch, mutate }] = createResource(slug, fetchArticle) - - // Handle Google Analytics - createEffect(() => { - const currentArticle = article() - if (gaIdentity && currentArticle?.id) { - loadGAScript(gaIdentity) - .then(() => initGA(gaIdentity)) - .catch((error) => { - console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) + createEffect( + on( + data, + (a?: Shout) => { + if (!a?.id) return + window?.gtag?.('event', 'page_view', { + page_title: a.title, + page_location: window?.location.href || '', + page_path: loc.pathname }) - } - }) - - createEffect(() => { - const currentArticle = article() - if (currentArticle?.id) { - window?.gtag?.('event', 'page_view', { - page_title: currentArticle.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }) - } - }) + }, + { defer: true } + ) + ) return ( }> }> @@ -153,15 +136,15 @@ function ArticlePageComponent(props: RouteSectionProps & { slug: } > - + From c26f960d9bf46de4102943d2f008e4472017f982 Mon Sep 17 00:00:00 2001 From: dufok Date: Tue, 24 Sep 2024 21:47:19 -0300 Subject: [PATCH 03/15] debug: slug with logging to async and useParam for fetching data and slugs --- src/routes/[slug]/[...tab].tsx | 45 ++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 88cde259..15385a9b 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -19,7 +19,7 @@ * - **TopicPage**: Displays topic-specific information (imported from `../topic/[slug]/[...tab]`). **/ -import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, createAsync, useLocation, useParams } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' @@ -65,25 +65,27 @@ export type SlugPageProps = { } export default function ArticlePage(props: RouteSectionProps) { - if (props.params.slug.startsWith('@')) { + const params = useParams(); + + if (params.slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { ...props, params: { ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) + slug: params.slug.slice(1, params.slug.length) } } as RouteSectionProps return } - if (props.params.slug.startsWith('!')) { + if (params.slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') const patchedProps = { ...props, params: { ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) + slug: params.slug.slice(1, params.slug.length) } } as RouteSectionProps return @@ -95,7 +97,14 @@ export default function ArticlePage(props: RouteSectionProps) { function InnerArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() - const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) + const params = useParams(); + + const data = createAsync(async () => { + console.debug('Fetching article with slug (createAsync):', params.slug) + const result = props.data?.article || (await fetchShout(params.slug)) + console.debug('Fetched article data (createAsync):', result) + return result + }) onMount(async () => { if (gaIdentity && data()?.id) { @@ -108,11 +117,24 @@ function InnerArticlePage(props: RouteSectionProps) { } }) + createEffect( + on( + () => params.slug, + async (newSlug) => { + console.debug('Slug changed (useParams):', newSlug) + const result = await fetchShout(newSlug); + console.debug('Fetched article data (useParams):', result) + data(result); + } + ) + ) + createEffect( on( data, (a?: Shout) => { if (!a?.id) return + console.debug('Page view event for article:', a) window?.gtag?.('event', 'page_view', { page_title: a.title, page_location: window?.location.href || '', @@ -123,18 +145,27 @@ function InnerArticlePage(props: RouteSectionProps) { ) ) + createEffect(async () => { + console.debug('Data from createAsync effect:', data()); + }); + return ( - }> + { + console.error('Rendering 500 error page') + return + }}> }> + {console.warn('Rendering 404 error page - no article data found')} } > + {console.debug('Rendering article page with data:', data())} Date: Tue, 24 Sep 2024 22:03:57 -0300 Subject: [PATCH 04/15] debug: more pres logs for slug tab.tsx --- src/routes/[slug]/[...tab].tsx | 48 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 15385a9b..6b187789 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -95,55 +95,59 @@ export default function ArticlePage(props: RouteSectionProps) { } function InnerArticlePage(props: RouteSectionProps) { - const loc = useLocation() - const { t } = useLocalize() + const loc = useLocation(); + const { t } = useLocalize(); const params = useParams(); - + + console.debug('Initial slug from useParams:', params.slug); + const data = createAsync(async () => { - console.debug('Fetching article with slug (createAsync):', params.slug) - const result = props.data?.article || (await fetchShout(params.slug)) - console.debug('Fetched article data (createAsync):', result) - return result - }) + console.debug('Fetching article with slug (createAsync):', params.slug); + const result = props.data?.article || (await fetchShout(params.slug)); + console.debug('Fetched article data (createAsync):', result); + return result; + }); onMount(async () => { + console.debug('onMount triggered'); if (gaIdentity && data()?.id) { try { - await loadGAScript(gaIdentity) - initGA(gaIdentity) + console.debug('Loading GA script'); + await loadGAScript(gaIdentity); + initGA(gaIdentity); } catch (error) { - console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) + console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error); } } - }) + }); createEffect( on( () => params.slug, async (newSlug) => { - console.debug('Slug changed (useParams):', newSlug) + console.debug('Slug changed (useParams):', newSlug); const result = await fetchShout(newSlug); - console.debug('Fetched article data (useParams):', result) + console.debug('Fetched article data (useParams):', result); data(result); } ) - ) + ); createEffect( on( data, (a?: Shout) => { - if (!a?.id) return - console.debug('Page view event for article:', a) + if (!a?.id) return; + console.debug('Page view event for article:', a); window?.gtag?.('event', 'page_view', { page_title: a.title, page_location: window?.location.href || '', page_path: loc.pathname - }) + }); }, { defer: true } ) - ) + ); createEffect(async () => { console.debug('Data from createAsync effect:', data()); @@ -151,8 +155,8 @@ function InnerArticlePage(props: RouteSectionProps) { return ( { - console.error('Rendering 500 error page') - return + console.error('Rendering 500 error page'); + return ; }}> }> ) { - ) + ); } From a805493b271f94050d47a140c0f62044afbd91f6 Mon Sep 17 00:00:00 2001 From: dufok Date: Tue, 24 Sep 2024 22:14:46 -0300 Subject: [PATCH 05/15] debug: used version only with useParam and with logging for slug tab --- src/routes/[slug]/[...tab].tsx | 122 ++++++++++----------------------- 1 file changed, 35 insertions(+), 87 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 6b187789..163e8c7c 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -19,9 +19,9 @@ * - **TopicPage**: Displays topic-specific information (imported from `../topic/[slug]/[...tab]`). **/ -import { RouteDefinition, RouteSectionProps, createAsync, useLocation, useParams } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, useLocation, useParams } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -65,98 +65,46 @@ export type SlugPageProps = { } export default function ArticlePage(props: RouteSectionProps) { - const params = useParams(); + const loc = useLocation() + const { t } = useLocalize() + const params = useParams() - if (params.slug.startsWith('@')) { - console.debug('[routes] [slug]/[...tab] starts with @, render as author page') - const patchedProps = { - ...props, - params: { - ...props.params, - slug: params.slug.slice(1, params.slug.length) - } - } as RouteSectionProps - return + console.debug('Initial slug from useParams:', params.slug) + + const [data, setData] = createSignal(undefined) + + const fetchData = async (slug: string) => { + console.debug('Fetching article with slug (useParams):', slug) + const result = await fetchShout(slug) + console.debug('Fetched article data (useParams):', result) + setData(result) } - if (params.slug.startsWith('!')) { - console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') - const patchedProps = { - ...props, - params: { - ...props.params, - slug: params.slug.slice(1, params.slug.length) - } - } as RouteSectionProps - return - } + onMount(() => { + console.debug('onMount triggered') + fetchData(params.slug) + }) - return -} + createEffect(() => { + console.debug('Slug changed (useParams):', params.slug) + fetchData(params.slug) + }) -function InnerArticlePage(props: RouteSectionProps) { - const loc = useLocation(); - const { t } = useLocalize(); - const params = useParams(); - - console.debug('Initial slug from useParams:', params.slug); - - const data = createAsync(async () => { - console.debug('Fetching article with slug (createAsync):', params.slug); - const result = props.data?.article || (await fetchShout(params.slug)); - console.debug('Fetched article data (createAsync):', result); - return result; - }); - - onMount(async () => { - console.debug('onMount triggered'); - if (gaIdentity && data()?.id) { - try { - console.debug('Loading GA script'); - await loadGAScript(gaIdentity); - initGA(gaIdentity); - } catch (error) { - console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error); - } - } - }); - - createEffect( - on( - () => params.slug, - async (newSlug) => { - console.debug('Slug changed (useParams):', newSlug); - const result = await fetchShout(newSlug); - console.debug('Fetched article data (useParams):', result); - data(result); - } - ) - ); - - createEffect( - on( - data, - (a?: Shout) => { - if (!a?.id) return; - console.debug('Page view event for article:', a); - window?.gtag?.('event', 'page_view', { - page_title: a.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }); - }, - { defer: true } - ) - ); - - createEffect(async () => { - console.debug('Data from createAsync effect:', data()); - }); + createEffect(() => { + const article = data() + if (!article?.id) return + console.debug('Page view event for article:', article) + window?.gtag?.('event', 'page_view', { + page_title: article.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + }) return ( { - console.error('Rendering 500 error page'); - return ; + console.error('Rendering 500 error page') + return }}> }> ) { - ); + ) } From 6dc25260bbf7320edcd0aa00b63e67888b23cdf8 Mon Sep 17 00:00:00 2001 From: dufok Date: Tue, 24 Sep 2024 22:25:56 -0300 Subject: [PATCH 06/15] debug: break everythig, rename Artile Page and add logs --- src/routes/[slug]/[...tab].tsx | 53 ++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 163e8c7c..1e3be49e 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,24 +1,3 @@ -/** - * [slug].tsx - * - * # Dynamic Slug Route Handler - * - * ## Overview - * - * This file handles dynamic routing based on the `slug` parameter in the URL. Depending on the prefix of the slug, it renders different pages: - * - * - **Author Page**: If the `slug` starts with `@`, it renders the `AuthorPage` component for the specified author. - * - **Topic Page**: If the `slug` starts with `!`, it renders the `TopicPage` component for the specified topic. - * - **Article Page**: For all other slugs, it renders the `ArticlePageComponent`, displaying the full article details. - * - * ## Components - * - * - **SlugPage**: The main component that determines which page to render based on the `slug`. - * - **InnerArticlePage**: Fetches and displays the detailed view of an article. - * - **AuthorPage**: Displays author-specific information (imported from `../author/[slug]/[...tab]`). - * - **TopicPage**: Displays topic-specific information (imported from `../topic/[slug]/[...tab]`). - **/ - import { RouteDefinition, RouteSectionProps, useLocation, useParams } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' import { ErrorBoundary, Show, Suspense, createEffect, onMount } from 'solid-js' @@ -64,7 +43,37 @@ export type SlugPageProps = { topics: Topic[] } -export default function ArticlePage(props: RouteSectionProps) { +export default function SlugPage(props: RouteSectionProps) { + const params = useParams() + + if (params.slug.startsWith('@')) { + console.debug('[routes] [slug]/[...tab] starts with @, render as author page') + const patchedProps = { + ...props, + params: { + ...props.params, + slug: params.slug.slice(1) + } + } as RouteSectionProps + return + } + + if (params.slug.startsWith('!')) { + console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') + const patchedProps = { + ...props, + params: { + ...props.params, + slug: params.slug.slice(1) + } + } as RouteSectionProps + return + } + + return +} + +function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() const params = useParams() From aa11c8d8b80eac3bcea4394bcea8596d7e2409a1 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 09:59:12 -0300 Subject: [PATCH 07/15] debug: With load topics and logs in slug tab to see why it is not loading topic from user page --- src/routes/[slug]/[...tab].tsx | 176 ++++++++++++++++++++------------- 1 file changed, 105 insertions(+), 71 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 1e3be49e..dfac04fb 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,11 +1,12 @@ -import { RouteDefinition, RouteSectionProps, useLocation, useParams } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' import { useLocalize } from '~/context/localize' import { getShout } from '~/graphql/api/public' +import { useTopics } from '~/context/topics' // Import Topics context import type { Author, Reaction, Shout, Topic } from '~/graphql/schema/core.gen' import { initGA, loadGAScript } from '~/utils/ga' import { descFromBody, keywordsFromTopics } from '~/utils/meta' @@ -43,104 +44,137 @@ export type SlugPageProps = { topics: Topic[] } -export default function SlugPage(props: RouteSectionProps) { - const params = useParams() +export default function ArticlePage(props: RouteSectionProps) { + const { topicEntities, loadTopics } = useTopics() // Get topics context + const slug = props.params.slug - if (params.slug.startsWith('@')) { + // Handle author page if slug starts with '@' + if (slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { ...props, params: { ...props.params, - slug: params.slug.slice(1) + slug: slug.slice(1) } } as RouteSectionProps return } - if (params.slug.startsWith('!')) { + // Handle topic page if slug starts with '!' + if (slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') + + const topicSlug = slug.slice(1) // Remove '!' from slug + const topic = topicEntities()[topicSlug] // Check if the topic is already loaded + + // If the topic is not loaded, fetch topics + if (!topic) { + onMount(async () => { + console.debug('Loading topics for the first time...') + await loadTopics() // Load topics if not already available + }) + + return // Show a loading state while fetching the topics + } + const patchedProps = { ...props, params: { ...props.params, - slug: params.slug.slice(1) + slug: topicSlug } } as RouteSectionProps return } - return -} + // Handle topic pages without '!' or '@' + if (!slug.startsWith('@') && !slug.startsWith('!')) { + console.debug('[routes] [slug]/[...tab] regular topic page') -function ArticlePage(props: RouteSectionProps) { - const loc = useLocation() - const { t } = useLocalize() - const params = useParams() + const topic = topicEntities()[slug] // Check if the topic is already loaded - console.debug('Initial slug from useParams:', params.slug) + // If the topic is not loaded, trigger topic loading + if (!topic) { + onMount(async () => { + console.debug('Topic not found, loading topics...') + await loadTopics() + }) - const [data, setData] = createSignal(undefined) + return // Show a loading state while fetching the topics + } - const fetchData = async (slug: string) => { - console.debug('Fetching article with slug (useParams):', slug) - const result = await fetchShout(slug) - console.debug('Fetched article data (useParams):', result) - setData(result) + const patchedProps = { + ...props, + params: { + ...props.params, + slug + } + } as RouteSectionProps + return } - onMount(() => { - console.debug('onMount triggered') - fetchData(params.slug) - }) + // ArticlePage logic for rendering articles if neither `@` nor `!` is in the slug + function ArticlePage(props: RouteSectionProps) { + const loc = useLocation() + const { t } = useLocalize() + const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) - createEffect(() => { - console.debug('Slug changed (useParams):', params.slug) - fetchData(params.slug) - }) - - createEffect(() => { - const article = data() - if (!article?.id) return - console.debug('Page view event for article:', article) - window?.gtag?.('event', 'page_view', { - page_title: article.title, - page_location: window?.location.href || '', - page_path: loc.pathname + onMount(async () => { + if (gaIdentity && data()?.id) { + try { + await loadGAScript(gaIdentity) + initGA(gaIdentity) + } catch (error) { + console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) + } + } }) - }) - return ( - { - console.error('Rendering 500 error page') - return - }}> - }> - - {console.warn('Rendering 404 error page - no article data found')} - - - - } - > - {console.debug('Rendering article page with data:', data())} - { + if (!a?.id) return + window?.gtag?.('event', 'page_view', { + page_title: a.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + }, + { defer: true } + ) + ) + + return ( + }> + }> + + + + + } > - - - - - - - - ) + + + + + + + + + ) + } + + return } From db8b53f9bdaaeb92a73711886faad041fa3cd012 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 10:21:08 -0300 Subject: [PATCH 08/15] debug: back to dev version. Investigate UserPage Artcicle Render --- src/routes/[slug]/[...tab].tsx | 57 +++------------------------------- 1 file changed, 4 insertions(+), 53 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index dfac04fb..e71bd611 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -6,7 +6,6 @@ import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' import { useLocalize } from '~/context/localize' import { getShout } from '~/graphql/api/public' -import { useTopics } from '~/context/topics' // Import Topics context import type { Author, Reaction, Shout, Topic } from '~/graphql/schema/core.gen' import { initGA, loadGAScript } from '~/utils/ga' import { descFromBody, keywordsFromTopics } from '~/utils/meta' @@ -45,76 +44,30 @@ export type SlugPageProps = { } export default function ArticlePage(props: RouteSectionProps) { - const { topicEntities, loadTopics } = useTopics() // Get topics context - const slug = props.params.slug - - // Handle author page if slug starts with '@' - if (slug.startsWith('@')) { + if (props.params.slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { ...props, params: { ...props.params, - slug: slug.slice(1) + slug: props.params.slug.slice(1, props.params.slug.length) } } as RouteSectionProps return } - // Handle topic page if slug starts with '!' - if (slug.startsWith('!')) { + if (props.params.slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') - - const topicSlug = slug.slice(1) // Remove '!' from slug - const topic = topicEntities()[topicSlug] // Check if the topic is already loaded - - // If the topic is not loaded, fetch topics - if (!topic) { - onMount(async () => { - console.debug('Loading topics for the first time...') - await loadTopics() // Load topics if not already available - }) - - return // Show a loading state while fetching the topics - } - const patchedProps = { ...props, params: { ...props.params, - slug: topicSlug + slug: props.params.slug.slice(1, props.params.slug.length) } } as RouteSectionProps return } - // Handle topic pages without '!' or '@' - if (!slug.startsWith('@') && !slug.startsWith('!')) { - console.debug('[routes] [slug]/[...tab] regular topic page') - - const topic = topicEntities()[slug] // Check if the topic is already loaded - - // If the topic is not loaded, trigger topic loading - if (!topic) { - onMount(async () => { - console.debug('Topic not found, loading topics...') - await loadTopics() - }) - - return // Show a loading state while fetching the topics - } - - const patchedProps = { - ...props, - params: { - ...props.params, - slug - } - } as RouteSectionProps - return - } - - // ArticlePage logic for rendering articles if neither `@` nor `!` is in the slug function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() @@ -175,6 +128,4 @@ export default function ArticlePage(props: RouteSectionProps) { ) } - return -} From 91d8fdf746a3ccbf09e8c6f87ad00638354f4dc9 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 16:20:42 -0300 Subject: [PATCH 09/15] debug: add logs in dev variant of slug/tab --- src/routes/[slug]/[...tab].tsx | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index e71bd611..b5918985 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -16,16 +16,21 @@ import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]' import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]' const fetchShout = async (slug: string): Promise => { + console.debug('fetchShout called with slug:', slug) if (slug.startsWith('@')) return const shoutLoader = getShout({ slug }) const result = await shoutLoader() + console.debug('fetchShout result:', result) return result } export const route: RouteDefinition = { - load: async ({ params }) => ({ - article: await fetchShout(params.slug) - }) + load: async ({ params }) => { + console.debug('route.load called with params:', params) + const article = await fetchShout(params.slug) + console.debug('route.load fetched article:', article) + return { article } + } } export type ArticlePageProps = { @@ -71,11 +76,18 @@ export default function ArticlePage(props: RouteSectionProps) { function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() - const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) + const data = createAsync(async () => { + console.debug('createAsync fetching data with slug:', props.params.slug) + const result = props.data?.article || (await fetchShout(props.params.slug)) + console.debug('createAsync fetched result:', result) + return result + }) onMount(async () => { + console.debug('onMount triggered') if (gaIdentity && data()?.id) { try { + console.debug('Loading GA script') await loadGAScript(gaIdentity) initGA(gaIdentity) } catch (error) { @@ -88,6 +100,7 @@ export default function ArticlePage(props: RouteSectionProps) { on( data, (a?: Shout) => { + console.debug('createEffect triggered with data:', a) if (!a?.id) return window?.gtag?.('event', 'page_view', { page_title: a.title, @@ -100,17 +113,22 @@ export default function ArticlePage(props: RouteSectionProps) { ) return ( - }> + { + console.error('Rendering 500 error page') + return + }}> }> + {console.warn('Rendering 404 error page - no article data found')} } > + {console.debug('Rendering article page with data:', data())} ) { ) } return +} From dc2b6a5ab108f9e378196035c5e9dd324422159c Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 17:04:08 -0300 Subject: [PATCH 10/15] debug: with reset data if slug is changes in slug/tab articalpage --- src/routes/[slug]/[...tab].tsx | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index b5918985..9ebe49e6 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,6 @@ import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -29,6 +29,9 @@ export const route: RouteDefinition = { console.debug('route.load called with params:', params) const article = await fetchShout(params.slug) console.debug('route.load fetched article:', article) + if (!article) { + console.warn('No article fetched for the given slug:', params.slug); + } return { article } } } @@ -96,22 +99,6 @@ export default function ArticlePage(props: RouteSectionProps) { } }) - createEffect( - on( - data, - (a?: Shout) => { - console.debug('createEffect triggered with data:', a) - if (!a?.id) return - window?.gtag?.('event', 'page_view', { - page_title: a.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }) - }, - { defer: true } - ) - ) - return ( { console.error('Rendering 500 error page') From bbab1e4cb83cfa0e9806849ff5748918bf6723d0 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 17:25:08 -0300 Subject: [PATCH 11/15] debug: Added logic for robust reload data forslug before render --- src/routes/[slug]/[...tab].tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 9ebe49e6..45a6dc05 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,6 @@ import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -79,6 +79,8 @@ export default function ArticlePage(props: RouteSectionProps) { function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() + + // Refactored createAsync to ensure data fetch on route changes const data = createAsync(async () => { console.debug('createAsync fetching data with slug:', props.params.slug) const result = props.data?.article || (await fetchShout(props.params.slug)) @@ -86,6 +88,7 @@ export default function ArticlePage(props: RouteSectionProps) { return result }) + // onMount to load GA and other scripts if needed onMount(async () => { console.debug('onMount triggered') if (gaIdentity && data()?.id) { @@ -99,6 +102,18 @@ export default function ArticlePage(props: RouteSectionProps) { } }) + // Re-trigger Google Analytics when data changes + createEffect(() => { + console.debug('createEffect triggered with data:', data()) + if (data()?.id) { + window?.gtag?.('event', 'page_view', { + page_title: data()?.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + } + }) + return ( { console.error('Rendering 500 error page') @@ -133,5 +148,7 @@ export default function ArticlePage(props: RouteSectionProps) { ) } + + // Return the ArticlePage component to ensure the route handles properly return } From c165742fbf48480a9f7fb90f96ef3daf1ae52215 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 19:16:13 -0300 Subject: [PATCH 12/15] debug: replace createAsync for slugloader to createSignal in slug/tab for trying avoid complex repeating of async functions --- src/routes/[slug]/[...tab].tsx | 97 +++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 45a6dc05..5806a6b9 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,6 @@ -import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, createSignal, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -15,23 +15,19 @@ import { ReactionsProvider } from '../../context/reactions' import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]' import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]' +// Simplified fetch function for the shout const fetchShout = async (slug: string): Promise => { console.debug('fetchShout called with slug:', slug) - if (slug.startsWith('@')) return - const shoutLoader = getShout({ slug }) - const result = await shoutLoader() + if (slug.startsWith('@')) return // Skip fetching article for slugs starting with @ (author pages) + const result = await getShout({ slug }) console.debug('fetchShout result:', result) return result } export const route: RouteDefinition = { load: async ({ params }) => { - console.debug('route.load called with params:', params) const article = await fetchShout(params.slug) console.debug('route.load fetched article:', article) - if (!article) { - console.warn('No article fetched for the given slug:', params.slug); - } return { article } } } @@ -52,6 +48,7 @@ export type SlugPageProps = { } export default function ArticlePage(props: RouteSectionProps) { + // If the slug starts with '@', render as author page if (props.params.slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { @@ -64,6 +61,7 @@ export default function ArticlePage(props: RouteSectionProps) { return } + // If the slug starts with '!', render as topic page if (props.params.slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') const patchedProps = { @@ -76,22 +74,38 @@ export default function ArticlePage(props: RouteSectionProps) { return } + // Handle regular article slugs function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() - // Refactored createAsync to ensure data fetch on route changes - const data = createAsync(async () => { - console.debug('createAsync fetching data with slug:', props.params.slug) - const result = props.data?.article || (await fetchShout(props.params.slug)) - console.debug('createAsync fetched result:', result) - return result + // Set up a signal for article data and loading state + const [article, setArticle] = createSignal(props.data?.article) + const [isLoading, setIsLoading] = createSignal(false) + + // Fetch article data manually based on slug changes + createEffect(() => { + const slug = props.params.slug + if (!slug) return + + setIsLoading(true) + fetchShout(slug) + .then((result) => { + setArticle(result) + if (!result) { + console.warn('No article data found for slug:', slug) + } + }) + .catch((error) => { + console.error('Error fetching shout:', error) + }) + .finally(() => setIsLoading(false)) }) - // onMount to load GA and other scripts if needed + // onMount to load GA script onMount(async () => { console.debug('onMount triggered') - if (gaIdentity && data()?.id) { + if (gaIdentity && article()?.id) { try { console.debug('Loading GA script') await loadGAScript(gaIdentity) @@ -102,26 +116,27 @@ export default function ArticlePage(props: RouteSectionProps) { } }) - // Re-trigger Google Analytics when data changes - createEffect(() => { - console.debug('createEffect triggered with data:', data()) - if (data()?.id) { - window?.gtag?.('event', 'page_view', { - page_title: data()?.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }) - } - }) + // Google Analytics effect + createEffect( + on( + article, + (a?: Shout) => { + if (!a?.id) return + window?.gtag?.('event', 'page_view', { + page_title: a.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + }, + { defer: true } + ) + ) return ( - { - console.error('Rendering 500 error page') - return - }}> + }> }> {console.warn('Rendering 404 error page - no article data found')} @@ -130,17 +145,16 @@ export default function ArticlePage(props: RouteSectionProps) { } > - {console.debug('Rendering article page with data:', data())} - + @@ -149,6 +163,5 @@ export default function ArticlePage(props: RouteSectionProps) { ) } - // Return the ArticlePage component to ensure the route handles properly return } From 29dbd67c27147d8189036863553bdad906a68337 Mon Sep 17 00:00:00 2001 From: dufok Date: Wed, 25 Sep 2024 21:15:17 -0300 Subject: [PATCH 13/15] debugL --- src/routes/[slug]/[...tab].tsx | 73 +++++++++------------------------- 1 file changed, 19 insertions(+), 54 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 5806a6b9..ef9fc842 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,6 @@ -import { RouteDefinition, RouteSectionProps, useLocation } from '@solidjs/router' +import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, createSignal, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -15,21 +15,17 @@ import { ReactionsProvider } from '../../context/reactions' import AuthorPage, { AuthorPageProps } from '../author/[slug]/[...tab]' import TopicPage, { TopicPageProps } from '../topic/[slug]/[...tab]' -// Simplified fetch function for the shout const fetchShout = async (slug: string): Promise => { - console.debug('fetchShout called with slug:', slug) - if (slug.startsWith('@')) return // Skip fetching article for slugs starting with @ (author pages) - const result = await getShout({ slug }) - console.debug('fetchShout result:', result) + if (slug.startsWith('@')) return + const shoutLoader = getShout({ slug }) + const result = await shoutLoader() return result } export const route: RouteDefinition = { - load: async ({ params }) => { - const article = await fetchShout(params.slug) - console.debug('route.load fetched article:', article) - return { article } - } + load: async ({ params }) => ({ + article: await fetchShout(params.slug) + }) } export type ArticlePageProps = { @@ -48,7 +44,6 @@ export type SlugPageProps = { } export default function ArticlePage(props: RouteSectionProps) { - // If the slug starts with '@', render as author page if (props.params.slug.startsWith('@')) { console.debug('[routes] [slug]/[...tab] starts with @, render as author page') const patchedProps = { @@ -61,7 +56,6 @@ export default function ArticlePage(props: RouteSectionProps) { return } - // If the slug starts with '!', render as topic page if (props.params.slug.startsWith('!')) { console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') const patchedProps = { @@ -74,40 +68,14 @@ export default function ArticlePage(props: RouteSectionProps) { return } - // Handle regular article slugs function ArticlePage(props: RouteSectionProps) { const loc = useLocation() const { t } = useLocalize() + const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) - // Set up a signal for article data and loading state - const [article, setArticle] = createSignal(props.data?.article) - const [isLoading, setIsLoading] = createSignal(false) - - // Fetch article data manually based on slug changes - createEffect(() => { - const slug = props.params.slug - if (!slug) return - - setIsLoading(true) - fetchShout(slug) - .then((result) => { - setArticle(result) - if (!result) { - console.warn('No article data found for slug:', slug) - } - }) - .catch((error) => { - console.error('Error fetching shout:', error) - }) - .finally(() => setIsLoading(false)) - }) - - // onMount to load GA script onMount(async () => { - console.debug('onMount triggered') - if (gaIdentity && article()?.id) { + if (gaIdentity && data()?.id) { try { - console.debug('Loading GA script') await loadGAScript(gaIdentity) initGA(gaIdentity) } catch (error) { @@ -116,10 +84,9 @@ export default function ArticlePage(props: RouteSectionProps) { } }) - // Google Analytics effect createEffect( on( - article, + data, (a?: Shout) => { if (!a?.id) return window?.gtag?.('event', 'page_view', { @@ -136,25 +103,24 @@ export default function ArticlePage(props: RouteSectionProps) { }> }> - {console.warn('Rendering 404 error page - no article data found')} } > - + @@ -162,6 +128,5 @@ export default function ArticlePage(props: RouteSectionProps) { ) } - return } From 32ebcff5fe6c7b7b5797eebde143f7b0a045f0c2 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Mon, 30 Sep 2024 16:35:15 +0000 Subject: [PATCH 14/15] feat: improve component structure and addded signal managment. Extract Article page Content into a separate block. Added createSignal and CreateEffect to track slug dynamically. Replace ifelse with Switch and Match. --- src/routes/[slug]/[...tab].tsx | 189 +++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 82 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index ef9fc842..67f19c70 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,6 @@ import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount } from 'solid-js' +import { ErrorBoundary, Show, Suspense, createEffect, on, onMount, Switch, Match, createSignal } from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -43,90 +43,115 @@ export type SlugPageProps = { topics: Topic[] } -export default function ArticlePage(props: RouteSectionProps) { - if (props.params.slug.startsWith('@')) { - console.debug('[routes] [slug]/[...tab] starts with @, render as author page') - const patchedProps = { - ...props, - params: { - ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) +function ArticlePageContent(props: RouteSectionProps) { + const loc = useLocation() + const { t } = useLocalize() + const data = createAsync(async () => { + const result = props.data?.article || (await fetchShout(props.params.slug)) + return result + }) + + onMount(async () => { + console.debug('[ArticlePage] onMount') + if (gaIdentity && data()?.id) { + try { + await loadGAScript(gaIdentity) + initGA(gaIdentity) + } catch (error) { + console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) } - } as RouteSectionProps - return - } + } + }) - if (props.params.slug.startsWith('!')) { - console.debug('[routes] [slug]/[...tab] starts with !, render as topic page') - const patchedProps = { - ...props, - params: { - ...props.params, - slug: props.params.slug.slice(1, props.params.slug.length) - } - } as RouteSectionProps - return - } - - function ArticlePage(props: RouteSectionProps) { - const loc = useLocation() - const { t } = useLocalize() - const data = createAsync(async () => props.data?.article || (await fetchShout(props.params.slug))) - - onMount(async () => { - if (gaIdentity && data()?.id) { - try { - await loadGAScript(gaIdentity) - initGA(gaIdentity) - } catch (error) { - console.warn('[routes] [slug]/[...tab] Failed to connect Google Analytics:', error) - } - } - }) - - createEffect( - on( - data, - (a?: Shout) => { - if (!a?.id) return - window?.gtag?.('event', 'page_view', { - page_title: a.title, - page_location: window?.location.href || '', - page_path: loc.pathname - }) - }, - { defer: true } - ) + createEffect( + on( + data, + (a?: Shout) => { + if (!a?.id) return + window?.gtag?.('event', 'page_view', { + page_title: a.title, + page_location: window?.location.href || '', + page_path: loc.pathname + }) + }, + { defer: true } ) + ) - return ( - }> - }> - - - - - } - > - - - - + return ( + }> + }> + + + - - - - ) - } - return + } + > + + + + + + + + + ) } + +export default function ArticlePage(props: RouteSectionProps) { + console.debug('[routes] [slug]/[...tab] props:', props) + + const { slug } = props.params + + const [currentSlug, setCurrentSlug] = createSignal(props.params.slug); + createEffect(() => { + if (props.params.slug !== currentSlug()) { + setCurrentSlug(props.params.slug); + } + }); + + return ( + Loading...}> + + } + /> + + + } + /> + + + + + + }> + + + + + ) +} \ No newline at end of file From 55e2b344661e48641755cd711f2cc37be69d6b25 Mon Sep 17 00:00:00 2001 From: Stepan Vladovskiy Date: Tue, 1 Oct 2024 20:50:01 +0000 Subject: [PATCH 15/15] feat: fix slug updating in ArticlePage component by managing curentSlug signal --- src/routes/[slug]/[...tab].tsx | 46 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/routes/[slug]/[...tab].tsx b/src/routes/[slug]/[...tab].tsx index 67f19c70..d31e7bee 100644 --- a/src/routes/[slug]/[...tab].tsx +++ b/src/routes/[slug]/[...tab].tsx @@ -1,6 +1,16 @@ import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router' import { HttpStatusCode } from '@solidjs/start' -import { ErrorBoundary, Show, Suspense, createEffect, on, onMount, Switch, Match, createSignal } from 'solid-js' +import { + ErrorBoundary, + Match, + Show, + Suspense, + Switch, + createEffect, + createSignal, + on, + onMount +} from 'solid-js' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' import { gaIdentity } from '~/config' @@ -52,7 +62,6 @@ function ArticlePageContent(props: RouteSectionProps) { }) onMount(async () => { - console.debug('[ArticlePage] onMount') if (gaIdentity && data()?.id) { try { await loadGAScript(gaIdentity) @@ -109,42 +118,39 @@ function ArticlePageContent(props: RouteSectionProps) { } export default function ArticlePage(props: RouteSectionProps) { - console.debug('[routes] [slug]/[...tab] props:', props) - - const { slug } = props.params - - const [currentSlug, setCurrentSlug] = createSignal(props.params.slug); + const [currentSlug, setCurrentSlug] = createSignal(props.params.slug) createEffect(() => { - if (props.params.slug !== currentSlug()) { - setCurrentSlug(props.params.slug); + const newSlug = props.params.slug + if (newSlug !== currentSlug()) { + setCurrentSlug(newSlug) } - }); + }) return ( Loading...}> } + slug: currentSlug().slice(1) + } + } as RouteSectionProps)} /> } + slug: currentSlug().slice(1) + } + } as RouteSectionProps)} /> - + currentSlug().startsWith(prefix))}> @@ -154,4 +160,4 @@ export default function ArticlePage(props: RouteSectionProps) { ) -} \ No newline at end of file +}