mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-06 12:36:56 +00:00
This commit is contained in:
parent
c7cb6f22cd
commit
7eff7a0173
@ -14,7 +14,7 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import { observer } from 'mobx-react';
|
||||
import { TableDetail } from 'Models';
|
||||
import React, { FunctionComponent, useEffect, useState } from 'react';
|
||||
@ -36,9 +36,11 @@ type Props = {
|
||||
currentTier?: string;
|
||||
currentUser?: string;
|
||||
hideTier?: boolean;
|
||||
isJoinable?: boolean;
|
||||
onSave: (
|
||||
owner: TableDetail['owner'],
|
||||
tier: TableDetail['tier']
|
||||
tier: TableDetail['tier'],
|
||||
isJoinable?: boolean
|
||||
) => Promise<void>;
|
||||
hasEditAccess: boolean;
|
||||
allowTeamOwner?: boolean;
|
||||
@ -51,8 +53,9 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
onSave,
|
||||
hasEditAccess,
|
||||
allowTeamOwner = true,
|
||||
isJoinable,
|
||||
}: Props) => {
|
||||
const { userPermissions } = useAuth();
|
||||
const { userPermissions, isAdminUser } = useAuth();
|
||||
const { isAuthDisabled } = useAuthContext();
|
||||
const getOwnerList = () => {
|
||||
const user = !isEmpty(appState.userDetails)
|
||||
@ -113,6 +116,7 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
);
|
||||
const [activeTier, setActiveTier] = useState(currentTier);
|
||||
const [listVisible, setListVisible] = useState(false);
|
||||
const [teamJoinable, setTeamJoinable] = useState(isJoinable);
|
||||
|
||||
const [tierData, setTierData] = useState<Array<CardWithListItems>>([]);
|
||||
const [listOwners, setListOwners] = useState(getOwnerList());
|
||||
@ -163,8 +167,8 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
}
|
||||
: undefined;
|
||||
if (hideTier) {
|
||||
if (newOwner) {
|
||||
onSave(newOwner, '').catch(() => {
|
||||
if (newOwner || !isUndefined(teamJoinable)) {
|
||||
onSave(newOwner, '', Boolean(teamJoinable)).catch(() => {
|
||||
setInitialLoadingState();
|
||||
});
|
||||
} else {
|
||||
@ -172,7 +176,7 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
}
|
||||
} else {
|
||||
const newTier = activeTier !== currentTier ? activeTier : undefined;
|
||||
onSave(newOwner, newTier).catch(() => {
|
||||
onSave(newOwner, newTier, Boolean(teamJoinable)).catch(() => {
|
||||
setInitialLoadingState();
|
||||
});
|
||||
}
|
||||
@ -242,71 +246,101 @@ const ManageTab: FunctionComponent<Props> = ({
|
||||
setListOwners(getOwnerList());
|
||||
}, [appState.users, appState.userDetails, appState.userTeams]);
|
||||
|
||||
useEffect(() => {
|
||||
setTeamJoinable(isJoinable);
|
||||
}, [isJoinable]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="tw-max-w-3xl tw-mx-auto"
|
||||
data-testid="manage-tab"
|
||||
id="manageTabDetails">
|
||||
<div className="tw-mt-2 tw-mb-4 tw-pb-4 tw-border-b tw-border-separator">
|
||||
<span className="tw-mr-2">Owner:</span>
|
||||
<span className="tw-relative">
|
||||
<NonAdminAction
|
||||
html={
|
||||
<>
|
||||
<p>You do not have permissions to update the owner.</p>
|
||||
</>
|
||||
}
|
||||
isOwner={hasEditAccess}
|
||||
permission={Operation.UpdateOwner}
|
||||
position="left">
|
||||
<Button
|
||||
className={classNames('tw-underline', {
|
||||
'tw-opacity-40':
|
||||
<div className="tw-mt-2 tw-mb-4 tw-pb-4 tw-border-b tw-border-separator ">
|
||||
<div>
|
||||
<span className="tw-mr-2">Owner:</span>
|
||||
<span className="tw-relative">
|
||||
<NonAdminAction
|
||||
html={
|
||||
<>
|
||||
<p>You do not have permissions to update the owner.</p>
|
||||
</>
|
||||
}
|
||||
isOwner={hasEditAccess}
|
||||
permission={Operation.UpdateOwner}
|
||||
position="left">
|
||||
<Button
|
||||
className={classNames('tw-underline', {
|
||||
'tw-opacity-40':
|
||||
!userPermissions[Operation.UpdateOwner] &&
|
||||
!isAuthDisabled &&
|
||||
!hasEditAccess,
|
||||
})}
|
||||
data-testid="owner-dropdown"
|
||||
disabled={
|
||||
!userPermissions[Operation.UpdateOwner] &&
|
||||
!isAuthDisabled &&
|
||||
!hasEditAccess,
|
||||
})}
|
||||
data-testid="owner-dropdown"
|
||||
disabled={
|
||||
!userPermissions[Operation.UpdateOwner] &&
|
||||
!isAuthDisabled &&
|
||||
!hasEditAccess
|
||||
}
|
||||
size="custom"
|
||||
theme="primary"
|
||||
variant="link"
|
||||
onClick={() => setListVisible((visible) => !visible)}>
|
||||
{ownerName ? (
|
||||
<span
|
||||
className={classNames('tw-truncate', {
|
||||
'tw-w-52': ownerName.length > 32,
|
||||
})}
|
||||
title={ownerName}>
|
||||
{ownerName}
|
||||
</span>
|
||||
) : (
|
||||
'Select Owner'
|
||||
)}
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
className="tw-ml-1"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
!hasEditAccess
|
||||
}
|
||||
size="custom"
|
||||
theme="primary"
|
||||
variant="link"
|
||||
onClick={() => setListVisible((visible) => !visible)}>
|
||||
{ownerName ? (
|
||||
<span
|
||||
className={classNames('tw-truncate', {
|
||||
'tw-w-52': ownerName.length > 32,
|
||||
})}
|
||||
title={ownerName}>
|
||||
{ownerName}
|
||||
</span>
|
||||
) : (
|
||||
'Select Owner'
|
||||
)}
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
className="tw-ml-1"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
{listVisible && (
|
||||
<DropDownList
|
||||
showSearchBar
|
||||
dropDownList={listOwners}
|
||||
groupType="tab"
|
||||
listGroups={getOwnerGroup()}
|
||||
value={owner}
|
||||
onSelect={handleOwnerSelection}
|
||||
/>
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
{listVisible && (
|
||||
<DropDownList
|
||||
showSearchBar
|
||||
dropDownList={listOwners}
|
||||
groupType="tab"
|
||||
listGroups={getOwnerGroup()}
|
||||
value={owner}
|
||||
onSelect={handleOwnerSelection}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
{!isUndefined(isJoinable) ? (
|
||||
<div className="tw-mt-3 tw-mb-1">
|
||||
{isAdminUser ||
|
||||
isAuthDisabled ||
|
||||
userPermissions[Operation.UpdateTeam] ||
|
||||
!hasEditAccess ? (
|
||||
<div className="tw-flex">
|
||||
<label htmlFor="join-team">
|
||||
Allow users to join this team during signup
|
||||
</label>
|
||||
<div
|
||||
className={classNames(
|
||||
'toggle-switch ',
|
||||
teamJoinable ? 'open' : null
|
||||
)}
|
||||
data-testid="team-isJoinable-switch"
|
||||
id="join-team"
|
||||
onClick={() => setTeamJoinable((prev) => !prev)}>
|
||||
<div className="switch" />
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{!hideTier &&
|
||||
(isLoadingTierData ? (
|
||||
|
||||
@ -33,6 +33,15 @@ jest.mock('../../auth-provider/AuthProvider', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../hooks/authHooks', () => ({
|
||||
useAuth: jest.fn().mockReturnValue({
|
||||
isAdminUser: true,
|
||||
userPermissions: {
|
||||
UpdateTeam: true,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const mockTierData = {
|
||||
children: [
|
||||
{
|
||||
@ -118,4 +127,29 @@ describe('Test Manage tab Component', () => {
|
||||
|
||||
expect(mockFunction).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Should render switch if isJoinable is present', async () => {
|
||||
const { container } = render(
|
||||
<ManageTab hasEditAccess isJoinable onSave={mockFunction} />
|
||||
);
|
||||
|
||||
const isJoinableSwitch = await findByTestId(
|
||||
container,
|
||||
'team-isJoinable-switch'
|
||||
);
|
||||
|
||||
expect(isJoinableSwitch).toHaveClass('open');
|
||||
|
||||
fireEvent.click(
|
||||
isJoinableSwitch,
|
||||
new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
);
|
||||
|
||||
expect(isJoinableSwitch).not.toHaveClass('open');
|
||||
|
||||
expect(isJoinableSwitch).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -64,6 +64,7 @@ const jsonData = {
|
||||
'update-glossary-term-error': 'Error while updating glossary term!',
|
||||
'update-description-error': 'Error while updating description!',
|
||||
'update-entity-error': 'Error while updating entity!',
|
||||
'update-team-error': 'Error while updating team',
|
||||
'update-tags-error': 'Error while updating tags!',
|
||||
'update-entity-follow-error': 'Error while following entity!',
|
||||
'update-entity-unfollow-error': 'Error while unfollowing entity!',
|
||||
|
||||
@ -23,14 +23,11 @@ import { Button } from '../../components/buttons/Button/Button';
|
||||
import PageContainer from '../../components/containers/PageContainer';
|
||||
import DropDown from '../../components/dropdown/DropDown';
|
||||
import { ROUTES } from '../../constants/constants';
|
||||
import { Team } from '../../generated/entity/teams/team';
|
||||
import { getNameFromEmail } from '../../utils/AuthProvider.util';
|
||||
import { getImages } from '../../utils/CommonUtils';
|
||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||
import { fetchAllUsers } from '../../utils/UsedDataUtils';
|
||||
type Team = {
|
||||
id: string;
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
const Signup = () => {
|
||||
const [selectedTeams, setSelectedTeams] = useState<Array<string | undefined>>(
|
||||
@ -113,12 +110,14 @@ const Signup = () => {
|
||||
};
|
||||
|
||||
const getTeamsData = (teams: Array<Team>) => {
|
||||
return teams.map((team: Team) => {
|
||||
return {
|
||||
name: team.displayName,
|
||||
value: team.id,
|
||||
};
|
||||
});
|
||||
return teams
|
||||
.filter((team) => team.isJoinable)
|
||||
.map((team: Team) => {
|
||||
return {
|
||||
name: team.displayName as string,
|
||||
value: team.id,
|
||||
};
|
||||
});
|
||||
};
|
||||
const errorMsg = (value: string) => {
|
||||
return (
|
||||
|
||||
@ -305,10 +305,12 @@ describe('Test Teams page', () => {
|
||||
|
||||
it('OnClick of manage tab, manage tab content should render', async () => {
|
||||
const { container } = render(<TeamsPage />);
|
||||
const assets = await findByTestId(container, 'manage');
|
||||
const manage = await findByTestId(container, 'manage');
|
||||
|
||||
expect(manage).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(
|
||||
assets,
|
||||
manage,
|
||||
new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
|
||||
@ -565,10 +565,18 @@ const TeamsPage = () => {
|
||||
return uniqueList;
|
||||
};
|
||||
|
||||
const handleUpdateOwner = (owner: Team['owner']) => {
|
||||
const handleUpdateOwner = (
|
||||
owner: Team['owner'],
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_tier = '',
|
||||
isJoinable?: boolean
|
||||
) => {
|
||||
const updatedTeam = {
|
||||
...currentTeam,
|
||||
owner,
|
||||
owner: !isUndefined(owner) ? owner : currentTeam?.owner,
|
||||
isJoinable: !isUndefined(isJoinable)
|
||||
? isJoinable
|
||||
: currentTeam?.isJoinable,
|
||||
};
|
||||
const jsonPatch = compare(currentTeam as Team, updatedTeam);
|
||||
|
||||
@ -629,7 +637,7 @@ const TeamsPage = () => {
|
||||
title={currentTeam?.displayName ?? currentTeam?.name}>
|
||||
{currentTeam?.displayName ?? currentTeam?.name}
|
||||
</div>
|
||||
<div>
|
||||
<div className="tw-flex">
|
||||
<NonAdminAction
|
||||
html={
|
||||
<Fragment>
|
||||
@ -731,6 +739,7 @@ const TeamsPage = () => {
|
||||
allowTeamOwner={false}
|
||||
currentUser={currentTeam?.owner?.id}
|
||||
hasEditAccess={isOwner()}
|
||||
isJoinable={currentTeam?.isJoinable}
|
||||
onSave={handleUpdateOwner}
|
||||
/>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user