fix: autosave for environment tabs and folder-level auth (#6510)

* feat: enhance autosave middleware to support environment draft and folder auth drafts

* feat: extend autosave middleware to handle global and collection environment drafts

* feat: update authentication components to use unified updateAuth function

* refactor: rename updateAuth to updateFolderAuth for consistency in authentication components
This commit is contained in:
Sanjai Kumar
2026-01-13 16:16:46 +05:30
committed by GitHub
parent ebc105d42e
commit fceb99edc2
3 changed files with 103 additions and 29 deletions

View File

@@ -3,7 +3,7 @@ import get from 'lodash/get';
import StyledWrapper from './StyledWrapper';
import { saveFolderRoot } from 'providers/ReduxStore/slices/collections/actions';
import OAuth2AuthorizationCode from 'components/RequestPane/Auth/OAuth2/AuthorizationCode/index';
import { updateFolderAuth } from 'providers/ReduxStore/slices/collections';
import { updateFolderAuth as _updateFolderAuth } from 'providers/ReduxStore/slices/collections';
import { useDispatch } from 'react-redux';
import OAuth2PasswordCredentials from 'components/RequestPane/Auth/OAuth2/PasswordCredentials/index';
import OAuth2ClientCredentials from 'components/RequestPane/Auth/OAuth2/ClientCredentials/index';
@@ -20,7 +20,7 @@ import AwsV4Auth from 'components/RequestPane/Auth/AwsV4Auth';
import { humanizeRequestAuthMode, getTreePathFromCollectionToItem } from 'utils/collections/index';
import Button from 'ui/Button';
const GrantTypeComponentMap = ({ collection, folder }) => {
const GrantTypeComponentMap = ({ collection, folder, updateFolderAuth }) => {
const dispatch = useDispatch();
const save = () => {
@@ -90,6 +90,13 @@ const Auth = ({ collection, folder }) => {
dispatch(saveFolderRoot(collection.uid, folder.uid));
};
const updateFolderAuth = ({ itemUid, ...rest }) => {
return _updateFolderAuth({
...rest,
folderUid: folder.uid
});
};
const getAuthView = () => {
switch (authMode) {
case 'basic': {
@@ -178,7 +185,7 @@ const Auth = ({ collection, folder }) => {
collection={collection}
item={folder}
/>
<GrantTypeComponentMap collection={collection} folder={folder} />
<GrantTypeComponentMap collection={collection} folder={folder} updateFolderAuth={updateFolderAuth} />
</>
);
}

View File

@@ -1,4 +1,5 @@
import { saveRequest, saveCollectionSettings, saveFolderRoot } from '../../slices/collections/actions';
import { saveRequest, saveCollectionSettings, saveFolderRoot, saveEnvironment } from '../../slices/collections/actions';
import { saveGlobalEnvironment } from '../../slices/global-environments';
import { flattenItems, isItemARequest, isItemAFolder } from 'utils/collections';
const actionsToIntercept = [
@@ -85,7 +86,11 @@ const actionsToIntercept = [
'collections/updateCollectionDocs',
'collections/updateCollectionClientCertificates',
'collections/updateCollectionProtobuf',
'collections/updateCollectionProxy'
'collections/updateCollectionProxy',
// Environment draft actions
'collections/setEnvironmentsDraft',
'globalEnvironments/setGlobalEnvironmentDraft'
];
// Simple object to track pending save timers
@@ -105,7 +110,8 @@ const scheduleAutoSave = (key, save, interval) => {
// Helper to find and schedule saves for all existing drafts
const saveExistingDrafts = (dispatch, getState, interval) => {
const collections = getState().collections.collections;
const state = getState();
const collections = state.collections.collections;
collections.forEach((collection) => {
// Check collection-level draft
@@ -114,6 +120,15 @@ const saveExistingDrafts = (dispatch, getState, interval) => {
scheduleAutoSave(key, () => dispatch(saveCollectionSettings(collection.uid, null, true)), interval);
}
// Check collection environment drafts
if (collection.environmentsDraft) {
const { environmentUid, variables } = collection.environmentsDraft;
if (environmentUid && variables) {
const key = `environment-${collection.uid}-${environmentUid}`;
scheduleAutoSave(key, () => dispatch(saveEnvironment(variables, environmentUid, collection.uid)), interval);
}
}
// Check all items (requests and folders) for drafts
const allItems = flattenItems(collection.items);
allItems.forEach((item) => {
@@ -128,6 +143,77 @@ const saveExistingDrafts = (dispatch, getState, interval) => {
}
});
});
// Check global environment drafts
const globalEnvironmentDraft = state.globalEnvironments?.globalEnvironmentDraft;
if (globalEnvironmentDraft) {
const { environmentUid, variables } = globalEnvironmentDraft;
if (environmentUid && variables) {
const key = `global-environment-${environmentUid}`;
scheduleAutoSave(key, () => dispatch(saveGlobalEnvironment({ variables, environmentUid })), interval);
}
}
};
// Helper to determine entity type and create save handler
const determineSaveHandler = (actionType, payload, dispatch, getState) => {
const { itemUid, folderUid, collectionUid, environmentUid } = payload;
// Handle environment drafts
if (actionType === 'collections/setEnvironmentsDraft') {
if (!environmentUid || !collectionUid) return null;
return {
key: `environment-${collectionUid}-${environmentUid}`,
save: () => {
const state = getState();
const collection = state.collections.collections.find((c) => c.uid === collectionUid);
const draft = collection?.environmentsDraft;
if (draft?.environmentUid === environmentUid && draft?.variables) {
dispatch(saveEnvironment(draft.variables, environmentUid, collectionUid));
}
}
};
}
if (actionType === 'globalEnvironments/setGlobalEnvironmentDraft') {
if (!environmentUid) return null;
return {
key: `global-environment-${environmentUid}`,
save: () => {
const state = getState();
const draft = state.globalEnvironments?.globalEnvironmentDraft;
if (draft?.environmentUid === environmentUid && draft?.variables) {
dispatch(saveGlobalEnvironment({ variables: draft.variables, environmentUid }));
}
}
};
}
// Handle folder actions
if (folderUid) {
return {
key: `folder-${folderUid}`,
save: () => dispatch(saveFolderRoot(collectionUid, folderUid, true))
};
}
// Handle request actions
if (itemUid) {
return {
key: `request-${itemUid}`,
save: () => dispatch(saveRequest(itemUid, collectionUid, true))
};
}
// Handle collection-level changes
if (collectionUid) {
return {
key: `collection-${collectionUid}`,
save: () => dispatch(saveCollectionSettings(collectionUid, null, true))
};
}
return null;
};
export const autosaveMiddleware = ({ dispatch, getState }) => (next) => (action) => {
@@ -155,28 +241,9 @@ export const autosaveMiddleware = ({ dispatch, getState }) => (next) => (action)
// Only handle actions that create dirty state
if (!actionsToIntercept.includes(action.type)) return result;
const { itemUid, folderUid, collectionUid } = action.payload;
const interval = autoSave.interval;
// Determine what to save based on what IDs are present
let key, save;
if (itemUid) {
// Request change
key = `request-${itemUid}`;
save = () => dispatch(saveRequest(itemUid, collectionUid, true));
} else if (folderUid) {
// Folder change
key = `folder-${folderUid}`;
save = () => dispatch(saveFolderRoot(collectionUid, folderUid, true));
} else if (collectionUid) {
// Collection change
key = `collection-${collectionUid}`;
save = () => dispatch(saveCollectionSettings(collectionUid, null, true));
}
if (key && save) {
scheduleAutoSave(key, save, interval);
const handler = determineSaveHandler(action.type, action.payload, dispatch, getState);
if (handler) {
scheduleAutoSave(handler.key, handler.save, autoSave.interval);
}
return result;

View File

@@ -2338,7 +2338,7 @@ export const collectionsSlice = createSlice({
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
if (!collection) return;
const folder = collection ? findItemInCollection(collection, action.payload.itemUid) : null;
const folder = collection ? findItemInCollection(collection, action.payload.folderUid) : null;
if (!folder) return;
if (folder) {