From 28f7e2096e40f25e40b7db4720e32f852de53cf8 Mon Sep 17 00:00:00 2001
From: Siddhiq <113336661+mohamed-siddhiq@users.noreply.github.com>
Date: Wed, 6 Mar 2024 11:00:08 +0530
Subject: [PATCH] Fix/validation in add new prompt studio (#60)
* Add validation in add new tool from prompt studio
* Handle error validation for update API deployment
---
frontend/package-lock.json | 58 +++-
frontend/package.json | 2 +
.../agency/cards-list/CardsList.jsx | 10 +-
.../agency/side-panel/SidePanel.jsx | 15 +-
.../components/agency/tool-icon/ToolIcon.jsx | 55 +++-
.../agency/tool-info-card/ToolInfoCard.jsx | 2 +-
.../AddCustomToolFormModal.css | 7 +-
.../AddCustomToolFormModal.jsx | 268 ++++++++++--------
.../list-of-tools/ListOfTools.jsx | 27 +-
.../CreateApiDeploymentModal.jsx | 5 +-
.../deployments/display-code/DisplayCode.jsx | 26 +-
frontend/src/helpers/GetStaticData.js | 14 +-
12 files changed, 308 insertions(+), 181 deletions(-)
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 91399eb6c..a57e18432 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -22,6 +22,8 @@
"antd": "^5.5.1",
"axios": "^1.4.0",
"cron-validator": "^1.3.1",
+ "emoji-picker-react": "^4.8.0",
+ "emoji-regex": "^10.3.0",
"handlebars": "^4.7.8",
"http-proxy-middleware": "^2.0.6",
"js-yaml": "^4.1.0",
@@ -7891,10 +7893,24 @@
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
}
},
+ "node_modules/emoji-picker-react": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.8.0.tgz",
+ "integrity": "sha512-gKv+NOM2FjNAokXqlhhmDJMLp1hBTx4X+OoYrPAK1qpTVBseoeybtqPBR1NXixTow7Vbxv1WOuI3SSTiEB089A==",
+ "dependencies": {
+ "flairup": "0.0.38"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=16"
+ }
+ },
"node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+ "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="
},
"node_modules/emojis-list": {
"version": "3.0.0",
@@ -8498,6 +8514,11 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
}
},
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
"node_modules/eslint-plugin-prettier": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
@@ -9110,6 +9131,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/flairup": {
+ "version": "0.0.38",
+ "resolved": "https://registry.npmjs.org/flairup/-/flairup-0.0.38.tgz",
+ "integrity": "sha512-W9QA5TM7eYNlGoBYwfVn/o6v4yWBCxfq4+EJ5w774oFeyWvVWnYq6Dgt4CJltjG9y/lPwbOqz3jSSr8K66ToGg=="
+ },
"node_modules/flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -26028,10 +26054,18 @@
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz",
"integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg=="
},
+ "emoji-picker-react": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.8.0.tgz",
+ "integrity": "sha512-gKv+NOM2FjNAokXqlhhmDJMLp1hBTx4X+OoYrPAK1qpTVBseoeybtqPBR1NXixTow7Vbxv1WOuI3SSTiEB089A==",
+ "requires": {
+ "flairup": "0.0.38"
+ }
+ },
"emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+ "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="
},
"emojis-list": {
"version": "3.0.0",
@@ -26498,6 +26532,13 @@
"object.entries": "^1.1.6",
"object.fromentries": "^2.0.6",
"semver": "^6.3.0"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ }
}
},
"eslint-plugin-prettier": {
@@ -26940,6 +26981,11 @@
"path-exists": "^4.0.0"
}
},
+ "flairup": {
+ "version": "0.0.38",
+ "resolved": "https://registry.npmjs.org/flairup/-/flairup-0.0.38.tgz",
+ "integrity": "sha512-W9QA5TM7eYNlGoBYwfVn/o6v4yWBCxfq4+EJ5w774oFeyWvVWnYq6Dgt4CJltjG9y/lPwbOqz3jSSr8K66ToGg=="
+ },
"flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 939df4ff2..fdc22fe68 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -17,6 +17,8 @@
"antd": "^5.5.1",
"axios": "^1.4.0",
"cron-validator": "^1.3.1",
+ "emoji-picker-react": "^4.8.0",
+ "emoji-regex": "^10.3.0",
"handlebars": "^4.7.8",
"http-proxy-middleware": "^2.0.6",
"js-yaml": "^4.1.0",
diff --git a/frontend/src/components/agency/cards-list/CardsList.jsx b/frontend/src/components/agency/cards-list/CardsList.jsx
index 939ec578c..ceae2ab8e 100644
--- a/frontend/src/components/agency/cards-list/CardsList.jsx
+++ b/frontend/src/components/agency/cards-list/CardsList.jsx
@@ -1,5 +1,5 @@
import { CloseOutlined } from "@ant-design/icons";
-import { Card, Col, Image, Progress, Row, Typography } from "antd";
+import { Card, Col, Progress, Row, Typography } from "antd";
import PropTypes from "prop-types";
import { useRef } from "react";
import { useDrag, useDrop } from "react-dnd";
@@ -13,6 +13,7 @@ import { useWorkflowStore } from "../../../store/workflow-store";
import { ConfirmModal } from "../../widgets/confirm-modal/ConfirmModal";
import "../step-card/StepCard.css";
import "./CardList.css";
+import { ToolIcon } from "../tool-icon/ToolIcon";
const CardsList = ({ step, index, activeTool, moveItem }) => {
const ref = useRef(null);
@@ -143,12 +144,7 @@ const CardsList = ({ step, index, activeTool, moveItem }) => {
-
+
diff --git a/frontend/src/components/agency/side-panel/SidePanel.jsx b/frontend/src/components/agency/side-panel/SidePanel.jsx
index b7b85e5e9..d64296c24 100644
--- a/frontend/src/components/agency/side-panel/SidePanel.jsx
+++ b/frontend/src/components/agency/side-panel/SidePanel.jsx
@@ -40,6 +40,10 @@ function SidePanel() {
setActiveTabKey(key.toString());
};
+ const isObjectEmpty = (obj) => {
+ return Object.keys(obj).length === 0;
+ };
+
useEffect(() => {
const toolSettingsId = toolSettings?.tool_id;
if (!toolSettingsId) {
@@ -65,8 +69,15 @@ function SidePanel() {
setSpecLoading(true);
axiosPrivate(requestOptions)
.then((res) => {
- setToolId(toolSettingsId);
- setSpec(res?.data);
+ if (isObjectEmpty(res?.data?.properties)) {
+ // Disable tool settings & switch to Tools tab - when custom tool is selected
+ setSpec({});
+ setToolId("");
+ setActiveTabKey("1");
+ } else {
+ setToolId(toolSettingsId);
+ setSpec(res?.data);
+ }
})
.catch((err) => {})
.finally(() => {
diff --git a/frontend/src/components/agency/tool-icon/ToolIcon.jsx b/frontend/src/components/agency/tool-icon/ToolIcon.jsx
index e1f6924d4..bbed9bd60 100644
--- a/frontend/src/components/agency/tool-icon/ToolIcon.jsx
+++ b/frontend/src/components/agency/tool-icon/ToolIcon.jsx
@@ -1,29 +1,54 @@
import { Image } from "antd";
+import emojiRegex from "emoji-regex";
import PropTypes from "prop-types";
import "./ToolIcon.css";
-import { useEffect, useState } from "react";
-function ToolIcon({ iconSrc }) {
- const [svgDataUri, setSvgDataUri] = useState("");
- useEffect(() => {
- if (!iconSrc) {
- setSvgDataUri("");
- return;
- }
+function ToolIcon({ iconSrc, showBorder }) {
+ const emojiregex = emojiRegex();
+ const isSVG =
+ iconSrc && typeof iconSrc === "string" && iconSrc.includes("
- );
+ return (
+
+
+
+ );
+ } else if (typeof iconSrc === "string" && emojiregex.test(iconSrc)) {
+ // If it's a string, render it using Typography
+ return (
+
+ {iconSrc}
+
+ );
+ } else {
+ // Handle other cases if needed
+ return (
+
+ {"🧰"}
+
+ );
+ }
}
ToolIcon.propTypes = {
iconSrc: PropTypes.string,
+ showBorder: PropTypes.bool,
};
export { ToolIcon };
diff --git a/frontend/src/components/agency/tool-info-card/ToolInfoCard.jsx b/frontend/src/components/agency/tool-info-card/ToolInfoCard.jsx
index 2c2033d99..784a7b827 100644
--- a/frontend/src/components/agency/tool-info-card/ToolInfoCard.jsx
+++ b/frontend/src/components/agency/tool-info-card/ToolInfoCard.jsx
@@ -15,7 +15,7 @@ function ToolInfoCard({ toolInfo }) {
-
+
diff --git a/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.css b/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.css
index 12f940646..14f8a1562 100644
--- a/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.css
+++ b/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.css
@@ -7,4 +7,9 @@
.add-cus-tool-gap {
margin-bottom: 16px;
-}
\ No newline at end of file
+}
+
+.emoji-modal .ant-modal-content {
+ padding: 0;
+ width: fit-content;
+ }
diff --git a/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.jsx b/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.jsx
index 01b8c462d..509559755 100644
--- a/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.jsx
+++ b/frontend/src/components/custom-tools/add-custom-tool-form-modal/AddCustomToolFormModal.jsx
@@ -1,161 +1,181 @@
-import { Input, Modal, Space, Typography } from "antd";
+import { useState } from "react";
+import { Form, Input, Modal, Popover, Button } from "antd";
import PropTypes from "prop-types";
+import EmojiPicker from "emoji-picker-react";
-import { CustomButton } from "../../widgets/custom-button/CustomButton";
-import SpaceWrapper from "../../widgets/space-wrapper/SpaceWrapper";
+import {
+ handleException,
+ getBackendErrorDetail,
+} from "../../../helpers/GetStaticData";
+import { useAlertStore } from "../../../store/alert-store";
import "./AddCustomToolFormModal.css";
-import { useEffect, useState } from "react";
-
-import { handleException } from "../../../helpers/GetStaticData";
-import { useAlertStore } from "../../../store/alert-store";
+const defaultFromDetails = {
+ tool_name: "",
+ author: "",
+ description: "",
+ icon: "",
+};
function AddCustomToolFormModal({
open,
setOpen,
editItem,
- setEditItem,
+ isEdit,
handleAddNewTool,
}) {
- const [title, setTitle] = useState("");
- const [toolName, setToolName] = useState("");
- const [author, setAuthor] = useState("");
- const [description, setDescription] = useState("");
- const [icon, setIcon] = useState("");
- const [isEdit, setIsEdit] = useState(false);
+ const [form] = Form.useForm();
+ const [isLoading, setIsLoading] = useState(false);
const { setAlertDetails } = useAlertStore();
+ const [showEmojiPicker, setShowEmojiPicker] = useState(false);
+ const [formDetails, setFormDetails] = useState(
+ isEdit ? { ...editItem } : { ...defaultFromDetails }
+ );
+ const [icon, setIcon] = useState(isEdit ? formDetails.icon : "");
+ const [backendErrors, setBackendErrors] = useState(null);
- useEffect(() => {
- setIsEdit(editItem && Object.keys(editItem)?.length > 0);
- }, [editItem]);
-
- useEffect(() => {
- if (!open) {
- clearForm();
- }
- }, [open]);
+ const updateIcon = (emoji) => {
+ setIcon(emoji);
+ setFormDetails((prevState) => ({
+ ...prevState,
+ icon: emoji,
+ }));
+ };
- useEffect(() => {
- if (isEdit) {
- setTitle("Edit Tool Information");
- setToolName(editItem?.tool_name || "");
- setAuthor(editItem?.author || "");
- setDescription(editItem?.description || "");
- setIcon(editItem?.icon || "");
- return;
- }
- setTitle("Add Tool Information");
- }, [isEdit]);
+ const handleInputChange = (changedValues, allValues) => {
+ setFormDetails({ ...formDetails, ...allValues });
+ const changedFieldName = Object.keys(changedValues)[0];
+ form.setFields([
+ {
+ name: changedFieldName,
+ errors: [],
+ },
+ ]);
+ setBackendErrors((prevErrors) => {
+ if (prevErrors) {
+ const updatedErrors = prevErrors.errors.filter(
+ (error) => error.attr !== changedFieldName
+ );
+ return { ...prevErrors, errors: updatedErrors };
+ }
+ return null;
+ });
+ };
const handleSubmit = (event) => {
- event.preventDefault();
- if (!toolName.trim() || !author.trim() || !description.trim()) {
- setAlertDetails({
- type: "error",
- content: "Please add valid values in input fields",
- });
- return;
- }
-
- const body = {
- tool_name: toolName,
- author: author,
- description: description,
- icon: icon,
- };
+ const body = formDetails;
+ setIsLoading(true);
handleAddNewTool(body)
.then((success) => {
setAlertDetails({
type: "success",
content: `${isEdit ? "Updated" : "Added"} Successfully`,
});
- clearForm();
+ setOpen(false);
+ clearFormDetails();
})
.catch((err) => {
- const msg = `Failed to ${isEdit ? "update" : "add"}`;
- setAlertDetails(handleException(err, msg));
+ handleException(err, "", setBackendErrors);
+ })
+ .finally(() => {
+ setIsLoading(false);
});
};
- const clearForm = () => {
- setToolName("");
- setAuthor("");
- setDescription("");
- setIcon("");
- setEditItem({});
- setIsEdit(false);
+ const clearFormDetails = () => {
+ setFormDetails({ ...defaultFromDetails });
};
return (
setOpen(false)}
- footer={null}
+ onCancel={() => {
+ setOpen(false);
+ setShowEmojiPicker(false);
+ }}
centered
maskClosable={false}
+ onOk={handleSubmit}
+ okText={isEdit ? "Update" : "Save"}
+ okButtonProps={{
+ loading: isLoading,
+ }}
+ destroyOnClose
>
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ updateIcon(emoji.emoji);
+ setShowEmojiPicker(false);
+ }}
+ />
+ }
+ >
+
+
+
+
);
}
@@ -164,7 +184,7 @@ AddCustomToolFormModal.propTypes = {
open: PropTypes.bool.isRequired,
setOpen: PropTypes.func.isRequired,
editItem: PropTypes.object.isRequired,
- setEditItem: PropTypes.func.isRequired,
+ isEdit: PropTypes.bool.isRequired,
handleAddNewTool: PropTypes.func.isRequired,
};
diff --git a/frontend/src/components/custom-tools/list-of-tools/ListOfTools.jsx b/frontend/src/components/custom-tools/list-of-tools/ListOfTools.jsx
index 84f3fb1c5..b41cac96f 100644
--- a/frontend/src/components/custom-tools/list-of-tools/ListOfTools.jsx
+++ b/frontend/src/components/custom-tools/list-of-tools/ListOfTools.jsx
@@ -14,7 +14,6 @@ import { useSessionStore } from "../../../store/session-store";
import { CustomButton } from "../../widgets/custom-button/CustomButton";
import { AddCustomToolFormModal } from "../add-custom-tool-form-modal/AddCustomToolFormModal";
import { ViewTools } from "../view-tools/ViewTools";
-
import { handleException } from "../../../helpers/GetStaticData";
import "./ListOfTools.css";
@@ -42,6 +41,7 @@ function ListOfTools() {
const [listOfTools, setListOfTools] = useState([]);
const [filteredListOfTools, setFilteredListOfTools] = useState([]);
const [search, setSearch] = useState("");
+ const [isEdit, setIsEdit] = useState(false);
useEffect(() => {
getListOfTools();
@@ -124,6 +124,7 @@ function ListOfTools() {
if (!editToolData) {
return;
}
+ setIsEdit(true);
setEditItem(editToolData);
setOpenAddTool(true);
};
@@ -175,6 +176,12 @@ function ListOfTools() {
[]
);
+ const showAddTool = () => {
+ setEditItem(null);
+ setIsEdit(false);
+ setOpenAddTool(true);
+ };
+
return (
<>
@@ -199,7 +206,7 @@ function ListOfTools() {
}
- onClick={() => setOpenAddTool(true)}
+ onClick={showAddTool}
>
New Tool
@@ -220,13 +227,15 @@ function ListOfTools() {
-
+ {openAddTool && (
+
+ )}
>
);
}
diff --git a/frontend/src/components/deployments/create-api-deployment-modal/CreateApiDeploymentModal.jsx b/frontend/src/components/deployments/create-api-deployment-modal/CreateApiDeploymentModal.jsx
index 9214923c6..ef3433c53 100644
--- a/frontend/src/components/deployments/create-api-deployment-modal/CreateApiDeploymentModal.jsx
+++ b/frontend/src/components/deployments/create-api-deployment-modal/CreateApiDeploymentModal.jsx
@@ -116,7 +116,7 @@ const CreateApiDeploymentModal = ({
});
})
.catch((err) => {
- setAlertDetails(handleException(err));
+ handleException(err, "", setBackendErrors);
})
.finally(() => {
setIsLoading(false);
@@ -139,7 +139,7 @@ const CreateApiDeploymentModal = ({
});
})
.catch((err) => {
- setAlertDetails(handleException(err));
+ handleException(err, "", setBackendErrors);
})
.finally(() => {
setIsLoading(false);
@@ -183,7 +183,6 @@ const CreateApiDeploymentModal = ({
{
const generatePythonCode = () => {
let code = `import requests
- api_url = '{{url}}'
- headers = {
- 'Authorization': 'Bearer REPLACE_WITH_API_KEY'
- }
{{#if isPost}}
+ api_url = '{{url}}'
+ headers = {
+ 'Authorization': 'Bearer REPLACE_WITH_API_KEY'
+ }
payload = {'timeout': '80'}
filepath = '/path/to/file'
- files=[('file',('file',open(filepath,'rb'),'application/octet-stream'))]
+ files=[('files',('file',open(filepath,'rb'),'application/octet-stream'))]
response = requests.request("POST", api_url, headers=headers, data=payload, files=files)
{{else}}
+ api_url = '{{url}}?execution_id=REPLACE_WITH_EXECUTION_ID'
+ headers = {
+ 'Authorization': 'Bearer REPLACE_WITH_API_KEY'
+ }
response = requests.request("GET", api_url, headers=headers, data=payload)
{{/if}}
print('Response:', response.json())
@@ -63,9 +67,14 @@ const DisplayCode = ({ isDialogOpen, setDialogOpen, url }) => {
};
const generateCurlCode = () => {
- let code = `curl --location '{{url}}'
+ let code = `{{#if isPost}}
+ curl --request POST --location '{{url}}'
+ --header 'Authorization: Bearer REPLACE_WITH_API_KEY'
+ --form 'files=@"{{pathToFile}}"' --form 'timeout="80"'
+ {{else}}
+ curl --location '{{url}}?execution_id=REPLACE_WITH_EXECUTION_ID'
--header 'Authorization: Bearer REPLACE_WITH_API_KEY'
- {{#if isPost}}--form 'files=@"{{pathToFile}}"' --form 'timeout="80"'{{/if}}
+ {{/if}}
`;
code = trimIndent(code);
const template = Handlebars.compile(code);
@@ -85,10 +94,11 @@ const DisplayCode = ({ isDialogOpen, setDialogOpen, url }) => {
formdata.append("files", fileInput.files[0], "file");
formdata.append("timeout", "80");
var requestOptions = { method: 'POST', body: formdata, redirect: 'follow', headers: myHeaders };
+ fetch("{{url}}", requestOptions)
{{else}}
var requestOptions = { method: 'GET', redirect: 'follow', headers: myHeaders};
+ fetch("{{url}}?execution_id=REPLACE_WITH_EXECUTION_ID", requestOptions)
{{/if}}
- fetch("{{url}}", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
diff --git a/frontend/src/helpers/GetStaticData.js b/frontend/src/helpers/GetStaticData.js
index 72c4b0353..6b2701d85 100644
--- a/frontend/src/helpers/GetStaticData.js
+++ b/frontend/src/helpers/GetStaticData.js
@@ -244,13 +244,17 @@ const getTimeForLogs = () => {
return formattedDate;
};
-const handleException = (err, errMessage) => {
+const handleException = (err, errMessage, setBackendErrors = undefined) => {
if (err?.response?.data?.type === "validation_error") {
// Handle validation errors
- return {
- type: "error",
- content: errMessage || "Something went wrong",
- };
+ if (setBackendErrors) {
+ setBackendErrors(err?.response?.data);
+ } else {
+ return {
+ type: "error",
+ content: errMessage || "Something went wrong",
+ };
+ }
}
if (["client_error", "server_error"].includes(err?.response?.data?.type)) {