Skip to content

Commit

Permalink
Add post view query
Browse files Browse the repository at this point in the history
  • Loading branch information
teodorus-nathaniel committed Mar 12, 2024
1 parent 9b25d00 commit fb04dec
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/components/posts/view-post/PostPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { useAppDispatch, useAppSelector } from 'src/rtk/app/store'
import { fetchPostRewards } from 'src/rtk/features/activeStaking/postRewardSlice'
import { fetchTopUsersWithSpaces } from 'src/rtk/features/leaderboard/topUsersSlice'
import { fetchPost, fetchPosts, selectPost } from 'src/rtk/features/posts/postsSlice'
import { fetchPostsViewCount } from 'src/rtk/features/posts/postsViewCountSlice'
import { useFetchMyReactionsByPostId } from 'src/rtk/features/reactions/myPostReactionsHooks'
import { asCommentStruct, HasStatusCode, idToBn, PostData, PostWithSomeDetails } from 'src/types'
import { DfImage } from '../../utils/DfImage'
Expand Down Expand Up @@ -336,7 +337,8 @@ const PostPage: FC<PostDetailsProps & HasStatusCode> = props => {
const { statusCode, postData } = props
const dispatch = useAppDispatch()
useEffect(() => {
dispatch(fetchPostRewards({ postIds: [postData.id] as string[] }))
dispatch(fetchPostRewards({ postIds: [postData.id] }))
dispatch(fetchPostsViewCount({ postIds: [postData.id] }))
}, [dispatch])

if (statusCode === 404) {
Expand Down
17 changes: 17 additions & 0 deletions src/components/posts/view-post/PostViewCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ComponentProps } from 'react'
import { FaRegEye } from 'react-icons/fa'
import { IconWithLabel } from 'src/components/utils'
import { usePostViewCount } from 'src/rtk/app/hooks'

export default function PostViewCount({
postId,
...props
}: { postId: string } & ComponentProps<'div'>) {
const viewCount = usePostViewCount(postId)

return (
<div {...props} className={props.className}>
<IconWithLabel renderZeroCount icon={<FaRegEye />} count={viewCount} />
</div>
)
}
3 changes: 3 additions & 0 deletions src/components/posts/view-post/helpers.module.sass
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

.PostActions
gap: $space_large
display: grid
width: 100%
grid-template-columns: 1fr 1fr 1fr 1fr

@media screen and ( max-width: 768px)
gap: $space_normal
Expand Down
6 changes: 4 additions & 2 deletions src/components/posts/view-post/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import ViewPostLink from '../ViewPostLink'
import styles from './helpers.module.sass'
import { PostDropDownMenu } from './PostDropDownMenu'
import PostRewardStat from './PostRewardStat'
import PostViewCount from './PostViewCount'
import TwitterPost from './TwitterPost'

type IsUnlistedPostProps = {
Expand Down Expand Up @@ -336,11 +337,12 @@ export const PostActionsPanel: FC<PostActionsPanelProps> = props => {

return (
<div className={`DfActionsPanel ${withBorder && 'DfActionBorder'} ${className ?? ''}`}>
<div className={clsx('d-flex align-items-center GapHuge', styles.PostActions)}>
<div className={clsx(styles.PostActions)}>
<SuperLike post={struct} />
{preview && <CommentAction {...props} />}
<PostViewCount postId={struct.id} />
<PostRewardStat postId={postDetails.id} />
</div>
<PostRewardStat postId={postDetails.id} />
{/* <ShareDropdown postDetails={postDetails} space={space} className='DfAction' /> */}
</div>
)
Expand Down
4 changes: 3 additions & 1 deletion src/components/spaces/ViewSpacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useAppDispatch } from 'src/rtk/app/store'
import { fetchPostRewards } from 'src/rtk/features/activeStaking/postRewardSlice'
import { useFetchMyPermissionsBySpaceId } from 'src/rtk/features/permissions/mySpacePermissionsHooks'
import { fetchPosts, selectPosts } from 'src/rtk/features/posts/postsSlice'
import { fetchPostsViewCount } from 'src/rtk/features/posts/postsViewCountSlice'
import { fetchProfileSpace, selectProfileSpace } from 'src/rtk/features/profiles/profilesSlice'
import { DataSourceTypes, HasStatusCode, idToBn, SpaceContent } from 'src/types'
import { descSort, isPolkaProject, isUnclaimedSpace } from 'src/utils'
Expand Down Expand Up @@ -81,7 +82,8 @@ const ViewSpacePage: FC<Props & { prefetchedIds: string[] }> = props => {

const dispatch = useAppDispatch()
useEffect(() => {
dispatch(fetchPostRewards({ postIds: prefetchedIds as string[] }))
dispatch(fetchPostRewards({ postIds: prefetchedIds }))
dispatch(fetchPostsViewCount({ postIds: prefetchedIds }))
}, [dispatch])

if (statusCode === 404) {
Expand Down
41 changes: 40 additions & 1 deletion src/components/utils/datahub/post-view.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
import { SocialCallDataArgs, socialCallName } from '@subsocial/data-hub-sdk'
import axios from 'axios'
import { createSocialDataEventPayload, DatahubParams } from './utils'
import gql from 'graphql-tag'
import { PostViewCount } from 'src/rtk/features/posts/postsViewCountSlice'
import { createSocialDataEventPayload, DatahubParams, datahubQueryRequest } from './utils'

// QUERIES
const GET_POSTS_VIEW_COUNT = gql`
query GetPostsViewCount($postIds: [String!]!) {
postsViewsCounts(where: { persistentIds: $postIds }) {
postPersistentId
viewsCountTotal
}
}
`
export async function getPostsViewCount(postIds: string[]): Promise<PostViewCount[]> {
const res = await datahubQueryRequest<
{
postsViewsCounts: { postPersistentId: string; viewsCountTotal: number }[]
},
{ postIds: string[] }
>({
query: GET_POSTS_VIEW_COUNT,
variables: { postIds },
})

const resultMap = new Map<string, PostViewCount>()
res.data.postsViewsCounts.forEach(item =>
resultMap.set(item.postPersistentId, {
postId: item.postPersistentId,
viewsCount: item.viewsCountTotal,
}),
)

return postIds.map(
postId =>
resultMap.get(postId) ?? {
postId,
viewsCount: 0,
},
)
}

// MUTATIONS
export async function addPostView(
Expand Down
2 changes: 2 additions & 0 deletions src/rtk/app/rootReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import mySpacePermissions from '../features/permissions/mySpacePermissionsSlice'
import myFeed from '../features/posts/myFeedSlice'
import ownPostIds from '../features/posts/ownPostIdsSlice'
import posts from '../features/posts/postsSlice'
import postsViewCount from '../features/posts/postsViewCountSlice'
import followedAccountIds from '../features/profiles/followedAccountIdsSlice'
import profileSpaces from '../features/profiles/profilesSlice'
import myPostReactions from '../features/reactions/myPostReactionsSlice'
Expand Down Expand Up @@ -79,6 +80,7 @@ const rootReducer = combineReducers({
leaderboard,
prevReward,
superLikeMessage,
postsViewCount,
})

export type RootState = ReturnType<typeof rootReducer>
Expand Down
5 changes: 5 additions & 0 deletions src/rtk/features/posts/postsHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
selectPostStructById,
upsertPost,
} from './postsSlice'
import { selectPostViewCount } from './postsViewCountSlice'

export function useIsMuted(address: string) {
const myAddress = useMyAddress() ?? ''
Expand Down Expand Up @@ -102,3 +103,7 @@ export function useFilterLowValuePosts(postIds: string[]) {
return { filtered, filteredCount }
}, [postIds.join(','), myAddress])
}

export function usePostViewCount(postId: string) {
return useAppSelector(state => selectPostViewCount(state, postId)?.viewsCount ?? 0)
}
2 changes: 2 additions & 0 deletions src/rtk/features/posts/postsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { fetchSuperLikeCounts } from '../activeStaking/superLikeCountsSlice'
import { Content, fetchContents, selectPostContentById } from '../contents/contentsSlice'
import { fetchProfileSpaces } from '../profiles/profilesSlice'
import { fetchSpaces } from '../spaces/spacesSlice'
import { fetchPostsViewCount } from './postsViewCountSlice'
export interface PostState extends PostStruct {
isOverview?: boolean
}
Expand Down Expand Up @@ -253,6 +254,7 @@ export const fetchPosts = createAsyncThunk<PostStruct[], FetchPostsArgs, ThunkAp
// will not be prefetched from server side because this query takes pretty long
if (isClientSide()) {
dispatch(fetchPostRewards({ postIds: newIds as string[] }))
dispatch(fetchPostsViewCount({ postIds: newIds as string[] }))
}
const fetches: Promise<any>[] = [
dispatch(fetchSuperLikeCounts({ postIds: newIds as string[] })),
Expand Down
45 changes: 45 additions & 0 deletions src/rtk/features/posts/postsViewCountSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'
import { getPostsViewCount } from 'src/components/utils/datahub/post-view'
import { RootState } from 'src/rtk/app/rootReducer'
import { createSimpleManyFetchWrapper } from 'src/rtk/app/wrappers'

export type PostViewCount = {
postId: string
viewsCount: number
}

const sliceName = 'postsViewCount'

const adapter = createEntityAdapter<PostViewCount>({
selectId: data => data.postId,
})
const selectors = adapter.getSelectors<RootState>(state => state.postsViewCount)

export const selectPostViewCount = selectors.selectById

export const fetchPostsViewCount = createSimpleManyFetchWrapper<
{ postIds: string[] },
PostViewCount
>({
sliceName,
fetchData: async function ({ postIds }) {
return await getPostsViewCount(postIds)
},
getCachedData: (state, id) => selectPostViewCount(state, id),
saveToCacheAction: data => slice.actions.setPostsViewCount(data),
shouldFetchCondition: ({ postIds }) => postIds?.length !== 0,
filterNewArgs: ({ postIds }, isNewId) => {
const newPostIds = postIds?.filter(postId => isNewId(postId))
return { postIds: newPostIds }
},
})

const slice = createSlice({
name: sliceName,
initialState: adapter.getInitialState(),
reducers: {
setPostsViewCount: adapter.upsertMany,
},
})

export default slice.reducer

0 comments on commit fb04dec

Please sign in to comment.