feat(ui): Update Profiler components for improved styling and functionality

This commit is contained in:
Shailesh Parmar 2025-09-22 20:45:33 +05:30
parent 3132d61efc
commit d4683a2e91
6 changed files with 162 additions and 95 deletions

View File

@ -43,9 +43,3 @@
border-bottom: none; border-bottom: none;
} }
} }
.profiler-latest-value {
.ant-statistic-title {
margin-bottom: 0px;
}
}

View File

@ -42,6 +42,7 @@ export interface ProfilerDetailsCardProps {
isLoading?: boolean; isLoading?: boolean;
noDataPlaceholderText?: ReactNode; noDataPlaceholderText?: ReactNode;
children?: ReactNode; children?: ReactNode;
chartType?: 'line' | 'area';
} }
export enum TableProfilerTab { export enum TableProfilerTab {
@ -78,6 +79,7 @@ export interface ProfilerLatestValueProps {
information: MetricChartType['information']; information: MetricChartType['information'];
tickFormatter?: string; tickFormatter?: string;
stringValue?: boolean; stringValue?: boolean;
onClick?: (dataKey: string) => void;
} }
export type TestCaseAction = { export type TestCaseAction = {

View File

@ -11,15 +11,21 @@
* limitations under the License. * limitations under the License.
*/ */
import { Card, Col, Row, Typography } from 'antd';
import React, { useMemo, useState } from 'react';
import { import {
Box,
Card,
Skeleton,
Stack,
Typography,
useTheme,
} from '@mui/material';
import React, { Fragment, useMemo, useState } from 'react';
import {
Area,
Brush, Brush,
CartesianGrid, CartesianGrid,
Legend, ComposedChart,
LegendProps,
Line, Line,
LineChart,
ResponsiveContainer, ResponsiveContainer,
Tooltip, Tooltip,
XAxis, XAxis,
@ -47,7 +53,9 @@ const ProfilerDetailsCard: React.FC<ProfilerDetailsCardProps> = ({
title, title,
isLoading, isLoading,
noDataPlaceholderText, noDataPlaceholderText,
chartType = 'line',
}: ProfilerDetailsCardProps) => { }: ProfilerDetailsCardProps) => {
const theme = useTheme();
const { data, information } = chartCollection; const { data, information } = chartCollection;
const [activeKeys, setActiveKeys] = useState<string[]>([]); const [activeKeys, setActiveKeys] = useState<string[]>([]);
const { showBrush, endIndex } = useMemo(() => { const { showBrush, endIndex } = useMemo(() => {
@ -57,38 +65,60 @@ const ProfilerDetailsCard: React.FC<ProfilerDetailsCardProps> = ({
}; };
}, [data]); }, [data]);
const handleClick: LegendProps['onClick'] = (event) => { const handleClick = (dataKey: string) => {
setActiveKeys((prevActiveKeys) => setActiveKeys((prevActiveKeys) =>
updateActiveChartFilter(event.dataKey, prevActiveKeys) updateActiveChartFilter(dataKey, prevActiveKeys)
); );
}; };
if (isLoading) {
return <Skeleton height={380} variant="rounded" width="100%" />;
}
return ( return (
<Card <Box>
className="shadow-none global-border-radius" {title && (
data-testid="profiler-details-card-container" <Typography
loading={isLoading}> sx={{
<Row gutter={[16, 16]}> fontSize: '16px',
{title && ( color: theme.palette.grey[900],
<Col span={24}> fontWeight: theme.typography.fontWeightBold,
<Typography.Title level={5}>{title}</Typography.Title> mb: 3,
</Col> }}
)} variant="h6">
<Col span={4}> {title}
</Typography>
)}
<Card
data-testid="profiler-details-card-container"
sx={{
p: 4,
borderRadius: '10px',
border: `1px solid ${theme.palette.grey[200]}`,
boxShadow: 'none',
}}>
<Stack spacing={4}>
<ProfilerLatestValue <ProfilerLatestValue
information={information} information={information}
tickFormatter={tickFormatter} tickFormatter={tickFormatter}
onClick={handleClick}
/> />
</Col>
<Col span={20}>
{data.length > 0 ? ( {data.length > 0 ? (
<ResponsiveContainer <ResponsiveContainer
className="custom-legend" className="custom-legend"
debounce={200} debounce={200}
id={`${name}_graph`} id={`${name}_graph`}
minHeight={300}> minHeight={300}>
<LineChart className="w-full" data={data} margin={{ left: 16 }}> <ComposedChart
<CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} /> className="w-full"
data={data}
margin={{ left: 16 }}>
<CartesianGrid
stroke={GRAPH_BACKGROUND_COLOR}
strokeDasharray="3 3"
vertical={false}
/>
<XAxis <XAxis
dataKey="name" dataKey="name"
padding={{ left: 16, right: 16 }} padding={{ left: 16, right: 16 }}
@ -116,20 +146,37 @@ const ProfilerDetailsCard: React.FC<ProfilerDetailsCardProps> = ({
} }
/> />
{information.map((info) => ( {information.map((info) => (
<Line <Fragment key={info.dataKey}>
dataKey={info.dataKey} {chartType === 'area' && (
hide={ <Area
activeKeys.length dataKey={info.dataKey}
? !activeKeys.includes(info.dataKey) fill={info.color}
: false fillOpacity={0.1}
} hide={
key={info.dataKey} activeKeys.length
name={info.title} ? !activeKeys.includes(info.dataKey)
stroke={info.color} : false
type={curveType ?? 'monotone'} }
/> key={info.dataKey}
name={info.title}
stroke={info.color}
type={curveType ?? 'monotone'}
/>
)}
<Line
dataKey={info.dataKey}
hide={
activeKeys.length
? !activeKeys.includes(info.dataKey)
: false
}
key={info.dataKey}
name={info.title}
stroke={info.color}
type={curveType ?? 'monotone'}
/>
</Fragment>
))} ))}
<Legend onClick={handleClick} />
{showBrush && ( {showBrush && (
<Brush <Brush
data={data} data={data}
@ -139,21 +186,17 @@ const ProfilerDetailsCard: React.FC<ProfilerDetailsCardProps> = ({
padding={{ left: 16, right: 16 }} padding={{ left: 16, right: 16 }}
/> />
)} )}
</LineChart> </ComposedChart>
</ResponsiveContainer> </ResponsiveContainer>
) : ( ) : (
<Row align="middle" className="h-full w-full" justify="center"> <ErrorPlaceHolder
<Col> className="mt-0-important"
<ErrorPlaceHolder placeholderText={noDataPlaceholderText}
className="mt-0-important" />
placeholderText={noDataPlaceholderText}
/>
</Col>
</Row>
)} )}
</Col> </Stack>
</Row> </Card>
</Card> </Box>
); );
}; };

View File

@ -11,7 +11,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Space, Statistic, Typography } from 'antd'; import { Box, Stack, Typography, useTheme } from '@mui/material';
import { isUndefined } from 'lodash'; import { isUndefined } from 'lodash';
import { getStatisticsDisplayValue } from '../../../../utils/CommonUtils'; import { getStatisticsDisplayValue } from '../../../../utils/CommonUtils';
import '../ProfilerDashboard/profiler-dashboard.less'; import '../ProfilerDashboard/profiler-dashboard.less';
@ -21,7 +21,10 @@ const ProfilerLatestValue = ({
information, information,
tickFormatter, tickFormatter,
stringValue = false, stringValue = false,
onClick,
}: ProfilerLatestValueProps) => { }: ProfilerLatestValueProps) => {
const theme = useTheme();
const getLatestValue = (value?: number | string) => { const getLatestValue = (value?: number | string) => {
if (isUndefined(value)) { if (isUndefined(value)) {
return '--'; return '--';
@ -35,23 +38,50 @@ const ProfilerLatestValue = ({
}; };
return ( return (
<Space data-testid="data-summary-container" direction="vertical" size={16}> <Stack
data-testid="data-summary-container"
direction="row"
spacing={4}
sx={{
width: '100%',
backgroundColor: theme.palette.grey[50],
borderRadius: '10px',
p: '16px 30px',
}}>
{information.map((info) => ( {information.map((info) => (
<Statistic <Box
className="profiler-latest-value"
key={info.title} key={info.title}
title={ sx={{
<Typography.Text cursor: onClick ? 'pointer' : 'default',
className="text-grey-body break-all" }}
data-testid="title"> onClick={() => onClick?.(info.dataKey)}>
{info.title} <Typography
</Typography.Text> className="break-all"
} data-testid="title"
value={getLatestValue(info.latestValue)} sx={{
valueStyle={{ color: info.color, fontSize: '18px', fontWeight: 700 }} color: theme.palette.grey[700],
/> fontSize: '12px',
fontWeight: theme.typography.fontWeightBold,
borderLeft: `4px solid ${info.color}`,
paddingLeft: '8px',
lineHeight: '12px',
mb: 1,
}}>
{info.title}
</Typography>
<Typography
className="break-all"
data-testid="value"
sx={{
color: theme.palette.grey[900],
fontSize: '18px',
fontWeight: 700,
}}>
{getLatestValue(info.latestValue)}
</Typography>
</Box>
))} ))}
</Space> </Stack>
); );
}; };

View File

@ -11,8 +11,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Grid, Stack } from '@mui/material'; import { Box, Grid, Stack } from '@mui/material';
import { Col } from 'antd';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { pick } from 'lodash'; import { pick } from 'lodash';
import { DateRangeObject } from 'Models'; import { DateRangeObject } from 'Models';
@ -220,50 +219,49 @@ const TableProfilerChart = ({
{showHeader && ( {showHeader && (
<> <>
{!isSummaryLoading && !isProfilingEnabled && ( {!isSummaryLoading && !isProfilingEnabled && (
<Col span={24}> <Box>
<NoProfilerBanner /> <NoProfilerBanner />
</Col> </Box>
)} )}
<Col span={24}>
<Grid container spacing={5}> <Grid container spacing={5}>
{overallSummary?.map((summary) => ( {overallSummary?.map((summary) => (
<Grid key={summary.title} size="grow"> <Grid key={summary.title} size="grow">
<SummaryCardV1 <SummaryCardV1
extra={summary.extra} extra={summary.extra}
icon={summary.icon} icon={summary.icon}
isLoading={isSummaryLoading} isLoading={isSummaryLoading}
title={summary.title} title={summary.title}
value={summary.value} value={summary.value}
/> />
</Grid> </Grid>
))} ))}
</Grid> </Grid>
</Col>
</> </>
)} )}
<Col data-testid="row-metrics" span={24}> <Box data-testid="row-metrics">
<ProfilerDetailsCard <ProfilerDetailsCard
chartCollection={rowCountMetrics} chartCollection={rowCountMetrics}
curveType="stepAfter" chartType="area"
isLoading={isTableProfilerLoading} isLoading={isTableProfilerLoading}
name="rowCount" name="rowCount"
noDataPlaceholderText={noProfilerMessage} noDataPlaceholderText={noProfilerMessage}
title={t('label.data-volume')} title={t('label.data-volume')}
/> />
</Col> </Box>
{showSystemMetrics && ( {showSystemMetrics && (
<> <>
<Col span={24}>{operationDateMetricsCard}</Col> <Box>{operationDateMetricsCard}</Box>
<Col span={24}>{operationMetricsCard}</Col> <Box>{operationMetricsCard}</Box>
</> </>
)} )}
<Col span={24}> <Box>
<CustomMetricGraphs <CustomMetricGraphs
customMetrics={customMetrics} customMetrics={customMetrics}
customMetricsGraphData={tableCustomMetricsProfiling} customMetricsGraphData={tableCustomMetricsProfiling}
isLoading={isTableProfilerLoading || isSummaryLoading} isLoading={isTableProfilerLoading || isSummaryLoading}
/> />
</Col> </Box>
</Stack> </Stack>
); );
}; };

View File

@ -27,7 +27,7 @@ export const TEXT_BODY_COLOR = '#37352F';
export const TEXT_GREY_MUTED = '#757575'; export const TEXT_GREY_MUTED = '#757575';
export const SUCCESS_COLOR = '#008376'; export const SUCCESS_COLOR = '#008376';
export const DE_ACTIVE_COLOR = '#6B7280'; export const DE_ACTIVE_COLOR = '#6B7280';
export const GRAPH_BACKGROUND_COLOR = '#f5f5f5'; export const GRAPH_BACKGROUND_COLOR = '#E9EAEB';
export const GRAYED_OUT_COLOR = '#959595'; export const GRAYED_OUT_COLOR = '#959595';
export const BORDER_COLOR = '#0000001a'; export const BORDER_COLOR = '#0000001a';
export const BLACK_COLOR = '#000000'; export const BLACK_COLOR = '#000000';