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;
}
}
.profiler-latest-value {
.ant-statistic-title {
margin-bottom: 0px;
}
}

View File

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

View File

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

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Space, Statistic, Typography } from 'antd';
import { Box, Stack, Typography, useTheme } from '@mui/material';
import { isUndefined } from 'lodash';
import { getStatisticsDisplayValue } from '../../../../utils/CommonUtils';
import '../ProfilerDashboard/profiler-dashboard.less';
@ -21,7 +21,10 @@ const ProfilerLatestValue = ({
information,
tickFormatter,
stringValue = false,
onClick,
}: ProfilerLatestValueProps) => {
const theme = useTheme();
const getLatestValue = (value?: number | string) => {
if (isUndefined(value)) {
return '--';
@ -35,23 +38,50 @@ const ProfilerLatestValue = ({
};
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) => (
<Statistic
className="profiler-latest-value"
<Box
key={info.title}
title={
<Typography.Text
className="text-grey-body break-all"
data-testid="title">
{info.title}
</Typography.Text>
}
value={getLatestValue(info.latestValue)}
valueStyle={{ color: info.color, fontSize: '18px', fontWeight: 700 }}
/>
sx={{
cursor: onClick ? 'pointer' : 'default',
}}
onClick={() => onClick?.(info.dataKey)}>
<Typography
className="break-all"
data-testid="title"
sx={{
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.
*/
import { Grid, Stack } from '@mui/material';
import { Col } from 'antd';
import { Box, Grid, Stack } from '@mui/material';
import { AxiosError } from 'axios';
import { pick } from 'lodash';
import { DateRangeObject } from 'Models';
@ -220,50 +219,49 @@ const TableProfilerChart = ({
{showHeader && (
<>
{!isSummaryLoading && !isProfilingEnabled && (
<Col span={24}>
<Box>
<NoProfilerBanner />
</Col>
</Box>
)}
<Col span={24}>
<Grid container spacing={5}>
{overallSummary?.map((summary) => (
<Grid key={summary.title} size="grow">
<SummaryCardV1
extra={summary.extra}
icon={summary.icon}
isLoading={isSummaryLoading}
title={summary.title}
value={summary.value}
/>
</Grid>
))}
</Grid>
</Col>
<Grid container spacing={5}>
{overallSummary?.map((summary) => (
<Grid key={summary.title} size="grow">
<SummaryCardV1
extra={summary.extra}
icon={summary.icon}
isLoading={isSummaryLoading}
title={summary.title}
value={summary.value}
/>
</Grid>
))}
</Grid>
</>
)}
<Col data-testid="row-metrics" span={24}>
<Box data-testid="row-metrics">
<ProfilerDetailsCard
chartCollection={rowCountMetrics}
curveType="stepAfter"
chartType="area"
isLoading={isTableProfilerLoading}
name="rowCount"
noDataPlaceholderText={noProfilerMessage}
title={t('label.data-volume')}
/>
</Col>
</Box>
{showSystemMetrics && (
<>
<Col span={24}>{operationDateMetricsCard}</Col>
<Col span={24}>{operationMetricsCard}</Col>
<Box>{operationDateMetricsCard}</Box>
<Box>{operationMetricsCard}</Box>
</>
)}
<Col span={24}>
<Box>
<CustomMetricGraphs
customMetrics={customMetrics}
customMetricsGraphData={tableCustomMetricsProfiling}
isLoading={isTableProfilerLoading || isSummaryLoading}
/>
</Col>
</Box>
</Stack>
);
};

View File

@ -27,7 +27,7 @@ export const TEXT_BODY_COLOR = '#37352F';
export const TEXT_GREY_MUTED = '#757575';
export const SUCCESS_COLOR = '#008376';
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 BORDER_COLOR = '#0000001a';
export const BLACK_COLOR = '#000000';