Merge pull request #58 from Discours/client-routing-minor-fixes
ClientContainer -> ShowOnlyOnClient, topic and author page fixes
This commit is contained in:
commit
ee06ab54d2
10965
pnpm-lock.yaml
10965
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -34,7 +34,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" class={styles.icon} />
|
||||
</a>
|
||||
|
|
|
@ -6,7 +6,6 @@ import { translit } from '../../utils/ru2en'
|
|||
import { Icon } from '../_shared/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'
|
||||
|
||||
|
@ -115,7 +114,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 '../_shared/Icon'
|
||||
import { createSignal, 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 '../_shared/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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -60,7 +60,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 '../_shared/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 '../_shared/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 = {
|
|||
shouts: 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>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -84,13 +84,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>
|
||||
|
||||
|
@ -101,7 +101,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 = (_props) => {
|
|||
|
||||
<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 = (_props) => {
|
|||
</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, loadShoutsBy } from '../../stores/zine/articles'
|
||||
import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
|
||||
import { useRouter } from '../../stores/router'
|
||||
|
||||
type SearchPageSearchParams = {
|
||||
by: '' | 'relevance' | 'rating'
|
||||
|
@ -19,7 +19,7 @@ export const SearchView = (props: Props) => {
|
|||
const { sortedArticles } = useArticlesStore({ shouts: props.results })
|
||||
const [getQuery, setQuery] = createSignal(props.query)
|
||||
|
||||
const { searchParams } = useRouter<SearchPageSearchParams>()
|
||||
const { searchParams, handleClientRouteLinkClick } = useRouter<SearchPageSearchParams>()
|
||||
|
||||
const handleQueryChange = (ev) => {
|
||||
setQuery(ev.target.value)
|
||||
|
@ -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>
|
||||
}
|
|
@ -63,7 +63,7 @@ const routerStore = createRouter<Routes>(
|
|||
|
||||
export const router = routerStore
|
||||
|
||||
export const handleClientRouteLinkClick = (event) => {
|
||||
const handleClientRouteLinkClick = (event) => {
|
||||
const link = event.target.closest('a')
|
||||
if (
|
||||
link &&
|
||||
|
@ -96,6 +96,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) {
|
||||
|
@ -125,6 +129,7 @@ export const useRouter = <TSearchParams extends Record<string, string> = Record<
|
|||
return {
|
||||
page,
|
||||
searchParams,
|
||||
changeSearchParam
|
||||
changeSearchParam,
|
||||
handleClientRouteLinkClick
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
33
yarn.lock
33
yarn.lock
|
@ -41,9 +41,9 @@
|
|||
node-fetch "^2.6.1"
|
||||
|
||||
"@astrojs/compiler@^0.27.0 || ^0.28.0 || ^0.29.0", "@astrojs/compiler@^0.29.15", "@astrojs/compiler@^0.29.3":
|
||||
version "0.29.16"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/compiler/-/compiler-0.29.16.tgz#453d7f4da6c2d0935743f4b7075141f619ac0a05"
|
||||
integrity sha512-1CCf+dktc8IQCdmsNNSIor3rcJE5OIirFnFtQWp1VUxqCacefqRRlsl9lH7JcKKpRvz1taL43yHYJP8dxNfVww==
|
||||
version "0.29.17"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/compiler/-/compiler-0.29.17.tgz#5c65e18fd5dde9620dcc1794a858609b66408215"
|
||||
integrity sha512-6ZbRGVunUMHxROD9Cleqkrfrj/kM9o43nLVwycdxCexCB5G372evy2ZM46LhaG/k5B5yC0PByNHTaGny0ll3iQ==
|
||||
|
||||
"@astrojs/language-server@^0.28.3":
|
||||
version "0.28.3"
|
||||
|
@ -138,12 +138,13 @@
|
|||
which-pm-runs "^1.1.0"
|
||||
|
||||
"@astrojs/vercel@^2.3.3":
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/vercel/-/vercel-2.3.3.tgz#354aebd3e504d57d9e7794a7e8c5229885d92928"
|
||||
integrity sha512-gdYf98Oii8MEfRHyX6Uwsbvx/rjimZV75qPSMbcGPFUCteshENFvtUAk5jMJvJNrDh/Cxjt4akTd4/llbvWBeQ==
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/vercel/-/vercel-2.3.4.tgz#79e3658786bebfa57d1c0efdec1b4db35ee3f4c4"
|
||||
integrity sha512-1mrPdlb68Y+DPtDpOfuRlene9F2t+wICXDLoG+bII9ryURxTYCReV5JQ1uwlKQ3yizQLIKIzm0rs5yp+K5FWbw==
|
||||
dependencies:
|
||||
"@astrojs/webapi" "^1.1.1"
|
||||
"@vercel/nft" "^0.22.1"
|
||||
fast-glob "^3.2.11"
|
||||
|
||||
"@astrojs/webapi@^1.1.1":
|
||||
version "1.1.1"
|
||||
|
@ -1765,9 +1766,9 @@
|
|||
integrity sha512-1eZA1/HYOhmlZ9LrrGot+LUi/ypO2NXqfB+9F1WY98dGNDMz9pG9k+X7kg2YDJTUHDGbzY7WrsBRyAE8LurE7Q==
|
||||
|
||||
"@solid-primitives/resize-observer@^2.0.5":
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@solid-primitives/resize-observer/-/resize-observer-2.0.6.tgz#2086c92d3a5f82512ecbc47fceff02eac272bd2c"
|
||||
integrity sha512-PbYmBFJBx1/WcrTZepcr6fABOrUP6CeXxehy2AKPCJInX3LKQ/elHLsM1g6KwVbvqpZ0aQ3a/3I7sRYk6BSrpw==
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@solid-primitives/resize-observer/-/resize-observer-2.0.7.tgz#0f909ed58d5fd7ec59b2fee15ddafdd28fdce4c8"
|
||||
integrity sha512-/RtCTs61ACdsCKJodNTgnKA05CI09dkg7usAb5jg14L6mzwTNWWdZbXtbYsUlD+kh1/1j+BKxp6VtkbpgJE5yQ==
|
||||
dependencies:
|
||||
"@solid-primitives/event-listener" "^2.2.4"
|
||||
"@solid-primitives/rootless" "^1.2.1"
|
||||
|
@ -2579,9 +2580,9 @@ astro-eslint-parser@^0.9.0:
|
|||
espree "^9.0.0"
|
||||
|
||||
astro@^1.6.8:
|
||||
version "1.6.8"
|
||||
resolved "https://registry.yarnpkg.com/astro/-/astro-1.6.8.tgz#46ab77d8e968088faf8bcc2e77d2856cb1fe0bdd"
|
||||
integrity sha512-+kOj8s2fguCFCim9he6fl9iugIHrmAl7BmfNXdTdC9zU30VYV162HF5eRJyMlY5hGuDn3GvAoaNSzCMnybVsFQ==
|
||||
version "1.6.9"
|
||||
resolved "https://registry.yarnpkg.com/astro/-/astro-1.6.9.tgz#08d7aed72168f8f45fc46e3ac47dd1a8ac0e2bbc"
|
||||
integrity sha512-KXFKXobe8MIYl4gduUPLcAazMz+thox6N1pOv3F3QMbJS5rMRXkWloVK/6XebBO7p3DYkOfOGB4qA9ijTc4ftA==
|
||||
dependencies:
|
||||
"@astrojs/compiler" "^0.29.15"
|
||||
"@astrojs/language-server" "^0.28.3"
|
||||
|
@ -2640,8 +2641,8 @@ astro@^1.6.8:
|
|||
typescript "*"
|
||||
unist-util-visit "^4.1.0"
|
||||
vfile "^5.3.2"
|
||||
vite "~3.2.1"
|
||||
vitefu "^0.2.0"
|
||||
vite "~3.2.4"
|
||||
vitefu "^0.2.1"
|
||||
yargs-parser "^21.0.1"
|
||||
zod "^3.17.3"
|
||||
|
||||
|
@ -9703,7 +9704,7 @@ vfile@^5.0.0, vfile@^5.3.2:
|
|||
unist-util-stringify-position "^3.0.0"
|
||||
vfile-message "^3.0.0"
|
||||
|
||||
vite@^3.2.4, vite@~3.2.1:
|
||||
vite@^3.2.4, vite@~3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.4.tgz#d8c7892dd4268064e04fffbe7d866207dd24166e"
|
||||
integrity sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==
|
||||
|
@ -9715,7 +9716,7 @@ vite@^3.2.4, vite@~3.2.1:
|
|||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vitefu@^0.2.0:
|
||||
vitefu@^0.2.0, vitefu@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vitefu/-/vitefu-0.2.1.tgz#9dcd78737c77b366206706dac2403a751903907d"
|
||||
integrity sha512-clkvXTAeUf+XQKm3bhWUhT4pye+3acm6YCTGaWhxxIvZZ/QjnA3JA8Zud+z/mO5y5XYvJJhevs5Sjkv/FI8nRw==
|
||||
|
|
Loading…
Reference in New Issue
Block a user