diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/StyledWrapper.js new file mode 100644 index 000000000..72d1d8a90 --- /dev/null +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/StyledWrapper.js @@ -0,0 +1,40 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + div.method-selector-container { + border: solid 1px ${(props) => props.theme.modal.input.border}; + border-right: none; + background-color: ${(props) => props.theme.modal.input.bg}; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + + .method-selector { + min-width: 80px; + } + } + + div.method-selector-container, + div.input-container { + background-color: ${(props) => props.theme.modal.input.bg}; + height: 2.3rem; + } + + div.input-container { + border: solid 1px ${(props) => props.theme.modal.input.border}; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + + input { + background-color: ${(props) => props.theme.modal.input.bg}; + outline: none; + box-shadow: none; + + &:focus { + outline: none !important; + box-shadow: none !important; + } + } + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/index.js index 376a88db4..0a72eb490 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionProperties/index.js @@ -1,5 +1,12 @@ import React from 'react'; import Modal from 'components/Modal'; +import { useState } from 'react'; +import { useFormik } from 'formik'; +import * as Yup from 'yup'; +import StyledWrapper from './StyledWrapper'; +import { useDispatch } from 'react-redux'; +import toast from 'react-hot-toast'; +import { updateCollectionProperties } from 'providers/ReduxStore/slices/collections/actions'; function countRequests(items) { let count = 0; @@ -21,29 +28,116 @@ function countRequests(items) { } const CollectionProperties = ({ collection, onClose }) => { + const dispatch = useDispatch(); + const { + brunoConfig: { properties: defaultProperties = {} } + } = collection; + const formik = useFormik({ + enableReinitialize: true, + initialValues: { + defaultType: defaultProperties.defaultType || 'http-request', + defaultUrl: defaultProperties.defaultUrl || '' + }, + onSubmit: (newProperties) => { + dispatch(updateCollectionProperties(newProperties, collection.uid)); + toast.success('Collection properties updated'); + onClose(); + } + }); + + const onSubmit = () => formik.handleSubmit(); + return ( - - - - - Name : - {collection.name} - - - Location : - {collection.pathname} - - - Environments : - {collection.environments?.length || 0} - - - Requests : - {countRequests(collection.items)} - - - - + + + + + + + Name : + {collection.name} + + + Location : + {collection.pathname} + + + Environments : + {collection.environments?.length || 0} + + + Requests : + {countRequests(collection.items)} + + + Default Request Type : + + + + + HTTP + + + + + GraphQL + + + + + + Default Base URL : + + + + + + + + + + + + {formik.touched.defaultUrl && formik.errors.defaultUrl ? ( + {formik.errors.defaultUrl} + ) : null} + + + + ); }; diff --git a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js index 2e54b56ad..99a7fe3bb 100644 --- a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js @@ -15,12 +15,15 @@ import StyledWrapper from './StyledWrapper'; const NewRequest = ({ collection, item, isEphemeral, onClose }) => { const dispatch = useDispatch(); const inputRef = useRef(); + const { + brunoConfig: { properties: collectionProperties = {} } + } = collection; const formik = useFormik({ enableReinitialize: true, initialValues: { requestName: '', - requestType: 'http-request', - requestUrl: '', + requestType: collectionProperties.defaultType || 'http-request', + requestUrl: collectionProperties.defaultUrl || '', requestMethod: 'GET' }, validationSchema: Yup.object({ diff --git a/packages/bruno-app/src/providers/App/useIpcEvents.js b/packages/bruno-app/src/providers/App/useIpcEvents.js index 8e87b1cf9..1c8787486 100644 --- a/packages/bruno-app/src/providers/App/useIpcEvents.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -18,6 +18,7 @@ import { updatePreferences } from 'providers/ReduxStore/slices/app'; import toast from 'react-hot-toast'; import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions'; import { isElectron } from 'utils/common/platform'; +import { collectionPropertiesUpdatedEvent } from 'providers/ReduxStore/slices/collections/index'; const useIpcEvents = () => { const dispatch = useDispatch(); @@ -107,6 +108,10 @@ const useIpcEvents = () => { dispatch(collectionRenamedEvent(val)); }); + const removeCollectionPropertiesUpdatedListener = ipcRenderer.on('main:collection-properties-updated', (val) => { + dispatch(collectionPropertiesUpdatedEvent(val)); + }); + const removeRunFolderEventListener = ipcRenderer.on('main:run-folder-event', (val) => { dispatch(runFolderEvent(val)); }); @@ -138,6 +143,7 @@ const useIpcEvents = () => { removeDisplayErrorListener(); removeScriptEnvUpdateListener(); removeCollectionRenamedListener(); + removeCollectionPropertiesUpdatedListener(); removeRunFolderEventListener(); removeRunRequestEventListener(); removeProcessEnvUpdatesListener(); 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 ce129d801..62839b9c9 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -47,6 +47,22 @@ import { resolveRequestFilename } from 'utils/common/platform'; import { parseQueryParams, splitOnFirst } from 'utils/url/index'; import { each } from 'lodash'; +export const updateCollectionProperties = (newProperties, collectionUid) => (dispatch, getState) => { + const state = getState(); + const collection = findCollectionByUid(state.collections.collections, collectionUid); + + return new Promise((resolve, reject) => { + if (!collection) { + return reject(new Error('Collection not found')); + } + + ipcRenderer + .invoke('renderer:update-collection-properties', newProperties, collection.pathname) + .then(resolve) + .catch(reject); + }); +}; + export const renameCollection = (newName, collectionUid) => (dispatch, getState) => { const state = getState(); const collection = findCollectionByUid(state.collections.collections, collectionUid); diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 4ad30d204..aef4d179e 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -1224,6 +1224,14 @@ export const collectionsSlice = createSlice({ collection.name = newName; } }, + collectionPropertiesUpdatedEvent: (state, action) => { + const { collectionPathname, newProperties } = action.payload; + const collection = findCollectionByPathname(state.collections, collectionPathname); + + if (collection) { + collection.properties = newProperties; + } + }, resetRunResults: (state, action) => { const { collectionUid } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); @@ -1427,6 +1435,7 @@ export const { collectionUnlinkDirectoryEvent, collectionAddEnvFileEvent, collectionRenamedEvent, + collectionPropertiesUpdatedEvent, resetRunResults, runRequestEvent, runFolderEvent, diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index ab92d50bd..c0a2e004b 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -94,6 +94,28 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection } }); + // update collection properties + ipcMain.handle('renderer:update-collection-properties', async (event, newProperties, collectionPathname) => { + try { + const brunoJsonFilePath = path.join(collectionPathname, 'bruno.json'); + const content = fs.readFileSync(brunoJsonFilePath, 'utf8'); + const json = JSON.parse(content); + + json.properties = newProperties; + + const newContent = await stringifyJson(json); + await writeFile(brunoJsonFilePath, newContent); + + // fire an event in renderer to change the collection properties + mainWindow.webContents.send('main:collection-properties-updated', { + collectionPathname, + newProperties + }); + } catch (error) { + return Promise.reject(error); + } + }); + ipcMain.handle('renderer:save-collection-root', async (event, collectionPathname, collectionRoot) => { try { const collectionBruFilePath = path.join(collectionPathname, 'collection.bru');