mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
refactor: stop using GET /:tenantId/usage API and GET /tenants usage field (#6434)
This commit is contained in:
parent
b42b37bb72
commit
c791847879
8 changed files with 23 additions and 98 deletions
|
@ -15,9 +15,6 @@ export type LogtoSkuResponse = GetArrayElementType<GuardedResponse<GetRoutes['/a
|
|||
|
||||
export type Subscription = GuardedResponse<GetRoutes['/api/tenants/:tenantId/subscription']>;
|
||||
|
||||
/** @deprecated */
|
||||
export type SubscriptionUsage = GuardedResponse<GetRoutes['/api/tenants/:tenantId/usage']>;
|
||||
|
||||
/* ===== Use `New` in the naming to avoid confusion with legacy types ===== */
|
||||
export type NewSubscriptionUsageResponse = GuardedResponse<
|
||||
GetRoutes['/api/tenants/:tenantId/subscription-usage']
|
||||
|
|
|
@ -4,10 +4,8 @@ import ReactModal from 'react-modal';
|
|||
|
||||
import PlanUsage from '@/components/PlanUsage';
|
||||
import { contactEmailLink } from '@/consts';
|
||||
import { isDevFeaturesEnabled } from '@/consts/env';
|
||||
import { subscriptionPage } from '@/consts/pages';
|
||||
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import InlineNotification from '@/ds-components/InlineNotification';
|
||||
|
@ -20,8 +18,6 @@ import PlanName from '../PlanName';
|
|||
import styles from './index.module.scss';
|
||||
|
||||
function MauExceededModal() {
|
||||
const { currentTenant } = useContext(TenantsContext);
|
||||
const { usage } = currentTenant ?? {};
|
||||
const {
|
||||
currentPlan,
|
||||
currentSubscription,
|
||||
|
@ -38,19 +34,15 @@ function MauExceededModal() {
|
|||
setHasClosed(true);
|
||||
};
|
||||
|
||||
if (!usage || hasClosed) {
|
||||
if (hasClosed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
quota: { mauLimit },
|
||||
name: planName,
|
||||
} = currentPlan;
|
||||
const { name: planName } = currentPlan;
|
||||
|
||||
const isMauExceeded = isDevFeaturesEnabled
|
||||
? currentSubscriptionQuota.mauLimit !== null &&
|
||||
currentSubscriptionUsage.mauLimit >= currentSubscriptionQuota.mauLimit
|
||||
: mauLimit !== null && usage.activeUsers >= mauLimit;
|
||||
const isMauExceeded =
|
||||
currentSubscriptionQuota.mauLimit !== null &&
|
||||
currentSubscriptionUsage.mauLimit >= currentSubscriptionQuota.mauLimit;
|
||||
|
||||
if (!isMauExceeded) {
|
||||
return null;
|
||||
|
@ -93,11 +85,7 @@ function MauExceededModal() {
|
|||
</Trans>
|
||||
</InlineNotification>
|
||||
<FormField title="subscription.plan_usage">
|
||||
<PlanUsage
|
||||
subscriptionUsage={usage}
|
||||
currentSubscription={currentSubscription}
|
||||
currentPlan={currentPlan}
|
||||
/>
|
||||
<PlanUsage currentSubscription={currentSubscription} currentPlan={currentPlan} />
|
||||
</FormField>
|
||||
</ModalLayout>
|
||||
</ReactModal>
|
||||
|
|
|
@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|||
import dayjs from 'dayjs';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { type SubscriptionUsage, type Subscription } from '@/cloud/types/router';
|
||||
import { type Subscription } from '@/cloud/types/router';
|
||||
import { isDevFeaturesEnabled } from '@/consts/env';
|
||||
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
|
@ -16,15 +16,13 @@ import styles from './index.module.scss';
|
|||
import { usageKeys, usageKeyMap, titleKeyMap, tooltipKeyMap } from './utils';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated */
|
||||
readonly subscriptionUsage: SubscriptionUsage;
|
||||
/** @deprecated */
|
||||
readonly currentSubscription: Subscription;
|
||||
/** @deprecated */
|
||||
readonly currentPlan: SubscriptionPlan;
|
||||
};
|
||||
|
||||
function PlanUsage({ subscriptionUsage, currentSubscription, currentPlan }: Props) {
|
||||
function PlanUsage({ currentSubscription, currentPlan }: Props) {
|
||||
const {
|
||||
currentSubscriptionQuota,
|
||||
currentSubscriptionUsage,
|
||||
|
@ -35,9 +33,10 @@ function PlanUsage({ subscriptionUsage, currentSubscription, currentPlan }: Prop
|
|||
? currentSubscriptionFromNewPricingModel
|
||||
: currentSubscription;
|
||||
|
||||
const [activeUsers, mauLimit] = isDevFeaturesEnabled
|
||||
? [currentSubscriptionUsage.mauLimit, currentSubscriptionQuota.mauLimit]
|
||||
: [subscriptionUsage.activeUsers, currentPlan.quota.mauLimit];
|
||||
const [activeUsers, mauLimit] = [
|
||||
currentSubscriptionUsage.mauLimit,
|
||||
isDevFeaturesEnabled ? currentSubscriptionQuota.mauLimit : currentPlan.quota.mauLimit,
|
||||
];
|
||||
|
||||
const usagePercent = conditional(mauLimit && activeUsers / mauLimit);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
defaultSubscriptionQuota,
|
||||
defaultSubscriptionUsage,
|
||||
} from '@/consts';
|
||||
import { isCloud, isDevFeaturesEnabled } from '@/consts/env';
|
||||
import { isCloud } from '@/consts/env';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import useLogtoSkus from '@/hooks/use-logto-skus';
|
||||
|
||||
|
@ -36,7 +36,7 @@ const useNewSubscriptionData: () => NewSubscriptionContext & { isLoading: boolea
|
|||
isLoading: isSubscriptionUsageDataLoading,
|
||||
mutate: mutateSubscriptionQuotaAndUsages,
|
||||
} = useSWR<NewSubscriptionUsageResponse, Error>(
|
||||
isCloud && isDevFeaturesEnabled && tenantId && `/api/tenants/${tenantId}/subscription-usage`,
|
||||
isCloud && tenantId && `/api/tenants/${tenantId}/subscription-usage`,
|
||||
async () =>
|
||||
cloudApi.get('/api/tenants/:tenantId/subscription-usage', {
|
||||
params: { tenantId },
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
import useSWR from 'swr';
|
||||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import { type SubscriptionUsage } from '@/cloud/types/router';
|
||||
import { isCloud } from '@/consts/env';
|
||||
|
||||
/** @deprecated */
|
||||
const useSubscriptionUsage = (tenantId: string) => {
|
||||
const cloudApi = useCloudApi();
|
||||
|
||||
return useSWR<SubscriptionUsage, Error>(isCloud && `/api/tenants/${tenantId}/usage`, async () =>
|
||||
cloudApi.get('/api/tenants/:tenantId/usage', {
|
||||
params: { tenantId },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export default useSubscriptionUsage;
|
|
@ -20,14 +20,12 @@ import {
|
|||
} from '@/utils/subscription';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated No need to pass in this argument in new pricing model */
|
||||
readonly activeUsers: number;
|
||||
/** @deprecated No need to pass in this argument in new pricing model */
|
||||
readonly currentPlan: SubscriptionPlan;
|
||||
readonly className?: string;
|
||||
};
|
||||
|
||||
function MauLimitExceededNotification({ activeUsers, currentPlan, className }: Props) {
|
||||
function MauLimitExceededNotification({ currentPlan, className }: Props) {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const { subscribe } = useSubscribe();
|
||||
const { show } = useConfirmModal();
|
||||
|
@ -52,7 +50,7 @@ function MauLimitExceededNotification({ activeUsers, currentPlan, className }: P
|
|||
|
||||
if (
|
||||
mauLimit === null || // Unlimited
|
||||
(isDevFeaturesEnabled ? currentSubscriptionUsage.mauLimit : activeUsers) < mauLimit ||
|
||||
currentSubscriptionUsage.mauLimit < mauLimit ||
|
||||
!proPlan ||
|
||||
!proSku
|
||||
) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { cond } from '@silverhand/essentials';
|
||||
import { useContext, useMemo } from 'react';
|
||||
|
||||
import { type SubscriptionUsage, type Subscription } from '@/cloud/types/router';
|
||||
import { type Subscription } from '@/cloud/types/router';
|
||||
import BillInfo from '@/components/BillInfo';
|
||||
import ChargeNotification from '@/components/ChargeNotification';
|
||||
import FormCard from '@/components/FormCard';
|
||||
|
@ -23,11 +23,9 @@ type Props = {
|
|||
readonly subscription: Subscription;
|
||||
/** @deprecated */
|
||||
readonly subscriptionPlan: SubscriptionPlan;
|
||||
/** @deprecated */
|
||||
readonly subscriptionUsage: SubscriptionUsage;
|
||||
};
|
||||
|
||||
function CurrentPlan({ subscription, subscriptionPlan, subscriptionUsage }: Props) {
|
||||
function CurrentPlan({ subscription, subscriptionPlan }: Props) {
|
||||
const { currentSku, currentSubscription, currentSubscriptionUsage, currentSubscriptionQuota } =
|
||||
useContext(SubscriptionDataContext);
|
||||
const {
|
||||
|
@ -52,7 +50,7 @@ function CurrentPlan({ subscription, subscriptionPlan, subscriptionUsage }: Prop
|
|||
})
|
||||
: hasSurpassedQuotaLimit({
|
||||
quotaKey: 'tokenLimit',
|
||||
usage: subscriptionUsage.tokenUsage,
|
||||
usage: currentSubscriptionUsage.tokenLimit,
|
||||
plan: subscriptionPlan,
|
||||
});
|
||||
|
||||
|
@ -67,25 +65,12 @@ function CurrentPlan({ subscription, subscriptionPlan, subscriptionUsage }: Prop
|
|||
</div>
|
||||
</div>
|
||||
<FormField title="subscription.plan_usage">
|
||||
<PlanUsage
|
||||
currentSubscription={subscription}
|
||||
currentPlan={subscriptionPlan}
|
||||
subscriptionUsage={subscriptionUsage}
|
||||
/>
|
||||
<PlanUsage currentSubscription={subscription} currentPlan={subscriptionPlan} />
|
||||
</FormField>
|
||||
<FormField title="subscription.next_bill">
|
||||
<BillInfo
|
||||
cost={isDevFeaturesEnabled ? upcomingCost : subscriptionUsage.cost}
|
||||
isManagePaymentVisible={Boolean(
|
||||
isDevFeaturesEnabled ? upcomingCost : subscriptionUsage.cost
|
||||
)}
|
||||
/>
|
||||
<BillInfo cost={upcomingCost} isManagePaymentVisible={Boolean(upcomingCost)} />
|
||||
</FormField>
|
||||
<MauLimitExceedNotification
|
||||
activeUsers={subscriptionUsage.activeUsers}
|
||||
currentPlan={subscriptionPlan}
|
||||
className={styles.notification}
|
||||
/>
|
||||
<MauLimitExceedNotification currentPlan={subscriptionPlan} className={styles.notification} />
|
||||
<ChargeNotification
|
||||
hasSurpassedLimit={hasTokenSurpassedLimit}
|
||||
quotaItemPhraseKey="tokens"
|
||||
|
|
|
@ -2,19 +2,14 @@ import { useContext } from 'react';
|
|||
|
||||
import PageMeta from '@/components/PageMeta';
|
||||
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import useSubscriptionUsage from '@/hooks/use-subscription-usage';
|
||||
import { pickupFeaturedLogtoSkus, pickupFeaturedPlans } from '@/utils/subscription';
|
||||
|
||||
import Skeleton from '../components/Skeleton';
|
||||
|
||||
import CurrentPlan from './CurrentPlan';
|
||||
import PlanComparisonTable from './PlanComparisonTable';
|
||||
import SwitchPlanActionBar from './SwitchPlanActionBar';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
function Subscription() {
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const {
|
||||
subscriptionPlans,
|
||||
currentPlan,
|
||||
|
@ -24,31 +19,13 @@ function Subscription() {
|
|||
onCurrentSubscriptionUpdated,
|
||||
} = useContext(SubscriptionDataContext);
|
||||
|
||||
const {
|
||||
data: subscriptionUsage,
|
||||
isLoading,
|
||||
mutate: mutateSubscriptionUsage,
|
||||
} = useSubscriptionUsage(currentTenantId);
|
||||
|
||||
const reservedPlans = pickupFeaturedPlans(subscriptionPlans);
|
||||
const reservedSkus = pickupFeaturedLogtoSkus(logtoSkus);
|
||||
|
||||
if (isLoading) {
|
||||
return <Skeleton />;
|
||||
}
|
||||
|
||||
if (!subscriptionUsage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<PageMeta titleKey={['tenants.tabs.subscription', 'tenants.title']} />
|
||||
<CurrentPlan
|
||||
subscription={currentSubscription}
|
||||
subscriptionPlan={currentPlan}
|
||||
subscriptionUsage={subscriptionUsage}
|
||||
/>
|
||||
<CurrentPlan subscription={currentSubscription} subscriptionPlan={currentPlan} />
|
||||
<PlanComparisonTable />
|
||||
<SwitchPlanActionBar
|
||||
currentSubscriptionPlanId={currentSubscription.planId}
|
||||
|
@ -62,7 +39,6 @@ function Subscription() {
|
|||
* need to manually trigger the usage update while the subscription plan is changed.
|
||||
*/
|
||||
onCurrentSubscriptionUpdated();
|
||||
await mutateSubscriptionUsage();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue