diff --git a/web/gui-v2/src/components/ListViewButtonBar.jsx b/web/gui-v2/src/components/ListViewButtonBar.jsx
new file mode 100644
index 0000000..5c1edd0
--- /dev/null
+++ b/web/gui-v2/src/components/ListViewButtonBar.jsx
@@ -0,0 +1,200 @@
+import React, { useLayoutEffect, useRef, useState } from 'react';
+import { css } from '@emotion/react';
+import { CSVLink } from 'react-csv';
+import {
+ AddCircleOutline as AddCircleOutlineIcon,
+ Close as CloseIcon,
+ Download as DownloadIcon,
+ Help as HelpIcon,
+} from "@mui/icons-material";
+import { Button } from '@mui/material';
+
+import {
+ HelpTooltip,
+ classes,
+} from '@eto/eto-ui-components';
+
+import { useWindowSize } from '../util';
+
+const styles = {
+ standardText: css`
+ font-family: GTZirkonLight;
+ letter-spacing: 0.00938em;
+ line-height: 1.5;
+ text-transform: uppercase;
+ `,
+ buttonBar: css`
+ background-color: var(--bright-blue-lighter);
+ display: flex;
+ flex-wrap: wrap;
+ padding: 0.5rem;
+
+ button {
+ font-family: GTZirkonLight;
+
+ svg {
+ margin-right: 5px;
+ }
+ }
+ `,
+ buttonBarLeft: css`
+ align-items: center;
+ color: var(--dark-blue);
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.25rem;
+ margin: 6px 8px;
+
+ & > span {
+ align-items: center;
+ }
+ `,
+ activeFilterTooltip: css`
+ .MuiTooltip-tooltip {
+ max-width: 400px;
+
+ li > span {
+ font-family: GTZirkonLight;
+ }
+ }
+ `,
+ activeFiltersText: css`
+ align-items: center;
+ display: flex;
+
+ svg {
+ fill: var(--bright-blue);
+ height: 16px;
+ }
+ `,
+ buttonBarRight: css`
+ display: flex;
+ margin-left: auto;
+ `,
+ buttonBarButton: css`
+ min-width: 40px;
+ `,
+
+};
+
+const BUTTONBAR_PADDING = 16;
+const BUTTONBAR_LEFT_MARGIN = 16;
+const BUTTON_WIDTH_RESET = 145;
+const BUTTON_WIDTH_DOWNLOAD = 182;
+const BUTTON_WIDTH_COLUMNS = 202;
+const BUTTON_WIDTH_NO_LABEL = 45;
+const BUTTONBAR_RIGHT_MIN_WIDTH = 3 * BUTTON_WIDTH_NO_LABEL;
+
+
+const ButtonBar = ({
+ activeFilters,
+ activeFiltersTooltip,
+ currentFilters,
+ exportData,
+ exportHeaders,
+ numCompanies,
+ resetFilters,
+ setDialogOpen,
+ totalRows,
+}) => {
+ const windowSize = useWindowSize();
+
+ // Adjust the visibility of the buttonbar labels based on how much space we have
+ // available based on the viewport width.
+ // TODO: Refactor the buttonbar into a separate component.
+ const buttonBarRef = useRef();
+ const buttonBarLeftRef = useRef();
+ const [buttonBarWidth, setButtonBarWidth] = useState(500);
+ const [buttonBarLeftWidth, setButtonBarLeftWidth] = useState(200);
+ const [showLabelReset, setShowLabelReset] = useState(false);
+ const [showLabelDownload, setShowLabelDownload] = useState(false);
+ const [showLabelColumns, setShowLabelColumns] = useState(false);
+
+ useLayoutEffect(() => {
+ const barBounds = buttonBarRef.current.getBoundingClientRect();
+ setButtonBarWidth(barBounds.width - BUTTONBAR_PADDING);
+ const leftBounds = buttonBarLeftRef.current.getBoundingClientRect();
+ setButtonBarLeftWidth(leftBounds.width + BUTTONBAR_LEFT_MARGIN);
+ }, [currentFilters, windowSize]);
+
+ // The label for Download is hidden first, then Columns, and finally Reset is hidden last.
+ useLayoutEffect(() => {
+ let spaceForButtons = buttonBarWidth - buttonBarLeftWidth;
+ // If we don't have enough space on the first row for the the buttons without *any* labels,
+ // flexbox will wrap us onto the next line, so we have the full buttonbar width to use.
+ if ( spaceForButtons < BUTTONBAR_RIGHT_MIN_WIDTH ) {
+ spaceForButtons = buttonBarWidth;
+ }
+
+ if ( spaceForButtons >= BUTTON_WIDTH_RESET + BUTTON_WIDTH_COLUMNS + BUTTON_WIDTH_DOWNLOAD ) {
+ setShowLabelReset(true);
+ setShowLabelDownload(true);
+ setShowLabelColumns(true);
+ } else if ( spaceForButtons >= BUTTON_WIDTH_RESET + BUTTON_WIDTH_COLUMNS + BUTTON_WIDTH_NO_LABEL) {
+ setShowLabelReset(true);
+ setShowLabelDownload(false);
+ setShowLabelColumns(true);
+ } else if ( spaceForButtons >= BUTTON_WIDTH_RESET + 2*BUTTON_WIDTH_NO_LABEL ) {
+ setShowLabelReset(true);
+ setShowLabelDownload(false);
+ setShowLabelColumns(false);
+ } else {
+ setShowLabelReset(false);
+ setShowLabelDownload(false);
+ setShowLabelColumns(false);
+ }
+ }, [buttonBarWidth, buttonBarLeftWidth]);
+
+
+ return (
+
+
+ Viewing {numCompanies !== totalRows ? `${numCompanies} of ${totalRows}` : totalRows} companies
+ {activeFilters.length > 0 &&
+
+
+ ({activeFilters.length} filters active)
+
+
+
+ }
+
+
+
0 && activeFiltersTooltip}
+ >
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ButtonBar;
diff --git a/web/gui-v2/src/components/ListViewTable.jsx b/web/gui-v2/src/components/ListViewTable.jsx
index 449c04d..2fb558f 100644
--- a/web/gui-v2/src/components/ListViewTable.jsx
+++ b/web/gui-v2/src/components/ListViewTable.jsx
@@ -1,28 +1,19 @@
import React, {
useEffect,
- useLayoutEffect,
useMemo,
useRef,
useState,
} from 'react';
-import { CSVLink } from 'react-csv';
import { getQueryParams, useQueryParamString } from 'react-use-query-param-string';
import { css } from '@emotion/react';
-import {
- AddCircleOutline as AddCircleOutlineIcon,
- Close as CloseIcon,
- Download as DownloadIcon,
- Help as HelpIcon,
-} from "@mui/icons-material";
-import { Button } from '@mui/material';
import {
HelpTooltip,
Table,
- classes,
} from '@eto/eto-ui-components';
import AddRemoveColumnDialog from './AddRemoveColumnDialog';
+import ButtonBar from './ListViewButtonBar';
import HeaderDropdown from './HeaderDropdown';
import HeaderSlider from './HeaderSlider';
import overallData from '../static_data/overall_data.json';
@@ -33,73 +24,15 @@ import {
commas,
debounce,
useMultiState,
- useWindowSize,
} from '../util';
import { plausibleEvent } from '../util/analytics';
import { formatActiveSliderFilter } from '../util/format';
const styles = {
- standardText: css`
- font-family: GTZirkonLight;
- letter-spacing: 0.00938em;
- line-height: 1.5;
- text-transform: uppercase;
- `,
- buttonBar: css`
- background-color: var(--bright-blue-lighter);
- display: flex;
- flex-wrap: wrap;
- padding: 0.5rem;
-
- button {
- font-family: GTZirkonLight;
-
- svg {
- margin-right: 5px;
- }
- }
- `,
- buttonBarLeft: css`
- align-items: center;
- color: var(--dark-blue);
- display: flex;
- flex-wrap: wrap;
- gap: 0.25rem;
- margin: 6px 8px;
-
- & > span {
- align-items: center;
- }
- `,
- activeFilterTooltip: css`
- .MuiTooltip-tooltip {
- max-width: 400px;
-
- li > span {
- font-family: GTZirkonLight;
- }
- }
- `,
activeFiltersList: css`
margin: 0;
padding-left: 1rem;
`,
- activeFiltersText: css`
- align-items: center;
- display: flex;
-
- svg {
- fill: var(--bright-blue);
- height: 16px;
- }
- `,
- buttonBarRight: css`
- display: flex;
- margin-left: auto;
- `,
- buttonBarButton: css`
- min-width: 40px;
- `,
table: css`
td.MuiTableCell-root {
padding: 0.5rem;
@@ -438,20 +371,11 @@ const AggregateCell = ({
);
}
-const BUTTONBAR_PADDING = 16;
-const BUTTONBAR_LEFT_MARGIN = 16;
-const BUTTON_WIDTH_RESET = 145;
-const BUTTON_WIDTH_DOWNLOAD = 182;
-const BUTTON_WIDTH_COLUMNS = 202;
-const BUTTON_WIDTH_NO_LABEL = 45;
-const BUTTONBAR_RIGHT_MIN_WIDTH = 3 * BUTTON_WIDTH_NO_LABEL;
-
const ListViewTable = ({
data,
}) => {
const [dialogOpen, setDialogOpen] = useState(false);
- const windowSize = useWindowSize();
const isFirstRender = useRef(true);
const tableRef = useRef();
@@ -616,53 +540,6 @@ const ListViewTable = ({
);
- // Adjust the visibility of the buttonbar labels based on how much space we have
- // available based on the viewport width.
- // TODO: Refactor the buttonbar into a separate component.
- const buttonBarRef = useRef();
- const buttonBarLeftRef = useRef();
- const [buttonBarWidth, setButtonBarWidth] = useState(500);
- const [buttonBarLeftWidth, setButtonBarLeftWidth] = useState(200);
- const [showLabelReset, setShowLabelReset] = useState(false);
- const [showLabelDownload, setShowLabelDownload] = useState(false);
- const [showLabelColumns, setShowLabelColumns] = useState(false);
-
- useLayoutEffect(() => {
- const barBounds = buttonBarRef.current.getBoundingClientRect();
- setButtonBarWidth(barBounds.width - BUTTONBAR_PADDING);
- const leftBounds = buttonBarLeftRef.current.getBoundingClientRect();
- setButtonBarLeftWidth(leftBounds.width + BUTTONBAR_LEFT_MARGIN);
- }, [currentFilters, windowSize]);
-
- // The label for Download is hidden first, then Columns, and finally Reset is hidden last.
- useLayoutEffect(() => {
- let spaceForButtons = buttonBarWidth - buttonBarLeftWidth;
- // If we don't have enough space on the first row for the the buttons without *any* labels,
- // flexbox will wrap us onto the next line, so we have the full buttonbar width to use.
- if ( spaceForButtons < BUTTONBAR_RIGHT_MIN_WIDTH ) {
- spaceForButtons = buttonBarWidth;
- }
-
- if ( spaceForButtons >= BUTTON_WIDTH_RESET + BUTTON_WIDTH_COLUMNS + BUTTON_WIDTH_DOWNLOAD ) {
- setShowLabelReset(true);
- setShowLabelDownload(true);
- setShowLabelColumns(true);
- } else if ( spaceForButtons >= BUTTON_WIDTH_RESET + BUTTON_WIDTH_COLUMNS + BUTTON_WIDTH_NO_LABEL) {
- setShowLabelReset(true);
- setShowLabelDownload(false);
- setShowLabelColumns(true);
- } else if ( spaceForButtons >= BUTTON_WIDTH_RESET + 2*BUTTON_WIDTH_NO_LABEL ) {
- setShowLabelReset(true);
- setShowLabelDownload(false);
- setShowLabelColumns(false);
- } else {
- setShowLabelReset(false);
- setShowLabelDownload(false);
- setShowLabelColumns(false);
- }
- }, [buttonBarWidth, buttonBarLeftWidth]);
-
-
// Prepare the columns that we will display in the ``, including
// adding the appropriate filter mechanisms to the header cells.
const columnsParamSplit = columnsParam.split(',');
@@ -883,53 +760,17 @@ const ListViewTable = ({
return (
-
-
- Viewing {numCompanies !== totalRows ? `${numCompanies} of ${totalRows}` : totalRows} companies
- {activeFilters.length > 0 &&
-
-
- ({activeFilters.length} filters active)
-
-
-
- }
-
-
-
0 && activeFiltersTooltip}
- >
-
-
-
-
-
-
-
-
+