Skip to content

Commit

Permalink
feat: increment page views server-side (#3981)
Browse files Browse the repository at this point in the history
feat: server-side page views
  • Loading branch information
mariojsnunes authored Nov 4, 2024
1 parent 9c8bb45 commit f50ff4e
Show file tree
Hide file tree
Showing 20 changed files with 50 additions and 221 deletions.
3 changes: 1 addition & 2 deletions src/pages/Howto/Content/Howto/Howto.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const mockHowtoStore = () => ({
setActiveHowtoBySlug: vi.fn(),
activeHowto: howto,
needsModeration: vi.fn().mockReturnValue(false),
incrementViewCount: vi.fn(),
removeActiveHowto: vi.fn(),
})

Expand Down Expand Up @@ -151,7 +150,7 @@ describe('Howto', () => {
act(() => {
wrapper = factory(
{
...mockHowtoStore(),
...(mockHowtoStore() as any),
},
FactoryHowto({
_createdBy: 'HowtoAuthor',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Fragment, useEffect, useState } from 'react'
import { Fragment, useState } from 'react'
import { Link, useNavigate } from '@remix-run/react'
import {
Button,
Expand All @@ -25,7 +25,6 @@ import {
isAllowedToDeleteContent,
isAllowedToEditContent,
} from 'src/utils/helpers'
import { incrementViewCount } from 'src/utils/incrementViewCount'
import { Alert, Box, Card, Divider, Flex, Heading, Image, Text } from 'theme-ui'

import { ContentAuthorTimestamp } from '../../../../common/ContentAuthorTimestamp/ContentAuthorTimestamp'
Expand Down Expand Up @@ -73,14 +72,6 @@ const HowtoDescription = ({ howto, loggedInUser, ...props }: IProps) => {
}
}

useEffect(() => {
incrementViewCount({
document: howto,
documentType: 'howto',
store: stores.howtoStore,
})
}, [howto._id])

return (
<Card>
<Flex
Expand Down
1 change: 0 additions & 1 deletion src/pages/Research/Content/ResearchArticle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ describe('Research Article', () => {
const mockResearchStore = {
addSubscriberToResearchArticle: vi.fn(),
formatResearchCommentList: vi.fn(),
incrementViewCount: vi.fn(),
}

it('displays content statistics', async () => {
Expand Down
11 changes: 1 addition & 10 deletions src/pages/Research/Content/ResearchDescription.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Fragment, useEffect, useState } from 'react'
import { Fragment, useState } from 'react'
import { Link, useNavigate } from '@remix-run/react'
import {
Button,
Expand All @@ -19,7 +19,6 @@ import { TagList } from 'src/common/Tags/TagsList'
import { logger } from 'src/logger'
import { useResearchStore } from 'src/stores/Research/research.store'
import { buildStatisticsLabel } from 'src/utils/helpers'
import { incrementViewCount } from 'src/utils/incrementViewCount'
import { Box, Card, Divider, Flex, Heading, Text } from 'theme-ui'

import { ContentAuthorTimestamp } from '../../common/ContentAuthorTimestamp/ContentAuthorTimestamp'
Expand Down Expand Up @@ -82,14 +81,6 @@ const ResearchDescription = ({
}
}

useEffect(() => {
incrementViewCount({
store,
document: research,
documentType: 'research',
})
}, [research._id])

return (
<Card
sx={{
Expand Down
1 change: 0 additions & 1 deletion src/pages/User/user.routes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ vi.mock('src/common/hooks/useCommonStores', () => ({
stores: {
userStore: {
updateUserBadge: mockUpdateUserBadge,
incrementViewCount: vi.fn(),
},
aggregationsStore: {
updateVerifiedUsers: vi.fn(),
Expand Down
6 changes: 6 additions & 0 deletions src/routes/_.how-to.$slug._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useLoaderData } from '@remix-run/react'
import { Howto } from 'src/pages/Howto/Content/Howto/Howto'
import { howtoService } from 'src/pages/Howto/howto.service'
import { NotFoundPage } from 'src/pages/NotFound/NotFound'
import { pageViewService } from 'src/services/pageView.service'
import { generateTags, mergeMeta } from 'src/utils/seo.utils'

import type { LoaderFunctionArgs } from '@remix-run/node'
Expand All @@ -11,6 +12,11 @@ import type { IHowtoDB } from 'oa-shared'
export async function loader({ params }: LoaderFunctionArgs) {
const howto = await howtoService.getBySlug(params.slug as string)

if (howto?._id) {
// not awaited to not block the render
pageViewService.incrementViewCount('howtos', howto._id)
}

return json({ howto })
}

Expand Down
6 changes: 6 additions & 0 deletions src/routes/_.questions.$slug._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useLoaderData } from '@remix-run/react'
import { NotFoundPage } from 'src/pages/NotFound/NotFound'
import { questionService } from 'src/pages/Question/question.service'
import { QuestionPage } from 'src/pages/Question/QuestionPage'
import { pageViewService } from 'src/services/pageView.service'
import { generateTags, mergeMeta } from 'src/utils/seo.utils'

import type { LoaderFunctionArgs } from '@remix-run/node'
Expand All @@ -11,6 +12,11 @@ import type { IQuestionDB, IUploadedFileMeta } from 'oa-shared'
export async function loader({ params }: LoaderFunctionArgs) {
const question = await questionService.getBySlug(params.slug as string)

if (question?._id) {
// not awaited to not block the render
pageViewService.incrementViewCount('questions', question._id)
}

return json({ question })
}

Expand Down
6 changes: 6 additions & 0 deletions src/routes/_.research.$slug._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ResearchUpdateStatus } from 'oa-shared'
import { NotFoundPage } from 'src/pages/NotFound/NotFound'
import ResearchArticle from 'src/pages/Research/Content/ResearchArticle'
import { researchService } from 'src/pages/Research/research.service'
import { pageViewService } from 'src/services/pageView.service'
import { generateTags, mergeMeta } from 'src/utils/seo.utils'

import type { LoaderFunctionArgs } from '@remix-run/node'
Expand All @@ -16,6 +17,11 @@ export async function loader({ params }: LoaderFunctionArgs) {
(x) => x.status !== ResearchUpdateStatus.DRAFT && x._deleted !== true,
) || []

if (research?._id) {
// not awaited to not block the render
pageViewService.incrementViewCount('research', research._id)
}

return json({ research, publicUpdates })
}

Expand Down
6 changes: 6 additions & 0 deletions src/routes/_.u.$id._index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { json } from '@remix-run/node'
import { useLoaderData } from '@remix-run/react'
import { UserProfile } from 'src/pages/User/content/UserProfile'
import { pageViewService } from 'src/services/pageView.service'
import { userService } from 'src/services/user.service'
import { generateTags, mergeMeta } from 'src/utils/seo.utils'
import { Text } from 'theme-ui'
Expand All @@ -16,6 +17,11 @@ export async function loader({ params }: LoaderFunctionArgs) {
userService.getUserCreatedDocs(userId),
])

if (profile?._id) {
// not awaited to not block the render
pageViewService.incrementViewCount('users', profile._id)
}

return json({ profile, userCreatedDocs: userCreatedDocs || [] })
}

Expand Down
23 changes: 23 additions & 0 deletions src/services/pageView.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { doc, increment, updateDoc } from 'firebase/firestore'
import { DB_ENDPOINTS } from 'oa-shared'
import { firestore } from 'src/utils/firebase'

type PageViewCollections = Pick<
typeof DB_ENDPOINTS,
'users' | 'questions' | 'research' | 'howtos'
>

const incrementViewCount = async (
collectionName: keyof PageViewCollections,
id: string,
) => {
const docRef = doc(firestore, DB_ENDPOINTS[collectionName], id)

return await updateDoc(docRef, {
total_views: increment(1),
})
}

export const pageViewService = {
incrementViewCount,
}
16 changes: 0 additions & 16 deletions src/stores/Howto/howto.store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,20 +227,4 @@ describe('howto.store', () => {
expect(updatedDownloads).toBe(downloads + 1)
})
})

describe('incrementViews', () => {
it('increments views by one', async () => {
const howtoDoc = FactoryHowto({ total_views: 18 })
const { store, howToItem, updateFn } = await factory([howtoDoc])

// Act
await store.incrementViewCount(howToItem)
const updatedTotalViews = 19

expect(updateFn).toHaveBeenCalledWith(
expect.objectContaining({ total_views: updatedTotalViews }),
expect.anything(),
)
})
})
})
9 changes: 0 additions & 9 deletions src/stores/Howto/howto.store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { logger } from 'src/logger'
import { getUserCountry } from 'src/utils/getUserCountry'
import { getKeywords } from 'src/utils/searchHelper'

import { incrementDocViewCount } from '../common/incrementDocViewCount'
import { changeMentionToUserReference } from '../common/mentions'
import { ModuleStore } from '../common/module.store'
import { toggleDocUsefulByUser } from '../common/toggleDocUsefulByUser'
Expand Down Expand Up @@ -91,14 +90,6 @@ export class HowtoStore extends ModuleStore {
}
}

public async incrementViewCount(howTo: Partial<IHowtoDB>) {
return await incrementDocViewCount({
collection: COLLECTION_NAME,
db: this.db,
doc: howTo,
})
}

private async addUserReference(msg: string): Promise<{
text: string
users: string[]
Expand Down
24 changes: 0 additions & 24 deletions src/stores/Question/question.store.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,6 @@ describe('question.store', () => {
})
})

describe('incrementViews', () => {
it('increments views by one', async () => {
const { store, updateFn } = factory()

const question = FactoryQuestionItem({
title: 'which trees to cut down',
_createdBy: undefined,
total_views: 56,
})

// Act
await store.upsertQuestion(question)

// Act
await store.incrementViewCount(question)
const updatedTotalViews = 57

expect(updateFn).toHaveBeenCalledWith(
expect.objectContaining({ total_views: updatedTotalViews }),
expect.anything(),
)
})
})

describe('toggleSubscriberStatusByUserName', () => {
it('calls the toggle subscriber function', async () => {
const { store } = factory()
Expand Down
10 changes: 0 additions & 10 deletions src/stores/Question/question.store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { logger } from 'src/logger'
import { getUserCountry } from 'src/utils/getUserCountry'
import { getKeywords } from 'src/utils/searchHelper'

import { incrementDocViewCount } from '../common/incrementDocViewCount'
import { ModuleStore } from '../common/module.store'
import { toggleDocSubscriberStatusByUserName } from '../common/toggleDocSubscriberStatusByUserName'
import { toggleDocUsefulByUser } from '../common/toggleDocUsefulByUser'
Expand All @@ -12,7 +11,6 @@ import type {
IConvertedFileMeta,
IModerationStatus,
IQuestion,
IQuestionDB,
IUploadedFileMeta,
} from 'oa-shared'
import type { DBEndpoint } from '../databaseV2/endpoints'
Expand All @@ -25,14 +23,6 @@ export class QuestionStore extends ModuleStore {
super(rootStore, COLLECTION_NAME)
}

public async incrementViewCount(question: Partial<IQuestionDB>) {
await incrementDocViewCount({
collection: COLLECTION_NAME,
db: this.db,
doc: question,
})
}

public async upsertQuestion(values: IQuestion.FormInput) {
logger.info(`upsertQuestion:`, { values, activeUser: this.activeUser })

Expand Down
15 changes: 0 additions & 15 deletions src/stores/Research/research.store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,21 +412,6 @@ describe('research.store', () => {
})
})

describe('incrementViews', () => {
it('increments views by one', async () => {
const { store, researchItem, updateFn } = await factoryResearchItem()

// Act
await store.incrementViewCount(researchItem)
const updatedTotalViews = researchItem.total_views + 1

expect(updateFn).toHaveBeenCalledWith(
expect.objectContaining({ total_views: updatedTotalViews }),
expect.anything(),
)
})
})

describe('Subscribe', () => {
it('adds subscriber to the research article', async () => {
const { store, researchItem, updateFn } =
Expand Down
9 changes: 0 additions & 9 deletions src/stores/Research/research.store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { getUserCountry } from 'src/utils/getUserCountry'
import { hasAdminRights, randomID } from 'src/utils/helpers'
import { getKeywords } from 'src/utils/searchHelper'

import { incrementDocViewCount } from '../common/incrementDocViewCount'
import { changeMentionToUserReference } from '../common/mentions'
import { ModuleStore } from '../common/module.store'
import { toggleDocSubscriberStatusByUserName } from '../common/toggleDocSubscriberStatusByUserName'
Expand Down Expand Up @@ -98,14 +97,6 @@ export class ResearchStore extends ModuleStore {
return
}

public async incrementViewCount(researchItem: Partial<IResearch.ItemDB>) {
return await incrementDocViewCount({
collection: COLLECTION_NAME,
db: this.db,
doc: researchItem,
})
}

public async deleteResearch(id: string) {
try {
const dbRef = this.db.collection<IResearchDB>(COLLECTION_NAME).doc(id)
Expand Down
9 changes: 0 additions & 9 deletions src/stores/User/user.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { logger } from '../../logger'
import { auth, EmailAuthProvider } from '../../utils/firebase'
import { getLocationData } from '../../utils/getLocationData'
import { formatLowerNoSpecial } from '../../utils/helpers'
import { incrementDocViewCount } from '../common/incrementDocViewCount'
import { ModuleStore } from '../common/module.store'
import { Storage } from '../storage'

Expand Down Expand Up @@ -274,14 +273,6 @@ export class UserStore extends ModuleStore {
return this.activeUser
}

public async incrementViewCount(user: Partial<IUserDB>) {
return await incrementDocViewCount({
collection: COLLECTION_NAME,
db: this.db,
doc: user,
})
}

public async updateUserImpact(
fields: IImpactYearFieldList,
year: IImpactYear,
Expand Down
27 changes: 0 additions & 27 deletions src/stores/common/incrementDocViewCount.tsx

This file was deleted.

Loading

0 comments on commit f50ff4e

Please sign in to comment.