Skip to content

Commit

Permalink
fix(table): UX and filter export (#2547)
Browse files Browse the repository at this point in the history
* fix(table): Fix table for UX
Closes #2506

* fix filterMap and style

* fix display, file name, clear filters

* fix header

---------

Co-authored-by: jolevesq <[email protected]>
  • Loading branch information
jolevesq and jolevesq authored Oct 15, 2024
1 parent 3d3bb37 commit 0a37a0a
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 72 deletions.
12 changes: 6 additions & 6 deletions packages/geoview-core/public/locales/en/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ _Note: Some tools in the Side Bar are also available as tabs in the Footer Bar,
| <img src="{{assetsURL}}/img/guide/sidebar/legend.svg" width="30"/> | Legend | Legend of map icons (_see Footer Bar section for help_) |
| <img src="{{assetsURL}}/img/guide/sidebar/details.svg" width="30"/> | Details | Details for selected features (_see Footer Bar section for help_) |
| <img src="{{assetsURL}}/img/guide/sidebar/guide.svg" width="30"/> | Guide | Help guide |
| <img src="{{assetsURL}}/img/guide/sidebar/export.svg" width="30"/> | Export | Download a PNG file of the map |
| <img src="{{assetsURL}}/img/guide/sidebar/export.svg" width="30"/> | Download | Download a PNG file of the map |
| <img src="{{assetsURL}}/img/guide/sidebar/notifications.svg" width="30"/> | Notifications | Display messages and notifications for the map |
| <img src="{{assetsURL}}/img/guide/sidebar/about.svg" width="30"/> | About Geoview | Display information about Geoview viewer |

Expand Down Expand Up @@ -152,13 +152,13 @@ The basemap selector modifies the underlying basemap to provide a variety of geo
<br>
=2!export=

### ![]({{assetsURL}}/img/guide/sidebar/export_30.svg) Export
### ![]({{assetsURL}}/img/guide/sidebar/export_30.svg) Download

You can export an image of the map and its visible layers along with a legend, title, north arrow, scalebar, and a timestamp.
You can download an image of the map and its visible layers along with a legend, title, north arrow, scalebar, and a timestamp.

Once **Export** button is clicked, a dialog will appear with an image of the map, and an option to enter a map title if desired.
Once **Download** button is clicked, a dialog will appear with an image of the map, and an option to enter a map title if desired.

Click on the Export button at the bottom to get the final generated map image.
Click on the **Download** button at the bottom to get the final generated map image.

=1!footerPanel=

Expand Down Expand Up @@ -330,7 +330,7 @@ _Note: Some options may not be available or are preselected depending on various
| <img src="{{assetsURL}}/img/guide/datatable/filter.png" width="30"/> | Filter switch | Apply filters to the map |
| <img src="{{assetsURL}}/img/guide/datatable/column_show.svg" width="30"/> | Display Columns | Allows you to choose which columns you want visible and to pin columns to the left or right of the table |
| <img src="{{assetsURL}}/img/guide/datatable/density.svg" width="30"/> | Density | Toggle the height of the rows in the data table |
| <img src="{{assetsURL}}/img/guide/datatable/export.svg" width="30"/> | Export | Export data table as CSV or GeoJSON. May not work as intended on mobile due to limitations with downloading files |
| <img src="{{assetsURL}}/img/guide/datatable/export.svg" width="30"/> | Download | Download data table as CSV or GeoJSON. May not work as intended on mobile due to limitations with downloading files |

The first three columns of the data table are Icon, Zoom and Details. The remaining columns vary depending on the layer selected.

Expand Down
9 changes: 5 additions & 4 deletions packages/geoview-core/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"crosshair": "Use <strong>Arrows</strong>, <strong>+</strong> and <strong>-</strong> keys to navigate the map, <strong>Enter</strong> to select and <strong>Shift+Arrow</strong> <strong>Up</strong> or <strong>Down</strong> to modify the pan value."
},
"appbar": {
"export": "Export",
"export": "Download map",
"notifications": "Notification",
"no_notifications_available": "No notifications available",
"layers": "Layers",
Expand Down Expand Up @@ -172,9 +172,9 @@
"invalidConfig": "Invalid JSON config, default configuration applied."
},
"exportModal": {
"title": "Export map as PNG",
"title": "Download map as PNG",
"cancelBtn": "Cancel",
"exportBtn": "Export",
"exportBtn": "Download",
"exportTitle": "Title",
"approx": "approx"
},
Expand All @@ -195,11 +195,12 @@
"icon": "ICON",
"zoom": "ZOOM",
"details": "DETAILS",
"exportBtn": "Export",
"exportBtn": "Download",
"jsonExportBtn": "Download GeoJSON",
"downloadAsCSV": "Download CSV",
"filterMap": "Filter map",
"stopFilterMap": "Stop filter map",
"clearFilters": "Clear filters",
"rowsSelected": "{rowsSelected} of {totalRows} row(s) selected",
"rowsFiltered": "{rowsFiltered} of {totalRows} row(s) filtered",
"enlargeBtn": "Enlarge",
Expand Down
12 changes: 6 additions & 6 deletions packages/geoview-core/public/locales/fr/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ _N.B.&nbsp;: Certains outils dans la barre latérale se trouvent aussi sous form
| <img src="{{assetsURL}}/img/guide/sidebar/legend.svg" width="30"/>| Légende| Légende des icônes de la carte (_voir la section sur le pied de page pour en savoir plus_).|
| <img src="{{assetsURL}}/img/guide/sidebar/details.svg" width="30"/>| Détails| Information détaillée des éléments sélectionnés (_voir la section sur le pied de page pour en savoir plus_).|
| <img src="{{assetsURL}}/img/guide/sidebar/guide.svg" width="30"/>| Guide| Guide d’aide|
| <img src="{{assetsURL}}/img/guide/sidebar/export.svg" width="30"/>| Exporter| Pour télécharger la carte en fichier PNG.|
| <img src="{{assetsURL}}/img/guide/sidebar/export.svg" width="30"/>| Télécharger| Pour télécharger la carte en fichier PNG.|
| <img src="{{assetsURL}}/img/guide/sidebar/notifications.svg" width="30"/>| Notification| Présente les messages et les notifications pour la carte.|
| <img src="{{assetsURL}}/img/guide/sidebar/about.svg" width="30"/>| À propos de GéoView| Affiche les renseignements sur le visualiseur GéoView.|

