chore: dashboard fixes (#14968)

* add rewrites for platform dashboard

* fix loading checking

* add checks

* dont display banner for platform client

* custom hooks for pllatform

* add comment for better explanation

* get data from custom hook

* update returned user attributes

* get data from custom hook
This commit is contained in:
Rajiv Sahal authored and GitHub committed 2024-05-10 15:16:03 +03:00
1 parent 57abb26c31
commit bc42c27230
6 files changed
+122 -67

No files matched your search

@@ -0,0 +1,14 @@
import { useCheckTeamBilling } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
import useMeQuery from "@lib/hooks/useMeQuery";
export const useGetUserAttributes = () => {
const { data: user, isLoading: isUserLoading } = useMeQuery();
const { data: userBillingData, isFetching: isUserBillingDataLoading } = useCheckTeamBilling(
user?.organizationId
);
const isPlatformUser = user?.organization.isPlatform;
const isPaidUser = userBillingData?.valid;
const userOrgId = user?.organizationId;
return { isUserLoading, isUserBillingDataLoading, isPlatformUser, isPaidUser, userBillingData, userOrgId };
};
+5
View File
@@ -537,6 +537,11 @@ const nextConfig = {
destination: "/apps/installed/calendar",
permanent: true,
},
{
source: "/settings/organizations/platform/:path*",
destination: "/settings/platform",
permanent: true,
},
// OAuth callbacks when sent to localhost:3000(w would be expected) should be redirected to corresponding to WEBAPP_URL
...(process.env.NODE_ENV === "development" &&
// Safer to enable the redirect only when the user is opting to test out organizations
+17 -12
View File
@@ -8,15 +8,12 @@ import {
useOAuthClients,
useGetOAuthClientManagedUsers,
} from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients";
import {
useDeleteOAuthClient,
useCheckTeamBilling,
} from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
import useMeQuery from "@lib/hooks/useMeQuery";
import { useDeleteOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
import PageWrapper from "@components/PageWrapper";
import { ManagedUserList } from "@components/settings/platform/dashboard/managed-user-list";
import { OAuthClientsList } from "@components/settings/platform/dashboard/oauth-clients-list";
import { useGetUserAttributes } from "@components/settings/platform/hooks/useGetUserAttributes";
import { PlatformPricing } from "@components/settings/platform/pricing/platform-pricing";
const queryClient = new QueryClient();
@@ -25,17 +22,15 @@ export default function Platform() {
const [initialClientId, setInitialClientId] = useState("");
const [initialClientName, setInitialClientName] = useState("");
const { data: user, isLoading } = useMeQuery();
const { data, isLoading: isOAuthClientLoading, refetch: refetchClients } = useOAuthClients();
const {
isLoading: isManagedUserLoading,
data: managedUserData,
refetch: refetchManagedUsers,
} = useGetOAuthClientManagedUsers(initialClientId);
const { data: userBillingData } = useCheckTeamBilling(user?.organizationId);
const isPlatformUser = user?.organization.isPlatform;
const isPaidUser = userBillingData?.valid;
const { isUserLoading, isUserBillingDataLoading, isPlatformUser, isPaidUser, userBillingData, userOrgId } =
useGetUserAttributes();
const { mutateAsync, isPending: isDeleting } = useDeleteOAuthClient({
onSuccess: () => {
@@ -54,9 +49,13 @@ export default function Platform() {
setInitialClientName(data[0]?.name);
}, [data]);
if (isLoading || isOAuthClientLoading) return <div className="m-5">Loading...</div>;
if (isUserLoading || isOAuthClientLoading) return <div className="m-5">Loading...</div>;
if (isPlatformUser && !isPaidUser) return <PlatformPricing teamId={user?.organizationId} />;
if (isUserBillingDataLoading && !userBillingData) {
return <div className="m-5">Loading...</div>;
}
if (isPlatformUser && !isPaidUser) return <PlatformPricing teamId={userOrgId} />;
if (isPlatformUser) {
return (
@@ -90,7 +89,13 @@ export default function Platform() {
return (
<div>
<Shell hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
<Shell
// we want to hide org banner and have different sidebar tabs for platform clients
// hence we pass isPlatformUser boolean as prop
isPlatformUser={true}
hideHeadingOnMobile
withoutMain={false}
SidebarContainer={<></>}>
You are not subscribed to a Platform plan.
</Shell>
</div>
@@ -9,6 +9,7 @@ import { useOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/useOA
import { useUpdateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
import PageWrapper from "@components/PageWrapper";
import { useGetUserAttributes } from "@components/settings/platform/hooks/useGetUserAttributes";
import type { FormValues } from "@components/settings/platform/oauth-clients/oauth-client-form";
import { OAuthClientForm as EditOAuthClientForm } from "@components/settings/platform/oauth-clients/oauth-client-form";
@@ -29,6 +30,9 @@ export default function EditOAuthClient() {
const router = useRouter();
const params = useParams<{ clientId: string }>();
const clientId = params?.clientId || "";
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
const { data, isFetched, isFetching, isError, refetch } = useOAuthClient(clientId);
const { mutateAsync: update, isPending: isUpdating } = useUpdateOAuthClient({
onSuccess: () => {
@@ -66,48 +70,60 @@ export default function EditOAuthClient() {
});
};
if (isUserLoading) return <div className="m-5">Loading...</div>;
if (isPlatformUser && isPaidUser) {
return (
<div>
<Shell title="OAuth client updation form" isPlatformUser={true}>
<div className="m-2 md:mx-14 md:mx-5">
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6">
<div className="flex w-full flex-col">
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide">
OAuth client updation form
</h1>
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">
This is the form to edit an existing OAuth client
</p>
</div>
</div>
{(!Boolean(clientId) || (isFetched && !data)) && <p>OAuth Client not found.</p>}
{isFetched && !!data && (
<EditOAuthClientForm
defaultValues={{
name: data?.name ?? "",
areEmailsEnabled: data.areEmailsEnabled ?? false,
redirectUris: data?.redirectUris?.map((uri) => ({ uri })) ?? [{ uri: "" }],
bookingRedirectUri: data?.bookingRedirectUri ?? "",
bookingCancelRedirectUri: data?.bookingCancelRedirectUri ?? "",
bookingRescheduleRedirectUri: data?.bookingRescheduleRedirectUri ?? "",
appsRead: hasAppsReadPermission(data?.permissions),
appsWrite: hasAppsWritePermission(data?.permissions),
bookingRead: hasBookingReadPermission(data?.permissions),
bookingWrite: hasBookingWritePermission(data?.permissions),
eventTypeRead: hasEventTypeReadPermission(data?.permissions),
eventTypeWrite: hasEventTypeWritePermission(data?.permissions),
profileRead: hasProfileReadPermission(data?.permissions),
profileWrite: hasProfileWritePermission(data?.permissions),
scheduleRead: hasScheduleReadPermission(data?.permissions),
scheduleWrite: hasScheduleWritePermission(data?.permissions),
}}
onSubmit={onSubmit}
isPending={isUpdating}
/>
)}
{isFetching && <p>Loading...</p>}
{isError && <p>Something went wrong.</p>}
</div>
</Shell>
</div>
);
}
return (
<div>
<Shell title="OAuth client updation form" isPlatformUser={true}>
<div className="m-2 md:mx-14 md:mx-5">
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6">
<div className="flex w-full flex-col">
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide">
OAuth client updation form
</h1>
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">
This is the form to edit an existing OAuth client
</p>
</div>
</div>
{(!Boolean(clientId) || (isFetched && !data)) && <p>OAuth Client not found.</p>}
{isFetched && !!data && (
<EditOAuthClientForm
defaultValues={{
name: data?.name ?? "",
areEmailsEnabled: data.areEmailsEnabled ?? false,
redirectUris: data?.redirectUris?.map((uri) => ({ uri })) ?? [{ uri: "" }],
bookingRedirectUri: data?.bookingRedirectUri ?? "",
bookingCancelRedirectUri: data?.bookingCancelRedirectUri ?? "",
bookingRescheduleRedirectUri: data?.bookingRescheduleRedirectUri ?? "",
appsRead: hasAppsReadPermission(data?.permissions),
appsWrite: hasAppsWritePermission(data?.permissions),
bookingRead: hasBookingReadPermission(data?.permissions),
bookingWrite: hasBookingWritePermission(data?.permissions),
eventTypeRead: hasEventTypeReadPermission(data?.permissions),
eventTypeWrite: hasEventTypeWritePermission(data?.permissions),
profileRead: hasProfileReadPermission(data?.permissions),
profileWrite: hasProfileWritePermission(data?.permissions),
scheduleRead: hasScheduleReadPermission(data?.permissions),
scheduleWrite: hasScheduleWritePermission(data?.permissions),
}}
onSubmit={onSubmit}
isPending={isUpdating}
/>
)}
{isFetching && <p>Loading...</p>}
{isError && <p>Something went wrong.</p>}
</div>
<Shell isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
You are not subscribed to a Platform plan.
</Shell>
</div>
);
@@ -8,6 +8,7 @@ import { showToast } from "@calcom/ui";
import { useCreateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
import PageWrapper from "@components/PageWrapper";
import { useGetUserAttributes } from "@components/settings/platform/hooks/useGetUserAttributes";
import type { FormValues } from "@components/settings/platform/oauth-clients/oauth-client-form";
import { OAuthClientForm } from "@components/settings/platform/oauth-clients/oauth-client-form";
@@ -16,6 +17,8 @@ export default function CreateOAuthClient() {
const router = useRouter();
const clientId = searchParams?.get("clientId") || "";
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
const { mutateAsync: save, isPending: isSaving } = useCreateOAuthClient({
onSuccess: () => {
showToast("OAuth client created successfully", "success");
@@ -51,22 +54,34 @@ export default function CreateOAuthClient() {
});
};
if (isUserLoading) return <div className="m-5">Loading...</div>;
if (isPlatformUser && isPaidUser) {
return (
<div>
<Shell title={`OAuth client ${!!clientId ? "updation" : "creation"} form`} isPlatformUser={true}>
<div className="m-2 md:mx-14 md:mx-5">
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6">
<div className="flex w-full flex-col">
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide">
OAuth client creation form
</h1>
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">
This is the form to create a new OAuth client
</p>
</div>
</div>
<OAuthClientForm isPending={isSaving} onSubmit={onSubmit} />
</div>
</Shell>
</div>
);
}
return (
<div>
<Shell title={`OAuth client ${!!clientId ? "updation" : "creation"} form`} isPlatformUser={true}>
<div className="m-2 md:mx-14 md:mx-5">
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6">
<div className="flex w-full flex-col">
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide">
OAuth client creation form
</h1>
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">
This is the form to create a new OAuth client
</p>
</div>
</div>
<OAuthClientForm isPending={isSaving} onSubmit={onSubmit} />
</div>
<Shell isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
You are not subscribed to a Platform plan.
</Shell>
</div>
);
+1 -1
View File
@@ -255,7 +255,7 @@ const Layout = (props: LayoutProps) => {
<TimezoneChangeDialog />
<div className="flex min-h-screen flex-col">
{banners && (
{banners && !props.isPlatformUser && (
<div className="sticky top-0 z-10 w-full divide-y divide-black">
<UserV2OptInBanner />
{Object.keys(banners).map((key) => {