2
0

(sheets) Add option to select single row when matching multiple

Closes #501
This commit is contained in:
Baptiste Arnaud
2023-05-12 11:21:24 -04:00
parent 45224f9fb3
commit 55dbb1abc7
3 changed files with 90 additions and 46 deletions

View File

@ -21,6 +21,7 @@ import {
GoogleSheetsInsertRowOptions, GoogleSheetsInsertRowOptions,
GoogleSheetsOptions, GoogleSheetsOptions,
GoogleSheetsUpdateRowOptions, GoogleSheetsUpdateRowOptions,
totalRowsToExtractOptions,
} from '@typebot.io/schemas' } from '@typebot.io/schemas'
import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import { isDefined } from '@typebot.io/lib' import { isDefined } from '@typebot.io/lib'
@ -184,6 +185,11 @@ const ActionOptions = ({
const handleFilterChange = (filter: GoogleSheetsGetOptions['filter']) => const handleFilterChange = (filter: GoogleSheetsGetOptions['filter']) =>
onOptionsChange({ ...options, filter } as GoogleSheetsOptions) onOptionsChange({ ...options, filter } as GoogleSheetsOptions)
const updateTotalRowsToExtract = (
totalRowsToExtract: GoogleSheetsGetOptions['totalRowsToExtract']
) =>
onOptionsChange({ ...options, totalRowsToExtract } as GoogleSheetsOptions)
const UpdatingCellItem = useMemo( const UpdatingCellItem = useMemo(
() => () =>
function Component(props: TableListItemProps<Cell>) { function Component(props: TableListItemProps<Cell>) {
@ -273,59 +279,69 @@ const ActionOptions = ({
case GoogleSheetsAction.GET: case GoogleSheetsAction.GET:
return ( return (
<Accordion allowMultiple> <Accordion allowMultiple>
{options.referenceCell && ( <Stack>
{options.referenceCell && (
<AccordionItem>
<AccordionButton>
<Text w="full" textAlign="left">
Rows to select
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
<CellWithValueStack
columns={sheet?.columns ?? []}
item={options.referenceCell ?? { id: 'reference' }}
onItemChange={handleReferenceCellChange}
/>
</AccordionPanel>
</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>
<DropdownList
items={totalRowsToExtractOptions}
currentItem={options.totalRowsToExtract ?? 'All'}
onItemSelect={updateTotalRowsToExtract}
/>
</>
)}
<AccordionItem> <AccordionItem>
<AccordionButton> <AccordionButton>
<Text w="full" textAlign="left"> <Text w="full" textAlign="left">
Rows to select Columns to extract
</Text> </Text>
<AccordionIcon /> <AccordionIcon />
</AccordionButton> </AccordionButton>
<AccordionPanel pt="4"> <AccordionPanel pt="4">
<CellWithValueStack <TableList<ExtractingCell>
columns={sheet?.columns ?? []} initialItems={options.cellsToExtract}
item={options.referenceCell ?? { id: 'reference' }} onItemsChange={handleExtractingCellsChange}
onItemChange={handleReferenceCellChange} Item={ExtractingCellItem}
addLabel="Add a value"
/> />
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>
)} </Stack>
{!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> </Accordion>
) )
default: default:

View File

@ -38,10 +38,13 @@ export const getRow = async (
await doc.loadInfo() await doc.loadInfo()
const sheet = doc.sheetsById[sheetId] const sheet = doc.sheetsById[sheetId]
const rows = await sheet.getRows() const rows = await sheet.getRows()
const filteredRows = rows.filter((row) => const filteredRows = getTotalRows(
referenceCell options.totalRowsToExtract,
? row[referenceCell.column as string] === referenceCell.value rows.filter((row) =>
: matchFilter(row, filter as NonNullable<typeof filter>) referenceCell
? row[referenceCell.column as string] === referenceCell.value
: matchFilter(row, filter as NonNullable<typeof filter>)
)
) )
if (filteredRows.length === 0) { if (filteredRows.length === 0) {
log = { log = {
@ -99,3 +102,20 @@ export const getRow = async (
} }
return { outgoingEdgeId, logs: log ? [log] : undefined } return { outgoingEdgeId, logs: log ? [log] : undefined }
} }
const getTotalRows = <T>(
totalRowsToExtract: GoogleSheetsGetOptions['totalRowsToExtract'],
rows: T[]
): T[] => {
switch (totalRowsToExtract) {
case 'All':
case undefined:
return rows
case 'First':
return rows.slice(0, 1)
case 'Last':
return rows.slice(-1)
case 'Random':
return [rows[Math.floor(Math.random() * rows.length)]]
}
}

View File

@ -35,6 +35,13 @@ const initialGoogleSheetsOptionsSchema = googleSheetsOptionsBaseSchema.merge(
}) })
) )
export const totalRowsToExtractOptions = [
'All',
'First',
'Last',
'Random',
] as const
const googleSheetsGetOptionsSchema = googleSheetsOptionsBaseSchema.merge( const googleSheetsGetOptionsSchema = googleSheetsOptionsBaseSchema.merge(
z.object({ z.object({
action: z.enum([GoogleSheetsAction.GET]), action: z.enum([GoogleSheetsAction.GET]),
@ -48,6 +55,7 @@ const googleSheetsGetOptionsSchema = googleSheetsOptionsBaseSchema.merge(
}) })
.optional(), .optional(),
cellsToExtract: z.array(extractingCellSchema), cellsToExtract: z.array(extractingCellSchema),
totalRowsToExtract: z.enum(totalRowsToExtractOptions).optional(),
}) })
) )