🧐 Add exportResults script
This commit is contained in:
8
packages/lib/parseUniqueKey.ts
Normal file
8
packages/lib/parseUniqueKey.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const parseUniqueKey = (
|
||||
key: string,
|
||||
existingKeys: string[],
|
||||
count = 0
|
||||
): string => {
|
||||
if (!existingKeys.includes(key)) return key
|
||||
return parseUniqueKey(`${key} (${count + 1})`, existingKeys, count + 1)
|
||||
}
|
79
packages/lib/results/convertResultsToTableData.ts
Normal file
79
packages/lib/results/convertResultsToTableData.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import {
|
||||
ResultWithAnswers,
|
||||
ResultHeaderCell,
|
||||
VariableWithValue,
|
||||
Answer,
|
||||
TableData,
|
||||
} from '@typebot.io/schemas'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { isDefined } from '../utils'
|
||||
|
||||
type CellParser = (
|
||||
content: VariableWithValue['value'],
|
||||
blockType?: InputBlockType
|
||||
) => { element?: React.JSX.Element; plainText: string }
|
||||
|
||||
const defaultCellParser: CellParser = (content, blockType) => {
|
||||
if (!content) return { plainText: '' }
|
||||
if (Array.isArray(content))
|
||||
return {
|
||||
plainText: content.join(', '),
|
||||
}
|
||||
return blockType === InputBlockType.FILE
|
||||
? { plainText: content }
|
||||
: { plainText: content.toString() }
|
||||
}
|
||||
|
||||
export const convertResultsToTableData = (
|
||||
results: ResultWithAnswers[] | undefined,
|
||||
headerCells: ResultHeaderCell[],
|
||||
cellParser: CellParser = defaultCellParser
|
||||
): TableData[] =>
|
||||
(results ?? []).map((result) => ({
|
||||
id: { plainText: result.id },
|
||||
date: {
|
||||
plainText: convertDateToReadable(result.createdAt),
|
||||
},
|
||||
...[...result.answers, ...result.variables].reduce<{
|
||||
[key: string]: { element?: JSX.Element; plainText: string }
|
||||
}>((tableData, answerOrVariable) => {
|
||||
if ('groupId' in answerOrVariable) {
|
||||
const answer = answerOrVariable satisfies Answer
|
||||
const header = answer.variableId
|
||||
? headerCells.find((headerCell) =>
|
||||
headerCell.variableIds?.includes(answer.variableId as string)
|
||||
)
|
||||
: headerCells.find((headerCell) =>
|
||||
headerCell.blocks?.some((block) => block.id === answer.blockId)
|
||||
)
|
||||
if (!header || !header.blocks || !header.blockType) return tableData
|
||||
const variableValue = result.variables.find(
|
||||
(variable) => variable.id === answer.variableId
|
||||
)?.value
|
||||
const content = variableValue ?? answer.content
|
||||
return {
|
||||
...tableData,
|
||||
[header.id]: cellParser(content, header.blockType),
|
||||
}
|
||||
}
|
||||
const variable = answerOrVariable satisfies VariableWithValue
|
||||
if (variable.value === null) return tableData
|
||||
const headerId = headerCells.find((headerCell) =>
|
||||
headerCell.variableIds?.includes(variable.id)
|
||||
)?.id
|
||||
if (!headerId) return tableData
|
||||
if (isDefined(tableData[headerId])) return tableData
|
||||
return {
|
||||
...tableData,
|
||||
[headerId]: cellParser(variable.value),
|
||||
}
|
||||
}, {}),
|
||||
}))
|
||||
|
||||
const convertDateToReadable = (date: Date): string =>
|
||||
date.toDateString().split(' ').slice(1, 3).join(' ') +
|
||||
', ' +
|
||||
date.toLocaleTimeString([], {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})
|
39
packages/lib/results/parseAnswers.ts
Normal file
39
packages/lib/results/parseAnswers.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import {
|
||||
AnswerInSessionState,
|
||||
Variable,
|
||||
VariableWithValue,
|
||||
} from '@typebot.io/schemas'
|
||||
import { isDefined, isEmpty } from '../utils'
|
||||
|
||||
export const parseAnswers = ({
|
||||
answers,
|
||||
variables: resultVariables,
|
||||
}: {
|
||||
answers: AnswerInSessionState[]
|
||||
variables: Variable[]
|
||||
}): {
|
||||
[key: string]: string
|
||||
} => {
|
||||
const variablesWithValues = resultVariables.filter((variable) =>
|
||||
isDefined(variable.value)
|
||||
) as VariableWithValue[]
|
||||
|
||||
return {
|
||||
submittedAt: new Date().toISOString(),
|
||||
...[...answers, ...variablesWithValues].reduce<{
|
||||
[key: string]: string
|
||||
}>((o, answerOrVariable) => {
|
||||
if ('id' in answerOrVariable) {
|
||||
const variable = answerOrVariable
|
||||
if (variable.value === null) return o
|
||||
return { ...o, [variable.name]: variable.value.toString() }
|
||||
}
|
||||
const answer = answerOrVariable as AnswerInSessionState
|
||||
if (isEmpty(answer.key)) return o
|
||||
return {
|
||||
...o,
|
||||
[answer.key]: answer.value,
|
||||
}
|
||||
}, {}),
|
||||
}
|
||||
}
|
15
packages/lib/results/parseColumnsOrder.ts
Normal file
15
packages/lib/results/parseColumnsOrder.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { ResultHeaderCell } from '@typebot.io/schemas'
|
||||
|
||||
export const parseColumnsOrder = (
|
||||
existingOrder: string[] | undefined,
|
||||
resultHeader: ResultHeaderCell[]
|
||||
) =>
|
||||
existingOrder
|
||||
? [
|
||||
...existingOrder.slice(0, -1),
|
||||
...resultHeader
|
||||
.filter((header) => !existingOrder.includes(header.id))
|
||||
.map((h) => h.id),
|
||||
'logs',
|
||||
]
|
||||
: ['select', ...resultHeader.map((h) => h.id), 'logs']
|
@ -1,15 +1,13 @@
|
||||
import {
|
||||
ResultWithAnswers,
|
||||
ResultHeaderCell,
|
||||
Group,
|
||||
Variable,
|
||||
InputBlock,
|
||||
ResultHeaderCell,
|
||||
VariableWithValue,
|
||||
Typebot,
|
||||
ResultWithAnswers,
|
||||
AnswerInSessionState,
|
||||
} from '@typebot.io/schemas'
|
||||
import { isInputBlock, isDefined, byId, isNotEmpty, isEmpty } from './utils'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { isInputBlock, byId, isNotEmpty } from '../utils'
|
||||
|
||||
export const parseResultHeader = (
|
||||
typebot: Pick<Typebot, 'groups' | 'variables'>,
|
||||
@ -212,37 +210,3 @@ const parseResultsFromPreviousBotVersions = (
|
||||
},
|
||||
]
|
||||
}, [])
|
||||
|
||||
export const parseAnswers = ({
|
||||
answers,
|
||||
variables: resultVariables,
|
||||
}: {
|
||||
answers: AnswerInSessionState[]
|
||||
variables: VariableWithValue[]
|
||||
}): {
|
||||
[key: string]: string
|
||||
} => {
|
||||
return {
|
||||
submittedAt: new Date().toISOString(),
|
||||
...[...answers, ...resultVariables].reduce<{
|
||||
[key: string]: string
|
||||
}>((o, answerOrVariable) => {
|
||||
if ('id' in answerOrVariable) {
|
||||
const variable = answerOrVariable
|
||||
if (variable.value === null) return o
|
||||
return { ...o, [variable.name]: variable.value.toString() }
|
||||
}
|
||||
const answer = answerOrVariable as AnswerInSessionState
|
||||
if (isEmpty(answer.key)) return o
|
||||
return {
|
||||
...o,
|
||||
[answer.key]: answer.value,
|
||||
}
|
||||
}, {}),
|
||||
}
|
||||
}
|
||||
|
||||
export const getDefinedVariables = (variables: Variable[]) =>
|
||||
variables.filter((variable) =>
|
||||
isDefined(variable.value)
|
||||
) as VariableWithValue[]
|
Reference in New Issue
Block a user