Skip to content

Commit

Permalink
✨ (googleSheets) Advanced get filtering
Browse files Browse the repository at this point in the history
Allows you to select rows based on advanced conditions / comparisons
  • Loading branch information
baptisteArno committed Dec 6, 2022
1 parent b2519b5 commit dcec1f0
Show file tree
Hide file tree
Showing 16 changed files with 1,507 additions and 1,233 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { ChangePlanForm } from '../ChangePlanForm'
export const BillingContent = () => {
const { workspace, refreshWorkspace } = useWorkspace()

console.log(workspace)
if (!workspace) return null
return (
<Stack spacing="10" w="full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { useTypebot } from '@/features/editor'
import {
Cell,
CredentialsType,
defaultGoogleSheetsGetOptions,
defaultGoogleSheetsInsertOptions,
defaultGoogleSheetsUpdateOptions,
ExtractingCell,
GoogleSheetsAction,
GoogleSheetsGetOptions,
Expand All @@ -22,6 +25,7 @@ import { TableListItemProps, TableList } from '@/components/TableList'
import { CredentialsDropdown } from '@/features/credentials'
import { useSheets } from '../../hooks/useSheets'
import { Sheet } from '../../types'
import { RowsFilterTableList } from './RowsFilterTableList'

type Props = {
options: GoogleSheetsOptions
Expand Down Expand Up @@ -56,24 +60,21 @@ export const GoogleSheetsSettingsBody = ({
case GoogleSheetsAction.GET: {
const newOptions: GoogleSheetsGetOptions = {
...options,
action,
cellsToExtract: [],
...defaultGoogleSheetsGetOptions,
}
return onOptionsChange({ ...newOptions })
}
case GoogleSheetsAction.INSERT_ROW: {
const newOptions: GoogleSheetsInsertRowOptions = {
...options,
action,
cellsToInsert: [],
...defaultGoogleSheetsInsertOptions,
}
return onOptionsChange({ ...newOptions })
}
case GoogleSheetsAction.UPDATE_ROW: {
const newOptions: GoogleSheetsUpdateRowOptions = {
...options,
action,
cellsToUpsert: [],
...defaultGoogleSheetsUpdateOptions,
}
return onOptionsChange({ ...newOptions })
}
Expand Down Expand Up @@ -161,6 +162,10 @@ const ActionOptions = ({
const handleExtractingCellsChange = (cellsToExtract: ExtractingCell[]) =>
onOptionsChange({ ...options, cellsToExtract } as GoogleSheetsOptions)

const handleFilterChange = (
filter: NonNullable<GoogleSheetsGetOptions['filter']>
) => onOptionsChange({ ...options, filter } as GoogleSheetsOptions)

const UpdatingCellItem = useMemo(
() =>
function Component(props: TableListItemProps<Cell>) {
Expand Down Expand Up @@ -210,12 +215,26 @@ const ActionOptions = ({
case GoogleSheetsAction.GET:
return (
<Stack>
<Text>Row to select</Text>
<CellWithValueStack
columns={sheet?.columns ?? []}
item={options.referenceCell ?? { id: 'reference' }}
onItemChange={handleReferenceCellChange}
/>
{options.referenceCell ? (
<>
<Text>Row to select</Text>
<CellWithValueStack
columns={sheet?.columns ?? []}
item={options.referenceCell ?? { id: 'reference' }}
onItemChange={handleReferenceCellChange}
/>
</>
) : (
<>
<Text>Filter</Text>
<RowsFilterTableList
columns={sheet?.columns ?? []}
filter={options.filter}
onFilterChange={handleFilterChange}
/>
</>
)}

<Text>Cells to extract</Text>
<TableList<ExtractingCell>
initialItems={options.cellsToExtract}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { DropdownList } from '@/components/DropdownList'
import { Input } from '@/components/inputs'
import { TableListItemProps } from '@/components/TableList'
import { Stack } from '@chakra-ui/react'
import { ComparisonOperators, RowsFilterComparison } from 'models'
import React from 'react'

export const RowsFilterComparisonItem = ({
item,
columns,
onItemChange,
}: TableListItemProps<RowsFilterComparison> & { columns: string[] }) => {
const handleColumnSelect = (column: string) => {
if (column === item.column) return
onItemChange({ ...item, column })
}

const handleSelectComparisonOperator = (
comparisonOperator: ComparisonOperators
) => {
if (comparisonOperator === item.comparisonOperator) return
onItemChange({ ...item, comparisonOperator })
}

const handleChangeValue = (value: string) => {
if (value === item.value) return
onItemChange({ ...item, value })
}

return (
<Stack p="4" rounded="md" flex="1" borderWidth="1px">
<DropdownList<string>
currentItem={item.column}
onItemSelect={handleColumnSelect}
items={columns}
placeholder="Select a column"
/>
<DropdownList<ComparisonOperators>
currentItem={item.comparisonOperator}
onItemSelect={handleSelectComparisonOperator}
items={Object.values(ComparisonOperators)}
placeholder="Select an operator"
/>
{item.comparisonOperator !== ComparisonOperators.IS_SET && (
<Input
defaultValue={item.value ?? ''}
onChange={handleChangeValue}
placeholder="Type a value..."
/>
)}
</Stack>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { DropdownList } from '@/components/DropdownList'
import { TableList, TableListItemProps } from '@/components/TableList'
import { Flex } from '@chakra-ui/react'
import {
GoogleSheetsGetOptions,
LogicalOperator,
RowsFilterComparison,
} from 'models'
import React, { useCallback } from 'react'
import { RowsFilterComparisonItem } from './RowsFilterComparisonItem'

type Props = {
filter: NonNullable<GoogleSheetsGetOptions['filter']>
columns: string[]
onFilterChange: (
filter: NonNullable<GoogleSheetsGetOptions['filter']>
) => void
}

export const RowsFilterTableList = ({
filter,
columns,
onFilterChange,
}: Props) => {
const handleComparisonsChange = (comparisons: RowsFilterComparison[]) =>
onFilterChange({ ...filter, comparisons })

const handleLogicalOperatorChange = (logicalOperator: LogicalOperator) =>
onFilterChange({ ...filter, logicalOperator })

const createRowsFilterComparisonItem = useCallback(
(props: TableListItemProps<RowsFilterComparison>) => (
<RowsFilterComparisonItem {...props} columns={columns} />
),
[columns]
)

return (
<TableList<RowsFilterComparison>
initialItems={filter?.comparisons}
onItemsChange={handleComparisonsChange}
Item={createRowsFilterComparisonItem}
ComponentBetweenItems={() => (
<Flex justify="center">
<DropdownList<LogicalOperator>
currentItem={filter?.logicalOperator}
onItemSelect={handleLogicalOperatorChange}
items={Object.values(LogicalOperator)}
/>
</Flex>
)}
addLabel="Add filter rule"
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './RowsFilterComparisonItem'
export * from './RowsFilterTableList'
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ test.describe.parallel('Google sheets integration', () => {
'/api/integrations/google-sheets/spreadsheets/1k_pIDw3YHl9tlZusbBVSBRY0PeRPd2H6t4Nj7rwnOtM/sheets/0'
) &&
resp.status() === 200 &&
resp.request().method() === 'PATCH'
resp.request().method() === 'POST'
),
typebotViewer(page)
.locator('input[placeholder="Type your email..."]')
Expand All @@ -118,10 +118,21 @@ test.describe.parallel('Google sheets integration', () => {

await page.click('text=Select a column')
await page.click('button >> text="Email"')
await page.getByRole('button', { name: 'Select an operator' }).click()
await page.getByRole('menuitem', { name: 'Equal to' }).click()
await page.click('[aria-label="Insert a variable"]')
await page.click('button >> text="Email" >> nth=1')

await page.click('text=Add a value')
await page.getByRole('button', { name: 'Add filter rule' }).click()
await page.getByRole('button', { name: 'AND', exact: true }).click()
await page.getByRole('menuitem', { name: 'OR' }).click()

await page.click('text=Select a column')
await page.getByRole('menuitem', { name: 'Email' }).click()
await page.getByRole('button', { name: 'Select an operator' }).click()
await page.getByRole('menuitem', { name: 'Equal to' }).click()
await page.getByPlaceholder('Type a value...').nth(-1).fill('test@test.com')

await page.click('text=Select a column')
await page.click('text="First name"')
await createNewVar(page, 'First name')
Expand All @@ -138,9 +149,9 @@ test.describe.parallel('Google sheets integration', () => {
await typebotViewer(page)
.locator('input[placeholder="Type your email..."]')
.press('Enter')
await expect(
typebotViewer(page).locator('text=Your name is: John Smith')
).toBeVisible({ timeout: 30000 })
await expect(typebotViewer(page).locator('text=Your name is:')).toHaveText(
/John|Fred|Georges/
)
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ export const WorkspaceSettingsModal = ({
const { currentRole } = useWorkspace()
const [selectedTab, setSelectedTab] = useState<SettingsTab>('my-account')

console.log(currentRole)

const canEditWorkspace = currentRole === WorkspaceRole.ADMIN

return (
Expand Down
Loading

5 comments on commit dcec1f0

@vercel
Copy link

@vercel vercel bot commented on dcec1f0 Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on dcec1f0 Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on dcec1f0 Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on dcec1f0 Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app
app.typebot.io

@vercel
Copy link

@vercel vercel bot commented on dcec1f0 Dec 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2-alpha – ./apps/viewer

bot.hostnation.de
bot.maitempah.com
bot.phuonghub.com
bot.reviewzer.com
cares.urlabout.me
kuiz.sistemniaga.com
offer.botscientis.us
sellmycarglasgow.com
talkbot.agfunnel.com
tenorioadvogados.com
uppity.wpwakanda.com
abutton.wpwakanda.com
aidigitalmarketing.kr
bbutton.wpwakanda.com
bot.incusservices.com
bot.meuesocial.com.br
bot.ramonmatos.com.br
cdd.searchcube.com.sg
chat.missarkansas.org
chatbot.ownacademy.co
sbutton.wpwakanda.com
815639944.21000000.one
aplicacao.bmind.com.br
apply.ansuraniphone.my
bbutton.wpwwakanda.com
bot.louismarcondes.com
bot.t20worldcup.com.au
c23111azqw.nigerias.io
felipewelington.com.br
form.searchcube.com.sg
gcase.barrettamario.it
help.giversforgood.com
info.clickasuransi.com
kodawariab736.skeep.it
my.swamprecordsgnv.com
premium.kandabrand.com
report.gratirabbit.com
resume.gratirabbit.com
83242573.actualizar.xyz
bot.blackboxtips.com.br
bot.upgradesolutions.eu
help.comebackreward.com
mainmenu.diddancing.com
register.kandabrand.com
signup.hypemarketing.in
subfooter.wpwakanda.com
survey.hypemarketing.in
testbot.afterorigin.com
91181264.your-access.one
ai.chromebookstoreph.com
form.sergiolimajr.com.br
hunterbot.saleshunter.ai
instant.botscientis.info
link.cascadigital.com.br
onboarding.growthside.io
reward.onlinebotdemo.xyz
type.opaulovieira.com.br
aibot.angrybranding.co.uk
bot.aidigitalmarketing.kr
bot.arraesecenteno.com.br
bot.blackboxsports.com.br
bot.cabinrentalagency.com
boyfriend-breakup.riku.ai
brigadeirosemdrama.com.br
chat.ertcrebateportal.com
chat.thisiscrushhouse.com
sellmyharleylouisiana.com
verfica.botmachine.com.br
configurator.bouclidom.com
help.atlasoutfittersk9.com
ted.meujalecobrasil.com.br
type.dericsoncalari.com.br
chatbot.berbelanjabiz.trade
designguide.techyscouts.com
presente.empresarias.com.mx
sell.sellthemotorhome.co.uk
anamnese.odontopavani.com.br
austin.channelautomation.com
bot.marketingplusmindset.com
piazzatorre.barrettamario.it
requests.swamprecordsgnv.com
type.cookieacademyonline.com
bot.brigadeirosemdrama.com.br
onboarding.libertydreamcare.ie
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
anamnese.clinicamegasjdr.com.br
bookings.littlepartymonkeys.com
bot.comercializadoraomicron.com
elevateyourmind.groovepages.com
yourfeedback.comebackreward.com
personal-trainer.barrettamario.it
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
download.thailandmicespecialist.com
register.thailandmicespecialist.com
viewer-v2-alpha-typebot-io.vercel.app
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
viewer-v2-alpha-git-main-typebot-io.vercel.app

Please sign in to comment.