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 ( - + ); }; diff --git a/packages/bruno-app/src/components/RequestPane/Auth/index.js b/packages/bruno-app/src/components/RequestPane/Auth/index.js index f525b065c..51a1450f1 100644 --- a/packages/bruno-app/src/components/RequestPane/Auth/index.js +++ b/packages/bruno-app/src/components/RequestPane/Auth/index.js @@ -41,7 +41,9 @@ const Auth = ({ item, collection }) => {
Collection level auth is:
{humanizeRequestAuthMode(collectionAuth?.mode)}
-
Cannot inherit Oauth2 from collection.
+
+ Note: You need to use scripting to set the access token in the request headers. +
) : ( <> diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index aa2080d11..7902eac65 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -129,7 +129,7 @@ const Sidebar = () => { Star */}
-
v1.14.0
+
v1.16.1
diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index 3e802444f..c3588c010 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -60,7 +60,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: '1.14.0' + version: '1.16.1' } }); }; diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js index 26a120991..f59d9e2d5 100644 --- a/packages/bruno-app/src/utils/collections/index.js +++ b/packages/bruno-app/src/utils/collections/index.js @@ -417,7 +417,10 @@ export const transformRequestToSaveToFilesystem = (item) => { }); if (itemToSave.request.body.mode === 'json') { - itemToSave.request.body.json = replaceTabsWithSpaces(itemToSave.request.body.json); + itemToSave.request.body = { + ...itemToSave.request.body, + json: replaceTabsWithSpaces(itemToSave.request.body.json) + }; } return itemToSave; diff --git a/packages/bruno-cli/src/runner/prepare-request.js b/packages/bruno-cli/src/runner/prepare-request.js index cd3d77c90..8dac18764 100644 --- a/packages/bruno-cli/src/runner/prepare-request.js +++ b/packages/bruno-cli/src/runner/prepare-request.js @@ -63,19 +63,8 @@ const prepareRequest = (request, collectionRoot) => { headers: headers }; - /** - * 27 Feb 2024: - * ['inherit', 'none'].includes(request.auth.mode) - * We are mainitaining the old behavior where 'none' used to inherit the collection auth. - * - * Very soon, 'none' will be treated as no auth and 'inherit' will be the only way to inherit collection auth. - * We will request users to update their collection files to use 'inherit' instead of 'none'. - * Don't want to break ongoing CI pipelines. - * - * Hoping to remove this by 1 April 2024. - */ const collectionAuth = get(collectionRoot, 'request.auth'); - if (collectionAuth && ['inherit', 'none'].includes(request.auth.mode)) { + if (collectionAuth && request.auth.mode === 'none') { if (collectionAuth.mode === 'basic') { axiosRequest.auth = { username: get(collectionAuth, 'basic.username'), diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index e45bcd813..866cb70ab 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v1.14.0", + "version": "v1.16.1", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js index 249b1754f..fed242eb3 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-request.js @@ -34,20 +34,9 @@ const parseFormData = (datas, collectionPath) => { return form; }; -/** - * 27 Feb 2024: - * ['inherit', 'none'].includes(request.auth.mode) - * We are mainitaining the old behavior where 'none' used to inherit the collection auth. - * - * Very soon, 'none' will be treated as no auth and 'inherit' will be the only way to inherit collection auth. - * We will request users to update their collection files to use 'inherit' instead of 'none'. - * Don't want to break ongoing CI pipelines. - * - * Hoping to remove this by 1 April 2024. - */ const setAuthHeaders = (axiosRequest, request, collectionRoot) => { const collectionAuth = get(collectionRoot, 'request.auth'); - if (collectionAuth && ['inherit', 'none'].includes(request.auth.mode)) { + if (collectionAuth && request.auth.mode === 'inherit') { switch (collectionAuth.mode) { case 'awsv4': axiosRequest.awsv4config = {