fix: enable event-type booking field url with api v2 (#19577)
Post release / release (push) Canceled after 0s

* fix: enable event-type booking field url with api v2

* fixup! fix: enable event-type booking field url with api v2

* fixup! fixup! fix: enable event-type booking field url with api v2

* fixup! fixup! fixup! fix: enable event-type booking field url with api v2
This commit is contained in:
Morgan authored and GitHub committed 2025-02-26 19:12:41 +00:00
1 parent 6b7ced262d
commit af524d9e93
11 files changed
+425 -29

No files matched your search

+1 -1
View File
@@ -30,7 +30,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.110",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.116",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -309,6 +309,23 @@ describe("Bookings Endpoints 2024-08-13", () => {
placeholder: "matrix",
disableOnPrefill: false,
},
{
name: "video-url",
type: "url",
label: "video url",
sources: [
{
id: "user",
type: "user",
label: "User",
fieldRequired: true,
},
],
editable: "user",
required: false,
placeholder: "add video url",
disableOnPrefill: false,
},
],
},
user.id
@@ -499,6 +516,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
location: "https://meet.google.com/abc-def-ghi",
bookingFieldsResponses: {
"favorite-movie": "lord of the rings",
"video-url": "http://video-url.com",
},
};
return request(app.getHttpServer())
@@ -515,6 +533,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
if (responseDataIsBooking(responseBody.data)) {
const data: BookingOutput_2024_08_13 = responseBody.data;
expect(data.bookingFieldsResponses["favorite-movie"]).toEqual("lord of the rings");
expect(data.bookingFieldsResponses["video-url"]).toEqual("http://video-url.com");
} else {
throw new Error(
"Invalid response data - expected booking but received array of possibily recurring bookings"
@@ -377,6 +377,15 @@ describe("Event types Endpoints", () => {
disableOnPrefill: true,
hidden: false,
},
{
type: "url",
label: "Video Url",
slug: "video-url",
required: true,
placeholder: "add video url",
disableOnPrefill: true,
hidden: false,
},
],
scheduleId: firstSchedule.id,
bookingLimitsCount: {
@@ -478,6 +487,16 @@ describe("Event types Endpoints", () => {
hidden: false,
isDefault: false,
},
{
type: "url",
label: "Video Url",
slug: "video-url",
required: true,
placeholder: "add video url",
disableOnPrefill: true,
hidden: false,
isDefault: false,
},
{ ...defaultResponseBookingFieldTitle },
{ ...defaultResponseBookingFieldNotes },
{ ...defaultResponseBookingFieldGuests },
+144 -13
View File
@@ -8494,6 +8494,48 @@
"hidden"
]
},
"UrlFieldInput_2024_06_14": {
"type": "object",
"properties": {
"type": {
"type": "string",
"example": "url",
"description": "only allowed value for type is `url`"
},
"slug": {
"type": "string",
"description": "Unique identifier for the field in format `some-slug`. It is used to access response to this booking field during the booking",
"example": "some-slug"
},
"label": {
"type": "string",
"example": "Please enter your text"
},
"required": {
"type": "boolean"
},
"placeholder": {
"type": "string",
"example": "e.g., Enter url here"
},
"disableOnPrefill": {
"type": "boolean",
"description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `video-url` and the URL contains query parameter `&video-url=https://youtube.com/abc`the url field will be prefilled with this value and disabled."
},
"hidden": {
"type": "boolean",
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
}
},
"required": [
"type",
"slug",
"label",
"required",
"placeholder",
"hidden"
]
},
"BusinessDaysWindow_2024_06_14": {
"type": "object",
"properties": {
@@ -9132,6 +9174,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldInput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldInput_2024_06_14"
}
]
}
@@ -9519,7 +9564,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "email",
"description": "only allowed value for type is `email`",
@@ -9575,7 +9621,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "name",
"description": "only allowed value for type is `name`. Used for having 1 booking field for both first name and last name.",
@@ -9864,7 +9911,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "address",
"description": "only allowed value for type is `address`"
@@ -9927,7 +9975,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "boolean",
"description": "only allowed value for type is `boolean`"
@@ -9985,7 +10034,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "checkbox",
"description": "only allowed value for type is `checkbox`"
@@ -10055,7 +10105,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "multiemail",
"description": "only allowed value for type is `multiemail`"
@@ -10118,7 +10169,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "multiselect",
"description": "only allowed value for type is `multiselect`"
@@ -10170,6 +10222,70 @@
"isDefault"
]
},
"UrlFieldOutput_2024_06_14": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"name",
"email",
"phone",
"address",
"text",
"number",
"textarea",
"select",
"multiselect",
"multiemail",
"checkbox",
"radio",
"boolean",
"url"
],
"example": "url",
"description": "only allowed value for type is `url`"
},
"slug": {
"type": "string",
"description": "Unique identifier for the field in format `some-slug`. It is used to access response to this booking field during the booking",
"example": "some-slug"
},
"label": {
"type": "string",
"example": "Please enter your text"
},
"required": {
"type": "boolean"
},
"placeholder": {
"type": "string",
"example": "e.g., Enter url here"
},
"disableOnPrefill": {
"type": "boolean",
"description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `video-url` and the URL contains query parameter `&video-url=https://youtube.com/abc`the url field will be prefilled with this value and disabled."
},
"hidden": {
"type": "boolean",
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
},
"isDefault": {
"type": "object",
"default": false,
"description": "This property is always false because it's not default field but custom field",
"example": false
}
},
"required": [
"type",
"slug",
"label",
"required",
"hidden",
"isDefault"
]
},
"NumberFieldOutput_2024_06_14": {
"type": "object",
"properties": {
@@ -10188,7 +10304,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "number",
"description": "only allowed value for type is `number`"
@@ -10251,7 +10368,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "phone",
"description": "only allowed value for type is `phone`"
@@ -10312,7 +10430,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "radio",
"description": "only allowed value for type is `radio`"
@@ -10382,7 +10501,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "select",
"description": "only allowed value for type is `select`"
@@ -10456,7 +10576,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "textarea",
"description": "only allowed value for type is `textarea`"
@@ -10519,7 +10640,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "text",
"description": "only allowed value for type is `text`"
@@ -10681,6 +10803,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldOutput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldOutput_2024_06_14"
}
]
}
@@ -12609,6 +12734,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldInput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldInput_2024_06_14"
}
]
}
@@ -13000,6 +13128,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldOutput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldOutput_2024_06_14"
}
]
}
+130 -13
View File
@@ -7893,6 +7893,41 @@
},
"required": ["type", "slug", "label", "required", "hidden"]
},
"UrlFieldInput_2024_06_14": {
"type": "object",
"properties": {
"type": {
"type": "string",
"example": "url",
"description": "only allowed value for type is `url`"
},
"slug": {
"type": "string",
"description": "Unique identifier for the field in format `some-slug`. It is used to access response to this booking field during the booking",
"example": "some-slug"
},
"label": {
"type": "string",
"example": "Please enter your text"
},
"required": {
"type": "boolean"
},
"placeholder": {
"type": "string",
"example": "e.g., Enter url here"
},
"disableOnPrefill": {
"type": "boolean",
"description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `video-url` and the URL contains query parameter `&video-url=https://youtube.com/abc`the url field will be prefilled with this value and disabled."
},
"hidden": {
"type": "boolean",
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
}
},
"required": ["type", "slug", "label", "required", "placeholder", "hidden"]
},
"BusinessDaysWindow_2024_06_14": {
"type": "object",
"properties": {
@@ -8444,6 +8479,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldInput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldInput_2024_06_14"
}
]
}
@@ -8807,7 +8845,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "email",
"description": "only allowed value for type is `email`",
@@ -8858,7 +8897,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "name",
"description": "only allowed value for type is `name`. Used for having 1 booking field for both first name and last name.",
@@ -9096,7 +9136,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "address",
"description": "only allowed value for type is `address`"
@@ -9152,7 +9193,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "boolean",
"description": "only allowed value for type is `boolean`"
@@ -9203,7 +9245,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "checkbox",
"description": "only allowed value for type is `checkbox`"
@@ -9262,7 +9305,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "multiemail",
"description": "only allowed value for type is `multiemail`"
@@ -9318,7 +9362,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "multiselect",
"description": "only allowed value for type is `multiselect`"
@@ -9359,6 +9404,63 @@
},
"required": ["type", "slug", "label", "required", "options", "hidden", "isDefault"]
},
"UrlFieldOutput_2024_06_14": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"name",
"email",
"phone",
"address",
"text",
"number",
"textarea",
"select",
"multiselect",
"multiemail",
"checkbox",
"radio",
"boolean",
"url"
],
"example": "url",
"description": "only allowed value for type is `url`"
},
"slug": {
"type": "string",
"description": "Unique identifier for the field in format `some-slug`. It is used to access response to this booking field during the booking",
"example": "some-slug"
},
"label": {
"type": "string",
"example": "Please enter your text"
},
"required": {
"type": "boolean"
},
"placeholder": {
"type": "string",
"example": "e.g., Enter url here"
},
"disableOnPrefill": {
"type": "boolean",
"description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `video-url` and the URL contains query parameter `&video-url=https://youtube.com/abc`the url field will be prefilled with this value and disabled."
},
"hidden": {
"type": "boolean",
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
},
"isDefault": {
"type": "object",
"default": false,
"description": "This property is always false because it's not default field but custom field",
"example": false
}
},
"required": ["type", "slug", "label", "required", "hidden", "isDefault"]
},
"NumberFieldOutput_2024_06_14": {
"type": "object",
"properties": {
@@ -9377,7 +9479,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "number",
"description": "only allowed value for type is `number`"
@@ -9433,7 +9536,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "phone",
"description": "only allowed value for type is `phone`"
@@ -9487,7 +9591,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "radio",
"description": "only allowed value for type is `radio`"
@@ -9546,7 +9651,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "select",
"description": "only allowed value for type is `select`"
@@ -9609,7 +9715,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "textarea",
"description": "only allowed value for type is `textarea`"
@@ -9665,7 +9772,8 @@
"multiemail",
"checkbox",
"radio",
"boolean"
"boolean",
"url"
],
"example": "text",
"description": "only allowed value for type is `text`"
@@ -9816,6 +9924,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldOutput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldOutput_2024_06_14"
}
]
}
@@ -11490,6 +11601,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldInput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldInput_2024_06_14"
}
]
}
@@ -11854,6 +11968,9 @@
},
{
"$ref": "#/components/schemas/BooleanFieldOutput_2024_06_14"
},
{
"$ref": "#/components/schemas/UrlFieldOutput_2024_06_14"
}
]
}
@@ -215,6 +215,28 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
};
}
if (field.type === "url") {
return {
name: field.slug,
type: field.type,
label: field.label,
placeholder: "placeholder" in field ? field.placeholder : "",
labelAsSafeHtml: `<p>${field.label}</p>\n`,
sources: [
{
id: "user",
type: "user",
label: "User",
fieldRequired: true,
},
],
editable: "user",
required: !!field.required,
disableOnPrefill: !!field.disableOnPrefill,
hidden: !!field.hidden,
};
}
return {
name: field.slug,
type: field.type,
@@ -23,6 +23,7 @@ import type {
SelectFieldOutput_2024_06_14,
TextAreaFieldOutput_2024_06_14,
TextFieldOutput_2024_06_14,
UrlFieldOutput_2024_06_14,
} from "@calcom/platform-types";
export function transformBookingFieldsInternalToApi(
@@ -266,6 +267,17 @@ export function transformBookingFieldsInternalToApi(
disableOnPrefill: !!field.disableOnPrefill,
hidden: !!field.hidden,
} satisfies RadioGroupFieldOutput_2024_06_14;
case "url":
return {
isDefault: false,
type: field.type,
slug: field.name,
label: field.label || "",
required: !!field.required,
placeholder: field.placeholder,
disableOnPrefill: !!field.disableOnPrefill,
hidden: !!field.hidden,
} satisfies UrlFieldOutput_2024_06_14;
default:
return {
type: "unknown",
@@ -290,6 +302,7 @@ const CustomFieldTypeEnum = z.enum([
"checkbox",
"radio",
"radioInput",
"url",
]);
const CustomFieldsSchema = z.object({
@@ -19,6 +19,7 @@ const inputBookingFieldTypes = [
"checkbox",
"radio",
"boolean",
"url",
] as const;
const inputBookingFieldSlugs = ["name", "email", "title", "notes", "guests"] as const;
@@ -438,6 +439,52 @@ export class TextFieldInput_2024_06_14 {
hidden?: boolean;
}
export class UrlFieldInput_2024_06_14 {
@IsIn(inputBookingFieldTypes)
@DocsProperty({ example: "url", description: "only allowed value for type is `url`" })
type!: "url";
@IsString()
@DocsProperty({
description:
"Unique identifier for the field in format `some-slug`. It is used to access response to this booking field during the booking",
example: "some-slug",
})
slug!: string;
@IsString()
@DocsProperty({ example: "Please enter your text" })
label!: string;
@IsBoolean()
@DocsProperty()
required!: boolean;
@IsString()
@DocsProperty({ example: "e.g., Enter url here" })
@IsOptional()
@DocsProperty()
placeholder?: string;
@IsBoolean()
@IsOptional()
@DocsPropertyOptional({
type: Boolean,
description:
"Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value.\
For example, if the slug is `video-url` and the URL contains query parameter `&video-url=https://youtube.com/abc`the url field will be prefilled with this value and disabled.",
})
disableOnPrefill?: boolean;
@IsBoolean()
@IsOptional()
@DocsProperty({
description:
"If true show under event type settings but don't show this booking field in the Booker. If false show in both.",
})
hidden?: boolean;
}
export class NumberFieldInput_2024_06_14 {
@IsIn(inputBookingFieldTypes)
@DocsProperty({ example: "number", description: "only allowed value for type is `number`" })
@@ -821,7 +868,8 @@ export type InputBookingField_2024_06_14 =
| MultiEmailFieldInput_2024_06_14
| CheckboxGroupFieldInput_2024_06_14
| RadioGroupFieldInput_2024_06_14
| BooleanFieldInput_2024_06_14;
| BooleanFieldInput_2024_06_14
| UrlFieldInput_2024_06_14;
@ValidatorConstraint({ async: true })
class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterface {
@@ -844,6 +892,7 @@ class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterf
checkbox: CheckboxGroupFieldInput_2024_06_14,
radio: RadioGroupFieldInput_2024_06_14,
boolean: BooleanFieldInput_2024_06_14,
url: UrlFieldInput_2024_06_14,
};
async validate(bookingFields: { type: string; slug: string }[]) {
@@ -40,6 +40,7 @@ import {
TextAreaFieldInput_2024_06_14,
TextFieldInput_2024_06_14,
TitleDefaultFieldInput_2024_06_14,
UrlFieldInput_2024_06_14,
} from "./booking-fields.input";
import type { InputBookingField_2024_06_14 } from "./booking-fields.input";
import { ValidateInputBookingFields_2024_06_14 } from "./booking-fields.input";
@@ -98,6 +99,7 @@ export const CREATE_EVENT_SLUG_EXAMPLE = "learn-the-secrets-of-masterchief";
CheckboxGroupFieldInput_2024_06_14,
RadioGroupFieldInput_2024_06_14,
BooleanFieldInput_2024_06_14,
UrlFieldInput_2024_06_14,
BusinessDaysWindow_2024_06_14,
CalendarDaysWindow_2024_06_14,
RangeWindow_2024_06_14,
@@ -191,6 +193,7 @@ export class CreateEventTypeInput_2024_06_14 {
{ $ref: getSchemaPath(CheckboxGroupFieldInput_2024_06_14) },
{ $ref: getSchemaPath(RadioGroupFieldInput_2024_06_14) },
{ $ref: getSchemaPath(BooleanFieldInput_2024_06_14) },
{ $ref: getSchemaPath(UrlFieldInput_2024_06_14) },
],
type: "array",
})
@@ -24,6 +24,7 @@ import {
RescheduleReasonDefaultFieldInput_2024_06_14,
TitleDefaultFieldInput_2024_06_14,
SplitNameDefaultFieldInput_2024_06_14,
UrlFieldInput_2024_06_14,
} from "../inputs";
export class NameDefaultFieldOutput_2024_06_14 extends NameDefaultFieldInput_2024_06_14 {
@@ -451,6 +452,23 @@ export class TextFieldOutput_2024_06_14 extends TextFieldInput_2024_06_14 {
hidden!: boolean;
}
export class UrlFieldOutput_2024_06_14 extends UrlFieldInput_2024_06_14 {
@IsBoolean()
@DocsProperty({
description: "This property is always false because it's not default field but custom field",
example: false,
default: false,
})
isDefault = false;
@IsBoolean()
@DocsProperty({
description:
"If true show under event type settings but don't show this booking field in the Booker. If false show in both.",
})
hidden!: boolean;
}
export class NumberFieldOutput_2024_06_14 extends NumberFieldInput_2024_06_14 {
@IsBoolean()
@DocsProperty({
@@ -620,7 +638,8 @@ export type CustomFieldOutput_2024_06_14 =
| MultiEmailFieldOutput_2024_06_14
| CheckboxGroupFieldOutput_2024_06_14
| RadioGroupFieldOutput_2024_06_14
| BooleanFieldOutput_2024_06_14;
| BooleanFieldOutput_2024_06_14
| UrlFieldOutput_2024_06_14;
export type KnownBookingField_2024_06_14 = DefaultFieldOutput_2024_06_14 | CustomFieldOutput_2024_06_14;
@@ -657,6 +676,7 @@ class OutputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInter
checkbox: CheckboxGroupFieldOutput_2024_06_14,
radio: RadioGroupFieldOutput_2024_06_14,
boolean: BooleanFieldOutput_2024_06_14,
url: UrlFieldOutput_2024_06_14,
};
async validate(bookingFields: OutputBookingField_2024_06_14[]) {
@@ -52,6 +52,7 @@ import {
SelectFieldOutput_2024_06_14,
TextAreaFieldOutput_2024_06_14,
TextFieldOutput_2024_06_14,
UrlFieldOutput_2024_06_14,
} from "../outputs/booking-fields.output";
import type { OutputBookingField_2024_06_14 } from "./booking-fields.output";
import { ValidateOutputBookingFields_2024_06_14 } from "./booking-fields.output";
@@ -173,6 +174,7 @@ class EventTypeTeam {
CheckboxGroupFieldOutput_2024_06_14,
MultiEmailFieldOutput_2024_06_14,
MultiSelectFieldOutput_2024_06_14,
UrlFieldOutput_2024_06_14,
NumberFieldOutput_2024_06_14,
PhoneFieldOutput_2024_06_14,
RadioGroupFieldOutput_2024_06_14,
@@ -261,6 +263,7 @@ class BaseEventTypeOutput_2024_06_14 {
{ $ref: getSchemaPath(CheckboxGroupFieldOutput_2024_06_14) },
{ $ref: getSchemaPath(RadioGroupFieldOutput_2024_06_14) },
{ $ref: getSchemaPath(BooleanFieldOutput_2024_06_14) },
{ $ref: getSchemaPath(UrlFieldOutput_2024_06_14) },
],
type: "array",
})