mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-24 00:48:36 +00:00
UI: Added custom property pages into global settings (#6381)
* Added custom property i global settings * prettier formatting * addressing comment * addressing comment * added prettier
This commit is contained in:
parent
384d64221f
commit
e35cfe489c
@ -14,7 +14,7 @@
|
|||||||
export const GLOBAL_SETTINGS_MENU = [
|
export const GLOBAL_SETTINGS_MENU = [
|
||||||
{
|
{
|
||||||
category: 'Access',
|
category: 'Access',
|
||||||
items: ['Teams', 'Users', 'Roles', 'Policies'],
|
items: ['Teams', 'Users', 'Roles'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Services',
|
category: 'Services',
|
||||||
@ -22,7 +22,7 @@ export const GLOBAL_SETTINGS_MENU = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Custom Attributes',
|
category: 'Custom Attributes',
|
||||||
items: ['Tables'],
|
items: ['Tables', 'Topics', 'Dashboards', 'Pipelines', 'ML Models'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Integrations',
|
category: 'Integrations',
|
||||||
@ -30,6 +30,14 @@ export const GLOBAL_SETTINGS_MENU = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const customAttributesPath = {
|
||||||
|
tables: 'table',
|
||||||
|
topics: 'topic',
|
||||||
|
dashboards: 'dashboard',
|
||||||
|
pipelines: 'pipeline',
|
||||||
|
mlModels: 'mlmodel',
|
||||||
|
};
|
||||||
|
|
||||||
export enum GlobalSettingsMenuCategory {
|
export enum GlobalSettingsMenuCategory {
|
||||||
ACCESS = 'access',
|
ACCESS = 'access',
|
||||||
SERVICES = 'services',
|
SERVICES = 'services',
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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 { AxiosError } from 'axios';
|
||||||
|
import { compare } from 'fast-json-patch';
|
||||||
|
import { isUndefined } from 'lodash';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
|
import { getTypeByFQN, updateType } from '../../axiosAPIs/metadataTypeAPI';
|
||||||
|
import { Button } from '../../components/buttons/Button/Button';
|
||||||
|
import ErrorPlaceHolder from '../../components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
|
import TabsPane from '../../components/common/TabsPane/TabsPane';
|
||||||
|
import { CustomPropertyTable } from '../../components/CustomEntityDetail/CustomPropertyTable';
|
||||||
|
import Loader from '../../components/Loader/Loader';
|
||||||
|
import SchemaEditor from '../../components/schema-editor/SchemaEditor';
|
||||||
|
import { getAddCustomPropertyPath } from '../../constants/constants';
|
||||||
|
import { customAttributesPath } from '../../constants/globalSettings.constants';
|
||||||
|
import { Type } from '../../generated/entity/type';
|
||||||
|
import jsonData from '../../jsons/en';
|
||||||
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
|
const CustomEntityDetailV1 = () => {
|
||||||
|
const { tab } = useParams<{ [key: string]: string }>();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState<number>(1);
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const [isError, setIsError] = useState<boolean>(false);
|
||||||
|
const [selectedEntityTypeDetail, setSelectedEntityTypeDetail] =
|
||||||
|
useState<Type>({} as Type);
|
||||||
|
|
||||||
|
const fetchTypeDetail = async (typeFQN: string) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const { data } = await getTypeByFQN(typeFQN);
|
||||||
|
setSelectedEntityTypeDetail(data);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
setIsError(true);
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTabChange = (tab: number) => {
|
||||||
|
setActiveTab(tab);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddProperty = () => {
|
||||||
|
const path = getAddCustomPropertyPath(tab);
|
||||||
|
history.push(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tabs = useMemo(() => {
|
||||||
|
const { customProperties } = selectedEntityTypeDetail;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'Custom Properties',
|
||||||
|
isProtected: false,
|
||||||
|
position: 1,
|
||||||
|
count: (customProperties || []).length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Schema',
|
||||||
|
isProtected: false,
|
||||||
|
position: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [selectedEntityTypeDetail]);
|
||||||
|
|
||||||
|
const updateEntityType = async (properties: Type['customProperties']) => {
|
||||||
|
const patch = compare(selectedEntityTypeDetail, {
|
||||||
|
...selectedEntityTypeDetail,
|
||||||
|
customProperties: properties,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await updateType(
|
||||||
|
selectedEntityTypeDetail.id || '',
|
||||||
|
patch
|
||||||
|
);
|
||||||
|
setSelectedEntityTypeDetail((prev) => ({
|
||||||
|
...prev,
|
||||||
|
customProperties: data.customProperties,
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isUndefined(tab)) {
|
||||||
|
setActiveTab(1);
|
||||||
|
setIsError(false);
|
||||||
|
fetchTypeDetail(
|
||||||
|
customAttributesPath[tab as keyof typeof customAttributesPath]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [tab]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <Loader />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<ErrorPlaceHolder>
|
||||||
|
{jsonData['message']['no-custom-entity']}
|
||||||
|
</ErrorPlaceHolder>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div data-testid="custom-entity-container">
|
||||||
|
<TabsPane activeTab={activeTab} setActiveTab={onTabChange} tabs={tabs} />
|
||||||
|
<div className="tw-mt-4">
|
||||||
|
{activeTab === 2 && (
|
||||||
|
<div data-testid="entity-schema">
|
||||||
|
<SchemaEditor
|
||||||
|
className="tw-border tw-border-main tw-rounded-md tw-py-4"
|
||||||
|
editorClass="custom-entity-schema"
|
||||||
|
value={JSON.parse(selectedEntityTypeDetail.schema ?? '{}')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{activeTab === 1 && (
|
||||||
|
<div data-testid="entity-custom-fields">
|
||||||
|
<div className="tw-flex tw-justify-end">
|
||||||
|
<Button
|
||||||
|
className="tw-mb-4 tw-py-1 tw-px-2 tw-rounded"
|
||||||
|
data-testid="add-field-button"
|
||||||
|
size="custom"
|
||||||
|
theme="primary"
|
||||||
|
onClick={() => handleAddProperty()}>
|
||||||
|
Add Property
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<CustomPropertyTable
|
||||||
|
customProperties={selectedEntityTypeDetail.customProperties || []}
|
||||||
|
updateEntityType={updateEntityType}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomEntityDetailV1;
|
@ -29,6 +29,11 @@ const ServicesPage = withSuspenseFallback(
|
|||||||
const BotsListPage = withSuspenseFallback(
|
const BotsListPage = withSuspenseFallback(
|
||||||
React.lazy(() => import('../pages/BotsListpage/BotsListpage.component'))
|
React.lazy(() => import('../pages/BotsListpage/BotsListpage.component'))
|
||||||
);
|
);
|
||||||
|
const CustomPropertiesPageV1 = withSuspenseFallback(
|
||||||
|
React.lazy(
|
||||||
|
() => import('../pages/CustomPropertiesPage/CustomPropertiesPageV1')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const GlobalSettingRouter = () => {
|
const GlobalSettingRouter = () => {
|
||||||
return (
|
return (
|
||||||
@ -63,6 +68,14 @@ const GlobalSettingRouter = () => {
|
|||||||
component={ServicesPage}
|
component={ServicesPage}
|
||||||
path={getSettingCategoryPath(GlobalSettingsMenuCategory.SERVICES)}
|
path={getSettingCategoryPath(GlobalSettingsMenuCategory.SERVICES)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
component={CustomPropertiesPageV1}
|
||||||
|
path={getSettingCategoryPath(
|
||||||
|
GlobalSettingsMenuCategory.CUSTOM_ATTRIBUTES
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user