mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 06:39:48 +00:00
Fixed signup and environments
This commit is contained in:
parent
0308ffb050
commit
5abf581f7f
@ -64,8 +64,19 @@ export function deconstructToParams (qs, strict = true) {
|
||||
for (let stringPair of stringPairs) {
|
||||
const tmp = stringPair.split('=');
|
||||
|
||||
const name = decodeURIComponent(tmp[0] || '');
|
||||
const value = decodeURIComponent(tmp[1] || '');
|
||||
let name = '';
|
||||
try {
|
||||
name = decodeURIComponent(tmp[0] || '');
|
||||
} catch (e) {
|
||||
console.warn(`[querystring] Failed to decode name: ${tmp[0]}`, e);
|
||||
}
|
||||
|
||||
let value = '';
|
||||
try {
|
||||
value = decodeURIComponent(tmp[0] || '');
|
||||
} catch (e) {
|
||||
console.warn(`[querystring] Failed to decode value: ${tmp[1]}`, e);
|
||||
}
|
||||
|
||||
if (strict && !name) {
|
||||
continue;
|
||||
|
@ -29,9 +29,9 @@ export function exportHarWithRequest (renderedRequest, addContentLength = false)
|
||||
};
|
||||
}
|
||||
|
||||
export async function exportHar (requestId, addContentLength = false) {
|
||||
export async function exportHar (requestId, environmentId, addContentLength = false) {
|
||||
const request = await models.request.getById(requestId);
|
||||
const renderedRequest = await getRenderedRequest(request);
|
||||
const renderedRequest = await getRenderedRequest(request, environmentId);
|
||||
return exportHarWithRequest(renderedRequest, addContentLength);
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,14 @@ export function isLoggedIn () {
|
||||
|
||||
/** Log out and delete session data */
|
||||
export async function logout () {
|
||||
await util.post('/auth/logout');
|
||||
try {
|
||||
await util.post('/auth/logout');
|
||||
} catch (e) {
|
||||
// Not a huge deal if this fails, but we don't want it to prevent the
|
||||
// user from signing out.
|
||||
console.warn('Failed to logout', e);
|
||||
}
|
||||
|
||||
unsetSessionData();
|
||||
trackEvent('Session', 'Logout');
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ class RenderedQueryString extends Component {
|
||||
_update (props, delay = false) {
|
||||
clearTimeout(this._askTimeout);
|
||||
this._askTimeout = setTimeout(async () => {
|
||||
const {url, parameters} = await getRenderedRequest(props.request);
|
||||
const {request, environmentId} = props;
|
||||
const {url, parameters} = await getRenderedRequest(request, environmentId);
|
||||
const qs = querystring.buildFromParams(parameters);
|
||||
const fullUrl = querystring.joinURL(url, qs);
|
||||
this.setState({string: util.prepareUrlForSending(fullUrl)});
|
||||
@ -53,6 +54,7 @@ class RenderedQueryString extends Component {
|
||||
|
||||
RenderedQueryString.propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
environmentId: PropTypes.string.isRequired,
|
||||
|
||||
// Optional
|
||||
placeholder: PropTypes.string
|
||||
|
@ -14,7 +14,8 @@ class RequestPane extends Component {
|
||||
render () {
|
||||
const {
|
||||
request,
|
||||
handleImportFileToWorkspace,
|
||||
environmentId,
|
||||
handleImportFile,
|
||||
showPasswords,
|
||||
editorFontSize,
|
||||
editorLineWrapping,
|
||||
@ -147,6 +148,7 @@ class RequestPane extends Component {
|
||||
<code className="txt-sm block">
|
||||
<RenderedQueryString
|
||||
request={request}
|
||||
environmentId={environmentId}
|
||||
placeholder="http://myproduct.com?name=Gregory"
|
||||
/>
|
||||
</code>
|
||||
@ -200,6 +202,7 @@ RequestPane.propTypes = {
|
||||
showPasswords: PropTypes.bool.isRequired,
|
||||
editorFontSize: PropTypes.number.isRequired,
|
||||
editorLineWrapping: PropTypes.bool.isRequired,
|
||||
environmentId: PropTypes.string.isRequired,
|
||||
|
||||
// Optional
|
||||
request: PropTypes.object,
|
||||
|
@ -18,7 +18,6 @@ import Sidebar from './sidebar/Sidebar';
|
||||
import RequestPane from './RequestPane';
|
||||
import ResponsePane from './ResponsePane';
|
||||
import * as models from '../../models/index';
|
||||
import {PREVIEW_MODE_FRIENDLY} from '../../common/constants';
|
||||
|
||||
|
||||
const Wrapper = props => {
|
||||
@ -115,6 +114,7 @@ const Wrapper = props => {
|
||||
useBulkHeaderEditor={settings.useBulkHeaderEditor}
|
||||
editorFontSize={settings.editorFontSize}
|
||||
editorLineWrapping={settings.editorLineWrapping}
|
||||
environmentId={activeEnvironment ? activeEnvironment._id : 'n/a'}
|
||||
handleCreateRequest={handleCreateRequest.bind(null, activeRequest ? activeRequest.parentId : activeWorkspace._id)}
|
||||
updateRequestBody={body => models.request.update(activeRequest, {body})}
|
||||
updateRequestUrl={url => handleUpdateRequestUrl(activeRequest, url)}
|
||||
@ -157,7 +157,10 @@ const Wrapper = props => {
|
||||
<LoginModal ref={m => registerModal(m)}/>
|
||||
<SignupModal ref={m => registerModal(m)}/>
|
||||
<PaymentModal ref={m => registerModal(m)}/>
|
||||
<GenerateCodeModal ref={m => registerModal(m)}/>
|
||||
<GenerateCodeModal
|
||||
ref={m => registerModal(m)}
|
||||
environmentId={activeEnvironment ? activeEnvironment._id : 'n/a'}
|
||||
/>
|
||||
<SettingsModal
|
||||
ref={m => registerModal(m)}
|
||||
handleExportWorkspaceToFile={handleExportWorkspaceToFile}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, {Component} from 'react';
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import HTTPSnippet, {availableTargets} from 'httpsnippet';
|
||||
|
||||
import CopyButton from '../base/CopyButton';
|
||||
@ -57,7 +57,8 @@ class GenerateCodeModal extends Component {
|
||||
// Some clients need a content-length for the request to succeed
|
||||
const addContentLength = (TO_ADD_CONTENT_LENGTH[target.key] || []).find(c => c === client.key);
|
||||
|
||||
const har = await exportHar(request._id, addContentLength);
|
||||
const {environmentId} = this.props;
|
||||
const har = await exportHar(request._id, environmentId, addContentLength);
|
||||
const snippet = new HTTPSnippet(har);
|
||||
const cmd = snippet.convert(target.key, client.key);
|
||||
|
||||
@ -132,6 +133,8 @@ class GenerateCodeModal extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
GenerateCodeModal.propTypes = {};
|
||||
GenerateCodeModal.propTypes = {
|
||||
environmentId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default GenerateCodeModal;
|
||||
|
@ -66,7 +66,7 @@ class LoginModal extends Component {
|
||||
<form onSubmit={this._handleLogin.bind(this)}>
|
||||
<Modal ref={m => this.modal = m} {...this.props}>
|
||||
<ModalHeader>{title || "Login to Your Account"}</ModalHeader>
|
||||
<ModalBody className="pad changelog">
|
||||
<ModalBody className="pad">
|
||||
{message ? (
|
||||
<p className="notice info">{message}</p>
|
||||
) : null}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import React, {Component} from 'react';
|
||||
import classnames from 'classnames';
|
||||
import Link from '../base/Link';
|
||||
import Modal from '../base/Modal';
|
||||
import ModalBody from '../base/ModalBody';
|
||||
import ModalHeader from '../base/ModalHeader';
|
||||
@ -9,11 +11,15 @@ import LoginModal from './LoginModal';
|
||||
import * as sync from '../../../sync';
|
||||
import {trackEvent} from '../../../analytics';
|
||||
|
||||
const STEP_BASIC_INFO = 'basic';
|
||||
const STEP_CONFIRM_PASSWORD = 'confirm';
|
||||
const STEP_LOGIN_INFO = 'done';
|
||||
|
||||
class SignupModal extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
step: 1,
|
||||
step: STEP_BASIC_INFO,
|
||||
error: '',
|
||||
loading: false
|
||||
}
|
||||
@ -21,6 +27,12 @@ class SignupModal extends Component {
|
||||
|
||||
async _handleSignup (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (this.state.step === STEP_BASIC_INFO) {
|
||||
this.setState({step: STEP_CONFIRM_PASSWORD});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({error: '', loading: true});
|
||||
|
||||
const email = this._emailInput.value;
|
||||
@ -30,7 +42,7 @@ class SignupModal extends Component {
|
||||
|
||||
try {
|
||||
await session.signup(firstName, lastName, email, password);
|
||||
this.setState({step: 2, loading: false});
|
||||
this.setState({step: STEP_LOGIN_INFO, loading: false});
|
||||
sync.init();
|
||||
} catch (e) {
|
||||
this.setState({error: e.message, loading: false});
|
||||
@ -45,101 +57,147 @@ class SignupModal extends Component {
|
||||
trackEvent('Auth', 'Switch', 'To Login');
|
||||
}
|
||||
|
||||
_checkPasswordsMatch () {
|
||||
if (this._passwordInput.value !== this._passwordConfirmInput.value) {
|
||||
this._passwordConfirmInput.setCustomValidity('Password didn\'t match')
|
||||
} else {
|
||||
this._passwordConfirmInput.setCustomValidity('')
|
||||
}
|
||||
}
|
||||
|
||||
show () {
|
||||
this.setState({step: 1});
|
||||
this.setState({step: STEP_BASIC_INFO});
|
||||
this.modal.show();
|
||||
setTimeout(() => this._nameFirstInput.focus(), 200);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {step} = this.state;
|
||||
if (step === 1) {
|
||||
return (
|
||||
<form onSubmit={this._handleSignup.bind(this)}>
|
||||
<Modal ref={m => this.modal = m} {...this.props}>
|
||||
<ModalHeader>Sign Up For a New Account</ModalHeader>
|
||||
<ModalBody className="pad">
|
||||
<label htmlFor="signup-name-first">First Name</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="text"
|
||||
required="required"
|
||||
id="signup-name-first"
|
||||
name="signup-name-first"
|
||||
placeholder="Jane"
|
||||
ref={n => this._nameFirstInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-name-last">Last Name</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="text"
|
||||
id="signup-name-last"
|
||||
name="signup-name-last"
|
||||
placeholder="Doe"
|
||||
ref={n => this._nameLastInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-email">Email Address</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="email"
|
||||
required="required"
|
||||
id="signup-email"
|
||||
name="signup-email"
|
||||
placeholder="me@mydomain.com"
|
||||
ref={n => this._emailInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-password">Password <span
|
||||
className="faint">(minimum 6 characters)</span></label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="password"
|
||||
required="required"
|
||||
pattern=".{6,}"
|
||||
id="signup-password"
|
||||
name="signup-password"
|
||||
placeholder="•••••••••••••"
|
||||
ref={n => this._passwordInput = n}/>
|
||||
</div>
|
||||
<p className="italic faint pad-top-sm">
|
||||
NOTE: your password is used for end-to-end encryption so try not
|
||||
to lose it
|
||||
|
||||
let inner = null;
|
||||
if (step === STEP_BASIC_INFO || step === STEP_CONFIRM_PASSWORD) {
|
||||
inner = [
|
||||
<ModalHeader key="header">Sign Up For a New Account</ModalHeader>,
|
||||
<ModalBody key="body" className="pad">
|
||||
<div className={classnames({hide: step !== STEP_BASIC_INFO})}>
|
||||
<label htmlFor="signup-name-first">First Name</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="text"
|
||||
required="required"
|
||||
id="signup-name-first"
|
||||
name="signup-name-first"
|
||||
placeholder="Jane"
|
||||
ref={n => this._nameFirstInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-name-last">Last Name</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="text"
|
||||
id="signup-name-last"
|
||||
name="signup-name-last"
|
||||
placeholder="Doe"
|
||||
ref={n => this._nameLastInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-email">Email Address</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="email"
|
||||
required="required"
|
||||
id="signup-email"
|
||||
name="signup-email"
|
||||
placeholder="me@mydomain.com"
|
||||
ref={n => this._emailInput = n}/>
|
||||
</div>
|
||||
<label htmlFor="signup-password">
|
||||
Password <span className="faint">(minimum 6 characters)</span>
|
||||
</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="password"
|
||||
required="required"
|
||||
pattern=".{6,}"
|
||||
id="signup-password"
|
||||
name="signup-password"
|
||||
placeholder="•••••••••••••"
|
||||
ref={n => this._passwordInput = n}/>
|
||||
</div>
|
||||
</div>
|
||||
{step === STEP_CONFIRM_PASSWORD ? (
|
||||
<div className="text-center pad">
|
||||
<p className="text-center txt-lg">
|
||||
Keep your password safe because it cannot be recovered
|
||||
<br/>
|
||||
<span className="txt-sm faint italic">
|
||||
<Link href="https://insomnia.rest/documentation/plus/">Read More</Link>
|
||||
{" "}
|
||||
on how your password is used to encrypt your data
|
||||
</span>
|
||||
</p>
|
||||
{this.state.error ? (
|
||||
<div className="danger pad-top">** {this.state.error}</div>
|
||||
) : null}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<div className="margin-left">
|
||||
Already have an account?
|
||||
{" "}
|
||||
<a href="#" onClick={this._handleLogin.bind(this)}>Login</a>
|
||||
<div className="text-left">
|
||||
<label htmlFor="signup-password-confirm" className="pad-left-half">
|
||||
Confirm your Password
|
||||
</label>
|
||||
<div className="form-control form-control--outlined">
|
||||
<input type="password"
|
||||
required="required"
|
||||
pattern=".{6,}"
|
||||
id="signup-password-confirm"
|
||||
name="signup-password-confirm"
|
||||
placeholder="•••••••••••••"
|
||||
autoFocus="autoFocus"
|
||||
onChange={this._checkPasswordsMatch.bind(this)}
|
||||
ref={n => this._passwordConfirmInput = n}/>
|
||||
</div>
|
||||
<button type="button"
|
||||
className="pad-sm faint"
|
||||
onClick={e => this.setState({step: STEP_BASIC_INFO})}>
|
||||
<i className="fa fa-caret-left"></i>
|
||||
Go back
|
||||
</button>
|
||||
</div>
|
||||
<button type="submit" className="btn">
|
||||
{this.state.loading ?
|
||||
<i className="fa fa-spin fa-refresh margin-right-sm"></i> : null}
|
||||
Create Account
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</form>
|
||||
)
|
||||
</div>
|
||||
) : null}
|
||||
{this.state.error ? (
|
||||
<div className="danger pad-top">** {this.state.error}</div>
|
||||
) : null}
|
||||
</ModalBody>,
|
||||
<ModalFooter key="footer">
|
||||
<div className="margin-left">
|
||||
Already have an account?
|
||||
{" "}
|
||||
<a href="#" onClick={this._handleLogin.bind(this)}>Login</a>
|
||||
</div>
|
||||
<button type="submit" className="btn">
|
||||
{this.state.loading ?
|
||||
<i className="fa fa-spin fa-refresh margin-right-sm"></i> : null}
|
||||
Create Account
|
||||
</button>
|
||||
</ModalFooter>
|
||||
]
|
||||
} else {
|
||||
return (
|
||||
<Modal ref={m => this.modal = m} {...this.props}>
|
||||
<ModalHeader>Account Created</ModalHeader>
|
||||
<ModalBody className="pad">
|
||||
<h1>Please verify your account</h1>
|
||||
<p>
|
||||
A verification email has been sent to your email address. Once
|
||||
you have received it, you may login.
|
||||
</p>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<button type="submit"
|
||||
className="btn"
|
||||
onClick={e => this._handleLogin(e)}>
|
||||
Proceed to Login
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
)
|
||||
inner = [
|
||||
<ModalHeader key="header">Account Created</ModalHeader>,
|
||||
<ModalBody key="body" className="pad">
|
||||
<h1>Please verify your account</h1>
|
||||
<p>
|
||||
A verification email has been sent to your email address. Once
|
||||
you have received it, you may login.
|
||||
</p>
|
||||
</ModalBody>,
|
||||
<ModalFooter key="footer">
|
||||
<button type="submit"
|
||||
className="btn"
|
||||
onClick={e => this._handleLogin(e)}>
|
||||
Proceed to Login
|
||||
</button>
|
||||
</ModalFooter>
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={this._handleSignup.bind(this)}>
|
||||
<Modal ref={m => this.modal = m} {...this.props}>
|
||||
{inner}
|
||||
</Modal>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,10 @@ const SettingsSync = ({
|
||||
</p>,
|
||||
<p key="3" className="text-center italic">
|
||||
$5 per month or $50 per year
|
||||
<div className="txt-sm faint pad-top-sm">
|
||||
<br/>
|
||||
<span className="txt-sm faint pad-top-sm">
|
||||
14-day trial (credit card required) cancel at any time
|
||||
</div>
|
||||
</span>
|
||||
</p>
|
||||
]}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user