mirror of
https://github.com/lukevella/rallly.git
synced 2025-05-03 20:26:03 +02:00
♻️ Handle self-hosting environment with updated authentication (#918)
This commit is contained in:
parent
221ae62d8e
commit
3e90c302d6
12 changed files with 133 additions and 222 deletions
|
@ -15,8 +15,6 @@ import { useCopyToClipboard } from "react-use";
|
||||||
import { useParticipants } from "@/components/participants-provider";
|
import { useParticipants } from "@/components/participants-provider";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { usePoll } from "@/contexts/poll";
|
import { usePoll } from "@/contexts/poll";
|
||||||
import { shortUrl } from "@/utils/absolute-url";
|
|
||||||
import { isSelfHosted } from "@/utils/constants";
|
|
||||||
|
|
||||||
export const InviteDialog = () => {
|
export const InviteDialog = () => {
|
||||||
const { participants } = useParticipants();
|
const { participants } = useParticipants();
|
||||||
|
@ -31,10 +29,6 @@ export const InviteDialog = () => {
|
||||||
}
|
}
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const inviteLink = isSelfHosted
|
|
||||||
? window.location.origin + `/invite/${poll?.id}`
|
|
||||||
: shortUrl(`/invite/${poll?.id}`);
|
|
||||||
|
|
||||||
const [didCopy, setDidCopy] = React.useState(false);
|
const [didCopy, setDidCopy] = React.useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -72,7 +66,7 @@ export const InviteDialog = () => {
|
||||||
<Button
|
<Button
|
||||||
className="w-full min-w-0 bg-gray-50 px-2.5"
|
className="w-full min-w-0 bg-gray-50 px-2.5"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copyToClipboard(inviteLink);
|
copyToClipboard(poll.inviteLink);
|
||||||
setDidCopy(true);
|
setDidCopy(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setDidCopy(false);
|
setDidCopy(false);
|
||||||
|
@ -82,7 +76,7 @@ export const InviteDialog = () => {
|
||||||
{didCopy ? (
|
{didCopy ? (
|
||||||
<Trans i18nKey="copied" />
|
<Trans i18nKey="copied" />
|
||||||
) : (
|
) : (
|
||||||
<span className="flex truncate">{inviteLink}</span>
|
<span className="flex truncate">{poll.inviteLink}</span>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
|
|
|
@ -23,11 +23,10 @@ import { UserDropdown } from "@/components/user-dropdown";
|
||||||
import { IfCloudHosted } from "@/contexts/environment";
|
import { IfCloudHosted } from "@/contexts/environment";
|
||||||
import { IfFreeUser } from "@/contexts/plan";
|
import { IfFreeUser } from "@/contexts/plan";
|
||||||
import { appVersion, isFeedbackEnabled } from "@/utils/constants";
|
import { appVersion, isFeedbackEnabled } from "@/utils/constants";
|
||||||
import { ConnectedDayjsProvider } from "@/utils/dayjs";
|
|
||||||
|
|
||||||
import { IconComponent, NextPageWithLayout } from "../../types";
|
import { IconComponent, NextPageWithLayout } from "../../types";
|
||||||
import ModalProvider from "../modal/modal-provider";
|
import ModalProvider from "../modal/modal-provider";
|
||||||
import { IfGuest, UserProvider } from "../user-provider";
|
import { IfGuest } from "../user-provider";
|
||||||
|
|
||||||
const NavMenuItem = ({
|
const NavMenuItem = ({
|
||||||
href,
|
href,
|
||||||
|
@ -181,49 +180,45 @@ export const StandardLayout: React.FunctionComponent<{
|
||||||
}> = ({ children, hideNav, ...rest }) => {
|
}> = ({ children, hideNav, ...rest }) => {
|
||||||
const key = hideNav ? "no-nav" : "nav";
|
const key = hideNav ? "no-nav" : "nav";
|
||||||
return (
|
return (
|
||||||
<UserProvider>
|
<ModalProvider>
|
||||||
<ConnectedDayjsProvider>
|
<Toaster />
|
||||||
<Toaster />
|
<div className="flex min-h-screen flex-col" {...rest}>
|
||||||
<ModalProvider>
|
<AnimatePresence initial={false}>
|
||||||
<div className="flex min-h-screen flex-col" {...rest}>
|
{!hideNav ? <MainNav /> : null}
|
||||||
<AnimatePresence initial={false}>
|
</AnimatePresence>
|
||||||
{!hideNav ? <MainNav /> : null}
|
<AnimatePresence mode="wait" initial={false}>
|
||||||
</AnimatePresence>
|
<m.div
|
||||||
<AnimatePresence mode="wait" initial={false}>
|
key={key}
|
||||||
<m.div
|
variants={{
|
||||||
key={key}
|
hidden: { opacity: 0, y: -56 },
|
||||||
variants={{
|
visible: { opacity: 1, y: 0 },
|
||||||
hidden: { opacity: 0, y: -56 },
|
}}
|
||||||
visible: { opacity: 1, y: 0 },
|
initial="hidden"
|
||||||
}}
|
animate="visible"
|
||||||
initial="hidden"
|
exit={{ opacity: 0, y: 56 }}
|
||||||
animate="visible"
|
>
|
||||||
exit={{ opacity: 0, y: 56 }}
|
{children}
|
||||||
>
|
</m.div>
|
||||||
{children}
|
</AnimatePresence>
|
||||||
</m.div>
|
{appVersion ? (
|
||||||
</AnimatePresence>
|
<div className="fixed bottom-0 right-0 z-50 rounded-tl-md bg-gray-200/90">
|
||||||
{appVersion ? (
|
<Link
|
||||||
<div className="fixed bottom-0 right-0 z-50 rounded-tl-md bg-gray-200/90">
|
className="px-2 py-1 text-xs tabular-nums tracking-tight"
|
||||||
<Link
|
target="_blank"
|
||||||
className="px-2 py-1 text-xs tabular-nums tracking-tight"
|
href={`https://github.com/lukevella/rallly/releases/${appVersion}`}
|
||||||
target="_blank"
|
>
|
||||||
href={`https://github.com/lukevella/rallly/releases/${appVersion}`}
|
{`${appVersion}`}
|
||||||
>
|
</Link>
|
||||||
{`${appVersion}`}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
{isFeedbackEnabled ? (
|
) : null}
|
||||||
<>
|
</div>
|
||||||
<FeaturebaseIdentify />
|
{isFeedbackEnabled ? (
|
||||||
<FeedbackButton />
|
<>
|
||||||
</>
|
<FeaturebaseIdentify />
|
||||||
) : null}
|
<FeedbackButton />
|
||||||
</ModalProvider>
|
</>
|
||||||
</ConnectedDayjsProvider>
|
) : null}
|
||||||
</UserProvider>
|
</ModalProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,14 @@ import { AppProps } from "next/app";
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider, signIn, useSession } from "next-auth/react";
|
||||||
import { appWithTranslation } from "next-i18next";
|
import { appWithTranslation } from "next-i18next";
|
||||||
import { DefaultSeo } from "next-seo";
|
import { DefaultSeo } from "next-seo";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
import Maintenance from "@/components/maintenance";
|
import Maintenance from "@/components/maintenance";
|
||||||
|
import { UserProvider } from "@/components/user-provider";
|
||||||
|
import { ConnectedDayjsProvider } from "@/utils/dayjs";
|
||||||
import { trpc } from "@/utils/trpc/client";
|
import { trpc } from "@/utils/trpc/client";
|
||||||
|
|
||||||
import * as nextI18nNextConfig from "../../next-i18next.config.js";
|
import * as nextI18nNextConfig from "../../next-i18next.config.js";
|
||||||
|
@ -29,12 +32,30 @@ type AppPropsWithLayout = AppProps & {
|
||||||
Component: NextPageWithLayout;
|
Component: NextPageWithLayout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Auth = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const session = useSession();
|
||||||
|
const isAuthenticated = !!session.data?.user.email;
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
signIn();
|
||||||
|
}
|
||||||
|
}, [isAuthenticated]);
|
||||||
|
|
||||||
|
if (isAuthenticated) {
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const MyApp: NextPage<AppPropsWithLayout> = ({ Component, pageProps }) => {
|
const MyApp: NextPage<AppPropsWithLayout> = ({ Component, pageProps }) => {
|
||||||
if (process.env.NEXT_PUBLIC_MAINTENANCE_MODE === "1") {
|
if (process.env.NEXT_PUBLIC_MAINTENANCE_MODE === "1") {
|
||||||
return <Maintenance />;
|
return <Maintenance />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLayout = Component.getLayout ?? ((page) => page);
|
const getLayout = Component.getLayout ?? ((page) => page);
|
||||||
|
const children = <Component {...pageProps} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SessionProvider>
|
<SessionProvider>
|
||||||
|
@ -83,7 +104,15 @@ const MyApp: NextPage<AppPropsWithLayout> = ({ Component, pageProps }) => {
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
<TooltipProvider delayDuration={200}>
|
<TooltipProvider delayDuration={200}>
|
||||||
{getLayout(<Component {...pageProps} />)}
|
<UserProvider>
|
||||||
|
<ConnectedDayjsProvider>
|
||||||
|
{Component.isAuthRequired ? (
|
||||||
|
<Auth>{getLayout(children)}</Auth>
|
||||||
|
) : (
|
||||||
|
getLayout(children)
|
||||||
|
)}
|
||||||
|
</ConnectedDayjsProvider>
|
||||||
|
</UserProvider>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</LazyMotion>
|
</LazyMotion>
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
|
|
|
@ -13,12 +13,11 @@ import { Poll } from "@/components/poll";
|
||||||
import { LegacyPollContextProvider } from "@/components/poll/poll-context-provider";
|
import { LegacyPollContextProvider } from "@/components/poll/poll-context-provider";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { UserDropdown } from "@/components/user-dropdown";
|
import { UserDropdown } from "@/components/user-dropdown";
|
||||||
import { UserProvider, useUser } from "@/components/user-provider";
|
import { useUser } from "@/components/user-provider";
|
||||||
import { VisibilityProvider } from "@/components/visibility";
|
import { VisibilityProvider } from "@/components/visibility";
|
||||||
import { PermissionsContext } from "@/contexts/permissions";
|
import { PermissionsContext } from "@/contexts/permissions";
|
||||||
import { usePoll } from "@/contexts/poll";
|
import { usePoll } from "@/contexts/poll";
|
||||||
import { absoluteUrl } from "@/utils/absolute-url";
|
import { absoluteUrl } from "@/utils/absolute-url";
|
||||||
import { ConnectedDayjsProvider } from "@/utils/dayjs";
|
|
||||||
import { trpc } from "@/utils/trpc/client";
|
import { trpc } from "@/utils/trpc/client";
|
||||||
import { getStaticTranslations } from "@/utils/with-page-translations";
|
import { getStaticTranslations } from "@/utils/with-page-translations";
|
||||||
|
|
||||||
|
@ -118,62 +117,58 @@ const Page = ({ id, title, user }: PageProps) => {
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<UserProvider>
|
<Prefetch>
|
||||||
<ConnectedDayjsProvider>
|
<LegacyPollContextProvider>
|
||||||
<Prefetch>
|
<VisibilityProvider>
|
||||||
<LegacyPollContextProvider>
|
<div>
|
||||||
<VisibilityProvider>
|
<svg
|
||||||
<div>
|
className="absolute inset-x-0 top-0 -z-10 hidden h-[64rem] w-full stroke-gray-300/75 [mask-image:radial-gradient(800px_800px_at_center,white,transparent)] sm:block"
|
||||||
<svg
|
aria-hidden="true"
|
||||||
className="absolute inset-x-0 top-0 -z-10 hidden h-[64rem] w-full stroke-gray-300/75 [mask-image:radial-gradient(800px_800px_at_center,white,transparent)] sm:block"
|
>
|
||||||
aria-hidden="true"
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id="1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84"
|
||||||
|
width={240}
|
||||||
|
height={240}
|
||||||
|
x="50%"
|
||||||
|
y={-1}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<defs>
|
<path d="M.5 240V.5H240" fill="none" />
|
||||||
<pattern
|
</pattern>
|
||||||
id="1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84"
|
</defs>
|
||||||
width={240}
|
<rect
|
||||||
height={240}
|
width="100%"
|
||||||
x="50%"
|
height="100%"
|
||||||
y={-1}
|
strokeWidth={0}
|
||||||
patternUnits="userSpaceOnUse"
|
fill="url(#1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84)"
|
||||||
>
|
/>
|
||||||
<path d="M.5 240V.5H240" fill="none" />
|
</svg>
|
||||||
</pattern>
|
<GoToApp />
|
||||||
</defs>
|
<div className="mx-auto max-w-4xl space-y-4 px-3 sm:py-8">
|
||||||
<rect
|
<Poll />
|
||||||
width="100%"
|
<div className="mt-4 space-y-4 text-center text-gray-500">
|
||||||
height="100%"
|
<div className="py-8">
|
||||||
strokeWidth={0}
|
<Trans
|
||||||
fill="url(#1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84)"
|
defaults="Powered by <a>{name}</a>"
|
||||||
|
i18nKey="poweredByRallly"
|
||||||
|
values={{ name: "rallly.co" }}
|
||||||
|
components={{
|
||||||
|
a: (
|
||||||
|
<Link
|
||||||
|
className="hover:text-primary-600 rounded-none border-b border-b-gray-500 font-semibold"
|
||||||
|
href="https://rallly.co"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</svg>
|
|
||||||
<GoToApp />
|
|
||||||
<div className="mx-auto max-w-4xl space-y-4 px-3 sm:py-8">
|
|
||||||
<Poll />
|
|
||||||
<div className="mt-4 space-y-4 text-center text-gray-500">
|
|
||||||
<div className="py-8">
|
|
||||||
<Trans
|
|
||||||
defaults="Powered by <a>{name}</a>"
|
|
||||||
i18nKey="poweredByRallly"
|
|
||||||
values={{ name: "rallly.co" }}
|
|
||||||
components={{
|
|
||||||
a: (
|
|
||||||
<Link
|
|
||||||
className="hover:text-primary-600 rounded-none border-b border-b-gray-500 font-semibold"
|
|
||||||
href="https://rallly.co"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VisibilityProvider>
|
</div>
|
||||||
</LegacyPollContextProvider>
|
</div>
|
||||||
</Prefetch>
|
</VisibilityProvider>
|
||||||
</ConnectedDayjsProvider>
|
</LegacyPollContextProvider>
|
||||||
</UserProvider>
|
</Prefetch>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
import { CreatePoll } from "@/components/create-poll";
|
import { CreatePoll } from "@/components/create-poll";
|
||||||
import { getStandardLayout } from "@/components/layouts/standard-layout";
|
import { getStandardLayout } from "@/components/layouts/standard-layout";
|
||||||
|
import { isSelfHosted } from "@/utils/constants";
|
||||||
|
|
||||||
import { NextPageWithLayout } from "../types";
|
import { NextPageWithLayout } from "../types";
|
||||||
import { getStaticTranslations } from "../utils/with-page-translations";
|
import { getStaticTranslations } from "../utils/with-page-translations";
|
||||||
|
@ -95,6 +96,7 @@ const Page: NextPageWithLayout = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.getLayout = getStandardLayout;
|
Page.getLayout = getStandardLayout;
|
||||||
|
Page.isAuthRequired = isSelfHosted;
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { RegisterLink } from "@/components/register-link";
|
||||||
import { useUser } from "@/components/user-provider";
|
import { useUser } from "@/components/user-provider";
|
||||||
import { usePoll } from "@/contexts/poll";
|
import { usePoll } from "@/contexts/poll";
|
||||||
import { NextPageWithLayout } from "@/types";
|
import { NextPageWithLayout } from "@/types";
|
||||||
|
import { isSelfHosted } from "@/utils/constants";
|
||||||
import { getStaticTranslations } from "@/utils/with-page-translations";
|
import { getStaticTranslations } from "@/utils/with-page-translations";
|
||||||
|
|
||||||
const GuestPollAlert = () => {
|
const GuestPollAlert = () => {
|
||||||
|
@ -58,6 +59,7 @@ const Page: NextPageWithLayout = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.getLayout = getPollLayout;
|
Page.getLayout = getPollLayout;
|
||||||
|
Page.isAuthRequired = isSelfHosted;
|
||||||
|
|
||||||
export const getStaticPaths = async () => {
|
export const getStaticPaths = async () => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { PollStatusBadge } from "@/components/poll-status";
|
||||||
import { Skeleton } from "@/components/skeleton";
|
import { Skeleton } from "@/components/skeleton";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { NextPageWithLayout } from "@/types";
|
import { NextPageWithLayout } from "@/types";
|
||||||
|
import { isSelfHosted } from "@/utils/constants";
|
||||||
import { useDayjs } from "@/utils/dayjs";
|
import { useDayjs } from "@/utils/dayjs";
|
||||||
import { trpc } from "@/utils/trpc/client";
|
import { trpc } from "@/utils/trpc/client";
|
||||||
import { getStaticTranslations } from "@/utils/with-page-translations";
|
import { getStaticTranslations } from "@/utils/with-page-translations";
|
||||||
|
@ -187,6 +188,7 @@ const Page: NextPageWithLayout = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.getLayout = getStandardLayout;
|
Page.getLayout = getStandardLayout;
|
||||||
|
Page.isAuthRequired = isSelfHosted;
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ const Page: NextPageWithLayout = () => {
|
||||||
Page.getLayout = getProfileLayout;
|
Page.getLayout = getProfileLayout;
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||||
|
// This page is only available on the hosted version
|
||||||
if (isSelfHosted) {
|
if (isSelfHosted) {
|
||||||
return {
|
return {
|
||||||
notFound: true,
|
notFound: true,
|
||||||
|
|
|
@ -71,6 +71,7 @@ const Page: NextPageWithLayout = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.getLayout = getProfileLayout;
|
Page.getLayout = getProfileLayout;
|
||||||
|
Page.isAuthRequired = true;
|
||||||
|
|
||||||
export const getStaticProps = getStaticTranslations;
|
export const getStaticProps = getStaticTranslations;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ export type PropsOf<TTag extends ReactTag> = TTag extends React.ElementType
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
||||||
getLayout?: (page: React.ReactElement) => React.ReactNode;
|
getLayout?: (page: React.ReactElement) => React.ReactNode;
|
||||||
|
isAuthRequired?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
router,
|
router,
|
||||||
} from "../trpc";
|
} from "../trpc";
|
||||||
import { comments } from "./polls/comments";
|
import { comments } from "./polls/comments";
|
||||||
import { demo } from "./polls/demo";
|
|
||||||
import { options } from "./polls/options";
|
import { options } from "./polls/options";
|
||||||
import { participants } from "./polls/participants";
|
import { participants } from "./polls/participants";
|
||||||
|
|
||||||
|
@ -42,7 +41,6 @@ const getPollIdFromAdminUrlId = async (urlId: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const polls = router({
|
export const polls = router({
|
||||||
demo,
|
|
||||||
participants,
|
participants,
|
||||||
comments,
|
comments,
|
||||||
options,
|
options,
|
||||||
|
@ -390,11 +388,12 @@ export const polls = router({
|
||||||
message: "Poll not found",
|
message: "Poll not found",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const inviteLink = ctx.shortUrl(`/invite/${res.id}`);
|
||||||
|
|
||||||
if (ctx.user.id === res.userId || res.adminUrlId === input.adminToken) {
|
if (ctx.user.id === res.userId || res.adminUrlId === input.adminToken) {
|
||||||
return res;
|
return { ...res, inviteLink };
|
||||||
} else {
|
} else {
|
||||||
return { ...res, adminUrlId: "" };
|
return { ...res, adminUrlId: "", inviteLink };
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
transfer: possiblyPublicProcedure
|
transfer: possiblyPublicProcedure
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
import { prisma, VoteType } from "@rallly/database";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
|
|
||||||
import { nanoid } from "../../../utils/nanoid";
|
|
||||||
import { possiblyPublicProcedure, router } from "../../trpc";
|
|
||||||
|
|
||||||
const participantData: Array<{ name: string; votes: VoteType[] }> = [
|
|
||||||
{
|
|
||||||
name: "Reed",
|
|
||||||
votes: ["yes", "no", "yes", "no"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Susan",
|
|
||||||
votes: ["yes", "yes", "yes", "no"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Johnny",
|
|
||||||
votes: ["no", "no", "yes", "yes"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Ben",
|
|
||||||
votes: ["yes", "yes", "yes", "yes"],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionValues = ["2022-12-14", "2022-12-15", "2022-12-16", "2022-12-17"];
|
|
||||||
|
|
||||||
export const demo = router({
|
|
||||||
create: possiblyPublicProcedure.mutation(async () => {
|
|
||||||
const adminUrlId = nanoid();
|
|
||||||
const demoUser = { name: "John Example", email: "noreply@rallly.co" };
|
|
||||||
|
|
||||||
const options: Array<{ start: Date; id: string }> = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < optionValues.length; i++) {
|
|
||||||
options.push({ id: await nanoid(), start: new Date(optionValues[i]) });
|
|
||||||
}
|
|
||||||
|
|
||||||
const participants: Array<{
|
|
||||||
name: string;
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
createdAt: Date;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
const votes: Array<{
|
|
||||||
optionId: string;
|
|
||||||
participantId: string;
|
|
||||||
type: VoteType;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < participantData.length; i++) {
|
|
||||||
const { name, votes: participantVotes } = participantData[i];
|
|
||||||
const participantId = await nanoid();
|
|
||||||
participants.push({
|
|
||||||
id: participantId,
|
|
||||||
name,
|
|
||||||
userId: "user-demo",
|
|
||||||
createdAt: dayjs()
|
|
||||||
.add(i * -1, "minutes")
|
|
||||||
.toDate(),
|
|
||||||
});
|
|
||||||
|
|
||||||
options.forEach((option, index) => {
|
|
||||||
votes.push({
|
|
||||||
optionId: option.id,
|
|
||||||
participantId,
|
|
||||||
type: participantVotes[index],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.poll.create({
|
|
||||||
data: {
|
|
||||||
id: nanoid(),
|
|
||||||
title: "Lunch Meeting",
|
|
||||||
location: "Starbucks, 901 New York Avenue",
|
|
||||||
description: `Hey everyone, please choose the dates when you are available to meet for our monthly get together. Looking forward to see you all!`,
|
|
||||||
demo: true,
|
|
||||||
adminUrlId,
|
|
||||||
participantUrlId: nanoid(),
|
|
||||||
user: {
|
|
||||||
connectOrCreate: {
|
|
||||||
where: {
|
|
||||||
email: demoUser.email,
|
|
||||||
},
|
|
||||||
create: demoUser,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
createMany: {
|
|
||||||
data: options,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
participants: {
|
|
||||||
createMany: {
|
|
||||||
data: participants,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
votes: {
|
|
||||||
createMany: {
|
|
||||||
data: votes,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return adminUrlId;
|
|
||||||
}),
|
|
||||||
});
|
|
Loading…
Add table
Reference in a new issue