Merge branch 'main' into pr/6775
This commit is contained in:
commit
17c374e7d4
|
@ -5,6 +5,7 @@ import { FormEvent, useRef, useState } from "react";
|
|||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, Editor, ImageUploader, Label, showToast } from "@calcom/ui";
|
||||
|
@ -34,6 +35,7 @@ const UserProfile = (props: IUserProfileProps) => {
|
|||
const utils = trpc.useContext();
|
||||
const router = useRouter();
|
||||
const createEventType = trpc.viewer.eventTypes.create.useMutation();
|
||||
const telemetry = useTelemetry();
|
||||
|
||||
const mutation = trpc.viewer.updateProfile.useMutation({
|
||||
onSuccess: async (_data, context) => {
|
||||
|
@ -64,6 +66,8 @@ const UserProfile = (props: IUserProfileProps) => {
|
|||
const onSubmit = handleSubmit((data: { bio: string }) => {
|
||||
const { bio } = data;
|
||||
|
||||
telemetry.event(telemetryEventTypes.onboardingFinished);
|
||||
|
||||
mutation.mutate({
|
||||
bio,
|
||||
completedOnboarding: true,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { ArrowRightIcon } from "@heroicons/react/outline";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, TimezoneSelect } from "@calcom/ui";
|
||||
|
||||
|
@ -20,7 +21,7 @@ const UserSettings = (props: IUserSettingsProps) => {
|
|||
const { user, nextStep } = props;
|
||||
const { t } = useLocale();
|
||||
const [selectedTimeZone, setSelectedTimeZone] = useState(dayjs.tz.guess());
|
||||
|
||||
const telemetry = useTelemetry();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
|
@ -31,6 +32,11 @@ const UserSettings = (props: IUserSettingsProps) => {
|
|||
},
|
||||
reValidateMode: "onChange",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
telemetry.event(telemetryEventTypes.onboardingStarted);
|
||||
}, [telemetry]);
|
||||
|
||||
const defaultOptions = { required: true, maxLength: 255 };
|
||||
|
||||
const utils = trpc.useContext();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { IS_SELF_HOSTED } from "@calcom/lib/constants";
|
||||
|
@ -6,6 +5,8 @@ import { User } from "@calcom/prisma/client";
|
|||
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||
import { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
|
||||
import useRouterQuery from "@lib/hooks/useRouterQuery";
|
||||
|
||||
import { PremiumTextfield } from "./PremiumTextfield";
|
||||
import { UsernameTextfield } from "./UsernameTextfield";
|
||||
|
||||
|
@ -21,7 +22,7 @@ export const UsernameAvailabilityField = ({
|
|||
onErrorMutation,
|
||||
user,
|
||||
}: UsernameAvailabilityFieldProps) => {
|
||||
const [currentUsername, setCurrentUsername] = useState(user.username ?? "");
|
||||
const { username: currentUsername, setQuery: setCurrentUsername } = useRouterQuery("username");
|
||||
const formMethods = useForm({
|
||||
defaultValues: {
|
||||
username: currentUsername,
|
||||
|
|
|
@ -88,7 +88,7 @@ const withQuery = <
|
|||
TInput = inferProcedureInput<TQuery>,
|
||||
TOutput = inferProcedureOutput<TQuery>
|
||||
>(
|
||||
queryProcedure: DecorateProcedure<TQuery, any>,
|
||||
queryProcedure: DecorateProcedure<TQuery, any, any>,
|
||||
input?: TInput,
|
||||
params?: UseTRPCQueryOptions<any, TInput, TOutput, TOutput, TError>
|
||||
) => {
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
import { DefaultSeo } from "next-seo";
|
||||
import Head from "next/head";
|
||||
import Script from "next/script";
|
||||
import superjson from "superjson";
|
||||
|
||||
import "@calcom/embed-core/src/embed-iframe";
|
||||
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
|
||||
import { httpBatchLink } from "@calcom/trpc/client/links/httpBatchLink";
|
||||
import { httpLink } from "@calcom/trpc/client/links/httpLink";
|
||||
import { loggerLink } from "@calcom/trpc/client/links/loggerLink";
|
||||
import { splitLink } from "@calcom/trpc/client/links/splitLink";
|
||||
import { withTRPC } from "@calcom/trpc/next";
|
||||
import type { TRPCClientErrorLike } from "@calcom/trpc/react";
|
||||
import { Maybe } from "@calcom/trpc/server";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
||||
import AppProviders, { AppProps } from "@lib/app-providers";
|
||||
import { seoConfig } from "@lib/config/next-seo.config";
|
||||
|
@ -70,79 +62,4 @@ function MyApp(props: AppProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withTRPC<AppRouter>({
|
||||
config() {
|
||||
const url =
|
||||
typeof window !== "undefined"
|
||||
? "/api/trpc"
|
||||
: process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}/api/trpc`
|
||||
: `http://${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/trpc`;
|
||||
|
||||
/**
|
||||
* If you want to use SSR, you need to use the server's full URL
|
||||
* @link https://trpc.io/docs/ssr
|
||||
*/
|
||||
return {
|
||||
/**
|
||||
* @link https://trpc.io/docs/links
|
||||
*/
|
||||
links: [
|
||||
// adds pretty logs to your console in development and logs errors in production
|
||||
loggerLink({
|
||||
enabled: (opts) =>
|
||||
!!process.env.NEXT_PUBLIC_DEBUG || (opts.direction === "down" && opts.result instanceof Error),
|
||||
}),
|
||||
splitLink({
|
||||
// check for context property `skipBatch`
|
||||
condition: (op) => {
|
||||
return op.context.skipBatch === true;
|
||||
},
|
||||
// when condition is true, use normal request
|
||||
true: httpLink({ url }),
|
||||
// when condition is false, use batching
|
||||
false: httpBatchLink({
|
||||
url,
|
||||
/** @link https://github.com/trpc/trpc/issues/2008 */
|
||||
// maxBatchSize: 7
|
||||
}),
|
||||
}),
|
||||
],
|
||||
/**
|
||||
* @link https://react-query.tanstack.com/reference/QueryClient
|
||||
*/
|
||||
queryClientConfig: {
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
/**
|
||||
* 1s should be enough to just keep identical query waterfalls low
|
||||
* @example if one page components uses a query that is also used further down the tree
|
||||
*/
|
||||
staleTime: 1000,
|
||||
/**
|
||||
* Retry `useQuery()` calls depending on this function
|
||||
*/
|
||||
retry(failureCount, _err) {
|
||||
const err = _err as never as Maybe<TRPCClientErrorLike<AppRouter>>;
|
||||
const code = err?.data?.code;
|
||||
if (code === "BAD_REQUEST" || code === "FORBIDDEN" || code === "UNAUTHORIZED") {
|
||||
// if input data is wrong or you're not authorized there's no point retrying a query
|
||||
return false;
|
||||
}
|
||||
const MAX_QUERY_RETRIES = 3;
|
||||
return failureCount < MAX_QUERY_RETRIES;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
/**
|
||||
* @link https://trpc.io/docs/data-transformers
|
||||
*/
|
||||
transformer: superjson,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* @link https://trpc.io/docs/ssr
|
||||
*/
|
||||
ssr: false,
|
||||
})(MyApp);
|
||||
export default trpc.withTRPC(MyApp);
|
||||
|
|
|
@ -182,8 +182,6 @@ export default function Login({
|
|||
StartIcon={FaGoogle}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault();
|
||||
// track Google logins. Without personal data/payload
|
||||
telemetry.event(telemetryEventTypes.googleLogin, collectPageParameters());
|
||||
await signIn("google");
|
||||
}}>
|
||||
{t("signin_with_google")}
|
||||
|
|
|
@ -100,9 +100,11 @@ export default function Setup(props: inferSSRProps<typeof getServerSideProps>) {
|
|||
const currentStep = isFreeLicense ? 3 : 4;
|
||||
return (
|
||||
<AdminAppsList
|
||||
id={`wizard-step-${currentStep}`}
|
||||
name={`wizard-step-${currentStep}`}
|
||||
classNames={{
|
||||
form: "mb-4 rounded-md bg-white px-0 pt-0 md:max-w-full",
|
||||
appCategoryNavigationContainer: " max-h-[400px] overflow-y-auto md:p-4",
|
||||
appCategoryNavigationContainer: "max-h-[400px] overflow-y-auto md:p-4",
|
||||
verticalTabsItem: "!w-48 md:p-4",
|
||||
}}
|
||||
baseURL={`/auth/setup?step=${currentStep}`}
|
||||
|
@ -127,7 +129,6 @@ export default function Setup(props: inferSSRProps<typeof getServerSideProps>) {
|
|||
finishLabel={t("finish")}
|
||||
prevLabel={t("prev_step")}
|
||||
stepLabel={(currentStep, maxSteps) => t("current_step_of_total", { currentStep, maxSteps })}
|
||||
containerClassname="md:w-[800px]"
|
||||
/>
|
||||
</main>
|
||||
</>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import dayjs from "@calcom/dayjs";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview";
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { yyyymmdd } from "@calcom/lib/date-fns";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { RouterOutputs, trpc } from "@calcom/trpc/react";
|
||||
import { SkeletonText } from "@calcom/ui";
|
||||
|
@ -18,13 +16,13 @@ export interface IBusySlot {
|
|||
}
|
||||
|
||||
const AvailabilityView = ({ user }: { user: User }) => {
|
||||
const { t } = useLocale();
|
||||
const { date, setQuery: setSelectedDate } = useRouterQuery("date");
|
||||
const selectedDate = dayjs(date);
|
||||
const formattedSelectedDate = selectedDate.format("YYYY-MM-DD");
|
||||
|
||||
const { data } = trpc.viewer.availability.user.useQuery(
|
||||
const { data, isLoading } = trpc.viewer.availability.user.useQuery(
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
username: user.username!,
|
||||
dateFrom: selectedDate.startOf("day").utc().format(),
|
||||
dateTo: selectedDate.endOf("day").utc().format(),
|
||||
|
@ -47,26 +45,70 @@ const AvailabilityView = ({ user }: { user: User }) => {
|
|||
}, [] as IBusySlot[]) || [];
|
||||
|
||||
return (
|
||||
<div className="max-w-xl overflow-hidden rounded-md border border-gray-200 bg-white">
|
||||
<div className="px-4">
|
||||
<Calendar
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
events={[...(data?.busy || []), ...overrides]
|
||||
.sort((a: IBusySlot, b: IBusySlot) => (a.start > b.start ? -1 : 1))
|
||||
.map((slot) => ({
|
||||
// TODO: Modify the Calendar view to be better at displaying blocks.
|
||||
id: undefined,
|
||||
title:
|
||||
(slot.title ? `(${slot.title}) - ` : "") + (slot.source ? `(source: ${slot.source})` : ""),
|
||||
start: new Date(slot.start),
|
||||
end: new Date(slot.end),
|
||||
}))}
|
||||
onDateChange={(e) => setSelectedDate(yyyymmdd(e))}
|
||||
startDate={selectedDate.startOf("day").toDate()}
|
||||
endDate={selectedDate.endOf("day").toDate()}
|
||||
view="day"
|
||||
<div className="max-w-xl overflow-hidden rounded-md bg-white shadow">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
{t("overview_of_day")}{" "}
|
||||
<input
|
||||
type="date"
|
||||
className="inline h-8 border-none p-0"
|
||||
defaultValue={formattedSelectedDate}
|
||||
onChange={(e) => {
|
||||
if (e.target.value) setSelectedDate(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<small className="block text-gray-400">{t("hover_over_bold_times_tip")}</small>
|
||||
<div className="mt-4 space-y-4">
|
||||
<div className="bg-brand dark:bg-darkmodebrand overflow-hidden rounded-md">
|
||||
<div className="text-brandcontrast dark:text-darkmodebrandcontrast px-4 py-2 sm:px-6">
|
||||
{t("your_day_starts_at")} {convertMinsToHrsMins(user.startTime)}
|
||||
</div>
|
||||
</div>
|
||||
{(() => {
|
||||
if (isLoading)
|
||||
return (
|
||||
<>
|
||||
<SkeletonText className="block h-16 w-full" />
|
||||
<SkeletonText className="block h-16 w-full" />
|
||||
</>
|
||||
);
|
||||
|
||||
if (data && (data.busy.length > 0 || overrides.length > 0))
|
||||
return [...data.busy, ...overrides]
|
||||
.sort((a: IBusySlot, b: IBusySlot) => (a.start > b.start ? -1 : 1))
|
||||
.map((slot: IBusySlot) => (
|
||||
<div
|
||||
key={dayjs(slot.start).format("HH:mm")}
|
||||
className="overflow-hidden rounded-md bg-gray-100"
|
||||
data-testid="troubleshooter-busy-time">
|
||||
<div className="px-4 py-5 text-black sm:p-6">
|
||||
{t("calendar_shows_busy_between")}{" "}
|
||||
<span className="font-medium text-gray-800" title={dayjs(slot.start).format("HH:mm")}>
|
||||
{dayjs(slot.start).format("HH:mm")}
|
||||
</span>{" "}
|
||||
{t("and")}{" "}
|
||||
<span className="font-medium text-gray-800" title={dayjs(slot.end).format("HH:mm")}>
|
||||
{dayjs(slot.end).format("HH:mm")}
|
||||
</span>{" "}
|
||||
{t("on")} {dayjs(slot.start).format("D")}{" "}
|
||||
{t(dayjs(slot.start).format("MMMM").toLowerCase())} {dayjs(slot.start).format("YYYY")}
|
||||
{slot.title && ` - (${slot.title})`}
|
||||
{slot.source && <small>{` - (source: ${slot.source})`}</small>}
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
return (
|
||||
<div className="overflow-hidden rounded-md bg-gray-100">
|
||||
<div className="px-4 py-5 text-black sm:p-6">{t("calendar_no_busy_slots")}</div>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
|
||||
<div className="bg-brand dark:bg-darkmodebrand overflow-hidden rounded-md">
|
||||
<div className="text-brandcontrast dark:text-darkmodebrandcontrast px-4 py-2 sm:px-6">
|
||||
{t("your_day_ends_at")} {convertMinsToHrsMins(user.endTime)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -83,3 +125,11 @@ export default function Troubleshoot() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function convertMinsToHrsMins(mins: number) {
|
||||
const h = Math.floor(mins / 60);
|
||||
const m = mins % 60;
|
||||
const hs = h < 10 ? "0" + h : h;
|
||||
const ms = m < 10 ? "0" + m : m;
|
||||
return `${hs}:${ms}`;
|
||||
}
|
||||
|
|
|
@ -386,15 +386,13 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||
/>
|
||||
</Tooltip>
|
||||
<Dropdown modal={false}>
|
||||
<DropdownMenuTrigger
|
||||
asChild
|
||||
data-testid={"event-type-options-" + type.id}
|
||||
className="radix-state-open:rounded-r-md">
|
||||
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
|
||||
<Button
|
||||
type="button"
|
||||
variant="icon"
|
||||
color="secondary"
|
||||
StartIcon={FiMoreHorizontal}
|
||||
className="ltr:radix-state-open:rounded-r-md rtl:radix-state-open:rounded-l-md"
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
|
|
|
@ -56,7 +56,7 @@ export default function Signup({ prepopulateFormValues }: inferSSRProps<typeof g
|
|||
})
|
||||
.then(handleErrors)
|
||||
.then(async () => {
|
||||
telemetry.event(telemetryEventTypes.login, collectPageParameters());
|
||||
telemetry.event(telemetryEventTypes.signup, collectPageParameters());
|
||||
await signIn<"credentials">("credentials", {
|
||||
...data,
|
||||
callbackUrl: router.query.callbackUrl
|
||||
|
|
|
@ -32,16 +32,15 @@ test.describe("Availablity tests", () => {
|
|||
await page.locator('[form="availability-form"][type="submit"]').click();
|
||||
});
|
||||
|
||||
// The troubleshooter is unaware of the selected schedule, kept the override logic for now but needs rework.
|
||||
// await test.step("Date override is displayed in troubleshooter", async () => {
|
||||
// const response = await page.waitForResponse("**/api/trpc/viewer.availability.schedule.update?batch=1");
|
||||
// const json = await response.json();
|
||||
// // @ts-expect-error trust me bro
|
||||
// const date = json[0].result.data.json.schedule.availability.find((a) => !!a.date);
|
||||
// const troubleshooterURL = `/availability/troubleshoot?date=${dayjs(date.date).format("YYYY-MM-DD")}`;
|
||||
// await page.goto(troubleshooterURL);
|
||||
// await expect(page.locator('[data-testid="troubleshooter-busy-time"]')).toHaveCount(1);
|
||||
// });
|
||||
await test.step("Date override is displayed in troubleshooter", async () => {
|
||||
const response = await page.waitForResponse("**/api/trpc/viewer.availability.schedule.update?batch=1");
|
||||
const json = await response.json();
|
||||
// @ts-expect-error trust me bro
|
||||
const date = json[0].result.data.json.schedule.availability.find((a) => !!a.date);
|
||||
const troubleshooterURL = `/availability/troubleshoot?date=${dayjs(date.date).format("YYYY-MM-DD")}`;
|
||||
await page.goto(troubleshooterURL);
|
||||
await expect(page.locator('[data-testid="troubleshooter-busy-time"]')).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
|
||||
test("Availablity pages", async ({ page }) => {
|
||||
|
|
|
@ -5,7 +5,6 @@ import z from "zod";
|
|||
|
||||
import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button } from "@calcom/ui";
|
||||
import { FiLock } from "@calcom/ui/components/icon";
|
||||
|
@ -23,7 +22,6 @@ const schema = z.object({
|
|||
export function SAMLLogin({ samlTenantID, samlProductID, setErrorMessage }: Props) {
|
||||
const { t } = useLocale();
|
||||
const methods = useFormContext();
|
||||
const telemetry = useTelemetry();
|
||||
|
||||
const mutation = trpc.viewer.public.samlTenantProduct.useMutation({
|
||||
onSuccess: async (data) => {
|
||||
|
@ -43,9 +41,6 @@ export function SAMLLogin({ samlTenantID, samlProductID, setErrorMessage }: Prop
|
|||
onClick={async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// track Google logins. Without personal data/payload
|
||||
telemetry.event(telemetryEventTypes.googleLogin, collectPageParameters());
|
||||
|
||||
if (!HOSTED_CAL_FEATURES) {
|
||||
await signIn("saml", {}, { tenant: samlTenantID, product: samlProductID });
|
||||
return;
|
||||
|
|
|
@ -14,8 +14,7 @@ export function SchedulerHeading() {
|
|||
return (
|
||||
<header className="flex flex-none flex-col justify-between py-4 sm:flex-row sm:items-center">
|
||||
<h1 className="text-xl font-semibold text-gray-900">
|
||||
{startDate.format("MMM DD")}
|
||||
{!startDate.isSame(endDate, "day") ? `-${endDate.format("DD")}` : ""}
|
||||
{startDate.format("MMM DD")}-{endDate.format("DD")}
|
||||
<span className="text-gray-500">,{startDate.format("YYYY")}</span>
|
||||
</h1>
|
||||
<div className="flex items-center space-x-2 rtl:space-x-reverse">
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Controller, useForm } from "react-hook-form";
|
|||
|
||||
import type { SSOConnection } from "@calcom/ee/sso/lib/saml";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, DialogFooter, Form, showToast, TextField, Dialog, DialogContent } from "@calcom/ui";
|
||||
|
||||
|
@ -56,12 +55,10 @@ const CreateConnectionDialog = ({
|
|||
}) => {
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useContext();
|
||||
const telemetry = useTelemetry();
|
||||
const form = useForm<FormValues>();
|
||||
|
||||
const mutation = trpc.viewer.saml.updateOIDC.useMutation({
|
||||
async onSuccess() {
|
||||
telemetry.event(telemetryEventTypes.samlConfig, collectPageParameters());
|
||||
showToast(
|
||||
t("sso_connection_created_successfully", {
|
||||
connectionType: "OIDC",
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Controller, useForm } from "react-hook-form";
|
|||
|
||||
import type { SSOConnection } from "@calcom/ee/sso/lib/saml";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, DialogFooter, Form, showToast, TextArea, Dialog, DialogContent } from "@calcom/ui";
|
||||
|
||||
|
@ -54,12 +53,10 @@ const CreateConnectionDialog = ({
|
|||
}) => {
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useContext();
|
||||
const telemetry = useTelemetry();
|
||||
const form = useForm<FormValues>();
|
||||
|
||||
const mutation = trpc.viewer.saml.update.useMutation({
|
||||
async onSuccess() {
|
||||
telemetry.event(telemetryEventTypes.samlConfig, collectPageParameters());
|
||||
showToast(
|
||||
t("sso_connection_created_successfully", {
|
||||
connectionType: "SAML",
|
||||
|
|
|
@ -5,6 +5,7 @@ import { z } from "zod";
|
|||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import slugify from "@calcom/lib/slugify";
|
||||
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Avatar, Button, Form, ImageUploader, TextField } from "@calcom/ui";
|
||||
import { FiArrowRight } from "@calcom/ui/components/icon";
|
||||
|
@ -18,7 +19,7 @@ const querySchema = z.object({
|
|||
export const CreateANewTeamForm = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
|
||||
const telemetry = useTelemetry();
|
||||
const returnToParsed = querySchema.safeParse(router.query);
|
||||
|
||||
const returnToParam =
|
||||
|
@ -29,6 +30,7 @@ export const CreateANewTeamForm = () => {
|
|||
|
||||
const createTeamMutation = trpc.viewer.teams.create.useMutation({
|
||||
onSuccess: (data) => {
|
||||
telemetry.event(telemetryEventTypes.team_created);
|
||||
router.push(`/settings/teams/${data.id}/onboard-members`);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -114,13 +114,13 @@ export const EventTypeDescription = ({ eventType, className }: EventTypeDescript
|
|||
) : (
|
||||
<></>
|
||||
)}
|
||||
{eventType.seatsPerTimeSlot && (
|
||||
{eventType?.seatsPerTimeSlot ? (
|
||||
<li>
|
||||
<Badge variant="gray" size="lg" StartIcon={FiUser}>
|
||||
<p>{t("event_type_seats", { numberOfSeats: eventType.seatsPerTimeSlot })} </p>
|
||||
</Badge>
|
||||
</li>
|
||||
)}
|
||||
) : null}
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -12,12 +12,16 @@ export const telemetryEventTypes = {
|
|||
bookingConfirmed: "booking_confirmed",
|
||||
bookingCancelled: "booking_cancelled",
|
||||
importSubmitted: "import_submitted",
|
||||
googleLogin: "google_login",
|
||||
login: "login",
|
||||
samlLogin: "saml_login",
|
||||
samlConfig: "saml_config",
|
||||
embedView: "embed_view",
|
||||
embedBookingConfirmed: "embed_booking_confirmed",
|
||||
onboardingFinished: "onboarding_finished",
|
||||
onboardingStarted: "onboarding_started",
|
||||
signup: "signup",
|
||||
team_created: "team_created",
|
||||
website: {
|
||||
pageView: "website_page_view",
|
||||
},
|
||||
};
|
||||
|
||||
export function collectPageParameters(
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
"main": "index.ts",
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^4.3.9",
|
||||
"@trpc/client": "^10.0.0-rc.6",
|
||||
"@trpc/next": "^10.0.0-rc.6",
|
||||
"@trpc/react-query": "^10.0.0-rc.6",
|
||||
"@trpc/server": "^10.0.0-rc.6",
|
||||
"@trpc/client": "^10.10.0",
|
||||
"@trpc/next": "^10.10.0",
|
||||
"@trpc/react-query": "^10.10.0",
|
||||
"@trpc/server": "^10.10.0",
|
||||
"superjson": "1.9.1",
|
||||
"zod": "^3.20.2"
|
||||
}
|
||||
|
|
|
@ -1,17 +1,96 @@
|
|||
import superjson from "superjson";
|
||||
|
||||
import { createTRPCReact } from "@trpc/react-query";
|
||||
|
||||
import { httpBatchLink } from "../client/links/httpBatchLink";
|
||||
import { httpLink } from "../client/links/httpLink";
|
||||
import { loggerLink } from "../client/links/loggerLink";
|
||||
import { splitLink } from "../client/links/splitLink";
|
||||
import { createTRPCNext } from "../next";
|
||||
// ℹ️ Type-only import:
|
||||
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
|
||||
import type { inferRouterInputs, inferRouterOutputs } from "../server";
|
||||
import type { TRPCClientErrorLike } from "../react";
|
||||
import type { inferRouterInputs, inferRouterOutputs, Maybe } from "../server";
|
||||
import type { AppRouter } from "../server/routers/_app";
|
||||
|
||||
/**
|
||||
* A set of strongly-typed React hooks from your `AppRouter` type signature with `createTRPCReact`.
|
||||
* @link https://trpc.io/docs/v10/react#2-create-trpc-hooks
|
||||
*/
|
||||
export const trpc = createTRPCReact<AppRouter>();
|
||||
export const trpc = createTRPCNext<AppRouter>({
|
||||
config() {
|
||||
const url =
|
||||
typeof window !== "undefined"
|
||||
? "/api/trpc"
|
||||
: process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}/api/trpc`
|
||||
: `http://${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/trpc`;
|
||||
|
||||
/**
|
||||
* If you want to use SSR, you need to use the server's full URL
|
||||
* @link https://trpc.io/docs/ssr
|
||||
*/
|
||||
return {
|
||||
/**
|
||||
* @link https://trpc.io/docs/links
|
||||
*/
|
||||
links: [
|
||||
// adds pretty logs to your console in development and logs errors in production
|
||||
loggerLink({
|
||||
enabled: (opts) =>
|
||||
!!process.env.NEXT_PUBLIC_DEBUG || (opts.direction === "down" && opts.result instanceof Error),
|
||||
}),
|
||||
splitLink({
|
||||
// check for context property `skipBatch`
|
||||
condition: (op) => {
|
||||
return op.context.skipBatch === true;
|
||||
},
|
||||
// when condition is true, use normal request
|
||||
true: httpLink({ url }),
|
||||
// when condition is false, use batching
|
||||
false: httpBatchLink({
|
||||
url,
|
||||
/** @link https://github.com/trpc/trpc/issues/2008 */
|
||||
// maxBatchSize: 7
|
||||
}),
|
||||
}),
|
||||
],
|
||||
/**
|
||||
* @link https://react-query.tanstack.com/reference/QueryClient
|
||||
*/
|
||||
queryClientConfig: {
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
/**
|
||||
* 1s should be enough to just keep identical query waterfalls low
|
||||
* @example if one page components uses a query that is also used further down the tree
|
||||
*/
|
||||
staleTime: 1000,
|
||||
/**
|
||||
* Retry `useQuery()` calls depending on this function
|
||||
*/
|
||||
retry(failureCount, _err) {
|
||||
const err = _err as never as Maybe<TRPCClientErrorLike<AppRouter>>;
|
||||
const code = err?.data?.code;
|
||||
if (code === "BAD_REQUEST" || code === "FORBIDDEN" || code === "UNAUTHORIZED") {
|
||||
// if input data is wrong or you're not authorized there's no point retrying a query
|
||||
return false;
|
||||
}
|
||||
const MAX_QUERY_RETRIES = 3;
|
||||
return failureCount < MAX_QUERY_RETRIES;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
/**
|
||||
* @link https://trpc.io/docs/data-transformers
|
||||
*/
|
||||
transformer: superjson,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* @link https://trpc.io/docs/ssr
|
||||
*/
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
export const transformer = superjson;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export function ButtonGroup({ children, combined = false, containerProps }: Prop
|
|||
"flex",
|
||||
!combined
|
||||
? "space-x-2 rtl:space-x-reverse"
|
||||
: "ltr:[&>*:first-child]:rounded-l-md ltr:[&>*:first-child]:border-l rtl:[&>*:first-child]:rounded-r-md rtl:[&>*:first-child]:border-r ltr:[&>*:last-child]:rounded-r-md rtl:[&>*:last-child]:rounded-l-md [&_button]:rounded-none [&_button]:ltr:border-l-0 rtl:[&_button]:border-r-0 [&_a]:rounded-none ltr:[&_a]:border-l-0 rtl:[&_a]:border-r-0",
|
||||
: "ltr:[&>*:first-child]:ml-0 ltr:[&>*:first-child]:rounded-l-md ltr:[&>*:first-child]:border-l rtl:[&>*:first-child]:rounded-r-md rtl:[&>*:first-child]:border-r ltr:[&>*:last-child]:rounded-r-md rtl:[&>*:last-child]:rounded-l-md [&_button]:rounded-none [&_a]:rounded-none [&>a]:-ml-[1px] hover:[&>a]:z-[1] [&>button]:-ml-[1px] hover:[&>button]:z-[1]",
|
||||
containerProps?.className
|
||||
)}>
|
||||
{children}
|
||||
|
|
32
yarn.lock
32
yarn.lock
|
@ -7835,27 +7835,27 @@
|
|||
javascript-natural-sort "0.7.1"
|
||||
lodash "4.17.21"
|
||||
|
||||
"@trpc/client@^10.0.0-rc.6":
|
||||
version "10.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.0.0-rc.6.tgz#de30c9107facdf7d54e000c1e6b95de50bbe7acd"
|
||||
integrity sha512-/vyi0b9R+DOJgvYFFYSveRwIX4Ttu01Af0ORzZGsDHYZGB7lfSqHfQhizf+AHfEpQXQsJYy5ZFOt6RtvF6LuKg==
|
||||
"@trpc/client@^10.10.0":
|
||||
version "10.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.10.0.tgz#5abdbf399639f2fdfe605682d2cdf3f9dba87cb1"
|
||||
integrity sha512-HRVGkOsR4FIYpyQILP84HLbj6pRnLKgxy4AIelTf9d9TxD60M5bNhbR2Uz3hqNSb9a2ppaRJBLv7twlV9b4qHQ==
|
||||
|
||||
"@trpc/next@^10.0.0-rc.6":
|
||||
version "10.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.0.0-rc.6.tgz#9c9a81183cc4c49ba0f21ee009595639448cacd3"
|
||||
integrity sha512-YaQbctwvYYk1HlVcJedRyQGT1EP5QiKse+T7zNj4Be0ZAiNVJwedC4AQ9YQDh0nK6GXDoHGVk8ocSCkNvEBddw==
|
||||
"@trpc/next@^10.10.0":
|
||||
version "10.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.10.0.tgz#083ff327b68b005d60b19af07008377f830ad73a"
|
||||
integrity sha512-7d84L2OoF0RW06drTbNGOOggwMes8JxI3Ln/VOIaYeERzwOFNCtWPmGjWCdq4l1SKbXC6+baS+b9n5cXc+euwA==
|
||||
dependencies:
|
||||
react-ssr-prepass "^1.5.0"
|
||||
|
||||
"@trpc/react-query@^10.0.0-rc.6":
|
||||
version "10.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.0.0-rc.6.tgz#a10cc0b4dc3a849d260d086e0dc3faccac7515dc"
|
||||
integrity sha512-OHkoZLDz86Q7wez7ayLAZiWATePi+QkwavyNu/x6c0f/dC8n7CUIZAhAjUN4SuZYEeZxbW351QtPIQwODT2XVA==
|
||||
"@trpc/react-query@^10.10.0":
|
||||
version "10.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.10.0.tgz#1faf32056aa3ee5ecb2ffd0d15e8abbcd7eff911"
|
||||
integrity sha512-Jc/uii1MPevf95/z/W3ufYGHvrFvrtkjxQ8UuXhJCzOgv/FGPqhmA5PH124nLHEgGLBA7zQxHumofhdXosEhUQ==
|
||||
|
||||
"@trpc/server@^10.0.0-rc.6":
|
||||
version "10.0.0-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.0.0-rc.6.tgz#076df5ab371ede9226868474e71333041020ec8a"
|
||||
integrity sha512-8JAIX2SSTEwpdp+CRoPGsrj9A9qee0ltqa1fPXlKOtzQKbxDjGoqy6kVVh25YUJ8GJrXf4LhV8pZGkyZOOX6ow==
|
||||
"@trpc/server@^10.10.0":
|
||||
version "10.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.10.0.tgz#0b494335140d4fd5e1452f7b57dcc9b8886720a4"
|
||||
integrity sha512-tCTqcqBT+3nebYFTHtwM877qo5xQPtVlptxKdUzMVWleWT4lFTL4oddk45qVURToci2iMbVJjd4jQU9y9/XwlQ==
|
||||
|
||||
"@tryvital/vital-node@^1.4.6":
|
||||
version "1.4.6"
|
||||
|
|
Loading…
Reference in New Issue
Block a user