Rework Routes.tsx and SharePage.tsx routing
This commit is contained in:
parent
722e639bb1
commit
ba01927707
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { MemoryRouter } from 'react-router-dom'
|
import { MemoryRouter, Routes, Route } from 'react-router-dom'
|
||||||
import { MockedProvider } from '@apollo/client/testing'
|
import { MockedProvider } from '@apollo/client/testing'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -8,8 +8,9 @@ import {
|
||||||
waitForElementToBeRemoved,
|
waitForElementToBeRemoved,
|
||||||
} from '@testing-library/react'
|
} from '@testing-library/react'
|
||||||
|
|
||||||
import SharePage, {
|
import {
|
||||||
SHARE_TOKEN_QUERY,
|
SHARE_TOKEN_QUERY,
|
||||||
|
TokenRoute,
|
||||||
VALIDATE_TOKEN_PASSWORD_QUERY,
|
VALIDATE_TOKEN_PASSWORD_QUERY,
|
||||||
} from './SharePage'
|
} from './SharePage'
|
||||||
|
|
||||||
|
@ -21,13 +22,6 @@ jest.mock('../../hooks/useScrollPagination')
|
||||||
describe('load correct share page, based on graphql query', () => {
|
describe('load correct share page, based on graphql query', () => {
|
||||||
const token = 'TOKEN123'
|
const token = 'TOKEN123'
|
||||||
|
|
||||||
const matchMock = {
|
|
||||||
url: `/share`,
|
|
||||||
params: {},
|
|
||||||
path: `/share`,
|
|
||||||
isExact: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
const historyMock = [{ pathname: `/share/${token}` }]
|
const historyMock = [{ pathname: `/share/${token}` }]
|
||||||
|
|
||||||
const graphqlMocks = [
|
const graphqlMocks = [
|
||||||
|
@ -101,7 +95,9 @@ describe('load correct share page, based on graphql query', () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MemoryRouter initialEntries={historyMock}>
|
<MemoryRouter initialEntries={historyMock}>
|
||||||
<SharePage match={matchMock} />
|
<Routes>
|
||||||
|
<Route path="/share/:token" element={<TokenRoute />} />
|
||||||
|
</Routes>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
)
|
)
|
||||||
|
@ -176,13 +172,93 @@ describe('load correct share page, based on graphql query', () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MemoryRouter initialEntries={historyMock}>
|
<MemoryRouter initialEntries={historyMock}>
|
||||||
<SharePage match={matchMock} />
|
<Routes>
|
||||||
|
<Route path="/share/:token" element={<TokenRoute />} />
|
||||||
|
</Routes>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(screen.getByText('Loading...')).toBeInTheDocument()
|
expect(screen.getByText('Loading...')).toBeInTheDocument()
|
||||||
|
await waitForElementToBeRemoved(() => screen.getByText('Loading...'))
|
||||||
|
|
||||||
|
expect(screen.getByTestId('Layout')).toBeInTheDocument()
|
||||||
|
expect(screen.getByTestId('AlbumSharePage')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('load subalbum of a shared album', async () => {
|
||||||
|
const subalbumID = '456'
|
||||||
|
const subalbumHistoryMock = [{ pathname: `/share/${token}/${subalbumID}` }]
|
||||||
|
|
||||||
|
const subalbumPageMocks = [
|
||||||
|
{
|
||||||
|
request: {
|
||||||
|
query: SHARE_TOKEN_QUERY,
|
||||||
|
variables: {
|
||||||
|
token,
|
||||||
|
password: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
shareToken: {
|
||||||
|
token: token,
|
||||||
|
album: {
|
||||||
|
id: subalbumID,
|
||||||
|
},
|
||||||
|
media: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request: {
|
||||||
|
query: SHARE_ALBUM_QUERY,
|
||||||
|
variables: {
|
||||||
|
id: subalbumID,
|
||||||
|
token: token,
|
||||||
|
password: null,
|
||||||
|
limit: 200,
|
||||||
|
offset: 0,
|
||||||
|
mediaOrderBy: 'date_shot',
|
||||||
|
mediaOrderDirection: 'ASC',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
album: {
|
||||||
|
id: '1',
|
||||||
|
title: 'album_title',
|
||||||
|
subAlbums: [],
|
||||||
|
thumbnail: {
|
||||||
|
url: 'https://photoview.example.com/album_thumbnail.jpg',
|
||||||
|
},
|
||||||
|
media: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
render(
|
||||||
|
<MockedProvider
|
||||||
|
mocks={[...graphqlMocks, ...subalbumPageMocks]}
|
||||||
|
addTypename={false}
|
||||||
|
defaultOptions={{
|
||||||
|
// disable cache, required to make fragments work
|
||||||
|
watchQuery: { fetchPolicy: 'no-cache' },
|
||||||
|
query: { fetchPolicy: 'no-cache' },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MemoryRouter initialEntries={subalbumHistoryMock}>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/share/:token/*" element={<TokenRoute />} />
|
||||||
|
</Routes>
|
||||||
|
</MemoryRouter>
|
||||||
|
</MockedProvider>
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(screen.getByText('Loading...')).toBeInTheDocument()
|
||||||
await waitForElementToBeRemoved(() => screen.getByText('Loading...'))
|
await waitForElementToBeRemoved(() => screen.getByText('Loading...'))
|
||||||
|
|
||||||
expect(screen.getByTestId('Layout')).toBeInTheDocument()
|
expect(screen.getByTestId('Layout')).toBeInTheDocument()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useQuery, gql } from '@apollo/client'
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import { Route, useParams } from 'react-router-dom'
|
import { Route, Routes, useParams } from 'react-router-dom'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import {
|
import {
|
||||||
getSharePassword,
|
getSharePassword,
|
||||||
|
@ -111,10 +111,10 @@ const AuthorizedTokenRoute = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Routes>
|
||||||
<Route path=":subAlbum" element={<SharedSubAlbumPage />} />
|
<Route path=":subAlbum" element={<SharedSubAlbumPage />} />
|
||||||
<Route
|
<Route
|
||||||
path="/"
|
index
|
||||||
element={
|
element={
|
||||||
<AlbumSharePage
|
<AlbumSharePage
|
||||||
albumID={data.shareToken.album.id}
|
albumID={data.shareToken.album.id}
|
||||||
|
@ -123,7 +123,7 @@ const AuthorizedTokenRoute = () => {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* Light lazy-loadable wrapper for share page module
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react'
|
|
||||||
import type { TFunction } from 'react-i18next'
|
|
||||||
import { Route } from 'react-router-dom'
|
|
||||||
import { NotFoundPage } from '../../components/routes/Routes'
|
|
||||||
|
|
||||||
const TokenRoute = React.lazy(() =>
|
|
||||||
import('./SharePage').then(x => ({
|
|
||||||
default: x.TokenRoute,
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
|
|
||||||
const sharePageRoute = ({ t }: { t: TFunction }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Route path={':token'} element={<TokenRoute />} />
|
|
||||||
<Route index element={<NotFoundPage t={t} />} />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default sharePageRoute
|
|
|
@ -1,11 +1,10 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
Route,
|
|
||||||
Routes as RouterRoutes,
|
|
||||||
Navigate,
|
Navigate,
|
||||||
useNavigate,
|
useNavigate,
|
||||||
NavigateFunction,
|
NavigateFunction,
|
||||||
Outlet,
|
Outlet,
|
||||||
|
useRoutes,
|
||||||
} from 'react-router-dom'
|
} from 'react-router-dom'
|
||||||
|
|
||||||
import Layout from '../layout/Layout'
|
import Layout from '../layout/Layout'
|
||||||
|
@ -13,8 +12,6 @@ import { authToken, clearTokenCookie } from '../../helpers/authentication'
|
||||||
import { TFunction, useTranslation } from 'react-i18next'
|
import { TFunction, useTranslation } from 'react-i18next'
|
||||||
import Loader from '../../primitives/Loader'
|
import Loader from '../../primitives/Loader'
|
||||||
import AuthorizedRoute from './AuthorizedRoute'
|
import AuthorizedRoute from './AuthorizedRoute'
|
||||||
import sharePageRoute from '../../Pages/SharePage/sharePageRoute'
|
|
||||||
import peoplePageRoute from '../../Pages/PeoplePage/peoplePageRoute'
|
|
||||||
|
|
||||||
const AlbumsPage = React.lazy(
|
const AlbumsPage = React.lazy(
|
||||||
() => import('../../Pages/AllAlbumsPage/AlbumsPage')
|
() => import('../../Pages/AllAlbumsPage/AlbumsPage')
|
||||||
|
@ -30,14 +27,102 @@ const InitialSetupPage = React.lazy(
|
||||||
() => import('../../Pages/LoginPage/InitialSetupPage')
|
() => import('../../Pages/LoginPage/InitialSetupPage')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const SharePageTokenRoute = React.lazy(() =>
|
||||||
|
import('../../Pages/SharePage/SharePage').then(x => ({
|
||||||
|
default: x.TokenRoute,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
const SettingsPage = React.lazy(
|
const SettingsPage = React.lazy(
|
||||||
() => import('../../Pages/SettingsPage/SettingsPage')
|
() => import('../../Pages/SettingsPage/SettingsPage')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PeoplePage = React.lazy(() =>
|
||||||
|
import('../../Pages/PeoplePage/PeoplePage').then(x => ({
|
||||||
|
default: x.PeoplePage,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
const PersonPage = React.lazy(() =>
|
||||||
|
import('../../Pages/PeoplePage/PeoplePage').then(x => ({
|
||||||
|
default: x.PersonPage,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
const Routes = () => {
|
const Routes = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const authorized = (element: React.ReactNode) => (
|
||||||
|
<AuthorizedRoute>{element}</AuthorizedRoute>
|
||||||
|
)
|
||||||
|
|
||||||
|
const routes = useRoutes([
|
||||||
|
{
|
||||||
|
index: true,
|
||||||
|
element: <IndexPage />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
element: <LoginPage />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/logout',
|
||||||
|
element: <LogoutPage navigate={navigate} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/initialSetup',
|
||||||
|
element: <InitialSetupPage />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/share/:token/*',
|
||||||
|
element: <SharePageTokenRoute />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/albums',
|
||||||
|
element: authorized(<AlbumsPage />),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/album/:id',
|
||||||
|
element: authorized(<AlbumPage />),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/timeline',
|
||||||
|
element: authorized(<TimelinePage />),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/places',
|
||||||
|
element: authorized(<PlacesPage />),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/settings',
|
||||||
|
element: authorized(<SettingsPage />),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/people',
|
||||||
|
element: authorized(<Outlet />),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: ':person',
|
||||||
|
element: <PersonPage />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: true,
|
||||||
|
element: <PeoplePage />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// for backwards-compatibility
|
||||||
|
path: '/photos',
|
||||||
|
element: <Navigate to="/timeline" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
element: <NotFoundPage t={t} />,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Suspense
|
<React.Suspense
|
||||||
fallback={
|
fallback={
|
||||||
|
@ -46,66 +131,7 @@ const Routes = () => {
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<RouterRoutes>
|
{routes}
|
||||||
<Route path="/login" element={<LoginPage />} />
|
|
||||||
<Route path="/logout" element={<LogoutPage navigate={navigate} />} />
|
|
||||||
<Route path="/initialSetup" element={<InitialSetupPage />} />
|
|
||||||
<Route path="/share">{sharePageRoute({ t })}</Route>
|
|
||||||
<Route
|
|
||||||
path="/albums"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<AlbumsPage />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/album/:id"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<AlbumPage />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/timeline"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<TimelinePage />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/places"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<PlacesPage />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/people"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<Outlet />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{peoplePageRoute()}
|
|
||||||
</Route>
|
|
||||||
<Route
|
|
||||||
path="/settings"
|
|
||||||
element={
|
|
||||||
<AuthorizedRoute>
|
|
||||||
<SettingsPage />
|
|
||||||
</AuthorizedRoute>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route index element={<IndexPage />} />
|
|
||||||
{/* For backwards compatibility */}
|
|
||||||
<Route path="/photos" element={<Navigate to="/timeline" />} />
|
|
||||||
<Route element={<NotFoundPage t={t} />} />
|
|
||||||
</RouterRoutes>
|
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue