From fa0d386bd66d40656671269874f9260b3fa9012e Mon Sep 17 00:00:00 2001 From: Shailesh Parmar Date: Fri, 22 Apr 2022 11:42:32 +0530 Subject: [PATCH] Fix #4292: Added hard delete support for team & users page (#4342) --- .../resources/ui/src/axiosAPIs/miscAPI.ts | 25 +- .../DashboardDetails.component.tsx | 4 +- .../DatasetDetails.component.tsx | 4 +- .../components/ManageTab/DeleteWidgetBody.tsx | 52 ++++ .../ManageTab/ManageTab.component.tsx | 87 +++---- .../ManageTab/ManageTab.interface.ts | 2 + .../components/ManageTab/ManageTab.test.tsx | 22 +- .../EntityDeleteModal/EntityDeleteModal.tsx | 12 +- .../PipelineDetails.component.tsx | 4 +- .../components/TeamDetails/TeamDetails.tsx | 233 ++++++++---------- .../TeamsAndUsers/TeamsAndUsers.component.tsx | 6 - .../TopicDetails/TopicDetails.component.tsx | 4 +- .../ui/src/components/app-bar/Appbar-old.tsx | 4 +- .../ui/src/components/app-bar/Appbar.tsx | 4 +- .../resources/ui/src/constants/constants.ts | 21 +- .../ui/src/constants/entity.constants.ts | 1 + .../src/interface/teamsAndUsers.interface.ts | 10 +- .../DatabaseSchemaPage.component.tsx | 4 +- .../TeamsAndUsersPage.component.tsx | 91 ++----- .../ui/src/pages/database-details/index.tsx | 4 +- .../resources/ui/src/pages/service/index.tsx | 4 +- .../resources/ui/src/pages/teams/index.tsx | 8 +- .../ui/src/router/AuthenticatedAppRouter.tsx | 9 - .../main/resources/ui/src/styles/tailwind.css | 3 +- .../resources/ui/src/utils/EntityUtils.tsx | 8 +- .../ui/src/utils/EntityVersionUtils.tsx | 9 +- 26 files changed, 295 insertions(+), 340 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/ManageTab/DeleteWidgetBody.tsx diff --git a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/miscAPI.ts b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/miscAPI.ts index 8c2f4337fcc..5376268539e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/miscAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/miscAPI.ts @@ -123,17 +123,24 @@ export const getInitialEntity: Function = (): Promise => { export const deleteEntity: Function = ( entityType: string, entityId: string, - isRecursive: boolean + isRecursive: boolean, + isSoftDelete = false ): Promise => { - const searchParams = new URLSearchParams({ hardDelete: `true` }); - if (!isUndefined(isRecursive)) { - searchParams.set('recursive', `${isRecursive}`); + let path = ''; + + if (isSoftDelete) { + path = getURLWithQueryFields(`/${entityType}/${entityId}`); + } else { + const searchParams = new URLSearchParams({ hardDelete: `true` }); + if (!isUndefined(isRecursive)) { + searchParams.set('recursive', `${isRecursive}`); + } + path = getURLWithQueryFields( + `/${entityType}/${entityId}`, + '', + `${searchParams.toString()}` + ); } - const path = getURLWithQueryFields( - `/${entityType}/${entityId}`, - '', - `${searchParams.toString()}` - ); return APIClient.delete(path); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx index 2506bbb7611..45db0bf562b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DashboardDetails/DashboardDetails.component.tsx @@ -18,7 +18,7 @@ import React, { RefObject, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; -import { getTeamDetailsPath } from '../../constants/constants'; +import { getTeamAndUserDetailsPath } from '../../constants/constants'; import { observerOptions } from '../../constants/Mydata.constants'; import { EntityType } from '../../enums/entity.enum'; import { Dashboard } from '../../generated/entity/data/dashboard'; @@ -200,7 +200,7 @@ const DashboardDetails = ({ key: 'Owner', value: owner?.type === 'team' - ? getTeamDetailsPath(owner?.name || '') + ? getTeamAndUserDetailsPath(owner?.name || '') : getEntityName(owner), placeholderText: getEntityPlaceHolder( getEntityName(owner), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DatasetDetails/DatasetDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DatasetDetails/DatasetDetails.component.tsx index aa2cc5d1a93..bc69dbe273b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DatasetDetails/DatasetDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DatasetDetails/DatasetDetails.component.tsx @@ -17,7 +17,7 @@ import { ColumnJoins, EntityTags, ExtraInfo } from 'Models'; import React, { RefObject, useEffect, useState } from 'react'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; -import { getTeamDetailsPath, ROUTES } from '../../constants/constants'; +import { getTeamAndUserDetailsPath, ROUTES } from '../../constants/constants'; import { observerOptions } from '../../constants/Mydata.constants'; import { CSMode } from '../../enums/codemirror.enum'; import { EntityType, FqnPart } from '../../enums/entity.enum'; @@ -329,7 +329,7 @@ const DatasetDetails: React.FC = ({ key: 'Owner', value: owner?.type === 'team' - ? getTeamDetailsPath(owner?.name || '') + ? getTeamAndUserDetailsPath(owner?.name || '') : getEntityName(owner), placeholderText: getEntityPlaceHolder( getEntityName(owner), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/DeleteWidgetBody.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/DeleteWidgetBody.tsx new file mode 100644 index 00000000000..7ed578ef36f --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/DeleteWidgetBody.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants'; +import { Button } from '../buttons/Button/Button'; +import NonAdminAction from '../common/non-admin-action/NonAdminAction'; + +type DeleteWidgetBodyProps = { + header: string; + description: string; + buttonText: string; + isOwner?: boolean; + hasPermission: boolean; + onClick: () => void; +}; + +const DeleteWidgetBody = ({ + header, + description, + buttonText, + isOwner, + hasPermission, + onClick, +}: DeleteWidgetBodyProps) => { + return ( +
+
+

