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 ( - + ); };