+
diff --git a/packages/bruno-app/src/components/Sidebar/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/StyledWrapper.js
index a677c0cb7..7781e6dc3 100644
--- a/packages/bruno-app/src/components/Sidebar/StyledWrapper.js
+++ b/packages/bruno-app/src/components/Sidebar/StyledWrapper.js
@@ -54,7 +54,7 @@ const Wrapper = styled.div`
&:hover div.drag-request-border {
width: 2px;
height: 100%;
- border-left: solid 1px var(--color-request-dragbar-background-active);
+ border-left: solid 1px ${(props) => props.theme.sidebar.dragbar};
}
}
`;
diff --git a/packages/bruno-app/src/globalStyles.js b/packages/bruno-app/src/globalStyles.js
index c9b212a5a..2e49f4a68 100644
--- a/packages/bruno-app/src/globalStyles.js
+++ b/packages/bruno-app/src/globalStyles.js
@@ -22,6 +22,10 @@ const GlobalStyle = createGlobalStyle`
padding: .215rem .6rem .215rem .6rem;
}
+ .btn-xs {
+ padding: .2rem .4rem .2rem .4rem;
+ }
+
.btn-md {
padding: .4rem 1.1rem;
line-height: 1.47;
diff --git a/packages/bruno-app/src/hooks/useGraphqlSchema/index.js b/packages/bruno-app/src/hooks/useGraphqlSchema/index.js
deleted file mode 100644
index 783faa68e..000000000
--- a/packages/bruno-app/src/hooks/useGraphqlSchema/index.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { useState, useEffect } from 'react';
-import { getIntrospectionQuery, buildClientSchema } from 'graphql';
-
-const useGraphqlSchema = (endpoint) => {
- const [isLoaded, setIsLoaded] = useState(false);
- const [schema, setSchema] = useState(null);
- const [error, setError] = useState(null);
-
- const introspectionQuery = getIntrospectionQuery();
- const queryParams = {
- query: introspectionQuery
- };
-
- useEffect(() => {
- fetch(endpoint, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(queryParams)
- })
- .then((res) => res.json())
- .then((s) => {
- if (s && s.data) {
- setSchema(buildClientSchema(s.data));
- setIsLoaded(true);
- } else {
- return Promise.reject(new Error('An error occurred while introspecting schema'));
- }
- })
- .catch((err) => {
- setError(err);
- });
- }, []);
-
- return {
- isLoaded,
- schema,
- error
- };
-};
-
-export default useGraphqlSchema;
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/app.js b/packages/bruno-app/src/providers/ReduxStore/slices/app.js
index 8c3c08f97..6736370c2 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/app.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/app.js
@@ -3,8 +3,8 @@ import { createSlice } from '@reduxjs/toolkit';
const initialState = {
isDragging: false,
idbConnectionReady: false,
- leftSidebarWidth: 270,
- leftMenuBarOpen: true,
+ leftSidebarWidth: 222,
+ leftMenuBarOpen: false,
screenWidth: 500,
showHomePage: false
};
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 190e1e7c7..acc9883f7 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js
@@ -16,7 +16,8 @@ import {
findEnvironmentInCollection,
isItemAFolder,
refreshUidsInItem,
- interpolateEnvironmentVars
+ interpolateEnvironmentVars,
+ getDefaultRequestPaneTab
} from 'utils/collections';
import { collectionSchema, itemSchema, environmentsSchema } from '@usebruno/schema';
import { waitForNextTick } from 'utils/common';
@@ -108,7 +109,8 @@ export const createCollection = (collectionName) => (dispatch, getState) => {
dispatch(
addTab({
uid: requestItem.uid,
- collectionUid: newCollection.uid
+ collectionUid: newCollection.uid,
+ requestPaneTab: getDefaultRequestPaneTab(requestItem)
})
)
)
@@ -635,7 +637,8 @@ export const newHttpRequest = (params) => (dispatch, getState) => {
dispatch(
addTab({
uid: item.uid,
- collectionUid: collection.uid
+ collectionUid: collection.uid,
+ requestPaneTab: getDefaultRequestPaneTab(item)
})
);
})
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 4ca807f4b..a9ae22597 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
@@ -606,6 +606,22 @@ export const collectionsSlice = createSlice({
}
}
},
+ updateRequestGraphqlQuery: (state, action) => {
+ const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
+
+ if (collection) {
+ const item = findItemInCollection(collection, action.payload.itemUid);
+
+ if (item && isItemARequest(item)) {
+ if (!item.draft) {
+ item.draft = cloneDeep(item);
+ }
+ item.draft.request.body.mode = 'graphql';
+ item.draft.request.body.graphql = item.draft.request.body.graphql || {};
+ item.draft.request.body.graphql.query = action.payload.query;
+ }
+ }
+ },
updateRequestMethod: (state, action) => {
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
@@ -791,6 +807,7 @@ export const {
deleteMultipartFormParam,
updateRequestBodyMode,
updateRequestBody,
+ updateRequestGraphqlQuery,
updateRequestMethod,
localCollectionAddFileEvent,
localCollectionAddDirectoryEvent,
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js b/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js
index bc6f1d52d..d12f18586 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js
@@ -23,7 +23,7 @@ export const tabsSlice = createSlice({
uid: action.payload.uid,
collectionUid: action.payload.collectionUid,
requestPaneWidth: null,
- requestPaneTab: 'params',
+ requestPaneTab: action.payload.requestPaneTab || 'params',
responsePaneTab: 'response'
});
state.activeTabUid = action.payload.uid;
diff --git a/packages/bruno-app/src/themes/dark.js b/packages/bruno-app/src/themes/dark.js
index 8f9dbb272..7124c3be6 100644
--- a/packages/bruno-app/src/themes/dark.js
+++ b/packages/bruno-app/src/themes/dark.js
@@ -22,6 +22,7 @@ const darkTheme = {
color: '#ccc',
muted: '#9d9d9d',
bg: '#252526',
+ dragbar: '#8a8a8a',
workspace: {
bg: '#3D3D3D'
diff --git a/packages/bruno-app/src/themes/light.js b/packages/bruno-app/src/themes/light.js
index 3b0cc0534..a308208b6 100644
--- a/packages/bruno-app/src/themes/light.js
+++ b/packages/bruno-app/src/themes/light.js
@@ -22,6 +22,7 @@ const lightTheme = {
color: 'rgb(52, 52, 52)',
muted: '#4b5563',
bg: '#F3F3F3',
+ dragbar: 'rgb(200, 200, 200)',
workspace: {
bg: '#e1e1e1'
diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js
index bfa84a1c7..8c8263809 100644
--- a/packages/bruno-app/src/utils/collections/index.js
+++ b/packages/bruno-app/src/utils/collections/index.js
@@ -196,7 +196,7 @@ export const transformCollectionToSaveToIdb = (collection, options = {}) => {
json: si.draft.request.body.json,
text: si.draft.request.body.text,
xml: si.draft.request.body.xml,
- multipartForm: si.draft.request.body.multipartForm,
+ graphql: si.draft.request.body.graphql,
formUrlEncoded: copyFormUrlEncodedParams(si.draft.request.body.formUrlEncoded),
multipartForm: copyMultipartFormParams(si.draft.request.body.multipartForm)
}
@@ -214,6 +214,7 @@ export const transformCollectionToSaveToIdb = (collection, options = {}) => {
json: si.request.body.json,
text: si.request.body.text,
xml: si.request.body.xml,
+ graphql: si.request.body.graphql,
formUrlEncoded: copyFormUrlEncodedParams(si.request.body.formUrlEncoded),
multipartForm: copyMultipartFormParams(si.request.body.multipartForm)
}
@@ -410,3 +411,13 @@ export const interpolateEnvironmentVars = (item, variables) => {
return request;
};
+
+export const getDefaultRequestPaneTab = (item) => {
+ if(item.type === 'http-request') {
+ return 'params';
+ }
+
+ if(item.type === 'graphql-request') {
+ return 'query';
+ }
+};
diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js
index 33f3a3f5f..1efde5692 100644
--- a/packages/bruno-app/src/utils/network/index.js
+++ b/packages/bruno-app/src/utils/network/index.js
@@ -1,14 +1,14 @@
+import get from 'lodash/get';
import each from 'lodash/each';
import filter from 'lodash/filter';
import qs from 'qs';
-import { rawRequest, gql } from 'graphql';
import { sendHttpRequestInBrowser } from './browser';
import { isElectron } from 'utils/common/platform';
import cancelTokens, { deleteCancelToken } from 'utils/network/cancelTokens';
export const sendNetworkRequest = async (item, options) => {
return new Promise((resolve, reject) => {
- if (item.type === 'http-request') {
+ if (['http-request', 'graphql-request'].includes(item.type)) {
const timeStart = Date.now();
sendHttpRequest(item.draft ? item.draft.request : item.request, options)
.then((response) => {
@@ -79,6 +79,15 @@ const sendHttpRequest = async (request, options) => {
axiosRequest.data = params;
}
+ if (request.body.mode === 'graphql') {
+ const graphqlQuery = {
+ query: get(request, 'body.graphql.query'),
+ variables: JSON.parse(get(request, 'body.graphql.variables') || '{}')
+ };
+ axiosRequest.headers['content-type'] = 'application/json';
+ axiosRequest.data = graphqlQuery;
+ }
+
console.log('>>> Sending Request');
console.log(axiosRequest);
@@ -90,21 +99,6 @@ const sendHttpRequest = async (request, options) => {
});
};
-const sendGraphqlRequest = async (request) => {
- const query = gql`
- ${request.request.body.graphql.query}
- `;
-
- const { data, errors, extensions, headers, status } = await rawRequest(request.request.url, query);
-
- return {
- data,
- headers,
- data,
- errors
- };
-};
-
export const cancelNetworkRequest = async (cancelTokenUid) => {
if (isElectron()) {
return new Promise((resolve, reject) => {
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index 60326de7d..e4481e6ba 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -29,13 +29,19 @@ const keyValueSchema = Yup.object({
const requestUrlSchema = Yup.string().min(0).max(2048, 'name must be 2048 characters or less').defined();
const requestMethodSchema = Yup.string().oneOf(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']).required('method is required');
+const graphqlBodySchema = Yup.object({
+ query: Yup.string().max(10240, 'json must be 10240 characters or less').nullable(),
+ variables: Yup.string().max(10240, 'text must be 10240 characters or less').nullable(),
+}).noUnknown(true).strict();
+
const requestBodySchema = Yup.object({
- mode: Yup.string().oneOf(['none', 'json', 'text', 'xml', 'formUrlEncoded', 'multipartForm']).required('mode is required'),
+ mode: Yup.string().oneOf(['none', 'json', 'text', 'xml', 'formUrlEncoded', 'multipartForm', 'graphql']).required('mode is required'),
json: Yup.string().max(10240, 'json must be 10240 characters or less').nullable(),
text: Yup.string().max(10240, 'text must be 10240 characters or less').nullable(),
xml: Yup.string().max(10240, 'xml must be 10240 characters or less').nullable(),
formUrlEncoded: Yup.array().of(keyValueSchema).nullable(),
multipartForm: Yup.array().of(keyValueSchema).nullable(),
+ graphql: graphqlBodySchema.nullable(),
}).noUnknown(true).strict();
// Right now, the request schema is very tightly coupled with http request