2
0

🚸 (sheets) Better Get data settings UI

This commit is contained in:
Baptiste Arnaud
2023-04-11 08:19:42 +02:00
parent 846dac0bf4
commit 6921cc23a5
13 changed files with 133 additions and 84 deletions

View File

@@ -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 && (

View File

@@ -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,

View File

@@ -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'

View File

@@ -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 <></>

View File

@@ -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>

View File

@@ -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()

View File

@@ -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)
} }

View File

@@ -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;
} }
``` ```

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -104,14 +104,6 @@ export const defaultGoogleSheetsGetOptions = (
id: createId(), id: createId(),
}, },
], ],
filter: {
comparisons: [
{
id: createId(),
},
],
logicalOperator: LogicalOperator.AND,
},
}) })
export const defaultGoogleSheetsInsertOptions = ( export const defaultGoogleSheetsInsertOptions = (