Merge branch 'main' into enterprise-license

staging
kodiakhq[bot] 2022-04-20 21:39:33 +00:00 committed by GitHub
commit db7e31a84c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 86 additions and 20 deletions

View File

@ -8,14 +8,13 @@ import {
} from "@heroicons/react/outline";
import { ChevronLeftIcon } from "@heroicons/react/solid";
import Link from "next/link";
import React from "react";
import React, { useEffect, useState } from "react";
import { InstallAppButton } from "@calcom/app-store/components";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { App as AppType } from "@calcom/types/App";
import { Button } from "@calcom/ui";
//import NavTabs from "@components/NavTabs";
import Shell from "@components/Shell";
import Badge from "@components/ui/Badge";
@ -60,7 +59,29 @@ export default function App({
currency: "USD",
useGrouping: false,
}).format(price);
const [installedApp, setInstalledApp] = useState(false);
useEffect(() => {
async function getInstalledApp(appCredentialType: string) {
const queryParam = new URLSearchParams();
queryParam.set("app-credential-type", appCredentialType);
try {
const result = await fetch(`/api/app-store/installed?${queryParam.toString()}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (result.status === 200) {
setInstalledApp(true);
}
} catch (error) {
if (error instanceof Error) {
console.log(error.message);
}
}
}
getInstalledApp(type);
}, []);
return (
<>
<Shell large>
@ -83,7 +104,7 @@ export default function App({
</div>
<div className="mt-4 sm:mt-0 sm:text-right">
{isGlobal ? (
{isGlobal || installedApp ? (
<Button color="secondary" disabled title="This app is globally installed">
{t("installed")}
</Button>

View File

@ -0,0 +1,34 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getSession } from "@lib/auth";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
req.session = await getSession({ req });
if (req.method === "GET" && req.session && req.session.user.id && req.query) {
const { "app-credential-type": appCredentialType } = req.query;
if (!appCredentialType && Array.isArray(appCredentialType)) {
return res.status(400);
}
const userId = req.session.user.id;
try {
const installedApp = await prisma?.credential.findFirst({
where: {
type: appCredentialType as string,
userId: userId,
},
});
if (installedApp && !!installedApp.key) {
res.status(200);
} else {
res.status(404);
}
} catch (error) {
res.status(500);
}
} else {
res.status(400);
}
res.end();
}

View File

@ -46,7 +46,7 @@ export default function Bookings() {
return (
<Shell heading={t("bookings")} subtitle={t("bookings_description")}>
<WipeMyCalActionButton trpc={trpc} />
<WipeMyCalActionButton trpc={trpc} bookingStatus={status} bookingsEmpty={isEmpty} />
<BookingsShell>
<div className="-mx-4 flex flex-col sm:mx-auto">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">

View File

@ -69,7 +69,7 @@
"request_reschedule_title_attendee": "Request to reschedule your booking",
"request_reschedule_subtitle": "{{organizer}} has cancelled the booking and requested you to pick another time.",
"request_reschedule_title_organizer": "You have requested {{attendee}} to reschedule",
"request_reschedule_subtitle_organizer": "You have cancelled the booking and {{attendee}} should be pick a new booking time with you.",
"request_reschedule_subtitle_organizer": "You have cancelled the booking and {{attendee}} should pick a new booking time with you.",
"reschedule_reason": "Reason for reschedule",
"hi_user_name": "Hi {{name}}",
"ics_event_title": "{{eventType}} with {{name}}",
@ -89,7 +89,7 @@
"meeting_url": "Meeting URL",
"meeting_request_rejected": "Your meeting request has been rejected",
"rescheduled_event_type_subject": "Rescheduled: {{eventType}} with {{name}} at {{date}}",
"requested_to_reschedule_subject_attendee": "Action Required Reschedule: Please book a new to time for {{eventType}} with {{name}}",
"requested_to_reschedule_subject_attendee": "Action Required Reschedule: Please book a new time for {{eventType}} with {{name}}",
"rejected_event_type_with_organizer": "Rejected: {{eventType}} with {{organizer}} on {{date}}",
"hi": "Hi",
"join_team": "Join team",
@ -735,7 +735,7 @@
"personal_note": "Name this key",
"personal_note_placeholder": "E.g. Development",
"api_key_no_note": "Nameless API key",
"api_key_never_expires":"This API key has no expiration date",
"api_key_never_expires": "This API key has no expiration date",
"edit_api_key": "Edit API key",
"never_expire_key": "Never expires",
"delete_api_key": "Revoke API key",

View File

@ -12,10 +12,13 @@ function useAddAppMutation(type: App["type"], options?: Parameters<typeof useMut
};
const stateStr = encodeURIComponent(JSON.stringify(state));
const searchParams = `?state=${stateStr}`;
const res = await fetch(`/api/integrations/${appName}/add` + searchParams);
if (!res.ok) {
throw new Error("Something went wrong");
}
const json = await res.json();
window.location.href = json.url;
}, options);

View File

@ -38,5 +38,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
return res.status(500);
}
return res.redirect("/apps/installed");
return res.status(200).json({ url: "/apps/installed" });
}

View File

@ -6,25 +6,32 @@ import { ConfirmDialog } from "./confirmDialog";
interface IWipeMyCalActionButtonProps {
trpc: any;
bookingsEmpty: boolean;
bookingStatus: "upcoming" | "past" | "cancelled";
}
const WipeMyCalActionButton = (props: IWipeMyCalActionButtonProps) => {
const { trpc } = props;
const { trpc, bookingsEmpty, bookingStatus } = props;
const [openDialog, setOpenDialog] = useState(false);
const { isSuccess, isLoading, data } = trpc.useQuery(["viewer.integrations"]);
if (bookingStatus !== "upcoming" || bookingsEmpty) {
return <></>;
}
const wipeMyCalCredentials: { credentialIds: number[] } = data?.other?.items.find(
(item: { type: string }) => item.type === "wipemycal_other"
);
const [credentialId] = wipeMyCalCredentials?.credentialIds || [false];
return (
<div>
{data &&
isSuccess &&
!isLoading &&
data?.other?.items.find((item: { type: string }) => item.type === "wipemycal_other") && (
<>
<ConfirmDialog trpc={trpc} isOpenDialog={openDialog} setIsOpenDialog={setOpenDialog} />
<Button onClick={() => setOpenDialog(true)}>Wipe Today</Button>
</>
)}
{data && isSuccess && !isLoading && credentialId && (
<>
<ConfirmDialog trpc={trpc} isOpenDialog={openDialog} setIsOpenDialog={setOpenDialog} />
<Button onClick={() => setOpenDialog(true)}>Wipe Today</Button>
</>
)}
</div>
);
};