chore: App router migration - settings/platform/**/*, settings/organizations/new and settings/organizations/[id]/* (#16334)
* remove WizardLayoutAppDir * refactor organizations/new and add platform/new * refactor organizations/[id]/* * add APP_ROUTER_SETTINGS_ORG_ENABLED * fix type error * fix organizations/new page * remove code not needed and fix type errors * Fix Metadata utils * remove unnecessary code * remove unneeded code * wip * do not remove buildWrappedOnboardTeamMembersPage * fix type error * do not introduce changes to yarn.lock * fix wrong route name * fix onboard members * fix platform pages * fix settings/platform main view * add requiresLicense to WithLayout * refactor * add requiresLicense to platform/new * Add LicenseRequired back to platform/new * add env variable * fix onboard-members --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com>
This commit is contained in:
co-authored by
Keith Williams
parent
5dff1c6df0
commit
9ed1624111
@@ -334,6 +334,8 @@ AB_TEST_BUCKET_PROBABILITY=50
|
||||
# whether we redirect to the future/event-types from event-types or not
|
||||
APP_ROUTER_EVENT_TYPES_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_ADMIN_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_PLATFORM_ENABLED=0
|
||||
APP_ROUTER_SETTINGS_ORG_ENABLED=0
|
||||
APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
|
||||
|
||||
@@ -8,6 +8,8 @@ import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME }
|
||||
const ROUTES: [URLPattern, boolean][] = [
|
||||
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
|
||||
["/settings/admin/:path*", process.env.APP_ROUTER_SETTINGS_ADMIN_ENABLED === "1"] as const,
|
||||
["/settings/platform/:path*", process.env.APP_ROUTER_SETTINGS_PLATFORM_ENABLED === "1"] as const,
|
||||
["/settings/organizations/:path*", process.env.APP_ROUTER_SETTINGS_ORG_ENABLED === "1"] as const,
|
||||
["/apps/installed/:category", process.env.APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED === "1"] as const,
|
||||
["/apps/:slug", process.env.APP_ROUTER_APPS_SLUG_ENABLED === "1"] as const,
|
||||
["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const,
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import LegacyPage, {
|
||||
buildWrappedOnboardTeamMembersPage,
|
||||
} from "@pages/settings/organizations/[id]/onboard-members";
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("invite_organization_admins"),
|
||||
(t) => t("invite_organization_admins_description")
|
||||
);
|
||||
|
||||
const Page = ({ params }: PageProps) => {
|
||||
return buildWrappedOnboardTeamMembersPage(params.id, <LegacyPage />);
|
||||
};
|
||||
|
||||
export default WithLayout({ Page });
|
||||
+6
-2
@@ -1,11 +1,15 @@
|
||||
import LegacyPage, { LayoutWrapper } from "@pages/settings/organizations/[id]/about";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/about-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("about_your_organization"),
|
||||
(t) => t("about_your_organization_description")
|
||||
);
|
||||
|
||||
export default WithLayout({ Page: LegacyPage, getLayout: LayoutWrapper });
|
||||
export default WithLayout({
|
||||
Page: LegacyPage,
|
||||
getLayout: LayoutWrapper,
|
||||
});
|
||||
+6
-2
@@ -1,11 +1,15 @@
|
||||
import LegacyPage, { LayoutWrapper } from "@pages/settings/organizations/[id]/add-teams";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/add-teams-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("create_your_teams"),
|
||||
(t) => t("create_your_teams_description")
|
||||
);
|
||||
|
||||
export default WithLayout({ Page: LegacyPage, getLayout: LayoutWrapper });
|
||||
export default WithLayout({
|
||||
Page: LegacyPage,
|
||||
getLayout: LayoutWrapper,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/[id]/onboard-members-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("invite_organization_admins"),
|
||||
(t) => t("invite_organization_admins_description")
|
||||
);
|
||||
|
||||
export default WithLayout({
|
||||
Page: LegacyPage,
|
||||
getLayout: LayoutWrapper,
|
||||
});
|
||||
+4
-1
@@ -1,10 +1,12 @@
|
||||
import LegacyPage, { getServerSideProps, LayoutWrapper } from "@pages/settings/organizations/new/index";
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
import { type inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/organizations/new/create-new-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("set_up_your_organization"),
|
||||
@@ -12,6 +14,7 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
export default WithLayout({
|
||||
requiresLicense: true,
|
||||
getLayout: LayoutWrapper,
|
||||
Page: LegacyPage,
|
||||
getData: withAppDirSsr<inferSSRProps<typeof getServerSideProps>>(getServerSideProps),
|
||||
@@ -0,0 +1,21 @@
|
||||
import { withAppDirSsr } from "app/WithAppDirSsr";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
import { type inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import LegacyPage, { LayoutWrapper } from "~/settings/platform/new/create-new-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
(t) => t("set_up_your_platform_organization"),
|
||||
(t) => t("platform_organization_description")
|
||||
);
|
||||
|
||||
export default WithLayout({
|
||||
getLayout: LayoutWrapper,
|
||||
Page: LegacyPage,
|
||||
getData: withAppDirSsr<inferSSRProps<typeof getServerSideProps>>(getServerSideProps),
|
||||
requiresLicense: true,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import EditView from "~/settings/platform/oauth-clients/[clientId]/edit/edit-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "OAuth client updation form",
|
||||
() => ""
|
||||
);
|
||||
|
||||
export default WithLayout({
|
||||
getLayout: null,
|
||||
Page: EditView,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import EditWebhooksView from "~/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
() => "OAuth client updation form",
|
||||
() => ""
|
||||
);
|
||||
|
||||
export default WithLayout({
|
||||
getLayout: null,
|
||||
Page: EditWebhooksView,
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { PageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import CreateNewView from "~/settings/platform/oauth-clients/create-new-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const p = { ...params, ...searchParams };
|
||||
const clientId = p?.clientId ?? "";
|
||||
return await _generateMetadata(
|
||||
() => `OAuth client ${!!clientId ? "updation" : "creation"} form`,
|
||||
() => ""
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({
|
||||
getLayout: null,
|
||||
Page: CreateNewView,
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
|
||||
import PlatformView from "~/settings/platform/platform-view";
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
return await _generateMetadata(
|
||||
() => "Platform",
|
||||
() => "Manage everything related to platform."
|
||||
);
|
||||
};
|
||||
|
||||
export default WithLayout({
|
||||
getLayout: null,
|
||||
Page: PlatformView,
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { AboutOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={3} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutOrganizationForm;
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { AddNewTeamsForm } from "@calcom/features/ee/organizations/components";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={5} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddNewTeamsForm;
|
||||
@@ -0,0 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import AddNewTeamMembers from "@calcom/features/ee/teams/components/AddNewTeamMembers";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const router = useRouter();
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const query = useCompatSearchParams();
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
currentStep={4}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
router.push(`/settings/organizations/${query.get("id")}/add-teams`);
|
||||
}}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
const OrgAddNewTeamMembers = () => <AddNewTeamMembers isOrg={true} />;
|
||||
export default OrgAddNewTeamMembers;
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { CreateANewOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={1} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateANewOrganizationForm;
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { CreateANewPlatformForm } from "@calcom/features/ee/platform/components/index";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={1} maxSteps={1}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateANewPlatformForm;
|
||||
@@ -0,0 +1,133 @@
|
||||
"use client";
|
||||
|
||||
import { useParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { PERMISSIONS_GROUPED_MAP } from "@calcom/platform-constants";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import { useOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients";
|
||||
import { useUpdateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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";
|
||||
|
||||
import {
|
||||
hasAppsReadPermission,
|
||||
hasAppsWritePermission,
|
||||
hasBookingReadPermission,
|
||||
hasBookingWritePermission,
|
||||
hasEventTypeReadPermission,
|
||||
hasEventTypeWritePermission,
|
||||
hasProfileReadPermission,
|
||||
hasProfileWritePermission,
|
||||
hasScheduleReadPermission,
|
||||
hasScheduleWritePermission,
|
||||
} from "../../../../../../../../packages/platform/utils/permissions";
|
||||
|
||||
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: () => {
|
||||
showToast("OAuth client updated successfully", "success");
|
||||
refetch();
|
||||
router.push("/settings/platform/");
|
||||
},
|
||||
onError: () => {
|
||||
showToast(ErrorCode.UpdatingOauthClientError, "error");
|
||||
},
|
||||
clientId,
|
||||
});
|
||||
|
||||
const onSubmit = (data: FormValues) => {
|
||||
let userPermissions = 0;
|
||||
const userRedirectUris = data.redirectUris.map((uri) => uri.uri).filter((uri) => !!uri);
|
||||
|
||||
Object.keys(PERMISSIONS_GROUPED_MAP).forEach((key) => {
|
||||
const entity = key as keyof typeof PERMISSIONS_GROUPED_MAP;
|
||||
const entityKey = PERMISSIONS_GROUPED_MAP[entity].key;
|
||||
const read = PERMISSIONS_GROUPED_MAP[entity].read;
|
||||
const write = PERMISSIONS_GROUPED_MAP[entity].write;
|
||||
if (data[`${entityKey}Read`]) userPermissions |= read;
|
||||
if (data[`${entityKey}Write`]) userPermissions |= write;
|
||||
});
|
||||
|
||||
update({
|
||||
name: data.name,
|
||||
// logo: data.logo,
|
||||
redirectUris: userRedirectUris,
|
||||
bookingRedirectUri: data.bookingRedirectUri,
|
||||
bookingCancelRedirectUri: data.bookingCancelRedirectUri,
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
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 isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
"use client";
|
||||
|
||||
import { useParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { WebhookForm } from "@calcom/features/webhooks/components";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import {
|
||||
useOAuthClientWebhooks,
|
||||
useCreateOAuthClientWebhook,
|
||||
useUpdateOAuthClientWebhook,
|
||||
} from "@lib/hooks/settings/platform/oauth-clients/useOAuthClientWebhooks";
|
||||
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
import { useGetUserAttributes } from "@components/settings/platform/hooks/useGetUserAttributes";
|
||||
|
||||
export default function EditOAuthClientWebhooks() {
|
||||
const router = useRouter();
|
||||
const params = useParams<{ clientId: string }>();
|
||||
const clientId = params?.clientId || "";
|
||||
|
||||
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
|
||||
|
||||
const {
|
||||
data: webhooks,
|
||||
status: webhooksStatus,
|
||||
isFetched: isWebhooksFetched,
|
||||
refetch: refetchWebhooks,
|
||||
} = useOAuthClientWebhooks(clientId);
|
||||
const webhookId = webhooks?.[0]?.id ?? "";
|
||||
const webhook = webhooks?.[0];
|
||||
const { mutateAsync: createWebhook } = useCreateOAuthClientWebhook(clientId);
|
||||
const { mutateAsync: updateWebhook } = useUpdateOAuthClientWebhook(clientId);
|
||||
|
||||
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-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">
|
||||
Webhook update form
|
||||
</h1>
|
||||
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">Add a webhook to your OAuthClient.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{webhooksStatus !== "success" && <p>Error while trying to access webhooks.</p>}
|
||||
|
||||
{isWebhooksFetched && webhooksStatus === "success" && (
|
||||
<WebhookForm
|
||||
overrideTriggerOptions={[
|
||||
{ value: WebhookTriggerEvents.BOOKING_CANCELLED, label: "booking_cancelled" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_CREATED, label: "booking_created" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_REJECTED, label: "booking_rejected" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_REQUESTED, label: "booking_requested" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_RESCHEDULED, label: "booking_rescheduled" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_NO_SHOW_UPDATED, label: "booking_no_show_updated" },
|
||||
{ value: WebhookTriggerEvents.MEETING_ENDED, label: "meeting_ended" },
|
||||
{ value: WebhookTriggerEvents.MEETING_STARTED, label: "meeting_started" },
|
||||
{ value: WebhookTriggerEvents.RECORDING_READY, label: "recording_ready" },
|
||||
{
|
||||
value: WebhookTriggerEvents.RECORDING_TRANSCRIPTION_GENERATED,
|
||||
label: "recording_transcription_generated",
|
||||
},
|
||||
]}
|
||||
onSubmit={async (data) => {
|
||||
try {
|
||||
const body = {
|
||||
active: data.active,
|
||||
payloadTemplate: data.payloadTemplate ?? undefined,
|
||||
subscriberUrl: data.subscriberUrl,
|
||||
triggers: data.eventTriggers,
|
||||
secret: data.secret ?? undefined,
|
||||
};
|
||||
if (webhook) {
|
||||
await updateWebhook({
|
||||
webhookId,
|
||||
body,
|
||||
});
|
||||
showToast("Webhook updated successfully.", "success");
|
||||
} else {
|
||||
await createWebhook(body);
|
||||
showToast("Webhook created successfully.", "success");
|
||||
}
|
||||
await refetchWebhooks();
|
||||
router.push("/settings/platform/");
|
||||
} catch (err) {
|
||||
showToast(`Failed to ${webhookId ? "update" : "create"} webhook.`, "error");
|
||||
}
|
||||
}}
|
||||
onCancel={() => {
|
||||
router.push("/settings/platform/");
|
||||
}}
|
||||
noRoutingFormTriggers={true}
|
||||
webhook={
|
||||
webhook
|
||||
? { ...webhook, eventTriggers: webhook.triggers, secret: webhook.secret ?? null }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Shell isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { PERMISSIONS_GROUPED_MAP } from "@calcom/platform-constants/permissions";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import { useCreateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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";
|
||||
|
||||
export default function CreateOAuthClient() {
|
||||
const searchParams = useCompatSearchParams();
|
||||
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");
|
||||
router.push("/settings/platform/");
|
||||
},
|
||||
onError: () => {
|
||||
showToast(ErrorCode.CreatingOauthClientError, "error");
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = (data: FormValues) => {
|
||||
let userPermissions = 0;
|
||||
const userRedirectUris = data.redirectUris.map((uri) => uri.uri).filter((uri) => !!uri);
|
||||
|
||||
Object.keys(PERMISSIONS_GROUPED_MAP).forEach((key) => {
|
||||
const entity = key as keyof typeof PERMISSIONS_GROUPED_MAP;
|
||||
const entityKey = PERMISSIONS_GROUPED_MAP[entity].key;
|
||||
const read = PERMISSIONS_GROUPED_MAP[entity].read;
|
||||
const write = PERMISSIONS_GROUPED_MAP[entity].write;
|
||||
if (data[`${entityKey}Read`]) userPermissions |= read;
|
||||
if (data[`${entityKey}Write`]) userPermissions |= write;
|
||||
});
|
||||
|
||||
save({
|
||||
name: data.name,
|
||||
permissions: userPermissions,
|
||||
// logo: data.logo,
|
||||
redirectUris: userRedirectUris,
|
||||
bookingRedirectUri: data.bookingRedirectUri,
|
||||
bookingCancelRedirectUri: data.bookingCancelRedirectUri,
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
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-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 isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
"use client";
|
||||
|
||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import {
|
||||
useOAuthClients,
|
||||
useGetOAuthClientManagedUsers,
|
||||
} from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients";
|
||||
import { useDeleteOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import { HelpCards } from "@components/settings/platform/dashboard/HelpCards";
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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();
|
||||
|
||||
export default function Platform() {
|
||||
const [initialClientId, setInitialClientId] = useState("");
|
||||
const [initialClientName, setInitialClientName] = useState("");
|
||||
|
||||
const { data, isLoading: isOAuthClientLoading, refetch: refetchClients } = useOAuthClients();
|
||||
const {
|
||||
isLoading: isManagedUserLoading,
|
||||
data: managedUserData,
|
||||
refetch: refetchManagedUsers,
|
||||
} = useGetOAuthClientManagedUsers(initialClientId);
|
||||
|
||||
const { isUserLoading, isUserBillingDataLoading, isPlatformUser, isPaidUser, userBillingData, userOrgId } =
|
||||
useGetUserAttributes();
|
||||
|
||||
const { mutateAsync, isPending: isDeleting } = useDeleteOAuthClient({
|
||||
onSuccess: () => {
|
||||
showToast("OAuth client deleted successfully", "success");
|
||||
refetchClients();
|
||||
refetchManagedUsers();
|
||||
},
|
||||
});
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
await mutateAsync({ id: id });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setInitialClientId(data[0]?.id);
|
||||
setInitialClientName(data[0]?.name);
|
||||
}, [data]);
|
||||
|
||||
if (isUserLoading || isOAuthClientLoading) return <div className="m-5">Loading...</div>;
|
||||
|
||||
if (isUserBillingDataLoading && !userBillingData) {
|
||||
return <div className="m-5">Loading...</div>;
|
||||
}
|
||||
|
||||
if (isPlatformUser && !isPaidUser) return <PlatformPricing teamId={userOrgId} />;
|
||||
|
||||
if (isPlatformUser) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<div>
|
||||
<Shell
|
||||
heading="Platform"
|
||||
title="Platform"
|
||||
hideHeadingOnMobile
|
||||
withoutMain={false}
|
||||
subtitle="Manage everything related to platform."
|
||||
isPlatformUser={true}>
|
||||
<HelpCards />
|
||||
<OAuthClientsList oauthClients={data} isDeleting={isDeleting} handleDelete={handleDelete} />
|
||||
<ManagedUserList
|
||||
oauthClients={data}
|
||||
managedUsers={managedUserData}
|
||||
isManagedUserLoading={isManagedUserLoading}
|
||||
initialClientName={initialClientName}
|
||||
initialClientId={initialClientId}
|
||||
handleChange={(id: string, name: string) => {
|
||||
setInitialClientId(id);
|
||||
setInitialClientName(name);
|
||||
refetchManagedUsers();
|
||||
}}
|
||||
/>
|
||||
</Shell>
|
||||
</div>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<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={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { AboutOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Meta, WizardLayout } from "@calcom/ui";
|
||||
import { Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
export { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import AboutOrganizationForm, { LayoutWrapper } from "~/settings/organizations/[id]/about-view";
|
||||
|
||||
const AboutOrganizationPage = () => {
|
||||
const Page = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<>
|
||||
@@ -17,15 +15,9 @@ const AboutOrganizationPage = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={3} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
AboutOrganizationPage.getLayout = LayoutWrapper;
|
||||
AboutOrganizationPage.PageWrapper = PageWrapper;
|
||||
Page.getLayout = LayoutWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default AboutOrganizationPage;
|
||||
export default Page;
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { AddNewTeamsForm } from "@calcom/features/ee/organizations/components";
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Meta, WizardLayout } from "@calcom/ui";
|
||||
import { Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
export { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import AddNewTeamsForm, { LayoutWrapper } from "~/settings/organizations/[id]/add-teams-view";
|
||||
|
||||
const AddNewTeamsPage = () => {
|
||||
const Page = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<>
|
||||
@@ -18,15 +16,9 @@ const AddNewTeamsPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={5} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
Page.getLayout = LayoutWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
AddNewTeamsPage.getLayout = LayoutWrapper;
|
||||
AddNewTeamsPage.PageWrapper = PageWrapper;
|
||||
export default Page;
|
||||
|
||||
export default AddNewTeamsPage;
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { redirect, useRouter } from "next/navigation";
|
||||
|
||||
import AddNewTeamMembers from "@calcom/features/ee/teams/components/AddNewTeamMembers";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Meta, WizardLayout } from "@calcom/ui";
|
||||
import { Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
export { getServerSideProps } from "@calcom/features/ee/organizations/pages/organization";
|
||||
import OrgAddNewTeamMembers, { LayoutWrapper } from "~/settings/organizations/[id]/onboard-members-view";
|
||||
|
||||
const OnboardTeamMembersPage = () => {
|
||||
const Page = () => {
|
||||
const { t } = useLocale();
|
||||
|
||||
return (
|
||||
@@ -20,45 +15,13 @@ const OnboardTeamMembersPage = () => {
|
||||
title={t("invite_organization_admins")}
|
||||
description={t("invite_organization_admins_description")}
|
||||
/>
|
||||
<AddNewTeamMembers isOrg={true} />
|
||||
<OrgAddNewTeamMembers />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
OnboardTeamMembersPage.getLayout = (page: React.ReactElement) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const router = useRouter();
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const query = useCompatSearchParams();
|
||||
Page.getLayout = LayoutWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
currentStep={4}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
router.push(`/settings/organizations/${query.get("id")}/add-teams`);
|
||||
}}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export const buildWrappedOnboardTeamMembersPage = (
|
||||
id: string | string[] | undefined,
|
||||
page: React.ReactElement
|
||||
) => {
|
||||
return (
|
||||
<WizardLayout
|
||||
currentStep={4}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
redirect(`/settings/organizations/${id}/add-teams`);
|
||||
}}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
OnboardTeamMembersPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default OnboardTeamMembersPage;
|
||||
export default Page;
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import { CreateANewOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
import { Meta } from "@calcom/ui";
|
||||
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const CreateNewOrganizationPage = ({ querySlug }: inferSSRProps<typeof getServerSideProps>) => {
|
||||
import CreateANewOrganizationForm, { LayoutWrapper } from "~/settings/organizations/new/create-new-view";
|
||||
|
||||
const Page = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<LicenseRequired>
|
||||
@@ -19,17 +17,10 @@ const CreateNewOrganizationPage = ({ querySlug }: inferSSRProps<typeof getServer
|
||||
</LicenseRequired>
|
||||
);
|
||||
};
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={1} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
CreateNewOrganizationPage.getLayout = LayoutWrapper;
|
||||
CreateNewOrganizationPage.PageWrapper = PageWrapper;
|
||||
Page.getLayout = LayoutWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default CreateNewOrganizationPage;
|
||||
export default Page;
|
||||
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -1,108 +1,12 @@
|
||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import {
|
||||
useOAuthClients,
|
||||
useGetOAuthClientManagedUsers,
|
||||
} from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients";
|
||||
import { useDeleteOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import { HelpCards } from "@components/settings/platform/dashboard/HelpCards";
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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();
|
||||
import PlatformView from "~/settings/platform/platform-view";
|
||||
|
||||
export default function Platform() {
|
||||
const [initialClientId, setInitialClientId] = useState("");
|
||||
const [initialClientName, setInitialClientName] = useState("");
|
||||
const Page = new Proxy<{
|
||||
(): JSX.Element;
|
||||
PageWrapper?: typeof PageWrapper;
|
||||
}>(PlatformView, {});
|
||||
|
||||
const { data, isLoading: isOAuthClientLoading, refetch: refetchClients } = useOAuthClients();
|
||||
const {
|
||||
isLoading: isManagedUserLoading,
|
||||
data: managedUserData,
|
||||
refetch: refetchManagedUsers,
|
||||
} = useGetOAuthClientManagedUsers(initialClientId);
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
const { isUserLoading, isUserBillingDataLoading, isPlatformUser, isPaidUser, userBillingData, userOrgId } =
|
||||
useGetUserAttributes();
|
||||
|
||||
const { mutateAsync, isPending: isDeleting } = useDeleteOAuthClient({
|
||||
onSuccess: () => {
|
||||
showToast("OAuth client deleted successfully", "success");
|
||||
refetchClients();
|
||||
refetchManagedUsers();
|
||||
},
|
||||
});
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
await mutateAsync({ id: id });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setInitialClientId(data[0]?.id);
|
||||
setInitialClientName(data[0]?.name);
|
||||
}, [data]);
|
||||
|
||||
if (isUserLoading || isOAuthClientLoading) return <div className="m-5">Loading...</div>;
|
||||
|
||||
if (isUserBillingDataLoading && !userBillingData) {
|
||||
return <div className="m-5">Loading...</div>;
|
||||
}
|
||||
|
||||
if (isPlatformUser && !isPaidUser) return <PlatformPricing teamId={userOrgId} />;
|
||||
|
||||
if (isPlatformUser) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<div>
|
||||
<Shell
|
||||
heading="Platform"
|
||||
title="Platform"
|
||||
hideHeadingOnMobile
|
||||
withoutMain={false}
|
||||
subtitle="Manage everything related to platform."
|
||||
isPlatformUser={true}>
|
||||
<HelpCards />
|
||||
<OAuthClientsList oauthClients={data} isDeleting={isDeleting} handleDelete={handleDelete} />
|
||||
<ManagedUserList
|
||||
oauthClients={data}
|
||||
managedUsers={managedUserData}
|
||||
isManagedUserLoading={isManagedUserLoading}
|
||||
initialClientName={initialClientName}
|
||||
initialClientId={initialClientId}
|
||||
handleChange={(id: string, name: string) => {
|
||||
setInitialClientId(id);
|
||||
setInitialClientName(name);
|
||||
refetchManagedUsers();
|
||||
}}
|
||||
/>
|
||||
</Shell>
|
||||
</div>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<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={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Platform.PageWrapper = PageWrapper;
|
||||
export default Page;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import { CreateANewPlatformForm } from "@calcom/features/ee/platform/components/index";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
import { Meta } from "@calcom/ui";
|
||||
|
||||
import { getServerSideProps } from "@lib/settings/organizations/new/getServerSideProps";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const CreateNewOrganizationPage = () => {
|
||||
import CreateNewOrganizationPage, { LayoutWrapper } from "~/settings/platform/new/create-new-view";
|
||||
|
||||
const Page = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<LicenseRequired>
|
||||
@@ -17,21 +16,14 @@ const CreateNewOrganizationPage = () => {
|
||||
title={t("set_up_your_platform_organization")}
|
||||
description={t("platform_organization_description")}
|
||||
/>
|
||||
<CreateANewPlatformForm />
|
||||
<CreateNewOrganizationPage />
|
||||
</LicenseRequired>
|
||||
);
|
||||
};
|
||||
export const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={1} maxSteps={1}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
CreateNewOrganizationPage.getLayout = LayoutWrapper;
|
||||
CreateNewOrganizationPage.PageWrapper = PageWrapper;
|
||||
Page.getLayout = LayoutWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default CreateNewOrganizationPage;
|
||||
export default Page;
|
||||
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -1,134 +1,12 @@
|
||||
import { useParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { PERMISSIONS_GROUPED_MAP } from "@calcom/platform-constants";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import { useOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients";
|
||||
import { useUpdateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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";
|
||||
|
||||
import {
|
||||
hasAppsReadPermission,
|
||||
hasAppsWritePermission,
|
||||
hasBookingReadPermission,
|
||||
hasBookingWritePermission,
|
||||
hasEventTypeReadPermission,
|
||||
hasEventTypeWritePermission,
|
||||
hasProfileReadPermission,
|
||||
hasProfileWritePermission,
|
||||
hasScheduleReadPermission,
|
||||
hasScheduleWritePermission,
|
||||
} from "../../../../../../../../packages/platform/utils/permissions";
|
||||
import EditView from "~/settings/platform/oauth-clients/[clientId]/edit/edit-view";
|
||||
|
||||
export default function EditOAuthClient() {
|
||||
const router = useRouter();
|
||||
const params = useParams<{ clientId: string }>();
|
||||
const clientId = params?.clientId || "";
|
||||
const Page = new Proxy<{
|
||||
(): JSX.Element;
|
||||
PageWrapper?: typeof PageWrapper;
|
||||
}>(EditView, {});
|
||||
|
||||
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
const { data, isFetched, isFetching, isError, refetch } = useOAuthClient(clientId);
|
||||
const { mutateAsync: update, isPending: isUpdating } = useUpdateOAuthClient({
|
||||
onSuccess: () => {
|
||||
showToast("OAuth client updated successfully", "success");
|
||||
refetch();
|
||||
router.push("/settings/platform/");
|
||||
},
|
||||
onError: () => {
|
||||
showToast(ErrorCode.UpdatingOauthClientError, "error");
|
||||
},
|
||||
clientId,
|
||||
});
|
||||
|
||||
const onSubmit = (data: FormValues) => {
|
||||
let userPermissions = 0;
|
||||
const userRedirectUris = data.redirectUris.map((uri) => uri.uri).filter((uri) => !!uri);
|
||||
|
||||
Object.keys(PERMISSIONS_GROUPED_MAP).forEach((key) => {
|
||||
const entity = key as keyof typeof PERMISSIONS_GROUPED_MAP;
|
||||
const entityKey = PERMISSIONS_GROUPED_MAP[entity].key;
|
||||
const read = PERMISSIONS_GROUPED_MAP[entity].read;
|
||||
const write = PERMISSIONS_GROUPED_MAP[entity].write;
|
||||
if (data[`${entityKey}Read`]) userPermissions |= read;
|
||||
if (data[`${entityKey}Write`]) userPermissions |= write;
|
||||
});
|
||||
|
||||
update({
|
||||
name: data.name,
|
||||
// logo: data.logo,
|
||||
redirectUris: userRedirectUris,
|
||||
bookingRedirectUri: data.bookingRedirectUri,
|
||||
bookingCancelRedirectUri: data.bookingCancelRedirectUri,
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
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 isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
EditOAuthClient.PageWrapper = PageWrapper;
|
||||
export default Page;
|
||||
|
||||
@@ -1,123 +1,12 @@
|
||||
import { useParams } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { WebhookForm } from "@calcom/features/webhooks/components";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import {
|
||||
useOAuthClientWebhooks,
|
||||
useCreateOAuthClientWebhook,
|
||||
useUpdateOAuthClientWebhook,
|
||||
} from "@lib/hooks/settings/platform/oauth-clients/useOAuthClientWebhooks";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
import { useGetUserAttributes } from "@components/settings/platform/hooks/useGetUserAttributes";
|
||||
|
||||
export default function EditOAuthClientWebhooks() {
|
||||
const router = useRouter();
|
||||
const params = useParams<{ clientId: string }>();
|
||||
const clientId = params?.clientId || "";
|
||||
import EditWebhooksView from "~/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view";
|
||||
|
||||
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
|
||||
const Page = new Proxy<{
|
||||
(): JSX.Element;
|
||||
PageWrapper?: typeof PageWrapper;
|
||||
}>(EditWebhooksView, {});
|
||||
|
||||
const {
|
||||
data: webhooks,
|
||||
status: webhooksStatus,
|
||||
isFetched: isWebhooksFetched,
|
||||
refetch: refetchWebhooks,
|
||||
} = useOAuthClientWebhooks(clientId);
|
||||
const webhookId = webhooks?.[0]?.id ?? "";
|
||||
const webhook = webhooks?.[0];
|
||||
const { mutateAsync: createWebhook } = useCreateOAuthClientWebhook(clientId);
|
||||
const { mutateAsync: updateWebhook } = useUpdateOAuthClientWebhook(clientId);
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
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-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">
|
||||
Webhook update form
|
||||
</h1>
|
||||
<p className="text-default text-sm ltr:mr-4 rtl:ml-4">Add a webhook to your OAuthClient.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{webhooksStatus !== "success" && <p>Error while trying to access webhooks.</p>}
|
||||
|
||||
{isWebhooksFetched && webhooksStatus === "success" && (
|
||||
<WebhookForm
|
||||
overrideTriggerOptions={[
|
||||
{ value: WebhookTriggerEvents.BOOKING_CANCELLED, label: "booking_cancelled" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_CREATED, label: "booking_created" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_REJECTED, label: "booking_rejected" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_REQUESTED, label: "booking_requested" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_RESCHEDULED, label: "booking_rescheduled" },
|
||||
{ value: WebhookTriggerEvents.BOOKING_NO_SHOW_UPDATED, label: "booking_no_show_updated" },
|
||||
{ value: WebhookTriggerEvents.MEETING_ENDED, label: "meeting_ended" },
|
||||
{ value: WebhookTriggerEvents.MEETING_STARTED, label: "meeting_started" },
|
||||
{ value: WebhookTriggerEvents.RECORDING_READY, label: "recording_ready" },
|
||||
{
|
||||
value: WebhookTriggerEvents.RECORDING_TRANSCRIPTION_GENERATED,
|
||||
label: "recording_transcription_generated",
|
||||
},
|
||||
]}
|
||||
onSubmit={async (data) => {
|
||||
try {
|
||||
const body = {
|
||||
active: data.active,
|
||||
payloadTemplate: data.payloadTemplate ?? undefined,
|
||||
subscriberUrl: data.subscriberUrl,
|
||||
triggers: data.eventTriggers,
|
||||
secret: data.secret ?? undefined,
|
||||
};
|
||||
if (webhook) {
|
||||
await updateWebhook({
|
||||
webhookId,
|
||||
body,
|
||||
});
|
||||
showToast("Webhook updated successfully.", "success");
|
||||
} else {
|
||||
await createWebhook(body);
|
||||
showToast("Webhook created successfully.", "success");
|
||||
}
|
||||
await refetchWebhooks();
|
||||
router.push("/settings/platform/");
|
||||
} catch (err) {
|
||||
showToast(`Failed to ${webhookId ? "update" : "create"} webhook.`, "error");
|
||||
}
|
||||
}}
|
||||
onCancel={() => {
|
||||
router.push("/settings/platform/");
|
||||
}}
|
||||
noRoutingFormTriggers={true}
|
||||
webhook={
|
||||
webhook
|
||||
? { ...webhook, eventTriggers: webhook.triggers, secret: webhook.secret ?? null }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Shell isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
EditOAuthClientWebhooks.PageWrapper = PageWrapper;
|
||||
export default Page;
|
||||
|
||||
@@ -1,92 +1,12 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { PERMISSIONS_GROUPED_MAP } from "@calcom/platform-constants/permissions";
|
||||
import { showToast } from "@calcom/ui";
|
||||
|
||||
import { useCreateOAuthClient } from "@lib/hooks/settings/platform/oauth-clients/usePersistOAuthClient";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import NoPlatformPlan from "@components/settings/platform/dashboard/NoPlatformPlan";
|
||||
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";
|
||||
|
||||
export default function CreateOAuthClient() {
|
||||
const searchParams = useCompatSearchParams();
|
||||
const router = useRouter();
|
||||
const clientId = searchParams?.get("clientId") || "";
|
||||
import CreateOAuthClientView from "~/settings/platform/oauth-clients/create-new-view";
|
||||
|
||||
const { isUserLoading, isPlatformUser, isPaidUser } = useGetUserAttributes();
|
||||
const Page = new Proxy<{
|
||||
(): JSX.Element;
|
||||
PageWrapper?: typeof PageWrapper;
|
||||
}>(CreateOAuthClientView, {});
|
||||
|
||||
const { mutateAsync: save, isPending: isSaving } = useCreateOAuthClient({
|
||||
onSuccess: () => {
|
||||
showToast("OAuth client created successfully", "success");
|
||||
router.push("/settings/platform/");
|
||||
},
|
||||
onError: () => {
|
||||
showToast(ErrorCode.CreatingOauthClientError, "error");
|
||||
},
|
||||
});
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
const onSubmit = (data: FormValues) => {
|
||||
let userPermissions = 0;
|
||||
const userRedirectUris = data.redirectUris.map((uri) => uri.uri).filter((uri) => !!uri);
|
||||
|
||||
Object.keys(PERMISSIONS_GROUPED_MAP).forEach((key) => {
|
||||
const entity = key as keyof typeof PERMISSIONS_GROUPED_MAP;
|
||||
const entityKey = PERMISSIONS_GROUPED_MAP[entity].key;
|
||||
const read = PERMISSIONS_GROUPED_MAP[entity].read;
|
||||
const write = PERMISSIONS_GROUPED_MAP[entity].write;
|
||||
if (data[`${entityKey}Read`]) userPermissions |= read;
|
||||
if (data[`${entityKey}Write`]) userPermissions |= write;
|
||||
});
|
||||
|
||||
save({
|
||||
name: data.name,
|
||||
permissions: userPermissions,
|
||||
// logo: data.logo,
|
||||
redirectUris: userRedirectUris,
|
||||
bookingRedirectUri: data.bookingRedirectUri,
|
||||
bookingCancelRedirectUri: data.bookingCancelRedirectUri,
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
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-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 isPlatformUser={true} hideHeadingOnMobile withoutMain={false} SidebarContainer={<></>}>
|
||||
<NoPlatformPlan />
|
||||
</Shell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CreateOAuthClient.PageWrapper = PageWrapper;
|
||||
export default Page;
|
||||
|
||||
@@ -9,6 +9,8 @@ checkRoute () {
|
||||
checkRoute "$APP_ROUTER_EVENT_TYPES_ENABLED" app/future/event-types
|
||||
checkRoute "$APP_ROUTER_AVAILABILITY_ENABLED" app/future/availability
|
||||
checkRoute "$APP_ROUTER_SETTINGS_ADMIN_ENABLED" app/future/settings/admin
|
||||
checkRoute "$APP_ROUTER_SETTINGS_PLATFORM_ENABLED" app/future/settings/platform
|
||||
checkRoute "$APP_ROUTER_SETTINGS_ORG_ENABLED" app/future/settings/organizations
|
||||
checkRoute "$APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED" app/future/apps/installed
|
||||
checkRoute "$APP_ROUTER_APPS_SLUG_ENABLED" app/future/apps/\[slug\]
|
||||
checkRoute "$APP_ROUTER_APPS_SLUG_SETUP_ENABLED" app/future/apps/\[slug\]/setup
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import type { SessionContextValue } from "next-auth/react";
|
||||
import { signIn, useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import type { SessionContextValue } from "next-auth/react";
|
||||
import { useSession, signIn } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -236,6 +236,8 @@
|
||||
"APP_ROUTER_EVENT_TYPES_ENABLED",
|
||||
"APP_ROUTER_GETTING_STARTED_STEP_ENABLED",
|
||||
"APP_ROUTER_SETTINGS_ADMIN_ENABLED",
|
||||
"APP_ROUTER_SETTINGS_PLATFORM_ENABLED",
|
||||
"APP_ROUTER_SETTINGS_ORG_ENABLED",
|
||||
"APP_ROUTER_SETTINGS_TEAMS_ENABLED",
|
||||
"APP_ROUTER_WORKFLOWS_ENABLED",
|
||||
"APP_ROUTER_VIDEO_ENABLED",
|
||||
|
||||
Reference in New Issue
Block a user