mirror of
https://github.com/usebruno/bruno.git
synced 2025-06-25 22:41:30 +02:00
feat: prettier config
This commit is contained in:
parent
93544f8ae6
commit
ba219d66db
7
packages/bruno-app/.prettierrc.json
Normal file
7
packages/bruno-app/.prettierrc.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 180
|
||||||
|
}
|
@ -5,16 +5,17 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build && next export",
|
"build": "next build && next export",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"prettier": "prettier --write \"./src/**/*.{js,jsx,json,ts,tsx}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@usebruno/schema": "0.1.0",
|
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.16",
|
"@fortawesome/react-fontawesome": "^0.1.16",
|
||||||
"@reduxjs/toolkit": "^1.8.0",
|
"@reduxjs/toolkit": "^1.8.0",
|
||||||
"@tabler/icons": "^1.46.0",
|
"@tabler/icons": "^1.46.0",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
|
"@usebruno/schema": "0.1.0",
|
||||||
"axios": "^0.26.0",
|
"axios": "^0.26.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"codemirror": "^5.65.2",
|
"codemirror": "^5.65.2",
|
||||||
@ -57,6 +58,7 @@
|
|||||||
"html-loader": "^3.0.1",
|
"html-loader": "^3.0.1",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"mini-css-extract-plugin": "^2.4.5",
|
"mini-css-extract-plugin": "^2.4.5",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"webpack": "^5.64.4",
|
"webpack": "^5.64.4",
|
||||||
"webpack-cli": "^4.9.1"
|
"webpack-cli": "^4.9.1"
|
||||||
|
@ -6,12 +6,13 @@ const AuthApi = {
|
|||||||
signup: (params) => post('auth/v1/user/signup', params),
|
signup: (params) => post('auth/v1/user/signup', params),
|
||||||
login: (params) => {
|
login: (params) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { ipcRenderer } = window.require("electron");
|
const { ipcRenderer } = window.require('electron');
|
||||||
|
|
||||||
ipcRenderer.invoke('bruno-account-request', {
|
ipcRenderer
|
||||||
|
.invoke('bruno-account-request', {
|
||||||
data: params,
|
data: params,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: `${process.env.NEXT_PUBLIC_BRUNO_SERVER_API}/auth/v1/user/login`,
|
url: `${process.env.NEXT_PUBLIC_BRUNO_SERVER_API}/auth/v1/user/login`
|
||||||
})
|
})
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
import axios from "axios";
|
import axios from 'axios';
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
baseURL: process.env.NEXT_PUBLIC_GRAFNODE_SERVER_API
|
baseURL: process.env.NEXT_PUBLIC_GRAFNODE_SERVER_API
|
||||||
});
|
});
|
||||||
|
|
||||||
apiClient.interceptors.request.use((config) => {
|
apiClient.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
|
|
||||||
return ({
|
return {
|
||||||
...config,
|
...config,
|
||||||
headers: headers
|
headers: headers
|
||||||
});
|
};
|
||||||
}, error => Promise.reject(error));
|
},
|
||||||
|
(error) => Promise.reject(error)
|
||||||
|
);
|
||||||
|
|
||||||
apiClient.interceptors.response.use((response) =>
|
apiClient.interceptors.response.use(
|
||||||
response,
|
(response) => response,
|
||||||
async (error) => {
|
async (error) => {
|
||||||
return Promise.reject(error.response ? error.response.data : error);
|
return Promise.reject(error.response ? error.response.data : error);
|
||||||
}
|
}
|
||||||
|
@ -4,27 +4,91 @@ const Bruno = ({width}) => {
|
|||||||
return (
|
return (
|
||||||
<svg id="emoji" width={width} viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
<svg id="emoji" width={width} viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g id="color">
|
<g id="color">
|
||||||
<path fill="#F4AA41" stroke="none" d="M23.5,14.5855l-4.5,1.75l-7.25,8.5l-4.5,10.75l2,5.25c1.2554,3.7911,3.5231,7.1832,7.25,10l2.5-3.3333 c0,0,3.8218,7.7098,10.7384,8.9598c0,0,10.2616,1.936,15.5949-0.8765c3.4203-1.8037,4.4167-4.4167,4.4167-4.4167l3.4167-3.4167 l1.5833,2.3333l2.0833-0.0833l5.4167-7.25L64,37.3355l-0.1667-4.5l-2.3333-5.5l-4.8333-7.4167c0,0-2.6667-4.9167-8.1667-3.9167 c0,0-6.5-4.8333-11.8333-4.0833S32.0833,10.6688,23.5,14.5855z"/>
|
<path
|
||||||
<polygon fill="#EA5A47" stroke="none" points="36,47.2521 32.9167,49.6688 30.4167,49.6688 30.3333,53.5021 31.0833,57.0021 32.1667,58.9188 35,60.4188 39.5833,59.8355 41.1667,58.0855 42.1667,53.8355 41.9167,49.8355 39.9167,50.0855"/>
|
fill="#F4AA41"
|
||||||
|
stroke="none"
|
||||||
|
d="M23.5,14.5855l-4.5,1.75l-7.25,8.5l-4.5,10.75l2,5.25c1.2554,3.7911,3.5231,7.1832,7.25,10l2.5-3.3333 c0,0,3.8218,7.7098,10.7384,8.9598c0,0,10.2616,1.936,15.5949-0.8765c3.4203-1.8037,4.4167-4.4167,4.4167-4.4167l3.4167-3.4167 l1.5833,2.3333l2.0833-0.0833l5.4167-7.25L64,37.3355l-0.1667-4.5l-2.3333-5.5l-4.8333-7.4167c0,0-2.6667-4.9167-8.1667-3.9167 c0,0-6.5-4.8333-11.8333-4.0833S32.0833,10.6688,23.5,14.5855z"
|
||||||
|
/>
|
||||||
|
<polygon
|
||||||
|
fill="#EA5A47"
|
||||||
|
stroke="none"
|
||||||
|
points="36,47.2521 32.9167,49.6688 30.4167,49.6688 30.3333,53.5021 31.0833,57.0021 32.1667,58.9188 35,60.4188 39.5833,59.8355 41.1667,58.0855 42.1667,53.8355 41.9167,49.8355 39.9167,50.0855"
|
||||||
|
/>
|
||||||
<polygon fill="#3F3F3F" stroke="none" points="32.5,36.9188 30.9167,40.6688 33.0833,41.9188 34.3333,42.4188 38.6667,42.5855 41.5833,40.3355 39.8333,37.0855" />
|
<polygon fill="#3F3F3F" stroke="none" points="32.5,36.9188 30.9167,40.6688 33.0833,41.9188 34.3333,42.4188 38.6667,42.5855 41.5833,40.3355 39.8333,37.0855" />
|
||||||
</g>
|
</g>
|
||||||
<g id="hair" />
|
<g id="hair" />
|
||||||
<g id="skin" />
|
<g id="skin" />
|
||||||
<g id="skin-shadow" />
|
<g id="skin-shadow" />
|
||||||
<g id="line">
|
<g id="line">
|
||||||
<path fill="#000000" stroke="none" d="M29.5059,30.1088c0,0-1.8051,1.2424-2.7484,0.6679c-0.9434-0.5745-1.2424-1.8051-0.6679-2.7484 s1.805-1.2424,2.7484-0.6679S29.5059,30.1088,29.5059,30.1088z"/>
|
<path
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M33.1089,37.006h6.1457c0.4011,0,0.7634,0.2397,0.9203,0.6089l1.1579,2.7245l-2.1792,1.1456 c-0.6156,0.3236-1.3654-0.0645-1.4567-0.754"/>
|
fill="#000000"
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M34.7606,40.763c-0.1132,0.6268-0.7757,0.9895-1.3647,0.7471l-2.3132-0.952l1.0899-2.9035 c0.1465-0.3901,0.5195-0.6486,0.9362-0.6486"/>
|
stroke="none"
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M30.4364,50.0268c0,0-0.7187,8.7934,3.0072,9.9375c2.6459,0.8125,5.1497,0.5324,6.0625-0.25 c0.875-0.75,2.6323-4.4741,1.8267-9.6875"/>
|
d="M29.5059,30.1088c0,0-1.8051,1.2424-2.7484,0.6679c-0.9434-0.5745-1.2424-1.8051-0.6679-2.7484 s1.805-1.2424,2.7484-0.6679S29.5059,30.1088,29.5059,30.1088z"
|
||||||
<path fill="#000000" stroke="none" d="M44.2636,30.1088c0,0,1.805,1.2424,2.7484,0.6679c0.9434-0.5745,1.2424-1.8051,0.6679-2.7484 c-0.5745-0.9434-1.805-1.2424-2.7484-0.6679C43.9881,27.9349,44.2636,30.1088,44.2636,30.1088z"/>
|
/>
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M25.6245,42.8393c-0.475,3.6024,2.2343,5.7505,4.2847,6.8414c1.1968,0.6367,2.6508,0.5182,3.7176-0.3181l2.581-2.0233l2.581,2.0233 c1.0669,0.8363,2.5209,0.9548,3.7176,0.3181c2.0504-1.0909,4.7597-3.239,4.2847-6.8414"/>
|
<path
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M19.9509,28.3572c-2.3166,5.1597-0.5084,13.0249,0.119,15.3759c0.122,0.4571,0.0755,0.9355-0.1271,1.3631l-1.9874,4.1937 c-0.623,1.3146-2.3934,1.5533-3.331,0.4409c-3.1921-3.7871-8.5584-11.3899-6.5486-16.686 c7.0625-18.6104,15.8677-18.1429,15.8677-18.1429c2.8453-1.9336,13.1042-6.9375,24.8125,0.875c0,0,8.6323-1.7175,14.9375,16.9375 c1.8036,5.3362-3.4297,12.8668-6.5506,16.6442c-0.9312,1.127-2.7162,0.8939-3.3423-0.4272l-1.9741-4.1656 c-0.2026-0.4275-0.2491-0.906-0.1271-1.3631c0.6275-2.3509,2.4356-10.2161,0.119-15.3759"/>
|
fill="none"
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M52.6309,46.4628c0,0-3.0781,6.7216-7.8049,8.2712"/>
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M33.1089,37.006h6.1457c0.4011,0,0.7634,0.2397,0.9203,0.6089l1.1579,2.7245l-2.1792,1.1456 c-0.6156,0.3236-1.3654-0.0645-1.4567-0.754"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M34.7606,40.763c-0.1132,0.6268-0.7757,0.9895-1.3647,0.7471l-2.3132-0.952l1.0899-2.9035 c0.1465-0.3901,0.5195-0.6486,0.9362-0.6486"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M30.4364,50.0268c0,0-0.7187,8.7934,3.0072,9.9375c2.6459,0.8125,5.1497,0.5324,6.0625-0.25 c0.875-0.75,2.6323-4.4741,1.8267-9.6875"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="#000000"
|
||||||
|
stroke="none"
|
||||||
|
d="M44.2636,30.1088c0,0,1.805,1.2424,2.7484,0.6679c0.9434-0.5745,1.2424-1.8051,0.6679-2.7484 c-0.5745-0.9434-1.805-1.2424-2.7484-0.6679C43.9881,27.9349,44.2636,30.1088,44.2636,30.1088z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M25.6245,42.8393c-0.475,3.6024,2.2343,5.7505,4.2847,6.8414c1.1968,0.6367,2.6508,0.5182,3.7176-0.3181l2.581-2.0233l2.581,2.0233 c1.0669,0.8363,2.5209,0.9548,3.7176,0.3181c2.0504-1.0909,4.7597-3.239,4.2847-6.8414"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M19.9509,28.3572c-2.3166,5.1597-0.5084,13.0249,0.119,15.3759c0.122,0.4571,0.0755,0.9355-0.1271,1.3631l-1.9874,4.1937 c-0.623,1.3146-2.3934,1.5533-3.331,0.4409c-3.1921-3.7871-8.5584-11.3899-6.5486-16.686 c7.0625-18.6104,15.8677-18.1429,15.8677-18.1429c2.8453-1.9336,13.1042-6.9375,24.8125,0.875c0,0,8.6323-1.7175,14.9375,16.9375 c1.8036,5.3362-3.4297,12.8668-6.5506,16.6442c-0.9312,1.127-2.7162,0.8939-3.3423-0.4272l-1.9741-4.1656 c-0.2026-0.4275-0.2491-0.906-0.1271-1.3631c0.6275-2.3509,2.4356-10.2161,0.119-15.3759"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="#000000"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M52.6309,46.4628c0,0-3.0781,6.7216-7.8049,8.2712"
|
||||||
|
/>
|
||||||
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M19.437,46.969c0,0,3.0781,6.0823,7.8049,7.632" />
|
<path fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M19.437,46.969c0,0,3.0781,6.0823,7.8049,7.632" />
|
||||||
<line x1="36.2078" x2="36.2078" y1="47.3393" y2="44.3093" fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" />
|
<line x1="36.2078" x2="36.2078" y1="47.3393" y2="44.3093" fill="none" stroke="#000000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Bruno;
|
export default Bruno;
|
||||||
|
@ -1,40 +1,36 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import {IconSpeakerphone, IconBrandTwitter} from "@tabler/icons";
|
import { IconSpeakerphone, IconBrandTwitter } from '@tabler/icons';
|
||||||
import StyledWrapper from "./StyledWrapper";
|
import StyledWrapper from './StyledWrapper';
|
||||||
import GithubSvg from 'assets/github.svg';
|
import GithubSvg from 'assets/github.svg';
|
||||||
|
|
||||||
const BrunoSupport = ({ onClose }) => {
|
const BrunoSupport = ({ onClose }) => {
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="sm" title={'Support'} handleCancel={onClose} hideFooter={true}>
|
||||||
size="sm"
|
|
||||||
title={"Support"}
|
|
||||||
handleCancel={onClose}
|
|
||||||
hideFooter={true}
|
|
||||||
>
|
|
||||||
<div className="collection-options">
|
<div className="collection-options">
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="flex items-center">
|
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="flex items-center">
|
||||||
<IconSpeakerphone size={18} strokeWidth={2}/><span className="label ml-2">Report Issues</span>
|
<IconSpeakerphone size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Report Issues</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<a href="https://github.com/usebruno/bruno" target="_blank" className="flex items-center">
|
<a href="https://github.com/usebruno/bruno" target="_blank" className="flex items-center">
|
||||||
<img src={GithubSvg.src} style={{width: "18px"}}/>
|
<img src={GithubSvg.src} style={{ width: '18px' }} />
|
||||||
<span className="label ml-2">Github</span>
|
<span className="label ml-2">Github</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<a href="https://twitter.com/use_bruno" target="_blank" className="flex items-center">
|
<a href="https://twitter.com/use_bruno" target="_blank" className="flex items-center">
|
||||||
<IconBrandTwitter size={18} strokeWidth={2}/><span className="label ml-2">Twitter</span>
|
<IconBrandTwitter size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Twitter</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default BrunoSupport;
|
export default BrunoSupport;
|
||||||
|
|
||||||
|
@ -11,4 +11,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export default class QueryEditor extends React.Component {
|
|||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
showCursorWhenSelecting: true,
|
showCursorWhenSelecting: true,
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||||
readOnly: this.props.readOnly ? 'nocursor' : false,
|
readOnly: this.props.readOnly ? 'nocursor' : false,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
'Cmd-Enter': () => {
|
'Cmd-Enter': () => {
|
||||||
@ -60,10 +60,10 @@ export default class QueryEditor extends React.Component {
|
|||||||
this.props.onSave();
|
this.props.onSave();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'Tab': function(cm){
|
Tab: function (cm) {
|
||||||
cm.replaceSelection(" " , "end");
|
cm.replaceSelection(' ', 'end');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
if (editor) {
|
if (editor) {
|
||||||
editor.on('change', this._onEdit);
|
editor.on('change', this._onEdit);
|
||||||
@ -82,14 +82,10 @@ export default class QueryEditor extends React.Component {
|
|||||||
this.editor.options.jump.schema = this.props.schema;
|
this.editor.options.jump.schema = this.props.schema;
|
||||||
CodeMirror.signal(this.editor, 'change', this.editor);
|
CodeMirror.signal(this.editor, 'change', this.editor);
|
||||||
}
|
}
|
||||||
if (
|
if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) {
|
||||||
this.props.value !== prevProps.value &&
|
|
||||||
this.props.value !== this.cachedValue &&
|
|
||||||
this.editor
|
|
||||||
) {
|
|
||||||
this.cachedValue = this.props.value;
|
this.cachedValue = this.props.value;
|
||||||
this.editor.setValue(this.props.value);
|
this.editor.setValue(this.props.value);
|
||||||
this.editor.setOption("mode", this.props.mode);
|
this.editor.setOption('mode', this.props.mode);
|
||||||
}
|
}
|
||||||
this.ignoreChangeEvent = false;
|
this.ignoreChangeEvent = false;
|
||||||
}
|
}
|
||||||
@ -106,7 +102,7 @@ export default class QueryEditor extends React.Component {
|
|||||||
<StyledWrapper
|
<StyledWrapper
|
||||||
className="h-full"
|
className="h-full"
|
||||||
aria-label="Code Editor"
|
aria-label="Code Editor"
|
||||||
ref={node => {
|
ref={(node) => {
|
||||||
this._node = node;
|
this._node = node;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -24,13 +24,13 @@ const Wrapper = styled.div`
|
|||||||
.label-item {
|
.label-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: .35rem .6rem;
|
padding: 0.35rem 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: .35rem .6rem;
|
padding: 0.35rem 0.6rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -5,16 +5,7 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
const Dropdown = ({ icon, children, onCreate, placement }) => {
|
const Dropdown = ({ icon, children, onCreate, placement }) => {
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="dropdown">
|
<StyledWrapper className="dropdown">
|
||||||
<Tippy
|
<Tippy content={children} placement={placement || 'bottom-end'} animation={false} arrow={false} onCreate={onCreate} interactive={true} trigger="click" appendTo="parent">
|
||||||
content={children}
|
|
||||||
placement={placement || "bottom-end"}
|
|
||||||
animation={false}
|
|
||||||
arrow={false}
|
|
||||||
onCreate={onCreate}
|
|
||||||
interactive={true}
|
|
||||||
trigger="click"
|
|
||||||
appendTo="parent"
|
|
||||||
>
|
|
||||||
{icon}
|
{icon}
|
||||||
</Tippy>
|
</Tippy>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -3,7 +3,7 @@ import find from 'lodash/find';
|
|||||||
import Dropdown from 'components/Dropdown';
|
import Dropdown from 'components/Dropdown';
|
||||||
import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { IconSettings, IconCaretDown, IconDatabase } from '@tabler/icons';
|
import { IconSettings, IconCaretDown, IconDatabase } from '@tabler/icons';
|
||||||
import EnvironmentSettings from "../EnvironmentSettings";
|
import EnvironmentSettings from '../EnvironmentSettings';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
@ -13,7 +13,7 @@ const EnvironmentSelector = ({collection}) => {
|
|||||||
const dropdownTippyRef = useRef();
|
const dropdownTippyRef = useRef();
|
||||||
const [openSettingsModal, setOpenSettingsModal] = useState(false);
|
const [openSettingsModal, setOpenSettingsModal] = useState(false);
|
||||||
const { environments, activeEnvironmentUid } = collection;
|
const { environments, activeEnvironmentUid } = collection;
|
||||||
const activeEnvironment = activeEnvironmentUid ? find(environments, e => e.uid === activeEnvironmentUid) : null;
|
const activeEnvironment = activeEnvironmentUid ? find(environments, (e) => e.uid === activeEnvironmentUid) : null;
|
||||||
|
|
||||||
const Icon = forwardRef((props, ref) => {
|
const Icon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
@ -24,7 +24,7 @@ const EnvironmentSelector = ({collection}) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
|
|
||||||
const onSelect = (environment) => {
|
const onSelect = (environment) => {
|
||||||
dispatch(selectEnvironment(environment ? environment.uid : null, collection.uid))
|
dispatch(selectEnvironment(environment ? environment.uid : null, collection.uid))
|
||||||
@ -35,25 +35,34 @@ const EnvironmentSelector = ({collection}) => {
|
|||||||
toast.success(`No Environments are active now`);
|
toast.success(`No Environments are active now`);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => console.log(err) && toast.error("An error occured while selecting the environment"));
|
.catch((err) => console.log(err) && toast.error('An error occured while selecting the environment'));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="flex items-center cursor-pointer environment-selector">
|
<div className="flex items-center cursor-pointer environment-selector">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||||
{(environments && environments.length) ? environments.map((e) => (
|
{environments && environments.length
|
||||||
<div className="dropdown-item" key={e.uid} onClick={() => {
|
? environments.map((e) => (
|
||||||
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
key={e.uid}
|
||||||
|
onClick={() => {
|
||||||
onSelect(e);
|
onSelect(e);
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<IconDatabase size={18} strokeWidth={1.5} /> <span className="ml-2">{e.name}</span>
|
<IconDatabase size={18} strokeWidth={1.5} /> <span className="ml-2">{e.name}</span>
|
||||||
</div>
|
</div>
|
||||||
)) : null}
|
))
|
||||||
<div className="dropdown-item" onClick={() => {
|
: null}
|
||||||
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onSelect(null);
|
onSelect(null);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<span>No Environment</span>
|
<span>No Environment</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" style={{ borderTop: 'solid 1px #e7e7e7' }} onClick={() => setOpenSettingsModal(true)}>
|
<div className="dropdown-item" style={{ borderTop: 'solid 1px #e7e7e7' }} onClick={() => setOpenSettingsModal(true)}>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import Portal from "components/Portal/index";
|
import Portal from 'components/Portal/index';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { addEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
import { addEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
@ -13,21 +13,18 @@ const CreateEnvironment = ({collection, onClose}) => {
|
|||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name: ""
|
name: ''
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(addEnvironment(values.name, collection.uid))
|
dispatch(addEnvironment(values.name, collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Environment created in collection");
|
toast.success('Environment created in collection');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while created the environment"));
|
.catch(() => toast.error('An error occured while created the environment'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,37 +36,35 @@ const CreateEnvironment = ({collection, onClose}) => {
|
|||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
formik.handleSubmit();
|
formik.handleSubmit();
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<Modal
|
<Modal size="sm" title={'Create Environment'} confirmText="Create" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={"Create Environment"}
|
|
||||||
confirmText='Create'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">Environment Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
Environment Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="environment-name" type="text" name="name"
|
id="environment-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</Portal>
|
</Portal>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default CreateEnvironment;
|
export default CreateEnvironment;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Portal from "components/Portal/index";
|
import Portal from 'components/Portal/index';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import { deleteEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
import { deleteEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
@ -11,29 +11,21 @@ const DeleteEnvironment = ({onClose, environment, collection}) => {
|
|||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
dispatch(deleteEnvironment(environment.uid, collection.uid))
|
dispatch(deleteEnvironment(environment.uid, collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Environment deleted successfully");
|
toast.success('Environment deleted successfully');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while deleting the environment"));
|
.catch(() => toast.error('An error occured while deleting the environment'));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="sm" title={'Delete Environment'} confirmText="Delete" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={"Delete Environment"}
|
|
||||||
confirmText="Delete"
|
|
||||||
handleConfirm={onConfirm}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
Are you sure you want to delete <span className="font-semibold">{environment.name}</span> ?
|
Are you sure you want to delete <span className="font-semibold">{environment.name}</span> ?
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default DeleteEnvironment;
|
export default DeleteEnvironment;
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ const Wrapper = styled.div`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
thead, td {
|
thead,
|
||||||
|
td {
|
||||||
border: 1px solid #efefef;
|
border: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ const Wrapper = styled.div`
|
|||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
@ -35,7 +36,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -10,20 +10,17 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
const EnvironmentVariables = ({ environment, collection }) => {
|
const EnvironmentVariables = ({ environment, collection }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [state, reducerDispatch] = useReducer(reducer, { hasChanges: false, variables: environment.variables || [] });
|
const [state, reducerDispatch] = useReducer(reducer, { hasChanges: false, variables: environment.variables || [] });
|
||||||
const {
|
const { variables, hasChanges } = state;
|
||||||
variables,
|
|
||||||
hasChanges
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
const saveChanges = () => {
|
const saveChanges = () => {
|
||||||
dispatch(saveEnvironment(cloneDeep(variables), environment.uid, collection.uid))
|
dispatch(saveEnvironment(cloneDeep(variables), environment.uid, collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Changes saved successfully");
|
toast.success('Changes saved successfully');
|
||||||
reducerDispatch({
|
reducerDispatch({
|
||||||
type: 'CHANGES_SAVED'
|
type: 'CHANGES_SAVED'
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while saving the changes"));
|
.catch(() => toast.error('An error occured while saving the changes'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const addVariable = () => {
|
const addVariable = () => {
|
||||||
@ -72,13 +69,17 @@ const EnvironmentVariables = ({environment, collection}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{variables && variables.length ? variables.map((variable, index) => {
|
{variables && variables.length
|
||||||
|
? variables.map((variable, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={variable.uid}>
|
<tr key={variable.uid}>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={variable.name}
|
value={variable.name}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleVarChange(e, variable, 'name')}
|
onChange={(e) => handleVarChange(e, variable, 'name')}
|
||||||
@ -87,7 +88,10 @@ const EnvironmentVariables = ({environment, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={variable.value}
|
value={variable.value}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleVarChange(e, variable, 'value')}
|
onChange={(e) => handleVarChange(e, variable, 'value')}
|
||||||
@ -95,12 +99,7 @@ const EnvironmentVariables = ({environment, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input type="checkbox" checked={variable.enabled} className="mr-3 mousetrap" onChange={(e) => handleVarChange(e, variable, 'enabled')} />
|
||||||
type="checkbox"
|
|
||||||
checked={variable.enabled}
|
|
||||||
className="mr-3 mousetrap"
|
|
||||||
onChange={(e) => handleVarChange(e, variable, 'enabled')}
|
|
||||||
/>
|
|
||||||
<button onClick={() => handleRemoveVars(variable)}>
|
<button onClick={() => handleRemoveVars(variable)}>
|
||||||
<IconTrash strokeWidth={1.5} size={20} />
|
<IconTrash strokeWidth={1.5} size={20} />
|
||||||
</button>
|
</button>
|
||||||
@ -108,12 +107,15 @@ const EnvironmentVariables = ({environment, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addVariable}>+ Add Variable</button>
|
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addVariable}>
|
||||||
|
+ Add Variable
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -122,6 +124,6 @@ const EnvironmentVariables = ({environment, collection}) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default EnvironmentVariables;
|
export default EnvironmentVariables;
|
@ -1,8 +1,8 @@
|
|||||||
import React, {useState } from "react";
|
import React, { useState } from 'react';
|
||||||
import { IconEdit, IconTrash, IconDatabase } from "@tabler/icons";
|
import { IconEdit, IconTrash, IconDatabase } from '@tabler/icons';
|
||||||
import EnvironmentVariables from './EnvironmentVariables';
|
import EnvironmentVariables from './EnvironmentVariables';
|
||||||
import RenameEnvironment from "../../RenameEnvironment";
|
import RenameEnvironment from '../../RenameEnvironment';
|
||||||
import DeleteEnvironment from "../../DeleteEnvironment";
|
import DeleteEnvironment from '../../DeleteEnvironment';
|
||||||
|
|
||||||
const EnvironmentDetails = ({ environment, collection }) => {
|
const EnvironmentDetails = ({ environment, collection }) => {
|
||||||
const [openEditModal, setOpenEditModal] = useState(false);
|
const [openEditModal, setOpenEditModal] = useState(false);
|
||||||
@ -28,7 +28,6 @@ const EnvironmentDetails = ({environment, collection}) => {
|
|||||||
<EnvironmentVariables key={environment.uid} environment={environment} collection={collection} />
|
<EnvironmentVariables key={environment.uid} environment={environment} collection={collection} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import styled from "styled-components";
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div`
|
||||||
margin-inline: -1rem;
|
margin-inline: -1rem;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useState, forwardRef, useRef } from "react";
|
import React, { useEffect, useState, forwardRef, useRef } from 'react';
|
||||||
import EnvironmentDetails from "./EnvironmentDetails";
|
import EnvironmentDetails from './EnvironmentDetails';
|
||||||
import CreateEnvironment from "../CreateEnvironment/index";
|
import CreateEnvironment from '../CreateEnvironment/index';
|
||||||
import StyledWrapper from "./StyledWrapper";
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const EnvironmentList = ({ collection }) => {
|
const EnvironmentList = ({ collection }) => {
|
||||||
const { environments } = collection;
|
const { environments } = collection;
|
||||||
@ -22,12 +22,10 @@ const EnvironmentList = ({collection}) => {
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div>
|
<div>
|
||||||
<div className="environments-sidebar">
|
<div className="environments-sidebar">
|
||||||
{environments && environments.length && environments.map((env) => (
|
{environments &&
|
||||||
<div
|
environments.length &&
|
||||||
key={env.uid}
|
environments.map((env) => (
|
||||||
className={selectedEnvironment.uid === env.uid ? "environment-item active": "environment-item"}
|
<div key={env.uid} className={selectedEnvironment.uid === env.uid ? 'environment-item active' : 'environment-item'} onClick={() => setSelectedEnvironment(env)}>
|
||||||
onClick={() => setSelectedEnvironment(env)}
|
|
||||||
>
|
|
||||||
<span>{env.name}</span>
|
<span>{env.name}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import Portal from "components/Portal/index";
|
import Portal from 'components/Portal/index';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { renameEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
import { renameEnvironment } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
@ -16,18 +16,15 @@ const RenameEnvironment = ({onClose, environment, collection}) => {
|
|||||||
name: environment.name
|
name: environment.name
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(renameEnvironment(values.name, environment.uid, collection.uid))
|
dispatch(renameEnvironment(values.name, environment.uid, collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Environment renamed successfully");
|
toast.success('Environment renamed successfully');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while renaming the environment"));
|
.catch(() => toast.error('An error occured while renaming the environment'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,37 +36,35 @@ const RenameEnvironment = ({onClose, environment, collection}) => {
|
|||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
formik.handleSubmit();
|
formik.handleSubmit();
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<Modal
|
<Modal size="sm" title={'Rename Environment'} confirmText="Rename" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={"Rename Environment"}
|
|
||||||
confirmText='Rename'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">Environment Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
Environment Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="environment-name" type="text" name="name"
|
id="environment-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</Portal>
|
</Portal>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default RenameEnvironment;
|
export default RenameEnvironment;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import styled from "styled-components";
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div`
|
||||||
button.btn-create-environment {
|
button.btn-create-environment {
|
||||||
|
@ -1,50 +1,34 @@
|
|||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react';
|
||||||
import CreateEnvironment from "./CreateEnvironment";
|
import CreateEnvironment from './CreateEnvironment';
|
||||||
import EnvironmentList from "./EnvironmentList";
|
import EnvironmentList from './EnvironmentList';
|
||||||
import StyledWrapper from "./StyledWrapper";
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const EnvironmentSettings = ({ collection, onClose }) => {
|
const EnvironmentSettings = ({ collection, onClose }) => {
|
||||||
const { environments } = collection;
|
const { environments } = collection;
|
||||||
const [openCreateModal, setOpenCreateModal] = useState(false)
|
const [openCreateModal, setOpenCreateModal] = useState(false);
|
||||||
|
|
||||||
if (!environments || !environments.length) {
|
if (!environments || !environments.length) {
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="md" title="Environments" confirmText={'Close'} handleConfirm={onClose} handleCancel={onClose} hideCancel={true}>
|
||||||
size="md"
|
|
||||||
title="Environments"
|
|
||||||
confirmText={"Close"}
|
|
||||||
handleConfirm={onClose}
|
|
||||||
handleCancel={onClose}
|
|
||||||
hideCancel={true}
|
|
||||||
>
|
|
||||||
{openCreateModal && <CreateEnvironment collection={collection} onClose={() => setOpenCreateModal(false)} />}
|
{openCreateModal && <CreateEnvironment collection={collection} onClose={() => setOpenCreateModal(false)} />}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p>No environments found!</p>
|
<p>No environments found!</p>
|
||||||
<button
|
<button className="btn-create-environment text-link pr-2 py-3 mt-2 select-none" onClick={() => setOpenCreateModal(true)}>
|
||||||
className="btn-create-environment text-link pr-2 py-3 mt-2 select-none"
|
|
||||||
onClick={() => setOpenCreateModal(true)}
|
|
||||||
>
|
|
||||||
+ <span>Create Environment</span>
|
+ <span>Create Environment</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="lg" title="Environments" handleCancel={onClose} hideFooter={true}>
|
||||||
size="lg"
|
|
||||||
title="Environments"
|
|
||||||
handleCancel={onClose}
|
|
||||||
hideFooter={true}
|
|
||||||
>
|
|
||||||
<EnvironmentList collection={collection} />
|
<EnvironmentList collection={collection} />
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default EnvironmentSettings;
|
export default EnvironmentSettings;
|
||||||
|
@ -2,10 +2,10 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
&.modal--animate-out {
|
&.modal--animate-out {
|
||||||
animation: fade-out 0.5s forwards cubic-bezier(.19,1,.22,1);
|
animation: fade-out 0.5s forwards cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
|
|
||||||
.bruno-modal-card {
|
.bruno-modal-card {
|
||||||
animation: fade-and-slide-out-from-top .50s forwards cubic-bezier(.19,1,.22,1);
|
animation: fade-and-slide-out-from-top 0.5s forwards cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,8 +23,8 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bruno-modal-card {
|
.bruno-modal-card {
|
||||||
animation-duration: .85s;
|
animation-duration: 0.85s;
|
||||||
animation-delay: .1s;
|
animation-delay: 0.1s;
|
||||||
background: var(--color-background-top);
|
background: var(--color-background-top);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -58,7 +58,7 @@ const Wrapper = styled.div`
|
|||||||
max-width: calc(100% - 30px);
|
max-width: calc(100% - 30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
animation: fade-and-slide-in-from-top .50s forwards cubic-bezier(.19,1,.22,1);
|
animation: fade-and-slide-in-from-top 0.5s forwards cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bruno-modal-header {
|
.bruno-modal-header {
|
||||||
@ -103,17 +103,17 @@ const Wrapper = styled.div`
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: '';
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: .4;
|
opacity: 0.4;
|
||||||
top: 0;
|
top: 0;
|
||||||
background: black;
|
background: black;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
animation: fade-in .1s forwards cubic-bezier(.19,1,.22,1);
|
animation: fade-in 0.1s forwards cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bruno-modal-footer {
|
.bruno-modal-footer {
|
||||||
|
@ -12,11 +12,7 @@ const ModalHeader = ({title, handleCancel}) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ModalContent = ({children}) => (
|
const ModalContent = ({ children }) => <div className="bruno-modal-content px-4 py-6">{children}</div>;
|
||||||
<div className="bruno-modal-content px-4 py-6">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const ModalFooter = ({ confirmText, cancelText, handleSubmit, handleCancel, confirmDisabled, hideCancel, hideFooter }) => {
|
const ModalFooter = ({ confirmText, cancelText, handleSubmit, handleCancel, confirmDisabled, hideCancel, hideFooter }) => {
|
||||||
confirmText = confirmText || 'Save';
|
confirmText = confirmText || 'Save';
|
||||||
@ -28,7 +24,7 @@ const ModalFooter = ({confirmText, cancelText, handleSubmit, handleCancel, confi
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-end p-4 bruno-modal-footer">
|
<div className="flex justify-end p-4 bruno-modal-footer">
|
||||||
<span className={hideCancel ? "hidden" : "mr-2"}>
|
<span className={hideCancel ? 'hidden' : 'mr-2'}>
|
||||||
<button type="button" onClick={handleCancel} className="btn btn-md btn-close">
|
<button type="button" onClick={handleCancel} className="btn btn-md btn-close">
|
||||||
{cancelText}
|
{cancelText}
|
||||||
</button>
|
</button>
|
||||||
@ -40,20 +36,9 @@ const ModalFooter = ({confirmText, cancelText, handleSubmit, handleCancel, confi
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const Modal = ({
|
const Modal = ({ size, title, confirmText, cancelText, handleCancel, handleConfirm, children, confirmDisabled, hideCancel, hideFooter }) => {
|
||||||
size,
|
|
||||||
title,
|
|
||||||
confirmText,
|
|
||||||
cancelText,
|
|
||||||
handleCancel,
|
|
||||||
handleConfirm,
|
|
||||||
children,
|
|
||||||
confirmDisabled,
|
|
||||||
hideCancel,
|
|
||||||
hideFooter
|
|
||||||
}) => {
|
|
||||||
const [isClosing, setIsClosing] = useState(false);
|
const [isClosing, setIsClosing] = useState(false);
|
||||||
const escFunction = (event) => {
|
const escFunction = (event) => {
|
||||||
const escKeyCode = 27;
|
const escKeyCode = 27;
|
||||||
@ -72,7 +57,7 @@ const Modal = ({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', escFunction, false);
|
document.removeEventListener('keydown', escFunction, false);
|
||||||
}
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
let classes = 'bruno-modal';
|
let classes = 'bruno-modal';
|
||||||
|
@ -14,7 +14,6 @@ const StyledWrapper = styled.div`
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, forwardRef, useRef } from 'react';
|
import React, { useState, forwardRef, useRef } from 'react';
|
||||||
import Dropdown from '../Dropdown';
|
import Dropdown from '../Dropdown';
|
||||||
import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
|
import { faCaretDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { IconBox, IconSearch, IconDots } from '@tabler/icons';
|
import { IconBox, IconSearch, IconDots } from '@tabler/icons';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ const Navbar = () => {
|
|||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
|
||||||
const menuDropdownTippyRef = useRef();
|
const menuDropdownTippyRef = useRef();
|
||||||
const onMenuDropdownCreate = (ref) => menuDropdownTippyRef.current = ref;
|
const onMenuDropdownCreate = (ref) => (menuDropdownTippyRef.current = ref);
|
||||||
const MenuIcon = forwardRef((props, ref) => {
|
const MenuIcon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="dropdown-icon cursor-pointer">
|
<div ref={ref} className="dropdown-icon cursor-pointer">
|
||||||
@ -25,27 +25,36 @@ const Navbar = () => {
|
|||||||
{/* <FontAwesomeIcon className="ml-2" icon={faCaretDown} style={{fontSize: 13}}/> */}
|
{/* <FontAwesomeIcon className="ml-2" icon={faCaretDown} style={{fontSize: 13}}/> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
||||||
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement='bottom-start'>
|
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Create Collection
|
Create Collection
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Import Collection
|
Import Collection
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Settings
|
Settings
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Navbar;
|
export default Navbar;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
|
|
||||||
function Portal({ children, wrapperId }) {
|
function Portal({ children, wrapperId }) {
|
||||||
wrapperId = wrapperId || "bruno-app-body";
|
wrapperId = wrapperId || 'bruno-app-body';
|
||||||
|
|
||||||
return createPortal(children, document.getElementById(wrapperId));
|
return createPortal(children, document.getElementById(wrapperId));
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@ const Wrapper = styled.div`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
thead, td {
|
thead,
|
||||||
|
td {
|
||||||
border: 1px solid #efefef;
|
border: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ const Wrapper = styled.div`
|
|||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
@ -35,7 +36,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -11,10 +11,12 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
const params = item.draft ? get(item, 'draft.request.body.formUrlEncoded') : get(item, 'request.body.formUrlEncoded');
|
const params = item.draft ? get(item, 'draft.request.body.formUrlEncoded') : get(item, 'request.body.formUrlEncoded');
|
||||||
|
|
||||||
const addParam = () => {
|
const addParam = () => {
|
||||||
dispatch(addFormUrlEncodedParam({
|
dispatch(
|
||||||
|
addFormUrlEncodedParam({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleParamChange = (e, _param, type) => {
|
const handleParamChange = (e, _param, type) => {
|
||||||
@ -37,19 +39,23 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch(updateFormUrlEncodedParam({
|
dispatch(
|
||||||
|
updateFormUrlEncodedParam({
|
||||||
param: param,
|
param: param,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveParams = (param) => {
|
const handleRemoveParams = (param) => {
|
||||||
dispatch(deleteFormUrlEncodedParam({
|
dispatch(
|
||||||
|
deleteFormUrlEncodedParam({
|
||||||
paramUid: param.uid,
|
paramUid: param.uid,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -64,13 +70,17 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{params && params.length ? params.map((param, index) => {
|
{params && params.length
|
||||||
|
? params.map((param, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={param.uid}>
|
<tr key={param.uid}>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.name}
|
value={param.name}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'name')}
|
onChange={(e) => handleParamChange(e, param, 'name')}
|
||||||
@ -79,7 +89,10 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.value}
|
value={param.value}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'value')}
|
onChange={(e) => handleParamChange(e, param, 'value')}
|
||||||
@ -88,7 +101,10 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.description}
|
value={param.description}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'description')}
|
onChange={(e) => handleParamChange(e, param, 'description')}
|
||||||
@ -96,12 +112,7 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input type="checkbox" checked={param.enabled} className="mr-3 mousetrap" onChange={(e) => handleParamChange(e, param, 'enabled')} />
|
||||||
type="checkbox"
|
|
||||||
checked={param.enabled}
|
|
||||||
className="mr-3 mousetrap"
|
|
||||||
onChange={(e) => handleParamChange(e, param, 'enabled')}
|
|
||||||
/>
|
|
||||||
<button onClick={() => handleRemoveParams(param)}>
|
<button onClick={() => handleRemoveParams(param)}>
|
||||||
<IconTrash strokeWidth={1.5} size={20} />
|
<IconTrash strokeWidth={1.5} size={20} />
|
||||||
</button>
|
</button>
|
||||||
@ -109,11 +120,14 @@ const FormUrlEncodedParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addParam}>+ Add Param</button>
|
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addParam}>
|
||||||
|
+ Add Param
|
||||||
|
</button>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default FormUrlEncodedParams;
|
export default FormUrlEncodedParams;
|
@ -18,7 +18,11 @@ const StyledWrapper = styled.div`
|
|||||||
color: rgb(125 125 125);
|
color: rgb(125 125 125);
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
|
|
||||||
&:focus, &:active, &:focus-within, &:focus-visible, &:target {
|
&:focus,
|
||||||
|
&:active,
|
||||||
|
&:focus-within,
|
||||||
|
&:focus-visible,
|
||||||
|
&:target {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
@ -38,7 +42,11 @@ const StyledWrapper = styled.div`
|
|||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
|
||||||
&:focus, &:active, &:focus-within, &:focus-visible, &:target {
|
&:focus,
|
||||||
|
&:active,
|
||||||
|
&:focus-within,
|
||||||
|
&:focus-visible,
|
||||||
|
&:target {
|
||||||
border: none;
|
border: none;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
@ -49,7 +57,6 @@ const StyledWrapper = styled.div`
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
@ -7,20 +7,14 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
const GraphQLRequestPane = ({ onRunQuery, schema, leftPaneWidth, value, onQueryChange }) => {
|
const GraphQLRequestPane = ({ onRunQuery, schema, leftPaneWidth, value, onQueryChange }) => {
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="h-full">
|
<StyledWrapper className="h-full">
|
||||||
<Tabs className='react-tabs mt-1 flex flex-grow flex-col h-full' forceRenderTabPanel>
|
<Tabs className="react-tabs mt-1 flex flex-grow flex-col h-full" forceRenderTabPanel>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab tabIndex="-1">Query</Tab>
|
<Tab tabIndex="-1">Query</Tab>
|
||||||
<Tab tabIndex="-1">Headers</Tab>
|
<Tab tabIndex="-1">Headers</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<QueryEditor
|
<QueryEditor schema={schema} width={leftPaneWidth} value={value} onRunQuery={onRunQuery} onEdit={onQueryChange} />
|
||||||
schema={schema}
|
|
||||||
width={leftPaneWidth}
|
|
||||||
value={value}
|
|
||||||
onRunQuery={onRunQuery}
|
|
||||||
onEdit={onQueryChange}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
@ -28,7 +22,7 @@ const GraphQLRequestPane = ({onRunQuery, schema, leftPaneWidth, value, onQueryCh
|
|||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GraphQLRequestPane;
|
export default GraphQLRequestPane;
|
||||||
|
@ -10,7 +10,11 @@ const StyledWrapper = styled.div`
|
|||||||
color: var(--color-tab-inactive);
|
color: var(--color-tab-inactive);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:focus, &:active, &:focus-within, &:focus-visible, &:target {
|
&:focus,
|
||||||
|
&:active,
|
||||||
|
&:focus-within,
|
||||||
|
&:focus-visible,
|
||||||
|
&:target {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,12 @@ const HttpRequestPane = ({item, collection, leftPaneWidth}) => {
|
|||||||
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
||||||
|
|
||||||
const selectTab = (tab) => {
|
const selectTab = (tab) => {
|
||||||
dispatch(updateRequestPaneTab({
|
dispatch(
|
||||||
|
updateRequestPaneTab({
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
requestPaneTab: tab
|
requestPaneTab: tab
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTabPanel = (tab) => {
|
const getTabPanel = (tab) => {
|
||||||
@ -36,33 +38,35 @@ const HttpRequestPane = ({item, collection, leftPaneWidth}) => {
|
|||||||
return <div className="mt-4">404 | Not found</div>;
|
return <div className="mt-4">404 | Not found</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if (!activeTabUid) {
|
if (!activeTabUid) {
|
||||||
return (
|
return <div>Something went wrong</div>;
|
||||||
<div>Something went wrong</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||||
if (!focusedTab || !focusedTab.uid || !focusedTab.requestPaneTab) {
|
if (!focusedTab || !focusedTab.uid || !focusedTab.requestPaneTab) {
|
||||||
return (
|
return <div className="pb-4 px-4">An error occured!</div>;
|
||||||
<div className="pb-4 px-4">An error occured!</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTabClassname = (tabName) => {
|
const getTabClassname = (tabName) => {
|
||||||
return classnames(`tab select-none ${tabName}`, {
|
return classnames(`tab select-none ${tabName}`, {
|
||||||
'active': tabName === focusedTab.requestPaneTab
|
active: tabName === focusedTab.requestPaneTab
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="flex flex-col h-full relative">
|
<StyledWrapper className="flex flex-col h-full relative">
|
||||||
<div className="flex items-center tabs" role="tablist">
|
<div className="flex items-center tabs" role="tablist">
|
||||||
<div className={getTabClassname('params')} role="tab" onClick={() => selectTab('params')}>Params</div>
|
<div className={getTabClassname('params')} role="tab" onClick={() => selectTab('params')}>
|
||||||
<div className={getTabClassname('body')} role="tab" onClick={() => selectTab('body')}>Body</div>
|
Params
|
||||||
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>Headers</div>
|
</div>
|
||||||
|
<div className={getTabClassname('body')} role="tab" onClick={() => selectTab('body')}>
|
||||||
|
Body
|
||||||
|
</div>
|
||||||
|
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
|
||||||
|
Headers
|
||||||
|
</div>
|
||||||
{/* Moved to post mvp */}
|
{/* Moved to post mvp */}
|
||||||
{/* <div className={getTabClassname('auth')} role="tab" onClick={() => selectTab('auth')}>Auth</div> */}
|
{/* <div className={getTabClassname('auth')} role="tab" onClick={() => selectTab('auth')}>Auth</div> */}
|
||||||
{focusedTab.requestPaneTab === 'body' ? (
|
{focusedTab.requestPaneTab === 'body' ? (
|
||||||
@ -71,11 +75,9 @@ const HttpRequestPane = ({item, collection, leftPaneWidth}) => {
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<section className="flex w-full mt-5">
|
<section className="flex w-full mt-5">{getTabPanel(focusedTab.requestPaneTab)}</section>
|
||||||
{getTabPanel(focusedTab.requestPaneTab)}
|
|
||||||
</section>
|
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HttpRequestPane;
|
export default HttpRequestPane;
|
||||||
|
@ -6,7 +6,8 @@ const Wrapper = styled.div`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
thead, td {
|
thead,
|
||||||
|
td {
|
||||||
border: 1px solid #efefef;
|
border: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ const Wrapper = styled.div`
|
|||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
@ -35,7 +36,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -11,10 +11,12 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
const params = item.draft ? get(item, 'draft.request.body.multipartForm') : get(item, 'request.body.multipartForm');
|
const params = item.draft ? get(item, 'draft.request.body.multipartForm') : get(item, 'request.body.multipartForm');
|
||||||
|
|
||||||
const addParam = () => {
|
const addParam = () => {
|
||||||
dispatch(addMultipartFormParam({
|
dispatch(
|
||||||
|
addMultipartFormParam({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleParamChange = (e, _param, type) => {
|
const handleParamChange = (e, _param, type) => {
|
||||||
@ -37,19 +39,23 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch(updateMultipartFormParam({
|
dispatch(
|
||||||
|
updateMultipartFormParam({
|
||||||
param: param,
|
param: param,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveParams = (param) => {
|
const handleRemoveParams = (param) => {
|
||||||
dispatch(deleteMultipartFormParam({
|
dispatch(
|
||||||
|
deleteMultipartFormParam({
|
||||||
paramUid: param.uid,
|
paramUid: param.uid,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -64,13 +70,17 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{params && params.length ? params.map((param, index) => {
|
{params && params.length
|
||||||
|
? params.map((param, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={param.uid}>
|
<tr key={param.uid}>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.name}
|
value={param.name}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'name')}
|
onChange={(e) => handleParamChange(e, param, 'name')}
|
||||||
@ -79,7 +89,10 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.value}
|
value={param.value}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'value')}
|
onChange={(e) => handleParamChange(e, param, 'value')}
|
||||||
@ -88,7 +101,10 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.description}
|
value={param.description}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'description')}
|
onChange={(e) => handleParamChange(e, param, 'description')}
|
||||||
@ -96,12 +112,7 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input type="checkbox" checked={param.enabled} className="mr-3 mousetrap" onChange={(e) => handleParamChange(e, param, 'enabled')} />
|
||||||
type="checkbox"
|
|
||||||
checked={param.enabled}
|
|
||||||
className="mr-3 mousetrap"
|
|
||||||
onChange={(e) => handleParamChange(e, param, 'enabled')}
|
|
||||||
/>
|
|
||||||
<button onClick={() => handleRemoveParams(param)}>
|
<button onClick={() => handleRemoveParams(param)}>
|
||||||
<IconTrash strokeWidth={1.5} size={20} />
|
<IconTrash strokeWidth={1.5} size={20} />
|
||||||
</button>
|
</button>
|
||||||
@ -109,11 +120,14 @@ const MultipartFormParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addParam}>+ Add Param</button>
|
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={addParam}>
|
||||||
|
+ Add Param
|
||||||
|
</button>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default MultipartFormParams;
|
export default MultipartFormParams;
|
@ -13,4 +13,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -44,44 +44,37 @@ export default class QueryEditor extends React.Component {
|
|||||||
showCursorWhenSelecting: true,
|
showCursorWhenSelecting: true,
|
||||||
readOnly: this.props.readOnly ? 'nocursor' : false,
|
readOnly: this.props.readOnly ? 'nocursor' : false,
|
||||||
foldGutter: {
|
foldGutter: {
|
||||||
minFoldSize: 4,
|
minFoldSize: 4
|
||||||
},
|
},
|
||||||
lint: {
|
lint: {
|
||||||
schema: this.props.schema,
|
schema: this.props.schema,
|
||||||
validationRules: this.props.validationRules ?? null,
|
validationRules: this.props.validationRules ?? null,
|
||||||
// linting accepts string or FragmentDefinitionNode[]
|
// linting accepts string or FragmentDefinitionNode[]
|
||||||
externalFragments: this.props?.externalFragments,
|
externalFragments: this.props?.externalFragments
|
||||||
},
|
},
|
||||||
hintOptions: {
|
hintOptions: {
|
||||||
schema: this.props.schema,
|
schema: this.props.schema,
|
||||||
closeOnUnfocus: false,
|
closeOnUnfocus: false,
|
||||||
completeSingle: false,
|
completeSingle: false,
|
||||||
container: this._node,
|
container: this._node,
|
||||||
externalFragments: this.props?.externalFragments,
|
externalFragments: this.props?.externalFragments
|
||||||
},
|
},
|
||||||
info: {
|
info: {
|
||||||
schema: this.props.schema,
|
schema: this.props.schema,
|
||||||
renderDescription: (text) => md.render(text),
|
renderDescription: (text) => md.render(text),
|
||||||
onClick: (reference) =>
|
onClick: (reference) => this.props.onClickReference && this.props.onClickReference(reference)
|
||||||
this.props.onClickReference && this.props.onClickReference(reference),
|
|
||||||
},
|
},
|
||||||
jump: {
|
jump: {
|
||||||
schema: this.props.schema,
|
schema: this.props.schema,
|
||||||
onClick: (reference) =>
|
onClick: (reference) => this.props.onClickReference && this.props.onClickReference(reference)
|
||||||
this.props.onClickReference && this.props.onClickReference(reference)
|
|
||||||
},
|
},
|
||||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
'Cmd-Space': () =>
|
'Cmd-Space': () => editor.showHint({ completeSingle: true, container: this._node }),
|
||||||
editor.showHint({ completeSingle: true, container: this._node }),
|
'Ctrl-Space': () => editor.showHint({ completeSingle: true, container: this._node }),
|
||||||
'Ctrl-Space': () =>
|
'Alt-Space': () => editor.showHint({ completeSingle: true, container: this._node }),
|
||||||
editor.showHint({ completeSingle: true, container: this._node }),
|
'Shift-Space': () => editor.showHint({ completeSingle: true, container: this._node }),
|
||||||
'Alt-Space': () =>
|
'Shift-Alt-Space': () => editor.showHint({ completeSingle: true, container: this._node }),
|
||||||
editor.showHint({ completeSingle: true, container: this._node }),
|
|
||||||
'Shift-Space': () =>
|
|
||||||
editor.showHint({ completeSingle: true, container: this._node }),
|
|
||||||
'Shift-Alt-Space': () =>
|
|
||||||
editor.showHint({ completeSingle: true, container: this._node }),
|
|
||||||
|
|
||||||
'Cmd-Enter': () => {
|
'Cmd-Enter': () => {
|
||||||
if (this.props.onRunQuery) {
|
if (this.props.onRunQuery) {
|
||||||
@ -129,8 +122,8 @@ export default class QueryEditor extends React.Component {
|
|||||||
if (this.props.onRunQuery) {
|
if (this.props.onRunQuery) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
}));
|
}));
|
||||||
if (editor) {
|
if (editor) {
|
||||||
editor.on('change', this._onEdit);
|
editor.on('change', this._onEdit);
|
||||||
@ -152,11 +145,7 @@ export default class QueryEditor extends React.Component {
|
|||||||
this.editor.options.jump.schema = this.props.schema;
|
this.editor.options.jump.schema = this.props.schema;
|
||||||
CodeMirror.signal(this.editor, 'change', this.editor);
|
CodeMirror.signal(this.editor, 'change', this.editor);
|
||||||
}
|
}
|
||||||
if (
|
if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) {
|
||||||
this.props.value !== prevProps.value &&
|
|
||||||
this.props.value !== this.cachedValue &&
|
|
||||||
this.editor
|
|
||||||
) {
|
|
||||||
this.cachedValue = this.props.value;
|
this.cachedValue = this.props.value;
|
||||||
this.editor.setValue(this.props.value);
|
this.editor.setValue(this.props.value);
|
||||||
}
|
}
|
||||||
@ -177,7 +166,7 @@ export default class QueryEditor extends React.Component {
|
|||||||
<StyledWrapper
|
<StyledWrapper
|
||||||
className="h-full"
|
className="h-full"
|
||||||
aria-label="Query Editor"
|
aria-label="Query Editor"
|
||||||
ref={node => {
|
ref={(node) => {
|
||||||
this._node = node;
|
this._node = node;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -7,10 +7,7 @@
|
|||||||
import escapeHTML from 'escape-html';
|
import escapeHTML from 'escape-html';
|
||||||
import MD from 'markdown-it';
|
import MD from 'markdown-it';
|
||||||
|
|
||||||
import {
|
import { GraphQLNonNull, GraphQLList } from 'graphql';
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLList
|
|
||||||
} from 'graphql';
|
|
||||||
|
|
||||||
const md = new MD();
|
const md = new MD();
|
||||||
|
|
||||||
@ -18,21 +15,14 @@ const md = new MD();
|
|||||||
* Render a custom UI for CodeMirror's hint which includes additional info
|
* Render a custom UI for CodeMirror's hint which includes additional info
|
||||||
* about the type and description for the selected context.
|
* about the type and description for the selected context.
|
||||||
*/
|
*/
|
||||||
export default function onHasCompletion(
|
export default function onHasCompletion(_cm, data, onHintInformationRender) {
|
||||||
_cm,
|
|
||||||
data,
|
|
||||||
onHintInformationRender,
|
|
||||||
) {
|
|
||||||
const CodeMirror = require('codemirror');
|
const CodeMirror = require('codemirror');
|
||||||
|
|
||||||
let information;
|
let information;
|
||||||
let deprecation;
|
let deprecation;
|
||||||
|
|
||||||
// When a hint result is selected, we augment the UI with information.
|
// When a hint result is selected, we augment the UI with information.
|
||||||
CodeMirror.on(
|
CodeMirror.on(data, 'select', (ctx, el) => {
|
||||||
data,
|
|
||||||
'select',
|
|
||||||
(ctx, el) => {
|
|
||||||
// Only the first time (usually when the hint UI is first displayed)
|
// Only the first time (usually when the hint UI is first displayed)
|
||||||
// do we create the information nodes.
|
// do we create the information nodes.
|
||||||
if (!information) {
|
if (!information) {
|
||||||
@ -61,31 +51,19 @@ export default function onHasCompletion(
|
|||||||
deprecation = null;
|
deprecation = null;
|
||||||
onRemoveFn = null;
|
onRemoveFn = null;
|
||||||
}
|
}
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the UI has been set up, add info to information.
|
// Now that the UI has been set up, add info to information.
|
||||||
const description = ctx.description
|
const description = ctx.description ? md.render(ctx.description) : 'Self descriptive.';
|
||||||
? md.render(ctx.description)
|
const type = ctx.type ? '<span className="infoType">' + renderType(ctx.type) + '</span>' : '';
|
||||||
: 'Self descriptive.';
|
|
||||||
const type = ctx.type
|
|
||||||
? '<span className="infoType">' + renderType(ctx.type) + '</span>'
|
|
||||||
: '';
|
|
||||||
|
|
||||||
information.innerHTML =
|
information.innerHTML = '<div className="content">' + (description.slice(0, 3) === '<p>' ? '<p>' + type + description.slice(3) : type + description) + '</div>';
|
||||||
'<div className="content">' +
|
|
||||||
(description.slice(0, 3) === '<p>'
|
|
||||||
? '<p>' + type + description.slice(3)
|
|
||||||
: type + description) +
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
if (ctx && deprecation && ctx.deprecationReason) {
|
if (ctx && deprecation && ctx.deprecationReason) {
|
||||||
const reason = ctx.deprecationReason
|
const reason = ctx.deprecationReason ? md.render(ctx.deprecationReason) : '';
|
||||||
? md.render(ctx.deprecationReason)
|
deprecation.innerHTML = '<span className="deprecation-label">Deprecated</span>' + reason;
|
||||||
: '';
|
|
||||||
deprecation.innerHTML =
|
|
||||||
'<span className="deprecation-label">Deprecated</span>' + reason;
|
|
||||||
deprecation.style.display = 'block';
|
deprecation.style.display = 'block';
|
||||||
} else if (deprecation) {
|
} else if (deprecation) {
|
||||||
deprecation.style.display = 'none';
|
deprecation.style.display = 'none';
|
||||||
@ -95,8 +73,7 @@ export default function onHasCompletion(
|
|||||||
if (onHintInformationRender) {
|
if (onHintInformationRender) {
|
||||||
onHintInformationRender(information);
|
onHintInformationRender(information);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderType(type) {
|
function renderType(type) {
|
||||||
|
@ -6,7 +6,8 @@ const Wrapper = styled.div`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
thead, td {
|
thead,
|
||||||
|
td {
|
||||||
border: 1px solid #efefef;
|
border: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
@ -38,7 +39,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -12,10 +12,12 @@ const QueryParams = ({item, collection}) => {
|
|||||||
const params = item.draft ? get(item, 'draft.request.params') : get(item, 'request.params');
|
const params = item.draft ? get(item, 'draft.request.params') : get(item, 'request.params');
|
||||||
|
|
||||||
const handleAddParam = () => {
|
const handleAddParam = () => {
|
||||||
dispatch(addQueryParam({
|
dispatch(
|
||||||
|
addQueryParam({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleParamChange = (e, _param, type) => {
|
const handleParamChange = (e, _param, type) => {
|
||||||
@ -40,19 +42,23 @@ const QueryParams = ({item, collection}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(updateQueryParam({
|
dispatch(
|
||||||
|
updateQueryParam({
|
||||||
param,
|
param,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveParam = (param) => {
|
const handleRemoveParam = (param) => {
|
||||||
dispatch(deleteQueryParam({
|
dispatch(
|
||||||
|
deleteQueryParam({
|
||||||
paramUid: param.uid,
|
paramUid: param.uid,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -67,13 +73,17 @@ const QueryParams = ({item, collection}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{params && params.length ? params.map((param, index) => {
|
{params && params.length
|
||||||
|
? params.map((param, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={param.uid}>
|
<tr key={param.uid}>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.name}
|
value={param.name}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'name')}
|
onChange={(e) => handleParamChange(e, param, 'name')}
|
||||||
@ -82,7 +92,10 @@ const QueryParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.value}
|
value={param.value}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'value')}
|
onChange={(e) => handleParamChange(e, param, 'value')}
|
||||||
@ -91,7 +104,10 @@ const QueryParams = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={param.description}
|
value={param.description}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleParamChange(e, param, 'description')}
|
onChange={(e) => handleParamChange(e, param, 'description')}
|
||||||
@ -99,12 +115,7 @@ const QueryParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input type="checkbox" checked={param.enabled} className="mr-3 mousetrap" onChange={(e) => handleParamChange(e, param, 'enabled')} />
|
||||||
type="checkbox"
|
|
||||||
checked={param.enabled}
|
|
||||||
className="mr-3 mousetrap"
|
|
||||||
onChange={(e) => handleParamChange(e, param, 'enabled')}
|
|
||||||
/>
|
|
||||||
<button onClick={() => handleRemoveParam(param)}>
|
<button onClick={() => handleRemoveParam(param)}>
|
||||||
<IconTrash strokeWidth={1.5} size={20} />
|
<IconTrash strokeWidth={1.5} size={20} />
|
||||||
</button>
|
</button>
|
||||||
@ -112,13 +123,14 @@ const QueryParams = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={handleAddParam}>
|
<button className="btn-add-param text-link pr-2 py-3 mt-2 select-none" onClick={handleAddParam}>
|
||||||
+ <span>Add Param</span>
|
+ <span>Add Param</span>
|
||||||
</button>
|
</button>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default QueryParams;
|
export default QueryParams;
|
@ -17,7 +17,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
padding: .25rem .6rem !important;
|
padding: 0.25rem 0.6rem !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,15 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
|
|
||||||
const HttpMethodSelector = ({ method, onMethodSelect }) => {
|
const HttpMethodSelector = ({ method, onMethodSelect }) => {
|
||||||
const dropdownTippyRef = useRef();
|
const dropdownTippyRef = useRef();
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
|
|
||||||
const Icon = forwardRef((props, ref) => {
|
const Icon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="flex w-full items-center pl-3 py-1 select-none uppercase">
|
<div ref={ref} className="flex w-full items-center pl-3 py-1 select-none uppercase">
|
||||||
<div className="flex-grow font-medium">{method}</div>
|
<div className="flex-grow font-medium">{method}</div>
|
||||||
<div><IconCaretDown className="caret ml-2 mr-2" size={14} strokeWidth={2}/></div>
|
<div>
|
||||||
|
<IconCaretDown className="caret ml-2 mr-2" size={14} strokeWidth={2} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -20,10 +22,13 @@ const HttpMethodSelector = ({method, onMethodSelect}) => {
|
|||||||
|
|
||||||
const Verb = ({ verb }) => {
|
const Verb = ({ verb }) => {
|
||||||
return (
|
return (
|
||||||
<div className="dropdown-item" onClick={() => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
handleMethodSelect(verb);
|
handleMethodSelect(verb);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{verb}
|
{verb}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -32,14 +37,14 @@ const HttpMethodSelector = ({method, onMethodSelect}) => {
|
|||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="flex items-center cursor-pointer method-selector">
|
<div className="flex items-center cursor-pointer method-selector">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-start'>
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-start">
|
||||||
<Verb verb='GET' />
|
<Verb verb="GET" />
|
||||||
<Verb verb='POST' />
|
<Verb verb="POST" />
|
||||||
<Verb verb='PUT' />
|
<Verb verb="PUT" />
|
||||||
<Verb verb='DELETE' />
|
<Verb verb="DELETE" />
|
||||||
<Verb verb='PATCH' />
|
<Verb verb="PATCH" />
|
||||||
<Verb verb='OPTIONS' />
|
<Verb verb="OPTIONS" />
|
||||||
<Verb verb='HEAD' />
|
<Verb verb="HEAD" />
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -12,19 +12,23 @@ const QueryUrl = ({item, collection, handleRun}) => {
|
|||||||
let url = item.draft ? get(item, 'draft.request.url') : get(item, 'request.url');
|
let url = item.draft ? get(item, 'draft.request.url') : get(item, 'request.url');
|
||||||
|
|
||||||
const onUrlChange = (value) => {
|
const onUrlChange = (value) => {
|
||||||
dispatch(requestUrlChanged({
|
dispatch(
|
||||||
|
requestUrlChanged({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid,
|
||||||
url: value
|
url: value
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMethodSelect = (verb) => {
|
const onMethodSelect = (verb) => {
|
||||||
dispatch(updateRequestMethod({
|
dispatch(
|
||||||
|
updateRequestMethod({
|
||||||
method: verb,
|
method: verb,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -35,8 +39,12 @@ const QueryUrl = ({item, collection, handleRun}) => {
|
|||||||
<div className="flex items-center flex-grow input-container h-full">
|
<div className="flex items-center flex-grow input-container h-full">
|
||||||
<input
|
<input
|
||||||
className="px-3 w-full mousetrap"
|
className="px-3 w-full mousetrap"
|
||||||
type="text" value={url}
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
value={url}
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={(event) => onUrlChange(event.target.value)}
|
onChange={(event) => onUrlChange(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center h-full mr-2 cursor-pointer" onClick={handleRun}>
|
<div className="flex items-center h-full mr-2 cursor-pointer" onClick={handleRun}>
|
||||||
@ -44,7 +52,7 @@ const QueryUrl = ({item, collection, handleRun}) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QueryUrl;
|
export default QueryUrl;
|
||||||
|
@ -8,12 +8,12 @@ const Wrapper = styled.div`
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
padding: .2rem .6rem !important;
|
padding: 0.2rem 0.6rem !important;
|
||||||
padding-left: 1.5rem !important;
|
padding-left: 1.5rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-item {
|
.label-item {
|
||||||
padding: .2rem .6rem !important;
|
padding: 0.2rem 0.6rem !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,9 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
const RequestBodyMode = ({ item, collection }) => {
|
const RequestBodyMode = ({ item, collection }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const dropdownTippyRef = useRef();
|
const dropdownTippyRef = useRef();
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode');
|
const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode');
|
||||||
|
|
||||||
|
|
||||||
const Icon = forwardRef((props, ref) => {
|
const Icon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="flex items-center justify-center pl-3 py-1 select-none">
|
<div ref={ref} className="flex items-center justify-center pl-3 py-1 select-none">
|
||||||
@ -23,60 +22,74 @@ const RequestBodyMode = ({item, collection}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onModeChange = (value) => {
|
const onModeChange = (value) => {
|
||||||
dispatch(updateRequestBodyMode({
|
dispatch(
|
||||||
|
updateRequestBodyMode({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid,
|
||||||
mode: value
|
mode: value
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="inline-flex items-center cursor-pointer body-mode-selector">
|
<div className="inline-flex items-center cursor-pointer body-mode-selector">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||||
<div className="label-item font-medium">
|
<div className="label-item font-medium">Form</div>
|
||||||
Form
|
<div
|
||||||
</div>
|
className="dropdown-item"
|
||||||
<div className="dropdown-item" onClick={() => {
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('multipartForm');
|
onModeChange('multipartForm');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Multipart Form
|
Multipart Form
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={() => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('formUrlEncoded');
|
onModeChange('formUrlEncoded');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Form Url Encoded
|
Form Url Encoded
|
||||||
</div>
|
</div>
|
||||||
<div className="label-item font-medium">
|
<div className="label-item font-medium">Raw</div>
|
||||||
Raw
|
<div
|
||||||
</div>
|
className="dropdown-item"
|
||||||
<div className="dropdown-item" onClick={() => {
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('json');
|
onModeChange('json');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
JSON
|
JSON
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={() => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('xml');
|
onModeChange('xml');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
XML
|
XML
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={() => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('text');
|
onModeChange('text');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
TEXT
|
TEXT
|
||||||
</div>
|
</div>
|
||||||
<div className="label-item font-medium">
|
<div className="label-item font-medium">Other</div>
|
||||||
Other
|
<div
|
||||||
</div>
|
className="dropdown-item"
|
||||||
<div className="dropdown-item" onClick={() => {
|
onClick={() => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
onModeChange('none');
|
onModeChange('none');
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
No Body
|
No Body
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
@ -14,14 +14,16 @@ const RequestBody = ({item, collection}) => {
|
|||||||
const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode');
|
const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode');
|
||||||
|
|
||||||
const onEdit = (value) => {
|
const onEdit = (value) => {
|
||||||
dispatch(updateRequestBody({
|
dispatch(
|
||||||
|
updateRequestBody({
|
||||||
content: value,
|
content: value,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRun = () => dispatch(sendRequest(item, collection.uid));;
|
const onRun = () => dispatch(sendRequest(item, collection.uid));
|
||||||
const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
const onSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
||||||
|
|
||||||
if (['json', 'xml', 'text'].includes(bodyMode)) {
|
if (['json', 'xml', 'text'].includes(bodyMode)) {
|
||||||
@ -39,13 +41,7 @@ const RequestBody = ({item, collection}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="w-full">
|
<StyledWrapper className="w-full">
|
||||||
<CodeEditor
|
<CodeEditor value={bodyContent[bodyMode] || ''} onEdit={onEdit} onRun={onRun} onSave={onSave} mode={codeMirrorMode[bodyMode]} />
|
||||||
value={bodyContent[bodyMode] || ''}
|
|
||||||
onEdit={onEdit}
|
|
||||||
onRun={onRun}
|
|
||||||
onSave={onSave}
|
|
||||||
mode={codeMirrorMode[bodyMode]}
|
|
||||||
/>
|
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -58,10 +54,6 @@ const RequestBody = ({item, collection}) => {
|
|||||||
return <MultipartFormParams item={item} collection={collection} />;
|
return <MultipartFormParams item={item} collection={collection} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(
|
return <StyledWrapper className="w-full">No Body</StyledWrapper>;
|
||||||
<StyledWrapper className="w-full">
|
|
||||||
No Body
|
|
||||||
</StyledWrapper>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
export default RequestBody;
|
export default RequestBody;
|
||||||
|
@ -6,7 +6,8 @@ const Wrapper = styled.div`
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
thead, td {
|
thead,
|
||||||
|
td {
|
||||||
border: 1px solid #efefef;
|
border: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ const Wrapper = styled.div`
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type='text'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px transparent;
|
border: solid 1px transparent;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
@ -37,7 +38,7 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type='checkbox'] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -11,10 +11,12 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
const headers = item.draft ? get(item, 'draft.request.headers') : get(item, 'request.headers');
|
const headers = item.draft ? get(item, 'draft.request.headers') : get(item, 'request.headers');
|
||||||
|
|
||||||
const addHeader = () => {
|
const addHeader = () => {
|
||||||
dispatch(addRequestHeader({
|
dispatch(
|
||||||
|
addRequestHeader({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleHeaderValueChange = (e, _header, type) => {
|
const handleHeaderValueChange = (e, _header, type) => {
|
||||||
@ -37,19 +39,23 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch(updateRequestHeader({
|
dispatch(
|
||||||
|
updateRequestHeader({
|
||||||
header: header,
|
header: header,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveHeader = (header) => {
|
const handleRemoveHeader = (header) => {
|
||||||
dispatch(deleteRequestHeader({
|
dispatch(
|
||||||
|
deleteRequestHeader({
|
||||||
headerUid: header.uid,
|
headerUid: header.uid,
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -64,13 +70,17 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{headers && headers.length ? headers.map((header, index) => {
|
{headers && headers.length
|
||||||
|
? headers.map((header, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={header.uid}>
|
<tr key={header.uid}>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={header.name}
|
value={header.name}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleHeaderValueChange(e, header, 'name')}
|
onChange={(e) => handleHeaderValueChange(e, header, 'name')}
|
||||||
@ -79,7 +89,10 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={header.value}
|
value={header.value}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleHeaderValueChange(e, header, 'value')}
|
onChange={(e) => handleHeaderValueChange(e, header, 'value')}
|
||||||
@ -88,7 +101,10 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={header.description}
|
value={header.description}
|
||||||
className="mousetrap"
|
className="mousetrap"
|
||||||
onChange={(e) => handleHeaderValueChange(e, header, 'description')}
|
onChange={(e) => handleHeaderValueChange(e, header, 'description')}
|
||||||
@ -96,12 +112,7 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input type="checkbox" checked={header.enabled} className="mr-3 mousetrap" onChange={(e) => handleHeaderValueChange(e, header, 'enabled')} />
|
||||||
type="checkbox"
|
|
||||||
checked={header.enabled}
|
|
||||||
className="mr-3 mousetrap"
|
|
||||||
onChange={(e) => handleHeaderValueChange(e, header, 'enabled')}
|
|
||||||
/>
|
|
||||||
<button onClick={() => handleRemoveHeader(header)}>
|
<button onClick={() => handleRemoveHeader(header)}>
|
||||||
<IconTrash strokeWidth={1.5} size={20} />
|
<IconTrash strokeWidth={1.5} size={20} />
|
||||||
</button>
|
</button>
|
||||||
@ -109,11 +120,14 @@ const RequestHeaders = ({item, collection}) => {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<button className="btn-add-header select-none" onClick={addHeader}>+ Add Header</button>
|
<button className="btn-add-header select-none" onClick={addHeader}>
|
||||||
|
+ Add Header
|
||||||
|
</button>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default RequestHeaders;
|
export default RequestHeaders;
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { faFolder } from "@fortawesome/free-solid-svg-icons";
|
import { faFolder } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
import Modal from 'components//Modal';
|
import Modal from 'components//Modal';
|
||||||
|
|
||||||
@ -9,14 +9,14 @@ const SaveRequest = ({items, onClose}) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowFolders(items || []);
|
setShowFolders(items || []);
|
||||||
}, [items])
|
}, [items]);
|
||||||
|
|
||||||
const handleFolderClick = (folder) => {
|
const handleFolderClick = (folder) => {
|
||||||
let subFolders = [];
|
let subFolders = [];
|
||||||
if (folder.items && folder.items.length) {
|
if (folder.items && folder.items.length) {
|
||||||
for (let item of folder.items) {
|
for (let item of folder.items) {
|
||||||
if (item.items) {
|
if (item.items) {
|
||||||
subFolders.push(item)
|
subFolders.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,30 +24,21 @@ const SaveRequest = ({items, onClose}) => {
|
|||||||
setShowFolders(subFolders);
|
setShowFolders(subFolders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="md" title="Save Request" confirmText="Save" cancelText="Cancel" handleCancel={onClose} handleConfirm={onClose}>
|
||||||
size ="md"
|
|
||||||
title ="Save Request"
|
|
||||||
confirmText ="Save"
|
|
||||||
cancelText ="Cancel"
|
|
||||||
handleCancel = {onClose}
|
|
||||||
handleConfirm = {onClose}
|
|
||||||
>
|
|
||||||
<p className="mb-2">Select a folder to save request:</p>
|
<p className="mb-2">Select a folder to save request:</p>
|
||||||
<div className="folder-list">
|
<div className="folder-list">
|
||||||
{showFolders && showFolders.length ? showFolders.map((folder) => (
|
{showFolders && showFolders.length
|
||||||
<div
|
? showFolders.map((folder) => (
|
||||||
key={folder.uid}
|
<div key={folder.uid} className="folder-name" onClick={() => handleFolderClick(folder)}>
|
||||||
className="folder-name"
|
|
||||||
onClick={() => handleFolderClick(folder)}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon className="mr-3 text-gray-500" icon={faFolder} style={{ fontSize: 20 }} />
|
<FontAwesomeIcon className="mr-3 text-gray-500" icon={faFolder} style={{ fontSize: 20 }} />
|
||||||
{folder.name}
|
{folder.name}
|
||||||
</div>
|
</div>
|
||||||
)): null}
|
))
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -6,18 +6,18 @@ const RequestNotFound = ({itemUid}) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const closeTab = () => {
|
const closeTab = () => {
|
||||||
dispatch(closeTabs({
|
dispatch(
|
||||||
|
closeTabs({
|
||||||
tabUids: [itemUid]
|
tabUids: [itemUid]
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6 px-6">
|
<div className="mt-6 px-6">
|
||||||
<div className="p-4 bg-orange-100 border-l-4 border-yellow-500 text-yellow-700 bg-yellow-100 p-4">
|
<div className="p-4 bg-orange-100 border-l-4 border-yellow-500 text-yellow-700 bg-yellow-100 p-4">
|
||||||
<div>Request no longer exists.</div>
|
<div>Request no longer exists.</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">This can happen when the yml file associated with this request was deleted on your filesystem.</div>
|
||||||
This can happen when the yml file associated with this request was deleted on your filesystem.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-md btn-secondary mt-6" onClick={closeTab}>
|
<button className="btn btn-md btn-secondary mt-6" onClick={closeTab}>
|
||||||
Close Tab
|
Close Tab
|
||||||
|
@ -28,7 +28,7 @@ const RequestTabPanel = () => {
|
|||||||
|
|
||||||
let asideWidth = useSelector((state) => state.app.leftSidebarWidth);
|
let asideWidth = useSelector((state) => state.app.leftSidebarWidth);
|
||||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||||
const [leftPaneWidth, setLeftPaneWidth] = useState(focusedTab && focusedTab.requestPaneWidth ? focusedTab.requestPaneWidth : ((screenWidth - asideWidth)/2.2)); // 2.2 so that request pane is relatively smaller
|
const [leftPaneWidth, setLeftPaneWidth] = useState(focusedTab && focusedTab.requestPaneWidth ? focusedTab.requestPaneWidth : (screenWidth - asideWidth) / 2.2); // 2.2 so that request pane is relatively smaller
|
||||||
const [rightPaneWidth, setRightPaneWidth] = useState(screenWidth - asideWidth - leftPaneWidth - 5);
|
const [rightPaneWidth, setRightPaneWidth] = useState(screenWidth - asideWidth - leftPaneWidth - 5);
|
||||||
const [dragging, setDragging] = useState(false);
|
const [dragging, setDragging] = useState(false);
|
||||||
|
|
||||||
@ -45,17 +45,19 @@ const RequestTabPanel = () => {
|
|||||||
if (dragging) {
|
if (dragging) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLeftPaneWidth(e.clientX - asideWidth - 5);
|
setLeftPaneWidth(e.clientX - asideWidth - 5);
|
||||||
setRightPaneWidth(screenWidth - (e.clientX) - 5);
|
setRightPaneWidth(screenWidth - e.clientX - 5);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleMouseUp = (e) => {
|
const handleMouseUp = (e) => {
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setDragging(false);
|
setDragging(false);
|
||||||
dispatch(updateRequestPaneTabWidth({
|
dispatch(
|
||||||
|
updateRequestPaneTabWidth({
|
||||||
uid: activeTabUid,
|
uid: activeTabUid,
|
||||||
requestPaneWidth: e.clientX - asideWidth - 5
|
requestPaneWidth: e.clientX - asideWidth - 5
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleDragbarMouseDown = (e) => {
|
const handleDragbarMouseDown = (e) => {
|
||||||
@ -78,38 +80,30 @@ const RequestTabPanel = () => {
|
|||||||
};
|
};
|
||||||
}, [dragging, asideWidth]);
|
}, [dragging, asideWidth]);
|
||||||
|
|
||||||
|
|
||||||
if (!activeTabUid) {
|
if (!activeTabUid) {
|
||||||
return (
|
return <Welcome />;
|
||||||
<Welcome/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!focusedTab || !focusedTab.uid || !focusedTab.collectionUid) {
|
if (!focusedTab || !focusedTab.uid || !focusedTab.collectionUid) {
|
||||||
return (
|
return <div className="pb-4 px-4">An error occured!</div>;
|
||||||
<div className="pb-4 px-4">An error occured!</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let collection = find(collections, (c) => c.uid === focusedTab.collectionUid);
|
let collection = find(collections, (c) => c.uid === focusedTab.collectionUid);
|
||||||
if (!collection || !collection.uid) {
|
if (!collection || !collection.uid) {
|
||||||
return (
|
return <div className="pb-4 px-4">Collection not found!</div>;
|
||||||
<div className="pb-4 px-4">Collection not found!</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = findItemInCollection(collection, activeTabUid);
|
const item = findItemInCollection(collection, activeTabUid);
|
||||||
if (!item || !item.uid) {
|
if (!item || !item.uid) {
|
||||||
return (
|
return <RequestNotFound itemUid={activeTabUid} />;
|
||||||
<RequestNotFound itemUid={activeTabUid}/>
|
}
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRun = async () => {
|
const handleRun = async () => {
|
||||||
dispatch(sendRequest(item, collection.uid))
|
dispatch(sendRequest(item, collection.uid)).catch((err) =>
|
||||||
.catch((err) => toast.custom((t) => (<NetworkError onClose={() => toast.dismiss(t.id)}/>), {
|
toast.custom((t) => <NetworkError onClose={() => toast.dismiss(t.id)} />, {
|
||||||
duration: 5000
|
duration: 5000
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const onGraphqlQueryChange = (value) => {};
|
const onGraphqlQueryChange = (value) => {};
|
||||||
const runQuery = async () => {};
|
const runQuery = async () => {};
|
||||||
@ -117,18 +111,11 @@ const RequestTabPanel = () => {
|
|||||||
return (
|
return (
|
||||||
<StyledWrapper className={`flex flex-col flex-grow ${dragging ? 'dragging' : ''}`}>
|
<StyledWrapper className={`flex flex-col flex-grow ${dragging ? 'dragging' : ''}`}>
|
||||||
<div className="pt-4 pb-3 px-4">
|
<div className="pt-4 pb-3 px-4">
|
||||||
<QueryUrl
|
<QueryUrl item={item} collection={collection} handleRun={handleRun} />
|
||||||
item = {item}
|
|
||||||
collection={collection}
|
|
||||||
handleRun={handleRun}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<section className="main flex flex-grow pb-4">
|
<section className="main flex flex-grow pb-4">
|
||||||
<section className="request-pane">
|
<section className="request-pane">
|
||||||
<div
|
<div className="px-4" style={{ width: `${leftPaneWidth}px`, height: 'calc(100% - 5px)' }}>
|
||||||
className="px-4"
|
|
||||||
style={{width: `${leftPaneWidth}px`, height: 'calc(100% - 5px)'}}
|
|
||||||
>
|
|
||||||
{item.type === 'graphql-request' ? (
|
{item.type === 'graphql-request' ? (
|
||||||
<GraphQLRequestPane
|
<GraphQLRequestPane
|
||||||
onRunQuery={runQuery}
|
onRunQuery={runQuery}
|
||||||
@ -139,13 +126,7 @@ const RequestTabPanel = () => {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{item.type === 'http-request' ? (
|
{item.type === 'http-request' ? <HttpRequestPane item={item} collection={collection} leftPaneWidth={leftPaneWidth} /> : null}
|
||||||
<HttpRequestPane
|
|
||||||
item={item}
|
|
||||||
collection={collection}
|
|
||||||
leftPaneWidth={leftPaneWidth}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -154,16 +135,11 @@ const RequestTabPanel = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section className="response-pane flex-grow">
|
<section className="response-pane flex-grow">
|
||||||
<ResponsePane
|
<ResponsePane item={item} collection={collection} rightPaneWidth={rightPaneWidth} response={item.response} />
|
||||||
item={item}
|
|
||||||
collection={collection}
|
|
||||||
rightPaneWidth={rightPaneWidth}
|
|
||||||
response={item.response}
|
|
||||||
/>
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RequestTabPanel;
|
export default RequestTabPanel;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div``;
|
||||||
`;
|
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
@ -16,7 +16,7 @@ const CollectionToolBar = ({collection}) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CollectionToolBar;
|
export default CollectionToolBar;
|
||||||
|
@ -25,7 +25,8 @@ const StyledWrapper = styled.div`
|
|||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover, &:hover .close-icon {
|
&:hover,
|
||||||
|
&:hover .close-icon {
|
||||||
background-color: #eaeaea;
|
background-color: #eaeaea;
|
||||||
color: rgb(76 76 76);
|
color: rgb(76 76 76);
|
||||||
}
|
}
|
||||||
@ -37,4 +38,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -12,9 +12,11 @@ const RequestTab = ({tab, collection}) => {
|
|||||||
const handleCloseClick = (event) => {
|
const handleCloseClick = (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
dispatch(closeTabs({
|
dispatch(
|
||||||
|
closeTabs({
|
||||||
tabUids: [tab.uid]
|
tabUids: [tab.uid]
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMethodColor = (method = '') => {
|
const getMethodColor = (method = '') => {
|
||||||
@ -65,7 +67,10 @@ const RequestTab = ({tab, collection}) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex px-2 close-icon-container" onClick={(e) => handleCloseClick(e)}>
|
<div className="flex px-2 close-icon-container" onClick={(e) => handleCloseClick(e)}>
|
||||||
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" className="close-icon">
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" className="close-icon">
|
||||||
<path fill="currentColor" d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"></path>
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"
|
||||||
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
@ -77,13 +82,20 @@ const RequestTab = ({tab, collection}) => {
|
|||||||
return (
|
return (
|
||||||
<StyledWrapper className="flex items-center justify-between tab-container px-1">
|
<StyledWrapper className="flex items-center justify-between tab-container px-1">
|
||||||
<div className="flex items-baseline tab-label pl-2">
|
<div className="flex items-baseline tab-label pl-2">
|
||||||
<span className="tab-method uppercase" style={{color: getMethodColor(method), fontSize: 12}}>{method}</span>
|
<span className="tab-method uppercase" style={{ color: getMethodColor(method), fontSize: 12 }}>
|
||||||
<span className="text-gray-700 ml-1 tab-name" title={item.name}>{item.name}</span>
|
{method}
|
||||||
|
</span>
|
||||||
|
<span className="text-gray-700 ml-1 tab-name" title={item.name}>
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex px-2 close-icon-container" onClick={(e) => handleCloseClick(e)}>
|
<div className="flex px-2 close-icon-container" onClick={(e) => handleCloseClick(e)}>
|
||||||
{!item.draft ? (
|
{!item.draft ? (
|
||||||
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" className="close-icon">
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" className="close-icon">
|
||||||
<path fill="currentColor" d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"></path>
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"
|
||||||
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
) : (
|
) : (
|
||||||
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="8" height="16" fill="#cc7b1b" className="has-changes-icon" viewBox="0 0 8 8">
|
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="8" height="16" fill="#cc7b1b" className="has-changes-icon" viewBox="0 0 8 8">
|
||||||
|
@ -21,16 +21,18 @@ const RequestTabs = () => {
|
|||||||
const screenWidth = useSelector((state) => state.app.screenWidth);
|
const screenWidth = useSelector((state) => state.app.screenWidth);
|
||||||
|
|
||||||
const getTabClassname = (tab, index) => {
|
const getTabClassname = (tab, index) => {
|
||||||
return classnames("request-tab select-none", {
|
return classnames('request-tab select-none', {
|
||||||
'active': tab.uid === activeTabUid,
|
active: tab.uid === activeTabUid,
|
||||||
'last-tab': tabs && tabs.length && (index === tabs.length - 1)
|
'last-tab': tabs && tabs.length && index === tabs.length - 1
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = (tab) => {
|
const handleClick = (tab) => {
|
||||||
dispatch(focusTab({
|
dispatch(
|
||||||
|
focusTab({
|
||||||
uid: tab.uid
|
uid: tab.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createNewTab = () => setNewRequestModalOpen(true);
|
const createNewTab = () => setNewRequestModalOpen(true);
|
||||||
@ -41,18 +43,14 @@ const RequestTabs = () => {
|
|||||||
|
|
||||||
const activeTab = find(tabs, (t) => t.uid === activeTabUid);
|
const activeTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||||
if (!activeTab) {
|
if (!activeTab) {
|
||||||
return (
|
return <StyledWrapper>Something went wrong!</StyledWrapper>;
|
||||||
<StyledWrapper>
|
|
||||||
Something went wrong!
|
|
||||||
</StyledWrapper>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeCollection = find(collections, (c) => c.uid === activeTab.collectionUid);
|
const activeCollection = find(collections, (c) => c.uid === activeTab.collectionUid);
|
||||||
const collectionRequestTabs = filter(tabs, (t) => t.collectionUid === activeTab.collectionUid);
|
const collectionRequestTabs = filter(tabs, (t) => t.collectionUid === activeTab.collectionUid);
|
||||||
|
|
||||||
const maxTablistWidth = screenWidth - leftSidebarWidth - 150;
|
const maxTablistWidth = screenWidth - leftSidebarWidth - 150;
|
||||||
const tabsWidth = (collectionRequestTabs.length * 150) + 34; // 34: (+)icon
|
const tabsWidth = collectionRequestTabs.length * 150 + 34; // 34: (+)icon
|
||||||
const showChevrons = maxTablistWidth < tabsWidth;
|
const showChevrons = maxTablistWidth < tabsWidth;
|
||||||
|
|
||||||
const leftSlide = () => {
|
const leftSlide = () => {
|
||||||
@ -102,13 +100,15 @@ const RequestTabs = () => {
|
|||||||
</li> */}
|
</li> */}
|
||||||
</ul>
|
</ul>
|
||||||
<ul role="tablist" style={{ maxWidth: maxTablistWidth }} ref={tabsRef}>
|
<ul role="tablist" style={{ maxWidth: maxTablistWidth }} ref={tabsRef}>
|
||||||
{collectionRequestTabs && collectionRequestTabs.length ? collectionRequestTabs.map((tab, index) => {
|
{collectionRequestTabs && collectionRequestTabs.length
|
||||||
|
? collectionRequestTabs.map((tab, index) => {
|
||||||
return (
|
return (
|
||||||
<li key={tab.uid} className={getTabClassname(tab, index)} role="tab" onClick={() => handleClick(tab)}>
|
<li key={tab.uid} className={getTabClassname(tab, index)} role="tab" onClick={() => handleClick(tab)}>
|
||||||
<RequestTab key={tab.uid} tab={tab} collection={activeCollection} activeTab={activeTab} />
|
<RequestTab key={tab.uid} tab={tab} collection={activeCollection} activeTab={activeTab} />
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul role="tablist">
|
<ul role="tablist">
|
||||||
|
@ -6,12 +6,9 @@ const NetworkError = ({onClose}) => {
|
|||||||
<div className="flex-1 w-0 p-4">
|
<div className="flex-1 w-0 p-4">
|
||||||
<div className="flex items-start">
|
<div className="flex items-start">
|
||||||
<div className="ml-3 flex-1">
|
<div className="ml-3 flex-1">
|
||||||
<p className="text-sm font-medium text-red-800">
|
<p className="text-sm font-medium text-red-800">Network Error</p>
|
||||||
Network Error
|
|
||||||
</p>
|
|
||||||
<p className="mt-2 text-xs text-gray-500">
|
<p className="mt-2 text-xs text-gray-500">
|
||||||
Please note that if you are using Bruno on the web, then the api you are connecting to must allow CORS.
|
Please note that if you are using Bruno on the web, then the api you are connecting to must allow CORS. If not, please use the chrome extension or the desktop app
|
||||||
If not, please use the chrome extension or the desktop app
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,4 +18,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ const ResponseLoadingOverlay = ({item, collection}) => {
|
|||||||
<IconRefresh size={24} className="animate-spin" />
|
<IconRefresh size={24} className="animate-spin" />
|
||||||
<button
|
<button
|
||||||
onClick={handleCancelRequest}
|
onClick={handleCancelRequest}
|
||||||
className="mt-4 uppercase bg-gray-200 active:bg-blueGray-600 text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button"
|
className="mt-4 uppercase bg-gray-200 active:bg-blueGray-600 text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
Cancel Request
|
Cancel Request
|
||||||
</button>
|
</button>
|
||||||
|
@ -6,4 +6,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -8,4 +8,3 @@ const StyledWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -12,17 +12,19 @@ const ResponseHeaders = ({headers}) => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{headers && headers.length ? headers.map((header, index) => {
|
{headers && headers.length
|
||||||
|
? headers.map((header, index) => {
|
||||||
return (
|
return (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td className="key">{header[0]}</td>
|
<td className="key">{header[0]}</td>
|
||||||
<td className="value">{header[1]}</td>
|
<td className="value">{header[1]}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default ResponseHeaders;
|
export default ResponseHeaders;
|
@ -2,20 +2,17 @@ import React from 'react';
|
|||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const ResponseSize = ({ size }) => {
|
const ResponseSize = ({ size }) => {
|
||||||
let sizeToDisplay = ''
|
let sizeToDisplay = '';
|
||||||
|
|
||||||
if(size > 1024 ) { // size is greater than 1kb
|
if (size > 1024) {
|
||||||
|
// size is greater than 1kb
|
||||||
let kb = Math.floor(size / 1024);
|
let kb = Math.floor(size / 1024);
|
||||||
let decimal = ((size % 1024) / 1024).toFixed(2) * 100;
|
let decimal = ((size % 1024) / 1024).toFixed(2) * 100;
|
||||||
sizeToDisplay = kb + '.' + decimal + 'KB';
|
sizeToDisplay = kb + '.' + decimal + 'KB';
|
||||||
} else {
|
} else {
|
||||||
sizeToDisplay = size + 'B'
|
sizeToDisplay = size + 'B';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <StyledWrapper className="ml-4">{sizeToDisplay}</StyledWrapper>;
|
||||||
<StyledWrapper className="ml-4">
|
|
||||||
{sizeToDisplay}
|
|
||||||
</StyledWrapper>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
export default ResponseSize;
|
export default ResponseSize;
|
@ -2,20 +2,17 @@ import React from 'react';
|
|||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const ResponseTime = ({ duration }) => {
|
const ResponseTime = ({ duration }) => {
|
||||||
let durationToDisplay = ''
|
let durationToDisplay = '';
|
||||||
|
|
||||||
if(duration > 1000 ) { // duration greater than a second
|
if (duration > 1000) {
|
||||||
|
// duration greater than a second
|
||||||
let seconds = Math.floor(duration / 1000);
|
let seconds = Math.floor(duration / 1000);
|
||||||
let decimal = ((duration % 1000) / 1000) * 100;
|
let decimal = ((duration % 1000) / 1000) * 100;
|
||||||
durationToDisplay = seconds + '.' + decimal.toFixed(0) + 's';
|
durationToDisplay = seconds + '.' + decimal.toFixed(0) + 's';
|
||||||
} else {
|
} else {
|
||||||
durationToDisplay = duration + 'ms'
|
durationToDisplay = duration + 'ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <StyledWrapper className="ml-4">{durationToDisplay}</StyledWrapper>;
|
||||||
<StyledWrapper className="ml-4">
|
|
||||||
{durationToDisplay}
|
|
||||||
</StyledWrapper>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
export default ResponseTime;
|
export default ResponseTime;
|
@ -41,7 +41,7 @@ const statusCodePhraseMap = {
|
|||||||
415: 'Unsupported Media Type',
|
415: 'Unsupported Media Type',
|
||||||
416: 'Range Not Satisfiable',
|
416: 'Range Not Satisfiable',
|
||||||
417: 'Expectation Failed',
|
417: 'Expectation Failed',
|
||||||
418: 'I\'m a teapot',
|
418: "I'm a teapot",
|
||||||
421: 'Misdirected Request',
|
421: 'Misdirected Request',
|
||||||
422: 'Unprocessable Entity',
|
422: 'Unprocessable Entity',
|
||||||
423: 'Locked',
|
423: 'Locked',
|
||||||
|
@ -18,6 +18,6 @@ const StatusCode = ({status}) => {
|
|||||||
<StyledWrapper className={getTabClassname()}>
|
<StyledWrapper className={getTabClassname()}>
|
||||||
{status} {statusCodePhraseMap[status]}
|
{status} {statusCodePhraseMap[status]}
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
export default StatusCode;
|
export default StatusCode;
|
@ -10,7 +10,11 @@ const StyledWrapper = styled.div`
|
|||||||
color: var(--color-tab-inactive);
|
color: var(--color-tab-inactive);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:focus, &:active, &:focus-within, &:focus-visible, &:target {
|
&:focus,
|
||||||
|
&:active,
|
||||||
|
&:focus-within,
|
||||||
|
&:focus-visible,
|
||||||
|
&:target {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,12 @@ const ResponsePane = ({rightPaneWidth, item, collection}) => {
|
|||||||
const isLoading = item.response && item.response.state === 'sending';
|
const isLoading = item.response && item.response.state === 'sending';
|
||||||
|
|
||||||
const selectTab = (tab) => {
|
const selectTab = (tab) => {
|
||||||
dispatch(updateResponsePaneTab({
|
dispatch(
|
||||||
|
updateResponsePaneTab({
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
responsePaneTab: tab
|
responsePaneTab: tab
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = item.response || {};
|
const response = item.response || {};
|
||||||
@ -30,17 +32,10 @@ const ResponsePane = ({rightPaneWidth, item, collection}) => {
|
|||||||
const getTabPanel = (tab) => {
|
const getTabPanel = (tab) => {
|
||||||
switch (tab) {
|
switch (tab) {
|
||||||
case 'response': {
|
case 'response': {
|
||||||
return (
|
return <QueryResult width={rightPaneWidth} value={response.data ? JSON.stringify(response.data, null, 2) : ''} />;
|
||||||
<QueryResult
|
|
||||||
width={rightPaneWidth}
|
|
||||||
value={response.data ? JSON.stringify(response.data, null, 2) : ''}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
case 'headers': {
|
case 'headers': {
|
||||||
return (
|
return <ResponseHeaders headers={response.headers} />;
|
||||||
<ResponseHeaders headers={response.headers}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
@ -66,29 +61,29 @@ const ResponsePane = ({rightPaneWidth, item, collection}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!activeTabUid) {
|
if (!activeTabUid) {
|
||||||
return (
|
return <div>Something went wrong</div>;
|
||||||
<div>Something went wrong</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||||
if (!focusedTab || !focusedTab.uid || !focusedTab.responsePaneTab) {
|
if (!focusedTab || !focusedTab.uid || !focusedTab.responsePaneTab) {
|
||||||
return (
|
return <div className="pb-4 px-4">An error occured!</div>;
|
||||||
<div className="pb-4 px-4">An error occured!</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTabClassname = (tabName) => {
|
const getTabClassname = (tabName) => {
|
||||||
return classnames(`tab select-none ${tabName}`, {
|
return classnames(`tab select-none ${tabName}`, {
|
||||||
'active': tabName === focusedTab.responsePaneTab
|
active: tabName === focusedTab.responsePaneTab
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="flex flex-col h-full relative">
|
<StyledWrapper className="flex flex-col h-full relative">
|
||||||
<div className="flex items-center px-3 tabs" role="tablist">
|
<div className="flex items-center px-3 tabs" role="tablist">
|
||||||
<div className={getTabClassname('response')} role="tab" onClick={() => selectTab('response')}>Response</div>
|
<div className={getTabClassname('response')} role="tab" onClick={() => selectTab('response')}>
|
||||||
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>Headers</div>
|
Response
|
||||||
|
</div>
|
||||||
|
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
|
||||||
|
Headers
|
||||||
|
</div>
|
||||||
{!isLoading ? (
|
{!isLoading ? (
|
||||||
<div className="flex flex-grow justify-end items-center">
|
<div className="flex flex-grow justify-end items-center">
|
||||||
<StatusCode status={response.status} />
|
<StatusCode status={response.status} />
|
||||||
@ -97,11 +92,9 @@ const ResponsePane = ({rightPaneWidth, item, collection}) => {
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<section className="flex flex-grow mt-5">
|
<section className="flex flex-grow mt-5">{getTabPanel(focusedTab.responsePaneTab)}</section>
|
||||||
{getTabPanel(focusedTab.responsePaneTab)}
|
|
||||||
</section>
|
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ResponsePane;
|
export default ResponsePane;
|
||||||
|
@ -16,10 +16,7 @@ const CloneCollectionItem = ({collection, item, onClose}) => {
|
|||||||
name: item.name
|
name: item.name
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(cloneItem(values.name, item.uid, collection.uid));
|
dispatch(cloneItem(values.name, item.uid, collection.uid));
|
||||||
@ -36,27 +33,26 @@ const CloneCollectionItem = ({collection, item, onClose}) => {
|
|||||||
const onSubmit = () => formik.handleSubmit();
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title={`Clone ${isFolder ? 'Folder' : 'Request'}`} confirmText="Clone" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={`Clone ${isFolder ? 'Folder' : 'Request'}`}
|
|
||||||
confirmText='Clone'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">{isFolder ? 'Folder' : 'Request'} Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
{isFolder ? 'Folder' : 'Request'} Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-item-name" type="text" name="name"
|
id="collection-item-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -11,16 +11,19 @@ const DeleteCollectionItem = ({onClose, item, collection}) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const isFolder = isItemAFolder(item);
|
const isFolder = isItemAFolder(item);
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
dispatch(deleteItem(item.uid, collection.uid))
|
dispatch(deleteItem(item.uid, collection.uid)).then(() => {
|
||||||
.then(() => {
|
|
||||||
if (isFolder) {
|
if (isFolder) {
|
||||||
dispatch(closeTabs({
|
dispatch(
|
||||||
|
closeTabs({
|
||||||
tabUids: recursivelyGetAllItemUids(item.items)
|
tabUids: recursivelyGetAllItemUids(item.items)
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch(closeTabs({
|
dispatch(
|
||||||
|
closeTabs({
|
||||||
tabUids: [item.uid]
|
tabUids: [item.uid]
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
onClose();
|
onClose();
|
||||||
@ -28,13 +31,7 @@ const DeleteCollectionItem = ({onClose, item, collection}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="sm" title={`Delete ${isFolder ? 'Folder' : 'Request'}`} confirmText="Delete" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={`Delete ${isFolder ? 'Folder' : 'Request'}`}
|
|
||||||
confirmText="Delete"
|
|
||||||
handleConfirm={onConfirm}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
Are you sure you want to delete <span className="font-semibold">{item.name}</span> ?
|
Are you sure you want to delete <span className="font-semibold">{item.name}</span> ?
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -16,10 +16,7 @@ const RenameCollectionItem = ({collection, item, onClose}) => {
|
|||||||
name: item.name
|
name: item.name
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(renameItem(values.name, item.uid, collection.uid));
|
dispatch(renameItem(values.name, item.uid, collection.uid));
|
||||||
@ -36,27 +33,26 @@ const RenameCollectionItem = ({collection, item, onClose}) => {
|
|||||||
const onSubmit = () => formik.handleSubmit();
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title={`Rename ${isFolder ? 'Folder' : 'Request'}`} confirmText="Rename" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={`Rename ${isFolder ? 'Folder' : 'Request'}`}
|
|
||||||
confirmText='Rename'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">{isFolder ? 'Folder' : 'Request'} Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
{isFolder ? 'Folder' : 'Request'} Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-item-name" type="text" name="name"
|
id="collection-item-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -12,13 +12,27 @@ const Wrapper = styled.div`
|
|||||||
top: 1px;
|
top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.method-get { color: var(--color-method-get);}
|
.method-get {
|
||||||
.method-post { color: var(--color-method-post);}
|
color: var(--color-method-get);
|
||||||
.method-put { color: var(--color-method-put);}
|
}
|
||||||
.method-delete { color: var(--color-method-delete);}
|
.method-post {
|
||||||
.method-patch { color: var(--color-method-patch);}
|
color: var(--color-method-post);
|
||||||
.method-options { color: var(--color-method-options);}
|
}
|
||||||
.method-head { color: var(--color-method-head);}
|
.method-put {
|
||||||
|
color: var(--color-method-put);
|
||||||
|
}
|
||||||
|
.method-delete {
|
||||||
|
color: var(--color-method-delete);
|
||||||
|
}
|
||||||
|
.method-patch {
|
||||||
|
color: var(--color-method-patch);
|
||||||
|
}
|
||||||
|
.method-options {
|
||||||
|
color: var(--color-method-options);
|
||||||
|
}
|
||||||
|
.method-head {
|
||||||
|
color: var(--color-method-head);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Wrapper;
|
export default Wrapper;
|
||||||
|
@ -9,7 +9,7 @@ const RequestMethod = ({item}) => {
|
|||||||
|
|
||||||
const getClassname = (method = '') => {
|
const getClassname = (method = '') => {
|
||||||
method = method.toLocaleLowerCase();
|
method = method.toLocaleLowerCase();
|
||||||
return classnames("mr-1", {
|
return classnames('mr-1', {
|
||||||
'method-get': method === 'get',
|
'method-get': method === 'get',
|
||||||
'method-post': method === 'post',
|
'method-post': method === 'post',
|
||||||
'method-put': method === 'put',
|
'method-put': method === 'put',
|
||||||
|
@ -5,10 +5,10 @@ const Wrapper = styled.div`
|
|||||||
color: rgb(110 110 110);
|
color: rgb(110 110 110);
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
div[aria-expanded="true"] {
|
div[aria-expanded='true'] {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
div[aria-expanded="false"] {
|
div[aria-expanded='false'] {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ const Wrapper = styled.div`
|
|||||||
background: #e7e7e7;
|
background: #e7e7e7;
|
||||||
.menu-icon {
|
.menu-icon {
|
||||||
.dropdown {
|
.dropdown {
|
||||||
div[aria-expanded="false"] {
|
div[aria-expanded='false'] {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,26 +60,32 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
const handleClick = (event) => {
|
const handleClick = (event) => {
|
||||||
if (isItemARequest(item)) {
|
if (isItemARequest(item)) {
|
||||||
if (itemIsOpenedInTabs(item, tabs)) {
|
if (itemIsOpenedInTabs(item, tabs)) {
|
||||||
dispatch(focusTab({
|
dispatch(
|
||||||
|
focusTab({
|
||||||
uid: item.uid
|
uid: item.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch(addTab({
|
dispatch(
|
||||||
|
addTab({
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
dispatch(hideHomePage());
|
dispatch(hideHomePage());
|
||||||
} else {
|
} else {
|
||||||
dispatch(collectionFolderClicked({
|
dispatch(
|
||||||
|
collectionFolderClicked({
|
||||||
itemUid: item.uid,
|
itemUid: item.uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let indents = range(item.depth);
|
let indents = range(item.depth);
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
const isFolder = isItemAFolder(item);
|
const isFolder = isItemAFolder(item);
|
||||||
|
|
||||||
const className = classnames('flex flex-col w-full', {
|
const className = classnames('flex flex-col w-full', {
|
||||||
@ -94,7 +100,7 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
} else {
|
} else {
|
||||||
if (!doesFolderHaveItemsMatchSearchText(item, searchText)) {
|
if (!doesFolderHaveItemsMatchSearchText(item, searchText)) {
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +116,8 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
{newFolderModalOpen && <NewFolder item={item} collection={collection} onClose={() => setNewFolderModalOpen(false)} />}
|
{newFolderModalOpen && <NewFolder item={item} collection={collection} onClose={() => setNewFolderModalOpen(false)} />}
|
||||||
<div className={itemRowClassName}>
|
<div className={itemRowClassName}>
|
||||||
<div className="flex items-center h-full w-full">
|
<div className="flex items-center h-full w-full">
|
||||||
{indents && indents.length ? indents.map((i) => {
|
{indents && indents.length
|
||||||
|
? indents.map((i) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
@ -125,7 +132,8 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
{/* Indent */}
|
{/* Indent */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}) : null}
|
})
|
||||||
|
: null}
|
||||||
<div
|
<div
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className="flex flex-grow items-center h-full overflow-hidden"
|
className="flex flex-grow items-center h-full overflow-hidden"
|
||||||
@ -134,52 +142,67 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ width: 16, minWidth: 16 }}>
|
<div style={{ width: 16, minWidth: 16 }}>
|
||||||
{isFolder ? (
|
{isFolder ? <IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{ color: 'rgb(160 160 160)' }} /> : null}
|
||||||
<IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{color: 'rgb(160 160 160)'}}/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ml-1 flex items-center overflow-hidden">
|
<div className="ml-1 flex items-center overflow-hidden">
|
||||||
<RequestMethod item={item} />
|
<RequestMethod item={item} />
|
||||||
<span className="item-name" title={item.name}>{item.name}</span>
|
<span className="item-name" title={item.name}>
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="menu-icon pr-2">
|
<div className="menu-icon pr-2">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<MenuIcon />} placement='bottom-start'>
|
<Dropdown onCreate={onDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
||||||
{isFolder && (
|
{isFolder && (
|
||||||
<>
|
<>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
setNewRequestModalOpen(true);
|
setNewRequestModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
New Request
|
New Request
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
setNewFolderModalOpen(true);
|
setNewFolderModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
New Folder
|
New Folder
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
setRenameItemModalOpen(true);
|
setRenameItemModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Rename
|
Rename
|
||||||
</div>
|
</div>
|
||||||
{!isFolder && (
|
{!isFolder && (
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
setCloneItemModalOpen(true);
|
setCloneItemModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Clone
|
Clone
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="dropdown-item delete-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item delete-item"
|
||||||
|
onClick={(e) => {
|
||||||
dropdownTippyRef.current.hide();
|
dropdownTippyRef.current.hide();
|
||||||
setDeleteItemModalOpen(true);
|
setDeleteItemModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Delete
|
Delete
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@ -189,22 +212,16 @@ const CollectionItem = ({item, collection, searchText}) => {
|
|||||||
|
|
||||||
{!itemIsCollapsed ? (
|
{!itemIsCollapsed ? (
|
||||||
<div>
|
<div>
|
||||||
{requestItems && requestItems.length ? requestItems.map((i) => {
|
{requestItems && requestItems.length
|
||||||
return <CollectionItem
|
? requestItems.map((i) => {
|
||||||
key={i.uid}
|
return <CollectionItem key={i.uid} item={i} collection={collection} searchText={searchText} />;
|
||||||
item={i}
|
})
|
||||||
collection={collection}
|
: null}
|
||||||
searchText={searchText}
|
{folderItems && folderItems.length
|
||||||
/>
|
? folderItems.map((i) => {
|
||||||
}) : null}
|
return <CollectionItem key={i.uid} item={i} collection={collection} searchText={searchText} />;
|
||||||
{folderItems && folderItems.length ? folderItems.map((i) => {
|
})
|
||||||
return <CollectionItem
|
: null}
|
||||||
key={i.uid}
|
|
||||||
item={i}
|
|
||||||
collection={collection}
|
|
||||||
searchText={searchText}
|
|
||||||
/>
|
|
||||||
}) : null}
|
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -10,20 +10,14 @@ const DeleteCollection = ({onClose, collection}) => {
|
|||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
dispatch(deleteCollection(collection.uid))
|
dispatch(deleteCollection(collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection deleted");
|
toast.success('Collection deleted');
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while deleting the collection"));
|
.catch(() => toast.error('An error occured while deleting the collection'));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="sm" title="Delete Collection" confirmText="Delete" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title="Delete Collection"
|
|
||||||
confirmText="Delete"
|
|
||||||
handleConfirm={onConfirm}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
Are you sure you want to delete the collection <span className="font-semibold">{collection.name}</span> ?
|
Are you sure you want to delete the collection <span className="font-semibold">{collection.name}</span> ?
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -14,23 +14,19 @@ const RemoveCollectionFromWorkspace = ({onClose, collection}) => {
|
|||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
dispatch(removeCollectionFromWorkspace(activeWorkspaceUid, collection.uid))
|
dispatch(removeCollectionFromWorkspace(activeWorkspaceUid, collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(closeTabs({
|
dispatch(
|
||||||
|
closeTabs({
|
||||||
tabUids: recursivelyGetAllItemUids(collection.items)
|
tabUids: recursivelyGetAllItemUids(collection.items)
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.then(() => dispatch(removeLocalCollection(collection.uid)))
|
.then(() => dispatch(removeLocalCollection(collection.uid)))
|
||||||
.then(() => toast.success("Collection removed from workspace"))
|
.then(() => toast.success('Collection removed from workspace'))
|
||||||
.catch((err) => console.log(err) && toast.error("An error occured while removing the collection"));
|
.catch((err) => console.log(err) && toast.error('An error occured while removing the collection'));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title="Remove Collection from Workspace" confirmText="Remove" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title="Remove Collection from Workspace"
|
|
||||||
confirmText="Remove"
|
|
||||||
handleConfirm={onConfirm}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
Are you sure you want to remove the collection <span className="font-semibold">{collection.name}</span> from this workspace?
|
Are you sure you want to remove the collection <span className="font-semibold">{collection.name}</span> from this workspace?
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -10,20 +10,14 @@ const RemoveLocalCollection = ({onClose, collection}) => {
|
|||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
dispatch(removeLocalCollection(collection.uid))
|
dispatch(removeLocalCollection(collection.uid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection removed");
|
toast.success('Collection removed');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while removing the collection"));
|
.catch(() => toast.error('An error occured while removing the collection'));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title="Remove Collection" confirmText="Remove" handleConfirm={onConfirm} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title="Remove Collection"
|
|
||||||
confirmText="Remove"
|
|
||||||
handleConfirm={onConfirm}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
Are you sure you want to remove this collection?
|
Are you sure you want to remove this collection?
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -15,10 +15,7 @@ const RenameCollection = ({collection, onClose}) => {
|
|||||||
name: collection.name
|
name: collection.name
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(renameCollection(values.name, collection.uid));
|
dispatch(renameCollection(values.name, collection.uid));
|
||||||
@ -36,27 +33,26 @@ const RenameCollection = ({collection, onClose}) => {
|
|||||||
const onSubmit = () => formik.handleSubmit();
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title="Rename Collection" confirmText="Rename" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title="Rename Collection"
|
|
||||||
confirmText='Rename'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-name" type="text" name="name"
|
id="collection-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -14,15 +14,14 @@ const Wrapper = styled.div`
|
|||||||
|
|
||||||
.collection-actions {
|
.collection-actions {
|
||||||
.dropdown {
|
.dropdown {
|
||||||
div[aria-expanded="true"] {
|
div[aria-expanded='true'] {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
div[aria-expanded="false"] {
|
div[aria-expanded='false'] {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
color: rgb(110 110 110);
|
color: rgb(110 110 110);
|
||||||
@ -32,7 +31,7 @@ const Wrapper = styled.div`
|
|||||||
&:hover {
|
&:hover {
|
||||||
.collection-actions {
|
.collection-actions {
|
||||||
.dropdown {
|
.dropdown {
|
||||||
div[aria-expanded="false"] {
|
div[aria-expanded='false'] {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ const Collection = ({collection, searchText}) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const menuDropdownTippyRef = useRef();
|
const menuDropdownTippyRef = useRef();
|
||||||
const onMenuDropdownCreate = (ref) => menuDropdownTippyRef.current = ref;
|
const onMenuDropdownCreate = (ref) => (menuDropdownTippyRef.current = ref);
|
||||||
const MenuIcon = forwardRef((props, ref) => {
|
const MenuIcon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="pr-2">
|
<div ref={ref} className="pr-2">
|
||||||
@ -84,58 +84,75 @@ const Collection = ({collection, searchText}) => {
|
|||||||
<IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{ width: 16, color: 'rgb(160 160 160)' }} />
|
<IconChevronRight size={16} strokeWidth={2} className={iconClassName} style={{ width: 16, color: 'rgb(160 160 160)' }} />
|
||||||
<div className="ml-1">{collection.name}</div>
|
<div className="ml-1">{collection.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='collection-actions'>
|
<div className="collection-actions">
|
||||||
<Dropdown
|
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
||||||
onCreate={onMenuDropdownCreate}
|
<div
|
||||||
icon={<MenuIcon />}
|
className="dropdown-item"
|
||||||
placement='bottom-start'
|
onClick={(e) => {
|
||||||
>
|
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowNewRequestModal(true);
|
setShowNewRequestModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
New Request
|
New Request
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowNewFolderModal(true);
|
setShowNewFolderModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
New Folder
|
New Folder
|
||||||
</div>
|
</div>
|
||||||
{!isLocal ? (
|
{!isLocal ? (
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowRenameCollectionModal(true);
|
setShowRenameCollectionModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Rename
|
Rename
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
handleExportClick(true);
|
handleExportClick(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Export
|
Export
|
||||||
</div>
|
</div>
|
||||||
{!isLocal ? (
|
{!isLocal ? (
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowRemoveCollectionFromWSModal(true);
|
setShowRemoveCollectionFromWSModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Remove from Workspace
|
Remove from Workspace
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowRemoveLocalCollectionModal(true);
|
setShowRemoveLocalCollectionModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Remove
|
Remove
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isLocal ? (
|
{!isLocal ? (
|
||||||
<div className="dropdown-item delete-collection" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item delete-collection"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setShowDeleteCollectionModal(true);
|
setShowDeleteCollectionModal(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Delete
|
Delete
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
@ -146,23 +163,17 @@ const Collection = ({collection, searchText}) => {
|
|||||||
<div>
|
<div>
|
||||||
{!collectionIsCollapsed ? (
|
{!collectionIsCollapsed ? (
|
||||||
<div>
|
<div>
|
||||||
{requestItems && requestItems.length ? requestItems.map((i) => {
|
{requestItems && requestItems.length
|
||||||
return <CollectionItem
|
? requestItems.map((i) => {
|
||||||
key={i.uid}
|
return <CollectionItem key={i.uid} item={i} collection={collection} searchText={searchText} />;
|
||||||
item={i}
|
})
|
||||||
collection={collection}
|
: null}
|
||||||
searchText={searchText}
|
|
||||||
/>
|
|
||||||
}) : null}
|
|
||||||
|
|
||||||
{folderItems && folderItems.length ? folderItems.map((i) => {
|
{folderItems && folderItems.length
|
||||||
return <CollectionItem
|
? folderItems.map((i) => {
|
||||||
key={i.uid}
|
return <CollectionItem key={i.uid} item={i} collection={collection} searchText={searchText} />;
|
||||||
item={i}
|
})
|
||||||
collection={collection}
|
: null}
|
||||||
searchText={searchText}
|
|
||||||
/>
|
|
||||||
}) : null}
|
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,43 +16,42 @@ const CreateOrAddCollection = () => {
|
|||||||
setCreateCollectionModalOpen(false);
|
setCreateCollectionModalOpen(false);
|
||||||
dispatch(createCollection(values.collectionName))
|
dispatch(createCollection(values.collectionName))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection created");
|
toast.success('Collection created');
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while creating the collection"));
|
.catch(() => toast.error('An error occured while creating the collection'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddCollectionToWorkspace = (collectionUid) => {
|
const handleAddCollectionToWorkspace = (collectionUid) => {
|
||||||
setAddCollectionToWSModalOpen(false);
|
setAddCollectionToWSModalOpen(false);
|
||||||
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection added to workspace");
|
toast.success('Collection added to workspace');
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while adding collection to workspace"));
|
.catch(() => toast.error('An error occured while adding collection to workspace'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const CreateLink = () => <span className='underline text-link cursor-pointer' onClick={() => setCreateCollectionModalOpen(true)}>Create</span>;
|
const CreateLink = () => (
|
||||||
const AddLink = () => <span className='underline text-link cursor-pointer' onClick={() => setAddCollectionToWSModalOpen(true)}>Add</span>;
|
<span className="underline text-link cursor-pointer" onClick={() => setCreateCollectionModalOpen(true)}>
|
||||||
|
Create
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
const AddLink = () => (
|
||||||
|
<span className="underline text-link cursor-pointer" onClick={() => setAddCollectionToWSModalOpen(true)}>
|
||||||
|
Add
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='px-2 mt-4 text-gray-600'>
|
<div className="px-2 mt-4 text-gray-600">
|
||||||
{createCollectionModalOpen ? (
|
{createCollectionModalOpen ? <CreateCollection handleCancel={() => setCreateCollectionModalOpen(false)} handleConfirm={handleCreateCollection} /> : null}
|
||||||
<CreateCollection
|
|
||||||
handleCancel={() => setCreateCollectionModalOpen(false)}
|
|
||||||
handleConfirm={handleCreateCollection}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{addCollectionToWSModalOpen ? (
|
{addCollectionToWSModalOpen ? (
|
||||||
<SelectCollection
|
<SelectCollection title="Add Collection to Workspace" onClose={() => setAddCollectionToWSModalOpen(false)} onSelect={handleAddCollectionToWorkspace} />
|
||||||
title='Add Collection to Workspace'
|
|
||||||
onClose={() => setAddCollectionToWSModalOpen(false)}
|
|
||||||
onSelect={handleAddCollectionToWorkspace}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className='text-xs text-center'>
|
<div className="text-xs text-center">
|
||||||
<div>No collections found.</div>
|
<div>No collections found.</div>
|
||||||
<div className='mt-2'>
|
<div className="mt-2">
|
||||||
<CreateLink /> or <AddLink /> Collection to Workspace.
|
<CreateLink /> or <AddLink /> Collection to Workspace.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import filter from "lodash/filter";
|
import filter from 'lodash/filter';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import { IconFiles } from '@tabler/icons';
|
import { IconFiles } from '@tabler/icons';
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from 'react-redux';
|
||||||
import { isLocalCollection } from "utils/collections";
|
import { isLocalCollection } from 'utils/collections';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const SelectCollection = ({ onClose, onSelect, title }) => {
|
const SelectCollection = ({ onClose, onSelect, title }) => {
|
||||||
@ -12,24 +12,21 @@ const SelectCollection = ({onClose, onSelect, title}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="sm" title={title || 'Select Collection'} hideFooter={true} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={title || "Select Collection"}
|
|
||||||
hideFooter={true}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<ul className="mb-2">
|
<ul className="mb-2">
|
||||||
{(collectionsToDisplay && collectionsToDisplay.length) ? collectionsToDisplay.map((c) => (
|
{collectionsToDisplay && collectionsToDisplay.length ? (
|
||||||
|
collectionsToDisplay.map((c) => (
|
||||||
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
<div className="collection" key={c.uid} onClick={() => onSelect(c.uid)}>
|
||||||
<IconFiles size={18} strokeWidth={1.5} /> <span className="ml-2">{c.name}</span>
|
<IconFiles size={18} strokeWidth={1.5} /> <span className="ml-2">{c.name}</span>
|
||||||
</div>
|
</div>
|
||||||
)) : (
|
))
|
||||||
|
) : (
|
||||||
<div>No collections found</div>
|
<div>No collections found</div>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</Modal>
|
</Modal>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default SelectCollection;
|
export default SelectCollection;
|
||||||
|
@ -10,7 +10,7 @@ import { isLocalCollection } from 'utils/collections';
|
|||||||
const Collections = ({ searchText }) => {
|
const Collections = ({ searchText }) => {
|
||||||
const { collections } = useSelector((state) => state.collections);
|
const { collections } = useSelector((state) => state.collections);
|
||||||
const { workspaces, activeWorkspaceUid } = useSelector((state) => state.workspaces);
|
const { workspaces, activeWorkspaceUid } = useSelector((state) => state.workspaces);
|
||||||
const activeWorkspace = find(workspaces, w => w.uid === activeWorkspaceUid);
|
const activeWorkspace = find(workspaces, (w) => w.uid === activeWorkspaceUid);
|
||||||
|
|
||||||
if (!activeWorkspace) {
|
if (!activeWorkspace) {
|
||||||
return null;
|
return null;
|
||||||
@ -24,13 +24,11 @@ const Collections = ({searchText}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 flex flex-col">
|
<div className="mt-4 flex flex-col">
|
||||||
{collectionToDisplay && collectionToDisplay.length ? collectionToDisplay.map((c) => {
|
{collectionToDisplay && collectionToDisplay.length
|
||||||
return <Collection
|
? collectionToDisplay.map((c) => {
|
||||||
searchText={searchText}
|
return <Collection searchText={searchText} collection={c} key={c.uid} />;
|
||||||
collection={c}
|
})
|
||||||
key={c.uid}
|
: null}
|
||||||
/>
|
|
||||||
}) : null}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,19 +20,16 @@ const CreateCollection = ({onClose, isLocal}) => {
|
|||||||
collectionLocation: ''
|
collectionLocation: ''
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
collectionName: Yup.string()
|
collectionName: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
const action = isLocal && isPlatformElectron ? createLocalCollection : createCollection;
|
const action = isLocal && isPlatformElectron ? createLocalCollection : createCollection;
|
||||||
dispatch(action(values.collectionName, values.collectionLocation))
|
dispatch(action(values.collectionName, values.collectionLocation))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection created");
|
toast.success('Collection created');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while creating the collection"));
|
.catch(() => toast.error('An error occured while creating the collection'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -56,16 +53,12 @@ const CreateCollection = ({onClose, isLocal}) => {
|
|||||||
const onSubmit = () => formik.handleSubmit();
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title="Create Collection" confirmText="Create" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title='Create Collection'
|
|
||||||
confirmText='Create'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="collectionName" className="block font-semibold">Name</label>
|
<label htmlFor="collectionName" className="block font-semibold">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-name"
|
id="collection-name"
|
||||||
type="text"
|
type="text"
|
||||||
@ -73,23 +66,29 @@ const CreateCollection = ({onClose, isLocal}) => {
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={formik.values.collectionName || ''}
|
value={formik.values.collectionName || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.collectionName && formik.errors.collectionName ? (
|
{formik.touched.collectionName && formik.errors.collectionName ? <div className="text-red-500">{formik.errors.collectionName}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.collectionName}</div>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{isLocal && isPlatformElectron ? (
|
{isLocal && isPlatformElectron ? (
|
||||||
<>
|
<>
|
||||||
<label htmlFor="collectionLocation" className="block font-semibold mt-3">Location</label>
|
<label htmlFor="collectionLocation" className="block font-semibold mt-3">
|
||||||
|
Location
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-location"
|
id="collection-location"
|
||||||
type="text"
|
type="text"
|
||||||
name="collectionLocation"
|
name="collectionLocation"
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
value={formik.values.collectionLocation || ''}
|
value={formik.values.collectionLocation || ''}
|
||||||
onClick={browse}
|
onClick={browse}
|
||||||
/>
|
/>
|
||||||
@ -101,7 +100,9 @@ const CreateCollection = ({onClose, isLocal}) => {
|
|||||||
|
|
||||||
{isLocal && isPlatformElectron ? (
|
{isLocal && isPlatformElectron ? (
|
||||||
<div className="mt-1">
|
<div className="mt-1">
|
||||||
<span className="text-link cursor-pointer hover:underline" onClick={browse}>Browse</span>
|
<span className="text-link cursor-pointer hover:underline" onClick={browse}>
|
||||||
|
Browse
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
.current-workspace {
|
.current-workspace {
|
||||||
margin-inline: .5rem;
|
margin-inline: 0.5rem;
|
||||||
background: #e1e1e1;
|
background: #e1e1e1;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
|
@ -24,38 +24,29 @@ const LocalCollections = ({searchText}) => {
|
|||||||
const Icon = forwardRef((props, ref) => {
|
const Icon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="current-workspace flex justify-between items-center pl-2 pr-2 py-1 select-none">
|
<div ref={ref} className="current-workspace flex justify-between items-center pl-2 pr-2 py-1 select-none">
|
||||||
<div className='flex items-center'>
|
<div className="flex items-center">
|
||||||
<span className='mr-2'>
|
<span className="mr-2">
|
||||||
<IconFolders size={18} strokeWidth={1.5} />
|
<IconFolders size={18} strokeWidth={1.5} />
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>Local Collections</span>
|
||||||
Local Collections
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<IconCaretDown className="caret" size={14} strokeWidth={2} />
|
<IconCaretDown className="caret" size={14} strokeWidth={2} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onDropdownCreate = (ref) => dropdownTippyRef.current = ref;
|
const onDropdownCreate = (ref) => (dropdownTippyRef.current = ref);
|
||||||
|
|
||||||
|
|
||||||
const handleOpenLocalCollection = () => {
|
const handleOpenLocalCollection = () => {
|
||||||
dispatch(openLocalCollection())
|
dispatch(openLocalCollection()).catch((err) => console.log(err) && toast.error('An error occured while opening the local collection'));
|
||||||
.catch((err) => console.log(err) && toast.error("An error occured while opening the local collection"));
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
{createCollectionModalOpen ? (
|
{createCollectionModalOpen ? <CreateCollection isLocal={true} onClose={() => setCreateCollectionModalOpen(false)} /> : null}
|
||||||
<CreateCollection
|
|
||||||
isLocal={true}
|
|
||||||
onClose={() => setCreateCollectionModalOpen(false)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<div className="items-center cursor-pointer mt-6 relative">
|
<div className="items-center cursor-pointer mt-6 relative">
|
||||||
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement='bottom-end'>
|
<Dropdown onCreate={onDropdownCreate} icon={<Icon />} placement="bottom-end">
|
||||||
<div className="dropdown-item" onClick={() => setCreateCollectionModalOpen(true)}>
|
<div className="dropdown-item" onClick={() => setCreateCollectionModalOpen(true)}>
|
||||||
<div className="pr-2 text-gray-600">
|
<div className="pr-2 text-gray-600">
|
||||||
<IconPlus size={18} strokeWidth={1.5} />
|
<IconPlus size={18} strokeWidth={1.5} />
|
||||||
@ -69,19 +60,17 @@ const LocalCollections = ({searchText}) => {
|
|||||||
<span>Open Collection</span>
|
<span>Open Collection</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='px-2 pt-2 text-gray-600' style={{fontSize: 10, borderTop: 'solid 1px #e7e7e7'}}>
|
<div className="px-2 pt-2 text-gray-600" style={{ fontSize: 10, borderTop: 'solid 1px #e7e7e7' }}>
|
||||||
Note: Local collections are not tied to a workspace
|
Note: Local collections are not tied to a workspace
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex flex-col">
|
<div className="mt-4 flex flex-col">
|
||||||
{collectionToDisplay && collectionToDisplay.length ? collectionToDisplay.map((c) => {
|
{collectionToDisplay && collectionToDisplay.length
|
||||||
return <Collection
|
? collectionToDisplay.map((c) => {
|
||||||
searchText={searchText}
|
return <Collection searchText={searchText} collection={c} key={c.uid} />;
|
||||||
collection={c}
|
})
|
||||||
key={c.uid}
|
: null}
|
||||||
/>
|
|
||||||
}) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
|
@ -9,7 +9,8 @@ const Wrapper = styled.div`
|
|||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover, &.active {
|
&:hover,
|
||||||
|
&.active {
|
||||||
color: rgba(255, 255, 255);
|
color: rgba(255, 255, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ const MenuBar = () => {
|
|||||||
const isPlatformElectron = isElectron();
|
const isPlatformElectron = isElectron();
|
||||||
|
|
||||||
const getClassName = (menu) => {
|
const getClassName = (menu) => {
|
||||||
return router.pathname === menu ? "active menu-item": "menu-item";
|
return router.pathname === menu ? 'active menu-item' : 'menu-item';
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -15,15 +15,12 @@ const NewFolder = ({collection, item, onClose}) => {
|
|||||||
folderName: ''
|
folderName: ''
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
folderName: Yup.string()
|
folderName: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(newFolder(values.folderName, collection.uid, item ? item.uid : null))
|
dispatch(newFolder(values.folderName, collection.uid, item ? item.uid : null))
|
||||||
.then(() => onClose())
|
.then(() => onClose())
|
||||||
.catch(() => toast.error("An error occured while adding the request"));
|
.catch(() => toast.error('An error occured while adding the request'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -36,27 +33,26 @@ const NewFolder = ({collection, item, onClose}) => {
|
|||||||
const onSubmit = () => formik.handleSubmit();
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal size="sm" title="New Folder" confirmText="Create" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title='New Folder'
|
|
||||||
confirmText='Create'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="folderName" className="block font-semibold">Folder Name</label>
|
<label htmlFor="folderName" className="block font-semibold">
|
||||||
|
Folder Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-name" type="text" name="folderName"
|
id="collection-name"
|
||||||
|
type="text"
|
||||||
|
name="folderName"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.folderName || ''}
|
value={formik.values.folderName || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.folderName && formik.errors.folderName ? (
|
{formik.touched.folderName && formik.errors.folderName ? <div className="text-red-500">{formik.errors.folderName}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.folderName}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -13,7 +13,8 @@ const StyledWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.method-selector-container, div.input-container {
|
div.method-selector-container,
|
||||||
|
div.input-container {
|
||||||
height: 2.3rem;
|
height: 2.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React, { useRef, useEffect } from 'react';
|
|||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { uuid } from 'utils/common';;
|
import { uuid } from 'utils/common';
|
||||||
import Modal from 'components/Modal';
|
import Modal from 'components/Modal';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { newEphermalHttpRequest } from 'providers/ReduxStore/slices/collections';
|
import { newEphermalHttpRequest } from 'providers/ReduxStore/slices/collections';
|
||||||
@ -23,41 +23,44 @@ const NewRequest = ({collection, item, isEphermal, onClose}) => {
|
|||||||
requestMethod: 'GET'
|
requestMethod: 'GET'
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
requestName: Yup.string()
|
requestName: Yup.string().min(1, 'must be atleast 1 characters').max(50, 'must be 50 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(50, 'must be 50 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
if (isEphermal) {
|
if (isEphermal) {
|
||||||
const uid = uuid();
|
const uid = uuid();
|
||||||
dispatch(newEphermalHttpRequest({
|
dispatch(
|
||||||
|
newEphermalHttpRequest({
|
||||||
uid: uid,
|
uid: uid,
|
||||||
requestName: values.requestName,
|
requestName: values.requestName,
|
||||||
requestType: values.requestType,
|
requestType: values.requestType,
|
||||||
requestUrl: values.requestUrl,
|
requestUrl: values.requestUrl,
|
||||||
requestMethod: values.requestMethod,
|
requestMethod: values.requestMethod,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(addTab({
|
dispatch(
|
||||||
|
addTab({
|
||||||
uid: uid,
|
uid: uid,
|
||||||
collectionUid: collection.uid
|
collectionUid: collection.uid
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while adding the request"));
|
.catch(() => toast.error('An error occured while adding the request'));
|
||||||
} else {
|
} else {
|
||||||
dispatch(newHttpRequest({
|
dispatch(
|
||||||
|
newHttpRequest({
|
||||||
requestName: values.requestName,
|
requestName: values.requestName,
|
||||||
requestType: values.requestType,
|
requestType: values.requestType,
|
||||||
requestUrl: values.requestUrl,
|
requestUrl: values.requestUrl,
|
||||||
requestMethod: values.requestMethod,
|
requestMethod: values.requestMethod,
|
||||||
collectionUid: collection.uid,
|
collectionUid: collection.uid,
|
||||||
itemUid: item ? item.uid : null
|
itemUid: item ? item.uid : null
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
.then(() => onClose())
|
.then(() => onClose())
|
||||||
.catch(() => toast.error("An error occured while adding the request"));
|
.catch(() => toast.error('An error occured while adding the request'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -72,60 +75,69 @@ const NewRequest = ({collection, item, isEphermal, onClose}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Modal
|
<Modal size="md" title="New Request" confirmText="Create" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="md"
|
|
||||||
title='New Request'
|
|
||||||
confirmText='Create'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div className="hidden">
|
<div className="hidden">
|
||||||
<label htmlFor="requestName" className="block font-semibold">Type</label>
|
<label htmlFor="requestName" className="block font-semibold">
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="flex items-center mt-2">
|
<div className="flex items-center mt-2">
|
||||||
<input
|
<input
|
||||||
id="http"
|
id="http"
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
type="radio" name="requestType"
|
type="radio"
|
||||||
|
name="requestType"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value="http"
|
value="http"
|
||||||
checked={formik.values.requestType === 'http-request'}
|
checked={formik.values.requestType === 'http-request'}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="http" className="ml-1 cursor-pointer select-none">Http</label>
|
<label htmlFor="http" className="ml-1 cursor-pointer select-none">
|
||||||
|
Http
|
||||||
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="graphql"
|
id="graphql"
|
||||||
className="ml-4 cursor-pointer"
|
className="ml-4 cursor-pointer"
|
||||||
type="radio" name="requestType"
|
type="radio"
|
||||||
|
name="requestType"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
formik.setFieldValue('requestMethod', 'POST')
|
formik.setFieldValue('requestMethod', 'POST');
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
}}
|
}}
|
||||||
value="graphql"
|
value="graphql"
|
||||||
checked={formik.values.requestType === 'graphql-request'}
|
checked={formik.values.requestType === 'graphql-request'}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="graphql" className="ml-1 cursor-pointer select-none">Graphql</label>
|
<label htmlFor="graphql" className="ml-1 cursor-pointer select-none">
|
||||||
|
Graphql
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="requestName" className="block font-semibold">Name</label>
|
<label htmlFor="requestName" className="block font-semibold">
|
||||||
|
Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-name" type="text" name="requestName"
|
id="collection-name"
|
||||||
|
type="text"
|
||||||
|
name="requestName"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.requestName || ''}
|
value={formik.values.requestName || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.requestName && formik.errors.requestName ? (
|
{formik.touched.requestName && formik.errors.requestName ? <div className="text-red-500">{formik.errors.requestName}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.requestName}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<label htmlFor="request-url" className="block font-semibold">Url</label>
|
<label htmlFor="request-url" className="block font-semibold">
|
||||||
|
Url
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="flex items-center mt-2 ">
|
<div className="flex items-center mt-2 ">
|
||||||
<div className="flex items-center h-full method-selector-container">
|
<div className="flex items-center h-full method-selector-container">
|
||||||
@ -133,17 +145,20 @@ const NewRequest = ({collection, item, isEphermal, onClose}) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center flex-grow input-container h-full">
|
<div className="flex items-center flex-grow input-container h-full">
|
||||||
<input
|
<input
|
||||||
id="request-url" type="text" name="requestUrl"
|
id="request-url"
|
||||||
|
type="text"
|
||||||
|
name="requestUrl"
|
||||||
className="px-3 w-full "
|
className="px-3 w-full "
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.requestUrl || ''}
|
value={formik.values.requestUrl || ''}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{formik.touched.requestUrl && formik.errors.requestUrl ? (
|
{formik.touched.requestUrl && formik.errors.requestUrl ? <div className="text-red-500">{formik.errors.requestUrl}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.requestUrl}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -23,7 +23,7 @@ const TitleBar = () => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const menuDropdownTippyRef = useRef();
|
const menuDropdownTippyRef = useRef();
|
||||||
const onMenuDropdownCreate = (ref) => menuDropdownTippyRef.current = ref;
|
const onMenuDropdownCreate = (ref) => (menuDropdownTippyRef.current = ref);
|
||||||
const MenuIcon = forwardRef((props, ref) => {
|
const MenuIcon = forwardRef((props, ref) => {
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="dropdown-icon cursor-pointer">
|
<div ref={ref} className="dropdown-icon cursor-pointer">
|
||||||
@ -35,17 +35,16 @@ const TitleBar = () => {
|
|||||||
const handleTitleClick = () => dispatch(showHomePage());
|
const handleTitleClick = () => dispatch(showHomePage());
|
||||||
|
|
||||||
const handleOpenLocalCollection = () => {
|
const handleOpenLocalCollection = () => {
|
||||||
dispatch(openLocalCollection())
|
dispatch(openLocalCollection()).catch((err) => console.log(err) && toast.error('An error occured while opening the local collection'));
|
||||||
.catch((err) => console.log(err) && toast.error("An error occured while opening the local collection"));
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const handleAddCollectionToWorkspace = (collectionUid) => {
|
const handleAddCollectionToWorkspace = (collectionUid) => {
|
||||||
setAddCollectionToWSModalOpen(false);
|
setAddCollectionToWSModalOpen(false);
|
||||||
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection added to workspace");
|
toast.success('Collection added to workspace');
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while adding collection to workspace"));
|
.catch(() => toast.error('An error occured while adding collection to workspace'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleImportCollection = () => {
|
const handleImportCollection = () => {
|
||||||
@ -59,19 +58,10 @@ const TitleBar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="px-2 py-2">
|
<StyledWrapper className="px-2 py-2">
|
||||||
{createCollectionModalOpen ? (
|
{createCollectionModalOpen ? <CreateCollection isLocal={createCollectionModalOpen === 'local' ? true : false} onClose={() => setCreateCollectionModalOpen(false)} /> : null}
|
||||||
<CreateCollection
|
|
||||||
isLocal={createCollectionModalOpen === 'local' ? true : false}
|
|
||||||
onClose={() => setCreateCollectionModalOpen(false)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{addCollectionToWSModalOpen ? (
|
{addCollectionToWSModalOpen ? (
|
||||||
<SelectCollection
|
<SelectCollection title="Add Collection to Workspace" onClose={() => setAddCollectionToWSModalOpen(false)} onSelect={handleAddCollectionToWorkspace} />
|
||||||
title='Add Collection to Workspace'
|
|
||||||
onClose={() => setAddCollectionToWSModalOpen(false)}
|
|
||||||
onSelect={handleAddCollectionToWorkspace}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@ -86,47 +76,60 @@ const TitleBar = () => {
|
|||||||
bruno
|
bruno
|
||||||
</div>
|
</div>
|
||||||
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
<div className="collection-dropdown flex flex-grow items-center justify-end">
|
||||||
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement='bottom-start'>
|
<Dropdown onCreate={onMenuDropdownCreate} icon={<MenuIcon />} placement="bottom-start">
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setCreateCollectionModalOpen(true);
|
setCreateCollectionModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Create Collection
|
Create Collection
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
handleImportCollection();
|
handleImportCollection();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Import Collection
|
Import Collection
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
setAddCollectionToWSModalOpen(true);
|
setAddCollectionToWSModalOpen(true);
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Add Collection to Workspace
|
Add Collection to Workspace
|
||||||
</div>
|
</div>
|
||||||
{isPlatformElectron ? (
|
{isPlatformElectron ? (
|
||||||
<>
|
<>
|
||||||
<div className="font-medium label-item font-medium local-collection-label">
|
<div className="font-medium label-item font-medium local-collection-label">
|
||||||
<div className='flex items-center'>
|
<div className="flex items-center">
|
||||||
<span className='mr-2'>
|
<span className="mr-2">
|
||||||
<IconFolders size={18} strokeWidth={1.5} />
|
<IconFolders size={18} strokeWidth={1.5} />
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>Local Collections</span>
|
||||||
Local Collections
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
setCreateCollectionModalOpen('local');
|
setCreateCollectionModalOpen('local');
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Create Local Collection
|
Create Local Collection
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown-item" onClick={(e) => {
|
<div
|
||||||
|
className="dropdown-item"
|
||||||
|
onClick={(e) => {
|
||||||
handleOpenLocalCollection();
|
handleOpenLocalCollection();
|
||||||
menuDropdownTippyRef.current.hide();
|
menuDropdownTippyRef.current.hide();
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Open Local Collection
|
Open Local Collection
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -135,12 +138,11 @@ const TitleBar = () => {
|
|||||||
Note: Local collections are only available on the desktop app.
|
Note: Local collections are only available on the desktop app.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TitleBar;
|
export default TitleBar;
|
||||||
|
@ -36,20 +36,26 @@ const Sidebar = () => {
|
|||||||
if (dragging) {
|
if (dragging) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setDragging(false);
|
setDragging(false);
|
||||||
dispatch(updateLeftSidebarWidth({
|
dispatch(
|
||||||
|
updateLeftSidebarWidth({
|
||||||
leftSidebarWidth: asideWidth
|
leftSidebarWidth: asideWidth
|
||||||
}));
|
})
|
||||||
dispatch(updateIsDragging({
|
);
|
||||||
|
dispatch(
|
||||||
|
updateIsDragging({
|
||||||
isDragging: false
|
isDragging: false
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleDragbarMouseDown = (e) => {
|
const handleDragbarMouseDown = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setDragging(true);
|
setDragging(true);
|
||||||
dispatch(updateIsDragging({
|
dispatch(
|
||||||
|
updateIsDragging({
|
||||||
isDragging: true
|
isDragging: true
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -87,7 +93,10 @@ const Sidebar = () => {
|
|||||||
type="text"
|
type="text"
|
||||||
name="search"
|
name="search"
|
||||||
id="search"
|
id="search"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
className="block w-full pl-7 py-1 sm:text-sm"
|
className="block w-full pl-7 py-1 sm:text-sm"
|
||||||
placeholder="search"
|
placeholder="search"
|
||||||
onChange={(e) => setSearchText(e.target.value.toLowerCase())}
|
onChange={(e) => setSearchText(e.target.value.toLowerCase())}
|
||||||
@ -103,12 +112,17 @@ const Sidebar = () => {
|
|||||||
{/* <IconLayoutGrid size={20} strokeWidth={1.5} className="mr-2"/> */}
|
{/* <IconLayoutGrid size={20} strokeWidth={1.5} className="mr-2"/> */}
|
||||||
{/* Need to ut github stars link here */}
|
{/* Need to ut github stars link here */}
|
||||||
</div>
|
</div>
|
||||||
<div className='pl-1'>
|
<div className="pl-1">
|
||||||
<iframe src="https://ghbtns.com/github-btn.html?user=usebruno&repo=bruno&type=star&count=true" frameBorder="0" scrolling="0" width="100" height="20" title="GitHub"></iframe>
|
<iframe
|
||||||
</div>
|
src="https://ghbtns.com/github-btn.html?user=usebruno&repo=bruno&type=star&count=true"
|
||||||
<div className="flex flex-grow items-center justify-end text-xs mr-2">
|
frameBorder="0"
|
||||||
v1.25.2
|
scrolling="0"
|
||||||
|
width="100"
|
||||||
|
height="20"
|
||||||
|
title="GitHub"
|
||||||
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-grow items-center justify-end text-xs mr-2">v1.25.2</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,9 +9,8 @@ const StyledWrapper = styled.div`
|
|||||||
border: 0.25em solid currentColor;
|
border: 0.25em solid currentColor;
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: spinner-border .75s linear infinite;
|
animation: spinner-border 0.75s linear infinite;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default StyledWrapper;
|
export default StyledWrapper;
|
||||||
|
|
||||||
|
@ -6,13 +6,9 @@ const Spinner = ({size, color, children}) => {
|
|||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<div className="animate-spin"></div>
|
<div className="animate-spin"></div>
|
||||||
{children &&
|
{children && <div>{children}</div>}
|
||||||
<div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Spinner;
|
export default Spinner;
|
||||||
|
@ -20,11 +20,7 @@ const StopWatch = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let seconds = milliseconds / 1000;
|
let seconds = milliseconds / 1000;
|
||||||
return (
|
return <span>{seconds.toFixed(1)}s</span>;
|
||||||
<span>
|
|
||||||
{seconds.toFixed(1)}s
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StopWatch;
|
export default StopWatch;
|
||||||
|
@ -12,16 +12,16 @@ const Wrapper = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bruno-toast-card {
|
.bruno-toast-card {
|
||||||
-webkit-animation-duration: .85s;
|
-webkit-animation-duration: 0.85s;
|
||||||
animation-duration: .85s;
|
animation-duration: 0.85s;
|
||||||
-webkit-animation-delay: .1s;
|
-webkit-animation-delay: 0.1s;
|
||||||
animation-delay: .1s;
|
animation-delay: 0.1s;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: calc(100% - var(--spacing-base-unit));
|
max-width: calc(100% - var(--spacing-base-unit));
|
||||||
margin: 3vh 10vw;
|
margin: 3vh 10vw;
|
||||||
|
|
||||||
animation: fade-and-slide-in-from-top .50s forwards cubic-bezier(.19,1,.22,1);
|
animation: fade-and-slide-in-from-top 0.5s forwards cubic-bezier(0.19, 1, 0.22, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-toast-content {
|
.notification-toast-content {
|
||||||
@ -34,9 +34,9 @@ const Wrapper = styled.div`
|
|||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: .25rem .75rem;
|
padding: 0.25rem 0.75rem;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: .25rem;
|
border-radius: 0.25rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faTimes } from "@fortawesome/free-solid-svg-icons";
|
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
const ToastContent = ({ type, text, handleClose }) => (
|
const ToastContent = ({ type, text, handleClose }) => (
|
||||||
<div className={`alert alert-${type}`} role="alert">
|
<div className={`alert alert-${type}`} role="alert">
|
||||||
@ -12,12 +12,7 @@ const ToastContent = ({type, text, handleClose}) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const Toast = ({
|
const Toast = ({ text, type, duration, handleClose }) => {
|
||||||
text,
|
|
||||||
type,
|
|
||||||
duration,
|
|
||||||
handleClose
|
|
||||||
}) => {
|
|
||||||
let lifetime = duration ? duration : 3000;
|
let lifetime = duration ? duration : 3000;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -27,8 +22,8 @@ const Toast = ({
|
|||||||
}, [text]);
|
}, [text]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className='bruno-toast'>
|
<StyledWrapper className="bruno-toast">
|
||||||
<div className='bruno-toast-card'>
|
<div className="bruno-toast-card">
|
||||||
<ToastContent type={type} text={text} handleClose={handleClose}></ToastContent>
|
<ToastContent type={type} text={text} handleClose={handleClose}></ToastContent>
|
||||||
</div>
|
</div>
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
|
@ -1,15 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import {
|
import { IconPlus, IconUpload, IconFiles, IconFolders, IconPlayerPlay, IconBrandChrome, IconSpeakerphone, IconDeviceDesktop } from '@tabler/icons';
|
||||||
IconPlus,
|
|
||||||
IconUpload,
|
|
||||||
IconFiles,
|
|
||||||
IconFolders,
|
|
||||||
IconPlayerPlay,
|
|
||||||
IconBrandChrome,
|
|
||||||
IconSpeakerphone,
|
|
||||||
IconDeviceDesktop
|
|
||||||
} from '@tabler/icons';
|
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
import { collectionImported } from 'providers/ReduxStore/slices/collections';
|
||||||
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
import { openLocalCollection } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
@ -33,9 +24,9 @@ const Welcome = () => {
|
|||||||
setAddCollectionToWSModalOpen(false);
|
setAddCollectionToWSModalOpen(false);
|
||||||
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collectionUid))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Collection added to workspace");
|
toast.success('Collection added to workspace');
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while adding collection to workspace"));
|
.catch(() => toast.error('An error occured while adding collection to workspace'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleImportCollection = () => {
|
const handleImportCollection = () => {
|
||||||
@ -53,33 +44,23 @@ const Welcome = () => {
|
|||||||
dispatch(collectionImported({ collection: collection }));
|
dispatch(collectionImported({ collection: collection }));
|
||||||
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collection.uid));
|
dispatch(addCollectionToWorkspace(activeWorkspaceUid, collection.uid));
|
||||||
})
|
})
|
||||||
.then(() => toast.success("Sample Collection loaded successfully"))
|
.then(() => toast.success('Sample Collection loaded successfully'))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
toast.error("Load sample collection failed");
|
toast.error('Load sample collection failed');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenLocalCollection = () => {
|
const handleOpenLocalCollection = () => {
|
||||||
dispatch(openLocalCollection())
|
dispatch(openLocalCollection()).catch((err) => console.log(err) && toast.error('An error occured while opening the local collection'));
|
||||||
.catch((err) => console.log(err) && toast.error("An error occured while opening the local collection"));
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper className="pb-4 px-6 mt-6">
|
<StyledWrapper className="pb-4 px-6 mt-6">
|
||||||
{createCollectionModalOpen ? (
|
{createCollectionModalOpen ? <CreateCollection isLocal={createCollectionModalOpen === 'local' ? true : false} onClose={() => setCreateCollectionModalOpen(false)} /> : null}
|
||||||
<CreateCollection
|
|
||||||
isLocal={createCollectionModalOpen === 'local' ? true : false}
|
|
||||||
onClose={() => setCreateCollectionModalOpen(false)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{addCollectionToWSModalOpen ? (
|
{addCollectionToWSModalOpen ? (
|
||||||
<SelectCollection
|
<SelectCollection title="Add Collection to Workspace" onClose={() => setAddCollectionToWSModalOpen(false)} onSelect={handleAddCollectionToWorkspace} />
|
||||||
title='Add Collection to Workspace'
|
|
||||||
onClose={() => setAddCollectionToWSModalOpen(false)}
|
|
||||||
onSelect={handleAddCollectionToWorkspace}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="">
|
<div className="">
|
||||||
@ -91,16 +72,24 @@ const Welcome = () => {
|
|||||||
<div className="uppercase font-semibold create-request mt-10">Collections</div>
|
<div className="uppercase font-semibold create-request mt-10">Collections</div>
|
||||||
<div className="mt-4 flex items-center collection-options select-none">
|
<div className="mt-4 flex items-center collection-options select-none">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<IconPlus size={18} strokeWidth={2}/><span className="label ml-2" onClick={() => setCreateCollectionModalOpen(true)}>Create Collection</span>
|
<IconPlus size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2" onClick={() => setCreateCollectionModalOpen(true)}>
|
||||||
|
Create Collection
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center ml-6">
|
<div className="flex items-center ml-6">
|
||||||
<IconFiles size={18} strokeWidth={2}/><span className="label ml-2" onClick={() => setAddCollectionToWSModalOpen(true)}>Add Collection to Workspace</span>
|
<IconFiles size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2" onClick={() => setAddCollectionToWSModalOpen(true)}>
|
||||||
|
Add Collection to Workspace
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center ml-6" onClick={handleImportCollection}>
|
<div className="flex items-center ml-6" onClick={handleImportCollection}>
|
||||||
<IconUpload size={18} strokeWidth={2}/><span className="label ml-2">Import Collection</span>
|
<IconUpload size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Import Collection</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center ml-6" onClick={handleImportSampleCollection}>
|
<div className="flex items-center ml-6" onClick={handleImportSampleCollection}>
|
||||||
<IconPlayerPlay size={18} strokeWidth={2}/><span className="label ml-2">Load Sample Collection</span>
|
<IconPlayerPlay size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Load Sample Collection</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -108,33 +97,40 @@ const Welcome = () => {
|
|||||||
{isPlatformElectron ? (
|
{isPlatformElectron ? (
|
||||||
<div className="mt-4 flex items-center collection-options select-none">
|
<div className="mt-4 flex items-center collection-options select-none">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<IconPlus size={18} strokeWidth={2}/><span className="label ml-2" onClick={() => setCreateCollectionModalOpen('local')}>Create Collection</span>
|
<IconPlus size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2" onClick={() => setCreateCollectionModalOpen('local')}>
|
||||||
|
Create Collection
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center ml-6">
|
<div className="flex items-center ml-6">
|
||||||
<IconFolders size={18} strokeWidth={2}/><span className="label ml-2" onClick={handleOpenLocalCollection}>Open Collection</span>
|
<IconFolders size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2" onClick={handleOpenLocalCollection}>
|
||||||
|
Open Collection
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-4 flex items-center collection-options select-none text-gray-600 text-xs">
|
<div className="mt-4 flex items-center collection-options select-none text-gray-600 text-xs">Local collections are only available on the desktop app.</div>
|
||||||
Local collections are only available on the desktop app.
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="uppercase font-semibold create-request mt-10 pt-6">Links</div>
|
<div className="uppercase font-semibold create-request mt-10 pt-6">Links</div>
|
||||||
<div className="mt-4 flex flex-col collection-options select-none">
|
<div className="mt-4 flex flex-col collection-options select-none">
|
||||||
<div>
|
<div>
|
||||||
<a href="https://www.usebruno.com/downloads" target="_blank" className="flex items-center">
|
<a href="https://www.usebruno.com/downloads" target="_blank" className="flex items-center">
|
||||||
<IconBrandChrome size={18} strokeWidth={2}/><span className="label ml-2">Chrome Extension</span>
|
<IconBrandChrome size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Chrome Extension</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<a href="https://www.usebruno.com/downloads" target="_blank" className="flex items-center">
|
<a href="https://www.usebruno.com/downloads" target="_blank" className="flex items-center">
|
||||||
<IconDeviceDesktop size={18} strokeWidth={2}/><span className="label ml-2">Desktop App</span>
|
<IconDeviceDesktop size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Desktop App</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="flex items-center">
|
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="flex items-center">
|
||||||
<IconSpeakerphone size={18} strokeWidth={2}/><span className="label ml-2">Report Issues</span>
|
<IconSpeakerphone size={18} strokeWidth={2} />
|
||||||
|
<span className="label ml-2">Report Issues</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="flex items-center mt-2">
|
{/* <div className="flex items-center mt-2">
|
||||||
@ -147,9 +143,8 @@ const Welcome = () => {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</StyledWrapper>
|
</StyledWrapper>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Welcome;
|
export default Welcome;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import Portal from "components/Portal/index";
|
import Portal from 'components/Portal/index';
|
||||||
import Modal from "components/Modal/index";
|
import Modal from 'components/Modal/index';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { addWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
import { addWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
@ -13,21 +13,18 @@ const AddWorkspace = ({onClose}) => {
|
|||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
name: ""
|
name: ''
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
name: Yup.string()
|
name: Yup.string().min(1, 'must be atleast 1 characters').max(30, 'must be 30 characters or less').required('name is required')
|
||||||
.min(1, 'must be atleast 1 characters')
|
|
||||||
.max(30, 'must be 30 characters or less')
|
|
||||||
.required('name is required')
|
|
||||||
}),
|
}),
|
||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
dispatch(addWorkspace(values.name))
|
dispatch(addWorkspace(values.name))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success("Workspace created!");
|
toast.success('Workspace created!');
|
||||||
onClose();
|
onClose();
|
||||||
})
|
})
|
||||||
.catch(() => toast.error("An error occured while creating the workspace"));
|
.catch(() => toast.error('An error occured while creating the workspace'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,37 +36,35 @@ const AddWorkspace = ({onClose}) => {
|
|||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
formik.handleSubmit();
|
formik.handleSubmit();
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<Modal
|
<Modal size="sm" title={'Add Workspace'} confirmText="Add" handleConfirm={onSubmit} handleCancel={onClose}>
|
||||||
size="sm"
|
|
||||||
title={"Add Workspace"}
|
|
||||||
confirmText='Add'
|
|
||||||
handleConfirm={onSubmit}
|
|
||||||
handleCancel={onClose}
|
|
||||||
>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="name" className="block font-semibold">Workspace Name</label>
|
<label htmlFor="name" className="block font-semibold">
|
||||||
|
Workspace Name
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="workspace-name" type="text" name="name"
|
id="workspace-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="block textbox mt-2 w-full"
|
className="block textbox mt-2 w-full"
|
||||||
autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck="false"
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
value={formik.values.name || ''}
|
value={formik.values.name || ''}
|
||||||
/>
|
/>
|
||||||
{formik.touched.name && formik.errors.name ? (
|
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
|
||||||
<div className="text-red-500">{formik.errors.name}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</Portal>
|
</Portal>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default AddWorkspace;
|
export default AddWorkspace;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user