This is an automated email from the ASF dual-hosted git repository. pawarprasad123 pushed a commit to branch ATLAS-5246-v1 in repository https://gitbox.apache.org/repos/asf/atlas.git
commit 2ca44bb2c95832d20982ff2962f038572208d78c Author: Prasad Pawar <[email protected]> AuthorDate: Fri May 8 12:54:08 2026 +0530 ATLAS-5267: ATLAS UI: Create Glossary: Add Import glossary terms tab (template + upload) (#617) --- dashboard/src/components/ImportDialog.tsx | 44 +- dashboard/src/utils/apiErrorToastMessage.ts | 43 ++ dashboard/src/utils/glossaryImportFlow.ts | 57 +++ .../DetailPage/GlossaryDetails/TermRelation.tsx | 1 + .../src/views/Glossary/AddUpdateCategoryForm.tsx | 1 + .../src/views/Glossary/AddUpdateGlossaryForm.tsx | 450 ++++++++++++++++----- dashboard/src/views/Glossary/AddUpdateTermForm.tsx | 1 + dashboard/src/views/Glossary/AssignCategory.tsx | 1 + dashboard/src/views/Glossary/AssignTerm.tsx | 1 + dashboard/src/views/Glossary/DeleteGlossary.tsx | 52 +-- 10 files changed, 517 insertions(+), 134 deletions(-) diff --git a/dashboard/src/components/ImportDialog.tsx b/dashboard/src/components/ImportDialog.tsx index a3adfbb54..10d82aa1d 100644 --- a/dashboard/src/components/ImportDialog.tsx +++ b/dashboard/src/components/ImportDialog.tsx @@ -37,7 +37,8 @@ import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; -import { getGlossaryImport } from "../api/apiMethods/glossaryApiMethod"; +import { postGlossaryImportFormData } from "@utils/glossaryImportFlow"; +import { getApiErrorToastMessage } from "@utils/apiErrorToastMessage"; const BootstrapDialog = styled(Dialog)(({ theme }) => ({ "& .MuiDialogContent-root": { @@ -77,22 +78,27 @@ export const ImportDialog: React.FC<CustomModalProps> = ({ const onUpload = async () => { if (fileData) { try { - let apiMethod = + const onProgress = (progressValue: number) => { + setProgress(progressValue); + }; + const importResp = title == "Import Business Metadata" - ? getBusinessMetadataImport - : getGlossaryImport; - let formData = new FormData(); - formData.append("file", fileData); - const importResp = await apiMethod(formData, { - onUploadProgress: (progressEvent: { - loaded: number; - total: number; - }) => { - let progressValue = - (progressEvent.loaded / progressEvent.total) * 100; - setProgress(progressValue); - } - }); + ? await (async () => { + const formData = new FormData(); + formData.append("file", fileData); + return getBusinessMetadataImport(formData, { + onUploadProgress: (progressEvent: { + loaded: number; + total: number; + }) => { + if (!progressEvent.total) return; + onProgress( + (progressEvent.loaded / progressEvent.total) * 100 + ); + } + }); + })() + : await postGlossaryImportFormData(fileData, onProgress); if (importResp.data.failedImportInfoList == undefined) { toast.dismiss(toastId.current); @@ -114,8 +120,12 @@ export const ImportDialog: React.FC<CustomModalProps> = ({ } setImportData(importResp.data); } catch (error) { + const message = getApiErrorToastMessage(error); + if (message === null) { + return; + } toast.dismiss(toastId.current); - toastId.current = toast.error(`Invalid JSON response from server`); + toastId.current = toast.error(message); } } }; diff --git a/dashboard/src/utils/apiErrorToastMessage.ts b/dashboard/src/utils/apiErrorToastMessage.ts new file mode 100644 index 000000000..7afa98d0b --- /dev/null +++ b/dashboard/src/utils/apiErrorToastMessage.ts @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/** + * Resolves user-visible toast text from an axios/fetchApi error. + * @returns null when the caller must not toast (403 is handled in fetchApi). + */ +export const getApiErrorToastMessage = (error: unknown): string | null => { + const er = error as { + response?: { status?: number; data?: unknown }; + }; + if (er?.response?.status === 403) { + return null; + } + const data = er?.response?.data; + if (data !== null && data !== undefined && typeof data === "object") { + const o = data as Record<string, unknown>; + if (o.errorMessage != null && String(o.errorMessage).trim() !== "") { + return String(o.errorMessage); + } + if (o.msgDesc != null && String(o.msgDesc).trim() !== "") { + return String(o.msgDesc); + } + } + if (typeof data === "string" && data.trim() !== "") { + return data; + } + return "Invalid JSON response from server"; +}; diff --git a/dashboard/src/utils/glossaryImportFlow.ts b/dashboard/src/utils/glossaryImportFlow.ts new file mode 100644 index 000000000..a3f564050 --- /dev/null +++ b/dashboard/src/utils/glossaryImportFlow.ts @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 { + getGlossaryImport, + getGlossaryImportTmpl +} from '@api/apiMethods/glossaryApiMethod'; + +/** + * Same behavior as glossary branch of SideBarTree.downloadFile. + */ +export const downloadGlossaryImportTemplate = async (): Promise<void> => { + const apiResp = await getGlossaryImportTmpl({}); + const text = + apiResp && typeof apiResp.data !== 'undefined' + ? String(apiResp.data) + : ''; + const blob = new Blob([text], { type: 'text/plain' }); + const url = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', 'template'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); +}; + +export const postGlossaryImportFormData = ( + file: File, + onUploadProgress?: (progressPercent: number) => void +) => { + const formData = new FormData(); + formData.append('file', file); + return getGlossaryImport(formData, { + onUploadProgress: (progressEvent: { loaded: number; total: number }) => { + if (!onUploadProgress || !progressEvent.total) return; + const progressValue = + (progressEvent.loaded / progressEvent.total) * 100; + onUploadProgress(progressValue); + } + }); +}; diff --git a/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx b/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx index ba1381528..68d069ea7 100644 --- a/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx +++ b/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx @@ -219,6 +219,7 @@ const TermRelation = ({ glossaryTypeData }: any) => { button2Label={editModal ? "Update" : "Close"} button2Handler={editModal ? handleSubmit(onSubmit) : handleCloseModal} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="md" > <form onSubmit={handleSubmit(onSubmit)}> diff --git a/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx b/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx index 12a80b6de..bd9084861 100644 --- a/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx @@ -146,6 +146,7 @@ const AddUpdateCategoryForm = (props: { button1Handler={onClose} button2Label={isAdd ? "Create" : "Update"} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="sm" button2Handler={handleSubmit(onSubmit)} > diff --git a/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx b/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx index 4aa2248d1..5f4a22854 100644 --- a/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx @@ -19,108 +19,370 @@ import CustomModal from "@components/Modal"; import GlossaryForm from "./GlossaryForm"; import { useForm } from "react-hook-form"; import { - createGlossary, - editGlossary + createGlossary, + editGlossary } from "@api/apiMethods/glossaryApiMethod"; import { isEmpty, serverError } from "@utils/Utils"; +import { + downloadGlossaryImportTemplate, + postGlossaryImportFormData +} from "@utils/glossaryImportFlow"; +import { getApiErrorToastMessage } from "@utils/apiErrorToastMessage"; import { toast } from "react-toastify"; -import { useRef } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import type { MouseEvent } from "react"; import { useAppDispatch, useAppSelector } from "@hooks/reducerHook"; import { fetchGlossaryData } from "@redux/slice/glossarySlice"; +import { + Button, + IconButton, + List, + ListItem, + ListItemText, + Stack, + ToggleButton, + ToggleButtonGroup +} from "@mui/material"; +import FileDownloadIcon from "@mui/icons-material/FileDownload"; +import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; +import ImportLayout from "@views/SideBar/Import/ImportLayout"; +import { LightTooltip } from "@components/muiComponents"; + +type GlossaryCreateTab = "create" | "import"; + +const hasSelectedImportFile = (fileData: unknown): boolean => { + if (fileData == null) return false; + if (fileData instanceof File) return true; + if (typeof fileData === "object" && Object.keys(fileData as object).length > 0) + return true; + return false; +}; const AddUpdateGlossaryForm = (props: { - open: any; - onClose: any; - isAdd: any; - node: Record<string, any> | undefined; + open: any; + onClose: any; + isAdd: any; + node: Record<string, any> | undefined; }) => { - const { open, onClose, isAdd, node } = props; - const dispatch = useAppDispatch(); - const toastId: any = useRef(null); - const { glossaryData }: any = useAppSelector((state: any) => state.glossary); - const { id } = node || {}; - let defaultValue: Record<string, string> = {}; - let glossaryObj: Record<string, string> = {}; - if (!isAdd) { - glossaryObj = glossaryData.find((obj: { name: string }) => { - return obj.name == id; - }); - const { name, shortDescription, longDescription } = glossaryObj || {}; - - defaultValue["name"] = name; - defaultValue["shortDescription"] = shortDescription; - defaultValue["longDescription"] = longDescription; - } - const { - control, - handleSubmit, - setValue, - formState: { isSubmitting } - } = useForm({ - defaultValues: isAdd ? {} : defaultValue, - mode: "onChange", - shouldUnregister: true - }); - - const onSubmit = async (formValues: any) => { - let formData = { ...formValues }; - const { guid, qualifiedName } = glossaryObj; - const { - name, - shortDescription, - longDescription - }: { name: string; shortDescription: string; longDescription: string } = - formData; - let data: Record<string, string> = {}; - if (!isAdd) { - data["guid"] = guid; - data["qualifiedName"] = qualifiedName; - } - data["name"] = name; - data["shortDescription"] = !isEmpty(shortDescription) - ? shortDescription - : ""; - data["longDescription"] = !isEmpty(longDescription) ? longDescription : ""; - - try { - if (isAdd) { - await createGlossary(data); - } else { - await editGlossary(guid, data); - } - - await dispatch(fetchGlossaryData()); - toast.dismiss(toastId.current); - toastId.current = toast.success( - `Glossary ${name} was ${isAdd ? "created" : "updated"} successfully` - ); - onClose(); - } catch (error) { - serverError(error, toastId); - } - }; - - return ( - <> - <CustomModal - open={open} - onClose={onClose} - title={isAdd ? "Create Glossary" : "Edit Glossary"} - button1Label="Cancel" - button1Handler={onClose} - button2Label={isAdd ? "Create" : "Update"} - maxWidth="sm" - button2Handler={handleSubmit(onSubmit)} - disableButton2={isSubmitting} - > - <GlossaryForm - control={control} - handleSubmit={handleSubmit(onSubmit)} - setValue={setValue} - /> - </CustomModal> - </> - ); + const { open, onClose, isAdd, node } = props; + const dispatch = useAppDispatch(); + const toastId: any = useRef(null); + const { glossaryData }: any = useAppSelector((state: any) => state.glossary); + const { id } = node || {}; + let defaultValue: Record<string, string> = {}; + let glossaryObj: Record<string, string> = {}; + if (!isAdd) { + glossaryObj = glossaryData.find((obj: { name: string }) => { + return obj.name == id; + }); + const { name, shortDescription, longDescription } = glossaryObj || {}; + + defaultValue["name"] = name; + defaultValue["shortDescription"] = shortDescription; + defaultValue["longDescription"] = longDescription; + } + const { + control, + handleSubmit, + setValue, + formState: { isSubmitting } + } = useForm({ + defaultValues: isAdd ? {} : defaultValue, + mode: "onChange", + shouldUnregister: true + }); + + const [glossaryCreateTab, setGlossaryCreateTab] = + useState<GlossaryCreateTab>("create"); + const [importFileData, setImportFileData] = useState<any>([]); + const [importProgress, setImportProgress] = useState(0); + const [importErrorDetails, setImportErrorDetails] = useState(false); + const [importData, setImportData] = useState<any>(null); + const [importUploading, setImportUploading] = useState(false); + + const resetImportUi = useCallback(() => { + setGlossaryCreateTab("create"); + setImportFileData([]); + setImportProgress(0); + setImportErrorDetails(false); + setImportData(null); + setImportUploading(false); + }, []); + + const handleModalClose = useCallback(() => { + resetImportUi(); + onClose(); + }, [onClose, resetImportUi]); + + useEffect(() => { + if (!open) { + resetImportUi(); + } + }, [open, resetImportUi]); + + const handleGlossaryCreateTabChange = ( + _event: MouseEvent<HTMLElement>, + next: GlossaryCreateTab | null + ) => { + if (next == null) return; + setGlossaryCreateTab(next); + if (next === "create") { + setImportFileData([]); + setImportProgress(0); + setImportErrorDetails(false); + setImportData(null); + } + }; + + const handleDownloadTemplate = async () => { + try { + await downloadGlossaryImportTemplate(); + } catch { + toast.dismiss(toastId.current); + toastId.current = toast.error("Could not download template"); + } + }; + + const handleImportUpload = async () => { + if (!hasSelectedImportFile(importFileData)) return; + setImportUploading(true); + try { + const importResp = await postGlossaryImportFormData( + importFileData, + (pct) => setImportProgress(pct) + ); + if (importResp.data.failedImportInfoList == undefined) { + toast.dismiss(toastId.current); + toastId.current = toast.success( + `File: ${importFileData.name} imported successfully` + ); + await dispatch(fetchGlossaryData()); + handleModalClose(); + return; + } + if (importResp.data.failedImportInfoList != undefined) { + toast.dismiss(toastId.current); + toastId.current = toast.error( + importResp.data.failedImportInfoList[0].remarks + ); + setImportErrorDetails(true); + } + setImportData(importResp.data); + } catch (error) { + const message = getApiErrorToastMessage(error); + if (message === null) { + return; + } + toast.dismiss(toastId.current); + toastId.current = toast.error(message); + } finally { + setImportUploading(false); + } + }; + + const onSubmit = async (formValues: any) => { + let formData = { ...formValues }; + const { guid, qualifiedName } = glossaryObj; + const { + name, + shortDescription, + longDescription + }: { name: string; shortDescription: string; longDescription: string } = + formData; + let data: Record<string, string> = {}; + if (!isAdd) { + data["guid"] = guid; + data["qualifiedName"] = qualifiedName; + } + data["name"] = name; + data["shortDescription"] = !isEmpty(shortDescription) + ? shortDescription + : ""; + data["longDescription"] = !isEmpty(longDescription) ? longDescription : ""; + + try { + if (isAdd) { + await createGlossary(data); + } else { + await editGlossary(guid, data); + } + + await dispatch(fetchGlossaryData()); + toast.dismiss(toastId.current); + toastId.current = toast.success( + `Glossary ${name} was ${isAdd ? "created" : "updated"} successfully` + ); + handleModalClose(); + } catch (error) { + serverError(error, toastId); + } + }; + + const showImportError = isAdd && glossaryCreateTab === "import" && importErrorDetails; + + const modalTitle = showImportError + ? "Error Details" + : isAdd + ? "Create Glossary" + : "Edit Glossary"; + + const titleIconNode = + showImportError ? ( + <IconButton + aria-label="Back to import file" + onClick={(e) => { + e.stopPropagation(); + setImportErrorDetails(false); + }} + size="small" + sx={{ color: (theme) => theme.palette.grey[500] }} + > + <LightTooltip title="Back to import file"> + <ArrowBackIosNewIcon sx={{ fontSize: "1.25rem" }} /> + </LightTooltip> + </IconButton> + ) : undefined; + + const isImportMode = isAdd && glossaryCreateTab === "import" && !importErrorDetails; + + const button2Label = (() => { + if (!isAdd) return "Update"; + if (glossaryCreateTab === "create") return "Create"; + if (importErrorDetails) return ""; + return "Upload"; + })(); + + const button2Handler = (() => { + if (!isAdd || glossaryCreateTab === "create") return handleSubmit(onSubmit); + if (importErrorDetails) return () => {}; + return handleImportUpload; + })(); + + const disableButton2 = (() => { + if (!isAdd) return isSubmitting; + if (glossaryCreateTab === "create") return isSubmitting; + if (importErrorDetails) return true; + return !hasSelectedImportFile(importFileData); + })(); + + const button2Loading = + isAdd && glossaryCreateTab === "import" && !importErrorDetails + ? importUploading + : isSubmitting; + + const hideButton2 = Boolean( + isAdd && glossaryCreateTab === "import" && importErrorDetails + ); + + return ( + <> + <CustomModal + open={open} + onClose={handleModalClose} + title={modalTitle} + titleIcon={titleIconNode} + button1Label="Cancel" + button1Handler={handleModalClose} + button2Label={button2Label} + maxWidth="sm" + button2Handler={button2Handler} + disableButton2={disableButton2} + button2Loading={button2Loading} + hideButton2={hideButton2} + > + <Stack> + {isAdd && ( + <Stack marginBottom="1rem"> + <ToggleButtonGroup + exclusive + value={glossaryCreateTab} + onChange={handleGlossaryCreateTabChange} + size="small" + color="primary" + aria-label="Choose create glossary or import glossary terms" + > + <ToggleButton + value="create" + className="entity-form-toggle-btn" + data-cy="create-glossary-tab" + > + Create glossary + </ToggleButton> + <ToggleButton + value="import" + className="entity-form-toggle-btn" + data-cy="import-glossary-terms-tab" + > + Import glossary terms + </ToggleButton> + </ToggleButtonGroup> + </Stack> + )} + {(!isAdd || glossaryCreateTab === "create") && ( + <GlossaryForm + control={control} + handleSubmit={handleSubmit(onSubmit)} + setValue={setValue} + /> + )} + {isImportMode && ( + <Stack gap={2}> + <Button + variant="outlined" + color="primary" + startIcon={<FileDownloadIcon />} + onClick={handleDownloadTemplate} + aria-label="Download import template" + > + Download import template + </Button> + <ImportLayout + setFileData={setImportFileData} + progressVal={importProgress} + setProgress={setImportProgress} + selectedFile={ + importFileData !== undefined && + hasSelectedImportFile(importFileData) + ? [importFileData] + : [] + } + errorDetails={importErrorDetails} + /> + </Stack> + )} + {showImportError && importData?.failedImportInfoList && ( + <Stack + sx={{ + width: "100%", + minHeight: 200, + maxHeight: 400, + bgcolor: "background.paper" + }} + > + <List> + {importData.failedImportInfoList.map( + ( + value: { + index: number; + remarks: string; + }, + index: number + ) => ( + <ListItem key={value.index} disableGutters disablePadding> + <ListItemText + className="dropzone-listitem" + primary={`${index + 1}. ${value.remarks}`} + /> + </ListItem> + ) + )} + </List> + </Stack> + )} + </Stack> + </CustomModal> + </> + ); }; export default AddUpdateGlossaryForm; diff --git a/dashboard/src/views/Glossary/AddUpdateTermForm.tsx b/dashboard/src/views/Glossary/AddUpdateTermForm.tsx index feea62032..f5ece0289 100644 --- a/dashboard/src/views/Glossary/AddUpdateTermForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateTermForm.tsx @@ -142,6 +142,7 @@ const AddUpdateTermForm = (props: { button1Handler={onClose} button2Label={isAdd ? "Create" : "Update"} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="sm" button2Handler={handleSubmit(onSubmit)} > diff --git a/dashboard/src/views/Glossary/AssignCategory.tsx b/dashboard/src/views/Glossary/AssignCategory.tsx index 9e588ae3c..5a6f8f8b9 100644 --- a/dashboard/src/views/Glossary/AssignCategory.tsx +++ b/dashboard/src/views/Glossary/AssignCategory.tsx @@ -288,6 +288,7 @@ const AssignCategory = ({ maxWidth="sm" button2Handler={assignCatgeory} disableButton2={loading} + button2Loading={loading} > <Stack> <TextField diff --git a/dashboard/src/views/Glossary/AssignTerm.tsx b/dashboard/src/views/Glossary/AssignTerm.tsx index 14eceb720..e4c2fc0ed 100644 --- a/dashboard/src/views/Glossary/AssignTerm.tsx +++ b/dashboard/src/views/Glossary/AssignTerm.tsx @@ -452,6 +452,7 @@ const AssignTerm = ({ maxWidth="sm" button2Handler={relatedTerm ? handleSubmit(onSubmit) : assignTerm} disableButton2={isSubmitting} + button2Loading={isSubmitting} isDirty={!isEmpty(selectedNode)} > {relatedTerm ? ( diff --git a/dashboard/src/views/Glossary/DeleteGlossary.tsx b/dashboard/src/views/Glossary/DeleteGlossary.tsx index 744447494..c4b5dcf60 100644 --- a/dashboard/src/views/Glossary/DeleteGlossary.tsx +++ b/dashboard/src/views/Glossary/DeleteGlossary.tsx @@ -26,6 +26,7 @@ import { Typography } from "@mui/material"; import { fetchGlossaryData } from "@redux/slice/glossarySlice"; import { isEmpty, serverError } from "@utils/Utils"; import { useRef } from "react"; +import { useAsyncPending } from "@hooks/useAsyncPending"; import { useLocation, useNavigate, useParams } from "react-router-dom"; import { toast } from "react-toastify"; @@ -48,36 +49,39 @@ const DeleteGlossary = (props: { const navigate = useNavigate(); const dispatchApi = useAppDispatch(); const toastId: any = useRef(null); + const { pending: deleteInProgress, run: runDelete } = useAsyncPending(); const fetchCurrentData = async () => { await dispatchApi(fetchGlossaryData()); }; - const handleRemove = async () => { - try { - gtype == "term" - ? await deleteGlossaryorType(cGuid) - : await deleteGlossaryorTerm(guid); - updatedData(); - fetchCurrentData(); - toast.success( - `${ - gtype == "term" ? "Term" : "Glossary" - } ${id} was deleted successfully` - ); - if (!isEmpty(glossaryGuid) || !isEmpty(glossaryType)) { - navigate( - { - pathname: "/" - }, - { replace: true } + const handleRemove = () => { + void runDelete(async () => { + try { + gtype == "term" + ? await deleteGlossaryorType(cGuid) + : await deleteGlossaryorTerm(guid); + updatedData(); + await fetchCurrentData(); + toast.success( + `${ + gtype == "term" ? "Term" : "Glossary" + } ${id} was deleted successfully` ); + if (!isEmpty(glossaryGuid) || !isEmpty(glossaryType)) { + navigate( + { + pathname: "/" + }, + { replace: true } + ); + } + onClose(); + setExpandNode(null); + } catch (error) { + serverError(error, toastId); } - onClose(); - setExpandNode(null); - } catch (error) { - serverError(error, toastId); - } + }); }; return ( @@ -92,6 +96,8 @@ const DeleteGlossary = (props: { button2Label="Ok" maxWidth="sm" button2Handler={handleRemove} + disableButton2={deleteInProgress} + button2Loading={deleteInProgress} > <Typography fontSize={15}> Are you sure you want to delete{" "}
