Skip to content

Commit

Permalink
🚸 (variables) Allow null values in variable list
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Mar 21, 2023
1 parent c52a284 commit 0c39ae4
Show file tree
Hide file tree
Showing 18 changed files with 69 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ import { Plan, Workspace } from '@typebot.io/prisma'
import React from 'react'
import { parseNumberWithCommas } from '@typebot.io/lib'
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
import { trpc } from '@/lib/trpc'
import { defaultQueryOptions, trpc } from '@/lib/trpc'
import { storageToReadable } from '../helpers/storageToReadable'

type Props = {
workspace: Workspace
}

export const UsageProgressBars = ({ workspace }: Props) => {
const { data, isLoading } = trpc.billing.getUsage.useQuery({
workspaceId: workspace.id,
})
const { data, isLoading } = trpc.billing.getUsage.useQuery(
{
workspaceId: workspace.id,
},
defaultQueryOptions
)
const totalChatsUsed = data?.totalChatsUsed ?? 0
const totalStorageUsed = data?.totalStorageUsed ?? 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ test.describe.parallel('Google sheets integration', () => {
.press('Enter')
await expect(
page.locator('typebot-standard').locator('text=Your name is:')
).toHaveText(`Your name is: Georges Smith`)
).toHaveText(`Your name is: Georges2 Smith2`)
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ test('should be able to connect custom domain', async ({ page }) => {
await expect(page.locator('text=sub.yolozeeer.com')).toBeHidden()
await page.click('button >> text=Add my domain')
await page.click('[aria-label="Remove domain"]')
await expect(page.locator('[aria-label="Remove domain"]')).toBeHidden()
await expect(page.locator('[aria-label="Remove domain"]')).toBeHidden({
timeout: 10000,
})
})

test.describe('Starter workspace', () => {
Expand Down
6 changes: 5 additions & 1 deletion apps/builder/src/features/dashboard/dashboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ test('folders navigation should work', async ({ page }) => {

test('folders and typebots should be deletable', async ({ page }) => {
await createFolders([{ name: 'Folder #1' }, { name: 'Folder #2' }])
await createTypebots([{ id: 'deletable-typebot', name: 'Typebot #1' }])
const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1)
await createTypebots([
{ id: 'deletable-typebot', name: 'Typebot #1', createdAt: tomorrow },
])
await page.goto('/typebots')
await page.click('button[aria-label="Show Folder #1 menu"]')
await page.click('li:has-text("Folder #1") >> button:has-text("Delete")')
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/src/features/workspace/WorkspaceProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const WorkspaceProvider = ({
onError: (error) => showToast({ description: error.message }),
onSuccess: async () => {
trpcContext.workspace.listWorkspaces.invalidate()
setWorkspaceId(undefined)
},
})

Expand Down Expand Up @@ -154,7 +155,6 @@ export const WorkspaceProvider = ({
const deleteCurrentWorkspace = async () => {
if (!workspaceId || !workspaces || workspaces.length < 2) return
await deleteWorkspaceMutation.mutateAsync({ workspaceId })
setWorkspaceId(workspaces[0].id)
}

const refreshWorkspace = () => {
Expand Down
5 changes: 5 additions & 0 deletions apps/builder/src/lib/trpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { httpBatchLink, loggerLink } from '@trpc/client'
import { createTRPCNext } from '@trpc/next'
import type { AppRouter } from '../helpers/server/routers/v1/trpcRouter'
import superjson from 'superjson'
import { env } from '@typebot.io/lib'

const getBaseUrl = () =>
typeof window !== 'undefined' ? '' : process.env.NEXTAUTH_URL
Expand All @@ -24,3 +25,7 @@ export const trpc = createTRPCNext<AppRouter>({
},
ssr: false,
})

export const defaultQueryOptions = {
refetchOnMount: env('E2E_TEST') === 'true',
}
3 changes: 2 additions & 1 deletion apps/docs/openapi/builder/_spec_.json
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,8 @@
{
"type": "array",
"items": {
"type": "string"
"type": "string",
"nullable": true
}
}
]
Expand Down
9 changes: 6 additions & 3 deletions apps/docs/openapi/chat/_spec_.json
Original file line number Diff line number Diff line change
Expand Up @@ -2535,7 +2535,8 @@
{
"type": "array",
"items": {
"type": "string"
"type": "string",
"nullable": true
}
}
],
Expand Down Expand Up @@ -3811,7 +3812,8 @@
{
"type": "array",
"items": {
"type": "string"
"type": "string",
"nullable": true
}
}
],
Expand Down Expand Up @@ -3905,7 +3907,8 @@
{
"type": "array",
"items": {
"type": "string"
"type": "string",
"nullable": true
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const injectVariableValuesInButtonsInputBlock =
if (!variable || typeof variable.value === 'string') return block
return {
...block,
items: variable.value.map((item, idx) => ({
items: variable.value.filter(isDefined).map((item, idx) => ({
id: idx.toString(),
type: ItemType.BUTTON,
blockId: block.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
SendEmailOptions,
SessionState,
SmtpCredentials,
Variable,
} from '@typebot.io/schemas'
import { createTransport } from 'nodemailer'
import Mail from 'nodemailer/lib/mailer'
import { byId, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
import { byId, isDefined, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
import { parseAnswers } from '@typebot.io/lib/results'
import { decrypt } from '@typebot.io/lib/api'
import { defaultFrom, defaultTransportOptions } from './constants'
Expand Down Expand Up @@ -51,8 +52,7 @@ export const executeSendEmailBlock = async (
replyTo: options.replyTo
? parseVariables(variables)(options.replyTo)
: undefined,
fileUrls:
variables.find(byId(options.attachmentsVariableId))?.value ?? undefined,
fileUrls: getFileUrls(variables)(options.attachmentsVariableId),
isCustomBody: options.isCustomBody,
isBodyCode: options.isBodyCode,
})
Expand Down Expand Up @@ -238,3 +238,12 @@ const parseEmailRecipient = (
email: recipient,
}
}

const getFileUrls =
(variables: Variable[]) =>
(variableId: string | undefined): string | string[] | undefined => {
const fileUrls = variables.find(byId(variableId))?.value
if (!fileUrls) return
if (typeof fileUrls === 'string') return fileUrls
return fileUrls.filter(isDefined)
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const parseResultSample = (
headerCells: ResultHeaderCell[],
variables: Variable[]
) =>
headerCells.reduce<Record<string, string | string[] | undefined>>(
headerCells.reduce<Record<string, string | (string | null)[] | undefined>>(
(resultSample, cell) => {
const inputBlock = inputBlocks.find((inputBlock) =>
cell.blocks?.some((block) => block.id === inputBlock.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ const executeComparison =
if (isNotDefined(value)) return false
switch (comparison.comparisonOperator) {
case ComparisonOperators.CONTAINS: {
const contains = (a: string, b: string) => {
if (b === '') return false
const contains = (a: string | null, b: string | null) => {
if (b === '' || !b || !a) return false
return a.toLowerCase().trim().includes(b.toLowerCase().trim())
}
return compare(contains, inputValue, value)
Expand All @@ -55,14 +55,20 @@ const executeComparison =
}
case ComparisonOperators.GREATER: {
return compare(
(a, b) => parseFloat(a) > parseFloat(b),
(a, b) =>
isDefined(a) && isDefined(b)
? parseFloat(a) > parseFloat(b)
: false,
inputValue,
value
)
}
case ComparisonOperators.LESS: {
return compare(
(a, b) => parseFloat(a) < parseFloat(b),
(a, b) =>
isDefined(a) && isDefined(b)
? parseFloat(a) < parseFloat(b)
: false,
inputValue,
value
)
Expand All @@ -74,10 +80,11 @@ const executeComparison =
}

const compare = (
func: (a: string, b: string) => boolean,
a: string | string[],
b: string | string[]
func: (a: string | null, b: string | null) => boolean,
a: Variable['value'],
b: Variable['value']
): boolean => {
if (!a || !b) return false
if (typeof a === 'string') {
if (typeof b === 'string') return func(a, b)
return b.some((b) => func(a, b))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Variable } from '@typebot.io/schemas'

export const findUniqueVariableValue =
(variables: Variable[]) =>
(value: string | undefined): string | string[] | null => {
(value: string | undefined): Variable['value'] => {
if (!value || !value.startsWith('{{') || !value.endsWith('}}')) return null
const variableName = value.slice(2, -2)
const variable = variables.find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Variable } from '@typebot.io/schemas'

export const parseGuessedValueType = (
value: Variable['value']
): string | string[] | boolean | number | null | undefined => {
): string | (string | null)[] | boolean | number | null | undefined => {
if (value === null) return null
if (value === undefined) return undefined
if (typeof value !== 'string') return value
Expand Down
4 changes: 2 additions & 2 deletions apps/viewer/src/features/variables/updateVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const updateResultVariables =
const serializedNewVariables = newVariables.map((variable) => ({
...variable,
value: Array.isArray(variable.value)
? variable.value.map(safeStringify).filter(isDefined)
? variable.value.map(safeStringify)
: safeStringify(variable.value),
}))

Expand Down Expand Up @@ -62,7 +62,7 @@ const updateTypebotVariables =
const serializedNewVariables = newVariables.map((variable) => ({
...variable,
value: Array.isArray(variable.value)
? variable.value.map(safeStringify).filter(isDefined)
? variable.value.map(safeStringify)
: safeStringify(variable.value),
}))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const safeStringify = (val: unknown): string | null => {

export const parseCorrectValueType = (
value: Variable['value']
): string | string[] | boolean | number | null | undefined => {
): string | (string | null)[] | boolean | number | null | undefined => {
if (value === null) return null
if (value === undefined) return undefined
if (Array.isArray(value)) return value
Expand Down
4 changes: 2 additions & 2 deletions packages/schemas/features/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from './blocks'
import { publicTypebotSchema } from './publicTypebot'
import { logSchema, resultSchema } from './result'
import { typebotSchema } from './typebot'
import { listVariableValue, typebotSchema } from './typebot'
import {
textBubbleContentSchema,
imageBubbleContentSchema,
Expand Down Expand Up @@ -123,7 +123,7 @@ const scriptToExecuteSchema = z.object({
.string()
.or(z.number())
.or(z.boolean())
.or(z.array(z.string()))
.or(listVariableValue)
.nullish(),
})
),
Expand Down
6 changes: 4 additions & 2 deletions packages/schemas/features/typebot/variable.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { z } from 'zod'

export const listVariableValue = z.array(z.string().nullable())

export const variableSchema = z.object({
id: z.string(),
name: z.string(),
value: z.string().or(z.array(z.string())).nullish(),
value: z.string().or(listVariableValue).nullish(),
})

/**
Expand All @@ -12,7 +14,7 @@ export const variableSchema = z.object({
export const variableWithValueSchema = z.object({
id: z.string(),
name: z.string(),
value: z.string().or(z.array(z.string())),
value: z.string().or(listVariableValue),
})

/**
Expand Down

4 comments on commit 0c39ae4

@vercel
Copy link

@vercel vercel bot commented on 0c39ae4 Mar 21, 2023

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 0c39ae4 Mar 21, 2023

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

@vercel
Copy link

@vercel vercel bot commented on 0c39ae4 Mar 21, 2023

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:

viewer-v2 – ./apps/viewer

1stop.au
yobot.me
klujo.com
me.cr8.ai
247987.com
8jours.top
aginap.com
ai.mprs.in
bee.cr8.ai
bot.aws.bj
bot.bbc.bj
cat.cr8.ai
finplex.be
nepkit.com
pig.cr8.ai
sat.cr8.ai
bot.aipr.kr
bot.joof.it
bull.cr8.ai
docs.cr8.ai
minipost.uk
mole.cr8.ai
team.cr8.ai
wolf.cr8.ai
bot.grace.bj
cinecorn.com
help.taxt.co
kusamint.com
rhino.cr8.ai
sheep.cr8.ai
snake.cr8.ai
svhm.mprs.in
tiger.cr8.ai
video.cr8.ai
yoda.riku.ai
zebra.cr8.ai
bergamo.store
bot.krdfy.com
bot.tvbeat.it
cgcassets.com
cnvhub.com.br
facelabko.com
filmylogy.com
goldorayo.com
rabbit.cr8.ai
abg-assistent.m-vogel.de
ai.chromebookstoreph.com
contextone.wpwakanda.com
form.sergiolimajr.com.br
hunterbot.saleshunter.ai
invite.bridesquadapp.com
link.cascadigital.com.br
onboarding.growthside.io
reward.onlinebotdemo.xyz
stap.venturemarketing.in
type.opaulovieira.com.br
aibot.angrybranding.co.uk
bot.aidigitalmarketing.kr
bot.amicidisanfaustino.it
bot.polychromes-project.com
bot.seidinembroseanchetu.it
chat.semanalimpanome.com.br
chatbot.berbelanjabiz.trade
designguide.techyscouts.com
liveconvert2.kandalearn.com
presente.empresarias.com.mx
sell.sellthemotorhome.co.uk
anamnese.odontopavani.com.br
austin.channelautomation.com
bot.marketingplusmindset.com
bot.seidibergamoseanchetu.it
desabafe.sergiolimajr.com.br
download.venturemarketing.in
piazzatorre.barrettamario.it
type.cookieacademyonline.com
upload.atlasoutfittersk9.com
bot.brigadeirosemdrama.com.br
forms.escoladeautomacao.com.br
onboarding.libertydreamcare.ie
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
anamnese.clinicamegasjdr.com.br
bookings.littlepartymonkeys.com
bot.comercializadoraomicron.com
elevateyourmind.groovepages.com
viewer-v2-typebot-io.vercel.app
yourfeedback.comebackreward.com
bot.cabin-rentals-of-georgia.net
gerador.verificadordehospedes.com
personal-trainer.barrettamario.it
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
download.thailandmicespecialist.com
register.thailandmicespecialist.com
bot.studiotecnicoimmobiliaremerelli.it
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
chrome-os-inquiry-system.itschromeos.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com

@vercel
Copy link

@vercel vercel bot commented on 0c39ae4 Mar 21, 2023

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:

docs – ./apps/docs

docs.typebot.io
docs-git-main-typebot-io.vercel.app
docs-typebot-io.vercel.app

Please sign in to comment.