Skip to content

Commit

Permalink
🧰 Aggregate utils & set up results collection in viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Dec 29, 2021
1 parent 447172d commit f088f69
Show file tree
Hide file tree
Showing 42 changed files with 404 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Block, StartBlock } from 'bot-engine'
import { useGraph } from 'contexts/GraphContext'
import { useDnd } from 'contexts/DndContext'
import { StepsList } from './StepsList'
import { isDefined } from 'services/utils'
import { isDefined } from 'utils'
import { useTypebot } from 'contexts/TypebotContext'
import { ContextMenu } from 'components/shared/ContextMenu'
import { BlockNodeContextMenu } from './BlockNodeContextMenu'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Block, StartStep, Step, StepType } from 'bot-engine'
import { SourceEndpoint } from './SourceEndpoint'
import { useGraph } from 'contexts/GraphContext'
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
import { isDefined } from 'services/utils'
import { isDefined } from 'utils'
import { Coordinates } from '@dnd-kit/core/dist/types'
import { TextEditor } from './TextEditor/TextEditor'
import { StepContent } from './StepContent'
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/components/board/preview/PreviewDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const PreviewDrawer = () => {
>
<TypebotViewer
typebot={publicTypebot}
onNewBlockVisisble={handleNewBlockVisible}
onNewBlockVisible={handleNewBlockVisible}
/>
</Flex>
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/contexts/TypebotContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ import {
import {
fetcher,
insertItemInList,
isDefined,
omit,
preventUserFromRefreshing,
} from 'services/utils'
import useSWR from 'swr'
import { isDefined } from 'utils'
import { NewBlockPayload, Coordinates } from './GraphContext'

const typebotContext = createContext<{
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/contexts/UserContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useMemo,
useState,
} from 'react'
import { isDefined } from 'services/utils'
import { isDefined } from 'utils'
import { updateUser as updateUserInDb } from 'services/user'
import { useToast } from '@chakra-ui/react'
import { deepEqual } from 'fast-equals'
Expand Down
6 changes: 6 additions & 0 deletions apps/builder/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withTM = require('next-transpile-modules')(['utils'])

module.exports = withTM({
reactStrictMode: true,
})
5 changes: 4 additions & 1 deletion apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"framer-motion": "^4",
"htmlparser2": "^7.2.0",
"kbar": "^0.1.0-beta.24",
"micro": "^9.3.4",
"micro-cors": "^0.1.1",
"next": "^12.0.7",
"next-auth": "beta",
Expand All @@ -50,7 +51,8 @@
"styled-components": "^5.3.3",
"svg-round-corners": "^0.3.0",
"swr": "^1.1.1",
"use-debounce": "^7.0.1"
"use-debounce": "^7.0.1",
"utils": "*"
},
"devDependencies": {
"@testing-library/cypress": "^8.0.2",
Expand All @@ -69,6 +71,7 @@
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-prettier": "^4.0.0",
"next-transpile-modules": "^9.0.0",
"prettier": "^2.5.1",
"typescript": "^4.5.4"
}
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DashboardFolder, User } from 'db'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/folders/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DashboardFolder } from 'db'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/publicTypebots.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/publicTypebots/[id].ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/storage/upload-url.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import aws from 'aws-sdk'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const maxUploadFileSize = 10485760 // 10 MB
const handler = async (
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/stripe/checkout.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'
import Stripe from 'stripe'

const usdPriceIdTest = 'price_1Jc4TQKexUFvKTWyGvsH4Ff5'
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/stripe/customer-portal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { User } from 'db'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'
import Stripe from 'stripe'

const createCheckoutSession = async (
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/stripe/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'
import Stripe from 'stripe'
import Cors from 'micro-cors'
import { buffer } from 'micro'
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/typebots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { User } from 'db'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/typebots/[id].ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/pages/api/users/[id].ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/services/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
firstStepOffsetY,
} from 'contexts/GraphContext'
import { roundCorners } from 'svg-round-corners'
import { isDefined } from './utils'
import { isDefined } from 'utils'

export const computeFlowChartConnectorPath = ({
sourcePosition,
Expand Down
4 changes: 0 additions & 4 deletions apps/builder/services/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ export const insertItemInList = <T>(
newItem: T
): T[] => [...arr.slice(0, index), newItem, ...arr.slice(index)]

export const isDefined = <T>(value: T | undefined | null): value is T => {
return <T>value !== undefined && <T>value !== null
}

export const preventUserFromRefreshing = (e: BeforeUnloadEvent) => {
e.preventDefault()
e.returnValue = ''
Expand Down
17 changes: 3 additions & 14 deletions apps/viewer/layouts/ErrorPage.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import React from 'react'

export const ErrorPage = ({ error }: { error: 'offline' | '500' | 'IE' }) => {
let errorLabel =
'An error occured. Please try to refresh or contact the owner of this bot.'
if (error === 'offline') {
errorLabel =
'Looks like your device is offline. Please, try to refresh the page.'
}
if (error === 'IE') {
errorLabel = "This bot isn't compatible with Internet Explorer."
}
export const ErrorPage = ({ error }: { error: Error }) => {
return (
<div
style={{
Expand All @@ -20,10 +11,8 @@ export const ErrorPage = ({ error }: { error: 'offline' | '500' | 'IE' }) => {
flexDirection: 'column',
}}
>
{error === '500' && (
<h1 style={{ fontWeight: 'bold', fontSize: '30px' }}>500</h1>
)}
<h2>{errorLabel}</h2>
<h1 style={{ fontWeight: 'bold', fontSize: '30px' }}>{error.name}</h1>
<h2>{error.message}</h2>
</div>
)
}
55 changes: 50 additions & 5 deletions apps/viewer/layouts/TypebotPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PublicTypebot, TypebotViewer } from 'bot-engine'
import React from 'react'
import { Answer, PublicTypebot, TypebotViewer } from 'bot-engine'
import React, { useEffect, useState } from 'react'
import { SEO } from '../components/Seo'
import { createResult, updateResult } from '../services/result'
import { ErrorPage } from './ErrorPage'
import { NotFoundPage } from './NotFoundPage'

Expand All @@ -10,17 +11,61 @@ export type TypebotPageProps = {
isIE: boolean
}

const sessionStorageKey = 'resultId'

export const TypebotPage = ({ typebot, isIE, url }: TypebotPageProps) => {
const [error, setError] = useState<Error | undefined>(
isIE ? new Error('Internet explorer is not supported') : undefined
)
const [resultId, setResultId] = useState<string | undefined>()

useEffect(() => {
initializeResult()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const initializeResult = async () => {
if (!typebot) return
const resultIdFromSession = sessionStorage.getItem(sessionStorageKey)
if (resultIdFromSession) setResultId(resultIdFromSession)
else {
const { error, data: result } = await createResult(typebot.typebotId)
if (error) setError(error)
if (result) {
setResultId(result.id)
sessionStorage.setItem(sessionStorageKey, result.id)
}
}
}

const handleAnswersUpdate = async (answers: Answer[]) => {
if (!resultId) return setError(new Error('Result was not created'))
const { error } = await updateResult(resultId, { answers })
if (error) setError(error)
}

const handleCompleted = async () => {
if (!resultId) return setError(new Error('Result was not created'))
const { error } = await updateResult(resultId, { isCompleted: true })
if (error) setError(error)
}

if (!typebot) {
return <NotFoundPage />
}
if (isIE) {
return <ErrorPage error={'IE'} />
if (error) {
return <ErrorPage error={error} />
}
return (
<div style={{ height: '100vh' }}>
<SEO url={url} chatbotName={typebot.name} />
<TypebotViewer typebot={typebot} />
{resultId && (
<TypebotViewer
typebot={typebot}
onAnswersUpdate={handleAnswersUpdate}
onCompleted={handleCompleted}
/>
)}
</div>
)
}
6 changes: 6 additions & 0 deletions apps/viewer/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withTM = require('next-transpile-modules')(['utils'])

module.exports = withTM({
reactStrictMode: true,
})
4 changes: 3 additions & 1 deletion apps/viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"db": "*",
"next": "^12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"utils": "*"
},
"devDependencies": {
"@types/node": "^17.0.4",
Expand All @@ -24,6 +25,7 @@
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-prettier": "^4.0.0",
"next-transpile-modules": "^9.0.0",
"prettier": "^2.5.1",
"typescript": "^4.5.4"
}
Expand Down
5 changes: 3 additions & 2 deletions apps/viewer/pages/[publicId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const getServerSideProps: GetServerSideProps = async (
const pathname = context.resolvedUrl.split('?')[0]
try {
if (!context.req.headers.host) return { props: {} }
typebot = await getTypebotFromPublicId(context.query.publicId.toString())
typebot = await getTypebotFromPublicId(context.query.publicId?.toString())
if (!typebot) return { props: {} }
return {
props: {
Expand All @@ -32,8 +32,9 @@ export const getServerSideProps: GetServerSideProps = async (
}

const getTypebotFromPublicId = async (
publicId: string
publicId?: string
): Promise<PublicTypebot | undefined> => {
if (!publicId) return
const typebot = await prisma.publicTypebot.findUnique({
where: { publicId },
})
Expand Down
16 changes: 16 additions & 0 deletions apps/viewer/pages/api/results.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'POST') {
const { typebotId } = JSON.parse(req.body)
const result = await prisma.result.create({
data: { typebotId },
})
return res.send(result)
}
return methodNotAllowed(res)
}

export default handler
18 changes: 18 additions & 0 deletions apps/viewer/pages/api/results/[id].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'PATCH') {
const data = JSON.parse(req.body)
const id = req.query.id.toString()
const result = await prisma.result.update({
where: { id },
data: { ...data, updatedAt: new Date() },
})
return res.send(result)
}
return methodNotAllowed(res)
}

export default handler
Loading

0 comments on commit f088f69

Please sign in to comment.