mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
refactor(console): refactor subscription-related hooks (#4197)
This commit is contained in:
parent
0d2f8edcb9
commit
a54fd502bd
14 changed files with 82 additions and 58 deletions
|
@ -3,15 +3,16 @@ import {
|
|||
type ConnectorResponse,
|
||||
type ConnectorFactoryResponse,
|
||||
} from '@logto/schemas';
|
||||
import { useMemo } from 'react';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
||||
import PlanName from '@/components/PlanName';
|
||||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import { ReservedPlanId } from '@/consts/subscriptions';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import { type ConnectorGroup } from '@/types/connector';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
|
@ -30,8 +31,9 @@ function Footer({
|
|||
isCreateButtonDisabled,
|
||||
onClickCreateButton,
|
||||
}: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.upsell.paywall' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
|
||||
const standardConnectorCount = useMemo(
|
||||
() =>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import { useContext } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import { type SubscriptionUsage } from '@/cloud/types/router';
|
||||
import { isCloud } from '@/consts/env';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
|
||||
const useCurrentSubscriptionUsage = () => {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const cloudApi = useCloudApi();
|
||||
|
||||
return useSWR<SubscriptionUsage, Error>(
|
||||
isCloud && `/api/tenants/${currentTenantId}/usage`,
|
||||
async () =>
|
||||
cloudApi.get('/api/tenants/:tenantId/usage', {
|
||||
params: { tenantId: currentTenantId },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default useCurrentSubscriptionUsage;
|
|
@ -1,10 +1,10 @@
|
|||
import { useMemo } from 'react';
|
||||
|
||||
import useCurrentSubscription from './use-current-subscription';
|
||||
import useSubscription from './use-subscription';
|
||||
import useSubscriptionPlans from './use-subscription-plans';
|
||||
|
||||
const useCurrentSubscriptionPlan = () => {
|
||||
const { data: subscription, error: fetchSubscriptionError } = useCurrentSubscription();
|
||||
const useSubscriptionPlan = (tenantId: string) => {
|
||||
const { data: subscription, error: fetchSubscriptionError } = useSubscription(tenantId);
|
||||
const { data: subscriptionPlans, error: fetchSubscriptionPlansError } = useSubscriptionPlans();
|
||||
|
||||
const currentPlan = useMemo(
|
||||
|
@ -18,4 +18,4 @@ const useCurrentSubscriptionPlan = () => {
|
|||
};
|
||||
};
|
||||
|
||||
export default useCurrentSubscriptionPlan;
|
||||
export default useSubscriptionPlan;
|
22
packages/console/src/hooks/use-subscription-usage.ts
Normal file
22
packages/console/src/hooks/use-subscription-usage.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import useSWR from 'swr';
|
||||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import { type SubscriptionUsage } from '@/cloud/types/router';
|
||||
import { isCloud, isProduction } from '@/consts/env';
|
||||
|
||||
const useSubscriptionUsage = (tenantId: string) => {
|
||||
const cloudApi = useCloudApi();
|
||||
|
||||
return useSWR<SubscriptionUsage, Error>(
|
||||
/**
|
||||
* Todo: @xiaoyijun remove this condition on subscription features ready.
|
||||
*/
|
||||
!isProduction && isCloud && `/api/tenants/${tenantId}/usage`,
|
||||
async () =>
|
||||
cloudApi.get('/api/tenants/:tenantId/usage', {
|
||||
params: { tenantId },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default useSubscriptionUsage;
|
|
@ -1,24 +1,21 @@
|
|||
import { useContext } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import { type Subscription } from '@/cloud/types/router';
|
||||
import { isCloud, isProduction } from '@/consts/env';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
|
||||
const useCurrentSubscription = () => {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const useSubscription = (tenantId: string) => {
|
||||
const cloudApi = useCloudApi();
|
||||
return useSWR<Subscription, Error>(
|
||||
/**
|
||||
* Todo: @xiaoyijun remove this condition on subscription features ready.
|
||||
*/
|
||||
!isProduction && isCloud && `/api/tenants/${currentTenantId}/subscription`,
|
||||
!isProduction && isCloud && `/api/tenants/${tenantId}/subscription`,
|
||||
async () =>
|
||||
cloudApi.get('/api/tenants/:tenantId/subscription', {
|
||||
params: { tenantId: currentTenantId },
|
||||
params: { tenantId },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default useCurrentSubscription;
|
||||
export default useSubscription;
|
|
@ -1,5 +1,6 @@
|
|||
import { noSpaceRegEx } from '@logto/core-kit';
|
||||
import type { Scope } from '@logto/schemas';
|
||||
import { useContext } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import ReactModal from 'react-modal';
|
||||
|
@ -7,12 +8,13 @@ import ReactModal from 'react-modal';
|
|||
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
||||
import PlanName from '@/components/PlanName';
|
||||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
@ -26,8 +28,9 @@ type Props = {
|
|||
type CreatePermissionFormData = Pick<Scope, 'name' | 'description'>;
|
||||
|
||||
function CreatePermissionModal({ resourceId, totalResourceCount, onClose }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
const {
|
||||
handleSubmit,
|
||||
register,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { isManagementApi, type Resource } from '@logto/schemas';
|
||||
import { useContext } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import useSWR from 'swr';
|
||||
|
@ -8,13 +9,14 @@ import PlanName from '@/components/PlanName';
|
|||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import { type ApiResource } from '@/consts';
|
||||
import { isProduction } from '@/consts/env';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
|
@ -28,8 +30,9 @@ type Props = {
|
|||
};
|
||||
|
||||
function CreateForm({ onClose }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
/**
|
||||
* Todo: @xiaoyijun remove this condition on subscription features ready.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type Application, ApplicationType } from '@logto/schemas';
|
||||
import { useMemo } from 'react';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import useSWR from 'swr';
|
||||
|
||||
|
@ -8,8 +8,9 @@ import PlanName from '@/components/PlanName';
|
|||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import { isProduction } from '@/consts/env';
|
||||
import { ReservedPlanId } from '@/consts/subscriptions';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
type Props = {
|
||||
|
@ -19,8 +20,9 @@ type Props = {
|
|||
};
|
||||
|
||||
function Footer({ selectedType, isLoading, onClickCreate }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.upsell.paywall' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
/**
|
||||
* Todo: @xiaoyijun remove this condition on subscription features ready.
|
||||
*/
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import { useContext } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import FreePlanNotificationImage from '@/assets/images/free-plan-notification-image.svg';
|
||||
import PlanName from '@/components/PlanName';
|
||||
import { isCloud, isProduction } from '@/consts/env';
|
||||
import { ReservedPlanId } from '@/consts/subscriptions';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import useCurrentSubscription from '@/hooks/use-current-subscription';
|
||||
import useSubscription from '@/hooks/use-subscription';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import { ReservedPlanName } from '@/types/subscriptions';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function FreePlanNotification() {
|
||||
const { data: currentSubscription, error } = useCurrentSubscription();
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { data: currentSubscription, error } = useSubscription(currentTenantId);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console.upsell.get_started' });
|
||||
const { navigate } = useTenantPathname();
|
||||
const isLoadingSubscription = !currentSubscription && !error;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { ScopeResponse } from '@logto/schemas';
|
||||
import { useState } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import ReactModal from 'react-modal';
|
||||
|
@ -8,11 +8,12 @@ import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
|||
import PlanName from '@/components/PlanName';
|
||||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import RoleScopesTransfer from '@/components/RoleScopesTransfer';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
|
@ -23,8 +24,9 @@ type Props = {
|
|||
};
|
||||
|
||||
function AssignPermissionsModal({ roleId, totalRoleScopeCount, onClose }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [scopes, setScopes] = useState<ScopeResponse[]>([]);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { Role, ScopeResponse } from '@logto/schemas';
|
||||
import { internalRolePrefix } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import { useContext } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -8,13 +9,14 @@ import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
|||
import PlanName from '@/components/PlanName';
|
||||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import RoleScopesTransfer from '@/components/RoleScopesTransfer';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useConfigs from '@/hooks/use-configs';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
|
@ -32,8 +34,9 @@ type CreateRolePayload = Pick<Role, 'name' | 'description'> & {
|
|||
};
|
||||
|
||||
function CreateRoleForm({ totalRoleCount, onClose }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { withAppInsights } from '@logto/app-insights/react';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import PageMeta from '@/components/PageMeta';
|
||||
import useCurrentSubscription from '@/hooks/use-current-subscription';
|
||||
import useCurrentSubscriptionUsage from '@/hooks/use-current-subscription-usage';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import useSubscription from '@/hooks/use-subscription';
|
||||
import useSubscriptionPlans from '@/hooks/use-subscription-plans';
|
||||
import useSubscriptionUsage from '@/hooks/use-subscription-usage';
|
||||
|
||||
import Skeleton from '../components/Skeleton';
|
||||
|
||||
|
@ -13,14 +15,15 @@ import SwitchPlanActionBar from './SwitchPlanActionBar';
|
|||
import * as styles from './index.module.scss';
|
||||
|
||||
function Subscription() {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { data: subscriptionPlans, error: fetchPlansError } = useSubscriptionPlans();
|
||||
const {
|
||||
data: currentSubscription,
|
||||
error: fetchSubscriptionError,
|
||||
mutate: mutateSubscription,
|
||||
} = useCurrentSubscription();
|
||||
} = useSubscription(currentTenantId);
|
||||
const { data: subscriptionUsage, error: fetchSubscriptionUsageError } =
|
||||
useCurrentSubscriptionUsage();
|
||||
useSubscriptionUsage(currentTenantId);
|
||||
|
||||
const isLoadingPlans = !subscriptionPlans && !fetchPlansError;
|
||||
const isLoadingSubscription = !currentSubscription && !fetchSubscriptionError;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { withAppInsights } from '@logto/app-insights/react';
|
||||
import { useContext } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import FormCard from '@/components/FormCard';
|
||||
|
@ -6,12 +7,13 @@ import PageMeta from '@/components/PageMeta';
|
|||
import ProTag from '@/components/ProTag';
|
||||
import { contactEmailLink } from '@/consts';
|
||||
import { isProduction } from '@/consts/env';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import InlineNotification from '@/ds-components/InlineNotification';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
|
||||
import Skeleton from '../components/Skeleton';
|
||||
|
@ -22,8 +24,9 @@ import DefaultDomain from './DefaultDomain';
|
|||
import * as styles from './index.module.scss';
|
||||
|
||||
function TenantDomainSettings() {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { data: customDomain, isLoading: isLoadingCustomDomain, mutate } = useCustomDomain(true);
|
||||
const { data: currentPlan, error: fetchCurrentPlanError } = useCurrentSubscriptionPlan();
|
||||
const { data: currentPlan, error: fetchCurrentPlanError } = useSubscriptionPlan(currentTenantId);
|
||||
const isLoadingCurrentPlan = !currentPlan && !fetchCurrentPlanError;
|
||||
const { getDocumentationUrl } = useDocumentationUrl();
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import { type Hook, type CreateHook, type HookEvent, type HookConfig } from '@logto/schemas';
|
||||
import { useContext } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
||||
import PlanName from '@/components/PlanName';
|
||||
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import ModalLayout from '@/ds-components/ModalLayout';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useCurrentSubscriptionPlan from '@/hooks/use-current-subscription-plan';
|
||||
import useSubscriptionPlan from '@/hooks/use-subscription-plan';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
import { hasReachedQuotaLimit } from '@/utils/quota';
|
||||
|
||||
|
@ -28,7 +30,8 @@ type CreateHookPayload = Pick<CreateHook, 'name'> & {
|
|||
};
|
||||
|
||||
function CreateForm({ totalWebhookCount, onClose }: Props) {
|
||||
const { data: currentPlan } = useCurrentSubscriptionPlan();
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { data: currentPlan } = useSubscriptionPlan(currentTenantId);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const shouldBlockCreation = hasReachedQuotaLimit({
|
||||
|
|
Loading…
Add table
Reference in a new issue