Skip to content

Commit

Permalink
Merge pull request #1475 from kaminderpal/1462-responsive-datatable
Browse files Browse the repository at this point in the history
fix(datatable): responsive datatable  Closes #1462 (#1475)
  • Loading branch information
jolevesq authored Nov 9, 2023
2 parents 2399da3 + 3f306e9 commit 78f18ce
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 71 deletions.
3 changes: 2 additions & 1 deletion packages/geoview-core/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"reduceBtn": "Reduce",
"features": "feature(s)",
"featureFiltered": "features filtered",
"images": "Images"
"images": "Images",
"close": "Close"
}
}
3 changes: 2 additions & 1 deletion packages/geoview-core/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"reduceBtn": "Réduire",
"features": "Item(s)",
"featureFiltered": "Item filtrée(s)",
"images": "Images"
"images": "Images",
"close": "Fermer"
}
}
162 changes: 103 additions & 59 deletions packages/geoview-core/src/core/components/data-table/data-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useTheme } from '@mui/material/styles';
import { Projection } from 'ol/proj';
import { useTranslation } from 'react-i18next';
import {
Box,
Grid,
Typography,
Paper,
List,
Expand All @@ -25,6 +24,7 @@ import MapDataTable, { MapDataTableData as MapDataTableDataProps } from './map-d
import { getSxClasses } from './data-table-style';
import { GroupLayers } from './data-table-api';
import { TypeDisplayLanguage, TypeLocalizedString } from '@/geo/map/map-schema-types';
import { DataTableGrid } from './data-table-grid';
import {
useDataTableStoreActions,
useDataTableStoreIsEnlargeDataTable,
Expand All @@ -51,9 +51,11 @@ interface DatapanelProps {
export function Datapanel({ layerData, mapId, projectionConfig, language }: DatapanelProps) {
const { t } = useTranslation();
const theme = useTheme();

const sxClasses = getSxClasses(theme);

const [isLoading, setIsLoading] = useState(false);
const [isLayersPanelVisible, setIsLayersPanelVisible] = useState(false);

const selectedLayerIndex = useDataTableStoreSelectedLayerIndex();
const isEnlargeDataTable = useDataTableStoreIsEnlargeDataTable();
Expand All @@ -64,6 +66,7 @@ export function Datapanel({ layerData, mapId, projectionConfig, language }: Data
const handleListItemClick = useCallback((event: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
setSelectedLayerIndex(index);
setIsLoading(true);
setIsLayersPanelVisible(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down Expand Up @@ -115,49 +118,52 @@ export function Datapanel({ layerData, mapId, projectionConfig, language }: Data
sx={{ ...sxClasses.paper, border: selectedLayerIndex === index ? sxClasses.borderWithIndex : sxClasses.borderNone }}
key={layerKey}
>
<ListItem disablePadding>
<ListItemButton
sx={{ height: '67px' }}
selected={selectedLayerIndex === index}
onClick={(event) => handleListItemClick(event, index)}
>
<ListItemIcon>
<SendIcon sx={{ width: '0.75em', height: '0.75em' }} />
</ListItemIcon>
<Tooltip title={getLayerTooltip(layerName!, layerKey, index)} placement="top" arrow>
<Box sx={sxClasses.listPrimaryText}>
<Typography component="p">{layerName![language]}</Typography>
<Box sx={{ display: 'flex', alignContent: 'center' }}>
<Typography component="p" variant="subtitle1" noWrap>
{getFeaturesOfLayer(layerKey, index)}
</Typography>
{isMapFilteredSelectedForLayer(layerKey) && <FilterAltIcon sx={{ color: theme.palette.grey['500'] }} />}
</Box>
</Box>
</Tooltip>
<Box
sx={{
padding: isEnlargeDataTable ? '0.25rem' : '1rem',
paddingRight: isEnlargeDataTable ? '0.25rem' : '1rem',
[theme.breakpoints.down('xl')]: {
display: isEnlargeDataTable ? 'none !important' : 'block',
},
[theme.breakpoints.down('sm')]: {
display: 'none',
},
}}
>
<IconButton
disabled
edge="end"
size="small"
sx={{ color: `${theme.palette.primary.main} !important`, background: `${theme.palette.grey.A100} !important` }}
<Tooltip title={getLayerTooltip(layerName!, layerKey, index)} placement="top" arrow>
<Box>
<ListItem disablePadding>
<ListItemButton
sx={{ height: '67px' }}
selected={selectedLayerIndex === index}
onClick={(event) => handleListItemClick(event, index)}
>
<ChevronRightIcon />
</IconButton>
</Box>
</ListItemButton>
</ListItem>
<ListItemIcon>
<SendIcon sx={{ width: '0.75em', height: '0.75em' }} />
</ListItemIcon>
<Box sx={sxClasses.listPrimaryText}>
<Typography component="p">{layerName![language]}</Typography>
<Box sx={{ display: 'flex', alignContent: 'center' }}>
<Typography component="p" variant="subtitle1" noWrap>
{getFeaturesOfLayer(layerKey, index)}
</Typography>
{isMapFilteredSelectedForLayer(layerKey) && <FilterAltIcon sx={{ color: theme.palette.grey['500'] }} />}
</Box>
</Box>

<Box
sx={{
padding: isEnlargeDataTable ? '0.25rem' : '1rem',
paddingRight: isEnlargeDataTable ? '0.25rem' : '1rem',
[theme.breakpoints.down('xl')]: {
display: isEnlargeDataTable ? 'none !important' : 'block',
},
[theme.breakpoints.down('sm')]: {
display: 'none',
},
}}
>
<IconButton
disabled
edge="end"
size="small"
sx={{ color: `${theme.palette.primary.main} !important`, background: `${theme.palette.grey.A100} !important` }}
>
<ChevronRightIcon />
</IconButton>
</Box>
</ListItemButton>
</ListItem>
</Box>
</Tooltip>
</Paper>
))}
</List>
Expand All @@ -176,25 +182,63 @@ export function Datapanel({ layerData, mapId, projectionConfig, language }: Data

return (
<Box sx={sxClasses.dataPanel}>
<Grid container spacing={2} sx={sxClasses.gridContainer}>
<Grid item xs={3}>
<DataTableGrid.Root spacing={2} sx={sxClasses.gridContainer}>
<DataTableGrid.Left xs={isLayersPanelVisible ? 12 : 0} md={3} isLayersPanelVisible={isLayersPanelVisible}>
<Typography component="p" sx={sxClasses.headline}>
{t('dataTable.leftPanelHeading')}
</Typography>
</Grid>

<Grid item xs={9} sx={{ display: 'flex', justifyContent: 'right' }}>
<Button type="text" size="small" sx={sxClasses.enlargeBtn} onClick={() => setIsEnlargeDataTable(!isEnlargeDataTable)}>
</DataTableGrid.Left>
<DataTableGrid.Right
xs={!isLayersPanelVisible ? 12 : 0}
md={9}
sx={{ display: 'flex', justifyContent: 'right' }}
isLayersPanelVisible={isLayersPanelVisible}
>
<Button
type="text"
size="small"
sx={{ ...sxClasses.enlargeBtn, [theme.breakpoints.down('md')]: { display: 'none' } }}
onClick={() => setIsEnlargeDataTable(!isEnlargeDataTable)}
tooltip={isEnlargeDataTable ? t('dataTable.reduceBtn')! : t('dataTable.enlargeBtn')!}
tooltipPlacement="top"
>
{isEnlargeDataTable ? <ArrowForwardIcon sx={sxClasses.enlargeBtnIcon} /> : <ArrowBackIcon sx={sxClasses.enlargeBtnIcon} />}
{isEnlargeDataTable ? t('dataTable.reduceBtn') : t('dataTable.enlargeBtn')}
</Button>
</Grid>
</Grid>
<Grid container sx={{ marginTop: '0.75rem' }}>
<Grid item xs={!isEnlargeDataTable ? 4 : 1.25}>
{!isLoading && (
<Button
type="text"
size="small"
sx={{
...sxClasses.enlargeBtn,
marginLeft: '1rem',
[theme.breakpoints.up('md')]: { display: 'none' },
[theme.breakpoints.between('sm', 'md')]: { display: !isLayersPanelVisible ? 'block' : 'none' },
[theme.breakpoints.down('md')]: { display: !isLayersPanelVisible ? 'block' : 'none' },
}}
onClick={() => setIsLayersPanelVisible(true)}
tooltip={t('dataTable.close') ?? ''}
tooltipPlacement="top"
>
{t('dataTable.close')}
</Button>
)}
</DataTableGrid.Right>
</DataTableGrid.Root>

<DataTableGrid.Root sx={{ marginTop: '0.75rem' }}>
<DataTableGrid.Left
isLayersPanelVisible={isLayersPanelVisible}
xs={isLayersPanelVisible ? 12 : 0}
md={!isEnlargeDataTable ? 4 : 1.25}
>
{renderList()}
</Grid>
<Grid item xs={!isEnlargeDataTable ? 8 : 10.75} sx={{ paddingLeft: '1rem', position: 'relative' }}>
</DataTableGrid.Left>
<DataTableGrid.Right
xs={!isLayersPanelVisible ? 12 : 0}
md={!isEnlargeDataTable ? 8 : 10.75}
isLayersPanelVisible={isLayersPanelVisible}
>
<CircularProgress
isLoaded={!isLoading}
sx={{
Expand All @@ -204,7 +248,7 @@ export function Datapanel({ layerData, mapId, projectionConfig, language }: Data

{!isLoading &&
layerData.map(({ layerKey, layerId }, index) => (
<Box key={layerKey} sx={{ paddingLeft: '3.5rem' }}>
<Box key={layerKey} sx={{ [theme.breakpoints.up('lg')]: { paddingLeft: '3.5rem' } }}>
{index === selectedLayerIndex ? (
<Box>
{layerData[index].features.length ? (
Expand All @@ -224,8 +268,8 @@ export function Datapanel({ layerData, mapId, projectionConfig, language }: Data
)}
</Box>
))}
</Grid>
</Grid>
</DataTableGrid.Right>
</DataTableGrid.Root>
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { ReactNode } from 'react';
import { GridProps } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { Grid } from '@/ui';

interface DataTableGridProps extends GridProps {
children: ReactNode;
}

interface DataTableGridPanelProps extends GridProps {
children: ReactNode;
isLayersPanelVisible: boolean;
}

/**
* Create Grid Container
* @param {ReactNode} children children to be renderer
* @returns JSX.Element
*/
function DataTableGridRoot({ children, ...rest }: DataTableGridProps) {
return (
<Grid container {...rest}>
{children}
</Grid>
);
}

/**
* Create Left Panel for Data table grid.
* @param {ReactNode} children child elements to be rendered
* @param {boolean} isLayersPanelVisible panel visibility
* @returns JSX.Element
*/
function DataTableGridLeftPanel({ children, isLayersPanelVisible = false, ...rest }: DataTableGridPanelProps) {
const theme = useTheme();

return (
<Grid
item
sx={{
[theme.breakpoints.down('md')]: { display: isLayersPanelVisible ? 'block' : 'none' },
}}
{...rest}
>
{children}
</Grid>
);
}

/**
* Create Right Panel for Data table grid.
* @param {ReactNode} children child elements to be rendered
* @param {boolean} isLayersPanelVisible panel visibility
* @returns JSX.Element
*/
function DataTableGridRightPanel({ children, isLayersPanelVisible = false, ...rest }: DataTableGridPanelProps) {
const theme = useTheme();
return (
<Grid
item
sx={{
position: 'relative',
[theme.breakpoints.up('md')]: { paddingLeft: '1rem' },
[theme.breakpoints.down('md')]: { display: !isLayersPanelVisible ? 'block' : 'none', minHeight: '250px' },
}}
{...rest}
>
{children}
</Grid>
);
}

export const DataTableGrid = {
Root: DataTableGridRoot,
Left: DataTableGridLeftPanel,
Right: DataTableGridRightPanel,
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
MaterialReactTable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactElement } from 'react';
import { ReactElement, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ExportToCsv } from 'export-to-csv';
import { type MRT_ColumnDef as MRTColumnDef } from 'material-react-table';
Expand All @@ -22,7 +22,7 @@ interface ExportButtonProps {
*/
function ExportButton({ rows, columns, children }: ExportButtonProps): JSX.Element {
const { t } = useTranslation<string>();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Switch, useTheme } from '@mui/material';
import { Switch } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { Tooltip } from '@/ui';
import { getSxClasses } from './data-table-style';
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { toLonLat, Projection } from 'ol/proj';
import { Geometry, Point, Polygon, LineString, MultiPoint } from 'ol/geom';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useRef, useState, memo, ReactNode } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState, memo, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import debounce from 'lodash/debounce';
import startCase from 'lodash/startCase';
Expand Down Expand Up @@ -26,7 +26,8 @@ import {
} from 'material-react-table';
import { Projection } from 'ol/proj';
import { Extent } from 'ol/extent';
import { darken, useTheme } from '@mui/material';
import { darken } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { difference } from 'lodash';
import { getUid } from 'ol/util';
import { Box, Button, IconButton, Tooltip, ZoomInSearchIcon } from '@/ui';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ export const getSxClasses = (theme: Theme) => ({
fontSize: 16,
noWrap: true,
marginLeft: 20,
}
}
},
},
});

0 comments on commit 78f18ce

Please sign in to comment.