From 9470175535486cb6299c45fedd16b3773e733d05 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 21 Feb 2024 12:13:40 +0300 Subject: [PATCH 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 11e722d2afc970b13367c3f37085d08d5e697b8a Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 23 Feb 2024 02:13:31 +0300 Subject: [PATCH 6/8] 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 7/8] 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 8/8] 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 })