diff --git a/packages/bruno-app/src/components/CollectionSettings/Presets/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Presets/StyledWrapper.js new file mode 100644 index 000000000..db26e863b --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Presets/StyledWrapper.js @@ -0,0 +1,29 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + max-width: 800px; + + .settings-label { + width: 110px; + } + + .textbox { + border: 1px solid #ccc; + padding: 0.15rem 0.45rem; + box-shadow: none; + border-radius: 0px; + outline: none; + box-shadow: none; + transition: border-color ease-in-out 0.1s; + border-radius: 3px; + background-color: ${(props) => props.theme.modal.input.bg}; + border: 1px solid ${(props) => props.theme.modal.input.border}; + + &:focus { + border: solid 1px ${(props) => props.theme.modal.input.focusBorder} !important; + outline: none !important; + } + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/CollectionSettings/Presets/index.js b/packages/bruno-app/src/components/CollectionSettings/Presets/index.js new file mode 100644 index 000000000..cf5dad8e3 --- /dev/null +++ b/packages/bruno-app/src/components/CollectionSettings/Presets/index.js @@ -0,0 +1,134 @@ +import React from 'react'; +import { useDispatch } from 'react-redux'; +import StyledWrapper from './StyledWrapper'; +import { updateCollectionPresets } from 'providers/ReduxStore/slices/collections'; +import { saveCollectionSettings } from 'providers/ReduxStore/slices/collections/actions'; +import { get } from 'lodash'; + +const PresetsSettings = ({ collection }) => { + const dispatch = useDispatch(); + const initialPresets = { requestType: 'http', requestUrl: '' }; + + // Get presets from draft.brunoConfig if it exists, otherwise from brunoConfig + const currentPresets = collection.draft?.brunoConfig + ? get(collection, 'draft.brunoConfig.presets', initialPresets) + : get(collection, 'brunoConfig.presets', initialPresets); + + // Helper to update presets config + const updatePresets = (updates) => { + const updatedPresets = { ...currentPresets, ...updates }; + dispatch(updateCollectionPresets({ + collectionUid: collection.uid, + presets: updatedPresets + })); + }; + + const handleSave = () => dispatch(saveCollectionSettings(collection.uid)); + + const handleRequestTypeChange = (e) => { + updatePresets({ requestType: e.target.value }); + }; + + const handleRequestUrlChange = (e) => { + updatePresets({ requestUrl: e.target.value }); + }; + + return ( + +
+ These presets will be used as the default values for new requests in this collection. +
+
+
+ +
+ + + + + + + + + + + +
+
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+ ); +}; + +export default PresetsSettings; diff --git a/packages/bruno-app/src/components/CollectionSettings/index.js b/packages/bruno-app/src/components/CollectionSettings/index.js index 48eb65a3b..dec9252c0 100644 --- a/packages/bruno-app/src/components/CollectionSettings/index.js +++ b/packages/bruno-app/src/components/CollectionSettings/index.js @@ -9,6 +9,7 @@ import Headers from './Headers'; import Auth from './Auth'; import Script from './Script'; import Test from './Tests'; +import Presets from './Presets'; import Protobuf from './Protobuf'; import StyledWrapper from './StyledWrapper'; import Vars from './Vars/index'; @@ -58,6 +59,8 @@ const CollectionSettings = ({ collection }) => { const protobufConfig = collection.draft?.brunoConfig ? get(collection, 'draft.brunoConfig.protobuf', {}) : get(collection, 'brunoConfig.protobuf', {}); + const presets = collection.draft?.brunoConfig ? get(collection, 'draft.brunoConfig.presets', {}) : get(collection, 'brunoConfig.presets', {}); + const hasPresets = presets && presets.requestUrl !== ''; const getTabPanel = (tab) => { switch (tab) { @@ -79,6 +82,9 @@ const CollectionSettings = ({ collection }) => { case 'tests': { return ; } + case 'presets': { + return ; + } case 'proxy': { return ; } @@ -123,6 +129,10 @@ const CollectionSettings = ({ collection }) => { Tests {hasTests && } +
setTab('presets')}> + Presets + {hasPresets && } +
setTab('proxy')}> Proxy {Object.keys(proxyConfig).length > 0 && proxyEnabled && } diff --git a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js index 219852657..2724c966d 100644 --- a/packages/bruno-app/src/components/Sidebar/NewRequest/index.js +++ b/packages/bruno-app/src/components/Sidebar/NewRequest/index.js @@ -1,4 +1,5 @@ import React, { useRef, useEffect, useCallback, forwardRef, useState } from 'react'; +import get from 'lodash/get'; import { useFormik } from 'formik'; import * as Yup from 'yup'; import toast from 'react-hot-toast'; @@ -29,6 +30,11 @@ const NewRequest = ({ collectionUid, item, isEphemeral, onClose }) => { const storedTheme = useTheme(); const collection = useSelector((state) => state.collections.collections?.find((c) => c.uid === collectionUid)); + const collectionPresets = get( + collection, + collection?.draft?.brunoConfig ? 'draft.brunoConfig.presets' : 'brunoConfig.presets', + {} + ); const [curlRequestTypeDetected, setCurlRequestTypeDetected] = useState(null); const [showFilesystemName, toggleShowFilesystemName] = useState(false); @@ -69,13 +75,41 @@ const NewRequest = ({ collectionUid, item, isEphemeral, onClose }) => { const [isEditing, toggleEditing] = useState(false); + const getRequestType = (collectionPresets) => { + if (!collectionPresets || !collectionPresets.requestType) { + return 'http-request'; + } + + // Note: Why different labels for the same thing? + // http-request and graphql-request are used inside the app's json representation of a request + // http and graphql are used in Bru DSL as well as collection exports + // We need to eventually standardize the app's DSL to use the same labels as bru DSL + if (collectionPresets.requestType === 'http') { + return 'http-request'; + } + + if (collectionPresets.requestType === 'graphql') { + return 'graphql-request'; + } + + if (collectionPresets.requestType === 'grpc') { + return 'grpc-request'; + } + + if (collectionPresets.requestType === 'ws') { + return 'ws-request'; + } + + return 'http-request'; + }; + const formik = useFormik({ enableReinitialize: true, initialValues: { requestName: '', filename: '', - requestType: 'http-request', - requestUrl: '', + requestType: getRequestType(collectionPresets), + requestUrl: collectionPresets.requestUrl || '', requestMethod: 'GET', curlCommand: '' }, diff --git a/packages/bruno-app/src/providers/ReduxStore/middlewares/autosave/middleware.js b/packages/bruno-app/src/providers/ReduxStore/middlewares/autosave/middleware.js index ab939fee5..e4e4122fa 100644 --- a/packages/bruno-app/src/providers/ReduxStore/middlewares/autosave/middleware.js +++ b/packages/bruno-app/src/providers/ReduxStore/middlewares/autosave/middleware.js @@ -41,6 +41,7 @@ const actionsToIntercept = [ 'collections/moveVar', 'collections/updateRequestDocs', 'collections/runRequestEvent', + 'collections/updateCollectionPresets', // Folder-level actions 'collections/addFolderHeader', 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 70cc7e20b..8dcfb3f56 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -2080,6 +2080,22 @@ export const collectionsSlice = createSlice({ set(collection, 'draft.brunoConfig.clientCertificates', action.payload.clientCertificates); } }, + updateCollectionPresets: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + if (!collection.draft) { + collection.draft = { + root: cloneDeep(collection.root), + brunoConfig: cloneDeep(collection.brunoConfig) + }; + } + if (!collection.draft.brunoConfig) { + collection.draft.brunoConfig = cloneDeep(collection.brunoConfig); + } + set(collection, 'draft.brunoConfig.presets', action.payload.presets); + } + }, updateCollectionProtobuf: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -3450,6 +3466,7 @@ export const { updateCollectionDocs, updateCollectionProxy, updateCollectionClientCertificates, + updateCollectionPresets, updateCollectionProtobuf, collectionAddFileEvent, collectionAddDirectoryEvent,