mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-19 14:37:52 +00:00
Revamp Glossary UI to support URL updation (#3453)
This commit is contained in:
parent
22b394d63f
commit
cbe667b7cb
@ -19,6 +19,9 @@ node_modules/
|
|||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
# mockups
|
||||||
|
mock-api/
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ node_modules/
|
|||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
# mockups
|
||||||
|
mock-api/
|
||||||
|
|
||||||
# Ignore files (Prettier has trouble parsing files without extension)
|
# Ignore files (Prettier has trouble parsing files without extension)
|
||||||
.gitignore
|
.gitignore
|
||||||
.prettierignore
|
.prettierignore
|
||||||
|
@ -21,12 +21,13 @@ import {
|
|||||||
getGlossariesByName,
|
getGlossariesByName,
|
||||||
getGlossaryTermByFQN,
|
getGlossaryTermByFQN,
|
||||||
} from '../../axiosAPIs/glossaryAPI';
|
} from '../../axiosAPIs/glossaryAPI';
|
||||||
import { ROUTES } from '../../constants/constants';
|
import { getGlossaryPath } from '../../constants/constants';
|
||||||
import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
|
import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
|
||||||
import { Glossary } from '../../generated/entity/data/glossary';
|
import { Glossary } from '../../generated/entity/data/glossary';
|
||||||
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import useToastContext from '../../hooks/useToastContext';
|
import useToastContext from '../../hooks/useToastContext';
|
||||||
|
import jsonData from '../../jsons/en';
|
||||||
import AddGlossaryTerm from '../AddGlossaryTerm/AddGlossaryTerm.component';
|
import AddGlossaryTerm from '../AddGlossaryTerm/AddGlossaryTerm.component';
|
||||||
import PageContainerV1 from '../containers/PageContainerV1';
|
import PageContainerV1 from '../containers/PageContainerV1';
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
@ -44,43 +45,65 @@ const AddGlossaryTermPage = () => {
|
|||||||
|
|
||||||
const [parentGlossaryData, setParentGlossaryData] = useState<GlossaryTerm>();
|
const [parentGlossaryData, setParentGlossaryData] = useState<GlossaryTerm>();
|
||||||
|
|
||||||
const goToGlossary = () => {
|
const goToGlossary = (name = '') => {
|
||||||
history.push(ROUTES.GLOSSARY);
|
history.push(getGlossaryPath(name));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
goToGlossary();
|
goToGlossary();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleShowErrorToast = (errMessage: string) => {
|
||||||
|
showToast({
|
||||||
|
variant: 'error',
|
||||||
|
body: errMessage,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveFailure = (errorMessage = '') => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
errorMessage || jsonData['api-error-messages']['add-glossary-term-error']
|
||||||
|
);
|
||||||
|
setStatus('initial');
|
||||||
|
};
|
||||||
|
|
||||||
const onSave = (data: CreateGlossaryTerm) => {
|
const onSave = (data: CreateGlossaryTerm) => {
|
||||||
setStatus('waiting');
|
setStatus('waiting');
|
||||||
addGlossaryTerm(data)
|
addGlossaryTerm(data)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
setStatus('success');
|
if (res.data) {
|
||||||
setTimeout(() => {
|
setStatus('success');
|
||||||
setStatus('initial');
|
setTimeout(() => {
|
||||||
goToGlossary();
|
setStatus('initial');
|
||||||
}, 500);
|
goToGlossary(res?.data?.fullyQualifiedName);
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
handleSaveFailure();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleSaveFailure(err.response?.data?.message);
|
||||||
variant: 'error',
|
|
||||||
body: err.message || 'Something went wrong!',
|
|
||||||
});
|
|
||||||
setStatus('initial');
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchGlossaryData = () => {
|
const fetchGlossaryData = () => {
|
||||||
getGlossariesByName(glossaryName, ['tags', 'owner', 'reviewers'])
|
getGlossariesByName(glossaryName, ['tags', 'owner', 'reviewers'])
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
setGlossaryData(res.data);
|
if (res.data) {
|
||||||
|
setGlossaryData(res.data);
|
||||||
|
} else {
|
||||||
|
setGlossaryData(undefined);
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-glossary-error']
|
||||||
|
);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
setGlossaryData(undefined);
|
||||||
variant: 'error',
|
handleShowErrorToast(
|
||||||
body: err.message || 'Error while fetching glossary!',
|
err.response?.data?.message ||
|
||||||
});
|
jsonData['api-error-messages']['fetch-glossary-error']
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.finally(() => setIsLoading(false));
|
.finally(() => setIsLoading(false));
|
||||||
};
|
};
|
||||||
@ -93,14 +116,21 @@ const AddGlossaryTermPage = () => {
|
|||||||
'tags',
|
'tags',
|
||||||
])
|
])
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
setParentGlossaryData(res.data);
|
if (res.data) {
|
||||||
|
setParentGlossaryData(res.data);
|
||||||
|
} else {
|
||||||
|
setParentGlossaryData(undefined);
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-glossary-term-error']
|
||||||
|
);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
setParentGlossaryData(undefined);
|
setParentGlossaryData(undefined);
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body: err.message || 'Error while fetching glossary terms!',
|
jsonData['api-error-messages']['fetch-glossary-term-error']
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,25 +58,13 @@ type Props = {
|
|||||||
handleAddGlossaryTermClick: () => void;
|
handleAddGlossaryTermClick: () => void;
|
||||||
updateGlossary: (value: Glossary) => void;
|
updateGlossary: (value: Glossary) => void;
|
||||||
handleGlossaryTermUpdate: (value: GlossaryTerm) => void;
|
handleGlossaryTermUpdate: (value: GlossaryTerm) => void;
|
||||||
handleSelectedData: (
|
handleSelectedData: (key: string) => void;
|
||||||
data: Glossary | GlossaryTerm,
|
|
||||||
pos: string,
|
|
||||||
key: string
|
|
||||||
) => void;
|
|
||||||
handleChildLoading: (status: boolean) => void;
|
handleChildLoading: (status: boolean) => void;
|
||||||
handleSearchText: (text: string) => void;
|
handleSearchText: (text: string) => void;
|
||||||
onGlossaryDelete: (id: string) => void;
|
onGlossaryDelete: (id: string) => void;
|
||||||
onGlossaryTermDelete: (id: string) => void;
|
onGlossaryTermDelete: (id: string) => void;
|
||||||
onAssetPaginate: (num: number) => void;
|
onAssetPaginate: (num: number) => void;
|
||||||
isChildLoading: boolean;
|
isChildLoading: boolean;
|
||||||
// handlePathChange: (
|
|
||||||
// glossary: string,
|
|
||||||
// glossaryTermsFQN?: string | undefined
|
|
||||||
// ) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ModifiedDataNode = DataNode & {
|
|
||||||
data: Glossary | GlossaryTerm;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const GlossaryV1 = ({
|
const GlossaryV1 = ({
|
||||||
@ -163,14 +151,8 @@ Props) => {
|
|||||||
const key = node.key as string;
|
const key = node.key as string;
|
||||||
if (selectedKey !== key) {
|
if (selectedKey !== key) {
|
||||||
handleChildLoading(true);
|
handleChildLoading(true);
|
||||||
const breadCrumbData = (treeRef.current?.state.keyEntities[key].nodes ||
|
handleSelectedData(key);
|
||||||
[]) as ModifiedDataNode[];
|
|
||||||
const selData = breadCrumbData[breadCrumbData.length - 1].data;
|
|
||||||
const pos = treeRef.current?.state.keyEntities[key].pos;
|
|
||||||
handleSelectedData(selData, pos as string, key);
|
|
||||||
}
|
}
|
||||||
// handlePathChange(key.split('.')[0], key);
|
|
||||||
// handleSelectedKey(key);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -295,8 +295,14 @@ export const getUserPath = (username: string) => {
|
|||||||
return path;
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getGlossaryPath = () => {
|
export const getGlossaryPath = (fqn?: string) => {
|
||||||
return ROUTES.GLOSSARY;
|
let path = ROUTES.GLOSSARY;
|
||||||
|
if (fqn) {
|
||||||
|
path = ROUTES.GLOSSARY_DETAILS;
|
||||||
|
path = path.replace(PLACEHOLDER_GLOSSARY_NAME, fqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getGlossaryTermsPath = (
|
export const getGlossaryTermsPath = (
|
||||||
|
31
openmetadata-ui/src/main/resources/ui/src/jsons/en.ts
Normal file
31
openmetadata-ui/src/main/resources/ui/src/jsons/en.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const jsonData = {
|
||||||
|
'api-error-messages': {
|
||||||
|
'add-glossary-error': 'Error while adding glossary!',
|
||||||
|
'add-glossary-term-error': 'Error while adding glossary term!',
|
||||||
|
'delete-glossary-error': 'Error while deleting glossary!',
|
||||||
|
'delete-glossary-term-error': 'Error while deleting glossary term!',
|
||||||
|
'elastic-search-error': 'Error while fetch data from Elasticsearch!',
|
||||||
|
'fetch-data-error': 'Error while fetching data!',
|
||||||
|
'fetch-glossary-error': 'Error while fetching glossary!',
|
||||||
|
'fetch-glossary-list-error': 'Error while fetching glossaries!',
|
||||||
|
'fetch-glossary-term-error': 'Error while fetching glossary term!',
|
||||||
|
'fetch-tags-error': 'Error while fetching tags!',
|
||||||
|
'update-glossary-term-error': 'Error while updating glossary term!',
|
||||||
|
'update-description-error': 'Error while updating description!',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default jsonData;
|
@ -6,10 +6,11 @@ import { useAuthContext } from '../../auth-provider/AuthProvider';
|
|||||||
import { addGlossaries } from '../../axiosAPIs/glossaryAPI';
|
import { addGlossaries } from '../../axiosAPIs/glossaryAPI';
|
||||||
import AddGlossary from '../../components/AddGlossary/AddGlossary.component';
|
import AddGlossary from '../../components/AddGlossary/AddGlossary.component';
|
||||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||||
import { ROUTES } from '../../constants/constants';
|
import { getGlossaryPath } from '../../constants/constants';
|
||||||
import { CreateGlossary } from '../../generated/api/data/createGlossary';
|
import { CreateGlossary } from '../../generated/api/data/createGlossary';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import useToastContext from '../../hooks/useToastContext';
|
import useToastContext from '../../hooks/useToastContext';
|
||||||
|
import jsonData from '../../jsons/en';
|
||||||
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
|
import { getTagCategories, getTaglist } from '../../utils/TagsUtils';
|
||||||
|
|
||||||
const AddGlossaryPage: FunctionComponent = () => {
|
const AddGlossaryPage: FunctionComponent = () => {
|
||||||
@ -21,30 +22,44 @@ const AddGlossaryPage: FunctionComponent = () => {
|
|||||||
const [isTagLoading, setIsTagLoading] = useState<boolean>(false);
|
const [isTagLoading, setIsTagLoading] = useState<boolean>(false);
|
||||||
const [status, setStatus] = useState<LoadingState>('initial');
|
const [status, setStatus] = useState<LoadingState>('initial');
|
||||||
|
|
||||||
const goToGlossary = () => {
|
const goToGlossary = (name = '') => {
|
||||||
history.push(ROUTES.GLOSSARY);
|
history.push(getGlossaryPath(name));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
goToGlossary();
|
goToGlossary();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleShowErrorToast = (errMessage: string) => {
|
||||||
|
showToast({
|
||||||
|
variant: 'error',
|
||||||
|
body: errMessage,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveFailure = (errorMessage = '') => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
errorMessage || jsonData['api-error-messages']['add-glossary-error']
|
||||||
|
);
|
||||||
|
setStatus('initial');
|
||||||
|
};
|
||||||
|
|
||||||
const onSave = (data: CreateGlossary) => {
|
const onSave = (data: CreateGlossary) => {
|
||||||
setStatus('waiting');
|
setStatus('waiting');
|
||||||
addGlossaries(data)
|
addGlossaries(data)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
setStatus('success');
|
if (res.data) {
|
||||||
setTimeout(() => {
|
setStatus('success');
|
||||||
setStatus('initial');
|
setTimeout(() => {
|
||||||
goToGlossary();
|
setStatus('initial');
|
||||||
}, 500);
|
goToGlossary(res.data.name);
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
handleSaveFailure();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleSaveFailure(err.response?.data?.message);
|
||||||
variant: 'error',
|
|
||||||
body: err.message || 'Something went wrong!',
|
|
||||||
});
|
|
||||||
setStatus('initial');
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,7 +67,19 @@ const AddGlossaryPage: FunctionComponent = () => {
|
|||||||
setIsTagLoading(true);
|
setIsTagLoading(true);
|
||||||
getTagCategories()
|
getTagCategories()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setTagList(getTaglist(res.data));
|
if (res.data) {
|
||||||
|
setTagList(getTaglist(res.data));
|
||||||
|
} else {
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-tags-error']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: AxiosError) => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
err.response?.data?.message ||
|
||||||
|
jsonData['api-error-messages']['fetch-tags-error']
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setIsTagLoading(false);
|
setIsTagLoading(false);
|
||||||
|
@ -1,8 +1,27 @@
|
|||||||
import { findByText, render } from '@testing-library/react';
|
import { findByText, render } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import GlossaryPage from './GlossaryPage.component';
|
import GlossaryPageV1 from './GlossaryPageV1.component';
|
||||||
|
|
||||||
jest.mock('../../components/Glossary/Glossary.component', () => {
|
jest.mock('react-router-dom', () => ({
|
||||||
|
useHistory: jest.fn(),
|
||||||
|
useParams: jest.fn().mockReturnValue({
|
||||||
|
glossaryName: 'GlossaryName',
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../auth-provider/AuthProvider', () => {
|
||||||
|
return {
|
||||||
|
useAuthContext: jest.fn(() => ({
|
||||||
|
isAuthDisabled: false,
|
||||||
|
isAuthenticated: true,
|
||||||
|
isProtectedRoute: jest.fn().mockReturnValue(true),
|
||||||
|
isTourRoute: jest.fn().mockReturnValue(false),
|
||||||
|
onLogoutHandler: jest.fn(),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.mock('../../components/Glossary/GlossaryV1.component', () => {
|
||||||
return jest.fn().mockReturnValue(<div>Glossary.component</div>);
|
return jest.fn().mockReturnValue(<div>Glossary.component</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -12,7 +31,7 @@ jest.mock('../../axiosAPIs/glossaryAPI', () => ({
|
|||||||
|
|
||||||
describe('Test GlossaryComponent page', () => {
|
describe('Test GlossaryComponent page', () => {
|
||||||
it('GlossaryComponent Page Should render', async () => {
|
it('GlossaryComponent Page Should render', async () => {
|
||||||
const { container } = render(<GlossaryPage />);
|
const { container } = render(<GlossaryPageV1 />);
|
||||||
|
|
||||||
const glossaryComponent = await findByText(
|
const glossaryComponent = await findByText(
|
||||||
container,
|
container,
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
import { AxiosError, AxiosResponse } from 'axios';
|
import { AxiosError, AxiosResponse } from 'axios';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { cloneDeep, extend } from 'lodash';
|
import { cloneDeep, extend, isEmpty } from 'lodash';
|
||||||
import {
|
import {
|
||||||
FormattedGlossarySuggestion,
|
FormattedGlossarySuggestion,
|
||||||
GlossarySuggestionHit,
|
GlossarySuggestionHit,
|
||||||
@ -22,7 +22,7 @@ import {
|
|||||||
SearchResponse,
|
SearchResponse,
|
||||||
} from 'Models';
|
} from 'Models';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { useAuthContext } from '../../auth-provider/AuthProvider';
|
import { useAuthContext } from '../../auth-provider/AuthProvider';
|
||||||
import {
|
import {
|
||||||
deleteGlossary,
|
deleteGlossary,
|
||||||
@ -38,6 +38,7 @@ import GlossaryV1 from '../../components/Glossary/GlossaryV1.component';
|
|||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
import {
|
import {
|
||||||
getAddGlossaryTermsPath,
|
getAddGlossaryTermsPath,
|
||||||
|
getGlossaryPath,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
@ -47,11 +48,14 @@ import { Glossary } from '../../generated/entity/data/glossary';
|
|||||||
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import useToastContext from '../../hooks/useToastContext';
|
import useToastContext from '../../hooks/useToastContext';
|
||||||
|
import jsonData from '../../jsons/en';
|
||||||
import { formatDataResponse } from '../../utils/APIUtils';
|
import { formatDataResponse } from '../../utils/APIUtils';
|
||||||
import {
|
import {
|
||||||
getChildGlossaryTerms,
|
getChildGlossaryTerms,
|
||||||
getGlossariesWithRootTerms,
|
getGlossariesWithRootTerms,
|
||||||
getHierarchicalKeysByFQN,
|
getHierarchicalKeysByFQN,
|
||||||
|
getTermDataFromGlossary,
|
||||||
|
getTermPosFromGlossaries,
|
||||||
updateGlossaryListBySearchedTerms,
|
updateGlossaryListBySearchedTerms,
|
||||||
} from '../../utils/GlossaryUtils';
|
} from '../../utils/GlossaryUtils';
|
||||||
|
|
||||||
@ -60,8 +64,7 @@ export type ModifiedGlossaryData = Glossary & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const GlossaryPageV1 = () => {
|
const GlossaryPageV1 = () => {
|
||||||
// const { glossaryName, glossaryTermsFQN } =
|
const { glossaryName } = useParams<Record<string, string>>();
|
||||||
// useParams<{ [key: string]: string }>();
|
|
||||||
|
|
||||||
const { isAdminUser } = useAuth();
|
const { isAdminUser } = useAuth();
|
||||||
const { isAuthDisabled } = useAuthContext();
|
const { isAuthDisabled } = useAuthContext();
|
||||||
@ -88,6 +91,13 @@ const GlossaryPageV1 = () => {
|
|||||||
currPage: 1,
|
currPage: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleShowErrorToast = (errMessage: string) => {
|
||||||
|
showToast({
|
||||||
|
variant: 'error',
|
||||||
|
body: errMessage,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleChildLoading = (status: boolean) => {
|
const handleChildLoading = (status: boolean) => {
|
||||||
setIsChildLoading(status);
|
setIsChildLoading(status);
|
||||||
};
|
};
|
||||||
@ -100,6 +110,16 @@ const GlossaryPageV1 = () => {
|
|||||||
setExpandedKey(key);
|
setExpandedKey(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSearchText = (text: string) => {
|
||||||
|
setSearchText(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects glossary after fetching list
|
||||||
|
* if no fqn is present in route params
|
||||||
|
* @param data Glossary to be selected initially
|
||||||
|
* @param noSetData bool to decide if data is already set
|
||||||
|
*/
|
||||||
const initSelectGlossary = (data: Glossary, noSetData = false) => {
|
const initSelectGlossary = (data: Glossary, noSetData = false) => {
|
||||||
if (!noSetData) {
|
if (!noSetData) {
|
||||||
setSelectedData(data);
|
setSelectedData(data);
|
||||||
@ -109,47 +129,24 @@ const GlossaryPageV1 = () => {
|
|||||||
setExpandedKey([data.name]);
|
setExpandedKey([data.name]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchGlossaryList = (paging = '') => {
|
/**
|
||||||
setIsLoading(true);
|
* To fetch glossary term data
|
||||||
getGlossariesWithRootTerms(paging, 100, ['owner', 'tags', 'reviewers'])
|
* @param fqn fullyQualifiedName of term
|
||||||
.then((data: ModifiedGlossaryData[]) => {
|
* @param pos hierarchical position of term in existing tree
|
||||||
if (data?.length) {
|
* @param arrGlossary list of available/fetched glossaries
|
||||||
setGlossaries(data);
|
*/
|
||||||
setGlossariesList(data);
|
|
||||||
initSelectGlossary(data[0]);
|
|
||||||
} else {
|
|
||||||
setGlossariesList([]);
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err: AxiosError) => {
|
|
||||||
showToast({
|
|
||||||
variant: 'error',
|
|
||||||
body: err.response?.data?.message ?? 'Something went wrong!',
|
|
||||||
});
|
|
||||||
setIsLoading(false);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
handleChildLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchGlossaryTermByName = (
|
const fetchGlossaryTermByName = (
|
||||||
name: string,
|
fqn: string,
|
||||||
pos: string[],
|
pos: number[],
|
||||||
key?: string
|
arrGlossary: ModifiedGlossaryData[]
|
||||||
) => {
|
) => {
|
||||||
getGlossaryTermByFQN(name, [
|
getGlossaryTermByFQN(fqn, ['children', 'relatedTerms', 'reviewers', 'tags'])
|
||||||
'children',
|
|
||||||
'relatedTerms',
|
|
||||||
'reviewers',
|
|
||||||
'tags',
|
|
||||||
])
|
|
||||||
.then(async (res: AxiosResponse) => {
|
.then(async (res: AxiosResponse) => {
|
||||||
const { data } = res;
|
const { data } = res;
|
||||||
if (data) {
|
if (data) {
|
||||||
const clonedGlossaryList = cloneDeep(glossariesList);
|
const clonedGlossaryList = cloneDeep(arrGlossary);
|
||||||
let treeNode = clonedGlossaryList[+pos[0]];
|
let treeNode = clonedGlossaryList[pos[0]];
|
||||||
|
|
||||||
for (let i = 1; i < pos.length; i++) {
|
for (let i = 1; i < pos.length; i++) {
|
||||||
if (treeNode.children) {
|
if (treeNode.children) {
|
||||||
treeNode = treeNode.children[+pos[i]] as ModifiedGlossaryData;
|
treeNode = treeNode.children[+pos[i]] as ModifiedGlossaryData;
|
||||||
@ -193,29 +190,188 @@ const GlossaryPageV1 = () => {
|
|||||||
extend(treeNode, { ...data, children });
|
extend(treeNode, { ...data, children });
|
||||||
|
|
||||||
setSelectedData(data);
|
setSelectedData(data);
|
||||||
if (key) {
|
if (fqn) {
|
||||||
handleSelectedKey(key);
|
if (!expandedKey.length) {
|
||||||
|
setExpandedKey(getHierarchicalKeysByFQN(fqn));
|
||||||
|
}
|
||||||
|
handleSelectedKey(fqn);
|
||||||
}
|
}
|
||||||
setGlossariesList(clonedGlossaryList);
|
setGlossariesList(clonedGlossaryList);
|
||||||
setIsGlossaryActive(false);
|
setIsGlossaryActive(false);
|
||||||
|
} else {
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-glossary-term-error']
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body:
|
jsonData['api-error-messages']['fetch-glossary-term-error']
|
||||||
err.response?.data?.message ??
|
);
|
||||||
'Error while fetching glossary terms!',
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
handleChildLoading(false);
|
handleChildLoading(false);
|
||||||
setLoadingKey((pre) => {
|
setLoadingKey((pre) => {
|
||||||
return pre.filter((item) => item !== key);
|
return pre.filter((item) => item !== fqn);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To fetch Assets using glossary term
|
||||||
|
* @param fqn fullyQualifiedName of term
|
||||||
|
* @param forceReset bool to reset the page to 1, incase of change in glossary term
|
||||||
|
*/
|
||||||
|
const fetchGlossaryTermAssets = (fqn: string, forceReset = false) => {
|
||||||
|
if (fqn) {
|
||||||
|
const tagName = fqn;
|
||||||
|
searchData(
|
||||||
|
'',
|
||||||
|
forceReset ? 1 : assetData.currPage,
|
||||||
|
PAGE_SIZE,
|
||||||
|
`(tags:"${tagName}")`,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
myDataSearchIndex
|
||||||
|
)
|
||||||
|
.then((res: SearchResponse) => {
|
||||||
|
const hits = res?.data?.hits?.hits;
|
||||||
|
if (hits?.length > 0) {
|
||||||
|
setAssetData((pre) => {
|
||||||
|
const data = formatDataResponse(hits);
|
||||||
|
const total = res.data.hits.total.value;
|
||||||
|
|
||||||
|
return forceReset
|
||||||
|
? {
|
||||||
|
data,
|
||||||
|
total,
|
||||||
|
currPage: 1,
|
||||||
|
}
|
||||||
|
: { ...pre, data, total };
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setAssetData((pre) => {
|
||||||
|
const data = [] as GlossaryTermAssets['data'];
|
||||||
|
const total = 0;
|
||||||
|
|
||||||
|
return forceReset
|
||||||
|
? {
|
||||||
|
data,
|
||||||
|
total,
|
||||||
|
currPage: 1,
|
||||||
|
}
|
||||||
|
: { ...pre, data, total };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: AxiosError) => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
err.response?.data?.message ||
|
||||||
|
jsonData['api-error-messages']['elastic-search-error']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setAssetData({ data: [], total: 0, currPage: 1 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To select data based on glossary or term name
|
||||||
|
* @param dataFQN fullyQualifiedName of glossary or term
|
||||||
|
* @param arrGlossary list of available/fetched glossaries
|
||||||
|
*/
|
||||||
|
const selectDataByFQN = (
|
||||||
|
dataFQN: string,
|
||||||
|
arrGlossary: ModifiedGlossaryData[]
|
||||||
|
) => {
|
||||||
|
handleChildLoading(true);
|
||||||
|
const hierarchy = getTermPosFromGlossaries(arrGlossary, dataFQN);
|
||||||
|
if (hierarchy.length < 2) {
|
||||||
|
setSelectedData(arrGlossary[hierarchy[0]]);
|
||||||
|
handleSelectedKey(dataFQN);
|
||||||
|
if (!expandedKey.length) {
|
||||||
|
setExpandedKey([dataFQN]);
|
||||||
|
}
|
||||||
|
setIsGlossaryActive(true);
|
||||||
|
setIsLoading(false);
|
||||||
|
handleChildLoading(false);
|
||||||
|
} else {
|
||||||
|
setLoadingKey((pre) => {
|
||||||
|
return !pre.includes(dataFQN) ? [...pre, dataFQN] : pre;
|
||||||
|
});
|
||||||
|
fetchGlossaryTermByName(dataFQN, hierarchy, arrGlossary);
|
||||||
|
fetchGlossaryTermAssets(dataFQN, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To check if glossary/term already exists and add to tree if they don't
|
||||||
|
* Then select the glossary/term by it's fqn
|
||||||
|
* @param arrGlossary list of available/fetched glossaries
|
||||||
|
* @param fqn fullyQualifiedName of glossary or term
|
||||||
|
*/
|
||||||
|
const checkAndFetchDataByFQN = (
|
||||||
|
arrGlossary: ModifiedGlossaryData[],
|
||||||
|
fqn: string
|
||||||
|
) => {
|
||||||
|
let modifiedData = cloneDeep(arrGlossary);
|
||||||
|
const arrFQN = getHierarchicalKeysByFQN(fqn);
|
||||||
|
const glossary: ModifiedGlossaryData | GlossaryTerm = modifiedData.find(
|
||||||
|
(item) => item.name === arrFQN[0]
|
||||||
|
) as ModifiedGlossaryData;
|
||||||
|
const data = getTermDataFromGlossary(glossary, fqn);
|
||||||
|
if (isEmpty(data)) {
|
||||||
|
modifiedData = updateGlossaryListBySearchedTerms(modifiedData, [
|
||||||
|
{ fqdn: arrFQN[arrFQN.length - 1] },
|
||||||
|
] as FormattedGlossarySuggestion[]);
|
||||||
|
}
|
||||||
|
selectDataByFQN(fqn, modifiedData);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To fetch the list of all glossaries,
|
||||||
|
* and check for selection if nested fqn available
|
||||||
|
* @param termFqn fullyQualifiedName of term
|
||||||
|
* @param paging cursor pagination
|
||||||
|
*/
|
||||||
|
const fetchGlossaryList = (termFqn = '', paging = '') => {
|
||||||
|
setIsLoading(true);
|
||||||
|
getGlossariesWithRootTerms(paging, 1000, ['owner', 'tags', 'reviewers'])
|
||||||
|
.then((data: ModifiedGlossaryData[]) => {
|
||||||
|
if (data?.length) {
|
||||||
|
setGlossaries(data);
|
||||||
|
setGlossariesList(data);
|
||||||
|
if (termFqn) {
|
||||||
|
checkAndFetchDataByFQN(data, termFqn);
|
||||||
|
} else {
|
||||||
|
initSelectGlossary(data[0]);
|
||||||
|
setIsLoading(false);
|
||||||
|
handleChildLoading(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setGlossariesList([]);
|
||||||
|
setIsLoading(false);
|
||||||
|
handleChildLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: AxiosError) => {
|
||||||
|
handleShowErrorToast(
|
||||||
|
err.response?.data?.message ||
|
||||||
|
jsonData['api-error-messages']['fetch-glossary-list-error']
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
|
handleChildLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To update glossary tree based on searched terms
|
||||||
|
* @param arrGlossaries list of glossaries
|
||||||
|
* @param newGlossaries set of glossaries present in searched terms
|
||||||
|
* @param searchedTerms list of formatted searched terms
|
||||||
|
*/
|
||||||
const getSearchedGlossaries = (
|
const getSearchedGlossaries = (
|
||||||
arrGlossaries: ModifiedGlossaryData[],
|
arrGlossaries: ModifiedGlossaryData[],
|
||||||
newGlossaries: string[],
|
newGlossaries: string[],
|
||||||
@ -247,6 +403,9 @@ const GlossaryPageV1 = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To fetch terms based on search text
|
||||||
|
*/
|
||||||
const fetchSearchedTerms = useCallback(() => {
|
const fetchSearchedTerms = useCallback(() => {
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
searchData(
|
searchData(
|
||||||
@ -298,6 +457,11 @@ const GlossaryPageV1 = () => {
|
|||||||
}
|
}
|
||||||
}, [searchText]);
|
}, [searchText]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To save updated glossary using patch method
|
||||||
|
* @param updatedData glossary with new values
|
||||||
|
* @returns promise of api response
|
||||||
|
*/
|
||||||
const saveUpdatedGlossaryData = (
|
const saveUpdatedGlossaryData = (
|
||||||
updatedData: Glossary
|
updatedData: Glossary
|
||||||
): Promise<AxiosResponse> => {
|
): Promise<AxiosResponse> => {
|
||||||
@ -309,6 +473,10 @@ const GlossaryPageV1 = () => {
|
|||||||
) as unknown as Promise<AxiosResponse>;
|
) as unknown as Promise<AxiosResponse>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To update glossary
|
||||||
|
* @param updatedData glossary with new values
|
||||||
|
*/
|
||||||
const updateGlossary = (updatedData: Glossary) => {
|
const updateGlossary = (updatedData: Glossary) => {
|
||||||
saveUpdatedGlossaryData(updatedData)
|
saveUpdatedGlossaryData(updatedData)
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
@ -337,17 +505,25 @@ const GlossaryPageV1 = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['update-description-error']
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body:
|
jsonData['api-error-messages']['update-description-error']
|
||||||
err.response?.data?.message ?? 'Error while updating description!',
|
);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To save updated glossary term using patch method
|
||||||
|
* @param updatedData glossary term with new values
|
||||||
|
* @returns promise of api response
|
||||||
|
*/
|
||||||
const saveUpdatedGlossaryTermData = (
|
const saveUpdatedGlossaryTermData = (
|
||||||
updatedData: GlossaryTerm
|
updatedData: GlossaryTerm
|
||||||
): Promise<AxiosResponse> => {
|
): Promise<AxiosResponse> => {
|
||||||
@ -359,20 +535,33 @@ const GlossaryPageV1 = () => {
|
|||||||
) as unknown as Promise<AxiosResponse>;
|
) as unknown as Promise<AxiosResponse>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To update glossary term
|
||||||
|
* @param updatedData glossary term with new values
|
||||||
|
*/
|
||||||
const handleGlossaryTermUpdate = (updatedData: GlossaryTerm) => {
|
const handleGlossaryTermUpdate = (updatedData: GlossaryTerm) => {
|
||||||
saveUpdatedGlossaryTermData(updatedData)
|
saveUpdatedGlossaryTermData(updatedData)
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
setSelectedData(res.data);
|
if (res.data) {
|
||||||
|
setSelectedData(res.data);
|
||||||
|
} else {
|
||||||
|
handleShowErrorToast(
|
||||||
|
jsonData['api-error-messages']['update-glossary-term-error']
|
||||||
|
);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body:
|
jsonData['api-error-messages']['update-glossary-term-error']
|
||||||
err.response?.data?.message ?? 'Error while updating glossaryTerm!',
|
);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To delete glossary by id
|
||||||
|
* @param id glossary id
|
||||||
|
*/
|
||||||
const handleGlossaryDelete = (id: string) => {
|
const handleGlossaryDelete = (id: string) => {
|
||||||
setDeleteStatus('waiting');
|
setDeleteStatus('waiting');
|
||||||
deleteGlossary(id)
|
deleteGlossary(id)
|
||||||
@ -381,14 +570,18 @@ const GlossaryPageV1 = () => {
|
|||||||
fetchGlossaryList();
|
fetchGlossaryList();
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body: err.response?.data?.message ?? 'Something went wrong!',
|
jsonData['api-error-messages']['delete-glossary-error']
|
||||||
});
|
);
|
||||||
setDeleteStatus('initial');
|
setDeleteStatus('initial');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To delete glossary term by id
|
||||||
|
* @param id glossary term id
|
||||||
|
*/
|
||||||
const handleGlossaryTermDelete = (id: string) => {
|
const handleGlossaryTermDelete = (id: string) => {
|
||||||
setDeleteStatus('waiting');
|
setDeleteStatus('waiting');
|
||||||
deleteGlossaryTerm(id)
|
deleteGlossaryTerm(id)
|
||||||
@ -397,18 +590,24 @@ const GlossaryPageV1 = () => {
|
|||||||
fetchGlossaryList();
|
fetchGlossaryList();
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
handleShowErrorToast(
|
||||||
variant: 'error',
|
err.response?.data?.message ||
|
||||||
body: err.response?.data?.message ?? 'Something went wrong!',
|
jsonData['api-error-messages']['delete-glossary-term-error']
|
||||||
});
|
);
|
||||||
setDeleteStatus('initial');
|
setDeleteStatus('initial');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To redirect to add glossary page
|
||||||
|
*/
|
||||||
const handleAddGlossaryClick = () => {
|
const handleAddGlossaryClick = () => {
|
||||||
history.push(ROUTES.ADD_GLOSSARY);
|
history.push(ROUTES.ADD_GLOSSARY);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To redirct to add glossary term page
|
||||||
|
*/
|
||||||
const handleAddGlossaryTermClick = () => {
|
const handleAddGlossaryTermClick = () => {
|
||||||
const activeTerm = selectedKey.split('.');
|
const activeTerm = selectedKey.split('.');
|
||||||
const glossaryName = activeTerm[0];
|
const glossaryName = activeTerm[0];
|
||||||
@ -419,88 +618,39 @@ const GlossaryPageV1 = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchGlossaryTermAssets = (data: GlossaryTerm, forceReset = false) => {
|
/**
|
||||||
if (data?.fullyQualifiedName || data?.name) {
|
* handle assets page change
|
||||||
const tagName = data?.fullyQualifiedName || data?.name; // Incase fqn is not fetched yet.
|
* @param page new page number
|
||||||
searchData(
|
*/
|
||||||
'',
|
|
||||||
forceReset ? 1 : assetData.currPage,
|
|
||||||
PAGE_SIZE,
|
|
||||||
`(tags:"${tagName}")`,
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
myDataSearchIndex
|
|
||||||
).then((res: SearchResponse) => {
|
|
||||||
const hits = res.data.hits.hits;
|
|
||||||
if (hits.length > 0) {
|
|
||||||
setAssetData((pre) => {
|
|
||||||
const data = formatDataResponse(hits);
|
|
||||||
const total = res.data.hits.total.value;
|
|
||||||
|
|
||||||
return forceReset
|
|
||||||
? {
|
|
||||||
data,
|
|
||||||
total,
|
|
||||||
currPage: 1,
|
|
||||||
}
|
|
||||||
: { ...pre, data, total };
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setAssetData((pre) => {
|
|
||||||
const data = [] as GlossaryTermAssets['data'];
|
|
||||||
const total = 0;
|
|
||||||
|
|
||||||
return forceReset
|
|
||||||
? {
|
|
||||||
data,
|
|
||||||
total,
|
|
||||||
currPage: 1,
|
|
||||||
}
|
|
||||||
: { ...pre, data, total };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setAssetData({ data: [], total: 0, currPage: 1 });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAssetPagination = (page: number) => {
|
const handleAssetPagination = (page: number) => {
|
||||||
setAssetData((pre) => ({ ...pre, currPage: page }));
|
setAssetData((pre) => ({ ...pre, currPage: page }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectedData = (
|
/**
|
||||||
data: Glossary | GlossaryTerm,
|
* handle route change on selecting glossary or glossary term
|
||||||
pos: string,
|
* @param key fqn of glossary or Term
|
||||||
key: string
|
*/
|
||||||
) => {
|
const handleSelectedData = (key: string) => {
|
||||||
handleChildLoading(true);
|
const path = getGlossaryPath(key);
|
||||||
const hierarchy = pos.split('-').splice(1);
|
history.push(path);
|
||||||
// console.log(hierarchy);
|
};
|
||||||
if (hierarchy.length < 2) {
|
|
||||||
setSelectedData(data);
|
/**
|
||||||
handleSelectedKey(key);
|
* Fetch details to show based on route params
|
||||||
setIsGlossaryActive(true);
|
* and existing data list
|
||||||
handleChildLoading(false);
|
*/
|
||||||
|
const fetchData = () => {
|
||||||
|
if (glossariesList.length) {
|
||||||
|
checkAndFetchDataByFQN(glossariesList, glossaryName);
|
||||||
} else {
|
} else {
|
||||||
setLoadingKey((pre) => {
|
fetchGlossaryList(glossaryName);
|
||||||
return !pre.includes(key) ? [...pre, key] : pre;
|
|
||||||
});
|
|
||||||
fetchGlossaryTermByName(
|
|
||||||
(data as GlossaryTerm)?.fullyQualifiedName || data?.name,
|
|
||||||
hierarchy,
|
|
||||||
key
|
|
||||||
);
|
|
||||||
fetchGlossaryTermAssets(data as GlossaryTerm, true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchText = (text: string) => {
|
|
||||||
setSearchText(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchGlossaryTermAssets(selectedData as GlossaryTerm);
|
fetchGlossaryTermAssets(
|
||||||
|
(selectedData as GlossaryTerm)?.fullyQualifiedName || ''
|
||||||
|
);
|
||||||
}, [assetData.currPage]);
|
}, [assetData.currPage]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -508,8 +658,8 @@ const GlossaryPageV1 = () => {
|
|||||||
}, [searchText]);
|
}, [searchText]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchGlossaryList();
|
fetchData();
|
||||||
}, []);
|
}, [glossaryName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainerV1 className="tw-pt-4">
|
<PageContainerV1 className="tw-pt-4">
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { AxiosError, AxiosResponse } from 'axios';
|
import { AxiosError, AxiosResponse } from 'axios';
|
||||||
|
import { cloneDeep, isEmpty } from 'lodash';
|
||||||
import {
|
import {
|
||||||
FormattedGlossarySuggestion,
|
FormattedGlossarySuggestion,
|
||||||
FormattedGlossaryTermData,
|
FormattedGlossaryTermData,
|
||||||
@ -37,6 +38,10 @@ export interface GlossaryTermTreeNode {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get all glossary terms
|
||||||
|
* @returns promise of list of formatted glossary terms
|
||||||
|
*/
|
||||||
export const fetchGlossaryTerms = (): Promise<FormattedGlossaryTermData[]> => {
|
export const fetchGlossaryTerms = (): Promise<FormattedGlossaryTermData[]> => {
|
||||||
return new Promise<FormattedGlossaryTermData[]>((resolve, reject) => {
|
return new Promise<FormattedGlossaryTermData[]>((resolve, reject) => {
|
||||||
searchData(WILD_CARD_CHAR, 1, 1000, '', '', '', SearchIndex.GLOSSARY)
|
searchData(WILD_CARD_CHAR, 1, 1000, '', '', '', SearchIndex.GLOSSARY)
|
||||||
@ -50,12 +55,22 @@ export const fetchGlossaryTerms = (): Promise<FormattedGlossaryTermData[]> => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get list of fqns from list of glossary terms
|
||||||
|
* @param terms formatted glossary terms
|
||||||
|
* @returns list of term fqns
|
||||||
|
*/
|
||||||
export const getGlossaryTermlist = (
|
export const getGlossaryTermlist = (
|
||||||
terms: Array<FormattedGlossaryTermData> = []
|
terms: Array<FormattedGlossaryTermData> = []
|
||||||
): Array<string> => {
|
): Array<string> => {
|
||||||
return terms.map((term: FormattedGlossaryTermData) => term?.fqdn);
|
return terms.map((term: FormattedGlossaryTermData) => term?.fqdn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get child terms of any node if available
|
||||||
|
* @param listTermFQN fqn of targeted child terms
|
||||||
|
* @returns promise of list of glossary terms
|
||||||
|
*/
|
||||||
export const getChildGlossaryTerms = (
|
export const getChildGlossaryTerms = (
|
||||||
listTermFQN: Array<string>
|
listTermFQN: Array<string>
|
||||||
): Promise<GlossaryTerm[]> => {
|
): Promise<GlossaryTerm[]> => {
|
||||||
@ -76,6 +91,11 @@ export const getChildGlossaryTerms = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To recursively generate RcTree data from glossary list
|
||||||
|
* @param data list of glossary or glossary terms
|
||||||
|
* @returns RcTree data node
|
||||||
|
*/
|
||||||
export const generateTreeData = (data: ModifiedGlossaryData[]): DataNode[] => {
|
export const generateTreeData = (data: ModifiedGlossaryData[]): DataNode[] => {
|
||||||
return data.map((d) => {
|
return data.map((d) => {
|
||||||
return d.children?.length
|
return d.children?.length
|
||||||
@ -93,6 +113,13 @@ export const generateTreeData = (data: ModifiedGlossaryData[]): DataNode[] => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates glossary term tree node from fqn
|
||||||
|
* and root node name
|
||||||
|
* @param leafFqn node fqn
|
||||||
|
* @param name root node name
|
||||||
|
* @returns node for glossary tree
|
||||||
|
*/
|
||||||
const createGlossaryTermNode = (
|
const createGlossaryTermNode = (
|
||||||
leafFqn: string,
|
leafFqn: string,
|
||||||
name: string
|
name: string
|
||||||
@ -112,6 +139,12 @@ const createGlossaryTermNode = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To merge the duplicate glossaries and terms
|
||||||
|
* to generate optimised tree
|
||||||
|
* @param treeNodes list of glossary nodes with duplicate items
|
||||||
|
* @returns list of glossary nodes with unique items
|
||||||
|
*/
|
||||||
const optimiseGlossaryTermTree = (treeNodes?: GlossaryTermTreeNode[]) => {
|
const optimiseGlossaryTermTree = (treeNodes?: GlossaryTermTreeNode[]) => {
|
||||||
if (treeNodes) {
|
if (treeNodes) {
|
||||||
for (let i = 0; i < treeNodes.length; i++) {
|
for (let i = 0; i < treeNodes.length; i++) {
|
||||||
@ -139,6 +172,11 @@ const optimiseGlossaryTermTree = (treeNodes?: GlossaryTermTreeNode[]) => {
|
|||||||
return treeNodes;
|
return treeNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To generate glossry tree from searched terms
|
||||||
|
* @param searchedTerms list of formatted searched terms
|
||||||
|
* @returns list of glossary tree
|
||||||
|
*/
|
||||||
export const getSearchedGlossaryTermTree = (
|
export const getSearchedGlossaryTermTree = (
|
||||||
searchedTerms: FormattedGlossarySuggestion[]
|
searchedTerms: FormattedGlossarySuggestion[]
|
||||||
): GlossaryTermTreeNode[] => {
|
): GlossaryTermTreeNode[] => {
|
||||||
@ -153,6 +191,12 @@ export const getSearchedGlossaryTermTree = (
|
|||||||
return termTree;
|
return termTree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get Tree of glossaries based on search result
|
||||||
|
* @param glossaries list of glossaries
|
||||||
|
* @param searchedTerms list of formatted searched terms
|
||||||
|
* @returns glossary list based on searched terms
|
||||||
|
*/
|
||||||
export const updateGlossaryListBySearchedTerms = (
|
export const updateGlossaryListBySearchedTerms = (
|
||||||
glossaries: ModifiedGlossaryData[],
|
glossaries: ModifiedGlossaryData[],
|
||||||
searchedTerms: FormattedGlossarySuggestion[]
|
searchedTerms: FormattedGlossarySuggestion[]
|
||||||
@ -171,6 +215,10 @@ export const updateGlossaryListBySearchedTerms = (
|
|||||||
}, [] as ModifiedGlossaryData[]);
|
}, [] as ModifiedGlossaryData[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get actions for action dropdown button
|
||||||
|
* @returns list of action items
|
||||||
|
*/
|
||||||
export const getActionsList = () => {
|
export const getActionsList = () => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -180,6 +228,12 @@ export const getActionsList = () => {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get hierarchy of fqns from glossary to targeted term
|
||||||
|
* from given fqn
|
||||||
|
* @param fqn fqn of glossary or glossary term
|
||||||
|
* @returns list of fqns
|
||||||
|
*/
|
||||||
export const getHierarchicalKeysByFQN = (fqn: string) => {
|
export const getHierarchicalKeysByFQN = (fqn: string) => {
|
||||||
const keys = fqn.split('.').reduce((prev, curr) => {
|
const keys = fqn.split('.').reduce((prev, curr) => {
|
||||||
const currFqn = prev.length ? `${prev[prev.length - 1]}.${curr}` : curr;
|
const currFqn = prev.length ? `${prev[prev.length - 1]}.${curr}` : curr;
|
||||||
@ -190,12 +244,80 @@ export const getHierarchicalKeysByFQN = (fqn: string) => {
|
|||||||
return keys;
|
return keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get glossary term data from glossary object
|
||||||
|
* @param glossary parent glossary
|
||||||
|
* @param termFqn fqn of targeted glossary term
|
||||||
|
* @returns Glossary term or {}
|
||||||
|
*/
|
||||||
|
export const getTermDataFromGlossary = (
|
||||||
|
glossary: ModifiedGlossaryData,
|
||||||
|
termFqn: string
|
||||||
|
) => {
|
||||||
|
let data: ModifiedGlossaryData | GlossaryTerm = cloneDeep(glossary);
|
||||||
|
const arrFQN = getHierarchicalKeysByFQN(termFqn);
|
||||||
|
for (let i = 1; i < arrFQN.length; i++) {
|
||||||
|
data = data?.children
|
||||||
|
? ((data.children as unknown as GlossaryTerm[])?.find(
|
||||||
|
(item) =>
|
||||||
|
item.fullyQualifiedName === arrFQN[i] || item.name === arrFQN[i]
|
||||||
|
) as GlossaryTerm)
|
||||||
|
: ({} as GlossaryTerm);
|
||||||
|
if (isEmpty(data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get relative indexed position of
|
||||||
|
* glossary term from tree of glossaries
|
||||||
|
* @param arrGlossary list of glossary
|
||||||
|
* @param termFqn fqn of target glossary term
|
||||||
|
* @returns array of numbered positions
|
||||||
|
*/
|
||||||
|
export const getTermPosFromGlossaries = (
|
||||||
|
arrGlossary: ModifiedGlossaryData[],
|
||||||
|
termFqn: string
|
||||||
|
) => {
|
||||||
|
const arrFQN = getHierarchicalKeysByFQN(termFqn);
|
||||||
|
const glossaryIdx = arrGlossary.findIndex((item) => item.name === arrFQN[0]);
|
||||||
|
const pos = [];
|
||||||
|
if (glossaryIdx !== -1) {
|
||||||
|
pos.push(glossaryIdx);
|
||||||
|
let data: ModifiedGlossaryData | GlossaryTerm = arrGlossary[glossaryIdx];
|
||||||
|
for (let i = 1; i < arrFQN.length; i++) {
|
||||||
|
const index = data?.children
|
||||||
|
? (data.children as unknown as GlossaryTerm[])?.findIndex(
|
||||||
|
(item) =>
|
||||||
|
item.fullyQualifiedName === arrFQN[i] || item.name === arrFQN[i]
|
||||||
|
)
|
||||||
|
: -1;
|
||||||
|
|
||||||
|
if (index === -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data = (data?.children ? data?.children[index] : {}) as GlossaryTerm;
|
||||||
|
pos.push(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches and adds root terms to each glossary
|
||||||
|
* @param glossaries list of glossaries
|
||||||
|
* @returns promise of list of glossaries with root terms
|
||||||
|
*/
|
||||||
const getRootTermEmbeddedGlossary = (
|
const getRootTermEmbeddedGlossary = (
|
||||||
glossaries: Array<ModifiedGlossaryData>
|
glossaries: Array<ModifiedGlossaryData>
|
||||||
): Promise<Array<ModifiedGlossaryData>> => {
|
): Promise<Array<ModifiedGlossaryData>> => {
|
||||||
return new Promise<Array<ModifiedGlossaryData>>((resolve, reject) => {
|
return new Promise<Array<ModifiedGlossaryData>>((resolve, reject) => {
|
||||||
const promises = glossaries.map((glossary) =>
|
const promises = glossaries.map((glossary) =>
|
||||||
getGlossaryTerms(glossary.id, 100, [
|
getGlossaryTerms(glossary.id, 1000, [
|
||||||
'children',
|
'children',
|
||||||
'relatedTerms',
|
'relatedTerms',
|
||||||
'reviewers',
|
'reviewers',
|
||||||
@ -222,6 +344,13 @@ const getRootTermEmbeddedGlossary = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches list of glossaries with root terms in each of them
|
||||||
|
* @param paging pagination cursor
|
||||||
|
* @param limit result count
|
||||||
|
* @param arrQueryFields api query-string
|
||||||
|
* @returns promise of api response
|
||||||
|
*/
|
||||||
export const getGlossariesWithRootTerms = (
|
export const getGlossariesWithRootTerms = (
|
||||||
paging = '',
|
paging = '',
|
||||||
limit = 10,
|
limit = 10,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user