mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-16 03:08:13 +00:00
parent
87335137e5
commit
c586bb1aed
@ -44,3 +44,7 @@ export const patchTeamDetail: Function = (id: string, data: Team) => {
|
|||||||
|
|
||||||
return APIClient.patch(`/teams/${id}`, data, configOptions);
|
return APIClient.patch(`/teams/${id}`, data, configOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deleteTeam = (id: string): Promise<AxiosResponse> => {
|
||||||
|
return APIClient.delete(`/teams/${id}`);
|
||||||
|
};
|
||||||
|
@ -19,6 +19,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import {
|
import {
|
||||||
getExplorePathWithSearch,
|
getExplorePathWithSearch,
|
||||||
|
getTeamDetailsPath,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
TITLE_FOR_NON_ADMIN_ACTION,
|
TITLE_FOR_NON_ADMIN_ACTION,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
@ -103,7 +104,7 @@ const MyAssetStats: FunctionComponent<Props> = ({
|
|||||||
icon: Icons.TEAMS_GREY,
|
icon: Icons.TEAMS_GREY,
|
||||||
data: 'Teams',
|
data: 'Teams',
|
||||||
count: userTeams.length,
|
count: userTeams.length,
|
||||||
link: ROUTES.TEAMS,
|
link: getTeamDetailsPath(),
|
||||||
dataTestId: 'terms',
|
dataTestId: 'terms',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -274,9 +274,12 @@ export const getPipelineDetailsPath = (pipelineFQN: string, tab?: string) => {
|
|||||||
return path;
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTeamDetailsPath = (teamName: string) => {
|
export const getTeamDetailsPath = (teamName?: string) => {
|
||||||
let path = ROUTES.TEAM_DETAILS;
|
let path = ROUTES.TEAMS;
|
||||||
path = path.replace(PLACEHOLDER_ROUTE_TEAM, teamName);
|
if (teamName) {
|
||||||
|
path = ROUTES.TEAM_DETAILS;
|
||||||
|
path = path.replace(PLACEHOLDER_ROUTE_TEAM, teamName);
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@ const jsonData = {
|
|||||||
'add-glossary-term-error': 'Error while adding glossary term!',
|
'add-glossary-term-error': 'Error while adding glossary term!',
|
||||||
'delete-glossary-error': 'Error while deleting glossary!',
|
'delete-glossary-error': 'Error while deleting glossary!',
|
||||||
'delete-glossary-term-error': 'Error while deleting glossary term!',
|
'delete-glossary-term-error': 'Error while deleting glossary term!',
|
||||||
|
'delete-team-error': 'Error while deleting team!',
|
||||||
'elastic-search-error': 'Error while fetch data from Elasticsearch!',
|
'elastic-search-error': 'Error while fetch data from Elasticsearch!',
|
||||||
'fetch-data-error': 'Error while fetching data!',
|
'fetch-data-error': 'Error while fetching data!',
|
||||||
'fetch-glossary-error': 'Error while fetching glossary!',
|
'fetch-glossary-error': 'Error while fetching glossary!',
|
||||||
|
@ -107,6 +107,7 @@ jest.mock('../../axiosAPIs/teamsAPI', () => ({
|
|||||||
Promise.resolve({ data: { data: mockTeamsData } })
|
Promise.resolve({ data: { data: mockTeamsData } })
|
||||||
),
|
),
|
||||||
patchTeamDetail: jest.fn(),
|
patchTeamDetail: jest.fn(),
|
||||||
|
deleteTeam: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock(
|
jest.mock(
|
||||||
@ -269,4 +270,30 @@ describe('Test Teams page', () => {
|
|||||||
|
|
||||||
expect(await findByTestId(container, 'form-modal')).toBeInTheDocument();
|
expect(await findByTestId(container, 'form-modal')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('onClick of delete team button, delete modal should open', async () => {
|
||||||
|
const { container } = render(<TeamsPage />);
|
||||||
|
|
||||||
|
const deleteTeamButton = await findByTestId(
|
||||||
|
container,
|
||||||
|
'delete-team-button'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(deleteTeamButton).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(
|
||||||
|
deleteTeamButton,
|
||||||
|
new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const confirmationModal = await findByTestId(
|
||||||
|
container,
|
||||||
|
'confirmation-modal'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(confirmationModal).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { AxiosError, AxiosResponse } from 'axios';
|
import { AxiosError, AxiosResponse } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
@ -23,6 +24,7 @@ import AppState from '../../AppState';
|
|||||||
import { useAuthContext } from '../../auth-provider/AuthProvider';
|
import { useAuthContext } from '../../auth-provider/AuthProvider';
|
||||||
import {
|
import {
|
||||||
createTeam,
|
createTeam,
|
||||||
|
deleteTeam,
|
||||||
getTeamByName,
|
getTeamByName,
|
||||||
getTeams,
|
getTeams,
|
||||||
patchTeamDetail,
|
patchTeamDetail,
|
||||||
@ -50,6 +52,7 @@ import {
|
|||||||
} from '../../generated/entity/teams/user';
|
} from '../../generated/entity/teams/user';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import useToastContext from '../../hooks/useToastContext';
|
import useToastContext from '../../hooks/useToastContext';
|
||||||
|
import jsonData from '../../jsons/en';
|
||||||
import {
|
import {
|
||||||
getActiveCatClass,
|
getActiveCatClass,
|
||||||
getCountBadge,
|
getCountBadge,
|
||||||
@ -58,7 +61,6 @@ import {
|
|||||||
import AddUsersModal from './AddUsersModal';
|
import AddUsersModal from './AddUsersModal';
|
||||||
import Form from './Form';
|
import Form from './Form';
|
||||||
import UserCard from './UserCard';
|
import UserCard from './UserCard';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
|
|
||||||
const TeamsPage = () => {
|
const TeamsPage = () => {
|
||||||
const { team } = useParams() as Record<string, string>;
|
const { team } = useParams() as Record<string, string>;
|
||||||
@ -79,9 +81,20 @@ const TeamsPage = () => {
|
|||||||
user: EntityReference | undefined;
|
user: EntityReference | undefined;
|
||||||
state: boolean;
|
state: boolean;
|
||||||
}>({ user: undefined, state: false });
|
}>({ user: undefined, state: false });
|
||||||
|
const [deletingTeam, setDeletingTeam] = useState<{
|
||||||
|
team: Team | undefined;
|
||||||
|
state: boolean;
|
||||||
|
}>({ team: undefined, state: false });
|
||||||
|
|
||||||
const showToast = useToastContext();
|
const showToast = useToastContext();
|
||||||
|
|
||||||
|
const handleShowErrorToast = (errMessage: string) => {
|
||||||
|
showToast({
|
||||||
|
variant: 'error',
|
||||||
|
body: errMessage,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const fetchTeams = () => {
|
const fetchTeams = () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
getTeams(['users', 'owns', 'defaultRoles'])
|
getTeams(['users', 'owns', 'defaultRoles'])
|
||||||
@ -102,6 +115,15 @@ const TeamsPage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const goToTeams = () => {
|
||||||
|
if (team) {
|
||||||
|
history.push(getTeamDetailsPath());
|
||||||
|
} else {
|
||||||
|
fetchTeams();
|
||||||
|
setCurrentTab(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchCurrentTeam = (name: string, update = false) => {
|
const fetchCurrentTeam = (name: string, update = false) => {
|
||||||
if (currentTeam?.name !== name || update) {
|
if (currentTeam?.name !== name || update) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@ -226,6 +248,33 @@ const TeamsPage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deleteTeamHandler = () => {
|
||||||
|
const team = currentTeam;
|
||||||
|
setDeletingTeam({ team: team, state: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTeamById = (id: string) => {
|
||||||
|
deleteTeam(id)
|
||||||
|
.then((res: AxiosResponse) => {
|
||||||
|
if (res.data) {
|
||||||
|
goToTeams();
|
||||||
|
} else {
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['delete-team-error']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: AxiosError) => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
err.response?.data?.message ||
|
||||||
|
jsonData['api-error-messages']['delete-team-error']
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setDeletingTeam({ team: undefined, state: false });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getActiveTabClass = (tab: number) => {
|
const getActiveTabClass = (tab: number) => {
|
||||||
return tab === currentTab ? 'active' : '';
|
return tab === currentTab ? 'active' : '';
|
||||||
};
|
};
|
||||||
@ -514,27 +563,50 @@ const TeamsPage = () => {
|
|||||||
title={currentTeam?.displayName ?? currentTeam?.name}>
|
title={currentTeam?.displayName ?? currentTeam?.name}>
|
||||||
{currentTeam?.displayName ?? currentTeam?.name}
|
{currentTeam?.displayName ?? currentTeam?.name}
|
||||||
</div>
|
</div>
|
||||||
<NonAdminAction
|
<div>
|
||||||
html={
|
<NonAdminAction
|
||||||
<>You do not have permission to update the team.</>
|
html={
|
||||||
}
|
<>You do not have permission to update the team.</>
|
||||||
permission={Operation.UpdateTeam}
|
}
|
||||||
position="bottom">
|
permission={Operation.UpdateTeam}
|
||||||
<Button
|
position="bottom">
|
||||||
className={classNames('tw-h-8 tw-rounded tw-mb-3', {
|
<Button
|
||||||
'tw-opacity-40':
|
className={classNames('tw-h-8 tw-rounded tw-mb-3', {
|
||||||
!isAdminUser &&
|
'tw-opacity-40':
|
||||||
!isAuthDisabled &&
|
!isAdminUser &&
|
||||||
!userPermissions[Operation.UpdateTeam],
|
!isAuthDisabled &&
|
||||||
})}
|
!userPermissions[Operation.UpdateTeam],
|
||||||
data-testid="add-new-user-button"
|
})}
|
||||||
size="small"
|
data-testid="add-new-user-button"
|
||||||
theme="primary"
|
size="small"
|
||||||
variant="contained"
|
theme="primary"
|
||||||
onClick={() => setIsAddingUsers(true)}>
|
variant="contained"
|
||||||
Add new user
|
onClick={() => setIsAddingUsers(true)}>
|
||||||
</Button>
|
Add new user
|
||||||
</NonAdminAction>
|
</Button>
|
||||||
|
</NonAdminAction>
|
||||||
|
<NonAdminAction
|
||||||
|
html={
|
||||||
|
<>You do not have permission to delete the team.</>
|
||||||
|
}
|
||||||
|
position="bottom">
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
'tw-h-8 tw-rounded tw-mb-3 tw-ml-2',
|
||||||
|
{
|
||||||
|
'tw-opacity-40':
|
||||||
|
!isAdminUser && !isAuthDisabled,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
data-testid="delete-team-button"
|
||||||
|
size="small"
|
||||||
|
theme="primary"
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => deleteTeamHandler()}>
|
||||||
|
Delete Team
|
||||||
|
</Button>
|
||||||
|
</NonAdminAction>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="tw-mb-3 tw--ml-5"
|
className="tw-mb-3 tw--ml-5"
|
||||||
@ -625,6 +697,22 @@ const TeamsPage = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{deletingTeam.state && (
|
||||||
|
<ConfirmationModal
|
||||||
|
bodyText={`Are you sure you want to delete the team "${
|
||||||
|
deletingTeam.team?.displayName || deletingTeam.team?.name
|
||||||
|
}"?`}
|
||||||
|
cancelText="Cancel"
|
||||||
|
confirmText="Confirm"
|
||||||
|
header="Delete Team"
|
||||||
|
onCancel={() =>
|
||||||
|
setDeletingTeam({ team: undefined, state: false })
|
||||||
|
}
|
||||||
|
onConfirm={() => {
|
||||||
|
deleteTeamById(deletingTeam.team?.id as string);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user