feat: Enhance QualityTab with search and filter options; refactor DataQualityTab and update styles

This commit is contained in:
Shailesh Parmar 2025-10-06 20:35:27 +05:30
parent fae21c5a76
commit ec8cf291f2
4 changed files with 157 additions and 75 deletions

View File

@ -89,11 +89,7 @@ const DataObservabilityTab = (props: TableProfilerProps) => {
'background-color 0.2s ease-in, color 0.2s ease-in', 'background-color 0.2s ease-in, color 0.2s ease-in',
borderRadius: '6px', borderRadius: '6px',
}, },
'.Mui-selected': { '.Mui-selected, .MuiTab-root:hover': {
backgroundColor: `${theme.palette.primary.main} !important`,
color: `${theme.palette.primary.contrastText} !important`,
},
'.MuiTab-root:hover': {
backgroundColor: `${theme.palette.primary.main} !important`, backgroundColor: `${theme.palette.primary.main} !important`,
color: `${theme.palette.primary.contrastText} !important`, color: `${theme.palette.primary.contrastText} !important`,
}, },

View File

@ -82,6 +82,7 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
fetchTestCases, fetchTestCases,
isEditAllowed, isEditAllowed,
tableHeader, tableHeader,
removeTableBorder = false,
}: DataQualityTabProps) => { }: DataQualityTabProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { getEntityPermissionByFqn } = usePermissionProvider(); const { getEntityPermissionByFqn } = usePermissionProvider();
@ -512,7 +513,8 @@ const DataQualityTab: React.FC<DataQualityTabProps> = ({
<Table <Table
columns={columns} columns={columns}
containerClassName={classNames('test-case-table-container', { containerClassName={classNames('test-case-table-container', {
'custom-card-with-table': !isUndefined(tableHeader), 'custom-card-with-table':
!isUndefined(tableHeader) || removeTableBorder,
})} })}
{...(pagingData && showPagination {...(pagingData && showPagination
? { ? {

View File

@ -71,6 +71,7 @@ export interface DataQualityTabProps {
fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>; fetchTestCases?: (params?: ListTestCaseParamsBySearch) => Promise<void>;
isEditAllowed?: boolean; isEditAllowed?: boolean;
tableHeader?: ReactNode; tableHeader?: ReactNode;
removeTableBorder?: boolean;
} }
export interface TestSummaryProps { export interface TestSummaryProps {

View File

@ -10,9 +10,10 @@
* 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 { Grid, Stack } from '@mui/material'; import { Box, Grid, Stack, Tab, Tabs, useTheme } from '@mui/material';
import { Col, Form, Row, Select, Space, Tabs } from 'antd'; import { Col, Form, Row, Select, Space } from 'antd';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import QueryString from 'qs';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@ -66,6 +67,7 @@ export const QualityTab = () => {
testCaseSummary, testCaseSummary,
} = useTableProfiler(); } = useTableProfiler();
const { getResourceLimit } = useLimitStore(); const { getResourceLimit } = useLimitStore();
const theme = useTheme();
const { const {
currentPage, currentPage,
@ -91,6 +93,26 @@ export const QualityTab = () => {
const location = useCustomLocation(); const location = useCustomLocation();
const { t } = useTranslation(); const { t } = useTranslation();
const searchData = useMemo(() => {
const param = location.search;
const searchData = QueryString.parse(
param.startsWith('?') ? param.substring(1) : param
);
return searchData as {
activeTab: TableProfilerTab;
activeColumnFqn: string;
qualityTab: string;
};
}, [location.search]);
const { qualityTab = EntityTabs.TEST_CASES } = searchData;
const isTestCaseTab = useMemo(
() => qualityTab === EntityTabs.TEST_CASES,
[qualityTab]
);
const [selectedTestCaseStatus, setSelectedTestCaseStatus] = const [selectedTestCaseStatus, setSelectedTestCaseStatus] =
useState<TestCaseStatus>('' as TestCaseStatus); useState<TestCaseStatus>('' as TestCaseStatus);
const [selectedTestType, setSelectedTestType] = useState(TestCaseType.all); const [selectedTestType, setSelectedTestType] = useState(TestCaseType.all);
@ -235,69 +257,6 @@ export const QualityTab = () => {
/> />
), ),
key: EntityTabs.TEST_CASES, key: EntityTabs.TEST_CASES,
children: (
<Row className="p-t-md">
<Col span={12}>
<Searchbar
placeholder={t('label.search-entity', {
entity: t('label.test-case-lowercase'),
})}
searchValue={searchValue}
onSearch={handleSearchTestCase}
/>
</Col>
<Col span={12}>
<Form layout="inline">
<Space align="center" className="w-full justify-end">
<Form.Item className="m-0 w-40" label={t('label.type')}>
<Select
options={TEST_CASE_TYPE_OPTION}
value={selectedTestType}
onChange={handleTestCaseTypeChange}
/>
</Form.Item>
<Form.Item className="m-0 w-40" label={t('label.status')}>
<Select
options={TEST_CASE_STATUS_OPTION}
value={selectedTestCaseStatus}
onChange={handleTestCaseStatusChange}
/>
</Form.Item>
</Space>
</Form>
</Col>
<Col span={24}>
<DataQualityTab
afterDeleteAction={async (...params) => {
await fetchAllTests(...params); // Update current count when Create / Delete operation performed
params?.length &&
(await getResourceLimit('dataQuality', true, true));
}}
breadcrumbData={tableBreadcrumb}
fetchTestCases={handleSortTestCase}
isEditAllowed={editTest}
isLoading={isTestsLoading}
showTableColumn={false}
testCases={allTestCases}
onTestCaseResultUpdate={onTestCaseUpdate}
onTestUpdate={onTestCaseUpdate}
/>
</Col>
<Col span={24}>
{showPagination && (
<NextPrevious
isNumberBased
currentPage={currentPage}
isLoading={isTestsLoading}
pageSize={pageSize}
paging={paging}
pagingHandler={handleTestCasePageChange}
onShowSizeChange={handlePageSizeChange}
/>
)}
</Col>
</Row>
),
}, },
{ {
label: ( label: (
@ -308,7 +267,6 @@ export const QualityTab = () => {
/> />
), ),
key: EntityTabs.PIPELINE, key: EntityTabs.PIPELINE,
children: <TestSuitePipelineTab testSuite={testSuite} />,
}, },
], ],
[ [
@ -324,11 +282,11 @@ export const QualityTab = () => {
] ]
); );
const handleTabChange = () => { const handleTabChange = (_: React.SyntheticEvent, tab: string) => {
navigate( navigate(
{ {
pathname: location.pathname, pathname: location.pathname,
search: location.search, search: QueryString.stringify({ ...searchData, qualityTab: tab }),
}, },
{ state: undefined, replace: true } { state: undefined, replace: true }
); );
@ -360,7 +318,132 @@ export const QualityTab = () => {
))} ))}
</Grid> </Grid>
<Tabs className="tabs-new" items={tabs} onChange={handleTabChange} /> <Box
sx={{
border: `1px solid ${theme.palette.grey['200']}`,
borderRadius: '10px',
}}>
<Box
alignItems="center"
display="flex"
justifyContent="space-between"
p={4}>
<Box display="flex" gap={5} width="100%">
<Tabs
sx={{
width: 'max-content',
minHeight: 'unset',
display: 'inline-flex',
'.MuiTab-root': {
color: theme.palette.grey['700'],
transition:
'background-color 0.2s ease-in, color 0.2s ease-in',
borderRadius: '6px',
},
'.Mui-selected, .MuiTab-root:hover': {
backgroundColor: `${theme.palette.grey['50']}`,
color: `${theme.palette.grey['800']}`,
},
'MuiTabs-root': {
minHeight: 'unset',
},
'.MuiTabs-indicator': {
display: 'none',
},
'.MuiTabs-scroller': {
padding: '0px',
height: 'unset',
},
'.MuiTab-root:not(:first-of-type)': {
marginLeft: '0px',
borderLeft: `1px solid ${theme.palette.grey['200']}`,
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
},
}}
value={qualityTab}
onChange={handleTabChange}>
{tabs.map(({ label, key }) => (
<Tab key={key} label={label} value={key} />
))}
</Tabs>
{isTestCaseTab && (
<Box width={400}>
<Searchbar
removeMargin
placeholder={t('label.search-entity', {
entity: t('label.test-case-lowercase'),
})}
searchValue={searchValue}
onSearch={handleSearchTestCase}
/>
</Box>
)}
</Box>
{isTestCaseTab && (
<Form layout="inline">
<Space align="center" className="w-full justify-end">
<Form.Item className="m-0 w-40" label={t('label.type')}>
<Select
options={TEST_CASE_TYPE_OPTION}
value={selectedTestType}
onChange={handleTestCaseTypeChange}
/>
</Form.Item>
<Form.Item className="m-0 w-40" label={t('label.status')}>
<Select
options={TEST_CASE_STATUS_OPTION}
value={selectedTestCaseStatus}
onChange={handleTestCaseStatusChange}
/>
</Form.Item>
</Space>
</Form>
)}
</Box>
{isTestCaseTab && (
<Row>
<Col span={24}>
<DataQualityTab
removeTableBorder
afterDeleteAction={async (...params) => {
await fetchAllTests(...params); // Update current count when Create / Delete operation performed
params?.length &&
(await getResourceLimit('dataQuality', true, true));
}}
breadcrumbData={tableBreadcrumb}
fetchTestCases={handleSortTestCase}
isEditAllowed={editTest}
isLoading={isTestsLoading}
showTableColumn={false}
testCases={allTestCases}
onTestCaseResultUpdate={onTestCaseUpdate}
onTestUpdate={onTestCaseUpdate}
/>
</Col>
<Col span={24}>
{showPagination && (
<NextPrevious
isNumberBased
currentPage={currentPage}
isLoading={isTestsLoading}
pageSize={pageSize}
paging={paging}
pagingHandler={handleTestCasePageChange}
onShowSizeChange={handlePageSizeChange}
/>
)}
</Col>
</Row>
)}
{qualityTab === EntityTabs.PIPELINE && (
<TestSuitePipelineTab testSuite={testSuite} />
)}
</Box>
</Stack> </Stack>
); );
}; };