Expand Down Expand Up @@ -146,13 +146,13 @@ Le sélecteur permet de modifier la carte de base pour obtenir différents conte

<br>
=2!export=
### ![]({{assetsURL}}/img/guide/sidebar/export_30.svg) Exporter
### ![]({{assetsURL}}/img/guide/sidebar/export_30.svg) Télécharger

Vous pouvez exporter une image de la carte avec ses couches visibles, la légende, le titre, la flèche du nord, la barre d’échelle et un horodatage.
Vous pouvez télécharger une image de la carte avec ses couches visibles, la légende, le titre, la flèche du nord, la barre d’échelle et un horodatage.

Lorsque vous cliquez sur le bouton **Exporter**, une fenêtre de dialogue s’ouvre contenant l’image de la carte et un champ où vous pouvez entrer un titre.
Lorsque vous cliquez sur le bouton **Télécharger**, une fenêtre de dialogue s’ouvre contenant l’image de la carte et un champ où vous pouvez entrer un titre.

Cliquez sur le bouton **Exporter** au bas de la fenêtre pour générer l’image finale de la carte.
Cliquez sur le bouton **Télécharger** au bas de la fenêtre pour générer l’image finale de la carte.

=1!footerPanel=

Expand Down Expand Up @@ -320,7 +320,7 @@ _N.B.&nbsp;: Selon différents facteurs, certaines options sont désactivées ou
| <img src="{{assetsURL}}/img/guide/datatable/filter.png" width="30"/>| Interrupteur de filtres| Appliquer les filtres à la carte.|
| <img src="{{assetsURL}}/img/guide/datatable/column_show.svg" width="30"/>| Afficher/masquer les colonnes| Choisir les colonnes visibles et épingler des colonnes à gauche ou à droite du tableau.|
| <img src="{{assetsURL}}/img/guide/datatable/density.svg" width="30"/>| Densité| Modifier la hauteur des lignes du tableau de données.|
| <img src="{{assetsURL}}/img/guide/datatable/export.svg" width="30"/>| Exporter| Exporter le tableau en format CSV ou GeoJSON. Pourrait échouer sur un appareil mobile en raison des restrictions de téléchargement de fichiers.|
| <img src="{{assetsURL}}/img/guide/datatable/export.svg" width="30"/>| Télécharger| Télécharger le tableau en format CSV ou GeoJSON. Pourrait échouer sur un appareil mobile en raison des restrictions de téléchargement de fichiers.|

