🚸 (sheets) Better Get data settings UI
This commit is contained in:
@@ -78,7 +78,7 @@ export const TableList = <T,>({
|
|||||||
const handleMouseLeave = () => setShowDeleteIndex(null)
|
const handleMouseLeave = () => setShowDeleteIndex(null)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={0} pt="2">
|
<Stack spacing={0}>
|
||||||
{items.map((item, itemIndex) => (
|
{items.map((item, itemIndex) => (
|
||||||
<Box key={item.id}>
|
<Box key={item.id}>
|
||||||
{itemIndex !== 0 && ComponentBetweenItems && (
|
{itemIndex !== 0 && ComponentBetweenItems && (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AlertInfo } from '@/components/AlertInfo'
|
import { AlertInfo } from '@/components/AlertInfo'
|
||||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import { useI18n, useScopedI18n } from '@/locales'
|
import { useI18n } from '@/locales'
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useI18n, useScopedI18n } from '@/locales'
|
|
||||||
import { Tag, TagProps, ThemeTypings } from '@chakra-ui/react'
|
import { Tag, TagProps, ThemeTypings } from '@chakra-ui/react'
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
import { Divider, Stack, Text, useDisclosure } from '@chakra-ui/react'
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionButton,
|
||||||
|
AccordionIcon,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionPanel,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
useDisclosure,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
import { DropdownList } from '@/components/DropdownList'
|
import { DropdownList } from '@/components/DropdownList'
|
||||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import {
|
import {
|
||||||
@@ -97,7 +106,7 @@ export const GoogleSheetsSettings = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack spacing={4}>
|
||||||
{workspace && (
|
{workspace && (
|
||||||
<CredentialsDropdown
|
<CredentialsDropdown
|
||||||
type="google sheets"
|
type="google sheets"
|
||||||
@@ -130,15 +139,12 @@ export const GoogleSheetsSettings = ({
|
|||||||
{options?.spreadsheetId &&
|
{options?.spreadsheetId &&
|
||||||
options.credentialsId &&
|
options.credentialsId &&
|
||||||
isDefined(options.sheetId) && (
|
isDefined(options.sheetId) && (
|
||||||
<>
|
<DropdownList
|
||||||
<Divider />
|
currentItem={'action' in options ? options.action : undefined}
|
||||||
<DropdownList
|
onItemSelect={handleActionChange}
|
||||||
currentItem={'action' in options ? options.action : undefined}
|
items={Object.values(GoogleSheetsAction)}
|
||||||
onItemSelect={handleActionChange}
|
placeholder="Select an operation"
|
||||||
items={Object.values(GoogleSheetsAction)}
|
/>
|
||||||
placeholder="Select an operation"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
{options.action && (
|
{options.action && (
|
||||||
<ActionOptions
|
<ActionOptions
|
||||||
@@ -175,9 +181,8 @@ const ActionOptions = ({
|
|||||||
const handleExtractingCellsChange = (cellsToExtract: ExtractingCell[]) =>
|
const handleExtractingCellsChange = (cellsToExtract: ExtractingCell[]) =>
|
||||||
onOptionsChange({ ...options, cellsToExtract } as GoogleSheetsOptions)
|
onOptionsChange({ ...options, cellsToExtract } as GoogleSheetsOptions)
|
||||||
|
|
||||||
const handleFilterChange = (
|
const handleFilterChange = (filter: GoogleSheetsGetOptions['filter']) =>
|
||||||
filter: NonNullable<GoogleSheetsGetOptions['filter']>
|
onOptionsChange({ ...options, filter } as GoogleSheetsOptions)
|
||||||
) => onOptionsChange({ ...options, filter } as GoogleSheetsOptions)
|
|
||||||
|
|
||||||
const UpdatingCellItem = useMemo(
|
const UpdatingCellItem = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -227,36 +232,61 @@ const ActionOptions = ({
|
|||||||
)
|
)
|
||||||
case GoogleSheetsAction.GET:
|
case GoogleSheetsAction.GET:
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Accordion allowMultiple>
|
||||||
{options.referenceCell && (
|
{options.referenceCell && (
|
||||||
<>
|
<AccordionItem>
|
||||||
<Text>Row to select</Text>
|
<AccordionButton>
|
||||||
<CellWithValueStack
|
<Text w="full" textAlign="left">
|
||||||
columns={sheet?.columns ?? []}
|
Rows to select
|
||||||
item={options.referenceCell ?? { id: 'reference' }}
|
</Text>
|
||||||
onItemChange={handleReferenceCellChange}
|
<AccordionIcon />
|
||||||
/>
|
</AccordionButton>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{options.filter && (
|
|
||||||
<>
|
|
||||||
<Text>Filter</Text>
|
|
||||||
<RowsFilterTableList
|
|
||||||
columns={sheet?.columns ?? []}
|
|
||||||
filter={options.filter ?? {}}
|
|
||||||
onFilterChange={handleFilterChange}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Text>Cells to extract</Text>
|
<AccordionPanel pt="4">
|
||||||
<TableList<ExtractingCell>
|
<CellWithValueStack
|
||||||
initialItems={options.cellsToExtract}
|
columns={sheet?.columns ?? []}
|
||||||
onItemsChange={handleExtractingCellsChange}
|
item={options.referenceCell ?? { id: 'reference' }}
|
||||||
Item={ExtractingCellItem}
|
onItemChange={handleReferenceCellChange}
|
||||||
addLabel="Add a value"
|
/>
|
||||||
/>
|
</AccordionPanel>
|
||||||
</Stack>
|
</AccordionItem>
|
||||||
|
)}
|
||||||
|
{!options.referenceCell && (
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionButton>
|
||||||
|
<Text w="full" textAlign="left">
|
||||||
|
Rows to filter
|
||||||
|
</Text>
|
||||||
|
<AccordionIcon />
|
||||||
|
</AccordionButton>
|
||||||
|
|
||||||
|
<AccordionPanel pt="4">
|
||||||
|
<RowsFilterTableList
|
||||||
|
columns={sheet?.columns ?? []}
|
||||||
|
filter={options.filter}
|
||||||
|
onFilterChange={handleFilterChange}
|
||||||
|
/>
|
||||||
|
</AccordionPanel>
|
||||||
|
</AccordionItem>
|
||||||
|
)}
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionButton>
|
||||||
|
<Text w="full" textAlign="left">
|
||||||
|
Columns to extract
|
||||||
|
</Text>
|
||||||
|
<AccordionIcon />
|
||||||
|
</AccordionButton>
|
||||||
|
|
||||||
|
<AccordionPanel pt="4">
|
||||||
|
<TableList<ExtractingCell>
|
||||||
|
initialItems={options.cellsToExtract}
|
||||||
|
onItemsChange={handleExtractingCellsChange}
|
||||||
|
Item={ExtractingCellItem}
|
||||||
|
addLabel="Add a value"
|
||||||
|
/>
|
||||||
|
</AccordionPanel>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return <></>
|
return <></>
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ import React, { useCallback } from 'react'
|
|||||||
import { RowsFilterComparisonItem } from './RowsFilterComparisonItem'
|
import { RowsFilterComparisonItem } from './RowsFilterComparisonItem'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
filter: NonNullable<GoogleSheetsGetOptions['filter']>
|
filter: GoogleSheetsGetOptions['filter']
|
||||||
columns: string[]
|
columns: string[]
|
||||||
onFilterChange: (
|
onFilterChange: (filter: GoogleSheetsGetOptions['filter']) => void
|
||||||
filter: NonNullable<GoogleSheetsGetOptions['filter']>
|
|
||||||
) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RowsFilterTableList = ({
|
export const RowsFilterTableList = ({
|
||||||
@@ -22,11 +20,15 @@ export const RowsFilterTableList = ({
|
|||||||
columns,
|
columns,
|
||||||
onFilterChange,
|
onFilterChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const handleComparisonsChange = (comparisons: RowsFilterComparison[]) =>
|
const updateComparisons = (comparisons: RowsFilterComparison[]) =>
|
||||||
onFilterChange({ ...filter, comparisons })
|
onFilterChange({
|
||||||
|
...filter,
|
||||||
|
logicalOperator: filter?.logicalOperator ?? LogicalOperator.AND,
|
||||||
|
comparisons,
|
||||||
|
})
|
||||||
|
|
||||||
const handleLogicalOperatorChange = (logicalOperator: LogicalOperator) =>
|
const updateLogicalOperator = (logicalOperator: LogicalOperator) =>
|
||||||
onFilterChange({ ...filter, logicalOperator })
|
filter && onFilterChange({ ...filter, logicalOperator })
|
||||||
|
|
||||||
const createRowsFilterComparisonItem = useCallback(
|
const createRowsFilterComparisonItem = useCallback(
|
||||||
(props: TableListItemProps<RowsFilterComparison>) => (
|
(props: TableListItemProps<RowsFilterComparison>) => (
|
||||||
@@ -37,14 +39,14 @@ export const RowsFilterTableList = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TableList<RowsFilterComparison>
|
<TableList<RowsFilterComparison>
|
||||||
initialItems={filter?.comparisons}
|
initialItems={filter?.comparisons ?? []}
|
||||||
onItemsChange={handleComparisonsChange}
|
onItemsChange={updateComparisons}
|
||||||
Item={createRowsFilterComparisonItem}
|
Item={createRowsFilterComparisonItem}
|
||||||
ComponentBetweenItems={() => (
|
ComponentBetweenItems={() => (
|
||||||
<Flex justify="center">
|
<Flex justify="center">
|
||||||
<DropdownList
|
<DropdownList
|
||||||
currentItem={filter?.logicalOperator}
|
currentItem={filter?.logicalOperator}
|
||||||
onItemSelect={handleLogicalOperatorChange}
|
onItemSelect={updateLogicalOperator}
|
||||||
items={Object.values(LogicalOperator)}
|
items={Object.values(LogicalOperator)}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ test.describe.parallel('Google sheets integration', () => {
|
|||||||
await page.click('text=Select an operation')
|
await page.click('text=Select an operation')
|
||||||
await page.click('text=Get data from sheet')
|
await page.click('text=Get data from sheet')
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Rows to filter' }).click()
|
||||||
|
await page.getByRole('button', { name: 'Add filter rule' }).click()
|
||||||
await page.click('text=Select a column')
|
await page.click('text=Select a column')
|
||||||
await page.click('button >> text="Email"')
|
await page.click('button >> text="Email"')
|
||||||
await page.getByRole('button', { name: 'Select an operator' }).click()
|
await page.getByRole('button', { name: 'Select an operator' }).click()
|
||||||
@@ -110,6 +112,7 @@ test.describe.parallel('Google sheets integration', () => {
|
|||||||
await page.getByRole('button', { name: 'AND', exact: true }).click()
|
await page.getByRole('button', { name: 'AND', exact: true }).click()
|
||||||
await page.getByRole('menuitem', { name: 'OR' }).click()
|
await page.getByRole('menuitem', { name: 'OR' }).click()
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Columns to extract' }).click()
|
||||||
await page.click('text=Select a column')
|
await page.click('text=Select a column')
|
||||||
await page.getByRole('menuitem', { name: 'Email' }).click()
|
await page.getByRole('menuitem', { name: 'Email' }).click()
|
||||||
await page.getByRole('button', { name: 'Select an operator' }).click()
|
await page.getByRole('button', { name: 'Select an operator' }).click()
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
}).files.list({
|
}).files.list({
|
||||||
q: "mimeType='application/vnd.google-apps.spreadsheet'",
|
q: "mimeType='application/vnd.google-apps.spreadsheet'",
|
||||||
fields: 'nextPageToken, files(id, name)',
|
fields: 'nextPageToken, files(id, name)',
|
||||||
|
pageSize: 300,
|
||||||
})
|
})
|
||||||
return res.send(response.data)
|
return res.send(response.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
- Paste the following Custom CSS:
|
- Paste the following Custom CSS:
|
||||||
|
|
||||||
```css
|
```css
|
||||||
body {
|
.typebot-container {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,15 +13,9 @@ body {
|
|||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.typebot-guest-bubble {
|
.guest-container {
|
||||||
margin-right: 0;
|
margin-left: 0;
|
||||||
margin-left: 0.5rem;
|
margin-right: 50px;
|
||||||
}
|
|
||||||
|
|
||||||
.bubble1,
|
|
||||||
.bubble2 {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -518,6 +518,18 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"clickLink": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"alt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -179,6 +179,18 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"clickLink": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"alt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -2923,6 +2935,18 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"clickLink": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"alt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { ComponentProps } from 'react'
|
import { ComponentProps } from 'react'
|
||||||
import {
|
import {
|
||||||
Mjml,
|
Mjml,
|
||||||
MjmlBody,
|
MjmlBody,
|
||||||
@@ -17,14 +17,6 @@ type ReachedChatsLimitEmailProps = {
|
|||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const firstDayOfNextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1)
|
|
||||||
const readableResetDate = firstDayOfNextMonth
|
|
||||||
.toDateString()
|
|
||||||
.split(' ')
|
|
||||||
.slice(1, 4)
|
|
||||||
.join(' ')
|
|
||||||
|
|
||||||
export const ReachedChatsLimitEmail = ({
|
export const ReachedChatsLimitEmail = ({
|
||||||
chatsLimit,
|
chatsLimit,
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type Props = {
|
|||||||
|
|
||||||
export const GuestBubble = (props: Props) => (
|
export const GuestBubble = (props: Props) => (
|
||||||
<div
|
<div
|
||||||
class="flex justify-end mb-2 items-end animate-fade-in"
|
class="flex justify-end mb-2 items-end animate-fade-in guest-container"
|
||||||
style={{ 'margin-left': '50px' }}
|
style={{ 'margin-left': '50px' }}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -104,14 +104,6 @@ export const defaultGoogleSheetsGetOptions = (
|
|||||||
id: createId(),
|
id: createId(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
filter: {
|
|
||||||
comparisons: [
|
|
||||||
{
|
|
||||||
id: createId(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
logicalOperator: LogicalOperator.AND,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const defaultGoogleSheetsInsertOptions = (
|
export const defaultGoogleSheetsInsertOptions = (
|
||||||
|
|||||||
Reference in New Issue
Block a user