diff --git a/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js b/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js
index 82c7d2d1..502a70e8 100644
--- a/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js
+++ b/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js
@@ -7,6 +7,7 @@ import QueryParams from 'components/RequestPane/QueryParams';
import RequestHeaders from 'components/RequestPane/RequestHeaders';
import RequestBody from 'components/RequestPane/RequestBody';
import RequestBodyMode from 'components/RequestPane/RequestBody/RequestBodyMode';
+import Vars from 'components/RequestPane/Vars';
import Script from 'components/RequestPane/Script';
import Tests from 'components/RequestPane/Tests';
import StyledWrapper from './StyledWrapper';
@@ -36,6 +37,9 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
case 'headers': {
return ;
}
+ case 'vars': {
+ return ;
+ }
case 'script': {
return ;
}
@@ -75,6 +79,9 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
selectTab('headers')}>
Headers
+ selectTab('vars')}>
+ Vars
+
selectTab('script')}>
Script
@@ -89,7 +96,7 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => {
) : null}
- {getTabPanel(focusedTab.requestPaneTab)}
+ {getTabPanel(focusedTab.requestPaneTab)}
);
};
diff --git a/packages/bruno-app/src/components/RequestPane/QueryParams/index.js b/packages/bruno-app/src/components/RequestPane/QueryParams/index.js
index 63f94001..cf76a77a 100644
--- a/packages/bruno-app/src/components/RequestPane/QueryParams/index.js
+++ b/packages/bruno-app/src/components/RequestPane/QueryParams/index.js
@@ -68,7 +68,7 @@ const QueryParams = ({ item, collection }) => {
- Key |
+ Name |
Value |
|
diff --git a/packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js b/packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js
index 253243db..4d4afe71 100644
--- a/packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js
+++ b/packages/bruno-app/src/components/RequestPane/RequestHeaders/index.js
@@ -65,7 +65,7 @@ const RequestHeaders = ({ item, collection }) => {
- Key |
+ Name |
Value |
|
diff --git a/packages/bruno-app/src/components/RequestPane/Script/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Script/StyledWrapper.js
index fad3a55f..66ba1ed3 100644
--- a/packages/bruno-app/src/components/RequestPane/Script/StyledWrapper.js
+++ b/packages/bruno-app/src/components/RequestPane/Script/StyledWrapper.js
@@ -6,8 +6,7 @@ const StyledWrapper = styled.div`
}
div.title {
- color: rgb(155 155 155);
- font-weight: 500;
+ color: var(--color-tab-inactive);
}
`;
diff --git a/packages/bruno-app/src/components/RequestPane/Script/index.js b/packages/bruno-app/src/components/RequestPane/Script/index.js
index de26b3ed..d7fc8d54 100644
--- a/packages/bruno-app/src/components/RequestPane/Script/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Script/index.js
@@ -41,8 +41,8 @@ const Script = ({ item, collection }) => {
return (
-
-
Request
+
-
Response
+
Post Response
props.theme.table.border};
+ }
+
+ thead {
+ color: ${(props) => props.theme.table.thead.color};
+ font-size: 0.8125rem;
+ user-select: none;
+ }
+ td {
+ padding: 6px 10px;
+
+ &:nth-child(1) {
+ width: 30%;
+ }
+
+ &:nth-child(3) {
+ width: 70px;
+ }
+ }
+ }
+
+ .btn-add-var {
+ font-size: 0.8125rem;
+ }
+
+ input[type='text'] {
+ width: 100%;
+ border: solid 1px transparent;
+ outline: none !important;
+ background-color: inherit;
+
+ &:focus {
+ outline: none !important;
+ border: solid 1px transparent;
+ }
+ }
+
+ input[type='checkbox'] {
+ cursor: pointer;
+ position: relative;
+ top: 1px;
+ }
+`;
+
+export default Wrapper;
diff --git a/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js
new file mode 100644
index 00000000..dda1f705
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Vars/VarsTable/index.js
@@ -0,0 +1,130 @@
+import React from 'react';
+import cloneDeep from 'lodash/cloneDeep';
+import { IconTrash } from '@tabler/icons';
+import { useDispatch } from 'react-redux';
+import { useTheme } from 'providers/Theme';
+import { addVar, updateVar, deleteVar } from 'providers/ReduxStore/slices/collections';
+import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
+import SingleLineEditor from 'components/SingleLineEditor';
+import StyledWrapper from './StyledWrapper';
+
+const VarsTable = ({ item, collection, vars, varType }) => {
+ const dispatch = useDispatch();
+ const { storedTheme } = useTheme();
+
+ const handleAddVar = () => {
+ dispatch(
+ addVar({
+ type: varType,
+ itemUid: item.uid,
+ collectionUid: collection.uid
+ })
+ );
+ };
+
+ const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
+ const handleRun = () => dispatch(sendRequest(item, collection.uid));
+ const handleVarChange = (e, v, type) => {
+ const _var = cloneDeep(v);
+ switch (type) {
+ case 'name': {
+ _var.name = e.target.value;
+ break;
+ }
+ case 'value': {
+ _var.value = e.target.value;
+ break;
+ }
+ case 'enabled': {
+ _var.enabled = e.target.checked;
+ break;
+ }
+ }
+ dispatch(
+ updateVar({
+ type: varType,
+ var: _var,
+ itemUid: item.uid,
+ collectionUid: collection.uid
+ })
+ );
+ };
+
+ const handleRemoveVar = (_var) => {
+ dispatch(
+ deleteVar({
+ type: varType,
+ varUid: _var.uid,
+ itemUid: item.uid,
+ collectionUid: collection.uid
+ })
+ );
+ };
+
+ return (
+
+
+
+
+ );
+};
+export default VarsTable;
diff --git a/packages/bruno-app/src/components/RequestPane/Vars/index.js b/packages/bruno-app/src/components/RequestPane/Vars/index.js
new file mode 100644
index 00000000..1da6f69b
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Vars/index.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import get from 'lodash/get';
+import { useDispatch } from 'react-redux';
+import { updateRequestScript, updateResponseScript } from 'providers/ReduxStore/slices/collections';
+import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
+import { useTheme } from 'providers/Theme';
+import VarsTable from './VarsTable';
+import StyledWrapper from './StyledWrapper';
+
+const Vars = ({ item, collection }) => {
+ const dispatch = useDispatch();
+ const requestVars = item.draft ? get(item, 'draft.request.vars.req') : get(item, 'request.vars.req');
+ const responseVars = item.draft ? get(item, 'draft.request.vars.res') : get(item, 'request.vars.res');
+
+ const {
+ storedTheme
+ } = useTheme();
+
+ const onRequestScriptEdit = (value) => {
+ dispatch(
+ updateRequestScript({
+ script: value,
+ itemUid: item.uid,
+ collectionUid: collection.uid
+ })
+ );
+ };
+
+ const onResponseScriptEdit = (value) => {
+ dispatch(
+ updateResponseScript({
+ script: value,
+ itemUid: item.uid,
+ collectionUid: collection.uid
+ })
+ );
+};
+
+ const onRun = () => dispatch(sendRequest(item, collection.uid));
+ const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
+
+ return (
+
+
+
+
+ );
+};
+
+export default Vars;
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 621d355d..c62a9b77 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
@@ -707,6 +707,100 @@ export const collectionsSlice = createSlice({
}
}
},
+ addVar: (state, action) => {
+ const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
+ const type = action.payload.type;
+
+ if (collection) {
+ const item = findItemInCollection(collection, action.payload.itemUid);
+
+ if (item && isItemARequest(item)) {
+ if (!item.draft) {
+ item.draft = cloneDeep(item);
+ }
+ if(type === 'request') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.req = item.draft.request.vars.req || [];
+ item.draft.request.vars.req.push({
+ uid: uuid(),
+ name: '',
+ value: '',
+ local: false,
+ enabled: true
+ });
+ } else if(type === 'response') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.res = item.draft.request.vars.res || [];
+ item.draft.request.vars.res.push({
+ uid: uuid(),
+ name: '',
+ value: '',
+ local: false,
+ enabled: true
+ });
+ }
+ }
+ }
+ },
+ updateVar: (state, action) => {
+ const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
+ const type = action.payload.type;
+
+ if (collection) {
+ const item = findItemInCollection(collection, action.payload.itemUid);
+
+ if (item && isItemARequest(item)) {
+ if (!item.draft) {
+ item.draft = cloneDeep(item);
+ }
+ if(type === 'request') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.req = item.draft.request.vars.req || [];
+
+ const reqVar = find(item.draft.request.vars.req, (v) => v.uid === action.payload.var.uid);
+ if (reqVar) {
+ reqVar.name = action.payload.var.name;
+ reqVar.value = action.payload.var.value;
+ reqVar.description = action.payload.var.description;
+ reqVar.enabled = action.payload.var.enabled;
+ }
+ } else if(type === 'response') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.res = item.draft.request.vars.res || [];
+ const resVar = find(item.draft.request.vars.res, (v) => v.uid === action.payload.var.uid);
+ if (resVar) {
+ resVar.name = action.payload.var.name;
+ resVar.value = action.payload.var.value;
+ resVar.description = action.payload.var.description;
+ resVar.enabled = action.payload.var.enabled;
+ }
+ }
+ }
+ }
+ },
+ deleteVar: (state, action) => {
+ const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
+ const type = action.payload.type;
+
+ if (collection) {
+ const item = findItemInCollection(collection, action.payload.itemUid);
+
+ if (item && isItemARequest(item)) {
+ if (!item.draft) {
+ item.draft = cloneDeep(item);
+ }
+ if(type === 'request') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.req = item.draft.request.vars.req || [];
+ item.draft.request.vars.req = item.draft.request.vars.req.filter((v) => v.uid !== action.payload.varUid);
+ } else if(type === 'response') {
+ item.draft.request.vars = item.draft.request.vars || {};
+ item.draft.request.vars.res = item.draft.request.vars.res || [];
+ item.draft.request.vars.res = item.draft.request.vars.res.filter((v) => v.uid !== action.payload.varUid);
+ }
+ }
+ }
+ },
collectionAddFileEvent: (state, action) => {
const file = action.payload.file;
const collection = findCollectionByUid(state.collections, file.meta.collectionUid);
@@ -1028,6 +1122,9 @@ export const {
updateResponseScript,
updateRequestTests,
updateRequestMethod,
+ addVar,
+ updateVar,
+ deleteVar,
collectionAddFileEvent,
collectionAddDirectoryEvent,
collectionChangeFileEvent,
diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js
index 6c9f066a..0983713a 100644
--- a/packages/bruno-app/src/utils/collections/index.js
+++ b/packages/bruno-app/src/utils/collections/index.js
@@ -349,6 +349,7 @@ export const transformRequestToSaveToFilesystem = (item) => {
headers: [],
body: _item.request.body,
script: _item.request.script,
+ vars: _item.request.vars,
tests: _item.request.tests
}
};
diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js
index e74ff833..4fdaad7b 100644
--- a/packages/bruno-electron/src/app/watcher.js
+++ b/packages/bruno-electron/src/app/watcher.js
@@ -40,11 +40,15 @@ const hydrateRequestWithUuid = (request, pathname) => {
const params = _.get(request, 'request.params', []);
const headers = _.get(request, 'request.headers', []);
+ const requestVars = _.get(request, 'request.vars.req', []);
+ const responseVars = _.get(request, 'request.vars.res', []);
const bodyFormUrlEncoded = _.get(request, 'request.body.formUrlEncoded', []);
const bodyMultipartForm = _.get(request, 'request.body.multipartForm', []);
params.forEach((param) => param.uid = uuid());
headers.forEach((header) => header.uid = uuid());
+ requestVars.forEach((variable) => variable.uid = uuid());
+ responseVars.forEach((variable) => variable.uid = uuid());
bodyFormUrlEncoded.forEach((param) => param.uid = uuid());
bodyMultipartForm.forEach((param) => param.uid = uuid());
diff --git a/packages/bruno-electron/src/bru/index.js b/packages/bruno-electron/src/bru/index.js
index ebbccb90..0c2a9e2a 100644
--- a/packages/bruno-electron/src/bru/index.js
+++ b/packages/bruno-electron/src/bru/index.js
@@ -68,6 +68,7 @@ const bruToJson = (bru) => {
"headers": _.get(json, "headers", []),
"body": _.get(json, "body", {}),
"script": _.get(json, "script", {}),
+ "vars": _.get(json, "vars", {}),
"tests": _.get(json, "tests", "")
}
};
@@ -113,6 +114,10 @@ const jsonToBru = (json) => {
headers: _.get(json, 'request.headers', []),
body: _.get(json, 'request.body', {}),
script: _.get(json, 'request.script', {}),
+ vars: {
+ req: _.get(json, 'request.vars.req', []),
+ res: _.get(json, 'request.vars.res', [])
+ },
tests: _.get(json, 'request.tests', ''),
};
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index 715ede24..46766d34 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -26,6 +26,15 @@ const keyValueSchema = Yup.object({
enabled: Yup.boolean()
}).noUnknown(true).strict();
+const varsSchema = Yup.object({
+ uid: uidSchema,
+ name: Yup.string().nullable(),
+ value: Yup.string().nullable(),
+ description: Yup.string().nullable(),
+ local: Yup.boolean(),
+ enabled: Yup.boolean()
+}).noUnknown(true).strict();
+
const requestUrlSchema = Yup.string().min(0).defined();
const requestMethodSchema = Yup.string().oneOf(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']).required('method is required');
@@ -57,6 +66,10 @@ const requestSchema = Yup.object({
req: Yup.string().nullable(),
res: Yup.string().nullable()
}).noUnknown(true).strict(),
+ vars: Yup.object({
+ req: Yup.array().of(varsSchema).nullable(),
+ res: Yup.array().of(varsSchema).nullable()
+ }).noUnknown(true).strict().nullable(),
tests: Yup.string().nullable()
}).noUnknown(true).strict();