Skip to content

Commit

Permalink
🚸 (results) Use header id as table accessor to allow duplicate names
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Sep 18, 2023
1 parent 6548752 commit 61c46bc
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import { parseResultHeader } from '@typebot.io/lib/results'
import { useResults } from '../../ResultsProvider'
import { parseColumnOrder } from '../../helpers/parseColumnsOrder'
import { convertResultsToTableData } from '../../helpers/convertResultsToTableData'
import { parseAccessor } from '../../helpers/parseAccessor'
import { isDefined } from '@typebot.io/lib'
import { byId, isDefined } from '@typebot.io/lib'

type Props = {
isOpen: boolean
Expand Down Expand Up @@ -90,40 +89,35 @@ export const ExportAllResultsModal = ({ isOpen, onClose }: Props) => {

const dataToUnparse = convertResultsToTableData(results, resultHeader)

const fields = parseColumnOrder(
const headerIds = parseColumnOrder(
typebot?.resultsTablePreferences?.columnsOrder,
resultHeader
).reduce<string[]>((currentHeaderLabels, columnId) => {
).reduce<string[]>((currentHeaderIds, columnId) => {
if (
typebot?.resultsTablePreferences?.columnsVisibility[columnId] === false
)
return currentHeaderLabels
return currentHeaderIds
const columnLabel = resultHeader.find(
(headerCell) => headerCell.id === columnId
)?.label
if (!columnLabel) return currentHeaderLabels
return [...currentHeaderLabels, columnLabel]
)?.id
if (!columnLabel) return currentHeaderIds
return [...currentHeaderIds, columnLabel]
}, [])

const data = dataToUnparse.map<{ [key: string]: string }>((data) => {
const newObject: { [key: string]: string } = {}
fields?.forEach((field) => {
newObject[field] = data[parseAccessor(field)]?.plainText
headerIds?.forEach((headerId) => {
const headerLabel = resultHeader.find(byId(headerId))?.label
if (!headerLabel) return
const newKey = parseUniqueKey(headerLabel, Object.keys(newObject))
newObject[newKey] = data[headerId]?.plainText
})
return newObject
})

const csvData = new Blob(
[
unparse({
data,
fields,
}),
],
{
type: 'text/csv;charset=utf-8;',
}
)
const csvData = new Blob([unparse(data)], {
type: 'text/csv;charset=utf-8;',
})
const fileName = `typebot-export_${new Date()
.toLocaleDateString()
.replaceAll('/', '-')}`
Expand Down Expand Up @@ -166,3 +160,12 @@ export const ExportAllResultsModal = ({ isOpen, onClose }: Props) => {
</Modal>
)
}

export const parseUniqueKey = (
key: string,
existingKeys: string[],
count = 0
): string => {
if (!existingKeys.includes(key)) return key
return parseUniqueKey(`${key} (${count + 1})`, existingKeys, count + 1)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { CellValueType, TableData } from '../../types'
import { IndeterminateCheckbox } from './IndeterminateCheckbox'
import { colors } from '@/lib/theme'
import { parseColumnOrder } from '../../helpers/parseColumnsOrder'
import { parseAccessor } from '../../helpers/parseAccessor'
import { HeaderIcon } from '../HeaderIcon'

type ResultsTableProps = {
Expand Down Expand Up @@ -136,7 +135,7 @@ export const ResultsTable = ({
},
...resultHeader.map<ColumnDef<TableData>>((header) => ({
id: header.id,
accessorKey: parseAccessor(header.label),
accessorKey: header.id,
size: 200,
header: () => (
<HStack overflow="hidden" data-testid={`${header.label} header`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { useToast } from '@/hooks/useToast'
import { useResults } from '../../ResultsProvider'
import { trpc } from '@/lib/trpc'
import { parseColumnOrder } from '../../helpers/parseColumnsOrder'
import { parseAccessor } from '../../helpers/parseAccessor'
import { byId } from '@typebot.io/lib/utils'
import { parseUniqueKey } from './ExportAllResultsModal'

type Props = {
selectedResultsId: string[]
Expand Down Expand Up @@ -69,21 +70,21 @@ export const SelectionToolbar = ({
selectedResultsId.includes(data.id.plainText)
)

const fields = parseColumnOrder(
const headerIds = parseColumnOrder(
typebot?.resultsTablePreferences?.columnsOrder,
resultHeader
)
.reduce<string[]>((currentHeaderLabels, columnId) => {
.reduce<string[]>((currentHeaderIds, columnId) => {
if (
typebot?.resultsTablePreferences?.columnsVisibility[columnId] ===
false
)
return currentHeaderLabels
return currentHeaderIds
const columnLabel = resultHeader.find(
(headerCell) => headerCell.id === columnId
)?.label
if (!columnLabel) return currentHeaderLabels
return [...currentHeaderLabels, columnLabel]
)?.id
if (!columnLabel) return currentHeaderIds
return [...currentHeaderIds, columnLabel]
}, [])
.concat(
typebot?.resultsTablePreferences?.columnsOrder
Expand All @@ -94,29 +95,24 @@ export const SelectionToolbar = ({
headerCell.id
)
)
.map((headerCell) => headerCell.label)
.map((headerCell) => headerCell.id)
: []
)

const data = dataToUnparse.map<{ [key: string]: string }>((data) => {
const newObject: { [key: string]: string } = {}
fields?.forEach((field) => {
newObject[field] = data[parseAccessor(field)]?.plainText
headerIds?.forEach((headerId) => {
const headerLabel = resultHeader.find(byId(headerId))?.label
if (!headerLabel) return
const newKey = parseUniqueKey(headerLabel, Object.keys(newObject))
newObject[newKey] = data[headerId]?.plainText
})
return newObject
})

const csvData = new Blob(
[
unparse({
data,
fields,
}),
],
{
type: 'text/csv;charset=utf-8;',
}
)
const csvData = new Blob([unparse(data)], {
type: 'text/csv;charset=utf-8;',
})
const fileName = `typebot-export_${new Date()
.toLocaleDateString()
.replaceAll('/', '-')}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import {
import { FileLinks } from '../components/FileLinks'
import { TableData } from '../types'
import { convertDateToReadable } from './convertDateToReadable'
import { parseAccessor } from './parseAccessor'

export const convertResultsToTableData = (
results: ResultWithAnswers[] | undefined,
headerCells: ResultHeaderCell[]
): TableData[] =>
(results ?? []).map((result) => ({
id: { plainText: result.id },
'Submitted at': {
date: {
plainText: convertDateToReadable(result.createdAt),
},
...[...result.answers, ...result.variables].reduce<{
Expand All @@ -40,22 +39,19 @@ export const convertResultsToTableData = (
const content = variableValue ?? answer.content
return {
...tableData,
[parseAccessor(header.label)]: parseCellContent(
content,
header.blockType
),
[header.id]: parseCellContent(content, header.blockType),
}
}
const variable = answerOrVariable satisfies VariableWithValue
if (variable.value === null) return tableData
const key = headerCells.find((headerCell) =>
const headerId = headerCells.find((headerCell) =>
headerCell.variableIds?.includes(variable.id)
)?.label
if (!key) return tableData
if (isDefined(tableData[key])) return tableData
)?.id
if (!headerId) return tableData
if (isDefined(tableData[headerId])) return tableData
return {
...tableData,
[parseAccessor(key)]: parseCellContent(variable.value),
[headerId]: parseCellContent(variable.value),
}
}, {}),
}))
Expand Down
1 change: 0 additions & 1 deletion apps/builder/src/features/results/helpers/parseAccessor.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { HStack, Text } from '@chakra-ui/react'
import { ResultHeaderCell } from '@typebot.io/schemas'
import { HeaderIcon } from '../components/HeaderIcon'
import { HeaderCell } from '../types'
import { parseAccessor } from './parseAccessor'

export const parseHeaderCells = (
resultHeader: ResultHeaderCell[]
Expand All @@ -14,5 +13,5 @@ export const parseHeaderCells = (
<Text>{header.label}</Text>
</HStack>
),
accessor: parseAccessor(header.label),
accessor: header.id,
}))

4 comments on commit 61c46bc

@vercel
Copy link

@vercel vercel bot commented on 61c46bc Sep 18, 2023

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 61c46bc Sep 18, 2023

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 – ./apps/viewer

cares.urlabout.me
chat.ezbooking.ai
chat.gaswadern.de
chat.gniorder.com
chat.onrentme.com
chat.rojie.online
chatdocidadao.com
chatwebonline.com
fmm.wpwakanda.com
footballmeetup.ie
gentleman-shop.fr
chat.mosdent.com.tr
chat.sr7digital.com
chatbot.matthesv.de
chatbot.repplai.com
chatwebandreia.site
co.onewebcenter.com
cr.onewebcenter.com
demo.botscientis.us
demo.wemakebots.xyz
feiralimpanomes.com
go.onewebcenter.com
gv.onewebcenter.com
hrbot.robomotion.io
inearephones.cr8.ai
joaomigowski.com.br
kbsub.wpwakanda.com
limitenahora.com.br
live.botscientis.us
mentoria.omelhor.vc
messengerbet.online
noticiariododia.com
nutrisamirbayde.com
online.onlinmey.com
order.maitempah.com
query.forgetsql.com
quest.wpwakanda.com
se.onewebcenter.com
secretespiao.online
start.belenmotz.com
support.wawplus.com
survey1.digienge.io
surveys.essiell.com
test.botscientis.us
test.getreview.help
test.reventepro.com
typebot.stillio.app
typebot.stillio.com
vg.onewebcenter.com
wa.onewebcenter.com
web.draleticiah.com
whatsdigital.online
wordsandimagery.com
88584434.therpm.club
92109660.therpm.club
app.horadelucrar.com
app.whatisappweb.com
assistent.m-vogel.de
ativandograna.online
bium.gratirabbit.com
bot.ansuraniphone.my
viewer-v2-typebot-io.vercel.app
mdb.assessoria.fernanda.progenbr.com
mdb.assessoria.jbatista.progenbr.com
mdb.assessoria.mauricio.progenbr.com
mdb.evento.autocadastro.progenbr.com
form.shopmercedesbenzsouthorlando.com
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

@vercel
Copy link

@vercel vercel bot commented on 61c46bc Sep 18, 2023

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 61c46bc Sep 18, 2023

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

Please sign in to comment.