Skip to content

Commit

Permalink
⚗️ Add export results
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jan 4, 2022
1 parent 72454c0 commit 6c1e0fd
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 103 deletions.
3 changes: 2 additions & 1 deletion apps/builder/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
cypress/videos
cypress/screenshots
cypress/screenshots
cypress/downloads
81 changes: 81 additions & 0 deletions apps/builder/components/results/ResultsActionButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {
HStack,
Button,
Fade,
Tag,
Text,
useDisclosure,
} from '@chakra-ui/react'
import { DownloadIcon, TrashIcon } from 'assets/icons'
import { ConfirmModal } from 'components/modals/ConfirmModal'
import React from 'react'

type ResultsActionButtonsProps = {
totalSelected: number
isDeleteLoading: boolean
isExportLoading: boolean
onDeleteClick: () => Promise<void>
onExportClick: () => void
}

export const ResultsActionButtons = ({
totalSelected,
isDeleteLoading,
isExportLoading,
onDeleteClick,
onExportClick,
}: ResultsActionButtonsProps) => {
const { isOpen, onOpen, onClose } = useDisclosure()
return (
<HStack>
<Fade in={totalSelected > 0} unmountOnExit>
<HStack
as={Button}
colorScheme="blue"
onClick={onExportClick}
isLoading={isExportLoading}
>
<DownloadIcon />
<Text>Export</Text>

<Tag colorScheme="blue" variant="subtle" size="sm">
{totalSelected}
</Tag>
</HStack>
</Fade>

<Fade in={totalSelected > 0} unmountOnExit>
<HStack
as={Button}
colorScheme="red"
onClick={onOpen}
isLoading={isDeleteLoading}
>
<TrashIcon />
<Text>Delete</Text>
{totalSelected > 0 && (
<Tag colorScheme="red" variant="subtle" size="sm">
{totalSelected}
</Tag>
)}
</HStack>
<ConfirmModal
isOpen={isOpen}
onConfirm={onDeleteClick}
onClose={onClose}
message={
<Text>
You are about to delete{' '}
<strong>
{totalSelected} submission
{totalSelected > 1 ? 's' : ''}
</strong>
. Are you sure you wish to continue?
</Text>
}
confirmButtonLabel={'Delete'}
/>
</Fade>
</HStack>
)
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable react/jsx-key */
import { Box, Checkbox, Flex } from '@chakra-ui/react'
import { Answer, Result } from 'bot-engine'
import { useTypebot } from 'contexts/TypebotContext'
import React, { useEffect, useRef } from 'react'
import React, { useEffect, useMemo, useRef } from 'react'
import { Hooks, useFlexLayout, useRowSelect, useTable } from 'react-table'
import { parseSubmissionsColumns } from 'services/publicTypebot'
import { parseDateToReadable } from 'services/results'
import { LoadingRows } from './LoadingRows'

const defaultCellWidth = 180

type SubmissionsTableProps = {
results?: (Result & { answers: Answer[] })[]
data?: any
hasMore?: boolean
onNewSelection: (selection: string[]) => void
onNewSelection: (indices: number[]) => void
onScrollToBottom: () => void
}

export const SubmissionsTable = ({
results,
data,
hasMore,
onNewSelection,
onScrollToBottom,
}: SubmissionsTableProps) => {
const { publishedTypebot } = useTypebot()
const columns: any = React.useMemo(
const columns: any = useMemo(
() => parseSubmissionsColumns(publishedTypebot),
[publishedTypebot]
)
const data = React.useMemo(
() =>
(results ?? []).map((result) => ({
createdAt: parseDateToReadable(result.createdAt),
...result.answers.reduce(
(o, answer) => ({ ...o, [answer.blockId]: answer.content }),
{}
),
})),
// eslint-disable-next-line react-hooks/exhaustive-deps
[results?.length]
)

const bottomElement = useRef<HTMLDivElement | null>(null)
const tableWrapper = useRef<HTMLDivElement | null>(null)

Expand All @@ -59,8 +46,7 @@ export const SubmissionsTable = ({
) as any

useEffect(() => {
if (!results) return
onNewSelection(selectedFlatRows.map((row: any) => results[row.index].id))
onNewSelection(selectedFlatRows.map((row: any) => row.index))
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFlatRows])

Expand Down Expand Up @@ -130,8 +116,7 @@ export const SubmissionsTable = ({
as="tr"
{...row.getRowProps()}
ref={(ref) => {
if (results && idx === results.length - 10)
bottomElement.current = ref
if (idx === data.length - 10) bottomElement.current = ref
}}
>
{row.cells.map((cell: any, idx: number) => {
Expand All @@ -155,9 +140,7 @@ export const SubmissionsTable = ({
</Flex>
)
})}
{(results === undefined || hasMore === true) && (
<LoadingRows totalColumns={columns.length} />
)}
{hasMore === true && <LoadingRows totalColumns={columns.length} />}
</Box>
</Box>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const TypebotHeader = () => {
h={`${headerHeight}px`}
zIndex={2}
bgColor="white"
flexShrink={0}
>
<HStack>
<Button
Expand Down
47 changes: 47 additions & 0 deletions apps/builder/cypress/tests/results.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import path from 'path'
import { parse } from 'papaparse'

describe('ResultsPage', () => {
before(() => {
cy.intercept({ url: '/api/typebots/typebot2/results*', method: 'GET' }).as(
Expand Down Expand Up @@ -44,4 +47,48 @@ describe('ResultsPage', () => {
cy.findByText('content50').should('exist')
cy.findByText('content0').should('exist')
})

it.only('should correctly export selection in CSV', () => {
const downloadsFolder = Cypress.config('downloadsFolder')
cy.signIn('test2@gmail.com')
cy.visit('/typebots/typebot2/results')
cy.wait('@getResults')
cy.findByRole('button', { name: 'Export' }).should('not.exist')
cy.findByText('content199').should('exist')
cy.findAllByRole('checkbox').eq(2).check({ force: true })
cy.findAllByRole('checkbox').eq(3).check({ force: true })
cy.findByRole('button', { name: 'Export 2' }).click({ force: true })
const filename = path.join(
downloadsFolder,
`typebot-export_${new Date()
.toLocaleDateString()
.replaceAll('/', '-')}.csv`
)
cy.readFile(filename, { timeout: 15000 })
.then(parse)
.then(validateExportSelection as any)
cy.findAllByRole('checkbox').first().check({ force: true })
cy.findByRole('button', { name: 'Export 200' }).click({ force: true })
const filenameAll = path.join(
downloadsFolder,
`typebot-export_${new Date()
.toLocaleDateString()
.replaceAll('/', '-')}_all.csv`
)
cy.readFile(filenameAll, { timeout: 15000 })
.then(parse)
.then(validateExportAll as any)
})
})

const validateExportSelection = (list: { data: unknown[][] }) => {
expect(list.data, 'number of records').to.have.length(3)
expect(list.data[1][1], 'first record').to.equal('content198')
expect(list.data[2][1], 'second record').to.equal('content197')
}

const validateExportAll = (list: { data: unknown[][] }) => {
expect(list.data, 'number of records').to.have.length(201)
expect(list.data[1][1], 'first record').to.equal('content199')
expect(list.data[200][1], 'second record').to.equal('content0')
}
2 changes: 1 addition & 1 deletion apps/builder/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"exclude": [],
"compilerOptions": {
"types": ["cypress", "@testing-library/cypress", "cypress-file-upload"],
"lib": ["es2015", "dom"],
"lib": ["es2015", "dom", "ES2021.String"],
"target": "es5",
"isolatedModules": false,
"allowJs": true,
Expand Down
Loading

0 comments on commit 6c1e0fd

Please sign in to comment.