Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
CircularProgress,
Chip,
} from '@material-ui/core';
import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';

import useMultiDatasetDownloadStore from '../stores/multiDatasetDownloadStore';
import useRowCountStore from '../stores/useRowCountStore';
import { dateToDateString } from '../../../shared/filtering/utils/dateHelpers';
import SelectAllDropdown from './SelectAllDropdown';
import { snackbarOpen } from '../../../Redux/actions/ui';

const styles = {
tableContainerStyle: {
Expand Down Expand Up @@ -63,7 +65,7 @@ const styles = {
};

const MultiDatasetDownloadTable = ({ datasetsMetadata }) => {
const history = useHistory();
const dispatch = useDispatch();
const {
isDatasetSelected,
toggleDatasetSelection,
Expand Down Expand Up @@ -92,38 +94,28 @@ const MultiDatasetDownloadTable = ({ datasetsMetadata }) => {
window.open(`/programs/${program}`, '_blank');
};

const handleSelectAllToggle = (event) => {
event.stopPropagation();
const { checked, indeterminate } =
getSelectAllCheckboxState(datasetsMetadata);

const getRowCountStoreConfig = () => ({
getThresholdConfig: getThresholdConfig,
getEffectiveRowCount: getEffectiveRowCount,
getTotalSelectedRows: getTotalSelectedRows,
});
const getRowCountStoreConfig = () => ({
getThresholdConfig: getThresholdConfig,
getEffectiveRowCount: getEffectiveRowCount,
getTotalSelectedRows: getTotalSelectedRows,
});

const shouldClear =
checked ||
(indeterminate &&
(() => {
// Try to add more datasets - if none can be added (at threshold), clear all
const selectionResult = selectAll(
getRowCountStoreConfig,
datasetsMetadata,
);
const noNewDatasetsAdded =
selectionResult && selectionResult.addedCount === 0;
return noNewDatasetsAdded;
})());
const handleSelectAll = () => {
const result = selectAll(getRowCountStoreConfig, datasetsMetadata);

if (shouldClear) {
clearSelections(datasetsMetadata);
} else {
selectAll(getRowCountStoreConfig, datasetsMetadata);
if (result.wasPartialSelection) {
dispatch(
snackbarOpen(
`Not all datasets could be selected because they would exceed the ${result.formattedThreshold}M row limit.`,
),
);
}
};

const handleClearAll = () => {
clearSelections(datasetsMetadata);
};

const formatLatLon = (value) => {
if (value === null || value === undefined) return 'N/A';
return Number(value).toFixed(1);
Expand Down Expand Up @@ -192,11 +184,15 @@ const MultiDatasetDownloadTable = ({ datasetsMetadata }) => {
<TableHead style={styles.tableHeadStyle}>
<TableRow>
<TableCell width={50} style={styles.headerCellStyle}>
<Checkbox
{...getSelectAllCheckboxState(datasetsMetadata)}
onChange={handleSelectAllToggle}
color="primary"
size="small"
<SelectAllDropdown
areAllSelected={
getSelectAllCheckboxState(datasetsMetadata).checked
}
areIndeterminate={
getSelectAllCheckboxState(datasetsMetadata).indeterminate
}
onSelectAll={handleSelectAll}
onClearAll={handleClearAll}
disabled={!datasetsMetadata || datasetsMetadata.length === 0}
/>
</TableCell>
Expand Down
114 changes: 114 additions & 0 deletions src/features/multiDatasetDownload/components/SelectAllDropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React, { useState } from 'react';
import { Checkbox, Menu, MenuItem, IconButton, Box } from '@material-ui/core';
import { ArrowDropDown } from '@material-ui/icons';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(() => ({
container: {
display: 'flex',
alignItems: 'center',
position: 'relative',
},
checkbox: {
padding: '9px',
},
dropdownButton: {
padding: '2px',
minWidth: 'auto',
marginLeft: '-6px',
'& .MuiSvgIcon-root': {
fontSize: '16px',
},
},
menuItem: {
fontSize: '14px',
padding: '8px 16px',
minHeight: 'auto',
},
}));

const SelectAllDropdown = ({
areAllSelected,
areIndeterminate,
onSelectAll,
onClearAll,
disabled = false,
}) => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = useState(null);

const handleDropdownClick = (event) => {
setAnchorEl(event.currentTarget);
};

const handleClose = () => {
setAnchorEl(null);
};

const handleMenuItemClick = (action) => {
action();
handleClose();
};

const handleCheckboxClick = (event) => {
event.stopPropagation();
const shouldClear = areAllSelected || areIndeterminate;

if (shouldClear) {
onClearAll();
} else {
onSelectAll();
}
};

return (
<Box className={classes.container}>
<Checkbox
indeterminate={areIndeterminate}
checked={areAllSelected}
color="primary"
size="small"
className={classes.checkbox}
disabled={disabled}
onClick={handleCheckboxClick}
/>
<IconButton
onClick={handleDropdownClick}
size="small"
className={classes.dropdownButton}
disabled={disabled}
>
<ArrowDropDown />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
style={{ zIndex: 9999 }}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
>
<MenuItem
onClick={() => handleMenuItemClick(onSelectAll)}
className={classes.menuItem}
>
Select All
</MenuItem>
<MenuItem
onClick={() => handleMenuItemClick(onClearAll)}
className={classes.menuItem}
>
Clear All
</MenuItem>
</Menu>
</Box>
);
};

export default SelectAllDropdown;
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,25 @@ const useMultiDatasetDownloadStore = create((set, get) => ({

selectAll: (getRowCountStore, filteredDatasets) => {
const { selectedDatasets: currentSelections } = get();
const totalAvailable = filteredDatasets.length;

if (!getRowCountStore) {
const allDatasetNames = new Set(
filteredDatasets.map((dataset) => dataset.Dataset_Name),
);
set({ selectedDatasets: allDatasetNames });
return { addedCount: allDatasetNames.size };
return {
totalAvailable,
actuallySelected: allDatasetNames.size,
wasPartialSelection: false,
};
}

const rowCountStore = getRowCountStore();
const { maxRowThreshold } = rowCountStore.getThresholdConfig();
const formattedThreshold = (maxRowThreshold / 1000000).toFixed(0);

const selectedDatasets = new Set(currentSelections);
const initialCount = selectedDatasets.size;

let currentTotal = rowCountStore.getTotalSelectedRows(
Array.from(selectedDatasets),
);
Expand All @@ -60,21 +64,26 @@ const useMultiDatasetDownloadStore = create((set, get) => ({

if (rowCount) {
const potentialTotal = currentTotal + rowCount;

if (potentialTotal > maxRowThreshold) {
continue;
}

selectedDatasets.add(datasetName);
currentTotal = potentialTotal;
} else {
selectedDatasets.add(datasetName);
}
}

const addedCount = selectedDatasets.size - initialCount;
const actuallySelected = selectedDatasets.size;
const wasPartialSelection = actuallySelected < totalAvailable;

set({ selectedDatasets });
return { addedCount };
return {
totalAvailable,
actuallySelected,
wasPartialSelection,
formattedThreshold,
};
},

clearSelections: (filteredDatasets) => {
Expand Down