mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-20 23:18:01 +00:00
Enhance Data Quality UI with new components and styling
- Added a PageHeader and Searchbar to the TestCases component for improved user navigation and search functionality. - Introduced a new stylesheet for TestSuites to enhance layout and visual consistency. - Refactored TestSuites component to include a styled header and integrated Searchbar. - Updated DataQualityTab to accept a tableHeader prop for better customization. - Enhanced styling for Data Quality tab and table components to improve overall user experience.
This commit is contained in:
parent
a708309f73
commit
4e47877d99
@ -79,6 +79,7 @@ import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder
|
|||||||
import { PagingHandlerParams } from '../../common/NextPrevious/NextPrevious.interface';
|
import { PagingHandlerParams } from '../../common/NextPrevious/NextPrevious.interface';
|
||||||
import Searchbar from '../../common/SearchBarComponent/SearchBar.component';
|
import Searchbar from '../../common/SearchBarComponent/SearchBar.component';
|
||||||
import DataQualityTab from '../../Database/Profiler/DataQualityTab/DataQualityTab';
|
import DataQualityTab from '../../Database/Profiler/DataQualityTab/DataQualityTab';
|
||||||
|
import PageHeader from '../../PageHeader/PageHeader.component';
|
||||||
import { TestCaseSearchParams } from '../DataQuality.interface';
|
import { TestCaseSearchParams } from '../DataQuality.interface';
|
||||||
import PieChartSummaryPanel from '../SummaryPannel/PieChartSummaryPanel.component';
|
import PieChartSummaryPanel from '../SummaryPannel/PieChartSummaryPanel.component';
|
||||||
|
|
||||||
@ -392,6 +393,31 @@ export const TestCases = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dqTableHeader = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={16}>
|
||||||
|
<PageHeader
|
||||||
|
data={{
|
||||||
|
header: t('label.test-case-insight-plural'),
|
||||||
|
subHeader: t('message.test-case-insight-description'),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Searchbar
|
||||||
|
removeMargin
|
||||||
|
placeholder={t('label.search-entity', {
|
||||||
|
entity: t('label.test-case-lowercase'),
|
||||||
|
})}
|
||||||
|
searchValue={searchValue}
|
||||||
|
onSearch={(value) => handleSearchParam('searchValue', value)}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}, [searchValue, handleSearchParam]);
|
||||||
|
|
||||||
const handleMenuClick = ({ key }: { key: string }) => {
|
const handleMenuClick = ({ key }: { key: string }) => {
|
||||||
setSelectedFilter((prevSelected) => {
|
setSelectedFilter((prevSelected) => {
|
||||||
if (prevSelected.includes(key)) {
|
if (prevSelected.includes(key)) {
|
||||||
@ -488,16 +514,6 @@ export const TestCases = () => {
|
|||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
onValuesChange={handleFilterChange}>
|
onValuesChange={handleFilterChange}>
|
||||||
<Space wrap align="center" className="w-full" size={16}>
|
<Space wrap align="center" className="w-full" size={16}>
|
||||||
<Form.Item className="m-0 w-80">
|
|
||||||
<Searchbar
|
|
||||||
removeMargin
|
|
||||||
placeholder={t('label.search-entity', {
|
|
||||||
entity: t('label.test-case-lowercase'),
|
|
||||||
})}
|
|
||||||
searchValue={searchValue}
|
|
||||||
onSearch={(value) => handleSearchParam('searchValue', value)}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item noStyle name="selectedFilters">
|
<Form.Item noStyle name="selectedFilters">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{
|
menu={{
|
||||||
@ -665,6 +681,7 @@ export const TestCases = () => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
pagingData={pagingData}
|
pagingData={pagingData}
|
||||||
showPagination={showPagination}
|
showPagination={showPagination}
|
||||||
|
tableHeader={dqTableHeader}
|
||||||
testCases={testCase}
|
testCases={testCase}
|
||||||
onTestCaseResultUpdate={handleStatusSubmit}
|
onTestCaseResultUpdate={handleStatusSubmit}
|
||||||
onTestUpdate={handleTestCaseUpdate}
|
onTestUpdate={handleTestCaseUpdate}
|
||||||
|
@ -72,6 +72,7 @@ import { TableProfilerTab } from '../../../Database/Profiler/ProfilerDashboard/p
|
|||||||
import ProfilerProgressWidget from '../../../Database/Profiler/TableProfiler/ProfilerProgressWidget/ProfilerProgressWidget';
|
import ProfilerProgressWidget from '../../../Database/Profiler/TableProfiler/ProfilerProgressWidget/ProfilerProgressWidget';
|
||||||
import { TestSuiteSearchParams } from '../../DataQuality.interface';
|
import { TestSuiteSearchParams } from '../../DataQuality.interface';
|
||||||
import PieChartSummaryPanel from '../../SummaryPannel/PieChartSummaryPanel.component';
|
import PieChartSummaryPanel from '../../SummaryPannel/PieChartSummaryPanel.component';
|
||||||
|
import './test-suites.style.less';
|
||||||
|
|
||||||
export const TestSuites = () => {
|
export const TestSuites = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -306,15 +307,6 @@ export const TestSuites = () => {
|
|||||||
align="center"
|
align="center"
|
||||||
className="w-full justify-between"
|
className="w-full justify-between"
|
||||||
size={16}>
|
size={16}>
|
||||||
<Form.Item className="m-0 w-80">
|
|
||||||
<Searchbar
|
|
||||||
removeMargin
|
|
||||||
searchValue={searchValue}
|
|
||||||
onSearch={(value) =>
|
|
||||||
handleSearchParam(value, 'searchValue')
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
className="m-0"
|
className="m-0"
|
||||||
label={t('label.owner')}
|
label={t('label.owner')}
|
||||||
@ -355,14 +347,21 @@ export const TestSuites = () => {
|
|||||||
testSummary={testCaseSummary}
|
testSummary={testCaseSummary}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
<div className="test-suite-list-container">
|
||||||
|
<div className="test-suite-list-header">
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={16}>
|
<Col span={16}>
|
||||||
<Radio.Group value={subTab} onChange={handleSubTabChange}>
|
<Radio.Group value={subTab} onChange={handleSubTabChange}>
|
||||||
<Radio.Button value={DataQualitySubTabs.TABLE_SUITES}>
|
<Radio.Button
|
||||||
|
data-testid="table-suite-radio-btn"
|
||||||
|
value={DataQualitySubTabs.TABLE_SUITES}>
|
||||||
{t('label.table-suite-plural')}
|
{t('label.table-suite-plural')}
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
<Radio.Button value={DataQualitySubTabs.BUNDLE_SUITES}>
|
<Radio.Button
|
||||||
|
data-testid="bundle-suite-radio-btn"
|
||||||
|
value={DataQualitySubTabs.BUNDLE_SUITES}>
|
||||||
{t('label.bundle-suite-plural')}
|
{t('label.bundle-suite-plural')}
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
@ -370,15 +369,21 @@ export const TestSuites = () => {
|
|||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Searchbar
|
<Searchbar
|
||||||
removeMargin
|
removeMargin
|
||||||
|
placeholder={t('label.search-entity', {
|
||||||
|
entity:
|
||||||
|
subTab === DataQualitySubTabs.TABLE_SUITES
|
||||||
|
? t('label.table-suite-plural')
|
||||||
|
: t('label.bundle-suite-plural'),
|
||||||
|
})}
|
||||||
searchValue={searchValue}
|
searchValue={searchValue}
|
||||||
onSearch={(value) => handleSearchParam(value, 'searchValue')}
|
onSearch={(value) => handleSearchParam(value, 'searchValue')}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</div>
|
||||||
<Col span={24}>
|
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
containerClassName="custom-card-with-table"
|
||||||
customPaginationProps={{
|
customPaginationProps={{
|
||||||
currentPage,
|
currentPage,
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -401,6 +406,7 @@ export const TestSuites = () => {
|
|||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
@import (reference) '../../../../styles/variables.less';
|
||||||
|
|
||||||
|
.test-suite-list-container {
|
||||||
|
background-color: @white;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
border: @global-border;
|
||||||
|
|
||||||
|
.test-suite-list-header {
|
||||||
|
padding: @padding-md;
|
||||||
|
}
|
||||||
|
}
|
@ -82,7 +82,8 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
breadcrumbData,
|
breadcrumbData,
|
||||||
fetchTestCases,
|
fetchTestCases,
|
||||||
isEditAllowed,
|
isEditAllowed,
|
||||||
}) => {
|
tableHeader,
|
||||||
|
}: DataQualityTabProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
const [selectedTestCase, setSelectedTestCase] = useState<TestCaseAction>();
|
const [selectedTestCase, setSelectedTestCase] = useState<TestCaseAction>();
|
||||||
@ -147,7 +148,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
title: t('label.status'),
|
title: t('label.status'),
|
||||||
dataIndex: 'testCaseResult',
|
dataIndex: 'testCaseResult',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
width: 100,
|
width: 120,
|
||||||
render: (result: TestCaseResult) => {
|
render: (result: TestCaseResult) => {
|
||||||
return result?.testCaseStatus ? (
|
return result?.testCaseStatus ? (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
@ -238,7 +239,14 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
getColumnNameFromEntityLink(entityLink) ?? ''
|
getColumnNameFromEntityLink(entityLink) ?? ''
|
||||||
);
|
);
|
||||||
|
|
||||||
return name;
|
return (
|
||||||
|
<Typography.Paragraph
|
||||||
|
className="m-0"
|
||||||
|
data-testid={name}
|
||||||
|
style={{ maxWidth: 150 }}>
|
||||||
|
{name}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '--';
|
return '--';
|
||||||
@ -483,10 +491,18 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
}, [testCases]);
|
}, [testCases]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
|
className={classNames({
|
||||||
|
'data-quality-tab-container': !isUndefined(tableHeader),
|
||||||
|
})}>
|
||||||
|
{tableHeader && (
|
||||||
|
<div className="data-quality-table-header">{tableHeader}</div>
|
||||||
|
)}
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
containerClassName="test-case-table-container"
|
containerClassName={classNames('test-case-table-container', {
|
||||||
|
'custom-card-with-table': !isUndefined(tableHeader),
|
||||||
|
})}
|
||||||
{...(pagingData && showPagination
|
{...(pagingData && showPagination
|
||||||
? {
|
? {
|
||||||
customPaginationProps: {
|
customPaginationProps: {
|
||||||
@ -562,7 +578,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
|||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,3 +18,12 @@
|
|||||||
padding-right: 0px;
|
padding-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.data-quality-tab-container {
|
||||||
|
background-color: @white;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
border: @global-border;
|
||||||
|
|
||||||
|
.data-quality-table-header {
|
||||||
|
padding: @padding-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -67,6 +67,7 @@ export interface DataQualityTabProps {
|
|||||||
breadcrumbData?: TitleBreadcrumbProps['titleLinks'];
|
breadcrumbData?: TitleBreadcrumbProps['titleLinks'];
|
||||||
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
|
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
|
||||||
isEditAllowed?: boolean;
|
isEditAllowed?: boolean;
|
||||||
|
tableHeader?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestSummaryProps {
|
export interface TestSummaryProps {
|
||||||
|
@ -57,3 +57,18 @@
|
|||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-card-with-table {
|
||||||
|
&.table-container {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0px 0px @border-radius-sm @border-radius-sm;
|
||||||
|
}
|
||||||
|
.ant-table {
|
||||||
|
table > tbody > tr:last-child > td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
tr > td:first-child.name-column {
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1427,6 +1427,7 @@
|
|||||||
"term-plural": "Terms",
|
"term-plural": "Terms",
|
||||||
"test": "Test",
|
"test": "Test",
|
||||||
"test-case": "Test case",
|
"test-case": "Test case",
|
||||||
|
"test-case-insight-plural": "Test Case Insights",
|
||||||
"test-case-lowercase": "test case",
|
"test-case-lowercase": "test case",
|
||||||
"test-case-lowercase-plural": "test cases",
|
"test-case-lowercase-plural": "test cases",
|
||||||
"test-case-name": "Test Case Name",
|
"test-case-name": "Test Case Name",
|
||||||
@ -2157,6 +2158,7 @@
|
|||||||
"team-member-management-description": "Streamline access to users and teams in {{brandName}}.",
|
"team-member-management-description": "Streamline access to users and teams in {{brandName}}.",
|
||||||
"team-moved-success": "Team moved successfully!",
|
"team-moved-success": "Team moved successfully!",
|
||||||
"team-no-asset": "Your team does not have any assets.",
|
"team-no-asset": "Your team does not have any assets.",
|
||||||
|
"test-case-insight-description": "Access a centralized view of your dataset's health based on configured test validations.",
|
||||||
"test-case-schedule-description": "The data quality tests can be scheduled to run at the desired frequency. The timezone is in UTC.",
|
"test-case-schedule-description": "The data quality tests can be scheduled to run at the desired frequency. The timezone is in UTC.",
|
||||||
"test-connection-cannot-be-triggered": "Test connection cannot be triggered.",
|
"test-connection-cannot-be-triggered": "Test connection cannot be triggered.",
|
||||||
"test-connection-taking-too-long": {
|
"test-connection-taking-too-long": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user