import { zodResolver } from "@hookform/resolvers/zod"; import { AppCategories } from "@prisma/client"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@radix-ui/react-collapsible"; import { useRouter } from "next/router"; import { useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import AppCategoryNavigation from "@calcom/app-store/_components/AppCategoryNavigation"; import { appKeysSchemas } from "@calcom/app-store/apps.keys-schemas.generated"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { Button, ConfirmationDialogContent, Dialog, EmptyScreen, Form, Icon, showToast, SkeletonButton, SkeletonContainer, SkeletonText, Switch, TextField, VerticalDivider, } from "@calcom/ui"; const IntegrationContainer = ({ app, lastEntry, category, }: { app: RouterOutputs["viewer"]["appsRouter"]["listLocal"][number]; lastEntry: boolean; category: string; }) => { const { t } = useLocale(); const utils = trpc.useContext(); const [disableDialog, setDisableDialog] = useState(false); const [showKeys, setShowKeys] = useState(false); const appKeySchema = appKeysSchemas[app.dirName as keyof typeof appKeysSchemas]; const formMethods = useForm({ resolver: zodResolver(appKeySchema), }); const enableAppMutation = trpc.viewer.appsRouter.toggle.useMutation({ onSuccess: (enabled) => { utils.viewer.appsRouter.listLocal.invalidate({ category }); setDisableDialog(false); showToast( enabled ? t("app_is_enabled", { appName: app.name }) : t("app_is_disabled", { appName: app.name }), "success" ); }, onError: (error) => { showToast(error.message, "error"); }, }); const saveKeysMutation = trpc.viewer.appsRouter.saveKeys.useMutation({ onSuccess: () => { showToast(t("keys_have_been_saved"), "success"); }, onError: (error) => { showToast(error.message, "error"); }, }); return ( <>
{app.logo && {app.title}}

{app.name || app.title}

{app.description}

<> { if (app.enabled) { setDisableDialog(true); } else { enableAppMutation.mutate({ slug: app.slug, enabled: app.enabled }); setShowKeys(true); } }} /> {app.keys && ( <> )}
{!!app.keys && typeof app.keys === "object" && (
saveKeysMutation.mutate({ slug: app.slug, type: app.type, keys: values, dirName: app.dirName, }) } className="px-4 pb-4"> {Object.keys(app.keys).map((key) => ( ( { formMethods.setValue(key, e?.target.value); }} /> )} /> ))} )}
{ enableAppMutation.mutate({ slug: app.slug, enabled: app.enabled }); }}> {t("disable_app_description")} ); }; const querySchema = z.object({ category: z .nativeEnum({ ...AppCategories, conferencing: "conferencing" }) .optional() .default(AppCategories.calendar), }); const AdminAppsList = ({ baseURL, className }: { baseURL: string; className?: string }) => { const router = useRouter(); return (
{ e.preventDefault(); router.replace("/"); }}>
); }; const AdminAppsListContainer = () => { const { t } = useLocale(); const router = useRouter(); const { category } = querySchema.parse(router.query); const { data: apps, isLoading } = trpc.viewer.appsRouter.listLocal.useQuery( { category }, { enabled: router.isReady } ); if (isLoading) return ; if (!apps) { return ( ); } return (
{apps.map((app, index) => ( ))}
); }; export default AdminAppsList; const SkeletonLoader = () => { return (
); };