Feature/unrated (#334)
* Rate first markup * WIP * lint * unrated articles + random top fixes --------- Co-authored-by: ilya-bkv <i.yablokov@ccmp.me> Co-authored-by: Igor Lobanov <igor.lobanov@onetwotrip.com>
This commit is contained in:
parent
e5846deab7
commit
d2977b9b21
|
@ -41,6 +41,7 @@
|
||||||
"Back": "Back",
|
"Back": "Back",
|
||||||
"Back to editor": "Back to editor",
|
"Back to editor": "Back to editor",
|
||||||
"Back to main page": "Back to main page",
|
"Back to main page": "Back to main page",
|
||||||
|
"Be the first to rate": "Be the first to rate",
|
||||||
"Become an author": "Become an author",
|
"Become an author": "Become an author",
|
||||||
"Bold": "Bold",
|
"Bold": "Bold",
|
||||||
"Bookmarked": "Saved",
|
"Bookmarked": "Saved",
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
"Back": "Назад",
|
"Back": "Назад",
|
||||||
"Back to editor": "Вернуться в редактор",
|
"Back to editor": "Вернуться в редактор",
|
||||||
"Back to main page": "Вернуться на главную",
|
"Back to main page": "Вернуться на главную",
|
||||||
|
"Be the first to rate": "Оцените первым",
|
||||||
"Become an author": "Стать автором",
|
"Become an author": "Стать автором",
|
||||||
"Bold": "Жирный",
|
"Bold": "Жирный",
|
||||||
"Bookmarked": "Сохранено",
|
"Bookmarked": "Сохранено",
|
||||||
|
|
|
@ -46,7 +46,7 @@ export type ArticleCardProps = {
|
||||||
withViewed?: boolean
|
withViewed?: boolean
|
||||||
noAuthorLink?: boolean
|
noAuthorLink?: boolean
|
||||||
}
|
}
|
||||||
desktopCoverSize: 'XS' | 'S' | 'M' | 'L'
|
desktopCoverSize?: 'XS' | 'S' | 'M' | 'L'
|
||||||
article: Shout
|
article: Shout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,12 @@ import { clsx } from 'clsx'
|
||||||
import { createEffect, createMemo, createSignal, For, on, onCleanup, onMount, Show } from 'solid-js'
|
import { createEffect, createMemo, createSignal, For, on, onCleanup, onMount, Show } from 'solid-js'
|
||||||
|
|
||||||
import { useLocalize } from '../../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
import { LoadRandomTopShoutsParams, LoadShoutsOptions, Shout } from '../../../graphql/types.gen'
|
import {
|
||||||
|
LoadRandomTopShoutsParams,
|
||||||
|
LoadShoutsFilters,
|
||||||
|
LoadShoutsOptions,
|
||||||
|
Shout,
|
||||||
|
} from '../../../graphql/types.gen'
|
||||||
import { LayoutType } from '../../../pages/types'
|
import { LayoutType } from '../../../pages/types'
|
||||||
import { router } from '../../../stores/router'
|
import { router } from '../../../stores/router'
|
||||||
import { loadShouts, resetSortedArticles, useArticlesStore } from '../../../stores/zine/articles'
|
import { loadShouts, resetSortedArticles, useArticlesStore } from '../../../stores/zine/articles'
|
||||||
|
@ -24,7 +29,7 @@ type Props = {
|
||||||
layout: LayoutType
|
layout: LayoutType
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PRERENDERED_ARTICLES_COUNT = 32
|
export const PRERENDERED_ARTICLES_COUNT = 24
|
||||||
const LOAD_MORE_PAGE_SIZE = 16
|
const LOAD_MORE_PAGE_SIZE = 16
|
||||||
|
|
||||||
export const Expo = (props: Props) => {
|
export const Expo = (props: Props) => {
|
||||||
|
@ -40,15 +45,26 @@ export const Expo = (props: Props) => {
|
||||||
shouts: isLoaded() ? props.shouts : [],
|
shouts: isLoaded() ? props.shouts : [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const getLoadShoutsFilters = (filters: LoadShoutsFilters = {}): LoadShoutsFilters => {
|
||||||
|
const result = { ...filters }
|
||||||
|
|
||||||
|
if (props.layout) {
|
||||||
|
filters.layout = props.layout
|
||||||
|
} else {
|
||||||
|
filters.excludeLayout = 'article'
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
const loadMore = async (count: number) => {
|
const loadMore = async (count: number) => {
|
||||||
saveScrollPosition()
|
saveScrollPosition()
|
||||||
const options: LoadShoutsOptions = {
|
const options: LoadShoutsOptions = {
|
||||||
|
filters: getLoadShoutsFilters(),
|
||||||
limit: count,
|
limit: count,
|
||||||
offset: sortedArticles().length,
|
offset: sortedArticles().length,
|
||||||
}
|
}
|
||||||
|
|
||||||
options.filters = props.layout ? { layout: props.layout } : { excludeLayout: 'article' }
|
|
||||||
|
|
||||||
const { hasMore } = await loadShouts(options)
|
const { hasMore } = await loadShouts(options)
|
||||||
setIsLoadMoreButtonVisible(hasMore)
|
setIsLoadMoreButtonVisible(hasMore)
|
||||||
restoreScrollPosition()
|
restoreScrollPosition()
|
||||||
|
@ -56,13 +72,10 @@ export const Expo = (props: Props) => {
|
||||||
|
|
||||||
const loadRandomTopArticles = async () => {
|
const loadRandomTopArticles = async () => {
|
||||||
const params: LoadRandomTopShoutsParams = {
|
const params: LoadRandomTopShoutsParams = {
|
||||||
filters: {
|
filters: getLoadShoutsFilters(),
|
||||||
visibility: 'public',
|
|
||||||
},
|
|
||||||
limit: 10,
|
limit: 10,
|
||||||
fromRandomCount: 100,
|
fromRandomCount: 100,
|
||||||
}
|
}
|
||||||
params.filters = props.layout ? { layout: props.layout } : { excludeLayout: 'article' }
|
|
||||||
|
|
||||||
const result = await apiClient.getRandomTopShouts(params)
|
const result = await apiClient.getRandomTopShouts(params)
|
||||||
setRandomTopArticles(result)
|
setRandomTopArticles(result)
|
||||||
|
@ -73,14 +86,10 @@ export const Expo = (props: Props) => {
|
||||||
const fromDate = getServerDate(new Date(now.setMonth(now.getMonth() - 1)))
|
const fromDate = getServerDate(new Date(now.setMonth(now.getMonth() - 1)))
|
||||||
|
|
||||||
const params: LoadRandomTopShoutsParams = {
|
const params: LoadRandomTopShoutsParams = {
|
||||||
filters: {
|
filters: getLoadShoutsFilters({ fromDate }),
|
||||||
visibility: 'public',
|
|
||||||
fromDate,
|
|
||||||
},
|
|
||||||
limit: 10,
|
limit: 10,
|
||||||
fromRandomCount: 10,
|
fromRandomCount: 10,
|
||||||
}
|
}
|
||||||
params.filters = props.layout ? { layout: props.layout } : { excludeLayout: 'article' }
|
|
||||||
|
|
||||||
const result = await apiClient.getRandomTopShouts(params)
|
const result = await apiClient.getRandomTopShouts(params)
|
||||||
setRandomTopMonthArticles(result)
|
setRandomTopMonthArticles(result)
|
||||||
|
@ -103,9 +112,7 @@ export const Expo = (props: Props) => {
|
||||||
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
|
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
|
||||||
loadMore(LOAD_MORE_PAGE_SIZE)
|
loadMore(LOAD_MORE_PAGE_SIZE)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
loadRandomTopArticles()
|
loadRandomTopArticles()
|
||||||
loadRandomTopMonthArticles()
|
loadRandomTopMonthArticles()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
import type { Author, LoadShoutsOptions, Reaction, Shout } from '../../graphql/types.gen'
|
import type { Author, LoadShoutsOptions, Reaction, Shout } from '../../../graphql/types.gen'
|
||||||
|
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '@solidjs/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { createEffect, createSignal, For, on, onMount, Show } from 'solid-js'
|
import { createEffect, createSignal, For, on, onMount, Show } from 'solid-js'
|
||||||
|
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
import { useReactions } from '../../context/reactions'
|
import { useReactions } from '../../../context/reactions'
|
||||||
import { router, useRouter } from '../../stores/router'
|
import { router, useRouter } from '../../../stores/router'
|
||||||
import { useArticlesStore, resetSortedArticles } from '../../stores/zine/articles'
|
import { useArticlesStore, resetSortedArticles } from '../../../stores/zine/articles'
|
||||||
import { useTopAuthorsStore } from '../../stores/zine/topAuthors'
|
import { useTopAuthorsStore } from '../../../stores/zine/topAuthors'
|
||||||
import { useTopicsStore } from '../../stores/zine/topics'
|
import { useTopicsStore } from '../../../stores/zine/topics'
|
||||||
import { capitalize } from '../../utils/capitalize'
|
import { apiClient } from '../../../utils/apiClient'
|
||||||
import { getImageUrl } from '../../utils/getImageUrl'
|
import { getImageUrl } from '../../../utils/getImageUrl'
|
||||||
import { getDescription } from '../../utils/meta'
|
import { Icon } from '../../_shared/Icon'
|
||||||
import { Icon } from '../_shared/Icon'
|
import { Loading } from '../../_shared/Loading'
|
||||||
import { Loading } from '../_shared/Loading'
|
import { CommentDate } from '../../Article/CommentDate'
|
||||||
import { CommentDate } from '../Article/CommentDate'
|
import { AuthorLink } from '../../Author/AhtorLink'
|
||||||
import { AuthorLink } from '../Author/AhtorLink'
|
import { AuthorBadge } from '../../Author/AuthorBadge'
|
||||||
import { AuthorBadge } from '../Author/AuthorBadge'
|
import { ArticleCard } from '../../Feed/ArticleCard'
|
||||||
import { ArticleCard } from '../Feed/ArticleCard'
|
import { Sidebar } from '../../Feed/Sidebar'
|
||||||
import { Sidebar } from '../Feed/Sidebar'
|
|
||||||
|
|
||||||
import styles from './Feed.module.scss'
|
import styles from './Feed.module.scss'
|
||||||
import stylesBeside from '../../components/Feed/Beside.module.scss'
|
import stylesBeside from '../../Feed/Beside.module.scss'
|
||||||
import stylesTopic from '../Feed/CardTopic.module.scss'
|
import stylesTopic from '../../Feed/CardTopic.module.scss'
|
||||||
|
|
||||||
export const FEED_PAGE_SIZE = 20
|
export const FEED_PAGE_SIZE = 20
|
||||||
|
const UNRATED_ARTICLES_COUNT = 5
|
||||||
|
|
||||||
type FeedSearchParams = {
|
type FeedSearchParams = {
|
||||||
by: 'publish_date' | 'rating' | 'last_comment'
|
by: 'publish_date' | 'rating' | 'last_comment'
|
||||||
|
@ -51,7 +51,7 @@ type Props = {
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FeedView = (props: Props) => {
|
export const Feed = (props: Props) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { page, searchParams } = useRouter<FeedSearchParams>()
|
const { page, searchParams } = useRouter<FeedSearchParams>()
|
||||||
const [isLoading, setIsLoading] = createSignal(false)
|
const [isLoading, setIsLoading] = createSignal(false)
|
||||||
|
@ -62,13 +62,20 @@ export const FeedView = (props: Props) => {
|
||||||
const { topAuthors } = useTopAuthorsStore()
|
const { topAuthors } = useTopAuthorsStore()
|
||||||
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
||||||
const [topComments, setTopComments] = createSignal<Reaction[]>([])
|
const [topComments, setTopComments] = createSignal<Reaction[]>([])
|
||||||
|
const [unratedArticles, setUnratedArticles] = createSignal<Shout[]>([])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
actions: { loadReactionsBy },
|
actions: { loadReactionsBy },
|
||||||
} = useReactions()
|
} = useReactions()
|
||||||
|
|
||||||
|
const loadUnratedArticles = async () => {
|
||||||
|
const result = await apiClient.getUnratedShouts(UNRATED_ARTICLES_COUNT)
|
||||||
|
setUnratedArticles(result)
|
||||||
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
loadMore()
|
loadMore()
|
||||||
|
loadUnratedArticles()
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(
|
createEffect(
|
||||||
|
@ -271,6 +278,14 @@ export const FeedView = (props: Props) => {
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
<Show when={unratedArticles().length > 0}>
|
||||||
|
<section class={clsx(styles.asideSection)}>
|
||||||
|
<h4>{t('Be the first to rate')}</h4>
|
||||||
|
<For each={unratedArticles()}>
|
||||||
|
{(article) => <ArticleCard article={article} settings={{ noimage: true, nodate: true }} />}
|
||||||
|
</For>
|
||||||
|
</section>
|
||||||
|
</Show>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
1
src/components/Views/Feed/index.ts
Normal file
1
src/components/Views/Feed/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { Feed } from './Feed'
|
|
@ -29,7 +29,7 @@ export const SearchView = (props: Props) => {
|
||||||
|
|
||||||
const { searchParams } = useRouter<SearchPageSearchParams>()
|
const { searchParams } = useRouter<SearchPageSearchParams>()
|
||||||
let searchEl: HTMLInputElement
|
let searchEl: HTMLInputElement
|
||||||
const handleQueryChange = (_ev) => {
|
const handleQueryChange = () => {
|
||||||
setQuery(searchEl.value)
|
setQuery(searchEl.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
& swiper-slide {
|
& swiper-slide {
|
||||||
//bind to html element <swiper-slide/>
|
// bind to html element <swiper-slide/>
|
||||||
width: unset !important;
|
width: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
46
src/graphql/query/articles-load-unrated.ts
Normal file
46
src/graphql/query/articles-load-unrated.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
|
export default gql`
|
||||||
|
query LoadUnratedShoutsQuery($limit: Int!) {
|
||||||
|
loadUnratedShouts(limit: $limit) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
lead
|
||||||
|
description
|
||||||
|
subtitle
|
||||||
|
slug
|
||||||
|
layout
|
||||||
|
cover
|
||||||
|
lead
|
||||||
|
# community
|
||||||
|
mainTopic
|
||||||
|
topics {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
body
|
||||||
|
slug
|
||||||
|
stat {
|
||||||
|
shouts
|
||||||
|
authors
|
||||||
|
followers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
authors {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
userpic
|
||||||
|
createdAt
|
||||||
|
bio
|
||||||
|
}
|
||||||
|
createdAt
|
||||||
|
publishedAt
|
||||||
|
stat {
|
||||||
|
viewed
|
||||||
|
reacted
|
||||||
|
rating
|
||||||
|
commented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
|
@ -377,6 +377,7 @@ export type Query = {
|
||||||
loadRecipients: Result
|
loadRecipients: Result
|
||||||
loadShout?: Maybe<Shout>
|
loadShout?: Maybe<Shout>
|
||||||
loadShouts: Array<Maybe<Shout>>
|
loadShouts: Array<Maybe<Shout>>
|
||||||
|
loadUnratedShouts: Array<Maybe<Shout>>
|
||||||
markdownBody: Scalars['String']['output']
|
markdownBody: Scalars['String']['output']
|
||||||
myFeed?: Maybe<Array<Maybe<Shout>>>
|
myFeed?: Maybe<Array<Maybe<Shout>>>
|
||||||
searchMessages: Result
|
searchMessages: Result
|
||||||
|
@ -449,6 +450,10 @@ export type QueryLoadShoutsArgs = {
|
||||||
options?: InputMaybe<LoadShoutsOptions>
|
options?: InputMaybe<LoadShoutsOptions>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type QueryLoadUnratedShoutsArgs = {
|
||||||
|
limit: Scalars['Int']['input']
|
||||||
|
}
|
||||||
|
|
||||||
export type QueryMarkdownBodyArgs = {
|
export type QueryMarkdownBodyArgs = {
|
||||||
body: Scalars['String']['input']
|
body: Scalars['String']['input']
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { createEffect, createMemo, createSignal, on, onCleanup, onMount, Show }
|
||||||
import { Loading } from '../components/_shared/Loading'
|
import { Loading } from '../components/_shared/Loading'
|
||||||
import { PageLayout } from '../components/_shared/PageLayout'
|
import { PageLayout } from '../components/_shared/PageLayout'
|
||||||
import { AuthorView, PRERENDERED_ARTICLES_COUNT } from '../components/Views/Author'
|
import { AuthorView, PRERENDERED_ARTICLES_COUNT } from '../components/Views/Author'
|
||||||
import { useLocalize } from '../context/localize'
|
|
||||||
import { ReactionsProvider } from '../context/reactions'
|
import { ReactionsProvider } from '../context/reactions'
|
||||||
import { useRouter } from '../stores/router'
|
import { useRouter } from '../stores/router'
|
||||||
import { loadShouts, resetSortedArticles } from '../stores/zine/articles'
|
import { loadShouts, resetSortedArticles } from '../stores/zine/articles'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { PageProps } from '../types'
|
import type { PageProps } from '../types'
|
||||||
|
|
||||||
import { createMemo } from 'solid-js'
|
import { createEffect, createMemo, on } from 'solid-js'
|
||||||
|
|
||||||
import { PageLayout } from '../../components/_shared/PageLayout'
|
import { PageLayout } from '../../components/_shared/PageLayout'
|
||||||
import { Topics } from '../../components/Nav/Topics'
|
import { Topics } from '../../components/Nav/Topics'
|
||||||
|
@ -14,7 +14,7 @@ export const ExpoPage = (props: PageProps) => {
|
||||||
const { page } = useRouter()
|
const { page } = useRouter()
|
||||||
const getLayout = createMemo<LayoutType>(() => page().params['layout'] as LayoutType)
|
const getLayout = createMemo<LayoutType>(() => page().params['layout'] as LayoutType)
|
||||||
|
|
||||||
const title = createMemo(() => {
|
const getTitle = () => {
|
||||||
switch (getLayout()) {
|
switch (getLayout()) {
|
||||||
case 'music': {
|
case 'music': {
|
||||||
return t('Audio')
|
return t('Audio')
|
||||||
|
@ -32,10 +32,20 @@ export const ExpoPage = (props: PageProps) => {
|
||||||
return t('Art')
|
return t('Art')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
createEffect(
|
||||||
|
on(
|
||||||
|
() => getLayout(),
|
||||||
|
() => {
|
||||||
|
document.title = getTitle()
|
||||||
|
},
|
||||||
|
{ defer: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageLayout withPadding={true} zeroBottomPadding={true} title={title()}>
|
<PageLayout withPadding={true} zeroBottomPadding={true} title={getTitle()}>
|
||||||
<Topics />
|
<Topics />
|
||||||
<Expo shouts={props.expoShouts} layout={getLayout()} />
|
<Expo shouts={props.expoShouts} layout={getLayout()} />
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createEffect, Match, on, onCleanup, Switch } from 'solid-js'
|
||||||
|
|
||||||
import { PageLayout } from '../components/_shared/PageLayout'
|
import { PageLayout } from '../components/_shared/PageLayout'
|
||||||
import { AuthGuard } from '../components/AuthGuard'
|
import { AuthGuard } from '../components/AuthGuard'
|
||||||
import { FeedView } from '../components/Views/Feed'
|
import { Feed } from '../components/Views/Feed'
|
||||||
import { useLocalize } from '../context/localize'
|
import { useLocalize } from '../context/localize'
|
||||||
import { ReactionsProvider } from '../context/reactions'
|
import { ReactionsProvider } from '../context/reactions'
|
||||||
import { LoadShoutsOptions } from '../graphql/types.gen'
|
import { LoadShoutsOptions } from '../graphql/types.gen'
|
||||||
|
@ -40,13 +40,13 @@ export const FeedPage = () => {
|
||||||
return (
|
return (
|
||||||
<PageLayout title={t('Feed')}>
|
<PageLayout title={t('Feed')}>
|
||||||
<ReactionsProvider>
|
<ReactionsProvider>
|
||||||
<Switch fallback={<FeedView loadShouts={handleFeedLoadShouts} />}>
|
<Switch fallback={<Feed loadShouts={handleFeedLoadShouts} />}>
|
||||||
<Match when={page().route === 'feed'}>
|
<Match when={page().route === 'feed'}>
|
||||||
<FeedView loadShouts={handleFeedLoadShouts} />
|
<Feed loadShouts={handleFeedLoadShouts} />
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={page().route === 'feedMy'}>
|
<Match when={page().route === 'feedMy'}>
|
||||||
<AuthGuard>
|
<AuthGuard>
|
||||||
<FeedView loadShouts={handleMyFeedLoadShouts} />
|
<Feed loadShouts={handleMyFeedLoadShouts} />
|
||||||
</AuthGuard>
|
</AuthGuard>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -4,16 +4,13 @@ import { createEffect, createMemo, createSignal, on, onCleanup, onMount } from '
|
||||||
|
|
||||||
import { PageLayout } from '../components/_shared/PageLayout'
|
import { PageLayout } from '../components/_shared/PageLayout'
|
||||||
import { PRERENDERED_ARTICLES_COUNT, TopicView } from '../components/Views/Topic'
|
import { PRERENDERED_ARTICLES_COUNT, TopicView } from '../components/Views/Topic'
|
||||||
import { useLocalize } from '../context/localize'
|
|
||||||
import { ReactionsProvider } from '../context/reactions'
|
import { ReactionsProvider } from '../context/reactions'
|
||||||
import { useRouter } from '../stores/router'
|
import { useRouter } from '../stores/router'
|
||||||
import { loadShouts, resetSortedArticles } from '../stores/zine/articles'
|
import { loadShouts, resetSortedArticles } from '../stores/zine/articles'
|
||||||
import { loadTopic } from '../stores/zine/topics'
|
import { loadTopic } from '../stores/zine/topics'
|
||||||
import { capitalize } from '../utils/capitalize'
|
|
||||||
|
|
||||||
export const TopicPage = (props: PageProps) => {
|
export const TopicPage = (props: PageProps) => {
|
||||||
const { page } = useRouter()
|
const { page } = useRouter()
|
||||||
const { t } = useLocalize()
|
|
||||||
const slug = createMemo(() => page().params['slug'] as string)
|
const slug = createMemo(() => page().params['slug'] as string)
|
||||||
|
|
||||||
const [isLoaded, setIsLoaded] = createSignal(
|
const [isLoaded, setIsLoaded] = createSignal(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Author, Shout, ShoutInput, LoadShoutsOptions } from '../../graphql/types.gen'
|
import type { Author, Shout, LoadShoutsOptions } from '../../graphql/types.gen'
|
||||||
|
|
||||||
import { createLazyMemo } from '@solid-primitives/memo'
|
import { createLazyMemo } from '@solid-primitives/memo'
|
||||||
import { createSignal } from 'solid-js'
|
import { createSignal } from 'solid-js'
|
||||||
|
@ -179,14 +179,6 @@ export const resetSortedArticles = () => {
|
||||||
setSortedArticles([])
|
setSortedArticles([])
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createArticle = async ({ article }: { article: ShoutInput }) => {
|
|
||||||
try {
|
|
||||||
await apiClient.createArticle({ article })
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InitialState = {
|
type InitialState = {
|
||||||
shouts?: Shout[]
|
shouts?: Shout[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,8 @@ import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
|
||||||
import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
|
import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
|
||||||
import shoutLoad from '../graphql/query/article-load'
|
import shoutLoad from '../graphql/query/article-load'
|
||||||
import shoutsLoadBy from '../graphql/query/articles-load-by'
|
import shoutsLoadBy from '../graphql/query/articles-load-by'
|
||||||
import shoutsLoadRandomTop from '../graphql/query/articles-load-random-top'
|
|
||||||
import articlesLoadRandomTop from '../graphql/query/articles-load-random-top'
|
import articlesLoadRandomTop from '../graphql/query/articles-load-random-top'
|
||||||
|
import articlesLoadUnrated from '../graphql/query/articles-load-unrated'
|
||||||
import authCheckEmailQuery from '../graphql/query/auth-check-email'
|
import authCheckEmailQuery from '../graphql/query/auth-check-email'
|
||||||
import authLoginQuery from '../graphql/query/auth-login'
|
import authLoginQuery from '../graphql/query/auth-login'
|
||||||
import authorBySlug from '../graphql/query/author-by-slug'
|
import authorBySlug from '../graphql/query/author-by-slug'
|
||||||
|
@ -362,6 +362,15 @@ export const apiClient = {
|
||||||
return resp.data.loadRandomTopShouts
|
return resp.data.loadRandomTopShouts
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getUnratedShouts: async (limit: number): Promise<Shout[]> => {
|
||||||
|
const resp = await publicGraphQLClient.query(articlesLoadUnrated, { limit }).toPromise()
|
||||||
|
if (resp.error) {
|
||||||
|
console.error(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.data.loadUnratedShouts
|
||||||
|
},
|
||||||
|
|
||||||
getMyFeed: async (options: LoadShoutsOptions) => {
|
getMyFeed: async (options: LoadShoutsOptions) => {
|
||||||
const resp = await privateGraphQLClient.query(myFeed, { options }).toPromise()
|
const resp = await privateGraphQLClient.query(myFeed, { options }).toPromise()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user