From 9fc05cb150f9d9a8ca21168a79654b437bde3a5e Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Mon, 5 Feb 2024 14:11:04 +0100 Subject: [PATCH] :children_crossing: (fileUpload) Add success labels cutomization Closes #515 --- .../components/FileInputSettings.tsx | 112 ++++++++++++++---- .../blocks/inputs/url/validateUrl.ts | 4 +- packages/embeds/js/package.json | 2 +- .../fileUpload/components/FileUploadForm.tsx | 26 +++- packages/embeds/nextjs/package.json | 2 +- packages/embeds/react/package.json | 2 +- .../features/blocks/inputs/file/constants.ts | 4 + .../features/blocks/inputs/file/schema.ts | 6 + 8 files changed, 125 insertions(+), 33 deletions(-) diff --git a/apps/builder/src/features/blocks/inputs/fileUpload/components/FileInputSettings.tsx b/apps/builder/src/features/blocks/inputs/fileUpload/components/FileInputSettings.tsx index bfa6fd1fc..21fa055f6 100644 --- a/apps/builder/src/features/blocks/inputs/fileUpload/components/FileInputSettings.tsx +++ b/apps/builder/src/features/blocks/inputs/fileUpload/components/FileInputSettings.tsx @@ -1,4 +1,12 @@ -import { FormLabel, Stack } from '@chakra-ui/react' +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + FormLabel, + Stack, +} from '@chakra-ui/react' import { CodeEditor } from '@/components/inputs/CodeEditor' import { FileInputBlock, Variable } from '@typebot.io/schemas' import React from 'react' @@ -45,6 +53,24 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => { visibility: (typeof fileVisibilityOptions)[number] ) => onOptionsChange({ ...options, visibility }) + const updateSingleFileSuccessLabel = (single: string) => + onOptionsChange({ + ...options, + labels: { + ...options?.labels, + success: { ...options?.labels?.success, single }, + }, + }) + + const updateMultipleFilesSuccessLabel = (multiple: string) => + onOptionsChange({ + ...options, + labels: { + ...options?.labels, + success: { ...options?.labels?.success, multiple }, + }, + }) + return ( { withVariableButton={false} /> - - - + + + + Labels + + + + + {options?.isMultipleAllowed && ( + + )} + {!(options?.isRequired ?? defaultFileInputOptions.isRequired) && ( + + )} + + {options?.isMultipleAllowed && ( + + )} + + + + - url.startsWith('http://localhost') || urlRegex.test(url) + url.startsWith('http://localhost') || + url.startsWith('http://fake-upload-url.com') || + urlRegex.test(url) diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json index 88cfdcc8a..4eedac705 100644 --- a/packages/embeds/js/package.json +++ b/packages/embeds/js/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/js", - "version": "0.2.39", + "version": "0.2.40", "description": "Javascript library to display typebots on your website", "type": "module", "main": "dist/index.js", diff --git a/packages/embeds/js/src/features/blocks/inputs/fileUpload/components/FileUploadForm.tsx b/packages/embeds/js/src/features/blocks/inputs/fileUpload/components/FileUploadForm.tsx index 8180d9e34..c905b3f90 100644 --- a/packages/embeds/js/src/features/blocks/inputs/fileUpload/components/FileUploadForm.tsx +++ b/packages/embeds/js/src/features/blocks/inputs/fileUpload/components/FileUploadForm.tsx @@ -51,7 +51,9 @@ export const FileUploadForm = (props: Props) => { const startSingleFileUpload = async (file: File) => { if (props.context.isPreview || !props.context.resultId) return props.onSubmit({ - label: `File uploaded`, + label: + props.block.options?.labels?.success?.single ?? + defaultFileInputOptions.labels.success.single, value: 'http://fake-upload-url.com', }) setIsUploading(true) @@ -70,7 +72,9 @@ export const FileUploadForm = (props: Props) => { setIsUploading(false) if (urls.length) return props.onSubmit({ - label: `File uploaded`, + label: + props.block.options?.labels?.success?.single ?? + defaultFileInputOptions.labels.success.single, value: urls[0] ? encodeUrl(urls[0]) : '', }) setErrorMessage('An error occured while uploading the file') @@ -79,7 +83,14 @@ export const FileUploadForm = (props: Props) => { const resultId = props.context.resultId if (props.context.isPreview || !resultId) return props.onSubmit({ - label: `${files.length} file${files.length > 1 ? 's' : ''} uploaded`, + label: + files.length > 1 + ? ( + props.block.options?.labels?.success?.multiple ?? + defaultFileInputOptions.labels.success.multiple + ).replaceAll('{total}', files.length.toString()) + : props.block.options?.labels?.success?.single ?? + defaultFileInputOptions.labels.success.single, value: files .map((_, idx) => `http://fake-upload-url.com/${idx}`) .join(', '), @@ -101,7 +112,14 @@ export const FileUploadForm = (props: Props) => { if (urls.length !== files.length) return setErrorMessage('An error occured while uploading the files') props.onSubmit({ - label: `${urls.length} file${urls.length > 1 ? 's' : ''} uploaded`, + label: + urls.length > 1 + ? ( + props.block.options?.labels?.success?.multiple ?? + defaultFileInputOptions.labels.success.multiple + ).replaceAll('{total}', urls.length.toString()) + : props.block.options?.labels?.success?.single ?? + defaultFileInputOptions.labels.success.single, value: urls.filter(isDefined).map(encodeUrl).join(', '), }) } diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json index cd1c8e1d7..64b18d118 100644 --- a/packages/embeds/nextjs/package.json +++ b/packages/embeds/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/nextjs", - "version": "0.2.39", + "version": "0.2.40", "description": "Convenient library to display typebots on your Next.js website", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json index fa2459e78..013cca657 100644 --- a/packages/embeds/react/package.json +++ b/packages/embeds/react/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/react", - "version": "0.2.39", + "version": "0.2.40", "description": "Convenient library to display typebots on your React app", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/schemas/features/blocks/inputs/file/constants.ts b/packages/schemas/features/blocks/inputs/file/constants.ts index 17059c1a6..cdf1eaa01 100644 --- a/packages/schemas/features/blocks/inputs/file/constants.ts +++ b/packages/schemas/features/blocks/inputs/file/constants.ts @@ -12,6 +12,10 @@ export const defaultFileInputOptions = { button: 'Upload', clear: 'Clear', skip: 'Skip', + success: { + single: 'File uploaded', + multiple: '{total} files uploaded', + }, }, } as const satisfies FileInputBlock['options'] diff --git a/packages/schemas/features/blocks/inputs/file/schema.ts b/packages/schemas/features/blocks/inputs/file/schema.ts index f2cf58dae..68e216d43 100644 --- a/packages/schemas/features/blocks/inputs/file/schema.ts +++ b/packages/schemas/features/blocks/inputs/file/schema.ts @@ -13,6 +13,12 @@ const fileInputOptionsV5Schema = optionBaseSchema.merge( button: z.string().optional(), clear: z.string().optional(), skip: z.string().optional(), + success: z + .object({ + single: z.string().optional(), + multiple: z.string().optional(), + }) + .optional(), }) .optional(), sizeLimit: z.number().optional(),