From 503873a0a45f2f6c0f04ddfb6e1d704a2cc9616e Mon Sep 17 00:00:00 2001
From: Sachin Chaurasiya
Date: Wed, 31 Aug 2022 01:46:33 +0530
Subject: [PATCH] Update Glossary with new roles and policy (#7067)
* Update Glossary with new roles and policy
* Fix unit tests
* Fix tests
* Fix tests
---
.../src/components/Glossary/Glossary.test.tsx | 56 ++++-
.../Glossary/GlossaryV1.component.tsx | 213 +++++++++++++-----
.../GlossaryDetails.component.tsx | 202 ++++++++---------
.../GlossaryDetails/GlossaryDetails.test.tsx | 11 +-
.../GlossaryTerms/GlossaryTerms.test.tsx | 65 ++++--
.../GlossaryTermsV1.component.tsx | 184 ++++++---------
.../GlossaryTerms/SummaryDetail.tsx | 57 +++++
.../common/description/DescriptionV1.tsx | 17 +-
.../GlossaryPage/GlossaryPageV1.component.tsx | 5 -
.../ui/src/router/AuthenticatedAppRouter.tsx | 63 +++++-
10 files changed, 535 insertions(+), 338 deletions(-)
create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/SummaryDetail.tsx
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx
index 563352c5f97..a602e90e3b2 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/Glossary.test.tsx
@@ -22,6 +22,44 @@ import React from 'react';
import { mockedAssetData, mockedGlossaries } from '../../mocks/Glossary.mock';
import GlossaryV1 from './GlossaryV1.component';
+jest.mock('../PermissionProvider/PermissionProvider', () => ({
+ usePermissionProvider: jest.fn().mockReturnValue({
+ getEntityPermission: jest.fn().mockReturnValue({
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ }),
+ permissions: {
+ glossaryTerm: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ },
+ glossary: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ },
+ },
+ }),
+}));
+
+jest.mock('../../utils/PermissionsUtils', () => ({
+ checkPermission: jest.fn().mockReturnValue(true),
+}));
+
jest.mock('react-router-dom', () => ({
useHistory: jest.fn(),
useParams: jest.fn().mockReturnValue({
@@ -29,18 +67,6 @@ jest.mock('react-router-dom', () => ({
}),
}));
-jest.mock('../../authentication/auth-provider/AuthProvider', () => {
- return {
- useAuthContext: jest.fn(() => ({
- isAuthDisabled: false,
- isAuthenticated: true,
- isProtectedRoute: jest.fn().mockReturnValue(true),
- isTourRoute: jest.fn().mockReturnValue(false),
- onLogoutHandler: jest.fn(),
- })),
- };
-});
-
jest.mock('../../components/GlossaryDetails/GlossaryDetails.component', () => {
return jest.fn().mockReturnValue(<>Glossary-Details component>);
});
@@ -77,6 +103,12 @@ jest.mock('antd', () => ({
})}
)),
+ Button: jest
+ .fn()
+ .mockImplementation(({ children }) => ),
+ Tooltip: jest
+ .fn()
+ .mockImplementation(({ children }) => {children}),
}));
jest.mock('../common/title-breadcrumb/title-breadcrumb.component', () =>
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx
index 570e39261a5..d4e592388be 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx
@@ -12,28 +12,38 @@
*/
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Col, Dropdown, Input, Menu, Row, Space, Typography } from 'antd';
-import classNames from 'classnames';
+import {
+ Button as ButtonAntd,
+ Col,
+ Dropdown,
+ Input,
+ Menu,
+ Row,
+ Space,
+ Tooltip,
+ Typography,
+} from 'antd';
+import { AxiosError } from 'axios';
import { cloneDeep, isEmpty } from 'lodash';
import { GlossaryTermAssets, LoadingState } from 'Models';
import RcTree from 'rc-tree';
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
-import React, { Fragment, useEffect, useRef, useState } from 'react';
-import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
+import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
-import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
+import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import { Glossary } from '../../generated/entity/data/glossary';
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
-import { useAuth } from '../../hooks/authHooks';
+import { Operation } from '../../generated/entity/policies/policy';
import { useAfterMount } from '../../hooks/useAfterMount';
import { ModifiedGlossaryData } from '../../pages/GlossaryPage/GlossaryPageV1.component';
import { getEntityDeleteMessage, getEntityName } from '../../utils/CommonUtils';
import { generateTreeData } from '../../utils/GlossaryUtils';
+import { checkPermission } from '../../utils/PermissionsUtils';
import { getGlossaryPath } from '../../utils/RouterUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
+import { showErrorToast } from '../../utils/ToastUtils';
import { Button } from '../buttons/Button/Button';
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
-import NonAdminAction from '../common/non-admin-action/NonAdminAction';
import Searchbar from '../common/searchbar/Searchbar';
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
@@ -43,6 +53,11 @@ import GlossaryDetails from '../GlossaryDetails/GlossaryDetails.component';
import GlossaryTermsV1 from '../GlossaryTerms/GlossaryTermsV1.component';
import Loader from '../Loader/Loader';
import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal';
+import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
+import {
+ OperationPermission,
+ ResourceEntity,
+} from '../PermissionProvider/PermissionProvider.interface';
import './GlossaryV1.style.less';
const { Title } = Typography;
@@ -50,7 +65,6 @@ type Props = {
assetData: GlossaryTermAssets;
deleteStatus: LoadingState;
isSearchResultEmpty: boolean;
- isHasAccess: boolean;
glossaryList: ModifiedGlossaryData[];
selectedKey: string;
expandedKey: string[];
@@ -80,7 +94,6 @@ const GlossaryV1 = ({
assetData,
deleteStatus = 'initial',
isSearchResultEmpty,
- isHasAccess,
glossaryList,
selectedKey,
expandedKey,
@@ -104,8 +117,7 @@ const GlossaryV1 = ({
onRelatedTermClick,
currentPage,
}: Props) => {
- const { isAdminUser } = useAuth();
- const { isAuthDisabled } = useAuthContext();
+ const { getEntityPermission, permissions } = usePermissionProvider();
const treeRef = useRef>(null);
const [treeData, setTreeData] = useState([]);
const [breadcrumb, setBreadcrumb] = useState<
@@ -124,6 +136,59 @@ const GlossaryV1 = ({
);
const [isNameEditing, setIsNameEditing] = useState(false);
const [displayName, setDisplayName] = useState();
+
+ const [glossaryPermission, setGlossaryPermission] =
+ useState({} as OperationPermission);
+
+ const [glossaryTermPermission, setGlossaryTermPermission] =
+ useState({} as OperationPermission);
+
+ const fetchGlossaryPermission = async () => {
+ try {
+ const response = await getEntityPermission(
+ ResourceEntity.GLOSSARY,
+ selectedData?.id as string
+ );
+ setGlossaryPermission(response);
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ }
+ };
+
+ const fetchGlossaryTermPermission = async () => {
+ try {
+ const response = await getEntityPermission(
+ ResourceEntity.GLOSSARY_TERM,
+ selectedData?.id as string
+ );
+ setGlossaryTermPermission(response);
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ }
+ };
+
+ const createGlossaryPermission = useMemo(
+ () =>
+ checkPermission(Operation.Create, ResourceEntity.GLOSSARY, permissions),
+ [permissions]
+ );
+
+ const createGlossaryTermPermission = useMemo(
+ () =>
+ checkPermission(
+ Operation.Create,
+ ResourceEntity.GLOSSARY_TERM,
+ permissions
+ ),
+ [permissions]
+ );
+
+ const editDisplayNamePermission = useMemo(() => {
+ return isGlossaryActive
+ ? glossaryPermission.EditDisplayName
+ : glossaryTermPermission.EditDisplayName;
+ }, [glossaryPermission, glossaryTermPermission]);
+
/**
* To create breadcrumb from the fqn
* @param fqn fqn of glossary or glossary term
@@ -269,16 +334,20 @@ const GlossaryV1 = ({
typingInterval={500}
onSearch={handleSearchText}
/>
-
+
-
+
{isSearchResultEmpty ? (
@@ -311,6 +380,10 @@ const GlossaryV1 = ({
useEffect(() => {
setDisplayName(selectedData?.displayName);
+ if (selectedData) {
+ fetchGlossaryPermission();
+ fetchGlossaryTermPermission();
+ }
}, [selectedData]);
return glossaryList.length ? (
@@ -327,32 +400,45 @@ const GlossaryV1 = ({
/>
-
-
-
-
-
+
+
+
+
+
-
-
+
+
{isChildLoading ? (
@@ -411,14 +497,24 @@ const GlossaryV1 = ({
) : (
{getEntityName(selectedData)}
-
+
+ setIsNameEditing(true)}>
+
+
+
)}
@@ -427,7 +523,7 @@ const GlossaryV1 = ({
) : (
@@ -437,7 +533,7 @@ const GlossaryV1 = ({
glossaryTerm={selectedData as GlossaryTerm}
handleGlossaryTermUpdate={handleGlossaryTermUpdate}
handleUserRedirection={handleUserRedirection}
- isHasAccess={isHasAccess}
+ permissions={glossaryTermPermission}
onAssetPaginate={onAssetPaginate}
onRelatedTermClick={onRelatedTermClick}
/>
@@ -460,19 +556,16 @@ const GlossaryV1 = ({
No glossaries found
-
-
-
+
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.component.tsx
index cd589083be9..4bf2478c1d8 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.component.tsx
@@ -12,29 +12,20 @@
*/
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Card as AntdCard } from 'antd';
+import { Button as ButtonAntd, Card as AntdCard, Tooltip } from 'antd';
import { AxiosError } from 'axios';
import classNames from 'classnames';
import { cloneDeep, debounce, includes, isEqual } from 'lodash';
import { EntityTags, FormattedUsersData } from 'Models';
import React, { useCallback, useEffect, useState } from 'react';
-import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
import { WILD_CARD_CHAR } from '../../constants/char.constants';
-import {
- TITLE_FOR_NON_ADMIN_ACTION,
- TITLE_FOR_NON_OWNER_ACTION,
- TITLE_FOR_UPDATE_OWNER,
-} from '../../constants/constants';
-import { EntityType } from '../../enums/entity.enum';
+import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import { Glossary } from '../../generated/entity/data/glossary';
-import { Operation } from '../../generated/entity/policies/policy';
import { EntityReference } from '../../generated/type/entityReference';
import { LabelType, State, TagSource } from '../../generated/type/tagLabel';
-import { useAuth } from '../../hooks/authHooks';
import jsonData from '../../jsons/en';
-import { getEntityName, hasEditAccess } from '../../utils/CommonUtils';
+import { getEntityName } from '../../utils/CommonUtils';
import { getOwnerList } from '../../utils/ManageUtils';
-import { hasPemission } from '../../utils/PermissionsUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
import {
getTagCategories,
@@ -47,27 +38,24 @@ import {
searchFormattedUsersAndTeams,
suggestFormattedUsersAndTeams,
} from '../../utils/UserDataUtils';
-import { Button } from '../buttons/Button/Button';
import Card from '../common/Card/Card';
import DescriptionV1 from '../common/description/DescriptionV1';
-import NonAdminAction from '../common/non-admin-action/NonAdminAction';
import ProfilePicture from '../common/ProfilePicture/ProfilePicture';
import DropDownList from '../dropdown/DropDownList';
import ReviewerModal from '../Modals/ReviewerModal/ReviewerModal.component';
+import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
import TagsContainer from '../tags-container/tags-container';
import TagsViewer from '../tags-viewer/tags-viewer';
import Tags from '../tags/tags';
type props = {
- isHasAccess: boolean;
+ permissions: OperationPermission;
glossary: Glossary;
updateGlossary: (value: Glossary) => void;
handleUserRedirection?: (name: string) => void;
};
-const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
- const { userPermissions } = useAuth();
- const { isAuthDisabled } = useAuthContext();
+const GlossaryDetails = ({ permissions, glossary, updateGlossary }: props) => {
const [isDescriptionEditable, setIsDescriptionEditable] = useState(false);
const [isTagEditable, setIsTagEditable] = useState(false);
const [tagList, setTagList] = useState>([]);
@@ -264,13 +252,6 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
setListVisible(false);
};
- const isOwner = () => {
- return hasEditAccess(
- glossary?.owner?.type || '',
- glossary?.owner?.id || ''
- );
- };
-
const handleTagContainerClick = () => {
if (!isTagEditable) {
fetchTags();
@@ -293,44 +274,39 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
const AddReviewerButton = () => {
return (
-
-
-
+
+
);
};
const ownerAction = () => {
return (
- {TITLE_FOR_UPDATE_OWNER}
}
- isOwner={isOwner()}
- permission={Operation.EditOwner}
- position="left">
-
-
+
+
{listVisible && (
{
{getEntityName(term)}
- {TITLE_FOR_NON_OWNER_ACTION}}
- isOwner={isOwner()}
- position="bottom">
- handleRemoveReviewer(term.id)}>
-
-
-
+
+
+ handleRemoveReviewer(term.id)}>
+
+
+
+
))}
@@ -426,52 +406,51 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
)}
>
)}
-
-
- {
- handleTagSelection();
- }}
- onSelectionChange={(tags) => {
- handleTagSelection(tags);
- }}>
- {glossary?.tags && glossary?.tags.length ? (
-
- ) : (
-
-
-
- )}
-
-
-
+
+
+ {
+ handleTagSelection();
+ }}
+ onSelectionChange={(tags) => {
+ handleTagSelection(tags);
+ }}>
+ {glossary?.tags && glossary?.tags.length ? (
+
+ ) : (
+
+
+
+ )}
+
+
@@ -481,6 +460,7 @@ const GlossaryDetails = ({ isHasAccess, glossary, updateGlossary }: props) => {
removeBlur
description={glossary?.description}
entityName={glossary?.displayName ?? glossary?.name}
+ hasEditAccess={permissions.EditDescription}
isEdit={isDescriptionEditable}
onCancel={onCancel}
onDescriptionEdit={onDescriptionEdit}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.test.tsx
index 08199eda6b9..44d65dbf0e7 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryDetails/GlossaryDetails.test.tsx
@@ -14,6 +14,7 @@
import { findByText, getByTestId, render } from '@testing-library/react';
import React from 'react';
import { mockedGlossaries } from '../../mocks/Glossary.mock';
+import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
import GlossaryDetails from './GlossaryDetails.component';
jest.mock('react-router-dom', () => ({
@@ -61,7 +62,15 @@ jest.mock('../common/ProfilePicture/ProfilePicture', () => {
const mockProps = {
glossary: mockedGlossaries[0],
- isHasAccess: true,
+ permissions: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ } as OperationPermission,
updateGlossary: jest.fn(),
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTerms.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTerms.test.tsx
index 2229b88dfe4..9a8cac86fca 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTerms.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTerms.test.tsx
@@ -17,8 +17,47 @@ import {
mockedAssetData,
mockedGlossaryTerms,
} from '../../mocks/Glossary.mock';
+import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
import GlossaryTerms from './GlossaryTermsV1.component';
+jest.mock('../PermissionProvider/PermissionProvider', () => ({
+ usePermissionProvider: jest.fn().mockReturnValue({
+ getEntityPermission: jest.fn().mockReturnValue({
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ }),
+ permissions: {
+ glossaryTerm: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ },
+ glossary: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ },
+ },
+ }),
+}));
+
+jest.mock('../../utils/PermissionsUtils', () => ({
+ checkPermission: jest.fn().mockReturnValue(true),
+}));
+
jest.mock('react-router-dom', () => ({
useHistory: jest.fn(),
useParams: jest.fn().mockReturnValue({
@@ -26,18 +65,6 @@ jest.mock('react-router-dom', () => ({
}),
}));
-jest.mock('../../authentication/auth-provider/AuthProvider', () => {
- return {
- useAuthContext: jest.fn(() => ({
- isAuthDisabled: false,
- isAuthenticated: true,
- isProtectedRoute: jest.fn().mockReturnValue(true),
- isTourRoute: jest.fn().mockReturnValue(false),
- onLogoutHandler: jest.fn(),
- })),
- };
-});
-
jest.mock('../../components/tags-container/tags-container', () => {
return jest.fn().mockReturnValue(<>Tags-container component>);
});
@@ -99,10 +126,22 @@ jest.mock('antd', () => ({
)),
}));
+jest.mock('./SummaryDetail', () =>
+ jest.fn().mockReturnValue(
SummaryDetails
)
+);
+
const mockProps = {
assetData: mockedAssetData,
currentPage: 1,
- isHasAccess: true,
+ permissions: {
+ Create: true,
+ Delete: true,
+ ViewAll: true,
+ EditAll: true,
+ EditDescription: true,
+ EditDisplayName: true,
+ EditCustomFields: true,
+ } as OperationPermission,
glossaryTerm: mockedGlossaryTerms[0],
handleGlossaryTermUpdate: jest.fn(),
onAssetPaginate: jest.fn(),
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTermsV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTermsV1.component.tsx
index 533e0f9763f..62e5db74550 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTermsV1.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/GlossaryTermsV1.component.tsx
@@ -20,19 +20,12 @@ import {
Input,
Row,
Space,
+ Tooltip,
Typography,
} from 'antd';
import { AxiosError } from 'axios';
import classNames from 'classnames';
-import {
- cloneDeep,
- includes,
- isEmpty,
- isEqual,
- isString,
- isUndefined,
- kebabCase,
-} from 'lodash';
+import { cloneDeep, includes, isEmpty, isEqual } from 'lodash';
import {
EntityTags,
FormattedGlossaryTermData,
@@ -40,10 +33,7 @@ import {
GlossaryTermAssets,
} from 'Models';
import React, { Fragment, useEffect, useState } from 'react';
-import {
- TITLE_FOR_NON_ADMIN_ACTION,
- TITLE_FOR_NON_OWNER_ACTION,
-} from '../../constants/constants';
+import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import {
GlossaryTerm,
TermReference,
@@ -59,21 +49,22 @@ import {
} from '../../utils/TagsUtils';
import { showErrorToast } from '../../utils/ToastUtils';
import DescriptionV1 from '../common/description/DescriptionV1';
-import NonAdminAction from '../common/non-admin-action/NonAdminAction';
import ProfilePicture from '../common/ProfilePicture/ProfilePicture';
import TabsPane from '../common/TabsPane/TabsPane';
import GlossaryReferenceModal from '../Modals/GlossaryReferenceModal/GlossaryReferenceModal';
import RelatedTermsModal from '../Modals/RelatedTermsModal/RelatedTermsModal';
import ReviewerModal from '../Modals/ReviewerModal/ReviewerModal.component';
+import { OperationPermission } from '../PermissionProvider/PermissionProvider.interface';
import TagsContainer from '../tags-container/tags-container';
import TagsViewer from '../tags-viewer/tags-viewer';
import Tags from '../tags/tags';
+import SummaryDetail from './SummaryDetail';
import AssetsTabs from './tabs/AssetsTabs.component';
const { Text } = Typography;
type Props = {
assetData: GlossaryTermAssets;
- isHasAccess: boolean;
+ permissions: OperationPermission;
glossaryTerm: GlossaryTerm;
currentPage: number;
handleGlossaryTermUpdate: (data: GlossaryTerm) => void;
@@ -82,21 +73,14 @@ type Props = {
handleUserRedirection?: (name: string) => void;
};
-type SummaryDetailsProps = {
- title: string;
- children: React.ReactElement;
- setShow?: (value: React.SetStateAction
) => void;
- data?: FormattedGlossaryTermData[] | TermReference[] | string;
-};
-
const GlossaryTermsV1 = ({
assetData,
- isHasAccess,
glossaryTerm,
handleGlossaryTermUpdate,
onAssetPaginate,
onRelatedTermClick,
currentPage,
+ permissions,
}: Props) => {
const [isTagEditable, setIsTagEditable] = useState(false);
const [tagList, setTagList] = useState>([]);
@@ -301,7 +285,7 @@ const GlossaryTermsV1 = ({
const handleValidation = (
event: React.ChangeEvent
) => {
- if (isHasAccess) {
+ if (permissions.EditAll) {
return;
}
const value = event.target.value;
@@ -344,28 +328,18 @@ const GlossaryTermsV1 = ({
const addReviewerButton = () => {
return (
-
-
- );
- };
-
- const addButton = (onClick: () => void) => {
- return (
-
-
-
-
-
+
+
);
};
@@ -398,9 +372,7 @@ const GlossaryTermsV1 = ({
{getEntityName(term)}
- {TITLE_FOR_NON_OWNER_ACTION}}
- position="bottom">
+
-
+
))}
@@ -437,34 +409,6 @@ const GlossaryTermsV1 = ({
);
};
- const SummaryDetail = ({
- title,
- children,
- setShow,
- data,
- ...props
- }: SummaryDetailsProps) => {
- return (
-
-
- {title}
-
- {addButton(() => setShow && setShow(true))}
-
-
- {!isString(data) && !isUndefined(data) && data.length > 0 ? (
-
- {children}
-
- ) : (
- {children}
- )}
-
- );
- };
-
const SummaryTab = () => {
return (
@@ -482,6 +426,7 @@ const GlossaryTermsV1 = ({
@@ -510,6 +455,7 @@ const GlossaryTermsV1 = ({
@@ -558,6 +504,7 @@ const GlossaryTermsV1 = ({
@@ -629,50 +576,49 @@ const GlossaryTermsV1 = ({
)}
>
)}
-
-
- {
- handleTagSelection();
- }}
- onSelectionChange={(tags) => {
- handleTagSelection(tags);
- }}>
- {glossaryTerm?.tags && glossaryTerm?.tags.length ? (
-
-
-
- ) : (
-
-
-
- )}
-
-
-
+
+
+ {
+ handleTagSelection();
+ }}
+ onSelectionChange={(tags) => {
+ handleTagSelection(tags);
+ }}>
+ {glossaryTerm?.tags && glossaryTerm?.tags.length ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/SummaryDetail.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/SummaryDetail.tsx
new file mode 100644
index 00000000000..83933e8f64f
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/components/GlossaryTerms/SummaryDetail.tsx
@@ -0,0 +1,57 @@
+import { Button, Space, Tooltip, Typography } from 'antd';
+import { isString, isUndefined, kebabCase } from 'lodash';
+import { FormattedGlossaryTermData } from 'Models';
+import React from 'react';
+import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
+import { TermReference } from '../../generated/entity/data/glossaryTerm';
+import SVGIcons from '../../utils/SvgUtils';
+
+interface SummaryDetailsProps {
+ title: string;
+ children: React.ReactElement;
+ hasAccess: boolean;
+ setShow?: (value: React.SetStateAction
) => void;
+ data?: FormattedGlossaryTermData[] | TermReference[] | string;
+}
+
+const SummaryDetail = ({
+ title,
+ children,
+ setShow,
+ data,
+ hasAccess,
+ ...props
+}: SummaryDetailsProps) => {
+ return (
+
+
+ {title}
+
+
+ setShow && setShow(true)}>
+
+
+
+
+
+ {!isString(data) && !isUndefined(data) && data.length > 0 ? (
+
+ {children}
+
+ ) : (
+ {children}
+ )}
+
+ );
+};
+
+export default SummaryDetail;
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/description/DescriptionV1.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/description/DescriptionV1.tsx
index 342c4f07376..7dc508b5b64 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/common/description/DescriptionV1.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/common/description/DescriptionV1.tsx
@@ -11,19 +11,17 @@
* limitations under the License.
*/
-import { Space, Typography } from 'antd';
+import { Space, Tooltip, Typography } from 'antd';
import classNames from 'classnames';
import { isUndefined } from 'lodash';
import { EntityFieldThreads } from 'Models';
import React, { Fragment } from 'react';
import { EntityField } from '../../../constants/feed.constants';
+import { NO_PERMISSION_FOR_ACTION } from '../../../constants/HelperTextUtil';
import { Table } from '../../../generated/entity/data/table';
-import { Operation } from '../../../generated/entity/policies/accessControl/rule';
-import { getHtmlForNonAdminAction } from '../../../utils/CommonUtils';
import { getEntityFeedLink } from '../../../utils/EntityUtils';
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
import { ModalWithMarkdownEditor } from '../../Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
-import NonAdminAction from '../non-admin-action/NonAdminAction';
import PopOver from '../popover/PopOver';
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
const { Text } = Typography;
@@ -47,7 +45,6 @@ interface Props {
onEntityFieldSelect?: (value: string) => void;
}
const DescriptionV1 = ({
- owner,
hasEditAccess,
onDescriptionEdit,
description = '',
@@ -67,14 +64,12 @@ const DescriptionV1 = ({
const editButton = () => {
return !isReadOnly ? (
-
+
-
+
) : (
<>>
);
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/GlossaryPage/GlossaryPageV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/GlossaryPage/GlossaryPageV1.component.tsx
index b48a1393b30..69442ded4dd 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/GlossaryPage/GlossaryPageV1.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/GlossaryPage/GlossaryPageV1.component.tsx
@@ -23,7 +23,6 @@ import {
} from 'Models';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
-import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
import {
deleteGlossary,
deleteGlossaryTerm,
@@ -42,7 +41,6 @@ import { myDataSearchIndex } from '../../constants/Mydata.constants';
import { SearchIndex } from '../../enums/search.enum';
import { Glossary } from '../../generated/entity/data/glossary';
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
-import { useAuth } from '../../hooks/authHooks';
import jsonData from '../../jsons/en';
import { formatDataResponse } from '../../utils/APIUtils';
import {
@@ -66,8 +64,6 @@ export type ModifiedGlossaryData = Glossary & {
const GlossaryPageV1 = () => {
const { glossaryName } = useParams>();
- const { isAdminUser } = useAuth();
- const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const [isLoading, setIsLoading] = useState(true);
const [isChildLoading, setIsChildLoading] = useState(true);
@@ -724,7 +720,6 @@ const GlossaryPageV1 = () => {
handleUserRedirection={handleUserRedirection}
isChildLoading={isChildLoading}
isGlossaryActive={isGlossaryActive}
- isHasAccess={!isAdminUser && !isAuthDisabled}
isSearchResultEmpty={isSearchResultEmpty}
loadingKey={loadingKey}
searchText={searchText}
diff --git a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
index e5f7fda85c8..56a2d416be8 100644
--- a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
@@ -12,7 +12,7 @@
*/
import { isEmpty } from 'lodash';
-import React, { FunctionComponent } from 'react';
+import React, { FunctionComponent, useMemo } from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
import AppState from '../AppState';
import { usePermissionProvider } from '../components/PermissionProvider/PermissionProvider';
@@ -212,6 +212,32 @@ const EditRulePage = withSuspenseFallback(
const AuthenticatedAppRouter: FunctionComponent = () => {
const { permissions } = usePermissionProvider();
+ const glossaryPermission = useMemo(
+ () =>
+ checkPermission(Operation.ViewAll, ResourceEntity.GLOSSARY, permissions),
+ [permissions]
+ );
+
+ const glossaryTermPermission = useMemo(
+ () =>
+ checkPermission(
+ Operation.ViewAll,
+ ResourceEntity.GLOSSARY_TERM,
+ permissions
+ ),
+ [permissions]
+ );
+
+ const tagCategoryPermission = useMemo(
+ () =>
+ checkPermission(
+ Operation.ViewAll,
+ ResourceEntity.TAG_CATEGORY,
+ permissions
+ ),
+ [permissions]
+ );
+
return (
@@ -251,8 +277,18 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
{!isEmpty(AppState.userDetails) && }
-
-
+
+
{
/>
-
-
-
+
+
+