import React, { useState, forwardRef, useRef, useEffect } from 'react'; import classnames from 'classnames'; import { uuid } from 'utils/common'; import filter from 'lodash/filter'; import { useDrop, useDrag } from 'react-dnd'; import { IconChevronRight, IconDots, IconLoader2 } from '@tabler/icons'; import Dropdown from 'components/Dropdown'; import { collapseCollection } from 'providers/ReduxStore/slices/collections'; import { mountCollection, moveItemToRootOfCollection, moveCollectionAndPersist } from 'providers/ReduxStore/slices/collections/actions'; import { useDispatch, useSelector } from 'react-redux'; import { addTab, makeTabPermanent } from 'providers/ReduxStore/slices/tabs'; import NewRequest from 'components/Sidebar/NewRequest'; import NewFolder from 'components/Sidebar/NewFolder'; import CollectionItem from './CollectionItem'; import RemoveCollection from './RemoveCollection'; import ExportCollection from './ExportCollection'; import { doesCollectionHaveItemsMatchingSearchText } from 'utils/collections/search'; import { isItemAFolder, isItemARequest } from 'utils/collections'; import RenameCollection from './RenameCollection'; import StyledWrapper from './StyledWrapper'; import CloneCollection from './CloneCollection'; import { areItemsLoading, findItemInCollection } from 'utils/collections'; import { scrollToTheActiveTab } from 'utils/tabs'; const Collection = ({ collection, searchText }) => { const [showNewFolderModal, setShowNewFolderModal] = useState(false); const [showNewRequestModal, setShowNewRequestModal] = useState(false); const [showRenameCollectionModal, setShowRenameCollectionModal] = useState(false); const [showCloneCollectionModalOpen, setShowCloneCollectionModalOpen] = useState(false); const [showExportCollectionModal, setShowExportCollectionModal] = useState(false); const [showRemoveCollectionModal, setShowRemoveCollectionModal] = useState(false); const tabs = useSelector((state) => state.tabs.tabs); const dispatch = useDispatch(); const isLoading = areItemsLoading(collection); const collectionRef = useRef(null); const menuDropdownTippyRef = useRef(); const onMenuDropdownCreate = (ref) => (menuDropdownTippyRef.current = ref); const MenuIcon = forwardRef((props, ref) => { return (
); }); const handleRun = () => { dispatch( addTab({ uid: uuid(), collectionUid: collection.uid, type: 'collection-runner' }) ); }; const ensureCollectionIsMounted = () => { if (collection.mountStatus === 'unmounted') { dispatch(mountCollection({ collectionUid: collection.uid, collectionPathname: collection.pathname, brunoConfig: collection.brunoConfig })); } } const hasSearchText = searchText && searchText?.trim()?.length; const collectionIsCollapsed = hasSearchText ? false : collection.collapsed; const iconClassName = classnames({ 'rotate-90': !collectionIsCollapsed }); const handleClick = (event) => { if (event.detail != 1) return; // Check if the click came from the chevron icon const isChevronClick = event.target.closest('svg')?.classList.contains('chevron-icon'); setTimeout(scrollToTheActiveTab, 50); ensureCollectionIsMounted(); dispatch(collapseCollection(collection.uid)); if(!isChevronClick) { dispatch( addTab({ uid: collection.uid, collectionUid: collection.uid, type: 'collection-settings', }) ); } }; const handleDoubleClick = (event) => { dispatch(makeTabPermanent({ uid: collection.uid })) }; const handleCollectionCollapse = (e) => { e.stopPropagation(); e.preventDefault(); ensureCollectionIsMounted(); dispatch(collapseCollection(collection.uid)); } const handleRightClick = (event) => { const _menuDropdown = menuDropdownTippyRef.current; if (_menuDropdown) { let menuDropdownBehavior = 'show'; if (_menuDropdown.state.isShown) { menuDropdownBehavior = 'hide'; } _menuDropdown[menuDropdownBehavior](); } }; const viewCollectionSettings = () => { dispatch( addTab({ uid: collection.uid, collectionUid: collection.uid, type: 'collection-settings' }) ); }; const isCollectionItem = (itemType) => { return itemType.startsWith('collection-item'); }; const [{ isDragging }, drag] = useDrag({ type: "collection", item: collection, collect: (monitor) => ({ isDragging: monitor.isDragging(), }), options: { dropEffect: "move" } }); const [{ isOver }, drop] = useDrop({ accept: ["collection", `collection-item-${collection.uid}`], drop: (draggedItem, monitor) => { const itemType = monitor.getItemType(); if (isCollectionItem(itemType)) { dispatch(moveItemToRootOfCollection(collection.uid, draggedItem.uid)) } else { dispatch(moveCollectionAndPersist({draggedItem, targetItem: collection})); } }, canDrop: (draggedItem) => { return draggedItem.uid !== collection.uid; }, collect: (monitor) => ({ isOver: monitor.isOver(), }), }); drag(drop(collectionRef)); if (searchText && searchText.length) { if (!doesCollectionHaveItemsMatchingSearchText(collection, searchText)) { return null; } } const collectionRowClassName = classnames('flex py-1 collection-name items-center', { 'item-hovered': isOver }); // 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 requestItems = sortRequestItems(filter(collection.items, (i) => isItemARequest(i))); const folderItems = sortFolderItems(filter(collection.items, (i) => isItemAFolder(i))); return ( {showNewRequestModal && setShowNewRequestModal(false)} />} {showNewFolderModal && setShowNewFolderModal(false)} />} {showRenameCollectionModal && ( setShowRenameCollectionModal(false)} /> )} {showRemoveCollectionModal && ( setShowRemoveCollectionModal(false)} /> )} {showExportCollectionModal && ( setShowExportCollectionModal(false)} /> )} {showCloneCollectionModalOpen && ( setShowCloneCollectionModalOpen(false)} /> )}
{isLoading ? : null}
} placement="bottom-start">
{ menuDropdownTippyRef.current.hide(); setShowNewRequestModal(true); }} > New Request
{ menuDropdownTippyRef.current.hide(); setShowNewFolderModal(true); }} > New Folder
{ menuDropdownTippyRef.current.hide(); setShowCloneCollectionModalOpen(true); }} > Clone
{ menuDropdownTippyRef.current.hide(); handleRun(); }} > Run
{ menuDropdownTippyRef.current.hide(); setShowRenameCollectionModal(true); }} > Rename
{ menuDropdownTippyRef.current.hide(); setShowExportCollectionModal(true); }} > Export
{ menuDropdownTippyRef.current.hide(); setShowRemoveCollectionModal(true); }} > Close
{ menuDropdownTippyRef.current.hide(); viewCollectionSettings(); }} > Settings
{!collectionIsCollapsed ? (
{folderItems && folderItems.length ? folderItems.map((i) => { return ; }) : null} {requestItems && requestItems.length ? requestItems.map((i) => { return ; }) : null}
) : null}
); }; export default Collection;