diff --git a/README.md b/README.md index c11373be..e7ebf05d 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/astro.config.ts b/astro.config.ts index c55017c3..c2ca1005 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -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' diff --git a/codegen.yml b/codegen.yml index 04ea8542..c5d2d3fa 100644 --- a/codegen.yml +++ b/codegen.yml @@ -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: diff --git a/src/components/Inbox/Message.module.scss b/src/components/Inbox/Message.module.scss index b80f3594..c1612044 100644 --- a/src/components/Inbox/Message.module.scss +++ b/src/components/Inbox/Message.module.scss @@ -1,6 +1,8 @@ .Message { .own { + // TODO } + .body { // message text } diff --git a/src/components/Pages/ArticlePage.tsx b/src/components/Pages/ArticlePage.tsx index 460a7f5f..349c40ff 100644 --- a/src/components/Pages/ArticlePage.tsx +++ b/src/components/Pages/ArticlePage.tsx @@ -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()) } }) diff --git a/src/components/Pages/AuthorPage.tsx b/src/components/Pages/AuthorPage.tsx index 7bde9aaa..556fbea3 100644 --- a/src/components/Pages/AuthorPage.tsx +++ b/src/components/Pages/AuthorPage.tsx @@ -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) diff --git a/src/components/Pages/HomePage.tsx b/src/components/Pages/HomePage.tsx index 4898d65f..670374a2 100644 --- a/src/components/Pages/HomePage.tsx +++ b/src/components/Pages/HomePage.tsx @@ -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) diff --git a/src/components/Pages/LayoutShoutsPage.tsx b/src/components/Pages/LayoutShoutsPage.tsx index 84052e2c..2082a12e 100644 --- a/src/components/Pages/LayoutShoutsPage.tsx +++ b/src/components/Pages/LayoutShoutsPage.tsx @@ -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 }) } }) diff --git a/src/components/Pages/SearchPage.tsx b/src/components/Pages/SearchPage.tsx index aabf7214..fde6bdaf 100644 --- a/src/components/Pages/SearchPage.tsx +++ b/src/components/Pages/SearchPage.tsx @@ -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) }) diff --git a/src/components/Pages/TopicPage.tsx b/src/components/Pages/TopicPage.tsx index fc314cd7..1135cdd3 100644 --- a/src/components/Pages/TopicPage.tsx +++ b/src/components/Pages/TopicPage.tsx @@ -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) diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index 5f6a2720..91db2bd3 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -37,7 +37,7 @@ export const AllAuthorsView = (props: Props) => { const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { return sortedAuthors().reduce((acc, author) => { let letter = author.name.trim().split(' ').pop().at(0).toUpperCase() - if (!/[а-яА-Я]/i.test(letter) && locale() === 'ru') letter = '@' + if (!/[А-я]/i.test(letter) && locale() === 'ru') letter = '@' if (!acc[letter]) acc[letter] = [] acc[letter].push(author) return acc diff --git a/src/components/Views/AllTopics.tsx b/src/components/Views/AllTopics.tsx index 4e2fe920..562c72a5 100644 --- a/src/components/Views/AllTopics.tsx +++ b/src/components/Views/AllTopics.tsx @@ -1,4 +1,4 @@ -import { createEffect, createMemo, createSignal, For, onMount, Show } from 'solid-js' +import { createEffect, createMemo, createSignal, For, Show } from 'solid-js' import type { Topic } from '../../graphql/types.gen' import { Icon } from '../_shared/Icon' import { t } from '../../utils/intl' @@ -40,7 +40,7 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => { return sortedTopics().reduce((acc, topic) => { let letter = topic.title[0].toUpperCase() - if (!/[а-яА-Я]/i.test(letter) && locale() === 'ru') letter = '#' + if (!/[А-я]/i.test(letter) && locale() === 'ru') letter = '#' if (!acc[letter]) acc[letter] = [] acc[letter].push(topic) return acc @@ -58,7 +58,8 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { const showMore = () => setLimit((oldLimit) => oldLimit + PAGE_SIZE) let searchEl: HTMLInputElement const [searchResults, setSearchResults] = createSignal([]) - const searchTopics = (ev) => { + // eslint-disable-next-line sonarjs/cognitive-complexity + const searchTopics = () => { /* very stupid search algorithm with no deps */ let q = searchEl.value.toLowerCase() if (q.length > 0) { @@ -66,29 +67,29 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { setSearchResults([]) if (locale() === 'ru') q = translit(q, 'ru') - let ttt: Topic[] = [] - sortedTopics().forEach((t: Topic) => { + const ttt: Topic[] = [] + sortedTopics().forEach((topic) => { let flag = false - t.slug.split('-').forEach((w) => { + topic.slug.split('-').forEach((w) => { if (w.startsWith(q)) flag = true }) if (!flag) { - let wrds: string = t.title.toLowerCase() + let wrds: string = topic.title.toLowerCase() if (locale() === 'ru') wrds = translit(wrds, 'ru') wrds.split(' ').forEach((w: string) => { if (w.startsWith(q)) flag = true }) } - if (flag && !ttt.includes(t)) ttt.push(t) + if (flag && !ttt.includes(topic)) ttt.push(topic) }) setSearchResults((sr: Topic[]) => [...sr, ...ttt]) changeSearchParam('by', '') } } - createEffect(() => {}) + const AllTopicsHead = () => (
diff --git a/src/components/Views/Author.tsx b/src/components/Views/Author.tsx index 6bbf77a0..ab64da1b 100644 --- a/src/components/Views/Author.tsx +++ b/src/components/Views/Author.tsx @@ -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 }) diff --git a/src/components/Views/Feed.tsx b/src/components/Views/Feed.tsx index 3a173bf0..c4d481fe 100644 --- a/src/components/Views/Feed.tsx +++ b/src/components/Views/Feed.tsx @@ -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) diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index 8fd58639..1378b453 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -11,10 +11,9 @@ import RowShort from '../Feed/RowShort' import Slider from '../Feed/Slider' import Group from '../Feed/Group' 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 +47,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 +75,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 }) diff --git a/src/components/Views/Search.tsx b/src/components/Views/Search.tsx index 062076c9..804f300f 100644 --- a/src/components/Views/Search.tsx +++ b/src/components/Views/Search.tsx @@ -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 { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' import { useRouter } from '../../stores/router' @@ -32,8 +32,8 @@ export const SearchView = (props: Props) => { const loadMore = async () => { saveScrollPosition() - const { hasMore } = await loadShoutsBy({ - by: { + const { hasMore } = await loadShouts({ + filters: { title: query(), body: query() }, diff --git a/src/components/Views/Topic.tsx b/src/components/Views/Topic.tsx index 81316cd6..f3ee8676 100644 --- a/src/components/Views/Topic.tsx +++ b/src/components/Views/Topic.tsx @@ -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 }) diff --git a/src/graphql/query/articles-load-by.ts b/src/graphql/query/articles-load-by.ts index a2d0891a..a006f1a7 100644 --- a/src/graphql/query/articles-load-by.ts +++ b/src/graphql/query/articles-load-by.ts @@ -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 diff --git a/src/graphql/query/articles-load.ts b/src/graphql/query/articles-load.ts new file mode 100644 index 00000000..276ef97e --- /dev/null +++ b/src/graphql/query/articles-load.ts @@ -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 + } + } + } +` diff --git a/src/graphql/query/author-by-slug.ts b/src/graphql/query/author-by-slug.ts index bf35df61..d25ae0ab 100644 --- a/src/graphql/query/author-by-slug.ts +++ b/src/graphql/query/author-by-slug.ts @@ -12,11 +12,11 @@ export default gql` links createdAt lastSeen - ratings { - _id: rater - rater - value - } + # ratings { + # _id: rater + # rater + # value + # } } } ` diff --git a/src/graphql/query/authors-load-by.ts b/src/graphql/query/authors-load-by.ts index 6463c488..a76bf102 100644 --- a/src/graphql/query/authors-load-by.ts +++ b/src/graphql/query/authors-load-by.ts @@ -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 + # } } } ` diff --git a/src/graphql/query/reactions-load-by.ts b/src/graphql/query/reactions-load-by.ts index 70990f49..914dc98d 100644 --- a/src/graphql/query/reactions-load-by.ts +++ b/src/graphql/query/reactions-load-by.ts @@ -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 { diff --git a/src/graphql/types.gen.ts b/src/graphql/types.gen.ts index 7ea1e0cf..a3bc45d2 100644 --- a/src/graphql/types.gen.ts +++ b/src/graphql/types.gen.ts @@ -80,6 +80,14 @@ export type ChatMember = { userpic?: Maybe } +export type ChatUser = { + id: Scalars['Int'] + lastSeen?: Maybe + name: Scalars['String'] + slug: Scalars['String'] + userpic?: Maybe +} + export type Collab = { authors: Array> body?: Maybe @@ -116,6 +124,25 @@ export enum FollowingEntity { Topic = 'TOPIC' } +export type LoadShoutsFilters = { + author?: InputMaybe + body?: InputMaybe + days?: InputMaybe + layout?: InputMaybe + reacted?: InputMaybe + title?: InputMaybe + topic?: InputMaybe + visibility?: InputMaybe +} + +export type LoadShoutsOptions = { + filters?: InputMaybe + limit: Scalars['Int'] + offset?: InputMaybe + order_by?: InputMaybe + order_by_desc?: InputMaybe +} + 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 } @@ -317,15 +344,17 @@ export type ProfileInput = { export type Query = { authorsAll: Array> - getAuthor: User + chatUsersAll: Array> + getAuthor?: Maybe getCollabs: Array> - getTopic: Topic + getTopic?: Maybe isEmailUsed: Scalars['Boolean'] loadAuthorsBy: Array> loadChats: Result loadMessagesBy: Result loadReactionsBy: Array> - loadShoutsBy: Array> + loadShout?: Maybe + loadShouts: Array> markdownBody: Scalars['String'] searchUsers: Result signIn: AuthResult @@ -374,10 +403,12 @@ export type QueryLoadReactionsByArgs = { offset?: InputMaybe } -export type QueryLoadShoutsByArgs = { - by?: InputMaybe - limit?: InputMaybe - offset?: InputMaybe +export type QueryLoadShoutArgs = { + slug: Scalars['String'] +} + +export type QueryLoadShoutsArgs = { + options?: InputMaybe } export type QueryMarkdownBodyArgs = { @@ -563,12 +594,12 @@ export type ShoutInput = { visibleForUsers?: InputMaybe>> } -export type ShoutsBy = { +export type ShoutsFilterBy = { author?: InputMaybe + authors?: InputMaybe>> body?: InputMaybe days?: InputMaybe layout?: InputMaybe - order?: InputMaybe slug?: InputMaybe stat?: InputMaybe title?: InputMaybe diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 0e0e13c0..1fd64acd 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -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' --- - + diff --git a/src/pages/author/[slug]/index.astro b/src/pages/author/[slug]/index.astro index efcd8ffd..97153431 100644 --- a/src/pages/author/[slug]/index.astro +++ b/src/pages/author/[slug]/index.astro @@ -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) diff --git a/src/pages/expo/[...layout].astro b/src/pages/expo/[...layout].astro index 858bbf01..c6f5201d 100644 --- a/src/pages/expo/[...layout].astro +++ b/src/pages/expo/[...layout].astro @@ -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) --- diff --git a/src/pages/inbox.astro b/src/pages/inbox.astro index e613673f..41af9430 100644 --- a/src/pages/inbox.astro +++ b/src/pages/inbox.astro @@ -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 diff --git a/src/pages/index.astro b/src/pages/index.astro index 2bf6b0bd..929af43a 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -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) diff --git a/src/pages/search.astro b/src/pages/search.astro index 21dd5fad..dd027bc4 100644 --- a/src/pages/search.astro +++ b/src/pages/search.astro @@ -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) diff --git a/src/pages/topic/[slug].astro b/src/pages/topic/[slug].astro index 4b43c5c0..3fa5c183 100644 --- a/src/pages/topic/[slug].astro +++ b/src/pages/topic/[slug].astro @@ -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' diff --git a/src/stores/zine/articles.ts b/src/stores/zine/articles.ts index 9638d803..54fc1a28 100644 --- a/src/stores/zine/articles.ts +++ b/src/stores/zine/articles.ts @@ -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 => { + 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, diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index 527ae5e5..49d8b53c 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -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) diff --git a/src/stores/zine/layouts.ts b/src/stores/zine/layouts.ts index 9ff3d4a0..b96ea96c 100644 --- a/src/stores/zine/layouts.ts +++ b/src/stores/zine/layouts.ts @@ -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 } } diff --git a/src/stores/zine/reactions.ts b/src/stores/zine/reactions.ts index d46db96a..784136fa 100644 --- a/src/stores/zine/reactions.ts +++ b/src/stores/zine/reactions.ts @@ -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") diff --git a/src/styles/Inbox.scss b/src/styles/Inbox.scss index b2c57920..a44bd748 100644 --- a/src/styles/Inbox.scss +++ b/src/styles/Inbox.scss @@ -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; } diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index e64037ef..f263cb3d 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -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 => { const response = await publicGraphQLClient.query(authorBySlug, { slug }).toPromise() + console.error('getAuthor', response) return response.data.getAuthor }, getTopic: async ({ slug }: { slug: string }): Promise => { @@ -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 },