mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-29 09:42:23 +00:00
fix(ui): tab label with persona assigned (#22927)
* fix(ui): tab label with persona assigned * fix tests * fix tests * add playwright to validate the same * remove dndProvider from glossary term table * fix unit tests * fix tests * fix data contract failure (cherry picked from commit 0081ece0ac8344edb699e7a3541fd086dde591a3)
This commit is contained in:
parent
3512549097
commit
eb57f6d5cd
@ -32,138 +32,188 @@ export enum ECustomizedGovernance {
|
|||||||
GLOSSARY_TERM = 'Glossary Term',
|
GLOSSARY_TERM = 'Glossary Term',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum EntityTabs {
|
||||||
|
SCHEMA = 'schema',
|
||||||
|
SCHEMAS = 'schemas',
|
||||||
|
ACTIVITY_FEED = 'activity_feed',
|
||||||
|
SAMPLE_DATA = 'sample_data',
|
||||||
|
TABLE_QUERIES = 'table_queries',
|
||||||
|
PROFILER = 'profiler',
|
||||||
|
LINEAGE = 'lineage',
|
||||||
|
KNOWLEDGE_GRAPH = 'knowledge_graph',
|
||||||
|
DBT = 'dbt',
|
||||||
|
VIEW_DEFINITION = 'view_definition',
|
||||||
|
SCHEMA_DEFINITION = 'schema_definition',
|
||||||
|
CUSTOM_PROPERTIES = 'custom_properties',
|
||||||
|
MODEL = 'model',
|
||||||
|
FEATURES = 'features',
|
||||||
|
TASKS = 'tasks',
|
||||||
|
CONFIG = 'config',
|
||||||
|
DETAILS = 'details',
|
||||||
|
CHILDREN = 'children',
|
||||||
|
EXECUTIONS = 'executions',
|
||||||
|
TABLE = 'table',
|
||||||
|
TEST_CASES = 'test-cases',
|
||||||
|
PIPELINE = 'pipeline',
|
||||||
|
DATA_Model = 'data-model',
|
||||||
|
AGENTS = 'agents',
|
||||||
|
CONNECTION = 'connection',
|
||||||
|
SQL = 'sql',
|
||||||
|
FIELDS = 'fields',
|
||||||
|
SEARCH_INDEX_SETTINGS = 'search-index-settings',
|
||||||
|
STORED_PROCEDURE = 'stored_procedure',
|
||||||
|
CODE = 'code',
|
||||||
|
API_COLLECTION = 'apiCollection',
|
||||||
|
API_ENDPOINT = 'apiEndpoint',
|
||||||
|
OVERVIEW = 'overview',
|
||||||
|
INCIDENTS = 'incidents',
|
||||||
|
TERMS = 'terms',
|
||||||
|
GLOSSARY_TERMS = 'glossary_terms',
|
||||||
|
ASSETS = 'assets',
|
||||||
|
EXPRESSION = 'expression',
|
||||||
|
INSIGHTS = 'insights',
|
||||||
|
DASHBOARD = 'dashboard',
|
||||||
|
DOCUMENTATION = 'documentation',
|
||||||
|
DATA_PRODUCTS = 'data_products',
|
||||||
|
SUBDOMAINS = 'subdomains',
|
||||||
|
CONTRACT = 'contract',
|
||||||
|
}
|
||||||
|
|
||||||
export const TABLE_DEFAULT_TABS = [
|
export const TABLE_DEFAULT_TABS = [
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Contract',
|
EntityTabs.CONTRACT,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
'Data Observability',
|
EntityTabs.PROFILER,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Queries',
|
EntityTabs.TABLE_QUERIES,
|
||||||
'Sample Data',
|
EntityTabs.SAMPLE_DATA,
|
||||||
'Schema',
|
EntityTabs.SCHEMA,
|
||||||
'View Definition',
|
EntityTabs.VIEW_DEFINITION,
|
||||||
'dbt',
|
EntityTabs.DBT,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const TOPIC_DEFAULT_TABS = [
|
export const TOPIC_DEFAULT_TABS = [
|
||||||
'Schema',
|
EntityTabs.SCHEMA,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Sample Data',
|
EntityTabs.SAMPLE_DATA,
|
||||||
'Config',
|
EntityTabs.CONFIG,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DASHBOARD_DEFAULT_TABS = [
|
export const DASHBOARD_DEFAULT_TABS = [
|
||||||
'Details',
|
EntityTabs.DETAILS,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MLMODEL_DEFAULT_TABS = [
|
export const MLMODEL_DEFAULT_TABS = [
|
||||||
'Features',
|
EntityTabs.FEATURES,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Details',
|
EntityTabs.DETAILS,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PIPELINE_DEFAULT_TABS = [
|
export const PIPELINE_DEFAULT_TABS = [
|
||||||
'Tasks',
|
EntityTabs.TASKS,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Executions',
|
EntityTabs.EXECUTIONS,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DASHBOARD_DATAMODEL_DEFAULT_TABS = [
|
export const DASHBOARD_DATAMODEL_DEFAULT_TABS = [
|
||||||
'Model',
|
EntityTabs.MODEL,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'SQL',
|
EntityTabs.SQL,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const API_COLLECTION_DEFAULT_TABS = [
|
export const API_COLLECTION_DEFAULT_TABS = [
|
||||||
'Endpoints',
|
EntityTabs.API_ENDPOINT,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SEARCH_INDEX_DEFAULT_TABS = [
|
export const SEARCH_INDEX_DEFAULT_TABS = [
|
||||||
'Fields',
|
EntityTabs.FIELDS,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Sample Data',
|
EntityTabs.SAMPLE_DATA,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Search Index Settings',
|
EntityTabs.SEARCH_INDEX_SETTINGS,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CONTAINER_DEFAULT_TABS = [
|
export const CONTAINER_DEFAULT_TABS = [
|
||||||
'Schema',
|
EntityTabs.SCHEMA,
|
||||||
'Children',
|
EntityTabs.CHILDREN,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DATABASE_DEFAULT_TABS = [
|
export const DATABASE_DEFAULT_TABS = [
|
||||||
'Schemas',
|
EntityTabs.SCHEMAS,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DATABASE_SCHEMA_DEFAULT_TABS = [
|
export const DATABASE_SCHEMA_DEFAULT_TABS = [
|
||||||
'Tables',
|
EntityTabs.TABLE,
|
||||||
'Stored Procedures',
|
EntityTabs.STORED_PROCEDURE,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const STORED_PROCEDURE_DEFAULT_TABS = [
|
export const STORED_PROCEDURE_DEFAULT_TABS = [
|
||||||
'Code',
|
EntityTabs.CODE,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const API_ENDPOINT_DEFAULT_TABS = [
|
export const API_ENDPOINT_DEFAULT_TABS = [
|
||||||
'Schema',
|
EntityTabs.SCHEMA,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DASHBOARD_DATA_MODEL_DEFAULT_TABS = [
|
export const DASHBOARD_DATA_MODEL_DEFAULT_TABS = [
|
||||||
'Model',
|
EntityTabs.MODEL,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ML_MODEL_DEFAULT_TABS = [
|
export const ML_MODEL_DEFAULT_TABS = [
|
||||||
'Features',
|
EntityTabs.FEATURES,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Details',
|
EntityTabs.DETAILS,
|
||||||
'Lineage',
|
EntityTabs.LINEAGE,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DOMAIN_DEFAULT_TABS = [
|
export const DOMAIN_DEFAULT_TABS = [
|
||||||
'Documentation',
|
EntityTabs.DOCUMENTATION,
|
||||||
'Sub Domains',
|
EntityTabs.SUBDOMAINS,
|
||||||
'Data Products',
|
EntityTabs.DATA_PRODUCTS,
|
||||||
'Assets',
|
EntityTabs.ASSETS,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const GLOSSARY_DEFAULT_TABS = ['Terms', 'Activity Feeds & Tasks'];
|
export const GLOSSARY_DEFAULT_TABS = [
|
||||||
|
EntityTabs.TERMS,
|
||||||
|
EntityTabs.ACTIVITY_FEED,
|
||||||
|
];
|
||||||
|
|
||||||
export const GLOSSARY_TERM_DEFAULT_TABS = [
|
export const GLOSSARY_TERM_DEFAULT_TABS = [
|
||||||
'Overview',
|
EntityTabs.OVERVIEW,
|
||||||
'Glossary Terms',
|
EntityTabs.GLOSSARY_TERMS,
|
||||||
'Assets',
|
EntityTabs.ASSETS,
|
||||||
'Activity Feeds & Tasks',
|
EntityTabs.ACTIVITY_FEED,
|
||||||
'Custom Properties',
|
EntityTabs.CUSTOM_PROPERTIES,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -388,7 +388,7 @@ test.describe('Persona customization', () => {
|
|||||||
.getByTestId('remove-widget-button')
|
.getByTestId('remove-widget-button')
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
await adminPage.getByTestId('tab-Custom Properties').click();
|
await adminPage.getByTestId('tab-custom_properties').click();
|
||||||
await adminPage.getByText('Hide', { exact: true }).click();
|
await adminPage.getByText('Hide', { exact: true }).click();
|
||||||
|
|
||||||
await adminPage.getByRole('button', { name: 'Add tab' }).click();
|
await adminPage.getByRole('button', { name: 'Add tab' }).click();
|
||||||
@ -470,9 +470,9 @@ test.describe('Persona customization', () => {
|
|||||||
|
|
||||||
for (const tabName of expectedTabs) {
|
for (const tabName of expectedTabs) {
|
||||||
await expect(
|
await expect(
|
||||||
adminPage.getByTestId('customize-tab-card').getByRole('button', {
|
adminPage
|
||||||
name: tabName,
|
.getByTestId('customize-tab-card')
|
||||||
})
|
.getByTestId(`tab-${tabName}`)
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,6 +489,9 @@ test.describe('Persona customization', () => {
|
|||||||
.click();
|
.click();
|
||||||
|
|
||||||
await adminPage.getByRole('button', { name: 'Add tab' }).click();
|
await adminPage.getByRole('button', { name: 'Add tab' }).click();
|
||||||
|
|
||||||
|
await expect(adminPage.getByRole('dialog')).toBeVisible();
|
||||||
|
|
||||||
await adminPage
|
await adminPage
|
||||||
.getByRole('dialog')
|
.getByRole('dialog')
|
||||||
.getByRole('button', { name: 'Add' })
|
.getByRole('button', { name: 'Add' })
|
||||||
@ -551,8 +554,8 @@ test.describe('Persona customization', () => {
|
|||||||
state: 'detached',
|
state: 'detached',
|
||||||
});
|
});
|
||||||
|
|
||||||
const dragElement = adminPage.getByTestId('tab-Overview');
|
const dragElement = adminPage.getByTestId('tab-overview');
|
||||||
const dropTarget = adminPage.getByTestId('tab-Custom Properties');
|
const dropTarget = adminPage.getByTestId('tab-custom_properties');
|
||||||
|
|
||||||
await dragElement.dragTo(dropTarget);
|
await dragElement.dragTo(dropTarget);
|
||||||
|
|
||||||
@ -597,4 +600,98 @@ test.describe('Persona customization', () => {
|
|||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("customize tab label should only render if it's customize by user", async ({
|
||||||
|
adminPage,
|
||||||
|
userPage,
|
||||||
|
}) => {
|
||||||
|
await test.step('apply tab label customization for Table', async () => {
|
||||||
|
await settingClick(adminPage, GlobalSettingOptions.PERSONA);
|
||||||
|
await adminPage.waitForLoadState('networkidle');
|
||||||
|
await adminPage
|
||||||
|
.getByTestId(`persona-details-card-${persona.data.name}`)
|
||||||
|
.click();
|
||||||
|
await adminPage.getByRole('tab', { name: 'Customize UI' }).click();
|
||||||
|
await adminPage.waitForLoadState('networkidle');
|
||||||
|
await adminPage.getByText('Data Assets').click();
|
||||||
|
await adminPage.getByText('Table', { exact: true }).click();
|
||||||
|
|
||||||
|
await adminPage.waitForSelector('[data-testid="loader"]', {
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
adminPage
|
||||||
|
.getByTestId('customize-tab-card')
|
||||||
|
.getByTestId(`tab-sample_data`)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await adminPage
|
||||||
|
.getByTestId('customize-tab-card')
|
||||||
|
.getByTestId(`tab-sample_data`)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await adminPage.getByRole('menuitem', { name: 'Rename' }).click();
|
||||||
|
|
||||||
|
await expect(adminPage.getByRole('dialog')).toBeVisible();
|
||||||
|
|
||||||
|
await adminPage.getByRole('dialog').getByRole('textbox').clear();
|
||||||
|
await adminPage
|
||||||
|
.getByRole('dialog')
|
||||||
|
.getByRole('textbox')
|
||||||
|
.fill('Sample Data Updated');
|
||||||
|
|
||||||
|
await adminPage
|
||||||
|
.getByRole('dialog')
|
||||||
|
.getByRole('button', { name: 'Ok' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
adminPage
|
||||||
|
.getByTestId('customize-tab-card')
|
||||||
|
.getByTestId(`tab-sample_data`)
|
||||||
|
).toHaveText('Sample Data Updated');
|
||||||
|
|
||||||
|
await adminPage.getByTestId('save-button').click();
|
||||||
|
|
||||||
|
await toastNotification(
|
||||||
|
adminPage,
|
||||||
|
/^Page layout (created|updated) successfully\.$/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await test.step(
|
||||||
|
'validate applied label change and language support for page',
|
||||||
|
async () => {
|
||||||
|
await redirectToHomePage(userPage);
|
||||||
|
|
||||||
|
const entity = getCustomizeDetailsEntity(ECustomizedDataAssets.TABLE);
|
||||||
|
await entity.visitEntityPage(userPage);
|
||||||
|
await userPage.waitForLoadState('networkidle');
|
||||||
|
await userPage.waitForSelector('[data-testid="loader"]', {
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change language to French
|
||||||
|
await userPage.getByRole('button', { name: 'EN' }).click();
|
||||||
|
await userPage.getByRole('menuitem', { name: 'Français - FR' }).click();
|
||||||
|
await userPage.waitForLoadState('networkidle');
|
||||||
|
await userPage.waitForSelector('[data-testid="loader"]', {
|
||||||
|
state: 'detached',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
userPage.getByRole('tab', { name: 'Sample Data Updated' })
|
||||||
|
).toBeVisible();
|
||||||
|
// Overview tab in French, only customized tab should be non-localized rest should be localized
|
||||||
|
await expect(
|
||||||
|
userPage.getByRole('tab', { name: 'Colonnes' })
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
userPage.getByRole('tab', { name: "Flux d'Activité & Tâches" })
|
||||||
|
).toBeVisible();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -696,7 +696,7 @@ test.describe('Data Contracts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Hide the Contract tab
|
// Hide the Contract tab
|
||||||
await page.getByTestId('tab-Contract').click();
|
await page.getByTestId('tab-contract').click();
|
||||||
await page.getByText('Hide', { exact: true }).click();
|
await page.getByText('Hide', { exact: true }).click();
|
||||||
|
|
||||||
// Save the customization
|
// Save the customization
|
||||||
|
|||||||
@ -32,6 +32,8 @@ import { useApplicationStore } from './hooks/useApplicationStore';
|
|||||||
import { getCustomUiThemePreference } from './rest/settingConfigAPI';
|
import { getCustomUiThemePreference } from './rest/settingConfigAPI';
|
||||||
import { getBasePath } from './utils/HistoryUtils';
|
import { getBasePath } from './utils/HistoryUtils';
|
||||||
|
|
||||||
|
import { DndProvider } from 'react-dnd';
|
||||||
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import i18n from './utils/i18next/LocalUtil';
|
import i18n from './utils/i18next/LocalUtil';
|
||||||
import { getThemeConfig } from './utils/ThemeUtils';
|
import { getThemeConfig } from './utils/ThemeUtils';
|
||||||
|
|
||||||
@ -88,7 +90,9 @@ const App: FC = () => {
|
|||||||
<AsyncDeleteProvider>
|
<AsyncDeleteProvider>
|
||||||
<EntityExportModalProvider>
|
<EntityExportModalProvider>
|
||||||
<AirflowStatusProvider>
|
<AirflowStatusProvider>
|
||||||
<AppRouter />
|
<DndProvider backend={HTML5Backend}>
|
||||||
|
<AppRouter />
|
||||||
|
</DndProvider>
|
||||||
</AirflowStatusProvider>
|
</AirflowStatusProvider>
|
||||||
</EntityExportModalProvider>
|
</EntityExportModalProvider>
|
||||||
</AsyncDeleteProvider>
|
</AsyncDeleteProvider>
|
||||||
|
|||||||
@ -13,17 +13,8 @@
|
|||||||
|
|
||||||
import { EyeFilled, MoreOutlined, PlusOutlined } from '@ant-design/icons';
|
import { EyeFilled, MoreOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Card, Col, Dropdown, Input, Modal, Space } from 'antd';
|
import { Button, Card, Col, Dropdown, Input, Modal, Space } from 'antd';
|
||||||
import {
|
import { cloneDeep, isEmpty, isNil, isUndefined, uniqueId } from 'lodash';
|
||||||
cloneDeep,
|
|
||||||
isEmpty,
|
|
||||||
isNil,
|
|
||||||
isUndefined,
|
|
||||||
toString,
|
|
||||||
uniqueId,
|
|
||||||
} from 'lodash';
|
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { DndProvider } from 'react-dnd';
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
||||||
import RGL, { Layout, WidthProvider } from 'react-grid-layout';
|
import RGL, { Layout, WidthProvider } from 'react-grid-layout';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
@ -50,6 +41,7 @@ import {
|
|||||||
getCustomizableWidgetByPage,
|
getCustomizableWidgetByPage,
|
||||||
getDefaultTabs,
|
getDefaultTabs,
|
||||||
getDefaultWidgetForTab,
|
getDefaultWidgetForTab,
|
||||||
|
getTabDisplayName,
|
||||||
} from '../../../utils/CustomizePage/CustomizePageUtils';
|
} from '../../../utils/CustomizePage/CustomizePageUtils';
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getEntityName } from '../../../utils/EntityUtils';
|
||||||
import { TabItem } from '../../common/DraggableTabs/DraggableTabs';
|
import { TabItem } from '../../common/DraggableTabs/DraggableTabs';
|
||||||
@ -388,46 +380,44 @@ export const CustomizeTabWidget = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
title={t('label.customize-tab-plural')}>
|
title={t('label.customize-tab-plural')}>
|
||||||
<DndProvider backend={HTML5Backend}>
|
<div className="d-flex flex-wrap gap-4">
|
||||||
<div className="d-flex flex-wrap gap-4">
|
{items.map((item, index) => (
|
||||||
{items.map((item, index) => (
|
<TabItem
|
||||||
<TabItem
|
index={index}
|
||||||
index={index}
|
item={item}
|
||||||
item={item}
|
key={item.id}
|
||||||
key={item.id}
|
moveTab={moveTab}
|
||||||
moveTab={moveTab}
|
shouldHide={systemTabIds.includes(item.id)}
|
||||||
shouldHide={systemTabIds.includes(item.id)}
|
onEdit={onChange}
|
||||||
onEdit={onChange}
|
onRemove={remove}
|
||||||
onRemove={remove}
|
onRename={handleTabEditClick}
|
||||||
onRename={handleTabEditClick}
|
/>
|
||||||
/>
|
))}
|
||||||
))}
|
{hiddenTabs.map((item) => (
|
||||||
{hiddenTabs.map((item) => (
|
<Dropdown
|
||||||
<Dropdown
|
key={item.id}
|
||||||
key={item.id}
|
menu={{
|
||||||
menu={{
|
items: [
|
||||||
items: [
|
{
|
||||||
{
|
label: t('label.show'),
|
||||||
label: t('label.show'),
|
key: 'show',
|
||||||
key: 'show',
|
icon: <EyeFilled />,
|
||||||
icon: <EyeFilled />,
|
},
|
||||||
},
|
],
|
||||||
],
|
onClick: () => add(item),
|
||||||
onClick: () => add(item),
|
}}
|
||||||
}}
|
trigger={['click']}>
|
||||||
trigger={['click']}>
|
<Button
|
||||||
<Button
|
className="draggable-hidden-tab-item bg-grey"
|
||||||
className="draggable-hidden-tab-item bg-grey"
|
data-testid={`tab-${item.name}`}>
|
||||||
data-testid={`tab-${item.displayName}`}>
|
<Space>
|
||||||
<Space>
|
{getTabDisplayName(item)}
|
||||||
{getEntityName(item)}
|
<MoreOutlined />
|
||||||
<MoreOutlined />
|
</Space>
|
||||||
</Space>
|
</Button>
|
||||||
</Button>
|
</Dropdown>
|
||||||
</Dropdown>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
|
||||||
</DndProvider>
|
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
@ -508,7 +498,7 @@ export const CustomizeTabWidget = () => {
|
|||||||
onOk={handleRenameSave}>
|
onOk={handleRenameSave}>
|
||||||
<Input
|
<Input
|
||||||
autoFocus
|
autoFocus
|
||||||
value={toString(getEntityName(editableItem))}
|
value={getTabDisplayName(editableItem)}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -32,8 +32,6 @@ import classNames from 'classnames';
|
|||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { cloneDeep, isEmpty, isUndefined } from 'lodash';
|
import { cloneDeep, isEmpty, isUndefined } from 'lodash';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { DndProvider } from 'react-dnd';
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { ReactComponent as IconDrag } from '../../../assets/svg/drag.svg';
|
import { ReactComponent as IconDrag } from '../../../assets/svg/drag.svg';
|
||||||
@ -882,28 +880,26 @@ const GlossaryTermTab = ({ isGlossary, className }: GlossaryTermTabProps) => {
|
|||||||
{/* Have use the col to set the width of the table, to only use the viewport width for the table columns */}
|
{/* Have use the col to set the width of the table, to only use the viewport width for the table columns */}
|
||||||
<Col className="w-full" ref={tableContainerRef} span={24}>
|
<Col className="w-full" ref={tableContainerRef} span={24}>
|
||||||
{glossaryTerms.length > 0 ? (
|
{glossaryTerms.length > 0 ? (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<Table
|
||||||
<Table
|
resizableColumns
|
||||||
resizableColumns
|
className={classNames('drop-over-background', {
|
||||||
className={classNames('drop-over-background', {
|
'drop-over-table': isTableHovered,
|
||||||
'drop-over-table': isTableHovered,
|
})}
|
||||||
})}
|
columns={columns}
|
||||||
columns={columns}
|
components={TABLE_CONSTANTS}
|
||||||
components={TABLE_CONSTANTS}
|
data-testid="glossary-terms-table"
|
||||||
data-testid="glossary-terms-table"
|
dataSource={filteredGlossaryTerms}
|
||||||
dataSource={filteredGlossaryTerms}
|
defaultVisibleColumns={DEFAULT_VISIBLE_COLUMNS}
|
||||||
defaultVisibleColumns={DEFAULT_VISIBLE_COLUMNS}
|
expandable={expandableConfig}
|
||||||
expandable={expandableConfig}
|
extraTableFilters={extraTableFilters}
|
||||||
extraTableFilters={extraTableFilters}
|
loading={isTableLoading || termsLoading}
|
||||||
loading={isTableLoading || termsLoading}
|
pagination={false}
|
||||||
pagination={false}
|
rowKey="fullyQualifiedName"
|
||||||
rowKey="fullyQualifiedName"
|
size="small"
|
||||||
size="small"
|
staticVisibleColumns={STATIC_VISIBLE_COLUMNS}
|
||||||
staticVisibleColumns={STATIC_VISIBLE_COLUMNS}
|
onHeaderRow={onTableHeader}
|
||||||
onHeaderRow={onTableHeader}
|
onRow={onTableRow}
|
||||||
onRow={onTableRow}
|
/>
|
||||||
/>
|
|
||||||
</DndProvider>
|
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder />
|
<ErrorPlaceHolder />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -19,6 +19,8 @@ import {
|
|||||||
getByText,
|
getByText,
|
||||||
render,
|
render,
|
||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
|
import { DndProvider } from 'react-dnd';
|
||||||
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
mockedGlossaryTerms,
|
mockedGlossaryTerms,
|
||||||
@ -104,6 +106,15 @@ jest.mock('../../Customization/GenericProvider/GenericProvider', () => ({
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const renderWithDndProvider = (props = {}) => {
|
||||||
|
return render(
|
||||||
|
<DndProvider backend={HTML5Backend}>
|
||||||
|
<GlossaryTermTab {...mockProps} {...props} />
|
||||||
|
</DndProvider>,
|
||||||
|
{ wrapper: MemoryRouter }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
describe('Test GlossaryTermTab component', () => {
|
describe('Test GlossaryTermTab component', () => {
|
||||||
it('should show the ErrorPlaceHolder component, if no glossary is present', () => {
|
it('should show the ErrorPlaceHolder component, if no glossary is present', () => {
|
||||||
const { container } = render(<GlossaryTermTab {...mockProps} />, {
|
const { container } = render(<GlossaryTermTab {...mockProps} />, {
|
||||||
@ -132,9 +143,7 @@ describe('Test GlossaryTermTab component', () => {
|
|||||||
glossaryChildTerms: mockedGlossaryTerms,
|
glossaryChildTerms: mockedGlossaryTerms,
|
||||||
updateActiveGlossary: jest.fn(),
|
updateActiveGlossary: jest.fn(),
|
||||||
}));
|
}));
|
||||||
const { container } = render(<GlossaryTermTab {...mockProps} />, {
|
const { container } = renderWithDndProvider();
|
||||||
wrapper: MemoryRouter,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getByTestId(container, 'Clothing')).toBeInTheDocument();
|
expect(getByTestId(container, 'Clothing')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@ -11,7 +11,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { act, fireEvent, render, screen } from '@testing-library/react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import { DndProvider } from 'react-dnd';
|
||||||
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
MOCK_CURRENT_TEAM,
|
MOCK_CURRENT_TEAM,
|
||||||
@ -80,13 +82,18 @@ jest.mock('../../../common/SearchBarComponent/SearchBar.component', () =>
|
|||||||
jest.fn().mockImplementation(() => <div>SearchBar</div>)
|
jest.fn().mockImplementation(() => <div>SearchBar</div>)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const renderComponent = (props = {}) => {
|
||||||
|
return render(
|
||||||
|
<DndProvider backend={HTML5Backend}>
|
||||||
|
<TeamHierarchy {...teamHierarchyPropsData} {...props} />
|
||||||
|
</DndProvider>,
|
||||||
|
{ wrapper: MemoryRouter }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
describe('Team Hierarchy page', () => {
|
describe('Team Hierarchy page', () => {
|
||||||
it('Initially, Table should load', async () => {
|
it('Initially, Table should load', async () => {
|
||||||
await act(async () => {
|
renderComponent();
|
||||||
render(<TeamHierarchy {...teamHierarchyPropsData} />, {
|
|
||||||
wrapper: MemoryRouter,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const table = await screen.findByTestId('team-hierarchy-table');
|
const table = await screen.findByTestId('team-hierarchy-table');
|
||||||
|
|
||||||
@ -94,11 +101,7 @@ describe('Team Hierarchy page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should render all table columns', async () => {
|
it('Should render all table columns', async () => {
|
||||||
await act(async () => {
|
renderComponent();
|
||||||
render(<TeamHierarchy {...teamHierarchyPropsData} />, {
|
|
||||||
wrapper: MemoryRouter,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const table = await screen.findByTestId('team-hierarchy-table');
|
const table = await screen.findByTestId('team-hierarchy-table');
|
||||||
const teamsColumn = await screen.findByText('label.team-plural');
|
const teamsColumn = await screen.findByText('label.team-plural');
|
||||||
@ -121,11 +124,7 @@ describe('Team Hierarchy page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should render child row in table', async () => {
|
it('Should render child row in table', async () => {
|
||||||
await act(async () => {
|
renderComponent();
|
||||||
render(<TeamHierarchy {...teamHierarchyPropsData} />, {
|
|
||||||
wrapper: MemoryRouter,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const table = await screen.findByTestId('team-hierarchy-table');
|
const table = await screen.findByTestId('team-hierarchy-table');
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,6 @@ import classNames from 'classnames';
|
|||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { isEmpty, isUndefined } from 'lodash';
|
import { isEmpty, isUndefined } from 'lodash';
|
||||||
import { FC, useCallback, useMemo, useState } from 'react';
|
import { FC, useCallback, useMemo, useState } from 'react';
|
||||||
import { DndProvider } from 'react-dnd';
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@ -271,51 +269,49 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="team-list-container">
|
<div className="team-list-container">
|
||||||
<DndProvider backend={HTML5Backend}>
|
<Table
|
||||||
<Table
|
className={classNames('teams-list-table drop-over-background', {
|
||||||
className={classNames('teams-list-table drop-over-background', {
|
'drop-over-table': isTableHovered,
|
||||||
'drop-over-table': isTableHovered,
|
})}
|
||||||
})}
|
columns={columns}
|
||||||
columns={columns}
|
components={TABLE_CONSTANTS}
|
||||||
components={TABLE_CONSTANTS}
|
data-testid="team-hierarchy-table"
|
||||||
data-testid="team-hierarchy-table"
|
dataSource={data}
|
||||||
dataSource={data}
|
expandable={expandableConfig}
|
||||||
expandable={expandableConfig}
|
extraTableFilters={
|
||||||
extraTableFilters={
|
<Space align="center">
|
||||||
<Space align="center">
|
<span>
|
||||||
<span>
|
<Switch
|
||||||
<Switch
|
checked={showDeletedTeam}
|
||||||
checked={showDeletedTeam}
|
data-testid="show-deleted"
|
||||||
data-testid="show-deleted"
|
onClick={onShowDeletedTeamChange}
|
||||||
onClick={onShowDeletedTeamChange}
|
/>
|
||||||
/>
|
<Typography.Text className="m-l-xs">
|
||||||
<Typography.Text className="m-l-xs">
|
{t('label.deleted')}
|
||||||
{t('label.deleted')}
|
</Typography.Text>
|
||||||
</Typography.Text>
|
</span>
|
||||||
</span>
|
|
||||||
|
|
||||||
{createTeamPermission && !isTeamDeleted && (
|
{createTeamPermission && !isTeamDeleted && (
|
||||||
<Button
|
<Button
|
||||||
data-testid="add-team"
|
data-testid="add-team"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleAddTeamButtonClick}>
|
onClick={handleAddTeamButtonClick}>
|
||||||
{t('label.add-entity', { entity: t('label.team') })}
|
{t('label.add-entity', { entity: t('label.team') })}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
loading={isTableLoading}
|
loading={isTableLoading}
|
||||||
locale={{
|
locale={{
|
||||||
emptyText: <FilterTablePlaceHolder />,
|
emptyText: <FilterTablePlaceHolder />,
|
||||||
}}
|
}}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowKey="name"
|
rowKey="name"
|
||||||
searchProps={searchProps}
|
searchProps={searchProps}
|
||||||
size="small"
|
size="small"
|
||||||
onHeaderRow={onTableHeader}
|
onHeaderRow={onTableHeader}
|
||||||
onRow={onTableRow}
|
onRow={onTableRow}
|
||||||
/>
|
/>
|
||||||
</DndProvider>
|
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
centered
|
centered
|
||||||
|
|||||||
@ -15,9 +15,8 @@ import { DndProvider } from 'react-dnd';
|
|||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import { TabItem } from './DraggableTabs';
|
import { TabItem } from './DraggableTabs';
|
||||||
|
|
||||||
// Mock the getEntityName utility function
|
jest.mock('../../../utils/CustomizePage/CustomizePageUtils', () => ({
|
||||||
jest.mock('../../../utils/EntityUtils', () => ({
|
getTabDisplayName: jest.fn().mockReturnValue('Test Tab'),
|
||||||
getEntityName: jest.fn().mockReturnValue('Test Tab'),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('TabItem', () => {
|
describe('TabItem', () => {
|
||||||
@ -53,12 +52,12 @@ describe('TabItem', () => {
|
|||||||
it('renders tab item with correct name', () => {
|
it('renders tab item with correct name', () => {
|
||||||
renderComponent();
|
renderComponent();
|
||||||
|
|
||||||
expect(screen.getByText('Test Tab')).toBeInTheDocument();
|
expect(screen.getByTestId('tab-Test Tab')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls onItemClick when tab is clicked', () => {
|
it('calls onItemClick when tab is clicked', () => {
|
||||||
renderComponent();
|
renderComponent();
|
||||||
fireEvent.click(screen.getByText('Test Tab'));
|
fireEvent.click(screen.getByTestId('tab-Test Tab'));
|
||||||
|
|
||||||
expect(defaultProps.onItemClick).toHaveBeenCalledWith(mockTab.id);
|
expect(defaultProps.onItemClick).toHaveBeenCalledWith(mockTab.id);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import React from 'react';
|
|||||||
import { useDrag, useDrop } from 'react-dnd';
|
import { useDrag, useDrop } from 'react-dnd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Tab } from '../../../generated/system/ui/tab';
|
import { Tab } from '../../../generated/system/ui/tab';
|
||||||
import { getEntityName } from '../../../utils/EntityUtils';
|
import { getTabDisplayName } from '../../../utils/CustomizePage/CustomizePageUtils';
|
||||||
import './draggable-tabs.less';
|
import './draggable-tabs.less';
|
||||||
|
|
||||||
type TargetKey = React.MouseEvent | React.KeyboardEvent | string;
|
type TargetKey = React.MouseEvent | React.KeyboardEvent | string;
|
||||||
@ -118,10 +118,10 @@ export const TabItem = ({
|
|||||||
trigger={['click']}>
|
trigger={['click']}>
|
||||||
<Button
|
<Button
|
||||||
className="draggable-tab-item"
|
className="draggable-tab-item"
|
||||||
data-testid={`tab-${item.displayName}`}
|
data-testid={`tab-${item.name}`}
|
||||||
onClick={() => onItemClick?.(item.id)}>
|
onClick={() => onItemClick?.(item.id)}>
|
||||||
<Space>
|
<Space>
|
||||||
{getEntityName(item)}
|
{getTabDisplayName(item)}
|
||||||
<MoreOutlined />
|
<MoreOutlined />
|
||||||
</Space>
|
</Space>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -33,8 +33,6 @@ import {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import { useAntdColumnResize } from 'react-antd-column-resize';
|
import { useAntdColumnResize } from 'react-antd-column-resize';
|
||||||
import { Column } from 'react-antd-column-resize/dist/useAntdColumnResize/types';
|
import { Column } from 'react-antd-column-resize/dist/useAntdColumnResize/types';
|
||||||
import { DndProvider } from 'react-dnd';
|
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ReactComponent as ColumnIcon } from '../../../assets/svg/ic-column.svg';
|
import { ReactComponent as ColumnIcon } from '../../../assets/svg/ic-column.svg';
|
||||||
import { useCurrentUserPreferences } from '../../../hooks/currentUserStore/useCurrentUserStore';
|
import { useCurrentUserPreferences } from '../../../hooks/currentUserStore/useCurrentUserStore';
|
||||||
@ -291,24 +289,22 @@ const Table = <T extends Record<string, unknown>>(
|
|||||||
span={searchProps ? 12 : 24}>
|
span={searchProps ? 12 : 24}>
|
||||||
{rest.extraTableFilters}
|
{rest.extraTableFilters}
|
||||||
{isCustomizeColumnEnable && (
|
{isCustomizeColumnEnable && (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<Dropdown
|
||||||
<Dropdown
|
className="custom-column-dropdown-menu text-primary"
|
||||||
className="custom-column-dropdown-menu text-primary"
|
menu={menu}
|
||||||
menu={menu}
|
open={isDropdownVisible}
|
||||||
open={isDropdownVisible}
|
placement="bottomRight"
|
||||||
placement="bottomRight"
|
trigger={['click']}
|
||||||
trigger={['click']}
|
onOpenChange={setIsDropdownVisible}>
|
||||||
onOpenChange={setIsDropdownVisible}>
|
<Button
|
||||||
<Button
|
className="remove-button-background-hover"
|
||||||
className="remove-button-background-hover"
|
data-testid="column-dropdown"
|
||||||
data-testid="column-dropdown"
|
icon={<Icon component={ColumnIcon} />}
|
||||||
icon={<Icon component={ColumnIcon} />}
|
size="small"
|
||||||
size="small"
|
type="text">
|
||||||
type="text">
|
{t('label.column-plural')}
|
||||||
{t('label.column-plural')}
|
</Button>
|
||||||
</Button>
|
</Dropdown>
|
||||||
</Dropdown>
|
|
||||||
</DndProvider>
|
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { WidgetConfig } from '../../pages/CustomizablePage/CustomizablePage.inte
|
|||||||
import {
|
import {
|
||||||
checkIfExpandViewSupported,
|
checkIfExpandViewSupported,
|
||||||
getDefaultTabs,
|
getDefaultTabs,
|
||||||
|
getTabDisplayName,
|
||||||
getTabLabelFromId,
|
getTabLabelFromId,
|
||||||
getTabLabelMapFromTabs,
|
getTabLabelMapFromTabs,
|
||||||
sortTabs,
|
sortTabs,
|
||||||
@ -24,6 +25,43 @@ import {
|
|||||||
} from './CustomizePageUtils';
|
} from './CustomizePageUtils';
|
||||||
|
|
||||||
describe('CustomizePageUtils', () => {
|
describe('CustomizePageUtils', () => {
|
||||||
|
describe('getTabDisplayName', () => {
|
||||||
|
it('should return displayName if present', () => {
|
||||||
|
const tab: Tab = {
|
||||||
|
id: EntityTabs.OVERVIEW,
|
||||||
|
name: EntityTabs.OVERVIEW,
|
||||||
|
displayName: 'Custom Overview',
|
||||||
|
layout: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getTabDisplayName(tab)).toBe('Custom Overview');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fallback to getTabLabelFromId if displayName is missing', () => {
|
||||||
|
const tab: Tab = {
|
||||||
|
id: EntityTabs.OVERVIEW,
|
||||||
|
name: EntityTabs.OVERVIEW,
|
||||||
|
layout: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = getTabDisplayName(tab);
|
||||||
|
|
||||||
|
expect(typeof result).toBe('string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty string if displayName and name are missing', () => {
|
||||||
|
const tab: Tab = {
|
||||||
|
id: EntityTabs.OVERVIEW,
|
||||||
|
name: '' as EntityTabs,
|
||||||
|
layout: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = getTabDisplayName(tab);
|
||||||
|
|
||||||
|
expect(typeof result).toBe('string');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('sortTabs', () => {
|
describe('sortTabs', () => {
|
||||||
it('should sort tabs according to given order', () => {
|
it('should sort tabs according to given order', () => {
|
||||||
const tabs: TabsProps['items'] = [
|
const tabs: TabsProps['items'] = [
|
||||||
|
|||||||
@ -691,3 +691,7 @@ export const updateWidgetHeightRecursively = (
|
|||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as WidgetConfig[]);
|
}, [] as WidgetConfig[]);
|
||||||
|
|
||||||
|
export const getTabDisplayName = (item: Tab) => {
|
||||||
|
return item.displayName ?? getTabLabelFromId(item.name as EntityTabs);
|
||||||
|
};
|
||||||
|
|||||||
@ -28,7 +28,6 @@ import { Tab } from '../generated/system/ui/uiCustomization';
|
|||||||
import { TestSummary } from '../generated/tests/testCase';
|
import { TestSummary } from '../generated/tests/testCase';
|
||||||
import { FeedCounts } from '../interface/feed.interface';
|
import { FeedCounts } from '../interface/feed.interface';
|
||||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||||
import { getTabLabelFromId } from './CustomizePage/CustomizePageUtils';
|
|
||||||
import i18n from './i18next/LocalUtil';
|
import i18n from './i18next/LocalUtil';
|
||||||
import {
|
import {
|
||||||
getTableDetailPageBaseTabs,
|
getTableDetailPageBaseTabs,
|
||||||
@ -106,7 +105,6 @@ class TableClassBase {
|
|||||||
].map((tab: EntityTabs) => ({
|
].map((tab: EntityTabs) => ({
|
||||||
id: tab,
|
id: tab,
|
||||||
name: tab,
|
name: tab,
|
||||||
displayName: getTabLabelFromId(tab),
|
|
||||||
layout: this.getDefaultLayout(tab),
|
layout: this.getDefaultLayout(tab),
|
||||||
editable: tab === EntityTabs.SCHEMA,
|
editable: tab === EntityTabs.SCHEMA,
|
||||||
}));
|
}));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user