feat: add Data Observability Tab component and integrate into TableUtils

This commit is contained in:
Shailesh Parmar 2025-09-18 10:30:14 +05:30
parent 296bc99c42
commit 4ac528dd36
4 changed files with 159 additions and 1 deletions

View File

@ -0,0 +1,109 @@
/*
* 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 { Tab, Tabs } from '@mui/material';
import Qs from 'qs';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTourProvider } from '../../../../context/TourProvider/TourProvider';
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
import { TableProfilerTab } from '../ProfilerDashboard/profilerDashboard.interface';
import profilerClassBase from '../TableProfiler/ProfilerClassBase';
import { TableProfilerProps } from '../TableProfiler/TableProfiler.interface';
import { TableProfilerProvider } from '../TableProfiler/TableProfilerProvider';
import './data-observability-tab.less';
const DataObservabilityTab = (props: TableProfilerProps) => {
const { isTourOpen } = useTourProvider();
const navigate = useNavigate();
const location = useCustomLocation();
const { activeTab = profilerClassBase.getDefaultTabKey(isTourOpen) } =
useMemo(() => {
const param = location.search;
const searchData = Qs.parse(
param.startsWith('?') ? param.substring(1) : param
);
return searchData as {
activeTab: TableProfilerTab;
activeColumnFqn: string;
};
}, [location.search, isTourOpen]);
const tabOptions = useMemo(() => {
return profilerClassBase.getProfilerTabOptions();
}, []);
const activeTabComponent = useMemo(() => {
const tabComponents = profilerClassBase.getProfilerTabs();
const ActiveComponent = tabComponents[activeTab];
return <ActiveComponent />;
}, [activeTab]);
const handleTabChangeMUI = (_: React.SyntheticEvent, newValue: string) => {
navigate(
{ search: Qs.stringify({ activeTab: newValue }) },
{
replace: true,
}
);
};
return (
<TableProfilerProvider {...props}>
<div
className="data-observability-tab-container"
data-testid="table-profiler-container"
id="profilerDetails">
<Tabs
sx={(theme) => ({
width: 'auto',
display: 'inline-flex',
'.MuiTab-root': {
transition: 'background-color 0.2s ease-in, color 0.2s ease-in',
borderRadius: '6px',
},
'.Mui-selected': {
backgroundColor: `${theme.palette.primary.main} !important`,
color: `${theme.palette.primary.contrastText} !important`,
},
'.MuiTab-root:hover': {
backgroundColor: `${theme.palette.primary.main} !important`,
color: `${theme.palette.primary.contrastText} !important`,
},
'.MuiTabs-indicator': {
display: 'none',
},
'.MuiTabs-scroller': {
padding: '0 8px',
},
'.MuiTab-root:not(:first-of-type)': {
marginLeft: '4px',
},
})}
value={activeTab}
onChange={handleTabChangeMUI}>
{tabOptions.map(({ label, key }) => (
<Tab key={key} label={label} value={key} />
))}
</Tabs>
<div className="data-observability-content-panel">
{activeTabComponent}
</div>
</div>
</TableProfilerProvider>
);
};
export default DataObservabilityTab;

View File

@ -0,0 +1,14 @@
import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
const TabComponent = ({ value, items, ...rest }) => {
return (
<Tabs value={value} variant="standard" {...rest}>
{items.map(({ label, key }) => (
<Tab key={key} label={label} value={key} />
))}
</Tabs>
);
};
export default TabComponent;

View File

@ -0,0 +1,15 @@
@import (reference) '../../../../styles/variables.less';
.data-observability-tab-container {
height: 100%;
flex-grow: 1;
overflow-y: scroll;
border-radius: @border-rad-sm;
border: 1px solid @grey-15;
padding: @padding-md;
background-color: @white;
.data-observability-content-panel {
margin-top: @margin-mlg;
}
}

View File

@ -128,6 +128,7 @@ import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
import { TabProps } from '../components/common/TabsLabel/TabsLabel.interface';
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
import DataObservabilityTab from '../components/Database/Profiler/DataObservability/DataObservabilityTab';
import TableProfiler from '../components/Database/Profiler/TableProfiler/TableProfiler';
import SampleDataTableComponent from '../components/Database/SampleDataTable/SampleDataTable.component';
import SchemaTable from '../components/Database/SchemaTable/SchemaTable.component';
@ -867,6 +868,22 @@ export const getTableDetailPageBaseTabs = ({
/>
),
},
{
label: (
<TabsLabel
id={EntityTabs.PROFILER + 'old'}
name={get(
labelMap,
EntityTabs.PROFILER,
t('label.data-observability')
)}
/>
),
key: EntityTabs.PROFILER + 'old',
children: (
<TableProfiler permissions={tablePermissions} table={tableDetails} />
),
},
{
label: (
<TabsLabel
@ -880,7 +897,10 @@ export const getTableDetailPageBaseTabs = ({
),
key: EntityTabs.PROFILER,
children: (
<TableProfiler permissions={tablePermissions} table={tableDetails} />
<DataObservabilityTab
permissions={tablePermissions}
table={tableDetails}
/>
),
},
{