mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-11 00:11:05 +00:00
feat: add Data Observability Tab component and integrate into TableUtils
This commit is contained in:
parent
296bc99c42
commit
4ac528dd36
@ -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;
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -128,6 +128,7 @@ import TabsLabel from '../components/common/TabsLabel/TabsLabel.component';
|
|||||||
import { TabProps } from '../components/common/TabsLabel/TabsLabel.interface';
|
import { TabProps } from '../components/common/TabsLabel/TabsLabel.interface';
|
||||||
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
|
import { GenericTab } from '../components/Customization/GenericTab/GenericTab';
|
||||||
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
|
import { CommonWidgets } from '../components/DataAssets/CommonWidgets/CommonWidgets';
|
||||||
|
import DataObservabilityTab from '../components/Database/Profiler/DataObservability/DataObservabilityTab';
|
||||||
import TableProfiler from '../components/Database/Profiler/TableProfiler/TableProfiler';
|
import TableProfiler from '../components/Database/Profiler/TableProfiler/TableProfiler';
|
||||||
import SampleDataTableComponent from '../components/Database/SampleDataTable/SampleDataTable.component';
|
import SampleDataTableComponent from '../components/Database/SampleDataTable/SampleDataTable.component';
|
||||||
import SchemaTable from '../components/Database/SchemaTable/SchemaTable.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: (
|
label: (
|
||||||
<TabsLabel
|
<TabsLabel
|
||||||
@ -880,7 +897,10 @@ export const getTableDetailPageBaseTabs = ({
|
|||||||
),
|
),
|
||||||
key: EntityTabs.PROFILER,
|
key: EntityTabs.PROFILER,
|
||||||
children: (
|
children: (
|
||||||
<TableProfiler permissions={tablePermissions} table={tableDetails} />
|
<DataObservabilityTab
|
||||||
|
permissions={tablePermissions}
|
||||||
|
table={tableDetails}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user