mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-29 19:35:56 +00:00
fix(ui): added no permission placeholder instead 404 (#11205)
* fix(ui): added no permission placeholder instead 404 * fix unit tests
This commit is contained in:
parent
e984d274d8
commit
f53ea03320
@ -16,6 +16,7 @@ import { AxiosError } from 'axios';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component';
|
import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component';
|
||||||
import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component';
|
import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component';
|
||||||
|
import { ClientErrors } from 'enums/axios.enum';
|
||||||
import { ExplorePageTabs } from 'enums/Explore.enum';
|
import { ExplorePageTabs } from 'enums/Explore.enum';
|
||||||
import { isEmpty, isUndefined } from 'lodash';
|
import { isEmpty, isUndefined } from 'lodash';
|
||||||
import {
|
import {
|
||||||
@ -120,7 +121,9 @@ function TableSummary({
|
|||||||
return {} as Table;
|
return {} as Table;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch {
|
} catch (error) {
|
||||||
|
const axiosError = error as AxiosError;
|
||||||
|
if (axiosError.response?.status !== ClientErrors.FORBIDDEN) {
|
||||||
showErrorToast(
|
showErrorToast(
|
||||||
t('server.entity-details-fetch-error', {
|
t('server.entity-details-fetch-error', {
|
||||||
entityType: t('label.table-lowercase'),
|
entityType: t('label.table-lowercase'),
|
||||||
@ -128,6 +131,7 @@ function TableSummary({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, [entityDetails]);
|
}, [entityDetails]);
|
||||||
|
|
||||||
const overallSummary: OverallTableSummeryType[] | undefined = useMemo(() => {
|
const overallSummary: OverallTableSummeryType[] | undefined = useMemo(() => {
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Col, Divider, Row, Typography } from 'antd';
|
import { Col, Divider, Row, Typography } from 'antd';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component';
|
import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component';
|
||||||
import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component';
|
import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component';
|
||||||
import { getTeamAndUserDetailsPath } from 'constants/constants';
|
import { getTeamAndUserDetailsPath } from 'constants/constants';
|
||||||
|
import { ClientErrors } from 'enums/axios.enum';
|
||||||
import { isArray, isEmpty } from 'lodash';
|
import { isArray, isEmpty } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -90,7 +92,9 @@ function TopicSummary({
|
|||||||
const { partitions, messageSchema } = res;
|
const { partitions, messageSchema } = res;
|
||||||
|
|
||||||
setTopicDetails({ ...entityDetails, partitions, messageSchema });
|
setTopicDetails({ ...entityDetails, partitions, messageSchema });
|
||||||
} catch {
|
} catch (error) {
|
||||||
|
const axiosError = error as AxiosError;
|
||||||
|
if (axiosError.response?.status !== ClientErrors.FORBIDDEN) {
|
||||||
showErrorToast(
|
showErrorToast(
|
||||||
t('server.entity-details-fetch-error', {
|
t('server.entity-details-fetch-error', {
|
||||||
entityType: t('label.topic-lowercase'),
|
entityType: t('label.topic-lowercase'),
|
||||||
@ -98,6 +102,7 @@ function TopicSummary({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, [entityDetails]);
|
}, [entityDetails]);
|
||||||
|
|
||||||
const formattedSchemaFieldsData: BasicEntityInfo[] = useMemo(
|
const formattedSchemaFieldsData: BasicEntityInfo[] = useMemo(
|
||||||
|
@ -27,31 +27,55 @@ jest.mock('../SummaryList/SummaryList.component', () =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
jest.mock('rest/topicsAPI', () => ({
|
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(() => <p>SummaryTagDescription</p>)
|
||||||
|
);
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component',
|
||||||
|
() => jest.fn().mockImplementation(({ children }) => <>{children}</>)
|
||||||
|
);
|
||||||
|
|
||||||
describe('TopicSummary component tests', () => {
|
describe('TopicSummary component tests', () => {
|
||||||
it('Component should render properly', async () => {
|
it('Component should render properly', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
||||||
});
|
});
|
||||||
|
|
||||||
const partitionsLabel = screen.getByTestId('Partitions-label');
|
const partitionsLabel = await screen.findByTestId('Partitions-label');
|
||||||
const replicationFactorLabel = screen.getByTestId(
|
const replicationFactorLabel = await screen.findByTestId(
|
||||||
'Replication Factor-label'
|
'Replication Factor-label'
|
||||||
);
|
);
|
||||||
const retentionSizeLabel = screen.getByTestId('Retention Size-label');
|
const retentionSizeLabel = await screen.findByTestId(
|
||||||
const cleanUpPoliciesLabel = screen.getByTestId('CleanUp Policies-label');
|
'Retention Size-label'
|
||||||
const maxMessageSizeLabel = screen.getByTestId('Max Message Size-label');
|
);
|
||||||
const partitionsValue = screen.getByTestId('Partitions-value');
|
const cleanUpPoliciesLabel = await screen.findByTestId(
|
||||||
const replicationFactorValue = screen.getByTestId(
|
'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'
|
'Replication Factor-value'
|
||||||
);
|
);
|
||||||
const retentionSizeValue = screen.getByTestId('Retention Size-value');
|
const retentionSizeValue = await screen.findByTestId(
|
||||||
const cleanUpPoliciesValue = screen.getByTestId('CleanUp Policies-value');
|
'Retention Size-value'
|
||||||
const maxMessageSizeValue = screen.getByTestId('Max Message Size-value');
|
);
|
||||||
const schemaHeader = screen.getByTestId('schema-header');
|
const cleanUpPoliciesValue = await screen.findByTestId(
|
||||||
const summaryList = screen.getByTestId('SummaryList');
|
'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(partitionsLabel).toBeInTheDocument();
|
||||||
expect(replicationFactorLabel).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 () => {
|
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 () => {
|
await act(async () => {
|
||||||
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
||||||
@ -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 () => {
|
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 () => {
|
await act(async () => {
|
||||||
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
render(<TopicSummary entityDetails={mockTopicEntityDetails} />);
|
||||||
});
|
});
|
||||||
|
@ -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 (
|
|
||||||
<PageLayoutV1
|
|
||||||
className="tw-h-full tw-px-6"
|
|
||||||
leftPanel={<GlobalSettingLeftPanel />}
|
|
||||||
pageTitle={t('label.setting-plural')}>
|
|
||||||
<GlobalSettingRouter />
|
|
||||||
</PageLayoutV1>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GlobalSetting;
|
|
@ -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(
|
|
||||||
<MemoryRouter initialEntries={[url]}>
|
|
||||||
<Route path="/settings/:settingCategory/:tab">
|
|
||||||
<GlobalSettingLeftPanel />
|
|
||||||
</Route>
|
|
||||||
</MemoryRouter>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(screen.getByText('label.service-plural')).toBeInTheDocument();
|
|
||||||
expect(screen.getByText('label.storage-plural')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should change the location path on user click', () => {
|
|
||||||
render(
|
|
||||||
<MemoryRouter initialEntries={[url]}>
|
|
||||||
<Route path="/settings/:settingCategory/:tab">
|
|
||||||
<GlobalSettingLeftPanel />
|
|
||||||
</Route>
|
|
||||||
</MemoryRouter>
|
|
||||||
);
|
|
||||||
|
|
||||||
userEvent.click(screen.getByText('label.team-plural'));
|
|
||||||
|
|
||||||
waitForElement(() =>
|
|
||||||
expect(window.location.pathname).toEqual('/teams/organizations')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -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 ? (
|
|
||||||
<LeftPanelCard id="settings">
|
|
||||||
<Menu
|
|
||||||
className="custom-menu"
|
|
||||||
data-testid="global-setting-left-panel"
|
|
||||||
items={menuItems}
|
|
||||||
mode="inline"
|
|
||||||
selectedKeys={[`${settingCategory}.${tab}`]}
|
|
||||||
onClick={onClick}
|
|
||||||
/>
|
|
||||||
</LeftPanelCard>
|
|
||||||
) : (
|
|
||||||
<ErrorPlaceHolder>
|
|
||||||
<p>{t('message.no-data-available')}</p>
|
|
||||||
</ErrorPlaceHolder>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GlobalSettingLeftPanel;
|
|
@ -11,11 +11,15 @@
|
|||||||
* limitations under the License.
|
* 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 React from 'react';
|
||||||
import { Redirect, Route, RouteProps } from 'react-router-dom';
|
import { Redirect, Route, RouteProps } from 'react-router-dom';
|
||||||
import { ROUTES } from '../../constants/constants';
|
import { ROUTES } from '../../constants/constants';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import { useAuthContext } from '../authentication/auth-provider/AuthProvider';
|
|
||||||
|
|
||||||
interface AdminProtectedRouteProps extends RouteProps {
|
interface AdminProtectedRouteProps extends RouteProps {
|
||||||
hasPermission: boolean;
|
hasPermission: boolean;
|
||||||
@ -23,12 +27,17 @@ interface AdminProtectedRouteProps extends RouteProps {
|
|||||||
|
|
||||||
const AdminProtectedRoute = (routeProps: AdminProtectedRouteProps) => {
|
const AdminProtectedRoute = (routeProps: AdminProtectedRouteProps) => {
|
||||||
const { isAdminUser } = useAuth();
|
const { isAdminUser } = useAuth();
|
||||||
const { isAuthDisabled, isAuthenticated } = useAuthContext();
|
|
||||||
|
|
||||||
if (isAuthDisabled || isAdminUser || routeProps.hasPermission) {
|
if (isAdminUser || routeProps.hasPermission) {
|
||||||
return <Route {...routeProps} />;
|
return <Route {...routeProps} />;
|
||||||
} else if (isAuthenticated) {
|
} else if (!routeProps.hasPermission) {
|
||||||
return <Redirect to={ROUTES.NOT_FOUND} />;
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return <Redirect to={ROUTES.SIGNIN} />;
|
return <Redirect to={ROUTES.SIGNIN} />;
|
||||||
}
|
}
|
||||||
|
@ -245,6 +245,10 @@ const AddQueryPage = withSuspenseFallback(
|
|||||||
React.lazy(() => import('pages/AddQueryPage/AddQueryPage.component'))
|
React.lazy(() => import('pages/AddQueryPage/AddQueryPage.component'))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const PageNotFound = withSuspenseFallback(
|
||||||
|
React.lazy(() => import('pages/page-not-found'))
|
||||||
|
);
|
||||||
|
|
||||||
const AuthenticatedAppRouter: FunctionComponent = () => {
|
const AuthenticatedAppRouter: FunctionComponent = () => {
|
||||||
const { permissions } = usePermissionProvider();
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
@ -603,6 +607,7 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
|||||||
<Route exact path={ROUTES.HOME}>
|
<Route exact path={ROUTES.HOME}>
|
||||||
<Redirect to={ROUTES.MY_DATA} />
|
<Redirect to={ROUTES.MY_DATA} />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route exact component={PageNotFound} path={ROUTES.NOT_FOUND} />
|
||||||
<Redirect to={ROUTES.NOT_FOUND} />
|
<Redirect to={ROUTES.NOT_FOUND} />
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
GlobalSettingOptions,
|
GlobalSettingOptions,
|
||||||
GlobalSettingsMenuCategory,
|
GlobalSettingsMenuCategory,
|
||||||
} from '../../constants/GlobalSettings.constants';
|
} from '../../constants/GlobalSettings.constants';
|
||||||
|
|
||||||
import { TeamType } from '../../generated/entity/teams/team';
|
import { TeamType } from '../../generated/entity/teams/team';
|
||||||
import { userPermissions } from '../../utils/PermissionsUtils';
|
import { userPermissions } from '../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
@ -27,7 +26,6 @@ import {
|
|||||||
} from '../../utils/RouterUtils';
|
} from '../../utils/RouterUtils';
|
||||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||||
|
|
||||||
import AdminProtectedRoute from './AdminProtectedRoute';
|
import AdminProtectedRoute from './AdminProtectedRoute';
|
||||||
import withSuspenseFallback from './withSuspenseFallback';
|
import withSuspenseFallback from './withSuspenseFallback';
|
||||||
|
|
||||||
@ -117,9 +115,13 @@ const GlobalSettingRouter = () => {
|
|||||||
<Route exact path={getSettingPath()}>
|
<Route exact path={getSettingPath()}>
|
||||||
<Redirect to={getTeamsWithFqnPath(TeamType.Organization)} />
|
<Redirect to={getTeamsWithFqnPath(TeamType.Organization)} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={TeamsPage}
|
component={TeamsPage}
|
||||||
|
hasPermission={userPermissions.hasViewPermissions(
|
||||||
|
ResourceEntity.TEAM,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={getSettingPath(
|
path={getSettingPath(
|
||||||
GlobalSettingsMenuCategory.MEMBERS,
|
GlobalSettingsMenuCategory.MEMBERS,
|
||||||
GlobalSettingOptions.TEAMS,
|
GlobalSettingOptions.TEAMS,
|
||||||
|
@ -17,4 +17,8 @@ export const NO_PERMISSION_FOR_ACTION = t('message.no-permission-for-action');
|
|||||||
|
|
||||||
export const NO_PERMISSION_TO_VIEW = t('message.no-permission-to-view');
|
export const NO_PERMISSION_TO_VIEW = t('message.no-permission-to-view');
|
||||||
|
|
||||||
|
export const REACH_OUT_TO_ADMIN_FOR_ACCESS = t(
|
||||||
|
'message.reach-out-to-admin-for-access'
|
||||||
|
);
|
||||||
|
|
||||||
export const ADMIN_ONLY_ACTION = t('message.admin-only-action');
|
export const ADMIN_ONLY_ACTION = t('message.admin-only-action');
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
||||||
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
||||||
"query-used-by-other-tables": "Query used by other tables",
|
"query-used-by-other-tables": "Query used by other tables",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reacted with {{type}} emoji",
|
"reacted-with-emoji": "reacted with {{type}} emoji",
|
||||||
"redirect-message": "Please wait while you are being redirected.",
|
"redirect-message": "Please wait while you are being redirected.",
|
||||||
"redirecting-to-home-page": "Redirecting to the home page",
|
"redirecting-to-home-page": "Redirecting to the home page",
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Las consultas que devuelvan 1 o más filas darán como resultado un fallo en el test.",
|
"queries-result-test": "Las consultas que devuelvan 1 o más filas darán como resultado un fallo en el test.",
|
||||||
"query-log-duration-message": "Configuración para ajustar cuánto tiempo queremos retroceder en los registros de consultas para procesar datos de uso.",
|
"query-log-duration-message": "Configuración para ajustar cuánto tiempo queremos retroceder en los registros de consultas para procesar datos de uso.",
|
||||||
"query-used-by-other-tables": "Consulta utilizada por otras tablas",
|
"query-used-by-other-tables": "Consulta utilizada por otras tablas",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reaccionó con el emoji {{type}}",
|
"reacted-with-emoji": "reaccionó con el emoji {{type}}",
|
||||||
"redirect-message": "Por favor espera mientras eres redirigido.",
|
"redirect-message": "Por favor espera mientras eres redirigido.",
|
||||||
"redirecting-to-home-page": "Redirigiendo a la página principal",
|
"redirecting-to-home-page": "Redirigiendo a la página principal",
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
||||||
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
||||||
"query-used-by-other-tables": "Query used by other tables",
|
"query-used-by-other-tables": "Query used by other tables",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reacted with {{type}} emoji",
|
"reacted-with-emoji": "reacted with {{type}} emoji",
|
||||||
"redirect-message": "Please wait while you are being redirected.",
|
"redirect-message": "Please wait while you are being redirected.",
|
||||||
"redirecting-to-home-page": "Redirecting to the home page",
|
"redirecting-to-home-page": "Redirecting to the home page",
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
||||||
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
||||||
"query-used-by-other-tables": "Query used by other tables",
|
"query-used-by-other-tables": "Query used by other tables",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reacted with {{type}} emoji",
|
"reacted-with-emoji": "reacted with {{type}} emoji",
|
||||||
"redirect-message": "Please wait while you are being redirected.",
|
"redirect-message": "Please wait while you are being redirected.",
|
||||||
"redirecting-to-home-page": "ホームに戻っています",
|
"redirecting-to-home-page": "ホームに戻っています",
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Consultas que retornam 1 ou mais linhas resultarão na falha do teste.",
|
"queries-result-test": "Consultas que retornam 1 ou mais linhas resultarão na falha do teste.",
|
||||||
"query-log-duration-message": "Configuração para ajustar até onde queremos olhar nos logs de consulta para processar os dados de uso.",
|
"query-log-duration-message": "Configuração para ajustar até onde queremos olhar nos logs de consulta para processar os dados de uso.",
|
||||||
"query-used-by-other-tables": "Consulta usada por outras tabelas",
|
"query-used-by-other-tables": "Consulta usada por outras tabelas",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reagiu com um emoji {{type}}",
|
"reacted-with-emoji": "reagiu com um emoji {{type}}",
|
||||||
"redirect-message": "Please wait while you are being redirected.",
|
"redirect-message": "Please wait while you are being redirected.",
|
||||||
"redirecting-to-home-page": "Redirecionando para a página inicial",
|
"redirecting-to-home-page": "Redirecionando para a página inicial",
|
||||||
|
@ -1208,6 +1208,7 @@
|
|||||||
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
"queries-result-test": "Queries returning 1 or more rows will result in the test failing.",
|
||||||
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
"query-log-duration-message": "Configuration to tune how far we want to look back in query logs to process usage data.",
|
||||||
"query-used-by-other-tables": "Query used by other tables",
|
"query-used-by-other-tables": "Query used by other tables",
|
||||||
|
"reach-out-to-admin-for-access": "Please reach out to your Admin to get access.",
|
||||||
"reacted-with-emoji": "reacted with {{type}} emoji",
|
"reacted-with-emoji": "reacted with {{type}} emoji",
|
||||||
"redirect-message": "Please wait while you are being redirected.",
|
"redirect-message": "Please wait while you are being redirected.",
|
||||||
"redirecting-to-home-page": "Redirecting to the home page",
|
"redirecting-to-home-page": "Redirecting to the home page",
|
||||||
|
@ -33,7 +33,10 @@ import {
|
|||||||
updateBotDetail,
|
updateBotDetail,
|
||||||
updateUserDetail,
|
updateUserDetail,
|
||||||
} from 'rest/userAPI';
|
} from 'rest/userAPI';
|
||||||
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
import {
|
||||||
|
NO_PERMISSION_TO_VIEW,
|
||||||
|
REACH_OUT_TO_ADMIN_FOR_ACCESS,
|
||||||
|
} from '../../constants/HelperTextUtil';
|
||||||
import { Bot } from '../../generated/entity/bot';
|
import { Bot } from '../../generated/entity/bot';
|
||||||
import { User } from '../../generated/entity/teams/user';
|
import { User } from '../../generated/entity/teams/user';
|
||||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
@ -181,7 +184,11 @@ const BotDetailsPage = () => {
|
|||||||
{botPermission.ViewAll || botPermission.ViewBasic ? (
|
{botPermission.ViewAll || botPermission.ViewBasic ? (
|
||||||
getBotsDetailComponent()
|
getBotsDetailComponent()
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -37,7 +37,10 @@ import {
|
|||||||
} from 'components/PermissionProvider/PermissionProvider.interface';
|
} from 'components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||||
import { getServiceDetailsPath, getVersionPath } from 'constants/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 { EntityInfo, EntityType } from 'enums/entity.enum';
|
||||||
import { ServiceCategory } from 'enums/service.enum';
|
import { ServiceCategory } from 'enums/service.enum';
|
||||||
import { OwnerType } from 'enums/user.enum';
|
import { OwnerType } from 'enums/user.enum';
|
||||||
@ -620,7 +623,13 @@ const ContainerPage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hasViewPermission && !isLoading) {
|
if (!hasViewPermission && !isLoading) {
|
||||||
return <ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>;
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -39,6 +39,7 @@ import { CUSTOM_PROPERTIES_DOCS } from '../../constants/docs.constants';
|
|||||||
import {
|
import {
|
||||||
NO_PERMISSION_FOR_ACTION,
|
NO_PERMISSION_FOR_ACTION,
|
||||||
NO_PERMISSION_TO_VIEW,
|
NO_PERMISSION_TO_VIEW,
|
||||||
|
REACH_OUT_TO_ADMIN_FOR_ACCESS,
|
||||||
} from '../../constants/HelperTextUtil';
|
} from '../../constants/HelperTextUtil';
|
||||||
import { PAGE_HEADERS } from '../../constants/PageHeaders.constant';
|
import { PAGE_HEADERS } from '../../constants/PageHeaders.constant';
|
||||||
import { Type } from '../../generated/entity/type';
|
import { Type } from '../../generated/entity/type';
|
||||||
@ -297,7 +298,9 @@ const CustomEntityDetailV1 = () => {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
<p>{NO_PERMISSION_TO_VIEW}</p>
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -37,7 +37,10 @@ import {
|
|||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} 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 { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -540,7 +543,11 @@ const DashboardDetailsPage = () => {
|
|||||||
onExtensionUpdate={handleExtensionUpdate}
|
onExtensionUpdate={handleExtensionUpdate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -21,7 +21,10 @@ import {
|
|||||||
OperationPermission,
|
OperationPermission,
|
||||||
ResourceEntity,
|
ResourceEntity,
|
||||||
} from 'components/PermissionProvider/PermissionProvider.interface';
|
} 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 { EntityType } from 'enums/entity.enum';
|
||||||
import { FeedFilter } from 'enums/mydata.enum';
|
import { FeedFilter } from 'enums/mydata.enum';
|
||||||
import { compare, Operation } from 'fast-json-patch';
|
import { compare, Operation } from 'fast-json-patch';
|
||||||
@ -469,7 +472,13 @@ const DataModelsPage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hasViewPermission && !isLoading) {
|
if (!hasViewPermission && !isLoading) {
|
||||||
return <ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>;
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -50,7 +50,10 @@ import {
|
|||||||
getVersionPath,
|
getVersionPath,
|
||||||
pagingObject,
|
pagingObject,
|
||||||
} from '../../constants/constants';
|
} 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 { EntityType, FqnPart, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -620,7 +623,11 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
|||||||
versionHandler={versionHandler}
|
versionHandler={versionHandler}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -11,14 +11,111 @@
|
|||||||
* limitations under the License.
|
* 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 PageContainerV1 from 'components/containers/PageContainerV1';
|
||||||
import GlobalSetting from 'components/GlobalSetting/GlobalSetting';
|
import PageLayoutV1 from 'components/containers/PageLayoutV1';
|
||||||
import React from 'react';
|
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 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 ? (
|
||||||
|
<LeftPanelCard id="settings">
|
||||||
|
<Menu
|
||||||
|
className="custom-menu"
|
||||||
|
data-testid="global-setting-left-panel"
|
||||||
|
items={menuItems}
|
||||||
|
mode="inline"
|
||||||
|
selectedKeys={[`${settingCategory}.${tab}`]}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
</LeftPanelCard>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainerV1>
|
<PageContainerV1>
|
||||||
<GlobalSetting />
|
<PageLayoutV1
|
||||||
|
className="tw-h-full tw-px-6"
|
||||||
|
leftPanel={leftPanel}
|
||||||
|
pageTitle={t('label.setting-plural')}>
|
||||||
|
<GlobalSettingRouter />
|
||||||
|
</PageLayoutV1>
|
||||||
</PageContainerV1>
|
</PageContainerV1>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,9 @@ import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider
|
|||||||
import { compare, Operation } from 'fast-json-patch';
|
import { compare, Operation } from 'fast-json-patch';
|
||||||
import { isEmpty, isNil, isUndefined, omitBy } from 'lodash';
|
import { isEmpty, isNil, isUndefined, omitBy } from 'lodash';
|
||||||
import { observer } from 'mobx-react';
|
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 { getAllFeeds, postFeedById, postThread } from 'rest/feedsAPI';
|
||||||
import {
|
import {
|
||||||
addFollower,
|
addFollower,
|
||||||
@ -27,13 +30,12 @@ import {
|
|||||||
patchMlModelDetails,
|
patchMlModelDetails,
|
||||||
removeFollower,
|
removeFollower,
|
||||||
} from 'rest/mlModelAPI';
|
} 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 AppState from '../../AppState';
|
||||||
import { getMlModelPath, getVersionPath } from '../../constants/constants';
|
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 { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { CreateThread } from '../../generated/api/feed/createThread';
|
import { CreateThread } from '../../generated/api/feed/createThread';
|
||||||
@ -450,7 +452,11 @@ const MlModelPage = () => {
|
|||||||
{mlModelPermissions.ViewAll || mlModelPermissions.ViewBasic ? (
|
{mlModelPermissions.ViewAll || mlModelPermissions.ViewBasic ? (
|
||||||
getMlModelDetail()
|
getMlModelDetail()
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -34,7 +34,10 @@ import {
|
|||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} 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 { EntityType } from '../../enums/entity.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
import { Pipeline } from '../../generated/entity/data/pipeline';
|
import { Pipeline } from '../../generated/entity/data/pipeline';
|
||||||
@ -310,7 +313,11 @@ const PipelineDetailsPage = () => {
|
|||||||
onExtensionUpdate={handleExtensionUpdate}
|
onExtensionUpdate={handleExtensionUpdate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -31,7 +31,10 @@ import {
|
|||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getTableTabPath,
|
getTableTabPath,
|
||||||
} from 'constants/constants';
|
} 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 { FqnPart } from 'enums/entity.enum';
|
||||||
import { ServiceCategory } from 'enums/service.enum';
|
import { ServiceCategory } from 'enums/service.enum';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
@ -214,7 +217,13 @@ const QueryPage = () => {
|
|||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
if (!isViewAllowed) {
|
if (!isViewAllowed) {
|
||||||
return <ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>;
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUndefined(query)) {
|
if (isUndefined(query)) {
|
||||||
|
@ -47,7 +47,10 @@ import {
|
|||||||
pagingObject,
|
pagingObject,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
} from '../../constants/constants';
|
} 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 { ACTION_TYPE } from '../../enums/common.enum';
|
||||||
import { OwnerType } from '../../enums/user.enum';
|
import { OwnerType } from '../../enums/user.enum';
|
||||||
import { TestCase } from '../../generated/tests/testCase';
|
import { TestCase } from '../../generated/tests/testCase';
|
||||||
@ -363,7 +366,11 @@ const TestSuiteDetailsPage = () => {
|
|||||||
</Row>
|
</Row>
|
||||||
</PageContainerV1>
|
</PageContainerV1>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,10 @@ import {
|
|||||||
getTopicDetailsPath,
|
getTopicDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} 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 { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -466,7 +469,11 @@ const TopicDetailsPage: FunctionComponent = () => {
|
|||||||
onExtensionUpdate={handleExtensionUpdate}
|
onExtensionUpdate={handleExtensionUpdate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -23,7 +23,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { getServices } from 'rest/serviceAPI';
|
import { getServices } from 'rest/serviceAPI';
|
||||||
import { pagingObject, SERVICE_VIEW_CAP } from '../../constants/constants';
|
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 {
|
import {
|
||||||
OPEN_METADATA,
|
OPEN_METADATA,
|
||||||
SERVICE_CATEGORY,
|
SERVICE_CATEGORY,
|
||||||
@ -119,7 +122,9 @@ const ServicesPage = () => {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
<p>{NO_PERMISSION_TO_VIEW}</p>
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -42,7 +42,10 @@ import {
|
|||||||
PAGE_SIZE_MEDIUM,
|
PAGE_SIZE_MEDIUM,
|
||||||
pagingObject,
|
pagingObject,
|
||||||
} from '../../constants/constants';
|
} 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 { myDataSearchIndex } from '../../constants/Mydata.constants';
|
||||||
import { SearchIndex } from '../../enums/search.enum';
|
import { SearchIndex } from '../../enums/search.enum';
|
||||||
import { CreateTeam, TeamType } from '../../generated/api/teams/createTeam';
|
import { CreateTeam, TeamType } from '../../generated/api/teams/createTeam';
|
||||||
@ -603,7 +606,11 @@ const TeamsPage = () => {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
|
<p className="text-center">
|
||||||
|
{NO_PERMISSION_TO_VIEW} <br /> {REACH_OUT_TO_ADMIN_FOR_ACCESS}
|
||||||
|
</p>
|
||||||
|
</ErrorPlaceHolder>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import { ClientErrors } from 'enums/axios.enum';
|
||||||
import { isEmpty, isString } from 'lodash';
|
import { isEmpty, isString } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@ -60,7 +61,8 @@ export const showErrorToast = (
|
|||||||
// except for principal domain mismatch errors
|
// except for principal domain mismatch errors
|
||||||
if (
|
if (
|
||||||
error &&
|
error &&
|
||||||
error.response?.status === 401 &&
|
(error.response?.status === ClientErrors.UNAUTHORIZED ||
|
||||||
|
error.response?.status === ClientErrors.FORBIDDEN) &&
|
||||||
!errorMessage.includes('principal domain')
|
!errorMessage.includes('principal domain')
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user