Skip to content

Commit

Permalink
feat(bot): ⚡️ Add required option on file upload input
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jun 25, 2022
1 parent a4aa293 commit 55108c8
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,27 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handlePlaceholderLabelChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleLongChange = (isMultipleAllowed: boolean) =>
const handleMultipleFilesChange = (isMultipleAllowed: boolean) =>
onOptionsChange({ ...options, isMultipleAllowed })
const handleVariableChange = (variable?: Variable) =>
onOptionsChange({ ...options, variableId: variable?.id })
const handleSizeLimitChange = (sizeLimit?: number) =>
onOptionsChange({ ...options, sizeLimit })
const handleRequiredChange = (isRequired: boolean) =>
onOptionsChange({ ...options, isRequired })
return (
<Stack spacing={4}>
<SwitchWithLabel
id="required"
label="Required?"
initialValue={options.isRequired ?? true}
onCheckChange={handleRequiredChange}
/>
<SwitchWithLabel
id="switch"
label="Allow multiple files?"
initialValue={options.isMultipleAllowed}
onCheckChange={handleLongChange}
onCheckChange={handleMultipleFilesChange}
/>
<Stack>
<FormLabel mb="0" htmlFor="limit">
Expand Down
3 changes: 3 additions & 0 deletions apps/builder/playwright/tests/inputs/file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@ test('options should work', async ({ page }) => {
await expect(
typebotViewer(page).locator(`text=Click to upload`)
).toBeVisible()
await expect(typebotViewer(page).locator(`text="Skip"`)).toBeHidden()
await typebotViewer(page)
.locator(`input[type="file"]`)
.setInputFiles([path.join(__dirname, '../../fixtures/avatar.jpg')])
await expect(typebotViewer(page).locator(`text=File uploaded`)).toBeVisible()
await page.click('text="Collect file"')
await page.click('text="Required?"')
await page.click('text="Allow multiple files?"')
await page.fill('div[contenteditable=true]', '<strong>Upload now!!</strong>')
await page.fill('[value="Upload"]', 'Go')
await page.fill('input[value="10"]', '20')
await page.click('text="Restart"')
await expect(typebotViewer(page).locator(`text="Skip"`)).toBeVisible()
await expect(typebotViewer(page).locator(`text="Upload now!!"`)).toBeVisible()
await typebotViewer(page)
.locator(`input[type="file"]`)
Expand Down
3 changes: 1 addition & 2 deletions apps/viewer/playwright/tests/fileUpload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import { parse } from 'papaparse'
import { typebotViewer } from '../services/selectorUtils'
import { importTypebotInDatabase } from '../services/database'
import { readFileSync } from 'fs'
import { isDefined } from 'utils'

test('should work as expected', async ({ page, browser }) => {
test('should work as expected', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/fileUpload.json'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const InputChatBlock = ({
hasAvatar,
hasGuestAvatar,
onTransitionEnd,
onSkip,
}: {
block: InputBlock
hasGuestAvatar: boolean
Expand All @@ -32,6 +33,7 @@ export const InputChatBlock = ({
answerContent?: InputSubmitContent,
isRetry?: boolean
) => void
onSkip: () => void
}) => {
const { typebot } = useTypebot()
const { addAnswer } = useAnswers()
Expand Down Expand Up @@ -84,6 +86,7 @@ export const InputChatBlock = ({
<Input
block={block}
onSubmit={handleSubmit}
onSkip={onSkip}
defaultValue={defaultValue?.toString()}
hasGuestAvatar={hasGuestAvatar}
/>
Expand All @@ -94,11 +97,13 @@ export const InputChatBlock = ({
const Input = ({
block,
onSubmit,
onSkip,
defaultValue,
hasGuestAvatar,
}: {
block: InputBlock
onSubmit: (value: InputSubmitContent) => void
onSkip: () => void
defaultValue?: string
hasGuestAvatar: boolean
}) => {
Expand Down Expand Up @@ -132,6 +137,8 @@ const Input = ({
case InputBlockType.RATING:
return <RatingForm block={block} onSubmit={onSubmit} />
case InputBlockType.FILE:
return <FileUploadForm block={block} onSubmit={onSubmit} />
return (
<FileUploadForm block={block} onSubmit={onSubmit} onSkip={onSkip} />
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import { SendButton, Spinner } from './SendButton'
type Props = {
block: FileInputBlock
onSubmit: (url: InputSubmitContent) => void
onSkip: () => void
}

export const FileUploadForm = ({
block: {
id,
options: { isMultipleAllowed, labels, sizeLimit },
options: { isMultipleAllowed, labels, sizeLimit, isRequired },
},
onSubmit,
onSkip,
}: Props) => {
const {
isPreview,
Expand Down Expand Up @@ -169,6 +171,18 @@ export const FileUploadForm = ({
</>
)}
</label>
{selectedFiles.length === 0 && isRequired === false && (
<div className="flex justify-end">
<button
className={
'py-2 px-4 justify-center font-semibold rounded-md text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button '
}
onClick={onSkip}
>
Skip
</button>
</div>
)}
{isMultipleAllowed && selectedFiles.length > 0 && !isUploading && (
<div className="flex justify-end">
<div className="flex">
Expand Down
44 changes: 28 additions & 16 deletions packages/bot-engine/src/components/ChatGroup/ChatGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,20 @@ const ChatChunks = ({
keepShowingHostAvatar,
onDisplayNextBlock,
}: Props) => {
const [isSkipped, setIsSkipped] = useState(false)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const avatarSideContainerRef = useRef<any>()

useEffect(() => {
refreshTopOffset()
})

const skipInput = () => {
onDisplayNextBlock()
setIsSkipped(true)
}

const refreshTopOffset = () =>
avatarSideContainerRef.current?.refreshTopOffset()

Expand All @@ -260,7 +267,9 @@ const ChatChunks = ({
<AvatarSideContainer
ref={avatarSideContainerRef}
hostAvatarSrc={hostAvatar.src}
keepShowing={keepShowingHostAvatar || isDefined(input)}
keepShowing={
(keepShowingHostAvatar || isDefined(input)) && !isSkipped
}
/>
)}
<div
Expand All @@ -287,21 +296,24 @@ const ChatChunks = ({
</TransitionGroup>
</div>
</div>
<CSSTransition
classNames="bubble"
timeout={500}
unmountOnExit
in={isDefined(input)}
>
{input && (
<InputChatBlock
block={input}
onTransitionEnd={onDisplayNextBlock}
hasAvatar={hostAvatar.isEnabled}
hasGuestAvatar={hasGuestAvatar}
/>
)}
</CSSTransition>
{!isSkipped && (
<CSSTransition
classNames="bubble"
timeout={500}
unmountOnExit
in={isDefined(input)}
>
{input && (
<InputChatBlock
block={input}
onTransitionEnd={onDisplayNextBlock}
onSkip={skipInput}
hasAvatar={hostAvatar.isEnabled}
hasGuestAvatar={hasGuestAvatar}
/>
)}
</CSSTransition>
)}
</>
)
}
2 changes: 2 additions & 0 deletions packages/models/src/typebot/blocks/input/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InputBlockType, optionBaseSchema, blockBaseSchema } from '../shared'

export const fileInputOptionsSchema = optionBaseSchema.and(
z.object({
isRequired: z.boolean().optional(),
isMultipleAllowed: z.boolean(),
labels: z.object({
placeholder: z.string(),
Expand All @@ -20,6 +21,7 @@ export const fileInputStepSchema = blockBaseSchema.and(
)

export const defaultFileInputOptions: FileInputOptions = {
isRequired: true,
isMultipleAllowed: false,
labels: {
placeholder: `<strong>
Expand Down

5 comments on commit 55108c8

@vercel
Copy link

@vercel vercel bot commented on 55108c8 Jun 25, 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

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

@vercel
Copy link

@vercel vercel bot commented on 55108c8 Jun 25, 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:

viewer-v2-alpha – ./apps/viewer

bt.id8rs.com
bot.aws.bj
vhpage.cr8.ai
sat.cr8.ai
apo.nigerias.io
aso.nigerias.io
am.nigerias.io
apr.nigerias.io
ar.nigerias.io
an.nigerias.io
eventhub.com.au
chat.sureb4.com
sakuranembro.it
feedback.ofx.one
games.klujo.com
faqs.nigerias.io
bot.piccinato.co
bot.upfunnel.art
clo.closeer.work
stan.vselise.com
voicehelp.cr8.ai
gentleman-shop.fr
app.chatforms.net
this-is-a-test.com
bot.eventhub.com.au
goalsettingbot.com
zap.techadviser.in
typebot.stillio.com
forms.webisharp.com
bot.ansuraniphone.my
chat.hayurihijab.com
bot.cotemeuplano.com
abutton.wpwakanda.com
get.freebotoffer.xyz
bot.incusservices.com
chat.missarkansas.org
sbutton.wpwakanda.com
bot.meuesocial.com.br
cdd.searchcube.com.sg
apply.ansuraniphone.my
bbutton.wpwwakanda.com
c23111azqw.nigerias.io
form.searchcube.com.sg
felipewelington.com.br
gcase.barrettamario.it
kodawariab736.skeep.it
83242573.actualizar.xyz
view.onlinebotdemo.xyz
mainmenu.diddancing.com
info.clickasuransi.com
91181264.your-access.one
form.sergiolimajr.com.br
hunterbot.saleshunter.ai
type.dericsoncalari.com.br
boyfriend-breakup.riku.ai
aibot.angrybranding.co.uk
designguide.techyscouts.com
type.opaulovieira.com.br
piazzatorre.barrettamario.it
onboarding.libertydreamcare.ie
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
bookings.littlepartymonkeys.com
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
viewer-v2-alpha-git-main-typebot-io.vercel.app
viewer-v2-alpha-typebot-io.vercel.app
bot.comercializadoraomicron.com
personal-trainer.barrettamario.it

@vercel
Copy link

@vercel vercel bot commented on 55108c8 Jun 25, 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 55108c8 Jun 25, 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:

docs – ./apps/docs

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

@vercel
Copy link

@vercel vercel bot commented on 55108c8 Jun 25, 2022

Choose a reason for hiding this comment

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

Please sign in to comment.