Merge branch 'show_author_subscriptions' into 'dev'

Show author subscriptions

See merge request discoursio/discoursio-webapp!54
This commit is contained in:
ilia tapazukk 2023-04-22 14:36:38 +00:00
commit f8a7e98a8e
8 changed files with 139 additions and 43 deletions

View File

@ -235,5 +235,7 @@
"Bookmarks": "Bookmarks",
"Logout": "Logout",
"This comment has not yet been rated": "This comment has not yet been rated",
"This post has not been rated yet": "This post has not been rated yet"
"This post has not been rated yet": "This post has not been rated yet",
"Author subscriptions": "Подписки на авторов",
"Topic subscriptions": "Подписки на темы"
}

View File

@ -253,5 +253,7 @@
"Bookmarks": "Закладки",
"Logout": "Выход",
"This comment has not yet been rated": "Этот комментарий еще пока никто не оценил",
"This post has not been rated yet": "Эту публикацию еще пока никто не оценил"
"This post has not been rated yet": "Эту публикацию еще пока никто не оценил",
"Author subscriptions": "Подписки на авторов",
"Topic subscriptions": "Подписки на темы"
}

View File

@ -1,5 +1,5 @@
import { Show, createMemo, createSignal, Switch, onMount, For, Match, createEffect } from 'solid-js'
import type { Author, Shout } from '../../graphql/types.gen'
import type { Author, Shout, Topic } from '../../graphql/types.gen'
import { Row1 } from '../Feed/Row1'
import { Row2 } from '../Feed/Row2'
import { AuthorFull } from '../Author/Full'
@ -19,6 +19,7 @@ import { apiClient } from '../../utils/apiClient'
import { Comment } from '../Article/Comment'
import { useLocalize } from '../../context/localize'
import { AuthorRatingControl } from '../Author/AuthorRatingControl'
import { TopicCard } from '../Topic/Card'
type AuthorProps = {
shouts: Shout[]
@ -27,7 +28,17 @@ type AuthorProps = {
}
export type AuthorPageSearchParams = {
by: '' | 'viewed' | 'rating' | 'commented' | 'recent' | 'followed' | 'about' | 'popular'
by:
| ''
| 'viewed'
| 'rating'
| 'commented'
| 'recent'
| 'subscribed-authors'
| 'subscribed-topics'
| 'followers'
| 'about'
| 'popular'
}
export const PRERENDERED_ARTICLES_COUNT = 12
@ -41,6 +52,34 @@ export const AuthorView = (props: AuthorProps) => {
const author = authorEntities()[props.authorSlug]
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const [followers, setFollowers] = createSignal<Author[]>([])
const [followingUsers, setFollowingUsers] = createSignal<Author[]>([])
const [subscribedTopics, setSubscribedTopics] = createSignal<Topic[]>([])
onMount(async () => {
if (!props.author.slug) return
try {
const userSubscribers = await apiClient.getAuthorFollowers({ slug: props.author.slug })
setFollowers(userSubscribers)
} catch (error) {
console.log('[getAuthorFollowers]', error)
}
try {
const authorSubscriptionsUsers = await apiClient.getAuthorFollowingUsers({ slug: props.author.slug })
setFollowingUsers(authorSubscriptionsUsers)
} catch (error) {
console.log('[getAuthorFollowingUsers]', error)
}
try {
const authorSubscriptionsTopics = await apiClient.getAuthorFollowingTopics({
slug: props.author.slug
})
setSubscribedTopics(authorSubscriptionsTopics)
} catch (error) {
console.log('[getAuthorFollowing]', error)
}
})
onMount(() => {
if (!searchParams().by) {
@ -114,23 +153,26 @@ export const AuthorView = (props: AuthorProps) => {
{t('Publications')}
</button>
</li>
<li classList={{ selected: searchParams().by === 'followed' }}>
<button type="button" onClick={() => changeSearchParam('by', 'followed')}>
<li classList={{ selected: searchParams().by === 'followers' }}>
<button type="button" onClick={() => changeSearchParam('by', 'followers')}>
{t('Followers')}
</button>
</li>
<li classList={{ selected: searchParams().by === 'subscribed-authors' }}>
<button type="button" onClick={() => changeSearchParam('by', 'subscribed-authors')}>
{t('Author subscriptions')}
</button>
</li>
<li classList={{ selected: searchParams().by === 'subscribed-topics' }}>
<button type="button" onClick={() => changeSearchParam('by', 'subscribed-topics')}>
{t('Topic subscriptions')}
</button>
</li>
<li classList={{ selected: searchParams().by === 'commented' }}>
<button type="button" onClick={() => changeSearchParam('by', 'commented')}>
{t('Comments')}
</button>
</li>
{/*
<li classList={{ selected: searchParams().by === 'popular' }}>
<button type="button" onClick={() => changeSearchParam('by', 'popular')}>
Популярное
</button>
</li>
*/}
<li classList={{ selected: searchParams().by === 'about' }}>
<button type="button" onClick={() => changeSearchParam('by', 'about')}>
{t('About myself')}
@ -205,7 +247,20 @@ export const AuthorView = (props: AuthorProps) => {
</ul>
</div>
</Match>
<Match when={searchParams().by === 'followed'}>
<Match when={searchParams().by === 'subscribed-topics'}>
<div class="wide-container">
<div class="row">
<For each={subscribedTopics()}>
{(topic) => (
<div class="col-md-12 col-lg-8">
<TopicCard compact iconButton isTopicInRow topic={topic} />
</div>
)}
</For>
</div>
</div>
</Match>
<Match when={searchParams().by === 'followers'}>
<div class="wide-container">
<div class="row">
<For each={followers()}>
@ -218,6 +273,19 @@ export const AuthorView = (props: AuthorProps) => {
</div>
</div>
</Match>
<Match when={searchParams().by === 'subscribed-authors'}>
<div class="wide-container">
<div class="row">
<For each={followingUsers()}>
{(follower: Author) => (
<div class="col-md-6 col-lg-4">
<AuthorCard author={follower} hideWriteButton={true} hasLink={true} />
</div>
)}
</For>
</div>
</div>
</Match>
<Match when={searchParams().by === 'rating'}>
<Row1 article={sortedArticles()[0]} />
<Row2 articles={sortedArticles().slice(1, 3)} isEqual={true} />

View File

@ -0,0 +1,19 @@
import { gql } from '@urql/core'
export default gql`
query UserFollowingTopicsQuery($slug: String!) {
userFollowedTopics(slug: $slug) {
id
slug
title
body
pic
# community
stat {
shouts
followers
authors
}
}
}
`

View File

@ -0,0 +1,12 @@
import { gql } from '@urql/core'
export default gql`
query UserFollowingUsersQuery($slug: String!) {
userFollowedAuthors(slug: $slug) {
id
slug
name
userpic
}
}
`

View File

@ -1,23 +0,0 @@
import { gql } from '@urql/core'
export default gql`
query UserFollowingQuery($slug: String!) {
userFollowing(slug: $slug) {
_id: slug
id
slug
name
bio
userpic
communities
links
createdAt
lastSeen
ratings {
_id: rater
rater
value
}
}
}
`

View File

@ -196,6 +196,7 @@ export type Mutation = {
deleteReaction: Result
deleteShout: Result
destroyTopic: Result
draftToShout: Result
follow: Result
getSession: AuthResult
inviteAccept: Result
@ -271,6 +272,10 @@ export type MutationDestroyTopicArgs = {
slug: Scalars['String']
}
export type MutationDraftToShoutArgs = {
draft: Scalars['Int']
}
export type MutationFollowArgs = {
slug: Scalars['String']
what: FollowingEntity
@ -382,6 +387,7 @@ export type Query = {
loadShout?: Maybe<Shout>
loadShouts: Array<Maybe<Shout>>
markdownBody: Scalars['String']
myFeed?: Maybe<Array<Maybe<Shout>>>
searchMessages: Result
searchRecipients: Result
signIn: AuthResult
@ -447,6 +453,10 @@ export type QueryMarkdownBodyArgs = {
body: Scalars['String']
}
export type QueryMyFeedArgs = {
options?: InputMaybe<LoadShoutsOptions>
}
export type QuerySearchMessagesArgs = {
by: MessagesBy
limit?: InputMaybe<Scalars['Int']>
@ -573,6 +583,7 @@ export type Result = {
chats?: Maybe<Array<Maybe<Chat>>>
communities?: Maybe<Array<Maybe<Community>>>
community?: Maybe<Community>
draft?: Maybe<DraftCollab>
drafts?: Maybe<Array<Maybe<DraftCollab>>>
error?: Maybe<Scalars['String']>
members?: Maybe<Array<Maybe<ChatMember>>>
@ -610,7 +621,6 @@ export type Shout = {
mainTopic?: Maybe<Scalars['String']>
media?: Maybe<Scalars['String']>
publishedAt?: Maybe<Scalars['DateTime']>
publishedBy?: Maybe<User>
slug: Scalars['String']
stat?: Maybe<Stat>
subtitle?: Maybe<Scalars['String']>
@ -675,7 +685,8 @@ export type Token = {
export type Topic = {
body?: Maybe<Scalars['String']>
community: Community
community?: Community
id: Scalars['Int']
oid?: Maybe<Scalars['String']>
pic?: Maybe<Scalars['String']>
slug: Scalars['String']

View File

@ -38,7 +38,8 @@ import myChats from '../graphql/query/chats-load'
import chatMessagesLoadBy from '../graphql/query/chat-messages-load-by'
import authorBySlug from '../graphql/query/author-by-slug'
import userSubscribers from '../graphql/query/author-followers'
import userFollowing from '../graphql/query/author-following'
import userFollowedAuthors from '../graphql/query/author-following-users'
import userFollowedTopics from '../graphql/query/author-following-topics'
import topicBySlug from '../graphql/query/topic-by-slug'
import createChat from '../graphql/mutation/create-chat'
import reactionsLoadBy from '../graphql/query/reactions-load-by'
@ -222,9 +223,13 @@ export const apiClient = {
const response = await publicGraphQLClient.query(userSubscribers, { slug }).toPromise()
return response.data.userFollowers
},
getAuthorFollowing: async ({ slug }: { slug: string }): Promise<Author[]> => {
const response = await publicGraphQLClient.query(userFollowing, { slug }).toPromise()
return response.data.userFollowing
getAuthorFollowingUsers: async ({ slug }: { slug: string }): Promise<Author[]> => {
const response = await publicGraphQLClient.query(userFollowedAuthors, { slug }).toPromise()
return response.data.userFollowedAuthors
},
getAuthorFollowingTopics: async ({ slug }: { slug: string }): Promise<Topic[]> => {
const response = await publicGraphQLClient.query(userFollowedTopics, { slug }).toPromise()
return response.data.userFollowedTopics
},
updateProfile: async (input: ProfileInput) => {
const response = await privateGraphQLClient.mutation(updateProfile, { profile: input }).toPromise()