Files
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ab21c7f805 refactor: Cal.diy (#28903)
* feat: Cal.diy — community-driven MIT-licensed fork of Cal.com

This squashed commit contains all Cal.diy changes applied on top of calcom/cal.com main:

- Rebrand Cal.com to Cal.diy across the entire codebase
- Remove Enterprise Edition (EE) features, license checks, and AGPL restrictions
- Switch license from AGPL-3.0 to MIT
- Remove docs/ directory (migrated to Nextra at cal.diy)
- Remove dead code: org tests, EE tips, platform nav, premium username, SAML/SSO, etc.
- Clean up .env.example for self-hosted Cal.diy
- Update Docker image references to calcom/cal.diy
- Update README, CONTRIBUTING.md, and issue templates for Cal.diy community fork
- Add PR welcome bot for Cal.diy contributors
- Fix API v2 breaking changes oasdiff ignore entries
- Replace Blacksmith CI runners with default GitHub Actions

3893 files changed, 20789 insertions(+), 411020 deletions(-)

Co-Authored-By: [email protected] <[email protected]>

* refactor: remove org-specific /organizations/:orgId endpoints from API v2 atoms controllers (#1701)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: revert Cal.diy Inc to Cal.com, Inc. in license files, copyright notices, and package metadata (#1702)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* rip out org related comments in api v2

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-15 09:52:36 -03:00

135 lines
3.0 KiB
TypeScript

import type { NextApiRequest } from "next";
import { WEBAPP_URL } from "@calcom/lib/constants";
import prisma from "@calcom/prisma";
import type {
NewCanvas,
ListComponent,
ListItem,
SpacerComponent,
TextComponent,
InputComponent,
} from "../../lib";
import { isValidCalURL } from "../../lib/isValidCalURL";
export async function handleLinkStep(req: NextApiRequest): Promise<NewCanvas | string> {
const { admin, component_id, input_values } = req.body;
const url = component_id === "submit_booking_url" ? input_values?.submit_booking_url : component_id;
const { isValid, error } = url ? await isValidCalURL(url) : { isValid: false, error: undefined };
if (isValid) return url;
const input: InputComponent = {
type: "input",
id: "submit_booking_url",
label: "Enter your Cal.diy link",
placeholder: "https://cal.com/valentinchmara/30min",
save_state: "unsaved",
action: {
type: "submit",
},
aria_label: "Enter your Cal.diy link",
};
const defaultCanvasData: NewCanvas = {
canvas: {
content: {
components: !error ? [input] : [error, input],
},
},
};
if (!admin?.id) return defaultCanvasData;
const credential = await prisma.credential.findFirst({
where: {
appId: "intercom",
key: {
string_contains: admin.id,
},
},
});
if (!credential) return defaultCanvasData;
const team = credential.teamId
? await prisma.team.findUnique({
where: {
id: credential.teamId,
},
})
: null;
const userId = credential.userId;
const user = userId
? await prisma.user.findUnique({
where: {
id: userId,
},
})
: null;
const eventTypes = await prisma.eventType.findMany({
where: {
userId,
hidden: false,
teamId: team ? team.id : undefined,
},
});
if (eventTypes && eventTypes?.length === 0) return defaultCanvasData;
if (!user && !team) return defaultCanvasData;
// Limit to 10 Events types
const list: ListItem[] = eventTypes.slice(0, 10).map((eventType) => {
let slug;
if (team && team.slug) {
slug = `team/${team.slug}`;
} else if (user && user.username) {
slug = user.username;
}
return {
id: `${WEBAPP_URL}/${slug}/${eventType.slug}`,
type: "item",
title: eventType.title,
subtitle: `${slug}/${eventType.slug}`,
rounded_image: false,
disabled: false,
action: {
type: "submit",
},
};
});
const components: ListComponent = {
type: "list",
items: list,
};
const spacer: SpacerComponent = {
type: "spacer",
size: "m",
};
const text: TextComponent = {
type: "text",
text: "Or choose another Cal.diy link:",
style: "muted",
align: "left",
};
const canvasData: NewCanvas = {
canvas: {
content: {
components: !error ? [components, spacer, text, input] : [components, spacer, text, input, error],
},
},
};
return canvasData;
}