CAL-473 Fixes client-side routing for authed pages (#763)

This commit is contained in:
Omar López 2021-09-24 04:16:46 -06:00 committed by GitHub
parent d3d6778c60
commit 420daec147
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 62 additions and 53 deletions

View file

@ -1,18 +1,26 @@
import { Provider } from "next-auth/client"; import { Provider } from "next-auth/client";
import React from "react"; import React from "react";
import { QueryClient, QueryClientProvider } from "react-query"; import { HydrateProps, QueryClient, QueryClientProvider } from "react-query";
import { Hydrate } from "react-query/hydration"; import { Hydrate } from "react-query/hydration";
import { Session } from "@lib/auth";
import { createTelemetryClient, TelemetryProvider } from "@lib/telemetry"; import { createTelemetryClient, TelemetryProvider } from "@lib/telemetry";
export const queryClient = new QueryClient(); export const queryClient = new QueryClient();
const AppProviders: React.FC = (props, pageProps) => { type AppProviderProps = {
pageProps: {
session?: Session;
dehydratedState?: HydrateProps;
};
};
const AppProviders: React.FC<AppProviderProps> = ({ pageProps, children }) => {
return ( return (
<TelemetryProvider value={createTelemetryClient()}> <TelemetryProvider value={createTelemetryClient()}>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}> <Hydrate state={pageProps.dehydratedState}>
<Provider session={pageProps.session}>{props.children}</Provider> <Provider session={pageProps.session}>{children}</Provider>
</Hydrate> </Hydrate>
</QueryClientProvider> </QueryClientProvider>
</TelemetryProvider> </TelemetryProvider>

View file

@ -15,7 +15,7 @@ export type AppProps = NextAppProps & {
function MyApp({ Component, pageProps, err }: AppProps) { function MyApp({ Component, pageProps, err }: AppProps) {
return ( return (
<AppProviders> <AppProviders pageProps={pageProps}>
<DefaultSeo {...seoConfig.defaultNextSeo} /> <DefaultSeo {...seoConfig.defaultNextSeo} />
<Component {...pageProps} err={err} /> <Component {...pageProps} err={err} />
</AppProviders> </AppProviders>

View file

@ -6,6 +6,8 @@ import { asStringOrNull } from "@lib/asStringOrNull";
import { getBusyCalendarTimes } from "@lib/calendarClient"; import { getBusyCalendarTimes } from "@lib/calendarClient";
import prisma from "@lib/prisma"; import prisma from "@lib/prisma";
import { Prisma } from ".prisma/client";
export default async function handler(req: NextApiRequest, res: NextApiResponse) { export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const user = asStringOrNull(req.query.user); const user = asStringOrNull(req.query.user);
const dateFrom = dayjs(asStringOrNull(req.query.dateFrom)); const dateFrom = dayjs(asStringOrNull(req.query.dateFrom));
@ -32,19 +34,24 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}, },
}); });
const eventType = await prisma.eventType.findUnique({ const getEventType = (id: number) =>
where: { id: eventTypeId }, prisma.eventType.findUnique({
select: { where: { id },
timeZone: true, select: {
availability: { timeZone: true,
select: { availability: {
startTime: true, select: {
endTime: true, startTime: true,
days: true, endTime: true,
days: true,
},
}, },
}, },
}, });
});
type EventType = Prisma.PromiseReturnType<typeof getEventType>;
let eventType: EventType | null = null;
if (eventTypeId) eventType = await getEventType(eventTypeId);
if (!rawUser) throw new Error("No user found"); if (!rawUser) throw new Error("No user found");

View file

@ -339,6 +339,6 @@ export async function getServerSideProps(context) {
}, },
}); });
return { return {
props: { user, types }, // will be passed to the page component as props props: { session, user, types },
}; };
} }

View file

@ -1,24 +1,23 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import utc from "dayjs/plugin/utc"; import utc from "dayjs/plugin/utc";
import { GetServerSideProps } from "next"; import { GetServerSidePropsContext } from "next";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getSession } from "@lib/auth"; import { getSession } from "@lib/auth";
import prisma from "@lib/prisma"; import prisma from "@lib/prisma";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import Loader from "@components/Loader"; import Loader from "@components/Loader";
import Shell from "@components/Shell"; import Shell from "@components/Shell";
dayjs.extend(utc); dayjs.extend(utc);
export default function Troubleshoot({ user }) { export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSideProps>) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [availability, setAvailability] = useState([]); const [availability, setAvailability] = useState([]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars const [selectedDate] = useState(dayjs());
const [selectedDate, setSelectedDate] = useState(dayjs());
function convertMinsToHrsMins(mins) { function convertMinsToHrsMins(mins: number) {
let h = Math.floor(mins / 60); let h = Math.floor(mins / 60);
let m = mins % 60; let m = mins % 60;
h = h < 10 ? "0" + h : h; h = h < 10 ? "0" + h : h;
@ -97,9 +96,9 @@ export default function Troubleshoot({ user }) {
); );
} }
export const getServerSideProps: GetServerSideProps = async (context) => { export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const session = await getSession(context); const session = await getSession(context);
if (!session) { if (!session?.user?.id) {
return { redirect: { permanent: false, destination: "/auth/login" } }; return { redirect: { permanent: false, destination: "/auth/login" } };
} }
@ -114,7 +113,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
}, },
}); });
if (!user) return { redirect: { permanent: false, destination: "/auth/login" } };
return { return {
props: { user }, props: { session, user },
}; };
}; };

View file

