mirror of
https://github.com/usebruno/bruno.git
synced 2024-12-23 15:19:01 +01:00
feat: improved handling logic while closing unsaved tabs/requests
This commit is contained in:
parent
3e627522b7
commit
db9aeec498
@ -64,6 +64,7 @@ const Modal = ({
|
||||
hideFooter,
|
||||
disableCloseOnOutsideClick,
|
||||
disableEscapeKey,
|
||||
onClick,
|
||||
closeModalFadeTimeout = 500
|
||||
}) => {
|
||||
const [isClosing, setIsClosing] = useState(false);
|
||||
@ -96,7 +97,7 @@ const Modal = ({
|
||||
classes += ' modal-footer-none';
|
||||
}
|
||||
return (
|
||||
<StyledWrapper className={classes}>
|
||||
<StyledWrapper className={classes} onClick={onClick ? (e) => onClick(e) : null}>
|
||||
<div className={`bruno-modal-card modal-${size}`}>
|
||||
<ModalHeader title={title} handleCancel={() => closeModal({ type: 'icon' })} />
|
||||
<ModalContent>{children}</ModalContent>
|
||||
|
@ -1,30 +1,46 @@
|
||||
import Modal from 'components/Modal';
|
||||
import React from 'react';
|
||||
import { IconAlertTriangle } from '@tabler/icons';
|
||||
import Modal from 'components/Modal';
|
||||
|
||||
const ConfirmRequestClose = ({ item, onCancel, onCloseWithoutSave, onSaveAndClose }) => {
|
||||
const _handleCancel = ({ type }) => {
|
||||
if (type === 'button') {
|
||||
return onCloseWithoutSave();
|
||||
}
|
||||
|
||||
return onCancel();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
size="sm"
|
||||
size="md"
|
||||
title="Unsaved changes"
|
||||
confirmText="Save and Close"
|
||||
cancelText="Close without saving"
|
||||
handleConfirm={onSaveAndClose}
|
||||
handleCancel={_handleCancel}
|
||||
disableEscapeKey={true}
|
||||
disableCloseOnOutsideClick={true}
|
||||
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>.
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
|
||||
import { saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { deleteRequestDraft } from 'providers/ReduxStore/slices/collections';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import darkTheme from 'themes/dark';
|
||||
@ -135,6 +136,9 @@ const RequestTab = ({ tab, collection }) => {
|
||||
className="flex px-2 close-icon-container"
|
||||
onClick={(e) => {
|
||||
if (!item.draft) return handleCloseClick(e);
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setShowConfirmClose(true);
|
||||
}}
|
||||
>
|
||||
|
@ -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 {
|
||||
color: ${(props) => props.theme.button.secondary.color};
|
||||
background: ${(props) => props.theme.button.secondary.bg};
|
||||
|
@ -94,7 +94,7 @@ const SaveRequestsModal = ({ onClose }) => {
|
||||
|
||||
<div className="flex justify-between mt-6">
|
||||
<div>
|
||||
<button className="btn btn-sm btn-close btn-border" onClick={closeWithoutSave}>
|
||||
<button className="btn btn-sm btn-danger" onClick={closeWithoutSave}>
|
||||
Don't Save
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1,16 +1,28 @@
|
||||
import getConfig from 'next/config';
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import tasksMiddleware from './middlewares/tasks/middleware';
|
||||
import debugMiddleware from './middlewares/debug/middleware';
|
||||
import appReducer from './slices/app';
|
||||
import collectionsReducer from './slices/collections';
|
||||
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({
|
||||
reducer: {
|
||||
app: appReducer,
|
||||
collections: collectionsReducer,
|
||||
tabs: tabsReducer
|
||||
},
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(tasksMiddleware.middleware)
|
||||
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(middleware)
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
@ -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;
|
@ -1,9 +1,8 @@
|
||||
import get from 'lodash/get';
|
||||
import each from 'lodash/each';
|
||||
import filter from 'lodash/filter';
|
||||
import { uuid } from 'utils/common';
|
||||
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 { collectionAddFileEvent } from 'providers/ReduxStore/slices/collections';
|
||||
import { findCollectionByUid, findItemInCollectionByPathname, getDefaultRequestPaneTab } from 'utils/collections/index';
|
||||
|
@ -173,6 +173,11 @@ const darkTheme = {
|
||||
color: '#a5a5a5',
|
||||
bg: '#626262',
|
||||
border: '#626262'
|
||||
},
|
||||
danger: {
|
||||
color: '#fff',
|
||||
bg: '#dc3545',
|
||||
border: '#dc3545'
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -177,6 +177,11 @@ const lightTheme = {
|
||||
color: '#9f9f9f',
|
||||
bg: '#efefef',
|
||||
border: 'rgb(234, 234, 234)'
|
||||
},
|
||||
danger: {
|
||||
color: '#fff',
|
||||
bg: '#dc3545',
|
||||
border: '#dc3545'
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user