fix: Embed - Better support for layout config(without flash of default toggle) (#9714)

This commit is contained in:
Hariom Balhara authored and GitHub committed 2023-06-26 17:24:19 +02:00
1 parent 6adaf0d3e8
commit 4ada428bcb
8 files changed
+226 -48

No files matched your search

+80 -18
View File
@@ -10,7 +10,7 @@ import { components } from "react-select";
import type { BookerLayout } from "@calcom/features/bookings/Booker/types";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { APP_NAME, EMBED_LIB_URL, WEBAPP_URL } from "@calcom/lib/constants";
import { APP_NAME, EMBED_LIB_URL, IS_SELF_HOSTED, WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { BookerLayouts } from "@calcom/prisma/zod-utils";
import {
@@ -38,13 +38,21 @@ const enum Theme {
dark = "dark",
}
const EMBED_CAL_ORIGIN = WEBAPP_URL;
const EMBED_CAL_JS_URL = `${WEBAPP_URL}/embed/embed.js`;
type PreviewState = {
inline: {
width: string;
height: string;
};
theme: Theme;
floatingPopup: Record<string, string | boolean | undefined>;
floatingPopup: {
config?: {
layout: BookerLayouts;
};
[key: string]: string | boolean | undefined | Record<string, string>;
};
elementClick: Record<string, string>;
palette: {
brandColor: string;
@@ -175,14 +183,24 @@ const Codes: Record<string, Record<string, (...args: any[]) => string>> = {
return code`
import Cal, { getCalApi } from "@calcom/embed-react";
import { useEffect } from "react";
function MyComponent() {
export default function MyApp() {
useEffect(()=>{
(async function () {
const cal = await getCalApi();
${uiInstructionCode}
})();
}, [])
return <Cal calLink="${calLink}" style={{width:"${width}",height:"${height}",overflow:"scroll"}} />;
return <Cal
calLink="${calLink}"
style={{width:"${width}",height:"${height}",overflow:"scroll"}}
${previewState.layout ? "config={{layout: '" + previewState.layout + "'}}" : ""}${
IS_SELF_HOSTED
? `
calOrigin="${EMBED_CAL_ORIGIN}"
calJsUrl="${EMBED_CAL_JS_URL}"`
: ""
}
/>;
};`;
},
"floating-popup": ({
@@ -193,38 +211,60 @@ function MyComponent() {
uiInstructionCode: string;
}) => {
return code`
import Cal, { getCalApi } from "@calcom/embed-react";
import { getCalApi } from "@calcom/embed-react";
import { useEffect } from "react";
function MyComponent() {
export default function App() {
useEffect(()=>{
(async function () {
const cal = await getCalApi();
const cal = await getCalApi(${IS_SELF_HOSTED ? `"${EMBED_CAL_JS_URL}"` : ""});
cal("floatingButton", ${floatingButtonArg});
${uiInstructionCode}
})();
}, [])
};`;
},
"element-click": ({ calLink, uiInstructionCode }: { calLink: string; uiInstructionCode: string }) => {
"element-click": ({
calLink,
uiInstructionCode,
previewState,
}: {
calLink: string;
uiInstructionCode: string;
previewState: PreviewState;
}) => {
return code`
import Cal, { getCalApi } from "@calcom/embed-react";
import { getCalApi } from "@calcom/embed-react";
import { useEffect } from "react";
function MyComponent() {
export default function App() {
useEffect(()=>{
(async function () {
const cal = await getCalApi();
const cal = await getCalApi(${IS_SELF_HOSTED ? `"${EMBED_CAL_JS_URL}"` : ""});
${uiInstructionCode}
})();
}, [])
return <button data-cal-link="${calLink}" />;
return <button
data-cal-link="${calLink}"${IS_SELF_HOSTED ? `\ndata-cal-origin="${EMBED_CAL_ORIGIN}"` : ""}
${`data-cal-config='${JSON.stringify({
layout: previewState.layout,
})}'`}
>Click me</button>;
};`;
},
},
HTML: {
inline: ({ calLink, uiInstructionCode }: { calLink: string; uiInstructionCode: string }) => {
inline: ({
calLink,
uiInstructionCode,
previewState,
}: {
calLink: string;
uiInstructionCode: string;
previewState: PreviewState;
}) => {
return code`Cal("inline", {
elementOrSelector:"#my-cal-inline",
calLink: "${calLink}"
calLink: "${calLink}",
layout: "${previewState.layout}"
});
${uiInstructionCode}`;
@@ -240,8 +280,22 @@ ${uiInstructionCode}`;
return code`Cal("floatingButton", ${floatingButtonArg});
${uiInstructionCode}`;
},
"element-click": ({ calLink, uiInstructionCode }: { calLink: string; uiInstructionCode: string }) => {
return code`// Important: Make sure to add \`data-cal-link="${calLink}"\` attribute to the element you want to open Cal on click
"element-click": ({
calLink,
uiInstructionCode,
previewState,
}: {
calLink: string;
uiInstructionCode: string;
previewState: PreviewState;
}) => {
return code`
// Important: Please add following attributes to the element you want to open Cal on click
// \`data-cal-link="${calLink}"\`
// \`data-cal-config='${JSON.stringify({
layout: previewState.layout,
})}'\`
${uiInstructionCode}`;
},
},
@@ -298,6 +352,7 @@ const getEmbedTypeSpecificString = ({
} else if (embedType === "floating-popup") {
const floatingButtonArg = {
calLink,
...(IS_SELF_HOSTED ? { calOrigin: EMBED_CAL_ORIGIN } : null),
...previewState.floatingPopup,
};
return frameworkCodes[embedType]({
@@ -710,13 +765,13 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
height: "100%",
},
theme: Theme.auto,
layout: BookerLayouts.MONTH_VIEW,
floatingPopup: {},
elementClick: {},
hideEventTypeDetails: false,
palette: {
brandColor: "#000000",
},
layout: BookerLayouts.MONTH_VIEW,
});
const close = () => {
@@ -778,8 +833,8 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
name: "ui",
arg: {
theme: previewState.theme,
hideEventTypeDetails: previewState.hideEventTypeDetails,
layout: previewState.layout,
hideEventTypeDetails: previewState.hideEventTypeDetails,
styles: {
branding: {
...previewState.palette,
@@ -1102,8 +1157,15 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
return;
}
setPreviewState((previewState) => {
const config = {
...(previewState.floatingPopup.config ?? {}),
layout: option.value,
};
return {
...previewState,
floatingPopup: {
config,
},
layout: option.value,
};
});
+3 -3
View File
@@ -100,7 +100,7 @@ plugins.push(withAxiom);
const userTypeRouteRegExp = `/:user((?!${pages.join("/|")})[^/]*)/:type((?!book$)[^/]+)`;
const teamTypeRouteRegExp = "/team/:slug/:type((?!book$)[^/]+)";
const privateLinkRouteRegExp = "/d/:link/:slug((?!book$)[^/]+)";
const embedUserTypeRouteRegExp = `/:user((?!${pages.join("|")}).*)/:type/embed`;
const embedUserTypeRouteRegExp = `/:user((?!${pages.join("/|")})[^/]*)/:type/embed`;
const embedTeamTypeRouteRegExp = "/team/:slug/:type/embed";
/** @type {import("next").NextConfig} */
@@ -312,11 +312,11 @@ const nextConfig = {
afterFiles.push(
...[
{
source: `/:user((?!${pages.join("|")}).*)/:type/embed`,
source: embedUserTypeRouteRegExp,
destination: "/new-booker/:user/:type/embed",
},
{
source: "/team/:slug/:type/embed",
source: embedTeamTypeRouteRegExp,
destination: "/new-booker/team/:slug/:type/embed",
},
]
+8 -2
View File
@@ -47,8 +47,8 @@ describe('next.config.js - RegExp', ()=>{
// privateLinkRouteRegExp = "/d/:link/:slug((?!book$)[^/]+)";
privateLinkRouteRegExp = getRegExpFromNextJsRewriteRegExp("/d/(?<link>[^/]+)/(?<slug>((?!book$)[^/]+))");
// embedUserTypeRouteRegExp = `/:user((?!${pages.join("|")}).*)/:type/embed`;
embedUserTypeRouteRegExp = getRegExpFromNextJsRewriteRegExp(`/(?<user>((?!${pages.join("|")}).*))/(?<type>[^/]+)/embed`);
// embedUserTypeRouteRegExp = `/:user((?!${pages.join("/|")})[^/]*)/:type/embed`;
embedUserTypeRouteRegExp = getRegExpFromNextJsRewriteRegExp(`/(?<user>((?!${pages.join("/|")})[^/]*))/(?<type>[^/]+)/embed`);
// embedTeamTypeRouteRegExp = "/team/:slug/:type/embed";
embedTeamTypeRouteRegExp = getRegExpFromNextJsRewriteRegExp("/team/(?<slug>[^/]+)/(?<type>[^/]+)/embed");
@@ -94,6 +94,12 @@ describe('next.config.js - RegExp', ()=>{
type:'30'
})
// Edgecase of username starting with team also works
expect(embedUserTypeRouteRegExp.exec('/teampro/30/embed')?.groups).toContain({
user: 'teampro',
type: '30'
})
expect(teamTypeRouteRegExp.exec('/team/seeded/30')?.groups).toContain({
slug: 'seeded',
type: '30'