Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add dynamic page title to all pages #20

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/communication-template/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
'use client'

import { CommunicationTemplateForm } from 'components/communication-template/form'
import { useEffect } from 'react'

export default function CommunicationTemplateEditPage({ params: { id } }) {
// Change page title dynamically
useEffect(() => {
document.title = `Edit Communication Templates #${id}`
}, [id])

return (
<div className="w-5/6 md:w-2/3 lg:w-1/2 mx-auto">
<h2 className="text-gray-600 font-semibold mb-3 pb-2 mt-4 border-b border-gray-300">
Expand Down
6 changes: 6 additions & 0 deletions app/communication-template/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
'use client'

import { CommunicationTemplateForm } from 'components/communication-template/form'
import { useEffect } from 'react'

export default function CommunicationTemplateCreatePage() {
// Change page title dynamically
useEffect(() => {
document.title = `Create Communication Templates`
}, [])

return (
<div className="w-5/6 md:w-2/3 lg:w-1/2 mx-auto">
<h2 className="text-gray-600 font-semibold mb-3 pb-2 mt-4 border-b border-gray-300">
Expand Down
7 changes: 6 additions & 1 deletion app/communication-template/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import format from 'date-fns/format'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import Link from 'next/link'
import { PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/20/solid'

Expand All @@ -17,6 +17,11 @@ export default function CommunicationTemplatePage() {
string | undefined
>()

// Change page title dynamically
useEffect(() => {
document.title = `Communication Templates`
}, [])

if (isLoading) {
return <Loading message="Loading templates" />
}
Expand Down
19 changes: 15 additions & 4 deletions app/events/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { useQuery } from '@tanstack/react-query'
import client from '@/lib/client'
import { Loading, LoadingFailed } from '@/common/Loader'
import { EventView } from '@/mod-event/View'
import { useEffect } from 'react'
import { MOD_EVENT_TITLES } from '@/mod-event/constants'

export default function EventViewPage({ params }: { params: { id: string } }) {
const id = decodeURIComponent(params.id)
const {
data: event,
error,
} = useQuery({
const { data: event, error } = useQuery({
queryKey: ['event', { id }],
queryFn: async () => {
const { data } = await client.api.com.atproto.admin.getModerationEvent(
Expand All @@ -20,6 +19,18 @@ export default function EventViewPage({ params }: { params: { id: string } }) {
},
})

// Change page title dynamically
// Use a human-readable event name once event details are fetched
useEffect(() => {
if (event) {
const eventTitle =
MOD_EVENT_TITLES[event.event.$type as string] || 'Moderation'
document.title = `${eventTitle} Event #${id}`
} else {
document.title = `Moderation Event #${id}`
}
}, [id, event])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the title is just a string which itself can be used as an effect dependency, you could imagine a hook for this like:

function useTitle(title: string) {
  useEffect(() => {
    document.title = title
  }, [title])
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... I mean we could also use the hook from react-use package since we're using it already across the codebase.


if (error) {
return <LoadingFailed error={error} />
}
Expand Down
5 changes: 5 additions & 0 deletions app/events/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { emitEvent } from '@/mod-event/helpers/emitEvent'
import { ComAtprotoAdminEmitModerationEvent } from '@atproto/api'
import { ModActionPanelQuick } from 'app/actions/ModActionPanel/QuickAction'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useEffect } from 'react'

export default function EventListPageContent() {
const searchParams = useSearchParams()
Expand All @@ -19,6 +20,10 @@ export default function EventListPageContent() {
router.push((pathname ?? '') + '?' + newParams.toString())
}

useEffect(() => {
document.title = `Moderation Events`
}, [])

return (
<div>
<div className="w-5/6 sm:w-3/4 md:w-2/3 lg:w-1/2 mx-auto my-4">
Expand Down
28 changes: 27 additions & 1 deletion app/reports/page-content.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import { useContext, useCallback, Suspense } from 'react'
import { useContext, useCallback, Suspense, useEffect } from 'react'
import {
ReadonlyURLSearchParams,
usePathname,
Expand Down Expand Up @@ -197,6 +197,32 @@ export const ReportsPageContent = () => {
),
)

useEffect(() => {
const titleFromTab =
currentTab === 'all'
? `All subjects`
: `${currentTab[0].toUpperCase()}${currentTab.slice(1)}`
const additionalFragments: string[] = []

if (takendown) {
additionalFragments.push('Taken Down')
}

if (includeMuted) {
additionalFragments.push('Include Muted')
}

if (appealed) {
additionalFragments.push('Appealed')
}

const additionalTitle = additionalFragments.length
? ` (${additionalFragments.join(', ')})`
: ''
const title = `Queue - ${titleFromTab}${additionalTitle}`
document.title = title
}, [currentTab, takendown, includeMuted, appealed])

return (
<>
<SectionHeader title="Queue" tabs={TABS} current={currentTab}>
Expand Down
25 changes: 25 additions & 0 deletions app/repositories/[id]/[...record]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,31 @@ export default function Record({
}
}, [data, reportUri])

// Change title dynamically
// Show the collection name
// Once we retrieve the profile/repo details, show the handle
useEffect(() => {
let title = `Record Details`

if (collection) {
const titleFromCollection = collection.split('.').pop()
if (titleFromCollection) {
title =
titleFromCollection[0].toUpperCase() + titleFromCollection.slice(1)
}
}

if (data?.record?.repo) {
title += ` - ${data.record.repo.handle}`
}

if (rkey) {
title += ` - ${rkey}`
}

document.title = title
}, [data, collection])

if (error) {
return <LoadingFailed error={error} />
}
Expand Down
25 changes: 25 additions & 0 deletions app/repositories/[id]/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ComAtprotoAdminEmitModerationEvent } from '@atproto/api'
import { ModActionPanelQuick } from 'app/actions/ModActionPanel/QuickAction'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { emitEvent } from '@/mod-event/helpers/emitEvent'
import { useEffect } from 'react'

export function RepositoryViewPageContent({ id }: { id: string }) {
const {
Expand All @@ -27,6 +28,30 @@ export function RepositoryViewPageContent({ id }: { id: string }) {
}
router.push((pathname ?? '') + '?' + newParams.toString())
}
const tab = searchParams.get('tab')

// Change title dynamically
// Once we retrieve the profile/repo details, show the handle
// Show the current tab name from account view
useEffect(() => {
let title = `Repository Details`
const titleFragments: string[] = [title]
const titleFromTab = tab ? tab[0].toUpperCase() + tab.slice(1) : ''

if (titleFromTab) {
titleFragments.unshift(titleFromTab)
}

if (profile) {
titleFragments.unshift(profile.handle)
} else if (repo) {
titleFragments.unshift(repo.handle)
} else {
titleFragments.unshift(id)
}

document.title = titleFragments.join(' - ')
}, [id, repo, profile, tab])

return (
<>
Expand Down
13 changes: 13 additions & 0 deletions app/repositories/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RepositoriesTable } from '@/repositories/RepositoriesTable'
import { useSearchParams } from 'next/navigation'
import { useInfiniteQuery } from '@tanstack/react-query'
import client from '@/lib/client'
import { useEffect } from 'react'

export default function RepositoriesListPage() {
const params = useSearchParams()
Expand All @@ -22,6 +23,18 @@ export default function RepositoriesListPage() {
},
getNextPageParam: (lastPage) => lastPage.cursor,
})

// Change title dynamically, if there's a search term, include that
useEffect(() => {
let title = `Repositories`

if (term) {
title += ` - ${term}`
}

document.title = title
}, [term])

const repos = data?.pages.flatMap((page) => page.repos) ?? []
return (
<>
Expand Down
11 changes: 11 additions & 0 deletions app/subject-status/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import client from '@/lib/client'
import { Loading, LoadingFailed } from '@/common/Loader'
import { useSearchParams } from 'next/navigation'
import { SubjectStatusView } from '@/subject/StatusView'
import { useEffect } from 'react'

export default function SubjectStatus() {
const params = useSearchParams()
Expand All @@ -21,6 +22,16 @@ export default function SubjectStatus() {
},
})

useEffect(() => {
let title = `Subject Status`

if (data?.subjectStatuses[0]) {
title = `${data.subjectStatuses[0].subjectRepoHandle} - ${title}`
}

document.title = title
}, [data])

if (status === 'loading') {
return <Loading />
}
Expand Down
6 changes: 5 additions & 1 deletion app/surprise-me/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useInterval } from 'react-use'
import dynamic from 'next/dynamic'

Expand Down Expand Up @@ -38,6 +38,10 @@ const Timer = () => {
// Right now, we only serve the tetris game here, in the future, we want to rotate
// between a few games/fun activities which is why it's named "surprise me"
export default function SurpriseMePage() {
useEffect(() => {
document.title = `Take a break!`
}, [])

return (
<>
{/* This is valid jsx but because of a known bug, typescript is confused */}
Expand Down
7 changes: 7 additions & 0 deletions components/shell/LoginModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ export function LoginModal() {
}
}, [])

useEffect(() => {
const title = `Ozone - Authenticate`
if (!isLoggedIn) {
document.title = title
}
}, [isLoggedIn])

const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
e.stopPropagation()
Expand Down
Loading