2022-03-21 17:05:51 +01:00
|
|
|
import {
|
2024-01-12 10:16:01 +01:00
|
|
|
ResultWithAnswers,
|
|
|
|
ResultHeaderCell,
|
2022-06-11 07:27:38 +02:00
|
|
|
Group,
|
2022-03-21 17:05:51 +01:00
|
|
|
Variable,
|
2022-06-11 07:27:38 +02:00
|
|
|
InputBlock,
|
2022-11-06 09:57:08 +01:00
|
|
|
Typebot,
|
2023-03-15 08:35:16 +01:00
|
|
|
} from '@typebot.io/schemas'
|
2024-03-15 16:32:29 +01:00
|
|
|
import { isInputBlock } from '@typebot.io/schemas/helpers'
|
2023-11-08 15:34:16 +01:00
|
|
|
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
2024-03-15 16:32:29 +01:00
|
|
|
import { byId, isNotEmpty } from '@typebot.io/lib/utils'
|
2022-03-21 17:05:51 +01:00
|
|
|
|
2022-11-06 09:57:08 +01:00
|
|
|
export const parseResultHeader = (
|
|
|
|
typebot: Pick<Typebot, 'groups' | 'variables'>,
|
2023-02-14 14:33:26 +01:00
|
|
|
linkedTypebots: Pick<Typebot, 'groups' | 'variables'>[] | undefined,
|
|
|
|
results?: ResultWithAnswers[]
|
2022-11-06 09:57:08 +01:00
|
|
|
): ResultHeaderCell[] => {
|
|
|
|
const parsedGroups = [
|
|
|
|
...typebot.groups,
|
2023-11-08 15:34:16 +01:00
|
|
|
...(linkedTypebots ?? []).flatMap(
|
|
|
|
(linkedTypebot) => linkedTypebot.groups as Group[]
|
|
|
|
),
|
2022-11-06 09:57:08 +01:00
|
|
|
]
|
|
|
|
const parsedVariables = [
|
|
|
|
...typebot.variables,
|
|
|
|
...(linkedTypebots ?? []).flatMap(
|
|
|
|
(linkedTypebot) => linkedTypebot.variables
|
|
|
|
),
|
|
|
|
]
|
|
|
|
const inputsResultHeader = parseInputsResultHeader({
|
|
|
|
groups: parsedGroups,
|
|
|
|
variables: parsedVariables,
|
|
|
|
})
|
2022-03-21 17:05:51 +01:00
|
|
|
return [
|
2022-07-01 17:08:35 +02:00
|
|
|
{ label: 'Submitted at', id: 'date' },
|
2022-11-06 09:57:08 +01:00
|
|
|
...inputsResultHeader,
|
|
|
|
...parseVariablesHeaders(parsedVariables, inputsResultHeader),
|
2023-02-14 14:33:26 +01:00
|
|
|
...parseResultsFromPreviousBotVersions(results ?? [], inputsResultHeader),
|
2022-03-21 17:05:51 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2022-11-06 09:57:08 +01:00
|
|
|
type ResultHeaderCellWithBlock = Omit<ResultHeaderCell, 'blocks'> & {
|
|
|
|
blocks: NonNullable<ResultHeaderCell['blocks']>
|
|
|
|
}
|
|
|
|
|
2022-03-21 17:05:51 +01:00
|
|
|
const parseInputsResultHeader = ({
|
2022-06-11 07:27:38 +02:00
|
|
|
groups,
|
2022-03-21 17:05:51 +01:00
|
|
|
variables,
|
|
|
|
}: {
|
2022-06-11 07:27:38 +02:00
|
|
|
groups: Group[]
|
2022-03-21 17:05:51 +01:00
|
|
|
variables: Variable[]
|
2022-11-06 09:57:08 +01:00
|
|
|
}): ResultHeaderCellWithBlock[] =>
|
2022-03-21 17:05:51 +01:00
|
|
|
(
|
2022-06-11 07:27:38 +02:00
|
|
|
groups
|
2022-11-06 09:57:08 +01:00
|
|
|
.flatMap((group) =>
|
|
|
|
group.blocks.map((block) => ({
|
|
|
|
...block,
|
2023-10-27 09:23:50 +02:00
|
|
|
groupTitle: group.title,
|
2023-11-08 15:34:16 +01:00
|
|
|
groupId: group.id,
|
2022-03-21 17:05:51 +01:00
|
|
|
}))
|
|
|
|
)
|
2022-06-11 07:27:38 +02:00
|
|
|
.filter((block) => isInputBlock(block)) as (InputBlock & {
|
2023-11-08 15:34:16 +01:00
|
|
|
groupId: string
|
2022-11-06 09:57:08 +01:00
|
|
|
groupTitle: string
|
2022-03-21 17:05:51 +01:00
|
|
|
})[]
|
2022-11-06 09:57:08 +01:00
|
|
|
).reduce<ResultHeaderCellWithBlock[]>((existingHeaders, inputBlock) => {
|
2022-03-21 17:05:51 +01:00
|
|
|
if (
|
2022-11-06 09:57:08 +01:00
|
|
|
existingHeaders.some(
|
|
|
|
(existingHeader) =>
|
2023-11-08 15:34:16 +01:00
|
|
|
inputBlock.options?.variableId &&
|
2022-11-06 09:57:08 +01:00
|
|
|
existingHeader.variableIds?.includes(inputBlock.options.variableId)
|
2022-03-21 17:05:51 +01:00
|
|
|
)
|
|
|
|
)
|
2022-11-06 09:57:08 +01:00
|
|
|
return existingHeaders
|
2022-03-21 17:05:51 +01:00
|
|
|
const matchedVariableName =
|
2023-11-08 15:34:16 +01:00
|
|
|
inputBlock.options?.variableId &&
|
2022-06-11 07:27:38 +02:00
|
|
|
variables.find(byId(inputBlock.options.variableId))?.name
|
2022-03-21 17:05:51 +01:00
|
|
|
|
2022-11-06 09:57:08 +01:00
|
|
|
let label = matchedVariableName ?? inputBlock.groupTitle
|
2023-11-08 15:34:16 +01:00
|
|
|
const headerWithSameLabel = existingHeaders.find((h) => h.label === label)
|
|
|
|
if (headerWithSameLabel) {
|
|
|
|
const shouldMerge = headerWithSameLabel.blocks?.some(
|
|
|
|
(block) => block.id === inputBlock.id
|
|
|
|
)
|
|
|
|
if (shouldMerge) {
|
|
|
|
const updatedHeaderCell: ResultHeaderCellWithBlock = {
|
|
|
|
...headerWithSameLabel,
|
|
|
|
variableIds:
|
|
|
|
headerWithSameLabel.variableIds && inputBlock.options?.variableId
|
|
|
|
? headerWithSameLabel.variableIds.concat([
|
|
|
|
inputBlock.options.variableId,
|
|
|
|
])
|
|
|
|
: undefined,
|
|
|
|
blocks: headerWithSameLabel.blocks.concat({
|
|
|
|
id: inputBlock.id,
|
|
|
|
groupId: inputBlock.groupId,
|
|
|
|
}),
|
2022-11-06 09:57:08 +01:00
|
|
|
}
|
2023-11-08 15:34:16 +01:00
|
|
|
return [
|
|
|
|
...existingHeaders.filter(
|
|
|
|
(existingHeader) => existingHeader.label !== label
|
|
|
|
),
|
|
|
|
updatedHeaderCell,
|
|
|
|
]
|
2022-11-06 09:57:08 +01:00
|
|
|
}
|
2023-11-08 15:34:16 +01:00
|
|
|
const totalPrevious = existingHeaders.filter((h) =>
|
|
|
|
h.label.includes(label)
|
|
|
|
).length
|
|
|
|
const newHeaderCell: ResultHeaderCellWithBlock = {
|
|
|
|
id: inputBlock.id,
|
|
|
|
label: label + ` (${totalPrevious})`,
|
|
|
|
blocks: [
|
|
|
|
{
|
|
|
|
id: inputBlock.id,
|
|
|
|
groupId: inputBlock.groupId,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
blockType: inputBlock.type,
|
|
|
|
variableIds: inputBlock.options?.variableId
|
|
|
|
? [inputBlock.options.variableId]
|
|
|
|
: undefined,
|
2022-11-06 09:57:08 +01:00
|
|
|
}
|
2023-11-08 15:34:16 +01:00
|
|
|
return [...existingHeaders, newHeaderCell]
|
2022-11-06 09:57:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const newHeaderCell: ResultHeaderCellWithBlock = {
|
|
|
|
id: inputBlock.id,
|
|
|
|
label,
|
|
|
|
blocks: [
|
|
|
|
{
|
|
|
|
id: inputBlock.id,
|
|
|
|
groupId: inputBlock.groupId,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
blockType: inputBlock.type,
|
2023-11-08 15:34:16 +01:00
|
|
|
variableIds: inputBlock.options?.variableId
|
2022-11-06 09:57:08 +01:00
|
|
|
? [inputBlock.options.variableId]
|
|
|
|
: undefined,
|
|
|
|
}
|
|
|
|
|
|
|
|
return [...existingHeaders, newHeaderCell]
|
2022-03-21 17:05:51 +01:00
|
|
|
}, [])
|
|
|
|
|
|
|
|
const parseVariablesHeaders = (
|
|
|
|
variables: Variable[],
|
2022-11-06 09:57:08 +01:00
|
|
|
existingInputResultHeaders: ResultHeaderCell[]
|
2022-03-21 17:05:51 +01:00
|
|
|
) =>
|
2022-11-06 09:57:08 +01:00
|
|
|
variables.reduce<ResultHeaderCell[]>((existingHeaders, variable) => {
|
|
|
|
if (
|
|
|
|
existingInputResultHeaders.some((existingInputResultHeader) =>
|
|
|
|
existingInputResultHeader.variableIds?.includes(variable.id)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return existingHeaders
|
|
|
|
|
|
|
|
const headerCellWithSameLabel = existingHeaders.find(
|
|
|
|
(existingHeader) => existingHeader.label === variable.name
|
|
|
|
)
|
|
|
|
if (headerCellWithSameLabel) {
|
|
|
|
const updatedHeaderCell: ResultHeaderCell = {
|
|
|
|
...headerCellWithSameLabel,
|
|
|
|
variableIds: headerCellWithSameLabel.variableIds?.concat([variable.id]),
|
|
|
|
}
|
|
|
|
return [
|
|
|
|
...existingHeaders.filter((h) => h.label !== variable.name),
|
|
|
|
updatedHeaderCell,
|
|
|
|
]
|
|
|
|
}
|
|
|
|
const newHeaderCell: ResultHeaderCell = {
|
|
|
|
id: variable.id,
|
|
|
|
label: variable.name,
|
|
|
|
variableIds: [variable.id],
|
|
|
|
}
|
|
|
|
|
|
|
|
return [...existingHeaders, newHeaderCell]
|
2022-03-21 17:05:51 +01:00
|
|
|
}, [])
|
|
|
|
|
2023-02-14 14:33:26 +01:00
|
|
|
const parseResultsFromPreviousBotVersions = (
|
|
|
|
results: ResultWithAnswers[],
|
|
|
|
existingInputResultHeaders: ResultHeaderCell[]
|
|
|
|
): ResultHeaderCell[] =>
|
|
|
|
results
|
|
|
|
.flatMap((result) => result.answers)
|
|
|
|
.filter(
|
|
|
|
(answer) =>
|
|
|
|
!answer.variableId &&
|
|
|
|
existingInputResultHeaders.every(
|
|
|
|
(header) => header.id !== answer.blockId
|
|
|
|
) &&
|
|
|
|
isNotEmpty(answer.content)
|
|
|
|
)
|
2023-02-14 15:21:29 +01:00
|
|
|
.reduce<ResultHeaderCell[]>((existingHeaders, answer) => {
|
|
|
|
if (
|
|
|
|
existingHeaders.some(
|
|
|
|
(existingHeader) => existingHeader.id === answer.blockId
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return existingHeaders
|
|
|
|
return [
|
|
|
|
...existingHeaders,
|
2023-02-14 14:33:26 +01:00
|
|
|
{
|
|
|
|
id: answer.blockId,
|
2023-02-14 15:21:29 +01:00
|
|
|
label: `${answer.blockId} (deleted block)`,
|
|
|
|
blocks: [
|
|
|
|
{
|
|
|
|
id: answer.blockId,
|
|
|
|
groupId: answer.groupId,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
blockType: InputBlockType.TEXT,
|
2023-02-14 14:33:26 +01:00
|
|
|
},
|
2023-02-14 15:21:29 +01:00
|
|
|
]
|
|
|
|
}, [])
|