This commit is contained in:
tonyrewin 2022-11-15 17:24:50 +03:00
parent a9a22cd7f6
commit 39aec90013
33 changed files with 137 additions and 441 deletions

View File

@ -1,3 +1,9 @@
[0.6.1]
[+] auth ver. 0.9
[+] load-by interfaces for shouts, authors and messages
[+] inbox logix and markup
[-] old views counting
[0.6.0] [0.6.0]
[+] hybrid routing ssr/spa [+] hybrid routing ssr/spa
[+] 'expo' pages [+] 'expo' pages

View File

@ -1,6 +1,6 @@
{ {
"name": "discoursio-webapp", "name": "discoursio-webapp",
"version": "0.6.0", "version": "0.6.1",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {

View File

@ -1,5 +1,5 @@
import { createEffect, createMemo, createSignal, onMount } from 'solid-js' import { createEffect, createMemo, createSignal, onMount, For } from 'solid-js'
import { For } from 'solid-js/web'
import type { Shout } from '../../graphql/types.gen' import type { Shout } from '../../graphql/types.gen'
import { Soundwave } from './Soundwave' import { Soundwave } from './Soundwave'
@ -40,7 +40,7 @@ export default (props: { shout: Shout }) => {
<div class="audio-player-list"> <div class="audio-player-list">
<div class="player current-track"> <div class="player current-track">
<div class="player-title">{currentTrack().title}</div> <div class="player-title">{currentTrack().title}</div>
<i class="fas fa-pause fa-3x fa-fw" onClick={togglePlayPause}></i> <i class="fas fa-pause fa-3x fa-fw" onClick={togglePlayPause} />
<div class="player-progress"> <div class="player-progress">
<Soundwave context={audioContext()} url={currentTrack().src} /> <Soundwave context={audioContext()} url={currentTrack().src} />
<span class="track-position">{`${audioRef.currentTime} / ${audioRef.duration}`}</span> <span class="track-position">{`${audioRef.currentTime} / ${audioRef.duration}`}</span>
@ -53,7 +53,7 @@ export default (props: { shout: Shout }) => {
{(m: MediaItem) => ( {(m: MediaItem) => (
<li> <li>
<div class="player-status"> <div class="player-status">
<i class="fas fa-play fa-fw" onClick={() => playMedia(m)}></i> <i class="fas fa-play fa-fw" onClick={() => playMedia(m)} />
</div> </div>
<span class="track-title">{m.title}</span> <span class="track-title">{m.title}</span>
</li> </li>

View File

@ -7,7 +7,6 @@ import { createMemo, For, onMount, Show } from 'solid-js'
import type { Author, Reaction, Shout } from '../../graphql/types.gen' import type { Author, Reaction, Shout } from '../../graphql/types.gen'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { showModal } from '../../stores/ui' import { showModal } from '../../stores/ui'
import { incrementView } from '../../stores/zine/articles'
import MD from './MD' import MD from './MD'
import { SharePopup } from './SharePopup' import { SharePopup } from './SharePopup'
import { useSession } from '../../context/session' import { useSession } from '../../context/session'
@ -39,11 +38,6 @@ const formatDate = (date: Date) => {
export const FullArticle = (props: ArticleProps) => { export const FullArticle = (props: ArticleProps) => {
const { session } = useSession() const { session } = useSession()
onMount(() => {
incrementView({ articleSlug: props.article.slug })
})
const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt))) const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt)))
const mainTopic = () => const mainTopic = () =>

View File

@ -105,5 +105,5 @@ export const Soundwave = (props: SoundwaveProps) => {
onMount(() => { onMount(() => {
drawAudio(props.context, props.url) drawAudio(props.context, props.url)
}) })
return <canvas ref={canvasRef}></canvas> return <canvas ref={canvasRef} />
} }

View File

@ -28,10 +28,12 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.name { .name {
color: #141414; color: #141414;
font-weight: 500; font-weight: 500;
} }
.message { .message {
color: #9fa1a7; color: #9fa1a7;
} }
@ -40,6 +42,7 @@
.activity { .activity {
font-size: 12px; font-size: 12px;
margin-left: 12px; margin-left: 12px;
.time { .time {
text-align: right; text-align: right;
color: #ccc; color: #ccc;

View File

@ -1,13 +1,10 @@
import './DialogCard.module.scss'
import styles from './DialogCard.module.scss' import styles from './DialogCard.module.scss'
import DialogAvatar from './DialogAvatar' import DialogAvatar from './DialogAvatar'
import type { Author } from '../../graphql/types.gen' import type { Author, AuthResult } from '../../graphql/types.gen'
// import { useAuthStore } from '../../stores/auth' import { useSession } from '../../context/session'
import { createEffect, createSignal } from 'solid-js' import { createMemo, InitializedResource } from 'solid-js'
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
const { session } = useAuthStore()
type DialogProps = { type DialogProps = {
online?: boolean online?: boolean
message?: string message?: string
@ -20,20 +17,18 @@ const createChat = async ({ title, members }: { title?: string; members?: string
} }
const DialogCard = (props: DialogProps) => { const DialogCard = (props: DialogProps) => {
const [currentUser, setCurrentUser] = createSignal(undefined) const { session } = useSession()
createEffect(() => { const currentSession = createMemo<AuthResult>(() => session)
setCurrentUser(session()?.user?.slug)
})
const handleOpenChat = async () => { const handleOpenChat = async () => {
try { try {
const test = await apiClient.createChat({ const test = await apiClient.createChat({
title: 'test chat', title: 'test chat',
members: [props.author.slug, currentUser()] members: [props.author.slug, currentSession().user.slug]
}) })
console.log('!!! test:', test) console.log('!!! test:', test)
} catch (err) { } catch (error) {
console.log('!!! errr:', err) console.log('!!! errr:', error)
} }
} }

View File

@ -1,7 +1,7 @@
.Search { .Search {
.field { .field {
position: relative; position: relative;
background: #ffffff; background: #fff;
border: 2px solid #e8e8e8; border: 2px solid #e8e8e8;
border-radius: 2px; border-radius: 2px;
overflow: hidden; overflow: hidden;
@ -22,8 +22,10 @@
color: #858585; color: #858585;
font-family: inherit; font-family: inherit;
} }
&:focus { &:focus {
outline: none; outline: none;
& + .icon { & + .icon {
opacity: 0; opacity: 0;
right: -30px; right: -30px;

View File

@ -18,7 +18,6 @@ export const ProfileModal = () => {
const author = createMemo<Author>(() => { const author = createMemo<Author>(() => {
const a: Author = { const a: Author = {
id: null,
name: 'anonymous', name: 'anonymous',
userpic: '', userpic: '',
slug: '' slug: ''

View File

@ -1,14 +1,14 @@
import { PageWrap } from '../_shared/PageWrap' import { PageWrap } from '../_shared/PageWrap'
import { ArticleView } from '../Views/Article' import { ArticleView } from '../Views/Article'
import type { PageProps } from '../types' import type { PageProps } from '../types'
import { loadArticle, useArticlesStore } from '../../stores/zine/articles' import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { createMemo, onMount, Show } from 'solid-js' import { createMemo, onMount, Show } from 'solid-js'
import type { Shout } from '../../graphql/types.gen' import type { Shout } from '../../graphql/types.gen'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { Loading } from '../Loading' import { Loading } from '../Loading'
export const ArticlePage = (props: PageProps) => { export const ArticlePage = (props: PageProps) => {
const sortedArticles = props.article ? [props.article] : [] const shouts = props.article ? [props.article] : []
const slug = createMemo(() => { const slug = createMemo(() => {
const { page: getPage } = useRouter() const { page: getPage } = useRouter()
@ -23,16 +23,16 @@ export const ArticlePage = (props: PageProps) => {
}) })
const { articleEntities } = useArticlesStore({ const { articleEntities } = useArticlesStore({
sortedArticles shouts
}) })
const article = createMemo<Shout>(() => articleEntities()[slug()]) const article = createMemo<Shout>(() => articleEntities()[slug()])
onMount(() => { onMount(async () => {
const articleValue = articleEntities()[slug()] const articleValue = articleEntities()[slug()]
if (!articleValue || !articleValue.body) { if (!articleValue || !articleValue.body) {
loadArticle({ slug: slug() }) await loadShoutsBy({ by: { slug: slug() }, limit: 1, offset: 0 })
} }
}) })

View File

@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap'
import { AuthorView, PRERENDERED_ARTICLES_COUNT } from '../Views/Author' import { AuthorView, PRERENDERED_ARTICLES_COUNT } from '../Views/Author'
import type { PageProps } from '../types' import type { PageProps } from '../types'
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
import { loadAuthorArticles, resetSortedArticles } from '../../stores/zine/articles' import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { loadAuthor } from '../../stores/zine/authors' import { loadAuthor } from '../../stores/zine/authors'
import { Loading } from '../Loading' import { Loading } from '../Loading'
@ -27,7 +27,7 @@ export const AuthorPage = (props: PageProps) => {
return return
} }
await loadAuthorArticles({ authorSlug: slug(), limit: PRERENDERED_ARTICLES_COUNT }) await loadShoutsBy({ by: { author: slug() }, limit: PRERENDERED_ARTICLES_COUNT })
await loadAuthor({ slug: slug() }) await loadAuthor({ slug: slug() })
setIsLoaded(true) setIsLoaded(true)
@ -38,7 +38,7 @@ export const AuthorPage = (props: PageProps) => {
return ( return (
<PageWrap> <PageWrap>
<Show when={isLoaded()} fallback={<Loading />}> <Show when={isLoaded()} fallback={<Loading />}>
<AuthorView author={props.author} authorArticles={props.shouts} authorSlug={slug()} /> <AuthorView author={props.author} shouts={props.shouts} authorSlug={slug()} />
</Show> </Show>
</PageWrap> </PageWrap>
) )

View File

@ -2,7 +2,7 @@ import { HomeView, PRERENDERED_ARTICLES_COUNT } from '../Views/Home'
import { PageWrap } from '../_shared/PageWrap' import { PageWrap } from '../_shared/PageWrap'
import type { PageProps } from '../types' import type { PageProps } from '../types'
import { createSignal, onCleanup, onMount, Show } from 'solid-js' import { createSignal, onCleanup, onMount, Show } from 'solid-js'
import { loadPublishedArticles, resetSortedArticles } from '../../stores/zine/articles' import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { loadRandomTopics } from '../../stores/zine/topics' import { loadRandomTopics } from '../../stores/zine/topics'
import { Loading } from '../Loading' import { Loading } from '../Loading'
@ -14,7 +14,7 @@ export const HomePage = (props: PageProps) => {
return return
} }
await loadPublishedArticles({ limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) await loadShoutsBy({ by: { visibility: 'public' }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
await loadRandomTopics() await loadRandomTopics()
setIsLoaded(true) setIsLoaded(true)
@ -25,7 +25,7 @@ export const HomePage = (props: PageProps) => {
return ( return (
<PageWrap> <PageWrap>
<Show when={isLoaded()} fallback={<Loading />}> <Show when={isLoaded()} fallback={<Loading />}>
<HomeView randomTopics={props.randomTopics} recentPublishedArticles={props.shouts || []} /> <HomeView randomTopics={props.randomTopics} shouts={props.shouts || []} />
</Show> </Show>
</PageWrap> </PageWrap>
) )

View File

@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap'
import { SearchView } from '../Views/Search' import { SearchView } from '../Views/Search'
import type { PageProps } from '../types' import type { PageProps } from '../types'
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
import { loadSearchResults, resetSortedArticles } from '../../stores/zine/articles' import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { Loading } from '../Loading' import { Loading } from '../Loading'
@ -26,7 +26,7 @@ export const SearchPage = (props: PageProps) => {
return return
} }
await loadSearchResults({ query: q(), limit: 50, offset: 0 }) await loadShoutsBy({ by: { title: q(), body: q() }, limit: 50, offset: 0 })
setIsLoaded(true) setIsLoaded(true)
}) })

View File

@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap'
import { PRERENDERED_ARTICLES_COUNT, TopicView } from '../Views/Topic' import { PRERENDERED_ARTICLES_COUNT, TopicView } from '../Views/Topic'
import type { PageProps } from '../types' import type { PageProps } from '../types'
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
import { loadTopicArticles, resetSortedArticles } from '../../stores/zine/articles' import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { loadTopic } from '../../stores/zine/topics' import { loadTopic } from '../../stores/zine/topics'
import { Loading } from '../Loading' import { Loading } from '../Loading'
@ -27,7 +27,7 @@ export const TopicPage = (props: PageProps) => {
return return
} }
await loadTopicArticles({ topicSlug: slug(), limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) await loadShoutsBy({ by: { topics: [slug()] }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
await loadTopic({ slug: slug() }) await loadTopic({ slug: slug() })
setIsLoaded(true) setIsLoaded(true)
@ -38,7 +38,7 @@ export const TopicPage = (props: PageProps) => {
return ( return (
<PageWrap> <PageWrap>
<Show when={isLoaded()} fallback={<Loading />}> <Show when={isLoaded()} fallback={<Loading />}>
<TopicView topic={props.topic} topicArticles={props.shouts} topicSlug={slug()} /> <TopicView topic={props.topic} shouts={props.shouts} topicSlug={slug()} />
</Show> </Show>
</PageWrap> </PageWrap>
) )

View File

@ -5,7 +5,7 @@ import { Row3 } from '../Feed/Row3'
import { AuthorFull } from '../Author/Full' import { AuthorFull } from '../Author/Full'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore } from '../../stores/zine/authors'
import { loadAuthorArticles, useArticlesStore } from '../../stores/zine/articles' import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { useTopicsStore } from '../../stores/zine/topics' import { useTopicsStore } from '../../stores/zine/topics'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
@ -15,7 +15,7 @@ import { splitToPages } from '../../utils/splitToPages'
// TODO: load reactions on client // TODO: load reactions on client
type AuthorProps = { type AuthorProps = {
authorArticles: Shout[] shouts: Shout[]
author: Author author: Author
authorSlug: string authorSlug: string
// FIXME author topics fro server // FIXME author topics fro server
@ -31,7 +31,7 @@ const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3
export const AuthorView = (props: AuthorProps) => { export const AuthorView = (props: AuthorProps) => {
const { sortedArticles } = useArticlesStore({ const { sortedArticles } = useArticlesStore({
sortedArticles: props.authorArticles shouts: props.shouts
}) })
const { authorEntities } = useAuthorsStore({ authors: [props.author] }) const { authorEntities } = useAuthorsStore({ authors: [props.author] })
const { topicsByAuthor } = useTopicsStore() const { topicsByAuthor } = useTopicsStore()
@ -42,8 +42,8 @@ export const AuthorView = (props: AuthorProps) => {
const loadMore = async () => { const loadMore = async () => {
saveScrollPosition() saveScrollPosition()
const { hasMore } = await loadAuthorArticles({ const { hasMore } = await loadShoutsBy({
authorSlug: author().slug, by: { author: author().slug },
limit: LOAD_MORE_PAGE_SIZE, limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length offset: sortedArticles().length
}) })

View File

@ -9,7 +9,7 @@ import { AuthorCard } from '../Author/Card'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { FeedSidebar } from '../Feed/Sidebar' import { FeedSidebar } from '../Feed/Sidebar'
import CommentCard from '../Article/Comment' import CommentCard from '../Article/Comment'
import { loadRecentArticles, useArticlesStore } from '../../stores/zine/articles' import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { useReactionsStore } from '../../stores/zine/reactions' import { useReactionsStore } from '../../stores/zine/reactions'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore } from '../../stores/zine/authors'
import { useTopicsStore } from '../../stores/zine/topics' import { useTopicsStore } from '../../stores/zine/topics'
@ -52,7 +52,11 @@ export const FeedView = () => {
// }) // })
const loadMore = async () => { const loadMore = async () => {
const { hasMore } = await loadRecentArticles({ limit: FEED_PAGE_SIZE, offset: sortedArticles().length }) const { hasMore } = await loadShoutsBy({
by: { visibility: 'community' },
limit: FEED_PAGE_SIZE,
offset: sortedArticles().length
})
setIsLoadMoreButtonVisible(hasMore) setIsLoadMoreButtonVisible(hasMore)
} }

View File

@ -14,12 +14,7 @@ import type { Shout, Topic } from '../../graphql/types.gen'
import { Icon } from '../_shared/Icon' import { Icon } from '../_shared/Icon'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useTopicsStore } from '../../stores/zine/topics' import { useTopicsStore } from '../../stores/zine/topics'
import { import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
loadPublishedArticles,
loadTopArticles,
loadTopMonthArticles,
useArticlesStore
} from '../../stores/zine/articles'
import { useTopAuthorsStore } from '../../stores/zine/topAuthors' import { useTopAuthorsStore } from '../../stores/zine/topAuthors'
import { locale } from '../../stores/ui' import { locale } from '../../stores/ui'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
@ -27,7 +22,7 @@ import { splitToPages } from '../../utils/splitToPages'
type HomeProps = { type HomeProps = {
randomTopics: Topic[] randomTopics: Topic[]
recentPublishedArticles: Shout[] shouts: Shout[]
} }
export const PRERENDERED_ARTICLES_COUNT = 5 export const PRERENDERED_ARTICLES_COUNT = 5
@ -37,26 +32,24 @@ const LOAD_MORE_PAGE_SIZE = 16 // Row1 + Row3 + Row2 + Beside (3 + 1) + Row1 + R
export const HomeView = (props: HomeProps) => { export const HomeView = (props: HomeProps) => {
const { const {
sortedArticles, sortedArticles,
articlesByLayout,
topArticles, topArticles,
topMonthArticles,
topViewedArticles,
topCommentedArticles, topCommentedArticles,
articlesByLayout topMonthArticles,
topViewedArticles
} = useArticlesStore({ } = useArticlesStore({
sortedArticles: props.recentPublishedArticles shouts: props.shouts
}) })
const { randomTopics, topTopics } = useTopicsStore({ const { randomTopics, topTopics } = useTopicsStore({
randomTopics: props.randomTopics randomTopics: props.randomTopics
}) })
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const { topAuthors } = useTopAuthorsStore() const { topAuthors } = useTopAuthorsStore()
onMount(async () => { onMount(async () => {
loadTopArticles()
loadTopMonthArticles()
if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) { if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) {
const { hasMore } = await loadPublishedArticles({ const { hasMore } = await loadShoutsBy({
by: {},
limit: CLIENT_LOAD_ARTICLES_COUNT, limit: CLIENT_LOAD_ARTICLES_COUNT,
offset: sortedArticles().length offset: sortedArticles().length
}) })
@ -91,7 +84,8 @@ export const HomeView = (props: HomeProps) => {
const loadMore = async () => { const loadMore = async () => {
saveScrollPosition() saveScrollPosition()
const { hasMore } = await loadPublishedArticles({ const { hasMore } = await loadShoutsBy({
by: { visibility: 'public' },
limit: LOAD_MORE_PAGE_SIZE, limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length offset: sortedArticles().length
}) })

View File

@ -3,7 +3,7 @@ import '../../styles/Search.scss'
import type { Shout } from '../../graphql/types.gen' import type { Shout } from '../../graphql/types.gen'
import { ArticleCard } from '../Feed/Card' import { ArticleCard } from '../Feed/Card'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useArticlesStore, loadSearchResults } from '../../stores/zine/articles' import { useArticlesStore, loadShoutsBy } from '../../stores/zine/articles'
import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
type SearchPageSearchParams = { type SearchPageSearchParams = {
@ -16,7 +16,7 @@ type Props = {
} }
export const SearchView = (props: Props) => { export const SearchView = (props: Props) => {
const { sortedArticles } = useArticlesStore({ sortedArticles: props.results }) const { sortedArticles } = useArticlesStore({ shouts: props.results })
const [getQuery, setQuery] = createSignal(props.query) const [getQuery, setQuery] = createSignal(props.query)
const { searchParams } = useRouter<SearchPageSearchParams>() const { searchParams } = useRouter<SearchPageSearchParams>()
@ -28,7 +28,7 @@ export const SearchView = (props: Props) => {
const handleSubmit = (_ev) => { const handleSubmit = (_ev) => {
// TODO page // TODO page
// TODO sort // TODO sort
loadSearchResults({ query: getQuery() }) loadShoutsBy({ by: { title: getQuery(), body: getQuery() }, limit: 50 })
} }
return ( return (

View File

@ -8,7 +8,7 @@ import { FullTopic } from '../Topic/Full'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'
import { useTopicsStore } from '../../stores/zine/topics' import { useTopicsStore } from '../../stores/zine/topics'
import { loadTopicArticles, useArticlesStore } from '../../stores/zine/articles' import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore } from '../../stores/zine/authors'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
import { splitToPages } from '../../utils/splitToPages' import { splitToPages } from '../../utils/splitToPages'
@ -22,7 +22,7 @@ type TopicsPageSearchParams = {
interface TopicProps { interface TopicProps {
topic: Topic topic: Topic
topicArticles: Shout[] shouts: Shout[]
topicSlug: string topicSlug: string
} }
@ -34,7 +34,7 @@ export const TopicView = (props: TopicProps) => {
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const { sortedArticles } = useArticlesStore({ sortedArticles: props.topicArticles }) const { sortedArticles } = useArticlesStore({ shouts: props.shouts })
const { topicEntities } = useTopicsStore({ topics: [props.topic] }) const { topicEntities } = useTopicsStore({ topics: [props.topic] })
const { authorsByTopic } = useAuthorsStore() const { authorsByTopic } = useAuthorsStore()
@ -44,8 +44,8 @@ export const TopicView = (props: TopicProps) => {
const loadMore = async () => { const loadMore = async () => {
saveScrollPosition() saveScrollPosition()
const { hasMore } = await loadTopicArticles({ const { hasMore } = await loadShoutsBy({
topicSlug: topic().slug, by: { topic: topic().slug },
limit: LOAD_MORE_PAGE_SIZE, limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length offset: sortedArticles().length
}) })

View File

@ -1,9 +0,0 @@
import { gql } from '@urql/core'
export default gql`
mutation IncrementViewMutation($shout: String!) {
incrementView(shout: $shout) {
error
}
}
`

View File

@ -494,6 +494,7 @@ export type ReactionBy = {
days?: InputMaybe<Scalars['Int']> days?: InputMaybe<Scalars['Int']>
order?: InputMaybe<Scalars['String']> order?: InputMaybe<Scalars['String']>
shout?: InputMaybe<Scalars['String']> shout?: InputMaybe<Scalars['String']>
shouts?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
stat?: InputMaybe<Scalars['String']> stat?: InputMaybe<Scalars['String']>
topic?: InputMaybe<Scalars['String']> topic?: InputMaybe<Scalars['String']>
} }
@ -618,6 +619,7 @@ export type ShoutsBy = {
stat?: InputMaybe<Scalars['String']> stat?: InputMaybe<Scalars['String']>
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']>
topic?: InputMaybe<Scalars['String']> topic?: InputMaybe<Scalars['String']>
topics?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
visibility?: InputMaybe<Scalars['String']> visibility?: InputMaybe<Scalars['String']>
} }

View File

@ -9,7 +9,7 @@ if (slug.endsWith('.map')) {
return Astro.redirect('/404') return Astro.redirect('/404')
} }
const article = await apiClient.getArticle({ slug }) const article = await apiClient.loadShoutsBy({ by: { slug }, amount: 1})
if (!article) { if (!article) {
return Astro.redirect('/404') return Astro.redirect('/404')
} }
@ -21,5 +21,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate'
--- ---
<Prerendered> <Prerendered>
<Root article={article} client:load /> <Root article={article.at(0)} client:load />
</Prerendered> </Prerendered>

View File

@ -6,8 +6,8 @@ import { initRouter } from '../../../stores/router'
import { PRERENDERED_ARTICLES_COUNT } from '../../../components/Views/Author' import { PRERENDERED_ARTICLES_COUNT } from '../../../components/Views/Author'
const slug = Astro.params.slug.toString() const slug = Astro.params.slug.toString()
const shouts = await apiClient.getArticlesForAuthors({ authorSlugs: [slug], limit: PRERENDERED_ARTICLES_COUNT }) const shouts = await apiClient.loadShoutsBy({ by: { authors: [slug] } , amount: PRERENDERED_ARTICLES_COUNT })
const author = await apiClient.getAuthor({ slug }) const author = await apiClient.loadAuthorsBy({ by: { slug } })
const { pathname, search } = Astro.url const { pathname, search } = Astro.url
initRouter(pathname, search) initRouter(pathname, search)

View File

@ -10,7 +10,7 @@ const layout = (Astro.params.layout?.toString() || 'article') as LayoutType
if (!layout || layout.endsWith('.map')) { if (!layout || layout.endsWith('.map')) {
return Astro.redirect('/404') return Astro.redirect('/404')
} }
const shouts = await apiClient.getRecentLayoutShouts({ layout }) const shouts = await apiClient.loadShoutsBy({ by: { layout } })
const { pathname, search } = Astro.url const { pathname, search } = Astro.url
initRouter(pathname, search) initRouter(pathname, search)
--- ---

View File

@ -6,7 +6,8 @@ import { initRouter } from '../stores/router'
import { PRERENDERED_ARTICLES_COUNT } from '../components/Views/Home' import { PRERENDERED_ARTICLES_COUNT } from '../components/Views/Home'
const randomTopics = await apiClient.getRandomTopics({ amount: 12 }) const randomTopics = await apiClient.getRandomTopics({ amount: 12 })
const articles = await apiClient.getRecentPublishedArticles({ limit: PRERENDERED_ARTICLES_COUNT }) const articles = await apiClient.loadShoutsBy(
{ by: { visibility: "public" }, amount: PRERENDERED_ARTICLES_COUNT, offset: 0 })
const { pathname, search } = Astro.url const { pathname, search } = Astro.url
initRouter(pathname, search) initRouter(pathname, search)

View File

@ -6,7 +6,7 @@ import { initRouter } from '../stores/router'
const params: URLSearchParams = Astro.url.searchParams const params: URLSearchParams = Astro.url.searchParams
const q = params.get('q') const q = params.get('q')
const searchResults = await apiClient.getSearchResults({ query: q, limit: 50 }) const searchResults = await apiClient.loadShoutsBy({ by: { title: q, body: q }, amount: 50 })
const { pathname, search } = Astro.url const { pathname, search } = Astro.url
initRouter(pathname, search) initRouter(pathname, search)

View File

@ -5,7 +5,7 @@ import { apiClient } from '../../utils/apiClient'
import { PRERENDERED_ARTICLES_COUNT } from '../../components/Views/Topic' import { PRERENDERED_ARTICLES_COUNT } from '../../components/Views/Topic'
const slug = Astro.params.slug?.toString() || '' const slug = Astro.params.slug?.toString() || ''
const shouts = await apiClient.getArticlesForTopics({ topicSlugs: [slug], limit: PRERENDERED_ARTICLES_COUNT }) const shouts = await apiClient.loadShoutsBy({ by: { topics: [slug] }, amount: PRERENDERED_ARTICLES_COUNT })
const topic = await apiClient.getTopic({ slug }) const topic = await apiClient.getTopic({ slug })
import { initRouter } from '../../stores/router' import { initRouter } from '../../stores/router'

View File

@ -1,4 +1,4 @@
import type { Author, Shout, ShoutInput, Topic } from '../../graphql/types.gen' import type { Author, Shout, ShoutInput, ShoutsBy, Topic } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
import { addAuthorsByTopic } from './authors' import { addAuthorsByTopic } from './authors'
import { addTopicsByAuthor } from './topics' import { addTopicsByAuthor } from './topics'
@ -123,96 +123,18 @@ const addSortedArticles = (articles: Shout[]) => {
setSortedArticles((prevSortedArticles) => [...prevSortedArticles, ...articles]) setSortedArticles((prevSortedArticles) => [...prevSortedArticles, ...articles])
} }
export const loadFeed = async ({ export const loadShoutsBy = async ({
limit, by,
offset
}: {
limit: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
// TODO: load actual feed
return await loadRecentArticles({ limit, offset })
}
export const loadRecentArticles = async ({
limit,
offset
}: {
limit: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.getRecentArticles({ limit: limit + 1, offset })
const hasMore = newArticles.length === limit + 1
if (hasMore) {
newArticles.splice(-1)
}
addArticles(newArticles)
addSortedArticles(newArticles)
return { hasMore }
}
export const loadPublishedArticles = async ({
limit, limit,
offset = 0 offset = 0
}: { }: {
by: ShoutsBy
limit: number limit: number
offset?: number offset?: number
}): Promise<{ hasMore: boolean }> => { }): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.getPublishedArticles({ limit: limit + 1, offset }) const newArticles = await apiClient.loadShoutsBy({
const hasMore = newArticles.length === limit + 1 by,
amount: limit + 1,
if (hasMore) {
newArticles.splice(-1)
}
addArticles(newArticles)
addSortedArticles(newArticles)
return { hasMore }
}
export const loadAuthorArticles = async ({
authorSlug,
limit,
offset = 0
}: {
authorSlug: string
limit: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.getArticlesForAuthors({
authorSlugs: [authorSlug],
limit: limit + 1,
offset
})
const hasMore = newArticles.length === limit + 1
if (hasMore) {
newArticles.splice(-1)
}
addArticles(newArticles)
addSortedArticles(newArticles)
return { hasMore }
}
export const loadTopicArticles = async ({
topicSlug,
limit,
offset
}: {
topicSlug: string
limit: number
offset: number
}): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.getArticlesForTopics({
topicSlugs: [topicSlug],
limit: limit + 1,
offset offset
}) })
@ -232,46 +154,6 @@ export const resetSortedArticles = () => {
setSortedArticles([]) setSortedArticles([])
} }
export const loadTopMonthArticles = async (): Promise<void> => {
const articles = await apiClient.getTopMonthArticles()
addArticles(articles)
setTopMonthArticles(articles)
}
export const loadTopArticles = async (): Promise<void> => {
const articles = await apiClient.getTopArticles()
addArticles(articles)
setTopArticles(articles)
}
export const loadSearchResults = async ({
query,
limit,
offset
}: {
query: string
limit?: number
offset?: number
}): Promise<void> => {
const newArticles = await apiClient.getSearchResults({ query, limit, offset })
addArticles(newArticles)
addSortedArticles(newArticles)
}
export const incrementView = async ({ articleSlug }: { articleSlug: string }): Promise<void> => {
await apiClient.incrementView({ articleSlug })
}
export const loadArticle = async ({ slug }: { slug: string }): Promise<void> => {
const article = await apiClient.getArticle({ slug })
if (!article) {
throw new Error(`Can't load article, slug: "${slug}"`)
}
addArticles([article])
}
export const createArticle = async ({ article }: { article: ShoutInput }) => { export const createArticle = async ({ article }: { article: ShoutInput }) => {
try { try {
await apiClient.createArticle({ article }) await apiClient.createArticle({ article })
@ -281,27 +163,26 @@ export const createArticle = async ({ article }: { article: ShoutInput }) => {
} }
type InitialState = { type InitialState = {
sortedArticles?: Shout[] shouts?: Shout[]
topRatedArticles?: Shout[]
topRatedMonthArticles?: Shout[]
} }
export const useArticlesStore = (initialState: InitialState = {}) => { export const useArticlesStore = (initialState: InitialState = {}) => {
addArticles([...(initialState.sortedArticles || [])]) addArticles([...(initialState.shouts || [])])
if (initialState.sortedArticles) { if (initialState.shouts) {
setSortedArticles([...initialState.sortedArticles]) setSortedArticles([...initialState.shouts])
} }
return { return {
articleEntities, articleEntities,
sortedArticles, sortedArticles,
articlesByTopic, loadShoutsBy,
articlesByAuthor, articlesByAuthor,
topArticles, articlesByLayout,
articlesByTopic,
topMonthArticles, topMonthArticles,
topViewedArticles, topArticles,
topCommentedArticles, topCommentedArticles,
articlesByLayout topViewedArticles
} }
} }

View File

@ -32,11 +32,11 @@ export const loadRecentLayoutShouts = async ({
amount: number amount: number
offset?: number offset?: number
}): Promise<{ hasMore: boolean }> => { }): Promise<{ hasMore: boolean }> => {
const layoutShouts: Shout[] = await apiClient.getRecentLayoutShouts({ layout, amount, offset }) const layoutShouts: Shout[] = await apiClient.loadShoutsBy({ by: { layout }, amount, offset })
const hasMore = layoutShouts.length < amount const hasMore = layoutShouts.length < amount
if (hasMore) layoutShouts.splice(-1) if (hasMore) layoutShouts.splice(-1)
const sortedArticles = layoutShouts.sort(byCreated) const shouts = layoutShouts.sort(byCreated)
const { articlesByLayout } = useArticlesStore({ sortedArticles }) const { articlesByLayout } = useArticlesStore({ shouts })
addLayoutShouts(layout, articlesByLayout()[layout]) addLayoutShouts(layout, articlesByLayout()[layout])
return { hasMore } return { hasMore }
} }
@ -46,7 +46,7 @@ export const loadTopMonthLayoutShouts = async (
amount: number, amount: number,
offset: number offset: number
): Promise<{ hasMore: boolean }> => { ): Promise<{ hasMore: boolean }> => {
const shouts = await apiClient.getTopMonthLayoutShouts({ layout }) const shouts = await apiClient.loadShoutsBy({ by: { layout, stat: 'rating', days: 30 } })
const hasMore = shouts.length < amount const hasMore = shouts.length < amount
if (hasMore) shouts.splice(-1) if (hasMore) shouts.splice(-1)
addLayoutShouts(layout, shouts) addLayoutShouts(layout, shouts)
@ -58,14 +58,14 @@ export const loadTopLayoutShouts = async (
amount, amount,
offset offset
): Promise<{ hasMore: boolean }> => { ): Promise<{ hasMore: boolean }> => {
const shouts = await apiClient.getTopLayoutShouts({ layout }) const shouts = await apiClient.loadShoutsBy({ by: { layout, stat: 'rating' } })
const hasMore = shouts.length < amount const hasMore = shouts.length < amount
if (hasMore) shouts.splice(-1) if (hasMore) shouts.splice(-1)
addLayoutShouts(layout, shouts) addLayoutShouts(layout, shouts)
return { hasMore } return { hasMore }
} }
export const loadSearchResults = async ({ export const loadShoutsSearch = async ({
layout, layout,
query, query,
limit, limit,
@ -76,25 +76,21 @@ export const loadSearchResults = async ({
limit?: number limit?: number
offset?: number offset?: number
}): Promise<void> => { }): Promise<void> => {
const newLayoutShouts = await apiClient.getSearchResults({ layout, query, limit, offset }) const by = {
layout: layout,
query: query
}
const amount = limit
const newLayoutShouts = await apiClient.loadShoutsBy({ by, amount, offset })
addLayoutShouts(layout, newLayoutShouts) addLayoutShouts(layout, newLayoutShouts)
} }
type InitialState = {
sortedLayoutShouts?: Shout[]
topRatedLayoutShouts?: Shout[]
topRatedMonthLayoutShouts?: Shout[]
}
export const useLayoutsStore = (layout: LayoutType, initialData: Shout[]) => { export const useLayoutsStore = (layout: LayoutType, initialData: Shout[]) => {
addLayoutShouts(layout, initialData || []) addLayoutShouts(layout, initialData || [])
return { return {
addLayoutShouts, addLayoutShouts,
sortedLayoutShouts, sortedLayoutShouts,
loadSearchResults, loadShoutsSearch
loadRecentLayoutShouts,
loadTopMonthLayoutShouts,
loadTopLayoutShouts
} }
} }

View File

@ -6,6 +6,8 @@ import { reduceBy } from '../../utils/reduce'
// import { roomConnect } from '../../utils/p2p' // import { roomConnect } from '../../utils/p2p'
// FIXME // FIXME
export const REACTIONS_AMOUNT_PER_PAGE = 100
let reactionsOrdered: WritableAtom<Reaction[]> let reactionsOrdered: WritableAtom<Reaction[]>
export const reactions = atom<{ [slug: string]: Reaction[] }>({}) // by shout export const reactions = atom<{ [slug: string]: Reaction[] }>({}) // by shout
@ -19,14 +21,14 @@ export const useReactionsStore = (initial?: Reaction[]) => {
export const loadArticleReactions = async ({ export const loadArticleReactions = async ({
articleSlug, articleSlug,
limit = 100, limit = REACTIONS_AMOUNT_PER_PAGE,
offset = 0 offset = 0
}: { }: {
articleSlug: string articleSlug: string
limit?: number limit?: number
offset?: number offset?: number
}): Promise<void> => { }): Promise<void> => {
const data = await apiClient.getReactionsForShouts({ shoutSlugs: [articleSlug], limit, offset }) const data = await apiClient.loadReactionsBy({ by: { shout: articleSlug }, amount: limit, offset })
// TODO: const [data, provider] = roomConnect(articleSlug, username, "reactions") // TODO: const [data, provider] = roomConnect(articleSlug, username, "reactions")
reactionsOrdered.set(data) reactionsOrdered.set(data)
} }
@ -40,7 +42,11 @@ export const loadReactions = async ({
limit: number limit: number
offset: number offset: number
}): Promise<void> => { }): Promise<void> => {
const reactionsForShouts = await apiClient.getReactionsForShouts({ shoutSlugs, limit, offset }) const reactionsForShouts = await apiClient.loadReactionsBy({
by: { shouts: shoutSlugs },
amount: limit,
offset
})
reactionsOrdered.set(reactionsForShouts) reactionsOrdered.set(reactionsForShouts)
} }

View File

@ -4,6 +4,7 @@ main {
flex-direction: column; flex-direction: column;
position: relative; position: relative;
} }
// TODO: добавлять когда открыт чат // TODO: добавлять когда открыт чат
body { body {
overflow: hidden; overflow: hidden;
@ -35,6 +36,7 @@ body {
position: relative; position: relative;
} }
} }
// список диалогов и юзеров // список диалогов и юзеров
.chat-list { .chat-list {
display: flex; display: flex;
@ -43,6 +45,7 @@ body {
height: calc(100% - 10px); height: calc(100% - 10px);
$fade-height: 10px; $fade-height: 10px;
.holder { .holder {
overflow: hidden; overflow: hidden;
flex: 1; flex: 1;
@ -63,6 +66,7 @@ body {
top: 0; top: 0;
background: linear-gradient(white, transparent $fade-height); background: linear-gradient(white, transparent $fade-height);
} }
&::after { &::after {
bottom: 0; bottom: 0;
background: linear-gradient(transparent, white $fade-height); background: linear-gradient(transparent, white $fade-height);
@ -93,7 +97,9 @@ body {
// табы выбора списка // табы выбора списка
.chat-list__types { .chat-list__types {
@include font-size(1.7rem); @include font-size(1.7rem);
margin: 16px 0; margin: 16px 0;
ul { ul {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@ -243,7 +249,6 @@ body {
.conversation__message { .conversation__message {
font-size: 14px; font-size: 14px;
max-width: 60%; max-width: 60%;
border-radius: 16px; border-radius: 16px;
padding: 12px 16px; padding: 12px 16px;

View File

@ -10,7 +10,6 @@ import type {
import { publicGraphQLClient } from '../graphql/publicGraphQLClient' import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient' import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
import topicsAll from '../graphql/query/topics-all' import topicsAll from '../graphql/query/topics-all'
import reactionsForShouts from '../graphql/query/reactions-load-by'
import mySession from '../graphql/mutation/my-session' import mySession from '../graphql/mutation/my-session'
import authLogoutQuery from '../graphql/mutation/auth-logout' import authLogoutQuery from '../graphql/mutation/auth-logout'
import authLoginQuery from '../graphql/query/auth-login' import authLoginQuery from '../graphql/query/auth-login'
@ -25,7 +24,6 @@ import authorsAll from '../graphql/query/authors-all'
import reactionCreate from '../graphql/mutation/reaction-create' import reactionCreate from '../graphql/mutation/reaction-create'
import reactionDestroy from '../graphql/mutation/reaction-destroy' import reactionDestroy from '../graphql/mutation/reaction-destroy'
import reactionUpdate from '../graphql/mutation/reaction-update' import reactionUpdate from '../graphql/mutation/reaction-update'
import incrementView from '../graphql/mutation/increment-view'
import createArticle from '../graphql/mutation/article-create' import createArticle from '../graphql/mutation/article-create'
import myChats from '../graphql/query/chats-load' import myChats from '../graphql/query/chats-load'
import loadChat from '../graphql/query/chat-messages-load-by' import loadChat from '../graphql/query/chat-messages-load-by'
@ -35,6 +33,7 @@ import shoutsLoadBy from '../graphql/query/articles-load-by'
import reactionsLoadBy from '../graphql/query/reactions-load-by' import reactionsLoadBy from '../graphql/query/reactions-load-by'
import authorsLoadBy from '../graphql/query/authors-load-by' import authorsLoadBy from '../graphql/query/authors-load-by'
import createChatQuery from '../graphql/mutation/create-chat' import createChatQuery from '../graphql/mutation/create-chat'
import { REACTIONS_AMOUNT_PER_PAGE } from '../stores/zine/reactions'
const FEED_SIZE = 50 const FEED_SIZE = 50
@ -148,37 +147,6 @@ export const apiClient = {
return response.data.confirmEmail return response.data.confirmEmail
}, },
getTopArticles: async () => {
const by = {
stat: 'rating',
visibility: 'public'
}
const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit: 10, offset: 0 }).toPromise()
return response.data.loadShoutsBy
},
getTopMonthArticles: async () => {
const by = {
stat: 'rating',
visibility: 'public',
days: 30
}
const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit: 10, offset: 0 }).toPromise()
return response.data.loadShoutsBy
},
getRecentPublishedArticles: async ({
limit = FEED_SIZE,
offset = 0
}: {
limit?: number
offset?: number
}) => {
const by = {
visibility: 'public'
}
const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit, offset }).toPromise()
return response.data.loadShoutsBy
},
getRandomTopics: async ({ amount }: { amount: number }) => { getRandomTopics: async ({ amount }: { amount: number }) => {
const response = await publicGraphQLClient.query(topicsRandomQuery, { amount }).toPromise() const response = await publicGraphQLClient.query(topicsRandomQuery, { amount }).toPromise()
@ -188,100 +156,6 @@ export const apiClient = {
return response.data.topicsRandom return response.data.topicsRandom
}, },
getSearchResults: async ({
query,
limit = FEED_SIZE,
offset = 0
}: {
query: string
limit: number
offset?: number
}): Promise<Shout[]> => {
const by = {
title: query,
body: query
}
const response = await publicGraphQLClient
.query(shoutsLoadBy, {
by,
limit,
offset
})
.toPromise()
return response.data?.searchQuery || []
},
getRecentArticles: async ({
limit = FEED_SIZE,
offset = 0
}: {
limit: number
offset?: number
}): Promise<Shout[]> => {
const response = await publicGraphQLClient
.query(shoutsLoadBy, {
by: {},
limit,
offset
})
.toPromise()
return response.data.recentAll
},
getArticlesForTopics: async ({
topicSlugs,
limit,
offset = 0
}: {
topicSlugs: string[]
limit: number
offset?: number
}): Promise<Shout[]> => {
const by = {
topics: topicSlugs,
visibility: 'public'
}
const response = await publicGraphQLClient
.query(shoutsLoadBy, {
by,
limit,
offset
})
.toPromise()
if (response.error) {
console.error('[api-client] getArticlesForTopics', response.error)
}
return response.data.shoutsByTopics
},
getArticlesForAuthors: async ({
authorSlugs,
limit,
offset = 0
}: {
authorSlugs: string[]
limit: number
offset?: number
}): Promise<Shout[]> => {
const by = {
authors: authorSlugs,
visibility: 'public'
}
const vars = {
by,
limit,
offset
}
// console.debug(vars)
const response = await publicGraphQLClient.query(shoutsLoadBy, vars).toPromise()
if (response.error) {
console.error('[api-client] getArticlesForAuthors', response.error)
}
return response.data.shoutsByAuthors
},
// subscribe // subscribe
@ -312,18 +186,6 @@ export const apiClient = {
return response.data.refreshSession return response.data.refreshSession
}, },
getPublishedArticles: async ({ limit = FEED_SIZE, offset }: { limit?: number; offset?: number }) => {
const by = {
visibility: 'public'
}
const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit, offset }).toPromise()
if (response.error) {
console.error('[api-client] getPublishedArticles', response.error)
}
return response.data.recentPublished
},
getAllTopics: async () => { getAllTopics: async () => {
const response = await publicGraphQLClient.query(topicsAll, {}).toPromise() const response = await publicGraphQLClient.query(topicsAll, {}).toPromise()
if (response.error) { if (response.error) {
@ -346,34 +208,6 @@ export const apiClient = {
const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise() const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise()
return response.data.getTopic return response.data.getTopic
}, },
getArticle: async ({ slug }: { slug: string }): Promise<Shout> => {
const response = await publicGraphQLClient
.query(shoutsLoadBy, { by: { slug }, amount: 1, offset: 0 })
.toPromise()
return response.data?.getShoutBySlug
},
// reactions
getReactionsForShouts: async ({
shoutSlugs,
limit = FEED_SIZE,
offset = 0
}: {
shoutSlugs: string[]
limit?: number
offset?: number
}): Promise<Reaction[]> => {
const response = await publicGraphQLClient
.query(reactionsForShouts, {
shouts: shoutSlugs,
limit,
offset
})
.toPromise()
return response.data.reactionsForShouts
},
createArticle: async ({ article }: { article: ShoutInput }) => { createArticle: async ({ article }: { article: ShoutInput }) => {
const response = await privateGraphQLClient.mutation(createArticle, { shout: article }).toPromise() const response = await privateGraphQLClient.mutation(createArticle, { shout: article }).toPromise()
console.debug('createArticle response:', response) console.debug('createArticle response:', response)
@ -394,9 +228,6 @@ export const apiClient = {
return response.data.deleteReaction return response.data.deleteReaction
}, },
incrementView: async ({ articleSlug }) => {
await privateGraphQLClient.mutation(incrementView, { shout: articleSlug })
},
createChat: async ({ title, members }) => { createChat: async ({ title, members }) => {
return await privateGraphQLClient return await privateGraphQLClient
.mutation(createChatQuery, { title: title, members: members }) .mutation(createChatQuery, { title: title, members: members })
@ -407,31 +238,17 @@ export const apiClient = {
const resp = await privateGraphQLClient.query(myChats, payload).toPromise() const resp = await privateGraphQLClient.query(myChats, payload).toPromise()
return resp.data.myChats return resp.data.myChats
}, },
getRecentLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { loadAuthorsBy: async ({ by, amount = 50, offset = 0 }) => {
const by = { const resp = await publicGraphQLClient.query(authorsLoadBy, { by, amount, offset }).toPromise()
layout return resp.data.loadShoutsBy
}
const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, amount, offset }).toPromise()
return resp.data.recentLayoutShouts
}, },
getTopLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { loadShoutsBy: async ({ by, amount = 50, offset = 0 }) => {
const by = {
layout,
stat: 'rating',
order: 'rating'
}
const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, amount, offset }).toPromise() const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, amount, offset }).toPromise()
return resp.data.topLayoutShouts return resp.data.loadShoutsBy
}, },
getTopMonthLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { loadReactionsBy: async ({ by, amount = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }) => {
const by = { const resp = await publicGraphQLClient.query(reactionsLoadBy, { by, amount, offset }).toPromise()
layout, return resp.data.loadReactionsBy
stat: 'rating',
order: 'rating',
days: 30
}
const resp = await publicGraphQLClient.query(shoutsLoadBy, { amount, offset, layout }).toPromise()
return resp.data.topMonthLayoutShouts
}, },
getChatMessages: async ({ getChatMessages: async ({
chat, chat,

View File

@ -1,6 +1,6 @@
export const isDev = import.meta.env.MODE === 'development' export const isDev = import.meta.env.MODE === 'development'
export const apiBaseUrl = 'https://testapi.discours.io' //export const apiBaseUrl = 'https://testapi.discours.io'
// export const apiBaseUrl = 'https://newapi.discours.io' // export const apiBaseUrl = 'https://newapi.discours.io'
// testapi.discours.io // testapi.discours.io
// export const apiBaseUrl = 'http://localhost:8080' export const apiBaseUrl = 'http://localhost:8080'