diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/ConfirmSwitchEnv.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/ConfirmSwitchEnv.js
new file mode 100644
index 000000000..715bf9e75
--- /dev/null
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/ConfirmSwitchEnv.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import { IconAlertTriangle } from '@tabler/icons';
+import Modal from 'components/Modal';
+import { createPortal } from 'react-dom';
+
+const ConfirmSwitchEnv = ({ onCancel }) => {
+ return createPortal(
+ {
+ e.stopPropagation();
+ e.preventDefault();
+ }}
+ hideFooter={true}
+ >
+
+
+
Hold on..
+
+ You have unsaved changes in this environment.
+
+
+ ,
+ document.body
+ );
+};
+
+export default ConfirmSwitchEnv;
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js
index 1220b193a..1f36d05ea 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js
@@ -1,19 +1,19 @@
import React from 'react';
-import toast from 'react-hot-toast';
-import cloneDeep from 'lodash/cloneDeep';
import { IconTrash } from '@tabler/icons';
import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux';
-import { saveEnvironment } from 'providers/ReduxStore/slices/collections/actions';
import SingleLineEditor from 'components/SingleLineEditor';
import StyledWrapper from './StyledWrapper';
+import { uuid } from 'utils/common';
+import { maskInputValue } from 'utils/collections';
import { useFormik } from 'formik';
import * as Yup from 'yup';
-import { uuid } from 'utils/common';
import { variableNameRegex } from 'utils/common/regex';
-import { maskInputValue } from 'utils/collections';
+import { saveEnvironment } from 'providers/ReduxStore/slices/collections/actions';
+import cloneDeep from 'lodash/cloneDeep';
+import toast from 'react-hot-toast';
-const EnvironmentVariables = ({ environment, collection }) => {
+const EnvironmentVariables = ({ environment, collection, setIsModified, originalEnvironmentVariables }) => {
const dispatch = useDispatch();
const { storedTheme } = useTheme();
@@ -46,11 +46,17 @@ const EnvironmentVariables = ({ environment, collection }) => {
.then(() => {
toast.success('Changes saved successfully');
formik.resetForm({ values });
+ setIsModified(false);
})
.catch(() => toast.error('An error occurred while saving the changes'));
}
});
+ // Effect to track modifications.
+ React.useEffect(() => {
+ setIsModified(formik.dirty);
+ }, [formik.dirty]);
+
const ErrorMessage = ({ name }) => {
const meta = formik.getFieldMeta(name);
if (!meta.error) {
@@ -80,6 +86,10 @@ const EnvironmentVariables = ({ environment, collection }) => {
formik.setValues(formik.values.filter((variable) => variable.uid !== id));
};
+ const handleReset = () => {
+ formik.resetForm({ originalEnvironmentVariables });
+ };
+
return (
@@ -162,6 +172,9 @@ const EnvironmentVariables = ({ environment, collection }) => {
+
);
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
index 8f58282e2..f9fca74ec 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/index.js
@@ -5,7 +5,7 @@ import DeleteEnvironment from '../../DeleteEnvironment';
import RenameEnvironment from '../../RenameEnvironment';
import EnvironmentVariables from './EnvironmentVariables';
-const EnvironmentDetails = ({ environment, collection }) => {
+const EnvironmentDetails = ({ environment, collection, setIsModified }) => {
const [openEditModal, setOpenEditModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [openCopyModal, setOpenCopyModal] = useState(false);
@@ -38,7 +38,7 @@ const EnvironmentDetails = ({ environment, collection }) => {
-
+
);
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
index 7dba5987e..4517bd8d3 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/index.js
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, forwardRef, useRef } from 'react';
+import React, { useEffect, useState } from 'react';
import { findEnvironmentInCollection } from 'utils/collections';
import usePrevious from 'hooks/usePrevious';
import EnvironmentDetails from './EnvironmentDetails';
@@ -7,19 +7,23 @@ import { IconDownload, IconShieldLock } from '@tabler/icons';
import ImportEnvironment from '../ImportEnvironment';
import ManageSecrets from '../ManageSecrets';
import StyledWrapper from './StyledWrapper';
+import ConfirmSwitchEnv from './ConfirmSwitchEnv';
-const EnvironmentList = ({ collection }) => {
+const EnvironmentList = ({ selectedEnvironment, setSelectedEnvironment, collection, isModified, setIsModified }) => {
const { environments } = collection;
- const [selectedEnvironment, setSelectedEnvironment] = useState(null);
const [openCreateModal, setOpenCreateModal] = useState(false);
const [openImportModal, setOpenImportModal] = useState(false);
const [openManageSecretsModal, setOpenManageSecretsModal] = useState(false);
+ const [switchEnvConfirmClose, setSwitchEnvConfirmClose] = useState(false);
+ const [originalEnvironmentVariables, setOriginalEnvironmentVariables] = useState([]);
+
const envUids = environments ? environments.map((env) => env.uid) : [];
const prevEnvUids = usePrevious(envUids);
useEffect(() => {
if (selectedEnvironment) {
+ setOriginalEnvironmentVariables(selectedEnvironment.variables);
return;
}
@@ -32,7 +36,6 @@ const EnvironmentList = ({ collection }) => {
}, [collection, environments, selectedEnvironment]);
useEffect(() => {
- // check env add
if (prevEnvUids && prevEnvUids.length && envUids.length > prevEnvUids.length) {
const newEnv = environments.find((env) => !prevEnvUids.includes(env.uid));
if (newEnv) {
@@ -40,23 +43,62 @@ const EnvironmentList = ({ collection }) => {
}
}
- // check env delete
if (prevEnvUids && prevEnvUids.length && envUids.length < prevEnvUids.length) {
setSelectedEnvironment(environments && environments.length ? environments[0] : null);
}
}, [envUids, environments, prevEnvUids]);
+ const handleEnvironmentClick = (env) => {
+ if (!isModified) {
+ setSelectedEnvironment(env);
+ } else {
+ setSwitchEnvConfirmClose(true);
+ }
+ };
+
if (!selectedEnvironment) {
return null;
}
+ const handleCreateEnvClick = () => {
+ if (!isModified) {
+ setOpenCreateModal(true);
+ } else {
+ setSwitchEnvConfirmClose(true);
+ }
+ };
+
+ const handleImportClick = () => {
+ if (!isModified) {
+ setOpenImportModal(true);
+ } else {
+ setSwitchEnvConfirmClose(true);
+ }
+ };
+
+ const handleSecretsClick = () => {
+ setOpenManageSecretsModal(true);
+ };
+
+ const handleConfirmSwitch = (saveChanges) => {
+ if (!saveChanges) {
+ setSwitchEnvConfirmClose(false);
+ }
+ };
+
return (
{openCreateModal && setOpenCreateModal(false)} />}
{openImportModal && setOpenImportModal(false)} />}
{openManageSecretsModal && setOpenManageSecretsModal(false)} />}
+
+ {switchEnvConfirmClose && (
+
+ handleConfirmSwitch(false)} />
+
+ )}
{environments &&
environments.length &&
@@ -64,28 +106,33 @@ const EnvironmentList = ({ collection }) => {
setSelectedEnvironment(env)}
+ onClick={() => handleEnvironmentClick(env)} // Use handleEnvironmentClick to handle clicks
>
{env.name}
))}
-
setOpenCreateModal(true)}>
+
handleCreateEnvClick()}>
+ Create
-
setOpenImportModal(true)}>
+
handleImportClick()}>
Import
-
setOpenManageSecretsModal(true)}>
+
handleSecretsClick()}>
Managing Secrets
-
+
);
diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
index 6daccc374..0a3f7e25b 100644
--- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
+++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/index.js
@@ -6,9 +6,11 @@ import StyledWrapper from './StyledWrapper';
import ImportEnvironment from './ImportEnvironment';
const EnvironmentSettings = ({ collection, onClose }) => {
+ const [isModified, setIsModified] = useState(false);
const { environments } = collection;
const [openCreateModal, setOpenCreateModal] = useState(false);
const [openImportModal, setOpenImportModal] = useState(false);
+ const [selectedEnvironment, setSelectedEnvironment] = useState(null);
if (!environments || !environments.length) {
return (
@@ -48,7 +50,13 @@ const EnvironmentSettings = ({ collection, onClose }) => {
return (
-
+
);
};