Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(console): manual update subscription data when add/delete resources #6360

Merged
merged 2 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions packages/console/src/hooks/use-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
import { useTranslation } from 'react-i18next';

import { requestTimeout } from '@/consts';
import { isCloud } from '@/consts/env';
import { isCloud, isDevFeaturesEnabled } from '@/consts/env';
import { AppDataContext } from '@/contexts/AppDataProvider';
import { TenantsContext } from '@/contexts/TenantsProvider';
import { useConfirmModal } from '@/hooks/use-confirm-modal';
import useRedirectUri from '@/hooks/use-redirect-uri';

import { useConfirmModal } from './use-confirm-modal';
import useRedirectUri from './use-redirect-uri';
import useSubscribe from './use-subscribe';

export class RequestError extends Error {
constructor(
Expand Down Expand Up @@ -61,7 +62,7 @@

// This is what will happen when the user still has the legacy refresh token without
// organization scope. We should sign them out and redirect to the sign in page.
// TODO: This is a temporary solution to prevent the user from getting stuck in Console,

Check warning on line 65 in packages/console/src/hooks/use-api.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/console/src/hooks/use-api.ts#L65

[no-warning-comments] Unexpected 'todo' comment: 'TODO: This is a temporary solution to...'.
// which can be removed after all legacy refresh tokens are expired, i.e. after Jan 10th,
// 2024.
if (response.status === 403 && data.message === 'Insufficient permissions.') {
Expand Down Expand Up @@ -124,6 +125,7 @@
const toastDisabledErrorCodes = Array.isArray(hideErrorToast) ? hideErrorToast : undefined;

const { handleError } = useGlobalRequestErrorHandler(toastDisabledErrorCodes);
const { syncSubscriptionData } = useSubscribe();

const api = useMemo(
() =>
Expand All @@ -150,19 +152,33 @@
}
},
],
afterResponse: [
async (request, _options, response) => {
if (
isCloud &&
isDevFeaturesEnabled &&
['POST', 'PUT', 'DELETE'].includes(request.method) &&
response.status >= 200 &&
response.status < 300
) {
syncSubscriptionData();
}
},
],
},
}),
[
prefixUrl,
timeout,
signal,
disableGlobalErrorHandling,
handleError,
isAuthenticated,
resourceIndicator,
getOrganizationToken,
getAccessToken,
i18n.language,
timeout,
signal,
syncSubscriptionData,
]
);

Expand Down
35 changes: 33 additions & 2 deletions packages/console/src/hooks/use-subscribe.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReservedPlanId } from '@logto/schemas';
import dayjs from 'dayjs';
import { nanoid } from 'nanoid';
import { useContext, useState } from 'react';
import { useCallback, useContext, useState } from 'react';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';

Expand All @@ -13,6 +13,10 @@ import { GlobalRoute, TenantsContext } from '@/contexts/TenantsProvider';
import { createLocalCheckoutSession } from '@/utils/checkout';
import { dropLeadingSlash } from '@/utils/url';

import useNewSubscriptionQuota from './use-new-subscription-quota';
import useNewSubscriptionScopeUsage from './use-new-subscription-scopes-usage';
import useNewSubscriptionUsage from './use-new-subscription-usage';
import useSubscription from './use-subscription';
import useTenantPathname from './use-tenant-pathname';

