Files
calendar/packages/embeds/embed-core/index.html
T
22f136d19b feat: Headless router - queue recording booking response (#21805)
* Add queued booking response table

* Create `RoutingFormResponseRepository`

* Pass `queueFormResponse` param

* Queue up form response if param is passed

* Forward queued form response parma to booker

* Pass `queuedFormResponse` from booker to `handleNewBooking`

* Write queued routing form response

* Type fixes

* Clean up

* Allow dry run to work which wont have any QueuedFormResponse or FormResponse

* Support passing the time when the modal was actually shown to the user and consider that time as the time of form submission

* fix ts error

* Queue -> Response through separate endpoint that would be triggered by
embed

* Make queueResponseId a non-guessable uid

* Change queueFormResponse query param

* fix ts error

* Support useQueuedResponse to record new response data

* revert handleNewBooking

* Remove dead code formResponse

* Refactor use repository

* Unify migration files

* refactor: moved api endpoint to app dir

Signed-off-by: Omar López <zomars@me.com>

* Update formResponse.ts

* Refactor use-queued-response for test

* Add tests

* Fix ts error and unit test. recordFormResponse cant return nullish response

* fix schema

* feat: Support full reuse of preloaded iframe (#21803)

* feat: support updating cal video settings in API v2 (#21784)

* feat: support updating cal video settings in API v2

* chore: update descriptio

* feat: support create event type

* test: add test for updating event type

* test: add test for create event type

* chore: undo openapi

* chore: bump libraries

* Revert "chore: bump libraries"

This reverts commit bdf36d09b021fc531497a7b7ea66ab9c52b7d136.

* chore: bump libraries

---------

Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>

* fix tests and ts

* Fix tests

* wip-useQueuedResponseEndpoint

* Add one more test

* Change queueFormResponse query param

* wip

* Support useQueuedResponse to record new response data

* Use the update useQueuedResponse endpoint

* self-review addressed

* Use queuedResponse if available in slots/utils

* Add documentation

* Remove use-queued-response from critical-path

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>

* Update schema.prisma

* refactor: renamed to avoid react hooks confusion

Signed-off-by: Omar López <zomars@me.com>

---------

Signed-off-by: Omar López <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2025-06-17 12:11:49 -03:00

462 lines
21 KiB
HTML

<html>
<head>
<title>Embed Playground</title>
<script type="text/javascript" src="./playground/lib/playground-init.ts"></script>
<script>
let popupRescheduleUid = null;
let calLink = null;
const initialNamespace = (url.searchParams.get("only") || "").split("ns:")[1] || "";
(function defineVariables() {
const searchParams = new URL(document.URL).searchParams;
popupRescheduleUid = searchParams.get("popupRescheduleUid") || "qm3kwt3aTnVD7vmP9tiT2f";
calLink = searchParams.get("calLink");
})()
if (!location.search.includes("nonResponsive")) {
document.write('<meta name="viewport" content="width=device-width"/>');
}
function addInlineEmbedInNewNamespaceWithoutReload(selector) {
Cal("init", "withoutReloadNamespace", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.withoutReloadNamespace("inline", {
elementOrSelector: selector,
calLink: "pro?case=addInlineEmbedInANewNamespaceWithoutReload",
config: {
"flag.coep":"true"
}
});
};
</script>
<script>
// Put the snippet in a function so that it can be re-executed for scenario testing
// TODO: How to reuse embed-snippet export here?
function embedSnippet() {
(function (C, A, L) {
let p = function (a, ar) {
a.q.push(ar);
};
let d = C.document;
C.Cal =
C.Cal ||
function () {
let cal = C.Cal;
let ar = arguments;
if (!cal.loaded) {
cal.ns = {};
cal.q = cal.q || [];
d.head.appendChild(d.createElement("script")).src = A;
cal.loaded = true;
}
if (ar[0] === L) {
const api = function () {
p(api, arguments);
};
const namespace = ar[1];
api.q = api.q || [];
if (typeof namespace === "string"){
// Make sure that even after re-execution of the snippet, the namespace is not overridden
cal.ns[namespace] = cal.ns[namespace] || api;
p(cal.ns[namespace], ar);
p(cal, ['initNamespace', namespace])
} else p(cal, ar);
return;
}
p(cal, ar);
};
})(window, window.calOrigin + "/embed/embed.js", "init");
}
embedSnippet();
</script>
<script>
function doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace(selector) {
Cal("init", "doubleInstall", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.doubleInstall("inline", {
elementOrSelector: selector,
calLink: "pro?case=doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace",
config: {
"flag.coep":"true"
}
});
embedSnippet();
Cal("init", "doubleInstall", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.doubleInstall("inline", {
elementOrSelector: selector,
calLink: "pro",
config: {
"flag.coep":"true"
}
});
}
function doubleInstallSnippetWithInlineEmbed(selector) {
Cal("init", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("inline", {
elementOrSelector: selector,
calLink: "pro?case=doubleInstallSnippetWithInlineEmbed",
config: {
"flag.coep":"true"
}
});
embedSnippet();
Cal("init", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("inline", {
elementOrSelector: selector,
calLink: "pro",
config: {
"flag.coep":"true"
}
});
}
function addTwoInlineEmbedWithTwoDifferentNamespacesWithDifferentInitConfig() {
Cal("init", "namespace-init-test-1", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("init", "namespace-init-test-2", {
debug: true,
calOrigin: "http://127.0.0.1:3000",
});
Cal.ns['namespace-init-test-2']("inline", {
elementOrSelector: '#two-different-namespace-with-different-init-config-content-2',
calLink: "pro",
config: {
"flag.coep":"true"
}
});
Cal.ns['namespace-init-test-1']("inline", {
elementOrSelector: '#two-different-namespace-with-different-init-config-content-1',
calLink: "pro",
config: {
"flag.coep":"true"
}
});
}
</script>
<style>
body {
background: linear-gradient(
90deg,
rgba(120, 116, 186, 1) 0%,
rgba(221, 221, 255, 1) 41%,
rgba(148, 232, 249, 1) 100%
);
}
.inline-embed-container {
/* border: 1px solid black; */
margin-bottom: 5px;
border-bottom: 1px solid;
}
.loader {
color: green;
}
* {
--cal-brand-color: gray;
}
</style>
</head>
<body>
<div id="misc-embeds">
<div>
<button id="add-inline-embed-in-a-new-namespace-without-reload-button" onclick="addInlineEmbedInNewNamespaceWithoutReload('#add-inline-embed-in-a-new-namespace-without-reload-button-content')">Add Inline Embed in a new namespace without reload</button>
<div id="add-inline-embed-in-a-new-namespace-without-reload-button-content"></div>
</div>
<div>
<button id="double-install-snippet-with-inline-embed-default-namespace-button" onclick="doubleInstallSnippetWithInlineEmbed('#double-install-snippet-with-inline-embed-default-namespace-content')">Double Install Embed Snippet with inline embed - Default Namespace</button>
<div id="double-install-snippet-with-inline-embed-default-namespace-content"></div>
</div>
<div>
<button id="double-install-snippet-with-inline-embed-non-default-namespace-button" onclick="doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace('#double-install-snippet-with-inline-embed-non-default-namespace-content')">Double Install Embed Snippet with inline embed - Non Default Namespace</button>
<div id="double-install-snippet-with-inline-embed-non-default-namespace-content"></div>
</div>
<div>
<button id="two-different-namespace-with-different-init-config" onclick="addTwoInlineEmbedWithTwoDifferentNamespacesWithDifferentInitConfig()">Two different namespace with two different config</button>
<div id="two-different-namespace-with-different-init-config-area">
<div id="two-different-namespace-with-different-init-config-content-1"></div>
<div id="two-different-namespace-with-different-init-config-content-2"></div>
</div>
</div>
<span style="display: block"><a href="?color-scheme=dark">With Dark Color Scheme for the Page</a></span>
<span style="display: block"><a href="?nonResponsive">Non responsive version of this page here</a></span>
<span style="display: block">
<a href="?name=john&email=email&guests=abc&guests=def&notes=NOTES&location=%7B%22optionValue%22%3A%22%2B919999999999%22%2C%22value%22%3A%22phone%22%7D&only=ns%3ApageParamsForwarding">
Page Params Forwarding(Prefills various fields by auto-forwarding query params)
</a>
</span>
<span style="display: block"
><a href="?only=prerender-test">Go to Prerender test page only</a><small></small
></span>
<span style="display: block"
><a href="?only=preload-test">Go to Preload test page only</a><small></small
></span>
<button onclick="document.documentElement.style.colorScheme='dark'">Toggle Dark Scheme(For Embedding Page)</button>
<button onclick="document.documentElement.style.colorScheme='light'">Toggle Light Scheme(For Embedding Page)</button>
<div>
<script>
if (only === "all" || only === "prerender-test") {
document.write(`
<button data-cal-namespace="e2ePrerenderLightTheme" data-cal-config='{"theme":"dark", "email":"preloaded-prefilled@example.com", "name": "Preloaded Prefilled", "flag.coep": "true"}' data-cal-link="free/30min">Book with Free User[Dark Theme]</button>
<i
>Corresponding Cal Link is being prerendered. Assuming that it would take you some time to click this
as you are reading this text, it would open up super fast[If you are running a production build on
local]. Try switching to slow 3G or create a custom Network configuration which is impossibly
slow. This should be used if you know beforehand which type of embed is going to be opened.</i
>`);
}
if (only === "all" || only === "preload-test") {
document.write(`
<button data-cal-namespace="preloadTest" data-cal-config='{"theme":"dark", "email":"preloaded-prefilled@example.com", "name": "Preloaded Prefilled", "flag.coep": "true"}' data-cal-link="free/30min">Book with Free User[Dark Theme]</button>
<i
>Corresponding Cal Link is being preloaded. That means that all the resources would be preloaded. This could be useful in preloading possible resources if you don't know before hand which type of embed you want to show</i
>`);
}
</script>
</div>
<span style="display: block"
><a href="?only=all">Render All embeds together</a><small> - It would be slow to load</small></span
>
<div>
<a href="?only=ns:floatingButton">Floating Popup</a>
<h2>Popup Examples - Theme Tests</h2>
<button data-cal-namespace="e2ePopupLightTheme" data-cal-link="free" data-cal-config='{"theme":"light", "flag.coep": "true"}'>Book an event with Free[Light Theme]</button>
<button data-cal-namespace="popupAutoTheme" data-cal-link="free" data-cal-config='{"flag.coep": "true"}'>
Book with Free User[Auto Theme]
</button>
<button data-cal-namespace="popupDarkTheme" data-cal-config='{"theme":"dark", "flag.coep": "true"}' data-cal-link="free">
Book with Free User[Dark Theme]
</button>
<button
data-cal-namespace="popupTeamLinkLightTheme"
data-cal-config='{"theme":"light", "flag.coep": "true"}'
data-cal-link="team/seeded-team/collective-seeded-team-event">
Book with Test Team[Light Theme]
</button>
<button
data-cal-namespace="popupTeamLinkDarkTheme"
data-cal-config='{"theme":"dark", "flag.coep": "true"}'
data-cal-link="team/seeded-team/collective-seeded-team-event">
Book with Test Team[Dark Theme]
</button>
<button data-cal-namespace="popupTeamLinksList" data-cal-link="team/seeded-team/" data-cal-config='{"flag.coep": "true"}'>
See Team Links [Auto Theme]
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-link="pro/paid" data-cal-config='{"flag.coep": "true"}'>
Book Paid Event [Auto Theme]
</button>
<h2>Popup Examples - Reschedule Tests</h2>
<script>
document.write(
`<button data-cal-namespace="popupRescheduleWithReschedulePath" data-cal-config='{"flag.coep":"true"}' data-cal-link="reschedule/${popupRescheduleUid}">Reschedule Event(with /reschedule) - Needs popupRescheduleUid param</button>`
);
</script>
<script>
document.write(
`<button data-cal-namespace="popupRescheduleWithRescheduleUidParam" data-cal-config='{"flag.coep":"true", "rescheduleUid": "${popupRescheduleUid}"}' data-cal-link="${calLink}">Reschedule Event(with rescheduleUid param) - Needs popupRescheduleUid and calLink param</button>`
);
</script>
<h2>Popup Examples - Different Configurations</h2>
<button data-cal-namespace="popupHideEventTypeDetails" data-cal-link="free/30min" data-cal-config='{"flag.coep": "true"}'>
Book Free Event [Auto Theme][uiConfig.hideEventTypeDetails=true]
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-config='{"layout":"week_view", "flag.coep": "true"}' data-cal-link="pro/paid">
Book Paid Event - weekly view
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-config='{"layout":"column_view", "flag.coep": "true"}' data-cal-link="pro/paid">
Book Paid Event - column view
</button>
<h2>Popup Examples - Routing Form Tests</h2>
<button data-cal-namespace="routingFormAuto" data-cal-link="forms/948ae412-d995-4865-875a-48302588de03" data-cal-config='{"flag.coep": "true"}'>
Book through Routing Form [Auto Theme] - Test for 'routed' event
</button>
<button
data-cal-namespace="routingFormDark"
data-cal-config='{"theme":"dark", "flag.coep": "true"}'
data-cal-link="forms/948ae412-d995-4865-875a-48302588de03">
Book through Routing Form [Dark Theme]
</button>
<button data-cal-namespace="routingFormHeadlessRouter" data-cal-link="router?form=948ae412-d995-4865-875a-48302588de03&Test field=event-routing" data-cal-config='{"flag.coep": "true"}'>
Book through Headless Router
</button>
<h2>Popup Examples - Child Element Target Tests</h2>
<a style="display: block;" data-cal-namespace="childElementTarget" href="javascript:void(0)" data-cal-link="free/30min" data-cal-config='{"flag.coep": "true"}'>
I am Anchor
<b>[I am Bold inside anchor]</b>
<span>
I am span inside anchor
</span>
</a>
</div>
<h2>Inline Embed Examples</h2>
<div id="namespaces-test">
<div class="inline-embed-container" id="cal-booking-place-default">
<h3>
<a href="?only=ns:default">[Dark Theme][Guests(janedoe@example.com and test@example.com)](Default Namespace)</a>
</h3>
<button onclick="Cal('ui',{theme:'light'})">Toggle to Light</button>
<button onclick="Cal('ui',{layout:'week_view'})">Toggle to Week View</button>
<button onclick="Cal('ui',{layout:'month_view'})">Toggle to Month View</button>
<button onclick="Cal('ui',{layout:'column_view'})">Toggle to Column View</button>
<i class="last-action"> You would see last Booking page action in my place </i>
<div>
<div class="place" style="width: 100%"></div>
<div class="loader" id="cal-booking-loader-"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-second">
<h3><a href="?only=ns:second">[Custom Styling]</a></h3>
<div class="place">
<div>
If you render booking embed in me, I won't restrict you. The entire page is yours. Content is by
default aligned center
</div>
<button
onclick="(function () {Cal.ns.second('ui', {cssVarsPerTheme:{light:{'cal-border-booker':'green', 'cal-border-booker-width':'20px'},dark:{'cal-border-booker':'red', 'cal-border-booker-width':'5px'}}})})()">
Change booker border for dark and light themes
</button>
<button
onclick="(function () {Cal.ns.second('ui', {cssVarsPerTheme:{light:{'cal-brand':'green'},dark:{'cal-brand':'red'}}})})()">
Change Brand color for dark and light theme
</button>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{eventTypeListItem:{backgroundColor:'blue'}}})})()">
Change <code>eventTypeListItem</code> bg color[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{body:{background:'red'}}})})()">
Change <code>body</code> bg color[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'left'}})})()">
Align left[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'center'}})})()">
Align Center[Deprecated]
</button>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{enabledDateButton: {
backgroundColor: window.generateRandomHexColor(),
},
disabledDateButton: {
backgroundColor: window.generateRandomHexColor(),
},}})})()">
Change 'enabledDateButton` and `disabledDateButton` background Color[Deprecated]
</button>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-third">
<h3><a href="?only=ns:third">[Custom Styling - Transparent Background]</a></h3>
<div style="width: 30%" class="place">
<div>If you render booking embed in me, I would not let you be more than 30% wide</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-fourth">
<h3><a href="?only=ns:fourth">[Team Event Test][inline taking entire width]</a></h3>
<div style="width: 30%" class="place">
<div>If you render booking embed in me, I would not let you be more than 30% wide</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-corpTest">
<h3><a href="?only=ns:corpTest">CORP/COEP Blocking Test</a></h3>
<div class="place">
<div>It would forever load</div>
</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-fifth">
<h3><a href="?only=ns:fifth">[Team Event Test][inline along with some content]</a></h3>
<div style="display: flex; align-items: center">
<h4 style="width: 30%">On the right side you can book a team meeting =></h4>
<div style="width: 70%" class="place"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-inline-routing-form">
<h3><a href="?only=inline-routing-form">Inline Routing Form</a></h3>
<div style="display: flex; align-items: center">
<h4 style="width: 30%">On the right side you can book a team meeting =></h4>
<div style="width: 70%" class="place"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-hideEventTypeDetails">
<h3><a href="?only=hideEventTypeDetails">Hide EventType Details Test</a></h3>
<div class="place"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-conflicting-theme">
<h3><a href="?only=conflicting-theme">You would be able to test out conflicting themes for the same namespace here.</a></h3>
<div class="light"></div>
<div class="dark"></div>
<i>Note that one of the embeds would stay in loading state as they are using the same namespace and it is not supported to have more than 1 embeds using same namespace</i>
</div>
<div class="inline-embed-container" id="cal-booking-place-monthView">
<h3><a href="?only=ns:monthView">Test Month View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-weekView">
<h3><a href="?only=ns:weekView">Test Week View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-columnView">
<h3><a href="?only=ns:columnView">Test Column View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-columnViewHideEventTypeDetails">
<h3><a href="?only=ns:columnViewHideEventTypeDetails">Test Column View Hide Event Type Details</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-pageParamsForwarding">
<h3><a href="?only=ns:pageParamsForwarding">Test Page Params Forwarding</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-autoScrollTest">
<h3><a href="?only=ns:autoScrollTest">Test Auto Scroll</a></h3>
<div class="place" style="width: 100%"></div>
</div>
</div>
<div id="cal-booking-place-skeletonDemo">
<h3><a href="?only=ns:skeletonDemo">Skeleton Loader INLINE Demo</a></h3>
<div class="inline-embed-container">
<div id="cal-booking-place-skeletonDemo">
<div class="place"></div>
</div>
</div>
</div>
<div id="cal-booking-place-skeletonDemoElementClick">
<a href="?only=ns:skeletonDemoElementClick">Skeleton Loader MODAL Demo</a>
<h3><button data-cal-namespace="skeletonDemoElementClick" data-cal-link="team/seeded-team/collective-seeded-team-event" data-cal-config='{"cal.embed.pageType":"team.event.booking.slots"}'>Skeleton Loader MODAL Demo</button></h3>
<div class="inline-embed-container">
<div id="cal-booking-place-skeletonDemoElementClick">
<div class="place"></div>
</div>
</div>
</div>
<script type="module" src="./playground/lib/playground.ts"></script>
<script>
if (initialNamespace.startsWith("skeletonDemo")) {
document.getElementById("misc-embeds").style.display = "none";
}
</script>
</body>
</html>