2
0

feat(editor): Add file upload input

This commit is contained in:
Baptiste Arnaud
2022-06-12 17:34:33 +02:00
parent d4c52d47b3
commit 75365a0d82
48 changed files with 1022 additions and 587 deletions

View File

@ -1,11 +1,17 @@
import { ResultWithAnswers, VariableWithValue, ResultHeaderCell } from 'models'
import {
ResultWithAnswers,
VariableWithValue,
ResultHeaderCell,
InputBlockType,
} from 'models'
import useSWRInfinite from 'swr/infinite'
import { stringify } from 'qs'
import { Answer } from 'db'
import { isDefined, isEmpty, sendRequest } from 'utils'
import { fetcher } from 'services/utils'
import { HStack, Text } from '@chakra-ui/react'
import { CodeIcon, CalendarIcon } from 'assets/icons'
import { HStack, Text, Wrap, WrapItem } from '@chakra-ui/react'
import { CodeIcon, CalendarIcon, FileIcon } from 'assets/icons'
import { Link } from '@chakra-ui/react'
import { BlockIcon } from 'components/editor/BlocksSideBar/BlockIcon'
const paginationLimit = 50
@ -147,28 +153,47 @@ const HeaderIcon = ({ header }: { header: ResultHeaderCell }) =>
export const convertResultsToTableData = (
results: ResultWithAnswers[] | undefined,
header: ResultHeaderCell[]
): { [key: string]: string }[] =>
headerCells: ResultHeaderCell[]
): { [key: string]: JSX.Element | string }[] =>
(results ?? []).map((result) => ({
'Submitted at': parseDateToReadable(result.createdAt),
...[...result.answers, ...result.variables].reduce<{
[key: string]: string
[key: string]: JSX.Element | string
}>((o, answerOrVariable) => {
if ('groupId' in answerOrVariable) {
const answer = answerOrVariable as Answer
const key = answer.variableId
? header.find((h) => h.variableId === answer.variableId)?.label
: header.find((h) => h.blockId === answer.blockId)?.label
if (!key) return o
const header = answer.variableId
? headerCells.find((h) => h.variableId === answer.variableId)
: headerCells.find((h) => h.blockId === answer.blockId)
if (!header || !header.blockId || !header.blockType) return o
return {
...o,
[key]: answer.content,
[header.label]: parseContent(answer.content, header.blockType),
}
}
const variable = answerOrVariable as VariableWithValue
if (isDefined(o[variable.id])) return o
const key = header.find((h) => h.variableId === variable.id)?.label
const key = headerCells.find((h) => h.variableId === variable.id)?.label
if (!key) return o
return { ...o, [key]: variable.value }
}, {}),
}))
const parseContent = (str: string, blockType: InputBlockType) =>
blockType === InputBlockType.FILE ? parseFileContent(str) : str
const parseFileContent = (str: string) => {
const fileNames = str.split(', ')
return (
<Wrap maxW="300px">
{fileNames.map((name) => (
<HStack as={WrapItem} key={name}>
<FileIcon />
<Link href={name} isExternal color="blue.500">
{name.split('/').pop()}
</Link>
</HStack>
))}
</Wrap>
)
}

View File

@ -39,6 +39,7 @@ import {
ConditionBlock,
defaultPaymentInputOptions,
defaultRatingInputOptions,
defaultFileInputOptions,
} from 'models'
import { Typebot } from 'models'
import useSWR from 'swr'
@ -329,6 +330,8 @@ const parseDefaultBlockOptions = (type: BlockWithOptionsType): BlockOptions => {
return defaultPaymentInputOptions
case InputBlockType.RATING:
return defaultRatingInputOptions
case InputBlockType.FILE:
return defaultFileInputOptions
case LogicBlockType.SET_VARIABLE:
return defaultSetVariablesOptions
case LogicBlockType.REDIRECT:

View File

@ -1,7 +1,6 @@
import imageCompression from 'browser-image-compression'
import { Parser } from 'htmlparser2'
import { Block, Typebot } from 'models'
import { sendRequest } from 'utils'
export const fetcher = async (input: RequestInfo, init?: RequestInit) => {
const res = await fetch(input, init)
@ -37,26 +36,6 @@ export const toKebabCase = (value: string) => {
return matched.map((x) => x.toLowerCase()).join('-')
}
export const uploadFile = async (file: File, filePath: string) => {
const { data } = await sendRequest<{ presignedUrl: string }>(
`/api/storage/upload-url?filePath=${encodeURIComponent(filePath)}`
)
if (!data?.presignedUrl)
return {
url: null,
}
await fetch(data.presignedUrl, {
method: 'PUT',
body: file,
})
return {
url: data.presignedUrl.split('?')[0],
}
}
export const compressFile = async (file: File) => {
const options = {
maxSizeMB: 0.5,