mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-08 06:53:11 +00:00
feat(ui): Enhance Profiler components with additional props and improve layout using Grid
This commit is contained in:
parent
b188cc56b3
commit
5a6443cfc3
@ -81,6 +81,7 @@ export interface ProfilerLatestValueProps {
|
|||||||
information: MetricChartType['information'];
|
information: MetricChartType['information'];
|
||||||
tickFormatter?: string;
|
tickFormatter?: string;
|
||||||
stringValue?: boolean;
|
stringValue?: boolean;
|
||||||
|
extra?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TestCaseAction = {
|
export type TestCaseAction = {
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Box, Divider, Stack, Typography, useTheme } from '@mui/material';
|
import { Box, Divider, Grid, 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,6 +21,7 @@ const ProfilerLatestValue = ({
|
|||||||
information,
|
information,
|
||||||
tickFormatter,
|
tickFormatter,
|
||||||
stringValue = false,
|
stringValue = false,
|
||||||
|
extra,
|
||||||
}: ProfilerLatestValueProps) => {
|
}: ProfilerLatestValueProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@ -37,65 +38,71 @@ const ProfilerLatestValue = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Grid
|
||||||
|
container
|
||||||
|
alignItems="center"
|
||||||
data-testid="data-summary-container"
|
data-testid="data-summary-container"
|
||||||
direction="row"
|
|
||||||
spacing={20}
|
|
||||||
sx={{
|
sx={{
|
||||||
width: '100%',
|
|
||||||
backgroundColor: theme.palette.grey[50],
|
backgroundColor: theme.palette.grey[50],
|
||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
p: '16px 30px',
|
p: '16px 30px',
|
||||||
}}>
|
}}>
|
||||||
{information.map((info) => (
|
<Grid display="flex" gap={20} size="grow">
|
||||||
<Box key={info.title}>
|
{information.map((info) => (
|
||||||
<Typography
|
<Box key={info.title}>
|
||||||
className="break-all"
|
<Typography
|
||||||
data-testid="title"
|
className="break-all"
|
||||||
sx={{
|
data-testid="title"
|
||||||
color: theme.palette.grey[700],
|
sx={{
|
||||||
fontSize: theme.typography.pxToRem(11),
|
color: theme.palette.grey[700],
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
fontSize: theme.typography.pxToRem(11),
|
||||||
borderLeft: `4px solid ${info.color}`,
|
fontWeight: theme.typography.fontWeightBold,
|
||||||
paddingLeft: '8px',
|
borderLeft: `4px solid ${info.color}`,
|
||||||
lineHeight: '12px',
|
paddingLeft: '8px',
|
||||||
mb: 1,
|
lineHeight: '12px',
|
||||||
}}>
|
mb: 1,
|
||||||
{info.title}
|
}}>
|
||||||
</Typography>
|
{info.title}
|
||||||
<Typography
|
</Typography>
|
||||||
className="break-all"
|
<Typography
|
||||||
data-testid="value"
|
className="break-all"
|
||||||
sx={{
|
data-testid="value"
|
||||||
color: theme.palette.grey[900],
|
sx={{
|
||||||
fontSize: theme.typography.pxToRem(17),
|
color: theme.palette.grey[900],
|
||||||
fontWeight: 700,
|
fontSize: theme.typography.pxToRem(17),
|
||||||
}}>
|
fontWeight: 700,
|
||||||
{getLatestValue(info.latestValue)}
|
}}>
|
||||||
</Typography>
|
{getLatestValue(info.latestValue)}
|
||||||
{info.extra && (
|
</Typography>
|
||||||
<>
|
{info.extra && (
|
||||||
<Divider
|
<>
|
||||||
sx={{
|
<Divider
|
||||||
my: 2,
|
sx={{
|
||||||
borderStyle: 'dashed',
|
my: 2,
|
||||||
borderColor: theme.palette.allShades.gray[300],
|
borderStyle: 'dashed',
|
||||||
}}
|
borderColor: theme.palette.allShades.gray[300],
|
||||||
/>
|
}}
|
||||||
<Typography
|
/>
|
||||||
className="break-all"
|
<Typography
|
||||||
data-testid="extra"
|
className="break-all"
|
||||||
sx={{
|
data-testid="extra"
|
||||||
color: theme.palette.grey[900],
|
sx={{
|
||||||
fontSize: theme.typography.pxToRem(11),
|
color: theme.palette.grey[900],
|
||||||
}}>
|
fontSize: theme.typography.pxToRem(11),
|
||||||
{info.extra}
|
}}>
|
||||||
</Typography>
|
{info.extra}
|
||||||
</>
|
</Typography>
|
||||||
)}
|
</>
|
||||||
</Box>
|
)}
|
||||||
))}
|
</Box>
|
||||||
</Stack>
|
))}
|
||||||
|
</Grid>
|
||||||
|
{extra && (
|
||||||
|
<Grid display="flex" justifyContent="flex-end" size={1}>
|
||||||
|
{extra}
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -10,33 +10,32 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
import {
|
import {
|
||||||
Button,
|
Box,
|
||||||
Card,
|
Grid,
|
||||||
Col,
|
IconButton,
|
||||||
Dropdown,
|
Menu,
|
||||||
Form,
|
MenuItem,
|
||||||
Modal,
|
Stack,
|
||||||
Row,
|
useTheme,
|
||||||
Typography,
|
} from '@mui/material';
|
||||||
} from 'antd';
|
import { Form, Modal } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { isEmpty, isUndefined, last, omit, toPairs } from 'lodash';
|
import { isEmpty, isUndefined, last, omit, toPairs } from 'lodash';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
|
Area,
|
||||||
CartesianGrid,
|
CartesianGrid,
|
||||||
Legend,
|
ComposedChart,
|
||||||
Line,
|
Line,
|
||||||
LineChart,
|
|
||||||
ResponsiveContainer,
|
ResponsiveContainer,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
XAxis,
|
XAxis,
|
||||||
YAxis,
|
YAxis,
|
||||||
} from 'recharts';
|
} from 'recharts';
|
||||||
import { ReactComponent as IconDropdown } from '../../../../../assets/svg/menu.svg';
|
|
||||||
import { GRAPH_BACKGROUND_COLOR } from '../../../../../constants/constants';
|
import { GRAPH_BACKGROUND_COLOR } from '../../../../../constants/constants';
|
||||||
import { PAGE_HEADERS } from '../../../../../constants/PageHeaders.constant';
|
|
||||||
import { EntityType } from '../../../../../enums/entity.enum';
|
import { EntityType } from '../../../../../enums/entity.enum';
|
||||||
import { CustomMetric } from '../../../../../generated/entity/data/table';
|
import { CustomMetric } from '../../../../../generated/entity/data/table';
|
||||||
import { Operation } from '../../../../../generated/entity/policies/policy';
|
import { Operation } from '../../../../../generated/entity/policies/policy';
|
||||||
@ -48,11 +47,7 @@ import {
|
|||||||
axisTickFormatter,
|
axisTickFormatter,
|
||||||
tooltipFormatter,
|
tooltipFormatter,
|
||||||
} from '../../../../../utils/ChartUtils';
|
} from '../../../../../utils/ChartUtils';
|
||||||
import { entityChartColor } from '../../../../../utils/CommonUtils';
|
import { CustomDQTooltip } from '../../../../../utils/DataQuality/DataQualityUtils';
|
||||||
import {
|
|
||||||
CustomTooltip,
|
|
||||||
getRandomHexColor,
|
|
||||||
} from '../../../../../utils/DataInsightUtils';
|
|
||||||
import { formatDateTimeLong } from '../../../../../utils/date-time/DateTimeUtils';
|
import { formatDateTimeLong } from '../../../../../utils/date-time/DateTimeUtils';
|
||||||
import { getPrioritizedEditPermission } from '../../../../../utils/PermissionsUtils';
|
import { getPrioritizedEditPermission } from '../../../../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
@ -62,8 +57,7 @@ import {
|
|||||||
import DeleteWidgetModal from '../../../../common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../../../../common/DeleteWidget/DeleteWidgetModal';
|
||||||
import ErrorPlaceHolder from '../../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||||
import CustomMetricForm from '../../../../DataQuality/CustomMetricForm/CustomMetricForm.component';
|
import CustomMetricForm from '../../../../DataQuality/CustomMetricForm/CustomMetricForm.component';
|
||||||
import PageHeader from '../../../../PageHeader/PageHeader.component';
|
import ProfilerStateWrapper from '../../ProfilerStateWrapper/ProfilerStateWrapper.component';
|
||||||
import ProfilerLatestValue from '../../ProfilerLatestValue/ProfilerLatestValue';
|
|
||||||
import { useTableProfiler } from '../TableProfilerProvider';
|
import { useTableProfiler } from '../TableProfilerProvider';
|
||||||
import './custom-metric-graphs.style.less';
|
import './custom-metric-graphs.style.less';
|
||||||
import {
|
import {
|
||||||
@ -76,6 +70,7 @@ const CustomMetricGraphs = ({
|
|||||||
isLoading,
|
isLoading,
|
||||||
customMetrics,
|
customMetrics,
|
||||||
}: CustomMetricGraphsProps) => {
|
}: CustomMetricGraphsProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm<CustomMetric>();
|
const [form] = Form.useForm<CustomMetric>();
|
||||||
const {
|
const {
|
||||||
@ -92,6 +87,9 @@ const CustomMetricGraphs = ({
|
|||||||
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
|
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
|
||||||
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||||
const [isActionLoading, setIsActionLoading] = useState(false);
|
const [isActionLoading, setIsActionLoading] = useState(false);
|
||||||
|
const [anchorEl, setAnchorEl] = useState<Record<string, HTMLElement | null>>(
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
const items = useMemo(
|
const items = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -168,6 +166,7 @@ const CustomMetricGraphs = ({
|
|||||||
setSelectedMetrics(
|
setSelectedMetrics(
|
||||||
customMetrics?.find((metric) => metric.name === metricName)
|
customMetrics?.find((metric) => metric.name === metricName)
|
||||||
);
|
);
|
||||||
|
setAnchorEl((prev) => ({ ...prev, [metricName]: null }));
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case MenuOptions.EDIT:
|
case MenuOptions.EDIT:
|
||||||
setIsEditModalVisible(true);
|
setIsEditModalVisible(true);
|
||||||
@ -182,119 +181,157 @@ const CustomMetricGraphs = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleMenuOpen = (
|
||||||
|
event: React.MouseEvent<HTMLElement>,
|
||||||
|
metricName: string
|
||||||
|
) => {
|
||||||
|
setAnchorEl((prev) => ({ ...prev, [metricName]: event.currentTarget }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMenuClose = (metricName: string) => {
|
||||||
|
setAnchorEl((prev) => ({ ...prev, [metricName]: null }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row data-testid="custom-metric-graph-container" gutter={[16, 16]}>
|
<Stack data-testid="custom-metric-graph-container" spacing="30px">
|
||||||
{!isEmpty(customMetrics) && (
|
{toPairs(customMetricsGraphData).map(([key, metric]) => {
|
||||||
<Col span={24}>
|
|
||||||
<PageHeader data={PAGE_HEADERS.CUSTOM_METRICS} />
|
|
||||||
</Col>
|
|
||||||
)}
|
|
||||||
{toPairs(customMetricsGraphData).map(([key, metric], i) => {
|
|
||||||
const metricDetails = customMetrics?.find(
|
const metricDetails = customMetrics?.find(
|
||||||
(metric) => metric.name === key
|
(metric) => metric.name === key
|
||||||
);
|
);
|
||||||
const color = entityChartColor(i) ?? getRandomHexColor();
|
|
||||||
|
|
||||||
return isUndefined(metricDetails) ? null : (
|
return isUndefined(metricDetails) ? null : (
|
||||||
<Col key={key} span={24}>
|
<Box key={key}>
|
||||||
<Card
|
<ProfilerStateWrapper
|
||||||
className="shadow-none global-border-radius custom-metric-card"
|
|
||||||
data-testid={`${key}-custom-metrics`}
|
data-testid={`${key}-custom-metrics`}
|
||||||
extra={
|
isLoading={isLoading}
|
||||||
editPermission || deletePermission ? (
|
profilerLatestValueProps={{
|
||||||
<Dropdown
|
information: [
|
||||||
menu={{
|
{
|
||||||
items,
|
latestValue: last(metric)?.[key] ?? '--',
|
||||||
onClick: (info) => handleMenuClick(info.key, key),
|
title: t('label.count'),
|
||||||
}}
|
dataKey: key,
|
||||||
placement="bottomLeft"
|
color: theme.palette.allShades.blue[500],
|
||||||
trigger={['click']}>
|
},
|
||||||
<Button
|
],
|
||||||
className="flex-center"
|
extra:
|
||||||
data-testid={`${key}-custom-metrics-menu`}
|
editPermission || deletePermission ? (
|
||||||
icon={<IconDropdown className="self-center" />}
|
<>
|
||||||
size="small"
|
<IconButton
|
||||||
/>
|
data-testid={`${key}-custom-metrics-menu`}
|
||||||
</Dropdown>
|
size="small"
|
||||||
) : null
|
sx={{
|
||||||
}
|
color: theme.palette.grey[800],
|
||||||
loading={isLoading}
|
}}
|
||||||
title={<Typography.Title level={5}>{key}</Typography.Title>}>
|
onClick={(e) => handleMenuOpen(e, key)}>
|
||||||
<Row gutter={[16, 16]}>
|
<MoreVertIcon fontSize="small" />
|
||||||
<Col span={4}>
|
</IconButton>
|
||||||
<ProfilerLatestValue
|
<Menu
|
||||||
information={[
|
anchorEl={anchorEl[key]}
|
||||||
{
|
anchorOrigin={{
|
||||||
latestValue: last(metric)?.[key] ?? '--',
|
vertical: 'bottom',
|
||||||
title: '',
|
horizontal: 'right',
|
||||||
dataKey: key,
|
}}
|
||||||
color,
|
open={Boolean(anchorEl[key])}
|
||||||
},
|
sx={{
|
||||||
]}
|
'.MuiPaper-root': {
|
||||||
/>
|
width: 'max-content',
|
||||||
</Col>
|
},
|
||||||
<Col span={20}>
|
}}
|
||||||
{isEmpty(metric) ? (
|
transformOrigin={{
|
||||||
<Row
|
vertical: 'top',
|
||||||
align="middle"
|
horizontal: 'right',
|
||||||
className="h-full w-full"
|
}}
|
||||||
justify="center">
|
onClose={() => handleMenuClose(key)}>
|
||||||
<Col>
|
{items.map((item) => (
|
||||||
<ErrorPlaceHolder className="mt-0-important" />
|
<MenuItem
|
||||||
</Col>
|
disabled={item.disabled}
|
||||||
</Row>
|
key={item.key}
|
||||||
) : (
|
onClick={() => handleMenuClick(item.key, key)}>
|
||||||
<ResponsiveContainer
|
{item.label}
|
||||||
className="custom-legend"
|
</MenuItem>
|
||||||
debounce={200}
|
))}
|
||||||
id={`${key}-graph`}
|
</Menu>
|
||||||
minHeight={300}>
|
</>
|
||||||
<LineChart
|
) : undefined,
|
||||||
className="w-full"
|
}}
|
||||||
data={metric}
|
title={key}>
|
||||||
margin={{ left: 16 }}>
|
<Box>
|
||||||
<CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} />
|
{isEmpty(metric) ? (
|
||||||
<XAxis
|
<Grid
|
||||||
dataKey="formattedTimestamp"
|
alignItems="middle"
|
||||||
padding={{ left: 16, right: 16 }}
|
className="h-full w-full"
|
||||||
tick={{ fontSize: 12 }}
|
display="flex"
|
||||||
/>
|
justifyContent="center">
|
||||||
|
<ErrorPlaceHolder className="mt-0-important" />
|
||||||
|
</Grid>
|
||||||
|
) : (
|
||||||
|
<ResponsiveContainer
|
||||||
|
className="custom-legend"
|
||||||
|
debounce={200}
|
||||||
|
id={`${key}-graph`}
|
||||||
|
minHeight={300}>
|
||||||
|
<ComposedChart
|
||||||
|
className="w-full"
|
||||||
|
data={metric}
|
||||||
|
margin={{ left: 16 }}>
|
||||||
|
<CartesianGrid
|
||||||
|
stroke={GRAPH_BACKGROUND_COLOR}
|
||||||
|
strokeDasharray="3 3"
|
||||||
|
vertical={false}
|
||||||
|
/>
|
||||||
|
<XAxis
|
||||||
|
axisLine={{
|
||||||
|
stroke: theme.palette.grey[200],
|
||||||
|
}}
|
||||||
|
dataKey="formattedTimestamp"
|
||||||
|
padding={{ left: 16, right: 16 }}
|
||||||
|
tick={{ fontSize: 12 }}
|
||||||
|
tickLine={false}
|
||||||
|
/>
|
||||||
|
|
||||||
<YAxis
|
<YAxis
|
||||||
domain={['min', 'max']}
|
axisLine={false}
|
||||||
padding={{ top: 16, bottom: 16 }}
|
domain={['min', 'max']}
|
||||||
tick={{ fontSize: 12 }}
|
padding={{ top: 16, bottom: 16 }}
|
||||||
tickFormatter={(props) => axisTickFormatter(props)}
|
tick={{ fontSize: 12 }}
|
||||||
type="number"
|
tickFormatter={(props) => axisTickFormatter(props)}
|
||||||
/>
|
tickLine={false}
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
<CustomTooltip
|
<CustomDQTooltip
|
||||||
dateTimeFormatter={formatDateTimeLong}
|
dateTimeFormatter={formatDateTimeLong}
|
||||||
timeStampKey="timestamp"
|
timeStampKey="timestamp"
|
||||||
valueFormatter={(value) =>
|
valueFormatter={(value) => tooltipFormatter(value)}
|
||||||
tooltipFormatter(value)
|
/>
|
||||||
}
|
}
|
||||||
/>
|
cursor={{
|
||||||
}
|
stroke: theme.palette.grey[200],
|
||||||
/>
|
strokeDasharray: '3 3',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Line
|
<Line
|
||||||
dataKey={key}
|
dataKey={key}
|
||||||
name={key}
|
name={key}
|
||||||
stroke={color}
|
stroke={theme.palette.allShades.blue[500]}
|
||||||
type="monotone"
|
type="monotone"
|
||||||
/>
|
/>
|
||||||
|
<Area
|
||||||
<Legend />
|
dataKey={key}
|
||||||
</LineChart>
|
fill={theme.palette.allShades.blue[50]}
|
||||||
</ResponsiveContainer>
|
name={key}
|
||||||
)}
|
stroke={theme.palette.allShades.blue[500]}
|
||||||
</Col>
|
type="monotone"
|
||||||
</Row>
|
/>
|
||||||
</Card>
|
</ComposedChart>
|
||||||
</Col>
|
</ResponsiveContainer>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</ProfilerStateWrapper>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<DeleteWidgetModal
|
<DeleteWidgetModal
|
||||||
@ -329,7 +366,7 @@ const CustomMetricGraphs = ({
|
|||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -209,29 +209,26 @@ const TableProfilerChart = ({
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{showSystemMetrics && (
|
{showSystemMetrics && (
|
||||||
<Box>
|
<ProfilerStateWrapper
|
||||||
<ProfilerStateWrapper
|
dataTestId="operation-metrics"
|
||||||
dataTestId="operation-metrics"
|
isLoading={isSystemProfilerLoading}
|
||||||
isLoading={isSystemProfilerLoading}
|
profilerLatestValueProps={{
|
||||||
profilerLatestValueProps={{
|
information: operationMetrics.information,
|
||||||
information: operationMetrics.information,
|
}}
|
||||||
}}
|
title={t('label.volume-change')}>
|
||||||
title={t('label.volume-change')}>
|
<CustomBarChart
|
||||||
<CustomBarChart
|
chartCollection={operationMetrics}
|
||||||
chartCollection={operationMetrics}
|
name="operationMetrics"
|
||||||
name="operationMetrics"
|
noDataPlaceholderText={noProfilerMessage}
|
||||||
noDataPlaceholderText={noProfilerMessage}
|
/>
|
||||||
/>
|
</ProfilerStateWrapper>
|
||||||
</ProfilerStateWrapper>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
<Box>
|
|
||||||
<CustomMetricGraphs
|
<CustomMetricGraphs
|
||||||
customMetrics={customMetrics}
|
customMetrics={customMetrics}
|
||||||
customMetricsGraphData={tableCustomMetricsProfiling}
|
customMetricsGraphData={tableCustomMetricsProfiling}
|
||||||
isLoading={isTableProfilerLoading || isSummaryLoading}
|
isLoading={isTableProfilerLoading || isSummaryLoading}
|
||||||
/>
|
/>
|
||||||
</Box>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user