diff --git a/app/network/o-auth-2/grant-password.js b/app/network/o-auth-2/grant-password.js
index 96521ad17..4fe6a165b 100644
--- a/app/network/o-auth-2/grant-password.js
+++ b/app/network/o-auth-2/grant-password.js
@@ -1,5 +1,5 @@
import * as querystring from '../../common/querystring';
-import {getBasicAuthHeader} from '../../common/misc';
+import {getBasicAuthHeader, setDefaultProtocol} from '../../common/misc';
import * as c from './constants';
import {responseToObject} from './misc';
@@ -38,7 +38,15 @@ export default async function (accessTokenUrl,
headers: headers
};
- const response = await window.fetch(accessTokenUrl, config);
+ const url = setDefaultProtocol(accessTokenUrl);
+
+ let response;
+ try {
+ response = await window.fetch(url, config);
+ } catch (err) {
+ throw new Error(`Failed to fetch access token at URL "${url}"`);
+ }
+
const body = await response.text();
const results = responseToObject(body, [
c.P_ACCESS_TOKEN,
diff --git a/app/ui/components/editors/environment-editor.js b/app/ui/components/editors/environment-editor.js
index a7da60862..7d5b73e51 100644
--- a/app/ui/components/editors/environment-editor.js
+++ b/app/ui/components/editors/environment-editor.js
@@ -5,7 +5,40 @@ import {DEBOUNCE_MILLIS} from '../../../common/constants';
@autobind
class EnvironmentEditor extends PureComponent {
+ constructor (props) {
+ super(props);
+ this.state = {
+ error: null,
+ warning: null
+ };
+ }
+
_handleChange () {
+ let error = null;
+ let warning = null;
+ let value = null;
+
+ // Check for JSON parse errors
+ try {
+ value = this.getValue();
+ } catch (err) {
+ error = err.message;
+ }
+
+ // Check for invalid key names
+ if (value) {
+ for (const key of Object.keys(value)) {
+ if (!key.match(/^[a-zA-Z_$][0-9a-zA-Z_$]*$/)) {
+ warning = `"${key}" must only contain letters, numbers, and underscores`;
+ break;
+ }
+ }
+ }
+
+ if (this.state.error !== error || this.state.warning !== warning) {
+ this.setState({error, warning});
+ }
+
this.props.didChange();
}
@@ -18,12 +51,7 @@ class EnvironmentEditor extends PureComponent {
}
isValid () {
- try {
- return this.getValue() !== undefined;
- } catch (e) {
- // Failed to parse JSON
- return false;
- }
+ return !this.state.error;
}
render () {
@@ -38,22 +66,28 @@ class EnvironmentEditor extends PureComponent {
...props
} = this.props;
+ const {error, warning} = this.state;
+
return (
-
+
+
+ {error &&
{error}
}
+ {(!error && warning) &&
{warning}
}
+
);
}
}
diff --git a/app/ui/components/modals/workspace-environments-edit-modal.js b/app/ui/components/modals/workspace-environments-edit-modal.js
index a22a02c99..82da0d8ac 100644
--- a/app/ui/components/modals/workspace-environments-edit-modal.js
+++ b/app/ui/components/modals/workspace-environments-edit-modal.js
@@ -133,7 +133,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
_didChange () {
const isValid = this._envEditor.isValid();
- if (this.state.isValid === isValid) {
+ if (this.state.isValid !== isValid) {
this.setState({isValid});
}
diff --git a/app/ui/components/request-pane.js b/app/ui/components/request-pane.js
index 5f18b888b..db5763194 100644
--- a/app/ui/components/request-pane.js
+++ b/app/ui/components/request-pane.js
@@ -241,12 +241,12 @@ class RequestPane extends PureComponent {
diff --git a/app/ui/components/response-pane.js b/app/ui/components/response-pane.js
index 50a5022b5..3b9c4d564 100644
--- a/app/ui/components/response-pane.js
+++ b/app/ui/components/response-pane.js
@@ -90,9 +90,9 @@ class ResponsePane extends PureComponent {
const {body, timeline, encoding} = this.state.response;
const headers = timeline
- .filter(v => v.name === 'HEADER_IN')
- .map(v => v.value)
- .join('');
+ .filter(v => v.name === 'HEADER_IN')
+ .map(v => v.value)
+ .join('');
const bodyBuffer = new Buffer(body, encoding);
const fullResponse = `${headers}${bodyBuffer}`;
@@ -249,8 +249,11 @@ class ResponsePane extends PureComponent {
@@ -259,7 +262,7 @@ class ResponsePane extends PureComponent {
{cookieHeaders.length}) : null}
- {response.timeline && response.timeline.length && (
+ {(response.timeline && response.timeline.length > 0) && (
@@ -305,15 +308,15 @@ class ResponsePane extends PureComponent {
/>
- {(response.timeline && response.timeline.length) && (
+ {(response.timeline && response.timeline.length > 0) && (
-
+
)}
diff --git a/app/ui/css/components/environment-editor.less b/app/ui/css/components/environment-editor.less
new file mode 100644
index 000000000..beb522b7c
--- /dev/null
+++ b/app/ui/css/components/environment-editor.less
@@ -0,0 +1,5 @@
+.environment-editor {
+ display: grid;
+ grid-template-rows: 1fr auto;
+ height: 100%;
+}
diff --git a/app/ui/css/index.less b/app/ui/css/index.less
index 40e40abbb..4d4cf65d3 100644
--- a/app/ui/css/index.less
+++ b/app/ui/css/index.less
@@ -24,6 +24,7 @@
@import 'components/dropdown';
@import 'components/editable';
@import 'components/environment-modal';
+@import 'components/environment-editor';
@import 'components/header-editor';
@import 'components/key-value-editor';
@import 'components/method-dropdown';