mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-06 22:35:24 +00:00
feat: Remove SummaryPanel component and tests; replace with SummaryCardV1 in QualityTab
This commit is contained in:
parent
f8df6c38c6
commit
f2b8f7786c
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Col, Row } from 'antd';
|
||||
import { FC, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as TestCaseAbortedIcon } from '../../../assets/svg/aborted-status.svg';
|
||||
import { ReactComponent as TestCaseIcon } from '../../../assets/svg/all-activity-v2.svg';
|
||||
import { ReactComponent as TestCaseFailedIcon } from '../../../assets/svg/failed-status.svg';
|
||||
import { ReactComponent as DataAssetsCoverageIcon } from '../../../assets/svg/ic-data-assets-coverage.svg';
|
||||
import { ReactComponent as HealthCheckIcon } from '../../../assets/svg/ic-green-heart-border.svg';
|
||||
import { ReactComponent as TestCaseSuccessIcon } from '../../../assets/svg/success-colored.svg';
|
||||
import { SummaryCard } from '../../../components/common/SummaryCard/SummaryCard.component';
|
||||
import { PRIMARY_COLOR, YELLOW_2 } from '../../../constants/Color.constants';
|
||||
import { SummaryPanelProps } from './SummaryPanel.interface';
|
||||
|
||||
export const SummaryPanel: FC<SummaryPanelProps> = ({
|
||||
testSummary: summary,
|
||||
isLoading = false,
|
||||
showAdditionalSummary = false,
|
||||
}: SummaryPanelProps) => {
|
||||
const { t } = useTranslation();
|
||||
const spanValue = useMemo(
|
||||
() => (showAdditionalSummary ? 8 : 6),
|
||||
[showAdditionalSummary]
|
||||
);
|
||||
|
||||
return (
|
||||
<Row wrap gutter={[16, 16]}>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-primary"
|
||||
className="h-full"
|
||||
isLoading={isLoading}
|
||||
showProgressBar={false}
|
||||
title={t('label.total-entity', { entity: t('label.test-plural') })}
|
||||
titleIcon={
|
||||
<TestCaseIcon color={PRIMARY_COLOR} height={16} width={16} />
|
||||
}
|
||||
total={summary?.total ?? 0}
|
||||
value={summary?.total ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-success"
|
||||
isLoading={isLoading}
|
||||
title={t('label.success')}
|
||||
titleIcon={<TestCaseSuccessIcon height={16} width={16} />}
|
||||
total={summary?.total ?? 0}
|
||||
type="success"
|
||||
value={summary?.success ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-aborted"
|
||||
isLoading={isLoading}
|
||||
title={t('label.aborted')}
|
||||
titleIcon={
|
||||
<TestCaseAbortedIcon color={YELLOW_2} height={16} width={16} />
|
||||
}
|
||||
total={summary?.total ?? 0}
|
||||
type="aborted"
|
||||
value={summary?.aborted ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-failed"
|
||||
isLoading={isLoading}
|
||||
title={t('label.failed')}
|
||||
titleIcon={<TestCaseFailedIcon height={16} width={16} />}
|
||||
total={summary?.total ?? 0}
|
||||
type="failed"
|
||||
value={summary?.failed ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
{showAdditionalSummary && (
|
||||
<>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-success"
|
||||
isLoading={isLoading}
|
||||
title={t('label.healthy-data-asset-plural')}
|
||||
titleIcon={<HealthCheckIcon height={16} width={16} />}
|
||||
total={summary?.totalDQEntities ?? 0}
|
||||
type="success"
|
||||
value={summary?.healthy ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={spanValue}>
|
||||
<SummaryCard
|
||||
inverseLabel
|
||||
cardBackgroundClass="bg-primary"
|
||||
isLoading={isLoading}
|
||||
title={t('label.data-asset-plural-coverage')}
|
||||
titleIcon={<DataAssetsCoverageIcon height={16} width={16} />}
|
||||
total={summary?.totalEntityCount ?? 0}
|
||||
type="acknowledged"
|
||||
value={summary?.totalDQEntities ?? 0}
|
||||
/>
|
||||
</Col>
|
||||
</>
|
||||
)}
|
||||
</Row>
|
||||
);
|
||||
};
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { getTestCaseExecutionSummary } from '../../../rest/testAPI';
|
||||
import { SummaryPanel } from './SummaryPanel.component';
|
||||
|
||||
const testCasePermission = {
|
||||
Create: true,
|
||||
Delete: true,
|
||||
ViewAll: true,
|
||||
EditAll: true,
|
||||
EditDescription: true,
|
||||
EditDisplayName: true,
|
||||
EditCustomFields: true,
|
||||
};
|
||||
const mockSummary = {
|
||||
total: 10,
|
||||
success: 7,
|
||||
aborted: 2,
|
||||
failed: 1,
|
||||
};
|
||||
|
||||
jest.mock('../../common/SummaryCard/SummaryCard.component', () => {
|
||||
return {
|
||||
SummaryCard: jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div>SummaryCard.component</div>),
|
||||
};
|
||||
});
|
||||
jest.mock('../../../rest/testAPI', () => {
|
||||
return {
|
||||
getTestCaseExecutionSummary: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockSummary)),
|
||||
};
|
||||
});
|
||||
|
||||
describe('SummaryPanel component', () => {
|
||||
it('component should render', async () => {
|
||||
render(<SummaryPanel testSummary={mockSummary} />);
|
||||
|
||||
const summaryCards = await screen.findAllByText('SummaryCard.component');
|
||||
|
||||
expect(summaryCards).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('Show additional summary card if showAdditionalSummary is true', async () => {
|
||||
render(<SummaryPanel showAdditionalSummary testSummary={mockSummary} />);
|
||||
|
||||
const summaryCards = await screen.findAllByText('SummaryCard.component');
|
||||
|
||||
expect(summaryCards).toHaveLength(6);
|
||||
});
|
||||
|
||||
it('should not call getTestCaseExecutionSummary API, if testSummary data is provided', async () => {
|
||||
const mockGetTestCaseExecutionSummary =
|
||||
getTestCaseExecutionSummary as jest.Mock;
|
||||
render(<SummaryPanel testSummary={mockSummary} />);
|
||||
|
||||
expect(mockGetTestCaseExecutionSummary).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call getTestCaseExecutionSummary API, if there is no permission', async () => {
|
||||
const mockGetTestCaseExecutionSummary =
|
||||
getTestCaseExecutionSummary as jest.Mock;
|
||||
testCasePermission.ViewAll = false;
|
||||
render(<SummaryPanel testSummary={mockSummary} />);
|
||||
|
||||
expect(mockGetTestCaseExecutionSummary).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -11,6 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import { Grid } from '@mui/material';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
@ -26,7 +27,11 @@ import { isEmpty } from 'lodash';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ReactComponent as AddItemIcon } from '../../../../../assets/svg/add-item-icon.svg';
|
||||
import { ReactComponent as SettingIcon } from '../../../../../assets/svg/ic-settings-primery.svg';
|
||||
import { ReactComponent as RedCircleIcon } from '../../../../../assets/svg/red-circle-with-dash.svg';
|
||||
import { ReactComponent as SuccessTicketIcon } from '../../../../../assets/svg/success-ticket-with-check.svg';
|
||||
import { ReactComponent as YellowCalendarIcon } from '../../../../../assets/svg/yellow-calendar.icon.svg';
|
||||
import { INITIAL_PAGING_VALUE } from '../../../../../constants/constants';
|
||||
import { PAGE_HEADERS } from '../../../../../constants/PageHeaders.constant';
|
||||
import {
|
||||
@ -56,9 +61,9 @@ import ErrorPlaceHolder from '../../../../common/ErrorWithPlaceholder/ErrorPlace
|
||||
import NextPrevious from '../../../../common/NextPrevious/NextPrevious';
|
||||
import { NextPreviousProps } from '../../../../common/NextPrevious/NextPrevious.interface';
|
||||
import Searchbar from '../../../../common/SearchBarComponent/SearchBar.component';
|
||||
import SummaryCardV1 from '../../../../common/SummaryCard/SummaryCardV1';
|
||||
import TabsLabel from '../../../../common/TabsLabel/TabsLabel.component';
|
||||
import { TestLevel } from '../../../../DataQuality/AddDataQualityTest/components/TestCaseFormV1.interface';
|
||||
import { SummaryPanel } from '../../../../DataQuality/SummaryPannel/SummaryPanel.component';
|
||||
import TestSuitePipelineTab from '../../../../DataQuality/TestSuite/TestSuitePipelineTab/TestSuitePipelineTab.component';
|
||||
import PageHeader from '../../../../PageHeader/PageHeader.component';
|
||||
import DataQualityTab from '../../DataQualityTab/DataQualityTab';
|
||||
@ -115,6 +120,37 @@ export const QualityTab = () => {
|
||||
const [ingestionPipelineCount, setIngestionPipelineCount] =
|
||||
useState<number>(0);
|
||||
|
||||
const totalTestCaseSummary = useMemo(() => {
|
||||
const tests = testCaseSummary?.total ?? INITIAL_TEST_SUMMARY;
|
||||
|
||||
return [
|
||||
{
|
||||
title: t('label.test-plural-type', { type: t('label.total') }),
|
||||
key: 'total-tests',
|
||||
value: tests.total,
|
||||
icon: AddItemIcon,
|
||||
},
|
||||
{
|
||||
title: t('label.test-plural-type', { type: t('label.successful') }),
|
||||
key: 'successful-tests',
|
||||
value: tests.success,
|
||||
icon: SuccessTicketIcon,
|
||||
},
|
||||
{
|
||||
title: t('label.test-plural-type', { type: t('label.failed') }),
|
||||
key: 'failed-tests',
|
||||
value: tests.failed,
|
||||
icon: RedCircleIcon,
|
||||
},
|
||||
{
|
||||
title: t('label.test-plural-type', { type: t('label.aborted') }),
|
||||
key: 'aborted-tests',
|
||||
value: tests.aborted,
|
||||
icon: YellowCalendarIcon,
|
||||
},
|
||||
];
|
||||
}, [testCaseSummary]);
|
||||
|
||||
const fetchIngestionPipelineCount = async () => {
|
||||
try {
|
||||
const { paging: ingestionPipelinePaging } = await getIngestionPipelines({
|
||||
@ -393,9 +429,18 @@ export const QualityTab = () => {
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<SummaryPanel
|
||||
testSummary={testCaseSummary?.total ?? INITIAL_TEST_SUMMARY}
|
||||
/>
|
||||
<Grid container spacing={5}>
|
||||
{totalTestCaseSummary?.map((summary) => (
|
||||
<Grid key={summary.title} size="grow">
|
||||
<SummaryCardV1
|
||||
icon={summary.icon}
|
||||
isLoading={isTestsLoading}
|
||||
title={summary.title}
|
||||
value={summary.value}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Tabs className="tabs-new" items={tabs} onChange={handleTabChange} />
|
||||
|
@ -1694,6 +1694,7 @@
|
||||
"test-email": "Test Email",
|
||||
"test-email-connection": "Test Email Connection",
|
||||
"test-entity": "Test {{entity}}",
|
||||
"test-plural-type": "{{type}} Tests",
|
||||
"test-level-lowercase": "test level",
|
||||
"test-plural": "Tests",
|
||||
"test-suite": "Test Suite",
|
||||
|
Loading…
x
Reference in New Issue
Block a user