mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-28 16:08:23 +00:00
parent
db0e34c709
commit
fa0d386bd6
@ -123,17 +123,24 @@ export const getInitialEntity: Function = (): Promise<AxiosResponse> => {
|
||||
export const deleteEntity: Function = (
|
||||
entityType: string,
|
||||
entityId: string,
|
||||
isRecursive: boolean
|
||||
isRecursive: boolean,
|
||||
isSoftDelete = false
|
||||
): Promise<AxiosResponse> => {
|
||||
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);
|
||||
};
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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<DatasetDetailsProps> = ({
|
||||
key: 'Owner',
|
||||
value:
|
||||
owner?.type === 'team'
|
||||
? getTeamDetailsPath(owner?.name || '')
|
||||
? getTeamAndUserDetailsPath(owner?.name || '')
|
||||
: getEntityName(owner),
|
||||
placeholderText: getEntityPlaceHolder(
|
||||
getEntityName(owner),
|
||||
|
||||
@ -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 (
|
||||
<div className="tw-flex tw-justify-between tw-px-4 tw-py-2">
|
||||
<div data-testid="danger-zone-text">
|
||||
<h4 className="tw-text-base" data-testid="danger-zone-text-title">
|
||||
{header}
|
||||
</h4>
|
||||
<p data-testid="danger-zone-text-para">{description}</p>
|
||||
</div>
|
||||
<NonAdminAction
|
||||
className="tw-self-center"
|
||||
html={<p>{TITLE_FOR_NON_ADMIN_ACTION}</p>}
|
||||
isOwner={isOwner}
|
||||
position="left">
|
||||
<Button
|
||||
className="tw-px-2 tw-py-1 tw-rounded tw-h-auto tw-self-center tw-shadow"
|
||||
data-testid="delete-button"
|
||||
disabled={!hasPermission}
|
||||
size="custom"
|
||||
theme="primary"
|
||||
type="button"
|
||||
variant="outlined"
|
||||
onClick={onClick}>
|
||||
{buttonText}
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteWidgetBody;
|
||||
@ -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<ManageProps> = ({
|
||||
@ -54,8 +55,10 @@ const ManageTab: FunctionComponent<ManageProps> = ({
|
||||
entityName,
|
||||
entityType,
|
||||
entityId,
|
||||
allowSoftDelete,
|
||||
isRecursiveDelete,
|
||||
deletEntityMessage,
|
||||
handleIsJoinable,
|
||||
}: ManageProps) => {
|
||||
const history = useHistory();
|
||||
const { userPermissions, isAdminUser } = useAuth();
|
||||
@ -161,8 +164,8 @@ const ManageTab: FunctionComponent<ManageProps> = ({
|
||||
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<ManageProps> = ({
|
||||
|
||||
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<ManageProps> = ({
|
||||
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<ManageProps> = ({
|
||||
return allowDelete && entityId && entityName && entityType ? (
|
||||
<div className="tw-mt-1" data-testid="danger-zone">
|
||||
<hr className="tw-border-main tw-mb-4" />
|
||||
<div className="tw-border tw-border-error tw-px-4 tw-py-2 tw-flex tw-justify-between tw-rounded tw-mt-3 tw-shadow">
|
||||
<div data-testid="danger-zone-text">
|
||||
<h4 className="tw-text-base" data-testid="danger-zone-text-title">
|
||||
Delete {entityType} {entityName}
|
||||
</h4>
|
||||
<p data-testid="danger-zone-text-para">{prepareDeleteMessage()}</p>
|
||||
</div>
|
||||
<NonAdminAction
|
||||
className="tw-self-center"
|
||||
html={
|
||||
<Fragment>
|
||||
<p>{TITLE_FOR_NON_ADMIN_ACTION}</p>
|
||||
</Fragment>
|
||||
}
|
||||
<div className="tw-border tw-border-error tw-rounded tw-mt-3 tw-shadow">
|
||||
{allowSoftDelete && (
|
||||
<div className="tw-border-b tw-border-error">
|
||||
<DeleteWidgetBody
|
||||
buttonText={`Soft delete this ${entityType}`}
|
||||
description={prepareDeleteMessage()}
|
||||
hasPermission={isAdminUser || isAuthDisabled}
|
||||
header={`Soft delete ${entityType} ${entityName}`}
|
||||
isOwner={isAdminUser}
|
||||
onClick={() => handleOnEntityDelete(true)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DeleteWidgetBody
|
||||
buttonText={`Delete this ${entityType}`}
|
||||
description={prepareDeleteMessage()}
|
||||
hasPermission={isAdminUser || isAuthDisabled}
|
||||
header={`Delete ${entityType} ${entityName}`}
|
||||
isOwner={isAdminUser}
|
||||
position="left">
|
||||
<Button
|
||||
className="tw-px-2 tw-py-1 tw-rounded tw-h-auto tw-self-center tw-shadow"
|
||||
data-testid="delete-button"
|
||||
disabled={!isAdminUser && !isAuthDisabled}
|
||||
size="custom"
|
||||
theme="primary"
|
||||
type="button"
|
||||
variant="outlined"
|
||||
onClick={handleOnEntityDelete}>
|
||||
Delete this {entityType}
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
onClick={handleOnEntityDelete}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
@ -315,18 +318,18 @@ const ManageTab: FunctionComponent<ManageProps> = ({
|
||||
userPermissions[Operation.UpdateTeam] ||
|
||||
!hasEditAccess;
|
||||
|
||||
const joinableSwitch = isActionAllowed ? (
|
||||
<div className="tw-flex">
|
||||
<label htmlFor="join-team">Allow users to join this team</label>
|
||||
<div
|
||||
className={classNames('toggle-switch ', { open: teamJoinable })}
|
||||
data-testid="team-isJoinable-switch"
|
||||
id="join-team"
|
||||
onClick={() => setTeamJoinable((prev) => !prev)}>
|
||||
<div className="switch" />
|
||||
const joinableSwitch =
|
||||
isActionAllowed && !isUndefined(teamJoinable) ? (
|
||||
<div className="tw-flex">
|
||||
<label htmlFor="join-team">Open to join</label>
|
||||
<ToggleSwitchV1
|
||||
checked={teamJoinable}
|
||||
handleCheck={() => {
|
||||
handleIsJoinable?.(!teamJoinable);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
) : null;
|
||||
|
||||
return !isUndefined(isJoinable) ? (
|
||||
<div className="tw-mt-3 tw-mb-1">{joinableSwitch}</div>
|
||||
|
||||
@ -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<void>;
|
||||
handleIsJoinable?: (bool: boolean) => void;
|
||||
hasEditAccess: boolean;
|
||||
allowTeamOwner?: boolean;
|
||||
entityId?: string;
|
||||
|
||||
@ -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(() => <p>ToggleSwitchV1.Component</p>);
|
||||
});
|
||||
|
||||
const mockTierData = {
|
||||
children: [
|
||||
{
|
||||
@ -96,23 +100,11 @@ describe('Test Manage tab Component', () => {
|
||||
<ManageTab hasEditAccess isJoinable onSave={mockFunction} />
|
||||
);
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ interface Prop extends HTMLAttributes<HTMLDivElement> {
|
||||
entityType: string;
|
||||
loadingState: string;
|
||||
bodyText?: string;
|
||||
softDelete?: boolean;
|
||||
}
|
||||
|
||||
const EntityDeleteModal: FC<Prop> = ({
|
||||
@ -39,6 +40,7 @@ const EntityDeleteModal: FC<Prop> = ({
|
||||
onCancel,
|
||||
onConfirm,
|
||||
bodyText,
|
||||
softDelete = false,
|
||||
}: Prop) => {
|
||||
const [name, setName] = useState('');
|
||||
|
||||
@ -58,7 +60,15 @@ const EntityDeleteModal: FC<Prop> = ({
|
||||
<div className="tw-modal-container tw-w-120">
|
||||
<div className={classNames('tw-modal-header')}>
|
||||
<p className="tw-modal-title" data-testid="modal-header">
|
||||
Delete <strong>{entityName}</strong>
|
||||
{softDelete ? (
|
||||
<span>
|
||||
Soft delete <strong>{entityName}</strong>
|
||||
</span>
|
||||
) : (
|
||||
<span>
|
||||
Delete <strong>{entityName}</strong>
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div className={classNames('tw-modal-body')} data-testid="body-text">
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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<User>();
|
||||
@ -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<HTMLElement, 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<UserTeams>)].find(
|
||||
(u) => u.id === id
|
||||
);
|
||||
setDeletingUser({ user, state: true });
|
||||
setDeletingUser({ user, state: true, leave });
|
||||
};
|
||||
|
||||
const getJoinableWidget = () => {
|
||||
return isActionAllowed(userPermissions[Operation.UpdateTeam]) ? (
|
||||
<div className="tw-flex">
|
||||
<label htmlFor="join-team">Open to join</label>
|
||||
<ToggleSwitchV1
|
||||
checked={(currentTeam?.isJoinable as boolean) || false}
|
||||
handleCheck={handleOpenToJoinToggle}
|
||||
/>
|
||||
</div>
|
||||
) : 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 = ({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{teamUserPagin.total > PAGE_SIZE_12 && (
|
||||
{teamUserPagin.total > PAGE_SIZE_MEDIUM && (
|
||||
<NextPrevious
|
||||
currentPage={currentTeamUserPage}
|
||||
isNumberBased={Boolean(teamUsersSearchText)}
|
||||
pageSize={PAGE_SIZE_12}
|
||||
pageSize={PAGE_SIZE_MEDIUM}
|
||||
paging={teamUserPagin}
|
||||
pagingHandler={teamUserPaginHandler}
|
||||
totalCount={teamUserPagin.total}
|
||||
@ -504,7 +501,7 @@ const TeamDetails = ({
|
||||
data-testid="header">
|
||||
{getTeamHeading()}
|
||||
<div className="tw-flex">
|
||||
{isActionAllowed() ? (
|
||||
{isActionAllowed() && (
|
||||
<Fragment>
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
@ -514,81 +511,45 @@ const TeamDetails = ({
|
||||
data-testid="add-teams"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
handleAddTeam(true);
|
||||
}}>
|
||||
Create New Team
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
<NonAdminAction
|
||||
html={
|
||||
<Fragment>
|
||||
You do not have permission to delete the team.
|
||||
</Fragment>
|
||||
}
|
||||
isOwner={isOwner()}
|
||||
position="bottom">
|
||||
<Button
|
||||
className="tw-h-8 tw-rounded tw-ml-2"
|
||||
data-testid="delete-team-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
handleDeleteTeam({ team: currentTeam, state: true })
|
||||
}>
|
||||
Delete Team
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
</Fragment>
|
||||
) : !isAlreadyJoinedTeam(currentTeam.id) &&
|
||||
)}
|
||||
{!isAlreadyJoinedTeam(currentTeam.id) ? (
|
||||
currentTeam.isJoinable ? (
|
||||
<Button
|
||||
className="tw-h-8 tw-px-2 tw-mb-4 tw-ml-2"
|
||||
data-testid="join-teams"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={joinTeam}>
|
||||
Join Team
|
||||
</Button>
|
||||
) : null
|
||||
) : (
|
||||
<Button
|
||||
className="tw-h-8 tw-px-2 tw-mb-4"
|
||||
data-testid="join-teams"
|
||||
className="tw-h-8 tw-rounded tw-ml-2"
|
||||
data-testid="delete-team-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={joinTeam}>
|
||||
Join Team
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
currentUser && deleteUserHandler(currentUser.id, true)
|
||||
}>
|
||||
Leave Team
|
||||
</Button>
|
||||
) : null}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-flex tw-items-center tw-gap-1 tw-mb-2">
|
||||
<span>{getInfoElements(extraInfo)}</span>
|
||||
{isActionAllowed(userPermissions[Operation.UpdateOwner]) && (
|
||||
<span className="tw-relative">
|
||||
<Button
|
||||
className="tw-relative tw-pb-1"
|
||||
data-testid="owner-dropdown"
|
||||
size="custom"
|
||||
theme="primary"
|
||||
variant="link"
|
||||
onClick={() => setShowOwnerDropdown((visible) => !visible)}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
className="tw-ml-1"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
{showOwnerDropdown && (
|
||||
<DropDownList
|
||||
dropDownList={getOwnerList()}
|
||||
groupType="tab"
|
||||
listGroups={['Users']}
|
||||
value={currentTeam?.owner?.id}
|
||||
onSelect={handleOwnerSelection}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div>{getJoinableWidget()}</div>
|
||||
<div className="tw-mb-3 tw--ml-5" data-testid="description-container">
|
||||
<Description
|
||||
blurWithBodyBG
|
||||
@ -617,6 +578,25 @@ const TeamDetails = ({
|
||||
{currentTab === 2 && getDatasetCards()}
|
||||
|
||||
{currentTab === 3 && getDefaultRoles()}
|
||||
|
||||
{currentTab === 4 && (
|
||||
<div>
|
||||
<ManageTab
|
||||
allowDelete
|
||||
allowSoftDelete
|
||||
hasEditAccess
|
||||
hideTier
|
||||
allowTeamOwner={false}
|
||||
currentUser={currentTeam.owner?.id}
|
||||
entityId={currentTeam.id}
|
||||
entityName={currentTeam.displayName || currentTeam.name}
|
||||
entityType="team"
|
||||
handleIsJoinable={handleOpenToJoinToggle}
|
||||
isJoinable={currentTeam.isJoinable}
|
||||
onSave={handleManageSave}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
@ -657,30 +637,13 @@ const TeamDetails = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{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={() => handleDeleteTeam({ team: undefined, state: false })}
|
||||
onConfirm={() => {
|
||||
deleteTeamById(deletingTeam.team?.id as string);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{deletingUser.state && (
|
||||
<ConfirmationModal
|
||||
bodyText={`Are you sure you want to remove ${
|
||||
deletingUser.user?.displayName ?? deletingUser.user?.name
|
||||
}?`}
|
||||
bodyText={removeUserBodyText(deletingUser.leave)}
|
||||
cancelText="Cancel"
|
||||
confirmText="Confirm"
|
||||
header="Removing user"
|
||||
onCancel={() => setDeletingUser({ user: undefined, state: false })}
|
||||
header={deletingUser.leave ? 'Leave team' : 'Removing user'}
|
||||
onCancel={() => setDeletingUser(DELETE_USER_INITIAL_STATE)}
|
||||
onConfirm={handleRemoveUser}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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<TopicDetailsProps> = ({
|
||||
key: 'Owner',
|
||||
value:
|
||||
owner?.type === 'team'
|
||||
? getTeamDetailsPath(owner?.name || '')
|
||||
? getTeamAndUserDetailsPath(owner?.name || '')
|
||||
: getEntityName(owner),
|
||||
placeholderText: getEntityPlaceHolder(
|
||||
getEntityName(owner),
|
||||
|
||||
@ -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 => {
|
||||
<span className="tw-font-medium tw-text-xs">Teams</span>
|
||||
{teams?.map((t, i) => (
|
||||
<p key={i}>
|
||||
<Link to={getTeamDetailsPath(t.name as string)}>
|
||||
<Link to={getTeamAndUserDetailsPath(t.name as string)}>
|
||||
{t.displayName}
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
@ -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 => {
|
||||
<span className="tw-font-medium tw-text-xs">Teams</span>
|
||||
{teams.map((t, i) => (
|
||||
<p key={i}>
|
||||
<Link to={getTeamDetailsPath(t.name as string)}>
|
||||
<Link to={getTeamAndUserDetailsPath(t.name as string)}>
|
||||
{t.displayName}
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -14,4 +14,5 @@
|
||||
export const ENTITY_DELETE_STATE = {
|
||||
loading: 'initial',
|
||||
state: false,
|
||||
softDelete: false,
|
||||
};
|
||||
|
||||
@ -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<void>;
|
||||
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<void>;
|
||||
createNewTeam: (data: Team) => void;
|
||||
teamUserPaginHandler: (
|
||||
cursorValue: string | number,
|
||||
|
||||
@ -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 ||
|
||||
''
|
||||
|
||||
@ -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<boolean>(false);
|
||||
const [isAddingUsers, setIsAddingUsers] = useState<boolean>(false);
|
||||
const [errorNewTeamData, setErrorNewTeamData] = useState<FormErrorData>();
|
||||
const [deletingTeam, setDeletingTeam] = useState<TeamDeleteType>({
|
||||
team: undefined,
|
||||
state: false,
|
||||
});
|
||||
const [activeUserTab, setactiveUserTab] = useState<UserType>();
|
||||
const [userList, setUserList] = useState<Array<User>>([]);
|
||||
const [users, setUsers] = useState<Array<User>>([]);
|
||||
@ -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<void>((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<UserTeams>)];
|
||||
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}
|
||||
|
||||
@ -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 || '',
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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 = () => {
|
||||
|
||||
@ -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 = () => {
|
||||
<Route exact component={ExplorePage} path={ROUTES.EXPLORE} />
|
||||
<Route component={ExplorePage} path={ROUTES.EXPLORE_WITH_SEARCH} />
|
||||
<Route component={ExplorePage} path={ROUTES.EXPLORE_WITH_TAB} />
|
||||
<Route exact component={TeamsPage} path={ROUTES.TEAMS} />
|
||||
<Route exact component={TeamsPage} path={ROUTES.TEAM_DETAILS} />
|
||||
<Route
|
||||
exact
|
||||
component={TeamsAndUsersPage}
|
||||
@ -155,11 +151,6 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
||||
component={CreateUserPage}
|
||||
path={ROUTES.CREATE_USER}
|
||||
/>
|
||||
<AdminProtectedRoute
|
||||
exact
|
||||
component={UserListPage}
|
||||
path={ROUTES.USER_LIST}
|
||||
/>
|
||||
<Redirect to={ROUTES.NOT_FOUND} />
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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' ? (
|
||||
<Link
|
||||
className="tw-pl-1"
|
||||
to={getTeamDetailsPath(newValue?.name || '')}>
|
||||
to={getTeamAndUserDetailsPath(newValue?.name || '')}>
|
||||
<span title={ownerName}>{ownerName}</span>
|
||||
</Link>
|
||||
) : (
|
||||
@ -397,7 +400,7 @@ export const feedSummaryFromatter = (
|
||||
{value?.type === 'team' ? (
|
||||
<Link
|
||||
className="tw-pl-1"
|
||||
to={getTeamDetailsPath(value?.name || '')}>
|
||||
to={getTeamAndUserDetailsPath(value?.name || '')}>
|
||||
<span title={ownerName}>{ownerName}</span>
|
||||
</Link>
|
||||
) : (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user