@-routing-fix

This commit is contained in:
Untone 2024-07-13 12:36:23 +03:00
parent ef1408327f
commit fde2335a02
9 changed files with 61 additions and 85 deletions

View File

@ -1,4 +1,4 @@
import { A, useLocation, useParams } from '@solidjs/router'
import { A, useLocation } from '@solidjs/router'
import { clsx } from 'clsx'
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
import { Loading } from '~/components/_shared/Loading'
@ -26,7 +26,7 @@ import { Row2 } from '../../Feed/Row2'
import { Row3 } from '../../Feed/Row3'
import styles from './Author.module.scss'
type Props = {
type AuthorViewProps = {
authorSlug: string
selectedTab: string
shouts?: Shout[]
@ -37,11 +37,10 @@ type Props = {
export const PRERENDERED_ARTICLES_COUNT = 12
const LOAD_MORE_PAGE_SIZE = 9
export const AuthorView = (props: Props) => {
export const AuthorView = (props: AuthorViewProps) => {
// contexts
const { t } = useLocalize()
const loc = useLocation()
const params = useParams()
const { session } = useSession()
const { query } = useGraphQL()
const { sortedFeed } = useFeed()
@ -173,19 +172,19 @@ export const AuthorView = (props: Props) => {
<div class={clsx(styles.groupControls, 'row')}>
<div class="col-md-16">
<ul class="view-switcher">
<li classList={{ 'view-switcher__item--selected': params.tab === '' }}>
<li classList={{ 'view-switcher__item--selected': !props.selectedTab }}>
<A href={`/author/${props.authorSlug}`}>{t('Publications')}</A>
<Show when={author()?.stat}>
<span class="view-switcher__counter">{author()?.stat?.shouts || 0}</span>
</Show>
</li>
<li classList={{ 'view-switcher__item--selected': params.tab === 'comment' }}>
<li classList={{ 'view-switcher__item--selected': props.selectedTab === 'comment' }}>
<A href={`/author/${props.authorSlug}/comments`}>{t('Comments')}</A>
<Show when={author()?.stat}>
<span class="view-switcher__counter">{author()?.stat?.comments || 0}</span>
</Show>
</li>
<li classList={{ 'view-switcher__item--selected': params.tab === 'about' }}>
<li classList={{ 'view-switcher__item--selected': props.selectedTab === 'about' }}>
<A onClick={() => checkBioHeight()} href={`/author/${props.authorSlug}/about`}>
{t('About the author')}
</A>
@ -206,7 +205,7 @@ export const AuthorView = (props: Props) => {
</div>
<Switch>
<Match when={params.tab === 'about'}>
<Match when={props.selectedTab === 'about'}>
<div class="wide-container">
<div class="row">
<div class="col-md-20 col-lg-18">
@ -230,7 +229,7 @@ export const AuthorView = (props: Props) => {
</div>
</div>
</Match>
<Match when={params.tab === 'comments'}>
<Match when={props.selectedTab === 'comments'}>
<Show when={me()?.slug === props.authorSlug && !me().stat?.comments}>
<div class="wide-container">
<Placeholder type={loc?.pathname} mode="profile" />
@ -256,7 +255,7 @@ export const AuthorView = (props: Props) => {
</div>
</div>
</Match>
<Match when={params.tab === ''}>
<Match when={!props.selectedTab}>
<Show when={me()?.slug === props.authorSlug && !me().stat?.shouts}>
<div class="wide-container">
<Placeholder type={loc?.pathname} mode="profile" />

View File

@ -16,6 +16,7 @@ import styles from './PageLayout.module.scss'
type PageLayoutProps = {
title: string
desc?: string
keywords?: string
headerTitle?: string
slug?: string
article?: Shout
@ -46,12 +47,10 @@ export const PageLayout = (props: PageLayoutProps) => {
})
: imageUrl
)
const description = createMemo(() => (props.desc ? t(props.desc) : ''))
const description = createMemo(() => props.desc || (props.article && descFromBody(props.article.body)))
const keypath = createMemo(() => (props.key || loc?.pathname.split('/')[0]) as keyof typeof ruKeywords)
const keywords = createMemo(
() =>
(props.article && descFromBody(props.article.body)) ||
(lang() === 'ru' ? ruKeywords[keypath()] : enKeywords[keypath()])
() => props.keywords || (lang() === 'ru' ? ruKeywords[keypath()] : enKeywords[keypath()])
)
const [scrollToComments, setScrollToComments] = createSignal<boolean>(false)
createEffect(() => props.scrollToComments?.(scrollToComments()))

View File

@ -92,12 +92,13 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
const loadAuthor = async (opts: QueryGet_AuthorArgs): Promise<void> => {
try {
console.debug('[context.authors] load author', opts)
const fetcher = await getAuthor(opts)
const author = await fetcher()
if (author) addAuthor(author as Author)
console.debug('Loaded author:', author)
console.debug('[context.authors]', author)
} catch (error) {
console.error('Error loading author:', error)
console.error('[context.authors] Error loading author:', error)
throw error
}
}

View File

@ -1,4 +1,4 @@
import { RouteDefinition, RouteSectionProps, createAsync, useLocation, useParams } from '@solidjs/router'
import { RouteDefinition, RouteSectionProps, createAsync, useLocation } from '@solidjs/router'
import { HttpStatusCode } from '@solidjs/start'
import {
ErrorBoundary,
@ -14,7 +14,7 @@ import { FourOuFourView } from '~/components/Views/FourOuFour'
import { Loading } from '~/components/_shared/Loading'
import { gaIdentity } from '~/config'
import { useLocalize } from '~/context/localize'
import { getAuthor, getShout } from '~/graphql/api/public'
import { getShout } from '~/graphql/api/public'
import type { Author, Reaction, Shout } from '~/graphql/schema/core.gen'
import { initGA, loadGAScript } from '~/utils/ga'
import { descFromBody, keywordsFromTopics } from '~/utils/meta'
@ -29,12 +29,6 @@ const fetchShout = async (slug: string): Promise<Shout | undefined> => {
return result
}
const fetchAuthor = async (slug: string): Promise<Author | undefined> => {
const authorLoader = getAuthor({ slug })
const result = await authorLoader()
return result
}
export const route: RouteDefinition = {
load: async ({ params }) => ({
article: await fetchShout(params.slug)
@ -44,21 +38,23 @@ export const route: RouteDefinition = {
type SlugPageProps = { article?: Shout; comments?: Reaction[]; votes?: Reaction[]; author?: Author }
export default (props: RouteSectionProps<SlugPageProps>) => {
const params = useParams()
if (params.slug.startsWith('@')) return AuthorPage(props as RouteSectionProps<AuthorPageProps>)
if (props.params.slug.startsWith('@')) {
console.debug('[slug] @ found, render as author page')
const patchedProps = {
...props,
params: {
...props.params,
slug: props.params.slug.slice(1, props.params.slug.length)
}
} as RouteSectionProps<AuthorPageProps>
return AuthorPage(patchedProps)
}
const loc = useLocation()
const { t } = useLocalize()
const [scrollToComments, setScrollToComments] = createSignal<boolean>(false)
const article = createAsync(async () => props.data.article || (await fetchShout(params.slug)))
const author = createAsync(async () =>
params.slug.startsWith('@')
? props.data.author || (await fetchAuthor(params.slug))
: article()?.authors?.[0]
)
const titleSuffix = createMemo(
() => (article()?.title || author()?.name) ?? ` :: ${article()?.title || author()?.name || ''}`
)
const article = createAsync(async () => props.data.article || (await fetchShout(props.params.slug)))
const titleSuffix = createMemo(() => (article()?.title ? ` :: ${article()?.title || ''}` : ''))
onMount(async () => {
if (gaIdentity && article()?.id) {
@ -98,12 +94,10 @@ export default (props: RouteSectionProps<SlugPageProps>) => {
</PageLayout>
}
>
<Show
when={params.slug.startsWith('@')}
fallback={
<PageLayout
title={`${t('Discours')}${titleSuffix() || ''}`}
desc={keywordsFromTopics(article()?.topics as { title: string }[])}
title={`${t('Discours')}${titleSuffix()}`}
desc={descFromBody(article()?.body || '')}
keywords={keywordsFromTopics(article()?.topics as { title: string }[])}
headerTitle={article()?.title || ''}
slug={article()?.slug}
cover={article()?.cover || ''}
@ -113,20 +107,6 @@ export default (props: RouteSectionProps<SlugPageProps>) => {
<FullArticle article={article() as Shout} scrollToComments={scrollToComments()} />
</ReactionsProvider>
</PageLayout>
}
>
<PageLayout
title={`${t('Discours')}${titleSuffix() || ''}`}
desc={descFromBody(author()?.about || author()?.bio || '')}
headerTitle={author()?.name || ''}
slug={author()?.slug}
cover={author()?.pic || ''}
>
<ReactionsProvider>
<FullArticle article={article() as Shout} scrollToComments={scrollToComments()} />
</ReactionsProvider>
</PageLayout>
</Show>
</Show>
</Suspense>
</ErrorBoundary>

View File

@ -1,4 +1,4 @@
import { RouteSectionProps, createAsync, useParams } from '@solidjs/router'
import { RouteSectionProps, createAsync } from '@solidjs/router'
import { ErrorBoundary, Suspense, createEffect, createMemo } from 'solid-js'
import { AuthorView } from '~/components/Views/Author'
import { FourOuFourView } from '~/components/Views/FourOuFour'
@ -50,13 +50,12 @@ export const route = {
export type AuthorPageProps = { articles?: Shout[]; author?: Author; topics?: Topic[] }
export const AuthorPage = (props: RouteSectionProps<AuthorPageProps>) => {
const params = useParams()
const { addAuthor } = useAuthors()
const articles = createAsync(
async () => props.data.articles || (await fetchAuthorShouts(params.slug)) || []
async () => props.data.articles || (await fetchAuthorShouts(props.params.slug)) || []
)
const author = createAsync(async () => {
const a = props.data.author || (await fetchAuthor(params.slug))
const a = props.data.author || (await fetchAuthor(props.params.slug))
a && addAuthor(a)
return a
})
@ -81,7 +80,9 @@ export const AuthorPage = (props: RouteSectionProps<AuthorPageProps>) => {
: getImageUrl('production/image/logo_image.png')
)
const selectedTab = createMemo(() => (params.tab in ['followers', 'shouts'] ? params.tab : 'name'))
const selectedTab = createMemo(() =>
props.params.tab in ['followers', 'shouts'] ? props.params.tab : 'name'
)
return (
<ErrorBoundary fallback={(_err) => <FourOuFourView />}>
<Suspense fallback={<Loading />}>
@ -96,7 +97,7 @@ export const AuthorPage = (props: RouteSectionProps<AuthorPageProps>) => {
<AuthorView
author={author() as Author}
selectedTab={selectedTab()}
authorSlug={params.slug}
authorSlug={props.params.slug}
shouts={articles() as Shout[]}
topics={topics()}
/>

View File

@ -1,4 +1,4 @@
import { redirect, useParams } from '@solidjs/router'
import { RouteSectionProps, redirect } from '@solidjs/router'
import { createEffect, createMemo, createSignal, lazy, on } from 'solid-js'
import { AuthGuard } from '~/components/AuthGuard'
import { PageLayout } from '~/components/_shared/PageLayout'
@ -27,7 +27,7 @@ export const getContentTypeTitle = (layout: LayoutType) => {
}
}
export default () => {
export default (props: RouteSectionProps) => {
const { t } = useLocalize()
const { session } = useSession()
const snackbar = useSnackbar()
@ -38,13 +38,12 @@ export default () => {
redirect('/edit') // all drafts page
}
const [shout, setShout] = createSignal<Shout>()
const params = useParams()
const client = useGraphQL()
createEffect(on(session, (s) => s?.access_token && loadDraft(), { defer: true }))
const loadDraft = async () => {
const result = await client.query(getShoutDraft, { shout_id: params.id }).toPromise()
const result = await client.query(getShoutDraft, { shout_id: props.params.id }).toPromise()
if (result) {
const { shout: loadedShout, error } = result.data.get_my_shout
if (error) {

View File

@ -1,4 +1,4 @@
import { useParams } from '@solidjs/router'
import { RouteSectionProps } from '@solidjs/router'
import { createEffect, createSignal, on } from 'solid-js'
import { AuthGuard } from '~/components/AuthGuard'
import EditSettingsView from '~/components/Views/EditView/EditSettingsView'
@ -9,15 +9,14 @@ import { useSession } from '~/context/session'
import getShoutDraft from '~/graphql/query/core/article-my'
import { Shout } from '~/graphql/schema/core.gen'
export default () => {
export default (props: RouteSectionProps) => {
const { t } = useLocalize()
const params = useParams()
const client = useGraphQL()
const { session } = useSession()
createEffect(on(session, (s) => s?.access_token && loadDraft(), { defer: true }))
const [shout, setShout] = createSignal<Shout>()
const loadDraft = async () => {
const result = await client.query(getShoutDraft, { shout_id: params.id }).toPromise()
const result = await client.query(getShoutDraft, { shout_id: props.params.id }).toPromise()
if (result) {
const { shout: loadedShout, error } = result.data.get_my_shout
if (error) throw new Error(error)

View File

@ -1,4 +1,4 @@
import { Params, RouteSectionProps, createAsync, useParams } from '@solidjs/router'
import { Params, RouteSectionProps, createAsync } from '@solidjs/router'
import { createEffect, createMemo, on } from 'solid-js'
import { TopicsNav } from '~/components/Nav/TopicsNav'
import { Expo } from '~/components/Views/Expo'
@ -28,15 +28,14 @@ export const route = {
export default (props: RouteSectionProps<Shout[]>) => {
const { t } = useLocalize()
const params = useParams()
const shouts = createAsync(
async () =>
props.data ||
(await fetchExpoShouts(
params.layout ? [params.layout] : ['audio', 'literature', 'article', 'video', 'image']
props.params.layout ? [props.params.layout] : ['audio', 'literature', 'article', 'video', 'image']
))
)
const layout = createMemo(() => params.layout)
const layout = createMemo(() => props.params.layout)
const title = createMemo(() => {
switch (layout()) {
case 'audio': {

View File

@ -1,4 +1,4 @@
import { RouteSectionProps, createAsync, useParams } from '@solidjs/router'
import { RouteSectionProps, createAsync } from '@solidjs/router'
import { HttpStatusCode } from '@solidjs/start'
import { Show, Suspense, createEffect, createMemo, createSignal } from 'solid-js'
import { FourOuFourView } from '~/components/Views/FourOuFour'
@ -37,7 +37,6 @@ export const route = {
export default (props: RouteSectionProps<{ articles: Shout[]; topics: Topic[] }>) => {
const { t } = useLocalize()
const params = useParams()
const { addTopics } = useTopics()
const [loadingError, setLoadingError] = createSignal(false)
@ -46,7 +45,7 @@ export default (props: RouteSectionProps<{ articles: Shout[]; topics: Topic[] }>
const ttt: Topic[] = props.data.topics || (await fetchAllTopics()) || []
addTopics(ttt)
console.debug('[route.topic] all topics loaded')
const t = ttt.find((x) => x.slug === params.slug)
const t = ttt.find((x) => x.slug === props.params.slug)
return t
} catch (_error) {
setLoadingError(true)
@ -55,7 +54,7 @@ export default (props: RouteSectionProps<{ articles: Shout[]; topics: Topic[] }>
})
const articles = createAsync(
async () => props.data.articles || (await fetchTopicShouts(params.slug)) || []
async () => props.data.articles || (await fetchTopicShouts(props.params.slug)) || []
)
const title = createMemo(() => `${t('Discours')} :: ${topic()?.title || ''}`)