mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-15 11:51:30 +00:00
Feature/prompt save before collection close (#6062)
* added confirmation dialog before collection close for items in draft state * chore: lint fix --------- Co-authored-by: Sid <siddharth@usebruno.com>
This commit is contained in:
committed by
GitHub
parent
8ec1925b9f
commit
2be602d16c
@@ -0,0 +1,122 @@
|
||||
import React from 'react';
|
||||
import filter from 'lodash/filter';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { flattenItems, isItemARequest, hasRequestChanges } from 'utils/collections';
|
||||
import { pluralizeWord } from 'utils/common';
|
||||
import { saveMultipleRequests } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections';
|
||||
import { removeCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { IconAlertTriangle } from '@tabler/icons';
|
||||
import Modal from 'components/Modal';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const ConfirmCollectionCloseDrafts = ({ onClose, collection, collectionUid }) => {
|
||||
const MAX_UNSAVED_REQUESTS_TO_SHOW = 5;
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// Get all draft items in the collection
|
||||
const currentDrafts = React.useMemo(() => {
|
||||
if (!collection) return [];
|
||||
const items = flattenItems(collection.items);
|
||||
const collectionDrafts = filter(items, (item) => isItemARequest(item) && hasRequestChanges(item));
|
||||
return collectionDrafts.map((draft) => ({
|
||||
...draft,
|
||||
collectionUid: collectionUid
|
||||
}));
|
||||
}, [collection, collectionUid]);
|
||||
|
||||
const handleSaveAll = () => {
|
||||
dispatch(saveMultipleRequests(currentDrafts))
|
||||
.then(() => {
|
||||
dispatch(removeCollection(collectionUid))
|
||||
.then(() => {
|
||||
toast.success('Collection closed');
|
||||
onClose();
|
||||
})
|
||||
.catch(() => toast.error('An error occurred while closing the collection'));
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error('Failed to save requests!');
|
||||
});
|
||||
};
|
||||
|
||||
const handleDiscardAll = () => {
|
||||
// Discard all drafts
|
||||
currentDrafts.forEach((draft) => {
|
||||
dispatch(deleteRequestDraft({
|
||||
collectionUid: collectionUid,
|
||||
itemUid: draft.uid
|
||||
}));
|
||||
});
|
||||
|
||||
// Then close the collection
|
||||
dispatch(removeCollection(collectionUid))
|
||||
.then(() => {
|
||||
toast.success('Collection closed');
|
||||
onClose();
|
||||
})
|
||||
.catch(() => toast.error('An error occurred while closing the collection'));
|
||||
};
|
||||
|
||||
if (!currentDrafts.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
size="md"
|
||||
title="Close Collection"
|
||||
confirmText="Save and Close"
|
||||
cancelText="Close 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-semibold">Hold on..</h1>
|
||||
</div>
|
||||
<p className="mt-4">
|
||||
Do you want to save the changes you made to the following{' '}
|
||||
<span className="font-medium">{currentDrafts.length}</span> {pluralizeWord('request', currentDrafts.length)}?
|
||||
</p>
|
||||
|
||||
<ul className="mt-4">
|
||||
{currentDrafts.slice(0, MAX_UNSAVED_REQUESTS_TO_SHOW).map((item) => {
|
||||
return (
|
||||
<li key={item.uid} className="mt-1 text-xs">
|
||||
{item.filename}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{currentDrafts.length > MAX_UNSAVED_REQUESTS_TO_SHOW && (
|
||||
<p className="mt-1 text-xs">
|
||||
...{currentDrafts.length - MAX_UNSAVED_REQUESTS_TO_SHOW} additional{' '}
|
||||
{pluralizeWord('request', currentDrafts.length - MAX_UNSAVED_REQUESTS_TO_SHOW)} not shown
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between mt-6">
|
||||
<div>
|
||||
<button className="btn btn-sm btn-danger" onClick={handleDiscardAll}>
|
||||
Discard and Close
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button className="btn btn-close btn-sm mr-2" onClick={onClose}>
|
||||
Cancel
|
||||
</button>
|
||||
<button className="btn btn-secondary btn-sm" onClick={handleSaveAll}>
|
||||
{currentDrafts.length > 1 ? 'Save All and Close' : 'Save and Close'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmCollectionCloseDrafts;
|
||||
@@ -1,15 +1,24 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import Modal from 'components/Modal';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { IconFiles } from '@tabler/icons';
|
||||
import { removeCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { findCollectionByUid } from 'utils/collections/index';
|
||||
import { findCollectionByUid, flattenItems, isItemARequest, hasRequestChanges } from 'utils/collections/index';
|
||||
import filter from 'lodash/filter';
|
||||
import ConfirmCollectionCloseDrafts from './ConfirmCollectionCloseDrafts';
|
||||
|
||||
const RemoveCollection = ({ onClose, collectionUid }) => {
|
||||
const dispatch = useDispatch();
|
||||
const collection = useSelector(state => findCollectionByUid(state.collections.collections, collectionUid));
|
||||
|
||||
// Detect drafts in the collection
|
||||
const drafts = useMemo(() => {
|
||||
if (!collection) return [];
|
||||
const items = flattenItems(collection.items);
|
||||
return filter(items, (item) => isItemARequest(item) && hasRequestChanges(item));
|
||||
}, [collection]);
|
||||
|
||||
const onConfirm = () => {
|
||||
dispatch(removeCollection(collection.uid))
|
||||
.then(() => {
|
||||
@@ -19,6 +28,12 @@ const RemoveCollection = ({ onClose, collectionUid }) => {
|
||||
.catch(() => toast.error('An error occurred while closing the collection'));
|
||||
};
|
||||
|
||||
// If there are drafts, show the draft confirmation modal
|
||||
if (drafts.length > 0) {
|
||||
return <ConfirmCollectionCloseDrafts onClose={onClose} collection={collection} collectionUid={collectionUid} />;
|
||||
}
|
||||
|
||||
// Otherwise, show the standard close confirmation modal
|
||||
return (
|
||||
<Modal size="sm" title="Close Collection" confirmText="Close" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||
<div className="flex items-center">
|
||||
|
||||
Reference in New Issue
Block a user