From 8a96a0ce71b52c29d4934abaea02f474447e7a65 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Tue, 18 Oct 2022 01:27:53 +0530 Subject: [PATCH] feat: wireup local collections open and create buttons --- .../components/Sidebar/Collections/index.js | 2 +- .../Sidebar/CreateCollection/index.js | 56 ++++++++++++++++++- .../Sidebar/LocalCollections/index.js | 25 +++++++-- .../Sidebar/TitleBar/StyledWrapper.js | 9 +++ .../src/components/Sidebar/TitleBar/index.js | 52 +++++++++++++---- .../bruno-app/src/components/Welcome/index.js | 24 ++++---- .../ReduxStore/slices/collections/actions.js | 33 +++++++++++ .../src/ipc/local-collection.js | 8 ++- 8 files changed, 173 insertions(+), 36 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/Collections/index.js b/packages/bruno-app/src/components/Sidebar/Collections/index.js index 8227ac9f..dfca61cc 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/index.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React from 'react'; import { useSelector } from 'react-redux'; import find from 'lodash/find'; import filter from 'lodash/filter'; diff --git a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js index f81d9984..e01fe173 100644 --- a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js @@ -1,10 +1,18 @@ import React, { useRef, useEffect } from 'react'; +import { useDispatch } from 'react-redux'; import { useFormik } from 'formik'; import * as Yup from 'yup'; +import { browserLocalDirectory } from 'providers/ReduxStore/slices/collections/actions'; +import { isElectron } from 'utils/common/platform'; +import { createCollection, createLocalCollection } from 'providers/ReduxStore/slices/collections/actions'; +import toast from 'react-hot-toast'; import Modal from 'components/Modal'; -const CreateCollection = ({handleConfirm, handleCancel}) => { +const CreateCollection = ({onClose, isLocal}) => { const inputRef = useRef(); + const dispatch = useDispatch(); + const isPlatformElectron = isElectron(); + const formik = useFormik({ enableReinitialize: true, initialValues: { @@ -18,9 +26,26 @@ const CreateCollection = ({handleConfirm, handleCancel}) => { .required('name is required') }), onSubmit: (values) => { - handleConfirm(values); + const action = isLocal && isPlatformElectron ? createLocalCollection : createCollection; + dispatch(action(values.collectionName, values.collectionLocation)) + .then(() => { + toast.success("Collection created"); + onClose(); + }) + .catch(() => toast.error("An error occured while creating the collection")); } }); + + const browse = () => { + dispatch(browserLocalDirectory()) + .then((dirPath) => { + formik.setFieldValue('collectionLocation', dirPath); + }) + .catch((error) => { + formik.setFieldValue('collectionLocation', ''); + console.error(error); + }); + }; useEffect(() => { if(inputRef && inputRef.current) { @@ -36,7 +61,7 @@ const CreateCollection = ({handleConfirm, handleCancel}) => { title='Create Collection' confirmText='Create' handleConfirm={onSubmit} - handleCancel={handleCancel} + handleCancel={onClose} >
@@ -54,6 +79,31 @@ const CreateCollection = ({handleConfirm, handleCancel}) => { {formik.touched.collectionName && formik.errors.collectionName ? (
{formik.errors.collectionName}
) : null} + + {isLocal && isPlatformElectron ? ( + <> + + + + ) : null} + {isLocal && isPlatformElectron && formik.touched.collectionLocation && formik.errors.collectionLocation ? ( +
{formik.errors.collectionLocation}
+ ) : null} + + {isLocal && isPlatformElectron ? ( +
+ Browse +
+ ) : null }
diff --git a/packages/bruno-app/src/components/Sidebar/LocalCollections/index.js b/packages/bruno-app/src/components/Sidebar/LocalCollections/index.js index a010b254..d6ae5e87 100644 --- a/packages/bruno-app/src/components/Sidebar/LocalCollections/index.js +++ b/packages/bruno-app/src/components/Sidebar/LocalCollections/index.js @@ -1,15 +1,19 @@ -import React, { useRef, forwardRef } from 'react'; +import React, { useState, useRef, forwardRef } from 'react'; import filter from 'lodash/filter'; -import { useSelector } from 'react-redux'; +import { useSelector, useDispatch } from 'react-redux'; import Dropdown from 'components/Dropdown'; +import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions'; import { IconArrowForwardUp, IconCaretDown, IconFolders, IconPlus } from '@tabler/icons'; import Collection from '../Collections/Collection'; +import CreateCollection from '../CreateCollection'; import { isLocalCollection } from 'utils/collections'; import StyledWrapper from './StyledWrapper'; const LocalCollections = ({searchText}) => { const dropdownTippyRef = useRef(); + const dispatch = useDispatch(); const { collections } = useSelector((state) => state.collections); + const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false); const collectionToDisplay = filter(collections, (c) => isLocalCollection(c)); @@ -35,17 +39,30 @@ const LocalCollections = ({searchText}) => { const onDropdownCreate = (ref) => dropdownTippyRef.current = ref; + + const handleOpenLocalCollection = () => { + dispatch(openLocalCollection()) + .catch((err) => console.log(err) && toast.error("An error occured while opening the local collection")); + } + return ( + {createCollectionModalOpen ? ( + setCreateCollectionModalOpen(false)} + /> + ) : null} +
} placement='bottom-end'> -
{}}> +
setCreateCollectionModalOpen(true)}>
Create Collection
-
{}}> +
diff --git a/packages/bruno-app/src/components/Sidebar/TitleBar/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/TitleBar/StyledWrapper.js index efdbe283..dfdcab3d 100644 --- a/packages/bruno-app/src/components/Sidebar/TitleBar/StyledWrapper.js +++ b/packages/bruno-app/src/components/Sidebar/TitleBar/StyledWrapper.js @@ -1,6 +1,15 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` + .local-collection-label { + background-color: var(--color-sidebar-background); + } + + .local-collections-unavailable { + padding: 0.35rem 0.6rem; + border-top: solid 1px #ddd; + font-size: 11px; + } .collection-dropdown { color: rgb(110 110 110); diff --git a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js index e82ee3e5..737e46b0 100644 --- a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js +++ b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js @@ -2,21 +2,24 @@ import React, { useState, forwardRef, useRef } from 'react'; import toast from 'react-hot-toast'; import Dropdown from 'components/Dropdown'; import Bruno from 'components/Bruno'; +import { IconFolders } from '@tabler/icons'; import { useSelector, useDispatch } from 'react-redux'; import { collectionImported } from 'providers/ReduxStore/slices/collections'; -import { createCollection } from 'providers/ReduxStore/slices/collections/actions'; +import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions'; import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions'; import { showHomePage } from 'providers/ReduxStore/slices/app'; import { IconDots } from '@tabler/icons'; import CreateCollection from '../CreateCollection'; import SelectCollection from 'components/Sidebar/Collections/SelectCollection'; import importCollection from 'utils/collections/import'; +import { isElectron } from 'utils/common/platform'; import StyledWrapper from './StyledWrapper'; const TitleBar = () => { const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false); const [addCollectionToWSModalOpen, setAddCollectionToWSModalOpen] = useState(false); const { activeWorkspaceUid } = useSelector((state) => state.workspaces); + const isPlatformElectron = isElectron(); const dispatch = useDispatch(); const menuDropdownTippyRef = useRef(); @@ -31,14 +34,10 @@ const TitleBar = () => { const handleTitleClick = () => dispatch(showHomePage()); - const handleCreateCollection = (values) => { - setCreateCollectionModalOpen(false); - dispatch(createCollection(values.collectionName)) - .then(() => { - toast.success("Collection created"); - }) - .catch(() => toast.error("An error occured while creating the collection")); - }; + const handleOpenLocalCollection = () => { + dispatch(openLocalCollection()) + .catch((err) => console.log(err) && toast.error("An error occured while opening the local collection")); + } const handleAddCollectionToWorkspace = (collectionUid) => { setAddCollectionToWSModalOpen(false); @@ -62,8 +61,8 @@ const TitleBar = () => { {createCollectionModalOpen ? ( setCreateCollectionModalOpen(false)} - handleConfirm={handleCreateCollection} + isLocal={createCollectionModalOpen === 'local' ? true : false} + onClose={() => setCreateCollectionModalOpen(false)} /> ) : null} @@ -106,6 +105,37 @@ const TitleBar = () => { }}> Add Collection to Workspace
+ {isPlatformElectron ? ( + <> +
+
+ + + + + Local Collections + +
+
+
{ + setCreateCollectionModalOpen('local'); + menuDropdownTippyRef.current.hide(); + }}> + Create Local Collection +
+
{ + handleOpenLocalCollection(); + menuDropdownTippyRef.current.hide(); + }}> + Open Local Collection +
+ + ) : ( +
+ Note: Local collections are only available on the desktop app. +
+ )} +
diff --git a/packages/bruno-app/src/components/Welcome/index.js b/packages/bruno-app/src/components/Welcome/index.js index 03543b6c..10fd70d9 100644 --- a/packages/bruno-app/src/components/Welcome/index.js +++ b/packages/bruno-app/src/components/Welcome/index.js @@ -12,7 +12,7 @@ import { } from '@tabler/icons'; import { useSelector, useDispatch } from 'react-redux'; import { collectionImported } from 'providers/ReduxStore/slices/collections'; -import { createCollection } from 'providers/ReduxStore/slices/collections/actions'; +import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions'; import { addCollectionToWorkspace } from 'providers/ReduxStore/slices/workspaces/actions'; import Bruno from 'components/Bruno'; import CreateCollection from 'components/Sidebar/CreateCollection'; @@ -29,15 +29,6 @@ const Welcome = () => { const { activeWorkspaceUid } = useSelector((state) => state.workspaces); const isPlatformElectron = isElectron(); - const handleCreateCollection = (values) => { - setCreateCollectionModalOpen(false); - dispatch(createCollection(values.collectionName)) - .then(() => { - toast.success("Collection created"); - }) - .catch(() => toast.error("An error occured while creating the collection")); - }; - const handleAddCollectionToWorkspace = (collectionUid) => { setAddCollectionToWSModalOpen(false); dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid)) @@ -69,12 +60,17 @@ const Welcome = () => { }); }; + const handleOpenLocalCollection = () => { + dispatch(openLocalCollection()) + .catch((err) => console.log(err) && toast.error("An error occured while opening the local collection")); + } + return ( {createCollectionModalOpen ? ( setCreateCollectionModalOpen(false)} - handleConfirm={handleCreateCollection} + isLocal={createCollectionModalOpen === 'local' ? true : false} + onClose={() => setCreateCollectionModalOpen(false)} /> ) : null} @@ -112,10 +108,10 @@ const Welcome = () => { {isPlatformElectron ? (
- setCreateCollectionModalOpen(true)}>Create Collection + setCreateCollectionModalOpen('local')}>Create Collection
- Open Collection + Open Collection
) : ( diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index a78853c9..8fd4ce7c 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -801,4 +801,37 @@ export const removeLocalCollection = (collectionUid) => (dispatch, getState) => .then(resolve) .catch(reject); }); +}; + +export const browserLocalDirectory = () => (dispatch, getState) => { + const { ipcRenderer } = window; + + return new Promise((resolve, reject) => { + ipcRenderer + .invoke('renderer:browse-directory') + .then(resolve) + .catch(reject); + }); +} + +export const createLocalCollection = (collectionName, collectionLocation) => () => { + const { ipcRenderer } = window; + + return new Promise((resolve, reject) => { + ipcRenderer + .invoke('renderer:create-collection', collectionName, collectionLocation) + .then(resolve) + .catch(reject); + }); +}; + +export const openLocalCollection = () => () => { + return new Promise((resolve, reject) => { + const { ipcRenderer } = window; + + ipcRenderer + .invoke('renderer:open-collection') + .then(resolve) + .catch(reject); + }); }; \ No newline at end of file diff --git a/packages/bruno-electron/src/ipc/local-collection.js b/packages/bruno-electron/src/ipc/local-collection.js index 0032df1c..81962308 100644 --- a/packages/bruno-electron/src/ipc/local-collection.js +++ b/packages/bruno-electron/src/ipc/local-collection.js @@ -30,22 +30,24 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection try { const dirPath = path.join(collectionLocation, collectionName); if (fs.existsSync(dirPath)){ - throw new Error(`collection: ${dir} already exists`); + throw new Error(`collection: ${dirPath} already exists`); } if(!isValidPathname(dirPath)) { - throw new Error(`collection: invaid pathname - ${dir}`); + throw new Error(`collection: invalid pathname - ${dir}`); } await createDirectory(dirPath); + const uid = uuid(); const content = await stringifyJson({ version: '1.0', + uid: uid, + name: collectionName, type: 'collection' }); await writeFile(path.join(dirPath, 'bruno.json'), content); - const uid = uuid(); mainWindow.webContents.send('main:collection-opened', dirPath, uid); ipcMain.emit('main:collection-opened', mainWindow, dirPath, uid);