diff --git a/app/components/EnvironmentEditModal.js b/app/components/EnvironmentEditModal.js index d63295309..9a6172f4f 100644 --- a/app/components/EnvironmentEditModal.js +++ b/app/components/EnvironmentEditModal.js @@ -1,50 +1,47 @@ import React, {PropTypes} from 'react'; import Link from './base/Link'; +import Editor from './base/Editor'; import Modal from './base/Modal'; import ModalBody from './base/ModalBody'; import ModalHeader from './base/ModalHeader'; import ModalFooter from './base/ModalFooter'; -import KeyValueEditor from './base/KeyValueEditor'; import ModalComponent from './lib/ModalComponent'; class EnvironmentEditModal extends ModalComponent { constructor (props) { super(props); - this.requestGroup = null; + this.state = { - pairs: [], - uniquenessKey: '' + environmentJSON: '{}', + requestGroup: null } } _saveChanges () { - const environment = this._mapPairsToData(this.state.pairs); - this.props.onChange(Object.assign({}, this.requestGroup, {environment})); + const {requestGroup, environmentJSON} = this.state; + + let environment; + try { + environment = JSON.parse(environmentJSON); + } catch (e) { + // That's OK. The user will (hopefully) fix the problem + console.warn('Failed to parse environment JSON', e); + return; + } + + this.props.onChange(Object.assign({}, requestGroup, {environment})); this.hide(); } - _keyValueChange (pairs) { - this.setState({pairs}); - } - - _mapPairsToData (pairs) { - return pairs.reduce((prev, curr) => { - return Object.assign({}, prev, {[curr.name]: curr.value}); - }, {}); - } - - _mapDataToPairs (data) { - return Object.keys(data).map(key => ({name: key, value: data[key]})); + _handleChange (environmentJSON) { + this.setState({environmentJSON}); } _update (requestGroup) { - this.requestGroup = requestGroup; - this.setState({ - pairs: this._mapDataToPairs(requestGroup.environment), - uniquenessKey: requestGroup._id - }) + const environmentJSON = JSON.stringify(requestGroup.environment, null, '\t'); + this.setState({environmentJSON, requestGroup}); } show (requestGroup) { @@ -58,26 +55,30 @@ class EnvironmentEditModal extends ModalComponent { } render () { - const {uniquenessKey, pairs} = this.state; + const {environmentJSON} = this.state; return ( Environment Variables - +
+ +
-
- This data can be used for  - Nunjucks Templating  - in your requests. +
+ * this data can be used for  + + Nunjucks Templating + in your requests
diff --git a/app/components/ResponseBodyWebview.js b/app/components/ResponseBodyWebview.js index 7169b2a5b..5fbd10142 100644 --- a/app/components/ResponseBodyWebview.js +++ b/app/components/ResponseBodyWebview.js @@ -3,10 +3,10 @@ import React, {Component, PropTypes} from 'react'; class ResponseBodyWebview extends Component { _setBody () { const {body, contentType, url} = this.props; - const {webview} = this.refs; + const {webView} = this.refs; const newBody = body.replace('', ``); - webview.loadURL(`data:${contentType},${encodeURIComponent(newBody)}`); + webView.loadURL(`data:${contentType},${encodeURIComponent(newBody)}`); } componentDidUpdate () { @@ -26,19 +26,19 @@ class ResponseBodyWebview extends Component { } componentDidMount () { - const {webview} = this.refs; + const {webView} = this.refs; const cb = () => { - webview.removeEventListener('dom-ready', cb); + webView.removeEventListener('dom-ready', cb); this._setBody(); }; - webview.addEventListener('dom-ready', cb); + webView.addEventListener('dom-ready', cb); } render () { return ( - + ); } } diff --git a/app/components/base/Editor.js b/app/components/base/Editor.js index 3905cbb6e..44651d417 100644 --- a/app/components/base/Editor.js +++ b/app/components/base/Editor.js @@ -223,12 +223,16 @@ class Editor extends Component { } render () { - const {value, readOnly, fontSize} = this.props; + const {value, readOnly, fontSize, lightTheme} = this.props; const classes = classnames( 'editor', this.props.className, - {'editor--readonly': readOnly} + { + 'editor--readonly': readOnly, + 'editor--light-theme': !!lightTheme, + 'editor--dark-theme': !lightTheme + } ); return ( @@ -253,7 +257,8 @@ Editor.propTypes = { fontSize: PropTypes.number, value: PropTypes.string, prettify: PropTypes.bool, - className: PropTypes.any + className: PropTypes.any, + lightTheme: PropTypes.bool }; export default Editor; diff --git a/app/containers/RequestGroupActionsDropdown.js b/app/containers/RequestGroupActionsDropdown.js index 0c6219dcd..8cde1ab9d 100644 --- a/app/containers/RequestGroupActionsDropdown.js +++ b/app/containers/RequestGroupActionsDropdown.js @@ -57,7 +57,7 @@ class RequestGroupActionsDropdown extends Component {
  • -
  • diff --git a/app/css/components/editor.scss b/app/css/components/editor.scss index 2f8efc4df..3a1918fbd 100644 --- a/app/css/components/editor.scss +++ b/app/css/components/editor.scss @@ -21,7 +21,7 @@ .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { // Let the background behind show through - background-color: $bg-super-dark !important; + background-color: transparent !important; border: 0; } @@ -82,114 +82,143 @@ } /* Based on Sublime Text's Monokai theme */ +.editor:not(.editor--light-theme) { + .cm-s-default.CodeMirror { + color: #f8f8f2; + } -.cm-s-default.CodeMirror { - color: #f8f8f2; + .cm-s-default div.CodeMirror-selected { + //background: #49483E; + background: $hl-xl; + } + + .cm-s-default .CodeMirror-line::selection, .cm-s-default .CodeMirror-line > span::selection, .cm-s-default .CodeMirror-line > span > span::selection { + //background: rgba(73, 72, 62, .99); + } + + .cm-s-default .CodeMirror-line::-moz-selection, .cm-s-default .CodeMirror-line > span::-moz-selection, .cm-s-default .CodeMirror-line > span > span::-moz-selection { + //background: rgba(73, 72, 62, .99); + } + + .cm-s-default .CodeMirror-gutters { + //background: #272822; + border-right: 0px; + } + + .cm-s-default .CodeMirror-guttermarker { + color: white; + } + + .cm-s-default .CodeMirror-guttermarker-subtle { + color: #d0d0d0; + } + + .cm-s-default .CodeMirror-linenumber { + color: #d0d0d0; + } + + .cm-s-default .CodeMirror-cursor { + border-left: 1px solid #f8f8f0; + } + + .cm-s-default span.cm-comment { + color: #75715e; + } + + .cm-s-default span.cm-atom { + color: lighten($surprise, 5); + } + + .cm-s-default span.cm-number { + color: lighten($surprise, 5); + } + + .cm-s-default span.cm-property, .cm-s-default span.cm-attribute { + color: lighten($success, 5); + } + + .cm-s-default span.cm-keyword { + color: #f92672; + } + + .cm-s-default span.cm-builtin { + color: #66d9ef; + } + + .cm-s-default span.cm-string { + color: lighten($notice, 5); + } + + .cm-s-default span.cm-variable { + color: #f8f8f2; + } + + .cm-s-default span.cm-variable-2 { + color: #9effff; + } + + .cm-s-default span.cm-variable-3 { + color: #66d9ef; + } + + .cm-s-default span.cm-def { + color: #fd971f; + } + + .cm-s-default span.cm-bracket { + color: #f8f8f2; + } + + .cm-s-default span.cm-tag { + color: #f92672; + } + + .cm-s-default span.cm-header { + color: lighten($surprise, 5); + } + + .cm-s-default span.cm-link { + color: lighten($surprise, 5); + } + + .cm-s-default span.cm-error { + background: #f92672; + color: #f8f8f0; + } + + .cm-s-default .CodeMirror-activeline-background { + background: $hl-md; + } + + .cm-s-default .CodeMirror-matchingbracket { + text-decoration: underline; + color: white !important; + } } -.cm-s-default div.CodeMirror-selected { - background: #49483E; -} +.editor--light-theme { + .cm-s-default span { + color: $hl; + } -.cm-s-default .CodeMirror-line::selection, .cm-s-default .CodeMirror-line > span::selection, .cm-s-default .CodeMirror-line > span > span::selection { - background: rgba(73, 72, 62, .99); -} + .cm-s-default span.cm-string { + color: saturate(darken($notice, 30), 100); + } -.cm-s-default .CodeMirror-line::-moz-selection, .cm-s-default .CodeMirror-line > span::-moz-selection, .cm-s-default .CodeMirror-line > span > span::-moz-selection { - background: rgba(73, 72, 62, .99); -} + .cm-s-default span.cm-property, .cm-s-default span.cm-attribute { + color: saturate(darken($success, 15), 100); + } -.cm-s-default .CodeMirror-gutters { - background: #272822; - border-right: 0px; -} + .cm-s-default span.cm-atom, + .cm-s-default span.cm-number { + color: saturate(darken($surprise, 30), 100); + } -.cm-s-default .CodeMirror-guttermarker { - color: white; -} + .cm-s-default .CodeMirror-activeline-background { + background: $hl-md; + } -.cm-s-default .CodeMirror-guttermarker-subtle { - color: #d0d0d0; -} - -.cm-s-default .CodeMirror-linenumber { - color: #d0d0d0; -} - -.cm-s-default .CodeMirror-cursor { - border-left: 1px solid #f8f8f0; -} - -.cm-s-default span.cm-comment { - color: #75715e; -} - -.cm-s-default span.cm-atom { - color: lighten($surprise, 5); -} - -.cm-s-default span.cm-number { - color: lighten($surprise, 5); -} - -.cm-s-default span.cm-property, .cm-s-default span.cm-attribute { - color: lighten($success, 5); -} - -.cm-s-default span.cm-keyword { - color: #f92672; -} - -.cm-s-default span.cm-builtin { - color: #66d9ef; -} - -.cm-s-default span.cm-string { - color: lighten($notice, 5); -} - -.cm-s-default span.cm-variable { - color: #f8f8f2; -} - -.cm-s-default span.cm-variable-2 { - color: #9effff; -} - -.cm-s-default span.cm-variable-3 { - color: #66d9ef; -} - -.cm-s-default span.cm-def { - color: #fd971f; -} - -.cm-s-default span.cm-bracket { - color: #f8f8f2; -} - -.cm-s-default span.cm-tag { - color: #f92672; -} - -.cm-s-default span.cm-header { - color: lighten($surprise, 5); -} - -.cm-s-default span.cm-link { - color: lighten($surprise, 5); -} - -.cm-s-default span.cm-error { - background: #f92672; - color: #f8f8f0; -} - -.cm-s-default .CodeMirror-activeline-background { - background: #373831; -} - -.cm-s-default .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; + .cm-s-default .CodeMirror-matchingbracket { + text-decoration: underline; + } } diff --git a/app/css/components/sidebar.scss b/app/css/components/sidebar.scss index 88cce5d76..ca1371205 100644 --- a/app/css/components/sidebar.scss +++ b/app/css/components/sidebar.scss @@ -230,7 +230,7 @@ } .form-control { - padding: 0; + padding: 0 $padding-xs 0 0; width: 100%; input { padding: $padding-xs; diff --git a/app/css/layout/base.scss b/app/css/layout/base.scss index facd60370..c75a43264 100644 --- a/app/css/layout/base.scss +++ b/app/css/layout/base.scss @@ -69,7 +69,11 @@ webview { table { td { - padding-top: 0.25em; + padding-top: $padding-sm; + + &:not(:last-child) { + padding-right: $padding-lg; + } } th { @@ -156,6 +160,11 @@ i.fa { padding-top: $padding-md; } +.pad-bottom { + box-sizing: border-box; + padding-bottom: $padding-md; +} + .no-pad-bottom { padding-bottom: 0; } diff --git a/app/lib/network.js b/app/lib/network.js index a3c7dd649..1e150964b 100644 --- a/app/lib/network.js +++ b/app/lib/network.js @@ -18,7 +18,10 @@ function buildRequestConfig (request, patch = {}) { timeout: -1, // Unzip gzipped responses - gzip: true + gzip: true, + + // Time the request + time: true }; // Set the URL, including the query parameters @@ -71,7 +74,7 @@ function actuallySend (request, settings) { contentType: networkResponse.headers['content-type'], url: config.url, // TODO: Handle redirects somehow elapsedTime: networkResponse.elapsedTime, - bytes: networkResponse.connection.bytesRead, + bytesRead: networkResponse.connection.bytesRead, body: networkResponse.body, headers: Object.keys(networkResponse.headers).map(name => { const value = networkResponse.headers[name];