From 9a78c859ae05271eb5d42e13e38bf4becb5bfd91 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Wed, 5 Oct 2022 13:13:15 +0200 Subject: [PATCH 1/4] WIP --- astro.config.ts | 1 - src/components/Views/AllAuthors.tsx | 20 ++++++++++++-------- src/layouts/zine.astro | 2 +- src/pages/authors.astro | 2 -- src/pages/topics.astro | 2 -- src/stores/zine/authors.ts | 4 ++-- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/astro.config.ts b/astro.config.ts index d6edf5f6..fb57d0b1 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -18,7 +18,6 @@ const getDevCssClassPrefix = (filename: string): string => { .slice(filename.indexOf(PATH_PREFIX) + PATH_PREFIX.length) .replace('.module.scss', '') .replace(/[/?\\]/g, '-') - .replace('?', '-') } const devGenerateScopedName = (name: string, filename: string, css: string) => diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index dbe5ddc4..f6bad799 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -8,8 +8,11 @@ import { t } from '../../utils/intl' import { useAuthorsStore } from '../../stores/zine/authors' import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { useAuthStore } from '../../stores/auth' +import { getLogger } from '../../utils/logger' import '../../styles/AllTopics.scss' +const log = getLogger('AllAuthorsView') + type AllAuthorsPageSearchParams = { by: '' | 'name' | 'shouts' | 'rating' } @@ -19,8 +22,7 @@ type Props = { } export const AllAuthorsView = (props: Props) => { - const { sortedAuthors: authorList } = useAuthorsStore({ authors: props.authors }) - const [sortedAuthors, setSortedAuthors] = createSignal([]) + const { sortedAuthors } = useAuthorsStore({ authors: props.authors }) const [sortedKeys, setSortedKeys] = createSignal([]) const [abc, setAbc] = createSignal([]) @@ -33,17 +35,19 @@ export const AllAuthorsView = (props: Props) => { createEffect(() => { if ((!getSearchParams().by || getSearchParams().by === 'name') && abc().length === 0) { console.log('[authors] default grouping by abc') - const grouped = { ...groupByName(authorList()) } + const grouped = { ...groupByName(sortedAuthors()) } grouped['A-Z'] = sortBy(grouped['A-Z'], byFirstChar) setAbc(grouped) const keys = Object.keys(abc) keys.sort() - setSortedKeys(keys as string[]) + setSortedKeys(keys) } else { console.log('[authors] sorting by ' + getSearchParams().by) - setSortedAuthors(sortBy(authorList(), getSearchParams().by)) + ///setSortedAuthors(sortBy(authorList(), getSearchParams().by)) } - }, [authorList(), getSearchParams().by]) + }) + + log.debug(getSearchParams()) return (
@@ -86,7 +90,7 @@ export const AllAuthorsView = (props: Props) => { fallback={() => (
- {(author: Author) => ( + {(author) => ( { )} > - {(letter: string) => ( + {(letter) => (

{letter}

diff --git a/src/layouts/zine.astro b/src/layouts/zine.astro index e4ce1d99..41be19e4 100644 --- a/src/layouts/zine.astro +++ b/src/layouts/zine.astro @@ -4,7 +4,7 @@ import '../styles/app.scss' import { t } from '../utils/intl' const lang = Astro.url.searchParams.get('lang') || 'ru' -// console.log('[layout] server locale is', lang) +console.log('[layout] server locale is', lang) setLocale(lang) --- diff --git a/src/pages/authors.astro b/src/pages/authors.astro index f3cd2131..2cb49a90 100644 --- a/src/pages/authors.astro +++ b/src/pages/authors.astro @@ -8,8 +8,6 @@ const authors = await apiClient.getAllAuthors() const { pathname, search } = Astro.url initRouter(pathname, search) - -Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate') --- diff --git a/src/pages/topics.astro b/src/pages/topics.astro index 633ca6b3..0ab55341 100644 --- a/src/pages/topics.astro +++ b/src/pages/topics.astro @@ -6,8 +6,6 @@ import { initRouter } from '../stores/router' const topics = await apiClient.getAllTopics() -Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate') - const { pathname, search } = Astro.url initRouter(pathname, search) --- diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index c09604dc..567f70a1 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -19,12 +19,12 @@ const sortedAuthors = createLazyMemo(() => { const authors = Object.values(authorEntities()) switch (sortAllBy()) { case 'created': { - // log.debug('sorted by created') + log.debug('sorted by created') authors.sort(byCreated) break } case 'name': { - // log.debug('sorted by name') + log.debug('sorted by name') authors.sort((a, b) => a.name.localeCompare(b.name)) break } From 32bbedfa1751a0fe87335c4466cadbdeffe113f8 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Wed, 5 Oct 2022 14:32:23 +0200 Subject: [PATCH 2/4] WIP --- src/graphql/types.gen.ts | 5 +++++ src/utils/apiClient.ts | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/src/graphql/types.gen.ts b/src/graphql/types.gen.ts index a2b73043..8c85b2f2 100644 --- a/src/graphql/types.gen.ts +++ b/src/graphql/types.gen.ts @@ -344,6 +344,7 @@ export type Query = { getUsersBySlugs: Array> isEmailUsed: Scalars['Boolean'] loadChat: Array> + markdownBody: Scalars['String'] myChats: Array> reactionsByAuthor: Array> reactionsByShout: Array> @@ -411,6 +412,10 @@ export type QueryLoadChatArgs = { size: Scalars['Int'] } +export type QueryMarkdownBodyArgs = { + body: Scalars['String'] +} + export type QueryReactionsByAuthorArgs = { limit: Scalars['Int'] offset: Scalars['Int'] diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index 4cf7ef76..4cd6c3ce 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -176,6 +176,10 @@ export const apiClient = { }) .toPromise() + if (response.error) { + log.error('getArticlesForTopics', response.error) + } + return response.data.shoutsByTopics }, getArticlesForAuthors: async ({ @@ -195,6 +199,10 @@ export const apiClient = { }) .toPromise() + if (response.error) { + log.error('getArticlesForAuthors', response.error) + } + return response.data.shoutsByAuthors }, From e63b018efa5b40dd445b46c890506adb68c9870e Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Wed, 5 Oct 2022 17:11:14 +0200 Subject: [PATCH 3/4] client data fetching --- src/components/Nav/Header.tsx | 2 +- src/components/Pages/AllAuthorsPage.tsx | 18 ++++++++++++- src/components/Pages/AllTopicsPage.tsx | 18 ++++++++++++- src/components/Pages/ArticlePage.tsx | 21 ++++++++------- src/components/Pages/AuthorPage.tsx | 36 ++++++++++++++++++++++++- src/components/Pages/FeedPage.tsx | 21 ++++++++++++++- src/components/Pages/HomePage.tsx | 23 +++++++++++++++- src/components/Pages/SearchPage.tsx | 33 ++++++++++++++++++++++- src/components/Pages/TopicPage.tsx | 36 ++++++++++++++++++++++++- src/components/Views/Author.tsx | 16 +++-------- src/components/Views/Home.tsx | 4 +-- src/components/Views/Topic.tsx | 12 ++++----- src/components/types.ts | 9 ++++--- src/pages/author/[slug]/index.astro | 2 +- src/pages/authors.astro | 2 +- src/pages/feed/index.astro | 2 +- src/pages/index.astro | 2 +- src/pages/topic/[slug].astro | 2 +- src/pages/topics.astro | 2 +- src/stores/zine/articles.ts | 16 +++++++++++ src/stores/zine/authors.ts | 7 +++++ src/stores/zine/topics.ts | 12 +++++++++ src/utils/apiClient.ts | 4 +++ 23 files changed, 254 insertions(+), 46 deletions(-) diff --git a/src/components/Nav/Header.tsx b/src/components/Nav/Header.tsx index c8109da7..0d0a08f2 100644 --- a/src/components/Nav/Header.tsx +++ b/src/components/Nav/Header.tsx @@ -71,7 +71,7 @@ export const Header = (props: Props) => { onMount(() => { let scrollTop = window.scrollY - window.console.log(props.title) + // window.console.log(props.title) const handleScroll = () => { setIsScrollingBottom(window.scrollY > scrollTop) diff --git a/src/components/Pages/AllAuthorsPage.tsx b/src/components/Pages/AllAuthorsPage.tsx index 4e6dee4c..78e95682 100644 --- a/src/components/Pages/AllAuthorsPage.tsx +++ b/src/components/Pages/AllAuthorsPage.tsx @@ -1,11 +1,27 @@ import { MainLayout } from '../Layouts/MainLayout' import { AllAuthorsView } from '../Views/AllAuthors' import type { PageProps } from '../types' +import { createSignal, onMount, Show } from 'solid-js' +import { loadAllAuthors } from '../../stores/zine/authors' +import { t } from '../../utils/intl' export const AllAuthorsPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.allAuthors)) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadAllAuthors() + setIsLoaded(true) + }) + return ( - + + + ) } diff --git a/src/components/Pages/AllTopicsPage.tsx b/src/components/Pages/AllTopicsPage.tsx index 745a6524..2e371ba6 100644 --- a/src/components/Pages/AllTopicsPage.tsx +++ b/src/components/Pages/AllTopicsPage.tsx @@ -1,11 +1,27 @@ import { MainLayout } from '../Layouts/MainLayout' import { AllTopicsView } from '../Views/AllTopics' import type { PageProps } from '../types' +import { createSignal, onMount, Show } from 'solid-js' +import { t } from '../../utils/intl' +import { loadAllTopics } from '../../stores/zine/topics' export const AllTopicsPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.allTopics)) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadAllTopics() + setIsLoaded(true) + }) + return ( - + + + ) } diff --git a/src/components/Pages/ArticlePage.tsx b/src/components/Pages/ArticlePage.tsx index 74c8a338..cc7fb918 100644 --- a/src/components/Pages/ArticlePage.tsx +++ b/src/components/Pages/ArticlePage.tsx @@ -10,26 +10,29 @@ import { useRouter } from '../../stores/router' export const ArticlePage = (props: PageProps) => { const sortedArticles = props.article ? [props.article] : [] - const { getPage } = useRouter() + const slug = createMemo(() => { + const { getPage } = useRouter() - const page = getPage() + const page = getPage() - if (page.route !== 'article') { - throw new Error('ts guard') - } + if (page.route !== 'article') { + throw new Error('ts guard') + } + + return page.params.slug + }) const { articleEntities } = useArticlesStore({ sortedArticles }) - const article = createMemo(() => articleEntities()[page.params.slug]) + const article = createMemo(() => articleEntities()[slug()]) onMount(() => { - const slug = page.params.slug - const articleValue = articleEntities()[slug] + const articleValue = articleEntities()[slug()] if (!articleValue || !articleValue.body) { - loadArticle({ slug }) + loadArticle({ slug: slug() }) } }) diff --git a/src/components/Pages/AuthorPage.tsx b/src/components/Pages/AuthorPage.tsx index a57c4dad..aa825fd9 100644 --- a/src/components/Pages/AuthorPage.tsx +++ b/src/components/Pages/AuthorPage.tsx @@ -1,11 +1,45 @@ import { MainLayout } from '../Layouts/MainLayout' import { AuthorView } from '../Views/Author' import type { PageProps } from '../types' +import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' +import { loadArticlesForAuthors, resetSortedArticles } from '../../stores/zine/articles' +import { useRouter } from '../../stores/router' +import { t } from '../../utils/intl' +import { loadAuthor } from '../../stores/zine/authors' export const AuthorPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.authorArticles) && Boolean(props.author)) + + const slug = createMemo(() => { + const { getPage } = useRouter() + + const page = getPage() + + if (page.route !== 'author') { + throw new Error('ts guard') + } + + return page.params.slug + }) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadArticlesForAuthors({ authorSlugs: [slug()] }) + await loadAuthor({ slug: slug() }) + + setIsLoaded(true) + }) + + onCleanup(() => resetSortedArticles()) + return ( - + + + ) } diff --git a/src/components/Pages/FeedPage.tsx b/src/components/Pages/FeedPage.tsx index de95f1b6..1e015e69 100644 --- a/src/components/Pages/FeedPage.tsx +++ b/src/components/Pages/FeedPage.tsx @@ -1,11 +1,30 @@ import { MainLayout } from '../Layouts/MainLayout' import { FeedView } from '../Views/Feed' import type { PageProps } from '../types' +import { createSignal, onCleanup, onMount, Show } from 'solid-js' +import { loadRecentArticles, resetSortedArticles } from '../../stores/zine/articles' +import { t } from '../../utils/intl' export const FeedPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.feedArticles)) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadRecentArticles({ limit: 50, offset: 0 }) + + setIsLoaded(true) + }) + + onCleanup(() => resetSortedArticles()) + return ( - + + + ) } diff --git a/src/components/Pages/HomePage.tsx b/src/components/Pages/HomePage.tsx index 78f5b3d1..cbfb9d10 100644 --- a/src/components/Pages/HomePage.tsx +++ b/src/components/Pages/HomePage.tsx @@ -1,11 +1,32 @@ import { HomeView } from '../Views/Home' import { MainLayout } from '../Layouts/MainLayout' import type { PageProps } from '../types' +import { createSignal, onCleanup, onMount, Show } from 'solid-js' +import { t } from '../../utils/intl' +import { loadPublishedArticles, resetSortedArticles } from '../../stores/zine/articles' +import { loadRandomTopics } from '../../stores/zine/topics' export const HomePage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.homeArticles) && Boolean(props.randomTopics)) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadPublishedArticles({ limit: 5, offset: 0 }) + await loadRandomTopics() + + setIsLoaded(true) + }) + + onCleanup(() => resetSortedArticles()) + return ( - + + + ) } diff --git a/src/components/Pages/SearchPage.tsx b/src/components/Pages/SearchPage.tsx index 830c00a9..b7668cf9 100644 --- a/src/components/Pages/SearchPage.tsx +++ b/src/components/Pages/SearchPage.tsx @@ -1,11 +1,42 @@ import { MainLayout } from '../Layouts/MainLayout' import { SearchView } from '../Views/Search' import type { PageProps } from '../types' +import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' +import { loadSearchResults, resetSortedArticles } from '../../stores/zine/articles' +import { t } from '../../utils/intl' +import { useRouter } from '../../stores/router' export const SearchPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.searchResults)) + + const q = createMemo(() => { + const { getPage } = useRouter() + + const page = getPage() + + if (page.route !== 'search') { + throw new Error('ts guard') + } + + return page.params.q + }) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadSearchResults({ query: q(), limit: 50, offset: 0 }) + setIsLoaded(true) + }) + + onCleanup(() => resetSortedArticles()) + return ( - + + + ) } diff --git a/src/components/Pages/TopicPage.tsx b/src/components/Pages/TopicPage.tsx index f6605f81..f974f20e 100644 --- a/src/components/Pages/TopicPage.tsx +++ b/src/components/Pages/TopicPage.tsx @@ -1,11 +1,45 @@ import { MainLayout } from '../Layouts/MainLayout' import { TopicView } from '../Views/Topic' import type { PageProps } from '../types' +import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' +import { loadArticlesForTopics, resetSortedArticles } from '../../stores/zine/articles' +import { useRouter } from '../../stores/router' +import { t } from '../../utils/intl' +import { loadTopic } from '../../stores/zine/topics' export const TopicPage = (props: PageProps) => { + const [isLoaded, setIsLoaded] = createSignal(Boolean(props.authorArticles) && Boolean(props.author)) + + const slug = createMemo(() => { + const { getPage } = useRouter() + + const page = getPage() + + if (page.route !== 'author') { + throw new Error('ts guard') + } + + return page.params.slug + }) + + onMount(async () => { + if (isLoaded()) { + return + } + + await loadArticlesForTopics({ topicSlugs: [slug()] }) + await loadTopic({ slug: slug() }) + + setIsLoaded(true) + }) + + onCleanup(() => resetSortedArticles()) + return ( - + + + ) } diff --git a/src/components/Views/Author.tsx b/src/components/Views/Author.tsx index 16f43e3e..d4afed8b 100644 --- a/src/components/Views/Author.tsx +++ b/src/components/Views/Author.tsx @@ -16,6 +16,7 @@ import { useRouter } from '../../stores/router' type AuthorProps = { authorArticles: Shout[] author: Author + authorSlug: string // FIXME author topics fro server // topics: Topic[] } @@ -30,18 +31,9 @@ export const AuthorView = (props: AuthorProps) => { }) const { authorEntities } = useAuthorsStore({ authors: [props.author] }) - const author = createMemo(() => authorEntities()[props.author.slug]) + const author = createMemo(() => authorEntities()[props.authorSlug]) const { getSearchParams, changeSearchParam } = useRouter() - //const slug = createMemo(() => author().slug) - /* - const slug = createMemo(() => { - let slug = props?.slug - if (props?.slug.startsWith('@')) slug = slug.replace('@', '') - return slug - }) - */ - const title = createMemo(() => { const m = getSearchParams().by if (m === 'viewed') return t('Top viewed') @@ -101,8 +93,8 @@ export const AuthorView = (props: AuthorProps) => { {/*/>*/} - - + +
diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index b508a63e..542325c7 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -1,4 +1,4 @@ -import { createMemo, For, onMount, Show } from 'solid-js' +import { createEffect, createMemo, For, onMount, Show } from 'solid-js' import Banner from '../Discours/Banner' import { NavTopics } from '../Nav/Topics' import { Row5 } from '../Feed/Row5' @@ -103,7 +103,7 @@ export const HomeView = (props: HomeProps) => { }) return ( - + 0}> diff --git a/src/components/Views/Topic.tsx b/src/components/Views/Topic.tsx index 0ae118ce..727c31f5 100644 --- a/src/components/Views/Topic.tsx +++ b/src/components/Views/Topic.tsx @@ -19,6 +19,7 @@ type TopicsPageSearchParams = { interface TopicProps { topic: Topic topicArticles: Shout[] + topicSlug: string } export const TopicView = (props: TopicProps) => { @@ -29,7 +30,7 @@ export const TopicView = (props: TopicProps) => { const { authorsByTopic } = useAuthorsStore() - const topic = createMemo(() => topicEntities()[props.topic.slug]) + const topic = createMemo(() => topicEntities()[props.topicSlug]) /* const slug = createMemo(() => { @@ -40,11 +41,10 @@ export const TopicView = (props: TopicProps) => { */ const title = createMemo(() => { - // FIXME - // const m = getSearchParams().by - // if (m === 'viewed') return t('Top viewed') - // if (m === 'rating') return t('Top rated') - // if (m === 'commented') return t('Top discussed') + const m = getSearchParams().by + if (m === 'viewed') return t('Top viewed') + if (m === 'rating') return t('Top rated') + if (m === 'commented') return t('Top discussed') return t('Top recent') }) diff --git a/src/components/types.ts b/src/components/types.ts index b8de6695..0b2fca98 100644 --- a/src/components/types.ts +++ b/src/components/types.ts @@ -5,11 +5,14 @@ import type { Author, Shout, Topic } from '../graphql/types.gen' export type PageProps = { randomTopics?: Topic[] article?: Shout - articles?: Shout[] + authorArticles?: Shout[] + topicArticles?: Shout[] + homeArticles?: Shout[] + feedArticles?: Shout[] author?: Author - authors?: Author[] + allAuthors?: Author[] topic?: Topic - topics?: Topic[] + allTopics?: Topic[] searchQuery?: string // other types? searchResults?: Shout[] diff --git a/src/pages/author/[slug]/index.astro b/src/pages/author/[slug]/index.astro index 69774b1f..7ad13be2 100644 --- a/src/pages/author/[slug]/index.astro +++ b/src/pages/author/[slug]/index.astro @@ -15,5 +15,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate' --- - + diff --git a/src/pages/authors.astro b/src/pages/authors.astro index 2cb49a90..2b5b1176 100644 --- a/src/pages/authors.astro +++ b/src/pages/authors.astro @@ -11,5 +11,5 @@ initRouter(pathname, search) --- - + diff --git a/src/pages/feed/index.astro b/src/pages/feed/index.astro index a16d6f37..93c40a9c 100644 --- a/src/pages/feed/index.astro +++ b/src/pages/feed/index.astro @@ -12,5 +12,5 @@ const articles = await apiClient.getRecentArticles({ limit: 50 }) --- - + diff --git a/src/pages/index.astro b/src/pages/index.astro index 7066509a..e03b076c 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -15,6 +15,6 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate' --- - + diff --git a/src/pages/topic/[slug].astro b/src/pages/topic/[slug].astro index 9a4d0ff1..98134a4b 100644 --- a/src/pages/topic/[slug].astro +++ b/src/pages/topic/[slug].astro @@ -16,5 +16,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate' --- - + diff --git a/src/pages/topics.astro b/src/pages/topics.astro index 0ab55341..eda7b67a 100644 --- a/src/pages/topics.astro +++ b/src/pages/topics.astro @@ -11,6 +11,6 @@ initRouter(pathname, search) --- - + diff --git a/src/stores/zine/articles.ts b/src/stores/zine/articles.ts index f3310868..fa2ca139 100644 --- a/src/stores/zine/articles.ts +++ b/src/stores/zine/articles.ts @@ -151,6 +151,22 @@ export const loadPublishedArticles = async ({ addSortedArticles(newArticles) } +export const loadArticlesForAuthors = async ({ authorSlugs }: { authorSlugs: string[] }): Promise => { + const articles = await apiClient.getArticlesForAuthors({ authorSlugs, limit: 50 }) + addArticles(articles) + setSortedArticles(articles) +} + +export const loadArticlesForTopics = async ({ topicSlugs }: { topicSlugs: string[] }): Promise => { + const articles = await apiClient.getArticlesForTopics({ topicSlugs, limit: 50 }) + addArticles(articles) + setSortedArticles(articles) +} + +export const resetSortedArticles = () => { + setSortedArticles([]) +} + export const loadTopMonthArticles = async (): Promise => { const articles = await apiClient.getTopMonthArticles() addArticles(articles) diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index 567f70a1..9932eb2c 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -46,6 +46,13 @@ const addAuthors = (authors: Author[]) => { }) } +export const loadAuthor = async ({ slug }: { slug: string }): Promise => { + // TODO: + const articles = await apiClient.getArticlesForAuthors({ authorSlugs: [slug], limit: 1 }) + const author = articles[0].authors.find((a) => a.slug === slug) + addAuthors([author]) +} + export const addAuthorsByTopic = (newAuthorsByTopic: { [topicSlug: string]: Author[] }) => { const allAuthors = Object.values(newAuthorsByTopic).flat() addAuthors(allAuthors) diff --git a/src/stores/zine/topics.ts b/src/stores/zine/topics.ts index 9fc75672..b9784387 100644 --- a/src/stores/zine/topics.ts +++ b/src/stores/zine/topics.ts @@ -92,6 +92,18 @@ export const loadAllTopics = async (): Promise => { addTopics(topics) } +export const loadRandomTopics = async (): Promise => { + const topics = await apiClient.getRandomTopics({ amount: 12 }) + setRandomTopics(topics) +} + +export const loadTopic = async ({ slug }: { slug: string }): Promise => { + // TODO: + const articles = await apiClient.getArticlesForTopics({ topicSlugs: [slug], limit: 1 }) + const topic = articles[0].topics.find(({ slug: topicSlug }) => topicSlug === slug) + addTopics([topic]) +} + type InitialState = { topics?: Topic[] randomTopics?: Topic[] diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index 4cd6c3ce..be9e29b5 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -225,6 +225,10 @@ export const apiClient = { getPublishedArticles: async ({ limit = FEED_SIZE, offset }: { limit?: number; offset?: number }) => { const response = await publicGraphQLClient.query(articlesRecentPublished, { limit, offset }).toPromise() + if (response.error) { + log.error('getPublishedArticles', response.error) + } + return response.data.recentPublished }, getAllTopics: async () => { From 71cec8a6c2f4ddf43d57b45cf9409102a2f0103b Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Wed, 5 Oct 2022 17:56:59 +0200 Subject: [PATCH 4/4] topics and authors grouped by letter --- src/components/Views/AllAuthors.tsx | 47 ++++++++------- src/components/Views/AllTopics.tsx | 92 ++++++++++++++++------------- src/stores/zine/authors.ts | 25 +++++--- 3 files changed, 93 insertions(+), 71 deletions(-) diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index f6bad799..1aa61b56 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -1,15 +1,14 @@ -import { createEffect, createSignal, For, Show } from 'solid-js' +import { createEffect, createMemo, createSignal, For, Show } from 'solid-js' import type { Author } from '../../graphql/types.gen' import { AuthorCard } from '../Author/Card' -import { byFirstChar, sortBy } from '../../utils/sortby' -import { groupByName } from '../../utils/groupby' import { Icon } from '../Nav/Icon' import { t } from '../../utils/intl' -import { useAuthorsStore } from '../../stores/zine/authors' +import { useAuthorsStore, setSortAllBy as setSortAllAuthorsBy } from '../../stores/zine/authors' import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { useAuthStore } from '../../stores/auth' import { getLogger } from '../../utils/logger' import '../../styles/AllTopics.scss' +import { Topic } from '../../graphql/types.gen' const log = getLogger('AllAuthorsView') @@ -23,31 +22,37 @@ type Props = { export const AllAuthorsView = (props: Props) => { const { sortedAuthors } = useAuthorsStore({ authors: props.authors }) - const [sortedKeys, setSortedKeys] = createSignal([]) - const [abc, setAbc] = createSignal([]) const { session } = useAuthStore() + createEffect(() => { + setSortAllAuthorsBy(getSearchParams().by || 'shouts') + }) + const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || '')) const { getSearchParams } = useRouter() - createEffect(() => { - if ((!getSearchParams().by || getSearchParams().by === 'name') && abc().length === 0) { - console.log('[authors] default grouping by abc') - const grouped = { ...groupByName(sortedAuthors()) } - grouped['A-Z'] = sortBy(grouped['A-Z'], byFirstChar) - setAbc(grouped) - const keys = Object.keys(abc) - keys.sort() - setSortedKeys(keys) - } else { - console.log('[authors] sorting by ' + getSearchParams().by) - ///setSortedAuthors(sortBy(authorList(), getSearchParams().by)) - } + const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { + return sortedAuthors().reduce((acc, author) => { + const letter = author.name[0] + if (!acc[letter]) { + acc[letter] = [] + } + + acc[letter].push(author) + + return acc + }, {} as { [letter: string]: Author[] }) }) - log.debug(getSearchParams()) + const sortedKeys = createMemo(() => { + const keys = Object.keys(byLetter()) + keys.sort() + return keys + }) + + // log.debug(getSearchParams()) return (
@@ -108,7 +113,7 @@ export const AllAuthorsView = (props: Props) => {

{letter}

- + {(author: Author) => (
diff --git a/src/components/Views/AllTopics.tsx b/src/components/Views/AllTopics.tsx index fa40f8fe..ae26f45d 100644 --- a/src/components/Views/AllTopics.tsx +++ b/src/components/Views/AllTopics.tsx @@ -1,4 +1,4 @@ -import { createEffect, For, Show } from 'solid-js' +import { createEffect, createMemo, For, Show } from 'solid-js' import type { Topic } from '../../graphql/types.gen' import { Icon } from '../Nav/Icon' import { t } from '../../utils/intl' @@ -33,6 +33,25 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { setSortAllTopicsBy(getSearchParams().by || 'shouts') }) + const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => { + return sortedTopics().reduce((acc, topic) => { + const letter = topic.title[0] + if (!acc[letter]) { + acc[letter] = [] + } + + acc[letter].push(topic) + + return acc + }, {} as { [letter: string]: Topic[] }) + }) + + const sortedKeys = createMemo(() => { + const keys = Object.keys(byLetter()) + keys.sort() + return keys + }) + const subscribed = (s) => Boolean(session()?.news?.topics && session()?.news?.topics?.includes(s || '')) return ( @@ -80,48 +99,39 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { -
- - {(topic) => ( - + ( +
+ + {(topic) => ( + + )} + +
+ )} + > + + {(letter) => ( +
+

{letter}

+
+
+ + {(topic) => ( +
+ +
+ )} +
+
+
+
)}
-
- - {/*FIXME*/} - {/* (*/} - {/*
*/} - {/* */} - {/* {(topic: Topic) => (*/} - {/* */} - {/* )}*/} - {/* */} - {/*
*/} - {/* )}*/} - {/*>*/} - {/* */} - {/* {(letter: string) => (*/} - {/*
*/} - {/*

{letter}

*/} - {/*
*/} - {/*
*/} - {/* */} - {/* {(topic: Partial) => (*/} - {/*
*/} - {/*
*/} - {/* {topic.title}*/} - {/*
*/} - {/*
*/} - {/* )}*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* )}*/} - {/*
*/} - {/**/} +
diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index 9932eb2c..f9e60d0f 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -1,6 +1,6 @@ import { apiClient } from '../../utils/apiClient' import type { Author } from '../../graphql/types.gen' -import { byCreated } from '../../utils/sortby' +import { byCreated, byStat, byTopicStatDesc } from '../../utils/sortby' import { getLogger } from '../../utils/logger' import { createSignal } from 'solid-js' @@ -8,9 +8,11 @@ import { createLazyMemo } from '@solid-primitives/memo' const log = getLogger('authors store') -export type AuthorsSortBy = 'created' | 'name' +export type AuthorsSortBy = 'shouts' | 'name' | 'rating' -const [sortAllBy, setSortAllBy] = createSignal('created') +const [sortAllBy, setSortAllBy] = createSignal('shouts') + +export { setSortAllBy } const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({}) const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({}) @@ -18,16 +20,21 @@ const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: const sortedAuthors = createLazyMemo(() => { const authors = Object.values(authorEntities()) switch (sortAllBy()) { - case 'created': { - log.debug('sorted by created') - authors.sort(byCreated) + // case 'created': { + // log.debug('sorted by created') + // authors.sort(byCreated) + // break + // } + case 'rating': + // TODO: break - } - case 'name': { + case 'shouts': + // TODO: + break + case 'name': log.debug('sorted by name') authors.sort((a, b) => a.name.localeCompare(b.name)) break - } } return authors })