feat: routing forms integration for booker atom (#18726)

* update booker atom for routing form

* remove logs

* hide routing form properties from docs

* fixup

* add comments to explain why certain fields are not defined for routing forms in v2

* chore: routing for handler return team and org id

* bump libraries platform

* fixup! bump libraries platform

* chore: get routing form params to embed

* logs to remove

* fix import path

* chore: handle routing form params in booker embed

* wip need router api v2 endpoint

* resolve merge conflicts

* fixup

* fixup! Merge branch 'main' into remove-redirect-on-success-for-platform

* fixup! fixup! Merge branch 'main' into remove-redirect-on-success-for-platform

* router atom

* fix libraries version

* cleanup

* remove console logs

* bump libraries

---------

Co-authored-by: Morgan Vernay <morgan@cal.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2025-01-29 13:51:58 +02:00
1 parent 9608669f98
commit 8615ccb1aa
21 files changed
+546 -171

No files matched your search

+1 -1
View File
@@ -29,7 +29,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.92",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.93",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -1,4 +1,4 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { ApiProperty, ApiPropertyOptional, ApiHideProperty } from "@nestjs/swagger";
import { Transform, Type } from "class-transformer";
import {
IsBoolean,
@@ -126,4 +126,47 @@ export class CreateBookingInput_2024_04_15 {
@IsOptional()
@ApiPropertyOptional()
locationUrl?: string;
// note(rajiv): after going through getUrlSearchParamsToForward.ts we found out
// that the below properties were not being included inside of handleNewBooking :- cc @morgan
// cal.salesforce.rrSkipToAccountLookupField, cal.rerouting & cal.isTestPreviewLink
// hence no input values have been setup for them in CreateBookingInput_2024_04_15
@IsArray()
@Type(() => Number)
@IsOptional()
@ApiHideProperty()
routedTeamMemberIds?: number[];
@IsNumber()
@IsOptional()
@ApiHideProperty()
routingFormResponseId?: number;
@IsBoolean()
@IsOptional()
@ApiHideProperty()
skipContactOwner?: boolean;
@IsBoolean()
@IsOptional()
@ApiHideProperty()
_shouldServeCache?: boolean;
@IsBoolean()
@IsOptional()
@ApiHideProperty()
_isDryRun?: boolean;
// reroutingFormResponses is similar to rescheduling which can only be done by the organiser
// won't really be necessary here in our usecase though :- cc @Hariom
@IsObject()
@IsOptional()
@ApiHideProperty()
reroutingFormResponses?: Record<
string,
{
value: (string | number | string[]) & (string | number | string[] | undefined);
label?: string | undefined;
}
>;
}
@@ -1,7 +1,7 @@
import { API_VERSIONS_VALUES } from "@/lib/api-versions";
import { Controller, Get, Req, NotFoundException, Res, Query, Param } from "@nestjs/common";
import { Controller, Req, NotFoundException, Param, Post, Body } from "@nestjs/common";
import { ApiTags as DocsTags, ApiExcludeController as DocsExcludeController } from "@nestjs/swagger";
import { Request, Response } from "express";
import { Request } from "express";
import { getRoutedUrl } from "@calcom/platform-libraries";
import { ApiResponse } from "@calcom/platform-types";
@@ -13,27 +13,27 @@ import { ApiResponse } from "@calcom/platform-types";
@DocsTags("Router controller")
@DocsExcludeController(true)
export class RouterController {
@Get("/forms/:formId")
@Post("/forms/:formId/submit")
async getRoutingFormResponse(
@Req() request: Request,
@Res() res: Response,
@Param("formId") formId: string,
@Query() query: Record<string, string>
): Promise<void | ApiResponse<unknown>> {
const routedUrlData = await getRoutedUrl({ req: request, query: { ...query, form: formId } });
@Body() body?: Record<string, string>
): Promise<void | (ApiResponse<unknown> & { redirect: boolean })> {
const params = Object.fromEntries(new URLSearchParams(body ?? {}));
const routedUrlData = await getRoutedUrl({ req: request, query: { ...params, form: formId } });
if (routedUrlData?.notFound) {
throw new NotFoundException("Route not found. Please check the provided form parameter.");
}
if (routedUrlData?.redirect?.destination) {
return res.redirect(307, routedUrlData.redirect.destination);
return { status: "success", data: routedUrlData?.redirect?.destination, redirect: true };
}
if (routedUrlData?.props) {
return { status: "success", data: routedUrlData.props };
return { status: "success", data: { message: routedUrlData?.props?.message ?? "" }, redirect: false };
}
return { status: "success", data: "route nor custom message found" };
return { status: "success", data: { message: "No Route nor custom message found." }, redirect: false };
}
}