Skip to content

Commit edae55e

Browse files
authored
fix(teams): team header layout, heading truncation, hierarchy overflow, and teams tab empty state (#27077)
* fix(teams): prevent team name truncation and align action buttons on header row * lint * fix empty placeholder bug & description bg change * address gitar * fix failing spec * refactor code to remove core-component depedency * fix lint
1 parent 5cdf7fa commit edae55e

File tree

10 files changed

+456
-100
lines changed

10 files changed

+456
-100
lines changed

openmetadata-ui/src/main/resources/ui/playwright/utils/dragDrop.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ export const dragAndDropElement = async (
3737
};
3838

3939
export const openDragDropDropdown = async (page: Page, name: string) => {
40-
const dropdownIcon = page.locator(
41-
`[data-row-key=${name}] > .whitespace-nowrap > [data-testid="expand-icon"] > svg`
42-
);
43-
await dropdownIcon.click();
40+
await page
41+
.locator(`[data-row-key="${name}"]`)
42+
.getByTestId('expand-icon')
43+
.click();
4444
};
4545

4646
export const confirmationDragAndDropTeam = async (

openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamDetailsV1.tsx

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,13 @@ const TeamDetailsV1 = ({
636636
);
637637
}
638638

639-
return currentTeam.childrenCount === 0 && !searchTerm ? (
639+
const showEmptyTeamPlaceholder =
640+
isEmpty(searchTerm) &&
641+
isEmpty(childTeamList) &&
642+
(currentTeam.childrenCount ?? 0) === 0 &&
643+
!isTeamBasicDataLoading;
644+
645+
return showEmptyTeamPlaceholder ? (
640646
<ErrorPlaceHolder
641647
className="border-none"
642648
icon={<AddPlaceHolderIcon className="h-32 w-32" />}
@@ -696,6 +702,7 @@ const TeamDetailsV1 = ({
696702
entityPermissions.Create,
697703
isFetchingAllTeamAdvancedDetails,
698704
isSearchLoading,
705+
isTeamBasicDataLoading,
699706
onTeamExpand,
700707
handleAddTeamButtonClick,
701708
handleTeamSearch,
@@ -946,15 +953,10 @@ const TeamDetailsV1 = ({
946953
const teamsCollapseHeader = useMemo(
947954
() => (
948955
<>
949-
<Space wrap className="w-full justify-between">
950-
<Space
951-
align="start"
952-
className="w-full flex-col justify-center p-t-xs"
953-
size="middle">
954-
{!isOrganization && (
955-
<TitleBreadcrumb titleLinks={slashedTeamName} />
956-
)}
957-
<div className="d-flex items-center gap-2">
956+
<div className="w-full p-t-xs">
957+
{!isOrganization && <TitleBreadcrumb titleLinks={slashedTeamName} />}
958+
<div className="d-flex items-center justify-between p-t-xs">
959+
<div className="d-flex items-center gap-2 flex-1 w-min-0">
958960
<Avatar className="teams-profile" size={40}>
959961
<IconTeams className="text-primary" width={20} />
960962
</Avatar>
@@ -965,50 +967,54 @@ const TeamDetailsV1 = ({
965967
updateTeamHandler={updateTeamHandler}
966968
/>
967969

968-
<LearningIcon
969-
pageId={LEARNING_PAGE_IDS.TEAMS}
970-
title={t('label.team-plural')}
971-
/>
970+
<div className="d-flex flex-1 items-center justify-end w-min-0">
971+
<LearningIcon
972+
pageId={LEARNING_PAGE_IDS.TEAMS}
973+
title={t('label.team-plural')}
974+
/>
975+
</div>
972976
</div>
973-
</Space>
974977

975-
<Space align="center">
976-
{teamActionButton}
977-
{!isOrganization ? (
978-
entityPermissions.EditAll && (
978+
<Space align="center">
979+
{teamActionButton}
980+
{!isOrganization ? (
981+
entityPermissions.EditAll && (
982+
<ManageButton
983+
isRecursiveDelete
984+
afterDeleteAction={afterDeleteAction}
985+
allowSoftDelete={!currentTeam.deleted}
986+
canDelete={entityPermissions.EditAll}
987+
displayName={getEntityName(currentTeam)}
988+
entityId={currentTeam.id}
989+
entityName={
990+
currentTeam.fullyQualifiedName ?? currentTeam.name
991+
}
992+
entityType={EntityType.TEAM}
993+
extraDropdownContent={extraDropdownContent}
994+
hardDeleteMessagePostFix={getDeleteMessagePostFix(
995+
currentTeam.fullyQualifiedName ?? currentTeam.name,
996+
t('label.permanently-lowercase')
997+
)}
998+
softDeleteMessagePostFix={getDeleteMessagePostFix(
999+
currentTeam.fullyQualifiedName ?? currentTeam.name,
1000+
t('label.soft-lowercase')
1001+
)}
1002+
/>
1003+
)
1004+
) : (
9791005
<ManageButton
980-
isRecursiveDelete
981-
afterDeleteAction={afterDeleteAction}
982-
allowSoftDelete={!currentTeam.deleted}
983-
canDelete={entityPermissions.EditAll}
1006+
canDelete={false}
9841007
displayName={getEntityName(currentTeam)}
985-
entityId={currentTeam.id}
9861008
entityName={
9871009
currentTeam.fullyQualifiedName ?? currentTeam.name
9881010
}
9891011
entityType={EntityType.TEAM}
990-
extraDropdownContent={extraDropdownContent}
991-
hardDeleteMessagePostFix={getDeleteMessagePostFix(
992-
currentTeam.fullyQualifiedName ?? currentTeam.name,
993-
t('label.permanently-lowercase')
994-
)}
995-
softDeleteMessagePostFix={getDeleteMessagePostFix(
996-
currentTeam.fullyQualifiedName ?? currentTeam.name,
997-
t('label.soft-lowercase')
998-
)}
1012+
extraDropdownContent={[...IMPORT_EXPORT_MENU_ITEM]}
9991013
/>
1000-
)
1001-
) : (
1002-
<ManageButton
1003-
canDelete={false}
1004-
displayName={getEntityName(currentTeam)}
1005-
entityName={currentTeam.fullyQualifiedName ?? currentTeam.name}
1006-
entityType={EntityType.TEAM}
1007-
extraDropdownContent={[...IMPORT_EXPORT_MENU_ITEM]}
1008-
/>
1009-
)}
1010-
</Space>
1011-
</Space>
1014+
)}
1015+
</Space>
1016+
</div>
1017+
</div>
10121018
<div className="p-t-md ">
10131019
<TeamsInfo
10141020
childTeamsCount={childTeams.length}

openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamHierarchy.test.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
import { fireEvent, render, screen } from '@testing-library/react';
15+
import { forwardRef, type ReactNode } from 'react';
1516
import { DndProvider } from 'react-dnd';
1617
import { HTML5Backend } from 'react-dnd-html5-backend';
1718
import { MemoryRouter } from 'react-router-dom';
@@ -26,6 +27,8 @@ import TeamHierarchy from './TeamHierarchy';
2627
const teamHierarchyPropsData: TeamHierarchyProps = {
2728
data: MOCK_TABLE_DATA,
2829
currentTeam: MOCK_CURRENT_TEAM,
30+
isSearchLoading: false,
31+
isTeamBasicDataLoading: false,
2932
onTeamExpand: jest.fn(),
3033
isFetchingAllTeamAdvancedDetails: false,
3134
showDeletedTeam: false,
@@ -38,12 +41,23 @@ const teamHierarchyPropsData: TeamHierarchyProps = {
3841

3942
const mockShowErrorToast = jest.fn();
4043

41-
// mock library imports
42-
jest.mock('react-router-dom', () => ({
43-
Link: jest
44-
.fn()
45-
.mockImplementation(({ children }) => <a href="#">{children}</a>),
46-
}));
44+
jest.mock('react-router-dom', () => {
45+
const actual = jest.requireActual('react-router-dom');
46+
47+
const MockLink = forwardRef<
48+
HTMLAnchorElement,
49+
{ children?: ReactNode; to?: unknown }
50+
>(({ children, to: _to, ...props }, ref) => (
51+
<a href="#" ref={ref} {...props}>
52+
{children}
53+
</a>
54+
));
55+
56+
return {
57+
...actual,
58+
Link: MockLink,
59+
};
60+
});
4761

4862
jest.mock('../../../../utils/TeamUtils', () => ({
4963
getMovedTeamData: jest.fn().mockReturnValue([]),

openmetadata-ui/src/main/resources/ui/src/components/Settings/Team/TeamDetails/TeamHierarchy.tsx

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,13 @@ import { compare } from 'fast-json-patch';
2020
import { isEmpty, isUndefined } from 'lodash';
2121
import { FC, useCallback, useMemo, useState } from 'react';
2222
import { useTranslation } from 'react-i18next';
23-
import { Link } from 'react-router-dom';
2423
import { TABLE_CONSTANTS } from '../../../../constants/Teams.constants';
2524
import { TabSpecificField } from '../../../../enums/entity.enum';
2625
import { Team } from '../../../../generated/entity/teams/team';
2726
import { Include } from '../../../../generated/type/include';
2827
import { getTeamByName, patchTeamDetail } from '../../../../rest/teamsAPI';
2928
import { Transi18next } from '../../../../utils/CommonUtils';
30-
import {
31-
getEntityName,
32-
highlightSearchText,
33-
} from '../../../../utils/EntityUtils';
34-
import { getTeamsWithFqnPath } from '../../../../utils/RouterUtils';
35-
import { stringToHTML } from '../../../../utils/StringsUtils';
29+
import { getEntityName } from '../../../../utils/EntityUtils';
3630
import { descriptionTableObject } from '../../../../utils/TableColumn.util';
3731
import { getTableExpandableConfig } from '../../../../utils/TableUtils';
3832
import { isDropRestricted } from '../../../../utils/TeamUtils';
@@ -42,6 +36,7 @@ import FilterTablePlaceHolder from '../../../common/ErrorWithPlaceholder/FilterT
4236
import Table from '../../../common/Table/Table';
4337
import { MovedTeamProps, TeamHierarchyProps } from './team.interface';
4438
import './teams.less';
39+
import { TeamHierarchyNameCell } from './TeamsHeaderSection/TeamHierarchyNameCell';
4540

4641
const TeamHierarchy: FC<TeamHierarchyProps> = ({
4742
currentTeam,
@@ -82,17 +77,11 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
8277
{
8378
title: t('label.team-plural'),
8479
dataIndex: 'teams',
85-
className: 'whitespace-nowrap',
80+
className: 'teams-hierarchy-name-column',
8681
key: 'teams',
82+
width: '32%',
8783
render: (_, record) => (
88-
<Link
89-
className="link-hover"
90-
data-testid={`team-name-${record.name}`}
91-
to={getTeamsWithFqnPath(record.fullyQualifiedName || record.name)}>
92-
{stringToHTML(
93-
highlightSearchText(getEntityName(record), searchTerm)
94-
)}
95-
</Link>
84+
<TeamHierarchyNameCell record={record} searchTerm={searchTerm} />
9685
),
9786
},
9887
{
@@ -152,7 +141,7 @@ const TeamHierarchy: FC<TeamHierarchyProps> = ({
152141
},
153142
...descriptionTableObject<Team>({ width: 300 }),
154143
];
155-
}, [data, isFetchingAllTeamAdvancedDetails, onTeamExpand, teamAssetCounts]);
144+
}, [isFetchingAllTeamAdvancedDetails, searchTerm, t, teamAssetCounts]);
156145

157146
const handleTableHover = useCallback(
158147
(value: boolean) => setIsTableHovered(value),

0 commit comments

Comments
 (0)