0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(console): reorg organization details routes (#5702)

This commit is contained in:
Gao Sun 2024-04-15 11:12:35 +08:00 committed by GitHub
parent 336aa6f49a
commit 077cd85a06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 52 additions and 43 deletions

View file

@ -1,8 +1,11 @@
import { condArray } from '@silverhand/essentials';
import { type RouteObject } from 'react-router-dom';
import { Navigate, type RouteObject } from 'react-router-dom';
import { isDevFeaturesEnabled } from '@/consts/env';
import OrganizationDetails from '@/pages/OrganizationDetails';
import Members from '@/pages/OrganizationDetails/Members';
import Settings from '@/pages/OrganizationDetails/Settings';
import { OrganizationDetailsTabs } from '@/pages/OrganizationDetails/types';
import Organizations from '@/pages/Organizations';
export const organizations: RouteObject = {
@ -14,6 +17,14 @@ export const organizations: RouteObject = {
path: 'template',
element: <Organizations tab="template" />,
},
{ path: ':id/*', element: <OrganizationDetails /> }
{
path: ':id/*',
element: <OrganizationDetails />,
children: [
{ index: true, element: <Navigate replace to={OrganizationDetailsTabs.Settings} /> },
{ path: OrganizationDetailsTabs.Settings, element: <Settings /> },
{ path: OrganizationDetailsTabs.Members, element: <Members /> },
],
}
),
};

View file

@ -1,6 +1,7 @@
import { type UserWithOrganizationRoles, type Organization } from '@logto/schemas';
import { type UserWithOrganizationRoles } from '@logto/schemas';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useOutletContext } from 'react-router-dom';
import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg';
@ -19,17 +20,16 @@ import useActionTranslation from '@/hooks/use-action-translation';
import useApi, { type RequestError } from '@/hooks/use-api';
import { buildUrl } from '@/utils/url';
import { type OrganizationDetailsOutletContext } from '../types';
import AddMembersToOrganization from './AddMembersToOrganization';
import EditOrganizationRolesModal from './EditOrganizationRolesModal';
import * as styles from './index.module.scss';
const pageSize = defaultPageSize;
type Props = {
organization: Organization;
};
function Members({ organization }: Props) {
function Members() {
const { data: organization } = useOutletContext<OrganizationDetailsOutletContext>();
const api = useApi();
const [keyword, setKeyword] = useState('');
const [page, setPage] = useState(1);

View file

@ -2,6 +2,7 @@ import { type Organization } from '@logto/schemas';
import { useForm } from 'react-hook-form';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
import { useOutletContext } from 'react-router-dom';
import DetailsForm from '@/components/DetailsForm';
import FormCard from '@/components/FormCard';
@ -11,17 +12,10 @@ import TextInput from '@/ds-components/TextInput';
import useApi from '@/hooks/use-api';
import { trySubmitSafe } from '@/utils/form';
type Props = {
/**
* Whether the organization is being deleted, this is used to disable the unsaved
* changes alert modal.
*/
isDeleting: boolean;
data: Organization;
onUpdated: (data: Organization) => void;
};
import { type OrganizationDetailsOutletContext } from '../types';
function Settings({ isDeleting, data, onUpdated }: Props) {
function Settings() {
const { isDeleting, data, onUpdated } = useOutletContext<OrganizationDetailsOutletContext>();
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const {
register,

View file

@ -1,9 +1,7 @@
import { type Organization } from '@logto/schemas';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
// FIXME: @gao
// eslint-disable-next-line no-restricted-imports
import { Navigate, Route, Routes, useParams } from 'react-router-dom';
import { Outlet, useParams } from 'react-router-dom';
import useSWR from 'swr';
import Delete from '@/assets/icons/delete.svg';
@ -23,15 +21,10 @@ import useTenantPathname from '@/hooks/use-tenant-pathname';
import Introduction from '../Organizations/Guide/Introduction';
import Members from './Members';
import Settings from './Settings';
import * as styles from './index.module.scss';
import { OrganizationDetailsTabs, type OrganizationDetailsOutletContext } from './types';
const pathname = '/organizations';
const tabs = Object.freeze({
settings: 'settings',
members: 'members',
});
function OrganizationDetails() {
const { id } = useParams();
@ -111,27 +104,22 @@ function OrganizationDetails() {
{t('organization_details.delete_confirmation')}
</DeleteConfirmModal>
<TabNav>
<TabNavItem href={`${pathname}/${data.id}/${tabs.settings}`}>
<TabNavItem href={`${pathname}/${data.id}/${OrganizationDetailsTabs.Settings}`}>
{t('general.settings_nav')}
</TabNavItem>
<TabNavItem href={`${pathname}/${data.id}/${tabs.members}`}>
<TabNavItem href={`${pathname}/${data.id}/${OrganizationDetailsTabs.Members}`}>
{t('organizations.members')}
</TabNavItem>
</TabNav>
<Routes>
<Route index element={<Navigate replace to={tabs.settings} />} />
<Route
path={tabs.settings}
element={
<Settings
isDeleting={isDeleting}
data={data}
onUpdated={async (data) => mutate(data)}
/>
}
/>
<Route path={tabs.members} element={<Members organization={data} />} />
</Routes>
<Outlet
context={
{
data,
isDeleting,
onUpdated: async (data) => mutate(data),
} satisfies OrganizationDetailsOutletContext
}
/>
</>
)}
</DetailsPage>

View file

@ -0,0 +1,16 @@
import { type Organization } from '@logto/schemas';
export type OrganizationDetailsOutletContext = {
data: Organization;
/**
* Whether the organization is being deleted, this is used to disable the unsaved
* changes alert modal.
*/
isDeleting: boolean;
onUpdated: (data: Organization) => void;
};
export enum OrganizationDetailsTabs {
Settings = 'settings',
Members = 'members',
}