forked from extern/bruno
feat: move requests across folders
This commit is contained in:
parent
6ce657d891
commit
ee4734c957
@ -7,6 +7,7 @@ import { IconChevronRight, IconDots } from '@tabler/icons';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { addTab, focusTab } from 'providers/ReduxStore/slices/tabs';
|
||||
import { collectionFolderClicked } from 'providers/ReduxStore/slices/collections';
|
||||
import { moveItem } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import Dropdown from 'components/Dropdown';
|
||||
import NewRequest from 'components/Sidebar/NewRequest';
|
||||
import NewFolder from 'components/Sidebar/NewFolder';
|
||||
@ -26,23 +27,6 @@ const CollectionItem = ({ item, collection, searchText }) => {
|
||||
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
||||
const isSidebarDragging = useSelector((state) => state.app.isDragging);
|
||||
const dispatch = useDispatch();
|
||||
const ref = useRef(null)
|
||||
|
||||
const [{isDragging}, drag] = useDrag(() => ({
|
||||
type: 'collection-item',
|
||||
collect: monitor => ({
|
||||
isDragging: !!monitor.isDragging(),
|
||||
})
|
||||
}));
|
||||
const [{ isOver, canDrop }, drop] = useDrop({
|
||||
accept: 'collection-item',
|
||||
drop: () => console.log('dropped'),
|
||||
canDrop: () => true,
|
||||
collect: monitor => ({
|
||||
isOver: !!monitor.isOver(),
|
||||
canDrop: !!monitor.canDrop()
|
||||
}),
|
||||
});
|
||||
|
||||
const [renameItemModalOpen, setRenameItemModalOpen] = useState(false);
|
||||
const [cloneItemModalOpen, setCloneItemModalOpen] = useState(false);
|
||||
@ -51,6 +35,29 @@ const CollectionItem = ({ item, collection, searchText }) => {
|
||||
const [newFolderModalOpen, setNewFolderModalOpen] = useState(false);
|
||||
const [itemIsCollapsed, setItemisCollapsed] = useState(item.collapsed);
|
||||
|
||||
const [{ isDragging }, drag] = useDrag({
|
||||
type: 'COLLECTION_ITEM',
|
||||
item: item,
|
||||
collect: (monitor) => ({
|
||||
isDragging: monitor.isDragging()
|
||||
})
|
||||
});
|
||||
|
||||
const [{ isOver }, drop] = useDrop({
|
||||
accept: 'COLLECTION_ITEM',
|
||||
drop: (draggedItem) => {
|
||||
if (draggedItem.uid !== item.uid) {
|
||||
dispatch(moveItem(collection.uid, draggedItem.uid, item.uid));
|
||||
}
|
||||
},
|
||||
canDrop: (draggedItem) => {
|
||||
return draggedItem.id !== item.uid;
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
isOver: monitor.isOver()
|
||||
})
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (searchText && searchText.length) {
|
||||
setItemisCollapsed(false);
|
||||
@ -127,8 +134,6 @@ const CollectionItem = ({ item, collection, searchText }) => {
|
||||
const requestItems = filter(item.items, (i) => isItemARequest(i));
|
||||
const folderItems = filter(item.items, (i) => isItemAFolder(i));
|
||||
|
||||
drag(drop(ref))
|
||||
|
||||
return (
|
||||
<StyledWrapper className={className}>
|
||||
{renameItemModalOpen && <RenameCollectionItem item={item} collection={collection} onClose={() => setRenameItemModalOpen(false)} />}
|
||||
@ -136,7 +141,7 @@ const CollectionItem = ({ item, collection, searchText }) => {
|
||||
{deleteItemModalOpen && <DeleteCollectionItem item={item} collection={collection} onClose={() => setDeleteItemModalOpen(false)} />}
|
||||
{newRequestModalOpen && <NewRequest item={item} collection={collection} onClose={() => setNewRequestModalOpen(false)} />}
|
||||
{newFolderModalOpen && <NewFolder item={item} collection={collection} onClose={() => setNewFolderModalOpen(false)} />}
|
||||
<div className={itemRowClassName} ref={ref}>
|
||||
<div className={itemRowClassName} ref={(node) => drag(drop(node))}>
|
||||
<div className="flex items-center h-full w-full">
|
||||
{indents && indents.length
|
||||
? indents.map((i) => {
|
||||
|
@ -7,6 +7,7 @@ import { uuid } from 'utils/common';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {
|
||||
findItemInCollection,
|
||||
moveCollectionItem,
|
||||
findCollectionByUid,
|
||||
recursivelyGetAllItemUids,
|
||||
transformCollectionToSaveToIdb,
|
||||
@ -33,6 +34,7 @@ import {
|
||||
renameItem as _renameItem,
|
||||
cloneItem as _cloneItem,
|
||||
deleteItem as _deleteItem,
|
||||
moveItem as _moveItem,
|
||||
saveRequest as _saveRequest,
|
||||
addEnvironment as _addEnvironment,
|
||||
renameEnvironment as _renameEnvironment,
|
||||
@ -550,6 +552,69 @@ export const deleteItem = (itemUid, collectionUid) => (dispatch, getState) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const moveItem = (collectionUid, draggedItemUid, targetItemUid) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!collection) {
|
||||
return reject(new Error('Collection not found'));
|
||||
}
|
||||
|
||||
if (isLocalCollection(collection)) {
|
||||
const draggedItem = findItemInCollection(collection, draggedItemUid);
|
||||
const targetItem = findItemInCollection(collection, targetItemUid);
|
||||
|
||||
if (!draggedItem) {
|
||||
return reject(new Error('Dragged item not found'));
|
||||
}
|
||||
|
||||
if (!targetItem) {
|
||||
return reject(new Error('Target item not found'));
|
||||
}
|
||||
|
||||
const { ipcRenderer } = window;
|
||||
|
||||
ipcRenderer
|
||||
.invoke('renderer:move-item', draggedItem.pathname, targetItem.pathname)
|
||||
.then(() => resolve())
|
||||
.catch((error) => reject(error));
|
||||
return;
|
||||
}
|
||||
|
||||
const collectionCopy = cloneDeep(collection);
|
||||
const draggedItem = findItemInCollection(collectionCopy, draggedItemUid);
|
||||
const targetItem = findItemInCollection(collectionCopy, targetItemUid);
|
||||
|
||||
if (!draggedItem) {
|
||||
return reject(new Error('Dragged item not found'));
|
||||
}
|
||||
|
||||
if (!targetItem) {
|
||||
return reject(new Error('Target item not found'));
|
||||
}
|
||||
|
||||
moveCollectionItem(collectionCopy, draggedItem, targetItem);
|
||||
|
||||
const collectionToSave = transformCollectionToSaveToIdb(collectionCopy);
|
||||
|
||||
collectionSchema
|
||||
.validate(collectionToSave)
|
||||
.then(() => saveCollectionToIdb(window.__idb, collectionToSave))
|
||||
.then(() => {
|
||||
dispatch(
|
||||
_moveItem({
|
||||
collectionUid: collectionUid,
|
||||
draggedItemUid: draggedItemUid,
|
||||
targetItemUid: targetItemUid
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(() => resolve())
|
||||
.catch((error) => reject(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const newHttpRequest = (params) => (dispatch, getState) => {
|
||||
const { requestName, requestType, requestUrl, requestMethod, collectionUid, itemUid } = params;
|
||||
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
findEnvironmentInCollection,
|
||||
findItemInCollectionByPathname,
|
||||
addDepth,
|
||||
moveCollectionItem,
|
||||
collapseCollection,
|
||||
deleteItemInCollection,
|
||||
isItemARequest
|
||||
@ -181,6 +182,23 @@ export const collectionsSlice = createSlice({
|
||||
}
|
||||
}
|
||||
},
|
||||
moveItem: (state, action) => {
|
||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||
const draggedItemUid = action.payload.draggedItemUid;
|
||||
const targetItemUid = action.payload.targetItemUid;
|
||||
|
||||
if (collection) {
|
||||
const draggedItem = findItemInCollection(collection, draggedItemUid);
|
||||
const targetItem = findItemInCollection(collection, targetItemUid);
|
||||
|
||||
if (!draggedItem || !targetItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
moveCollectionItem(collection, draggedItem, targetItem);
|
||||
addDepth(collection.items);
|
||||
}
|
||||
},
|
||||
requestSent: (state, action) => {
|
||||
const { itemUid, collectionUid, cancelTokenUid } = action.payload;
|
||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||
@ -785,6 +803,7 @@ export const {
|
||||
deleteItem,
|
||||
renameItem,
|
||||
cloneItem,
|
||||
moveItem,
|
||||
requestSent,
|
||||
requestCancelled,
|
||||
responseReceived,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import reckon from 'reckonjs';
|
||||
import get from 'lodash/get';
|
||||
import each from 'lodash/each';
|
||||
import find from 'lodash/find';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import isString from 'lodash/isString';
|
||||
import map from 'lodash/map';
|
||||
import filter from 'lodash/filter';
|
||||
@ -122,6 +122,31 @@ export const findEnvironmentInCollection = (collection, envUid) => {
|
||||
return find(collection.environments, (e) => e.uid === envUid);
|
||||
};
|
||||
|
||||
export const moveCollectionItem = (collection, draggedItem, targetItem) => {
|
||||
let draggedItemParent = findParentItemInCollection(collection, draggedItem.uid);
|
||||
|
||||
if (draggedItemParent) {
|
||||
draggedItemParent.items = filter(draggedItemParent.items, (i) => i.uid !== draggedItem.uid);
|
||||
} else {
|
||||
collection.items = filter(collection.items, (i) => i.uid !== draggedItem.uid);
|
||||
}
|
||||
|
||||
if (targetItem.type === 'folder') {
|
||||
targetItem.items = targetItem.items || [];
|
||||
targetItem.items.push(draggedItem);
|
||||
} else {
|
||||
let targetItemParent = findParentItemInCollection(collection, targetItem.uid);
|
||||
|
||||
if (targetItemParent) {
|
||||
let targetItemIndex = findIndex(targetItemParent.items, (i) => i.uid === targetItem.uid);
|
||||
targetItemParent.items.splice(targetItemIndex + 1, 0, draggedItem);
|
||||
} else {
|
||||
let targetItemIndex = findIndex(collection.items, (i) => i.uid === targetItem.uid);
|
||||
collection.items.splice(targetItemIndex + 1, 0, draggedItem);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const transformCollectionToSaveToIdb = (collection, options = {}) => {
|
||||
const copyHeaders = (headers) => {
|
||||
return map(headers, (header) => {
|
||||
|
Loading…
Reference in New Issue
Block a user