mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console): remove use tenant hook and use cloud SWR instead (#4060)
This commit is contained in:
parent
42d844f258
commit
da6f9eef5c
4 changed files with 44 additions and 86 deletions
|
@ -1,16 +1,17 @@
|
||||||
import { Theme } from '@logto/schemas';
|
import { Theme } from '@logto/schemas';
|
||||||
import type { TenantInfo } from '@logto/schemas/models';
|
import type { TenantInfo } from '@logto/schemas/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Plus from '@/assets/icons/plus.svg';
|
import Plus from '@/assets/icons/plus.svg';
|
||||||
import TenantLandingPageImageDark from '@/assets/images/tenant-landing-page-dark.svg';
|
import TenantLandingPageImageDark from '@/assets/images/tenant-landing-page-dark.svg';
|
||||||
import TenantLandingPageImage from '@/assets/images/tenant-landing-page.svg';
|
import TenantLandingPageImage from '@/assets/images/tenant-landing-page.svg';
|
||||||
|
import { useCloudSwr } from '@/cloud/hooks/use-cloud-swr';
|
||||||
|
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||||
import Button from '@/ds-components/Button';
|
import Button from '@/ds-components/Button';
|
||||||
import DynamicT from '@/ds-components/DynamicT';
|
import DynamicT from '@/ds-components/DynamicT';
|
||||||
import useTenants from '@/hooks/use-tenants';
|
|
||||||
import useTheme from '@/hooks/use-theme';
|
import useTheme from '@/hooks/use-theme';
|
||||||
|
|
||||||
import CreateTenantModal from './CreateTenantModal';
|
import CreateTenantModal from './CreateTenantModal';
|
||||||
|
@ -22,7 +23,15 @@ type Props = {
|
||||||
|
|
||||||
function TenantLandingPageContent({ className }: Props) {
|
function TenantLandingPageContent({ className }: Props) {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
const { tenants, mutate } = useTenants();
|
const { tenants, setTenants } = useContext(TenantsContext);
|
||||||
|
const { data: availableTenants, mutate } = useCloudSwr('/api/tenants');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (availableTenants) {
|
||||||
|
setTenants(availableTenants);
|
||||||
|
}
|
||||||
|
}, [availableTenants, setTenants]);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
import { type TenantInfo } from '@logto/schemas/models';
|
import { type TenantInfo } from '@logto/schemas/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useRef, useState } from 'react';
|
import { useContext, useRef, useState, useEffect, useMemo } from 'react';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import KeyboardArrowDown from '@/assets/icons/keyboard-arrow-down.svg';
|
import KeyboardArrowDown from '@/assets/icons/keyboard-arrow-down.svg';
|
||||||
import PlusSign from '@/assets/icons/plus.svg';
|
import PlusSign from '@/assets/icons/plus.svg';
|
||||||
import Tick from '@/assets/icons/tick.svg';
|
import Tick from '@/assets/icons/tick.svg';
|
||||||
|
import { useCloudSwr } from '@/cloud/hooks/use-cloud-swr';
|
||||||
import CreateTenantModal from '@/cloud/pages/Main/TenantLandingPage/TenantLandingPageContent/CreateTenantModal';
|
import CreateTenantModal from '@/cloud/pages/Main/TenantLandingPage/TenantLandingPageContent/CreateTenantModal';
|
||||||
import AppError from '@/components/AppError';
|
import AppError from '@/components/AppError';
|
||||||
|
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||||
import Divider from '@/ds-components/Divider';
|
import Divider from '@/ds-components/Divider';
|
||||||
import Dropdown, { DropdownItem } from '@/ds-components/Dropdown';
|
import Dropdown, { DropdownItem } from '@/ds-components/Dropdown';
|
||||||
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
|
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
|
||||||
import useTenants from '@/hooks/use-tenants';
|
|
||||||
import { onKeyDownHandler } from '@/utils/a11y';
|
import { onKeyDownHandler } from '@/utils/a11y';
|
||||||
|
|
||||||
import TenantEnvTag from './TenantEnvTag';
|
import TenantEnvTag from './TenantEnvTag';
|
||||||
|
@ -20,13 +21,18 @@ import * as styles from './index.module.scss';
|
||||||
|
|
||||||
function TenantSelector() {
|
function TenantSelector() {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
const {
|
const { tenants, setTenants, currentTenantId } = useContext(TenantsContext);
|
||||||
tenants,
|
const { data: availableTenants, mutate, error } = useCloudSwr('/api/tenants');
|
||||||
currentTenant: currentTenantInfo,
|
|
||||||
currentTenantId,
|
useEffect(() => {
|
||||||
error,
|
if (availableTenants) {
|
||||||
mutate,
|
setTenants(availableTenants);
|
||||||
} = useTenants();
|
}
|
||||||
|
}, [availableTenants, setTenants]);
|
||||||
|
|
||||||
|
const currentTenantInfo = useMemo(() => {
|
||||||
|
return tenants?.find((tenant) => tenant.id === currentTenantId);
|
||||||
|
}, [currentTenantId, tenants]);
|
||||||
|
|
||||||
const anchorRef = useRef<HTMLDivElement>(null);
|
const anchorRef = useRef<HTMLDivElement>(null);
|
||||||
const [showDropdown, setShowDropdown] = useState(false);
|
const [showDropdown, setShowDropdown] = useState(false);
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
import { useLogto } from '@logto/react';
|
|
||||||
import { type TenantInfo } from '@logto/schemas/models';
|
|
||||||
import { type Optional, trySafe } from '@silverhand/essentials';
|
|
||||||
import { useCallback, useContext, useEffect, useMemo } from 'react';
|
|
||||||
import { type KeyedMutator } from 'swr';
|
|
||||||
|
|
||||||
import { useCloudSwr } from '@/cloud/hooks/use-cloud-swr';
|
|
||||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
|
||||||
|
|
||||||
type TenantsHook = {
|
|
||||||
currentTenant?: TenantInfo;
|
|
||||||
currentTenantId: string;
|
|
||||||
error?: Error;
|
|
||||||
isLoaded: boolean;
|
|
||||||
isLoading: boolean;
|
|
||||||
isSettle: boolean;
|
|
||||||
mutate: KeyedMutator<TenantInfo[]>;
|
|
||||||
setCurrentTenantId: (id: string) => void;
|
|
||||||
tenants?: TenantInfo[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const useTenants = (): TenantsHook => {
|
|
||||||
const { signIn, getAccessToken } = useLogto();
|
|
||||||
const { currentTenantId, setCurrentTenantId, isSettle, setIsSettle } = useContext(TenantsContext);
|
|
||||||
const { data: availableTenants, error, mutate } = useCloudSwr('/api/tenants');
|
|
||||||
const isLoading = !availableTenants && !error;
|
|
||||||
const isLoaded = Boolean(availableTenants && !error);
|
|
||||||
|
|
||||||
const validate = useCallback(
|
|
||||||
async (tenant: TenantInfo) => {
|
|
||||||
const { id, indicator } = tenant;
|
|
||||||
if (await trySafe(getAccessToken(indicator))) {
|
|
||||||
setIsSettle(true);
|
|
||||||
} else {
|
|
||||||
void signIn(new URL(`/${id}/callback`, window.location.origin).toString());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[getAccessToken, setIsSettle, signIn]
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentTenant: Optional<TenantInfo> = useMemo(() => {
|
|
||||||
return availableTenants?.find(({ id }) => id === currentTenantId);
|
|
||||||
}, [currentTenantId, availableTenants]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentTenant) {
|
|
||||||
void validate(currentTenant);
|
|
||||||
}
|
|
||||||
}, [currentTenant, validate]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
currentTenant,
|
|
||||||
currentTenantId,
|
|
||||||
error,
|
|
||||||
isLoaded,
|
|
||||||
isLoading,
|
|
||||||
isSettle,
|
|
||||||
mutate,
|
|
||||||
setCurrentTenantId, // Will be used to switch to another tenant.
|
|
||||||
tenants: availableTenants,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useTenants;
|
|
|
@ -1,17 +1,18 @@
|
||||||
import { type TenantInfo, TenantTag } from '@logto/schemas/models';
|
import { type TenantInfo, TenantTag } from '@logto/schemas/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState, useContext, useMemo } from 'react';
|
||||||
import { FormProvider, useForm } from 'react-hook-form';
|
import { FormProvider, useForm } from 'react-hook-form';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||||
|
import { useCloudSwr } from '@/cloud/hooks/use-cloud-swr';
|
||||||
import AppError from '@/components/AppError';
|
import AppError from '@/components/AppError';
|
||||||
import AppLoading from '@/components/AppLoading';
|
import AppLoading from '@/components/AppLoading';
|
||||||
import PageMeta from '@/components/PageMeta';
|
import PageMeta from '@/components/PageMeta';
|
||||||
import SubmitFormChangesActionBar from '@/components/SubmitFormChangesActionBar';
|
import SubmitFormChangesActionBar from '@/components/SubmitFormChangesActionBar';
|
||||||
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
||||||
import useTenants from '@/hooks/use-tenants';
|
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||||
|
|
||||||
import DeleteCard from './DeleteCard';
|
import DeleteCard from './DeleteCard';
|
||||||
import DeleteModal from './DeleteModal';
|
import DeleteModal from './DeleteModal';
|
||||||
|
@ -28,14 +29,20 @@ const tenantProfileToForm = (tenant?: TenantInfo): TenantSettingsForm => {
|
||||||
function TenantBasicSettings() {
|
function TenantBasicSettings() {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
const api = useCloudApi();
|
const api = useCloudApi();
|
||||||
const {
|
const { tenants, setTenants, currentTenantId } = useContext(TenantsContext);
|
||||||
currentTenant,
|
const { data: availableTenants, mutate, error: requestError } = useCloudSwr('/api/tenants');
|
||||||
currentTenantId,
|
const isLoading = !availableTenants && !requestError;
|
||||||
error: requestError,
|
|
||||||
mutate,
|
useEffect(() => {
|
||||||
isLoading,
|
if (availableTenants) {
|
||||||
tenants,
|
setTenants(availableTenants);
|
||||||
} = useTenants();
|
}
|
||||||
|
}, [availableTenants, setTenants]);
|
||||||
|
|
||||||
|
const currentTenant = useMemo(() => {
|
||||||
|
return tenants?.find((tenant) => tenant.id === currentTenantId);
|
||||||
|
}, [currentTenantId, tenants]);
|
||||||
|
|
||||||
const [error, setError] = useState<Error>();
|
const [error, setError] = useState<Error>();
|
||||||
const [isDeletionModalOpen, setIsDeletionModalOpen] = useState(false);
|
const [isDeletionModalOpen, setIsDeletionModalOpen] = useState(false);
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
|
|
Loading…
Reference in a new issue