* 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: benny@cal.com <sldisek783@gmail.com> * 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>
173 lines
6.6 KiB
TypeScript
173 lines
6.6 KiB
TypeScript
import type { InferGetServerSidePropsType } from "next";
|
|
import { useState } from "react";
|
|
import { Toaster } from "sonner";
|
|
|
|
import AppNotInstalledMessage from "@calcom/app-store/_components/AppNotInstalledMessage";
|
|
import type { getServerSideProps } from "@calcom/app-store/make/pages/setup/_getServerSideProps";
|
|
import ServerTrans from "@calcom/lib/components/ServerTrans";
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|
import { trpc } from "@calcom/trpc/react";
|
|
import { Button } from "@calcom/ui/components/button";
|
|
import { showToast } from "@calcom/ui/components/toast";
|
|
import { Tooltip } from "@calcom/ui/components/tooltip";
|
|
import { ClipboardIcon } from "@coss/ui/icons";
|
|
|
|
const MAKE = "make";
|
|
|
|
export default function MakeSetup({ inviteLink }: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
|
const [newApiKeys, setNewApiKeys] = useState<Record<string, string>>({});
|
|
|
|
const { t } = useLocale();
|
|
const utils = trpc.useUtils();
|
|
const integrations = trpc.viewer.apps.integrations.useQuery({ variant: "automation" });
|
|
const oldApiKey = undefined as { data?: Array<{ id: string; teamId?: number }> } | undefined;
|
|
|
|
const teamsList = null as { data?: Array<{ id: number; name: string }> } | null;
|
|
|
|
const teams = teamsList?.data?.map((team) => ({ id: team.id, name: team.name }));
|
|
const deleteApiKey = { mutate: (_args: Record<string, unknown>) => {} };
|
|
|
|
const makeCredentials: { userCredentialIds: number[] } | undefined = integrations.data?.items.find(
|
|
(item: { type: string }) => item.type === "make_automation"
|
|
);
|
|
const [credentialId] = makeCredentials?.userCredentialIds || [false];
|
|
const showContent = integrations.data && integrations.isSuccess && credentialId;
|
|
|
|
async function createApiKey(teamId?: number) {
|
|
const event = { note: "Make", expiresAt: null, appId: MAKE, teamId };
|
|
const apiKey = `cal_live_${Math.random().toString(36).substring(2)}`;
|
|
|
|
if (oldApiKey?.data) {
|
|
const oldKey = teamId
|
|
? oldApiKey.data.find((key) => key.teamId === teamId)
|
|
: oldApiKey.data.find((key) => !key.teamId);
|
|
|
|
if (oldKey) {
|
|
deleteApiKey.mutate({
|
|
id: oldKey.id,
|
|
});
|
|
}
|
|
}
|
|
|
|
return apiKey;
|
|
}
|
|
|
|
async function generateApiKey(teamId?: number) {
|
|
const apiKey = await createApiKey(teamId);
|
|
setNewApiKeys({ ...newApiKeys, [teamId || ""]: apiKey });
|
|
}
|
|
|
|
if (integrations.isPending) {
|
|
return <div className="bg-emphasis absolute z-50 flex h-screen w-full items-center" />;
|
|
}
|
|
|
|
return (
|
|
<div className="bg-emphasis flex h-screen">
|
|
{showContent ? (
|
|
<div className="bg-default m-auto max-w-[43em] overflow-auto rounded pb-10 md:p-10">
|
|
<div className="md:flex md:flex-row">
|
|
<div className="invisible md:visible">
|
|
{/* eslint-disable @next/next/no-img-element */}
|
|
<img className="h-11" src="/api/app-store/make/icon.svg" alt="Make Logo" />
|
|
</div>
|
|
<div className="ml-2 md:ml-5 ltr:mr-2 rtl:ml-2">
|
|
<div className="text-default">{t("setting_up_make")}</div>
|
|
|
|
<>
|
|
<div className="mt-1 text-xl">{t("generate_api_key")}:</div>
|
|
{!teams ? (
|
|
<Button color="secondary" onClick={() => createApiKey()} className="mb-4 mt-2">
|
|
{t("generate_api_key")}
|
|
</Button>
|
|
) : (
|
|
<>
|
|
<div className="mt-8 text-sm font-semibold">Your event types:</div>
|
|
{!newApiKeys[""] ? (
|
|
<Button color="secondary" onClick={() => generateApiKey()} className="mb-4 mt-2">
|
|
{t("generate_api_key")}
|
|
</Button>
|
|
) : (
|
|
<CopyApiKey apiKey={newApiKeys[""]} />
|
|
)}
|
|
{teams.map((team) => {
|
|
return (
|
|
<div key={team.name}>
|
|
<div className="mt-2 text-sm font-semibold">{team.name}:</div>
|
|
{!newApiKeys[team.id] ? (
|
|
<Button
|
|
color="secondary"
|
|
onClick={() => generateApiKey(team.id)}
|
|
className="mb-4 mt-2">
|
|
{t("generate_api_key")}
|
|
</Button>
|
|
) : (
|
|
<CopyApiKey apiKey={newApiKeys[team.id]} />
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
</>
|
|
|
|
<ol className="mb-5 ml-5 mt-5 list-decimal ltr:mr-5 rtl:ml-5">
|
|
<li>
|
|
<ServerTrans
|
|
t={t}
|
|
i18nKey="make_setup_instructions_1"
|
|
components={[
|
|
<a
|
|
key="make-invite-link"
|
|
href={inviteLink}
|
|
className="ml-1 mr-1 text-orange-600 underline">
|
|
Make Invite Link
|
|
</a>,
|
|
]}
|
|
/>
|
|
</li>
|
|
<li>{t("make_setup_instructions_2")}</li>
|
|
<li>{t("make_setup_instructions_3")}</li>
|
|
<li>{t("make_setup_instructions_4")}</li>
|
|
<li>{t("make_setup_instructions_5")}</li>
|
|
<li>{t("make_setup_instructions_6")}</li>
|
|
</ol>
|
|
<Button href="/apps/installed/automation?hl=make" color="secondary">
|
|
{t("done")}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<AppNotInstalledMessage appName="make" />
|
|
)}
|
|
<Toaster position="bottom-right" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const CopyApiKey = ({ apiKey }: { apiKey: string }) => {
|
|
const { t } = useLocale();
|
|
return (
|
|
<div>
|
|
<div className="my-2 mt-3 flex-wrap sm:flex sm:flex-nowrap">
|
|
<code className="bg-subtle h-full w-full whitespace-pre-wrap rounded-md py-[6px] pl-2 pr-2 sm:rounded-r-none sm:pr-5">
|
|
{apiKey}
|
|
</code>
|
|
<Tooltip side="top" content={t("copy_to_clipboard")}>
|
|
<Button
|
|
onClick={() => {
|
|
navigator.clipboard.writeText(apiKey);
|
|
showToast(t("api_key_copied"), "success");
|
|
}}
|
|
type="button"
|
|
className="mt-4 text-base sm:mt-0 sm:rounded-l-none">
|
|
<ClipboardIcon className="h-4 w-4 ltr:mr-2 rtl:ml-2" />
|
|
{t("copy")}
|
|
</Button>
|
|
</Tooltip>
|
|
</div>
|
|
<div className="text-subtle mb-5 mt-2 text-sm">{t("copy_somewhere_safe")}</div>
|
|
</div>
|
|
);
|
|
};
|