diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component.tsx index d1397164af1..acd129e1686 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component.tsx @@ -16,6 +16,7 @@ import { AxiosError } from 'axios'; import classNames from 'classnames'; import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component'; import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component'; +import { ClientErrors } from 'enums/axios.enum'; import { ExplorePageTabs } from 'enums/Explore.enum'; import { isEmpty, isUndefined } from 'lodash'; import { @@ -120,13 +121,16 @@ function TableSummary({ return {} as Table; } }); - } catch { - showErrorToast( - t('server.entity-details-fetch-error', { - entityType: t('label.table-lowercase'), - entityName: entityDetails.name, - }) - ); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response?.status !== ClientErrors.FORBIDDEN) { + showErrorToast( + t('server.entity-details-fetch-error', { + entityType: t('label.table-lowercase'), + entityName: entityDetails.name, + }) + ); + } } }, [entityDetails]); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx index 5edc7f17cfe..314d8e8374f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component.tsx @@ -12,9 +12,11 @@ */ import { Col, Divider, Row, Typography } from 'antd'; +import { AxiosError } from 'axios'; import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component'; import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component'; import { getTeamAndUserDetailsPath } from 'constants/constants'; +import { ClientErrors } from 'enums/axios.enum'; import { isArray, isEmpty } from 'lodash'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -90,13 +92,16 @@ function TopicSummary({ const { partitions, messageSchema } = res; setTopicDetails({ ...entityDetails, partitions, messageSchema }); - } catch { - showErrorToast( - t('server.entity-details-fetch-error', { - entityType: t('label.topic-lowercase'), - entityName: entityDetails.name, - }) - ); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response?.status !== ClientErrors.FORBIDDEN) { + showErrorToast( + t('server.entity-details-fetch-error', { + entityType: t('label.topic-lowercase'), + entityName: entityDetails.name, + }) + ); + } } }, [entityDetails]); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.test.tsx index 6c78baabea3..eada1ab8c7c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.test.tsx @@ -27,31 +27,55 @@ jest.mock('../SummaryList/SummaryList.component', () => ); jest.mock('rest/topicsAPI', () => ({ - getTopicByFqn: jest.fn().mockImplementation(() => mockTopicByFqnResponse), + getTopicByFqn: jest + .fn() + .mockImplementation(() => Promise.resolve(mockTopicByFqnResponse)), })); +jest.mock( + 'components/common/SummaryTagsDescription/SummaryTagsDescription.component', + () => jest.fn().mockImplementation(() =>

SummaryTagDescription

) +); + +jest.mock( + 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component', + () => jest.fn().mockImplementation(({ children }) => <>{children}) +); + describe('TopicSummary component tests', () => { it('Component should render properly', async () => { await act(async () => { render(); }); - const partitionsLabel = screen.getByTestId('Partitions-label'); - const replicationFactorLabel = screen.getByTestId( + const partitionsLabel = await screen.findByTestId('Partitions-label'); + const replicationFactorLabel = await screen.findByTestId( 'Replication Factor-label' ); - const retentionSizeLabel = screen.getByTestId('Retention Size-label'); - const cleanUpPoliciesLabel = screen.getByTestId('CleanUp Policies-label'); - const maxMessageSizeLabel = screen.getByTestId('Max Message Size-label'); - const partitionsValue = screen.getByTestId('Partitions-value'); - const replicationFactorValue = screen.getByTestId( + const retentionSizeLabel = await screen.findByTestId( + 'Retention Size-label' + ); + const cleanUpPoliciesLabel = await screen.findByTestId( + 'CleanUp Policies-label' + ); + const maxMessageSizeLabel = await screen.findByTestId( + 'Max Message Size-label' + ); + const partitionsValue = await screen.findByTestId('Partitions-value'); + const replicationFactorValue = await screen.findByTestId( 'Replication Factor-value' ); - const retentionSizeValue = screen.getByTestId('Retention Size-value'); - const cleanUpPoliciesValue = screen.getByTestId('CleanUp Policies-value'); - const maxMessageSizeValue = screen.getByTestId('Max Message Size-value'); - const schemaHeader = screen.getByTestId('schema-header'); - const summaryList = screen.getByTestId('SummaryList'); + const retentionSizeValue = await screen.findByTestId( + 'Retention Size-value' + ); + const cleanUpPoliciesValue = await screen.findByTestId( + 'CleanUp Policies-value' + ); + const maxMessageSizeValue = await screen.findByTestId( + 'Max Message Size-value' + ); + const schemaHeader = await screen.findByTestId('schema-header'); + const summaryList = await screen.findByTestId('SummaryList'); expect(partitionsLabel).toBeInTheDocument(); expect(replicationFactorLabel).toBeInTheDocument(); @@ -68,7 +92,9 @@ describe('TopicSummary component tests', () => { }); it('No data message should be shown in case no schemaFields are available in topic details', async () => { - (getTopicByFqn as jest.Mock).mockImplementation(() => Promise.resolve({})); + (getTopicByFqn as jest.Mock).mockImplementation(() => + Promise.resolve({ ...mockTopicEntityDetails, messageSchema: {} }) + ); await act(async () => { render(); @@ -82,7 +108,9 @@ describe('TopicSummary component tests', () => { }); it('In case any topic field is not present, "-" should be displayed in place of value', async () => { - (getTopicByFqn as jest.Mock).mockImplementationOnce(() => Promise.reject()); + (getTopicByFqn as jest.Mock).mockImplementationOnce(() => + Promise.reject({}) + ); await act(async () => { render(); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSetting.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSetting.tsx deleted file mode 100644 index 8c0564429fa..00000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSetting.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import PageLayoutV1 from '../containers/PageLayoutV1'; -import GlobalSettingRouter from '../router/GlobalSettingRouter'; -import './GlobalSetting.less'; -import GlobalSettingLeftPanel from './GlobalSettingLeftPanel'; - -const GlobalSetting = () => { - const { t } = useTranslation(); - - return ( - } - pageTitle={t('label.setting-plural')}> - - - ); -}; - -export default GlobalSetting; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.test.tsx deleted file mode 100644 index 688b6c52788..00000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.test.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2023 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { render, screen, waitForElement } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { PERMISSIONS } from 'mocks/Permissions.mock'; -import React from 'react'; -import { MemoryRouter, Route } from 'react-router-dom'; -import GlobalSettingLeftPanel from './GlobalSettingLeftPanel'; - -jest.mock('../PermissionProvider/PermissionProvider', () => ({ - usePermissionProvider: jest.fn().mockImplementation(() => ({ - permissions: PERMISSIONS, - getEntityPermission: jest.fn().mockResolvedValue({ - Create: true, - Delete: true, - EditAll: true, - EditCustomFields: true, - EditDataProfile: true, - EditDescription: true, - EditDisplayName: true, - EditLineage: true, - EditOwner: true, - EditQueries: true, - EditSampleData: true, - EditTags: true, - EditTests: true, - EditTier: true, - ViewAll: true, - ViewDataProfile: true, - ViewQueries: true, - ViewSampleData: true, - ViewTests: true, - ViewUsage: true, - }), - })), -})); - -const selectedCategory = 'services'; -const selectedOption = 'storages'; -const url = `/settings/${selectedCategory}/${selectedOption}`; - -describe('GlobalSettingLeftPanel', () => { - it('Should render global settings menu with correct selected item', () => { - render( - - - - - - ); - - expect(screen.getByText('label.service-plural')).toBeInTheDocument(); - expect(screen.getByText('label.storage-plural')).toBeInTheDocument(); - }); - - it('Should change the location path on user click', () => { - render( - - - - - - ); - - userEvent.click(screen.getByText('label.team-plural')); - - waitForElement(() => - expect(window.location.pathname).toEqual('/teams/organizations') - ); - }); -}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.tsx b/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.tsx deleted file mode 100644 index 6c1258884ef..00000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSettingLeftPanel.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2022 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Menu, MenuProps } from 'antd'; -import { ItemType } from 'antd/lib/menu/hooks/useItems'; -import { ELASTIC_SEARCH_RE_INDEX_PAGE_TABS } from 'enums/ElasticSearch.enum'; -import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useHistory, useParams } from 'react-router-dom'; -import { GlobalSettingOptions } from '../../constants/GlobalSettings.constants'; -import { TeamType } from '../../generated/entity/teams/team'; -import { useAuth } from '../../hooks/authHooks'; -import { - getGlobalSettingMenuItem, - getGlobalSettingsMenuWithPermission, - MenuList, -} from '../../utils/GlobalSettingsUtils'; -import { - getSettingPath, - getSettingsPathWithFqn, - getTeamsWithFqnPath, -} from '../../utils/RouterUtils'; -import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder'; -import LeftPanelCard from '../common/LeftPanelCard/LeftPanelCard'; -import { usePermissionProvider } from '../PermissionProvider/PermissionProvider'; - -const GlobalSettingLeftPanel = () => { - const history = useHistory(); - const { t } = useTranslation(); - const { tab, settingCategory } = useParams<{ [key: string]: string }>(); - - const { permissions } = usePermissionProvider(); - - const { isAdminUser } = useAuth(); - - const menuItems: ItemType[] = useMemo( - () => - getGlobalSettingsMenuWithPermission(permissions, isAdminUser).reduce( - (acc: ItemType[], curr: MenuList) => { - const menuItem = getGlobalSettingMenuItem({ - label: curr.category, - key: curr.key, - category: curr.category, - children: curr.items, - type: 'group', - isBeta: curr.isBeta, - }); - if (menuItem.children?.length) { - return [...acc, menuItem]; - } else { - return acc; - } - }, - [] as ItemType[] - ), - [permissions] - ); - - const onClick: MenuProps['onClick'] = (e) => { - // As we are setting key as "category.option" and extracting here category and option - const [category, option] = e.key.split('.'); - - switch (option) { - case GlobalSettingOptions.TEAMS: - history.push(getTeamsWithFqnPath(TeamType.Organization)); - - break; - case GlobalSettingOptions.SEARCH: - history.push( - getSettingsPathWithFqn( - category, - option, - ELASTIC_SEARCH_RE_INDEX_PAGE_TABS.ON_DEMAND - ) - ); - - break; - default: - history.push(getSettingPath(category, option)); - - break; - } - }; - - return menuItems.length ? ( - - - - ) : ( - -

{t('message.no-data-available')}

-
- ); -}; - -export default GlobalSettingLeftPanel; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/router/AdminProtectedRoute.tsx b/openmetadata-ui/src/main/resources/ui/src/components/router/AdminProtectedRoute.tsx index f71e782c8d8..94d96b247b5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/router/AdminProtectedRoute.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/router/AdminProtectedRoute.tsx @@ -11,11 +11,15 @@ * limitations under the License. */ +import ErrorPlaceHolder from 'components/common/error-with-placeholder/ErrorPlaceHolder'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from 'constants/HelperTextUtil'; import React from 'react'; import { Redirect, Route, RouteProps } from 'react-router-dom'; import { ROUTES } from '../../constants/constants'; import { useAuth } from '../../hooks/authHooks'; -import { useAuthContext } from '../authentication/auth-provider/AuthProvider'; interface AdminProtectedRouteProps extends RouteProps { hasPermission: boolean; @@ -23,12 +27,17 @@ interface AdminProtectedRouteProps extends RouteProps { const AdminProtectedRoute = (routeProps: AdminProtectedRouteProps) => { const { isAdminUser } = useAuth(); - const { isAuthDisabled, isAuthenticated } = useAuthContext(); - if (isAuthDisabled || isAdminUser || routeProps.hasPermission) { + if (isAdminUser || routeProps.hasPermission) { return ; - } else if (isAuthenticated) { - return ; + } else if (!routeProps.hasPermission) { + return ( + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
+ ); } else { return ; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/router/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/router/AuthenticatedAppRouter.tsx index d5f56efda05..09dbeaa4f30 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/router/AuthenticatedAppRouter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/router/AuthenticatedAppRouter.tsx @@ -245,6 +245,10 @@ const AddQueryPage = withSuspenseFallback( React.lazy(() => import('pages/AddQueryPage/AddQueryPage.component')) ); +const PageNotFound = withSuspenseFallback( + React.lazy(() => import('pages/page-not-found')) +); + const AuthenticatedAppRouter: FunctionComponent = () => { const { permissions } = usePermissionProvider(); @@ -603,6 +607,7 @@ const AuthenticatedAppRouter: FunctionComponent = () => { + ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/router/GlobalSettingRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/router/GlobalSettingRouter.tsx index 764c91f4ba6..d3429c3b90f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/router/GlobalSettingRouter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/router/GlobalSettingRouter.tsx @@ -17,7 +17,6 @@ import { GlobalSettingOptions, GlobalSettingsMenuCategory, } from '../../constants/GlobalSettings.constants'; - import { TeamType } from '../../generated/entity/teams/team'; import { userPermissions } from '../../utils/PermissionsUtils'; import { @@ -27,7 +26,6 @@ import { } from '../../utils/RouterUtils'; import { usePermissionProvider } from '../PermissionProvider/PermissionProvider'; import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface'; - import AdminProtectedRoute from './AdminProtectedRoute'; import withSuspenseFallback from './withSuspenseFallback'; @@ -117,9 +115,13 @@ const GlobalSettingRouter = () => { - { {botPermission.ViewAll || botPermission.ViewBasic ? ( getBotsDetailComponent() ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx index 1458d816a83..e2d097849fd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx @@ -37,7 +37,10 @@ import { } from 'components/PermissionProvider/PermissionProvider.interface'; import { FQN_SEPARATOR_CHAR } from 'constants/char.constants'; import { getServiceDetailsPath, getVersionPath } from 'constants/constants'; -import { NO_PERMISSION_TO_VIEW } from 'constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from 'constants/HelperTextUtil'; import { EntityInfo, EntityType } from 'enums/entity.enum'; import { ServiceCategory } from 'enums/service.enum'; import { OwnerType } from 'enums/user.enum'; @@ -620,7 +623,13 @@ const ContainerPage = () => { } if (!hasViewPermission && !isLoading) { - return {NO_PERMISSION_TO_VIEW}; + return ( + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
+ ); } return ( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/CustomPropertiesPageV1/CustomPropertiesPageV1.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/CustomPropertiesPageV1/CustomPropertiesPageV1.tsx index 340e1fbebd5..ee2e0339501 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/CustomPropertiesPageV1/CustomPropertiesPageV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/CustomPropertiesPageV1/CustomPropertiesPageV1.tsx @@ -39,6 +39,7 @@ import { CUSTOM_PROPERTIES_DOCS } from '../../constants/docs.constants'; import { NO_PERMISSION_FOR_ACTION, NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, } from '../../constants/HelperTextUtil'; import { PAGE_HEADERS } from '../../constants/PageHeaders.constant'; import { Type } from '../../generated/entity/type'; @@ -297,7 +298,9 @@ const CustomEntityDetailV1 = () => { -

{NO_PERMISSION_TO_VIEW}

+

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx index e6139f9e85c..909b54013b0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx @@ -37,7 +37,10 @@ import { getServiceDetailsPath, getVersionPath, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { FeedFilter } from '../../enums/mydata.enum'; import { ServiceCategory } from '../../enums/service.enum'; @@ -540,7 +543,11 @@ const DashboardDetailsPage = () => { onExtensionUpdate={handleExtensionUpdate} /> ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx index b1b10072ba3..d644cebd256 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx @@ -21,7 +21,10 @@ import { OperationPermission, ResourceEntity, } from 'components/PermissionProvider/PermissionProvider.interface'; -import { NO_PERMISSION_TO_VIEW } from 'constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from 'constants/HelperTextUtil'; import { EntityType } from 'enums/entity.enum'; import { FeedFilter } from 'enums/mydata.enum'; import { compare, Operation } from 'fast-json-patch'; @@ -469,7 +472,13 @@ const DataModelsPage = () => { } if (!hasViewPermission && !isLoading) { - return {NO_PERMISSION_TO_VIEW}; + return ( + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
+ ); } return ( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatasetDetailsPage/DatasetDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatasetDetailsPage/DatasetDetailsPage.component.tsx index 35e3b9899db..7feecdbc30f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DatasetDetailsPage/DatasetDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatasetDetailsPage/DatasetDetailsPage.component.tsx @@ -50,7 +50,10 @@ import { getVersionPath, pagingObject, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { EntityType, FqnPart, TabSpecificField } from '../../enums/entity.enum'; import { FeedFilter } from '../../enums/mydata.enum'; import { ServiceCategory } from '../../enums/service.enum'; @@ -620,7 +623,11 @@ const DatasetDetailsPage: FunctionComponent = () => { versionHandler={versionHandler} /> ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx index e97b11e5a23..4af38dcded8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/GlobalSettingPage.tsx @@ -11,14 +11,111 @@ * limitations under the License. */ +import { Menu, MenuProps } from 'antd'; +import { ItemType } from 'antd/lib/menu/hooks/useItems'; +import LeftPanelCard from 'components/common/LeftPanelCard/LeftPanelCard'; import PageContainerV1 from 'components/containers/PageContainerV1'; -import GlobalSetting from 'components/GlobalSetting/GlobalSetting'; -import React from 'react'; +import PageLayoutV1 from 'components/containers/PageLayoutV1'; +import { usePermissionProvider } from 'components/PermissionProvider/PermissionProvider'; +import GlobalSettingRouter from 'components/router/GlobalSettingRouter'; +import { GlobalSettingOptions } from 'constants/GlobalSettings.constants'; +import { ELASTIC_SEARCH_RE_INDEX_PAGE_TABS } from 'enums/ElasticSearch.enum'; +import { TeamType } from 'generated/entity/teams/team'; +import { useAuth } from 'hooks/authHooks'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useHistory, useParams } from 'react-router-dom'; +import { + getGlobalSettingMenuItem, + getGlobalSettingsMenuWithPermission, + MenuList, +} from 'utils/GlobalSettingsUtils'; +import { + getSettingPath, + getSettingsPathWithFqn, + getTeamsWithFqnPath, +} from 'utils/RouterUtils'; +import './global-setting-page.style.less'; const GlobalSettingPage = () => { + const history = useHistory(); + const { t } = useTranslation(); + const { tab, settingCategory } = useParams<{ [key: string]: string }>(); + + const { permissions } = usePermissionProvider(); + + const { isAdminUser } = useAuth(); + + const menuItems: ItemType[] = useMemo( + () => + getGlobalSettingsMenuWithPermission(permissions, isAdminUser).reduce( + (acc: ItemType[], curr: MenuList) => { + const menuItem = getGlobalSettingMenuItem({ + label: curr.category, + key: curr.key, + category: curr.category, + children: curr.items, + type: 'group', + isBeta: curr.isBeta, + }); + if (menuItem.children?.length) { + return [...acc, menuItem]; + } else { + return acc; + } + }, + [] as ItemType[] + ), + [permissions] + ); + + const onClick: MenuProps['onClick'] = (e) => { + // As we are setting key as "category.option" and extracting here category and option + const [category, option] = e.key.split('.'); + + switch (option) { + case GlobalSettingOptions.TEAMS: + history.push(getTeamsWithFqnPath(TeamType.Organization)); + + break; + case GlobalSettingOptions.SEARCH: + history.push( + getSettingsPathWithFqn( + category, + option, + ELASTIC_SEARCH_RE_INDEX_PAGE_TABS.ON_DEMAND + ) + ); + + break; + default: + history.push(getSettingPath(category, option)); + + break; + } + }; + + const leftPanel = menuItems.length ? ( + + + + ) : null; + return ( - + + + ); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSetting.less b/openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/global-setting-page.style.less similarity index 100% rename from openmetadata-ui/src/main/resources/ui/src/components/GlobalSetting/GlobalSetting.less rename to openmetadata-ui/src/main/resources/ui/src/pages/GlobalSettingPage/global-setting-page.style.less diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx index af0a7bf07b2..4b6540faab6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx @@ -20,6 +20,9 @@ import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider import { compare, Operation } from 'fast-json-patch'; import { isEmpty, isNil, isUndefined, omitBy } from 'lodash'; import { observer } from 'mobx-react'; +import React, { Fragment, useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useHistory, useParams } from 'react-router-dom'; import { getAllFeeds, postFeedById, postThread } from 'rest/feedsAPI'; import { addFollower, @@ -27,13 +30,12 @@ import { patchMlModelDetails, removeFollower, } from 'rest/mlModelAPI'; - -import React, { Fragment, useEffect, useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useHistory, useParams } from 'react-router-dom'; import AppState from '../../AppState'; import { getMlModelPath, getVersionPath } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { FeedFilter } from '../../enums/mydata.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -450,7 +452,11 @@ const MlModelPage = () => { {mlModelPermissions.ViewAll || mlModelPermissions.ViewBasic ? ( getMlModelDetail() ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx index 99188cea96e..8f736e6787f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx @@ -34,7 +34,10 @@ import { getServiceDetailsPath, getVersionPath, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { EntityType } from '../../enums/entity.enum'; import { ServiceCategory } from '../../enums/service.enum'; import { Pipeline } from '../../generated/entity/data/pipeline'; @@ -310,7 +313,11 @@ const PipelineDetailsPage = () => { onExtensionUpdate={handleExtensionUpdate} /> ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/QueryPage/QueryPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/QueryPage/QueryPage.component.tsx index c10833b027f..5135c2c7870 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/QueryPage/QueryPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/QueryPage/QueryPage.component.tsx @@ -31,7 +31,10 @@ import { getServiceDetailsPath, getTableTabPath, } from 'constants/constants'; -import { NO_PERMISSION_TO_VIEW } from 'constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from 'constants/HelperTextUtil'; import { FqnPart } from 'enums/entity.enum'; import { ServiceCategory } from 'enums/service.enum'; import { compare } from 'fast-json-patch'; @@ -214,7 +217,13 @@ const QueryPage = () => { return ; } if (!isViewAllowed) { - return {NO_PERMISSION_TO_VIEW}; + return ( + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
+ ); } if (isUndefined(query)) { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx index e06bad64003..d6557deee7e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx @@ -47,7 +47,10 @@ import { pagingObject, ROUTES, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { ACTION_TYPE } from '../../enums/common.enum'; import { OwnerType } from '../../enums/user.enum'; import { TestCase } from '../../generated/tests/testCase'; @@ -363,7 +366,11 @@ const TestSuiteDetailsPage = () => { ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx index 7face105236..c68925f1629 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx @@ -40,7 +40,10 @@ import { getTopicDetailsPath, getVersionPath, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { FeedFilter } from '../../enums/mydata.enum'; import { ServiceCategory } from '../../enums/service.enum'; @@ -466,7 +469,11 @@ const TopicDetailsPage: FunctionComponent = () => { onExtensionUpdate={handleExtensionUpdate} /> ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
)} )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx index 65a3bd9f57f..1b1ed337bfc 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx @@ -23,7 +23,10 @@ import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import { getServices } from 'rest/serviceAPI'; import { pagingObject, SERVICE_VIEW_CAP } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { OPEN_METADATA, SERVICE_CATEGORY, @@ -119,7 +122,9 @@ const ServicesPage = () => { -

{NO_PERMISSION_TO_VIEW}

+

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx index dc0ed1be01c..59d76ba2f0c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/teams/TeamsPage.tsx @@ -42,7 +42,10 @@ import { PAGE_SIZE_MEDIUM, pagingObject, } from '../../constants/constants'; -import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; +import { + NO_PERMISSION_TO_VIEW, + REACH_OUT_TO_ADMIN_FOR_ACCESS, +} from '../../constants/HelperTextUtil'; import { myDataSearchIndex } from '../../constants/Mydata.constants'; import { SearchIndex } from '../../enums/search.enum'; import { CreateTeam, TeamType } from '../../generated/api/teams/createTeam'; @@ -603,7 +606,11 @@ const TeamsPage = () => { /> ) : ( - {NO_PERMISSION_TO_VIEW} + +

+ {NO_PERMISSION_TO_VIEW}
{REACH_OUT_TO_ADMIN_FOR_ACCESS} +

+
); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ToastUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/ToastUtils.ts index 6e7366e129d..a60c2492eac 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ToastUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ToastUtils.ts @@ -12,6 +12,7 @@ */ import { AxiosError } from 'axios'; +import { ClientErrors } from 'enums/axios.enum'; import { isEmpty, isString } from 'lodash'; import React from 'react'; import { toast } from 'react-toastify'; @@ -60,7 +61,8 @@ export const showErrorToast = ( // except for principal domain mismatch errors if ( error && - error.response?.status === 401 && + (error.response?.status === ClientErrors.UNAUTHORIZED || + error.response?.status === ClientErrors.FORBIDDEN) && !errorMessage.includes('principal domain') ) { return;