feat: added request tab context menu (#2183)

* feat: added close menus on the request tab

* feat: added close to the left button

* feat: added new request and clone request buttons

* chore: fix prettier
This commit is contained in:
Rinku Chaudhari 2024-08-14 15:55:44 +05:45 committed by GitHub
parent 8de6b72ab9
commit 1bedfc2046
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 165 additions and 5 deletions

View File

@ -40,10 +40,15 @@ const Wrapper = styled.div`
color: ${(props) => props.theme.dropdown.iconColor}; color: ${(props) => props.theme.dropdown.iconColor};
} }
&:hover { &:hover:not(:disabled) {
background-color: ${(props) => props.theme.dropdown.hoverBg}; background-color: ${(props) => props.theme.dropdown.hoverBg};
} }
&:disabled {
cursor: not-allowed;
color: gray;
}
&.border-top { &.border-top {
border-top: solid 1px ${(props) => props.theme.dropdown.separator}; border-top: solid 1px ${(props) => props.theme.dropdown.separator};
} }

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useRef, Fragment } 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';
@ -12,12 +12,18 @@ import ConfirmRequestClose from './ConfirmRequestClose';
import RequestTabNotFound from './RequestTabNotFound'; import RequestTabNotFound from './RequestTabNotFound';
import SpecialTab from './SpecialTab'; import SpecialTab from './SpecialTab';
import StyledWrapper from './StyledWrapper'; import StyledWrapper from './StyledWrapper';
import Dropdown from 'components/Dropdown';
import CloneCollectionItem from 'components/Sidebar/Collections/Collection/CollectionItem/CloneCollectionItem/index';
import NewRequest from 'components/Sidebar/NewRequest/index';
const RequestTab = ({ tab, collection, folderUid }) => { const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUid }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { storedTheme } = useTheme(); const { storedTheme } = useTheme();
const [showConfirmClose, setShowConfirmClose] = useState(false); const [showConfirmClose, setShowConfirmClose] = useState(false);
const dropdownTippyRef = useRef();
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
const handleCloseClick = (event) => { const handleCloseClick = (event) => {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -28,6 +34,19 @@ const RequestTab = ({ tab, collection, folderUid }) => {
); );
}; };
const handleRightClick = (_event) => {
const menuDropdown = dropdownTippyRef.current;
if (!menuDropdown) {
return;
}
if (menuDropdown.state.isShown) {
menuDropdown.hide();
} else {
menuDropdown.show();
}
};
const handleMouseUp = (e) => { const handleMouseUp = (e) => {
if (e.button === 1) { if (e.button === 1) {
e.stopPropagation(); e.stopPropagation();
@ -143,6 +162,7 @@ const RequestTab = ({ tab, collection, folderUid }) => {
)} )}
<div <div
className="flex items-baseline tab-label pl-2" className="flex items-baseline tab-label pl-2"
onContextMenu={handleRightClick}
onMouseUp={(e) => { onMouseUp={(e) => {
if (!item.draft) return handleMouseUp(e); if (!item.draft) return handleMouseUp(e);
@ -159,6 +179,15 @@ const RequestTab = ({ tab, collection, folderUid }) => {
<span className="ml-1 tab-name" title={item.name}> <span className="ml-1 tab-name" title={item.name}>
{item.name} {item.name}
</span> </span>
<RequestTabMenu
onDropdownCreate={onDropdownCreate}
tabIndex={tabIndex}
collectionRequestTabs={collectionRequestTabs}
tabItem={item}
collection={collection}
dropdownTippyRef={dropdownTippyRef}
dispatch={dispatch}
/>
</div> </div>
<div <div
className="flex px-2 close-icon-container" className="flex px-2 close-icon-container"
@ -195,4 +224,124 @@ const RequestTab = ({ tab, collection, folderUid }) => {
); );
}; };
function RequestTabMenu({ onDropdownCreate, collectionRequestTabs, tabIndex, collection, dropdownTippyRef, dispatch }) {
const [showCloneRequestModal, setShowCloneRequestModal] = useState(false);
const [showAddNewRequestModal, setShowAddNewRequestModal] = useState(false);
const totalTabs = collectionRequestTabs.length || 0;
const currentTabUid = collectionRequestTabs[tabIndex]?.uid;
const currentTabItem = findItemInCollection(collection, currentTabUid);
const hasLeftTabs = tabIndex !== 0;
const hasRightTabs = totalTabs > tabIndex + 1;
const hasOtherTabs = totalTabs > 1;
async function handleCloseTab(event, tabUid) {
event.stopPropagation();
dropdownTippyRef.current.hide();
if (!tabUid) {
return;
}
try {
const item = findItemInCollection(collection, tabUid);
// silently save unsaved changes before closing the tab
if (item.draft) {
await dispatch(saveRequest(item.uid, collection.uid, true));
}
dispatch(closeTabs({ tabUids: [tabUid] }));
} catch (err) {}
}
function handleCloseOtherTabs(event) {
dropdownTippyRef.current.hide();
const otherTabs = collectionRequestTabs.filter((_, index) => index !== tabIndex);
otherTabs.forEach((tab) => handleCloseTab(event, tab.uid));
}
function handleCloseTabsToTheLeft(event) {
dropdownTippyRef.current.hide();
const leftTabs = collectionRequestTabs.filter((_, index) => index < tabIndex);
leftTabs.forEach((tab) => handleCloseTab(event, tab.uid));
}
function handleCloseTabsToTheRight(event) {
dropdownTippyRef.current.hide();
const rightTabs = collectionRequestTabs.filter((_, index) => index > tabIndex);
rightTabs.forEach((tab) => handleCloseTab(event, tab.uid));
}
function handleCloseSavedTabs(event) {
event.stopPropagation();
const savedTabs = collection.items.filter((item) => !item.draft);
const savedTabIds = savedTabs.map((item) => item.uid) || [];
dispatch(closeTabs({ tabUids: savedTabIds }));
}
function handleCloseAllTabs(event) {
collectionRequestTabs.forEach((tab) => handleCloseTab(event, tab.uid));
}
return (
<Fragment>
{showAddNewRequestModal && (
<NewRequest collection={collection} onClose={() => setShowAddNewRequestModal(false)} />
)}
{showCloneRequestModal && (
<CloneCollectionItem
item={currentTabItem}
collection={collection}
onClose={() => setShowCloneRequestModal(false)}
/>
)}
<Dropdown onCreate={onDropdownCreate} icon={<span></span>} placement="bottom-start">
<button
className="dropdown-item w-full"
onClick={() => {
dropdownTippyRef.current.hide();
setShowAddNewRequestModal(true);
}}
>
New Request
</button>
<button
className="dropdown-item w-full"
onClick={() => {
dropdownTippyRef.current.hide();
setShowCloneRequestModal(true);
}}
>
Clone Request
</button>
<button className="dropdown-item w-full" onClick={(e) => handleCloseTab(e, currentTabUid)}>
Close
</button>
<button disabled={!hasOtherTabs} className="dropdown-item w-full" onClick={handleCloseOtherTabs}>
Close Others
</button>
<button disabled={!hasLeftTabs} className="dropdown-item w-full" onClick={handleCloseTabsToTheLeft}>
Close to the Left
</button>
<button disabled={!hasRightTabs} className="dropdown-item w-full" onClick={handleCloseTabsToTheRight}>
Close to the Right
</button>
<button className="dropdown-item w-full" onClick={handleCloseSavedTabs}>
Close Saved
</button>
<button className="dropdown-item w-full" onClick={handleCloseAllTabs}>
Close All
</button>
</Dropdown>
</Fragment>
);
}
export default RequestTab; export default RequestTab;

View File

@ -7,7 +7,6 @@ const Wrapper = styled.div`
padding: 0; padding: 0;
margin: 0; margin: 0;
display: flex; display: flex;
position: relative;
overflow: scroll; overflow: scroll;
&::-webkit-scrollbar { &::-webkit-scrollbar {

View File

@ -110,7 +110,14 @@ const RequestTabs = () => {
role="tab" role="tab"
onClick={() => handleClick(tab)} onClick={() => handleClick(tab)}
> >
<RequestTab key={tab.uid} tab={tab} collection={activeCollection} folderUid={tab.folderUid} /> <RequestTab
collectionRequestTabs={collectionRequestTabs}
tabIndex={index}
key={tab.uid}
tab={tab}
collection={activeCollection}
folderUid={tab.folderUid}
/>
</li> </li>
); );
}) })