mirror of
https://github.com/usebruno/bruno.git
synced 2025-02-02 10:59:22 +01:00
feat: create request inside a folder
This commit is contained in:
parent
afb545e14b
commit
4245ef7d13
@ -1,15 +1,17 @@
|
|||||||
import React, { useState, useRef, forwardRef } from 'react';
|
import React, { useState, useRef, forwardRef } from 'react';
|
||||||
import range from 'lodash/range';
|
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import { IconChevronRight, IconDots } from '@tabler/icons';
|
import range from 'lodash/range';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { IconChevronRight, IconDots } from '@tabler/icons';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { addTab, focusTab } from 'providers/ReduxStore/slices/tabs';
|
import { addTab, focusTab } from 'providers/ReduxStore/slices/tabs';
|
||||||
import { isItemARequest, isItemAFolder, itemIsOpenedInTabs } from 'utils/tabs';
|
import { collectionFolderClicked } from 'providers/ReduxStore/slices/collections';
|
||||||
import Dropdown from 'components/Dropdown';
|
import Dropdown from 'components/Dropdown';
|
||||||
|
import NewRequest from 'components/Sidebar/NewRequest';
|
||||||
import RequestMethod from './RequestMethod';
|
import RequestMethod from './RequestMethod';
|
||||||
import RenameCollectionItem from './RenameCollectionItem';
|
import RenameCollectionItem from './RenameCollectionItem';
|
||||||
import DeleteCollectionItem from './DeleteCollectionItem';
|
import DeleteCollectionItem from './DeleteCollectionItem';
|
||||||
|
import { isItemARequest, isItemAFolder, itemIsOpenedInTabs } from 'utils/tabs';
|
||||||
|
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
@ -20,6 +22,7 @@ const CollectionItem = ({item, collection}) => {
|
|||||||
|
|
||||||
const [renameItemModalOpen, setRenameItemModalOpen] = useState(false);
|
const [renameItemModalOpen, setRenameItemModalOpen] = useState(false);
|
||||||
const [deleteItemModalOpen, setDeleteItemModalOpen] = useState(false);
|
const [deleteItemModalOpen, setDeleteItemModalOpen] = useState(false);
|
||||||
|
const [newRequestModalOpen, setNewRequestModalOpen] = useState(false);
|
||||||
|
|
||||||
const dropdownTippyRef = useRef();
|
const dropdownTippyRef = useRef();
|
||||||
const MenuIcon = forwardRef((props, ref) => {
|
const MenuIcon = forwardRef((props, ref) => {
|
||||||
@ -44,6 +47,10 @@ const CollectionItem = ({item, collection}) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(event && event.target && event.target.className === 'dropdown-item') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(isItemARequest(item)) {
|
if(isItemARequest(item)) {
|
||||||
if(itemIsOpenedInTabs(item, tabs)) {
|
if(itemIsOpenedInTabs(item, tabs)) {
|
||||||
dispatch(focusTab({
|
dispatch(focusTab({
|
||||||
@ -56,19 +63,22 @@ const CollectionItem = ({item, collection}) => {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// todo for folder: must expand folder : item.collapsed = !item.collapsed;
|
dispatch(collectionFolderClicked({
|
||||||
|
itemUid: item.uid,
|
||||||
|
collectionUid: collection.uid
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let indents = range(item.depth);
|
let indents = range(item.depth);
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
||||||
const isRequest = isItemARequest(item);
|
|
||||||
const isFolder = isItemAFolder(item);
|
const isFolder = isItemAFolder(item);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="flex flex-col">
|
<StyledWrapper className="flex flex-col">
|
||||||
{renameItemModalOpen && <RenameCollectionItem item={item} collection={collection} onClose={() => setRenameItemModalOpen(false)}/>}
|
{renameItemModalOpen && <RenameCollectionItem item={item} collection={collection} onClose={() => setRenameItemModalOpen(false)}/>}
|
||||||
{deleteItemModalOpen && <DeleteCollectionItem item={item} collection={collection} onClose={() => setDeleteItemModalOpen(false)}/>}
|
{deleteItemModalOpen && <DeleteCollectionItem item={item} collection={collection} onClose={() => setDeleteItemModalOpen(false)}/>}
|
||||||
|
{newRequestModalOpen && <NewRequest item={item} collection={collection} onClose={() => setNewRequestModalOpen(false)}/>}
|
||||||
<div
|
<div
|
||||||
className={itemRowClassName}
|
className={itemRowClassName}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
@ -111,6 +121,7 @@ const CollectionItem = ({item, collection}) => {
|
|||||||
<>
|
<>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div className="dropdown-item" onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
|
setNewRequestModalOpen(true);
|
||||||
}}>
|
}}>
|
||||||
New Request
|
New Request
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,17 +44,10 @@ const Collection = ({collection}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hideNewFolderModal = () => setShowNewFolderModal(false);
|
const hideNewFolderModal = () => setShowNewFolderModal(false);
|
||||||
const hideNewRequestModal = () => setShowNewRequestModal(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="flex flex-col">
|
<StyledWrapper className="flex flex-col">
|
||||||
{showNewRequestModal && (
|
{showNewRequestModal && <NewRequest collection={collection} onClose={() => setShowNewRequestModal(false)}/>}
|
||||||
<NewRequest
|
|
||||||
collectionUid={collection.uid}
|
|
||||||
handleCancel={hideNewRequestModal}
|
|
||||||
handleClose={hideNewRequestModal}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{showNewFolderModal && (
|
{showNewFolderModal && (
|
||||||
<NewFolder
|
<NewFolder
|
||||||
collectionUid={collection.uid}
|
collectionUid={collection.uid}
|
||||||
|
@ -6,7 +6,7 @@ import { useDispatch } from 'react-redux';
|
|||||||
import { newHttpRequest } from 'providers/ReduxStore/slices/collections';
|
import { newHttpRequest } from 'providers/ReduxStore/slices/collections';
|
||||||
import { addTab } from 'providers/ReduxStore/slices/tabs';
|
import { addTab } from 'providers/ReduxStore/slices/tabs';
|
||||||
|
|
||||||
const NewRequest = ({collectionUid, handleCancel, handleClose}) => {
|
const NewRequest = ({collection, item, onClose}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const inputRef = useRef();
|
const inputRef = useRef();
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@ -21,14 +21,14 @@ const NewRequest = ({collectionUid, handleCancel, handleClose}) => {
|
|||||||
.required('name is required')
|
.required('name is required')
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(newHttpRequest(values.requestName, collectionUid))
|
dispatch(newHttpRequest(values.requestName, collection.uid, item ? item.uid : null))
|
||||||
.then((action) => {
|
.then((action) => {
|
||||||
dispatch(addTab({
|
dispatch(addTab({
|
||||||
uid: action.payload.item.uid,
|
uid: action.payload.item.uid,
|
||||||
collectionUid: collectionUid
|
collectionUid: collection.uid
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
handleClose();
|
onClose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ const NewRequest = ({collectionUid, handleCancel, handleClose}) => {
|
|||||||
title='New Request'
|
title='New Request'
|
||||||
confirmText='Create'
|
confirmText='Create'
|
||||||
handleConfirm={onSubmit}
|
handleConfirm={onSubmit}
|
||||||
handleCancel={handleCancel}
|
handleCancel={onClose}
|
||||||
>
|
>
|
||||||
<form className="grafnode-form" onSubmit={formik.handleSubmit}>
|
<form className="grafnode-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
|
@ -80,7 +80,16 @@ export const collectionsSlice = createSlice({
|
|||||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
if(collection) {
|
if(collection) {
|
||||||
collection.items.push(action.payload.item);
|
if(!action.payload.currentItemUid) {
|
||||||
|
collection.items.push(action.payload.item);
|
||||||
|
} else {
|
||||||
|
const item = findItemInCollection(collection, action.payload.currentItemUid);
|
||||||
|
|
||||||
|
if(item) {
|
||||||
|
item.items = item.items || [];
|
||||||
|
item.items.push(action.payload.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
addDepth(collection.items);
|
addDepth(collection.items);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -109,6 +118,17 @@ export const collectionsSlice = createSlice({
|
|||||||
collection.collapsed = !collection.collapsed;
|
collection.collapsed = !collection.collapsed;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
collectionFolderClicked: (state, action) => {
|
||||||
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
|
if(collection) {
|
||||||
|
const item = findItemInCollection(collection, action.payload.itemUid);
|
||||||
|
|
||||||
|
if(item && item.type === 'folder') {
|
||||||
|
item.collapsed = !item.collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
requestUrlChanged: (state, action) => {
|
requestUrlChanged: (state, action) => {
|
||||||
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
|
||||||
|
|
||||||
@ -137,6 +157,7 @@ export const {
|
|||||||
_deleteItem,
|
_deleteItem,
|
||||||
_renameItem,
|
_renameItem,
|
||||||
collectionClicked,
|
collectionClicked,
|
||||||
|
collectionFolderClicked,
|
||||||
requestUrlChanged,
|
requestUrlChanged,
|
||||||
} = collectionsSlice.actions;
|
} = collectionsSlice.actions;
|
||||||
|
|
||||||
@ -220,7 +241,7 @@ export const newFolder = (folderName, collectionUid) => (dispatch, getState) =>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newHttpRequest = (requestName, collectionUid) => (dispatch, getState) => {
|
export const newHttpRequest = (requestName, collectionUid, itemUid) => (dispatch, getState) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
||||||
@ -239,13 +260,22 @@ export const newHttpRequest = (requestName, collectionUid) => (dispatch, getStat
|
|||||||
body: null
|
body: null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
collectionCopy.items.push(item);
|
if(!itemUid) {
|
||||||
|
collectionCopy.items.push(item);
|
||||||
|
} else {
|
||||||
|
const currentItem = findItemInCollection(collectionCopy, itemUid);
|
||||||
|
if(currentItem && currentItem.type === 'folder') {
|
||||||
|
currentItem.items = currentItem.items || [];
|
||||||
|
currentItem.items.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
const collectionToSave = transformCollectionToSaveToIdb(collectionCopy);
|
const collectionToSave = transformCollectionToSaveToIdb(collectionCopy);
|
||||||
|
|
||||||
saveCollectionToIdb(window.__idb, collectionToSave)
|
saveCollectionToIdb(window.__idb, collectionToSave)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
Promise.resolve(dispatch(_newRequest({
|
Promise.resolve(dispatch(_newRequest({
|
||||||
item: item,
|
item: item,
|
||||||
|
currentItemUid: itemUid,
|
||||||
collectionUid: collectionUid
|
collectionUid: collectionUid
|
||||||
})))
|
})))
|
||||||
.then((val) => resolve(val))
|
.then((val) => resolve(val))
|
||||||
|
@ -30,7 +30,6 @@ html, body {
|
|||||||
font-kerning: none;
|
font-kerning: none;
|
||||||
text-rendering: optimizeSpeed;
|
text-rendering: optimizeSpeed;
|
||||||
letter-spacing: normal;
|
letter-spacing: normal;
|
||||||
/* font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; */
|
|
||||||
font-family: Inter, sans-serif !important;
|
font-family: Inter, sans-serif !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user