Skip to content

Commit

Permalink
fix(ZipDownloadLimit): it wasn't being rendered when navigating throu…
Browse files Browse the repository at this point in the history
…gh pagination
  • Loading branch information
MellyGray committed Sep 1, 2023
1 parent d695c0c commit 8aab40e
Showing 9 changed files with 227 additions and 152 deletions.
12 changes: 5 additions & 7 deletions src/sections/dataset/dataset-files/files-table/FilesTable.tsx
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ interface FilesTableProps {
}

export function FilesTable({ files, isLoading, paginationInfo }: FilesTableProps) {
const { table, rowSelection, selectAllRows, clearRowSelection } = useFilesTable(
const { table, fileSelection, selectAllFiles, clearFileSelection } = useFilesTable(
files,
paginationInfo
)
@@ -26,14 +26,12 @@ export function FilesTable({ files, isLoading, paginationInfo }: FilesTableProps
return (
<>
<RowSelectionMessage
rowSelection={rowSelection}
selectAllRows={selectAllRows}
fileSelection={fileSelection}
selectAllRows={selectAllFiles}
totalFilesCount={paginationInfo.totalFiles}
clearRowSelection={clearRowSelection}
/>
<ZipDownloadLimitMessage
selectedFiles={table.getSelectedRowModel().flatRows.map((row) => row.original)}
clearRowSelection={clearFileSelection}
/>
<ZipDownloadLimitMessage fileSelection={fileSelection} />
<Table>
<FilesTableHeader headers={table.getHeaderGroups()} />
<FilesTableBody rows={table.getRowModel().rows} />
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { RowSelection } from './useRowSelection'
import { FileSelection } from './useFileSelection'
import { Button } from '@iqss/dataverse-design-system'
import { useTranslation } from 'react-i18next'
import styles from './RowSelectionMessage.module.scss'

interface RowSelectionMessageProps {
rowSelection: RowSelection
fileSelection: FileSelection
totalFilesCount: number
selectAllRows: () => void
clearRowSelection: () => void
@@ -14,13 +14,13 @@ const MINIMUM_SELECTED_FILES_TO_SHOW_MESSAGE = 0
const MINIMUM_FILES_TO_SHOW_MESSAGE = 10

export function RowSelectionMessage({
rowSelection,
fileSelection,
totalFilesCount,
selectAllRows,
clearRowSelection
}: RowSelectionMessageProps) {
const { t } = useTranslation('files')
const selectedFilesCount = Object.keys(rowSelection).length
const selectedFilesCount = Object.keys(fileSelection).length
const showMessage =
totalFilesCount > MINIMUM_FILES_TO_SHOW_MESSAGE &&
selectedFilesCount > MINIMUM_SELECTED_FILES_TO_SHOW_MESSAGE
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { useEffect, useState } from 'react'
import { FilePaginationInfo } from '../../../../../files/domain/models/FilePaginationInfo'
import { File } from '../../../../../files/domain/models/File'
import { Row } from '@tanstack/react-table'
import { RowSelection } from '../useFilesTable'

export type FileSelection = {
[key: string]: File | undefined
}

export function useFileSelection(
currentPageSelectedRowModel: Record<string, Row<File>>,
setCurrentPageRowSelection: (rowSelection: RowSelection) => void,
paginationInfo: FilePaginationInfo
) {
const [fileSelection, setFileSelection] = useState<FileSelection>({})
const updateFileSelection = () => {
const currentPageFileSelection = getCurrentPageFileSelection()
const currentPageIndexes = getCurrentPageIndexes()

Object.keys(fileSelection).forEach((key) => {
const rowIndex = parseInt(key)
if (currentPageIndexes.includes(rowIndex)) {
if (!currentPageFileSelection[key]) {
delete fileSelection[key]
}
}
})

return { ...fileSelection, ...currentPageFileSelection }
}
const getCurrentPageIndexes = () => {
return Array.from(
{ length: paginationInfo.pageSize },
(_, i) => i + (paginationInfo.page - 1) * paginationInfo.pageSize
)
}
const getCurrentPageFileSelection = () => {
const rowSelectionFixed: FileSelection = {}
const currentPageIndexes = getCurrentPageIndexes()

Object.entries(currentPageSelectedRowModel).forEach(([string, Row]) => {
const rowIndex = parseInt(string)
rowSelectionFixed[currentPageIndexes[rowIndex]] = Row.original
})
return rowSelectionFixed
}
const computeCurrentPageRowSelection = () => {
const rowSelectionOfCurrentPage: RowSelection = {}
const currentPageIndexes = getCurrentPageIndexes()

Object.keys(fileSelection).forEach((key) => {
const rowIndex = parseInt(key)
if (currentPageIndexes.includes(rowIndex)) {
rowSelectionOfCurrentPage[currentPageIndexes.indexOf(rowIndex)] = true
}
})

return rowSelectionOfCurrentPage
}
const selectAllFiles = () => {
setCurrentPageRowSelection(createRowSelection(paginationInfo.pageSize))
setFileSelection(createFileSelection(paginationInfo.totalFiles))
}
const clearFileSelection = () => {
setCurrentPageRowSelection({})
setFileSelection({})
}
const toggleAllFilesSelected = () => {
if (areAllFilesSelected()) {
clearFileSelection()
} else {
selectAllFiles()
}
}
const areAllFilesSelected = () => {
return Object.keys(fileSelection).length === paginationInfo.totalFiles
}

useEffect(() => {
setFileSelection(updateFileSelection())
}, [currentPageSelectedRowModel])

useEffect(() => {
setCurrentPageRowSelection(computeCurrentPageRowSelection())
}, [paginationInfo])

return {
fileSelection,
selectAllFiles,
clearFileSelection,
toggleAllFilesSelected
}
}

export function createRowSelection(numberOfRows: number) {
const rowSelection: Record<string, boolean> = {}

for (let i = 0; i < numberOfRows; i++) {
rowSelection[String(i)] = true
}

return rowSelection
}

export function createFileSelection(numberOfRows: number) {
const fileSelection: FileSelection = {}

for (let i = 0; i < numberOfRows; i++) {
fileSelection[String(i)] = undefined
}

return fileSelection
}

This file was deleted.

30 changes: 19 additions & 11 deletions src/sections/dataset/dataset-files/files-table/useFilesTable.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { useEffect, useState } from 'react'
import { File } from '../../../../files/domain/models/File'
import { getCoreRowModel, useReactTable } from '@tanstack/react-table'
import { getCoreRowModel, Row, useReactTable } from '@tanstack/react-table'
import { createColumnsDefinition } from './FilesTableColumnsDefinition'
import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo'
import { RowSelection, useRowSelection } from './row-selection/useRowSelection'
import { useFileSelection } from './row-selection/useFileSelection'

export type RowSelection = {
[key: string]: boolean
}

export function useFilesTable(files: File[], paginationInfo: FilePaginationInfo) {
const [currentPageRowSelection, setCurrentPageRowSelection] = useState<RowSelection>({})
const { rowSelection, selectAllRows, clearRowSelection, toggleAllRowsSelected } = useRowSelection(
currentPageRowSelection,
setCurrentPageRowSelection,
paginationInfo
)
const [currentPageSelectedRowModel, setCurrentPageSelectedRowModel] = useState<
Record<string, Row<File>>
>({})
const { fileSelection, selectAllFiles, clearFileSelection, toggleAllFilesSelected } =
useFileSelection(currentPageSelectedRowModel, setCurrentPageRowSelection, paginationInfo)
const table = useReactTable({
data: files,
columns: createColumnsDefinition(toggleAllRowsSelected),
columns: createColumnsDefinition(toggleAllFilesSelected),
state: {
rowSelection: currentPageRowSelection
},
@@ -30,10 +34,14 @@ export function useFilesTable(files: File[], paginationInfo: FilePaginationInfo)
table.setPageIndex(paginationInfo.page - 1)
}, [paginationInfo])

useEffect(() => {
setCurrentPageSelectedRowModel(table.getSelectedRowModel().rowsById)
}, [table.getSelectedRowModel().rowsById])

return {
table,
rowSelection,
selectAllRows,
clearRowSelection
fileSelection,
selectAllFiles,
clearFileSelection
}
}
Original file line number Diff line number Diff line change
@@ -5,19 +5,18 @@ import { useSettings } from '../../../../settings/SettingsContext'
import { SettingName } from '../../../../../settings/domain/models/Setting'
import { ZipDownloadLimit } from '../../../../../settings/domain/models/ZipDownloadLimit'
import { useEffect, useState } from 'react'
import { FileSelection } from '../row-selection/useFileSelection'

interface ZipDownloadLimitMessageProps {
selectedFiles: File[]
fileSelection: FileSelection
}

const MINIMUM_FILES_TO_SHOW_MESSAGE = 1

export function ZipDownloadLimitMessage({ selectedFiles }: ZipDownloadLimitMessageProps) {
export function ZipDownloadLimitMessage({ fileSelection }: ZipDownloadLimitMessageProps) {
const { t } = useTranslation('files')
const { getSettingByName } = useSettings()
const [zipDownloadLimitInBytes, setZipDownloadLimitInBytes] = useState<number>()
const selectionTotalSizeInBytes = getFilesTotalSizeInBytes(selectedFiles)

useEffect(() => {
getSettingByName<ZipDownloadLimit>(SettingName.ZIP_DOWNLOAD_LIMIT)
.then((zipDownloadLimit) => {
@@ -28,9 +27,11 @@ export function ZipDownloadLimitMessage({ selectedFiles }: ZipDownloadLimitMessa
})
}, [getSettingByName])

// TODO - When selecting all files, the size should come from a call to a use case that returns the total size of the dataset files. Check issue https://github.com/IQSS/dataverse-frontend/issues/170
const selectionTotalSizeInBytes = getFilesTotalSizeInBytes(Object.values(fileSelection))
const showMessage =
zipDownloadLimitInBytes &&
selectedFiles.length > MINIMUM_FILES_TO_SHOW_MESSAGE &&
Object.values(fileSelection).length > MINIMUM_FILES_TO_SHOW_MESSAGE &&
selectionTotalSizeInBytes > zipDownloadLimitInBytes

if (!showMessage) {
@@ -48,8 +49,10 @@ export function ZipDownloadLimitMessage({ selectedFiles }: ZipDownloadLimitMessa
)
}

function getFilesTotalSizeInBytes(files: File[]) {
return files.map((file) => file.size).reduce((bytes, size) => bytes + size.toBytes(), 0)
function getFilesTotalSizeInBytes(files: (File | undefined)[]) {
return files
.map((file) => file?.size)
.reduce((bytes, size) => bytes + (size ? size.toBytes() : 0), 0)
}

function bytesToHumanReadable(bytes: number) {
Loading

0 comments on commit 8aab40e

Please sign in to comment.