mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 18:36:08 +00:00
Update Users, Admins and tags page with new roles and policy (#7050)
* Update Users, Admins and tags page with new roles and policy * Fix unit tests * Minor change
This commit is contained in:
parent
7cd5579c84
commit
c366d39737
@ -11,55 +11,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Menu, MenuProps } from 'antd';
|
import { Empty, Menu, MenuProps } from 'antd';
|
||||||
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { GLOBAL_SETTING_PERMISSION_RESOURCES } from '../../constants/globalSettings.constants';
|
|
||||||
import {
|
import {
|
||||||
getGlobalSettingMenuItem,
|
getGlobalSettingMenuItem,
|
||||||
getGlobalSettingsMenuWithPermission,
|
getGlobalSettingsMenuWithPermission,
|
||||||
MenuList,
|
MenuList,
|
||||||
} from '../../utils/GlobalSettingsUtils';
|
} from '../../utils/GlobalSettingsUtils';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
|
||||||
import Loader from '../Loader/Loader';
|
|
||||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
import {
|
|
||||||
ResourceEntity,
|
|
||||||
UIPermission,
|
|
||||||
} from '../PermissionProvider/PermissionProvider.interface';
|
|
||||||
|
|
||||||
const GlobalSettingLeftPanel = () => {
|
const GlobalSettingLeftPanel = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
||||||
const [settingResourcePermission, setSettingResourcePermission] =
|
|
||||||
useState<UIPermission>({} as UIPermission);
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
const { getResourcePermission } = usePermissionProvider();
|
|
||||||
|
|
||||||
const fetchResourcesPermission = async (resource: ResourceEntity) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
|
||||||
const response = await getResourcePermission(resource);
|
|
||||||
setSettingResourcePermission((prev) => ({
|
|
||||||
...prev,
|
|
||||||
[resource]: response,
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
showErrorToast(error as AxiosError);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const menuItems: ItemType[] = useMemo(
|
const menuItems: ItemType[] = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getGlobalSettingsMenuWithPermission(settingResourcePermission).reduce(
|
getGlobalSettingsMenuWithPermission(permissions).reduce(
|
||||||
(acc: ItemType[], curr: MenuList) => {
|
(acc: ItemType[], curr: MenuList) => {
|
||||||
const menuItem = getGlobalSettingMenuItem(
|
const menuItem = getGlobalSettingMenuItem(
|
||||||
curr.category,
|
curr.category,
|
||||||
@ -77,7 +50,7 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
},
|
},
|
||||||
[] as ItemType[]
|
[] as ItemType[]
|
||||||
),
|
),
|
||||||
[setSettingResourcePermission]
|
[permissions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onClick: MenuProps['onClick'] = (e) => {
|
const onClick: MenuProps['onClick'] = (e) => {
|
||||||
@ -86,20 +59,7 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
history.push(getSettingPath(category, option));
|
history.push(getSettingPath(category, option));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
return menuItems.length ? (
|
||||||
// TODO: This will make number of API calls, need to think of better solution
|
|
||||||
GLOBAL_SETTING_PERMISSION_RESOURCES.forEach((resource) => {
|
|
||||||
fetchResourcesPermission(resource);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <Loader />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{menuItems.length ? (
|
|
||||||
<Menu
|
<Menu
|
||||||
className="global-setting-left-panel"
|
className="global-setting-left-panel"
|
||||||
items={menuItems}
|
items={menuItems}
|
||||||
@ -107,8 +67,8 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
selectedKeys={[`${settingCategory}.${tab}`]}
|
selectedKeys={[`${settingCategory}.${tab}`]}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : (
|
||||||
</>
|
<Empty className="tw-mt-8" />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,25 +121,12 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
[resource]: operationPermission,
|
[resource]: operationPermission,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
|
||||||
* Store updated resource permission
|
|
||||||
*/
|
|
||||||
setPermissions((prev) => ({
|
|
||||||
...prev,
|
|
||||||
[resource]: operationPermission,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return operationPermission;
|
return operationPermission;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
/**
|
|
||||||
* Only fetch permission if user is logged In
|
|
||||||
*/
|
|
||||||
if (currentUser && currentUser.id) {
|
|
||||||
fetchLoggedInUserPermissions();
|
fetchLoggedInUserPermissions();
|
||||||
}
|
|
||||||
}, [currentUser]);
|
}, [currentUser]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,17 +19,22 @@ import React, { FC, useMemo, useState } from 'react';
|
|||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { updateUser } from '../../axiosAPIs/userAPI';
|
import { updateUser } from '../../axiosAPIs/userAPI';
|
||||||
import { getUserPath, PAGE_SIZE, ROUTES } from '../../constants/constants';
|
import { getUserPath, PAGE_SIZE, ROUTES } from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||||
import { CreateUser } from '../../generated/api/teams/createUser';
|
import { CreateUser } from '../../generated/api/teams/createUser';
|
||||||
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
import { EntityReference, User } from '../../generated/entity/teams/user';
|
import { EntityReference, User } from '../../generated/entity/teams/user';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import { getEntityName, getTeamsText } from '../../utils/CommonUtils';
|
import { getEntityName, getTeamsText } from '../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||||
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
||||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||||
import Searchbar from '../common/searchbar/Searchbar';
|
import Searchbar from '../common/searchbar/Searchbar';
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||||
import './usersList.less';
|
import './usersList.less';
|
||||||
|
|
||||||
interface UserListV1Props {
|
interface UserListV1Props {
|
||||||
@ -57,12 +62,23 @@ const UserListV1: FC<UserListV1Props> = ({
|
|||||||
onPagingChange,
|
onPagingChange,
|
||||||
afterDeleteAction,
|
afterDeleteAction,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [selectedUser, setSelectedUser] = useState<User>();
|
const [selectedUser, setSelectedUser] = useState<User>();
|
||||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||||
const [showReactiveModal, setShowReactiveModal] = useState(false);
|
const [showReactiveModal, setShowReactiveModal] = useState(false);
|
||||||
const showRestore = showDeletedUser && !isDataLoading;
|
const showRestore = showDeletedUser && !isDataLoading;
|
||||||
|
|
||||||
|
const createPermission = useMemo(
|
||||||
|
() => checkPermission(Operation.Create, ResourceEntity.USER, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const deletePermission = useMemo(
|
||||||
|
() => checkPermission(Operation.Delete, ResourceEntity.USER, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
const handleAddNewUser = () => {
|
const handleAddNewUser = () => {
|
||||||
history.push(ROUTES.CREATE_USER);
|
history.push(ROUTES.CREATE_USER);
|
||||||
};
|
};
|
||||||
@ -156,8 +172,11 @@ const UserListV1: FC<UserListV1Props> = ({
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Tooltip placement="bottom" title="Delete">
|
<Tooltip
|
||||||
|
placement="bottom"
|
||||||
|
title={deletePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={!deletePermission}
|
||||||
icon={
|
icon={
|
||||||
<SVGIcons
|
<SVGIcons
|
||||||
alt="Delete"
|
alt="Delete"
|
||||||
@ -199,9 +218,15 @@ const UserListV1: FC<UserListV1Props> = ({
|
|||||||
/>
|
/>
|
||||||
<span className="tw-ml-2">Deleted Users</span>
|
<span className="tw-ml-2">Deleted Users</span>
|
||||||
</span>
|
</span>
|
||||||
<Button type="primary" onClick={handleAddNewUser}>
|
<Tooltip
|
||||||
|
title={createPermission ? 'Add User' : NO_PERMISSION_FOR_ACTION}>
|
||||||
|
<Button
|
||||||
|
disabled={!createPermission}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleAddNewUser}>
|
||||||
Add User
|
Add User
|
||||||
</Button>
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@ type Props = {
|
|||||||
permission?: Operation;
|
permission?: Operation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* TODO: Remove this component once we have new permission structure everywhere
|
||||||
|
*/
|
||||||
const NonAdminAction = ({
|
const NonAdminAction = ({
|
||||||
children,
|
children,
|
||||||
className = '',
|
className = '',
|
||||||
|
@ -190,6 +190,41 @@ const mockCategory = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockReturnValue({
|
||||||
|
getEntityPermission: jest.fn().mockReturnValue({
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
ViewAll: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
}),
|
||||||
|
permissions: {
|
||||||
|
tagCategory: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
ViewAll: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
},
|
||||||
|
tag: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
ViewAll: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
checkPermission: jest.fn().mockReturnValue(true),
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock('../../axiosAPIs/tagAPI', () => ({
|
jest.mock('../../axiosAPIs/tagAPI', () => ({
|
||||||
createTag: jest.fn(),
|
createTag: jest.fn(),
|
||||||
createTagCategory: jest.fn(),
|
createTagCategory: jest.fn(),
|
||||||
|
@ -12,14 +12,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Card } from 'antd';
|
import { Button, Card, Tooltip } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { isEmpty, isUndefined, toLower } from 'lodash';
|
import { isEmpty, isUndefined, toLower } from 'lodash';
|
||||||
import { FormErrorData, LoadingState } from 'Models';
|
import { FormErrorData, LoadingState } from 'Models';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
|
||||||
import {
|
import {
|
||||||
createTag,
|
createTag,
|
||||||
createTagCategory,
|
createTagCategory,
|
||||||
@ -29,11 +27,9 @@ import {
|
|||||||
updateTag,
|
updateTag,
|
||||||
updateTagCategory,
|
updateTagCategory,
|
||||||
} from '../../axiosAPIs/tagAPI';
|
} from '../../axiosAPIs/tagAPI';
|
||||||
import { Button } from '../../components/buttons/Button/Button';
|
|
||||||
import Description from '../../components/common/description/Description';
|
import Description from '../../components/common/description/Description';
|
||||||
import Ellipses from '../../components/common/Ellipses/Ellipses';
|
import Ellipses from '../../components/common/Ellipses/Ellipses';
|
||||||
import ErrorPlaceHolder from '../../components/common/error-with-placeholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../../components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
|
|
||||||
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||||
import PageLayout, {
|
import PageLayout, {
|
||||||
@ -43,7 +39,12 @@ import Loader from '../../components/Loader/Loader';
|
|||||||
import ConfirmationModal from '../../components/Modals/ConfirmationModal/ConfirmationModal';
|
import ConfirmationModal from '../../components/Modals/ConfirmationModal/ConfirmationModal';
|
||||||
import FormModal from '../../components/Modals/FormModal';
|
import FormModal from '../../components/Modals/FormModal';
|
||||||
import { ModalWithMarkdownEditor } from '../../components/Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
import { ModalWithMarkdownEditor } from '../../components/Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
||||||
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import {
|
||||||
|
OperationPermission,
|
||||||
|
ResourceEntity,
|
||||||
|
} from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||||
import { delimiterRegex } from '../../constants/regex.constants';
|
import { delimiterRegex } from '../../constants/regex.constants';
|
||||||
import {
|
import {
|
||||||
CreateTagCategory,
|
CreateTagCategory,
|
||||||
@ -52,7 +53,6 @@ import {
|
|||||||
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
||||||
import { TagCategory, TagClass } from '../../generated/entity/tags/tagCategory';
|
import { TagCategory, TagClass } from '../../generated/entity/tags/tagCategory';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
import { EntityReference } from '../../generated/type/entityReference';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import {
|
import {
|
||||||
getActiveCatClass,
|
getActiveCatClass,
|
||||||
@ -61,6 +61,7 @@ import {
|
|||||||
isEven,
|
isEven,
|
||||||
isUrlFriendlyName,
|
isUrlFriendlyName,
|
||||||
} from '../../utils/CommonUtils';
|
} from '../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
getExplorePathWithInitFilters,
|
getExplorePathWithInitFilters,
|
||||||
getTagPath,
|
getTagPath,
|
||||||
@ -85,10 +86,9 @@ type DeleteTagsType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const TagsPage = () => {
|
const TagsPage = () => {
|
||||||
|
const { getEntityPermission, permissions } = usePermissionProvider();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { tagCategoryName } = useParams<Record<string, string>>();
|
const { tagCategoryName } = useParams<Record<string, string>>();
|
||||||
const { isAdminUser } = useAuth();
|
|
||||||
const { isAuthDisabled } = useAuthContext();
|
|
||||||
const [categories, setCategoreis] = useState<Array<TagCategory>>([]);
|
const [categories, setCategoreis] = useState<Array<TagCategory>>([]);
|
||||||
const [currentCategory, setCurrentCategory] = useState<TagCategory>();
|
const [currentCategory, setCurrentCategory] = useState<TagCategory>();
|
||||||
const [isEditCategory, setIsEditCategory] = useState<boolean>(false);
|
const [isEditCategory, setIsEditCategory] = useState<boolean>(false);
|
||||||
@ -104,6 +104,35 @@ const TagsPage = () => {
|
|||||||
data: undefined,
|
data: undefined,
|
||||||
state: false,
|
state: false,
|
||||||
});
|
});
|
||||||
|
const [categoryPermissions, setCategoryPermissions] =
|
||||||
|
useState<OperationPermission>({} as OperationPermission);
|
||||||
|
|
||||||
|
const createCategoryPermission = useMemo(
|
||||||
|
() =>
|
||||||
|
checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.TAG_CATEGORY,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const createTagPermission = useMemo(
|
||||||
|
() => checkPermission(Operation.Create, ResourceEntity.TAG, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchCurrentCategoryPermission = async () => {
|
||||||
|
try {
|
||||||
|
const response = await getEntityPermission(
|
||||||
|
ResourceEntity.TAG_CATEGORY,
|
||||||
|
currentCategory?.id as string
|
||||||
|
);
|
||||||
|
setCategoryPermissions(response);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchCategories = () => {
|
const fetchCategories = () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@ -405,6 +434,7 @@ const TagsPage = () => {
|
|||||||
setCurrentCategory(categories[0]);
|
setCurrentCategory(categories[0]);
|
||||||
if (currentCategory) {
|
if (currentCategory) {
|
||||||
setCurrentCategory(currentCategory);
|
setCurrentCategory(currentCategory);
|
||||||
|
fetchCurrentCategoryPermission();
|
||||||
}
|
}
|
||||||
}, [categories, currentCategory]);
|
}, [categories, currentCategory]);
|
||||||
|
|
||||||
@ -426,24 +456,25 @@ const TagsPage = () => {
|
|||||||
style={{ fontSize: '14px' }}>
|
style={{ fontSize: '14px' }}>
|
||||||
Tag Categories
|
Tag Categories
|
||||||
</span>
|
</span>
|
||||||
<NonAdminAction
|
<Tooltip
|
||||||
position="bottom"
|
title={
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
createCategoryPermission
|
||||||
|
? 'Add Category'
|
||||||
|
: NO_PERMISSION_FOR_ACTION
|
||||||
|
}>
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-px-2 ', {
|
className="tw-px-2 "
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
})}
|
|
||||||
data-testid="add-category"
|
data-testid="add-category"
|
||||||
|
disabled={!createCategoryPermission}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
type="primary"
|
||||||
variant="contained"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsAddingCategory((prevState) => !prevState);
|
setIsAddingCategory((prevState) => !prevState);
|
||||||
setErrorDataCategory(undefined);
|
setErrorDataCategory(undefined);
|
||||||
}}>
|
}}>
|
||||||
<FontAwesomeIcon icon="plus" />
|
<FontAwesomeIcon icon="plus" />
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
}>
|
}>
|
||||||
<>
|
<>
|
||||||
@ -505,44 +536,39 @@ const TagsPage = () => {
|
|||||||
{currentCategory.displayName ?? currentCategory.name}
|
{currentCategory.displayName ?? currentCategory.name}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<NonAdminAction
|
<Tooltip
|
||||||
position="bottom"
|
title={
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
createTagPermission || categoryPermissions.EditAll
|
||||||
|
? 'Add Tag'
|
||||||
|
: NO_PERMISSION_FOR_ACTION
|
||||||
|
}>
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-h-8 tw-rounded tw-mb-3', {
|
className="tw-h-8 tw-rounded tw-mb-3"
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
})}
|
|
||||||
data-testid="add-new-tag-button"
|
data-testid="add-new-tag-button"
|
||||||
|
disabled={
|
||||||
|
!createTagPermission && !categoryPermissions.EditAll
|
||||||
|
}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
type="primary"
|
||||||
variant="contained"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsAddingTag((prevState) => !prevState);
|
setIsAddingTag((prevState) => !prevState);
|
||||||
setErrorDataTag(undefined);
|
setErrorDataTag(undefined);
|
||||||
}}>
|
}}>
|
||||||
Add new tag
|
Add new tag
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
</Tooltip>
|
||||||
<NonAdminAction
|
|
||||||
position="bottom"
|
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
|
||||||
<Button
|
<Button
|
||||||
className={classNames(
|
className="tw-h-8 tw-rounded tw-mb-3 tw-ml-2"
|
||||||
'tw-h-8 tw-rounded tw-mb-3 tw-ml-2',
|
|
||||||
{
|
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
data-testid="delete-tag-category-button"
|
data-testid="delete-tag-category-button"
|
||||||
|
disabled={!categoryPermissions.Delete}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
type="primary"
|
||||||
variant="outlined"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteTagHandler();
|
deleteTagHandler();
|
||||||
}}>
|
}}>
|
||||||
Delete category
|
Delete category
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -554,6 +580,7 @@ const TagsPage = () => {
|
|||||||
entityName={
|
entityName={
|
||||||
currentCategory?.displayName ?? currentCategory?.name
|
currentCategory?.displayName ?? currentCategory?.name
|
||||||
}
|
}
|
||||||
|
hasEditAccess={categoryPermissions.EditDescription}
|
||||||
isEdit={isEditCategory}
|
isEdit={isEditCategory}
|
||||||
onCancel={() => setIsEditCategory(false)}
|
onCancel={() => setIsEditCategory(false)}
|
||||||
onDescriptionEdit={() => setIsEditCategory(true)}
|
onDescriptionEdit={() => setIsEditCategory(true)}
|
||||||
@ -605,10 +632,8 @@ const TagsPage = () => {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<NonAdminAction
|
|
||||||
permission={Operation.EditDescription}
|
{categoryPermissions.EditDescription && (
|
||||||
position="left"
|
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
|
||||||
<button
|
<button
|
||||||
className="tw-self-start tw-w-8 tw-h-auto tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none"
|
className="tw-self-start tw-w-8 tw-h-auto tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -623,7 +648,7 @@ const TagsPage = () => {
|
|||||||
width="16px"
|
width="16px"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</NonAdminAction>
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="tw-mt-1" data-testid="usage">
|
<div className="tw-mt-1" data-testid="usage">
|
||||||
<span className="tw-text-grey-muted tw-mr-1">
|
<span className="tw-text-grey-muted tw-mr-1">
|
||||||
@ -649,12 +674,10 @@ const TagsPage = () => {
|
|||||||
</td>
|
</td>
|
||||||
<td className="tableBody-cell">
|
<td className="tableBody-cell">
|
||||||
<div className="tw-text-center">
|
<div className="tw-text-center">
|
||||||
<NonAdminAction
|
|
||||||
position="bottom"
|
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
|
||||||
<button
|
<button
|
||||||
className="link-text"
|
className="link-text"
|
||||||
data-testid="delete-tag"
|
data-testid="delete-tag"
|
||||||
|
disabled={!categoryPermissions.EditAll}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setDeleteTags({
|
setDeleteTags({
|
||||||
data: {
|
data: {
|
||||||
@ -682,7 +705,6 @@ const TagsPage = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</NonAdminAction>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user