Skip to content

Commit

Permalink
Merge pull request #20 from bluesky-social/page-title
Browse files Browse the repository at this point in the history
✨ Add dynamic page title to all pages
  • Loading branch information
foysalit authored Feb 7, 2024
2 parents 848835a + 73af95f commit f05587e
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 7 deletions.
3 changes: 3 additions & 0 deletions app/communication-template/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use client'

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

export default function CommunicationTemplateEditPage({ params: { id } }) {
useTitle(`Edit Communication Templates #${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
3 changes: 3 additions & 0 deletions app/communication-template/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use client'

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

export default function CommunicationTemplateCreatePage() {
useTitle(`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
3 changes: 3 additions & 0 deletions app/communication-template/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import format from 'date-fns/format'
import { useState } from 'react'
import Link from 'next/link'
import { PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/20/solid'
import { useTitle } from 'react-use'

import { LabelChip } from '@/common/labels'
import { Loading, LoadingFailed } from '@/common/Loader'
Expand All @@ -17,6 +18,8 @@ export default function CommunicationTemplatePage() {
string | undefined
>()

useTitle(`Communication Templates`)

if (isLoading) {
return <Loading message="Loading templates" />
}
Expand Down
15 changes: 11 additions & 4 deletions app/events/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import { useTitle } from 'react-use'
import client from '@/lib/client'
import { Loading, LoadingFailed } from '@/common/Loader'
import { EventView } from '@/mod-event/View'
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,14 @@ export default function EventViewPage({ params }: { params: { id: string } }) {
},
})

let pageTitle = `Moderation Event #${id}`
if (event) {
const eventTitle =
MOD_EVENT_TITLES[event.event.$type as string] || 'Moderation'
pageTitle = `${eventTitle} Event #${id}`
}
useTitle(pageTitle)

if (error) {
return <LoadingFailed error={error} />
}
Expand Down
3 changes: 3 additions & 0 deletions app/events/page-content.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTitle } from 'react-use'
import { ModEventList } from '@/mod-event/EventList'
import { emitEvent } from '@/mod-event/helpers/emitEvent'
import { ComAtprotoAdminEmitModerationEvent } from '@atproto/api'
Expand All @@ -19,6 +20,8 @@ export default function EventListPageContent() {
router.push((pathname ?? '') + '?' + newParams.toString())
}

useTitle(`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
47 changes: 46 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 All @@ -22,6 +22,7 @@ import { AuthContext } from '@/shell/AuthContext'
import { ButtonGroup } from '@/common/buttons'
import { useFluentReportSearch } from '@/reports/useFluentReportSearch'
import { SubjectTable } from 'components/subject/table'
import { useTitle } from 'react-use'

const TABS = [
{
Expand All @@ -48,6 +49,42 @@ const TABS = [
{ key: 'all', name: 'All', href: '/reports' },
]

const buildPageTitle = ({
currentTab,
takendown,
includeMuted,
appealed,
}: {
currentTab: string
takendown: boolean
includeMuted: boolean
appealed: boolean
}) => {
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}`
return title
}

const ResolvedFilters = () => {
const router = useRouter()
const pathname = usePathname()
Expand Down Expand Up @@ -197,6 +234,14 @@ export const ReportsPageContent = () => {
),
)

const pageTitle = buildPageTitle({
currentTab,
takendown,
includeMuted,
appealed,
})
useTitle(pageTitle)

return (
<>
<SectionHeader title="Queue" tabs={TABS} current={currentTab}>
Expand Down
37 changes: 37 additions & 0 deletions app/repositories/[id]/[...record]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@ import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { ModActionPanelQuick } from 'app/actions/ModActionPanel/QuickAction'
import { emitEvent } from '@/mod-event/helpers/emitEvent'
import { useEffect } from 'react'
import { useTitle } from 'react-use'

const buildPageTitle = ({
handle,
collection,
rkey,
}: {
handle?: string
collection?: string
rkey?: string
}) => {
let title = `Record Details`

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

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

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

export default function Record({
params,
Expand Down Expand Up @@ -116,6 +146,13 @@ export default function Record({
}
}, [data, reportUri])

const pageTitle = buildPageTitle({
handle: data?.record?.repo.handle,
rkey,
collection,
})
useTitle(pageTitle)

if (error) {
return <LoadingFailed error={error} />
}
Expand Down
29 changes: 29 additions & 0 deletions app/repositories/[id]/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,29 @@ 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 { useTitle } from 'react-use'

const buildPageTitle = ({
handle,
tab,
}: {
handle: string
tab: string | null
}) => {
let title = `Repository Details`
const titleFragments: string[] = [title]
const titleFromTab = tab ? tab[0].toUpperCase() + tab.slice(1) : ''

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

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

return titleFragments.join(' - ')
}
export function RepositoryViewPageContent({ id }: { id: string }) {
const {
error,
Expand All @@ -27,6 +49,13 @@ export function RepositoryViewPageContent({ id }: { id: string }) {
}
router.push((pathname ?? '') + '?' + newParams.toString())
}
const tab = searchParams.get('tab')

const pageTitle = buildPageTitle({
handle: profile?.handle || repo?.handle || id,
tab,
})
useTitle(pageTitle)

return (
<>
Expand Down
10 changes: 10 additions & 0 deletions app/repositories/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ 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'
import { useTitle } from 'react-use'

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

let pageTitle = `Repositories`
if (term) {
pageTitle += ` - ${term}`
}

useTitle(pageTitle)

const repos = data?.pages.flatMap((page) => page.repos) ?? []
return (
<>
Expand Down
10 changes: 10 additions & 0 deletions app/subject-status/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ 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'
import { useTitle } from 'react-use'

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

let pageTitle = `Subject Status`

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

useTitle(pageTitle)

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

// The game package uses some client only code so we can't really import and use it here because that breaks SSR for some reason
Expand Down Expand Up @@ -38,6 +38,8 @@ 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() {
useTitle(`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

0 comments on commit f05587e

Please sign in to comment.