mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-29 07:34:07 +00:00
handle unsaved changes in dot env file editor (#7094)
* handle unsaved changes in dot env file editor * fixes
This commit is contained in:
@@ -4,7 +4,14 @@ import Modal from 'components/Modal';
|
||||
import Portal from 'components/Portal';
|
||||
import Button from 'ui/Button';
|
||||
|
||||
const ConfirmCloseEnvironment = ({ onCancel, onCloseWithoutSave, onSaveAndClose, isGlobal }) => {
|
||||
const ConfirmCloseEnvironment = ({ onCancel, onCloseWithoutSave, onSaveAndClose, isGlobal, isDotEnv }) => {
|
||||
let settingsLabel = 'collection environment settings';
|
||||
if (isDotEnv) {
|
||||
settingsLabel = '.env file';
|
||||
} else if (isGlobal) {
|
||||
settingsLabel = 'global environment settings';
|
||||
}
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<Modal
|
||||
@@ -21,7 +28,7 @@ const ConfirmCloseEnvironment = ({ onCancel, onCloseWithoutSave, onSaveAndClose,
|
||||
<h1 className="ml-2 text-lg font-medium">Hold on...</h1>
|
||||
</div>
|
||||
<div className="font-normal mt-4">
|
||||
You have unsaved changes in {isGlobal ? 'global' : 'collection'} environment settings.
|
||||
You have unsaved changes in {settingsLabel}.
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mt-6">
|
||||
|
||||
@@ -217,10 +217,12 @@ const DotEnvFileEditor = ({
|
||||
];
|
||||
formik.resetForm({ values: newValues });
|
||||
setIsModified(false);
|
||||
window.dispatchEvent(new Event('dotenv-save-complete'));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
toast.error('An error occurred while saving the changes');
|
||||
window.dispatchEvent(new Event('dotenv-save-failed'));
|
||||
})
|
||||
.finally(() => {
|
||||
setIsSaving(false);
|
||||
@@ -240,10 +242,12 @@ const DotEnvFileEditor = ({
|
||||
.then(() => {
|
||||
toast.success('Changes saved successfully');
|
||||
setIsModified(false);
|
||||
window.dispatchEvent(new Event('dotenv-save-complete'));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
toast.error('An error occurred while saving the changes');
|
||||
window.dispatchEvent(new Event('dotenv-save-failed'));
|
||||
})
|
||||
.finally(() => {
|
||||
setIsSaving(false);
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
createDotEnvFile,
|
||||
deleteDotEnvFile
|
||||
} from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { setEnvironmentsDraft, clearEnvironmentsDraft } from 'providers/ReduxStore/slices/collections';
|
||||
import { validateName, validateNameError } from 'utils/common/regex';
|
||||
import toast from 'react-hot-toast';
|
||||
import classnames from 'classnames';
|
||||
@@ -72,11 +73,24 @@ const EnvironmentList = ({
|
||||
const envUids = environments ? environments.map((env) => env.uid) : [];
|
||||
const prevEnvUids = usePrevious(envUids);
|
||||
|
||||
const handleDotEnvModifiedChange = useCallback((modified) => {
|
||||
setIsDotEnvModified(modified);
|
||||
if (modified) {
|
||||
dispatch(setEnvironmentsDraft({
|
||||
collectionUid: collection.uid,
|
||||
environmentUid: `dotenv:${selectedDotEnvFile}`,
|
||||
variables: []
|
||||
}));
|
||||
} else {
|
||||
dispatch(clearEnvironmentsDraft({ collectionUid: collection.uid }));
|
||||
}
|
||||
}, [dispatch, collection.uid, selectedDotEnvFile]);
|
||||
|
||||
useEffect(() => {
|
||||
if (dotEnvFiles.length === 0) {
|
||||
setSelectedDotEnvFile(null);
|
||||
setActiveView('environment');
|
||||
setIsDotEnvModified(false);
|
||||
handleDotEnvModifiedChange(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -424,7 +438,7 @@ const EnvironmentList = ({
|
||||
dispatch(deleteDotEnvFile(collection.uid, filename))
|
||||
.then(() => {
|
||||
toast.success(`${filename} file deleted!`);
|
||||
setIsDotEnvModified(false);
|
||||
handleDotEnvModifiedChange(false);
|
||||
if (selectedDotEnvFile === filename) {
|
||||
const remainingFiles = dotEnvFiles.filter((f) => f.filename !== filename);
|
||||
if (remainingFiles.length > 0) {
|
||||
@@ -467,7 +481,7 @@ const EnvironmentList = ({
|
||||
onSave={handleSaveDotEnv}
|
||||
onSaveRaw={handleSaveDotEnvRaw}
|
||||
isModified={isDotEnvModified}
|
||||
setIsModified={setIsDotEnvModified}
|
||||
setIsModified={handleDotEnvModifiedChange}
|
||||
dotEnvExists={selectedDotEnvData?.exists}
|
||||
viewMode={dotEnvViewMode}
|
||||
collection={collection}
|
||||
|
||||
@@ -236,6 +236,7 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
{showConfirmEnvironmentClose && tab.type === 'environment-settings' && (
|
||||
<ConfirmCloseEnvironment
|
||||
isGlobal={false}
|
||||
isDotEnv={collection.environmentsDraft?.environmentUid?.startsWith('dotenv:')}
|
||||
onCancel={() => setShowConfirmEnvironmentClose(false)}
|
||||
onCloseWithoutSave={() => {
|
||||
dispatch(clearEnvironmentsDraft({ collectionUid: collection.uid }));
|
||||
@@ -244,7 +245,25 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
}}
|
||||
onSaveAndClose={() => {
|
||||
const draft = collection.environmentsDraft;
|
||||
if (draft?.environmentUid && draft?.variables) {
|
||||
if (draft?.environmentUid?.startsWith('dotenv:')) {
|
||||
const onSuccess = () => {
|
||||
cleanup();
|
||||
dispatch(clearEnvironmentsDraft({ collectionUid: collection.uid }));
|
||||
dispatch(closeTabs({ tabUids: [tab.uid] }));
|
||||
setShowConfirmEnvironmentClose(false);
|
||||
};
|
||||
const onFailed = () => {
|
||||
cleanup();
|
||||
setShowConfirmEnvironmentClose(false);
|
||||
};
|
||||
const cleanup = () => {
|
||||
window.removeEventListener('dotenv-save-complete', onSuccess);
|
||||
window.removeEventListener('dotenv-save-failed', onFailed);
|
||||
};
|
||||
window.addEventListener('dotenv-save-complete', onSuccess, { once: true });
|
||||
window.addEventListener('dotenv-save-failed', onFailed, { once: true });
|
||||
window.dispatchEvent(new Event('dotenv-save'));
|
||||
} else if (draft?.environmentUid && draft?.variables) {
|
||||
dispatch(saveEnvironment(draft.variables, draft.environmentUid, collection.uid))
|
||||
.then(() => {
|
||||
dispatch(clearEnvironmentsDraft({ collectionUid: collection.uid }));
|
||||
@@ -263,6 +282,7 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
{showConfirmGlobalEnvironmentClose && tab.type === 'global-environment-settings' && (
|
||||
<ConfirmCloseEnvironment
|
||||
isGlobal={true}
|
||||
isDotEnv={globalEnvironmentDraft?.environmentUid?.startsWith('dotenv:')}
|
||||
onCancel={() => setShowConfirmGlobalEnvironmentClose(false)}
|
||||
onCloseWithoutSave={() => {
|
||||
dispatch(clearGlobalEnvironmentDraft());
|
||||
@@ -271,7 +291,25 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
}}
|
||||
onSaveAndClose={() => {
|
||||
const draft = globalEnvironmentDraft;
|
||||
if (draft?.environmentUid && draft?.variables) {
|
||||
if (draft?.environmentUid?.startsWith('dotenv:')) {
|
||||
const onSuccess = () => {
|
||||
cleanup();
|
||||
dispatch(clearGlobalEnvironmentDraft());
|
||||
dispatch(closeTabs({ tabUids: [tab.uid] }));
|
||||
setShowConfirmGlobalEnvironmentClose(false);
|
||||
};
|
||||
const onFailed = () => {
|
||||
cleanup();
|
||||
setShowConfirmGlobalEnvironmentClose(false);
|
||||
};
|
||||
const cleanup = () => {
|
||||
window.removeEventListener('dotenv-save-complete', onSuccess);
|
||||
window.removeEventListener('dotenv-save-failed', onFailed);
|
||||
};
|
||||
window.addEventListener('dotenv-save-complete', onSuccess, { once: true });
|
||||
window.addEventListener('dotenv-save-failed', onFailed, { once: true });
|
||||
window.dispatchEvent(new Event('dotenv-save'));
|
||||
} else if (draft?.environmentUid && draft?.variables) {
|
||||
dispatch(saveGlobalEnvironment({ variables: draft.variables, environmentUid: draft.environmentUid }))
|
||||
.then(() => {
|
||||
dispatch(clearGlobalEnvironmentDraft());
|
||||
|
||||
@@ -13,7 +13,7 @@ import DotEnvFileDetails from 'components/Environments/DotEnvFileDetails';
|
||||
import ColorBadge from 'components/ColorBadge';
|
||||
import { isEqual } from 'lodash';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { addGlobalEnvironment, renameGlobalEnvironment, selectGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
|
||||
import { addGlobalEnvironment, renameGlobalEnvironment, selectGlobalEnvironment, setGlobalEnvironmentDraft, clearGlobalEnvironmentDraft } from 'providers/ReduxStore/slices/global-environments';
|
||||
import {
|
||||
saveWorkspaceDotEnvVariables,
|
||||
saveWorkspaceDotEnvRaw,
|
||||
@@ -72,9 +72,22 @@ const EnvironmentList = ({
|
||||
const envUids = environments ? environments.map((env) => env.uid) : [];
|
||||
const prevEnvUids = usePrevious(envUids);
|
||||
|
||||
const handleDotEnvModifiedChange = useCallback((modified) => {
|
||||
setIsDotEnvModified(modified);
|
||||
if (modified) {
|
||||
dispatch(setGlobalEnvironmentDraft({
|
||||
environmentUid: `dotenv:${selectedDotEnvFile}`,
|
||||
variables: []
|
||||
}));
|
||||
} else {
|
||||
dispatch(clearGlobalEnvironmentDraft());
|
||||
}
|
||||
}, [dispatch, selectedDotEnvFile]);
|
||||
|
||||
useEffect(() => {
|
||||
if (dotEnvFiles.length === 0) {
|
||||
setSelectedDotEnvFile(null);
|
||||
handleDotEnvModifiedChange(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -422,7 +435,7 @@ const EnvironmentList = ({
|
||||
dispatch(deleteWorkspaceDotEnvFile(workspace.uid, filename))
|
||||
.then(() => {
|
||||
toast.success(`${filename} file deleted!`);
|
||||
setIsDotEnvModified(false);
|
||||
handleDotEnvModifiedChange(false);
|
||||
if (selectedDotEnvFile === filename) {
|
||||
const remainingFiles = dotEnvFiles.filter((f) => f.filename !== filename);
|
||||
if (remainingFiles.length > 0) {
|
||||
@@ -465,7 +478,7 @@ const EnvironmentList = ({
|
||||
onSave={handleSaveDotEnv}
|
||||
onSaveRaw={handleSaveDotEnvRaw}
|
||||
isModified={isDotEnvModified}
|
||||
setIsModified={setIsDotEnvModified}
|
||||
setIsModified={handleDotEnvModifiedChange}
|
||||
dotEnvExists={selectedDotEnvData?.exists}
|
||||
viewMode={dotEnvViewMode}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user