* Fixes round #1 * disabled any warning for intentional typing of AsyncReturnType * Whacked MetaMask add / remove button * types, not great, not terrible, better than any * Fixed typo in CheckboxField and wrapped description in <label> * Feedback Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Peer Richelsen
zomars
kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
parent
547b40913f
commit
ba04533de3
@@ -62,7 +62,8 @@ const useOptions = () => {
|
||||
const filter = useCallback(
|
||||
({ offset, limit, current }: { offset?: ConfigType; limit?: ConfigType; current?: ConfigType }) => {
|
||||
if (current) {
|
||||
setFilteredOptions([options.find((option) => option.value === dayjs(current).toDate().valueOf())!]);
|
||||
const currentOption = options.find((option) => option.value === dayjs(current).toDate().valueOf());
|
||||
if (currentOption) setFilteredOptions([currentOption]);
|
||||
} else
|
||||
setFilteredOptions(
|
||||
options.filter((option) => {
|
||||
|
||||
@@ -35,7 +35,7 @@ const CustomInputTypeForm: FC<Props> = (props) => {
|
||||
defaultValues,
|
||||
});
|
||||
const selectedInputType = useWatch({ name: "type", control });
|
||||
const selectedInputOption = inputOptions.find((e) => selectedInputType === e.value)!;
|
||||
const selectedInputOption = inputOptions.find((e) => selectedInputType === e.value);
|
||||
|
||||
const onCancel = () => {
|
||||
props.onCancel();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { MembershipRole } from "@prisma/client";
|
||||
import { useState } from "react";
|
||||
import React, { SyntheticEvent, useEffect } from "react";
|
||||
import { SyntheticEvent, useMemo, useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import Button from "@calcom/ui/Button";
|
||||
@@ -11,12 +10,10 @@ import ModalContainer from "@components/ui/ModalContainer";
|
||||
import Select from "@components/ui/form/Select";
|
||||
|
||||
type MembershipRoleOption = {
|
||||
label: string;
|
||||
value: MembershipRole;
|
||||
label?: string;
|
||||
};
|
||||
|
||||
const options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }, { value: "OWNER" }];
|
||||
|
||||
export default function MemberChangeRoleModal(props: {
|
||||
isOpen: boolean;
|
||||
currentMember: MembershipRole;
|
||||
@@ -25,18 +22,32 @@ export default function MemberChangeRoleModal(props: {
|
||||
initialRole: MembershipRole;
|
||||
onExit: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
options.forEach((option, i) => {
|
||||
options[i].label = t(option.value.toLowerCase());
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
const { t } = useLocale();
|
||||
|
||||
const [role, setRole] = useState(
|
||||
options.find((option) => option.value === props.initialRole || MembershipRole.MEMBER)!
|
||||
const options = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
label: t("member"),
|
||||
value: MembershipRole.MEMBER,
|
||||
},
|
||||
{
|
||||
label: t("admin"),
|
||||
value: MembershipRole.ADMIN,
|
||||
},
|
||||
{
|
||||
label: t("owner"),
|
||||
value: MembershipRole.OWNER,
|
||||
},
|
||||
].filter(({ value }) => value !== MembershipRole.OWNER || props.currentMember === MembershipRole.OWNER);
|
||||
}, [t, props.currentMember]);
|
||||
|
||||
const [role, setRole] = useState<MembershipRoleOption>(
|
||||
options.find((option) => option.value === props.initialRole) || {
|
||||
label: t("member"),
|
||||
value: MembershipRole.MEMBER,
|
||||
}
|
||||
);
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useContext();
|
||||
|
||||
const changeRoleMutation = trpc.useMutation("viewer.teams.changeMemberRole", {
|
||||
@@ -76,7 +87,7 @@ export default function MemberChangeRoleModal(props: {
|
||||
{/*<option value="OWNER">{t("owner")}</option> - needs dialog to confirm change of ownership */}
|
||||
<Select
|
||||
isSearchable={false}
|
||||
options={props.currentMember !== MembershipRole.OWNER ? options.slice(0, 2) : options}
|
||||
options={options}
|
||||
value={role}
|
||||
onChange={(option) => option && setRole(option)}
|
||||
id="role"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import React, { PropsWithChildren } from "react";
|
||||
|
||||
import { Dialog, DialogContent } from "@calcom/ui/Dialog";
|
||||
|
||||
interface Props extends React.PropsWithChildren<any> {
|
||||
wide?: boolean;
|
||||
scroll?: boolean;
|
||||
noPadding?: boolean;
|
||||
isOpen: boolean;
|
||||
onExit: () => void;
|
||||
}
|
||||
|
||||
export default function ModalContainer(props: Props) {
|
||||
export default function ModalContainer(
|
||||
props: PropsWithChildren<{
|
||||
wide?: boolean;
|
||||
scroll?: boolean;
|
||||
noPadding?: boolean;
|
||||
isOpen: boolean;
|
||||
onExit: () => void;
|
||||
}>
|
||||
) {
|
||||
return (
|
||||
<div className="flex min-h-screen items-end justify-center px-4 pt-4 pb-20 text-center sm:block sm:p-0">
|
||||
<Dialog open={props.isOpen} onOpenChange={props.onExit}>
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import { ChatAltIcon } from "@heroicons/react/solid";
|
||||
import { useState } from "react";
|
||||
import { HelpScout, useChat } from "react-live-chat-loader";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { DropdownMenuItem } from "@calcom/ui/Dropdown";
|
||||
|
||||
import classNames from "@lib/classNames";
|
||||
|
||||
export default function HelpscoutMenuItem() {
|
||||
const { t } = useLocale();
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
const [state, loadChat] = useChat();
|
||||
const [, loadChat] = useChat();
|
||||
|
||||
function handleClick() {
|
||||
setActive(true);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from "react";
|
||||
import { LiveChatLoaderProvider } from "react-live-chat-loader";
|
||||
|
||||
const Provider: FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
<LiveChatLoaderProvider providerKey={process.env.NEXT_PUBLIC_HELPSCOUT_KEY!} provider="helpScout">
|
||||
<LiveChatLoaderProvider providerKey={process.env.NEXT_PUBLIC_HELPSCOUT_KEY || ""} provider="helpScout">
|
||||
<>{children}</>
|
||||
</LiveChatLoaderProvider>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import { ChatAltIcon } from "@heroicons/react/solid";
|
||||
|
||||
import { DropdownMenuItem } from "@calcom/ui/Dropdown";
|
||||
|
||||
import classNames from "@lib/classNames";
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import { useIntercom } from "./useIntercom";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from "react";
|
||||
import { IntercomProvider } from "react-use-intercom";
|
||||
|
||||
const Provider: FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
<IntercomProvider appId={process.env.NEXT_PUBLIC_INTERCOM_APP_ID!}>{children}</IntercomProvider>
|
||||
<IntercomProvider appId={process.env.NEXT_PUBLIC_INTERCOM_APP_ID || ""}>{children}</IntercomProvider>
|
||||
);
|
||||
|
||||
export default Provider;
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { ChatAltIcon } from "@heroicons/react/solid";
|
||||
import Script from "next/script";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { DropdownMenuItem } from "@calcom/ui/Dropdown";
|
||||
|
||||
import classNames from "@lib/classNames";
|
||||
|
||||
const ZENDESK_KEY = process.env.NEXT_PUBLIC_ZENDESK_KEY;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from "react";
|
||||
const isInteractionObserverSupported = typeof window !== "undefined" && "IntersectionObserver" in window;
|
||||
|
||||
export const useInViewObserver = (onInViewCallback: () => void) => {
|
||||
const [node, setRef] = React.useState<any>(null);
|
||||
const [node, setRef] = React.useState<HTMLElement | null>(null);
|
||||
|
||||
const onInViewCallbackRef = React.useRef(onInViewCallback);
|
||||
onInViewCallbackRef.current = onInViewCallback;
|
||||
|
||||
@@ -4,11 +4,7 @@ import { baseEventTypeSelect } from "@calcom/prisma";
|
||||
|
||||
import prisma from "@lib/prisma";
|
||||
|
||||
type AsyncReturnType<T extends (...args: any) => Promise<any>> = T extends (...args: any) => Promise<infer R>
|
||||
? R
|
||||
: any;
|
||||
|
||||
export type TeamWithMembers = AsyncReturnType<typeof getTeamWithMembers>;
|
||||
export type TeamWithMembers = Awaited<ReturnType<typeof getTeamWithMembers>>;
|
||||
|
||||
export async function getTeamWithMembers(id?: number, slug?: string) {
|
||||
const userSelect = Prisma.validator<Prisma.UserSelect>()({
|
||||
|
||||
@@ -5,6 +5,14 @@ import { getSession } from "@lib/auth";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
type CalendlyEventType = {
|
||||
name: string;
|
||||
slug: string;
|
||||
duration: number;
|
||||
description_plain: string;
|
||||
secret: boolean;
|
||||
};
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const session = await getSession({ req });
|
||||
const authenticatedUser = await prisma.user.findFirst({
|
||||
@@ -50,7 +58,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const eventTypesData = await eventTypesResult.json();
|
||||
|
||||
eventTypesData.collection.forEach(async (eventType: any) => {
|
||||
eventTypesData.collection.forEach(async (eventType: CalendlyEventType) => {
|
||||
await prisma.eventType.create({
|
||||
data: {
|
||||
title: eventType.name,
|
||||
|
||||
@@ -5,6 +5,14 @@ import { getSession } from "@lib/auth";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
type SavvyCalEventType = {
|
||||
name: string;
|
||||
slug: string;
|
||||
durations: [number];
|
||||
description: string;
|
||||
state: "active";
|
||||
};
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const session = await getSession({ req });
|
||||
const authenticatedUser = await prisma.user.findFirst({
|
||||
@@ -50,7 +58,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const eventTypesData = await eventTypesResult.json();
|
||||
|
||||
eventTypesData.entries.forEach(async (eventType: any) => {
|
||||
eventTypesData.entries.forEach(async (eventType: SavvyCalEventType) => {
|
||||
await prisma.eventType.create({
|
||||
data: {
|
||||
title: eventType.name,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getSession } from "@lib/auth";
|
||||
import prisma from "@lib/prisma";
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (!["GET", "DELETE"].includes(req.method!)) {
|
||||
if (!["GET", "DELETE"].includes(req.method || "")) {
|
||||
return res.status(405).end();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
return res.status(401).json({ message: "Not authenticated" });
|
||||
}
|
||||
|
||||
if (!["GET", "POST"].includes(req.method!)) {
|
||||
if (!["GET", "POST"].includes(req.method || "")) {
|
||||
throw new HttpCode({ statusCode: 405, message: "Method Not Allowed" });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ArrowRightIcon, ViewGridIcon } from "@heroicons/react/solid";
|
||||
import Image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { JSONObject } from "superjson/dist/types";
|
||||
import React from "react";
|
||||
|
||||
import { InstallAppButton } from "@calcom/app-store/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -186,17 +185,16 @@ function Web3Container() {
|
||||
function Web3ConnectBtn() {
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useContext();
|
||||
const [connectionBtn, setConnection] = useState(false);
|
||||
const result = trpc.useQuery(["viewer.web3Integration"]);
|
||||
const mutation = trpc.useMutation("viewer.enableOrDisableWeb3", {
|
||||
onSuccess: async (result) => {
|
||||
const { key = {} } = result as JSONObject;
|
||||
|
||||
if ((key as JSONObject).isWeb3Active) {
|
||||
const { key } = result;
|
||||
if ((key as { isWeb3Active: boolean }).isWeb3Active) {
|
||||
showToast(t("web3_metamask_added"), "success");
|
||||
} else {
|
||||
showToast(t("web3_metamask_disconnected"), "success");
|
||||
}
|
||||
utils.invalidateQueries("viewer.web3Integration");
|
||||
},
|
||||
onError: (err) => {
|
||||
if (err instanceof HttpError) {
|
||||
@@ -206,26 +204,16 @@ function Web3ConnectBtn() {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (result.data) {
|
||||
setConnection(result.data.isWeb3Active as boolean);
|
||||
}
|
||||
}, [result]);
|
||||
|
||||
const enableOrDisableWeb3 = async (mutation: any) => {
|
||||
const result = await mutation.mutateAsync({});
|
||||
setConnection(result.key.isWeb3Active);
|
||||
utils.invalidateQueries("viewer.web3Integration");
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
loading={mutation.isLoading}
|
||||
color={connectionBtn ? "warn" : "secondary"}
|
||||
color={result.data?.isWeb3Active ? "warn" : "secondary"}
|
||||
disabled={result.isLoading || mutation.isLoading}
|
||||
onClick={async () => await enableOrDisableWeb3(mutation)}
|
||||
onClick={() => {
|
||||
mutation.mutateAsync({});
|
||||
}}
|
||||
data-testid="metamask">
|
||||
{connectionBtn ? t("remove") : t("add")}
|
||||
{result.data?.isWeb3Active ? t("remove") : t("add")}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -172,12 +172,9 @@ export default function Onboarding(props: inferSSRProps<typeof getServerSideProp
|
||||
const handleConfirmStep = async () => {
|
||||
try {
|
||||
setSubmitting(true);
|
||||
if (
|
||||
steps[currentStep] &&
|
||||
steps[currentStep].onComplete &&
|
||||
typeof steps[currentStep].onComplete === "function"
|
||||
) {
|
||||
await steps[currentStep].onComplete!();
|
||||
const onComplete = steps[currentStep]?.onComplete;
|
||||
if (onComplete) {
|
||||
await onComplete();
|
||||
}
|
||||
incrementStep();
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -30,7 +30,7 @@ const page = sandboxPage(function BadgePage() {
|
||||
)}
|
||||
</code>
|
||||
</h3>
|
||||
<Badge {...(props as any)}>Badge text</Badge>
|
||||
<Badge {...props}>Badge text</Badge>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,7 @@ const page = sandboxPage(function ButtonPage() {
|
||||
)}
|
||||
</code>
|
||||
</h3>
|
||||
<Button {...(props as any)}>Button text</Button>
|
||||
<Button {...props}>Button text</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,6 @@ import { TextField } from "@calcom/ui/form/fields";
|
||||
import { getSession } from "@lib/auth";
|
||||
|
||||
import SettingsShell from "@components/SettingsShell";
|
||||
import Shell from "@components/Shell";
|
||||
|
||||
function AdminView() {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -581,11 +581,18 @@ const loggedInViewerRouter = createProtectedRouter()
|
||||
});
|
||||
|
||||
if (web3Credential) {
|
||||
return ctx.prisma.credential.delete({
|
||||
const deleted = await ctx.prisma.credential.delete({
|
||||
where: {
|
||||
id: web3Credential.id,
|
||||
},
|
||||
});
|
||||
return {
|
||||
...deleted,
|
||||
key: {
|
||||
...(deleted.key as JSONObject),
|
||||
isWeb3Active: false,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return ctx.prisma.credential.create({
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user