catch up with backend refactoring

This commit is contained in:
Igor Lobanov 2022-11-18 03:23:04 +01:00
parent ee06ab54d2
commit 46b4ecc7ea
34 changed files with 213 additions and 140 deletions

View File

@ -1,11 +1,4 @@
# Astro + Solid.js
Created with
```
npm init astro -- --template framework-solid
yarn install
npm start
```
Astro working with [Solid](https://www.solidjs.com/).
Write your Solid components as `.jsx` or `.tsx` files in your project.

View File

@ -1,7 +1,7 @@
import { defineConfig, AstroUserConfig } from 'astro/config'
import vercel from '@astrojs/vercel/serverless'
import solidJs from '@astrojs/solid-js'
import type { CSSOptions, PluginOption } from 'vite'
import type { CSSOptions } from 'vite'
import defaultGenerateScopedName from 'postcss-modules/build/generateScopedName'
import { isDev } from './src/utils/config'
import { visualizer } from 'rollup-plugin-visualizer'

View File

@ -1,5 +1,5 @@
overwrite: true
schema: 'https://testapi.discours.io/graphql'
schema: 'http://v2.discours.io/graphql'
generates:
src/graphql/introspec.gen.ts:
plugins:

View File

@ -1,6 +1,8 @@
.Message {
.own {
// TODO
}
.body {
// message text
}

View File

@ -1,7 +1,7 @@
import { PageWrap } from '../_shared/PageWrap'
import { ArticleView } from '../Views/Article'
import type { PageProps } from '../types'
import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { loadShout, useArticlesStore } from '../../stores/zine/articles'
import { createMemo, onMount, Show } from 'solid-js'
import type { Shout } from '../../graphql/types.gen'
import { useRouter } from '../../stores/router'
@ -32,7 +32,7 @@ export const ArticlePage = (props: PageProps) => {
const articleValue = articleEntities()[slug()]
if (!articleValue || !articleValue.body) {
await loadShoutsBy({ by: { slug: slug() }, limit: 1, offset: 0 })
await loadShout(slug())
}
})

View File

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

View File

@ -2,7 +2,7 @@ import { HomeView, PRERENDERED_ARTICLES_COUNT } from '../Views/Home'
import { PageWrap } from '../_shared/PageWrap'
import type { PageProps } from '../types'
import { createSignal, onCleanup, onMount, Show } from 'solid-js'
import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { loadShouts, resetSortedArticles } from '../../stores/zine/articles'
import { loadRandomTopics } from '../../stores/zine/topics'
import { Loading } from '../Loading'
import styles from './HomePage.module.scss'
@ -15,7 +15,7 @@ export const HomePage = (props: PageProps) => {
return
}
await loadShoutsBy({ by: { visibility: 'public' }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
await loadShouts({ filters: { visibility: 'public' }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
await loadRandomTopics()
setIsLoaded(true)

View File

@ -1,14 +1,14 @@
import { PageWrap } from '../_shared/PageWrap'
import type { PageProps } from '../types'
import { createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles'
import { loadShouts, resetSortedArticles } from '../../stores/zine/articles'
import { useRouter } from '../../stores/router'
import { LayoutType, useLayoutsStore } from '../../stores/zine/layouts'
import { Loading } from '../Loading'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
import type { Shout } from '../../graphql/types.gen'
import { splitToPages } from '../../utils/splitToPages'
import clsx from 'clsx'
import { clsx } from 'clsx'
import { t } from '../../utils/intl'
import { Row3 } from '../Feed/Row3'
import { Row2 } from '../Feed/Row2'
@ -33,7 +33,8 @@ export const LayoutShoutsPage = (props: PageProps) => {
const loadMoreLayout = async (kind: LayoutType) => {
saveScrollPosition()
const { hasMore } = await loadLayoutShoutsBy({
by: { layout: kind },
// filters: { layout: kind },
limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length
})
@ -62,7 +63,7 @@ export const LayoutShoutsPage = (props: PageProps) => {
onMount(async () => {
if (!isLoaded()) {
await loadShoutsBy({ by: { layout: layout() }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
await loadShouts({ filters: { layout: layout() }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 })
}
})

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import { Row3 } from '../Feed/Row3'
import { AuthorFull } from '../Author/Full'
import { t } from '../../utils/intl'
import { useAuthorsStore } from '../../stores/zine/authors'
import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useTopicsStore } from '../../stores/zine/topics'
import { useRouter } from '../../stores/router'
@ -42,8 +42,8 @@ export const AuthorView = (props: AuthorProps) => {
const loadMore = async () => {
saveScrollPosition()
const { hasMore } = await loadShoutsBy({
by: { author: author().slug },
const { hasMore } = await loadShouts({
filters: { author: author().slug },
limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length
})

View File

@ -8,7 +8,7 @@ import { AuthorCard } from '../Author/Card'
import { t } from '../../utils/intl'
import { FeedSidebar } from '../Feed/Sidebar'
import CommentCard from '../Article/Comment'
import { useArticlesStore } from '../../stores/zine/articles'
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useReactionsStore } from '../../stores/zine/reactions'
import { useAuthorsStore } from '../../stores/zine/authors'
import { useTopicsStore } from '../../stores/zine/topics'
@ -28,7 +28,7 @@ export const FEED_PAGE_SIZE = 20
export const FeedView = () => {
// state
const { sortedArticles, loadShoutsBy } = useArticlesStore()
const { sortedArticles } = useArticlesStore()
const { sortedReactions: topComments, loadReactionsBy } = useReactionsStore({})
const { sortedAuthors } = useAuthorsStore()
const { topTopics } = useTopicsStore()
@ -37,8 +37,8 @@ export const FeedView = () => {
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const loadMore = async () => {
const { hasMore } = await loadShoutsBy({
by: { visibility: 'community' },
const { hasMore } = await loadShouts({
filters: { visibility: 'community' },
limit: FEED_PAGE_SIZE,
offset: sortedArticles().length
})
@ -57,7 +57,7 @@ export const FeedView = () => {
// load recent editing shouts ( visibility = authors )
const userslug = session().user.slug
await loadShoutsBy({ by: { author: userslug, visibility: 'authors' }, limit: 15, offset: 0 })
await loadShouts({ filters: { author: userslug, visibility: 'authors' }, limit: 15, offset: 0 })
const collaborativeShouts = sortedArticles().filter((s: Shout, n: number, arr: Shout[]) => {
if (s.visibility !== 'authors') {
arr.splice(n, 1)

View File

@ -14,7 +14,7 @@ import type { Shout, Topic } from '../../graphql/types.gen'
import { Icon } from '../_shared/Icon'
import { t } from '../../utils/intl'
import { useTopicsStore } from '../../stores/zine/topics'
import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useTopAuthorsStore } from '../../stores/zine/topAuthors'
import { locale } from '../../stores/ui'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
@ -48,8 +48,7 @@ export const HomeView = (props: HomeProps) => {
onMount(async () => {
if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) {
const { hasMore } = await loadShoutsBy({
by: {},
const { hasMore } = await loadShouts({
limit: CLIENT_LOAD_ARTICLES_COUNT,
offset: sortedArticles().length
})
@ -77,8 +76,8 @@ export const HomeView = (props: HomeProps) => {
const loadMore = async () => {
saveScrollPosition()
const { hasMore } = await loadShoutsBy({
by: { visibility: 'public' },
const { hasMore } = await loadShouts({
filters: { visibility: 'public' },
limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length
})

View File

@ -3,7 +3,7 @@ import '../../styles/Search.scss'
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 { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useRouter } from '../../stores/router'
type SearchPageSearchParams = {
@ -28,7 +28,7 @@ export const SearchView = (props: Props) => {
const handleSubmit = (_ev) => {
// TODO page
// TODO sort
loadShoutsBy({ by: { title: getQuery(), body: getQuery() }, limit: 50 })
loadShouts({ filters: { title: getQuery(), body: getQuery() }, limit: 50 })
}
return (

View File

@ -8,7 +8,7 @@ import { FullTopic } from '../Topic/Full'
import { t } from '../../utils/intl'
import { useRouter } from '../../stores/router'
import { useTopicsStore } from '../../stores/zine/topics'
import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles'
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useAuthorsStore } from '../../stores/zine/authors'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
import { splitToPages } from '../../utils/splitToPages'
@ -44,8 +44,8 @@ export const TopicView = (props: TopicProps) => {
const loadMore = async () => {
saveScrollPosition()
const { hasMore } = await loadShoutsBy({
by: { topic: topic().slug },
const { hasMore } = await loadShouts({
filters: { topic: topic().slug },
limit: LOAD_MORE_PAGE_SIZE,
offset: sortedArticles().length
})

View File

@ -1,8 +1,8 @@
import { gql } from '@urql/core'
export default gql`
query LoadShoutsByQuery($by: ShoutsBy, $limit: Int!, $offset: Int!) {
loadShoutsBy(by: $by, limit: $limit, offset: $offset) {
query LoadShoutsQuery($options: LoadShoutsOptions) {
loadShouts(options: $options) {
_id: slug
title
subtitle

View File

@ -0,0 +1,42 @@
import { gql } from '@urql/core'
export default gql`
query LoadShoutQuery($slug: String!) {
loadShout(slug: $slug) {
_id: slug
title
subtitle
slug
layout
cover
body
# community
mainTopic
topics {
title
body
slug
stat {
_id: shouts
shouts
authors
followers
}
}
authors {
_id: slug
name
slug
userpic
}
createdAt
publishedAt
stat {
_id: viewed
viewed
reacted
rating
}
}
}
`

View File

@ -12,11 +12,11 @@ export default gql`
links
createdAt
lastSeen
ratings {
_id: rater
rater
value
}
# ratings {
# _id: rater
# rater
# value
# }
}
}
`

View File

@ -8,15 +8,15 @@ export default gql`
name
bio
userpic
communities
# communities
links
createdAt
# createdAt
lastSeen
ratings {
_id: rater
rater
value
}
# ratings {
# _id: rater
# rater
# value
# }
}
}
`

View File

@ -1,7 +1,7 @@
import { gql } from '@urql/core'
export default gql`
query LoadReactionsByQuery($by: ReactionsBy, $limit: Int!, $offset: Int!) {
query LoadReactionsByQuery($by: ReactionBy!, $limit: Int!, $offset: Int!) {
loadReactionsBy(by: $by, limit: $limit, offset: $offset) {
id
createdBy {

View File

@ -80,6 +80,14 @@ export type ChatMember = {
userpic?: Maybe<Scalars['String']>
}
export type ChatUser = {
id: Scalars['Int']
lastSeen?: Maybe<Scalars['DateTime']>
name: Scalars['String']
slug: Scalars['String']
userpic?: Maybe<Scalars['String']>
}
export type Collab = {
authors: Array<Maybe<Scalars['String']>>
body?: Maybe<Scalars['String']>
@ -116,6 +124,25 @@ export enum FollowingEntity {
Topic = 'TOPIC'
}
export type LoadShoutsFilters = {
author?: InputMaybe<Scalars['String']>
body?: InputMaybe<Scalars['String']>
days?: InputMaybe<Scalars['Int']>
layout?: InputMaybe<Scalars['String']>
reacted?: InputMaybe<Scalars['Boolean']>
title?: InputMaybe<Scalars['String']>
topic?: InputMaybe<Scalars['String']>
visibility?: InputMaybe<Scalars['String']>
}
export type LoadShoutsOptions = {
filters?: InputMaybe<LoadShoutsFilters>
limit: Scalars['Int']
offset?: InputMaybe<Scalars['Int']>
order_by?: InputMaybe<Scalars['String']>
order_by_desc?: InputMaybe<Scalars['Boolean']>
}
export type Message = {
author: Scalars['String']
body: Scalars['String']
@ -183,7 +210,7 @@ export type MutationCreateChatArgs = {
export type MutationCreateMessageArgs = {
body: Scalars['String']
chatId: Scalars['String']
chat: Scalars['String']
replyTo?: InputMaybe<Scalars['String']>
}
@ -317,15 +344,17 @@ export type ProfileInput = {
export type Query = {
authorsAll: Array<Maybe<Author>>
getAuthor: User
chatUsersAll: Array<Maybe<ChatUser>>
getAuthor?: Maybe<User>
getCollabs: Array<Maybe<Collab>>
getTopic: Topic
getTopic?: Maybe<Topic>
isEmailUsed: Scalars['Boolean']
loadAuthorsBy: Array<Maybe<Author>>
loadChats: Result
loadMessagesBy: Result
loadReactionsBy: Array<Maybe<Reaction>>
loadShoutsBy: Array<Maybe<Shout>>
loadShout?: Maybe<Shout>
loadShouts: Array<Maybe<Shout>>
markdownBody: Scalars['String']
searchUsers: Result
signIn: AuthResult
@ -374,10 +403,12 @@ export type QueryLoadReactionsByArgs = {
offset?: InputMaybe<Scalars['Int']>
}
export type QueryLoadShoutsByArgs = {
by?: InputMaybe<ShoutsBy>
limit?: InputMaybe<Scalars['Int']>
offset?: InputMaybe<Scalars['Int']>
export type QueryLoadShoutArgs = {
slug: Scalars['String']
}
export type QueryLoadShoutsArgs = {
options?: InputMaybe<LoadShoutsOptions>
}
export type QueryMarkdownBodyArgs = {
@ -563,12 +594,12 @@ export type ShoutInput = {
visibleForUsers?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
}
export type ShoutsBy = {
export type ShoutsFilterBy = {
author?: InputMaybe<Scalars['String']>
authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
body?: InputMaybe<Scalars['String']>
days?: InputMaybe<Scalars['Int']>
layout?: InputMaybe<Scalars['String']>
order?: InputMaybe<Scalars['String']>
slug?: InputMaybe<Scalars['String']>
stat?: InputMaybe<Scalars['String']>
title?: InputMaybe<Scalars['String']>

View File

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

View File

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

View File

@ -4,13 +4,12 @@ import Prerendered from '../../main.astro'
import { apiClient } from '../../utils/apiClient'
import { initRouter } from '../../stores/router'
import type { LayoutType } from '../../stores/zine/layouts'
import { Layout } from '../../components/EditorExample/components/Layout'
const layout = (Astro.params.layout?.toString() || 'article') as LayoutType
if (!layout || layout.endsWith('.map')) {
return Astro.redirect('/404')
}
const shouts = await apiClient.loadShoutsBy({ by: { layout } })
const shouts = await apiClient.getShouts({ filters: { layout }, limit: 50 })
const { pathname, search } = Astro.url
initRouter(pathname, search)
---

View File

@ -1,7 +1,6 @@
---
import Prerendered from '../main.astro'
import { Root } from '../components/Root'
import { apiClient } from '../utils/apiClient'
import { initRouter } from '../stores/router'
const { pathname, search } = Astro.url

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
import type { Author, Shout, ShoutInput, ShoutsBy, Topic } from '../../graphql/types.gen'
import type { Author, Shout, ShoutInput, Topic, LoadShoutsOptions } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { addAuthorsByTopic } from './authors'
import { addTopicsByAuthor } from './topics'
@ -123,22 +123,18 @@ const addSortedArticles = (articles: Shout[]) => {
setSortedArticles((prevSortedArticles) => [...prevSortedArticles, ...articles])
}
export const loadShoutsBy = async ({
by,
limit,
offset = 0
}: {
by: ShoutsBy
limit: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.loadShoutsBy({
by,
limit: limit + 1,
offset
export const loadShout = async (slug: string): Promise<void> => {
const newArticle = await apiClient.getShout(slug)
addArticles([newArticle])
}
export const loadShouts = async (options: LoadShoutsOptions): Promise<{ hasMore: boolean }> => {
const newArticles = await apiClient.getShouts({
...options,
limit: options.limit + 1
})
const hasMore = newArticles.length === limit + 1
const hasMore = newArticles.length === options.limit + 1
if (hasMore) {
newArticles.splice(-1)
@ -176,7 +172,6 @@ export const useArticlesStore = (initialState: InitialState = {}) => {
return {
articleEntities,
sortedArticles,
loadShoutsBy,
articlesByAuthor,
articlesByLayout,
articlesByTopic,

View File

@ -38,7 +38,7 @@ const sortedAuthors = createLazyMemo(() => {
})
const addAuthors = (authors: Author[]) => {
const newAuthorEntities = authors.reduce((acc, author) => {
const newAuthorEntities = authors.filter(Boolean).reduce((acc, author) => {
acc[author.slug] = author
return acc
}, {} as Record<string, Author>)

View File

@ -1,6 +1,5 @@
import type { Shout, ShoutsBy } from '../../graphql/types.gen'
import type { Shout, LoadShoutsOptions } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { useArticlesStore } from './articles'
import { createSignal } from 'solid-js'
export type LayoutType = 'article' | 'audio' | 'video' | 'image' | 'literature'
@ -22,27 +21,18 @@ export const resetSortedLayoutShouts = () => {
setSortedLayoutShouts(new Map())
}
export const loadLayoutShoutsBy = async ({
by,
limit,
offset
}: {
by: ShoutsBy
limit?: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
const newLayoutShouts = await apiClient.loadShoutsBy({
by,
limit: limit + 1,
offset
export const loadLayoutShoutsBy = async (options: LoadShoutsOptions): Promise<{ hasMore: boolean }> => {
const newLayoutShouts = await apiClient.getShouts({
...options,
limit: options.limit + 1
})
const hasMore = newLayoutShouts.length === limit + 1
const hasMore = newLayoutShouts.length === options.limit + 1
if (hasMore) {
newLayoutShouts.splice(-1)
}
addLayoutShouts(by.layout as LayoutType, newLayoutShouts)
addLayoutShouts(options.filters.layout as LayoutType, newLayoutShouts)
return { hasMore }
}

View File

@ -16,7 +16,7 @@ export const loadReactionsBy = async ({
limit?: number
offset?: number
}): Promise<{ hasMore: boolean }> => {
const data = await apiClient.loadReactionsBy({ by, limit: limit + 1, offset })
const data = await apiClient.getReactionsBy({ by, limit: limit + 1, offset })
const hasMore = data.length === limit + 1
if (hasMore) data.splice(-1)
// TODO: const [data, provider] = roomConnect(articleSlug, username, "reactions")

View File

@ -7,18 +7,19 @@ main {
.messages {
display: none;
//top: 74px;
//height: calc(100% - 74px);
//left: 0;
//right: 0;
//padding-left: 42px;
//padding-right: 26px;
//background: #fff;
//display: flex;
//flex: 1;
//flex-direction: column;
//position: fixed;
//z-index: 9;
// top: 74px;
// height: calc(100% - 74px);
// left: 0;
// right: 0;
// padding-left: 42px;
// padding-right: 26px;
// background: #fff;
// display: flex;
// flex: 1;
// flex-direction: column;
// position: fixed;
// z-index: 9;
> .row {
flex: 1;
@ -165,10 +166,10 @@ main {
.message-form {
background: #fff;
padding: 2px 0 12px 0;
padding: 2px 0 12px;
> .wrapper {
border: 2px solid #cccccc;
border: 2px solid #ccc;
border-radius: 16px;
padding: 4px;
display: flex;
@ -291,6 +292,7 @@ main {
a {
color: inherit;
text-decoration: underline;
&:hover {
color: inherit;
}

View File

@ -1,4 +1,11 @@
import type { FollowingEntity, AuthResult, ShoutInput, Topic, Author } from '../graphql/types.gen'
import type {
FollowingEntity,
AuthResult,
ShoutInput,
Topic,
Author,
LoadShoutsOptions
} from '../graphql/types.gen'
import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
import topicsAll from '../graphql/query/topics-all'
@ -26,8 +33,7 @@ import reactionsLoadBy from '../graphql/query/reactions-load-by'
import { REACTIONS_AMOUNT_PER_PAGE } from '../stores/zine/reactions'
import authorsLoadBy from '../graphql/query/authors-load-by'
import shoutsLoadBy from '../graphql/query/articles-load-by'
const FEED_SIZE = 50
import shoutLoad from '../graphql/query/articles-load'
type ApiErrorCode =
| 'unknown'
@ -194,6 +200,7 @@ export const apiClient = {
},
getAuthor: async ({ slug }: { slug: string }): Promise<Author> => {
const response = await publicGraphQLClient.query(authorBySlug, { slug }).toPromise()
console.error('getAuthor', response)
return response.data.getAuthor
},
getTopic: async ({ slug }: { slug: string }): Promise<Topic> => {
@ -229,20 +236,33 @@ export const apiClient = {
return response.data.deleteReaction
},
// LOAD BY
loadAuthorsBy: async ({ by, limit = 50, offset = 0 }) => {
getAuthorsBy: async ({ by, limit = 50, offset = 0 }) => {
const resp = await publicGraphQLClient.query(authorsLoadBy, { by, limit, offset }).toPromise()
console.debug(resp)
return resp.data.loadShoutsBy
return resp.data.loadAuthorsBy
},
loadShoutsBy: async ({ by, limit = 50, offset = 0 }) => {
const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, limit, offset }).toPromise()
console.debug(resp)
return resp.data.loadShoutsBy
getShout: async (slug: string) => {
const resp = await publicGraphQLClient
.query(shoutLoad, {
slug
})
.toPromise()
return resp.data.loadShout
},
loadReactionsBy: async ({ by, limit = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }) => {
getShouts: async (options: LoadShoutsOptions) => {
const resp = await publicGraphQLClient
.query(shoutsLoadBy, {
options
})
.toPromise()
// console.debug(resp)
return resp.data.loadShouts
},
getReactionsBy: async ({ by, limit = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }) => {
const resp = await publicGraphQLClient.query(reactionsLoadBy, { by, limit, offset }).toPromise()
console.log('resactions response', resp)
return resp.data.loadReactionsBy
},