Allow user to share a flow publicly and make it duplicatable

Closes #360
This commit is contained in:
Baptiste Arnaud
2023-11-23 12:05:31 +01:00
parent 8a07392821
commit bb41226a04
130 changed files with 1150 additions and 2012 deletions

View File

@@ -1,9 +1,9 @@
import { createContext } from '@/helpers/server/context'
import { trpcRouter } from '@/helpers/server/routers/v1/trpcRouter'
import * as Sentry from '@sentry/nextjs'
import { NextApiRequest, NextApiResponse } from 'next'
import { createOpenApiNextHandler } from 'trpc-openapi'
import cors from 'nextjs-cors'
import { publicRouter } from '@/helpers/server/routers/publicRouter'
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
await cors(req, res, {
@@ -11,7 +11,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
})
return createOpenApiNextHandler({
router: trpcRouter,
router: publicRouter,
createContext,
onError({ error }) {
if (error.code === 'INTERNAL_SERVER_ERROR') {

View File

@@ -1,10 +1,10 @@
import { createContext } from '@/helpers/server/context'
import { trpcRouter } from '@/helpers/server/routers/v1/trpcRouter'
import { appRouter } from '@/helpers/server/routers/appRouter'
import * as Sentry from '@sentry/nextjs'
import { createNextApiHandler } from '@trpc/server/adapters/next'
export default createNextApiHandler({
router: trpcRouter,
router: appRouter,
createContext,
onError({ error }) {
if (error.code === 'INTERNAL_SERVER_ERROR') {

View File

@@ -8,7 +8,12 @@ export default function Page() {
export const getServerSideProps = async (
context: GetServerSidePropsContext
) => {
const redirectPath = context.query.redirectPath?.toString()
const callbackUrl = context.query.callbackUrl?.toString()
const redirectPath =
context.query.redirectPath?.toString() ??
(callbackUrl
? new URL(callbackUrl).searchParams.get('redirectPath')
: undefined)
return redirectPath
? {
redirect: {

View File

@@ -0,0 +1,75 @@
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
import { trpc } from '@/lib/trpc'
import { Text, HStack, Button, Stack } from '@chakra-ui/react'
import { PlanTag } from '@/features/billing/components/PlanTag'
import { HardDriveIcon } from '@/components/icons'
import { useRouter } from 'next/router'
import { RadioButtons } from '@/components/inputs/RadioButtons'
import { useState } from 'react'
const Page = () => {
const { push } = useRouter()
const { typebot } = useTypebot()
const { workspaces } = useWorkspace()
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState<string>()
const { mutate, isLoading } = trpc.typebot.importTypebot.useMutation({
onSuccess: (data) => {
push(`/typebots/${data.typebot.id}/edit`)
},
})
const duplicateTypebot = (workspaceId: string) => {
mutate({ workspaceId, typebot })
}
const updateSelectedWorkspaceId = (workspaceId: string) => {
setSelectedWorkspaceId(workspaceId)
}
return (
<Stack
w="full"
justifyContent="center"
pt="10"
h="100vh"
maxW="350px"
mx="auto"
spacing={4}
>
<Text>
Choose a workspace to duplicate <strong>{typebot?.name}</strong> in:
</Text>
<RadioButtons
options={workspaces?.map((workspace) => ({
value: workspace.id,
label: (
<HStack w="full">
<EmojiOrImageIcon
icon={workspace.icon}
boxSize="16px"
defaultIcon={HardDriveIcon}
/>
<Text>{workspace.name}</Text>
<PlanTag plan={workspace.plan} />
</HStack>
),
}))}
value={selectedWorkspaceId}
onSelect={updateSelectedWorkspaceId}
/>
<Button
isDisabled={!selectedWorkspaceId}
onClick={() => duplicateTypebot(selectedWorkspaceId as string)}
isLoading={isLoading}
colorScheme="blue"
size="sm"
>
Duplicate
</Button>
</Stack>
)
}
export default Page