import React, { useState, useRef, forwardRef, useEffect } from 'react';
import range from 'lodash/range';
import filter from 'lodash/filter';
import classnames from 'classnames';
import { useDrag, useDrop } from 'react-dnd';
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';
import RequestMethod from './RequestMethod';
import RenameCollectionItem from './RenameCollectionItem';
import CloneCollectionItem from './CloneCollectionItem';
import DeleteCollectionItem from './DeleteCollectionItem';
import RunCollectionItem from './RunCollectionItem';
import GenerateCodeItem from './GenerateCodeItem';
import { isItemARequest, isItemAFolder, itemIsOpenedInTabs } from 'utils/tabs';
import { doesRequestMatchSearchText, doesFolderHaveItemsMatchSearchText } from 'utils/collections/search';
import { getDefaultRequestPaneTab } from 'utils/collections';
import { hideHomePage } from 'providers/ReduxStore/slices/app';
import toast from 'react-hot-toast';
import StyledWrapper from './StyledWrapper';
const CollectionItem = ({ item, collection, searchText }) => {
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
const isSidebarDragging = useSelector((state) => state.app.isDragging);
const dispatch = useDispatch();
const [renameItemModalOpen, setRenameItemModalOpen] = useState(false);
const [cloneItemModalOpen, setCloneItemModalOpen] = useState(false);
const [deleteItemModalOpen, setDeleteItemModalOpen] = useState(false);
const [generateCodeItemModalOpen, setGenerateCodeItemModalOpen] = useState(false);
const [newRequestModalOpen, setNewRequestModalOpen] = useState(false);
const [newFolderModalOpen, setNewFolderModalOpen] = useState(false);
const [runCollectionModalOpen, setRunCollectionModalOpen] = useState(false);
const [itemIsCollapsed, setItemisCollapsed] = useState(item.collapsed);
const [{ isDragging }, drag] = useDrag({
type: `COLLECTION_ITEM_${collection.uid}`,
item: item,
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
});
const [{ isOver }, drop] = useDrop({
accept: `COLLECTION_ITEM_${collection.uid}`,
drop: (draggedItem) => {
if (draggedItem.uid !== item.uid) {
dispatch(moveItem(collection.uid, draggedItem.uid, item.uid));
}
},
canDrop: (draggedItem) => {
return draggedItem.uid !== item.uid;
},
collect: (monitor) => ({
isOver: monitor.isOver()
})
});
useEffect(() => {
if (searchText && searchText.length) {
setItemisCollapsed(false);
} else {
setItemisCollapsed(item.collapsed);
}
}, [searchText, item]);
const dropdownTippyRef = useRef();
const MenuIcon = forwardRef((props, ref) => {
return (
);
});
const iconClassName = classnames({
'rotate-90': !itemIsCollapsed
});
const itemRowClassName = classnames('flex collection-item-name items-center', {
'item-focused-in-tab': item.uid == activeTabUid
});
const handleClick = (event) => {
switch (event.button) {
case 0: // left click
if (isItemARequest(item)) {
dispatch(hideHomePage());
if (itemIsOpenedInTabs(item, tabs)) {
dispatch(
focusTab({
uid: item.uid
})
);
return;
}
dispatch(
addTab({
uid: item.uid,
collectionUid: collection.uid,
requestPaneTab: getDefaultRequestPaneTab(item)
})
);
return;
}
dispatch(
collectionFolderClicked({
itemUid: item.uid,
collectionUid: collection.uid
})
);
return;
case 2: // right click
const _menuDropdown = dropdownTippyRef.current;
if (_menuDropdown) {
let menuDropdownBehavior = 'show';
if (_menuDropdown.state.isShown) {
menuDropdownBehavior = 'hide';
}
_menuDropdown[menuDropdownBehavior]();
}
return;
}
};
const handleDoubleClick = (event) => {
setRenameItemModalOpen(true);
};
let indents = range(item.depth);
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
const isFolder = isItemAFolder(item);
const className = classnames('flex flex-col w-full', {
'is-sidebar-dragging': isSidebarDragging
});
if (searchText && searchText.length) {
if (isItemARequest(item)) {
if (!doesRequestMatchSearchText(item, searchText)) {
return null;
}
} else {
if (!doesFolderHaveItemsMatchSearchText(item, searchText)) {
return null;
}
}
}
// we need to sort request items by seq property
const sortRequestItems = (items = []) => {
return items.sort((a, b) => a.seq - b.seq);
};
// we need to sort folder items by name alphabetically
const sortFolderItems = (items = []) => {
return items.sort((a, b) => a.name.localeCompare(b.name));
};
const handleGenerateCode = (e) => {
e.stopPropagation();
dropdownTippyRef.current.hide();
if (item.request.url !== '' || (item.draft?.request.url !== undefined && item.draft?.request.url !== '')) {
setGenerateCodeItemModalOpen(true);
} else {
toast.error('URL is required');
}
};
const requestItems = sortRequestItems(filter(item.items, (i) => isItemARequest(i)));
const folderItems = sortFolderItems(filter(item.items, (i) => isItemAFolder(i)));
return (
{renameItemModalOpen && (
setRenameItemModalOpen(false)} />
)}
{cloneItemModalOpen && (
setCloneItemModalOpen(false)} />
)}
{deleteItemModalOpen && (
setDeleteItemModalOpen(false)} />
)}
{newRequestModalOpen && (
setNewRequestModalOpen(false)} />
)}
{newFolderModalOpen && (
setNewFolderModalOpen(false)} />
)}
{runCollectionModalOpen && (
setRunCollectionModalOpen(false)} />
)}
{generateCodeItemModalOpen && (
setGenerateCodeItemModalOpen(false)} />
)}
drag(drop(node))}>
{indents && indents.length
? indents.map((i) => {
return (
{/* Indent */}
);
})
: null}
{isFolder ? (
) : null}
{item.name}
} placement="bottom-start">
{isFolder && (
<>
{
dropdownTippyRef.current.hide();
setNewRequestModalOpen(true);
}}
>
New Request
{
dropdownTippyRef.current.hide();
setNewFolderModalOpen(true);
}}
>
New Folder
{
dropdownTippyRef.current.hide();
setRunCollectionModalOpen(true);
}}
>
Run
>
)}
{
dropdownTippyRef.current.hide();
setRenameItemModalOpen(true);
}}
>
Rename
{!isFolder && (
{
dropdownTippyRef.current.hide();
setCloneItemModalOpen(true);
}}
>
Clone
)}
{!isFolder && item.type === 'http-request' && (
{
handleGenerateCode(e);
}}
>
Generate Code
)}
{
dropdownTippyRef.current.hide();
setDeleteItemModalOpen(true);
}}
>
Delete
{!itemIsCollapsed ? (
{folderItems && folderItems.length
? folderItems.map((i) => {
return ;
})
: null}
{requestItems && requestItems.length
? requestItems.map((i) => {
return ;
})
: null}
) : null}
);
};
export default CollectionItem;