feat: improved handling logic while closing unsaved tabs/requests

This commit is contained in:
Anoop M D 2024-01-09 22:12:40 +05:30
parent 3e627522b7
commit db9aeec498
10 changed files with 87 additions and 18 deletions

View File

@ -64,6 +64,7 @@ const Modal = ({
hideFooter, hideFooter,
disableCloseOnOutsideClick, disableCloseOnOutsideClick,
disableEscapeKey, disableEscapeKey,
onClick,
closeModalFadeTimeout = 500 closeModalFadeTimeout = 500
}) => { }) => {
const [isClosing, setIsClosing] = useState(false); const [isClosing, setIsClosing] = useState(false);
@ -96,7 +97,7 @@ const Modal = ({
classes += ' modal-footer-none'; classes += ' modal-footer-none';
} }
return ( return (
<StyledWrapper className={classes}> <StyledWrapper className={classes} onClick={onClick ? (e) => onClick(e) : null}>
<div className={`bruno-modal-card modal-${size}`}> <div className={`bruno-modal-card modal-${size}`}>
<ModalHeader title={title} handleCancel={() => closeModal({ type: 'icon' })} /> <ModalHeader title={title} handleCancel={() => closeModal({ type: 'icon' })} />
<ModalContent>{children}</ModalContent> <ModalContent>{children}</ModalContent>

View File

@ -1,30 +1,46 @@
import Modal from 'components/Modal';
import React from 'react'; import React from 'react';
import { IconAlertTriangle } from '@tabler/icons';
import Modal from 'components/Modal';
const ConfirmRequestClose = ({ item, onCancel, onCloseWithoutSave, onSaveAndClose }) => { const ConfirmRequestClose = ({ item, onCancel, onCloseWithoutSave, onSaveAndClose }) => {
const _handleCancel = ({ type }) => {
if (type === 'button') {
return onCloseWithoutSave();
}
return onCancel();
};
return ( return (
<Modal <Modal
size="sm" size="md"
title="Unsaved changes" title="Unsaved changes"
confirmText="Save and Close" confirmText="Save and Close"
cancelText="Close without saving" cancelText="Close without saving"
handleConfirm={onSaveAndClose}
handleCancel={_handleCancel}
disableEscapeKey={true} disableEscapeKey={true}
disableCloseOnOutsideClick={true} disableCloseOnOutsideClick={true}
closeModalFadeTimeout={150} closeModalFadeTimeout={150}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
hideFooter={true}
> >
<div className="font-normal"> <div className="flex items-center font-normal">
<IconAlertTriangle size={32} strokeWidth={1.5} className="text-yellow-600" />
<h1 className="ml-2 text-lg font-semibold">Hold on..</h1>
</div>
<div className="font-normal mt-4">
You have unsaved changes in request <span className="font-semibold">{item.name}</span>. You have unsaved changes in request <span className="font-semibold">{item.name}</span>.
</div> </div>
<div className="flex justify-between mt-6">
<div>
<button className="btn btn-sm btn-danger" onClick={onCloseWithoutSave}>
Don't Save
</button>
</div>
<div>
<button className="btn btn-close btn-sm mr-2" onClick={onCancel}>
Cancel
</button>
<button className="btn btn-secondary btn-sm" onClick={onSaveAndClose}>
Save
</button>
</div>
</div>
</Modal> </Modal>
); );
}; };

View File

@ -2,6 +2,7 @@ import React, { useState } from 'react';
import get from 'lodash/get'; import get from 'lodash/get';
import { closeTabs } from 'providers/ReduxStore/slices/tabs'; import { closeTabs } from 'providers/ReduxStore/slices/tabs';
import { saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { saveRequest } from 'providers/ReduxStore/slices/collections/actions';
import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections';
import { useTheme } from 'providers/Theme'; import { useTheme } from 'providers/Theme';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import darkTheme from 'themes/dark'; import darkTheme from 'themes/dark';
@ -135,6 +136,9 @@ const RequestTab = ({ tab, collection }) => {
className="flex px-2 close-icon-container" className="flex px-2 close-icon-container"
onClick={(e) => { onClick={(e) => {
if (!item.draft) return handleCloseClick(e); if (!item.draft) return handleCloseClick(e);
e.stopPropagation();
e.preventDefault();
setShowConfirmClose(true); setShowConfirmClose(true);
}} }}
> >

View File

@ -57,6 +57,18 @@ const GlobalStyle = createGlobalStyle`
} }
} }
.btn-danger {
color: ${(props) => props.theme.button.danger.color};
background: ${(props) => props.theme.button.danger.bg};
border: solid 1px ${(props) => props.theme.button.danger.border};
&:hover,
&:focus {
outline: none;
box-shadow: none;
}
}
.btn-secondary { .btn-secondary {
color: ${(props) => props.theme.button.secondary.color}; color: ${(props) => props.theme.button.secondary.color};
background: ${(props) => props.theme.button.secondary.bg}; background: ${(props) => props.theme.button.secondary.bg};

View File

@ -94,7 +94,7 @@ const SaveRequestsModal = ({ onClose }) => {
<div className="flex justify-between mt-6"> <div className="flex justify-between mt-6">
<div> <div>
<button className="btn btn-sm btn-close btn-border" onClick={closeWithoutSave}> <button className="btn btn-sm btn-danger" onClick={closeWithoutSave}>
Don't Save Don't Save
</button> </button>
</div> </div>

View File

@ -1,16 +1,28 @@
import getConfig from 'next/config';
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import tasksMiddleware from './middlewares/tasks/middleware'; import tasksMiddleware from './middlewares/tasks/middleware';
import debugMiddleware from './middlewares/debug/middleware';
import appReducer from './slices/app'; import appReducer from './slices/app';
import collectionsReducer from './slices/collections'; import collectionsReducer from './slices/collections';
import tabsReducer from './slices/tabs'; import tabsReducer from './slices/tabs';
const { publicRuntimeConfig } = getConfig();
const isDevEnv = () => {
return publicRuntimeConfig.ENV === 'dev';
};
let middleware = [tasksMiddleware.middleware];
if (isDevEnv()) {
middleware = [...middleware, debugMiddleware.middleware];
}
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
app: appReducer, app: appReducer,
collections: collectionsReducer, collections: collectionsReducer,
tabs: tabsReducer tabs: tabsReducer
}, },
middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(tasksMiddleware.middleware) middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(middleware)
}); });
export default store; export default store;

View File

@ -0,0 +1,15 @@
import { createListenerMiddleware } from '@reduxjs/toolkit';
const debugMiddleware = createListenerMiddleware();
debugMiddleware.startListening({
predicate: () => true, // it'll track every change
effect: (action, listenerApi) => {
console.debug('---redux action---');
console.debug('action', action.type); // which action did it
console.debug('action.payload', action.payload);
console.debug(listenerApi.getState()); // the updated store
}
});
export default debugMiddleware;

View File

@ -1,9 +1,8 @@
import get from 'lodash/get'; import get from 'lodash/get';
import each from 'lodash/each'; import each from 'lodash/each';
import filter from 'lodash/filter'; import filter from 'lodash/filter';
import { uuid } from 'utils/common';
import { createListenerMiddleware } from '@reduxjs/toolkit'; import { createListenerMiddleware } from '@reduxjs/toolkit';
import { completeQuitFlow, removeTaskFromQueue, hideHomePage } from 'providers/ReduxStore/slices/app'; import { removeTaskFromQueue, hideHomePage } from 'providers/ReduxStore/slices/app';
import { addTab } from 'providers/ReduxStore/slices/tabs'; import { addTab } from 'providers/ReduxStore/slices/tabs';
import { collectionAddFileEvent } from 'providers/ReduxStore/slices/collections'; import { collectionAddFileEvent } from 'providers/ReduxStore/slices/collections';
import { findCollectionByUid, findItemInCollectionByPathname, getDefaultRequestPaneTab } from 'utils/collections/index'; import { findCollectionByUid, findItemInCollectionByPathname, getDefaultRequestPaneTab } from 'utils/collections/index';

View File

@ -173,6 +173,11 @@ const darkTheme = {
color: '#a5a5a5', color: '#a5a5a5',
bg: '#626262', bg: '#626262',
border: '#626262' border: '#626262'
},
danger: {
color: '#fff',
bg: '#dc3545',
border: '#dc3545'
} }
}, },

View File

@ -177,6 +177,11 @@ const lightTheme = {
color: '#9f9f9f', color: '#9f9f9f',
bg: '#efefef', bg: '#efefef',
border: 'rgb(234, 234, 234)' border: 'rgb(234, 234, 234)'
},
danger: {
color: '#fff',
bg: '#dc3545',
border: '#dc3545'
} }
}, },