From da7c98afabb85b648743b7b61ee82b0c1be14f3e Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 16:04:47 +0300 Subject: [PATCH 01/37] minor --- src/components/Nav/Header/Link.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Nav/Header/Link.tsx b/src/components/Nav/Header/Link.tsx index c041c4d0..6bf639b5 100644 --- a/src/components/Nav/Header/Link.tsx +++ b/src/components/Nav/Header/Link.tsx @@ -17,11 +17,11 @@ type Props = { export const Link = (props: Props) => { const { page } = useRouter() - const isSelected = page().route === props.routeName + const isSelected = page()?.route === props.routeName return (
  • Date: Wed, 21 Feb 2024 12:13:40 +0300 Subject: [PATCH 02/37] api update --- src/components/Views/Author/Author.tsx | 8 +-- src/components/Views/Home.tsx | 8 +-- src/context/following.tsx | 21 +++----- src/graphql/client/core.ts | 43 +++++++-------- src/graphql/query/core/author-follows.ts | 54 +++++++++++++++++++ src/graphql/query/core/authors-followed-by.ts | 17 ------ 6 files changed, 90 insertions(+), 61 deletions(-) create mode 100644 src/graphql/query/core/author-follows.ts delete mode 100644 src/graphql/query/core/authors-followed-by.ts diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index bb62322c..5bcd6ba8 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -71,13 +71,7 @@ export const AuthorView = (props: Props) => { const fetchData = async (slug) => { try { const [subscriptionsResult, followersResult] = await Promise.all([ - (async () => { - const [getAuthors, getTopics] = await Promise.all([ - apiClient.getAuthorFollowingAuthors({ slug }), - apiClient.getAuthorFollowingTopics({ slug }), - ]) - return { authors: getAuthors, topics: getTopics } - })(), + apiClient.getAuthorFollows({ slug }), apiClient.getAuthorFollowers({ slug }), ]) diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index 200434b5..4e4dbce3 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -69,10 +69,12 @@ export const HomeView = (props: Props) => { } const result = await apiClient.getRandomTopicShouts(RANDOM_TOPIC_SHOUTS_COUNT) - if (!result) console.warn('[apiClient.getRandomTopicShouts] failed') + if (!result || result.error) console.warn('[apiClient.getRandomTopicShouts] failed') batch(() => { - if (result?.topic) setRandomTopic(result.topic) - if (result?.shouts) setRandomTopicArticles(result.shouts) + if (!result?.error) { + if (result?.topic) setRandomTopic(result.topic) + if (result?.shouts) setRandomTopicArticles(result.shouts) + } }) }) diff --git a/src/context/following.tsx b/src/context/following.tsx index b7a5ab0d..5ba1c369 100644 --- a/src/context/following.tsx +++ b/src/context/following.tsx @@ -2,20 +2,14 @@ import { Accessor, JSX, createContext, createEffect, createSignal, useContext } import { createStore } from 'solid-js/store' import { apiClient } from '../graphql/client/core' -import { Author, Community, FollowingEntity, Topic } from '../graphql/schema/core.gen' +import { AuthorFollows, FollowingEntity } from '../graphql/schema/core.gen' import { useSession } from './session' -type SubscriptionsData = { - topics?: Topic[] - authors?: Author[] - communities?: Community[] -} - interface FollowingContextType { loading: Accessor - subscriptions: SubscriptionsData - setSubscriptions: (subscriptions: SubscriptionsData) => void + subscriptions: AuthorFollows + setSubscriptions: (subscriptions: AuthorFollows) => void setFollowing: (what: FollowingEntity, slug: string, value: boolean) => void loadSubscriptions: () => void follow: (what: FollowingEntity, slug: string) => Promise @@ -29,23 +23,24 @@ export function useFollowing() { return useContext(FollowingContext) } -const EMPTY_SUBSCRIPTIONS = { +const EMPTY_SUBSCRIPTIONS: AuthorFollows = { topics: [], authors: [], + shouts: [], communities: [], } export const FollowingProvider = (props: { children: JSX.Element }) => { const [loading, setLoading] = createSignal(false) - const [subscriptions, setSubscriptions] = createStore(EMPTY_SUBSCRIPTIONS) - const { author } = useSession() + const [subscriptions, setSubscriptions] = createStore(EMPTY_SUBSCRIPTIONS) + const { author, session } = useSession() const fetchData = async () => { setLoading(true) try { if (apiClient.private) { console.debug('[context.following] fetching subs data...') - const result = await apiClient.getMySubscriptions() + const result = await apiClient.getAuthorFollows({ user: session()?.user.id }) setSubscriptions(result || EMPTY_SUBSCRIPTIONS) console.info('[context.following] subs:', subscriptions) } diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index c80fe931..44942c73 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -1,7 +1,7 @@ import type { Author, + AuthorFollows, CommonResult, - Community, FollowingEntity, LoadShoutsOptions, MutationDelete_ShoutArgs, @@ -37,16 +37,14 @@ import shoutsLoadSearch from '../query/core/articles-load-search' import loadShoutsUnrated from '../query/core/articles-load-unrated' import authorBy from '../query/core/author-by' import authorFollowers from '../query/core/author-followers' +import authorFollows from '../query/core/author-follows' import authorId from '../query/core/author-id' import authorsAll from '../query/core/authors-all' -import authorFollowedAuthors from '../query/core/authors-followed-by' import authorsLoadBy from '../query/core/authors-load-by' -import authorFollowedCommunities from '../query/core/communities-followed-by' import mySubscriptions from '../query/core/my-followed' import reactionsLoadBy from '../query/core/reactions-load-by' import topicBySlug from '../query/core/topic-by-slug' import topicsAll from '../query/core/topics-all' -import authorFollowedTopics from '../query/core/topics-followed-by' import topicsRandomQuery from '../query/core/topics-random' const publicGraphQLClient = createGraphQLClient('core') @@ -86,7 +84,7 @@ export const apiClient = { return response.data.get_topics_random }, - getRandomTopicShouts: async (limit: number): Promise<{ topic: Topic; shouts: Shout[] }> => { + getRandomTopicShouts: async (limit: number): Promise => { const resp = await publicGraphQLClient.query(articlesLoadRandomTopic, { limit }).toPromise() if (!resp.data) console.error('[graphql.client.core] load_shouts_random_topic', resp) return resp.data.load_shouts_random_topic @@ -96,6 +94,7 @@ export const apiClient = { const response = await apiClient.private.mutation(followMutation, { what, slug }).toPromise() return response.data.follow }, + unfollow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => { const response = await apiClient.private.mutation(unfollowMutation, { what, slug }).toPromise() return response.data.unfollow @@ -107,48 +106,53 @@ export const apiClient = { return response.data.get_topics_all }, + getAllAuthors: async () => { const response = await publicGraphQLClient.query(authorsAll, {}).toPromise() if (!response.data) console.error('[graphql.client.core] getAllAuthors', response) return response.data.get_authors_all }, + getAuthor: async (params: { slug?: string; author_id?: number }): Promise => { const response = await publicGraphQLClient.query(authorBy, params).toPromise() return response.data.get_author }, + getAuthorId: async (params: { user: string }): Promise => { const response = await publicGraphQLClient.query(authorId, params).toPromise() return response.data.get_author_id }, + getAuthorFollowers: async ({ slug }: { slug: string }): Promise => { const response = await publicGraphQLClient.query(authorFollowers, { slug }).toPromise() return response.data.get_author_followers }, - getAuthorFollowingAuthors: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedAuthors, { slug }).toPromise() - return response.data.get_author_followed - }, - getAuthorFollowingTopics: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedTopics, { slug }).toPromise() - return response.data.get_topics_by_author - }, - getAuthorFollowingCommunities: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedCommunities, { slug }).toPromise() - return response.data.get_communities_by_author + + getAuthorFollows: async (params: { + slug?: string + author_id?: number + user?: string + }): Promise => { + const response = await publicGraphQLClient.query(authorFollows, params).toPromise() + return response.data.get_author_follows }, + updateAuthor: async (input: ProfileInput) => { const response = await apiClient.private.mutation(updateAuthor, { profile: input }).toPromise() return response.data.update_author }, + getTopic: async ({ slug }: { slug: string }): Promise => { const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise() return response.data.get_topic }, + createArticle: async ({ article }: { article: ShoutInput }): Promise => { const response = await apiClient.private.mutation(createArticle, { shout: article }).toPromise() return response.data.create_shout.shout }, + updateArticle: async ({ shout_id, shout_input, @@ -164,10 +168,12 @@ export const apiClient = { console.debug('[graphql.client.core] updateArticle:', response.data) return response.data.update_shout.shout }, + deleteShout: async (params: MutationDelete_ShoutArgs): Promise => { const response = await apiClient.private.mutation(deleteShout, params).toPromise() console.debug('[graphql.client.core] deleteShout:', response) }, + getDrafts: async (): Promise => { const response = await apiClient.private.query(draftsLoad, {}).toPromise() console.debug('[graphql.client.core] getDrafts:', response) @@ -233,9 +239,4 @@ export const apiClient = { .toPromise() return resp.data.load_reactions_by }, - getMySubscriptions: async (): Promise => { - const resp = await apiClient.private.query(mySubscriptions, {}).toPromise() - - return resp.data.get_my_followed - }, } diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts new file mode 100644 index 00000000..84bb4d2a --- /dev/null +++ b/src/graphql/query/core/author-follows.ts @@ -0,0 +1,54 @@ +import { gql } from '@urql/core' + +export default gql` + query GetAuthorFollows($slug: String, $user: String, $author_id: Int) { + get_author_follows(slug: $slug, user: $user, author_id: $author_id) { + authors { + id + slug + name + pic + bio + stat { + shouts + followers + } + } + topics { + id + slug + title + stat { + shouts + followers + } + } + shouts { + id + slug + title + subtitle + main_topic + authors { + id + name + slug + pic + } + stat { + viewed + rating + commented + } + created_at + updated_at + } + communities { + id + slug + name + pic + } + } + } +` diff --git a/src/graphql/query/core/authors-followed-by.ts b/src/graphql/query/core/authors-followed-by.ts deleted file mode 100644 index 06f6f5e9..00000000 --- a/src/graphql/query/core/authors-followed-by.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - query AuthorsFollowedByQuery($slug: String, $user: String, $author_id: Int) { - get_author_followed(slug: $slug, user: $user, author_id: $author_id) { - id - slug - name - pic - bio - created_at - stat { - shouts - } - } - } -` From 861bfafbd36f85f9cce61060778db9cbfa301d61 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 21 Feb 2024 12:20:06 +0300 Subject: [PATCH 03/37] query-fix --- src/graphql/query/core/author-follows.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts index 84bb4d2a..327a948e 100644 --- a/src/graphql/query/core/author-follows.ts +++ b/src/graphql/query/core/author-follows.ts @@ -23,26 +23,6 @@ export default gql` followers } } - shouts { - id - slug - title - subtitle - main_topic - authors { - id - name - slug - pic - } - stat { - viewed - rating - commented - } - created_at - updated_at - } communities { id slug From acbe96a830bb6f2da35372cd83e0eb076f0f562e Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 21 Feb 2024 14:37:22 +0300 Subject: [PATCH 04/37] nostat --- src/graphql/query/core/author-follows.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts index 327a948e..b1c8c0ce 100644 --- a/src/graphql/query/core/author-follows.ts +++ b/src/graphql/query/core/author-follows.ts @@ -9,25 +9,11 @@ export default gql` name pic bio - stat { - shouts - followers - } } topics { id slug title - stat { - shouts - followers - } - } - communities { - id - slug - name - pic } } } From 7af3f1d405c4ec651b6c6b2eb6d4da1a4430401b Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 21 Feb 2024 14:43:04 +0300 Subject: [PATCH 05/37] tsc-passed --- .../Views/ProfileSubscriptions/ProfileSubscriptions.tsx | 9 +++------ src/context/following.tsx | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx b/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx index 8c342356..6e1b4d8d 100644 --- a/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx +++ b/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx @@ -29,12 +29,9 @@ export const ProfileSubscriptions = () => { const fetchSubscriptions = async () => { try { const slug = author()?.slug - const [getAuthors, getTopics] = await Promise.all([ - apiClient.getAuthorFollowingAuthors({ slug }), - apiClient.getAuthorFollowingTopics({ slug }), - ]) - setFollowing([...getAuthors, ...getTopics]) - setFiltered([...getAuthors, ...getTopics]) + const authorFollows = await apiClient.getAuthorFollows({ slug }) + setFollowing([...authorFollows['authors']]) + setFiltered([...authorFollows['authors'], ...authorFollows['topics']]) } catch (error) { console.error('[fetchSubscriptions] :', error) throw error diff --git a/src/context/following.tsx b/src/context/following.tsx index 5ba1c369..f3208ca9 100644 --- a/src/context/following.tsx +++ b/src/context/following.tsx @@ -26,7 +26,6 @@ export function useFollowing() { const EMPTY_SUBSCRIPTIONS: AuthorFollows = { topics: [], authors: [], - shouts: [], communities: [], } From fa594b6009b81075e22a97585e31aa29330fee28 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 21 Feb 2024 14:59:40 +0300 Subject: [PATCH 06/37] toler --- src/components/Author/AuthorBadge/AuthorBadge.tsx | 2 +- src/components/Topic/TopicBadge/TopicBadge.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index a3d7e74d..063cf8f7 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -120,7 +120,7 @@ export const AuthorBadge = (props: Props) => { 0}>
    - {t('PublicationsWithCount', { count: props.author.stat?.shouts ?? 0 })} + {t('PublicationsWithCount', { count: props.author?.stat.shouts ?? 0 })}
    diff --git a/src/components/Topic/TopicBadge/TopicBadge.tsx b/src/components/Topic/TopicBadge/TopicBadge.tsx index a4ccd348..9f7f712e 100644 --- a/src/components/Topic/TopicBadge/TopicBadge.tsx +++ b/src/components/Topic/TopicBadge/TopicBadge.tsx @@ -75,7 +75,7 @@ export const TopicBadge = (props: Props) => { when={props.topic.body} fallback={
    - {t('PublicationsWithCount', { count: props.topic.stat.shouts ?? 0 })} + {t('PublicationsWithCount', { count: props.topic?.stat?.shouts ?? 0 })}
    } > From a7f3ee54c17b3fbf277d386f0c45ae077fa87cb8 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:44:21 +0300 Subject: [PATCH 07/37] fix scroll to comments by search params (#416) * fix scroll to comments by search params * CommentsTree sort * Cancel cleanup search params in link to comment --- src/components/Article/CommentsTree.tsx | 3 --- src/components/Article/FullArticle.tsx | 25 ++++++++++--------------- src/stores/router.ts | 2 +- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/components/Article/CommentsTree.tsx b/src/components/Article/CommentsTree.tsx index 3057ffb6..03a39287 100644 --- a/src/components/Article/CommentsTree.tsx +++ b/src/components/Article/CommentsTree.tsx @@ -66,9 +66,6 @@ export const CommentsTree = (props: Props) => { if (commentsOrder() === 'rating') { newSortedComments = newSortedComments.sort(sortCommentsByRating) } - - newSortedComments.reverse() - return newSortedComments }) diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 46177b8c..1bb30930 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -58,9 +58,8 @@ export type ArticlePageSearchParams = { const scrollTo = (el: HTMLElement) => { const { top } = el.getBoundingClientRect() - window.scrollTo({ - top: top + window.scrollY - DEFAULT_HEADER_OFFSET, + top: top - DEFAULT_HEADER_OFFSET, left: 0, behavior: 'smooth', }) @@ -152,22 +151,16 @@ export const FullArticle = (props: Props) => { current: HTMLDivElement } = { current: null } - const scrollToComments = () => { - scrollTo(commentsRef.current) - } - createEffect(() => { if (props.scrollToComments) { - scrollToComments() + scrollTo(commentsRef.current) } }) createEffect(() => { if (searchParams()?.scrollTo === 'comments' && commentsRef.current) { - scrollToComments() - changeSearchParams({ - scrollTo: null, - }) + requestAnimationFrame(() => scrollTo(commentsRef.current)) + changeSearchParams({ scrollTo: null }) } }) @@ -177,10 +170,8 @@ export const FullArticle = (props: Props) => { `[id='comment_${searchParams().commentId}']`, ) - changeSearchParams({ commentId: null }) - if (commentElement) { - scrollTo(commentElement) + requestAnimationFrame(() => scrollTo(commentElement)) } } }) @@ -473,7 +464,11 @@ export const FullArticle = (props: Props) => { {(triggerRef: (el) => void) => ( -
    +
    scrollTo(commentsRef.current)} + > = Record< } const clearSearchParams = (replace = false) => { - searchParamsStore.open({}, replace) + // searchParamsStore.open({}, replace) } return { From 01a4b558bd983e007c15a069812a2a8706c65665 Mon Sep 17 00:00:00 2001 From: Tony <454794+tonyrewin@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:25:28 +0300 Subject: [PATCH 08/37] api update (#417) * api update * query-fix --- .../Author/AuthorBadge/AuthorBadge.tsx | 2 +- .../Topic/TopicBadge/TopicBadge.tsx | 2 +- src/components/Views/Author/Author.tsx | 8 +--- src/components/Views/Home.tsx | 8 ++-- .../ProfileSubscriptions.tsx | 9 ++-- src/context/following.tsx | 20 +++------ src/graphql/client/core.ts | 43 ++++++++++--------- src/graphql/query/core/author-follows.ts | 20 +++++++++ src/graphql/query/core/authors-followed-by.ts | 17 -------- 9 files changed, 60 insertions(+), 69 deletions(-) create mode 100644 src/graphql/query/core/author-follows.ts delete mode 100644 src/graphql/query/core/authors-followed-by.ts diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index a3d7e74d..063cf8f7 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -120,7 +120,7 @@ export const AuthorBadge = (props: Props) => { 0}>
    - {t('PublicationsWithCount', { count: props.author.stat?.shouts ?? 0 })} + {t('PublicationsWithCount', { count: props.author?.stat.shouts ?? 0 })}
    diff --git a/src/components/Topic/TopicBadge/TopicBadge.tsx b/src/components/Topic/TopicBadge/TopicBadge.tsx index a4ccd348..9f7f712e 100644 --- a/src/components/Topic/TopicBadge/TopicBadge.tsx +++ b/src/components/Topic/TopicBadge/TopicBadge.tsx @@ -75,7 +75,7 @@ export const TopicBadge = (props: Props) => { when={props.topic.body} fallback={
    - {t('PublicationsWithCount', { count: props.topic.stat.shouts ?? 0 })} + {t('PublicationsWithCount', { count: props.topic?.stat?.shouts ?? 0 })}
    } > diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index bb62322c..5bcd6ba8 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -71,13 +71,7 @@ export const AuthorView = (props: Props) => { const fetchData = async (slug) => { try { const [subscriptionsResult, followersResult] = await Promise.all([ - (async () => { - const [getAuthors, getTopics] = await Promise.all([ - apiClient.getAuthorFollowingAuthors({ slug }), - apiClient.getAuthorFollowingTopics({ slug }), - ]) - return { authors: getAuthors, topics: getTopics } - })(), + apiClient.getAuthorFollows({ slug }), apiClient.getAuthorFollowers({ slug }), ]) diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index 200434b5..4e4dbce3 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -69,10 +69,12 @@ export const HomeView = (props: Props) => { } const result = await apiClient.getRandomTopicShouts(RANDOM_TOPIC_SHOUTS_COUNT) - if (!result) console.warn('[apiClient.getRandomTopicShouts] failed') + if (!result || result.error) console.warn('[apiClient.getRandomTopicShouts] failed') batch(() => { - if (result?.topic) setRandomTopic(result.topic) - if (result?.shouts) setRandomTopicArticles(result.shouts) + if (!result?.error) { + if (result?.topic) setRandomTopic(result.topic) + if (result?.shouts) setRandomTopicArticles(result.shouts) + } }) }) diff --git a/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx b/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx index 8c342356..6e1b4d8d 100644 --- a/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx +++ b/src/components/Views/ProfileSubscriptions/ProfileSubscriptions.tsx @@ -29,12 +29,9 @@ export const ProfileSubscriptions = () => { const fetchSubscriptions = async () => { try { const slug = author()?.slug - const [getAuthors, getTopics] = await Promise.all([ - apiClient.getAuthorFollowingAuthors({ slug }), - apiClient.getAuthorFollowingTopics({ slug }), - ]) - setFollowing([...getAuthors, ...getTopics]) - setFiltered([...getAuthors, ...getTopics]) + const authorFollows = await apiClient.getAuthorFollows({ slug }) + setFollowing([...authorFollows['authors']]) + setFiltered([...authorFollows['authors'], ...authorFollows['topics']]) } catch (error) { console.error('[fetchSubscriptions] :', error) throw error diff --git a/src/context/following.tsx b/src/context/following.tsx index b7a5ab0d..f3208ca9 100644 --- a/src/context/following.tsx +++ b/src/context/following.tsx @@ -2,20 +2,14 @@ import { Accessor, JSX, createContext, createEffect, createSignal, useContext } import { createStore } from 'solid-js/store' import { apiClient } from '../graphql/client/core' -import { Author, Community, FollowingEntity, Topic } from '../graphql/schema/core.gen' +import { AuthorFollows, FollowingEntity } from '../graphql/schema/core.gen' import { useSession } from './session' -type SubscriptionsData = { - topics?: Topic[] - authors?: Author[] - communities?: Community[] -} - interface FollowingContextType { loading: Accessor - subscriptions: SubscriptionsData - setSubscriptions: (subscriptions: SubscriptionsData) => void + subscriptions: AuthorFollows + setSubscriptions: (subscriptions: AuthorFollows) => void setFollowing: (what: FollowingEntity, slug: string, value: boolean) => void loadSubscriptions: () => void follow: (what: FollowingEntity, slug: string) => Promise @@ -29,7 +23,7 @@ export function useFollowing() { return useContext(FollowingContext) } -const EMPTY_SUBSCRIPTIONS = { +const EMPTY_SUBSCRIPTIONS: AuthorFollows = { topics: [], authors: [], communities: [], @@ -37,15 +31,15 @@ const EMPTY_SUBSCRIPTIONS = { export const FollowingProvider = (props: { children: JSX.Element }) => { const [loading, setLoading] = createSignal(false) - const [subscriptions, setSubscriptions] = createStore(EMPTY_SUBSCRIPTIONS) - const { author } = useSession() + const [subscriptions, setSubscriptions] = createStore(EMPTY_SUBSCRIPTIONS) + const { author, session } = useSession() const fetchData = async () => { setLoading(true) try { if (apiClient.private) { console.debug('[context.following] fetching subs data...') - const result = await apiClient.getMySubscriptions() + const result = await apiClient.getAuthorFollows({ user: session()?.user.id }) setSubscriptions(result || EMPTY_SUBSCRIPTIONS) console.info('[context.following] subs:', subscriptions) } diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index 752b4de4..d9fef87a 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -1,7 +1,7 @@ import type { Author, + AuthorFollows, CommonResult, - Community, FollowingEntity, LoadShoutsOptions, MutationDelete_ShoutArgs, @@ -37,16 +37,14 @@ import shoutsLoadSearch from '../query/core/articles-load-search' import loadShoutsUnrated from '../query/core/articles-load-unrated' import authorBy from '../query/core/author-by' import authorFollowers from '../query/core/author-followers' +import authorFollows from '../query/core/author-follows' import authorId from '../query/core/author-id' import authorsAll from '../query/core/authors-all' -import authorFollowedAuthors from '../query/core/authors-followed-by' import authorsLoadBy from '../query/core/authors-load-by' -import authorFollowedCommunities from '../query/core/communities-followed-by' import mySubscriptions from '../query/core/my-followed' import reactionsLoadBy from '../query/core/reactions-load-by' import topicBySlug from '../query/core/topic-by-slug' import topicsAll from '../query/core/topics-all' -import authorFollowedTopics from '../query/core/topics-followed-by' import topicsRandomQuery from '../query/core/topics-random' const publicGraphQLClient = createGraphQLClient('core') @@ -86,7 +84,7 @@ export const apiClient = { return response.data.get_topics_random }, - getRandomTopicShouts: async (limit: number): Promise<{ topic: Topic; shouts: Shout[] }> => { + getRandomTopicShouts: async (limit: number): Promise => { const resp = await publicGraphQLClient.query(articlesLoadRandomTopic, { limit }).toPromise() if (!resp.data) console.error('[graphql.client.core] load_shouts_random_topic', resp) return resp.data.load_shouts_random_topic @@ -96,6 +94,7 @@ export const apiClient = { const response = await apiClient.private.mutation(followMutation, { what, slug }).toPromise() return response.data.follow }, + unfollow: async ({ what, slug }: { what: FollowingEntity; slug: string }) => { const response = await apiClient.private.mutation(unfollowMutation, { what, slug }).toPromise() return response.data.unfollow @@ -107,48 +106,53 @@ export const apiClient = { return response.data.get_topics_all }, + getAllAuthors: async () => { const response = await publicGraphQLClient.query(authorsAll, {}).toPromise() if (!response.data) console.error('[graphql.client.core] getAllAuthors', response) return response.data.get_authors_all }, + getAuthor: async (params: { slug?: string; author_id?: number }): Promise => { const response = await publicGraphQLClient.query(authorBy, params).toPromise() return response.data.get_author }, + getAuthorId: async (params: { user: string }): Promise => { const response = await publicGraphQLClient.query(authorId, params).toPromise() return response.data.get_author_id }, + getAuthorFollowers: async ({ slug }: { slug: string }): Promise => { const response = await publicGraphQLClient.query(authorFollowers, { slug }).toPromise() return response.data.get_author_followers }, - getAuthorFollowingAuthors: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedAuthors, { slug }).toPromise() - return response.data.get_author_followed - }, - getAuthorFollowingTopics: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedTopics, { slug }).toPromise() - return response.data.get_topics_by_author - }, - getAuthorFollowingCommunities: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient.query(authorFollowedCommunities, { slug }).toPromise() - return response.data.get_communities_by_author + + getAuthorFollows: async (params: { + slug?: string + author_id?: number + user?: string + }): Promise => { + const response = await publicGraphQLClient.query(authorFollows, params).toPromise() + return response.data.get_author_follows }, + updateAuthor: async (input: ProfileInput) => { const response = await apiClient.private.mutation(updateAuthor, { profile: input }).toPromise() return response.data.update_author }, + getTopic: async ({ slug }: { slug: string }): Promise => { const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise() return response.data.get_topic }, + createArticle: async ({ article }: { article: ShoutInput }): Promise => { const response = await apiClient.private.mutation(createArticle, { shout: article }).toPromise() return response.data.create_shout.shout }, + updateArticle: async ({ shout_id, shout_input, @@ -164,10 +168,12 @@ export const apiClient = { console.debug('[graphql.client.core] updateArticle:', response.data) return response.data.update_shout.shout }, + deleteShout: async (params: MutationDelete_ShoutArgs): Promise => { const response = await apiClient.private.mutation(deleteShout, params).toPromise() console.debug('[graphql.client.core] deleteShout:', response) }, + getDrafts: async (): Promise => { const response = await apiClient.private.query(draftsLoad, {}).toPromise() console.debug('[graphql.client.core] getDrafts:', response) @@ -231,9 +237,4 @@ export const apiClient = { .toPromise() return resp.data.load_reactions_by }, - getMySubscriptions: async (): Promise => { - const resp = await apiClient.private.query(mySubscriptions, {}).toPromise() - - return resp.data.get_my_followed - }, } diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts new file mode 100644 index 00000000..b1c8c0ce --- /dev/null +++ b/src/graphql/query/core/author-follows.ts @@ -0,0 +1,20 @@ +import { gql } from '@urql/core' + +export default gql` + query GetAuthorFollows($slug: String, $user: String, $author_id: Int) { + get_author_follows(slug: $slug, user: $user, author_id: $author_id) { + authors { + id + slug + name + pic + bio + } + topics { + id + slug + title + } + } + } +` diff --git a/src/graphql/query/core/authors-followed-by.ts b/src/graphql/query/core/authors-followed-by.ts deleted file mode 100644 index 06f6f5e9..00000000 --- a/src/graphql/query/core/authors-followed-by.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - query AuthorsFollowedByQuery($slug: String, $user: String, $author_id: Int) { - get_author_followed(slug: $slug, user: $user, author_id: $author_id) { - id - slug - name - pic - bio - created_at - stat { - shouts - } - } - } -` From 4e931a39c5993fdb55c28a6d66e5c1394e17c0c4 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:29:52 +0300 Subject: [PATCH 09/37] Feature/all authors order (#410) Load Authors by btn click --------- Co-authored-by: Untone --- .husky/pre-commit | 4 - public/locales/en/translation.json | 1 + public/locales/ru/translation.json | 3 +- .../AuthorBadge/AuthorBadge.module.scss | 5 + .../Author/AuthorBadge/AuthorBadge.tsx | 15 +- .../AuthorsList/AuthorsList.module.scss | 26 ++ src/components/AuthorsList/AuthorsList.tsx | 90 +++++++ src/components/AuthorsList/index.ts | 1 + .../InlineLoader/InlineLoader.module.scss | 18 ++ src/components/InlineLoader/InlineLoader.tsx | 20 ++ src/components/InlineLoader/index.ts | 1 + src/components/Views/AllAuthors.tsx | 234 ------------------ .../{ => AllAuthors}/AllAuthors.module.scss | 2 + .../Views/AllAuthors/AllAuthors.tsx | 177 +++++++++++++ src/components/Views/AllAuthors/index.ts | 1 + .../InviteMembers/InviteMembers.module.scss | 18 -- .../_shared/InviteMembers/InviteMembers.tsx | 10 +- src/pages/allAuthors.page.tsx | 6 +- src/stores/zine/authors.ts | 8 +- 19 files changed, 368 insertions(+), 272 deletions(-) delete mode 100755 .husky/pre-commit create mode 100644 src/components/AuthorsList/AuthorsList.module.scss create mode 100644 src/components/AuthorsList/AuthorsList.tsx create mode 100644 src/components/AuthorsList/index.ts create mode 100644 src/components/InlineLoader/InlineLoader.module.scss create mode 100644 src/components/InlineLoader/InlineLoader.tsx create mode 100644 src/components/InlineLoader/index.ts delete mode 100644 src/components/Views/AllAuthors.tsx rename src/components/Views/{ => AllAuthors}/AllAuthors.module.scss (99%) create mode 100644 src/components/Views/AllAuthors/AllAuthors.tsx create mode 100644 src/components/Views/AllAuthors/index.ts diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index d4a43dd1..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npm run pre-commit diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 113182a4..5dfd02bb 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -291,6 +291,7 @@ "Profile": "Profile", "Publications": "Publications", "PublicationsWithCount": "{count, plural, =0 {no publications} one {{count} publication} other {{count} publications}}", + "FollowersWithCount": "{count, plural, =0 {no followers} one {{count} follower} other {{count} followers}}", "Publish Album": "Publish Album", "Publish Settings": "Publish Settings", "Published": "Published", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index bcdc7e2c..647917b0 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -309,9 +309,10 @@ "Publication settings": "Настройки публикации", "Publications": "Публикации", "PublicationsWithCount": "{count, plural, =0 {нет публикаций} one {{count} публикация} few {{count} публикации} other {{count} публикаций}}", + "FollowersWithCount": "{count, plural, =0 {нет подписчиков} one {{count} подписчик} few {{count} подписчика} other {{count} подписчиков}}", + "Publish": "Опубликовать", "Publish Album": "Опубликовать альбом", "Publish Settings": "Настройки публикации", - "Publish": "Опубликовать", "Published": "Опубликованные", "Punchline": "Панчлайн", "Quit": "Выйти", diff --git a/src/components/Author/AuthorBadge/AuthorBadge.module.scss b/src/components/Author/AuthorBadge/AuthorBadge.module.scss index e78f10ca..8dc68f4b 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.module.scss +++ b/src/components/Author/AuthorBadge/AuthorBadge.module.scss @@ -58,6 +58,11 @@ } .bio { + @include font-size(1.2rem); + + display: flex; + flex-direction: row; + gap: 1rem; color: var(--black-400); font-weight: 500; } diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index 063cf8f7..e0ef0334 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -118,12 +118,17 @@ export const AuthorBadge = (props: Props) => {
    - 0}> -
    - {t('PublicationsWithCount', { count: props.author?.stat.shouts ?? 0 })} -
    -
    + +
    + 0}> +
    {t('PublicationsWithCount', { count: props.author.stat?.shouts ?? 0 })}
    +
    + 0}> +
    {t('FollowersWithCount', { count: props.author.stat?.followers ?? 0 })}
    +
    +
    +
    diff --git a/src/components/AuthorsList/AuthorsList.module.scss b/src/components/AuthorsList/AuthorsList.module.scss new file mode 100644 index 00000000..bad088be --- /dev/null +++ b/src/components/AuthorsList/AuthorsList.module.scss @@ -0,0 +1,26 @@ +.AuthorsList { + .action { + display: flex; + align-items: center; + justify-content: center; + min-height: 8rem; + } + + .loading { + @include font-size(1.4rem); + + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + width: 100%; + flex-direction: row; + opacity: 0.5; + + .icon { + position: relative; + width: 18px; + height: 18px; + } + } +} diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx new file mode 100644 index 00000000..236a586e --- /dev/null +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -0,0 +1,90 @@ +import { clsx } from 'clsx' +import { For, Show, createEffect, createSignal } from 'solid-js' +import { useFollowing } from '../../context/following' +import { useLocalize } from '../../context/localize' +import { apiClient } from '../../graphql/client/core' +import { setAuthorsByFollowers, setAuthorsByShouts, useAuthorsStore } from '../../stores/zine/authors' +import { AuthorBadge } from '../Author/AuthorBadge' +import { InlineLoader } from '../InlineLoader' +import { Button } from '../_shared/Button' +import styles from './AuthorsList.module.scss' + +type Props = { + class?: string + query: 'shouts' | 'followers' +} + +const PAGE_SIZE = 20 +export const AuthorsList = (props: Props) => { + const { t } = useLocalize() + const { isOwnerSubscribed } = useFollowing() + const [loading, setLoading] = createSignal(false) + const [currentPage, setCurrentPage] = createSignal({ shouts: 0, followers: 0 }) + const { authorsByShouts, authorsByFollowers } = useAuthorsStore() + + const fetchAuthors = async (queryType: 'shouts' | 'followers', page: number) => { + setLoading(true) + const offset = PAGE_SIZE * page + const result = await apiClient.loadAuthorsBy({ + by: { order: queryType }, + limit: PAGE_SIZE, + offset: offset, + }) + + if (queryType === 'shouts') { + setAuthorsByShouts((prev) => [...prev, ...result]) + } else { + setAuthorsByFollowers((prev) => [...prev, ...result]) + } + setLoading(false) + return result + } + + const loadMoreAuthors = () => { + const queryType = props.query + const nextPage = currentPage()[queryType] + 1 + fetchAuthors(queryType, nextPage).then(() => + setCurrentPage({ ...currentPage(), [queryType]: nextPage }), + ) + } + + createEffect(() => { + const queryType = props.query + if ( + currentPage()[queryType] === 0 && + (authorsByShouts().length === 0 || authorsByFollowers().length === 0) + ) { + loadMoreAuthors() + } + }) + + const authorsList = () => (props.query === 'shouts' ? authorsByShouts() : authorsByFollowers()) + + return ( +
    + + {(author) => ( +
    +
    + +
    +
    + )} +
    +
    + +
    +
    + ) +} diff --git a/src/components/AuthorsList/index.ts b/src/components/AuthorsList/index.ts new file mode 100644 index 00000000..4187ebae --- /dev/null +++ b/src/components/AuthorsList/index.ts @@ -0,0 +1 @@ +export { AuthorsList } from './AuthorsList' diff --git a/src/components/InlineLoader/InlineLoader.module.scss b/src/components/InlineLoader/InlineLoader.module.scss new file mode 100644 index 00000000..dc90c7bd --- /dev/null +++ b/src/components/InlineLoader/InlineLoader.module.scss @@ -0,0 +1,18 @@ +.InlineLoader { + @include font-size(1.4rem); + + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + width: 100%; + flex-direction: row; + opacity: 0.5; + + .icon { + position: relative; + width: 18px; + height: 18px; + } + +} diff --git a/src/components/InlineLoader/InlineLoader.tsx b/src/components/InlineLoader/InlineLoader.tsx new file mode 100644 index 00000000..6f36ff4e --- /dev/null +++ b/src/components/InlineLoader/InlineLoader.tsx @@ -0,0 +1,20 @@ +import { clsx } from 'clsx' +import { useLocalize } from '../../context/localize' +import { Loading } from '../_shared/Loading' +import styles from './InlineLoader.module.scss' + +type Props = { + class?: string +} + +export const InlineLoader = (props: Props) => { + const { t } = useLocalize() + return ( +
    +
    + +
    +
    {t('Loading')}
    +
    + ) +} diff --git a/src/components/InlineLoader/index.ts b/src/components/InlineLoader/index.ts new file mode 100644 index 00000000..c94c5a50 --- /dev/null +++ b/src/components/InlineLoader/index.ts @@ -0,0 +1 @@ +export { InlineLoader } from './InlineLoader' diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx deleted file mode 100644 index 6275621f..00000000 --- a/src/components/Views/AllAuthors.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import type { Author } from '../../graphql/schema/core.gen' - -import { Meta } from '@solidjs/meta' -import { clsx } from 'clsx' -import { For, Show, createEffect, createMemo, createSignal } from 'solid-js' - -import { useFollowing } from '../../context/following' -import { useLocalize } from '../../context/localize' -import { useRouter } from '../../stores/router' -import { loadAuthors, setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors' -import { dummyFilter } from '../../utils/dummyFilter' -import { getImageUrl } from '../../utils/getImageUrl' -import { scrollHandler } from '../../utils/scroll' -import { authorLetterReduce, translateAuthor } from '../../utils/translate' -import { AuthorBadge } from '../Author/AuthorBadge' -import { Loading } from '../_shared/Loading' -import { SearchField } from '../_shared/SearchField' - -import styles from './AllAuthors.module.scss' - -type AllAuthorsPageSearchParams = { - by: '' | 'name' | 'shouts' | 'followers' -} - -type Props = { - authors: Author[] - isLoaded: boolean -} - -const PAGE_SIZE = 20 - -export const AllAuthorsView = (props: Props) => { - const { t, lang } = useLocalize() - const ALPHABET = - lang() === 'ru' ? [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@'] : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ@'] - const [offsetByShouts, setOffsetByShouts] = createSignal(0) - const [offsetByFollowers, setOffsetByFollowers] = createSignal(0) - const { searchParams, changeSearchParams } = useRouter() - const { sortedAuthors } = useAuthorsStore({ - authors: props.authors, - sortBy: searchParams().by || 'name', - }) - - const [searchQuery, setSearchQuery] = createSignal('') - const offset = searchParams()?.by === 'shouts' ? offsetByShouts : offsetByFollowers - createEffect(() => { - let by = searchParams().by - if (by) { - setAuthorsSort(by) - } else { - by = 'name' - changeSearchParams({ by }) - } - }) - - const loadMoreByShouts = async () => { - await loadAuthors({ by: { order: 'shouts_stat' }, limit: PAGE_SIZE, offset: offsetByShouts() }) - setOffsetByShouts((o) => o + PAGE_SIZE) - } - const loadMoreByFollowers = async () => { - await loadAuthors({ by: { order: 'followers_stat' }, limit: PAGE_SIZE, offset: offsetByFollowers() }) - setOffsetByFollowers((o) => o + PAGE_SIZE) - } - - const isStatsLoaded = createMemo(() => sortedAuthors()?.some((author) => author.stat)) - - createEffect(async () => { - if (!isStatsLoaded()) { - await loadMoreByShouts() - await loadMoreByFollowers() - } - }) - - const showMore = async () => - await { - shouts: loadMoreByShouts, - followers: loadMoreByFollowers, - }[searchParams().by]() - - const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { - return sortedAuthors().reduce( - (acc, author) => authorLetterReduce(acc, author, lang()), - {} as { [letter: string]: Author[] }, - ) - }) - - const { isOwnerSubscribed } = useFollowing() - - const sortedKeys = createMemo(() => { - const keys = Object.keys(byLetter()) - keys.sort() - keys.push(keys.shift()) - return keys - }) - - const filteredAuthors = createMemo(() => { - return dummyFilter(sortedAuthors(), searchQuery(), lang()) - }) - - const ogImage = getImageUrl('production/image/logo_image.png') - const ogTitle = t('Authors') - const description = t('List of authors of the open editorial community') - - return ( -
    - - - - - - - - - - - }> -
    -
    -
    -

    {t('Authors')}

    -

    {t('Subscribe who you like to tune your personal feed')}

    - - - -
    -
    - - 0}> - - - - - {(letter) => ( -
    -

    {letter}

    -
    -
    -
    -
    - - {(author) => ( -
    -
    - {translateAuthor(author, lang())} - - {author.stat.shouts} - -
    -
    - )} -
    -
    -
    -
    -
    -
    - )} -
    -
    - - - - {(author) => ( -
    -
    - -
    -
    - )} -
    -
    - - PAGE_SIZE + offset() && searchParams().by !== 'name'}> -
    -
    - -
    -
    -
    -
    -
    -
    -
    - ) -} diff --git a/src/components/Views/AllAuthors.module.scss b/src/components/Views/AllAuthors/AllAuthors.module.scss similarity index 99% rename from src/components/Views/AllAuthors.module.scss rename to src/components/Views/AllAuthors/AllAuthors.module.scss index 94d4302c..63188b2b 100644 --- a/src/components/Views/AllAuthors.module.scss +++ b/src/components/Views/AllAuthors/AllAuthors.module.scss @@ -81,3 +81,5 @@ overflow-x: auto; } } + + diff --git a/src/components/Views/AllAuthors/AllAuthors.tsx b/src/components/Views/AllAuthors/AllAuthors.tsx new file mode 100644 index 00000000..c1723891 --- /dev/null +++ b/src/components/Views/AllAuthors/AllAuthors.tsx @@ -0,0 +1,177 @@ +import type { Author } from '../../../graphql/schema/core.gen' + +import { Meta } from '@solidjs/meta' +import { clsx } from 'clsx' +import { For, Show, createEffect, createMemo, createSignal } from 'solid-js' + +import { useLocalize } from '../../../context/localize' +import { useRouter } from '../../../stores/router' +import { setAuthorsSort, useAuthorsStore } from '../../../stores/zine/authors' +import { getImageUrl } from '../../../utils/getImageUrl' +import { scrollHandler } from '../../../utils/scroll' +import { authorLetterReduce, translateAuthor } from '../../../utils/translate' + +import { AuthorsList } from '../../AuthorsList' +import { Loading } from '../../_shared/Loading' +import { SearchField } from '../../_shared/SearchField' + +import styles from './AllAuthors.module.scss' + +type AllAuthorsPageSearchParams = { + by: '' | 'name' | 'shouts' | 'followers' +} + +type Props = { + authors: Author[] + isLoaded: boolean +} + +export const AllAuthors = (props: Props) => { + const { t, lang } = useLocalize() + const ALPHABET = + lang() === 'ru' ? [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@'] : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ@'] + const { searchParams, changeSearchParams } = useRouter() + const { sortedAuthors } = useAuthorsStore({ + authors: props.authors, + sortBy: searchParams().by || 'name', + }) + + const [searchQuery, setSearchQuery] = createSignal('') + + createEffect(() => { + let by = searchParams().by + if (by) { + setAuthorsSort(by) + } else { + by = 'name' + changeSearchParams({ by }) + } + }) + + const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { + return sortedAuthors().reduce( + (acc, author) => authorLetterReduce(acc, author, lang()), + {} as { [letter: string]: Author[] }, + ) + }) + + const sortedKeys = createMemo(() => { + const keys = Object.keys(byLetter()) + keys.sort() + keys.push(keys.shift()) + return keys + }) + + const ogImage = getImageUrl('production/image/logo_image.png') + const ogTitle = t('Authors') + const description = t('List of authors of the open editorial community') + + return ( +
    + + + + + + + + + + + }> +
    +
    +
    +

    {t('Authors')}

    +

    {t('Subscribe who you like to tune your personal feed')}

    + +
    +
    + + + + + {(letter) => ( +
    +

    {letter}

    +
    +
    +
    +
    + + {(author) => ( +
    +
    + {translateAuthor(author, lang())} + + {author.stat.shouts} + +
    +
    + )} +
    +
    +
    +
    +
    +
    + )} +
    +
    + }> + + +
    +
    +
    + ) +} diff --git a/src/components/Views/AllAuthors/index.ts b/src/components/Views/AllAuthors/index.ts new file mode 100644 index 00000000..13e92537 --- /dev/null +++ b/src/components/Views/AllAuthors/index.ts @@ -0,0 +1 @@ +export { AllAuthors } from './AllAuthors' diff --git a/src/components/_shared/InviteMembers/InviteMembers.module.scss b/src/components/_shared/InviteMembers/InviteMembers.module.scss index 8710a65a..0e9f8964 100644 --- a/src/components/_shared/InviteMembers/InviteMembers.module.scss +++ b/src/components/_shared/InviteMembers/InviteMembers.module.scss @@ -50,24 +50,6 @@ } } - .loading { - @include font-size(1.4rem); - - display: flex; - align-items: center; - justify-content: center; - gap: 1rem; - width: 100%; - flex-direction: row; - opacity: 0.5; - - .icon { - position: relative; - width: 18px; - height: 18px; - } - } - .teaser { min-height: 300px; display: flex; diff --git a/src/components/_shared/InviteMembers/InviteMembers.tsx b/src/components/_shared/InviteMembers/InviteMembers.tsx index 0458c7a5..3eca7cdc 100644 --- a/src/components/_shared/InviteMembers/InviteMembers.tsx +++ b/src/components/_shared/InviteMembers/InviteMembers.tsx @@ -12,6 +12,7 @@ import { Button } from '../Button' import { DropdownSelect } from '../DropdownSelect' import { Loading } from '../Loading' +import { InlineLoader } from '../../InlineLoader' import styles from './InviteMembers.module.scss' type InviteAuthor = Author & { selected: boolean } @@ -62,7 +63,7 @@ export const InviteMembers = (props: Props) => { return authors?.slice(start, end) } - const [pages, _infiniteScrollLoader, { end }] = createInfiniteScroll(fetcher) + const [pages, setEl, { end }] = createInfiniteScroll(fetcher) createEffect( on( @@ -158,11 +159,8 @@ export const InviteMembers = (props: Props) => { )} -
    -
    - -
    -
    {t('Loading')}
    +
    void}> +
    diff --git a/src/pages/allAuthors.page.tsx b/src/pages/allAuthors.page.tsx index 87a427b2..7079e8af 100644 --- a/src/pages/allAuthors.page.tsx +++ b/src/pages/allAuthors.page.tsx @@ -1,8 +1,8 @@ import type { PageProps } from './types' -import { createSignal, onMount } from 'solid-js' +import { createEffect, createSignal, onMount } from 'solid-js' -import { AllAuthorsView } from '../components/Views/AllAuthors' +import { AllAuthors } from '../components/Views/AllAuthors/' import { PageLayout } from '../components/_shared/PageLayout' import { useLocalize } from '../context/localize' import { loadAllAuthors } from '../stores/zine/authors' @@ -23,7 +23,7 @@ export const AllAuthorsPage = (props: PageProps) => { return ( - + ) } diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index db3f0627..c046737a 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -6,6 +6,7 @@ import { Author, QueryLoad_Authors_ByArgs } from '../../graphql/schema/core.gen' import { byStat } from '../../utils/sortby' export type AuthorsSortBy = 'shouts' | 'name' | 'followers' +type SortedAuthorsSetter = (prev: Author[]) => Author[] const [sortAllBy, setSortAllBy] = createSignal('name') @@ -13,6 +14,11 @@ export const setAuthorsSort = (sortBy: AuthorsSortBy) => setSortAllBy(sortBy) const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({}) const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({}) +const [authorsByShouts, setSortedAuthorsByShout] = createSignal([]) +const [authorsByFollowers, setSortedAuthorsByFollowers] = createSignal([]) + +export const setAuthorsByShouts = (authors: SortedAuthorsSetter) => setSortedAuthorsByShout(authors) +export const setAuthorsByFollowers = (authors: SortedAuthorsSetter) => setSortedAuthorsByFollowers(authors) const sortedAuthors = createLazyMemo(() => { const authors = Object.values(authorEntities()) @@ -108,5 +114,5 @@ export const useAuthorsStore = (initialState: InitialState = {}) => { } addAuthors([...(initialState.authors || [])]) - return { authorEntities, sortedAuthors, authorsByTopic } + return { authorEntities, sortedAuthors, authorsByTopic, authorsByShouts, authorsByFollowers } } From 11e722d2afc970b13367c3f37085d08d5e697b8a Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 02:13:31 +0300 Subject: [PATCH 10/37] stat-fix --- src/graphql/query/core/author-follows.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts index b1c8c0ce..7de7d9c4 100644 --- a/src/graphql/query/core/author-follows.ts +++ b/src/graphql/query/core/author-follows.ts @@ -3,17 +3,33 @@ import { gql } from '@urql/core' export default gql` query GetAuthorFollows($slug: String, $user: String, $author_id: Int) { get_author_follows(slug: $slug, user: $user, author_id: $author_id) { - authors { + authors { id slug name pic bio + stat { + shouts + authors + followers + } } topics { id slug title + stat { + shouts + authors + followers + } + } + communities { + id + slug + name + pic } } } From b30ae915bb217788c38a9dc43be2c4f6c5e8cc98 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 02:15:17 +0300 Subject: [PATCH 11/37] stat-query-fix --- src/graphql/query/core/author-by.ts | 2 +- src/graphql/query/core/author-id.ts | 4 ++-- src/graphql/query/core/authors-load-by.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/graphql/query/core/author-by.ts b/src/graphql/query/core/author-by.ts index d40173c1..6fc79a12 100644 --- a/src/graphql/query/core/author-by.ts +++ b/src/graphql/query/core/author-by.ts @@ -15,8 +15,8 @@ export default gql` last_seen stat { shouts + authors followers - followings rating commented } diff --git a/src/graphql/query/core/author-id.ts b/src/graphql/query/core/author-id.ts index 38596c1c..9f1155a6 100644 --- a/src/graphql/query/core/author-id.ts +++ b/src/graphql/query/core/author-id.ts @@ -14,10 +14,10 @@ export default gql` last_seen stat { shouts - comments: commented + authors followers - followings rating + comments: commented rating_shouts rating_comments } diff --git a/src/graphql/query/core/authors-load-by.ts b/src/graphql/query/core/authors-load-by.ts index 427889c4..5e5b7541 100644 --- a/src/graphql/query/core/authors-load-by.ts +++ b/src/graphql/query/core/authors-load-by.ts @@ -11,10 +11,10 @@ export default gql` created_at stat { shouts - comments: commented + authors followers - followings rating + comments: commented rating_shouts rating_comments } From a85a493022bdbef5286f5d26b0f98ff4dc622ff6 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 10:38:11 +0300 Subject: [PATCH 12/37] session-modal-fix --- src/context/session.tsx | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/context/session.tsx b/src/context/session.tsx index 8da23006..67495f73 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -92,30 +92,34 @@ export const SessionProvider = (props: { const authorizer = createMemo(() => new Authorizer(config())) const [oauthState, setOauthState] = createSignal() - // handle callback's redirect_uri - createEffect(() => { - // oauth - const state = searchParams()?.state - if (state) { - setOauthState((_s) => state) - const scope = searchParams()?.scope - ? searchParams()?.scope?.toString().split(' ') - : ['openid', 'profile', 'email'] - if (scope) console.info(`[context.session] scope: ${scope}`) - const url = searchParams()?.redirect_uri || searchParams()?.redirectURL || window.location.href - setConfig((c: ConfigType) => ({ ...c, redirectURL: url.split('?')[0] })) - changeSearchParams({ mode: 'confirm-email', modal: 'auth' }, true) - } - }) + // handle auth state callback + createEffect( + on( + () => searchParams()?.state, + (state) => { + if (state) { + setOauthState((_s) => state) + const scope = searchParams()?.scope + ? searchParams()?.scope?.toString().split(' ') + : ['openid', 'profile', 'email'] + if (scope) console.info(`[context.session] scope: ${scope}`) + const url = searchParams()?.redirect_uri || searchParams()?.redirectURL || window.location.href + setConfig((c: ConfigType) => ({ ...c, redirectURL: url.split('?')[0] })) + changeSearchParams({ mode: 'confirm-email', m: 'auth' }, true) + } + }, + { defer: true } + ) + ) - // handle email confirm + // handle token confirm createEffect(() => { const token = searchParams()?.token const access_token = searchParams()?.access_token if (access_token) changeSearchParams({ mode: 'confirm-email', - modal: 'auth', + m: 'auth', access_token, }) else if (token) changeSearchParams({ mode: 'change-password', modal: 'auth', token }) From 4b73ace2f0387ea4370b41239b398c294041d63f Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 10:39:35 +0300 Subject: [PATCH 13/37] session-modal-hotfix --- src/context/session.tsx | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/context/session.tsx b/src/context/session.tsx index 8da23006..67495f73 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -92,30 +92,34 @@ export const SessionProvider = (props: { const authorizer = createMemo(() => new Authorizer(config())) const [oauthState, setOauthState] = createSignal() - // handle callback's redirect_uri - createEffect(() => { - // oauth - const state = searchParams()?.state - if (state) { - setOauthState((_s) => state) - const scope = searchParams()?.scope - ? searchParams()?.scope?.toString().split(' ') - : ['openid', 'profile', 'email'] - if (scope) console.info(`[context.session] scope: ${scope}`) - const url = searchParams()?.redirect_uri || searchParams()?.redirectURL || window.location.href - setConfig((c: ConfigType) => ({ ...c, redirectURL: url.split('?')[0] })) - changeSearchParams({ mode: 'confirm-email', modal: 'auth' }, true) - } - }) + // handle auth state callback + createEffect( + on( + () => searchParams()?.state, + (state) => { + if (state) { + setOauthState((_s) => state) + const scope = searchParams()?.scope + ? searchParams()?.scope?.toString().split(' ') + : ['openid', 'profile', 'email'] + if (scope) console.info(`[context.session] scope: ${scope}`) + const url = searchParams()?.redirect_uri || searchParams()?.redirectURL || window.location.href + setConfig((c: ConfigType) => ({ ...c, redirectURL: url.split('?')[0] })) + changeSearchParams({ mode: 'confirm-email', m: 'auth' }, true) + } + }, + { defer: true } + ) + ) - // handle email confirm + // handle token confirm createEffect(() => { const token = searchParams()?.token const access_token = searchParams()?.access_token if (access_token) changeSearchParams({ mode: 'confirm-email', - modal: 'auth', + m: 'auth', access_token, }) else if (token) changeSearchParams({ mode: 'change-password', modal: 'auth', token }) From 3d4f542cdf69099de76c7b7e1349340d456bb1c7 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 10:44:50 +0300 Subject: [PATCH 14/37] session-modal-hotfix --- src/context/session.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context/session.tsx b/src/context/session.tsx index 67495f73..f1c3ecc1 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -108,8 +108,8 @@ export const SessionProvider = (props: { changeSearchParams({ mode: 'confirm-email', m: 'auth' }, true) } }, - { defer: true } - ) + { defer: true }, + ), ) // handle token confirm From 7a57c39a75f0782c8c73aca9de9579826b40d80e Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 22:31:33 +0300 Subject: [PATCH 15/37] follows-queries-hotfix --- .../query/core/author-follows-authors.ts | 18 ++++++++++++++++++ .../query/core/author-follows-topics.ts | 16 ++++++++++++++++ src/graphql/query/core/author-follows.ts | 12 ++++++------ 3 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/graphql/query/core/author-follows-authors.ts create mode 100644 src/graphql/query/core/author-follows-topics.ts diff --git a/src/graphql/query/core/author-follows-authors.ts b/src/graphql/query/core/author-follows-authors.ts new file mode 100644 index 00000000..39fdc4d8 --- /dev/null +++ b/src/graphql/query/core/author-follows-authors.ts @@ -0,0 +1,18 @@ +import { gql } from '@urql/core' + +export default gql` + query GetAuthorFollowsAuthors($slug: String, $user: String, $author_id: Int) { + get_author_follows_authors(slug: $slug, user: $user, author_id: $author_id) { + id + slug + name + pic + bio + stat { + shouts + authors + followers + } + } + } +` diff --git a/src/graphql/query/core/author-follows-topics.ts b/src/graphql/query/core/author-follows-topics.ts new file mode 100644 index 00000000..efd9a1dd --- /dev/null +++ b/src/graphql/query/core/author-follows-topics.ts @@ -0,0 +1,16 @@ +import { gql } from '@urql/core' + +export default gql` + query GetAuthorFollowsTopics($slug: String, $user: String, $author_id: Int) { + get_author_follows_topics(slug: $slug, user: $user, author_id: $author_id) { + id + slug + title + stat { + shouts + authors + followers + } + } + } +` diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts index 7de7d9c4..ac16b532 100644 --- a/src/graphql/query/core/author-follows.ts +++ b/src/graphql/query/core/author-follows.ts @@ -25,12 +25,12 @@ export default gql` followers } } - communities { - id - slug - name - pic - } + #communities { + # id + # slug + # name + # pic + #} } } ` From fe9fd37d9d9d8d0ac898db4f33c61ef7d39dc8ef Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Sun, 25 Feb 2024 10:04:05 +0300 Subject: [PATCH 16/37] Fix getRandomTopics (#419) --- src/components/Nav/Header/Header.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/Nav/Header/Header.tsx b/src/components/Nav/Header/Header.tsx index c0d2d466..dfbb2e71 100644 --- a/src/components/Nav/Header/Header.tsx +++ b/src/components/Nav/Header/Header.tsx @@ -142,10 +142,8 @@ export const Header = (props: Props) => { } onMount(async () => { - if (window.location.pathname === '/' || window.location.pathname === '') { - const topics = await apiClient.getRandomTopics({ amount: RANDOM_TOPICS_COUNT }) - setRandomTopics(topics) - } + const topics = await apiClient.getRandomTopics({ amount: RANDOM_TOPICS_COUNT }) + setRandomTopics(topics) }) const handleToggleMenuByLink = (event: MouseEvent, route: keyof typeof ROUTES) => { From 73e1f575f8e7d8a9099bd68f1d006e0a57109576 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Sun, 25 Feb 2024 10:31:11 +0300 Subject: [PATCH 17/37] Hotfix/all authors bugfix (#418) bufgix to authors --- src/components/AuthorsList/AuthorsList.tsx | 72 ++++++++++++------- .../Views/AllAuthors/AllAuthors.tsx | 36 +++++----- src/stores/zine/authors.ts | 15 +--- 3 files changed, 66 insertions(+), 57 deletions(-) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index 236a586e..2f3bb060 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -1,5 +1,5 @@ import { clsx } from 'clsx' -import { For, Show, createEffect, createSignal } from 'solid-js' +import { For, Show, createEffect, createSignal, on, onMount } from 'solid-js' import { useFollowing } from '../../context/following' import { useLocalize } from '../../context/localize' import { apiClient } from '../../graphql/client/core' @@ -11,24 +11,29 @@ import styles from './AuthorsList.module.scss' type Props = { class?: string - query: 'shouts' | 'followers' + query: 'shouts' | 'authors' + searchQuery?: string + allAuthorsLength?: number } const PAGE_SIZE = 20 export const AuthorsList = (props: Props) => { const { t } = useLocalize() const { isOwnerSubscribed } = useFollowing() + const { authorsByShouts, authorsByFollowers } = useAuthorsStore() const [loading, setLoading] = createSignal(false) const [currentPage, setCurrentPage] = createSignal({ shouts: 0, followers: 0 }) - const { authorsByShouts, authorsByFollowers } = useAuthorsStore() + const [allLoaded, setAllLoaded] = createSignal(false) - const fetchAuthors = async (queryType: 'shouts' | 'followers', page: number) => { + const fetchAuthors = async (queryType: 'shouts' | 'authors', page: number) => { setLoading(true) + + console.log('!!! AAA:') const offset = PAGE_SIZE * page const result = await apiClient.loadAuthorsBy({ by: { order: queryType }, limit: PAGE_SIZE, - offset: offset, + offset, }) if (queryType === 'shouts') { @@ -41,25 +46,38 @@ export const AuthorsList = (props: Props) => { } const loadMoreAuthors = () => { - const queryType = props.query - const nextPage = currentPage()[queryType] + 1 - fetchAuthors(queryType, nextPage).then(() => - setCurrentPage({ ...currentPage(), [queryType]: nextPage }), + const nextPage = currentPage()[props.query] + 1 + fetchAuthors(props.query, nextPage).then(() => + setCurrentPage({ ...currentPage(), [props.query]: nextPage }), ) } - createEffect(() => { - const queryType = props.query - if ( - currentPage()[queryType] === 0 && - (authorsByShouts().length === 0 || authorsByFollowers().length === 0) - ) { - loadMoreAuthors() - } - }) + createEffect( + on( + () => props.query, + (query) => { + const authorsList = query === 'shouts' ? authorsByShouts() : authorsByFollowers() + if (authorsList.length === 0 || currentPage()[query] === 0) { + setCurrentPage((prev) => ({ ...prev, [query]: 0 })) + fetchAuthors(query, 0).then(() => setCurrentPage((prev) => ({ ...prev, [query]: 1 }))) + } + }, + ), + ) const authorsList = () => (props.query === 'shouts' ? authorsByShouts() : authorsByFollowers()) + // TODO: do it with backend + // createEffect(() => { + // if (props.searchQuery) { + // // search logic + // } + // }) + + createEffect(() => { + setAllLoaded(authorsByShouts().length === authorsList.length) + }) + return (
    @@ -77,13 +95,17 @@ export const AuthorsList = (props: Props) => {
    )} -
    - -
    +
    ) diff --git a/src/components/Views/AllAuthors/AllAuthors.tsx b/src/components/Views/AllAuthors/AllAuthors.tsx index c1723891..3d0552b9 100644 --- a/src/components/Views/AllAuthors/AllAuthors.tsx +++ b/src/components/Views/AllAuthors/AllAuthors.tsx @@ -28,6 +28,7 @@ type Props = { export const AllAuthors = (props: Props) => { const { t, lang } = useLocalize() + const [searchQuery, setSearchQuery] = createSignal('') const ALPHABET = lang() === 'ru' ? [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@'] : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ@'] const { searchParams, changeSearchParams } = useRouter() @@ -36,27 +37,22 @@ export const AllAuthors = (props: Props) => { sortBy: searchParams().by || 'name', }) - const [searchQuery, setSearchQuery] = createSignal('') - - createEffect(() => { - let by = searchParams().by - if (by) { - setAuthorsSort(by) - } else { - by = 'name' - changeSearchParams({ by }) - } + const filteredAuthors = createMemo(() => { + const query = searchQuery().toLowerCase() + return sortedAuthors().filter((author) => { + return author.name.toLowerCase().includes(query) // Предполагаем, что у автора есть свойство name + }) }) - const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { - return sortedAuthors().reduce( + const byLetterFiltered = createMemo<{ [letter: string]: Author[] }>(() => { + return filteredAuthors().reduce( (acc, author) => authorLetterReduce(acc, author, lang()), {} as { [letter: string]: Author[] }, ) }) const sortedKeys = createMemo(() => { - const keys = Object.keys(byLetter()) + const keys = Object.keys(byLetterFiltered()) keys.sort() keys.push(keys.shift()) return keys @@ -106,7 +102,7 @@ export const AllAuthors = (props: Props) => { > {t('By name')}
  • - + @@ -122,7 +118,7 @@ export const AllAuthors = (props: Props) => { {(letter, index) => (
  • - + { @@ -147,7 +143,7 @@ export const AllAuthors = (props: Props) => {
    - + {(author) => (
    @@ -167,8 +163,12 @@ export const AllAuthors = (props: Props) => { )} - }> - + +
    diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index c046737a..131b70c6 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -3,7 +3,6 @@ import { createSignal } from 'solid-js' import { apiClient } from '../../graphql/client/core' import { Author, QueryLoad_Authors_ByArgs } from '../../graphql/schema/core.gen' -import { byStat } from '../../utils/sortby' export type AuthorsSortBy = 'shouts' | 'name' | 'followers' type SortedAuthorsSetter = (prev: Author[]) => Author[] @@ -21,19 +20,7 @@ export const setAuthorsByShouts = (authors: SortedAuthorsSetter) => setSortedAut export const setAuthorsByFollowers = (authors: SortedAuthorsSetter) => setSortedAuthorsByFollowers(authors) const sortedAuthors = createLazyMemo(() => { - const authors = Object.values(authorEntities()) - switch (sortAllBy()) { - case 'followers': { - return authors.sort(byStat('followers')) - } - case 'shouts': { - return authors.sort(byStat('shouts')) - } - case 'name': { - return authors.sort((a, b) => a.name.localeCompare(b.name)) - } - } - return authors + return Object.values(authorEntities()) }) export const addAuthors = (authors: Author[]) => { From f5295d2c3d4b5053f88367d9b8aeff5484804524 Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 26 Feb 2024 00:20:55 +0300 Subject: [PATCH 18/37] stat-api-hotfix --- package.json | 2 +- src/graphql/query/core/articles-load-random-topic.ts | 1 - src/graphql/query/core/author-by.ts | 2 +- src/graphql/query/core/author-id.ts | 2 +- src/graphql/query/core/authors-load-by.ts | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9a277dbc..fedffd56 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "patch-package": "^8.0.0", "prosemirror-history": "1.3.2", "prosemirror-trailing-node": "2.0.7", - "prosemirror-view": "1.32.7", + "prosemirror-view": "1.33.1", "rollup": "4.11.0", "sass": "1.69.5", "solid-js": "1.8.15", diff --git a/src/graphql/query/core/articles-load-random-topic.ts b/src/graphql/query/core/articles-load-random-topic.ts index 099895a6..c7ee8dc8 100644 --- a/src/graphql/query/core/articles-load-random-topic.ts +++ b/src/graphql/query/core/articles-load-random-topic.ts @@ -53,7 +53,6 @@ export default gql` featured_at stat { viewed - rating commented } diff --git a/src/graphql/query/core/author-by.ts b/src/graphql/query/core/author-by.ts index 6fc79a12..3f5e0f95 100644 --- a/src/graphql/query/core/author-by.ts +++ b/src/graphql/query/core/author-by.ts @@ -18,7 +18,7 @@ export default gql` authors followers rating - commented + comments } } } diff --git a/src/graphql/query/core/author-id.ts b/src/graphql/query/core/author-id.ts index 9f1155a6..8c621479 100644 --- a/src/graphql/query/core/author-id.ts +++ b/src/graphql/query/core/author-id.ts @@ -17,7 +17,7 @@ export default gql` authors followers rating - comments: commented + comments rating_shouts rating_comments } diff --git a/src/graphql/query/core/authors-load-by.ts b/src/graphql/query/core/authors-load-by.ts index 5e5b7541..e806919e 100644 --- a/src/graphql/query/core/authors-load-by.ts +++ b/src/graphql/query/core/authors-load-by.ts @@ -14,7 +14,7 @@ export default gql` authors followers rating - comments: commented + comments rating_shouts rating_comments } From 132418d539b5aa5fcbf4ec220c79fef449851f29 Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 26 Feb 2024 00:50:26 +0300 Subject: [PATCH 19/37] version-sync --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fedffd56..9a277dbc 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "patch-package": "^8.0.0", "prosemirror-history": "1.3.2", "prosemirror-trailing-node": "2.0.7", - "prosemirror-view": "1.33.1", + "prosemirror-view": "1.32.7", "rollup": "4.11.0", "sass": "1.69.5", "solid-js": "1.8.15", From 96c52ae2b4621ae4fbfecc144fa82d981aad7562 Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 26 Feb 2024 01:29:26 +0300 Subject: [PATCH 20/37] load-author-hotfix --- src/components/Views/Author/Author.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 8c544520..0020993b 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -58,9 +58,9 @@ export const AuthorView = (props: Props) => { } }) - createEffect(() => { + createEffect(async () => { if (author()?.id && !author().stat) { - const a = loadAuthor({ slug: '', author_id: author().id }) + const a = await loadAuthor({ slug: '', author_id: author().id }) console.debug('[AuthorView] loaded author:', a) } }) From bfc7ed15d8459e30da36fb82197d647298ae5942 Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 26 Feb 2024 01:40:09 +0300 Subject: [PATCH 21/37] sort-order-fix --- src/components/AuthorsList/AuthorsList.tsx | 4 ++-- src/components/Views/AllAuthors/AllAuthors.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index 2f3bb060..6597b171 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -11,7 +11,7 @@ import styles from './AuthorsList.module.scss' type Props = { class?: string - query: 'shouts' | 'authors' + query: 'followers' | 'shouts' searchQuery?: string allAuthorsLength?: number } @@ -25,7 +25,7 @@ export const AuthorsList = (props: Props) => { const [currentPage, setCurrentPage] = createSignal({ shouts: 0, followers: 0 }) const [allLoaded, setAllLoaded] = createSignal(false) - const fetchAuthors = async (queryType: 'shouts' | 'authors', page: number) => { + const fetchAuthors = async (queryType: Props['query'], page: number) => { setLoading(true) console.log('!!! AAA:') diff --git a/src/components/Views/AllAuthors/AllAuthors.tsx b/src/components/Views/AllAuthors/AllAuthors.tsx index 3d0552b9..68dd3605 100644 --- a/src/components/Views/AllAuthors/AllAuthors.tsx +++ b/src/components/Views/AllAuthors/AllAuthors.tsx @@ -167,7 +167,7 @@ export const AllAuthors = (props: Props) => {
    From 55ebc1c6344407e5e237f5135e562362c5b8de6c Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 26 Feb 2024 01:43:15 +0300 Subject: [PATCH 22/37] space-fix --- src/components/Views/AllAuthors/AllAuthors.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Views/AllAuthors/AllAuthors.tsx b/src/components/Views/AllAuthors/AllAuthors.tsx index 68dd3605..3934a73d 100644 --- a/src/components/Views/AllAuthors/AllAuthors.tsx +++ b/src/components/Views/AllAuthors/AllAuthors.tsx @@ -167,7 +167,7 @@ export const AllAuthors = (props: Props) => {
    From 507cfebd48611e6bd0e2622f1c2103d56a218265 Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Mon, 26 Feb 2024 14:19:12 +0300 Subject: [PATCH 23/37] Cleanup code --- src/components/AuthorsList/AuthorsList.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index 6597b171..9d1e8c95 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -27,8 +27,6 @@ export const AuthorsList = (props: Props) => { const fetchAuthors = async (queryType: Props['query'], page: number) => { setLoading(true) - - console.log('!!! AAA:') const offset = PAGE_SIZE * page const result = await apiClient.loadAuthorsBy({ by: { order: queryType }, From e34aa5e70baf21454d2bd77e2285889280917390 Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Mon, 26 Feb 2024 14:38:23 +0300 Subject: [PATCH 24/37] fix authors list pages --- src/components/AuthorsList/AuthorsList.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index 9d1e8c95..e4d10b26 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -28,6 +28,7 @@ export const AuthorsList = (props: Props) => { const fetchAuthors = async (queryType: Props['query'], page: number) => { setLoading(true) const offset = PAGE_SIZE * page + const result = await apiClient.loadAuthorsBy({ by: { order: queryType }, limit: PAGE_SIZE, @@ -35,12 +36,11 @@ export const AuthorsList = (props: Props) => { }) if (queryType === 'shouts') { - setAuthorsByShouts((prev) => [...prev, ...result]) + setAuthorsByShouts((prev) => [prev, ...result]) } else { - setAuthorsByFollowers((prev) => [...prev, ...result]) + setAuthorsByFollowers((prev) => [prev, ...result]) } setLoading(false) - return result } const loadMoreAuthors = () => { @@ -73,7 +73,7 @@ export const AuthorsList = (props: Props) => { // }) createEffect(() => { - setAllLoaded(authorsByShouts().length === authorsList.length) + setAllLoaded(props.allAuthorsLength === authorsList.length) }) return ( @@ -96,10 +96,11 @@ export const AuthorsList = (props: Props) => {
    +

    {`${loading()}`}

    0 && !allLoaded()}>
    From 80e338a60d19f750f6de376749f3cea9b9799b6e Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Mon, 26 Feb 2024 14:38:48 +0300 Subject: [PATCH 25/37] Cleanup code --- src/components/AuthorsList/AuthorsList.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index e4d10b26..55568f5c 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -96,7 +96,6 @@ export const AuthorsList = (props: Props) => {
    -

    {`${loading()}`}

    0 && !allLoaded()}>
    diff --git a/src/stores/ui.ts b/src/stores/ui.ts index b4ae712b..a97db243 100644 --- a/src/stores/ui.ts +++ b/src/stores/ui.ts @@ -48,7 +48,9 @@ export const MODALS: Record = { const [modal, setModal] = createSignal(null) -const { changeSearchParams, clearSearchParams } = useRouter() +const { changeSearchParams, clearSearchParams } = useRouter< + AuthModalSearchParams & ConfirmEmailSearchParams & RootSearchParams +>() export const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => { if (modalSource) { From b1b3f8b435b641c1425beac24c26a39cea15aef5 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:42:54 +0300 Subject: [PATCH 30/37] auth modals fix logic (#420) auth modals fix logic --- src/components/App.tsx | 4 ---- src/components/AuthorsList/AuthorsList.tsx | 11 ++--------- src/components/Nav/AuthModal/RegisterForm.tsx | 4 +--- src/components/Nav/AuthModal/SendResetLinkForm.tsx | 1 - src/context/session.tsx | 10 +++++++--- src/pages/types.ts | 1 + 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index b024f194..c595ec15 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -94,10 +94,6 @@ export const App = (props: Props) => { const is404 = createMemo(() => props.is404) createEffect(() => { - if (!searchParams().m) { - hideModal() - } - const modal = MODALS[searchParams().m] if (modal) { showModal(modal) diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx index 651792e6..ccde9a92 100644 --- a/src/components/AuthorsList/AuthorsList.tsx +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -19,13 +19,6 @@ type Props = { const PAGE_SIZE = 20 -// TODO: проверить нет ли дубликатов в базе данных, если нет - то не использовать addUniqueAuthors() -const addUniqueAuthors = (prevAuthors: Author[], newAuthors: Author[]) => { - const uniqueNewAuthors = newAuthors.filter( - (newAuthor) => !prevAuthors.some((prevAuthor) => prevAuthor.id === newAuthor.id), - ) - return [...prevAuthors, ...uniqueNewAuthors] -} export const AuthorsList = (props: Props) => { const { t } = useLocalize() const { isOwnerSubscribed } = useFollowing() @@ -44,9 +37,9 @@ export const AuthorsList = (props: Props) => { }) if (queryType === 'shouts') { - setAuthorsByShouts((prev) => addUniqueAuthors(prev, result)) + setAuthorsByShouts((prev) => [...prev, ...result]) } else { - setAuthorsByFollowers((prev) => addUniqueAuthors(prev, result)) + setAuthorsByFollowers((prev) => [...prev, ...result]) } setLoading(false) } diff --git a/src/components/Nav/AuthModal/RegisterForm.tsx b/src/components/Nav/AuthModal/RegisterForm.tsx index fd3b2467..ec78b44e 100644 --- a/src/components/Nav/AuthModal/RegisterForm.tsx +++ b/src/components/Nav/AuthModal/RegisterForm.tsx @@ -53,7 +53,6 @@ export const RegisterForm = () => { const handleSubmit = async (event: Event) => { event.preventDefault() - if (passwordError()) { setValidationErrors((errors) => ({ ...errors, password: passwordError() })) } else { @@ -102,7 +101,7 @@ export const RegisterForm = () => { redirect_uri: window.location.origin, } const { errors } = await signUp(opts) - if (errors) return + if (errors.length > 0) return setIsSuccess(true) } catch (error) { console.error(error) @@ -134,7 +133,6 @@ export const RegisterForm = () => { ), })) break - case 'verified': setValidationErrors((prev) => ({ email: ( diff --git a/src/components/Nav/AuthModal/SendResetLinkForm.tsx b/src/components/Nav/AuthModal/SendResetLinkForm.tsx index b1880d9d..f429a256 100644 --- a/src/components/Nav/AuthModal/SendResetLinkForm.tsx +++ b/src/components/Nav/AuthModal/SendResetLinkForm.tsx @@ -96,7 +96,6 @@ export const SendResetLinkForm = () => { placeholder={t('Email')} onInput={(event) => handleEmailInput(event.currentTarget.value)} /> -
    diff --git a/src/context/session.tsx b/src/context/session.tsx index f1c3ecc1..e6086097 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -122,7 +122,13 @@ export const SessionProvider = (props: { m: 'auth', access_token, }) - else if (token) changeSearchParams({ mode: 'change-password', modal: 'auth', token }) + else if (token) { + changeSearchParams({ + mode: 'change-password', + m: 'auth', + token, + }) + } }) // load @@ -207,7 +213,6 @@ export const SessionProvider = (props: { if (session()) { const token = session()?.access_token if (token) { - // console.log('[context.session] token observer got token', token) if (!inboxClient.private) { apiClient.connect(token) notifierClient.connect(token) @@ -333,7 +338,6 @@ export const SessionProvider = (props: { const response = await authorizer().graphqlQuery({ query: `query { is_registered(email: "${email}") { message }}`, }) - // console.log(response) return response?.data?.is_registered?.message } catch (error) { console.warn(error) diff --git a/src/pages/types.ts b/src/pages/types.ts index 05fd3f61..96701c6c 100644 --- a/src/pages/types.ts +++ b/src/pages/types.ts @@ -25,6 +25,7 @@ export type PageProps = { export type RootSearchParams = { m: string // modal lang: string + token: string } export type LayoutType = 'article' | 'audio' | 'video' | 'image' | 'literature' From 147417d172b594e75caf0e98585334c28b716041 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 29 Feb 2024 09:51:39 +0300 Subject: [PATCH 31/37] gql-hotfix --- src/graphql/query/core/author-follows-authors.ts | 1 + src/graphql/query/core/author-follows.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/graphql/query/core/author-follows-authors.ts b/src/graphql/query/core/author-follows-authors.ts index 39fdc4d8..cb624a4a 100644 --- a/src/graphql/query/core/author-follows-authors.ts +++ b/src/graphql/query/core/author-follows-authors.ts @@ -8,6 +8,7 @@ export default gql` name pic bio + created_at stat { shouts authors diff --git a/src/graphql/query/core/author-follows.ts b/src/graphql/query/core/author-follows.ts index ac16b532..9d46ea2c 100644 --- a/src/graphql/query/core/author-follows.ts +++ b/src/graphql/query/core/author-follows.ts @@ -9,6 +9,7 @@ export default gql` name pic bio + created_at stat { shouts authors From 9e513b24300413aad60b5700ed3b5a967ce456d5 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 29 Feb 2024 16:08:35 +0300 Subject: [PATCH 32/37] drafts-order-fix --- src/components/Views/DraftsView/DraftsView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Views/DraftsView/DraftsView.tsx b/src/components/Views/DraftsView/DraftsView.tsx index 17a425f1..193b4bc4 100644 --- a/src/components/Views/DraftsView/DraftsView.tsx +++ b/src/components/Views/DraftsView/DraftsView.tsx @@ -18,7 +18,7 @@ export const DraftsView = () => { const loadDrafts = async () => { if (apiClient.private) { const loadedDrafts = await apiClient.getDrafts() - setDrafts(loadedDrafts || []) + setDrafts(loadedDrafts.reverse() || []) } } From c9d79088d8423478ea9a8083b64a601e2feca510 Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Thu, 29 Feb 2024 17:24:34 +0300 Subject: [PATCH 33/37] Fix link border bottom color --- src/styles/app.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/app.scss b/src/styles/app.scss index ad7a13ef..d563840e 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -204,7 +204,7 @@ a:hover, a:visited, a:link, .link { - border-bottom: 2px solid rgb(0 0 0 / 30%); + border-bottom: 2px solid var(--link-color); text-decoration: none; cursor: pointer; } From 72cb6325d9f14ec5bb96d093786605b2e553ebda Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Thu, 29 Feb 2024 17:33:17 +0300 Subject: [PATCH 34/37] Fix comments date in Feed page --- .../Article/CommentDate/CommentDate.module.scss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/Article/CommentDate/CommentDate.module.scss b/src/components/Article/CommentDate/CommentDate.module.scss index 7f27ffaf..20410cce 100644 --- a/src/components/Article/CommentDate/CommentDate.module.scss +++ b/src/components/Article/CommentDate/CommentDate.module.scss @@ -2,15 +2,16 @@ @include font-size(1.2rem); color: var(--secondary-color); - align-items: center; - align-self: center; + //align-self: center; display: flex; + align-items: flex-start; + justify-content: flex-start; + flex-direction: column; + gap: .5rem; flex: 1; flex-wrap: wrap; font-size: 1.2rem; - justify-content: flex-start; - margin: 0 1rem; - height: 1.6rem; + margin-bottom: .5rem; .date { font-weight: 500; From abc2d01485b9ef453c1635276384a342e2818100 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 29 Feb 2024 18:05:05 +0300 Subject: [PATCH 35/37] comments-order-hotfix --- src/components/Views/Author/Author.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 0020993b..352d8f6c 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -25,6 +25,7 @@ import { Loading } from '../../_shared/Loading' import stylesArticle from '../../Article/Article.module.scss' import styles from './Author.module.scss' +import {byCreated} from "../../../utils/sortby"; type Props = { shouts: Shout[] @@ -231,7 +232,7 @@ export const AuthorView = (props: Props) => {
      - + {(comment) => }
    From deebe79f551cfede0c1be4389059219262911aa2 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 29 Feb 2024 20:51:07 +0300 Subject: [PATCH 36/37] comments-hotfix --- src/components/Article/CommentsTree.tsx | 68 +++++++++---------------- src/components/Views/Feed/Feed.tsx | 2 +- 2 files changed, 24 insertions(+), 46 deletions(-) diff --git a/src/components/Article/CommentsTree.tsx b/src/components/Article/CommentsTree.tsx index 03a39287..cf28fcfd 100644 --- a/src/components/Article/CommentsTree.tsx +++ b/src/components/Article/CommentsTree.tsx @@ -1,41 +1,20 @@ -import { clsx } from 'clsx' -import { For, Show, createMemo, createSignal, lazy, onMount } from 'solid-js' +import {clsx} from 'clsx' +import {createMemo, createSignal, For, lazy, onMount, Show} from 'solid-js' -import { useLocalize } from '../../context/localize' -import { useReactions } from '../../context/reactions' -import { useSession } from '../../context/session' -import { Author, Reaction, ReactionKind } from '../../graphql/schema/core.gen' -import { byCreated } from '../../utils/sortby' -import { Button } from '../_shared/Button' -import { ShowIfAuthenticated } from '../_shared/ShowIfAuthenticated' +import {useLocalize} from '../../context/localize' +import {useReactions} from '../../context/reactions' +import {useSession} from '../../context/session' +import {Author, Reaction, ReactionKind, ReactionSort} from '../../graphql/schema/core.gen' +import {byCreated, byStat} from '../../utils/sortby' +import {Button} from '../_shared/Button' +import {ShowIfAuthenticated} from '../_shared/ShowIfAuthenticated' -import { Comment } from './Comment' +import {Comment} from './Comment' import styles from './Article.module.scss' const SimplifiedEditor = lazy(() => import('../Editor/SimplifiedEditor')) -type CommentsOrder = 'createdAt' | 'rating' | 'newOnly' - -const sortCommentsByRating = (a: Reaction, b: Reaction): -1 | 0 | 1 => { - if (a.reply_to && b.reply_to) { - return 0 - } - - const x = a.stat?.rating || 0 - const y = b.stat?.rating || 0 - - if (x > y) { - return 1 - } - - if (x < y) { - return -1 - } - - return 0 -} - type Props = { articleAuthors: Author[] shoutSlug: string @@ -45,7 +24,8 @@ type Props = { export const CommentsTree = (props: Props) => { const { author } = useSession() const { t } = useLocalize() - const [commentsOrder, setCommentsOrder] = createSignal('createdAt') + const [commentsOrder, setCommentsOrder] = createSignal(ReactionSort.Newest) + const [onlyNew, setOnlyNew] = createSignal(false) const [newReactions, setNewReactions] = createSignal([]) const [clearEditor, setClearEditor] = createSignal(false) const [clickedReplyId, setClickedReplyId] = createSignal() @@ -59,12 +39,12 @@ export const CommentsTree = (props: Props) => { let newSortedComments = [...comments()] newSortedComments = newSortedComments.sort(byCreated) - if (commentsOrder() === 'newOnly') { - return newReactions().reverse() + if (onlyNew()) { + return newReactions().sort(byCreated).reverse() } - if (commentsOrder() === 'rating') { - newSortedComments = newSortedComments.sort(sortCommentsByRating) + if (commentsOrder() === ReactionSort.Like) { + newSortedComments = newSortedComments.sort(byStat('rating')) } return newSortedComments }) @@ -88,7 +68,7 @@ export const CommentsTree = (props: Props) => { setCookie() } }) - const handleSubmitComment = async (value) => { + const handleSubmitComment = async (value: string) => { try { await createReaction({ kind: ReactionKind.Comment, @@ -114,31 +94,29 @@ export const CommentsTree = (props: Props) => { 0}>
      0}> -
    • +
    • -
    • +
    • -
    • +
    • diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index a1010684..2a886a10 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -145,7 +145,7 @@ export const FeedView = (props: Props) => { } const loadTopComments = async () => { - const comments = await loadReactionsBy({ by: { comment: true }, limit: 5 }) + const comments = await loadReactionsBy({ by: { comment: true }, limit: 50 }) setTopComments(comments) } From 780f59f5174a3827621406e8c37e8f2f89251a51 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 1 Mar 2024 16:04:28 +0300 Subject: [PATCH 37/37] feed-comments-order-fix --- .../CommentDate/CommentDate.module.scss | 3 +- src/components/Article/CommentsTree.tsx | 26 +++++++-------- src/components/Views/Author/Author.tsx | 2 +- src/components/Views/Feed/Feed.tsx | 32 ++++++------------- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/components/Article/CommentDate/CommentDate.module.scss b/src/components/Article/CommentDate/CommentDate.module.scss index 20410cce..b492cb84 100644 --- a/src/components/Article/CommentDate/CommentDate.module.scss +++ b/src/components/Article/CommentDate/CommentDate.module.scss @@ -2,7 +2,8 @@ @include font-size(1.2rem); color: var(--secondary-color); - //align-self: center; + + // align-self: center; display: flex; align-items: flex-start; justify-content: flex-start; diff --git a/src/components/Article/CommentsTree.tsx b/src/components/Article/CommentsTree.tsx index cf28fcfd..60054831 100644 --- a/src/components/Article/CommentsTree.tsx +++ b/src/components/Article/CommentsTree.tsx @@ -1,15 +1,15 @@ -import {clsx} from 'clsx' -import {createMemo, createSignal, For, lazy, onMount, Show} from 'solid-js' +import { clsx } from 'clsx' +import { For, Show, createMemo, createSignal, lazy, onMount } from 'solid-js' -import {useLocalize} from '../../context/localize' -import {useReactions} from '../../context/reactions' -import {useSession} from '../../context/session' -import {Author, Reaction, ReactionKind, ReactionSort} from '../../graphql/schema/core.gen' -import {byCreated, byStat} from '../../utils/sortby' -import {Button} from '../_shared/Button' -import {ShowIfAuthenticated} from '../_shared/ShowIfAuthenticated' +import { useLocalize } from '../../context/localize' +import { useReactions } from '../../context/reactions' +import { useSession } from '../../context/session' +import { Author, Reaction, ReactionKind, ReactionSort } from '../../graphql/schema/core.gen' +import { byCreated, byStat } from '../../utils/sortby' +import { Button } from '../_shared/Button' +import { ShowIfAuthenticated } from '../_shared/ShowIfAuthenticated' -import {Comment} from './Comment' +import { Comment } from './Comment' import styles from './Article.module.scss' @@ -95,11 +95,7 @@ export const CommentsTree = (props: Props) => {
        0}>
      • -
      • diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 352d8f6c..1649d92c 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -23,9 +23,9 @@ import { Row2 } from '../../Feed/Row2' import { Row3 } from '../../Feed/Row3' import { Loading } from '../../_shared/Loading' +import { byCreated } from '../../../utils/sortby' import stylesArticle from '../../Article/Article.module.scss' import styles from './Author.module.scss' -import {byCreated} from "../../../utils/sortby"; type Props = { shouts: Shout[] diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index 2a886a10..aeee25b9 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -14,6 +14,7 @@ import { resetSortedArticles, useArticlesStore } from '../../../stores/zine/arti import { useTopAuthorsStore } from '../../../stores/zine/topAuthors' import { useTopicsStore } from '../../../stores/zine/topics' import { getImageUrl } from '../../../utils/getImageUrl' +import { byCreated } from '../../../utils/sortby' import { CommentDate } from '../../Article/CommentDate' import { getShareUrl } from '../../Article/SharePopup' import { AuthorBadge } from '../../Author/AuthorBadge' @@ -48,23 +49,11 @@ type VisibilityItem = { } type FeedSearchParams = { - by: 'publish_date' | 'likes_stat' | 'rating' | 'last_comment' + by: 'publish_date' | 'likes' | 'comments' period: FeedPeriod visibility: VisibilityMode } -const getOrderBy = (by: FeedSearchParams['by']) => { - if (by === 'likes_stat' || by === 'rating') { - return 'likes_stat' - } - - if (by === 'last_comment') { - return 'last_comment' - } - - return '' -} - const getFromDate = (period: FeedPeriod): number => { const now = new Date() let d: Date = now @@ -146,7 +135,7 @@ export const FeedView = (props: Props) => { const loadTopComments = async () => { const comments = await loadReactionsBy({ by: { comment: true }, limit: 50 }) - setTopComments(comments) + setTopComments(comments.sort(byCreated).reverse()) } onMount(() => { @@ -178,9 +167,8 @@ export const FeedView = (props: Props) => { offset: sortedArticles().length, } - const orderBy = getOrderBy(searchParams().by) - if (orderBy) { - options.order_by = orderBy + if (searchParams()?.by) { + options.order_by = searchParams().by } const visibilityMode = searchParams().visibility @@ -222,7 +210,7 @@ export const FeedView = (props: Props) => { const ogTitle = t('Feed') const [shareData, setShareData] = createSignal() - const handleShare = (shared) => { + const handleShare = (shared: Shout | undefined) => { showModal('share') setShareData(shared) } @@ -260,19 +248,19 @@ export const FeedView = (props: Props) => { {/*
      • */}
      • - changeSearchParams({ by: 'rating' })}> + changeSearchParams({ by: 'likes' })}> {t('Top rated')}
      • - changeSearchParams({ by: 'last_comment' })}> + changeSearchParams({ by: 'comments' })}> {t('Most commented')}