mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 18:36:08 +00:00
Update MyData and Explore with new roles and policy (#7018)
* Update MyData and Explore with new roles and policy * Add placeholder for explore side panel * Fix unit tests * Remove Permission API call from AuthProvider * Fix loading issue * Update global settings left panel * Remove feed check from mydata page * Remove permission check from explore page * Minor change * Add resource permission method to provider * Change global settings left panel * Remove unwanted codes * Add comments * Addressing review comments
This commit is contained in:
parent
a6a4e08af1
commit
106f99f4c8
@ -33,10 +33,7 @@ import React, {
|
|||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import appState from '../../AppState';
|
import appState from '../../AppState';
|
||||||
import axiosClient from '../../axiosAPIs';
|
import axiosClient from '../../axiosAPIs';
|
||||||
import {
|
import { fetchAuthenticationConfig } from '../../axiosAPIs/miscAPI';
|
||||||
fetchAuthenticationConfig,
|
|
||||||
getLoggedInUserPermissions,
|
|
||||||
} from '../../axiosAPIs/miscAPI';
|
|
||||||
import {
|
import {
|
||||||
getLoggedInUser,
|
getLoggedInUser,
|
||||||
getUserByName,
|
getUserByName,
|
||||||
@ -166,32 +163,14 @@ export const AuthProvider = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserPermissions = () => {
|
|
||||||
setLoading(true);
|
|
||||||
getLoggedInUserPermissions()
|
|
||||||
.then((res) => {
|
|
||||||
appState.updateUserPermissions(res.data);
|
|
||||||
})
|
|
||||||
.catch((err: AxiosError) => {
|
|
||||||
showErrorToast(
|
|
||||||
err,
|
|
||||||
jsonData['api-error-messages']['fetch-user-permission-error']
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.finally(() => setLoading(false));
|
|
||||||
};
|
|
||||||
|
|
||||||
const getLoggedInUserDetails = () => {
|
const getLoggedInUserDetails = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
getLoggedInUser(userAPIQueryFields)
|
getLoggedInUser(userAPIQueryFields)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
getUserPermissions();
|
|
||||||
appState.updateUserDetails(res);
|
appState.updateUserDetails(res);
|
||||||
fetchAllUsers();
|
|
||||||
} else {
|
} else {
|
||||||
resetUserDetails();
|
resetUserDetails();
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
@ -204,6 +183,9 @@ export const AuthProvider = ({
|
|||||||
jsonData['api-error-messages']['fetch-logged-in-user-error']
|
jsonData['api-error-messages']['fetch-logged-in-user-error']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -368,8 +350,6 @@ export const AuthProvider = ({
|
|||||||
} else {
|
} else {
|
||||||
appState.updateUserDetails(res);
|
appState.updateUserDetails(res);
|
||||||
}
|
}
|
||||||
getUserPermissions();
|
|
||||||
fetchAllUsers();
|
|
||||||
handledVerifiedUser();
|
handledVerifiedUser();
|
||||||
// Start expiry timer on successful login
|
// Start expiry timer on successful login
|
||||||
startTokenExpiryTimer();
|
startTokenExpiryTimer();
|
||||||
@ -439,8 +419,6 @@ export const AuthProvider = ({
|
|||||||
storeRedirectPath();
|
storeRedirectPath();
|
||||||
showErrorToast(error);
|
showErrorToast(error);
|
||||||
resetUserDetails(true);
|
resetUserDetails(true);
|
||||||
} else if (status === ClientErrors.FORBIDDEN) {
|
|
||||||
showErrorToast(jsonData['api-error-messages']['forbidden-error']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ import { WILD_CARD_CHAR } from '../constants/char.constants';
|
|||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
import { AirflowConfiguration } from '../generated/configuration/airflowConfiguration';
|
import { AirflowConfiguration } from '../generated/configuration/airflowConfiguration';
|
||||||
import { AuthenticationConfiguration } from '../generated/configuration/authenticationConfiguration';
|
import { AuthenticationConfiguration } from '../generated/configuration/authenticationConfiguration';
|
||||||
import { ResourcePermission } from '../generated/entity/policies/accessControl/resourcePermission';
|
|
||||||
import { EntitiesCount } from '../generated/entity/utils/entitiesCount';
|
import { EntitiesCount } from '../generated/entity/utils/entitiesCount';
|
||||||
import { Paging } from '../generated/type/paging';
|
import { Paging } from '../generated/type/paging';
|
||||||
import { getURLWithQueryFields } from '../utils/APIUtils';
|
import { getURLWithQueryFields } from '../utils/APIUtils';
|
||||||
@ -121,18 +120,6 @@ export const deleteLineageEdge: Function = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLoggedInUserPermissions = async () => {
|
|
||||||
const params = {
|
|
||||||
limit: 100,
|
|
||||||
};
|
|
||||||
const response = await APIClient.get<{
|
|
||||||
data: ResourcePermission[];
|
|
||||||
paging: Paging;
|
|
||||||
}>('/permissions', { params });
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getInitialEntity = (
|
export const getInitialEntity = (
|
||||||
index: SearchIndex,
|
index: SearchIndex,
|
||||||
params = {} as AxiosRequestConfig
|
params = {} as AxiosRequestConfig
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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 { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import { ResourcePermission } from '../generated/entity/policies/accessControl/resourcePermission';
|
||||||
|
import { Paging } from '../generated/type/paging';
|
||||||
|
import APIClient from './index';
|
||||||
|
|
||||||
|
export const getLoggedInUserPermissions = async () => {
|
||||||
|
const params = {
|
||||||
|
limit: 100,
|
||||||
|
};
|
||||||
|
const response = await APIClient.get<{
|
||||||
|
data: ResourcePermission[];
|
||||||
|
paging: Paging;
|
||||||
|
}>('/permissions', { params });
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getEntityPermissionById = async (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityId: string
|
||||||
|
) => {
|
||||||
|
const response = await APIClient.get<ResourcePermission>(
|
||||||
|
`/permissions/${resource}/${entityId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getResourcePermission = async (resource: ResourceEntity) => {
|
||||||
|
const response = await APIClient.get<ResourcePermission>(
|
||||||
|
`/permissions/${resource}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
@ -13,11 +13,9 @@
|
|||||||
|
|
||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
|
||||||
import { CreatePolicy } from '../generated/api/policies/createPolicy';
|
import { CreatePolicy } from '../generated/api/policies/createPolicy';
|
||||||
import { CreateRole } from '../generated/api/teams/createRole';
|
import { CreateRole } from '../generated/api/teams/createRole';
|
||||||
import { ResourceDescriptor } from '../generated/entity/policies/accessControl/resourceDescriptor';
|
import { ResourceDescriptor } from '../generated/entity/policies/accessControl/resourceDescriptor';
|
||||||
import { ResourcePermission } from '../generated/entity/policies/accessControl/resourcePermission';
|
|
||||||
import { Policy } from '../generated/entity/policies/policy';
|
import { Policy } from '../generated/entity/policies/policy';
|
||||||
import { Role } from '../generated/entity/teams/role';
|
import { Role } from '../generated/entity/teams/role';
|
||||||
import { Function } from '../generated/type/function';
|
import { Function } from '../generated/type/function';
|
||||||
@ -156,14 +154,3 @@ export const validateRuleCondition = async (condition: string) => {
|
|||||||
*/
|
*/
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getEntityPermissionById = async (
|
|
||||||
resource: ResourceEntity,
|
|
||||||
entityId: string
|
|
||||||
) => {
|
|
||||||
const response = await APIClient.get<ResourcePermission>(
|
|
||||||
`/permissions/${resource}/${entityId}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
|
||||||
|
@ -15,13 +15,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||||||
import { Card } from 'antd';
|
import { Card } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isNil } from 'lodash';
|
import { isEmpty, isNil } from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, {
|
import React, {
|
||||||
FC,
|
FC,
|
||||||
Fragment,
|
Fragment,
|
||||||
HTMLAttributes,
|
HTMLAttributes,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import Select, { SingleValue } from 'react-select';
|
import Select, { SingleValue } from 'react-select';
|
||||||
@ -77,21 +78,32 @@ const BotDetails: FC<BotsDetailProp> = ({
|
|||||||
const [generateToken, setGenerateToken] = useState<boolean>(false);
|
const [generateToken, setGenerateToken] = useState<boolean>(false);
|
||||||
const [selectedExpiry, setSelectedExpiry] = useState('7');
|
const [selectedExpiry, setSelectedExpiry] = useState('7');
|
||||||
|
|
||||||
const editAllPermission = checkPermission(
|
const editAllPermission = useMemo(
|
||||||
Operation.EditAll,
|
() =>
|
||||||
ResourceEntity.BOT,
|
!isEmpty(permissions) &&
|
||||||
permissions
|
checkPermission(Operation.EditAll, ResourceEntity.BOT, permissions),
|
||||||
|
[permissions]
|
||||||
);
|
);
|
||||||
const displayNamePermission = checkPermission(
|
const displayNamePermission = useMemo(
|
||||||
Operation.EditDisplayName,
|
() =>
|
||||||
ResourceEntity.BOT,
|
!isEmpty(permissions) &&
|
||||||
permissions
|
checkPermission(
|
||||||
|
Operation.EditDisplayName,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
[permissions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const descriptionPermission = checkPermission(
|
const descriptionPermission = useMemo(
|
||||||
Operation.EditDescription,
|
() =>
|
||||||
ResourceEntity.BOT,
|
!isEmpty(permissions) &&
|
||||||
permissions
|
checkPermission(
|
||||||
|
Operation.EditDescription,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
[permissions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getJWTTokenExpiryOptions = () => {
|
const getJWTTokenExpiryOptions = () => {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
import { Button, Col, Row, Space, Table, Tooltip } from 'antd';
|
import { Button, Col, Row, Space, Table, Tooltip } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { getBots } from '../../axiosAPIs/botsAPI';
|
import { getBots } from '../../axiosAPIs/botsAPI';
|
||||||
@ -46,10 +47,11 @@ const BotListV1 = ({ showDeleted }: BotListV1Props) => {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
||||||
|
|
||||||
const deletePermission = checkPermission(
|
const deletePermission = useMemo(
|
||||||
Operation.Delete,
|
() =>
|
||||||
ResourceEntity.BOT,
|
!isEmpty(permissions) &&
|
||||||
permissions
|
checkPermission(Operation.Delete, ResourceEntity.BOT, permissions),
|
||||||
|
[permissions]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,12 +89,8 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
fetchData,
|
fetchData,
|
||||||
showDeleted,
|
showDeleted,
|
||||||
onShowDeleted,
|
onShowDeleted,
|
||||||
updateTableCount,
|
|
||||||
updateTopicCount,
|
|
||||||
updateDashboardCount,
|
|
||||||
updatePipelineCount,
|
|
||||||
isFilterSelected,
|
isFilterSelected,
|
||||||
updateMlModelCount,
|
handleTabCounts,
|
||||||
}: ExploreProps) => {
|
}: ExploreProps) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@ -273,23 +269,23 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
const setCount = (count = 0, index = searchIndex) => {
|
const setCount = (count = 0, index = searchIndex) => {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case SearchIndex.TABLE:
|
case SearchIndex.TABLE:
|
||||||
updateTableCount(count);
|
handleTabCounts({ table: count });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SearchIndex.DASHBOARD:
|
case SearchIndex.DASHBOARD:
|
||||||
updateDashboardCount(count);
|
handleTabCounts({ dashboard: count });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SearchIndex.TOPIC:
|
case SearchIndex.TOPIC:
|
||||||
updateTopicCount(count);
|
handleTabCounts({ topic: count });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SearchIndex.PIPELINE:
|
case SearchIndex.PIPELINE:
|
||||||
updatePipelineCount(count);
|
handleTabCounts({ pipeline: count });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SearchIndex.MLMODEL:
|
case SearchIndex.MLMODEL:
|
||||||
updateMlModelCount(count);
|
handleTabCounts({ mlmodel: count });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -441,7 +437,7 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
case SearchIndex.PIPELINE:
|
case SearchIndex.PIPELINE:
|
||||||
return getCountBadge(tabCounts.pipeline, className, isActive);
|
return getCountBadge(tabCounts.pipeline, className, isActive);
|
||||||
case SearchIndex.MLMODEL:
|
case SearchIndex.MLMODEL:
|
||||||
return getCountBadge(tabCounts.mlModel, className, isActive);
|
return getCountBadge(tabCounts.mlmodel, className, isActive);
|
||||||
default:
|
default:
|
||||||
return getCountBadge();
|
return getCountBadge();
|
||||||
}
|
}
|
||||||
@ -469,18 +465,6 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
'tw-flex tw-flex-row tw-justify-between tw-gh-tabs-container'
|
'tw-flex tw-flex-row tw-justify-between tw-gh-tabs-container'
|
||||||
)}>
|
)}>
|
||||||
<div className="tw-flex">
|
<div className="tw-flex">
|
||||||
{/* <div className="tw-w-64 tw-mr-5 tw-flex-shrink-0">
|
|
||||||
<Button
|
|
||||||
className={classNames('tw-underline tw-mt-5', {
|
|
||||||
'tw-invisible': !getFilterCount(filters),
|
|
||||||
})}
|
|
||||||
size="custom"
|
|
||||||
theme="primary"
|
|
||||||
variant="link"
|
|
||||||
onClick={() => resetFilters(true)}>
|
|
||||||
Clear All
|
|
||||||
</Button>
|
|
||||||
</div> */}
|
|
||||||
<div>
|
<div>
|
||||||
{tabsInfo.map((tabDetail, index) => (
|
{tabsInfo.map((tabDetail, index) => (
|
||||||
<button
|
<button
|
||||||
|
@ -95,6 +95,7 @@ describe('Test Explore component', () => {
|
|||||||
handleFilterChange={mockFunction}
|
handleFilterChange={mockFunction}
|
||||||
handlePathChange={mockFunction}
|
handlePathChange={mockFunction}
|
||||||
handleSearchText={mockFunction}
|
handleSearchText={mockFunction}
|
||||||
|
handleTabCounts={mockFunction}
|
||||||
searchQuery=""
|
searchQuery=""
|
||||||
searchResult={mockSearchResult}
|
searchResult={mockSearchResult}
|
||||||
searchText=""
|
searchText=""
|
||||||
@ -106,15 +107,8 @@ describe('Test Explore component', () => {
|
|||||||
topic: 2,
|
topic: 2,
|
||||||
dashboard: 8,
|
dashboard: 8,
|
||||||
pipeline: 5,
|
pipeline: 5,
|
||||||
dbtModel: 7,
|
mlmodel: 2,
|
||||||
mlModel: 2,
|
|
||||||
}}
|
}}
|
||||||
updateDashboardCount={mockFunction}
|
|
||||||
updateDbtModelCount={mockFunction}
|
|
||||||
updateMlModelCount={mockFunction}
|
|
||||||
updatePipelineCount={mockFunction}
|
|
||||||
updateTableCount={mockFunction}
|
|
||||||
updateTopicCount={mockFunction}
|
|
||||||
onShowDeleted={mockFunction}
|
onShowDeleted={mockFunction}
|
||||||
/>,
|
/>,
|
||||||
{
|
{
|
||||||
|
@ -29,14 +29,7 @@ export type ExploreSearchData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface ExploreProps {
|
export interface ExploreProps {
|
||||||
tabCounts: {
|
tabCounts: TabCounts;
|
||||||
table: number;
|
|
||||||
topic: number;
|
|
||||||
dashboard: number;
|
|
||||||
pipeline: number;
|
|
||||||
dbtModel: number;
|
|
||||||
mlModel: number;
|
|
||||||
};
|
|
||||||
searchText: string;
|
searchText: string;
|
||||||
initialFilter?: FilterObject;
|
initialFilter?: FilterObject;
|
||||||
searchFilter?: FilterObject;
|
searchFilter?: FilterObject;
|
||||||
@ -51,17 +44,20 @@ export interface ExploreProps {
|
|||||||
handleFilterChange: (data: FilterObject) => void;
|
handleFilterChange: (data: FilterObject) => void;
|
||||||
handlePathChange: (path: string) => void;
|
handlePathChange: (path: string) => void;
|
||||||
handleSearchText: (text: string) => void;
|
handleSearchText: (text: string) => void;
|
||||||
updateTableCount: (count: number) => void;
|
|
||||||
updateTopicCount: (count: number) => void;
|
|
||||||
updateDashboardCount: (count: number) => void;
|
|
||||||
updatePipelineCount: (count: number) => void;
|
|
||||||
updateDbtModelCount: (count: number) => void;
|
|
||||||
updateMlModelCount: (count: number) => void;
|
|
||||||
fetchData: (value: SearchDataFunctionType[]) => void;
|
fetchData: (value: SearchDataFunctionType[]) => void;
|
||||||
onShowDeleted: (checked: boolean) => void;
|
onShowDeleted: (checked: boolean) => void;
|
||||||
|
handleTabCounts: (value: { [key: string]: number }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AdvanceField {
|
export interface AdvanceField {
|
||||||
key: string;
|
key: string;
|
||||||
value: string | undefined;
|
value: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TabCounts {
|
||||||
|
table: number;
|
||||||
|
topic: number;
|
||||||
|
dashboard: number;
|
||||||
|
pipeline: number;
|
||||||
|
mlmodel: number;
|
||||||
|
}
|
||||||
|
@ -13,46 +13,72 @@
|
|||||||
|
|
||||||
import { Menu, MenuProps } from 'antd';
|
import { Menu, MenuProps } from 'antd';
|
||||||
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import React from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { GLOBAL_SETTINGS_MENU } from '../../constants/globalSettings.constants';
|
import { GLOBAL_SETTING_PERMISSION_RESOURCES } from '../../constants/globalSettings.constants';
|
||||||
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
import {
|
||||||
import { getGlobalSettingMenus } from '../../utils/GlobalSettingsUtils';
|
getGlobalSettingMenuItem,
|
||||||
import { checkPermission } from '../../utils/PermissionsUtils';
|
getGlobalSettingsMenuWithPermission,
|
||||||
|
MenuList,
|
||||||
|
} from '../../utils/GlobalSettingsUtils';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
import Loader from '../Loader/Loader';
|
||||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
import {
|
||||||
|
ResourceEntity,
|
||||||
|
UIPermission,
|
||||||
|
} from '../PermissionProvider/PermissionProvider.interface';
|
||||||
|
|
||||||
const GlobalSettingLeftPanel = () => {
|
const GlobalSettingLeftPanel = () => {
|
||||||
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
|
||||||
|
|
||||||
const { permissions } = usePermissionProvider();
|
|
||||||
|
|
||||||
const viewAllPermission = checkPermission(
|
|
||||||
Operation.ViewAll,
|
|
||||||
ResourceEntity.ALL,
|
|
||||||
permissions
|
|
||||||
);
|
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const items: ItemType[] = GLOBAL_SETTINGS_MENU.filter(({ isProtected }) => {
|
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
||||||
if (viewAllPermission) {
|
const [settingResourcePermission, setSettingResourcePermission] =
|
||||||
return viewAllPermission;
|
useState<UIPermission>({} as UIPermission);
|
||||||
}
|
|
||||||
|
|
||||||
return !isProtected;
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
}).map(({ category, items }) => {
|
|
||||||
return getGlobalSettingMenus(
|
const { getResourcePermission } = usePermissionProvider();
|
||||||
category,
|
|
||||||
camelCase(category),
|
const fetchResourcesPermission = async (resource: ResourceEntity) => {
|
||||||
'',
|
setIsLoading(true);
|
||||||
'',
|
try {
|
||||||
items,
|
const response = await getResourcePermission(resource);
|
||||||
'group',
|
setSettingResourcePermission((prev) => ({
|
||||||
viewAllPermission
|
...prev,
|
||||||
);
|
[resource]: response,
|
||||||
});
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const menuItems: ItemType[] = useMemo(
|
||||||
|
() =>
|
||||||
|
getGlobalSettingsMenuWithPermission(settingResourcePermission).reduce(
|
||||||
|
(acc: ItemType[], curr: MenuList) => {
|
||||||
|
const menuItem = getGlobalSettingMenuItem(
|
||||||
|
curr.category,
|
||||||
|
camelCase(curr.category),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
curr.items,
|
||||||
|
'group'
|
||||||
|
);
|
||||||
|
if (menuItem.children?.length) {
|
||||||
|
return [...acc, menuItem];
|
||||||
|
} else {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[] as ItemType[]
|
||||||
|
),
|
||||||
|
[setSettingResourcePermission]
|
||||||
|
);
|
||||||
|
|
||||||
const onClick: MenuProps['onClick'] = (e) => {
|
const onClick: MenuProps['onClick'] = (e) => {
|
||||||
// As we are setting key as "category.option" and extracting here category and option
|
// As we are setting key as "category.option" and extracting here category and option
|
||||||
@ -60,14 +86,29 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
history.push(getSettingPath(category, option));
|
history.push(getSettingPath(category, option));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// TODO: This will make number of API calls, need to think of better solution
|
||||||
|
GLOBAL_SETTING_PERMISSION_RESOURCES.forEach((resource) => {
|
||||||
|
fetchResourcesPermission(resource);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu
|
<>
|
||||||
className="global-setting-left-panel"
|
{menuItems.length ? (
|
||||||
items={items}
|
<Menu
|
||||||
mode="inline"
|
className="global-setting-left-panel"
|
||||||
selectedKeys={[`${settingCategory}.${tab}`]}
|
items={menuItems}
|
||||||
onClick={onClick}
|
mode="inline"
|
||||||
/>
|
selectedKeys={[`${settingCategory}.${tab}`]}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
import { Operation } from '../../generated/entity/policies/accessControl/resourcePermission';
|
import { Operation } from '../../generated/entity/policies/accessControl/resourcePermission';
|
||||||
|
|
||||||
export type UIPermission = {
|
export type UIPermission = {
|
||||||
@ -65,7 +64,10 @@ export interface PermissionContextType {
|
|||||||
getEntityPermission: (
|
getEntityPermission: (
|
||||||
resource: ResourceEntity,
|
resource: ResourceEntity,
|
||||||
entityId: string
|
entityId: string
|
||||||
) => Promise<OperationPermission | AxiosError>;
|
) => Promise<OperationPermission>;
|
||||||
|
getResourcePermission: (
|
||||||
|
resource: ResourceEntity
|
||||||
|
) => Promise<OperationPermission>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityPermissionMap {
|
export interface EntityPermissionMap {
|
||||||
|
@ -23,8 +23,11 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import { getLoggedInUserPermissions } from '../../axiosAPIs/miscAPI';
|
import {
|
||||||
import { getEntityPermissionById } from '../../axiosAPIs/rolesAPIV1';
|
getEntityPermissionById,
|
||||||
|
getLoggedInUserPermissions,
|
||||||
|
getResourcePermission,
|
||||||
|
} from '../../axiosAPIs/permissionAPI';
|
||||||
import {
|
import {
|
||||||
getOperationPermissions,
|
getOperationPermissions,
|
||||||
getUIPermission,
|
getUIPermission,
|
||||||
@ -36,12 +39,12 @@ import {
|
|||||||
ResourceEntity,
|
ResourceEntity,
|
||||||
UIPermission,
|
UIPermission,
|
||||||
} from './PermissionProvider.interface';
|
} from './PermissionProvider.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission Context
|
* Permission Context
|
||||||
* Returns ResourcePermission List for loggedIn User
|
* Returns ResourcePermission List for loggedIn User
|
||||||
* @returns PermissionMap
|
* @returns PermissionMap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const PermissionContext = createContext<PermissionContextType>(
|
export const PermissionContext = createContext<PermissionContextType>(
|
||||||
{} as PermissionContextType
|
{} as PermissionContextType
|
||||||
);
|
);
|
||||||
@ -63,6 +66,10 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
const [entitiesPermission, setEntitiesPermission] =
|
const [entitiesPermission, setEntitiesPermission] =
|
||||||
useState<EntityPermissionMap>({} as EntityPermissionMap);
|
useState<EntityPermissionMap>({} as EntityPermissionMap);
|
||||||
|
|
||||||
|
const [resourcesPermission, setResourcesPermission] = useState<UIPermission>(
|
||||||
|
{} as UIPermission
|
||||||
|
);
|
||||||
|
|
||||||
// Update current user details of AppState change
|
// Update current user details of AppState change
|
||||||
const currentUser = useMemo(() => {
|
const currentUser = useMemo(() => {
|
||||||
return AppState.getCurrentUserDetails();
|
return AppState.getCurrentUserDetails();
|
||||||
@ -84,22 +91,45 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
resource: ResourceEntity,
|
resource: ResourceEntity,
|
||||||
entityId: string
|
entityId: string
|
||||||
) => {
|
) => {
|
||||||
try {
|
const entityPermission = entitiesPermission[entityId];
|
||||||
const entityPermission = entitiesPermission[entityId];
|
if (entityPermission) {
|
||||||
if (entityPermission) {
|
return entityPermission;
|
||||||
return entityPermission;
|
} else {
|
||||||
} else {
|
const response = await getEntityPermissionById(resource, entityId);
|
||||||
const response = await getEntityPermissionById(resource, entityId);
|
const operationPermission = getOperationPermissions(response);
|
||||||
const operationPermission = getOperationPermissions(response);
|
setEntitiesPermission((prev) => ({
|
||||||
setEntitiesPermission((prev) => ({
|
...prev,
|
||||||
...prev,
|
[entityId]: operationPermission,
|
||||||
[entityId]: operationPermission,
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
return operationPermission;
|
return operationPermission;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
};
|
||||||
return error as AxiosError;
|
|
||||||
|
const fetchResourcePermission = async (resource: ResourceEntity) => {
|
||||||
|
const resourcePermission = resourcesPermission[resource];
|
||||||
|
if (resourcePermission) {
|
||||||
|
return resourcePermission;
|
||||||
|
} else {
|
||||||
|
const response = await getResourcePermission(resource);
|
||||||
|
const operationPermission = getOperationPermissions(response);
|
||||||
|
/**
|
||||||
|
* Store resource permission if it's not exits
|
||||||
|
*/
|
||||||
|
setResourcesPermission((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[resource]: operationPermission,
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store updated resource permission
|
||||||
|
*/
|
||||||
|
setPermissions((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[resource]: operationPermission,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return operationPermission;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,6 +147,7 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
value={{
|
value={{
|
||||||
permissions,
|
permissions,
|
||||||
getEntityPermission: fetchEntityPermission,
|
getEntityPermission: fetchEntityPermission,
|
||||||
|
getResourcePermission: fetchResourcePermission,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</PermissionContext.Provider>
|
</PermissionContext.Provider>
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
import { toLower } from 'lodash';
|
import { toLower } from 'lodash';
|
||||||
import { AggregationType, Bucket, FilterObject } from 'Models';
|
import { AggregationType, Bucket, FilterObject } from 'Models';
|
||||||
|
import { TabCounts } from '../components/Explore/explore.interface';
|
||||||
|
import { EntityType } from '../enums/entity.enum';
|
||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
import { getFilterKey } from '../utils/FilterUtils';
|
import { getFilterKey } from '../utils/FilterUtils';
|
||||||
import { Icons } from '../utils/SvgUtils';
|
import { Icons } from '../utils/SvgUtils';
|
||||||
@ -301,3 +303,27 @@ export const tabsInfo = [
|
|||||||
selectedIcon: '',
|
selectedIcon: '',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const INITIAL_TAB_COUNTS: TabCounts = {
|
||||||
|
table: 0,
|
||||||
|
topic: 0,
|
||||||
|
dashboard: 0,
|
||||||
|
pipeline: 0,
|
||||||
|
mlmodel: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getEntityTypeByIndex = (index: SearchIndex) => {
|
||||||
|
switch (index) {
|
||||||
|
case SearchIndex.TOPIC:
|
||||||
|
return EntityType.TOPIC;
|
||||||
|
case SearchIndex.DASHBOARD:
|
||||||
|
return EntityType.DASHBOARD;
|
||||||
|
case SearchIndex.PIPELINE:
|
||||||
|
return EntityType.PIPELINE;
|
||||||
|
case SearchIndex.MLMODEL:
|
||||||
|
return EntityType.MLMODEL;
|
||||||
|
case SearchIndex.TABLE:
|
||||||
|
default:
|
||||||
|
return EntityType.TABLE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -11,148 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { ReactComponent as BotIcon } from '../../src/assets/svg/bot-profile.svg';
|
|
||||||
import { ReactComponent as DashboardIcon } from '../../src/assets/svg/dashboard-grey.svg';
|
|
||||||
import { ReactComponent as RolesIcon } from '../../src/assets/svg/icon-role-grey.svg';
|
|
||||||
import { ReactComponent as MlModelIcon } from '../../src/assets/svg/mlmodal.svg';
|
|
||||||
import { ReactComponent as MSTeams } from '../../src/assets/svg/ms-teams.svg';
|
|
||||||
import { ReactComponent as PipelineIcon } from '../../src/assets/svg/pipeline-grey.svg';
|
|
||||||
import { ReactComponent as PoliciesIcon } from '../../src/assets/svg/policies.svg';
|
|
||||||
import { ReactComponent as SlackIcon } from '../../src/assets/svg/slack.svg';
|
|
||||||
import { ReactComponent as TableIcon } from '../../src/assets/svg/table-grey.svg';
|
|
||||||
import { ReactComponent as TeamsIcon } from '../../src/assets/svg/teams-grey.svg';
|
|
||||||
import { ReactComponent as TopicIcon } from '../../src/assets/svg/topic-grey.svg';
|
|
||||||
import { ReactComponent as UsersIcon } from '../../src/assets/svg/user.svg';
|
|
||||||
import { ReactComponent as WebhookIcon } from '../../src/assets/svg/webhook-grey.svg';
|
|
||||||
|
|
||||||
export const GLOBAL_SETTINGS_MENU = [
|
|
||||||
{
|
|
||||||
category: 'Members',
|
|
||||||
isProtected: false,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: 'Teams',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <TeamsIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Users',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <UsersIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Admins',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <UsersIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Access',
|
|
||||||
isProtected: true,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: 'Roles',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <RolesIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Policies',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <PoliciesIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Services',
|
|
||||||
isProtected: false,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: 'Databases',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <TableIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Messaging',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <TopicIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Dashboards',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <DashboardIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Pipelines',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <PipelineIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ML Models',
|
|
||||||
isProtected: false,
|
|
||||||
icon: <MlModelIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Custom Attributes',
|
|
||||||
isProtected: true,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: 'Tables',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <TableIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Topics',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <TopicIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Dashboards',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <DashboardIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Pipelines',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <PipelineIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ML Models',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <MlModelIcon className="side-panel-icons" />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Integrations',
|
|
||||||
isProtected: true,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: 'Webhook',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <WebhookIcon className="tw-w-4 side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Slack',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <SlackIcon className="tw-w-4 side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MS Teams',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <MSTeams className="tw-w-4 side-panel-icons" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Bots',
|
|
||||||
isProtected: true,
|
|
||||||
icon: <BotIcon className="tw-w-4 side-panel-icons" />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const customAttributesPath = {
|
export const customAttributesPath = {
|
||||||
tables: 'table',
|
tables: 'table',
|
||||||
@ -187,3 +46,18 @@ export enum GlobalSettingOptions {
|
|||||||
TABLES = 'tables',
|
TABLES = 'tables',
|
||||||
MSTEAMS = 'msteams',
|
MSTEAMS = 'msteams',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GLOBAL_SETTING_PERMISSION_RESOURCES = [
|
||||||
|
ResourceEntity.TEAM,
|
||||||
|
ResourceEntity.USER,
|
||||||
|
ResourceEntity.ROLE,
|
||||||
|
ResourceEntity.POLICY,
|
||||||
|
ResourceEntity.DATABASE_SERVICE,
|
||||||
|
ResourceEntity.MESSAGING_SERVICE,
|
||||||
|
ResourceEntity.DASHBOARD_SERVICE,
|
||||||
|
ResourceEntity.PIPELINE_SERVICE,
|
||||||
|
ResourceEntity.ML_MODEL_SERVICE,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
ResourceEntity.WEBHOOK,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
];
|
||||||
|
@ -32,20 +32,25 @@ import PageContainerV1 from '../../components/containers/PageContainerV1';
|
|||||||
import GithubStarButton from '../../components/GithubStarButton/GithubStarButton';
|
import GithubStarButton from '../../components/GithubStarButton/GithubStarButton';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
import MyData from '../../components/MyData/MyData.component';
|
import MyData from '../../components/MyData/MyData.component';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { useWebSocketConnector } from '../../components/web-scoket/web-scoket.provider';
|
import { useWebSocketConnector } from '../../components/web-scoket/web-scoket.provider';
|
||||||
import { SOCKET_EVENTS } from '../../constants/constants';
|
import { SOCKET_EVENTS } from '../../constants/constants';
|
||||||
import { AssetsType } from '../../enums/entity.enum';
|
import { AssetsType } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { Post, Thread, ThreadType } from '../../generated/entity/feed/thread';
|
import { Post, Thread, ThreadType } from '../../generated/entity/feed/thread';
|
||||||
|
import { Operation as RuleOperation } from '../../generated/entity/policies/accessControl/rule';
|
||||||
import { EntitiesCount } from '../../generated/entity/utils/entitiesCount';
|
import { EntitiesCount } from '../../generated/entity/utils/entitiesCount';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
const MyDataPage = () => {
|
const MyDataPage = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
const { isAuthDisabled } = useAuth(location.pathname);
|
const { isAuthDisabled } = useAuth(location.pathname);
|
||||||
const [error, setError] = useState<string>('');
|
const [error, setError] = useState<string>('');
|
||||||
const [entityCounts, setEntityCounts] = useState<EntitiesCount>(
|
const [entityCounts, setEntityCounts] = useState<EntitiesCount>(
|
||||||
@ -72,6 +77,13 @@ const MyDataPage = () => {
|
|||||||
[AppState.userDetails, AppState.nonSecureUserDetails]
|
[AppState.userDetails, AppState.nonSecureUserDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewUserPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(RuleOperation.ViewAll, ResourceEntity.USER, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const fetchEntityCount = () => {
|
const fetchEntityCount = () => {
|
||||||
getAllEntityCount()
|
getAllEntityCount()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -258,7 +270,7 @@ const MyDataPage = () => {
|
|||||||
!isEmpty(AppState.userDetails)) &&
|
!isEmpty(AppState.userDetails)) &&
|
||||||
(isNil(ownedData) || isNil(followedData))
|
(isNil(ownedData) || isNil(followedData))
|
||||||
) {
|
) {
|
||||||
fetchMyData();
|
viewUserPermission && fetchMyData();
|
||||||
}
|
}
|
||||||
}, [AppState.userDetails, AppState.users, isAuthDisabled]);
|
}, [AppState.userDetails, AppState.users, isAuthDisabled]);
|
||||||
|
|
||||||
|
@ -19,13 +19,7 @@ import {
|
|||||||
SearchDataFunctionType,
|
SearchDataFunctionType,
|
||||||
SearchResponse,
|
SearchResponse,
|
||||||
} from 'Models';
|
} from 'Models';
|
||||||
import React, {
|
import React, { FunctionComponent, useEffect, useMemo, useState } from 'react';
|
||||||
Fragment,
|
|
||||||
FunctionComponent,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import { searchData } from '../../axiosAPIs/miscAPI';
|
import { searchData } from '../../axiosAPIs/miscAPI';
|
||||||
@ -33,6 +27,7 @@ import PageContainerV1 from '../../components/containers/PageContainerV1';
|
|||||||
import Explore from '../../components/Explore/Explore.component';
|
import Explore from '../../components/Explore/Explore.component';
|
||||||
import {
|
import {
|
||||||
ExploreSearchData,
|
ExploreSearchData,
|
||||||
|
TabCounts,
|
||||||
UrlParams,
|
UrlParams,
|
||||||
} from '../../components/Explore/explore.interface';
|
} from '../../components/Explore/explore.interface';
|
||||||
import { getExplorePathWithSearch, PAGE_SIZE } from '../../constants/constants';
|
import { getExplorePathWithSearch, PAGE_SIZE } from '../../constants/constants';
|
||||||
@ -40,11 +35,13 @@ import {
|
|||||||
emptyValue,
|
emptyValue,
|
||||||
getCurrentIndex,
|
getCurrentIndex,
|
||||||
getCurrentTab,
|
getCurrentTab,
|
||||||
|
getEntityTypeByIndex,
|
||||||
getInitialFilter,
|
getInitialFilter,
|
||||||
getQueryParam,
|
getQueryParam,
|
||||||
getSearchFilter,
|
getSearchFilter,
|
||||||
INITIAL_FROM,
|
INITIAL_FROM,
|
||||||
INITIAL_SORT_ORDER,
|
INITIAL_SORT_ORDER,
|
||||||
|
INITIAL_TAB_COUNTS,
|
||||||
tabsInfo,
|
tabsInfo,
|
||||||
ZERO_SIZE,
|
ZERO_SIZE,
|
||||||
} from '../../constants/explore.constants';
|
} from '../../constants/explore.constants';
|
||||||
@ -68,46 +65,21 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
const [error, setError] = useState<string>('');
|
const [error, setError] = useState<string>('');
|
||||||
const { searchQuery, tab } = useParams<UrlParams>();
|
const { searchQuery, tab } = useParams<UrlParams>();
|
||||||
const [searchText, setSearchText] = useState<string>(searchQuery || '');
|
const [searchText, setSearchText] = useState<string>(searchQuery || '');
|
||||||
const [tableCount, setTableCount] = useState<number>(0);
|
const [tabCounts, setTabCounts] = useState<TabCounts>(INITIAL_TAB_COUNTS);
|
||||||
const [topicCount, setTopicCount] = useState<number>(0);
|
|
||||||
const [dashboardCount, setDashboardCount] = useState<number>(0);
|
|
||||||
const [pipelineCount, setPipelineCount] = useState<number>(0);
|
|
||||||
const [dbtModelCount, setDbtModelCount] = useState<number>(0);
|
|
||||||
const [mlModelCount, setMlModelCount] = useState<number>(0);
|
|
||||||
const [searchResult, setSearchResult] = useState<ExploreSearchData>();
|
const [searchResult, setSearchResult] = useState<ExploreSearchData>();
|
||||||
const [showDeleted, setShowDeleted] = useState(false);
|
const [showDeleted, setShowDeleted] = useState(false);
|
||||||
const [initialSortField] = useState<string>(
|
const [initialSortField] = useState<string>(
|
||||||
tabsInfo[getCurrentTab(tab) - 1].sortField
|
tabsInfo[getCurrentTab(tab) - 1].sortField
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleTabCounts = (value: { [key: string]: number }) => {
|
||||||
|
setTabCounts((prev) => ({ ...prev, ...value }));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSearchText = (text: string) => {
|
const handleSearchText = (text: string) => {
|
||||||
setSearchText(text);
|
setSearchText(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTableCount = (count: number) => {
|
|
||||||
setTableCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTopicCount = (count: number) => {
|
|
||||||
setTopicCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDashboardCount = (count: number) => {
|
|
||||||
setDashboardCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePipelineCount = (count: number) => {
|
|
||||||
setPipelineCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDbtModelCount = (count: number) => {
|
|
||||||
setDbtModelCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMlModelCount = (count: number) => {
|
|
||||||
setMlModelCount(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePathChange = (path: string) => {
|
const handlePathChange = (path: string) => {
|
||||||
AppState.updateExplorePageTab(path);
|
AppState.updateExplorePageTab(path);
|
||||||
};
|
};
|
||||||
@ -127,86 +99,42 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchCounts = () => {
|
const fetchEntityCount = async (indexType: SearchIndex) => {
|
||||||
const entities = [
|
const entityType = getEntityTypeByIndex(indexType);
|
||||||
SearchIndex.TABLE,
|
try {
|
||||||
SearchIndex.TOPIC,
|
const { data } = await searchData(
|
||||||
SearchIndex.DASHBOARD,
|
|
||||||
SearchIndex.PIPELINE,
|
|
||||||
SearchIndex.MLMODEL,
|
|
||||||
];
|
|
||||||
|
|
||||||
const entityCounts = entities.map((entity) =>
|
|
||||||
searchData(
|
|
||||||
searchText,
|
searchText,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
getFilterString(initialFilter),
|
getFilterString(initialFilter),
|
||||||
emptyValue,
|
emptyValue,
|
||||||
emptyValue,
|
emptyValue,
|
||||||
entity,
|
indexType,
|
||||||
showDeleted,
|
showDeleted,
|
||||||
true
|
true
|
||||||
)
|
);
|
||||||
);
|
const count = getTotalEntityCountByType(
|
||||||
|
data.aggregations?.['sterms#EntityType']?.buckets as Bucket[]
|
||||||
|
);
|
||||||
|
|
||||||
Promise.allSettled(entityCounts)
|
setTabCounts((prev) => ({ ...prev, [entityType]: count }));
|
||||||
.then(
|
} catch (_error) {
|
||||||
([
|
showErrorToast(
|
||||||
table,
|
jsonData['api-error-messages']['fetch-entity-count-error']
|
||||||
topic,
|
);
|
||||||
dashboard,
|
}
|
||||||
pipeline,
|
};
|
||||||
mlmodel,
|
|
||||||
]: PromiseSettledResult<SearchResponse>[]) => {
|
const fetchCounts = () => {
|
||||||
setTableCount(
|
fetchEntityCount(SearchIndex.TABLE);
|
||||||
table.status === 'fulfilled'
|
|
||||||
? getTotalEntityCountByType(
|
fetchEntityCount(SearchIndex.TOPIC);
|
||||||
table.value.data.aggregations?.['sterms#EntityType']
|
|
||||||
?.buckets as Bucket[]
|
fetchEntityCount(SearchIndex.DASHBOARD);
|
||||||
)
|
|
||||||
: 0
|
fetchEntityCount(SearchIndex.PIPELINE);
|
||||||
);
|
|
||||||
setTopicCount(
|
fetchEntityCount(SearchIndex.MLMODEL);
|
||||||
topic.status === 'fulfilled'
|
|
||||||
? getTotalEntityCountByType(
|
|
||||||
topic.value.data.aggregations?.['sterms#EntityType']
|
|
||||||
?.buckets as Bucket[]
|
|
||||||
)
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
setDashboardCount(
|
|
||||||
dashboard.status === 'fulfilled'
|
|
||||||
? getTotalEntityCountByType(
|
|
||||||
dashboard.value.data.aggregations?.['sterms#EntityType']
|
|
||||||
?.buckets as Bucket[]
|
|
||||||
)
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
setPipelineCount(
|
|
||||||
pipeline.status === 'fulfilled'
|
|
||||||
? getTotalEntityCountByType(
|
|
||||||
pipeline.value.data.aggregations?.['sterms#EntityType']
|
|
||||||
?.buckets as Bucket[]
|
|
||||||
)
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
setMlModelCount(
|
|
||||||
mlmodel.status === 'fulfilled'
|
|
||||||
? getTotalEntityCountByType(
|
|
||||||
mlmodel.value.data.aggregations?.['sterms#EntityType']
|
|
||||||
?.buckets as Bucket[]
|
|
||||||
)
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.catch((err: AxiosError) => {
|
|
||||||
showErrorToast(
|
|
||||||
err,
|
|
||||||
jsonData['api-error-messages']['fetch-entity-count-error']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchData = (value: SearchDataFunctionType[]) => {
|
const fetchData = (value: SearchDataFunctionType[]) => {
|
||||||
@ -262,6 +190,7 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSearchResult(undefined);
|
setSearchResult(undefined);
|
||||||
|
|
||||||
fetchData([
|
fetchData([
|
||||||
{
|
{
|
||||||
queryString: searchText,
|
queryString: searchText,
|
||||||
@ -303,42 +232,28 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<PageContainerV1>
|
||||||
<PageContainerV1>
|
<Explore
|
||||||
<Explore
|
error={error}
|
||||||
error={error}
|
fetchCount={fetchCounts}
|
||||||
fetchCount={fetchCounts}
|
fetchData={fetchData}
|
||||||
fetchData={fetchData}
|
handleFilterChange={handleFilterChange}
|
||||||
handleFilterChange={handleFilterChange}
|
handlePathChange={handlePathChange}
|
||||||
handlePathChange={handlePathChange}
|
handleSearchText={handleSearchText}
|
||||||
handleSearchText={handleSearchText}
|
handleTabCounts={handleTabCounts}
|
||||||
initialFilter={initialFilter}
|
initialFilter={initialFilter}
|
||||||
isFilterSelected={!isEmpty(searchFilter) || !isEmpty(initialFilter)}
|
isFilterSelected={!isEmpty(searchFilter) || !isEmpty(initialFilter)}
|
||||||
searchFilter={searchFilter}
|
searchFilter={searchFilter}
|
||||||
searchQuery={searchQuery}
|
searchQuery={searchQuery}
|
||||||
searchResult={searchResult}
|
searchResult={searchResult}
|
||||||
searchText={searchText}
|
searchText={searchText}
|
||||||
showDeleted={showDeleted}
|
showDeleted={showDeleted}
|
||||||
sortValue={initialSortField}
|
sortValue={initialSortField}
|
||||||
tab={tab}
|
tab={tab}
|
||||||
tabCounts={{
|
tabCounts={tabCounts}
|
||||||
table: tableCount,
|
onShowDeleted={(checked) => setShowDeleted(checked)}
|
||||||
topic: topicCount,
|
/>
|
||||||
dashboard: dashboardCount,
|
</PageContainerV1>
|
||||||
pipeline: pipelineCount,
|
|
||||||
dbtModel: dbtModelCount,
|
|
||||||
mlModel: mlModelCount,
|
|
||||||
}}
|
|
||||||
updateDashboardCount={handleDashboardCount}
|
|
||||||
updateDbtModelCount={handleDbtModelCount}
|
|
||||||
updateMlModelCount={handleMlModelCount}
|
|
||||||
updatePipelineCount={handlePipelineCount}
|
|
||||||
updateTableCount={handleTableCount}
|
|
||||||
updateTopicCount={handleTopicCount}
|
|
||||||
onShowDeleted={(checked) => setShowDeleted(checked)}
|
|
||||||
/>
|
|
||||||
</PageContainerV1>
|
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import React, { useState } from 'react';
|
|||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import appState from '../../AppState';
|
import appState from '../../AppState';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||||
import { getLoggedInUserPermissions } from '../../axiosAPIs/miscAPI';
|
|
||||||
import { createUser } from '../../axiosAPIs/userAPI';
|
import { createUser } from '../../axiosAPIs/userAPI';
|
||||||
import { Button } from '../../components/buttons/Button/Button';
|
import { Button } from '../../components/buttons/Button/Button';
|
||||||
import PageContainer from '../../components/containers/PageContainer';
|
import PageContainer from '../../components/containers/PageContainer';
|
||||||
@ -30,7 +29,6 @@ import { getNameFromEmail } from '../../utils/AuthProvider.util';
|
|||||||
import { getImages } from '../../utils/CommonUtils';
|
import { getImages } from '../../utils/CommonUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import { fetchAllUsers } from '../../utils/UserDataUtils';
|
|
||||||
|
|
||||||
const cookieStorage = new CookieStorage();
|
const cookieStorage = new CookieStorage();
|
||||||
|
|
||||||
@ -46,31 +44,12 @@ const Signup = () => {
|
|||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const getUserPermissions = () => {
|
|
||||||
getLoggedInUserPermissions()
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data) {
|
|
||||||
appState.updateUserPermissions(res.data);
|
|
||||||
} else {
|
|
||||||
throw jsonData['api-error-messages']['unexpected-server-response'];
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err: AxiosError) => {
|
|
||||||
showErrorToast(
|
|
||||||
err,
|
|
||||||
jsonData['api-error-messages']['fetch-user-permission-error']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createNewUser = (details: User | CreateUser) => {
|
const createNewUser = (details: User | CreateUser) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
createUser(details as CreateUser)
|
createUser(details as CreateUser)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
appState.updateUserDetails(res);
|
appState.updateUserDetails(res);
|
||||||
fetchAllUsers();
|
|
||||||
getUserPermissions();
|
|
||||||
cookieStorage.removeItem(REDIRECT_PATHNAME);
|
cookieStorage.removeItem(REDIRECT_PATHNAME);
|
||||||
setIsSigningIn(false);
|
setIsSigningIn(false);
|
||||||
history.push(ROUTES.HOME);
|
history.push(ROUTES.HOME);
|
||||||
|
@ -48,7 +48,7 @@ const exploreCount = {
|
|||||||
dashboard: 0,
|
dashboard: 0,
|
||||||
pipeline: 0,
|
pipeline: 0,
|
||||||
dbtModel: 0,
|
dbtModel: 0,
|
||||||
mlModel: 0,
|
mlmodel: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TourPage = () => {
|
const TourPage = () => {
|
||||||
@ -164,6 +164,7 @@ const TourPage = () => {
|
|||||||
handleFilterChange={handleFilterChange}
|
handleFilterChange={handleFilterChange}
|
||||||
handlePathChange={handleCountChange}
|
handlePathChange={handleCountChange}
|
||||||
handleSearchText={() => setExploreSearchResult(exploreSearchData)}
|
handleSearchText={() => setExploreSearchResult(exploreSearchData)}
|
||||||
|
handleTabCounts={handleCountChange}
|
||||||
searchQuery=""
|
searchQuery=""
|
||||||
searchResult={exploreSearchResult as unknown as ExploreSearchData}
|
searchResult={exploreSearchResult as unknown as ExploreSearchData}
|
||||||
searchText=""
|
searchText=""
|
||||||
@ -171,12 +172,6 @@ const TourPage = () => {
|
|||||||
sortValue=""
|
sortValue=""
|
||||||
tab=""
|
tab=""
|
||||||
tabCounts={explorePageCounts}
|
tabCounts={explorePageCounts}
|
||||||
updateDashboardCount={handleCountChange}
|
|
||||||
updateDbtModelCount={handleCountChange}
|
|
||||||
updateMlModelCount={handleCountChange}
|
|
||||||
updatePipelineCount={handleCountChange}
|
|
||||||
updateTableCount={handleCountChange}
|
|
||||||
updateTopicCount={handleCountChange}
|
|
||||||
onShowDeleted={() => {
|
onShowDeleted={() => {
|
||||||
return;
|
return;
|
||||||
}}
|
}}
|
||||||
|
@ -15,6 +15,7 @@ import { isEmpty, isNil, isUndefined, startCase } from 'lodash';
|
|||||||
import { Bucket, LeafNodes, LineagePos } from 'Models';
|
import { Bucket, LeafNodes, LineagePos } from 'Models';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EntityData } from '../components/common/PopOverCard/EntityPopOverCard';
|
import { EntityData } from '../components/common/PopOverCard/EntityPopOverCard';
|
||||||
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import TableProfilerGraph from '../components/TableProfiler/TableProfilerGraph.component';
|
import TableProfilerGraph from '../components/TableProfiler/TableProfilerGraph.component';
|
||||||
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from '../constants/char.constants';
|
||||||
import {
|
import {
|
||||||
@ -23,6 +24,7 @@ import {
|
|||||||
getTeamAndUserDetailsPath,
|
getTeamAndUserDetailsPath,
|
||||||
} from '../constants/constants';
|
} from '../constants/constants';
|
||||||
import { AssetsType, EntityType, FqnPart } from '../enums/entity.enum';
|
import { AssetsType, EntityType, FqnPart } from '../enums/entity.enum';
|
||||||
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
import { ServiceCategory } from '../enums/service.enum';
|
import { ServiceCategory } from '../enums/service.enum';
|
||||||
import { PrimaryTableDataTypes } from '../enums/table.enum';
|
import { PrimaryTableDataTypes } from '../enums/table.enum';
|
||||||
import { Dashboard } from '../generated/entity/data/dashboard';
|
import { Dashboard } from '../generated/entity/data/dashboard';
|
||||||
@ -443,3 +445,29 @@ export const filterEntityAssets = (data: EntityReference[]) => {
|
|||||||
|
|
||||||
return data.filter((d) => includedEntity.includes(d.type as AssetsType));
|
return data.filter((d) => includedEntity.includes(d.type as AssetsType));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getResourceEntityFromEntityType = (entityType: string) => {
|
||||||
|
switch (entityType) {
|
||||||
|
case EntityType.TABLE:
|
||||||
|
case SearchIndex.TABLE:
|
||||||
|
return ResourceEntity.TABLE;
|
||||||
|
|
||||||
|
case EntityType.TOPIC:
|
||||||
|
case SearchIndex.TOPIC:
|
||||||
|
return ResourceEntity.TOPIC;
|
||||||
|
|
||||||
|
case EntityType.DASHBOARD:
|
||||||
|
case SearchIndex.DASHBOARD:
|
||||||
|
return ResourceEntity.DASHBOARD;
|
||||||
|
|
||||||
|
case EntityType.PIPELINE:
|
||||||
|
case SearchIndex.PIPELINE:
|
||||||
|
return ResourceEntity.PIPELINE;
|
||||||
|
|
||||||
|
case EntityType.MLMODEL:
|
||||||
|
case SearchIndex.MLMODEL:
|
||||||
|
return ResourceEntity.ML_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResourceEntity.ALL;
|
||||||
|
};
|
||||||
|
@ -13,9 +13,231 @@
|
|||||||
|
|
||||||
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
|
import { ReactComponent as BotIcon } from '../../src/assets/svg/bot-profile.svg';
|
||||||
|
import { ReactComponent as DashboardIcon } from '../../src/assets/svg/dashboard-grey.svg';
|
||||||
|
import { ReactComponent as RolesIcon } from '../../src/assets/svg/icon-role-grey.svg';
|
||||||
|
import { ReactComponent as MlModelIcon } from '../../src/assets/svg/mlmodal.svg';
|
||||||
|
import { ReactComponent as PipelineIcon } from '../../src/assets/svg/pipeline-grey.svg';
|
||||||
|
import { ReactComponent as PoliciesIcon } from '../../src/assets/svg/policies.svg';
|
||||||
|
import { ReactComponent as SlackIcon } from '../../src/assets/svg/slack.svg';
|
||||||
|
import { ReactComponent as TableIcon } from '../../src/assets/svg/table-grey.svg';
|
||||||
|
import { ReactComponent as TeamsIcon } from '../../src/assets/svg/teams-grey.svg';
|
||||||
|
import { ReactComponent as TopicIcon } from '../../src/assets/svg/topic-grey.svg';
|
||||||
|
import { ReactComponent as UsersIcon } from '../../src/assets/svg/user.svg';
|
||||||
|
import { ReactComponent as WebhookIcon } from '../../src/assets/svg/webhook-grey.svg';
|
||||||
|
import {
|
||||||
|
ResourceEntity,
|
||||||
|
UIPermission,
|
||||||
|
} from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import { Operation } from '../generated/entity/policies/accessControl/rule';
|
||||||
|
import { checkPermission } from '../utils/PermissionsUtils';
|
||||||
|
|
||||||
export const getGlobalSettingMenus = (
|
export interface MenuListItem {
|
||||||
|
label: string;
|
||||||
|
isProtected: boolean;
|
||||||
|
icon: ReactNode;
|
||||||
|
}
|
||||||
|
export interface MenuList {
|
||||||
|
category: string;
|
||||||
|
items: MenuListItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getGlobalSettingsMenuWithPermission = (
|
||||||
|
permissions: UIPermission
|
||||||
|
) => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
category: 'Members',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Teams',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TEAM,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <TeamsIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Users',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.USER,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <UsersIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Admins',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.USER,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <UsersIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Access',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Roles',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.ROLE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <RolesIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Policies',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.POLICY,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <PoliciesIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Services',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Databases',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.DATABASE_SERVICE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <TableIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Messaging',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.MESSAGING_SERVICE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <TopicIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Dashboards',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.DASHBOARD_SERVICE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <DashboardIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Pipelines',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.PIPELINE_SERVICE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <PipelineIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ML Models',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.ML_MODEL_SERVICE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <MlModelIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Custom Attributes',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Tables',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <TableIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Topics',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <TopicIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Dashboards',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <DashboardIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Pipelines',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <PipelineIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ML Models',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <MlModelIcon className="side-panel-icons" />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Integrations',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'Webhook',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.WEBHOOK,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <WebhookIcon className="tw-w-4 side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Slack',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.WEBHOOK,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <SlackIcon className="tw-w-4 side-panel-icons" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Bots',
|
||||||
|
isProtected: checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
icon: <BotIcon className="tw-w-4 side-panel-icons" />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getGlobalSettingMenuItem = (
|
||||||
label: string,
|
label: string,
|
||||||
key: string,
|
key: string,
|
||||||
category?: string,
|
category?: string,
|
||||||
@ -25,8 +247,7 @@ export const getGlobalSettingMenus = (
|
|||||||
isProtected: boolean;
|
isProtected: boolean;
|
||||||
icon: React.ReactNode;
|
icon: React.ReactNode;
|
||||||
}[],
|
}[],
|
||||||
type?: string,
|
type?: string
|
||||||
hasAccess?: boolean
|
|
||||||
): {
|
): {
|
||||||
key: string;
|
key: string;
|
||||||
icon: React.ReactNode;
|
icon: React.ReactNode;
|
||||||
@ -34,16 +255,18 @@ export const getGlobalSettingMenus = (
|
|||||||
label: string;
|
label: string;
|
||||||
type: string | undefined;
|
type: string | undefined;
|
||||||
} => {
|
} => {
|
||||||
|
const subItems = children
|
||||||
|
? children
|
||||||
|
.filter((menu) => menu.isProtected)
|
||||||
|
.map(({ label, icon }) => {
|
||||||
|
return getGlobalSettingMenuItem(label, camelCase(label), key, icon);
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: `${category}.${key}`,
|
key: `${category}.${key}`,
|
||||||
icon,
|
icon,
|
||||||
children: children
|
children: subItems,
|
||||||
? children
|
|
||||||
.filter((menu) => (hasAccess ? menu : !menu.isProtected))
|
|
||||||
.map(({ label, icon }) => {
|
|
||||||
return getGlobalSettingMenus(label, camelCase(label), key, icon);
|
|
||||||
})
|
|
||||||
: undefined,
|
|
||||||
label,
|
label,
|
||||||
type,
|
type,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user