mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-09 16:03:31 +00:00
feat(ui) Use new Tabs component on entity profile pages (#13640)
This commit is contained in:
parent
b9b97e4bfe
commit
d505ed7c24
@ -7,7 +7,7 @@ import { Tooltip } from '@components/components/Tooltip';
|
|||||||
|
|
||||||
import { colors } from '@src/alchemy-components/theme';
|
import { colors } from '@src/alchemy-components/theme';
|
||||||
|
|
||||||
const StyledTabs = styled(AntTabs)`
|
const StyledTabs = styled(AntTabs)<{ $addPaddingLeft?: boolean; $hideTabsHeader: boolean }>`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@ -17,9 +17,26 @@ const StyledTabs = styled(AntTabs)`
|
|||||||
color: ${colors.gray[600]};
|
color: ${colors.gray[600]};
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-tabs-tab + .ant-tabs-tab {
|
${({ $addPaddingLeft }) =>
|
||||||
margin-left: 16px;
|
$addPaddingLeft
|
||||||
}
|
? `
|
||||||
|
.ant-tabs-tab {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
: `
|
||||||
|
.ant-tabs-tab + .ant-tabs-tab {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
|
||||||
|
${({ $hideTabsHeader }) =>
|
||||||
|
$hideTabsHeader &&
|
||||||
|
`
|
||||||
|
.ant-tabs-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
|
||||||
.ant-tabs-tab-active .ant-tabs-tab-btn {
|
.ant-tabs-tab-active .ant-tabs-tab-btn {
|
||||||
color: ${(props) => props.theme.styles['primary-color']};
|
color: ${(props) => props.theme.styles['primary-color']};
|
||||||
@ -43,16 +60,17 @@ const StyledTabs = styled(AntTabs)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TabViewWrapper = styled.div`
|
const TabViewWrapper = styled.div<{ $disabled?: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 4px;
|
||||||
|
${({ $disabled }) => $disabled && `color: ${colors.gray[1800]};`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function TabView({ tab }: { tab: Tab }) {
|
function TabView({ tab }: { tab: Tab }) {
|
||||||
return (
|
return (
|
||||||
<Tooltip title={tab.tooltip}>
|
<Tooltip title={tab.tooltip}>
|
||||||
<TabViewWrapper id={tab.id}>
|
<TabViewWrapper id={tab.id} $disabled={tab.disabled} data-testid={tab.dataTestId}>
|
||||||
{tab.name}
|
{tab.name}
|
||||||
{!!tab.count && <Pill label={`${tab.count}`} size="xs" color="violet" />}
|
{!!tab.count && <Pill label={`${tab.count}`} size="xs" color="violet" />}
|
||||||
</TabViewWrapper>
|
</TabViewWrapper>
|
||||||
@ -68,6 +86,8 @@ export interface Tab {
|
|||||||
onSelectTab?: () => void;
|
onSelectTab?: () => void;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
dataTestId?: string;
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -78,6 +98,8 @@ export interface Props {
|
|||||||
onUrlChange?: (url: string) => void;
|
onUrlChange?: (url: string) => void;
|
||||||
defaultTab?: string;
|
defaultTab?: string;
|
||||||
getCurrentUrl?: () => string;
|
getCurrentUrl?: () => string;
|
||||||
|
addPaddingLeft?: boolean;
|
||||||
|
hideTabsHeader?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tabs({
|
export function Tabs({
|
||||||
@ -88,6 +110,8 @@ export function Tabs({
|
|||||||
onUrlChange = (url) => window.history.replaceState({}, '', url),
|
onUrlChange = (url) => window.history.replaceState({}, '', url),
|
||||||
defaultTab,
|
defaultTab,
|
||||||
getCurrentUrl = () => window.location.pathname,
|
getCurrentUrl = () => window.location.pathname,
|
||||||
|
addPaddingLeft,
|
||||||
|
hideTabsHeader,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { TabPane } = AntTabs;
|
const { TabPane } = AntTabs;
|
||||||
|
|
||||||
@ -128,10 +152,15 @@ export function Tabs({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledTabs activeKey={selectedTab} onChange={handleTabClick}>
|
<StyledTabs
|
||||||
|
activeKey={selectedTab}
|
||||||
|
onChange={handleTabClick}
|
||||||
|
$addPaddingLeft={addPaddingLeft}
|
||||||
|
$hideTabsHeader={!!hideTabsHeader}
|
||||||
|
>
|
||||||
{tabs.map((tab) => {
|
{tabs.map((tab) => {
|
||||||
return (
|
return (
|
||||||
<TabPane tab={<TabView tab={tab} />} key={tab.key}>
|
<TabPane tab={<TabView tab={tab} />} key={tab.key} disabled={tab.disabled}>
|
||||||
{tab.component}
|
{tab.component}
|
||||||
</TabPane>
|
</TabPane>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import { getDataForEntityType } from '@app/entityV2/shared/containers/profile/ut
|
|||||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
|
|
||||||
import { useGetApplicationQuery } from '@graphql/application.generated';
|
import { useGetApplicationQuery } from '@graphql/application.generated';
|
||||||
@ -115,9 +114,8 @@ export class ApplicationEntity implements Entity<Application> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Assets',
|
name: 'Assets',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _, loading) => {
|
||||||
const assetCount = entityData?.children?.total;
|
return !loading ? entityData?.children?.total : undefined;
|
||||||
return <TabNameWithCount name="Assets" count={assetCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
component: ApplicationEntitiesTab,
|
component: ApplicationEntitiesTab,
|
||||||
icon: AppstoreOutlined,
|
icon: AppstoreOutlined,
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import TabToolbar from '@app/entity/shared/components/styled/TabToolbar';
|
|||||||
import { ANTD_GRAY } from '@app/entity/shared/constants';
|
import { ANTD_GRAY } from '@app/entity/shared/constants';
|
||||||
import { TestResults } from '@app/entity/shared/tabs/Dataset/Governance/TestResults';
|
import { TestResults } from '@app/entity/shared/tabs/Dataset/Governance/TestResults';
|
||||||
import { useGetValidationsTab } from '@app/entity/shared/tabs/Dataset/Validations/useGetValidationsTab';
|
import { useGetValidationsTab } from '@app/entity/shared/tabs/Dataset/Validations/useGetValidationsTab';
|
||||||
|
import { GOVERNANCE_TAB_NAME } from '@app/entityV2/dataset/constants';
|
||||||
|
|
||||||
const TabTitle = styled.span`
|
const TabTitle = styled.span`
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
@ -41,7 +42,7 @@ export const GovernanceTab = () => {
|
|||||||
|
|
||||||
// If no tab was selected, select a default tab.
|
// If no tab was selected, select a default tab.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedTab) {
|
if (!selectedTab && basePath.endsWith(GOVERNANCE_TAB_NAME)) {
|
||||||
// Route to the default tab.
|
// Route to the default tab.
|
||||||
history.replace(`${basePath}/${DEFAULT_TAB}`);
|
history.replace(`${basePath}/${DEFAULT_TAB}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
|||||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
|
|
||||||
import { useGetApplicationQuery } from '@graphql/application.generated';
|
import { useGetApplicationQuery } from '@graphql/application.generated';
|
||||||
@ -106,9 +105,8 @@ export class ApplicationEntity implements Entity<Application> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Assets',
|
name: 'Assets',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _, loading) => {
|
||||||
const assetCount = entityData?.children?.total;
|
return !loading ? entityData?.children?.total : undefined;
|
||||||
return <TabNameWithCount name="Assets" count={assetCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
component: ApplicationEntitiesTab,
|
component: ApplicationEntitiesTab,
|
||||||
icon: AppstoreOutlined,
|
icon: AppstoreOutlined,
|
||||||
|
|||||||
@ -39,7 +39,6 @@ import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/Docume
|
|||||||
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
||||||
import { ChartDashboardsTab } from '@app/entityV2/shared/tabs/Entity/ChartDashboardsTab';
|
import { ChartDashboardsTab } from '@app/entityV2/shared/tabs/Entity/ChartDashboardsTab';
|
||||||
import { InputFieldsTab } from '@app/entityV2/shared/tabs/Entity/InputFieldsTab';
|
import { InputFieldsTab } from '@app/entityV2/shared/tabs/Entity/InputFieldsTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -197,9 +196,8 @@ export class ChartEntity implements Entity<Chart> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
getDynamicName: (_, chart, loading) => {
|
getCount: (_, chart, loading) => {
|
||||||
const activeIncidentCount = chart?.chart?.activeIncidents?.total;
|
return !loading ? chart?.chart?.activeIncidents?.total : undefined;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
icon: WarningOutlined,
|
icon: WarningOutlined,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
|
|||||||
@ -40,7 +40,6 @@ import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/Docume
|
|||||||
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
||||||
import { DashboardChartsTab } from '@app/entityV2/shared/tabs/Entity/DashboardChartsTab';
|
import { DashboardChartsTab } from '@app/entityV2/shared/tabs/Entity/DashboardChartsTab';
|
||||||
import { DashboardDatasetsTab } from '@app/entityV2/shared/tabs/Entity/DashboardDatasetsTab';
|
import { DashboardDatasetsTab } from '@app/entityV2/shared/tabs/Entity/DashboardDatasetsTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -193,9 +192,8 @@ export class DashboardEntity implements Entity<Dashboard> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningOutlined,
|
icon: WarningOutlined,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, dashboard, loading) => {
|
getCount: (_, dashboard) => {
|
||||||
const activeIncidentCount = dashboard?.dashboard?.activeIncidents?.total;
|
return dashboard?.dashboard?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNote
|
|||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import { DataFlowJobsTab } from '@app/entityV2/shared/tabs/Entity/DataFlowJobsTab';
|
import { DataFlowJobsTab } from '@app/entityV2/shared/tabs/Entity/DataFlowJobsTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
import { getDataProduct, isOutputPort } from '@app/entityV2/shared/utils';
|
import { getDataProduct, isOutputPort } from '@app/entityV2/shared/utils';
|
||||||
@ -110,9 +109,8 @@ export class DataFlowEntity implements Entity<DataFlow> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningCircle,
|
icon: WarningCircle,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, dataFlow, loading) => {
|
getCount: (_, dataFlow) => {
|
||||||
const activeIncidentCount = dataFlow?.dataFlow?.activeIncidents?.total;
|
return dataFlow?.dataFlow?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNote
|
|||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import { DataJobFlowTab } from '@app/entityV2/shared/tabs/Entity/DataJobFlowTab';
|
import { DataJobFlowTab } from '@app/entityV2/shared/tabs/Entity/DataJobFlowTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -142,9 +141,8 @@ export class DataJobEntity implements Entity<DataJob> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningCircle,
|
icon: WarningCircle,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, dataJob, loading) => {
|
getCount: (_, dataJob) => {
|
||||||
const activeIncidentCount = dataJob?.dataJob?.activeIncidents?.total;
|
return dataJob?.dataJob?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -30,7 +30,6 @@ import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
|||||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
|
|
||||||
import { useGetDataProductQuery } from '@graphql/dataProduct.generated';
|
import { useGetDataProductQuery } from '@graphql/dataProduct.generated';
|
||||||
@ -118,9 +117,8 @@ export class DataProductEntity implements Entity<DataProduct> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Assets',
|
name: 'Assets',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _) => {
|
||||||
const assetCount = entityData?.entities?.total;
|
return entityData?.entities?.total;
|
||||||
return <TabNameWithCount name="Assets" count={assetCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
component: DataProductEntitiesTab,
|
component: DataProductEntitiesTab,
|
||||||
icon: AppstoreOutlined,
|
icon: AppstoreOutlined,
|
||||||
|
|||||||
@ -17,9 +17,11 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { GenericEntityProperties } from '@app/entity/shared/types';
|
import { GenericEntityProperties } from '@app/entity/shared/types';
|
||||||
import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '@app/entityV2/Entity';
|
import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '@app/entityV2/Entity';
|
||||||
|
import { GOVERNANCE_TAB_NAME, QUALITY_TAB_NAME } from '@app/entityV2/dataset/constants';
|
||||||
import { Preview } from '@app/entityV2/dataset/preview/Preview';
|
import { Preview } from '@app/entityV2/dataset/preview/Preview';
|
||||||
import { OperationsTab } from '@app/entityV2/dataset/profile/OperationsTab';
|
import { OperationsTab } from '@app/entityV2/dataset/profile/OperationsTab';
|
||||||
import { DatasetStatsSummarySubHeader } from '@app/entityV2/dataset/profile/stats/stats/DatasetStatsSummarySubHeader';
|
import { DatasetStatsSummarySubHeader } from '@app/entityV2/dataset/profile/stats/stats/DatasetStatsSummarySubHeader';
|
||||||
|
import { useGetColumnTabCount } from '@app/entityV2/dataset/profile/useGetColumnTabCount';
|
||||||
import { EntityMenuItems } from '@app/entityV2/shared/EntityDropdown/EntityMenuActions';
|
import { EntityMenuItems } from '@app/entityV2/shared/EntityDropdown/EntityMenuActions';
|
||||||
import { SubType, TYPE_ICON_CLASS_NAME } from '@app/entityV2/shared/components/subtypes';
|
import { SubType, TYPE_ICON_CLASS_NAME } from '@app/entityV2/shared/components/subtypes';
|
||||||
import { EntityProfile } from '@app/entityV2/shared/containers/profile/EntityProfile';
|
import { EntityProfile } from '@app/entityV2/shared/containers/profile/EntityProfile';
|
||||||
@ -49,8 +51,6 @@ import { AcrylValidationsTab } from '@app/entityV2/shared/tabs/Dataset/Validatio
|
|||||||
import ViewDefinitionTab from '@app/entityV2/shared/tabs/Dataset/View/ViewDefinitionTab';
|
import ViewDefinitionTab from '@app/entityV2/shared/tabs/Dataset/View/ViewDefinitionTab';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
import { EmbedTab } from '@app/entityV2/shared/tabs/Embed/EmbedTab';
|
||||||
import ColumnTabNameHeader from '@app/entityV2/shared/tabs/Entity/ColumnTabNameHeader';
|
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -156,7 +156,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
name: 'Columns',
|
name: 'Columns',
|
||||||
component: SchemaTab,
|
component: SchemaTab,
|
||||||
icon: LayoutOutlined,
|
icon: LayoutOutlined,
|
||||||
getDynamicName: ColumnTabNameHeader,
|
getCount: useGetColumnTabCount,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'View Definition',
|
name: 'View Definition',
|
||||||
@ -203,12 +203,12 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
name: 'Properties',
|
name: 'Properties',
|
||||||
component: PropertiesTab,
|
component: PropertiesTab,
|
||||||
icon: UnorderedListOutlined,
|
icon: UnorderedListOutlined,
|
||||||
getDynamicName: (_, dataset: GetDatasetQuery, loading) => {
|
getCount: (_, dataset: GetDatasetQuery) => {
|
||||||
const customPropertiesCount = dataset?.dataset?.properties?.customProperties?.length || 0;
|
const customPropertiesCount = dataset?.dataset?.properties?.customProperties?.length || 0;
|
||||||
const structuredPropertiesCount =
|
const structuredPropertiesCount =
|
||||||
dataset?.dataset?.structuredProperties?.properties?.length || 0;
|
dataset?.dataset?.structuredProperties?.properties?.length || 0;
|
||||||
const propertiesCount = customPropertiesCount + structuredPropertiesCount;
|
const propertiesCount = customPropertiesCount + structuredPropertiesCount;
|
||||||
return <TabNameWithCount name="Properties" count={propertiesCount} loading={loading} />;
|
return propertiesCount;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -234,12 +234,12 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Quality',
|
name: QUALITY_TAB_NAME,
|
||||||
component: AcrylValidationsTab, // Use SaaS specific Validations Tab.
|
component: AcrylValidationsTab, // Use SaaS specific Validations Tab.
|
||||||
icon: CheckCircleOutlined,
|
icon: CheckCircleOutlined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Governance',
|
name: GOVERNANCE_TAB_NAME,
|
||||||
icon: () => (
|
icon: () => (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
@ -268,9 +268,8 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningOutlined,
|
icon: WarningOutlined,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, dataset, loading) => {
|
getCount: (_, dataset) => {
|
||||||
const activeIncidentCount = dataset?.dataset?.activeIncidents?.total;
|
return dataset?.dataset?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|||||||
2
datahub-web-react/src/app/entityV2/dataset/constants.ts
Normal file
2
datahub-web-react/src/app/entityV2/dataset/constants.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const GOVERNANCE_TAB_NAME = 'Governance';
|
||||||
|
export const QUALITY_TAB_NAME = 'Quality';
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { useGetEntityWithSchema } from '@app/entityV2/shared/tabs/Dataset/Schema/useGetEntitySchema';
|
||||||
|
|
||||||
|
export const useGetColumnTabCount = () => {
|
||||||
|
const { entityWithSchema, loading } = useGetEntityWithSchema();
|
||||||
|
const fieldsCount = entityWithSchema?.schemaMetadata?.fields?.length || 0;
|
||||||
|
|
||||||
|
return !loading ? fieldsCount : undefined;
|
||||||
|
};
|
||||||
@ -22,7 +22,6 @@ import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNote
|
|||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { SUMMARY_TAB_ICON } from '@app/entityV2/shared/summary/HeaderComponents';
|
import { SUMMARY_TAB_ICON } from '@app/entityV2/shared/summary/HeaderComponents';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
|
|
||||||
import { useGetDomainQuery } from '@graphql/domain.generated';
|
import { useGetDomainQuery } from '@graphql/domain.generated';
|
||||||
@ -111,9 +110,8 @@ export class DomainEntity implements Entity<Domain> {
|
|||||||
{
|
{
|
||||||
id: EntityProfileTab.DOMAIN_ENTITIES_TAB,
|
id: EntityProfileTab.DOMAIN_ENTITIES_TAB,
|
||||||
name: 'Assets',
|
name: 'Assets',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _) => {
|
||||||
const assetCount = entityData?.entities?.total;
|
return entityData?.entities?.total;
|
||||||
return <TabNameWithCount name="Assets" count={assetCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
component: DomainEntitiesTab,
|
component: DomainEntitiesTab,
|
||||||
icon: AppstoreOutlined,
|
icon: AppstoreOutlined,
|
||||||
@ -127,9 +125,8 @@ export class DomainEntity implements Entity<Domain> {
|
|||||||
{
|
{
|
||||||
id: EntityProfileTab.DATA_PRODUCTS_TAB,
|
id: EntityProfileTab.DATA_PRODUCTS_TAB,
|
||||||
name: 'Data Products',
|
name: 'Data Products',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _) => {
|
||||||
const dataProductsCount = entityData?.dataProducts?.total;
|
return entityData?.dataProducts?.total;
|
||||||
return <TabNameWithCount name="Data Products" count={dataProductsCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
component: DataProductsTab,
|
component: DataProductsTab,
|
||||||
icon: FileDoneOutlined,
|
icon: FileDoneOutlined,
|
||||||
|
|||||||
@ -4,11 +4,11 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { GenericEntityProperties } from '@app/entity/shared/types';
|
import { GenericEntityProperties } from '@app/entity/shared/types';
|
||||||
import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '@app/entityV2/Entity';
|
import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '@app/entityV2/Entity';
|
||||||
import GlossaryRelatedAssetsTabHeader from '@app/entityV2/glossaryTerm/GlossaryRelatedAssetsTabHeader';
|
|
||||||
import { Preview } from '@app/entityV2/glossaryTerm/preview/Preview';
|
import { Preview } from '@app/entityV2/glossaryTerm/preview/Preview';
|
||||||
import GlossaryRelatedEntity from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedEntity';
|
import GlossaryRelatedEntity from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedEntity';
|
||||||
import GlossayRelatedTerms from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedTerms';
|
import GlossayRelatedTerms from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedTerms';
|
||||||
import { RelatedTermTypes } from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedTermsResult';
|
import { RelatedTermTypes } from '@app/entityV2/glossaryTerm/profile/GlossaryRelatedTermsResult';
|
||||||
|
import useGlossaryRelatedAssetsTabCount from '@app/entityV2/glossaryTerm/profile/useGlossaryRelatedAssetsTabCount';
|
||||||
import { EntityMenuItems } from '@app/entityV2/shared/EntityDropdown/EntityMenuActions';
|
import { EntityMenuItems } from '@app/entityV2/shared/EntityDropdown/EntityMenuActions';
|
||||||
import { TYPE_ICON_CLASS_NAME } from '@app/entityV2/shared/components/subtypes';
|
import { TYPE_ICON_CLASS_NAME } from '@app/entityV2/shared/components/subtypes';
|
||||||
import { EntityProfile } from '@app/entityV2/shared/containers/profile/EntityProfile';
|
import { EntityProfile } from '@app/entityV2/shared/containers/profile/EntityProfile';
|
||||||
@ -24,7 +24,6 @@ import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNote
|
|||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { SchemaTab } from '@app/entityV2/shared/tabs/Dataset/Schema/SchemaTab';
|
import { SchemaTab } from '@app/entityV2/shared/tabs/Dataset/Schema/SchemaTab';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
import { FetchedEntity } from '@app/lineage/types';
|
import { FetchedEntity } from '@app/lineage/types';
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ export class GlossaryTermEntity implements Entity<GlossaryTerm> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Related Assets',
|
name: 'Related Assets',
|
||||||
getDynamicName: GlossaryRelatedAssetsTabHeader,
|
getCount: useGlossaryRelatedAssetsTabCount,
|
||||||
component: GlossaryRelatedEntity,
|
component: GlossaryRelatedEntity,
|
||||||
icon: AppstoreOutlined,
|
icon: AppstoreOutlined,
|
||||||
},
|
},
|
||||||
@ -130,13 +129,11 @@ export class GlossaryTermEntity implements Entity<GlossaryTerm> {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Related Terms',
|
name: 'Related Terms',
|
||||||
getDynamicName: (entityData, _, loading) => {
|
getCount: (entityData, _, loading) => {
|
||||||
const totalRelatedTerms = Object.keys(RelatedTermTypes).reduce((acc, curr) => {
|
const totalRelatedTerms = Object.keys(RelatedTermTypes).reduce((acc, curr) => {
|
||||||
return acc + (entityData?.[curr]?.total || 0);
|
return acc + (entityData?.[curr]?.total || 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
return (
|
return !loading ? totalRelatedTerms : undefined;
|
||||||
<TabNameWithCount name="Related Terms" count={totalRelatedTerms} loading={loading} />
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
component: GlossayRelatedTerms,
|
component: GlossayRelatedTerms,
|
||||||
icon: () => <BookmarkSimple style={{ marginRight: 6 }} />,
|
icon: () => <BookmarkSimple style={{ marginRight: 6 }} />,
|
||||||
|
|||||||
@ -1,21 +1,7 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import { Pill } from '@src/alchemy-components';
|
|
||||||
import { useEntityData } from '@src/app/entity/shared/EntityContext';
|
import { useEntityData } from '@src/app/entity/shared/EntityContext';
|
||||||
import { formatNumber } from '@src/app/shared/formatNumber';
|
|
||||||
import { useGetSearchResultsForMultipleQuery } from '@src/graphql/search.generated';
|
import { useGetSearchResultsForMultipleQuery } from '@src/graphql/search.generated';
|
||||||
|
|
||||||
const Styled = styled.div`
|
export default function useGlossaryRelatedAssetsTabCount() {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TabName = styled.div`
|
|
||||||
padding-right: 4px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
function GlossaryRelatedAssetsTabHeader() {
|
|
||||||
const { entityData } = useEntityData();
|
const { entityData } = useEntityData();
|
||||||
|
|
||||||
// To get the number of related assets
|
// To get the number of related assets
|
||||||
@ -44,12 +30,5 @@ function GlossaryRelatedAssetsTabHeader() {
|
|||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return data?.searchAcrossEntities?.total || 0;
|
||||||
<Styled>
|
|
||||||
<TabName>Related Assets</TabName>
|
|
||||||
<Pill label={formatNumber(data?.searchAcrossEntities?.total || 0)} />
|
|
||||||
</Styled>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GlossaryRelatedAssetsTabHeader;
|
|
||||||
@ -21,7 +21,6 @@ import { getDataForEntityType } from '@app/entityV2/shared/containers/profile/ut
|
|||||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { FeatureTableTab } from '@app/entityV2/shared/tabs/ML/MlFeatureFeatureTableTab';
|
import { FeatureTableTab } from '@app/entityV2/shared/tabs/ML/MlFeatureFeatureTableTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -128,9 +127,8 @@ export class MLFeatureEntity implements Entity<MlFeature> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningCircle,
|
icon: WarningCircle,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, mlFeature, loading) => {
|
getCount: (_, mlFeature) => {
|
||||||
const activeIncidentCount = mlFeature?.mlFeature?.activeIncidents?.total;
|
return mlFeature?.mlFeature?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -68,8 +68,7 @@ export default function SourcesView() {
|
|||||||
</ViewRawButtonContainer>
|
</ViewRawButtonContainer>
|
||||||
</div>
|
</div>
|
||||||
<List
|
<List
|
||||||
style={{ marginTop: '24px', padding: '16px 32px' }}
|
style={{ padding: '0 32px 16px 32px' }}
|
||||||
bordered
|
|
||||||
dataSource={sources}
|
dataSource={sources}
|
||||||
header={<Typography.Title level={3}>Sources</Typography.Title>}
|
header={<Typography.Title level={3}>Sources</Typography.Title>}
|
||||||
renderItem={(item) => (
|
renderItem={(item) => (
|
||||||
|
|||||||
@ -24,7 +24,6 @@ import { getDataForEntityType } from '@app/entityV2/shared/containers/profile/ut
|
|||||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
import { IncidentTab } from '@app/entityV2/shared/tabs/Incident/IncidentTab';
|
||||||
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
import { LineageTab } from '@app/entityV2/shared/tabs/Lineage/LineageTab';
|
||||||
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
import { PropertiesTab } from '@app/entityV2/shared/tabs/Properties/PropertiesTab';
|
||||||
@ -135,9 +134,8 @@ export class MLModelEntity implements Entity<MlModel> {
|
|||||||
name: 'Incidents',
|
name: 'Incidents',
|
||||||
icon: WarningOutlined,
|
icon: WarningOutlined,
|
||||||
component: IncidentTab,
|
component: IncidentTab,
|
||||||
getDynamicName: (_, mlModel, loading) => {
|
getCount: (_, mlModel) => {
|
||||||
const activeIncidentCount = mlModel?.mlModel?.activeIncidents?.total;
|
return mlModel?.mlModel?.activeIncidents?.total;
|
||||||
return <TabNameWithCount name="Incidents" count={activeIncidentCount} loading={loading} />;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -30,13 +30,7 @@ import {
|
|||||||
import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
||||||
import NonExistentEntityPage from '@app/entityV2/shared/entity/NonExistentEntityPage';
|
import NonExistentEntityPage from '@app/entityV2/shared/entity/NonExistentEntityPage';
|
||||||
import DynamicTab from '@app/entityV2/shared/tabs/Entity/weaklyTypedAspects/DynamicTab';
|
import DynamicTab from '@app/entityV2/shared/tabs/Entity/weaklyTypedAspects/DynamicTab';
|
||||||
import {
|
import { EntitySidebarSection, EntitySidebarTab, EntityTab, TabContextType } from '@app/entityV2/shared/types';
|
||||||
EntitySidebarSection,
|
|
||||||
EntitySidebarTab,
|
|
||||||
EntityTab,
|
|
||||||
TabContextType,
|
|
||||||
TabRenderType,
|
|
||||||
} from '@app/entityV2/shared/types';
|
|
||||||
import { useIsSeparateSiblingsMode } from '@app/entityV2/shared/useIsSeparateSiblingsMode';
|
import { useIsSeparateSiblingsMode } from '@app/entityV2/shared/useIsSeparateSiblingsMode';
|
||||||
import VersionsDrawer from '@app/entityV2/shared/versioning/VersionsDrawer';
|
import VersionsDrawer from '@app/entityV2/shared/versioning/VersionsDrawer';
|
||||||
import LineageExplorer from '@app/lineage/LineageExplorer';
|
import LineageExplorer from '@app/lineage/LineageExplorer';
|
||||||
@ -155,6 +149,7 @@ const Body = styled.div<{ $isShowNavBarRedesign?: boolean }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const BodyContent = styled.div<{ $isShowNavBarRedesign?: boolean }>`
|
const BodyContent = styled.div<{ $isShowNavBarRedesign?: boolean }>`
|
||||||
|
padding-top: 12px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: ${(props) =>
|
border-radius: ${(props) =>
|
||||||
props.$isShowNavBarRedesign ? props.theme.styles['border-radius-navbar-redesign'] : '8px'};
|
props.$isShowNavBarRedesign ? props.theme.styles['border-radius-navbar-redesign'] : '8px'};
|
||||||
@ -169,15 +164,6 @@ const BodyContent = styled.div<{ $isShowNavBarRedesign?: boolean }>`
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TabsWrapper = styled.div``;
|
|
||||||
|
|
||||||
const TabContent = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex: 1;
|
|
||||||
overflow: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledAlert = styled(Alert)`
|
const StyledAlert = styled(Alert)`
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -406,20 +392,7 @@ export const EntityProfile = <T, U>({
|
|||||||
)}
|
)}
|
||||||
<Body $isShowNavBarRedesign={isShowNavBarRedesign}>
|
<Body $isShowNavBarRedesign={isShowNavBarRedesign}>
|
||||||
<BodyContent $isShowNavBarRedesign={isShowNavBarRedesign}>
|
<BodyContent $isShowNavBarRedesign={isShowNavBarRedesign}>
|
||||||
{!isTabFullsize && (
|
<EntityTabs tabs={visibleTabs} selectedTab={routedTab} />
|
||||||
<TabsWrapper>
|
|
||||||
<EntityTabs tabs={visibleTabs} selectedTab={routedTab} />
|
|
||||||
</TabsWrapper>
|
|
||||||
)}
|
|
||||||
<TabContent>
|
|
||||||
{routedTab && (
|
|
||||||
<routedTab.component
|
|
||||||
properties={routedTab.properties}
|
|
||||||
contextType={TabContextType.PROFILE}
|
|
||||||
renderType={TabRenderType.DEFAULT}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TabContent>
|
|
||||||
</BodyContent>
|
</BodyContent>
|
||||||
</Body>
|
</Body>
|
||||||
</HeaderAndTabsFlex>
|
</HeaderAndTabsFlex>
|
||||||
|
|||||||
@ -1,82 +1,31 @@
|
|||||||
import { Tabs } from 'antd';
|
import { Tabs } from '@components';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useContext, useEffect } from 'react';
|
||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
|
|
||||||
|
import { Tab } from '@components/components/Tabs/Tabs';
|
||||||
|
|
||||||
import { useBaseEntity, useEntityData, useRouteToTab } from '@app/entity/shared/EntityContext';
|
import { useBaseEntity, useEntityData, useRouteToTab } from '@app/entity/shared/EntityContext';
|
||||||
import { EntityTab } from '@app/entityV2/shared/types';
|
import { EntityTab, TabContextType, TabRenderType } from '@app/entityV2/shared/types';
|
||||||
|
import TabFullsizedContext from '@app/shared/TabFullsizedContext';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
tabs: EntityTab[];
|
tabs: EntityTab[];
|
||||||
selectedTab?: EntityTab;
|
selectedTab?: EntityTab;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = styled.div`
|
const TabContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const UnborderedTabs = styled(Tabs)`
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 14px 10px 12px;
|
|
||||||
|
|
||||||
&&& .ant-tabs-nav {
|
|
||||||
margin-bottom: 0;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-nav-wrap {
|
|
||||||
background-color: #f6f7fa;
|
|
||||||
border-radius: 4px;
|
|
||||||
gap: 3px;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-tab {
|
|
||||||
padding: 10px 16px;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-tab-active {
|
|
||||||
background-color: ${(p) => p.theme.styles['primary-color']};
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-tab-active .ant-tabs-tab-btn {
|
|
||||||
color: #ffffff;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-ink-bar {
|
|
||||||
height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&&& .ant-tabs-content-holder {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
background-color: #ffffff;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Tab = styled(Tabs.TabPane)`
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const tabIconStyle = { fontSize: 14, marginRight: 6 };
|
|
||||||
|
|
||||||
export const EntityTabs = <T,>({ tabs, selectedTab }: Props) => {
|
export const EntityTabs = <T,>({ tabs, selectedTab }: Props) => {
|
||||||
const { entityData, loading } = useEntityData();
|
const { entityData, loading } = useEntityData();
|
||||||
const routeToTab = useRouteToTab();
|
const routeToTab = useRouteToTab();
|
||||||
const baseEntity = useBaseEntity<T>();
|
const baseEntity = useBaseEntity<T>();
|
||||||
|
const { isTabFullsize } = useContext(TabFullsizedContext);
|
||||||
|
|
||||||
const enabledTabs = tabs.filter((tab) => tab.display?.enabled(entityData, baseEntity));
|
const enabledTabs = tabs.filter((tab) => tab.display?.enabled(entityData, baseEntity));
|
||||||
|
|
||||||
@ -86,42 +35,30 @@ export const EntityTabs = <T,>({ tabs, selectedTab }: Props) => {
|
|||||||
}
|
}
|
||||||
}, [loading, enabledTabs, selectedTab, routeToTab]);
|
}, [loading, enabledTabs, selectedTab, routeToTab]);
|
||||||
|
|
||||||
|
const finalTabs: Tab[] = tabs.map((t) => ({
|
||||||
|
key: t.name,
|
||||||
|
name: t.name,
|
||||||
|
component: (
|
||||||
|
<TabContent>
|
||||||
|
<t.component
|
||||||
|
properties={t.properties}
|
||||||
|
contextType={TabContextType.PROFILE}
|
||||||
|
renderType={TabRenderType.DEFAULT}
|
||||||
|
/>
|
||||||
|
</TabContent>
|
||||||
|
),
|
||||||
|
disabled: !t.display?.enabled(entityData, baseEntity),
|
||||||
|
dataTestId: `${t.name}-entity-tab-header`,
|
||||||
|
count: t.getCount?.(entityData, baseEntity, loading),
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UnborderedTabs
|
<Tabs
|
||||||
animated={false}
|
onChange={(t) => routeToTab({ tabName: t })}
|
||||||
activeKey={selectedTab?.name || ''}
|
selectedTab={selectedTab?.name}
|
||||||
size="large"
|
tabs={finalTabs}
|
||||||
onTabClick={(tab: string) => routeToTab({ tabName: tab })}
|
hideTabsHeader={isTabFullsize}
|
||||||
>
|
addPaddingLeft
|
||||||
{tabs.map((tab) => {
|
/>
|
||||||
const TabIcon = tab.icon;
|
|
||||||
const tabName = (tab.getDynamicName && tab.getDynamicName(entityData, baseEntity, loading)) || tab.name;
|
|
||||||
if (!tab.display?.enabled(entityData, baseEntity)) {
|
|
||||||
return (
|
|
||||||
<Tab
|
|
||||||
tab={
|
|
||||||
<span data-testid={`${tab.name}-entity-tab-header`}>
|
|
||||||
{TabIcon && <TabIcon style={tabIconStyle} />}
|
|
||||||
{tab.name}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
key={tab.name}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Tab
|
|
||||||
tab={
|
|
||||||
<Header data-testid={`${tab.name}-entity-tab-header`}>
|
|
||||||
{TabIcon && <TabIcon style={tabIconStyle} />}
|
|
||||||
{tabName}
|
|
||||||
</Header>
|
|
||||||
}
|
|
||||||
key={tab.name}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</UnborderedTabs>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useHistory, useLocation } from 'react-router';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { useEntityData } from '@app/entity/shared/EntityContext';
|
import { useEntityData } from '@app/entity/shared/EntityContext';
|
||||||
|
import { QUALITY_TAB_NAME } from '@app/entityV2/dataset/constants';
|
||||||
import { AcrylAssertionList } from '@app/entityV2/shared/tabs/Dataset/Validations/AssertionList/AcrylAssertionList';
|
import { AcrylAssertionList } from '@app/entityV2/shared/tabs/Dataset/Validations/AssertionList/AcrylAssertionList';
|
||||||
import { AcrylAssertionSummaryTab } from '@app/entityV2/shared/tabs/Dataset/Validations/AssertionList/Summary/AcrylAssertionSummaryTab';
|
import { AcrylAssertionSummaryTab } from '@app/entityV2/shared/tabs/Dataset/Validations/AssertionList/Summary/AcrylAssertionSummaryTab';
|
||||||
import { DataContractTab } from '@app/entityV2/shared/tabs/Dataset/Validations/contract/DataContractTab';
|
import { DataContractTab } from '@app/entityV2/shared/tabs/Dataset/Validations/contract/DataContractTab';
|
||||||
@ -67,7 +68,7 @@ export const AcrylValidationsTab = () => {
|
|||||||
|
|
||||||
// If no tab was selected, select a default tab.
|
// If no tab was selected, select a default tab.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedTab) {
|
if (!selectedTab && basePath.endsWith(QUALITY_TAB_NAME)) {
|
||||||
// Route to the default tab.
|
// Route to the default tab.
|
||||||
history.replace(`${basePath}/${DEFAULT_TAB}?${SEPARATE_SIBLINGS_URL_PARAM}=${isHideSiblingMode}`);
|
history.replace(`${basePath}/${DEFAULT_TAB}?${SEPARATE_SIBLINGS_URL_PARAM}=${isHideSiblingMode}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { useGetEntityWithSchema } from '@app/entityV2/shared/tabs/Dataset/Schema/useGetEntitySchema';
|
|
||||||
import TabNameWithCount from '@app/entityV2/shared/tabs/Entity/TabNameWithCount';
|
|
||||||
|
|
||||||
const ColumnTabNameHeader = () => {
|
|
||||||
const { entityWithSchema, loading } = useGetEntityWithSchema();
|
|
||||||
const fieldsCount = entityWithSchema?.schemaMetadata?.fields?.length || 0;
|
|
||||||
|
|
||||||
return <TabNameWithCount name="Columns" count={fieldsCount} loading={loading} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ColumnTabNameHeader;
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import { Pill } from '@src/alchemy-components';
|
|
||||||
import { formatNumber } from '@src/app/shared/formatNumber';
|
|
||||||
|
|
||||||
const Container = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const TabName = styled.div`
|
|
||||||
margin-right: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
loading: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const TabNameWithCount = ({ name, count = 0, loading }: Props) => {
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<TabName>{name}</TabName>
|
|
||||||
{!loading && <Pill label={formatNumber(count)} size="sm" />}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default TabNameWithCount;
|
|
||||||
@ -40,7 +40,7 @@ const StyledList = styled(List)`
|
|||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
padding-top: 15px;
|
padding-top: 0px;
|
||||||
}
|
}
|
||||||
` as typeof List;
|
` as typeof List;
|
||||||
|
|
||||||
@ -106,7 +106,6 @@ export const EntityList = ({
|
|||||||
<>
|
<>
|
||||||
<ScrollWrapper>
|
<ScrollWrapper>
|
||||||
<StyledList
|
<StyledList
|
||||||
bordered
|
|
||||||
dataSource={entities}
|
dataSource={entities}
|
||||||
header={title || `${entities.length || 0} ${entityRegistry.getCollectionName(type)}`}
|
header={title || `${entities.length || 0} ${entityRegistry.getCollectionName(type)}`}
|
||||||
renderItem={(item) => (
|
renderItem={(item) => (
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { ReactElement } from 'react';
|
|
||||||
|
|
||||||
export enum TabRenderType {
|
export enum TabRenderType {
|
||||||
/**
|
/**
|
||||||
* A default, full screen tab.
|
* A default, full screen tab.
|
||||||
@ -63,7 +61,7 @@ export type EntityTab = {
|
|||||||
};
|
};
|
||||||
properties?: any;
|
properties?: any;
|
||||||
id?: string;
|
id?: string;
|
||||||
getDynamicName?: (GenericEntityProperties, T, loading: boolean) => ReactElement;
|
getCount?: (GenericEntityProperties, T, loading: boolean) => number | undefined;
|
||||||
supportsFullsize?: boolean; // As per TabFullsizedContext
|
supportsFullsize?: boolean; // As per TabFullsizedContext
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@ describe("glossaryTerm", () => {
|
|||||||
it("can apply filters on related entities", () => {
|
it("can apply filters on related entities", () => {
|
||||||
cy.clickOptionWithText("CypressNode");
|
cy.clickOptionWithText("CypressNode");
|
||||||
cy.clickOptionWithText("GlossaryNewTerm");
|
cy.clickOptionWithText("GlossaryNewTerm");
|
||||||
cy.clickOptionWithSpecificClass(".anticon.anticon-appstore", 0);
|
cy.clickTextOptionWithClass(".ant-tabs-tab", "Related Assets");
|
||||||
elementVisibility();
|
elementVisibility();
|
||||||
cy.clickOptionWithSpecificClass(".anticon-filter", 0);
|
cy.clickOptionWithSpecificClass(".anticon-filter", 0);
|
||||||
cy.waitTextVisible("Filter");
|
cy.waitTextVisible("Filter");
|
||||||
@ -102,7 +102,7 @@ describe("glossaryTerm", () => {
|
|||||||
it("can search related entities by a specific tag using advanced search", () => {
|
it("can search related entities by a specific tag using advanced search", () => {
|
||||||
cy.clickOptionWithText("CypressNode");
|
cy.clickOptionWithText("CypressNode");
|
||||||
cy.clickOptionWithText("GlossaryNewTerm");
|
cy.clickOptionWithText("GlossaryNewTerm");
|
||||||
cy.clickOptionWithSpecificClass(".anticon.anticon-appstore", 0);
|
cy.clickTextOptionWithClass(".ant-tabs-tab", "Related Assets");
|
||||||
elementVisibility();
|
elementVisibility();
|
||||||
applyAdvancedSearchFilter("Tag", "Cypress");
|
applyAdvancedSearchFilter("Tag", "Cypress");
|
||||||
elementVisibility();
|
elementVisibility();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user