type SubscribeProps = {
Expand All @@ -32,10 +36,34 @@ type SubscribeProps = {
const useSubscribe = () => {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const cloudApi = useCloudApi({ hideErrorToast: true });
const { updateTenant } = useContext(TenantsContext);
const { updateTenant, currentTenantId } = useContext(TenantsContext);
const { getUrl } = useTenantPathname();
const [isSubscribeLoading, setIsSubscribeLoading] = useState(false);

const { mutate: mutateSubscription } = useSubscription(currentTenantId);
const { mutate: mutateSubscriptionQuota } = useNewSubscriptionQuota(currentTenantId);
const { mutate: mutateSubscriptionUsage } = useNewSubscriptionUsage(currentTenantId);
const {
scopeResourceUsage: { mutate: mutateScopeResourceUsage },
scopeRoleUsage: { mutate: mutateScopeRoleUsage },
} = useNewSubscriptionScopeUsage(currentTenantId);

const syncSubscriptionData = useCallback(() => {
void mutateSubscription();
if (isDevFeaturesEnabled) {
void mutateSubscriptionQuota();
void mutateSubscriptionUsage();
void mutateScopeResourceUsage();
void mutateScopeRoleUsage();
}
}, [
mutateScopeResourceUsage,
mutateScopeRoleUsage,
mutateSubscription,
mutateSubscriptionQuota,
mutateSubscriptionUsage,
]);

const subscribe = async ({
skuId,
planId,
Expand Down Expand Up @@ -104,6 +132,8 @@ const useSubscribe = () => {
tenantId,
},
});

syncSubscriptionData();
updateTenant(tenantId, {
planId: rest.planId,
subscription: rest,
Expand Down Expand Up @@ -147,6 +177,7 @@ const useSubscribe = () => {
isSubscribeLoading,
subscribe,
cancelSubscription,
syncSubscriptionData,
visitManagePaymentPage,
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import PlanName from '@/components/PlanName';
import QuotaGuardFooter from '@/components/QuotaGuardFooter';
import { isDevFeaturesEnabled } from '@/consts/env';
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
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 useNewSubscriptionScopeUsage from '@/hooks/use-new-subscription-scopes-usage';
import modalStyles from '@/scss/modal.module.scss';
import { trySubmitSafe } from '@/utils/form';
import { hasReachedQuotaLimit, hasReachedSubscriptionQuotaLimit } from '@/utils/quota';
Expand All @@ -37,10 +35,6 @@ function CreatePermissionModal({ resourceId, totalResourceCount, onClose }: Prop
currentSubscriptionQuota,
currentSubscriptionScopeResourceUsage,
} = useContext(SubscriptionDataContext);
const { currentTenantId } = useContext(TenantsContext);
const {
scopeResourceUsage: { mutate: mutateScopeResourceUsage },
} = useNewSubscriptionScopeUsage(currentTenantId);
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });

const {
Expand All @@ -61,7 +55,6 @@ function CreatePermissionModal({ resourceId, totalResourceCount, onClose }: Prop
.post(`api/resources/${resourceId}/scopes`, { json: formData })
.json<Scope>();

void mutateScopeResourceUsage();
onClose(createdScope);
})
);
Expand Down
9 changes: 1 addition & 8 deletions packages/console/src/pages/ApiResourceDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Resource } from '@logto/schemas';
import { isManagementApi, Theme } from '@logto/schemas';
import { conditionalArray } from '@silverhand/essentials';
import classNames from 'classnames';
import { useEffect, useState, useContext } from 'react';
import { useEffect, useState } from 'react';
import { toast } from 'react-hot-toast';
import { Trans, useTranslation } from 'react-i18next';
import { Outlet, useLocation, useParams } from 'react-router-dom';
Expand All @@ -19,13 +19,11 @@ import DetailsPageHeader, { type MenuItem } from '@/components/DetailsPage/Detai
import Drawer from '@/components/Drawer';
import PageMeta from '@/components/PageMeta';
import { ApiResourceDetailsTabs } from '@/consts/page-tabs';
import { TenantsContext } from '@/contexts/TenantsProvider';
import DeleteConfirmModal from '@/ds-components/DeleteConfirmModal';
import TabNav, { TabNavItem } from '@/ds-components/TabNav';
import type { RequestError } from '@/hooks/use-api';
import useApi from '@/hooks/use-api';
import useDocumentationUrl from '@/hooks/use-documentation-url';
import useNewSubscriptionScopeUsage from '@/hooks/use-new-subscription-scopes-usage';
import useTenantPathname from '@/hooks/use-tenant-pathname';
import useTheme from '@/hooks/use-theme';

Expand All @@ -43,10 +41,6 @@ const icons = {
function ApiResourceDetails() {
const { pathname } = useLocation();
const { id, guideId } = useParams();
const { currentTenantId } = useContext(TenantsContext);
const {
scopeResourceUsage: { mutate: mutateScopeResourceUsage },
} = useNewSubscriptionScopeUsage(currentTenantId);
const { navigate, match } = useTenantPathname();
const { getDocumentationUrl } = useDocumentationUrl();
const isGuideView = !!id && !!guideId && match(`/api-resources/${id}/guide/${guideId}`);
Expand Down Expand Up @@ -81,7 +75,6 @@ function ApiResourceDetails() {

try {
await api.delete(`api/resources/${data.id}`);
void mutateScopeResourceUsage();
toast.success(t('api_resource_details.api_resource_deleted', { name: data.name }));
navigate(`/api-resources`);
} finally {
Expand Down
Loading