Skip to content

Commit

Permalink
Merge pull request #1594 from fedspendingtransparency/FDG-9970
Browse files Browse the repository at this point in the history
FDG-9970 Data table - All Tables Selected
  • Loading branch information
nicweidner authored Jan 28, 2025
2 parents 16397fd + 041f126 commit 0f2a427
Show file tree
Hide file tree
Showing 30 changed files with 667 additions and 341 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$cell-height: 2.125rem;

.tableNotice {
position: absolute;
top: calc($cell-height * 4);
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import ChartTableDisplay from './data-preview-chart-table-display';
import { render } from '@testing-library/react';

describe('Chart Table Display', () => {
it('displays table', () => {
const mockTable = <table></table>;
const { getByRole } = render(<ChartTableDisplay table={mockTable} allTablesSelected={false} />);
expect(getByRole('table')).toBeInTheDocument();
});

it(`display "All Data Tables" banner when all tables is selected`, () => {
const mockTable = <table></table>;
const { getByText } = render(<ChartTableDisplay table={mockTable} allTablesSelected={true} />);
expect(getByText('The current "All Data Tables" selection is for download only')).toBeInTheDocument();
expect(getByText("To download the data, select the 'Download' button and choose the desired format.")).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { FunctionComponent } from 'react';
import NotShownMessage from '../../dataset-data/table-section-container/not-shown-message/not-shown-message';
import { getMessageForDefaultApiFilter, getMessageForUnmatchedUserFilter } from '../../filter-download-container/user-filter/user-filter';
import { allTablesSelectedBody, emptyDataMessageBody } from '../../dataset-data/chart-table-toggle/chart-table-toggle';
import TableNotice from './table-notice/table-notice';
import EmptyTable from './empty-table/empty-table';
import { tableNotice } from './data-preview-chart-table-display.module.scss';
import { pxToNumber } from '../../../helpers/styles-helper/styles-helper';
import { breakpointLg } from '../../../variables.module.scss';

const ChartTableDisplay: FunctionComponent = ({
table,
allTablesSelected,
selectedTable,
emptyData,
unchartable,
legend,
selectedTab,
chart,
userFilterUnmatchedForDateRange,
apiFilterDefault,
pivotSelected,
width,
}) => {
let emptyDataMessage = null;

const allTableHeading = 'The current "All Data Tables" selection is for download only';
const allTableBody = "To download the data, select the 'Download' button and choose the desired format.";

if (allTablesSelected) {
emptyDataMessage = <TableNotice heading={allTableHeading} bodyText={allTableBody} />;
}
//TODO: Add in additional cases for the table notice
// else if (userFilterUnmatchedForDateRange) {
// emptyDataMessage = getMessageForUnmatchedUserFilter(selectedTable);
// } else if (apiFilterDefault) {
// emptyDataMessage = getMessageForDefaultApiFilter(selectedTable);
// } else if (emptyData) {
// emptyDataMessage = <NotShownMessage heading="Change selections in order to preview data" bodyText={emptyDataMessageBody} />;
// }

return (
<>
{emptyDataMessage ? (
<>
<EmptyTable mobileDisplay={width < pxToNumber(breakpointLg)} />
<div className={tableNotice}>{emptyDataMessage}</div>
</>
) : (
table
)}
</>
);
};

export default ChartTableDisplay;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@import 'src/variables.module';
$cell-height: 2.125rem;

.emptyTable {
opacity: 40%;
width: 100%;
border-spacing: 0;
border: $table-border-style;
border-collapse: collapse;

th,
td {
height: $cell-height;
border-right: $table-border-style;
}

tr:not(:last-child) td {
border-bottom: $table-border-style;
}

th {
background-color: #f1f1f1;
border-bottom: $table-border-style;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import EmptyTable from './empty-table';
import { render } from '@testing-library/react';

describe('Empty Table', () => {
it('renders a table', () => {
const { getByRole, getAllByRole } = render(<EmptyTable />);

expect(getByRole('table')).toBeInTheDocument();
expect(getAllByRole('row')).toHaveLength(11);
});

it('renders a table with specified number of rows', () => {
const { getByRole, getAllByRole } = render(<EmptyTable rowCount={5} />);

expect(getByRole('table')).toBeInTheDocument();
expect(getAllByRole('row')).toHaveLength(6);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { FunctionComponent } from 'react';
import { emptyTable } from './empty-table.module.scss';
import DataTableFooter from '../../../data-table/data-table-footer/data-table-footer';

const EmptyTable: FunctionComponent = ({ rowCount = 10, mobileDisplay }) => {
const columnCount = mobileDisplay ? 2 : 6;

return (
<>
<table className={emptyTable}>
<tbody>
<tr>
{Array.from({ length: columnCount }, (_, index) => (
<th key={`header-${index}`} />
))}
</tr>
{Array.from({ length: rowCount }, (_, index) => (
<tr key={`row-${index}`}>
{Array.from({ length: columnCount }, (_, index) => (
<td key={`cell-${index}`} />
))}
</tr>
))}
</tbody>
</table>
<DataTableFooter
rowsShowing={{ begin: 0, end: 0 }}
manualPagination={true}
pagingProps={{ maxRows: 0, itemsPerPage: rowCount, disablePerPage: true, showWhenEmpty: true, currentPage: 1, maxPage: 1 }}
showPaginationControls={true}
/>
</>
);
};

export default EmptyTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@import 'src/variables.module.scss';

.container {
text-align: center;
}

.info {
display: inline-flex;
padding: 1.5rem 2rem;
background-color: $table-notice-color;
text-align: left;
max-width: 47.5rem;
}

.icon {
color: $primary;
font-size: $font-size-16;
margin-right: 0.75rem;
margin-top: 0.125rem;
}

.notShownHeading {
@include headingStyle6;
margin-bottom: 0.5rem;
}

.notShownBodyText {
@include bodyStyleRegular;
}

@media screen and (max-width: $breakpoint-lg - 1) {
.container {
margin: 0 1.5rem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import TableNotice from './table-notice';
import { render } from '@testing-library/react';

describe('Table Notice', () => {
it('renders the table notice', () => {
const heading = 'Mock Heading!';
const bodyText = 'Mock body text.';
const { getByText } = render(<TableNotice heading={heading} bodyText={bodyText} />);

expect(getByText(heading)).toBeInTheDocument();
expect(getByText(bodyText)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FunctionComponent } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { container, icon, info, notShownBodyText, notShownHeading } from './table-notice.module.scss';

interface iTableMessage {
heading: string;
bodyText: string;
}

const TableNotice: FunctionComponent<iTableMessage> = ({ heading, bodyText }) => {
return (
<div className={container} data-testid="container">
<div className={info}>
<div className={icon}>
<FontAwesomeIcon icon={faInfoCircle} />
</div>
<div>
{heading && (
<div className={notShownHeading} data-testid="heading">
{heading}
</div>
)}
<div className={notShownBodyText} data-testid="bodyText">
{bodyText}
</div>
</div>
</div>
</div>
);
};

export default TableNotice;
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@import 'src/variables.module';
$table-border-style: 1px solid $light-grey-border;

.fillCellGrey,
.fillCellWhite {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@import 'src/variables.module.scss';
@import '../data-preview-data-table.module';

.tableHeader {
cursor: default;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@import 'src/variables.module.scss';

$borderRadius: 5px;
$table-border-style: 1px solid $light-grey-border;

.overlayContainerNoFooter {
position: relative;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,28 @@ describe('Data Preview Dropdown Dialog', () => {
pivotView: { dimensionField: 'account_number', title: 'By Account Number' },
});
});

it('updates dropdown when All Data Tables is selected', () => {
const mockSetSelectedTable = jest.fn();
const mockSetSelectedPivot = jest.fn();

const { getByRole, getAllByText, queryByRole } = render(
<DataPreviewTableSelectDropdown
selectedTable={mockSelectedTable}
setSelectedTable={mockSetSelectedTable}
apis={mockApis}
setSelectedPivot={mockSetSelectedPivot}
/>
);

const dropdownButton = getByRole('button', { name: 'Data Table: Mock Table Name' });
fireEvent.click(dropdownButton);

const allTablesButton = getByRole('button', { name: 'All Data Tables (Download Only)' });
fireEvent.click(allTablesButton);

expect(getAllByText('All Data Tables (Download Only)').length).toBe(2);
expect(getByRole('radio', { name: 'Raw Data' })).toBeInTheDocument();
expect(queryByRole('radio', { name: 'Pivot Data' })).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import DropdownContainer from '../../dropdown-container/dropdown-container';
import DataPreviewDropdownDialogContainer from '../data-preview-dropdown-dialog/data-preview-dropdown-dialog';
import DataPreviewPivotSelect from '../data-preview-pivot-select/data-preview-pivot-select';
import { ITableSelectDropdown } from '../../../models/data-preview/ITableSelectDropdown';
import { allTablesOption } from '../../datatable-select/datatable-select';
import DataPreviewDropdownDialogSearch from '../data-preview-dropdown-search/data-preview-dropdown-dialog-search';

const DataPreviewTableSelectDropdown: FunctionComponent<ITableSelectDropdown> = ({
Expand All @@ -20,8 +19,16 @@ const DataPreviewTableSelectDropdown: FunctionComponent<ITableSelectDropdown> =
setSelectedPivot,
hideDropdown,
}) => {
const allTablesOption = {
allDataTables: true,
pathName: 'all-data-tables',
tableName: 'All Data Tables (Download Only)',
valueFieldOptions: null,
};

const initialSelectedTable = allTablesSelected ? allTablesOption : selectedTable;
const [active, setActive] = useState(false);
const [tableToApply, setTableToApply] = useState(selectedTable);
const [tableToApply, setTableToApply] = useState(initialSelectedTable);
const [pivotToApply, setPivotToApply] = useState(selectedPivot);
const [appliedTableView, setAppliedTableView] = useState('rawData');
const [tableViewSelection, setTableViewSelection] = useState(appliedTableView);
Expand All @@ -39,7 +46,7 @@ const DataPreviewTableSelectDropdown: FunctionComponent<ITableSelectDropdown> =
<DropdownLabelButton
label="Data Table"
icon={faDatabase}
selectedOption={selectedTable?.tableName}
selectedOption={allTablesSelected ? allTablesOption.tableName : selectedTable?.tableName}
active={active}
setActive={setActive}
dropdownWidth="30rem"
Expand All @@ -48,7 +55,7 @@ const DataPreviewTableSelectDropdown: FunctionComponent<ITableSelectDropdown> =

const handleApply = () => {
setAppliedTableView(tableViewSelection);
if (tableToApply !== selectedTable) {
if (tableToApply !== selectedTable || (allTablesSelected && !tableToApply.allDataTables)) {
setSelectedTable(tableToApply);
}
if (tableViewSelection === 'pivotData') {
Expand Down Expand Up @@ -87,11 +94,14 @@ const DataPreviewTableSelectDropdown: FunctionComponent<ITableSelectDropdown> =
useEffect(() => {
if (!active) {
setTableViewSelection(appliedTableView);
setTableToApply(selectedTable);
if (!allTablesSelected) {
setTableToApply(selectedTable);
}
}
}, [active]);

useEffect(() => {
//initialize pivot options
if (selectedTable && !selectedTable.allDataTables && !selectedPivot) {
const localPivotFields = getPivotFields(selectedTable);
const pivot = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import React, { FunctionComponent, useState } from 'react';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { faTable } from '@fortawesome/free-solid-svg-icons';
import DropdownLabelButton from '../../../dropdown-label-button/dropdown-label-button';
import DropdownContainer from '../../../dropdown-container/dropdown-container';
import ColumnFilterContainer from '../column-filter-container/column-filter-container';

const ColumnFilter: FunctionComponent = () => {
interface iColumnFilter {
allTablesSelected: boolean;
}

const ColumnFilter: FunctionComponent<iColumnFilter> = ({ allTablesSelected }) => {
const [visibleColumns, setVisibleColumns] = useState([]);
const totalColumns = 17;
const [active, setActive] = useState(false);

const filterDropdownButton = (
<DropdownLabelButton
label="Filters"
label="Columns"
selectedOption={visibleColumns.length + '/' + totalColumns}
icon={faTable}
active={active}
setActive={setActive}
disabled={allTablesSelected}
/>
);

Expand Down
Loading

0 comments on commit 0f2a427

Please sign in to comment.