Skip to content

Commit

Permalink
refactor(models): 🎨 Build types from validation schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jun 7, 2022
1 parent c67fa7d commit e79ff09
Show file tree
Hide file tree
Showing 62 changed files with 1,268 additions and 734 deletions.
9 changes: 6 additions & 3 deletions apps/builder/contexts/WorkspaceContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useEffect,
useState,
} from 'react'
import { byId, isNotEmpty } from 'utils'
import { byId } from 'utils'
import { MemberInWorkspace, Plan, Workspace, WorkspaceRole } from 'db'
import {
createNewWorkspace,
Expand Down Expand Up @@ -87,8 +87,11 @@ export const WorkspaceContext = ({ children }: { children: ReactNode }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [typebot?.workspaceId])

const switchWorkspace = (workspaceId: string) =>
setCurrentWorkspace(workspaces?.find(byId(workspaceId)))
const switchWorkspace = (workspaceId: string) => {
const newWorkspace = workspaces?.find(byId(workspaceId))
if (!newWorkspace) return
setCurrentWorkspace(newWorkspace)
}

const createWorkspace = async (name?: string) => {
if (!workspaces) return
Expand Down
4 changes: 3 additions & 1 deletion apps/builder/layouts/results/ResultsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ export const ResultsContent = () => {
</HStack>
</Flex>
<Flex pt={['10px', '60px']} w="full" justify="center">
{publishedTypebot &&
{workspace &&
publishedTypebot &&
(isAnalytics ? (
<AnalyticsContent stats={stats} />
) : (
<SubmissionsContent
workspaceId={workspace.id}
typebotId={publishedTypebot.typebotId}
onDeleteResults={handleDeletedResults}
totalResults={stats?.totalStarts ?? 0}
Expand Down
5 changes: 4 additions & 1 deletion apps/builder/layouts/results/SubmissionContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import { Plan } from 'db'
import { useToast } from 'components/shared/hooks/useToast'

type Props = {
workspaceId: string
typebotId: string
totalResults: number
totalHiddenResults?: number
onDeleteResults: (total: number) => void
}
export const SubmissionsContent = ({
workspaceId,
typebotId,
totalResults,
totalHiddenResults,
Expand Down Expand Up @@ -51,6 +53,7 @@ export const SubmissionsContent = ({
const resultHeader = parseResultHeader(blocksAndVariables)

const { data, mutate, setSize, hasMore } = useResults({
workspaceId,
typebotId,
onError: (err) => showToast({ title: err.name, description: err.message }),
})
Expand Down Expand Up @@ -125,7 +128,7 @@ export const SubmissionsContent = ({

const getAllTableData = async () => {
if (!publishedTypebot) return []
const results = await getAllResults(typebotId)
const results = await getAllResults(workspaceId, typebotId)
return convertResultsToTableData(results, resultHeader)
}

Expand Down
8 changes: 7 additions & 1 deletion apps/builder/pages/api/typebots/[typebotId]/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ import { NextApiRequest, NextApiResponse } from 'next'
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
import { getAuthenticatedUser } from 'services/api/utils'
import { isFreePlan } from 'services/workspace'
import { forbidden, methodNotAllowed, notAuthenticated } from 'utils'
import {
badRequest,
forbidden,
methodNotAllowed,
notAuthenticated,
} from 'utils'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const user = await getAuthenticatedUser(req)
if (!user) return notAuthenticated(res)
const workspaceId = req.query.workspaceId as string | undefined
if (req.method === 'GET') {
if (!workspaceId) return badRequest(res, 'workspaceId is required')
const workspace = await prisma.workspace.findFirst({
where: { id: workspaceId, members: { some: { userId: user.id } } },
select: { plan: true },
Expand Down
3 changes: 2 additions & 1 deletion apps/builder/playwright/tests/editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,13 @@ test.describe.parallel('Editor', () => {
await page.goto(`/typebots/${typebotId}/edit`)

await page.click('[data-testid="editable-icon"]')
await expect(page.locator('text="My awesome typebot"')).toBeVisible()
await page.fill('input[placeholder="Search..."]', 'love')
await page.click('text="😍"')
await page.click('text="My awesome typebot"')
await page.fill('input[value="My awesome typebot"]', 'My superb typebot')
await page.press('input[value="My superb typebot"]', 'Enter')
await page.goto(`/typebots`)
await page.click('[aria-label="Navigate back"]')
await expect(page.locator('text="😍"')).toBeVisible()
await expect(page.locator('text="My superb typebot"')).toBeVisible()
})
Expand Down
1 change: 1 addition & 0 deletions apps/builder/playwright/tests/settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ test.describe.parallel('Settings page', () => {
)
await page.goto(`/typebots/${typebotId}/settings`)
await page.click('button:has-text("Metadata")')
await page.waitForTimeout(1000)

// Fav icon
const favIconImg = page.locator('img >> nth=0')
Expand Down
23 changes: 16 additions & 7 deletions apps/builder/services/typebots/results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ResultWithAnswers, VariableWithValue, ResultHeaderCell } from 'models'
import useSWRInfinite from 'swr/infinite'
import { stringify } from 'qs'
import { Answer } from 'db'
import { isDefined, sendRequest } from 'utils'
import { isDefined, isEmpty, sendRequest } from 'utils'
import { fetcher } from 'services/utils'
import { HStack, Text } from '@chakra-ui/react'
import { CodeIcon, CalendarIcon } from 'assets/icons'
Expand All @@ -11,23 +11,27 @@ import { StepIcon } from 'components/editor/StepsSideBar/StepIcon'
const paginationLimit = 50

const getKey = (
workspaceId: string,
typebotId: string,
pageIndex: number,
previousPageData: {
results: ResultWithAnswers[]
}
) => {
if (previousPageData && previousPageData.results.length === 0) return null
if (pageIndex === 0) return `/api/typebots/${typebotId}/results?limit=50`
if (pageIndex === 0)
return `/api/typebots/${typebotId}/results?limit=50&workspaceId=${workspaceId}`
return `/api/typebots/${typebotId}/results?lastResultId=${
previousPageData.results[previousPageData.results.length - 1].id
}&limit=${paginationLimit}`
}&limit=${paginationLimit}&workspaceId=${workspaceId}`
}

export const useResults = ({
workspaceId,
typebotId,
onError,
}: {
workspaceId: string
typebotId: string
onError: (error: Error) => void
}) => {
Expand All @@ -40,9 +44,14 @@ export const useResults = ({
previousPageData: {
results: ResultWithAnswers[]
}
) => getKey(typebotId, pageIndex, previousPageData),
) => getKey(workspaceId, typebotId, pageIndex, previousPageData),
fetcher,
{ revalidateAll: true }
{
revalidateAll: true,
dedupingInterval: isEmpty(process.env.NEXT_PUBLIC_E2E_TEST)
? undefined
: 0,
}
)

if (error) onError(error)
Expand Down Expand Up @@ -80,12 +89,12 @@ export const deleteAllResults = async (typebotId: string) =>
method: 'DELETE',
})

export const getAllResults = async (typebotId: string) => {
export const getAllResults = async (workspaceId: string, typebotId: string) => {
const results = []
let hasMore = true
let lastResultId: string | undefined = undefined
do {
const query = stringify({ limit: 200, lastResultId })
const query = stringify({ limit: 200, lastResultId, workspaceId })
const { data } = await sendRequest<{ results: ResultWithAnswers[] }>({
url: `/api/typebots/${typebotId}/results?${query}`,
method: 'GET',
Expand Down
5 changes: 4 additions & 1 deletion packages/bot-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@
"typescript": "^4.6.4"
},
"peerDependencies": {
"react": "^18.1.0"
"react": "^18.1.0",
"utils": "*",
"db": "*",
"models": "*"
},
"scripts": {
"build": "yarn rollup -c",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Warnings:
- Made the column `workspaceId` on table `Credentials` required. This step will fail if there are existing NULL values in that column.
- Made the column `workspaceId` on table `CustomDomain` required. This step will fail if there are existing NULL values in that column.
- Made the column `workspaceId` on table `DashboardFolder` required. This step will fail if there are existing NULL values in that column.
- Made the column `workspaceId` on table `Typebot` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "Credentials" ALTER COLUMN "workspaceId" SET NOT NULL;

-- AlterTable
ALTER TABLE "CustomDomain" ALTER COLUMN "workspaceId" SET NOT NULL;

-- AlterTable
ALTER TABLE "DashboardFolder" ALTER COLUMN "workspaceId" SET NOT NULL;

-- AlterTable
ALTER TABLE "Typebot" ALTER COLUMN "workspaceId" SET NOT NULL;
16 changes: 8 additions & 8 deletions packages/db/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,15 @@ enum GraphNavigation {
model CustomDomain {
name String @id
createdAt DateTime @default(now())
workspaceId String?
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
}

model Credentials {
id String @id @default(cuid())
createdAt DateTime @default(now())
workspaceId String?
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
data String // Encrypted data
name String
type String
Expand Down Expand Up @@ -154,8 +154,8 @@ model DashboardFolder {
parentFolder DashboardFolder? @relation("ParentChild", fields: [parentFolderId], references: [id])
childrenFolder DashboardFolder[] @relation("ParentChild")
typebots Typebot[]
workspaceId String?
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
}

model Typebot {
Expand All @@ -179,8 +179,8 @@ model Typebot {
collaborators CollaboratorsOnTypebots[]
invitations Invitation[]
webhooks Webhook[]
workspaceId String?
workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
workspaceId String
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
}

model Invitation {
Expand Down
25 changes: 18 additions & 7 deletions packages/models/package.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
{
"name": "models",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/types/index.d.ts",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"license": "AGPL-3.0-or-later",
"private": true,
"devDependencies": {
"typescript": "^4.6.4"
"typescript": "^4.6.4",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-typescript": "^8.3.2",
"rollup": "^2.72.1",
"rollup-plugin-dts": "^4.2.1",
"rollup-plugin-peer-deps-external": "^2.2.4"
},
"dependencies": {
"next": "^12.1.6",
"db": "*",
"@udecode/plate-core": "^11.0.0"
"next": "^12.1.6",
"zod": "^3.17.3"
},
"peerDependencies": {
"next": "^12.1.6",
"db": "*"
},
"scripts": {
"build": "tsc",
"dx": "tsc --watch --preserveWatchOutput"
"build": "yarn rollup -c",
"dx": "yarn rollup -c --watch"
}
}
38 changes: 38 additions & 0 deletions packages/models/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'

const packageJson = require('./package.json')

export default [
{
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
inlineDynamicImports: true,
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
inlineDynamicImports: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({ tsconfig: './tsconfig.json' }),
],
},
{
input: 'dist/esm/types/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'esm' }],
plugins: [dts()],
},
]
3 changes: 2 additions & 1 deletion packages/models/src/result.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Result as ResultFromPrisma } from 'db'
import { Answer, InputStepType, VariableWithValue } from '.'
import { Answer, VariableWithValue } from '.'
import { InputStepType } from './typebot/steps/shared'

export type Result = Omit<ResultFromPrisma, 'createdAt' | 'variables'> & {
createdAt: string
Expand Down
Loading

4 comments on commit e79ff09

@vercel
Copy link

@vercel vercel bot commented on e79ff09 Jun 7, 2022

@vercel
Copy link

@vercel vercel bot commented on e79ff09 Jun 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on e79ff09 Jun 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on e79ff09 Jun 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

app.typebot.io
builder-v2-typebot-io.vercel.app
builder-v2-git-main-typebot-io.vercel.app

Please sign in to comment.