+ {header} +

+

{description}

+
+ {TITLE_FOR_NON_ADMIN_ACTION}

} + isOwner={isOwner} + position="left"> + +
+
+ ); +}; + +export default DeleteWidgetBody; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx index 27c2d7b724e..6ef5e66931b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.component.tsx @@ -24,7 +24,6 @@ import { useAuthContext } from '../../authentication/auth-provider/AuthProvider' import { deleteEntity } from '../../axiosAPIs/miscAPI'; import { getCategory } from '../../axiosAPIs/tagAPI'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; -import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants'; import { ENTITY_DELETE_STATE } from '../../constants/entity.constants'; import { EntityType } from '../../enums/entity.enum'; import { Operation } from '../../generated/entity/policies/accessControl/rule'; @@ -37,9 +36,11 @@ import { Button } from '../buttons/Button/Button'; import CardListItem from '../card-list/CardListItem/CardWithListItems'; import { CardWithListItems } from '../card-list/CardListItem/CardWithListItems.interface'; import NonAdminAction from '../common/non-admin-action/NonAdminAction'; +import ToggleSwitchV1 from '../common/toggle-switch/ToggleSwitchV1'; import DropDownList from '../dropdown/DropDownList'; import Loader from '../Loader/Loader'; import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal'; +import DeleteWidgetBody from './DeleteWidgetBody'; import { ManageProps, Status } from './ManageTab.interface'; const ManageTab: FunctionComponent = ({ @@ -54,8 +55,10 @@ const ManageTab: FunctionComponent = ({ entityName, entityType, entityId, + allowSoftDelete, isRecursiveDelete, deletEntityMessage, + handleIsJoinable, }: ManageProps) => { const history = useHistory(); const { userPermissions, isAdminUser } = useAuth(); @@ -161,8 +164,8 @@ const ManageTab: FunctionComponent = ({ setActiveTier(cardId); }; - const handleOnEntityDelete = () => { - setEntityDeleteState((prev) => ({ ...prev, state: true })); + const handleOnEntityDelete = (softDelete = false) => { + setEntityDeleteState((prev) => ({ ...prev, state: true, softDelete })); }; const handleOnEntityDeleteCancel = () => { @@ -190,7 +193,12 @@ const ManageTab: FunctionComponent = ({ const handleOnEntityDeleteConfirm = () => { setEntityDeleteState((prev) => ({ ...prev, loading: 'waiting' })); - deleteEntity(prepareEntityType(), entityId, isRecursiveDelete) + deleteEntity( + prepareEntityType(), + entityId, + isRecursiveDelete, + allowSoftDelete + ) .then((res: AxiosResponse) => { if (res.status === 200) { setTimeout(() => { @@ -227,6 +235,7 @@ const ManageTab: FunctionComponent = ({ entityName={entityName as string} entityType={entityType as string} loadingState={entityDeleteState.loading} + softDelete={entityDeleteState.softDelete} onCancel={handleOnEntityDeleteCancel} onConfirm={handleOnEntityDeleteConfirm} /> @@ -240,34 +249,28 @@ const ManageTab: FunctionComponent = ({ return allowDelete && entityId && entityName && entityType ? (

-
-
-

- Delete {entityType} {entityName} -

-

{prepareDeleteMessage()}

-
- -

{TITLE_FOR_NON_ADMIN_ACTION}

- - } +
+ {allowSoftDelete && ( +
+ handleOnEntityDelete(true)} + /> +
+ )} + + - - + onClick={handleOnEntityDelete} + />
) : null; @@ -315,18 +318,18 @@ const ManageTab: FunctionComponent = ({ userPermissions[Operation.UpdateTeam] || !hasEditAccess; - const joinableSwitch = isActionAllowed ? ( -
- -
setTeamJoinable((prev) => !prev)}> -
+ const joinableSwitch = + isActionAllowed && !isUndefined(teamJoinable) ? ( +
+ + { + handleIsJoinable?.(!teamJoinable); + }} + />
-
- ) : null; + ) : null; return !isUndefined(isJoinable) ? (
{joinableSwitch}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.interface.ts index 3c293993e21..37163fcb02b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.interface.ts @@ -18,11 +18,13 @@ export interface ManageProps { currentUser?: string; hideTier?: boolean; isJoinable?: boolean; + allowSoftDelete?: boolean; onSave: ( owner: TableDetail['owner'], tier: TableDetail['tier'], isJoinable?: boolean ) => Promise; + handleIsJoinable?: (bool: boolean) => void; hasEditAccess: boolean; allowTeamOwner?: boolean; entityId?: string; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.test.tsx index db803fed452..d7c36005f20 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ManageTab/ManageTab.test.tsx @@ -14,7 +14,7 @@ import { findAllByTestId, findByTestId, - fireEvent, + findByText, render, } from '@testing-library/react'; import React from 'react'; @@ -41,6 +41,10 @@ jest.mock('../../hooks/authHooks', () => ({ }), })); +jest.mock('../common/toggle-switch/ToggleSwitchV1', () => { + return jest.fn().mockImplementation(() =>

ToggleSwitchV1.Component

); +}); + const mockTierData = { children: [ { @@ -96,23 +100,11 @@ describe('Test Manage tab Component', () => { ); - const isJoinableSwitch = await findByTestId( + const isJoinableSwitch = await findByText( container, - 'team-isJoinable-switch' + 'ToggleSwitchV1.Component' ); - expect(isJoinableSwitch).toHaveClass('open'); - - fireEvent.click( - isJoinableSwitch, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); - - expect(isJoinableSwitch).not.toHaveClass('open'); - expect(isJoinableSwitch).toBeInTheDocument(); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx index b95d0854084..d2eadfa1037 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Modals/EntityDeleteModal/EntityDeleteModal.tsx @@ -29,6 +29,7 @@ interface Prop extends HTMLAttributes { entityType: string; loadingState: string; bodyText?: string; + softDelete?: boolean; } const EntityDeleteModal: FC = ({ @@ -39,6 +40,7 @@ const EntityDeleteModal: FC = ({ onCancel, onConfirm, bodyText, + softDelete = false, }: Prop) => { const [name, setName] = useState(''); @@ -58,7 +60,15 @@ const EntityDeleteModal: FC = ({

- Delete {entityName} + {softDelete ? ( + + Soft delete {entityName} + + ) : ( + + Delete {entityName} + + )}

diff --git a/openmetadata-ui/src/main/resources/ui/src/components/PipelineDetails/PipelineDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/PipelineDetails/PipelineDetails.component.tsx index 9efcb5b7812..d06f3dbfd91 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/PipelineDetails/PipelineDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/PipelineDetails/PipelineDetails.component.tsx @@ -19,7 +19,7 @@ import React, { Fragment, RefObject, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; -import { getTeamDetailsPath } from '../../constants/constants'; +import { getTeamAndUserDetailsPath } from '../../constants/constants'; import { observerOptions } from '../../constants/Mydata.constants'; import { EntityType } from '../../enums/entity.enum'; import { Pipeline, Task } from '../../generated/entity/data/pipeline'; @@ -207,7 +207,7 @@ const PipelineDetails = ({ key: 'Owner', value: owner?.type === 'team' - ? getTeamDetailsPath(owner?.name || '') + ? getTeamAndUserDetailsPath(owner?.name || '') : getEntityName(owner), placeholderText: getEntityPlaceHolder( getEntityName(owner), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx index 30ada07eee5..d25e2bd6afb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamDetails/TeamDetails.tsx @@ -15,13 +15,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import { compare } from 'fast-json-patch'; import { cloneDeep, orderBy } from 'lodash'; -import { ExtraInfo } from 'Models'; +import { ExtraInfo, TableDetail } from 'Models'; import React, { Fragment, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import AppState from '../../AppState'; import { getTeamAndUserDetailsPath, - PAGE_SIZE_12, + PAGE_SIZE_MEDIUM, TITLE_FOR_NON_ADMIN_ACTION, } from '../../constants/constants'; import { OwnerType } from '../../enums/user.enum'; @@ -37,7 +37,6 @@ import AddUsersModal from '../../pages/teams/AddUsersModal'; import UserCard from '../../pages/teams/UserCard'; import { hasEditAccess } from '../../utils/CommonUtils'; import { getInfoElements } from '../../utils/EntityUtils'; -import { getOwnerList } from '../../utils/ManageUtils'; import SVGIcons from '../../utils/SvgUtils'; import { Button } from '../buttons/Button/Button'; import Description from '../common/description/Description'; @@ -46,8 +45,7 @@ import NextPrevious from '../common/next-previous/NextPrevious'; import NonAdminAction from '../common/non-admin-action/NonAdminAction'; import Searchbar from '../common/searchbar/Searchbar'; import TabsPane from '../common/TabsPane/TabsPane'; -import ToggleSwitchV1 from '../common/toggle-switch/ToggleSwitchV1'; -import DropDownList from '../dropdown/DropDownList'; +import ManageTab from '../ManageTab/ManageTab.component'; import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal'; import FormModal from '../Modals/FormModal'; import Form from './Form'; @@ -63,9 +61,6 @@ const TeamDetails = ({ isDescriptionEditable, errorNewTeamData, isAddingTeam, - deletingTeam, - deleteTeamById, - handleDeleteTeam, handleAddTeam, createNewTeam, onNewTeamDataChange, @@ -81,8 +76,12 @@ const TeamDetails = ({ handleAddUser, removeUserFromTeam, }: TeamDetailsProp) => { + const DELETE_USER_INITIAL_STATE = { + user: undefined, + state: false, + leave: false, + }; const { userPermissions } = useAuth(); - const [showOwnerDropdown, setShowOwnerDropdown] = useState(false); const [currentTab, setCurrentTab] = useState(1); const [isHeadingEditing, setIsHeadingEditing] = useState(false); const [currentUser, setCurrentUser] = useState(); @@ -92,7 +91,19 @@ const TeamDetails = ({ const [deletingUser, setDeletingUser] = useState<{ user: UserTeams | undefined; state: boolean; - }>({ user: undefined, state: false }); + leave: boolean; + }>(DELETE_USER_INITIAL_STATE); + + /** + * Check if current team is the owner or not + * @returns - True true or false based on hasEditAccess response + */ + const isOwner = () => { + return hasEditAccess( + currentTeam?.owner?.type || '', + currentTeam?.owner?.id || '' + ); + }; const tabs = [ { @@ -113,6 +124,12 @@ const TeamDetails = ({ position: 3, count: currentTeam?.defaultRoles?.length, }, + { + name: 'Manage', + isProtected: false, + isHidden: isOwner() || userPermissions[Operation.UpdateOwner], + position: 4, + }, ]; const extraInfo: ExtraInfo = { @@ -129,44 +146,15 @@ const TeamDetails = ({ openInNewTab: false, }; - /** - * Check if current team is the owner or not - * @returns - True true or false based on hasEditAccess response - */ - const isOwner = () => { - return hasEditAccess( - currentTeam?.owner?.type || '', - currentTeam?.owner?.id || '' - ); - }; - const isActionAllowed = (operation = false) => { return hasAccess || isOwner() || operation; }; - const handleOwnerSelection = ( - _e: React.MouseEvent, - value?: string - ) => { - if (value && currentTeam) { - const updatedData: Team = { - ...currentTeam, - owner: { - id: value, - type: OwnerType.USER, - }, - }; - - updateTeamHandler(updatedData); - } - setShowOwnerDropdown(false); - }; - - const handleOpenToJoinToggle = () => { + const handleOpenToJoinToggle = (value: boolean) => { if (currentTeam) { const updatedData: Team = { ...currentTeam, - isJoinable: !currentTeam.isJoinable, + isJoinable: value, }; updateTeamHandler(updatedData); } @@ -174,7 +162,7 @@ const TeamDetails = ({ const handleRemoveUser = () => { removeUserFromTeam(deletingUser.user?.id as string).then(() => { - setDeletingUser({ user: undefined, state: false }); + setDeletingUser(DELETE_USER_INITIAL_STATE); }); }; @@ -217,6 +205,19 @@ const TeamDetails = ({ } }; + const handleManageSave = (owner: TableDetail['owner']) => { + if (currentTeam) { + const updatedData: Team = { + ...currentTeam, + owner: owner, + }; + + return updateTeamHandler(updatedData); + } + + return Promise.reject(); + }; + useEffect(() => { if (currentTeam) { setHeading(currentTeam.displayName); @@ -228,23 +229,19 @@ const TeamDetails = ({ * Take user id as input to find out the user data and set it for delete * @param id - user id */ - const deleteUserHandler = (id: string) => { + const deleteUserHandler = (id: string, leave = false) => { const user = [...(currentTeam?.users as Array)].find( (u) => u.id === id ); - setDeletingUser({ user, state: true }); + setDeletingUser({ user, state: true, leave }); }; - const getJoinableWidget = () => { - return isActionAllowed(userPermissions[Operation.UpdateTeam]) ? ( -
- - -
- ) : null; + const removeUserBodyText = (leave: boolean) => { + const text = leave + ? `leave the team ${currentTeam?.displayName ?? currentTeam?.name}?` + : `remove ${deletingUser.user?.displayName ?? deletingUser.user?.name}?`; + + return `Are you sure you want to ${text}`; }; /** @@ -334,11 +331,11 @@ const TeamDetails = ({ ); })}
- {teamUserPagin.total > PAGE_SIZE_12 && ( + {teamUserPagin.total > PAGE_SIZE_MEDIUM && ( {getTeamHeading()}
- {isActionAllowed() ? ( + {isActionAllowed() && ( { handleAddTeam(true); }}> Create New Team - - You do not have permission to delete the team. - - } - isOwner={isOwner()} - position="bottom"> - - - ) : !isAlreadyJoinedTeam(currentTeam.id) && + )} + {!isAlreadyJoinedTeam(currentTeam.id) ? ( currentTeam.isJoinable ? ( + + ) : null + ) : ( - ) : null} + )}
{getInfoElements(extraInfo)} - {isActionAllowed(userPermissions[Operation.UpdateOwner]) && ( - - - - {showOwnerDropdown && ( - - )} - - )}
-
{getJoinableWidget()}
+ +
+ )}
@@ -657,30 +637,13 @@ const TeamDetails = ({ /> )} - {deletingTeam.state && ( - handleDeleteTeam({ team: undefined, state: false })} - onConfirm={() => { - deleteTeamById(deletingTeam.team?.id as string); - }} - /> - )} - {deletingUser.state && ( setDeletingUser({ user: undefined, state: false })} + header={deletingUser.leave ? 'Leave team' : 'Removing user'} + onCancel={() => setDeletingUser(DELETE_USER_INITIAL_STATE)} onConfirm={handleRemoveUser} /> )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamsAndUsers/TeamsAndUsers.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TeamsAndUsers/TeamsAndUsers.component.tsx index 7cd6b31381e..d54130cc3e9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TeamsAndUsers/TeamsAndUsers.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamsAndUsers/TeamsAndUsers.component.tsx @@ -45,9 +45,6 @@ const TeamsAndUsers = ({ isAddingTeam, createNewTeam, handleAddNewUser, - deletingTeam, - deleteTeamById, - handleDeleteTeam, handleAddTeam, onNewTeamDataChange, updateTeamHandler, @@ -167,14 +164,11 @@ const TeamsAndUsers = ({ currentTeam={currentTeam} currentTeamUserPage={currentTeamUserPage} currentTeamUsers={currentTeamUsers} - deleteTeamById={deleteTeamById} - deletingTeam={deletingTeam} descriptionHandler={descriptionHandler} errorNewTeamData={errorNewTeamData} getUniqueUserList={getUniqueUserList} handleAddTeam={handleAddTeam} handleAddUser={handleAddUser} - handleDeleteTeam={handleDeleteTeam} handleJoinTeamClick={handleJoinTeamClick} handleTeamUsersSearchAction={handleTeamUsersSearchAction} hasAccess={hasAccess} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TopicDetails/TopicDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TopicDetails/TopicDetails.component.tsx index bd63c1592d9..5dece748b87 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TopicDetails/TopicDetails.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TopicDetails/TopicDetails.component.tsx @@ -15,7 +15,7 @@ import { EntityTags } from 'Models'; import React, { RefObject, useEffect, useState } from 'react'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; -import { getTeamDetailsPath } from '../../constants/constants'; +import { getTeamAndUserDetailsPath } from '../../constants/constants'; import { observerOptions } from '../../constants/Mydata.constants'; import { EntityType } from '../../enums/entity.enum'; import { Topic } from '../../generated/entity/data/topic'; @@ -198,7 +198,7 @@ const TopicDetails: React.FC = ({ key: 'Owner', value: owner?.type === 'team' - ? getTeamDetailsPath(owner?.name || '') + ? getTeamAndUserDetailsPath(owner?.name || '') : getEntityName(owner), placeholderText: getEntityPlaceHolder( getEntityName(owner), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar-old.tsx b/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar-old.tsx index 1bbee49080d..8ecc426a53e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar-old.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar-old.tsx @@ -22,7 +22,7 @@ import appState from '../../AppState'; import { getVersion } from '../../axiosAPIs/miscAPI'; import { getExplorePathWithSearch, - getTeamDetailsPath, + getTeamAndUserDetailsPath, navLinkSettings, ROUTES, } from '../../constants/constants'; @@ -166,7 +166,7 @@ const Appbar: React.FC = (): JSX.Element => { Teams {teams?.map((t, i) => (

- + {t.displayName}

diff --git a/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar.tsx b/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar.tsx index 0dff335a37f..5ef8f15ff91 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/app-bar/Appbar.tsx @@ -23,7 +23,7 @@ import { useAuthContext } from '../../authentication/auth-provider/AuthProvider' import { getVersion } from '../../axiosAPIs/miscAPI'; import { getExplorePathWithSearch, - getTeamDetailsPath, + getTeamAndUserDetailsPath, getUserPath, navLinkSettings, ROUTES, @@ -181,7 +181,7 @@ const Appbar: React.FC = (): JSX.Element => { Teams {teams.map((t, i) => (

- + {t.displayName}

diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts index 709c0c02683..ffa681285b4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts @@ -17,7 +17,7 @@ import { FQN_SEPARATOR_CHAR } from './char.constants'; export const FOLLOWERS_VIEW_CAP = 20; export const JSON_TAB_SIZE = 2; export const PAGE_SIZE = 10; -export const PAGE_SIZE_12 = 12; +export const PAGE_SIZE_MEDIUM = 16; export const API_RES_MAX_SIZE = 100000; export const LIST_SIZE = 5; export const SIDEBAR_WIDTH_COLLAPSED = 290; @@ -50,7 +50,6 @@ const PLACEHOLDER_ROUTE_SERVICE_FQN = ':serviceFQN'; export const PLACEHOLDER_ROUTE_SERVICE_CAT = ':serviceCategory'; const PLACEHOLDER_ROUTE_SEARCHQUERY = ':searchQuery'; const PLACEHOLDER_ROUTE_TAB = ':tab'; -const PLACEHOLDER_ROUTE_TEAM = ':team'; const PLACEHOLDER_ROUTE_TEAM_AND_USER = ':teamAndUser'; const PLAEHOLDER_ROUTE_VERSION = ':version'; const PLACEHOLDER_ROUTE_ENTITY_TYPE = ':entityType'; @@ -151,8 +150,6 @@ export const ROUTES = { EXPLORE_WITH_TAB: `/explore/${PLACEHOLDER_ROUTE_TAB}`, WORKFLOWS: '/workflows', SQL_BUILDER: '/sql-builder', - TEAMS: '/teams', - TEAM_DETAILS: `/teams/${PLACEHOLDER_ROUTE_TEAM}`, TEAMS_AND_USERS: '/teams-and-users', TEAMS_AND_USERS_DETAILS: `/teams-and-users/${PLACEHOLDER_ROUTE_TEAM_AND_USER}`, SETTINGS: '/settings', @@ -325,16 +322,6 @@ export const getTeamAndUserDetailsPath = (name?: string) => { return path; }; -export const getTeamDetailsPath = (teamName?: string) => { - let path = ROUTES.TEAMS; - if (teamName) { - path = ROUTES.TEAM_DETAILS; - path = path.replace(PLACEHOLDER_ROUTE_TEAM, teamName); - } - - return path; -}; - export const getEditWebhookPath = (webhookName: string) => { let path = ROUTES.EDIT_WEBHOOK; path = path.replace(PLACEHOLDER_WEBHOOK_NAME, webhookName); @@ -406,13 +393,7 @@ export const navLinkSettings = [ { name: 'Services', to: '/services', disabled: false }, { name: 'Tags', to: '/tags', disabled: false }, { name: 'Teams & Users', to: ROUTES.TEAMS_AND_USERS, disabled: false }, - // { name: 'Teams', to: '/teams', disabled: false }, - // { name: 'Users', to: '/user-list', disabled: false, isAdminOnly: true }, - // { name: 'Store', to: '/store', disabled: false }, { name: 'Webhooks', to: '/webhooks', disabled: false }, - // { name: 'Ingestions', to: '/ingestion', disabled: false }, - // { name: 'Marketplace', to: '/marketplace', disabled: true }, - // { name: 'Preferences', to: '/preference', disabled: true }, ]; export const TITLE_FOR_NON_OWNER_ACTION = diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/entity.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/entity.constants.ts index 59630db4c41..7028f1e477e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/entity.constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/entity.constants.ts @@ -14,4 +14,5 @@ export const ENTITY_DELETE_STATE = { loading: 'initial', state: false, + softDelete: false, }; diff --git a/openmetadata-ui/src/main/resources/ui/src/interface/teamsAndUsers.interface.ts b/openmetadata-ui/src/main/resources/ui/src/interface/teamsAndUsers.interface.ts index edc021b67af..710f0f64b11 100644 --- a/openmetadata-ui/src/main/resources/ui/src/interface/teamsAndUsers.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/interface/teamsAndUsers.interface.ts @@ -47,16 +47,13 @@ export interface TeamsAndUsersProps { updateUser: (id: string, data: Operation[], updatedUser: User) => void; createNewTeam: (data: Team) => void; handleAddTeam: (value: boolean) => void; - handleDeleteTeam: (data: TeamDeleteType) => void; - deleteTeamById: (id: string) => void; - deletingTeam: TeamDeleteType; onNewTeamDataChange: ( data: Team, forceSet?: boolean ) => { [key: string]: string; }; - updateTeamHandler: (data: Team) => void; + updateTeamHandler: (data: Team) => Promise; handleDeleteUser: (id: string) => void; handleTeamUsersSearchAction: (text: string) => void; teamUserPaginHandler: ( @@ -88,9 +85,6 @@ export interface TeamDetailsProp { hasAccess: boolean; errorNewTeamData: FormErrorData | undefined; isAddingTeam: boolean; - handleDeleteTeam: (data: TeamDeleteType) => void; - deleteTeamById: (id: string) => void; - deletingTeam: TeamDeleteType; handleAddTeam: (value: boolean) => void; onNewTeamDataChange: ( data: Team, @@ -101,7 +95,7 @@ export interface TeamDetailsProp { descriptionHandler: (value: boolean) => void; onDescriptionUpdate: (value: string) => void; handleTeamUsersSearchAction: (text: string) => void; - updateTeamHandler: (data: Team) => void; + updateTeamHandler: (data: Team) => Promise; createNewTeam: (data: Team) => void; teamUserPaginHandler: ( cursorValue: string | number, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx index 7f6044e1a63..a2c06c0c492 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx @@ -59,7 +59,7 @@ import { getDatabaseSchemaDetailsPath, getServiceDetailsPath, getTableDetailsPath, - getTeamDetailsPath, + getTeamAndUserDetailsPath, } from '../../constants/constants'; import { observerOptions } from '../../constants/Mydata.constants'; import { EntityType, FqnPart, TabSpecificField } from '../../enums/entity.enum'; @@ -174,7 +174,7 @@ const DatabaseSchemaPage: FunctionComponent = () => { key: 'Owner', value: databaseSchema?.owner?.type === 'team' - ? getTeamDetailsPath( + ? getTeamAndUserDetailsPath( databaseSchema?.owner?.displayName || databaseSchema?.owner?.name || '' diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TeamsAndUsersPage/TeamsAndUsersPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TeamsAndUsersPage/TeamsAndUsersPage.component.tsx index de22a8a307a..d2aa73860d1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TeamsAndUsersPage/TeamsAndUsersPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TeamsAndUsersPage/TeamsAndUsersPage.component.tsx @@ -23,7 +23,6 @@ import { useAuthContext } from '../../authentication/auth-provider/AuthProvider' import { searchData } from '../../axiosAPIs/miscAPI'; import { createTeam, - deleteTeam, getTeamByName, getTeams, patchTeamDetail, @@ -38,7 +37,7 @@ import Loader from '../../components/Loader/Loader'; import TeamsAndUsers from '../../components/TeamsAndUsers/TeamsAndUsers.component'; import { getTeamAndUserDetailsPath, - PAGE_SIZE_12, + PAGE_SIZE_MEDIUM, ROUTES, } from '../../constants/constants'; import { SearchIndex } from '../../enums/search.enum'; @@ -50,7 +49,6 @@ import { } from '../../generated/entity/teams/user'; import { Paging } from '../../generated/type/paging'; import { useAuth } from '../../hooks/authHooks'; -import { TeamDeleteType } from '../../interface/teamsAndUsers.interface'; import jsonData from '../../jsons/en'; import { formatUsersResponse } from '../../utils/APIUtils'; import { isUrlFriendlyName } from '../../utils/CommonUtils'; @@ -74,10 +72,6 @@ const TeamsAndUsersPage = () => { const [isAddingTeam, setIsAddingTeam] = useState(false); const [isAddingUsers, setIsAddingUsers] = useState(false); const [errorNewTeamData, setErrorNewTeamData] = useState(); - const [deletingTeam, setDeletingTeam] = useState({ - team: undefined, - state: false, - }); const [activeUserTab, setactiveUserTab] = useState(); const [userList, setUserList] = useState>([]); const [users, setUsers] = useState>([]); @@ -94,10 +88,6 @@ const TeamsAndUsersPage = () => { setIsAddingTeam(value); }; - const handleDeleteTeam = (data: TeamDeleteType) => { - setDeletingTeam(data); - }; - const handleAddUser = (data: boolean) => { setIsAddingUsers(data); }; @@ -228,7 +218,7 @@ const TeamsAndUsersPage = () => { team: string, pagin = {} as { [key: string]: string } ) => { - getUsers('', PAGE_SIZE_12, { team, ...pagin }).then( + getUsers('', PAGE_SIZE_MEDIUM, { team, ...pagin }).then( (res: AxiosResponse) => { if (res.data) { setCurrentTeamUsers(res.data.data); @@ -273,7 +263,7 @@ const TeamsAndUsersPage = () => { */ const fetchCurrentTeam = (name: string, update = false) => { if (currentTeam?.name !== name || update) { - setIsLoading(true); + // setIsLoading(true); getTeamByName(name, ['users', 'owns', 'defaultRoles', 'owner']) .then((res: AxiosResponse) => { if (res.data) { @@ -308,43 +298,11 @@ const TeamsAndUsersPage = () => { } }; - const goToTeams = () => { - if (teamAndUser) { - history.push(getTeamAndUserDetailsPath()); - } else { - fetchTeams(); - } - }; - - /** - * Take team id and delete the team - * @param id - Team id - */ - const deleteTeamById = (id: string) => { - deleteTeam(id) - .then((res: AxiosResponse) => { - if (res.data) { - goToTeams(); - } else { - throw jsonData['api-error-messages']['unexpected-server-response']; - } - }) - .catch((err: AxiosError) => { - showErrorToast( - err, - jsonData['api-error-messages']['delete-team-error'] - ); - }) - .finally(() => { - setDeletingTeam({ team: undefined, state: false }); - }); - }; - const searchUsers = (text: string, currentPage: number) => { searchData( text, currentPage, - PAGE_SIZE_12, + PAGE_SIZE_MEDIUM, `(teams:${currentTeam?.id})`, '', '', @@ -472,20 +430,27 @@ const TeamsAndUsersPage = () => { const updateTeamHandler = (updatedData: Team) => { const jsonPatch = compare(currentTeam as Team, updatedData); - patchTeamDetail(currentTeam?.id, jsonPatch) - .then((res: AxiosResponse) => { - if (res.data) { - fetchCurrentTeam(res.data.name, true); - } else { - throw jsonData['api-error-messages']['unexpected-server-response']; - } - }) - .catch((error: AxiosError) => { - showErrorToast( - error, - jsonData['api-error-messages']['update-team-error'] - ); - }); + + return new Promise((resolve, reject) => { + patchTeamDetail(currentTeam?.id, jsonPatch) + .then((res: AxiosResponse) => { + if (res.data) { + fetchCurrentTeam(res.data.name, true); + resolve(); + } else { + reject(); + + throw jsonData['api-error-messages']['unexpected-server-response']; + } + }) + .catch((error: AxiosError) => { + showErrorToast( + error, + jsonData['api-error-messages']['update-team-error'] + ); + reject(); + }); + }); }; /** @@ -560,8 +525,7 @@ const TeamsAndUsersPage = () => { * @param id - user id */ const removeUserFromTeam = (id: string) => { - const users = [...(currentTeam?.users as Array)]; - const newUsers = users.filter((user) => { + const newUsers = currentTeam?.users?.filter((user) => { return user.id !== id; }); const updatedTeam = { @@ -657,15 +621,12 @@ const TeamsAndUsersPage = () => { currentTeam={currentTeam} currentTeamUserPage={currentTeamUserPage} currentTeamUsers={currentTeamUsers} - deleteTeamById={deleteTeamById} - deletingTeam={deletingTeam} descriptionHandler={descriptionHandler} errorNewTeamData={errorNewTeamData} getUniqueUserList={getUniqueUserList} handleAddNewUser={handleAddNewUser} handleAddTeam={handleAddTeam} handleAddUser={handleAddUser} - handleDeleteTeam={handleDeleteTeam} handleDeleteUser={handleDeleteUser} handleJoinTeamClick={handleJoinTeamClick} handleTeamUsersSearchAction={handleTeamUsersSearchAction} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/database-details/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/database-details/index.tsx index f2517afedaa..4286efa2c11 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/database-details/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/database-details/index.tsx @@ -58,7 +58,7 @@ import { getDatabaseSchemaDetailsPath, getExplorePathWithSearch, getServiceDetailsPath, - getTeamDetailsPath, + getTeamAndUserDetailsPath, PAGE_SIZE, pagingObject, } from '../../constants/constants'; @@ -182,7 +182,7 @@ const DatabaseDetails: FunctionComponent = () => { key: 'Owner', value: database?.owner?.type === 'team' - ? getTeamDetailsPath( + ? getTeamAndUserDetailsPath( database?.owner?.displayName || database?.owner?.name || '' ) : database?.owner?.displayName || database?.owner?.name || '', diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx index 85fc5f9f1f0..b8c43ed7d67 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx @@ -48,7 +48,7 @@ import ServiceConfig from '../../components/ServiceConfig/ServiceConfig'; import TagsViewer from '../../components/tags-viewer/tags-viewer'; import { getServiceDetailsPath, - getTeamDetailsPath, + getTeamAndUserDetailsPath, PAGE_SIZE, pagingObject, } from '../../constants/constants'; @@ -186,7 +186,7 @@ const ServicePage: FunctionComponent = () => { key: 'Owner', value: serviceDetails?.owner?.type === 'team' - ? getTeamDetailsPath(serviceDetails?.owner?.name || '') + ? getTeamAndUserDetailsPath(serviceDetails?.owner?.name || '') : serviceDetails?.owner?.name || '', placeholderText: serviceDetails?.owner?.displayName || '', isLink: serviceDetails?.owner?.type === 'team', diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/teams/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/teams/index.tsx index 5bfb9f40acd..2ebe78dd20e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/teams/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/teams/index.tsx @@ -40,7 +40,7 @@ import ManageTabComponent from '../../components/ManageTab/ManageTab.component'; import ConfirmationModal from '../../components/Modals/ConfirmationModal/ConfirmationModal'; import FormModal from '../../components/Modals/FormModal'; import { - getTeamDetailsPath, + getTeamAndUserDetailsPath, TITLE_FOR_NON_ADMIN_ACTION, } from '../../constants/constants'; import { Operation } from '../../generated/entity/policies/accessControl/rule'; @@ -95,7 +95,7 @@ const TeamsPage = () => { key: 'Owner', value: currentTeam?.owner?.type === 'team' - ? getTeamDetailsPath( + ? getTeamAndUserDetailsPath( currentTeam?.owner?.displayName || currentTeam?.owner?.name || '' ) : currentTeam?.owner?.displayName || currentTeam?.owner?.name || '', @@ -149,7 +149,7 @@ const TeamsPage = () => { const goToTeams = () => { if (team) { - history.push(getTeamDetailsPath()); + history.push(getTeamAndUserDetailsPath()); } else { fetchTeams(); setCurrentTab(1); @@ -375,7 +375,7 @@ const TeamsPage = () => { * @param name - team name */ const changeCurrentTeam = (name: string) => { - history.push(getTeamDetailsPath(name)); + history.push(getTeamAndUserDetailsPath(name)); }; const Tabs = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx index 5280dafef71..d60bf8998e7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx @@ -37,11 +37,9 @@ import ServicesPage from '../pages/services'; import SignupPage from '../pages/signup'; import SwaggerPage from '../pages/swagger'; import TagsPage from '../pages/tags'; -import TeamsPage from '../pages/teams'; import TeamsAndUsersPage from '../pages/TeamsAndUsersPage/TeamsAndUsersPage.component'; import TopicDetailsPage from '../pages/TopicDetails/TopicDetailsPage.component'; import TourPageComponent from '../pages/tour-page/TourPage.component'; -import UserListPage from '../pages/UserListPage/UserListPage'; import UserPage from '../pages/UserPage/UserPage.component'; import WebhooksPage from '../pages/WebhooksPage/WebhooksPage.component'; import AdminProtectedRoute from './AdminProtectedRoute'; @@ -53,8 +51,6 @@ const AuthenticatedAppRouter: FunctionComponent = () => { - - { component={CreateUserPage} path={ROUTES.CREATE_USER} /> - ); diff --git a/openmetadata-ui/src/main/resources/ui/src/styles/tailwind.css b/openmetadata-ui/src/main/resources/ui/src/styles/tailwind.css index 0fc3e13bc4b..d2368611302 100644 --- a/openmetadata-ui/src/main/resources/ui/src/styles/tailwind.css +++ b/openmetadata-ui/src/main/resources/ui/src/styles/tailwind.css @@ -445,8 +445,9 @@ /* react tostify */ .Toastify__toast-container { - @apply tw-font-sans tw-break-all; + @apply tw-font-sans; width: 450px; + word-break: break-word; } .Toastify__toast { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index dae1b4c61ab..3d2df150bba 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -21,7 +21,7 @@ import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; import { getDatabaseDetailsPath, getServiceDetailsPath, - getTeamDetailsPath, + getTeamAndUserDetailsPath, } from '../constants/constants'; import { ColumnTestType } from '../enums/columnTest.enum'; import { EntityType, FqnPart } from '../enums/entity.enum'; @@ -127,7 +127,7 @@ export const getEntityOverview = ( { name: 'Owner', value: ownerValue?.displayName || ownerValue?.name || '--', - url: getTeamDetailsPath(owner?.name || ''), + url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: ownerValue ? ownerValue.type === 'team' ? true @@ -205,7 +205,7 @@ export const getEntityOverview = ( { name: 'Owner', value: ownerValue?.displayName || ownerValue?.name || '--', - url: getTeamDetailsPath(owner?.name || ''), + url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: ownerValue ? ownerValue.type === 'team' ? true @@ -253,7 +253,7 @@ export const getEntityOverview = ( { name: 'Owner', value: ownerValue?.displayName || ownerValue?.name || '--', - url: getTeamDetailsPath(owner?.name || ''), + url: getTeamAndUserDetailsPath(owner?.name || ''), isLink: ownerValue ? ownerValue.type === 'team' ? true diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx index 8219c67b8e5..e1f5ed7ea19 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityVersionUtils.tsx @@ -22,7 +22,10 @@ import { Link } from 'react-router-dom'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; import { FQN_SEPARATOR_CHAR } from '../constants/char.constants'; -import { DESCRIPTIONLENGTH, getTeamDetailsPath } from '../constants/constants'; +import { + DESCRIPTIONLENGTH, + getTeamAndUserDetailsPath, +} from '../constants/constants'; import { ChangeType } from '../enums/entity.enum'; import { Column } from '../generated/entity/data/table'; import { @@ -383,7 +386,7 @@ export const feedSummaryFromatter = ( {newValue?.type === 'team' ? ( + to={getTeamAndUserDetailsPath(newValue?.name || '')}> {ownerName} ) : ( @@ -397,7 +400,7 @@ export const feedSummaryFromatter = ( {value?.type === 'team' ? ( + to={getTeamAndUserDetailsPath(value?.name || '')}> {ownerName} ) : (