Les trois premières colonnes du tableau de données sont **Icône**, **Zoom** et **Détails**. Les autres colonnes varient selon la couche sélectionnée.

Expand Down
10 changes: 5 additions & 5 deletions packages/geoview-core/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"crosshair": "Utiliser les touches <strong>fléchées</strong>, <strong>+</strong> et <strong>-</strong> pour naviguer sur la carte, <strong>Entrée</strong> pour sélectionner et <strong>Shift+fléchées</strong> <strong>Haut</strong> et <strong>Bas</strong> pour modfier le déplacement."
},
"appbar": {
"export": "Exporter",
"export": "Télécharger la carte",
"notifications": "Notification",
"no_notifications_available": "Aucune notification disponible",
"layers": "Couches",
Expand Down Expand Up @@ -172,9 +172,9 @@
"invalidConfig": "Configuration JSON non valide, configuration par défaut appliquée."
},
"exportModal": {
"title": "Exporter la carte en PNG",
"title": "Télécharger la carte en PNG",
"cancelBtn": "Annuler",
"exportBtn": "Exporter",
"exportBtn": "Télécharger",
"exportTitle": "Titre",
"approx": "approx"
},
Expand All @@ -195,11 +195,11 @@
"icon": "ICÔNE",
"zoom": "ZOOM",
"details": "DÉTAILS",
"exportBtn": "Exporter",
"exportBtn": "Télécharger",
"jsonExportBtn": "Télécharger GeoJSON",
"downloadAsCSV": "Télécharger CSV",
"filterMap": "Filtrer la carte",
"stopFilterMap": "Arrêt des filtres",
"clearFilters": "Effacer les filtres",
"rowsSelected": "{rowsSelected} sur {totalRows} ligne(s) sélectionnée(s)",
"rowsFiltered": "{rowsFiltered} sur {totalRows} ligne(s) filtrée(s)",
"enlargeBtn": "Agrandir",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const getSxClasses = (theme: Theme) =>
letterSpacing: '0.01071em',
display: 'flex',
padding: '6px',
alignItems: 'center',
},
selectedRowsDirection: {
display: 'flex',
Expand All @@ -36,6 +37,11 @@ export const getSxClasses = (theme: Theme) =>
color: theme.palette.geoViewColor.grey.dark[900],
},
},
tableHead: {
'& th:nth-of-type(-n+3)': {
justifyContent: 'end',
},
},
tableHeadCell: {
'& .MuiCollapse-wrapperInner': {
'& .MuiBox-root': {
Expand Down
73 changes: 52 additions & 21 deletions packages/geoview-core/src/core/components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
Button,
IconButton,
Tooltip,
ClearFiltersIcon,
ZoomInSearchIcon,
InfoOutlinedIcon,
} from '@/ui';
Expand Down Expand Up @@ -70,20 +71,21 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
const sxtheme = useTheme();
const sxClasses = getSxClasses(sxtheme);

// internal state
const [density, setDensity] = useState<MRTDensityState>('compact');
const rowVirtualizerInstanceRef = useRef<MRTRowVirtualizer>(null);
const columnVirtualizerInstanceRef = useRef<MRTColumnVirtualizer>(null);
const [sorting, setSorting] = useState<MRTSortingState>([]);

// get store actions and values
const { zoomToExtent, highlightBBox, transformPoints, showClickMarker, addHighlightedFeature, removeHighlightedFeature } =
useMapStoreActions();
const { applyMapFilters, setSelectedFeature } = useDataTableStoreActions();
const { applyMapFilters, setSelectedFeature, setColumnsFiltersVisibility } = useDataTableStoreActions();
const { getExtentFromFeatures } = useLayerStoreActions();
const language = useAppDisplayLanguage();
const datatableSettings = useDataTableLayerSettings();

// internal state
const [density, setDensity] = useState<MRTDensityState>('compact');
const [showColumnFilters, setShowColumnFilters] = useState<boolean>(datatableSettings[layerPath].columnsFiltersVisibility);
const rowVirtualizerInstanceRef = useRef<MRTRowVirtualizer>(null);
const columnVirtualizerInstanceRef = useRef<MRTColumnVirtualizer>(null);
const [sorting, setSorting] = useState<MRTSortingState>([]);

const dataTableLocalization = language === 'fr' ? MRTLocalizationFR : MRTLocalizationEN;

// #region PINNED Datatable columns
Expand Down Expand Up @@ -111,7 +113,7 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):

return (
<Tooltip title={header} placement="top" arrow>
<Box component="span" sx={{ whiteSpace: 'nowrap' }}>
<Box component="span" sx={{ whiteSpace: 'nowrap', justifyContent: 'end' }}>
{header}
</Box>
</Tooltip>
Expand Down Expand Up @@ -345,7 +347,7 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
// Log
logger.logTraceUseMemo('DATA-TABLE - rows', data.features);
return (data?.features ?? []).map((feature) => {
return {
const featureInfo = {
ICON: (
<Box
component="img"
Expand Down Expand Up @@ -380,21 +382,33 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
),
...feature.fieldInfo,
};

return featureInfo;
}) as unknown as ColumnsType[];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.features, handleZoomIn]);

// Create the Material React Table
const useTable = useMaterialReactTable({
columns,
data: rows,
enableDensityToggle: true,
onDensityChange: setDensity,
onShowColumnFiltersChange: () => {
setShowColumnFilters(!showColumnFilters);
setColumnsFiltersVisibility(false, layerPath);
},
// NOTE: showGlobalFilter as true when layer change and we want to show global filter by default
initialState: { showColumnFilters: !!columnFilters.length, showGlobalFilter: true },
initialState: {
showColumnFilters: datatableSettings[layerPath].columnsFiltersVisibility,
showGlobalFilter: true,
columnVisibility: { geoviewID: false },
},
state: {
sorting,
columnFilters,
density,
showColumnFilters,
columnPinning: { left: ['ICON', 'ZOOM', 'DETAILS'] },
globalFilter,
},
Expand All @@ -407,27 +421,41 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
enableBottomToolbar: false,
positionToolbarAlertBanner: 'none', // hide existing row count
renderTopToolbar: ({ table }) => (
<Box display="flex" justifyContent="space-between" p={4}>
<Box>
<Box display="flex" sx={{ justifyContent: 'space-between', borderBottom: '1px solid #9e9e9e' }} p={4}>
<Box display="flex" sx={{ flexDirection: 'column', justifyContent: 'space-evenly' }}>
<Box sx={sxClasses.selectedRows}>{datatableSettings[layerPath].toolbarRowSelectedMessageRecord}</Box>
<Box display="flex">
<Box sx={sxClasses.selectedRows}>{t('dataTable.filterMap')}</Box>
<FilterMap layerPath={layerPath} isGlobalFilterOn={!!globalFilter?.length} />
</Box>
</Box>
<Box>
<Box>
<Box display="flex" sx={{ flexDirection: 'column' }}>
<Box sx={{ float: 'right', marginLeft: 'auto', maxWidth: '15rem' }}>
<MRTGlobalFilterTextField className="buttonOutline" table={table} />
</Box>
<Box display="flex" sx={{ justifyContent: 'space-around' }}>
<IconButton className="buttonOutline" color="primary" onClick={() => useTable.resetColumnFilters()}>
<Tooltip title={t('dataTable.clearFilters')} placement="bottom" arrow>
<ClearFiltersIcon />
</Tooltip>
</IconButton>

<MRTToggleFiltersButton className="buttonOutline" table={table} />
<FilterMap layerPath={layerPath} isGlobalFilterOn={!!globalFilter?.length} />
{/* enable column pinning options is override, so that pinning option in menu can be hide. */}
<MRTShowHideColumnsButton
className="buttonOutline"
table={{ ...table, options: { ...table.options, enableColumnPinning: false } }}
/>
<MRTToggleDensePaddingButton className="buttonOutline" table={table} />
<ExportButton rows={rows} columns={columns}>
<JSONExportButton features={data.features as TypeFeatureInfoEntry[]} layerPath={layerPath} />
{/* Only use filtered rows from material table */}
<ExportButton layerPath={layerPath} rows={useTable.getFilteredRowModel().rows.map((row) => row.original)} columns={columns}>
<JSONExportButton
rows={useTable.getFilteredRowModel().rows.map((row) => row.original)}
features={data.features as TypeFeatureInfoEntry[]}
layerPath={layerPath}
/>
</ExportButton>
</Box>
<Box sx={{ marginLeft: 'auto', maxWidth: '15rem', marginRight: '1rem' }}>
<MRTGlobalFilterTextField className="buttonOutline" table={table} />
</Box>
</Box>
</Box>
),
Expand All @@ -445,6 +473,9 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
muiTableHeadCellProps: {
sx: () => sxClasses.tableHeadCell,
},
muiTableHeadProps: {
sx: () => sxClasses.tableHead,
},
defaultColumn: {
muiFilterTextFieldProps: {
sx: () => ({
Expand Down Expand Up @@ -557,7 +588,7 @@ function DataTable({ data, layerPath, tableHeight = '500px' }: DataTableProps):
.filter((filterValue) => filterValue.length)
.join(' and ');
applyMapFilters(filterStrings);
}, 1000);
}, 500);

// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedColumnFilters = useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,30 @@ import { type MRT_ColumnDef as MRTColumnDef } from 'material-react-table';
import { IconButton, DownloadIcon, Tooltip, Menu, MenuItem } from '@/ui';
import { logger } from '@/core/utils/logger';
import { ColumnsType } from './data-table-types';
import { useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state';

interface ExportButtonProps {
layerPath: string;
rows: ColumnsType[];
columns: MRTColumnDef<ColumnsType>[];
children?: ReactElement | undefined;
}

/**
* Custom export button which will help to download data table data in csv format.
* @param {string} layerPath id of the layer
* @param {ColumnsType} rows list of rows to be displayed in data table
* @param {MRTColumnDef<ColumnsType>[]} columns array of object represent column header data.
* @param {ReactElement} children Menu item to be rendered in Menu.
* @returns {JSX.Element} returns export button
*
*/
function ExportButton({ rows, columns, children }: ExportButtonProps): JSX.Element {
function ExportButton({ layerPath, rows, columns, children }: ExportButtonProps): JSX.Element {
// Log
logger.logTraceRender('components/data-table/export-button');

const { getLayer } = useLayerStoreActions();

const { t } = useTranslation<string>();
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
Expand Down Expand Up @@ -61,16 +66,20 @@ function ExportButton({ rows, columns, children }: ExportButtonProps): JSX.Eleme
// Log
logger.logTraceUseMemo('DATA-TABLE - EXPORT BUTTON - getCsvOptions', columns);

// Remove the utility columns
const filteredColumns = columns.filter((col) => !['ICON', 'ZOOM', 'DETAILS', 'geoviewID'].includes(col.id as string));

return (): Options => ({
filename: `table-${getLayer(layerPath)?.layerName.replaceAll(' ', '-')}`,
fieldSeparator: ',',
quoteStrings: '"',
decimalSeparator: '.',
showLabels: true,
useBom: true,
useKeysAsHeaders: false,
headers: columns.map((c) => c.id as string),
headers: filteredColumns.map((c) => c.id as string),
});
}, [columns]);
}, [columns, getLayer, layerPath]);

/**
* Export data table in csv format.
Expand Down
Loading

0 comments on commit 0a37a0a

Please sign in to comment.