forked from extern/bruno
feat: local collections displayed separately (resolves #22)
This commit is contained in:
parent
c95bc8fdf9
commit
f2ffca35da
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import Modal from 'components/Modal';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { removeLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
|
|
||||||
|
const RemoveLocalCollection = ({onClose, collection}) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const onConfirm = () =>{
|
||||||
|
dispatch(removeLocalCollection(collection.uid))
|
||||||
|
.then(() => {
|
||||||
|
toast.success("Collection removed");
|
||||||
|
onClose();
|
||||||
|
})
|
||||||
|
.catch(() => toast.error("An error occured while removing the collection"));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
size="sm"
|
||||||
|
title="Remove Collection"
|
||||||
|
confirmText="Remove"
|
||||||
|
handleConfirm={onConfirm}
|
||||||
|
handleCancel={onClose}
|
||||||
|
>
|
||||||
|
Are you sure you want to remove this collection?
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RemoveLocalCollection;
|
@ -10,6 +10,7 @@ import NewRequest from 'components/Sidebar/NewRequest';
|
|||||||
import NewFolder from 'components/Sidebar/NewFolder';
|
import NewFolder from 'components/Sidebar/NewFolder';
|
||||||
import CollectionItem from './CollectionItem';
|
import CollectionItem from './CollectionItem';
|
||||||
import RemoveCollectionFromWorkspace from './RemoveCollectionFromWorkspace';
|
import RemoveCollectionFromWorkspace from './RemoveCollectionFromWorkspace';
|
||||||
|
import RemoveLocalCollection from './RemoveLocalCollection';
|
||||||
import { doesCollectionHaveItemsMatchingSearchText } from 'utils/collections/search';
|
import { doesCollectionHaveItemsMatchingSearchText } from 'utils/collections/search';
|
||||||
import { isItemAFolder, isItemARequest, transformCollectionToSaveToIdb, isLocalCollection } from 'utils/collections';
|
import { isItemAFolder, isItemARequest, transformCollectionToSaveToIdb, isLocalCollection } from 'utils/collections';
|
||||||
import exportCollection from 'utils/collections/export';
|
import exportCollection from 'utils/collections/export';
|
||||||
@ -23,6 +24,7 @@ const Collection = ({collection, searchText}) => {
|
|||||||
const [showNewRequestModal, setShowNewRequestModal] = useState(false);
|
const [showNewRequestModal, setShowNewRequestModal] = useState(false);
|
||||||
const [showRenameCollectionModal, setShowRenameCollectionModal] = useState(false);
|
const [showRenameCollectionModal, setShowRenameCollectionModal] = useState(false);
|
||||||
const [showRemoveCollectionFromWSModal, setShowRemoveCollectionFromWSModal] = useState(false);
|
const [showRemoveCollectionFromWSModal, setShowRemoveCollectionFromWSModal] = useState(false);
|
||||||
|
const [showRemoveLocalCollectionModal, setShowRemoveLocalCollectionModal] = useState(false);
|
||||||
const [showDeleteCollectionModal, setShowDeleteCollectionModal] = useState(false);
|
const [showDeleteCollectionModal, setShowDeleteCollectionModal] = useState(false);
|
||||||
const [collectionIsCollapsed, setCollectionIsCollapsed] = useState(collection.collapsed);
|
const [collectionIsCollapsed, setCollectionIsCollapsed] = useState(collection.collapsed);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -76,6 +78,7 @@ const Collection = ({collection, searchText}) => {
|
|||||||
{showRenameCollectionModal && <RenameCollection collection={collection} onClose={() => setShowRenameCollectionModal(false)}/>}
|
{showRenameCollectionModal && <RenameCollection collection={collection} onClose={() => setShowRenameCollectionModal(false)}/>}
|
||||||
{showRemoveCollectionFromWSModal && <RemoveCollectionFromWorkspace collection={collection} onClose={() => setShowRemoveCollectionFromWSModal(false)}/>}
|
{showRemoveCollectionFromWSModal && <RemoveCollectionFromWorkspace collection={collection} onClose={() => setShowRemoveCollectionFromWSModal(false)}/>}
|
||||||
{showDeleteCollectionModal && <DeleteCollection collection={collection} onClose={() => setShowDeleteCollectionModal(false)}/>}
|
{showDeleteCollectionModal && <DeleteCollection collection={collection} onClose={() => setShowDeleteCollectionModal(false)}/>}
|
||||||
|
{showRemoveLocalCollectionModal && <RemoveLocalCollection collection={collection} onClose={() => setShowRemoveLocalCollectionModal(false)}/>}
|
||||||
<div className="flex py-1 collection-name items-center">
|
<div className="flex py-1 collection-name items-center">
|
||||||
<div className="flex flex-grow items-center" onClick={handleClick}>
|
<div className="flex flex-grow items-center" onClick={handleClick}>
|
||||||
<IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{width:16, color: 'rgb(160 160 160)'}}/>
|
<IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{width:16, color: 'rgb(160 160 160)'}}/>
|
||||||
@ -111,12 +114,21 @@ const Collection = ({collection, searchText}) => {
|
|||||||
}}>
|
}}>
|
||||||
Export
|
Export
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
{!isLocal ? (
|
||||||
menuDropdownTippyRef.current.hide();
|
<div className="dropdown-item" onClick={(e) => {
|
||||||
setShowRemoveCollectionFromWSModal(true);
|
menuDropdownTippyRef.current.hide();
|
||||||
}}>
|
setShowRemoveCollectionFromWSModal(true);
|
||||||
Remove from Workspace
|
}}>
|
||||||
</div>
|
Remove from Workspace
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="dropdown-item" onClick={(e) => {
|
||||||
|
menuDropdownTippyRef.current.hide();
|
||||||
|
setShowRemoveLocalCollectionModal(true);
|
||||||
|
}}>
|
||||||
|
Remove
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{!isLocal ? (
|
{!isLocal ? (
|
||||||
<div className="dropdown-item delete-collection" onClick={(e) => {
|
<div className="dropdown-item delete-collection" onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import filter from "lodash/filter";
|
||||||
import Modal from "components/Modal/index";
|
import Modal from "components/Modal/index";
|
||||||
import { IconFiles } from '@tabler/icons';
|
import { IconFiles } from '@tabler/icons';
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
import { isLocalCollection } from "utils/collections";
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const SelectCollection = ({onClose, onSelect, title}) => {
|
const SelectCollection = ({onClose, onSelect, title}) => {
|
||||||
const { collections } = useSelector((state) => state.collections);
|
const { collections } = useSelector((state) => state.collections);
|
||||||
|
const collectionsToDisplay = filter(collections, (c) => !isLocalCollection(c));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
@ -16,7 +19,7 @@ const SelectCollection = ({onClose, onSelect, title}) => {
|
|||||||
handleCancel={onClose}
|
handleCancel={onClose}
|
||||||
>
|
>
|
||||||
<ul className="mb-2" >
|
<ul className="mb-2" >
|
||||||
{(collections && collections.length) ? collections.map((c) => (
|
{(collectionsToDisplay && collectionsToDisplay.length) ? collectionsToDisplay.map((c) => (
|
||||||
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
||||||
<IconFiles size={18} strokeWidth={1.5}/> <span className="ml-2">{c.name}</span>
|
<IconFiles size={18} strokeWidth={1.5}/> <span className="ml-2">{c.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,6 +5,7 @@ import filter from 'lodash/filter';
|
|||||||
import Collection from './Collection';
|
import Collection from './Collection';
|
||||||
import CreateOrAddCollection from './CreateOrAddCollection';
|
import CreateOrAddCollection from './CreateOrAddCollection';
|
||||||
import { findCollectionInWorkspace } from 'utils/workspaces';
|
import { findCollectionInWorkspace } from 'utils/workspaces';
|
||||||
|
import { isLocalCollection } from 'utils/collections';
|
||||||
|
|
||||||
const Collections = ({searchText}) => {
|
const Collections = ({searchText}) => {
|
||||||
const { collections } = useSelector((state) => state.collections);
|
const { collections } = useSelector((state) => state.collections);
|
||||||
@ -15,7 +16,7 @@ const Collections = ({searchText}) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const collectionToDisplay = filter(collections, (c) => findCollectionInWorkspace(activeWorkspace, c.uid));
|
const collectionToDisplay = filter(collections, (c) => findCollectionInWorkspace(activeWorkspace, c.uid) && !isLocalCollection(c));
|
||||||
|
|
||||||
if(!collectionToDisplay || !collectionToDisplay.length) {
|
if(!collectionToDisplay || !collectionToDisplay.length) {
|
||||||
return <CreateOrAddCollection />;
|
return <CreateOrAddCollection />;
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
.current-workspace {
|
||||||
|
margin-inline: .5rem;
|
||||||
|
background: #e1e1e1;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
.caret {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
color: rgb(140, 140, 140);
|
||||||
|
fill: rgb(140, 140, 140);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div[data-tippy-root] {
|
||||||
|
width: calc(100% - 1rem);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Wrapper;
|
@ -0,0 +1,73 @@
|
|||||||
|
import React, { useRef, forwardRef } from 'react';
|
||||||
|
import filter from 'lodash/filter';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import Dropdown from 'components/Dropdown';
|
||||||
|
import { IconArrowForwardUp, IconCaretDown, IconFolders, IconPlus } from '@tabler/icons';
|
||||||
|
import Collection from '../Collections/Collection';
|
||||||
|
import { isLocalCollection } from 'utils/collections';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
|
const LocalCollections = ({searchText}) => {
|
||||||
|
const dropdownTippyRef = useRef();
|
||||||
|
const { collections } = useSelector((state) => state.collections);
|
||||||
|
|
||||||
|
const collectionToDisplay = filter(collections, (c) => isLocalCollection(c));
|
||||||
|
|
||||||
|
if(!collectionToDisplay || !collectionToDisplay.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Icon = forwardRef((props, ref) => {
|
||||||
|
return (
|
||||||
|
<div ref={ref} className="current-workspace flex justify-between items-center pl-2 pr-2 py-1 select-none">
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<span className='mr-2'>
|
||||||
|
<IconFolders size={18} strokeWidth={1.5}/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Local Collections
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<IconCaretDown className="caret" size={14} strokeWidth={2}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledWrapper>
|
||||||
|
<div className="items-center cursor-pointer mt-6 relative">
|
||||||
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
||||||
|
<div className="dropdown-item" onClick={() => {}}>
|
||||||
|
<div className="pr-2 text-gray-600">
|
||||||
|
<IconPlus size={18} strokeWidth={1.5}/>
|
||||||
|
</div>
|
||||||
|
<span>Create Collection</span>
|
||||||
|
</div>
|
||||||
|
<div className="dropdown-item" onClick={() => {}}>
|
||||||
|
<div className="pr-2 text-gray-600">
|
||||||
|
<IconArrowForwardUp size={18} strokeWidth={1.5}/>
|
||||||
|
</div>
|
||||||
|
<span>Open Collection</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='px-2 pt-2 text-gray-600' style={{fontSize: 10, borderTop: 'solid 1px #e7e7e7'}}>
|
||||||
|
Note: Local collections are not tied to a workspace
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 flex flex-col">
|
||||||
|
{collectionToDisplay && collectionToDisplay.length ? collectionToDisplay.map((c) => {
|
||||||
|
return <Collection
|
||||||
|
searchText={searchText}
|
||||||
|
collection={c}
|
||||||
|
key={c.uid}
|
||||||
|
/>
|
||||||
|
}) : null}
|
||||||
|
</div>
|
||||||
|
</StyledWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LocalCollections;
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect} from 'react';
|
import React, { useState, useEffect} from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import Collections from './Collections';
|
import Collections from './Collections';
|
||||||
|
import LocalCollections from './LocalCollections';
|
||||||
import TitleBar from './TitleBar';
|
import TitleBar from './TitleBar';
|
||||||
import MenuBar from './MenuBar';
|
import MenuBar from './MenuBar';
|
||||||
import { IconSearch, IconChevronsRight } from '@tabler/icons';
|
import { IconSearch, IconChevronsRight } from '@tabler/icons';
|
||||||
@ -94,6 +95,7 @@ const Sidebar = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Collections searchText={searchText}/>
|
<Collections searchText={searchText}/>
|
||||||
|
<LocalCollections searchText={searchText}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex px-1 py-2 items-center cursor-pointer text-gray-500 select-none">
|
<div className="flex px-1 py-2 items-center cursor-pointer text-gray-500 select-none">
|
||||||
<div className="flex items-center ml-1 text-xs ">
|
<div className="flex items-center ml-1 text-xs ">
|
||||||
|
@ -3,7 +3,7 @@ import styled from 'styled-components';
|
|||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
.current-workspace {
|
.current-workspace {
|
||||||
margin-inline: .5rem;
|
margin-inline: .5rem;
|
||||||
background: #fff;
|
background: #e1e1e1;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
.caret {
|
.caret {
|
||||||
@ -12,6 +12,10 @@ const Wrapper = styled.div`
|
|||||||
fill: rgb(140, 140, 140);
|
fill: rgb(140, 140, 140);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div[data-tippy-root] {
|
||||||
|
width: calc(100% - 1rem);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Wrapper;
|
export default Wrapper;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useRef, forwardRef, useState, useEffect } from 'react';
|
import React, { useRef, forwardRef, useState, useEffect } from 'react';
|
||||||
import Dropdown from 'components/Dropdown';
|
import Dropdown from 'components/Dropdown';
|
||||||
import { IconAdjustmentsHorizontal, IconCaretDown, IconBox } from '@tabler/icons';
|
import { IconCaretDown, IconBox, IconSwitch3, IconSettings, IconFolders } from '@tabler/icons';
|
||||||
import WorkspaceConfigurer from "../WorkspaceConfigurer";
|
import WorkspaceConfigurer from "../WorkspaceConfigurer";
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { selectWorkspace } from 'providers/ReduxStore/slices/workspaces';
|
import { selectWorkspace } from 'providers/ReduxStore/slices/workspaces';
|
||||||
@ -42,21 +42,25 @@ const WorkspaceSelector = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="items-center cursor-pointer">
|
<div className="items-center cursor-pointer relative">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
||||||
{workspaces && workspaces.length && workspaces.map((workspace) => (
|
{/* {workspaces && workspaces.length && workspaces.map((workspace) => (
|
||||||
<div className="dropdown-item" onClick={() => handleSelectWorkspace(workspace)} key={workspace.uid}>
|
<div className="dropdown-item" onClick={() => handleSelectWorkspace(workspace)} key={workspace.uid}>
|
||||||
<span>{workspace.name}</span>
|
<span>{workspace.name}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))} */}
|
||||||
|
<div className="dropdown-item" onClick={() => handleSelectWorkspace(workspace)}>
|
||||||
<div className="dropdown-item" style={{borderTop: 'solid 1px #e7e7e7'}} onClick={() => {
|
|
||||||
setOpenWorkspacesModal(true);
|
|
||||||
}}>
|
|
||||||
<div className="pr-2 text-gray-600">
|
<div className="pr-2 text-gray-600">
|
||||||
<IconAdjustmentsHorizontal size={18} strokeWidth={1.5}/>
|
<IconSwitch3 size={18} strokeWidth={1.5}/>
|
||||||
</div>
|
</div>
|
||||||
<span>Configure</span>
|
<span>Switch Workspace</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="dropdown-item" onClick={() => handleSelectWorkspace(workspace)}>
|
||||||
|
<div className="pr-2 text-gray-600">
|
||||||
|
<IconSettings size={18} strokeWidth={1.5}/>
|
||||||
|
</div>
|
||||||
|
<span>Configure Workspaces</span>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import filter from "lodash/filter";
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import CollectionItem from './CollectionItem';
|
import CollectionItem from './CollectionItem';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
import { isLocalCollection } from 'utils/collections';
|
||||||
|
|
||||||
export default function Collections() {
|
export default function Collections() {
|
||||||
const collections = useSelector((state) => state.collections.collections);
|
const collections = useSelector((state) => state.collections.collections);
|
||||||
|
const collectionsToDisplay = filter(collections, (c) => !isLocalCollection(c));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<h4 className="heading">Collections</h4>
|
<h4 className="heading">Collections</h4>
|
||||||
|
|
||||||
<div className="collection-list mt-6">
|
<div className="collection-list mt-6">
|
||||||
{collections && collections.length ? collections.map((collection) => {
|
{(collectionsToDisplay && collectionsToDisplay.length) ? collectionsToDisplay.map((collection) => {
|
||||||
return <CollectionItem key={collection.uid} collection={collection}/>;
|
return <CollectionItem key={collection.uid} collection={collection}/>;
|
||||||
}): null}
|
}): (
|
||||||
|
<div>No collections found</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
|
@ -35,6 +35,8 @@ export default function Main() {
|
|||||||
const isDragging = useSelector((state) => state.app.isDragging);
|
const isDragging = useSelector((state) => state.app.isDragging);
|
||||||
const showHomePage = useSelector((state) => state.app.showHomePage);
|
const showHomePage = useSelector((state) => state.app.showHomePage);
|
||||||
|
|
||||||
|
console.log(useSelector((state) => state.collections.collections));
|
||||||
|
|
||||||
const className = classnames({
|
const className = classnames({
|
||||||
'is-dragging': isDragging
|
'is-dragging': isDragging
|
||||||
});
|
});
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
removeCollectionEvent,
|
|
||||||
localCollectionAddDirectoryEvent,
|
localCollectionAddDirectoryEvent,
|
||||||
localCollectionAddFileEvent,
|
localCollectionAddFileEvent,
|
||||||
localCollectionChangeFileEvent,
|
localCollectionChangeFileEvent,
|
||||||
localCollectionUnlinkFileEvent,
|
localCollectionUnlinkFileEvent,
|
||||||
localCollectionUnlinkDirectoryEvent
|
localCollectionUnlinkDirectoryEvent
|
||||||
} from 'providers/ReduxStore/slices/collections';
|
} from 'providers/ReduxStore/slices/collections';
|
||||||
import {
|
import toast from 'react-hot-toast';
|
||||||
openLocalCollectionEvent
|
import { openLocalCollectionEvent } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
} from 'providers/ReduxStore/slices/collections/actions';
|
|
||||||
import { isElectron } from 'utils/common/platform';
|
import { isElectron } from 'utils/common/platform';
|
||||||
|
|
||||||
const useLocalCollectionTreeSync = () => {
|
const useLocalCollectionTreeSync = () => {
|
||||||
@ -58,15 +56,13 @@ const useLocalCollectionTreeSync = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _collectionRemoved = (pathname) => {
|
const _collectionAlreadyOpened = (pathname) => {
|
||||||
// dispatch(removeCollectionEvent({
|
toast.success('Collection is already opened under local collections');
|
||||||
// pathname
|
|
||||||
// }));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection);
|
const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection);
|
||||||
const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated);
|
const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated);
|
||||||
const removeListener3 = ipcRenderer.on('main:collection-removed', _collectionRemoved);
|
const removeListener3 = ipcRenderer.on('main:collection-already-opened', _collectionAlreadyOpened);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
removeListener1();
|
removeListener1();
|
||||||
|
@ -59,15 +59,10 @@ export const openLocalCollectionEvent = (uid, pathname) => (dispatch, getState)
|
|||||||
items: []
|
items: []
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = getState();
|
|
||||||
const { activeWorkspaceUid } = state.workspaces;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
collectionSchema
|
collectionSchema
|
||||||
.validate(localCollection)
|
.validate(localCollection)
|
||||||
.then(() => dispatch(_createCollection(localCollection)))
|
.then(() => dispatch(_createCollection(localCollection)))
|
||||||
.then(waitForNextTick)
|
|
||||||
.then(() => dispatch(addCollectionToWorkspace(activeWorkspaceUid, localCollection.uid)))
|
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
@ -624,6 +619,17 @@ export const removeLocalCollection = (collectionUid) => (dispatch, getState) =>
|
|||||||
const { ipcRenderer } = window;
|
const { ipcRenderer } = window;
|
||||||
ipcRenderer
|
ipcRenderer
|
||||||
.invoke('renderer:remove-collection', collection.pathname)
|
.invoke('renderer:remove-collection', collection.pathname)
|
||||||
|
.then(() => {
|
||||||
|
dispatch(closeTabs({
|
||||||
|
tabUids: recursivelyGetAllItemUids(collection.items)
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.then(waitForNextTick)
|
||||||
|
.then(() => {
|
||||||
|
dispatch(_deleteCollection({
|
||||||
|
collectionUid: collectionUid
|
||||||
|
}));
|
||||||
|
})
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
|
@ -176,7 +176,9 @@ export const removeCollectionFromWorkspace = (workspaceUid, collectionUid) => (d
|
|||||||
workspaceCopy.collections = filter(workspaceCopy.collections, (c) => c.uid !== collectionUid);
|
workspaceCopy.collections = filter(workspaceCopy.collections, (c) => c.uid !== collectionUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveWorkspaceToIdb(window.__idb, workspaceCopy)
|
workspaceSchema
|
||||||
|
.validate(workspaceCopy)
|
||||||
|
.then(() => saveWorkspaceToIdb(window.__idb, workspaceCopy))
|
||||||
.then(() => dispatch(_removeCollectionFromWorkspace({
|
.then(() => dispatch(_removeCollectionFromWorkspace({
|
||||||
workspaceUid: workspaceUid,
|
workspaceUid: workspaceUid,
|
||||||
collectionUid: collectionUid
|
collectionUid: collectionUid
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--color-brand: #546de5;
|
--color-brand: #546de5;
|
||||||
--color-sidebar-collection-item-active-indent-border: #d0d0d0;
|
--color-sidebar-collection-item-active-indent-border: #d0d0d0;
|
||||||
--color-sidebar-collection-item-active-background: #dddddd;
|
--color-sidebar-collection-item-active-background: #e1e1e1;
|
||||||
--color-sidebar-background: #f3f3f3;
|
--color-sidebar-background: #f3f3f3;
|
||||||
--color-request-dragbar-background: #efefef;
|
--color-request-dragbar-background: #efefef;
|
||||||
--color-request-dragbar-background-active: rgb(200, 200, 200);
|
--color-request-dragbar-background-active: rgb(200, 200, 200);
|
||||||
|
@ -83,6 +83,10 @@ export const findCollectionByUid = (collections, collectionUid) => {
|
|||||||
return find(collections, (c) => c.uid === collectionUid);
|
return find(collections, (c) => c.uid === collectionUid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const findCollectionByPathname = (collections, pathname) => {
|
||||||
|
return find(collections, (c) => c.pathname === pathname);
|
||||||
|
};
|
||||||
|
|
||||||
export const findItemByPathname = (items = [], pathname) => {
|
export const findItemByPathname = (items = [], pathname) => {
|
||||||
return find(items, (i) => i.pathname === pathname);
|
return find(items, (i) => i.pathname === pathname);
|
||||||
};
|
};
|
||||||
|
34
packages/bruno-app/src/utils/common/error.js
Normal file
34
packages/bruno-app/src/utils/common/error.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
|
// levels: 'warning, error'
|
||||||
|
export class BrunoError extends Error {
|
||||||
|
constructor(message, level) {
|
||||||
|
super(message);
|
||||||
|
this.name = "BrunoError";
|
||||||
|
this.level = level || "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const parseError = (error) => {
|
||||||
|
if(error instanceof BrunoError) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.message ? error.message : 'An error occured';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toastError = (error) => {
|
||||||
|
if(error instanceof BrunoError) {
|
||||||
|
if(error.level === 'warning') {
|
||||||
|
return toast(error.message, {
|
||||||
|
icon: '⚠️',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return toast.error(error.message, {
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return toast.error(error.message || 'An error occured');
|
||||||
|
};
|
@ -14,6 +14,8 @@ const openCollection = async (win, watcher) => {
|
|||||||
const uid = uuid();
|
const uid = uuid();
|
||||||
win.webContents.send('main:collection-opened', resolvedPath, uid);
|
win.webContents.send('main:collection-opened', resolvedPath, uid);
|
||||||
watcher.addWatcher(win, resolvedPath, uid);
|
watcher.addWatcher(win, resolvedPath, uid);
|
||||||
|
} else {
|
||||||
|
win.webContents.send('main:collection-already-opened', resolvedPath);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(`[ERROR] Cannot open unknown folder: "${resolvedPath}"`);
|
console.error(`[ERROR] Cannot open unknown folder: "${resolvedPath}"`);
|
||||||
|
@ -126,7 +126,6 @@ class Watcher {
|
|||||||
if(this.watchers[watchPath]) {
|
if(this.watchers[watchPath]) {
|
||||||
this.watchers[watchPath].close();
|
this.watchers[watchPath].close();
|
||||||
this.watchers[watchPath] = null;
|
this.watchers[watchPath] = null;
|
||||||
win.webContents.send('main:collection-removed', watchPath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user