diff --git a/packages/console/src/App.tsx b/packages/console/src/App.tsx index 3c9e5dc7e..6d696d180 100644 --- a/packages/console/src/App.tsx +++ b/packages/console/src/App.tsx @@ -53,13 +53,11 @@ const Main = () => { } /> } /> - - } /> - } /> - + } /> } /> + } /> } /> @@ -69,6 +67,7 @@ const Main = () => { } /> + } /> } /> } /> } /> diff --git a/packages/console/src/pages/ApiResources/index.tsx b/packages/console/src/pages/ApiResources/index.tsx index 4a8ae3e34..5f95b1d20 100644 --- a/packages/console/src/pages/ApiResources/index.tsx +++ b/packages/console/src/pages/ApiResources/index.tsx @@ -1,11 +1,10 @@ import type { Resource } from '@logto/schemas'; import { AppearanceMode } from '@logto/schemas'; import classNames from 'classnames'; -import { useState } from 'react'; import { toast } from 'react-hot-toast'; import { useTranslation } from 'react-i18next'; import Modal from 'react-modal'; -import { useNavigate, useSearchParams } from 'react-router-dom'; +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import useSWR from 'swr'; import ApiResourceDark from '@/assets/images/api-resource-dark.svg'; @@ -28,14 +27,18 @@ import * as tableStyles from '@/scss/table.module.scss'; import CreateForm from './components/CreateForm'; import * as styles from './index.module.scss'; -const buildDetailsLink = (id: string) => `/api-resources/${id}`; +const apiResourcesPathname = '/api-resources'; +const createApiResourcePathname = `${apiResourcesPathname}/create`; +const buildDetailsPathname = (id: string) => `${apiResourcesPathname}/${id}`; const pageSize = 20; const ApiResources = () => { - const [isCreateFormOpen, setIsCreateFormOpen] = useState(false); + const { pathname } = useLocation(); + const isCreateNew = pathname.endsWith('/create'); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const [query, setQuery] = useSearchParams(); + const search = query.toString(); const pageIndex = Number(query.get('page') ?? '1'); const { data, error, mutate } = useSWR<[Resource[], number], RequestError>( `/api/resources?page=${pageIndex}&page_size=${pageSize}` @@ -55,28 +58,38 @@ const ApiResources = () => { size="large" icon={} onClick={() => { - setIsCreateFormOpen(true); + navigate({ + pathname: createApiResourcePathname, + search, + }); }} /> { - setIsCreateFormOpen(false); + navigate({ + pathname: apiResourcesPathname, + search, + }); }} > { - setIsCreateFormOpen(false); - if (createdApiResource) { toast.success( t('api_resources.api_resource_created', { name: createdApiResource.name }) ); - navigate(buildDetailsLink(createdApiResource.id)); + navigate(buildDetailsPathname(createdApiResource.id), { replace: true }); + + return; } + navigate({ + pathname: apiResourcesPathname, + search, + }); }} /> @@ -109,7 +122,10 @@ const ApiResources = () => { title="api_resources.create" type="outline" onClick={() => { - setIsCreateFormOpen(true); + navigate({ + pathname: createApiResourcePathname, + search, + }); }} /> @@ -123,14 +139,14 @@ const ApiResources = () => { key={id} className={tableStyles.clickable} onClick={() => { - navigate(buildDetailsLink(id)); + navigate(buildDetailsPathname(id)); }} > } - to={buildDetailsLink(id)} + to={buildDetailsPathname(id)} /> diff --git a/packages/console/src/pages/ApplicationDetails/index.tsx b/packages/console/src/pages/ApplicationDetails/index.tsx index b6264809e..5c66d65cc 100644 --- a/packages/console/src/pages/ApplicationDetails/index.tsx +++ b/packages/console/src/pages/ApplicationDetails/index.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { toast } from 'react-hot-toast'; import { Trans, useTranslation } from 'react-i18next'; -import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import useSWR from 'swr'; import Back from '@/assets/images/back.svg'; @@ -41,7 +41,6 @@ const mapToUriOriginFormatArrays = (value?: string[]) => const ApplicationDetails = () => { const { id } = useParams(); - const { pathname } = useLocation(); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const { data, error, mutate } = useSWR( id && `/api/applications/${id}` @@ -197,9 +196,7 @@ const ApplicationDetails = () => { - - {t('general.settings_nav')} - + {t('general.settings_nav')} `${applicationsPathname}/${id}`; + const Applications = () => { const navigate = useNavigate(); - const location = useLocation(); - const isCreateNew = location.pathname.endsWith('/create'); + const { pathname } = useLocation(); + const isCreateNew = pathname === createApplicationPathname; const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const [query, setQuery] = useSearchParams(); + const search = query.toString(); const pageIndex = Number(query.get('page') ?? '1'); const { data, error, mutate } = useSWR<[Application[], number], RequestError>( `/api/applications?page=${pageIndex}&page_size=${pageSize}` @@ -50,7 +55,10 @@ const Applications = () => { type="primary" size="large" onClick={() => { - navigate('/applications/create'); + navigate({ + pathname: createApplicationPathname, + search, + }); }} /> { className={modalStyles.content} overlayClassName={modalStyles.overlay} onRequestClose={() => { - navigate('/applications'); + navigate({ + pathname: applicationsPathname, + search, + }); }} > { if (createdApp) { toast.success(t('applications.application_created', { name: createdApp.name })); - navigate(`/applications/${createdApp.id}`); + navigate(buildDetailsPathname(createdApp.id), { replace: true }); return; } - navigate('/applications'); + navigate({ + pathname: applicationsPathname, + search, + }); }} /> @@ -105,7 +119,10 @@ const Applications = () => { title="applications.create" type="outline" onClick={() => { - navigate('/applications/create'); + navigate({ + pathname: createApplicationPathname, + search, + }); }} /> @@ -115,7 +132,7 @@ const Applications = () => { key={id} className={tableStyles.clickable} onClick={() => { - navigate(`/applications/${id}`); + navigate(buildDetailsPathname(id)); }} > @@ -123,7 +140,7 @@ const Applications = () => { title={name} subtitle={t(`${applicationTypeI18nKey[type]}.title`)} icon={} - to={`/applications/${id}`} + to={buildDetailsPathname(id)} /> diff --git a/packages/console/src/pages/Users/index.tsx b/packages/console/src/pages/Users/index.tsx index e4122b384..36fdcd177 100644 --- a/packages/console/src/pages/Users/index.tsx +++ b/packages/console/src/pages/Users/index.tsx @@ -1,10 +1,9 @@ import type { User } from '@logto/schemas'; import { conditional, conditionalString } from '@silverhand/essentials'; import classNames from 'classnames'; -import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import Modal from 'react-modal'; -import { useNavigate, useSearchParams } from 'react-router-dom'; +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import useSWR from 'swr'; import Plus from '@/assets/images/plus.svg'; @@ -32,10 +31,16 @@ const pageSize = 20; const userTableColumn = 3; +const usersPathname = '/users'; +const createUserPathname = `${usersPathname}/create`; +const buildDetailsPathname = (id: string) => `${usersPathname}/id`; + const Users = () => { - const [isCreateFormOpen, setIsCreateFormOpen] = useState(false); + const { pathname } = useLocation(); + const isCreateNew = pathname === createUserPathname; const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const [query, setQuery] = useSearchParams(); + const search = query.toString(); const pageIndex = Number(query.get('page') ?? '1'); const keyword = query.get('search') ?? ''; const { data, error, mutate } = useSWR<[User[], number], RequestError>( @@ -57,26 +62,37 @@ const Users = () => { type="primary" icon={} onClick={() => { - setIsCreateFormOpen(true); + navigate({ + pathname: createUserPathname, + search, + }); }} /> { - setIsCreateFormOpen(false); + navigate({ + pathname: usersPathname, + search, + }); }} > { - setIsCreateFormOpen(false); - if (createdUser && password) { sessionStorage.setItem(generatedPasswordStorageKey, password); - navigate(`/users/${createdUser.id}`); + navigate(buildDetailsPathname(createdUser.id), { replace: true }); + + return; } + + navigate({ + pathname: usersPathname, + search, + }); }} /> @@ -124,7 +140,10 @@ const Users = () => { title="users.create" type="outline" onClick={() => { - setIsCreateFormOpen(true); + navigate({ + pathname: createUserPathname, + search, + }); }} /> @@ -134,7 +153,7 @@ const Users = () => { key={id} className={tableStyles.clickable} onClick={() => { - navigate(`/users/${id}`); + navigate(buildDetailsPathname(id)); }} > @@ -142,7 +161,7 @@ const Users = () => { title={name ?? t('users.unnamed')} subtitle={id} icon={} - to={`/users/${id}`} + to={buildDetailsPathname(id)} size="compact" />