mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Lots
This commit is contained in:
parent
c39b1824c1
commit
b4c48fb411
@ -27,14 +27,16 @@ describe('Requests Actions', () => {
|
||||
type: types.REQUEST_ADD,
|
||||
request: {
|
||||
id: 'rq_1000000000000',
|
||||
_mode: 'json',
|
||||
created: 1000000000000,
|
||||
modified: 1000000000000,
|
||||
name: 'Test Request',
|
||||
name: 'My Request',
|
||||
method: 'GET',
|
||||
url: '',
|
||||
body: '',
|
||||
headers: [],
|
||||
headers: [{
|
||||
name: 'Content-Type',
|
||||
value: 'application/json'
|
||||
}],
|
||||
params: [],
|
||||
authentication: {}
|
||||
}
|
||||
@ -43,7 +45,7 @@ describe('Requests Actions', () => {
|
||||
];
|
||||
|
||||
const store = mockStore();
|
||||
store.dispatch(addRequest('Test Request'));
|
||||
store.dispatch(addRequest());
|
||||
jest.runAllTimers();
|
||||
|
||||
const actions = store.getActions();
|
||||
|
@ -4,11 +4,13 @@ import {loadStart} from "./global";
|
||||
import {loadStop} from "./global";
|
||||
|
||||
const defaultRequestGroup = {
|
||||
id: null,
|
||||
created: 0,
|
||||
modified: 0,
|
||||
name: '',
|
||||
environment: {}
|
||||
id: null,
|
||||
created: 0,
|
||||
modified: 0,
|
||||
collapsed: false,
|
||||
name: '',
|
||||
environment: {},
|
||||
children: []
|
||||
};
|
||||
|
||||
/**
|
||||
@ -43,6 +45,20 @@ export function addRequestGroup (name = 'My Group') {
|
||||
};
|
||||
}
|
||||
|
||||
export function addChildRequest (id, requestId) {
|
||||
return (dispatch) => {
|
||||
dispatch(loadStart());
|
||||
dispatch({type: types.REQUEST_GROUP_ADD_CHILD_REQUEST, id, requestId});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
dispatch(loadStop());
|
||||
resolve();
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function updateRequestGroup (requestGroupPatch) {
|
||||
if (!requestGroupPatch.id) {
|
||||
throw new Error('Cannot update RequestGroup without id');
|
||||
|
@ -5,7 +5,6 @@ import {loadStop} from "./global";
|
||||
|
||||
const defaultRequest = {
|
||||
id: null,
|
||||
_mode: 'json',
|
||||
created: 0,
|
||||
modified: 0,
|
||||
url: '',
|
||||
@ -13,15 +12,13 @@ const defaultRequest = {
|
||||
method: methods.METHOD_GET,
|
||||
body: '',
|
||||
params: [],
|
||||
headers: [],
|
||||
headers: [{
|
||||
name: 'Content-Type',
|
||||
value: 'application/json'
|
||||
}],
|
||||
authentication: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a new request from a subset of fields
|
||||
* @param request values to override defaults with
|
||||
* @returns {*}
|
||||
*/
|
||||
function buildRequest (request) {
|
||||
// Build the required fields
|
||||
const id = request.id || `rq_${Date.now()}`;
|
||||
@ -34,12 +31,18 @@ function buildRequest (request) {
|
||||
});
|
||||
}
|
||||
|
||||
export function addRequest (name = 'My Request') {
|
||||
export function addRequest (requestGroupId = null) {
|
||||
return (dispatch) => {
|
||||
dispatch(loadStart());
|
||||
const request = buildRequest({name});
|
||||
const request = buildRequest({name: 'My Request'});
|
||||
dispatch({type: types.REQUEST_ADD, request});
|
||||
|
||||
if (requestGroupId) {
|
||||
const id = requestGroupId;
|
||||
const requestId = request.id;
|
||||
dispatch({type: types.REQUEST_GROUP_ADD_CHILD_REQUEST, requestId, id});
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
dispatch(loadStop());
|
||||
@ -103,3 +106,7 @@ export function activateRequest (id) {
|
||||
export function changeFilter (filter) {
|
||||
return {type: types.REQUEST_CHANGE_FILTER, filter};
|
||||
}
|
||||
|
||||
export function sendRequest (id) {
|
||||
|
||||
}
|
||||
|
27
app/components/MethodTag.js
Normal file
27
app/components/MethodTag.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React, {Component, PropTypes} from 'react'
|
||||
import * as constants from '../constants/global';
|
||||
|
||||
class MethodTag extends Component {
|
||||
render () {
|
||||
const {method} = this.props;
|
||||
|
||||
let methodName;
|
||||
if (method === constants.METHOD_DELETE || method === constants.METHOD_OPTIONS) {
|
||||
methodName = method.slice(0, 3);
|
||||
} else {
|
||||
methodName = method.slice(0, 4);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={'tag tag--small method-' + method}>
|
||||
{methodName}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MethodTag.propTypes = {
|
||||
method: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default MethodTag;
|
@ -8,13 +8,16 @@ class RequestBodyEditor extends Component {
|
||||
|
||||
render () {
|
||||
const {request, onChange, className} = this.props;
|
||||
const contentTypeHeader = request.headers.find(h => h.name.toLowerCase() === 'content-type');
|
||||
const mode = contentTypeHeader ? contentTypeHeader.value : 'text/plain';
|
||||
|
||||
return (
|
||||
<CodeEditor
|
||||
value={request.body}
|
||||
className={className}
|
||||
onChange={onChange}
|
||||
options={{
|
||||
mode: request._mode,
|
||||
mode: mode,
|
||||
placeholder: 'request body here...'
|
||||
}}
|
||||
/>
|
||||
@ -24,8 +27,7 @@ class RequestBodyEditor extends Component {
|
||||
|
||||
RequestBodyEditor.propTypes = {
|
||||
request: PropTypes.shape({
|
||||
body: PropTypes.string.isRequired,
|
||||
_mode: PropTypes.string.isRequired
|
||||
body: PropTypes.string.isRequired
|
||||
}).isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
@ -12,10 +12,10 @@ class UrlInput extends Component {
|
||||
return (
|
||||
<div className="grid form-control form-control--left form-control--right">
|
||||
<Dropdown>
|
||||
<button className="btn txt-lg">
|
||||
<button className="btn txt-md">
|
||||
{request.method} <i className="fa fa-caret-down"></i>
|
||||
</button>
|
||||
<ul className="bg-super-light">
|
||||
<ul>
|
||||
{METHODS.map((method) => (
|
||||
<li key={method}>
|
||||
<button onClick={onMethodChange.bind(null, method)}>
|
||||
@ -26,12 +26,12 @@ class UrlInput extends Component {
|
||||
</ul>
|
||||
</Dropdown>
|
||||
<Input type="text"
|
||||
className="txt-lg"
|
||||
className="txt-md"
|
||||
placeholder="http://echo.insomnia.rest/status/200"
|
||||
initialValue={request.url}
|
||||
onChange={onUrlChange}/>
|
||||
<button className="btn">
|
||||
<i className="fa fa-repeat txt-xl"></i>
|
||||
<i className="fa fa-repeat txt-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,7 +1,9 @@
|
||||
import React, {Component, PropTypes} from 'react'
|
||||
import Dropdown from './base/Dropdown'
|
||||
import WorkspaceDropdown from './dropdowns/WorkspaceDropdown'
|
||||
import DebouncingInput from './base/DebouncingInput'
|
||||
import RequestActionsDropdown from './dropdowns/RequestActionsDropdown'
|
||||
import MethodTag from './MethodTag'
|
||||
import Dropdown from './base/Dropdown'
|
||||
|
||||
class Sidebar extends Component {
|
||||
onFilterChange (value) {
|
||||
@ -9,80 +11,97 @@ class Sidebar extends Component {
|
||||
}
|
||||
|
||||
renderRequestGroupRow (requestGroup) {
|
||||
const {activeFilter, addRequest, requests} = this.props;
|
||||
const {activeFilter, activeRequest, addRequest, toggleRequestGroup, requests, requestGroups} = this.props;
|
||||
|
||||
const filteredRequests = requests.filter(
|
||||
r => !requestGroup || requestGroup.requests.find(r.id)
|
||||
).filter(
|
||||
r => r.name.toLowerCase().indexOf(activeFilter.toLowerCase()) >= 0
|
||||
let filteredRequests = requests.filter(
|
||||
r => r.name.toLowerCase().indexOf(activeFilter.toLowerCase()) != -1
|
||||
);
|
||||
|
||||
if (requestGroup) {
|
||||
if (!requestGroup) {
|
||||
// Grab all requests that are not children of request groups
|
||||
filteredRequests = filteredRequests.filter(r => {
|
||||
return !requestGroups.find(rg => {
|
||||
return rg.children.find(c => c.id === r.id)
|
||||
})
|
||||
});
|
||||
|
||||
return filteredRequests.map(request => this.renderRequestRow(request));
|
||||
} else {
|
||||
// Grab all of the children for this request group
|
||||
filteredRequests = filteredRequests.filter(
|
||||
r => requestGroup.children.find(c => c.id === r.id)
|
||||
);
|
||||
|
||||
const isActive = activeRequest && filteredRequests.find(r => r.id == activeRequest.id);
|
||||
|
||||
let folderIconClass = 'fa-folder';
|
||||
folderIconClass += requestGroup.collapsed ? '' : '-open';
|
||||
folderIconClass += isActive ? '' : '-o';
|
||||
|
||||
return (
|
||||
<li>
|
||||
<div className="grid">
|
||||
<button className="sidebar__item col text-left">
|
||||
<i className="fa fa-folder-open-o"></i> Request Group
|
||||
</button>
|
||||
<button className="sidebar__item-btn" onClick={(e) => addRequest()}>
|
||||
<i className="fa fa-plus-circle"></i>
|
||||
</button>
|
||||
<li key={requestGroup.id}>
|
||||
<div
|
||||
className={'sidebar__item sidebar__item--bordered ' + (isActive ? 'sidebar__item--active' : '')}>
|
||||
<div className="sidebar__item__row">
|
||||
<button onClick={e => toggleRequestGroup(requestGroup.id)}>
|
||||
<i className={'fa ' + folderIconClass}></i>
|
||||
{requestGroup.name}
|
||||
</button>
|
||||
</div>
|
||||
<div className="sidebar__item__btn">
|
||||
<button onClick={(e) => addRequest(requestGroup.id)}>
|
||||
<i className="fa fa-plus-circle"></i>
|
||||
</button>
|
||||
<Dropdown right={true} className="tall">
|
||||
<button>
|
||||
<i className="fa fa-caret-down"></i>
|
||||
</button>
|
||||
<ul>
|
||||
<li><button>Hello</button></li>
|
||||
<li><button>Hello</button></li>
|
||||
<li><button>Hello</button></li>
|
||||
</ul>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
{filteredRequests.map(request => this.renderRequestRow(request))}
|
||||
{requestGroup.collapsed ? null : filteredRequests.map(request => this.renderRequestRow(request))}
|
||||
</ul>
|
||||
</li>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
filteredRequests.map(request => this.renderRequestRow(request))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
renderRequestRow (request) {
|
||||
const {activeRequest, activateRequest} = this.props;
|
||||
const isActive = activeRequest && request.id === activeRequest.id;
|
||||
const className = ['grid'].concat(isActive ? ['active'] : '');
|
||||
|
||||
return (
|
||||
<li key={request.id} className={className.join(' ')}>
|
||||
<div className="grid">
|
||||
<button className='sidebar__item col' onClick={() => {activateRequest(request.id)}}>
|
||||
{request.name}
|
||||
</button>
|
||||
<RequestActionsDropdown className="sidebar__item-btn" right={true} request={request}/>
|
||||
<li key={request.id}>
|
||||
<div className={'sidebar__item ' + (isActive ? 'sidebar__item--active' : '')}>
|
||||
<div className="sidebar__item__row">
|
||||
<button onClick={() => {activateRequest(request.id)}}>
|
||||
<MethodTag method={request.method}/> {request.name}
|
||||
</button>
|
||||
</div>
|
||||
<RequestActionsDropdown
|
||||
className="sidebar__item__btn"
|
||||
right={true}
|
||||
request={request}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {activeFilter, loading, addRequest, requestGroups} = this.props;
|
||||
const {activeFilter, requestGroups} = this.props;
|
||||
|
||||
return (
|
||||
<aside className="sidebar pane">
|
||||
<div className="grid-v">
|
||||
<header className="pane__header bg-primary">
|
||||
<h1>
|
||||
<Dropdown right={true}>
|
||||
<button className="pane__header__content">
|
||||
<i className="fa fa-angle-down pull-right"></i>
|
||||
{loading ? <i className="fa fa-refresh fa-spin pull-right"></i> : ''}
|
||||
Insomnia
|
||||
</button>
|
||||
<ul className="bg-super-light">
|
||||
<li>
|
||||
<button onClick={(e) => addRequest()}>
|
||||
<i className="fa fa-plus-circle"></i> Add Request
|
||||
</button>
|
||||
</li>
|
||||
<li><button><i className="fa fa-share-square-o"></i> Import/Export</button></li>
|
||||
<li><button><i className="fa fa-empty"></i> Toggle Sidebar</button></li>
|
||||
<li><button><i className="fa fa-empty"></i> Delete Workspace</button></li>
|
||||
</ul>
|
||||
</Dropdown>
|
||||
</h1>
|
||||
<header className="pane__header bg-dark">
|
||||
<h1><WorkspaceDropdown /></h1>
|
||||
</header>
|
||||
<div className="pane__body hide-scrollbars bg-dark">
|
||||
<div className="stock-height form-control form-control--outlined col">
|
||||
@ -106,13 +125,12 @@ class Sidebar extends Component {
|
||||
|
||||
Sidebar.propTypes = {
|
||||
activateRequest: PropTypes.func.isRequired,
|
||||
addRequest: PropTypes.func.isRequired,
|
||||
changeFilter: PropTypes.func.isRequired,
|
||||
toggleRequestGroup: PropTypes.func.isRequired,
|
||||
activeFilter: PropTypes.string,
|
||||
requests: PropTypes.array.isRequired,
|
||||
requestGroups: PropTypes.array.isRequired,
|
||||
activeRequest: PropTypes.object,
|
||||
loading: PropTypes.bool.isRequired
|
||||
activeRequest: PropTypes.object
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
|
@ -31,7 +31,7 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const classes = ['dropdown'];
|
||||
const classes = ['dropdown'].concat(this.props.className || []);
|
||||
|
||||
this.state.open && classes.push('dropdown--open');
|
||||
this.props.right && classes.push('dropdown--right');
|
||||
|
@ -6,15 +6,18 @@ import * as RequestActions from '../../actions/requests'
|
||||
|
||||
class RequestActionsDropdown extends Component {
|
||||
render () {
|
||||
const {actions, request, ...other} = this.props;
|
||||
const {actions, request, buttonClassName, ...other} = this.props;
|
||||
|
||||
return (
|
||||
<Dropdown right={this.props.right || false} {...other}>
|
||||
<button className="pane__header__content">
|
||||
<i className="fa fa-angle-down pull-right"></i>
|
||||
<Dropdown {...other}>
|
||||
<button className={buttonClassName}>
|
||||
<i className="fa fa-gear"></i>
|
||||
</button>
|
||||
<ul className="bg-super-light">
|
||||
<li><button onClick={actions.deleteRequest.bind(null, request.id)}>Delete</button></li>
|
||||
<ul>
|
||||
<li><button>Duplicate</button></li>
|
||||
<li><button>Rename</button></li>
|
||||
<li><button>Export</button></li>
|
||||
<li><button onClick={e => actions.deleteRequest(request.id)}>Delete</button></li>
|
||||
</ul>
|
||||
</Dropdown>
|
||||
)
|
||||
@ -25,7 +28,8 @@ RequestActionsDropdown.propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
deleteRequest: PropTypes.func.isRequired
|
||||
})
|
||||
}),
|
||||
buttonClassName: PropTypes.string
|
||||
};
|
||||
|
||||
function mapStateToProps (state) {
|
||||
|
69
app/components/dropdowns/WorkspaceDropdown.js
Normal file
69
app/components/dropdowns/WorkspaceDropdown.js
Normal file
@ -0,0 +1,69 @@
|
||||
import React, {Component, PropTypes} from 'react'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {connect} from 'react-redux'
|
||||
import Dropdown from '../base/Dropdown'
|
||||
import * as RequestActions from '../../actions/requests'
|
||||
import * as RequestGroupActions from '../../actions/requestGroups'
|
||||
|
||||
class WorkspaceDropdown extends Component {
|
||||
render () {
|
||||
const {actions, loading, ...other} = this.props;
|
||||
|
||||
return (
|
||||
<Dropdown right={true} {...other} className="block">
|
||||
<button className="pane__header__content">
|
||||
<div className="grid">
|
||||
<div className="col">
|
||||
Insomnia
|
||||
</div>
|
||||
<div className="no-wrap">
|
||||
{loading ? <i className="fa fa-refresh fa-spin txt-lg"></i> : ''}
|
||||
<i className="fa fa-caret-down txt-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<ul>
|
||||
<li><button onClick={e => actions.addRequest()}>
|
||||
<i className="fa fa-plus-circle"></i> Add Request
|
||||
</button></li>
|
||||
<li><button onClick={e => actions.addRequestGroup()}>
|
||||
<i className="fa fa-plus-circle"></i> Add Request Group
|
||||
</button></li>
|
||||
<li><button><i className="fa fa-share-square-o"></i> Import/Export</button></li>
|
||||
<li><button><i className="fa fa-empty"></i> Toggle Sidebar</button></li>
|
||||
<li><button><i className="fa fa-empty"></i> Delete Workspace</button></li>
|
||||
</ul>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
WorkspaceDropdown.propTypes = {
|
||||
loading: PropTypes.bool.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
addRequest: PropTypes.func.isRequired,
|
||||
addRequestGroup: PropTypes.func.isRequired
|
||||
})
|
||||
};
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
actions: state.actions,
|
||||
loading: state.loading
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
actions: Object.assign(
|
||||
{},
|
||||
bindActionCreators(RequestActions, dispatch),
|
||||
bindActionCreators(RequestGroupActions, dispatch)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(WorkspaceDropdown);
|
@ -16,3 +16,4 @@ export const REQUEST_GROUP_ADD = 'REQUEST_GROUP.ADD';
|
||||
export const REQUEST_GROUP_UPDATE = 'REQUEST_GROUP.UPDATE';
|
||||
export const REQUEST_GROUP_DELETE = 'REQUEST_GROUP.DELETE';
|
||||
export const REQUEST_GROUP_TOGGLE = 'REQUEST_GROUP.TOGGLE';
|
||||
export const REQUEST_GROUP_ADD_CHILD_REQUEST = 'REQUEST_GROUP.ADD_CHILD_REQUEST';
|
||||
|
@ -9,6 +9,7 @@ export const METHOD_POST = 'POST';
|
||||
export const METHOD_DELETE = 'DELETE';
|
||||
export const METHOD_OPTIONS = 'OPTIONS';
|
||||
export const METHOD_HEAD = 'HEAD';
|
||||
|
||||
export const METHODS = [
|
||||
METHOD_GET,
|
||||
METHOD_PUT,
|
||||
@ -17,3 +18,4 @@ export const METHODS = [
|
||||
METHOD_OPTIONS,
|
||||
METHOD_HEAD
|
||||
];
|
||||
|
||||
|
@ -9,6 +9,7 @@ import RequestUrlBar from '../components/RequestUrlBar'
|
||||
import Sidebar from '../components/Sidebar'
|
||||
|
||||
import * as RequestActions from '../actions/requests'
|
||||
import * as RequestGroupActions from '../actions/requestGroups'
|
||||
import * as GlobalActions from '../actions/global'
|
||||
|
||||
// Don't inject component styles (use our own)
|
||||
@ -27,9 +28,9 @@ class App extends Component {
|
||||
|
||||
return (
|
||||
<div className="grid grid-collapse">
|
||||
<section id="request-pane" className="pane col">
|
||||
<section id="request-pane" className="pane col tall">
|
||||
<div className="grid-v">
|
||||
<header className="pane__header bg-super-light">
|
||||
<header className="pane__header bg-super-dark">
|
||||
<RequestUrlBar
|
||||
onUrlChange={updateRequestUrl}
|
||||
onMethodChange={updateRequestMethod}
|
||||
@ -37,18 +38,17 @@ class App extends Component {
|
||||
</header>
|
||||
<div className="pane__body grid-v">
|
||||
<Tabs selectedIndex={0} className="grid-v">
|
||||
<TabList className="grid">
|
||||
<Tab><button className="btn">Body</button></Tab>
|
||||
<Tab><button className="btn">Params</button></Tab>
|
||||
<Tab><button className="btn">Auth</button></Tab>
|
||||
<Tab><button className="btn">Headers</button></Tab>
|
||||
<TabList className="grid txt-sm">
|
||||
<Tab><button className="btn btn--compact">Body</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Params</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Auth</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Headers</button></Tab>
|
||||
</TabList>
|
||||
<TabPanel className="grid-v">
|
||||
<RequestBodyEditor
|
||||
className="grid-v"
|
||||
onChange={updateRequestBody}
|
||||
request={activeRequest}
|
||||
options={{mode: activeRequest._mode}}/>
|
||||
request={activeRequest}/>
|
||||
</TabPanel>
|
||||
<TabPanel className="grid-v pad">Params</TabPanel>
|
||||
<TabPanel className="grid-v pad">Basic Auth</TabPanel>
|
||||
@ -57,9 +57,9 @@ class App extends Component {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="response-pane" className="pane col">
|
||||
<section id="response-pane" className="pane col tall">
|
||||
<div className="grid-v">
|
||||
<header className="pane__header text-center bg-light">
|
||||
<header className="pane__header text-center bg-super-dark">
|
||||
<div className="grid">
|
||||
<div className="tag success"><strong>200</strong> SUCCESS</div>
|
||||
<div className="tag">TIME <strong>143ms</strong></div>
|
||||
@ -67,11 +67,11 @@ class App extends Component {
|
||||
</header>
|
||||
<div className="pane__body grid-v">
|
||||
<Tabs selectedIndex={0} className="grid-v">
|
||||
<TabList className="grid">
|
||||
<Tab><button className="btn">Response</button></Tab>
|
||||
<Tab><button className="btn">Raw</button></Tab>
|
||||
<Tab><button className="btn">Headers</button></Tab>
|
||||
<Tab><button className="btn">Cookies</button></Tab>
|
||||
<TabList className="grid txt-sm">
|
||||
<Tab><button className="btn btn--compact">Response</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Raw</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Headers</button></Tab>
|
||||
<Tab><button className="btn btn--compact">Cookies</button></Tab>
|
||||
</TabList>
|
||||
<TabPanel className="grid-v">
|
||||
<Editor
|
||||
@ -111,12 +111,13 @@ class App extends Component {
|
||||
activateRequest={actions.activateRequest}
|
||||
changeFilter={actions.changeFilter}
|
||||
addRequest={actions.addRequest}
|
||||
toggleRequestGroup={actions.toggleRequestGroup}
|
||||
activeRequest={activeRequest}
|
||||
activeFilter={requests.filter}
|
||||
loading={loading}
|
||||
requestGroups={requestGroups.all}
|
||||
requests={requests.all}/>
|
||||
<div className="col">
|
||||
<div className="col tall">
|
||||
{this.renderPageBody(actions, activeRequest)}
|
||||
</div>
|
||||
</div>
|
||||
@ -130,15 +131,15 @@ App.propTypes = {
|
||||
updateRequestBody: PropTypes.func.isRequired,
|
||||
updateRequestUrl: PropTypes.func.isRequired,
|
||||
changeFilter: PropTypes.func.isRequired,
|
||||
updateRequestMethod: PropTypes.func.isRequired
|
||||
updateRequestMethod: PropTypes.func.isRequired,
|
||||
toggleRequestGroup: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
requests: PropTypes.shape({
|
||||
all: PropTypes.array.isRequired,
|
||||
active: PropTypes.string // "required" but can be null
|
||||
}).isRequired,
|
||||
requestGroups: PropTypes.shape({
|
||||
all: PropTypes.array.isRequired,
|
||||
collapsed: PropTypes.array.isRequired
|
||||
all: PropTypes.array.isRequired
|
||||
}).isRequired,
|
||||
loading: PropTypes.bool.isRequired
|
||||
};
|
||||
@ -157,7 +158,8 @@ function mapDispatchToProps (dispatch) {
|
||||
actions: Object.assign(
|
||||
{},
|
||||
bindActionCreators(GlobalActions, dispatch),
|
||||
bindActionCreators(RequestActions, dispatch)
|
||||
bindActionCreators(RequestActions, dispatch),
|
||||
bindActionCreators(RequestGroupActions, dispatch)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,7 @@
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
|
||||
&.dropdown--open ul {
|
||||
display: block;
|
||||
@ -21,29 +20,44 @@
|
||||
display: none;
|
||||
z-index: 10;
|
||||
width: 180px;
|
||||
border-radius: $radius-md;
|
||||
padding: 2px 0;
|
||||
margin-top: 4px;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.15);
|
||||
padding-top: 4px;
|
||||
|
||||
a, button {
|
||||
font-size: $font-size-md;
|
||||
text-align: left;
|
||||
padding: 10px $padding-md;
|
||||
width: 100%;
|
||||
display: block;
|
||||
li {
|
||||
background: $bg-super-light;
|
||||
|
||||
&:hover {
|
||||
background: $hl-xs;
|
||||
&:first-child {
|
||||
border-top-left-radius: $radius-md;
|
||||
border-top-right-radius: $radius-md;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: $hl-md;
|
||||
&:last-child {
|
||||
border-bottom-left-radius: $radius-md;
|
||||
border-bottom-right-radius: $radius-md;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
width: 1.5em;
|
||||
& > button {
|
||||
font-size: $font-size-md;
|
||||
text-align: left;
|
||||
padding: 10px $padding-md;
|
||||
width: 100%;
|
||||
display: block;
|
||||
color: $font-light-bg !important;
|
||||
|
||||
&:hover {
|
||||
background: $hl-sm;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: $hl-md;
|
||||
}
|
||||
|
||||
i.fa {
|
||||
display: inline-block;
|
||||
width: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
width: 100%;
|
||||
font-family: "Source Code Pro", monospace;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.CodeMirror,
|
||||
@ -43,7 +44,7 @@
|
||||
}
|
||||
|
||||
.CodeMirror-placeholder {
|
||||
color: $hl-xl;
|
||||
color: $hl-xxl;
|
||||
}
|
||||
|
||||
&.editor--readonly .CodeMirror-cursors {
|
||||
|
@ -34,14 +34,13 @@
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
padding: 0 ($padding-md * 1.5);
|
||||
height: $line-height-md;
|
||||
|
||||
&.btn--compact {
|
||||
padding: 0 ($padding-md);
|
||||
height: $line-height-md / 2;
|
||||
padding: 0 $padding-md;
|
||||
height: $line-height-sm;
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,4 +70,6 @@ input, button {
|
||||
button {
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -2,5 +2,4 @@
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: darken($bg-primary, 10%);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
.pane__header {
|
||||
border-color: transparent;
|
||||
//border-color: transparent;
|
||||
height: $line-height-md;
|
||||
line-height: $line-height-md;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
.ReactTabs {
|
||||
.ReactTabs__TabList {
|
||||
height: $line-height-md;
|
||||
height: $line-height-sm;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,16 @@
|
||||
margin-right: 1em;
|
||||
line-height: 1em;
|
||||
box-sizing: border-box;
|
||||
border-radius: $radius-md;
|
||||
font-size: $font-size-sm;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.tag--small {
|
||||
padding: $padding-xxs;
|
||||
font-size: $font-size-xs;
|
||||
border-radius: $radius-sm;
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,71 @@
|
||||
/* Background Colors */
|
||||
$bg-primary: #7D70CC;
|
||||
//$bg-primary: #7D70CC;
|
||||
$bg-light: #efefef;
|
||||
$bg-super-light: #fff;
|
||||
$bg-dark: #272824;
|
||||
$bg-super-dark: #222320;
|
||||
|
||||
// For light theme
|
||||
//$bg-super-dark: #efefef;
|
||||
//$bg-dark: #fff;
|
||||
//$bg-light: #272824;
|
||||
//$bg-super-light: #22231f;
|
||||
|
||||
/* Font Colors */
|
||||
$font-light-bg: #555;
|
||||
$font-dark-bg: #ddd;
|
||||
$font-super-dark-bg: #ccc;
|
||||
$font-primary-bg: #eee;
|
||||
|
||||
// For light theme
|
||||
//$font-dark-bg: #444;
|
||||
//$font-light-bg: #ddd;
|
||||
//$font-super-dark-bg: #333;
|
||||
//$font-primary-bg: #eee;
|
||||
|
||||
$hl-xxs: rgba(140, 140, 140, 0.05);
|
||||
$hl-xs: rgba(140, 140, 140, 0.09);
|
||||
$hl-sm: rgba(140, 140, 140, 0.15);
|
||||
$hl-md: rgba(140, 140, 140, 0.25);
|
||||
$hl-lg: rgba(140, 140, 140, 0.35);
|
||||
$hl-xl: rgba(140, 140, 140, 0.5);
|
||||
$hl: rgba(130, 130, 130, 1);
|
||||
$hl-xxl: rgba(140, 140, 140, 0.7);
|
||||
$hl: rgba(140, 140, 140, 1);
|
||||
|
||||
$success: #598f07;
|
||||
$success: #91c74e;
|
||||
$warning: #ffad36;
|
||||
$danger: #ff6d59;
|
||||
$info: #52adc1;
|
||||
|
||||
$faint-opacity: 0.5;
|
||||
$faint-opacity: 0.4;
|
||||
|
||||
.success {
|
||||
.success,
|
||||
.method-POST {
|
||||
border-color: $success !important;
|
||||
color: $success;
|
||||
}
|
||||
|
||||
.warning,
|
||||
.method-PUT,
|
||||
.method-PATCH {
|
||||
border-color: $warning !important;
|
||||
color: $warning;
|
||||
}
|
||||
|
||||
.danger,
|
||||
.method-DELETE {
|
||||
border-color: $danger !important;
|
||||
color: $danger;
|
||||
}
|
||||
|
||||
.info,
|
||||
.method-GET,
|
||||
.method-OPTIONS,
|
||||
.method-HEAD {
|
||||
border-color: $info !important;
|
||||
color: $info;
|
||||
}
|
||||
|
||||
.bg-dark {
|
||||
background: $bg-dark;
|
||||
&, a, textarea, input, button {
|
||||
@ -33,14 +73,21 @@ $faint-opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background: $bg-primary;
|
||||
|
||||
.bg-super-dark {
|
||||
background: $bg-super-dark;
|
||||
&, a, textarea, input, button {
|
||||
color: $font-primary-bg;
|
||||
color: $font-super-dark-bg;
|
||||
}
|
||||
}
|
||||
|
||||
//.bg-primary {
|
||||
// background: $bg-primary;
|
||||
//
|
||||
// &, a, textarea, input, button {
|
||||
// color: $font-primary-bg;
|
||||
// }
|
||||
//}
|
||||
|
||||
.bg-light {
|
||||
background: $bg-light;
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
/* Padding */
|
||||
$padding-md: 1.25rem;
|
||||
$padding-sm: $padding-md / 2;
|
||||
$padding-sm: $padding-md * 0.5;
|
||||
$padding-xs: $padding-md * 0.35;
|
||||
$padding-xxs: $padding-md * 0.20;
|
||||
$padding-lg: $padding-md * 2;
|
||||
|
||||
/* Fonts */
|
||||
$font-size: 12px;
|
||||
$font-size-xs: 0.7rem;
|
||||
$font-size-sm: 0.8rem;
|
||||
$font-size-md: 1.0rem;
|
||||
$font-size-lg: 1.2rem;
|
||||
@ -17,10 +20,10 @@ $line-height-sm: $line-height-md * 0.75;
|
||||
|
||||
/* Sidebar */
|
||||
$sidebar-width: 20rem;
|
||||
$sidebar-width-sm: $sidebar-width * 0.75;
|
||||
|
||||
/* Borders */
|
||||
$radius-md: 2px;
|
||||
$radius-sm: 1px;
|
||||
$radius-md: 3px;
|
||||
|
||||
/* Breakpoints */
|
||||
$breakpoint-lg: 1500px;
|
||||
|
@ -32,20 +32,38 @@ h2 {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.tall {
|
||||
height: 100%;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Make all font awesome icons the same width */
|
||||
i.fa {
|
||||
width: 1.1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.faint {
|
||||
opacity: $faint-opacity;
|
||||
}
|
||||
|
||||
.no-wrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wide {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.hide-scrollbars {
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
|
@ -7,58 +7,86 @@
|
||||
.pane__body {
|
||||
overflow-y: auto;
|
||||
width: $sidebar-width;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pane__header, .pane__body {
|
||||
.pane__header,
|
||||
.pane__body {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
li.active .sidebar__item {
|
||||
color: inherit;
|
||||
.sidebar__item__row {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
height: $line-height-sm;
|
||||
line-height: $line-height-sm;
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
background: $hl-xxs;
|
||||
}
|
||||
|
||||
.sidebar__item, .sidebar__item-btn {
|
||||
height: $line-height-sm;
|
||||
line-height: $line-height-sm;
|
||||
& > button {
|
||||
padding: 0 $padding-md;
|
||||
color: inherit;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar__item__btn {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
color: $hl-xl;
|
||||
|
||||
& > button,
|
||||
& > .dropdown > button {
|
||||
padding: 0 $padding-sm;
|
||||
height: 100%;
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
background: $hl-xs;
|
||||
color: $font-dark-bg;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: $hl-md;
|
||||
}
|
||||
}
|
||||
|
||||
& .sidebar__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $hl;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
&.sidebar__item--right-menu {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& .sidebar__item .sidebar__item {
|
||||
padding-left: $padding-sm * 5;
|
||||
}
|
||||
& .sidebar__item .sidebar__item .sidebar__item {
|
||||
padding-left: $padding-md * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-sm) {
|
||||
.sidebar {
|
||||
.pane__body {
|
||||
overflow-y: auto;
|
||||
width: $sidebar-width-sm;
|
||||
.sidebar__item {
|
||||
color: $hl;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
&.sidebar__item--active {
|
||||
color: $font-dark-bg;
|
||||
|
||||
.tag {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.sidebar__item--right-menu {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
&:hover .sidebar__item__btn {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.sidebar__item--bordered {
|
||||
border-top: 1px solid $hl-xs;
|
||||
}
|
||||
|
||||
.tag {
|
||||
opacity: $faint-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
ul ul .sidebar__item__row > button {
|
||||
padding-left: $padding-sm * 3 !important;
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,25 @@
|
||||
jest.unmock('../requests');
|
||||
jest.unmock('../requestGroups');
|
||||
jest.unmock('../../constants/actionTypes');
|
||||
|
||||
import reducer from '../requests';
|
||||
import * as types from '../../constants/actionTypes';
|
||||
import reducer from '../requestGroups';
|
||||
|
||||
describe('Requests Reducer', () => {
|
||||
describe('RequestGroups Reducer', () => {
|
||||
var initialState;
|
||||
var request;
|
||||
var requestGroup;
|
||||
|
||||
beforeEach(() => {
|
||||
initialState = {
|
||||
all: [],
|
||||
active: null,
|
||||
filter: ''
|
||||
collapsed: []
|
||||
};
|
||||
|
||||
request = {
|
||||
_mode: 'json',
|
||||
id: 'req_1234567890',
|
||||
requestGroup = {
|
||||
id: 'rg_1234567890',
|
||||
created: Date.now(),
|
||||
modified: Date.now(),
|
||||
name: 'My Request',
|
||||
method: 'GET',
|
||||
body: '{"foo": "bar"}',
|
||||
authentication: {username: 'user', password: 'secret'},
|
||||
params: [{name: 'page', value: '3'}],
|
||||
headers: [{name: 'Content-Type', value: 'application/json'}]
|
||||
name: 'My Group',
|
||||
environment: {},
|
||||
children: []
|
||||
};
|
||||
});
|
||||
|
||||
@ -34,126 +28,4 @@ describe('Requests Reducer', () => {
|
||||
reducer(undefined, {})
|
||||
).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('returns initial same state with unknown action', () => {
|
||||
const state = {foo: 'bar'};
|
||||
expect(
|
||||
reducer(state, {type: '__INVALID__'})
|
||||
).toBe(state);
|
||||
});
|
||||
|
||||
it('should add request', () => {
|
||||
expect(
|
||||
reducer(undefined, {
|
||||
type: types.REQUEST_ADD,
|
||||
request: request
|
||||
})
|
||||
).toEqual({
|
||||
all: [request],
|
||||
active: request.id,
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should add request of same name', () => {
|
||||
initialState.all.push(request);
|
||||
const newRequest = Object.assign({}, request);
|
||||
|
||||
expect(
|
||||
reducer(initialState, {
|
||||
type: types.REQUEST_ADD,
|
||||
request: newRequest
|
||||
})
|
||||
).toEqual({
|
||||
all: [
|
||||
Object.assign(newRequest, {name: `${request.name} (1)`}),
|
||||
request
|
||||
],
|
||||
active: request.id,
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete request', () => {
|
||||
initialState.all.push(request);
|
||||
initialState.active = request.id;
|
||||
|
||||
expect(
|
||||
reducer(initialState, {
|
||||
type: types.REQUEST_DELETE,
|
||||
id: request.id
|
||||
})
|
||||
).toEqual({
|
||||
all: [],
|
||||
active: null,
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete request and not remove active', () => {
|
||||
initialState.all.push(request);
|
||||
initialState.active = 'req_9999999999';
|
||||
|
||||
expect(
|
||||
reducer(initialState, {
|
||||
type: types.REQUEST_DELETE,
|
||||
id: request.id
|
||||
})
|
||||
).toEqual({
|
||||
all: [],
|
||||
active: 'req_9999999999',
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should update request', () => {
|
||||
const state = reducer(undefined, {
|
||||
type: types.REQUEST_ADD,
|
||||
request: request
|
||||
});
|
||||
|
||||
const patch = {
|
||||
id: request.id,
|
||||
name: 'New Name'
|
||||
};
|
||||
|
||||
expect(reducer(state, {
|
||||
type: types.REQUEST_UPDATE,
|
||||
patch: patch
|
||||
})).toEqual({
|
||||
all: [Object.assign({}, request, patch)],
|
||||
active: request.id,
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should not update unknown request', () => {
|
||||
expect(reducer(initialState, {
|
||||
type: types.REQUEST_UPDATE,
|
||||
patch: {id: 'req_1234567890123'}
|
||||
})).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should activate request', () => {
|
||||
initialState.all = [request];
|
||||
initialState.active = null;
|
||||
|
||||
expect(reducer(initialState, {
|
||||
type: types.REQUEST_ACTIVATE,
|
||||
id: request.id
|
||||
})).toEqual({
|
||||
all: [request],
|
||||
active: request.id,
|
||||
filter: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should not activate invalid request', () => {
|
||||
initialState.all = [request];
|
||||
initialState.active = null;
|
||||
|
||||
expect(reducer(initialState, {
|
||||
type: types.REQUEST_ACTIVATE
|
||||
})).toEqual(initialState);
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,6 @@ describe('Requests Reducer', () => {
|
||||
};
|
||||
|
||||
request = {
|
||||
_mode: 'json',
|
||||
id: 'req_1234567890',
|
||||
created: Date.now(),
|
||||
modified: Date.now(),
|
||||
|
@ -1,12 +1,12 @@
|
||||
import * as types from "../constants/actionTypes";
|
||||
|
||||
const initialState = {
|
||||
all: [],
|
||||
collapsed: []
|
||||
all: []
|
||||
};
|
||||
|
||||
function requestGroupsReducer (state = [], action) {
|
||||
switch (action.type) {
|
||||
|
||||
case types.REQUEST_GROUP_ADD:
|
||||
// Change name if there is a duplicate
|
||||
const requestGroup = action.requestGroup;
|
||||
@ -18,14 +18,37 @@ function requestGroupsReducer (state = [], action) {
|
||||
}
|
||||
}
|
||||
return [requestGroup, ...state];
|
||||
|
||||
case types.REQUEST_GROUP_UPDATE:
|
||||
return state.map(requestGroup => {
|
||||
if (requestGroup.id === action.patch.id) {
|
||||
return Object.assign({}, requestGroup, action.patch);
|
||||
return state.map(rg => {
|
||||
if (rg.id === action.patch.id) {
|
||||
return Object.assign({}, rg, action.patch);
|
||||
} else {
|
||||
return requestGroup;
|
||||
return rg;
|
||||
}
|
||||
});
|
||||
|
||||
case types.REQUEST_GROUP_TOGGLE:
|
||||
return state.map(rg => {
|
||||
if (rg.id === action.id) {
|
||||
const collapsed = !rg.collapsed;
|
||||
return Object.assign({}, rg, {collapsed});
|
||||
} else {
|
||||
return rg;
|
||||
}
|
||||
});
|
||||
|
||||
case types.REQUEST_GROUP_ADD_CHILD_REQUEST:
|
||||
return state.map(rg => {
|
||||
if (rg.id === action.id) {
|
||||
rg.children = [
|
||||
{type: 'Request', id: action.requestId},
|
||||
...rg.children
|
||||
];
|
||||
}
|
||||
return rg;
|
||||
});
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@ -34,23 +57,28 @@ function requestGroupsReducer (state = [], action) {
|
||||
export default function (state = initialState, action) {
|
||||
let all, collapsed;
|
||||
switch (action.type) {
|
||||
|
||||
case types.REQUEST_GROUP_ADD:
|
||||
all = requestGroupsReducer(state.all, action);
|
||||
return Object.assign({}, state, {all});
|
||||
|
||||
case types.REQUEST_GROUP_DELETE:
|
||||
// TODO: Remove from collapsed as well
|
||||
all = state.all.filter(rg => rg.id !== action.id);
|
||||
return Object.assign({}, state, {all});
|
||||
|
||||
case types.REQUEST_GROUP_ADD_CHILD_REQUEST:
|
||||
all = requestGroupsReducer(state.all, action);
|
||||
return Object.assign({}, state, {all});
|
||||
|
||||
case types.REQUEST_GROUP_TOGGLE:
|
||||
if (state.collapsed.indexOf(action.id) >= 0) {
|
||||
collapsed = state.collapsed.filter(id => id !== action.id);
|
||||
} else {
|
||||
collapsed = [...state.collapsed, action.id]
|
||||
}
|
||||
return Object.assign({}, state, {collapsed});
|
||||
all = requestGroupsReducer(state.all, action);
|
||||
return Object.assign({}, state, {all});
|
||||
|
||||
case types.REQUEST_GROUP_UPDATE:
|
||||
all = requestGroupsReducer(state.all, action);
|
||||
return Object.assign({}, state, {all});
|
||||
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ describe('RequestSchema', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
request = {
|
||||
_mode: 'json',
|
||||
id: 'rq_1234567890123',
|
||||
created: Date.now(),
|
||||
modified: Date.now(),
|
||||
|
@ -47,7 +47,6 @@ const requestSchema = {
|
||||
id: '/Request',
|
||||
type: 'object',
|
||||
properties: {
|
||||
_mode: {type: 'string'},
|
||||
id: {type: 'string', pattern: '^rq_[\\w]{13}$'},
|
||||
created: {type: 'number', minimum: 1000000000000, maximum: 10000000000000},
|
||||
modified: {type: 'number', minimum: 1000000000000, maximum: 10000000000000},
|
||||
@ -65,7 +64,6 @@ const requestSchema = {
|
||||
headers: {type: 'array', items: {$ref: '/Header'}}
|
||||
},
|
||||
required: [
|
||||
'_mode',
|
||||
'id',
|
||||
'url',
|
||||
'created',
|
||||
|
@ -19,7 +19,6 @@ const requestGroupSchema = {
|
||||
environment: {type: 'object'}
|
||||
},
|
||||
required: [
|
||||
'_mode',
|
||||
'id',
|
||||
'created',
|
||||
'modified',
|
||||
|
@ -21,8 +21,8 @@ app.on('ready', function () {
|
||||
width: IS_DEV ? 1600 : 1200,
|
||||
height: 800,
|
||||
minHeight: 500,
|
||||
minWidth: 500,
|
||||
acceptFirstMouse: true,
|
||||
minWidth: 520,
|
||||
acceptFirstMouse: true
|
||||
// titleBarStyle: IS_MAC ? 'hidden-inset' : 'default'
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user