mixnode datagrid performant
This commit is contained in:
@@ -17,6 +17,8 @@ export const CustomColumnHeading: React.FC<{ headingTitle: string }> = ({
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
padding: 0,
|
||||
// border: '1px solid red',
|
||||
// minWidth: 300,
|
||||
}}
|
||||
data-testid={headingTitle}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import * as React from 'react';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import {
|
||||
DataGrid,
|
||||
GridColDef,
|
||||
GridColumns,
|
||||
GridRowModel,
|
||||
GridSortModel,
|
||||
useGridApiContext,
|
||||
useGridState,
|
||||
} from '@mui/x-data-grid';
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { LinearProgress } from '@mui/material';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
},
|
||||
});
|
||||
|
||||
export const cellStyles: SxProps = {
|
||||
width: '100%',
|
||||
padding: 0,
|
||||
maxHeight: 100,
|
||||
color: 'inherit',
|
||||
textDecoration: 'none',
|
||||
fontWeight: 400,
|
||||
fontSize: 12,
|
||||
lineHeight: 2,
|
||||
textAlign: 'start',
|
||||
wordBreak: 'break-word',
|
||||
whiteSpace: 'break-spaces',
|
||||
};
|
||||
|
||||
function CustomPagination() {
|
||||
const apiRef = useGridApiContext();
|
||||
const [state] = useGridState(apiRef);
|
||||
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Pagination
|
||||
className={classes.root}
|
||||
sx={{ mt: 2 }}
|
||||
color="primary"
|
||||
count={state.pagination.pageCount}
|
||||
page={state.pagination.page + 1}
|
||||
onChange={(event, value) => apiRef.current.setPage(value - 1)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
type DataGridProps = {
|
||||
columns: GridColDef[];
|
||||
pagination?: boolean;
|
||||
hideFooter?: boolean | undefined;
|
||||
pageSize?: string | undefined;
|
||||
rows: {
|
||||
id: number | null;
|
||||
lastName: string | null;
|
||||
firstName: string | null;
|
||||
age: number | null;
|
||||
}[];
|
||||
loading?: boolean;
|
||||
};
|
||||
export const NewniversalDataGrid: React.FC<DataGridProps> = ({
|
||||
rows,
|
||||
columns,
|
||||
loading,
|
||||
pagination,
|
||||
hideFooter,
|
||||
pageSize,
|
||||
}) => {
|
||||
if (loading) return <LinearProgress />;
|
||||
if (!loading)
|
||||
return (
|
||||
<DataGrid
|
||||
pagination={pagination ? true : undefined}
|
||||
rows={rows}
|
||||
components={{
|
||||
Pagination: CustomPagination,
|
||||
}}
|
||||
columns={columns}
|
||||
pageSize={Number(pageSize)}
|
||||
rowsPerPageOptions={[5]}
|
||||
disableSelectionOnClick
|
||||
autoHeight
|
||||
hideFooter={hideFooter}
|
||||
style={{
|
||||
width: '100%',
|
||||
border: 'none',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return null;
|
||||
};
|
||||
|
||||
NewniversalDataGrid.defaultProps = {
|
||||
loading: false,
|
||||
pagination: false,
|
||||
hideFooter: true,
|
||||
pageSize: '10',
|
||||
// sortModel: undefined,
|
||||
};
|
||||
@@ -25,7 +25,7 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
width: '100%',
|
||||
marginBottom: 2,
|
||||
display: 'flex',
|
||||
flexDirection: matches ? 'column' : 'row',
|
||||
flexDirection: matches ? 'column-reverse' : 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
@@ -35,8 +35,8 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
value={pageSize}
|
||||
onChange={onChangePageSize}
|
||||
sx={{
|
||||
width: 200,
|
||||
marginBottom: matches ? 2 : 0,
|
||||
width: matches ? 100 : 200,
|
||||
// marginBottom: matches ? 2 : 0,
|
||||
}}
|
||||
>
|
||||
<MenuItem value={10} data-testid="ten">
|
||||
@@ -53,7 +53,7 @@ export const TableToolbar: React.FC<TableToolBarProps> = ({
|
||||
</MenuItem>
|
||||
</Select>
|
||||
<TextField
|
||||
sx={{ width: 350 }}
|
||||
sx={{ width: matches ? '100%' : 350, marginBottom: matches ? 2 : 0 }}
|
||||
value={searchTerm}
|
||||
data-testid="search-box"
|
||||
placeholder="search"
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import * as React from 'react';
|
||||
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
|
||||
import { printableCoin } from '@nymproject/nym-validator-client';
|
||||
import { Button, Grid, Link as MuiLink, Card } from '@mui/material';
|
||||
import { Link as RRDLink } from 'react-router-dom';
|
||||
import { Button, Grid, Link as MuiLink } from '@mui/material';
|
||||
import { SelectChangeEvent } from '@mui/material/Select';
|
||||
import {
|
||||
cellStyles,
|
||||
UniversalDataGrid,
|
||||
} from 'src/components/Universal-DataGrid';
|
||||
import { useMainContext } from 'src/context/main';
|
||||
import { mixnodeToGridRow } from 'src/utils';
|
||||
import { TableToolbar } from 'src/components/TableToolbar';
|
||||
import { MixNodeResponse } from 'src/typeDefs/explorer-api';
|
||||
import { BIG_DIPPER } from 'src/api/constants';
|
||||
import { ContentCard } from 'src/components/ContentCard';
|
||||
import { CustomColumnHeading } from 'src/components/CustomColumnHeading';
|
||||
import { Title } from 'src/components/Title';
|
||||
import {
|
||||
NewniversalDataGrid,
|
||||
cellStyles,
|
||||
} from 'src/components/Newniversal-DataGrid';
|
||||
|
||||
export const PageMixnodes: React.FC = () => {
|
||||
const { mixnodes } = useMainContext();
|
||||
@@ -51,8 +50,9 @@ export const PageMixnodes: React.FC = () => {
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: 'owner',
|
||||
headerName: 'Owner',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Owner" />,
|
||||
flex: 3,
|
||||
width: 380,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
@@ -68,10 +68,10 @@ export const PageMixnodes: React.FC = () => {
|
||||
},
|
||||
{
|
||||
field: 'identity_key',
|
||||
headerName: 'Identity Key',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Identity Key" />,
|
||||
flex: 3,
|
||||
width: 380,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={cellStyles}
|
||||
@@ -86,11 +86,11 @@ export const PageMixnodes: React.FC = () => {
|
||||
{
|
||||
field: 'bond',
|
||||
headerName: 'Bond',
|
||||
type: 'number',
|
||||
headerAlign: 'left',
|
||||
flex: 1,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Bond" />,
|
||||
type: 'number',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 150,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => {
|
||||
const bondAsPunk = printableCoin({
|
||||
amount: params.value as string,
|
||||
@@ -107,44 +107,11 @@ export const PageMixnodes: React.FC = () => {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'self_percentage',
|
||||
headerName: 'Self %',
|
||||
headerAlign: 'left',
|
||||
type: 'number',
|
||||
width: 99,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Self %" />,
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={cellStyles}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnodes/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}%
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'host',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Host" />,
|
||||
flex: 1,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={cellStyles}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnodes/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'location',
|
||||
headerName: 'Location',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Location" />,
|
||||
flex: 1,
|
||||
width: 150,
|
||||
headerAlign: 'left',
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
@@ -157,12 +124,47 @@ export const PageMixnodes: React.FC = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'layer',
|
||||
headerAlign: 'left',
|
||||
field: 'self_percentage',
|
||||
headerName: 'Self %',
|
||||
width: 110,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Layer" />,
|
||||
flex: 1,
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Self %" />,
|
||||
type: 'number',
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={cellStyles}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnodes/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}%
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'host',
|
||||
headerName: 'Host',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Host" />,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 110,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={cellStyles}
|
||||
component={RRDLink}
|
||||
to={`/network-components/mixnodes/${params.row.identity_key}`}
|
||||
>
|
||||
{params.value}
|
||||
</MuiLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'layer',
|
||||
headerName: 'Layer',
|
||||
renderHeader: () => <CustomColumnHeading headingTitle="Layer" />,
|
||||
headerClassName: 'MuiDataGrid-header-override',
|
||||
width: 110,
|
||||
headerAlign: 'left',
|
||||
renderCell: (params: GridRenderCellParams) => (
|
||||
<MuiLink
|
||||
sx={{ ...cellStyles, textAlign: 'left' }}
|
||||
@@ -182,30 +184,29 @@ export const PageMixnodes: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Title text="Mixnodes" />
|
||||
<Grid>
|
||||
<Grid item>
|
||||
<ContentCard>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<Card
|
||||
sx={{
|
||||
padding: 2,
|
||||
height: '100%',
|
||||
// border: '1px solid blue',
|
||||
}}
|
||||
>
|
||||
<TableToolbar
|
||||
onChangeSearch={handleSearch}
|
||||
onChangePageSize={handlePageSize}
|
||||
pageSize={pageSize}
|
||||
searchTerm={searchTerm}
|
||||
/>
|
||||
<UniversalDataGrid
|
||||
loading={mixnodes?.isLoading}
|
||||
columnsData={columns}
|
||||
rows={mixnodeToGridRow(filteredMixnodes)}
|
||||
pageSize={pageSize}
|
||||
<NewniversalDataGrid
|
||||
pagination
|
||||
rows={mixnodeToGridRow(filteredMixnodes)}
|
||||
columns={columns}
|
||||
hideFooter={false}
|
||||
sortModel={[
|
||||
{
|
||||
field: 'bond',
|
||||
sort: 'desc',
|
||||
},
|
||||
]}
|
||||
pageSize={pageSize}
|
||||
/>
|
||||
</ContentCard>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
the theme declaration in index.tsx or the style prop
|
||||
in <DataGrid /> */
|
||||
|
||||
.MuiDataGrid-sortIcon {
|
||||
.MuiDataGrid-sortIcon, .MuiDataGrid-menuIcon {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ export function countryDataToGridRow(
|
||||
return sorted;
|
||||
}
|
||||
|
||||
export function mixnodeToGridRow(
|
||||
arrayOfMixnodes: MixNodeResponse,
|
||||
): MixnodeRowType[] {
|
||||
export function mixnodeToGridRow(arrayOfMixnodes: MixNodeResponse): any {
|
||||
return !arrayOfMixnodes
|
||||
? []
|
||||
: arrayOfMixnodes.map((mn) => {
|
||||
@@ -75,16 +73,15 @@ export function mixnodeToGridRow(
|
||||
const delegations = Number(mn.total_delegation.amount) || 0;
|
||||
const totalBond = pledge + delegations;
|
||||
const selfPercentage = ((pledge * 100) / totalBond).toFixed(2);
|
||||
|
||||
return {
|
||||
id: mn.owner,
|
||||
owner: mn.owner,
|
||||
location: mn?.location?.country_name || '',
|
||||
identity_key: mn.mix_node.identity_key || '',
|
||||
bond: totalBond || 0,
|
||||
location: mn?.location?.country_name || '',
|
||||
self_percentage: selfPercentage,
|
||||
host: mn.mix_node.host || '',
|
||||
layer: mn.layer || '',
|
||||
host: mn?.mix_node?.host || '',
|
||||
layer: mn?.layer || '',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user