Compare commits

...

9 Commits

Author SHA1 Message Date
Udit Takkar 6e43291350 test: display public location 2023-10-26 17:02:42 +05:30
Udit Takkar 42060b1202 test: add e2e test 2023-10-26 16:13:42 +05:30
Udit Takkar 82c5f6f22c fix: add location publicly 2023-10-26 15:22:48 +05:30
Udit Takkar 52b3120fd9 fix: move logic to BookingFields 2023-10-26 14:45:18 +05:30
Hariom Balhara 38638f99f3
Merge branch 'main' into fix/organizer-location 2023-10-26 08:29:54 +05:30
Udit Takkar c040851f9f chore: import type 2023-10-26 01:29:39 +05:30
Udit Takkar a7b01a3e0d fix: multiple options input 2023-10-26 01:26:45 +05:30
Udit Takkar cc19baa38d test: add e2e test 2023-10-26 01:18:04 +05:30
Udit Takkar 3e4afd6c61 fix: display organizer location after booking 2023-10-26 01:03:59 +05:30
4 changed files with 129 additions and 16 deletions

View File

@ -8,7 +8,7 @@ import { Controller, useFormContext, useFieldArray } from "react-hook-form";
import type { MultiValue } from "react-select"; import type { MultiValue } from "react-select";
import type { EventLocationType } from "@calcom/app-store/locations"; import type { EventLocationType } from "@calcom/app-store/locations";
import { getEventLocationType, LocationType, MeetLocationType } from "@calcom/app-store/locations"; import { getEventLocationType, MeetLocationType } from "@calcom/app-store/locations";
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager"; import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { CAL_URL } from "@calcom/lib/constants"; import { CAL_URL } from "@calcom/lib/constants";
@ -256,21 +256,22 @@ export const EventSetupTab = (
const [showEmptyLocationSelect, setShowEmptyLocationSelect] = useState(false); const [showEmptyLocationSelect, setShowEmptyLocationSelect] = useState(false);
const [selectedNewOption, setSelectedNewOption] = useState<SingleValueLocationOption | null>(null); const [selectedNewOption, setSelectedNewOption] = useState<SingleValueLocationOption | null>(null);
return ( return (
<div className="w-full"> <div className="w-full">
<ul ref={animationRef} className="space-y-2"> <ul ref={animationRef} className="space-y-2">
{locationFields.map((field, index) => { {locationFields.map((field, index) => {
const eventLocationType = getEventLocationType(field.type); const eventLocationType = getEventLocationType(field.type);
const defaultLocation = formMethods const defaultLocation = formMethods.getValues("locations")?.find((location) => {
.getValues("locations") if (eventLocationType?.organizerInputType) {
?.find((location: { type: EventLocationType["type"]; address?: string }) => { return (
if (location.type === LocationType.InPerson) { location.type === eventLocationType?.type &&
return location.type === eventLocationType?.type && location.address === field?.address; location[eventLocationType.defaultValueVariable] ===
} else { field?.[eventLocationType.defaultValueVariable]
return location.type === eventLocationType?.type; );
} } else {
}); return location.type === eventLocationType?.type;
}
});
const option = getLocationFromType(field.type, locationOptions); const option = getLocationFromType(field.type, locationOptions);
@ -338,6 +339,7 @@ export const EventSetupTab = (
</div> </div>
<div className="ml-6"> <div className="ml-6">
<CheckboxField <CheckboxField
name={`locations[${index}].displayLocationPublicly`}
data-testid="display-location" data-testid="display-location"
defaultChecked={defaultLocation?.displayLocationPublicly} defaultChecked={defaultLocation?.displayLocationPublicly}
description={t("display_location_label")} description={t("display_location_label")}

View File

@ -254,6 +254,87 @@ test.describe("Event Types tests", () => {
await expect(page.locator("[data-testid=success-page]")).toBeVisible(); await expect(page.locator("[data-testid=success-page]")).toBeVisible();
await expect(page.locator("[data-testid=where]")).toHaveText(/Cal Video/); await expect(page.locator("[data-testid=where]")).toHaveText(/Cal Video/);
}); });
test("can add single organizer address location without display location public option", async ({
page,
}) => {
const $eventTypes = page.locator("[data-testid=event-types] > li a");
const firstEventTypeElement = $eventTypes.first();
await firstEventTypeElement.click();
await page.waitForURL((url) => {
return !!url.pathname.match(/\/event-types\/.+/);
});
const locationAddress = "New Delhi";
await fillLocation(page, locationAddress, 0, false);
await page.locator("[data-testid=update-eventtype]").click();
await page.goto("/event-types");
const previewLink = await page
.locator("[data-testid=preview-link-button]")
.first()
.getAttribute("href");
await page.goto(previewLink ?? "");
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
await expect(page.locator(`[data-testid="where"]`)).toHaveText(locationAddress);
});
test("can select 'display on booking page' option when multiple organizer input type are present", async ({
page,
}) => {
await gotoFirstEventType(page);
await page.locator("#location-select").click();
await page.locator(`text="Link meeting"`).click();
const locationInputName = (idx: number) => `locations[${idx}].link`;
const testUrl1 = "https://cal.ai/";
await page.locator(`input[name="${locationInputName(0)}"]`).fill(testUrl1);
await page.locator("[data-testid=display-location]").last().check();
await checkDisplayLocation(page);
await unCheckDisplayLocation(page);
await page.locator("[data-testid=add-location]").click();
const testUrl2 = "https://cal.com/ai";
await page.locator(`text="Link meeting"`).last().click();
await page.locator(`input[name="${locationInputName(1)}"]`).waitFor();
await page.locator(`input[name="${locationInputName(1)}"]`).fill(testUrl2);
await checkDisplayLocation(page);
await unCheckDisplayLocation(page);
// Remove Both of the locations
const removeButtomId = "delete-locations.0.type";
await page.getByTestId(removeButtomId).click();
await page.getByTestId(removeButtomId).click();
// Add Multiple Organizer Phone Number options
await page.locator("#location-select").click();
await page.locator(`text="Organizer Phone Number"`).click();
const organizerPhoneNumberInputName = (idx: number) => `locations[${idx}].hostPhoneNumber`;
const testPhoneInputValue1 = "9199999999";
await page.locator(`input[name="${organizerPhoneNumberInputName(0)}"]`).waitFor();
await page.locator(`input[name="${organizerPhoneNumberInputName(0)}"]`).fill(testPhoneInputValue1);
await page.locator("[data-testid=display-location]").last().check();
await checkDisplayLocation(page);
await unCheckDisplayLocation(page);
await page.locator("[data-testid=add-location]").click();
const testPhoneInputValue2 = "9188888888";
await page.locator(`text="Organizer Phone Number"`).last().click();
await page.locator(`input[name="${organizerPhoneNumberInputName(1)}"]`).waitFor();
await page.locator(`input[name="${organizerPhoneNumberInputName(1)}"]`).fill(testPhoneInputValue2);
await checkDisplayLocation(page);
await unCheckDisplayLocation(page);
});
}); });
}); });
}); });
@ -293,7 +374,7 @@ async function addAnotherLocation(page: Page, locationOptionText: string) {
await page.locator(`text="${locationOptionText}"`).click(); await page.locator(`text="${locationOptionText}"`).click();
} }
const fillLocation = async (page: Page, inputText: string, index: number) => { const fillLocation = async (page: Page, inputText: string, index: number, selectDisplayLocation = true) => {
// Except the first location, dropdown automatically opens when adding another location // Except the first location, dropdown automatically opens when adding another location
if (index == 0) { if (index == 0) {
await page.locator("#location-select").last().click(); await page.locator("#location-select").last().click();
@ -303,5 +384,17 @@ const fillLocation = async (page: Page, inputText: string, index: number) => {
const locationInputName = `locations[${index}].address`; const locationInputName = `locations[${index}].address`;
await page.locator(`input[name="${locationInputName}"]`).waitFor(); await page.locator(`input[name="${locationInputName}"]`).waitFor();
await page.locator(`input[name="locations[${index}].address"]`).fill(inputText); await page.locator(`input[name="locations[${index}].address"]`).fill(inputText);
await page.locator("[data-testid=display-location]").last().check(); if (selectDisplayLocation) {
await page.locator("[data-testid=display-location]").last().check();
}
};
const checkDisplayLocation = async (page: Page) => {
await page.locator("[data-testid=display-location]").last().check();
await expect(page.locator("[data-testid=display-location]").last()).toBeChecked();
};
const unCheckDisplayLocation = async (page: Page) => {
await page.locator("[data-testid=display-location]").last().uncheck();
await expect(page.locator("[data-testid=display-location]").last()).toBeChecked({ checked: false });
}; };

View File

@ -1,6 +1,7 @@
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import type { LocationObject } from "@calcom/app-store/locations"; import type { LocationObject } from "@calcom/app-store/locations";
import { DefaultEventLocationTypeEnum } from "@calcom/app-store/locations";
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
import getLocationOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect"; import getLocationOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect";
import { FormBuilderField } from "@calcom/features/form-builder/FormBuilderField"; import { FormBuilderField } from "@calcom/features/form-builder/FormBuilderField";
@ -105,6 +106,24 @@ export const BookingFields = ({
); );
} }
if (field?.options) {
const moreThanOneInPersonOptions = !!(
field.options.filter((field) => {
return field.value === DefaultEventLocationTypeEnum.InPerson;
}).length > 1
);
field.options = field.options.map((field) => {
return {
...field,
value:
field.value === DefaultEventLocationTypeEnum.InPerson && moreThanOneInPersonOptions
? field.label
: field.value,
};
});
}
return ( return (
<FormBuilderField className="mb-4" field={{ ...field, hidden }} readOnly={readOnly} key={index} /> <FormBuilderField className="mb-4" field={{ ...field, hidden }} readOnly={readOnly} key={index} />
); );

View File

@ -311,9 +311,8 @@ export const ComponentForField = ({
if (!field.optionsInputs) { if (!field.optionsInputs) {
throw new Error("Field optionsInputs is not defined"); throw new Error("Field optionsInputs is not defined");
} }
const options = field.options.map((field) => {
return { ...field, value: field.value === "inPerson" ? field.label : field.value }; const options = field.options;
});
return field.options.length ? ( return field.options.length ? (
<WithLabel field={field} readOnly={readOnly}> <WithLabel field={field} readOnly={readOnly}>