@ -31,6 +31,13 @@ export default defineConfig({
|
||||
locale: 'en-US',
|
||||
baseURL: process.env.NEXTAUTH_URL,
|
||||
storageState: './src/test/storageState.json',
|
||||
permissions: ['microphone'],
|
||||
launchOptions: {
|
||||
args: [
|
||||
'--use-fake-ui-for-media-stream',
|
||||
'--use-fake-device-for-media-stream',
|
||||
],
|
||||
},
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
|
@ -16,6 +16,10 @@ export const TextInputNodeContent = ({ options }: Props) => {
|
||||
typebot &&
|
||||
options?.attachments?.isEnabled &&
|
||||
options?.attachments.saveVariableId
|
||||
const audioClipVariableId =
|
||||
typebot &&
|
||||
options?.audioClip?.isEnabled &&
|
||||
options?.audioClip.saveVariableId
|
||||
if (options?.variableId)
|
||||
return (
|
||||
<Stack w="calc(100% - 25px)">
|
||||
@ -29,6 +33,12 @@ export const TextInputNodeContent = ({ options }: Props) => {
|
||||
variableId={attachmentVariableId}
|
||||
/>
|
||||
)}
|
||||
{audioClipVariableId && (
|
||||
<SetVariableLabel
|
||||
variables={typebot.variables}
|
||||
variableId={audioClipVariableId}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
return (
|
||||
@ -43,6 +53,12 @@ export const TextInputNodeContent = ({ options }: Props) => {
|
||||
variableId={attachmentVariableId}
|
||||
/>
|
||||
)}
|
||||
{audioClipVariableId && (
|
||||
<SetVariableLabel
|
||||
variables={typebot.variables}
|
||||
variableId={audioClipVariableId}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
@ -49,6 +49,26 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
attachments: { ...options?.attachments, visibility },
|
||||
})
|
||||
|
||||
const updateAudioClipEnabled = (isEnabled: boolean) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
audioClip: { ...options?.audioClip, isEnabled },
|
||||
})
|
||||
|
||||
const updateAudioClipSaveVariableId = (variable?: Pick<Variable, 'id'>) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
audioClip: { ...options?.audioClip, saveVariableId: variable?.id },
|
||||
})
|
||||
|
||||
const updateAudioClipVisibility = (
|
||||
visibility: (typeof fileVisibilityOptions)[number]
|
||||
) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
audioClip: { ...options?.audioClip, visibility },
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithLabel
|
||||
@ -71,6 +91,34 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
}
|
||||
onChange={updateButtonLabel}
|
||||
/>
|
||||
<SwitchWithRelatedSettings
|
||||
label={'Allow audio clip'}
|
||||
initialValue={
|
||||
options?.audioClip?.isEnabled ??
|
||||
defaultTextInputOptions.audioClip.isEnabled
|
||||
}
|
||||
onCheckChange={updateAudioClipEnabled}
|
||||
>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="variable">
|
||||
Save the URL in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options?.audioClip?.saveVariableId}
|
||||
onSelectVariable={updateAudioClipSaveVariableId}
|
||||
/>
|
||||
</Stack>
|
||||
<DropdownList
|
||||
label="Visibility:"
|
||||
moreInfoTooltip='This setting determines who can see the uploaded files. "Public" means that anyone who has the link can see the files. "Private" means that only a members of this workspace can see the files.'
|
||||
currentItem={
|
||||
options?.audioClip?.visibility ??
|
||||
defaultTextInputOptions.audioClip.visibility
|
||||
}
|
||||
onItemSelect={updateAudioClipVisibility}
|
||||
items={fileVisibilityOptions}
|
||||
/>
|
||||
</SwitchWithRelatedSettings>
|
||||
<SwitchWithRelatedSettings
|
||||
label={'Allow attachments'}
|
||||
initialValue={
|
||||
|
@ -39,7 +39,7 @@ test.describe.parallel('Text input block', () => {
|
||||
await expect(page.getByRole('button', { name: 'Go' })).toBeVisible()
|
||||
})
|
||||
|
||||
test('hey boy', async ({ page }) => {
|
||||
test('attachments should work', async ({ page }) => {
|
||||
const typebotId = createId()
|
||||
await createTypebots([
|
||||
{
|
||||
@ -82,4 +82,31 @@ test.describe.parallel('Text input block', () => {
|
||||
).toBeVisible()
|
||||
await expect(page.getByText('Help me with these')).toBeVisible()
|
||||
})
|
||||
|
||||
test('audio clips should work', async ({ page }) => {
|
||||
const typebotId = createId()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
|
||||
await page.click(`text=${defaultTextInputOptions.labels.placeholder}`)
|
||||
await page.getByText('Allow audio clip').click()
|
||||
await page.locator('[data-testid="variables-input"]').first().click()
|
||||
await page.getByText('var1').click()
|
||||
await page.getByRole('button', { name: 'Test' }).click()
|
||||
await page.getByRole('button', { name: 'Record voice' }).click()
|
||||
await page.waitForTimeout(1000)
|
||||
await page.getByRole('button', { name: 'Send' }).click()
|
||||
await expect(page.locator('audio')).toHaveAttribute(
|
||||
'src',
|
||||
/http:\/\/localhost:9000/
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -12986,6 +12986,37 @@
|
||||
"workspaceId",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"segment"
|
||||
]
|
||||
},
|
||||
"workspaceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data",
|
||||
"type",
|
||||
"workspaceId",
|
||||
"name"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -13106,7 +13137,8 @@
|
||||
"anthropic",
|
||||
"together-ai",
|
||||
"open-router",
|
||||
"nocodb"
|
||||
"nocodb",
|
||||
"segment"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -13142,7 +13174,8 @@
|
||||
"anthropic",
|
||||
"together-ai",
|
||||
"open-router",
|
||||
"nocodb"
|
||||
"nocodb",
|
||||
"segment"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
@ -13838,6 +13871,37 @@
|
||||
"type",
|
||||
"workspaceId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"segment"
|
||||
]
|
||||
},
|
||||
"workspaceId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"data",
|
||||
"type",
|
||||
"workspaceId"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -16402,6 +16466,25 @@
|
||||
"isLong": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"audioClip": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"saveVariableId": {
|
||||
"type": "string"
|
||||
},
|
||||
"visibility": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Auto",
|
||||
"Public",
|
||||
"Private"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"attachments": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -22214,6 +22297,176 @@
|
||||
"id",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"outgoingEdgeId": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"segment"
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Alias"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"previousId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Identify User"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"traits": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Page"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Track"
|
||||
]
|
||||
},
|
||||
"eventName": {
|
||||
"type": "string"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Block"
|
||||
|
@ -1082,6 +1082,25 @@
|
||||
"type",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"audio"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"description": "Can only be provided if current input block is a text input that allows audio clips"
|
||||
}
|
||||
],
|
||||
"description": "Only provide it if your flow starts with an input block and you'd like to directly provide an answer to it."
|
||||
@ -1502,6 +1521,25 @@
|
||||
"type",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"audio"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"description": "Can only be provided if current input block is a text input that allows audio clips"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1872,6 +1910,25 @@
|
||||
"type",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"audio"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"description": "Can only be provided if current input block is a text input that allows audio clips"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -5928,6 +5985,25 @@
|
||||
"isLong": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"audioClip": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"saveVariableId": {
|
||||
"type": "string"
|
||||
},
|
||||
"visibility": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Auto",
|
||||
"Public",
|
||||
"Private"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"attachments": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -12505,6 +12581,176 @@
|
||||
"id",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"outgoingEdgeId": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"segment"
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Alias"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"previousId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Identify User"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"traits": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Page"
|
||||
]
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"credentialsId": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Track"
|
||||
]
|
||||
},
|
||||
"eventName": {
|
||||
"type": "string"
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Block"
|
||||
|
@ -85,7 +85,9 @@ export const generateUploadUrl = publicProcedure
|
||||
if (
|
||||
block?.type !== InputBlockType.FILE &&
|
||||
(block.type !== InputBlockType.TEXT ||
|
||||
!block.options?.attachments?.isEnabled)
|
||||
!block.options?.attachments?.isEnabled) &&
|
||||
(block.type !== InputBlockType.TEXT ||
|
||||
!block.options?.audioClip?.isEnabled)
|
||||
)
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
|
@ -27,7 +27,10 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.getByRole('link', { name: 'api.json' })).toHaveAttribute(
|
||||
'href',
|
||||
/.+\/api\.json/
|
||||
/.+\/api\.json/,
|
||||
{
|
||||
timeout: 10000,
|
||||
}
|
||||
)
|
||||
await expect(
|
||||
page.getByRole('link', { name: 'fileUpload.json' })
|
||||
|
@ -17,7 +17,9 @@ test('Big groups should work as expected', async ({ page }) => {
|
||||
await page.locator('input').press('Enter')
|
||||
await page.getByRole('button', { name: 'Yes' }).click()
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text="Baptiste"')).toBeVisible()
|
||||
await expect(page.locator('text="Baptiste"')).toBeVisible({
|
||||
timeout: 10000,
|
||||
})
|
||||
await expect(page.locator('text="26"')).toBeVisible()
|
||||
await expect(page.locator('text="Yes"')).toBeVisible()
|
||||
await page.hover('tbody > tr')
|
||||
|
Reference in New Issue
Block a user