Files
bruno/packages/bruno-app/src/components/Sidebar/Collections/Collection/RemoveCollection/ConfirmCollectionCloseDrafts.js
Chirag Chandrashekhar ca4d0dd40b Feature/transient request (#6878)
* feat: add functionality to retrieve collection path from transient file requests in IPC module

* feat: implement transient directory handling in collection mounting process

* add action to store transient directory paths in Redux state
* update IPC handler to create and return a temporary directory for collections
* modify collection mount action to dispatch transient directory addition

* feat: add CreateTransientRequest component for managing transient requests

* implement CreateTransientRequest component to facilitate the creation of HTTP, GraphQL, gRPC, and WebSocket transient requests
* integrate the component into RequestTabs for user interaction
* update collection and request handling to differentiate between transient and non-transient requests
* enhance Redux actions to support transient request creation and management

* feat: enhance transient request handling and add temp directory watcher

* refactor Redux actions for HTTP, gRPC, and WebSocket requests to utilize a unified task queue for transient requests
* implement a new helper function to retrieve collection paths from temporary directory metadata
* add functionality to watch transient directories for file changes, excluding metadata.json
* integrate transient directory watcher into the collection mounting process

* feat: enhance transient request management with temp directory integration

* update generateTransientRequestName function to accept tempDirectory parameter for improved request naming
* modify CreateTransientRequest component to utilize tempDirectory for transient request creation
* adjust middleware to check for transient status based on tempDirectory
* implement transient file and directory identification in collections slice for better state management

* feat: add SaveTransientRequest component for managing transient requests

* implement SaveTransientRequest component to facilitate saving transient requests to selected folders
* create StyledWrapper for component styling
* introduce useCollectionFolderTree hook for managing folder navigation and state
* update Redux actions to handle saving requests from transient state

* feat: implement SaveTransientRequestContainer and enhance modal management

* add SaveTransientRequestContainer to manage multiple transient request modals
* refactor SaveTransientRequest component to utilize Redux for modal state management
* implement open and close actions for transient request modals in Redux slice
* update Bruno page to include SaveTransientRequestContainer for improved UI integration

* feat: enhance SaveTransientRequest component with new folder creation functionality

* add input for creating new folders within the SaveTransientRequest component
* implement validation for new folder names and filesystem names
* integrate folder creation logic with Redux actions for better state management
* update styling for new folder input elements in StyledWrapper
* improve modal behavior to reset state when opened

* feat: update CreateTransientRequest to utilize collection presets for request URLs

* Refactored CreateTransientRequest component to retrieve request URLs from collection presets.
* Enhanced request handling by dynamically setting request URLs based on the selected collection's configuration.

* refactor: clean up unused imports and adjust request handling in collections actions

* Removed unused imports from actions.js to streamline the code.
* Updated the saveRequest function to reject the modal instead of resolving it when handling transient requests.
* Cleaned up comments in index.js for better clarity.

* refactor: streamline transient request handling and improve save functionality

* Removed success toast notifications from CreateTransientRequest component to simplify user feedback.
* Enhanced SaveTransientRequest component to handle transient requests more effectively, including improved filename resolution and validation.
* Added IPC handler for saving transient requests, ensuring proper file management and error handling.
* Updated Redux actions to check for duplicate transient request names within the temporary directory.

* feat: enhance request handling in ConfirmCollectionCloseDrafts component

* Added logic to differentiate between transient and non-transient drafts, ensuring transient requests are saved individually before closing the collection.
* Improved user feedback by displaying unsaved changes for both regular and transient requests.
* Updated save and discard functionality to handle all drafts appropriately, enhancing overall user experience.

* fix:fixed useCallback dependency array

* fix:added request name checks before save

* fix: added isTransient to files

* fix: added watcher cleanup for temp directory

* refactor: enhance transient request handling and optimize component logic

* Updated CreateTransientRequest to utilize useMemo for improved performance and prevent unnecessary re-renders.
* Refactored generateTransientRequestName to focus solely on transient requests, removing tempDirectory dependency.
* Streamlined SaveTransientRequest by consolidating form reset logic and removing unused state variables.
* Improved ConfirmCollectionCloseDrafts to differentiate between transient and non-transient drafts more effectively.
* Cleaned up imports and optimized Redux actions for better maintainability.

* feat: implement transient request file deletion on tab close

* Added middleware to handle the deletion of transient request files when tabs are closed.
* Enhanced collection-watcher to unlink temporary files, ensuring metadata.json is skipped and only request files are processed.
* Improved error handling for file deletion operations.

* feat: enhance autosave middleware to skip transient requests

* Updated autosave middleware to check for transient requests and skip auto-save operations accordingly.

* fix: update ConfirmCollectionCloseDrafts to display all transient drafts

* Modified the ConfirmCollectionCloseDrafts component to show all transient drafts without limiting the display to a maximum number.
* Removed the conditional message for additional drafts not shown, enhancing the user experience by providing complete visibility of transient requests.

* feat: enhance SaveTransientRequest component for better modal management

* Refactored SaveTransientRequest and its container to improve modal handling for unsaved transient requests.
* Introduced state management for opening specific modals and added functionality to discard all unsaved requests.
* Updated Redux actions to manage transient request modals more effectively, ensuring no duplicates are added.
* Enhanced user interface to display a list of unsaved requests with options to save or discard them.

* feat: improve modal management in SaveTransientRequestContainer

* Added useEffect to reset openItemUid when the corresponding modal is no longer present.
* Implemented functionality to close all tabs associated with transient requests and show a success message upon discarding them.
* Removed unnecessary modal close handler and streamlined modal opening logic for better clarity and performance.

* refactor: streamline code formatting and improve readability in collection actions

* Consolidated multiple lines of code into single lines for better readability in ConfirmCollectionCloseDrafts and actions.js.
* Enhanced consistency in the formatting of function parameters and return statements across the collections slice.
* Removed unnecessary line breaks and improved the structure of the code for easier maintenance.

* refactor: improve code readability and structure in middleware and actions

* Consolidated multiple lines of code into single lines for better readability in middleware.js and actions.js.
* Enhanced consistency in formatting function parameters and return statements across the collections slice.
* Removed unnecessary line breaks and improved the structure of the code for easier maintenance.
* Streamlined dispatch calls for better clarity and performance.

* refactor: enhance code readability and consistency in middleware and actions

* Improved formatting and structure in middleware.js for dispatch calls.
* Streamlined comments and indentation in actions.js for better clarity.
* Consolidated multiple lines into single lines where appropriate to enhance readability.

* refactor: enhance transient request handling and modal interactions

* Improved the modal handling logic for removing collections to differentiate between regular and drafts confirmation modals.
* Added new tests for creating and saving transient requests (HTTP, GraphQL, gRPC, WebSocket) ensuring they do not appear in the sidebar until saved.
* Introduced utility functions for creating transient requests and filling request URLs, improving code reusability and clarity.

* refactor: simplify transient request modal rendering and improve collection watcher logic

* Introduced a new TransientRequestModalsRenderer component to streamline modal rendering based on the number of transient requests.
* Refactored the collection watcher logic to enhance readability by removing unnecessary setTimeout and consolidating file handling functions.
* Improved error handling and logging for the temp directory watcher.

* fix: correct spelling of 'WebSocket' in transient request components and tests

* Updated the spelling of 'Websocket' to 'WebSocket' in CreateTransientRequest component, transient requests test, and action type definitions for consistency and accuracy.
2026-01-29 18:38:42 +05:30

212 lines
7.4 KiB
JavaScript

import React, { useMemo } from 'react';
import filter from 'lodash/filter';
import { useDispatch, useSelector } from 'react-redux';
import { flattenItems, isItemARequest, hasRequestChanges, findCollectionByUid } from 'utils/collections';
import { pluralizeWord } from 'utils/common';
import { saveRequest, saveMultipleRequests } from 'providers/ReduxStore/slices/collections/actions';
import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections';
import { removeCollection } from 'providers/ReduxStore/slices/collections/actions';
import { IconAlertTriangle, IconDeviceFloppy } from '@tabler/icons';
import Modal from 'components/Modal';
import toast from 'react-hot-toast';
import Button from 'ui/Button';
const MAX_UNSAVED_REQUESTS_TO_SHOW = 5;
const ConfirmCollectionCloseDrafts = ({ onClose, collection, collectionUid }) => {
const dispatch = useDispatch();
const latestCollection = useSelector((state) => findCollectionByUid(state.collections.collections, collectionUid));
const activeCollection = latestCollection || collection;
const currentDrafts = useMemo(() => {
if (!activeCollection) return [];
const items = flattenItems(activeCollection.items);
return items
?.filter((item) => isItemARequest(item) && hasRequestChanges(item) && !item.isTransient)
.map((item) => {
return {
...item,
collectionUid: collectionUid
};
});
}, [activeCollection, collectionUid]);
const currentTransientDrafts = useMemo(() => {
if (!activeCollection) return [];
const items = flattenItems(activeCollection.items);
return items
?.filter((item) => isItemARequest(item) && hasRequestChanges(item) && item.isTransient)
.map((item) => {
return {
...item,
collectionUid: collectionUid
};
});
}, [activeCollection, collectionUid]);
const allDrafts = useMemo(() => {
return [...currentDrafts, ...currentTransientDrafts];
}, [currentDrafts, currentTransientDrafts]);
const handleSaveAll = () => {
// If there are transient drafts, we can't proceed with batch save
if (currentTransientDrafts.length > 0) {
toast.error('Please save or discard transient requests first');
return;
}
// Save only non-transient drafts
if (currentDrafts.length > 0) {
dispatch(saveMultipleRequests(currentDrafts))
.then(() => {
dispatch(removeCollection(collectionUid))
.then(() => {
toast.success('Collection removed from workspace');
onClose();
})
.catch(() => toast.error('An error occurred while removing the collection'));
})
.catch(() => {
toast.error('Failed to save requests!');
});
} else {
// No non-transient drafts, just remove the collection
dispatch(removeCollection(collectionUid))
.then(() => {
toast.success('Collection removed from workspace');
onClose();
})
.catch(() => toast.error('An error occurred while removing the collection'));
}
};
const handleDiscardAll = () => {
// Discard all drafts (both regular and transient)
allDrafts.forEach((draft) => {
dispatch(deleteRequestDraft({
collectionUid: collectionUid,
itemUid: draft.uid
}));
});
// Then remove the collection
dispatch(removeCollection(collectionUid))
.then(() => {
toast.success('Collection removed from workspace');
onClose();
})
.catch(() => toast.error('An error occurred while removing the collection'));
};
const handleSaveTransient = (draft) => {
dispatch(saveRequest(draft.uid, collectionUid));
};
if (!currentDrafts.length && !currentTransientDrafts.length) {
return null;
}
return (
<Modal
size="md"
title="Remove Collection"
confirmText="Save and Remove"
cancelText="Remove without saving"
handleCancel={onClose}
disableEscapeKey={true}
disableCloseOnOutsideClick={true}
closeModalFadeTimeout={150}
hideFooter={true}
>
<div className="flex items-center">
<IconAlertTriangle size={32} strokeWidth={1.5} className="text-yellow-600" />
<h1 className="ml-2 text-lg font-medium">Hold on..</h1>
</div>
<p className="mt-4">
You have unsaved changes in <span className="font-medium">{allDrafts.length}</span>{' '}
{pluralizeWord('request', allDrafts.length)}.
</p>
{/* Regular (saved) requests with changes */}
{currentDrafts.length > 0 && (
<div className="mt-4">
<p className="text-sm font-medium mb-2">
Saved {pluralizeWord('Request', currentDrafts.length)} ({currentDrafts.length})
</p>
<ul className="ml-2">
{currentDrafts.slice(0, MAX_UNSAVED_REQUESTS_TO_SHOW).map((item) => {
return (
<li key={item.uid} className="mt-1 text-xs text-gray-600">
{item.filename || item.name}
</li>
);
})}
</ul>
{currentDrafts.length > MAX_UNSAVED_REQUESTS_TO_SHOW && (
<p className="ml-2 mt-1 text-xs text-gray-500">
...{currentDrafts.length - MAX_UNSAVED_REQUESTS_TO_SHOW} additional{' '}
{pluralizeWord('request', currentDrafts.length - MAX_UNSAVED_REQUESTS_TO_SHOW)} not shown
</p>
)}
</div>
)}
{/* Transient (unsaved) requests */}
{currentTransientDrafts.length > 0 && (
<div className="mt-4">
<p className="text-sm font-medium mb-2">
Transient {pluralizeWord('Request', currentTransientDrafts.length)} ({currentTransientDrafts.length})
</p>
<p className="text-xs text-orange-600 mb-3">
These requests need to be saved individually before closing the collection.
</p>
<div className="space-y-2 max-h-64 overflow-y-auto pr-1">
{currentTransientDrafts.map((item) => {
return (
<div
key={item.uid}
className="flex items-center justify-between py-2 px-3 bg-gray-50 rounded border border-gray-200"
>
<span className="text-sm text-gray-700 truncate mr-3">{item.name}</span>
<Button
color="primary"
variant="ghost"
size="sm"
onClick={() => handleSaveTransient(item)}
icon={<IconDeviceFloppy size={14} strokeWidth={1.5} />}
>
Save
</Button>
</div>
);
})}
</div>
</div>
)}
<div className="flex justify-between mt-6">
<div>
<Button color="danger" onClick={handleDiscardAll}>
Discard All and Remove
</Button>
</div>
<div>
<Button className="mr-2" color="secondary" variant="ghost" onClick={onClose}>
Cancel
</Button>
<Button
onClick={handleSaveAll}
disabled={currentTransientDrafts.length > 0}
title={currentTransientDrafts.length > 0 ? 'Please save or discard transient requests first' : ''}
>
{currentDrafts.length > 1 ? 'Save All and Remove' : 'Save and Remove'}
</Button>
</div>
</div>
</Modal>
);
};
export default ConfirmCollectionCloseDrafts;