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 Searchbar from '../../common/SearchBarComponent/SearchBar.component';
|
||||
import DataQualityTab from '../../Database/Profiler/DataQualityTab/DataQualityTab';
|
||||
import PageHeader from '../../PageHeader/PageHeader.component';
|
||||
import { TestCaseSearchParams } from '../DataQuality.interface';
|
||||
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 }) => {
|
||||
setSelectedFilter((prevSelected) => {
|
||||
if (prevSelected.includes(key)) {
|
||||
@ -488,16 +514,6 @@ export const TestCases = () => {
|
||||
layout="horizontal"
|
||||
onValuesChange={handleFilterChange}>
|
||||
<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">
|
||||
<Dropdown
|
||||
menu={{
|
||||
@ -665,6 +681,7 @@ export const TestCases = () => {
|
||||
isLoading={isLoading}
|
||||
pagingData={pagingData}
|
||||
showPagination={showPagination}
|
||||
tableHeader={dqTableHeader}
|
||||
testCases={testCase}
|
||||
onTestCaseResultUpdate={handleStatusSubmit}
|
||||
onTestUpdate={handleTestCaseUpdate}
|
||||
|
@ -72,6 +72,7 @@ import { TableProfilerTab } from '../../../Database/Profiler/ProfilerDashboard/p
|
||||
import ProfilerProgressWidget from '../../../Database/Profiler/TableProfiler/ProfilerProgressWidget/ProfilerProgressWidget';
|
||||
import { TestSuiteSearchParams } from '../../DataQuality.interface';
|
||||
import PieChartSummaryPanel from '../../SummaryPannel/PieChartSummaryPanel.component';
|
||||
import './test-suites.style.less';
|
||||
|
||||
export const TestSuites = () => {
|
||||
const { t } = useTranslation();
|
||||
@ -306,15 +307,6 @@ export const TestSuites = () => {
|
||||
align="center"
|
||||
className="w-full justify-between"
|
||||
size={16}>
|
||||
<Form.Item className="m-0 w-80">
|
||||
<Searchbar
|
||||
removeMargin
|
||||
searchValue={searchValue}
|
||||
onSearch={(value) =>
|
||||
handleSearchParam(value, 'searchValue')
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
className="m-0"
|
||||
label={t('label.owner')}
|
||||
@ -355,52 +347,66 @@ export const TestSuites = () => {
|
||||
testSummary={testCaseSummary}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={16}>
|
||||
<Radio.Group value={subTab} onChange={handleSubTabChange}>
|
||||
<Radio.Button value={DataQualitySubTabs.TABLE_SUITES}>
|
||||
{t('label.table-suite-plural')}
|
||||
</Radio.Button>
|
||||
<Radio.Button value={DataQualitySubTabs.BUNDLE_SUITES}>
|
||||
{t('label.bundle-suite-plural')}
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Searchbar
|
||||
removeMargin
|
||||
searchValue={searchValue}
|
||||
onSearch={(value) => handleSearchParam(value, 'searchValue')}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Table
|
||||
columns={columns}
|
||||
customPaginationProps={{
|
||||
currentPage,
|
||||
isLoading,
|
||||
pageSize,
|
||||
isNumberBased: true,
|
||||
paging,
|
||||
pagingHandler: handleTestSuitesPageChange,
|
||||
onShowSizeChange: handlePageSizeChange,
|
||||
showPagination,
|
||||
}}
|
||||
data-testid="test-suite-table"
|
||||
dataSource={testSuites}
|
||||
loading={isLoading}
|
||||
locale={{
|
||||
emptyText: <FilterTablePlaceHolder />,
|
||||
}}
|
||||
pagination={false}
|
||||
scroll={{
|
||||
x: '100%',
|
||||
}}
|
||||
size="small"
|
||||
/>
|
||||
<div className="test-suite-list-container">
|
||||
<div className="test-suite-list-header">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={16}>
|
||||
<Radio.Group value={subTab} onChange={handleSubTabChange}>
|
||||
<Radio.Button
|
||||
data-testid="table-suite-radio-btn"
|
||||
value={DataQualitySubTabs.TABLE_SUITES}>
|
||||
{t('label.table-suite-plural')}
|
||||
</Radio.Button>
|
||||
<Radio.Button
|
||||
data-testid="bundle-suite-radio-btn"
|
||||
value={DataQualitySubTabs.BUNDLE_SUITES}>
|
||||
{t('label.bundle-suite-plural')}
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Searchbar
|
||||
removeMargin
|
||||
placeholder={t('label.search-entity', {
|
||||
entity:
|
||||
subTab === DataQualitySubTabs.TABLE_SUITES
|
||||
? t('label.table-suite-plural')
|
||||
: t('label.bundle-suite-plural'),
|
||||
})}
|
||||
searchValue={searchValue}
|
||||
onSearch={(value) => handleSearchParam(value, 'searchValue')}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
containerClassName="custom-card-with-table"
|
||||
customPaginationProps={{
|
||||
currentPage,
|
||||
isLoading,
|
||||
pageSize,
|
||||
isNumberBased: true,
|
||||
paging,
|
||||
pagingHandler: handleTestSuitesPageChange,
|
||||
onShowSizeChange: handlePageSizeChange,
|
||||
showPagination,
|
||||
}}
|
||||
data-testid="test-suite-table"
|
||||
dataSource={testSuites}
|
||||
loading={isLoading}
|
||||
locale={{
|
||||
emptyText: <FilterTablePlaceHolder />,
|
||||
}}
|
||||
pagination={false}
|
||||
scroll={{
|
||||
x: '100%',
|
||||
}}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</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,
|
||||
fetchTestCases,
|
||||
isEditAllowed,
|
||||
}) => {
|
||||
tableHeader,
|
||||
}: DataQualityTabProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||
const [selectedTestCase, setSelectedTestCase] = useState<TestCaseAction>();
|
||||
@ -147,7 +148,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
||||
title: t('label.status'),
|
||||
dataIndex: 'testCaseResult',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
width: 120,
|
||||
render: (result: TestCaseResult) => {
|
||||
return result?.testCaseStatus ? (
|
||||
<StatusBadge
|
||||
@ -238,7 +239,14 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
||||
getColumnNameFromEntityLink(entityLink) ?? ''
|
||||
);
|
||||
|
||||
return name;
|
||||
return (
|
||||
<Typography.Paragraph
|
||||
className="m-0"
|
||||
data-testid={name}
|
||||
style={{ maxWidth: 150 }}>
|
||||
{name}
|
||||
</Typography.Paragraph>
|
||||
);
|
||||
}
|
||||
|
||||
return '--';
|
||||
@ -483,10 +491,18 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
||||
}, [testCases]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={classNames({
|
||||
'data-quality-tab-container': !isUndefined(tableHeader),
|
||||
})}>
|
||||
{tableHeader && (
|
||||
<div className="data-quality-table-header">{tableHeader}</div>
|
||||
)}
|
||||
<Table
|
||||
columns={columns}
|
||||
containerClassName="test-case-table-container"
|
||||
containerClassName={classNames('test-case-table-container', {
|
||||
'custom-card-with-table': !isUndefined(tableHeader),
|
||||
})}
|
||||
{...(pagingData && showPagination
|
||||
? {
|
||||
customPaginationProps: {
|
||||
@ -562,7 +578,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -18,3 +18,12 @@
|
||||
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'];
|
||||
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
|
||||
isEditAllowed?: boolean;
|
||||
tableHeader?: ReactNode;
|
||||
}
|
||||
|
||||
export interface TestSummaryProps {
|
||||
|
@ -57,3 +57,18 @@
|
||||
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",
|
||||
"test": "Test",
|
||||
"test-case": "Test case",
|
||||
"test-case-insight-plural": "Test Case Insights",
|
||||
"test-case-lowercase": "test case",
|
||||
"test-case-lowercase-plural": "test cases",
|
||||
"test-case-name": "Test Case Name",
|
||||
@ -2157,6 +2158,7 @@
|
||||
"team-member-management-description": "Streamline access to users and teams in {{brandName}}.",
|
||||
"team-moved-success": "Team moved successfully!",
|
||||
"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-connection-cannot-be-triggered": "Test connection cannot be triggered.",
|
||||
"test-connection-taking-too-long": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user