ClientContainer -> ShowOnlyOnClient, topic and author page fixes
This commit is contained in:
parent
ac3b4b82d8
commit
28fa18b7c0
|
@ -33,7 +33,7 @@ export const Beside = (props: BesideProps) => {
|
|||
<h4>{props.title}</h4>
|
||||
|
||||
<Show when={props.wrapper === 'author'}>
|
||||
<a href="/user/list">
|
||||
<a href="/authors">
|
||||
{t('All authors')}
|
||||
<Icon name="arrow-right" />
|
||||
</a>
|
||||
|
|
|
@ -6,7 +6,6 @@ import { translit } from '../../utils/ru2en'
|
|||
import { Icon } from '../Nav/Icon'
|
||||
import styles from './Card.module.scss'
|
||||
import { locale } from '../../stores/ui'
|
||||
import { handleClientRouteLinkClick } from '../../stores/router'
|
||||
import { clsx } from 'clsx'
|
||||
import CardTopic from './CardTopic'
|
||||
|
||||
|
@ -113,7 +112,7 @@ export const ArticleCard = (props: ArticleCardProps) => {
|
|||
</Show>
|
||||
|
||||
<div class={styles.shoutCardTitlesContainer}>
|
||||
<a href={`/${slug || ''}`} onClick={handleClientRouteLinkClick}>
|
||||
<a href={`/${slug || ''}`}>
|
||||
<div class={styles.shoutCardTitle}>
|
||||
<span class={styles.shoutCardLinkContainer}>{title}</span>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { clsx } from 'clsx'
|
|||
import { t } from '../../../utils/intl'
|
||||
import { hideModal } from '../../../stores/ui'
|
||||
import { createMemo, createSignal, onMount, Show } from 'solid-js'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../../stores/router'
|
||||
import { useRouter } from '../../../stores/router'
|
||||
import type { ConfirmEmailSearchParams } from './types'
|
||||
import { ApiError } from '../../../utils/apiClient'
|
||||
import { useSession } from '../../../context/session'
|
||||
|
@ -48,7 +48,7 @@ export const EmailConfirm = () => {
|
|||
<Show when={isTokenExpired()}>
|
||||
<div class={styles.title}>Ссылка больше не действительна</div>
|
||||
<div class={styles.text}>
|
||||
<a href="/?modal=auth&mode=login" class={styles.sendLink} onClick={handleClientRouteLinkClick}>
|
||||
<a href="/?modal=auth&mode=login" class={styles.sendLink}>
|
||||
{/*TODO: temp solution, should be send link again, but we don't have email here*/}
|
||||
Вход
|
||||
</a>
|
||||
|
@ -57,7 +57,7 @@ export const EmailConfirm = () => {
|
|||
<Show when={isTokenInvalid()}>
|
||||
<div class={styles.title}>Неправильная ссылка</div>
|
||||
<div class={styles.text}>
|
||||
<a href="/?modal=auth&mode=login" class={styles.sendLink} onClick={handleClientRouteLinkClick}>
|
||||
<a href="/?modal=auth&mode=login" class={styles.sendLink}>
|
||||
{/*TODO: temp solution, should be send link again, but we don't have email here*/}
|
||||
Вход
|
||||
</a>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Dynamic } from 'solid-js/web'
|
|||
import { Component, createEffect, createMemo } from 'solid-js'
|
||||
import { t } from '../../../utils/intl'
|
||||
import { hideModal } from '../../../stores/ui'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../../stores/router'
|
||||
import { useRouter } from '../../../stores/router'
|
||||
import { clsx } from 'clsx'
|
||||
import styles from './AuthModal.module.scss'
|
||||
import { LoginForm } from './LoginForm'
|
||||
|
@ -57,9 +57,8 @@ export const AuthModal = () => {
|
|||
{t('By signing up you agree with our')}{' '}
|
||||
<a
|
||||
href="/about/terms-of-use"
|
||||
onClick={(event) => {
|
||||
onClick={() => {
|
||||
hideModal()
|
||||
handleClientRouteLinkClick(event)
|
||||
}}
|
||||
>
|
||||
{t('terms of use')}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Modal } from './Modal'
|
|||
import { AuthModal } from './AuthModal'
|
||||
import { t } from '../../utils/intl'
|
||||
import { useModalStore } from '../../stores/ui'
|
||||
import { handleClientRouteLinkClick, router, Routes, useRouter } from '../../stores/router'
|
||||
import { router, Routes, useRouter } from '../../stores/router'
|
||||
import styles from './Header.module.scss'
|
||||
import { getPagePath } from '@nanostores/router'
|
||||
import { clsx } from 'clsx'
|
||||
|
@ -91,7 +91,7 @@ export const Header = (props: Props) => {
|
|||
<div class={clsx(styles.mainHeaderInner, 'wide-container')}>
|
||||
<nav class={clsx(styles.headerInner, 'row')} classList={{ fixed: fixed() }}>
|
||||
<div class={clsx(styles.mainLogo, 'col-auto')}>
|
||||
<a href={getPagePath(router, 'home')} onClick={handleClientRouteLinkClick}>
|
||||
<a href={getPagePath(router, 'home')}>
|
||||
<img src="/logo.svg" alt={t('Discours')} />
|
||||
</a>
|
||||
</div>
|
||||
|
@ -107,9 +107,7 @@ export const Header = (props: Props) => {
|
|||
<For each={resources}>
|
||||
{(r) => (
|
||||
<li classList={{ [styles.selected]: r.route === page().route }}>
|
||||
<a href={getPagePath(router, r.route, null)} onClick={handleClientRouteLinkClick}>
|
||||
{r.name}
|
||||
</a>
|
||||
<a href={getPagePath(router, r.route, null)}>{r.name}</a>
|
||||
</li>
|
||||
)}
|
||||
</For>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import styles from './Header.module.scss'
|
||||
import { clsx } from 'clsx'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import { t } from '../../utils/intl'
|
||||
import { Icon } from './Icon'
|
||||
import { createSignal, onMount, Show } from 'solid-js'
|
||||
|
@ -9,7 +9,7 @@ import { ProfilePopup } from './ProfilePopup'
|
|||
import Userpic from '../Author/Userpic'
|
||||
import type { Author } from '../../graphql/types.gen'
|
||||
import { showModal, useWarningsStore } from '../../stores/ui'
|
||||
import { ClientContainer } from '../_shared/ClientContainer'
|
||||
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
|
||||
import { useSession } from '../../context/session'
|
||||
|
||||
type HeaderAuthProps = {
|
||||
|
@ -37,12 +37,12 @@ export const HeaderAuth = (props: HeaderAuthProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<ClientContainer>
|
||||
<ShowOnlyOnClient>
|
||||
<Show when={!session.loading}>
|
||||
<div class={styles.usernav}>
|
||||
<div class={clsx(styles.userControl, styles.userControl, 'col')}>
|
||||
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
||||
<a href="/create" onClick={handleClientRouteLinkClick}>
|
||||
<a href="/create">
|
||||
<span class={styles.textLabel}>{t('Create post')}</span>
|
||||
<Icon name="pencil" class={styles.icon} />
|
||||
</a>
|
||||
|
@ -68,7 +68,7 @@ export const HeaderAuth = (props: HeaderAuthProps) => {
|
|||
when={isAuthenticated()}
|
||||
fallback={
|
||||
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose, 'loginbtn')}>
|
||||
<a href="?modal=auth&mode=login" onClick={handleClientRouteLinkClick}>
|
||||
<a href="?modal=auth&mode=login">
|
||||
<span class={styles.textLabel}>{t('Enter')}</span>
|
||||
<Icon name="user-anonymous" class={styles.icon} />
|
||||
</a>
|
||||
|
@ -102,6 +102,6 @@ export const HeaderAuth = (props: HeaderAuthProps) => {
|
|||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
</ClientContainer>
|
||||
</ShowOnlyOnClient>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Icon } from './Icon'
|
|||
import './Topics.scss'
|
||||
import { t } from '../../utils/intl'
|
||||
import { locale } from '../../stores/ui'
|
||||
import { handleClientRouteLinkClick } from '../../stores/router'
|
||||
|
||||
export const NavTopics = (props: { topics: Topic[] }) => {
|
||||
const tag = (topic: Topic) =>
|
||||
|
@ -18,7 +17,7 @@ export const NavTopics = (props: { topics: Topic[] }) => {
|
|||
<For each={props.topics}>
|
||||
{(topic) => (
|
||||
<li class="item">
|
||||
<a href={`/topic/${topic.slug}`} onClick={handleClientRouteLinkClick}>
|
||||
<a href={`/topic/${topic.slug}`}>
|
||||
<span>#{tag(topic)}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -8,8 +8,6 @@ import { loadAuthor } from '../../stores/zine/authors'
|
|||
import { Loading } from '../Loading'
|
||||
|
||||
export const AuthorPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.authorArticles) && Boolean(props.author))
|
||||
|
||||
const slug = createMemo(() => {
|
||||
const { page: getPage } = useRouter()
|
||||
|
||||
|
@ -22,6 +20,10 @@ export const AuthorPage = (props: PageProps) => {
|
|||
return page.params.slug
|
||||
})
|
||||
|
||||
const [isLoaded, setIsLoaded] = createSignal(
|
||||
Boolean(props.authorArticles) && props?.author?.slug === slug()
|
||||
)
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
|
|
|
@ -8,8 +8,6 @@ import { loadTopic } from '../../stores/zine/topics'
|
|||
import { Loading } from '../Loading'
|
||||
|
||||
export const TopicPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.topicArticles) && Boolean(props.topic))
|
||||
|
||||
const slug = createMemo(() => {
|
||||
const { page: getPage } = useRouter()
|
||||
|
||||
|
@ -22,6 +20,8 @@ export const TopicPage = (props: PageProps) => {
|
|||
return page.params.slug
|
||||
})
|
||||
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.topicArticles) && props?.topic.slug === slug())
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
|
|
|
@ -40,10 +40,7 @@ export const DogmaPage = () => {
|
|||
<li>
|
||||
<b>Всегда исправляем ошибки, если мы их допустили.</b>
|
||||
Никто не безгрешен, иногда и мы ошибаемся. Заметили ошибку - отправьте{' '}
|
||||
<a href="/about/guide#editing" target="_self">
|
||||
ремарку
|
||||
</a>{' '}
|
||||
автору или напишите нам на{' '}
|
||||
<a href="/about/guide#editing">ремарку</a> автору или напишите нам на{' '}
|
||||
<a href="mailto:welcome@discours.io" target="_blank">
|
||||
welcome@discours.io
|
||||
</a>
|
||||
|
|
|
@ -67,28 +67,28 @@ export const GuidePage = () => {
|
|||
|
||||
<p>
|
||||
Дискурс — независимый журнал о культуре, науке, искусстве и обществе
|
||||
с <a href="/about/manifest">открытой редакцией</a>. У нас нет главного редактора,
|
||||
инвестора и вообще никого, кто бы принимал единоличные решения. Вместо традиционных
|
||||
иерархий Дискурс основан на принципах прямой демократии: в нашем горизонтальном
|
||||
сообществе все редакционные вопросы решаются открытым голосованием авторов журнала. Вот как
|
||||
это работает.
|
||||
с
|
||||
<a href="/about/manifest">открытой редакцией</a>. У нас нет главного редактора, инвестора
|
||||
и вообще никого, кто бы принимал единоличные решения. Вместо традиционных иерархий
|
||||
Дискурс основан на принципах прямой демократии: в нашем горизонтальном сообществе
|
||||
все редакционные вопросы решаются открытым голосованием авторов журнала. Вот как это работает.
|
||||
</p>
|
||||
<h3 id="how-it-works">Как устроен сайт Дискурса</h3>
|
||||
<p>Дискурс состоит из четырех основных разделов:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>
|
||||
<a href="/topics">Темы</a> — у нас публикуются исследования, обзоры, эссе,
|
||||
интервью, репортажи, аналитика и другие материалы о культуре, науке, искусстве
|
||||
и обществе.
|
||||
<a href="/topics">Темы</a>
|
||||
— у нас публикуются исследования, обзоры, эссе, интервью, репортажи,
|
||||
аналитика и другие материалы о культуре, науке, искусстве и обществе.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="/topic/art">Искусство</a> — здесь, например, представлены
|
||||
художественные произведения: литература, живопись, музыка, фотографии, видео. Этот раздел
|
||||
помогает прозвучать новому искусству, которое создают российские художники, писатели,
|
||||
режиссёры и музыканты.
|
||||
<a href="/topic/art">Искусство</a>
|
||||
— здесь, например, представлены художественные произведения: литература,
|
||||
живопись, музыка, фотографии, видео. Этот раздел помогает прозвучать новому искусству,
|
||||
которое создают российские художники, писатели, режиссёры и музыканты.
|
||||
</p>
|
||||
</li>
|
||||
{/*
|
||||
|
@ -118,14 +118,16 @@ export const GuidePage = () => {
|
|||
— ключевым словам, которые располагаются в конце материалов и связывают
|
||||
материалы по жанрам (например,
|
||||
<a href="/topic/interview">интервью</a>, <a href="/topic/reportage">репортажи</a>,{' '}
|
||||
<a href="/topic/essay">эссе</a>, <a href="/topic/likbez">ликбезы</a>), по тематике (
|
||||
<a href="/topic/cinema">кино</a>, <a href="/topic/philosophy">философия</a>,{' '}
|
||||
<a href="/topic/history">история</a>, <a href="/topic/absurdism">абсурдизм</a>,{' '}
|
||||
<a href="/topic/sex">секс</a> и т.д.) или в серии (как «
|
||||
<a href="/topic/zakony-mira">Законы мира</a>» или «
|
||||
<a href="/topic/za-liniey-mannergeyma">За линией Маннергейма</a>»). Темы объединяют
|
||||
сотни публикаций, помогают ориентироваться в журнале и следить за интересными
|
||||
материалами.
|
||||
<a href="/topic/essay">эссе</a>, <a href="/topic/likbez">ликбезы</a>
|
||||
), по тематике (<a href="/topic/cinema">кино</a>,{' '}
|
||||
<a href="/topic/philosophy">философия</a>, <a href="/topic/history">история</a>,{' '}
|
||||
<a href="/topic/absurdism">абсурдизм</a>, <a href="/topic/sex">секс</a> и т.д.) или
|
||||
в серии (как «
|
||||
<a href="/topic/zakony-mira">Законы мира</a>
|
||||
» или «
|
||||
<a href="/topic/za-liniey-mannergeyma">За линией Маннергейма</a>
|
||||
»). Темы объединяют сотни публикаций, помогают ориентироваться в журнале
|
||||
и следить за интересными материалами.
|
||||
</p>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -91,10 +91,11 @@ export const ManifestPage = () => {
|
|||
<p>
|
||||
Редакция Дискурса открыта для всех: у нас нет цензуры, запретных тем
|
||||
и идеологических рамок. Каждый может <a href="/create">прислать материал</a>{' '}
|
||||
в журнал и <a href="/about/guide">присоединиться к редакции</a>. Предоставляя
|
||||
трибуну для независимой журналистики и художественных проектов, мы помогаем людям
|
||||
рассказывать свои истории так, чтобы они были услышаны. Мы убеждены: чем больше голосов
|
||||
будет звучать на Дискурсе, тем громче в полифонии мнений будет слышна истина.
|
||||
в журнал и
|
||||
<a href="/about/guide">присоединиться к редакции</a>. Предоставляя трибуну для
|
||||
независимой журналистики и художественных проектов, мы помогаем людям рассказывать
|
||||
свои истории так, чтобы они были услышаны. Мы убеждены: чем больше голосов будет звучать
|
||||
на Дискурсе, тем громче в полифонии мнений будет слышна истина.
|
||||
</p>
|
||||
|
||||
<h2 class="h2" id="participation">
|
||||
|
|
|
@ -269,7 +269,7 @@ export const TermsOfUsePage = () => {
|
|||
<a href="mailto:welcome@discours.io" target="_blank">
|
||||
welcome@discours.io
|
||||
</a>{' '}
|
||||
или через форму <a href="/feedback-idea">«предложить идею»</a>.
|
||||
или через форму <a href="/connect">«предложить идею»</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -76,11 +76,7 @@ export const ThanksPage = () => {
|
|||
признательны всем, кто нас поддерживает. Ваши пожертвования — финансовый фундамент
|
||||
журнала. Благодаря вам мы развиваем платформу качественной журналистики, которая помогает
|
||||
самым разным авторам быть услышанными. Стать нашим меценатом и подписаться
|
||||
на ежемесячную поддержку проекта можно{' '}
|
||||
<a href="/about/help" target="_self">
|
||||
здесь
|
||||
</a>
|
||||
.
|
||||
на ежемесячную поддержку проекта можно <a href="/about/help">здесь</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -58,7 +58,7 @@ export const TopicCard = (props: TopicProps) => {
|
|||
</Show>
|
||||
<Show when={props.topic.pic}>
|
||||
<div class={styles.topicAvatar}>
|
||||
<a href={props.topic.slug}>
|
||||
<a href={`/topic/${props.topic.slug}`}>
|
||||
<img src={props.topic.pic} alt={props.topic.title} />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { AuthorCard } from '../Author/Card'
|
|||
import { Icon } from '../Nav/Icon'
|
||||
import { t } from '../../utils/intl'
|
||||
import { useAuthorsStore, setAuthorsSort } from '../../stores/zine/authors'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import styles from '../../styles/AllTopics.module.scss'
|
||||
import { clsx } from 'clsx'
|
||||
import { useSession } from '../../context/session'
|
||||
|
@ -70,19 +70,13 @@ export const AllAuthorsView = (props: Props) => {
|
|||
|
||||
<ul class={clsx(styles.viewSwitcher, 'view-switcher')}>
|
||||
<li classList={{ selected: searchParams().by === 'shouts' }}>
|
||||
<a href="/authors?by=shouts" onClick={handleClientRouteLinkClick}>
|
||||
{t('By shouts')}
|
||||
</a>
|
||||
<a href="/authors?by=shouts">{t('By shouts')}</a>
|
||||
</li>
|
||||
<li classList={{ selected: searchParams().by === 'rating' }}>
|
||||
<a href="/authors?by=rating" onClick={handleClientRouteLinkClick}>
|
||||
{t('By rating')}
|
||||
</a>
|
||||
<a href="/authors?by=rating">{t('By rating')}</a>
|
||||
</li>
|
||||
<li classList={{ selected: !searchParams().by || searchParams().by === 'name' }}>
|
||||
<a href="/authors" onClick={handleClientRouteLinkClick}>
|
||||
{t('By alphabet')}
|
||||
</a>
|
||||
<a href="/authors">{t('By alphabet')}</a>
|
||||
</li>
|
||||
<li class="view-switcher__search">
|
||||
<a href="/authors/search">
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { Topic } from '../../graphql/types.gen'
|
|||
import { Icon } from '../Nav/Icon'
|
||||
import { t } from '../../utils/intl'
|
||||
import { setTopicsSort, useTopicsStore } from '../../stores/zine/topics'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import { TopicCard } from '../Topic/Card'
|
||||
import styles from '../../styles/AllTopics.module.scss'
|
||||
import { clsx } from 'clsx'
|
||||
|
@ -69,14 +69,10 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
|
|||
|
||||
<ul class={clsx(styles.viewSwitcher, 'view-switcher')}>
|
||||
<li classList={{ selected: searchParams().by === 'shouts' || !searchParams().by }}>
|
||||
<a href="/topics?by=shouts" onClick={handleClientRouteLinkClick}>
|
||||
{t('By shouts')}
|
||||
</a>
|
||||
<a href="/topics?by=shouts">{t('By shouts')}</a>
|
||||
</li>
|
||||
<li classList={{ selected: searchParams().by === 'authors' }}>
|
||||
<a href="/topics?by=authors" onClick={handleClientRouteLinkClick}>
|
||||
{t('By authors')}
|
||||
</a>
|
||||
<a href="/topics?by=authors">{t('By authors')}</a>
|
||||
</li>
|
||||
<li classList={{ selected: searchParams().by === 'title' }}>
|
||||
<a
|
||||
|
|
|
@ -18,7 +18,7 @@ type AuthorProps = {
|
|||
authorArticles: Shout[]
|
||||
author: Author
|
||||
authorSlug: string
|
||||
// FIXME author topics fro server
|
||||
// FIXME author topics from server
|
||||
// topics: Topic[]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Editor } from '../EditorNew/Editor'
|
||||
import { ClientContainer } from '../_shared/ClientContainer'
|
||||
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
|
||||
|
||||
export const CreateView = () => {
|
||||
return (
|
||||
<ClientContainer>
|
||||
<ShowOnlyOnClient>
|
||||
<Editor />
|
||||
</ClientContainer>
|
||||
</ShowOnlyOnClient>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -76,13 +76,13 @@ export const FeedView = () => {
|
|||
</li>
|
||||
</Show>
|
||||
<li>
|
||||
<a href="?by=views">{t('Most read')}</a>
|
||||
<a href="/feed/?by=views">{t('Most read')}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?by=rating">{t('Top rated')}</a>
|
||||
<a href="/feed/?by=rating">{t('Top rated')}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?by=comments">{t('Most commented')}</a>
|
||||
<a href="/feed/?by=comments">{t('Most commented')}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -93,7 +93,7 @@ export const FeedView = () => {
|
|||
|
||||
<div class={stylesBeside.besideColumnTitle}>
|
||||
<h4>{t('Popular authors')}</h4>
|
||||
<a href="/user/list">
|
||||
<a href="/authors">
|
||||
{t('All authors')}
|
||||
<Icon name="arrow-right" />
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import '../../styles/FeedSettings.scss'
|
||||
import { t } from '../../utils/intl'
|
||||
import { handleClientRouteLinkClick } from '../../stores/router'
|
||||
|
||||
// type FeedSettingsSearchParams = {
|
||||
// by: '' | 'topics' | 'authors' | 'reacted'
|
||||
|
@ -13,9 +12,7 @@ export const FeedSettingsView = () => {
|
|||
|
||||
<ul class="view-switcher">
|
||||
<li class="selected">
|
||||
<a href="?by=topics" onClick={handleClientRouteLinkClick}>
|
||||
{t('topics')}
|
||||
</a>
|
||||
<a href="?by=topics">{t('topics')}</a>
|
||||
</li>
|
||||
{/*<li>
|
||||
<a href="?by=collections" onClick={() => setBy('collections')}>
|
||||
|
@ -23,14 +20,10 @@ export const FeedSettingsView = () => {
|
|||
</a>
|
||||
</li>*/}
|
||||
<li>
|
||||
<a href="?by=authors" onClick={handleClientRouteLinkClick}>
|
||||
{t('authors')}
|
||||
</a>
|
||||
<a href="?by=authors">{t('authors')}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?by=reacted" onClick={handleClientRouteLinkClick}>
|
||||
{t('reactions')}
|
||||
</a>
|
||||
<a href="?by=reacted">{t('reactions')}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import type { Shout } from '../../graphql/types.gen'
|
|||
import { ArticleCard } from '../Feed/Card'
|
||||
import { t } from '../../utils/intl'
|
||||
import { useArticlesStore, loadSearchResults } from '../../stores/zine/articles'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
|
||||
import { useRouter } from '../../stores/router'
|
||||
|
||||
type SearchPageSearchParams = {
|
||||
by: '' | 'relevance' | 'rating'
|
||||
|
@ -51,18 +51,14 @@ export const SearchView = (props: Props) => {
|
|||
selected: searchParams().by === 'relevance'
|
||||
}}
|
||||
>
|
||||
<a href="?by=relevance" onClick={handleClientRouteLinkClick}>
|
||||
{t('By relevance')}
|
||||
</a>
|
||||
<a href="?by=relevance">{t('By relevance')}</a>
|
||||
</li>
|
||||
<li
|
||||
classList={{
|
||||
selected: searchParams().by === 'rating'
|
||||
}}
|
||||
>
|
||||
<a href="?by=rating" onClick={handleClientRouteLinkClick}>
|
||||
{t('Top rated')}
|
||||
</a>
|
||||
<a href="?by=rating">{t('Top rated')}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import type { JSX } from 'solid-js'
|
||||
import { createSignal, onMount, Show } from 'solid-js'
|
||||
|
||||
// show children only on client side
|
||||
// usage of isServer causing hydration errors
|
||||
export const ClientContainer = (props: { children: JSX.Element }) => {
|
||||
const [isMounted, setIsMounted] = createSignal(false)
|
||||
|
||||
onMount(() => setIsMounted(true))
|
||||
|
||||
return <Show when={isMounted()}>{props.children}</Show>
|
||||
}
|
12
src/components/_shared/ShowOnlyOnClient.tsx
Normal file
12
src/components/_shared/ShowOnlyOnClient.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import type { JSX } from 'solid-js'
|
||||
import { createSignal, onMount, Show } from 'solid-js'
|
||||
|
||||
const [isClient, setIsClient] = createSignal(false)
|
||||
|
||||
// show children only on client side
|
||||
// usage of isServer causing hydration errors
|
||||
export const ShowOnlyOnClient = (props: { children: JSX.Element }) => {
|
||||
onMount(() => setIsClient(true))
|
||||
|
||||
return <Show when={isClient()}>{props.children}</Show>
|
||||
}
|
|
@ -41,6 +41,17 @@ export type AuthorStat = {
|
|||
rating?: Maybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type AuthorsBy = {
|
||||
createdAt?: InputMaybe<Scalars['DateTime']>
|
||||
days?: InputMaybe<Scalars['Int']>
|
||||
lastSeen?: InputMaybe<Scalars['DateTime']>
|
||||
name?: InputMaybe<Scalars['String']>
|
||||
order?: InputMaybe<Scalars['String']>
|
||||
slug?: InputMaybe<Scalars['String']>
|
||||
stat?: InputMaybe<Scalars['String']>
|
||||
topic?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type Chat = {
|
||||
admins?: Maybe<Array<Maybe<User>>>
|
||||
createdAt: Scalars['Int']
|
||||
|
@ -88,12 +99,6 @@ export type Collection = {
|
|||
title: Scalars['String']
|
||||
}
|
||||
|
||||
export type CollectionInput = {
|
||||
desc?: InputMaybe<Scalars['String']>
|
||||
pic?: InputMaybe<Scalars['String']>
|
||||
title: Scalars['String']
|
||||
}
|
||||
|
||||
export type Community = {
|
||||
createdAt: Scalars['DateTime']
|
||||
createdBy: User
|
||||
|
@ -104,12 +109,6 @@ export type Community = {
|
|||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type CommunityInput = {
|
||||
desc?: InputMaybe<Scalars['String']>
|
||||
pic?: InputMaybe<Scalars['String']>
|
||||
title: Scalars['String']
|
||||
}
|
||||
|
||||
export enum FollowingEntity {
|
||||
Author = 'AUTHOR',
|
||||
Community = 'COMMUNITY',
|
||||
|
@ -133,25 +132,28 @@ export enum MessageStatus {
|
|||
Updated = 'UPDATED'
|
||||
}
|
||||
|
||||
export type MessagesBy = {
|
||||
author?: InputMaybe<Scalars['String']>
|
||||
body?: InputMaybe<Scalars['String']>
|
||||
chat?: InputMaybe<Scalars['String']>
|
||||
days?: InputMaybe<Scalars['Int']>
|
||||
order?: InputMaybe<Scalars['String']>
|
||||
stat?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type Mutation = {
|
||||
confirmEmail: AuthResult
|
||||
createChat: Result
|
||||
createCollection: Result
|
||||
createCommunity: Result
|
||||
createMessage: Result
|
||||
createReaction: Result
|
||||
createShout: Result
|
||||
createTopic: Result
|
||||
deleteChat: Result
|
||||
deleteCollection: Result
|
||||
deleteCommunity: Result
|
||||
deleteMessage: Result
|
||||
deleteReaction: Result
|
||||
deleteShout: Result
|
||||
destroyTopic: Result
|
||||
enterChat: Result
|
||||
follow: Result
|
||||
incrementView: Result
|
||||
inviteAuthor: Result
|
||||
inviteChat: Result
|
||||
markAsRead: Result
|
||||
|
@ -162,9 +164,8 @@ export type Mutation = {
|
|||
sendLink: Result
|
||||
unfollow: Result
|
||||
updateChat: Result
|
||||
updateCollection: Result
|
||||
updateCommunity: Result
|
||||
updateMessage: Result
|
||||
updateOnlineStatus: Result
|
||||
updateProfile: Result
|
||||
updateReaction: Result
|
||||
updateShout: Result
|
||||
|
@ -180,14 +181,6 @@ export type MutationCreateChatArgs = {
|
|||
title?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type MutationCreateCollectionArgs = {
|
||||
collection: CollectionInput
|
||||
}
|
||||
|
||||
export type MutationCreateCommunityArgs = {
|
||||
community: CommunityInput
|
||||
}
|
||||
|
||||
export type MutationCreateMessageArgs = {
|
||||
body: Scalars['String']
|
||||
chatId: Scalars['String']
|
||||
|
@ -210,14 +203,6 @@ export type MutationDeleteChatArgs = {
|
|||
chatId: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationDeleteCollectionArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationDeleteCommunityArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationDeleteMessageArgs = {
|
||||
chatId: Scalars['String']
|
||||
id: Scalars['Int']
|
||||
|
@ -235,19 +220,11 @@ export type MutationDestroyTopicArgs = {
|
|||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationEnterChatArgs = {
|
||||
chatId: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationFollowArgs = {
|
||||
slug: Scalars['String']
|
||||
what: FollowingEntity
|
||||
}
|
||||
|
||||
export type MutationIncrementViewArgs = {
|
||||
shout: Scalars['String']
|
||||
}
|
||||
|
||||
export type MutationInviteAuthorArgs = {
|
||||
author: Scalars['String']
|
||||
shout: Scalars['String']
|
||||
|
@ -293,14 +270,6 @@ export type MutationUpdateChatArgs = {
|
|||
chat: ChatInput
|
||||
}
|
||||
|
||||
export type MutationUpdateCollectionArgs = {
|
||||
collection: CollectionInput
|
||||
}
|
||||
|
||||
export type MutationUpdateCommunityArgs = {
|
||||
community: CommunityInput
|
||||
}
|
||||
|
||||
export type MutationUpdateMessageArgs = {
|
||||
body: Scalars['String']
|
||||
chatId: Scalars['String']
|
||||
|
@ -348,98 +317,66 @@ export type ProfileInput = {
|
|||
|
||||
export type Query = {
|
||||
authorsAll: Array<Maybe<Author>>
|
||||
collectionsAll: Array<Maybe<Collection>>
|
||||
getAuthor: User
|
||||
getCollabs: Array<Maybe<Collab>>
|
||||
getCommunities: Array<Maybe<Community>>
|
||||
getCommunity: Community
|
||||
getShoutBySlug: Shout
|
||||
getTopic: Topic
|
||||
getUserCollections: Array<Maybe<Collection>>
|
||||
getUserRoles: Array<Maybe<Role>>
|
||||
getUsersBySlugs: Array<Maybe<Author>>
|
||||
isEmailUsed: Scalars['Boolean']
|
||||
loadAuthorsBy: Array<Maybe<Author>>
|
||||
loadChats: Result
|
||||
loadMessages: Result
|
||||
loadMessagesBy: Result
|
||||
loadReactionsBy: Array<Maybe<Reaction>>
|
||||
loadShoutsBy: Array<Maybe<Shout>>
|
||||
markdownBody: Scalars['String']
|
||||
reactionsByAuthor: Array<Maybe<Reaction>>
|
||||
reactionsForShouts: Array<Maybe<Reaction>>
|
||||
recentAll: Array<Maybe<Shout>>
|
||||
recentCandidates: Array<Maybe<Shout>>
|
||||
recentCommented: Array<Maybe<Shout>>
|
||||
recentLayoutShouts: Array<Maybe<Shout>>
|
||||
recentPublished: Array<Maybe<Shout>>
|
||||
recentReacted: Array<Maybe<Shout>>
|
||||
searchChats: Result
|
||||
searchMessages: Result
|
||||
searchQuery?: Maybe<Array<Maybe<Shout>>>
|
||||
searchUsers: Result
|
||||
shoutsByAuthors: Array<Maybe<Shout>>
|
||||
shoutsByCollection: Array<Maybe<Shout>>
|
||||
shoutsByCommunities: Array<Maybe<Shout>>
|
||||
shoutsByLayout: Array<Maybe<Shout>>
|
||||
shoutsByTopics: Array<Maybe<Shout>>
|
||||
shoutsForFeed: Array<Maybe<Shout>>
|
||||
signIn: AuthResult
|
||||
signOut: AuthResult
|
||||
topAuthors: Array<Maybe<Author>>
|
||||
topCommented: Array<Maybe<Shout>>
|
||||
topLayoutShouts: Array<Maybe<Shout>>
|
||||
topMonth: Array<Maybe<Shout>>
|
||||
topMonthLayoutShouts: Array<Maybe<Shout>>
|
||||
topOverall: Array<Maybe<Shout>>
|
||||
topPublished: Array<Maybe<Shout>>
|
||||
topicsAll: Array<Maybe<Topic>>
|
||||
topicsByAuthor: Array<Maybe<Topic>>
|
||||
topicsByCommunity: Array<Maybe<Topic>>
|
||||
topicsRandom: Array<Maybe<Topic>>
|
||||
userFollowedAuthors: Array<Maybe<Author>>
|
||||
userFollowedCommunities: Array<Maybe<Community>>
|
||||
userFollowedTopics: Array<Maybe<Topic>>
|
||||
userFollowers: Array<Maybe<Author>>
|
||||
userReactedShouts: Array<Maybe<Shout>>
|
||||
}
|
||||
|
||||
export type QueryGetAuthorArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryGetCommunityArgs = {
|
||||
slug?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type QueryGetShoutBySlugArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryGetTopicArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryGetUserCollectionsArgs = {
|
||||
author: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryGetUserRolesArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryGetUsersBySlugsArgs = {
|
||||
slugs: Array<InputMaybe<Scalars['String']>>
|
||||
}
|
||||
|
||||
export type QueryIsEmailUsedArgs = {
|
||||
email: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryLoadAuthorsByArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
by?: InputMaybe<AuthorsBy>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryLoadChatsArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryLoadMessagesArgs = {
|
||||
export type QueryLoadMessagesByArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
chatId: Scalars['String']
|
||||
by: MessagesBy
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryLoadReactionsByArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
by: ReactionBy
|
||||
limit?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryLoadShoutsByArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
by?: InputMaybe<ShoutsBy>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
|
@ -447,106 +384,10 @@ export type QueryMarkdownBodyArgs = {
|
|||
body: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryReactionsByAuthorArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryReactionsForShoutsArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
shouts: Array<InputMaybe<Scalars['String']>>
|
||||
}
|
||||
|
||||
export type QueryRecentAllArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryRecentCandidatesArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryRecentCommentedArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryRecentLayoutShoutsArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
layout: Scalars['String']
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryRecentPublishedArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryRecentReactedArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QuerySearchChatsArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
q: Scalars['String']
|
||||
}
|
||||
|
||||
export type QuerySearchMessagesArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
q: Scalars['String']
|
||||
}
|
||||
|
||||
export type QuerySearchQueryArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
q?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type QuerySearchUsersArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
q: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryShoutsByAuthorsArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
slugs: Array<InputMaybe<Scalars['String']>>
|
||||
}
|
||||
|
||||
export type QueryShoutsByCollectionArgs = {
|
||||
collection: Scalars['String']
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryShoutsByCommunitiesArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
slugs: Array<InputMaybe<Scalars['String']>>
|
||||
}
|
||||
|
||||
export type QueryShoutsByLayoutArgs = {
|
||||
amount: Scalars['Int']
|
||||
layout?: InputMaybe<Scalars['String']>
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryShoutsByTopicsArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
slugs: Array<InputMaybe<Scalars['String']>>
|
||||
}
|
||||
|
||||
export type QueryShoutsForFeedArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
query: Scalars['String']
|
||||
}
|
||||
|
||||
export type QuerySignInArgs = {
|
||||
|
@ -555,44 +396,6 @@ export type QuerySignInArgs = {
|
|||
password?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type QueryTopAuthorsArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryTopCommentedArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryTopLayoutShoutsArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
layout: Scalars['String']
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryTopMonthArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryTopMonthLayoutShoutsArgs = {
|
||||
amount?: InputMaybe<Scalars['Int']>
|
||||
layout: Scalars['String']
|
||||
offset?: InputMaybe<Scalars['Int']>
|
||||
}
|
||||
|
||||
export type QueryTopOverallArgs = {
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryTopPublishedArgs = {
|
||||
daysago: Scalars['Int']
|
||||
limit: Scalars['Int']
|
||||
offset: Scalars['Int']
|
||||
}
|
||||
|
||||
export type QueryTopicsByAuthorArgs = {
|
||||
author: Scalars['String']
|
||||
}
|
||||
|
@ -609,10 +412,6 @@ export type QueryUserFollowedAuthorsArgs = {
|
|||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryUserFollowedCommunitiesArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryUserFollowedTopicsArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
@ -621,10 +420,6 @@ export type QueryUserFollowersArgs = {
|
|||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type QueryUserReactedShoutsArgs = {
|
||||
slug: Scalars['String']
|
||||
}
|
||||
|
||||
export type Rating = {
|
||||
rater: Scalars['String']
|
||||
value: Scalars['Int']
|
||||
|
@ -647,6 +442,16 @@ export type Reaction = {
|
|||
updatedAt?: Maybe<Scalars['DateTime']>
|
||||
}
|
||||
|
||||
export type ReactionBy = {
|
||||
author?: InputMaybe<Scalars['String']>
|
||||
body?: InputMaybe<Scalars['String']>
|
||||
days?: InputMaybe<Scalars['Int']>
|
||||
order?: InputMaybe<Scalars['String']>
|
||||
shout?: InputMaybe<Scalars['String']>
|
||||
stat?: InputMaybe<Scalars['String']>
|
||||
topic?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type ReactionInput = {
|
||||
body?: InputMaybe<Scalars['String']>
|
||||
kind: Scalars['Int']
|
||||
|
@ -757,6 +562,19 @@ export type ShoutInput = {
|
|||
visibleForUsers?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
|
||||
}
|
||||
|
||||
export type ShoutsBy = {
|
||||
author?: InputMaybe<Scalars['String']>
|
||||
body?: InputMaybe<Scalars['String']>
|
||||
days?: InputMaybe<Scalars['Int']>
|
||||
layout?: InputMaybe<Scalars['String']>
|
||||
order?: InputMaybe<Scalars['String']>
|
||||
slug?: InputMaybe<Scalars['String']>
|
||||
stat?: InputMaybe<Scalars['String']>
|
||||
title?: InputMaybe<Scalars['String']>
|
||||
topic?: InputMaybe<Scalars['String']>
|
||||
visibility?: InputMaybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type Stat = {
|
||||
commented?: Maybe<Scalars['Int']>
|
||||
ranking?: Maybe<Scalars['Int']>
|
||||
|
|
|
@ -59,7 +59,7 @@ const routerStore = createRouter<Routes>(
|
|||
|
||||
export const router = routerStore
|
||||
|
||||
export const handleClientRouteLinkClick = (event) => {
|
||||
const handleClientRouteLinkClick = (event) => {
|
||||
const link = event.target.closest('a')
|
||||
if (
|
||||
link &&
|
||||
|
@ -92,6 +92,10 @@ export const initRouter = (pathname: string, search: string) => {
|
|||
routerStore.open(pathname)
|
||||
const params = Object.fromEntries(new URLSearchParams(search))
|
||||
searchParamsStore.open(params)
|
||||
|
||||
if (!isServer) {
|
||||
document.addEventListener('click', handleClientRouteLinkClick)
|
||||
}
|
||||
}
|
||||
|
||||
if (!isServer) {
|
||||
|
|
|
@ -53,7 +53,7 @@ const topTopics = createMemo(() => {
|
|||
})
|
||||
|
||||
const addTopics = (...args: Topic[][]) => {
|
||||
const allTopics = args.flatMap((topics) => topics || [])
|
||||
const allTopics = args.flatMap((topics) => (topics || []).filter(Boolean))
|
||||
|
||||
const newTopicEntities = allTopics.reduce((acc, topic) => {
|
||||
acc[topic.slug] = topic
|
||||
|
|
Loading…
Reference in New Issue
Block a user