♻️ (builder) Change to features-centric folder structure
This commit is contained in:
committed by
Baptiste Arnaud
parent
3686465a85
commit
643571fe7d
@ -0,0 +1,12 @@
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { FileInputOptions } from 'models'
|
||||
|
||||
type Props = {
|
||||
options: FileInputOptions
|
||||
}
|
||||
|
||||
export const FileInputContent = ({ options: { isMultipleAllowed } }: Props) => (
|
||||
<Text noOfLines={1} pr="6">
|
||||
Collect {isMultipleAllowed ? 'files' : 'file'}
|
||||
</Text>
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
import { UploadIcon } from '@/components/icons'
|
||||
import { IconProps } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
|
||||
export const FileInputIcon = (props: IconProps) => (
|
||||
<UploadIcon color="orange.500" {...props} />
|
||||
)
|
@ -0,0 +1,81 @@
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { FileInputOptions, Variable } from 'models'
|
||||
import React from 'react'
|
||||
import { Input, SmartNumberInput } from '@/components/inputs'
|
||||
import { SwitchWithLabel } from '@/components/SwitchWithLabel'
|
||||
import { VariableSearchInput } from '@/components/VariableSearchInput'
|
||||
|
||||
type Props = {
|
||||
options: FileInputOptions
|
||||
onOptionsChange: (options: FileInputOptions) => void
|
||||
}
|
||||
|
||||
export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
const handlePlaceholderLabelChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
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
|
||||
label="Required?"
|
||||
initialValue={options.isRequired ?? true}
|
||||
onCheckChange={handleRequiredChange}
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
label="Allow multiple files?"
|
||||
initialValue={options.isMultipleAllowed}
|
||||
onCheckChange={handleMultipleFilesChange}
|
||||
/>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="limit">
|
||||
Size limit (MB):
|
||||
</FormLabel>
|
||||
<SmartNumberInput
|
||||
id="limit"
|
||||
value={options.sizeLimit ?? 10}
|
||||
onValueChange={handleSizeLimitChange}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0">Placeholder:</FormLabel>
|
||||
<CodeEditor
|
||||
lang="html"
|
||||
onChange={handlePlaceholderLabelChange}
|
||||
value={options.labels.placeholder}
|
||||
height={'100px'}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
Button label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
defaultValue={options.labels.button}
|
||||
onChange={handleButtonLabelChange}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="variable">
|
||||
Save upload URL{options.isMultipleAllowed ? 's' : ''} in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from 'utils/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers'
|
||||
import { defaultFileInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from 'utils/playwright/testHelpers'
|
||||
import cuid from 'cuid'
|
||||
import { freeWorkspaceId } from 'utils/playwright/databaseSetup'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
|
||||
test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
test('options should work', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.FILE,
|
||||
options: defaultFileInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
|
||||
await page.click('text=Preview')
|
||||
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([getTestAsset('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"]`)
|
||||
.setInputFiles([
|
||||
getTestAsset('avatar.jpg'),
|
||||
getTestAsset('avatar.jpg'),
|
||||
getTestAsset('avatar.jpg'),
|
||||
])
|
||||
await expect(typebotViewer(page).locator(`text="3"`)).toBeVisible()
|
||||
await typebotViewer(page).locator('text="Go 3 files"').click()
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text="3 files uploaded"`)
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
test.describe('Free workspace', () => {
|
||||
test("shouldn't be able to publish typebot", async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.FILE,
|
||||
options: defaultFileInputOptions,
|
||||
}),
|
||||
workspaceId: freeWorkspaceId,
|
||||
},
|
||||
])
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
await page.click('text="Collect file"')
|
||||
await page.click('text="Allow multiple files?"')
|
||||
await page.click('text="Publish"')
|
||||
await expect(
|
||||
page.locator(
|
||||
'text="You need to upgrade your plan in order to use file input blocks"'
|
||||
)
|
||||
).toBeVisible()
|
||||
})
|
||||
})
|
@ -0,0 +1,3 @@
|
||||
export { FileInputSettings } from './components/FileInputSettings'
|
||||
export { FileInputContent } from './components/FileInputContent'
|
||||
export { FileInputIcon } from './components/FileInputIcon'
|
Reference in New Issue
Block a user