2
0

🚸 (results) Use header id as table accessor to allow duplicate names

This commit is contained in:
Baptiste Arnaud
2023-09-18 18:34:53 +02:00
parent 6548752b1b
commit 61c46bcb46
6 changed files with 50 additions and 58 deletions

View File

@@ -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
@@ -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('/', '-')}`
@@ -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)
}

View File

@@ -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 = {
@@ -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`}>

View File

@@ -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[]
@@ -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
@@ -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('/', '-')}`

View File

@@ -10,7 +10,6 @@ import {
import { FileLinks } from '../components/FileLinks'
import { TableData } from '../types'
import { convertDateToReadable } from './convertDateToReadable'
import { parseAccessor } from './parseAccessor'
export const convertResultsToTableData = (
results: ResultWithAnswers[] | undefined,
@@ -18,7 +17,7 @@ export const convertResultsToTableData = (
): TableData[] =>
(results ?? []).map((result) => ({
id: { plainText: result.id },
'Submitted at': {
date: {
plainText: convertDateToReadable(result.createdAt),
},
...[...result.answers, ...result.variables].reduce<{
@@ -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),
}
}, {}),
}))

View File

@@ -1 +0,0 @@
export const parseAccessor = (label: string) => label.replaceAll('.', '')

View File

@@ -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[]
@@ -14,5 +13,5 @@ export const parseHeaderCells = (
<Text>{header.label}</Text>
</HStack>
),
accessor: parseAccessor(header.label),
accessor: header.id,
}))