diff --git a/packages/bruno-app/src/components/RequestTabs/CollectionToolBar/index.js b/packages/bruno-app/src/components/RequestTabs/CollectionToolBar/index.js
index 98a399e79..15a96a7db 100644
--- a/packages/bruno-app/src/components/RequestTabs/CollectionToolBar/index.js
+++ b/packages/bruno-app/src/components/RequestTabs/CollectionToolBar/index.js
@@ -1,6 +1,7 @@
import React from 'react';
import { IconFiles } from '@tabler/icons';
import EnvironmentSelector from 'components/Environments/EnvironmentSelector';
+import VariablesView from 'components/VariablesView';
import StyledWrapper from './StyledWrapper';
const CollectionToolBar = ({ collection }) => {
@@ -12,6 +13,7 @@ const CollectionToolBar = ({ collection }) => {
{collection.name}
+
diff --git a/packages/bruno-app/src/components/VariablesView/Popover/StyledWrapper.js b/packages/bruno-app/src/components/VariablesView/Popover/StyledWrapper.js
new file mode 100644
index 000000000..48dc8f871
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/Popover/StyledWrapper.js
@@ -0,0 +1,19 @@
+import styled from 'styled-components';
+
+const Wrapper = styled.div`
+ position: absolute;
+ min-width: fit-content;
+ font-size: 14px;
+ top: 36px;
+ right: 0;
+ white-space: nowrap;
+ z-index: 1000;
+ background-color: ${(props) => props.theme.variables.bg};
+
+ .popover {
+ border-radius: 2px;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
+ }
+`;
+
+export default Wrapper;
\ No newline at end of file
diff --git a/packages/bruno-app/src/components/VariablesView/Popover/index.js b/packages/bruno-app/src/components/VariablesView/Popover/index.js
new file mode 100644
index 000000000..713621f79
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/Popover/index.js
@@ -0,0 +1,30 @@
+import React, {useRef} from 'react';
+import StyledWrapper from './StyledWrapper';
+import useOnClickOutside from 'hooks/useOnClickOutside';
+
+const PopOver = ({
+ children,
+ iconRef,
+ handleClose
+}) => {
+ const popOverRef = useRef(null);
+
+ useOnClickOutside(popOverRef, (e) => {
+ if(iconRef && iconRef.current) {
+ if (e.target == iconRef.current || iconRef.current.contains(e.target)) {
+ return;
+ }
+ }
+ handleClose();
+ });
+
+ return (
+
+
+
+ );
+};
+
+export default PopOver;
\ No newline at end of file
diff --git a/packages/bruno-app/src/components/VariablesView/StyledWrapper.js b/packages/bruno-app/src/components/VariablesView/StyledWrapper.js
new file mode 100644
index 000000000..5741b12c4
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/StyledWrapper.js
@@ -0,0 +1,15 @@
+import styled from 'styled-components';
+
+const StyledWrapper = styled.div`
+ position: relative;
+ align-self: stretch;
+ display: flex;
+ align-items: center;
+
+ .view-environment {
+ width: 1rem;
+ font-size: 10px;
+ }
+`
+
+export default StyledWrapper;
\ No newline at end of file
diff --git a/packages/bruno-app/src/components/VariablesView/VariablesTable/StyledWrapper.js b/packages/bruno-app/src/components/VariablesView/VariablesTable/StyledWrapper.js
new file mode 100644
index 000000000..a3fb048ee
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/VariablesTable/StyledWrapper.js
@@ -0,0 +1,9 @@
+import styled from 'styled-components';
+
+const StyledWrapper = styled.div`
+ .variable-name {
+ color: ${(props) => props.theme.variables.name.color};
+ }
+`
+
+export default StyledWrapper;
\ No newline at end of file
diff --git a/packages/bruno-app/src/components/VariablesView/VariablesTable/index.js b/packages/bruno-app/src/components/VariablesView/VariablesTable/index.js
new file mode 100644
index 000000000..19d13fd51
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/VariablesTable/index.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import StyledWrapper from './StyledWrapper';
+
+const VariablesTable = ({ variables }) => {
+ return (
+
+
+
+ {variables.map((variable) => (
+
+ | {variable.name} |
+ {variable.value} |
+
+ ))}
+
+
+
+ );
+};
+
+export default VariablesTable;
diff --git a/packages/bruno-app/src/components/VariablesView/index.js b/packages/bruno-app/src/components/VariablesView/index.js
new file mode 100644
index 000000000..05fa834f3
--- /dev/null
+++ b/packages/bruno-app/src/components/VariablesView/index.js
@@ -0,0 +1,46 @@
+import React, { useState, useRef } from 'react';
+import get from 'lodash/get';
+import filter from 'lodash/filter';
+import { findEnvironmentInCollection } from 'utils/collections';
+import VariablesTable from './VariablesTable';
+import StyledWrapper from './StyledWrapper';
+import PopOver from './PopOver';
+import { IconEye } from '@tabler/icons';
+
+const VariablesView = ({collection}) => {
+ const iconRef = useRef(null);
+ const [popOverOpen, setPopOverOpen] = useState(false);
+
+ const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid);
+ const variables = get(environment, 'variables', []);
+ const enabledVariables = filter(variables, (variable) => variable.enabled);
+
+ return (
+
+ setPopOverOpen(true)}
+ onMouseEnter={() => setPopOverOpen(true)}
+ onMouseLeave={() => setPopOverOpen(false)}
+ >
+
+
+
+ {popOverOpen && (
+
setPopOverOpen(false)}
+ >
+
+ {(enabledVariables && enabledVariables.length) ? : 'No variables found'}
+
+
+ )}
+
+
+ )
+};
+
+export default VariablesView;
\ No newline at end of file
diff --git a/packages/bruno-app/src/hooks/useOnClickOutside/index.js b/packages/bruno-app/src/hooks/useOnClickOutside/index.js
new file mode 100644
index 000000000..dcff4a2ff
--- /dev/null
+++ b/packages/bruno-app/src/hooks/useOnClickOutside/index.js
@@ -0,0 +1,34 @@
+// See https://usehooks.com/useOnClickOutside/
+import { useEffect } from 'react';
+
+const useOnClickOutside = (ref, handler) => {
+ useEffect(
+ () => {
+ const listener = event => {
+ // Do nothing if clicking ref's element or descendent elements
+ if (!ref.current || ref.current.contains(event.target)) {
+ return;
+ }
+
+ handler(event);
+ };
+
+ document.addEventListener('mousedown', listener);
+ document.addEventListener('touchstart', listener);
+
+ return () => {
+ document.removeEventListener('mousedown', listener);
+ document.removeEventListener('touchstart', listener);
+ };
+ },
+ // Add ref and handler to effect dependencies
+ // It's worth noting that because passed in handler is a new ...
+ // ... function on every render that will cause this effect ...
+ // ... callback/cleanup to run every render. It's not a big deal ...
+ // ... but to optimize you can wrap handler in useCallback before ...
+ // ... passing it into this hook.
+ [ref, handler]
+ );
+};
+
+export default useOnClickOutside;
\ No newline at end of file
diff --git a/packages/bruno-app/src/themes/dark.js b/packages/bruno-app/src/themes/dark.js
index 917c8d4af..1f40049ed 100644
--- a/packages/bruno-app/src/themes/dark.js
+++ b/packages/bruno-app/src/themes/dark.js
@@ -16,6 +16,14 @@ const darkTheme = {
}
},
+ variables: {
+ bg: 'rgb(48, 48, 49)',
+
+ name: {
+ color: '#569cd6',
+ }
+ },
+
menubar: {
bg: '#333333'
},
diff --git a/packages/bruno-app/src/themes/light.js b/packages/bruno-app/src/themes/light.js
index 81d5ecd94..21bdda3f4 100644
--- a/packages/bruno-app/src/themes/light.js
+++ b/packages/bruno-app/src/themes/light.js
@@ -20,6 +20,14 @@ const lightTheme = {
bg: 'rgb(44, 44, 44)'
},
+ variables: {
+ bg: '#fff',
+
+ name: {
+ color: '#546de5',
+ }
+ },
+
sidebar: {
color: 'rgb(52, 52, 52)',
muted: '#4b5563',
diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js
index a4cfce6e0..4f6a08cb2 100644
--- a/packages/bruno-electron/src/ipc/network/index.js
+++ b/packages/bruno-electron/src/ipc/network/index.js
@@ -6,6 +6,7 @@ const { ScriptRuntime } = require('@usebruno/js');
const prepareRequest = require('./prepare-request');
const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token');
const { uuid } = require('../../utils/common');
+const interpolateVars = require('./interpolate-vars');
const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
// handler for sending http request
@@ -34,7 +35,7 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
if(request.script && request.script.length) {
request.script = request.script += '\n onRequest(brunoRequest);';
const scriptRuntime = new ScriptRuntime();
- scriptRuntime.run(request.script, request);
+ scriptRuntime.run(request.script, request, environment);
}
mainWindow.webContents.send('main:http-request-sent', {
@@ -49,6 +50,8 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => {
cancelTokenUid
});
+ interpolateVars(request, environment);
+
const result = await axios(request);
deleteCancelToken(cancelTokenUid);
diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
index 5f2df21dd..87fc46a3c 100644
--- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js
+++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
@@ -1,5 +1,5 @@
const Mustache = require('mustache');
-const { each } = require('lodash');
+const { each, get } = require('lodash');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {
@@ -39,7 +39,8 @@ const interpolateVars = (request, environment) => {
});
// Todo: Make interpolation work with body mode json
- switch (request.body.mode) {
+ const mode = get(request, 'body.mode');
+ switch (mode) {
case 'text': {
request.body.text = interpolate(request.body.text);
break;
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index 7fefd1d74..8b024ecec 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -1,9 +1,7 @@
const { get, each, filter } = require('lodash');
const qs = require('qs');
-const interpolateVars = require('./interpolate-vars');
const prepareRequest = (request, environment) => {
- interpolateVars(request, environment);
const headers = {};
each(request.headers, (h) => {
if (h.enabled) {
diff --git a/packages/bruno-js/src/scripts/bru.js b/packages/bruno-js/src/scripts/bru.js
new file mode 100644
index 000000000..bee556b0b
--- /dev/null
+++ b/packages/bruno-js/src/scripts/bru.js
@@ -0,0 +1,10 @@
+class Bru {
+ constructor(environment) {
+ this._environment = environment;
+ }
+
+ setVar(key, value) {
+ }
+}
+
+module.exports = Bru;
\ No newline at end of file
diff --git a/packages/bruno-js/src/scripts/script-runtime.js b/packages/bruno-js/src/scripts/script-runtime.js
index caebfe455..d7fdb1c83 100644
--- a/packages/bruno-js/src/scripts/script-runtime.js
+++ b/packages/bruno-js/src/scripts/script-runtime.js
@@ -1,14 +1,17 @@
const { NodeVM } = require('vm2');
+const Bru = require('./bru');
const BrunoRequest = require('./bruno-request');
class ScriptRuntime {
constructor() {
}
- run(script, request) {
+ run(script, request, environment) {
+ const bru = new Bru(environment);
const brunoRequest = new BrunoRequest(request);
const context = {
+ bru,
brunoRequest
};
const vm = new NodeVM({