@ -346,5 +346,5 @@ export async function getServerSideProps(context) {
return { ...booking, startTime: booking.startTime.toISOString(), endTime: booking.endTime.toISOString() }; return { ...booking, startTime: booking.startTime.toISOString(), endTime: booking.endTime.toISOString() };
}); });
return { props: { bookings } }; return { props: { session, bookings } };
} }

View file

@ -1350,6 +1350,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
return { return {
props: { props: {
session,
localeProp: locale, localeProp: locale,
eventType: eventTypeObject, eventType: eventTypeObject,
locationOptions, locationOptions,

View file

@ -475,7 +475,7 @@ const CreateNewEventDialog = ({
<div className="mt-1"> <div className="mt-1">
<div className="flex rounded-sm shadow-sm"> <div className="flex rounded-sm shadow-sm">
<span className="inline-flex items-center px-3 text-gray-500 border border-r-0 border-gray-300 rounded-l-md bg-gray-50 sm:text-sm"> <span className="inline-flex items-center px-3 text-gray-500 border border-r-0 border-gray-300 rounded-l-md bg-gray-50 sm:text-sm">
{location.hostname}/{router.query.eventPage || profiles[0].slug}/ {process.env.NEXT_PUBLIC_APP_URL}/{router.query.eventPage || profiles[0].slug}/
</span> </span>
<input <input
ref={slugRef} ref={slugRef}
@ -723,6 +723,7 @@ export async function getServerSideProps(context) {
return { return {
props: { props: {
session,
localeProp: locale, localeProp: locale,
canAddEvents, canAddEvents,
user: userObj, user: userObj,

View file

@ -98,6 +98,6 @@ export async function getServerSideProps(context) {
}, },
}); });
return { return {
props: { integration }, // will be passed to the page component as props props: { session, integration },
}; };
} }

View file

@ -495,6 +495,6 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
const integrations = getIntegrations(credentials); const integrations = getIntegrations(credentials);
return { return {
props: { integrations }, props: { session, integrations },
}; };
} }

View file

@ -44,6 +44,6 @@ export async function getServerSideProps(context) {
}); });
return { return {
props: { user }, // will be passed to the page component as props props: { session, user },
}; };
} }

View file

@ -1,20 +1,24 @@
import { GetServerSidePropsContext } from "next";
import { useSession } from "next-auth/client"; import { useSession } from "next-auth/client";
import { getSession } from "@lib/auth"; import { getSession } from "@lib/auth";
import prisma from "@lib/prisma"; import prisma from "@lib/prisma";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import Loader from "@components/Loader"; import Loader from "@components/Loader";
import SettingsShell from "@components/Settings"; import SettingsShell from "@components/Settings";
import Shell from "@components/Shell"; import Shell from "@components/Shell";
export default function Embed(props) { export default function Embed(props: inferSSRProps<typeof getServerSideProps>) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars const [, loading] = useSession();
const [session, loading] = useSession();
if (loading) { if (loading) {
return <Loader />; return <Loader />;
} }
const iframeTemplate = `<iframe src="${process.env.NEXT_PUBLIC_APP_URL}/${props.user?.username}" frameborder="0" allowfullscreen></iframe>`;
const htmlTemplate = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Schedule a meeting</title><style>body {margin: 0;}iframe {height: calc(100vh - 4px);width: calc(100vw - 4px);box-sizing: border-box;}</style></head><body>${iframeTemplate}</body></html>`;
return ( return (
<Shell heading="Embed" subtitle="Integrate with your website using our embed options."> <Shell heading="Embed" subtitle="Integrate with your website using our embed options.">
<SettingsShell> <SettingsShell>
@ -33,13 +37,7 @@ export default function Embed(props) {
id="iframe" id="iframe"
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm" className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
placeholder="Loading..." placeholder="Loading..."
defaultValue={ defaultValue={iframeTemplate}
'<iframe src="' +
props.BASE_URL +
"/" +
session.user.username +
'" frameborder="0" allowfullscreen></iframe>'
}
readOnly readOnly
/> />
</div> </div>
@ -53,13 +51,7 @@ export default function Embed(props) {
id="fullscreen" id="fullscreen"
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm" className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
placeholder="Loading..." placeholder="Loading..."
defaultValue={ defaultValue={htmlTemplate}
'<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Schedule a meeting</title><style>body {margin: 0;}iframe {height: calc(100vh - 4px);width: calc(100vw - 4px);box-sizing: border-box;}</style></head><body><iframe src="' +
props.BASE_URL +
"/" +
session.user.username +
'" frameborder="0" allowfullscreen></iframe></body></html>'
}
readOnly readOnly
/> />
</div> </div>
@ -80,9 +72,9 @@ export default function Embed(props) {
); );
} }
export async function getServerSideProps(context) { export async function getServerSideProps(context: GetServerSidePropsContext) {
const session = await getSession(context); const session = await getSession(context);
if (!session) { if (!session?.user?.email) {
return { redirect: { permanent: false, destination: "/auth/login" } }; return { redirect: { permanent: false, destination: "/auth/login" } };
} }
@ -102,9 +94,7 @@ export async function getServerSideProps(context) {
}, },
}); });
const BASE_URL = process.env.BASE_URL;
return { return {
props: { user, BASE_URL }, // will be passed to the page component as props props: { session, user },
}; };
} }

View file

@ -433,6 +433,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
return { return {
props: { props: {
session,
localeProp: locale, localeProp: locale,
localeOptions, localeOptions,
localeLabels, localeLabels,

View file

@ -46,6 +46,6 @@ export async function getServerSideProps(context) {
}); });
return { return {
props: { user }, // will be passed to the page component as props props: { session, user },
}; };
} }