feat: add organization-level autofill disable setting (#23504)
* feat: add organization-level autofill disable setting - Create DisableAutofillOnBookingPageSwitch component following existing patterns - Add toggle to organization general page alongside other settings - Update tRPC organizations update handler to support new field - Add organization-level check to useShouldBeDisabledDueToPrefill hook - Add translation keys for new autofill disable setting - Include database migration for disableAutofillOnBookingPage field - Maintain backward compatibility with individual field settings Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * feat: complete autofill disable implementation - Add disableAutofillOnBookingPage to orgSettings type definition - Update Prisma schema with new organization setting field - Clean up test file formatting Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: resolve tRPC mocking issues in tests and add missing disableAutofillOnBookingPage to organization repository - Fix tRPC module mocking in useShouldBeDisabledDueToPrefill tests - Add disableAutofillOnBookingPage to organization repository select and return statements - All form builder tests now pass (24/24) - Organization-level autofill disable tests working correctly Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * test: simplify autofill disable test to single focused test - Replace multiple tests with one test that verifies org setting blocks autocomplete - Test includes searchParams with prefill data to verify blocking behavior - Removes unnecessary test complexity as requested Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: add missing disableAutofillOnBookingPage to organizationSettings select statements - Add disableAutofillOnBookingPage to both parent and main organizationSettings select statements in getTeamWithMembers - Resolves TypeScript error in getServerSideProps.tsx where MinimumOrganizationSettings type requires this property - Ensures organization settings type compatibility across the codebase Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * Remove disableAutofillOnBookingPage setting Removed 'disableAutofillOnBookingPage' setting from organization configuration. * update * Remove duplicate settings in common.json Removed duplicate entries for automatic transcription and autofill settings. * Fix syntax error in common.json * update * add tests * Remove comments for autofill disabled check Removed comments explaining scenarios for autofill check. * addressed review * fix * change * Add handling for disableAutofillOnBookingPage input --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
anik@cal.com
Devin AI
parent
5cda123a4c
commit
a0eca13c18
@@ -1076,6 +1076,8 @@
|
||||
"warning_instant_meeting_experimental": "Experimental: Instant Meeting Events are currently experimental.",
|
||||
"starting": "Starting",
|
||||
"disable_guests": "Disable Guests",
|
||||
"disable_autofill_on_booking_page": "Disable autofill on booking pages",
|
||||
"disable_autofill_on_booking_page_description": "Prevent booking forms from being automatically filled with URL parameters or session-based prefill for all users in this organization",
|
||||
"disable_guests_description": "Disable adding additional guests while booking.",
|
||||
"private_link": "Generate private link",
|
||||
"enable_private_url": "Enable Private URL",
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { useInitialFormValues } from "./useInitialFormValues";
|
||||
|
||||
export interface IUseBookingForm {
|
||||
event?: Pick<BookerEvent, "bookingFields"> | null;
|
||||
event?: Pick<BookerEvent, "bookingFields" | "team" | "owner"> | null;
|
||||
sessionEmail?: string | null;
|
||||
sessionName?: string | null;
|
||||
sessionUsername?: string | null;
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* @vitest-environment jsdom
|
||||
*/
|
||||
import { renderHook, waitFor } from "@testing-library/react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
|
||||
import { useInitialFormValues } from "./useInitialFormValues";
|
||||
|
||||
vi.mock("@calcom/features/bookings/Booker/store", () => ({
|
||||
useBookerStore: vi.fn((selector) => {
|
||||
const state = {
|
||||
bookingData: null,
|
||||
formValues: {},
|
||||
};
|
||||
return selector(state);
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/features/bookings/lib/getBookingResponsesSchema", () => ({
|
||||
getBookingResponsesPartialSchema: vi.fn(() => ({
|
||||
parseAsync: vi.fn((data) => Promise.resolve(data)),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe("useInitialFormValues - Autofill Disable Feature", () => {
|
||||
const mockBookingFields = [
|
||||
{ name: "name", type: "text" as const, required: true },
|
||||
{ name: "email", type: "email" as const, required: true },
|
||||
{ name: "phone", type: "phone" as const, required: false },
|
||||
] as unknown as BookerEvent["bookingFields"];
|
||||
|
||||
const baseProps = {
|
||||
rescheduleUid: null,
|
||||
isRescheduling: false,
|
||||
email: null,
|
||||
name: null,
|
||||
username: null,
|
||||
hasSession: false,
|
||||
extraOptions: {},
|
||||
prefillFormParams: {
|
||||
guests: [],
|
||||
name: null,
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("when organization has NOT disabled autofill", () => {
|
||||
it("should use URL parameters to prefill form fields", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: {
|
||||
organizationSettings: {
|
||||
disableAutofillOnBookingPage: false,
|
||||
},
|
||||
},
|
||||
owner: null,
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+1234567890",
|
||||
customField: "custom value",
|
||||
};
|
||||
|
||||
const prefillFormParams = {
|
||||
guests: ["guest1@example.com", "guest2@example.com"],
|
||||
name: "John Doe",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
prefillFormParams,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses).toMatchObject({
|
||||
name: "John Doe",
|
||||
phone: "+1234567890",
|
||||
});
|
||||
});
|
||||
|
||||
it("should use URL parameters when organizationSettings is undefined", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: null,
|
||||
owner: null,
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+1234567890",
|
||||
};
|
||||
|
||||
const prefillFormParams = {
|
||||
guests: [],
|
||||
name: "Jane Smith",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
prefillFormParams,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses).toMatchObject({
|
||||
name: "Jane Smith",
|
||||
phone: "+1234567890",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when organization HAS disabled autofill", () => {
|
||||
it("should NOT use URL parameters when team.organizationSettings.disableAutofillOnBookingPage is true", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: {
|
||||
parent: {
|
||||
organizationSettings: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
owner: null,
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+1234567890",
|
||||
customField: "custom value",
|
||||
};
|
||||
|
||||
const prefillFormParams = {
|
||||
guests: ["guest1@example.com"],
|
||||
name: "John Doe",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
prefillFormParams,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses?.phone).toBeUndefined();
|
||||
expect(result.current.values.responses?.name).toBe("");
|
||||
});
|
||||
|
||||
it("should NOT use URL parameters when team.parent.organizationSettings.disableAutofillOnBookingPage is true", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: {
|
||||
organizationSettings: null,
|
||||
parent: {
|
||||
organizationSettings: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
owner: null,
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+9876543210",
|
||||
};
|
||||
|
||||
const prefillFormParams = {
|
||||
guests: [],
|
||||
name: "Parent Team User",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
prefillFormParams,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses?.phone).toBeUndefined();
|
||||
expect(result.current.values.responses?.name).toBe("");
|
||||
});
|
||||
|
||||
it("should NOT use URL parameters when owner.organization.organizationSettings.disableAutofillOnBookingPage is true", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: null,
|
||||
owner: {
|
||||
profile: {
|
||||
organization: {
|
||||
organizationSettings: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+5555555555",
|
||||
};
|
||||
|
||||
const prefillFormParams = {
|
||||
guests: [],
|
||||
name: "Personal Event User",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
prefillFormParams,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses?.phone).toBeUndefined();
|
||||
expect(result.current.values.responses?.name).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("session data handling with autofill disabled", () => {
|
||||
it("should not use session email/name when autofill is disabled", async () => {
|
||||
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
|
||||
bookingFields: mockBookingFields,
|
||||
team: {
|
||||
parent: {
|
||||
organizationSettings: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
owner: null,
|
||||
};
|
||||
|
||||
const extraOptions = {
|
||||
phone: "+1234567890", // This should be blocked
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useInitialFormValues({
|
||||
...baseProps,
|
||||
eventType,
|
||||
extraOptions,
|
||||
email: "session@example.com", // Session data
|
||||
name: "Session User", // Session data
|
||||
hasSession: true,
|
||||
})
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.values.responses).toBeDefined();
|
||||
});
|
||||
|
||||
expect(result.current.values.responses?.email).toBe("");
|
||||
expect(result.current.values.responses?.name).toBe("");
|
||||
expect(result.current.values.responses?.phone).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
export type useInitialFormValuesReturnType = ReturnType<typeof useInitialFormValues>;
|
||||
|
||||
type UseInitialFormValuesProps = {
|
||||
eventType?: Pick<BookerEvent, "bookingFields"> | null;
|
||||
eventType?: Pick<BookerEvent, "bookingFields" | "team" | "owner"> | null;
|
||||
rescheduleUid: string | null;
|
||||
isRescheduling: boolean;
|
||||
email?: string | null;
|
||||
@@ -78,6 +78,12 @@ export function useInitialFormValues({
|
||||
});
|
||||
const bookingData = useBookerStore((state) => state.bookingData);
|
||||
const formValues = useBookerStore((state) => state.formValues);
|
||||
|
||||
// Check if organization has disabled autofill from URL parameters
|
||||
const isAutofillDisabledByOrg =
|
||||
eventType?.team?.parent?.organizationSettings?.disableAutofillOnBookingPage ??
|
||||
eventType?.owner?.profile?.organization?.organizationSettings?.disableAutofillOnBookingPage ??
|
||||
false;
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
if (Object.keys(formValues).length) {
|
||||
@@ -96,28 +102,41 @@ export function useInitialFormValues({
|
||||
view: rescheduleUid ? "reschedule" : "booking",
|
||||
});
|
||||
|
||||
const parsedQuery = await querySchema.parseAsync({
|
||||
...extraOptions,
|
||||
name: prefillFormParams.name,
|
||||
// `guest` because we need to support legacy URL with `guest` query param support
|
||||
// `guests` because the `name` of the corresponding bookingField is `guests`
|
||||
guests: prefillFormParams.guests,
|
||||
});
|
||||
// If organization has disabled autofill, don't use URL parameters for prefill
|
||||
const urlParamsToUse = isAutofillDisabledByOrg
|
||||
? {}
|
||||
: {
|
||||
...extraOptions,
|
||||
name: prefillFormParams.name,
|
||||
// `guest` because we need to support legacy URL with `guest` query param support
|
||||
// `guests` because the `name` of the corresponding bookingField is `guests`
|
||||
guests: prefillFormParams.guests,
|
||||
};
|
||||
|
||||
const defaultUserValues = {
|
||||
email:
|
||||
const parsedQuery = await querySchema.parseAsync(urlParamsToUse);
|
||||
|
||||
const defaultUserValues = (() => {
|
||||
const rescheduledEmail =
|
||||
rescheduleUid && bookingData && bookingData.attendees.length > 0
|
||||
? bookingData?.attendees[0].email
|
||||
: !!parsedQuery["email"]
|
||||
? parsedQuery["email"]
|
||||
: email ?? "",
|
||||
name:
|
||||
? bookingData.attendees[0].email ?? ""
|
||||
: "";
|
||||
const rescheduledName =
|
||||
rescheduleUid && bookingData && bookingData.attendees.length > 0
|
||||
? bookingData?.attendees[0].name
|
||||
: !!parsedQuery["name"]
|
||||
? parsedQuery["name"]
|
||||
: name ?? username ?? "",
|
||||
};
|
||||
? bookingData.attendees[0].name ?? ""
|
||||
: "";
|
||||
|
||||
if (isAutofillDisabledByOrg) {
|
||||
return {
|
||||
email: rescheduledEmail,
|
||||
name: rescheduledName,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
email: rescheduledEmail || (parsedQuery["email"] ? parsedQuery["email"] : email ?? ""),
|
||||
name: rescheduledName || (parsedQuery["name"] ? parsedQuery["name"] : name ?? username ?? ""),
|
||||
};
|
||||
})();
|
||||
|
||||
if (clientId) {
|
||||
defaultUserValues.email = defaultUserValues.email.replace(`+${clientId}`, "");
|
||||
@@ -189,6 +208,7 @@ export function useInitialFormValues({
|
||||
prefillFormParams,
|
||||
// We need to have extraOptions as a dep so that any change in query params can update the form values, but extraOptions itself isn't stable and changes reference on every render
|
||||
stableHashExtraOptions,
|
||||
isAutofillDisabledByOrg,
|
||||
]);
|
||||
|
||||
return initialValuesState;
|
||||
|
||||
@@ -64,6 +64,8 @@ export type BookerEvent = Pick<
|
||||
| "disableCancelling"
|
||||
| "disableRescheduling"
|
||||
| "interfaceLanguage"
|
||||
| "team"
|
||||
| "owner"
|
||||
> & {
|
||||
subsetOfUsers: BookerEventUser[];
|
||||
showInstantEventConnectNowModal: boolean;
|
||||
|
||||
@@ -2,7 +2,10 @@ import type { OrganizationSettings } from "@calcom/prisma/client";
|
||||
|
||||
type MinimumOrganizationSettings = Pick<
|
||||
OrganizationSettings,
|
||||
"orgAutoAcceptEmail" | "orgProfileRedirectsToVerifiedDomain" | "allowSEOIndexing"
|
||||
| "orgAutoAcceptEmail"
|
||||
| "orgProfileRedirectsToVerifiedDomain"
|
||||
| "allowSEOIndexing"
|
||||
| "disableAutofillOnBookingPage"
|
||||
>;
|
||||
|
||||
type SEOOrganizationSettings = Pick<OrganizationSettings, "allowSEOIndexing">;
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
import { SettingsToggle } from "@calcom/ui/components/form";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
|
||||
interface GeneralViewProps {
|
||||
currentOrg: RouterOutputs["viewer"]["organizations"]["listCurrent"];
|
||||
}
|
||||
|
||||
export const DisableAutofillOnBookingPageSwitch = ({ currentOrg }: GeneralViewProps) => {
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useUtils();
|
||||
const [disableAutofillOnBookingPageActive, setDisableAutofillOnBookingPageActive] = useState(
|
||||
!!currentOrg.organizationSettings?.disableAutofillOnBookingPage
|
||||
);
|
||||
|
||||
const mutation = trpc.viewer.organizations.update.useMutation({
|
||||
onSuccess: async (_data, variables) => {
|
||||
setDisableAutofillOnBookingPageActive(!!variables.disableAutofillOnBookingPage);
|
||||
showToast(t("settings_updated_successfully"), "success");
|
||||
},
|
||||
onError: () => {
|
||||
showToast(t("error_updating_settings"), "error");
|
||||
},
|
||||
onSettled: () => {
|
||||
utils.viewer.organizations.listCurrent.invalidate();
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsToggle
|
||||
toggleSwitchAtTheEnd={true}
|
||||
title={t("disable_autofill_on_booking_page")}
|
||||
disabled={mutation?.isPending}
|
||||
description={t("disable_autofill_on_booking_page_description")}
|
||||
checked={disableAutofillOnBookingPageActive}
|
||||
onCheckedChange={(checked) => {
|
||||
mutation.mutate({
|
||||
disableAutofillOnBookingPage: checked,
|
||||
});
|
||||
}}
|
||||
switchContainerClassName="mt-6"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -20,6 +20,7 @@ import { Select } from "@calcom/ui/components/form";
|
||||
import { SkeletonButton, SkeletonContainer, SkeletonText } from "@calcom/ui/components/skeleton";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
|
||||
import { DisableAutofillOnBookingPageSwitch } from "../components/DisableAutofillOnBookingPageSwitch";
|
||||
import { DisablePhoneOnlySMSNotificationsSwitch } from "../components/DisablePhoneOnlySMSNotificationsSwitch";
|
||||
import { LockEventTypeSwitch } from "../components/LockEventTypeSwitch";
|
||||
import { NoSlotsNotificationSwitch } from "../components/NoSlotsNotificationSwitch";
|
||||
@@ -94,6 +95,7 @@ const OrgGeneralView = ({
|
||||
<LockEventTypeSwitch currentOrg={currentOrg} />
|
||||
<NoSlotsNotificationSwitch currentOrg={currentOrg} />
|
||||
<DisablePhoneOnlySMSNotificationsSwitch currentOrg={currentOrg} />
|
||||
<DisableAutofillOnBookingPageSwitch currentOrg={currentOrg} />
|
||||
</>
|
||||
)}
|
||||
</LicenseRequired>
|
||||
|
||||
@@ -287,6 +287,7 @@ export class OrganizationRepository {
|
||||
orgProfileRedirectsToVerifiedDomain: true,
|
||||
orgAutoAcceptEmail: true,
|
||||
disablePhoneOnlySMSNotifications: true,
|
||||
disableAutofillOnBookingPage: true,
|
||||
orgAutoJoinOnSignup: true,
|
||||
},
|
||||
});
|
||||
@@ -306,6 +307,7 @@ export class OrganizationRepository {
|
||||
orgProfileRedirectsToVerifiedDomain: organizationSettings?.orgProfileRedirectsToVerifiedDomain,
|
||||
orgAutoAcceptEmail: organizationSettings?.orgAutoAcceptEmail,
|
||||
disablePhoneOnlySMSNotifications: organizationSettings?.disablePhoneOnlySMSNotifications,
|
||||
disableAutofillOnBookingPage: organizationSettings?.disableAutofillOnBookingPage,
|
||||
orgAutoJoinOnSignup: organizationSettings?.orgAutoJoinOnSignup,
|
||||
},
|
||||
user: {
|
||||
|
||||
@@ -111,6 +111,7 @@ export async function getTeamWithMembers(args: {
|
||||
allowSEOIndexing: true,
|
||||
orgProfileRedirectsToVerifiedDomain: true,
|
||||
orgAutoAcceptEmail: true,
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -175,6 +176,7 @@ export async function getTeamWithMembers(args: {
|
||||
allowSEOIndexing: true,
|
||||
orgProfileRedirectsToVerifiedDomain: true,
|
||||
orgAutoAcceptEmail: true,
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -44,6 +44,11 @@ const userSelect = {
|
||||
name: true,
|
||||
slug: true,
|
||||
bannerUrl: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultScheduleId: true,
|
||||
@@ -105,9 +110,19 @@ export const getPublicEventSelect = (fetchAllUsers: boolean) => {
|
||||
name: true,
|
||||
bannerUrl: true,
|
||||
logoUrl: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
isPrivate: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
disableAutofillOnBookingPage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
successRedirectUrl: true,
|
||||
|
||||
@@ -40,6 +40,7 @@ const log = logger.getSubLogger({ prefix: ["repository/profile"] });
|
||||
const organizationSettingsSelect = {
|
||||
allowSEOIndexing: true,
|
||||
orgProfileRedirectsToVerifiedDomain: true,
|
||||
disableAutofillOnBookingPage: true,
|
||||
} satisfies Prisma.OrganizationSettingsSelect;
|
||||
const organizationSelect = {
|
||||
id: true,
|
||||
@@ -71,7 +72,6 @@ const profileSelect = {
|
||||
updatedAt: true,
|
||||
};
|
||||
|
||||
|
||||
export enum LookupTarget {
|
||||
User,
|
||||
Profile,
|
||||
@@ -583,7 +583,7 @@ export class ProfileRepository {
|
||||
},
|
||||
include: {
|
||||
organization: {
|
||||
select: organizationSelect,
|
||||
select: organizationWithSettingsSelect,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -615,7 +615,7 @@ export class ProfileRepository {
|
||||
},
|
||||
include: {
|
||||
organization: {
|
||||
select: organizationSelect,
|
||||
select: organizationWithSettingsSelect,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "OrganizationSettings" ADD COLUMN "disableAutofillOnBookingPage" BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -686,6 +686,7 @@ model OrganizationSettings {
|
||||
allowSEOIndexing Boolean @default(false)
|
||||
orgProfileRedirectsToVerifiedDomain Boolean @default(false)
|
||||
disablePhoneOnlySMSNotifications Boolean @default(false)
|
||||
disableAutofillOnBookingPage Boolean @default(false)
|
||||
orgAutoJoinOnSignup Boolean @default(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,10 @@ const updateOrganizationSettings = async ({
|
||||
data.disablePhoneOnlySMSNotifications = input.disablePhoneOnlySMSNotifications;
|
||||
}
|
||||
|
||||
if (input.hasOwnProperty("disableAutofillOnBookingPage")) {
|
||||
data.disableAutofillOnBookingPage = input.disableAutofillOnBookingPage;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (input.hasOwnProperty("orgAutoJoinOnSignup")) {
|
||||
data.orgAutoJoinOnSignup = input.orgAutoJoinOnSignup;
|
||||
|
||||
@@ -35,6 +35,7 @@ export const ZUpdateInputSchema = z.object({
|
||||
allowSEOIndexing: z.boolean().optional(),
|
||||
orgProfileRedirectsToVerifiedDomain: z.boolean().optional(),
|
||||
disablePhoneOnlySMSNotifications: z.boolean().optional(),
|
||||
disableAutofillOnBookingPage: z.boolean().optional(),
|
||||
orgAutoJoinOnSignup: z.boolean().optional(),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user