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:
Shailesh Parmar 2025-07-03 18:00:30 +05:30
parent a708309f73
commit 4e47877d99
8 changed files with 147 additions and 70 deletions

View File

@ -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}

View File

@ -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,14 +347,21 @@ export const TestSuites = () => {
testSummary={testCaseSummary}
/>
</Col>
<Col span={24}>
<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 value={DataQualitySubTabs.TABLE_SUITES}>
<Radio.Button
data-testid="table-suite-radio-btn"
value={DataQualitySubTabs.TABLE_SUITES}>
{t('label.table-suite-plural')}
</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')}
</Radio.Button>
</Radio.Group>
@ -370,15 +369,21 @@ export const TestSuites = () => {
<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>
</Col>
<Col span={24}>
</div>
<Table
columns={columns}
containerClassName="custom-card-with-table"
customPaginationProps={{
currentPage,
isLoading,
@ -401,6 +406,7 @@ export const TestSuites = () => {
}}
size="small"
/>
</div>
</Col>
</Row>
);

View File

@ -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;
}
}

View File

@ -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>
);
};

View File

@ -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;
}
}

View File

@ -67,6 +67,7 @@ export interface DataQualityTabProps {
breadcrumbData?: TitleBreadcrumbProps['titleLinks'];
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
isEditAllowed?: boolean;
tableHeader?: ReactNode;
}
export interface TestSummaryProps {

View File

@ -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;
}
}
}

View File

@ -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": {