More changes to cookie editing

This commit is contained in:
Gregory Schier 2017-08-22 16:54:31 -07:00
parent d654feca82
commit 9e3d79ccc0
10 changed files with 112 additions and 66 deletions

View File

@ -12,7 +12,9 @@ export type Cookie = {
path: string,
key: string,
value: string,
expires: number
expires: number,
httpOnly: boolean,
secure: boolean
}
type BaseCookieJar = {

View File

@ -59,7 +59,7 @@ export function types () {
return all().map(model => model.type);
}
export function getModel (type: string) {
export function getModel (type: string): Object | null {
return all().find(m => m.type === type) || null;
}
@ -99,7 +99,7 @@ export function initModel (type: string, ...sources: Array<Object>) {
created: Date.now()
}, model.init());
const fullObject = Object.assign({}, objectDefaults, ...sources);
const fullObject = Object.assign(objectDefaults, ...sources);
// Generate an _id if there isn't one yet
if (!fullObject._id) {

View File

@ -1,5 +1,5 @@
// @flow
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import {Cookie} from 'tough-cookie';
@ -9,6 +9,15 @@ import RenderedText from './rendered-text';
@autobind
class CookieList extends PureComponent {
props: {
onCookieAdd: Function,
onCookieDelete: Function,
cookies: Array<Cookie>,
newCookieDomainName: string,
handleShowModifyCookieModal: Function,
handleRender: Function
};
_handleCookieAdd () {
const newCookie = new Cookie({
key: 'foo',
@ -22,7 +31,7 @@ class CookieList extends PureComponent {
this.props.onCookieAdd(newCookie);
}
_handleDeleteCookie (cookie) {
_handleDeleteCookie (cookie: Cookie) {
this.props.onCookieDelete(cookie);
}
@ -58,7 +67,8 @@ class CookieList extends PureComponent {
<RenderedText render={handleRender} component="td">
{cookie.domain}
</RenderedText>
<RenderedText render={handleRender} component="td">
<RenderedText render={handleRender} component="td"
props={{className: 'force-wrap wide'}}>
{cookieString}
</RenderedText>
<td onClick={null} className="text-right no-wrap">
@ -98,13 +108,4 @@ class CookieList extends PureComponent {
}
}
CookieList.propTypes = {
onCookieAdd: PropTypes.func.isRequired,
onCookieDelete: PropTypes.func.isRequired,
cookies: PropTypes.array.isRequired,
newCookieDomainName: PropTypes.string.isRequired,
handleShowModifyCookieModal: PropTypes.func.isRequired,
handleRender: PropTypes.func.isRequired
};
export default CookieList;

View File

@ -1,8 +1,8 @@
// @flow
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Tabs, TabList, Tab, TabPanel} from 'react-tabs';
import autobind from 'autobind-decorator';
import {Cookie} from 'tough-cookie';
import * as toughCookie from 'tough-cookie';
import * as models from '../../../models';
import {DEBOUNCE_MILLIS} from '../../../common/constants';
import {trackEvent} from '../../../analytics/index';
@ -12,14 +12,38 @@ import ModalHeader from '../base/modal-header';
import ModalFooter from '../base/modal-footer';
import OneLineEditor from '../codemirror/one-line-editor';
import {cookieToString} from '../../../common/cookies';
import type {Cookie, CookieJar} from '../../../models/cookie-jar';
import type {Workspace} from '../../../models/workspace';
@autobind
class CookieModifyModal extends PureComponent {
constructor (props) {
props: {
handleRender: Function,
handleGetRenderContext: Function,
workspace: Workspace,
cookieJar: CookieJar
};
state: {
cookie: Cookie | null,
rawValue: string,
isValid: {
key: boolean,
value: boolean,
domain: boolean,
path: boolean,
expires: boolean
}
};
modal: Modal | null;
_rawTimeout: number | null;
_cookieUpdateTimeout: number | null;
constructor (props: any) {
super(props);
this.state = {
cookieJar: null,
cookie: null,
rawValue: '',
isValid: {
@ -30,52 +54,49 @@ class CookieModifyModal extends PureComponent {
expires: true
}
};
this._rawTimeout = null;
this._cookieUpdateTimeout = null;
}
_setModalRef (n) {
_setModalRef (n: Modal | null) {
this.modal = n;
}
async _load () {
const {workspace} = this.props;
const cookieJar = await models.cookieJar.getOrCreateForParentId(workspace._id);
this.setState({cookieJar});
}
async show (cookie) {
await this._load();
async show (cookie: Cookie) {
// Dunno why this is sent as an array
cookie = cookie[0] || cookie;
this.setState({cookie});
this.modal.show();
this.modal && this.modal.show();
trackEvent('Cookie Modifier', 'Show');
}
hide () {
this.modal.hide();
this.modal && this.modal.hide();
}
async _saveChanges () {
const {cookieJar} = this.state;
async _saveChanges (cookieJar: CookieJar) {
await models.cookieJar.update(cookieJar);
await this._load();
}
_handleChangeRawValue (e) {
_handleChangeRawValue (e: Event & {target: HTMLInputElement}) {
const value = e.target.value;
clearTimeout(this._rawTimeout);
this._rawTimeout = setTimeout(async () => {
const cookie = Cookie.parse(value);
const cookie = toughCookie.Cookie.parse(value);
if (!this.state.cookie) {
return;
}
await this._handleCookieUpdate(this.state.cookie, cookie);
}, DEBOUNCE_MILLIS);
}
async _handleCookieUpdate (oldCookie, cookie) {
const {cookieJar} = this.state;
async _handleCookieUpdate (oldCookie: Cookie, cookie: Cookie) {
const {cookieJar} = this.props;
const {cookies} = cookieJar;
const index = cookies.findIndex(c => c.domain === oldCookie.domain && c.key === oldCookie.key);
@ -91,21 +112,23 @@ class CookieModifyModal extends PureComponent {
trackEvent('Cookie', 'Update');
}
_handleChange (input, field) {
_handleChange (field: string, eventOrValue: Event & {target: HTMLInputElement}) {
const {cookie} = this.state;
let valid = true;
if (typeof input === 'object') {
input = input.target.checked;
}
const value = typeof eventOrValue === 'object'
? eventOrValue.target.checked
: eventOrValue;
if (valid) {
const newCookie = Object.assign({}, cookie, {[field]: input});
const newCookie = Object.assign({}, cookie, {[field]: value});
clearTimeout(this._cookieUpdateTimeout);
this._cookieUpdateTimeout = setTimeout(() => {
this._handleCookieUpdate(cookie, newCookie);
this.setState({cookie: newCookie});
this._cookieUpdateTimeout = setTimeout(async () => {
if (cookie) {
await this._handleCookieUpdate(cookie, newCookie);
this.setState({cookie: newCookie});
}
}, DEBOUNCE_MILLIS * 2);
}
@ -117,20 +140,24 @@ class CookieModifyModal extends PureComponent {
});
}
_capitalize (str) {
_capitalize (str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
render () {
const {
cookieJar,
handleRender,
handleGetRenderContext
} = this.props;
if (!cookieJar) {
return null;
}
const {
isValid,
cookie,
cookieJar
cookie
} = this.state;
if (!cookie || !cookieJar) {
@ -142,7 +169,7 @@ class CookieModifyModal extends PureComponent {
let rawCookieString = '';
try {
rawCookieString = cookieToString(Cookie.fromJSON(JSON.stringify(cookie)));
rawCookieString = cookieToString(toughCookie.Cookie.fromJSON(JSON.stringify(cookie)));
} catch (err) {
console.warn('Failed to parse cookie', err);
}
@ -170,13 +197,12 @@ class CookieModifyModal extends PureComponent {
<label>{this._capitalize(field)}
<OneLineEditor
className={isValid[field] ? '' : 'input--error'}
ref={this._setInputRef}
forceEditor
type="text"
render={handleRender}
getRenderContext={handleGetRenderContext}
defaultValue={val || ''}
onChange={(i) => this._handleChange(i, field)}/>
onChange={value => this._handleChange(field, value)}/>
</label>
</div>
);
@ -193,7 +219,7 @@ class CookieModifyModal extends PureComponent {
type="checkbox"
name={field}
defaultChecked={checked || false}
onChange={(e) => this._handleChange(e, field)}
onChange={e => this._handleChange(field, e)}
/>
</label>
);
@ -221,11 +247,5 @@ class CookieModifyModal extends PureComponent {
}
}
CookieModifyModal.propTypes = {
handleRender: PropTypes.func.isRequired,
handleGetRenderContext: PropTypes.func.isRequired,
workspace: PropTypes.object.isRequired
};
// export CookieModifyModal;
export default CookieModifyModal;

View File

@ -34,6 +34,13 @@ class CookiesModal extends PureComponent {
};
}
async _ensureCookieJarExists () {
const {cookieJar, workspace} = this.props;
if (!cookieJar) {
models.cookieJar.getOrCreateForParentId(workspace._id);
}
}
_setModalRef (n: React.Element<*> | null) {
this.modal = n;
}
@ -85,11 +92,13 @@ class CookiesModal extends PureComponent {
}
async show () {
this.modal && this.modal.show();
await this._ensureCookieJarExists();
setTimeout(() => {
this.filterInput && this.filterInput.focus();
}, 100);
this.modal && this.modal.show();
trackEvent('Cookie Manager', 'Show');
}
@ -98,16 +107,22 @@ class CookiesModal extends PureComponent {
}
render () {
const filteredCookies = this._getFilteredSortedCookies();
const {
handleShowModifyCookieModal,
handleRender
handleRender,
cookieJar
} = this.props;
if (!cookieJar) {
return null;
}
const {
filter
} = this.state;
const filteredCookies = this._getFilteredSortedCookies();
return (
<Modal ref={this._setModalRef} wide tall {...this.props}>
<ModalHeader>Manage Cookies</ModalHeader>

View File

@ -5,7 +5,8 @@ class RenderedText extends React.PureComponent {
props: {
component: string,
children: string,
render: Function
render: Function,
props?: Object
};
state: {
@ -34,8 +35,8 @@ class RenderedText extends React.PureComponent {
}
render () {
const {component} = this.props;
return React.createElement(component, {}, this.state.renderedText);
const {component, props} = this.props;
return React.createElement(component, props || {}, this.state.renderedText);
}
}

View File

@ -540,6 +540,7 @@ class Wrapper extends React.PureComponent {
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
ref={registerModal}
cookieJar={activeCookieJar}
workspace={activeWorkspace}
/>
<NunjucksModal

View File

@ -903,11 +903,13 @@ function mapStateToProps (state, props) {
// Request stuff
const requestMeta = selectActiveRequestMeta(state, props) || {};
const activeRequest = selectActiveRequest(state, props);
const activeCookieJar = selectActiveCookieJar(state, props);
const responsePreviewMode = requestMeta.previewMode || PREVIEW_MODE_SOURCE;
const responseFilter = requestMeta.responseFilter || '';
const responseFilterHistory = requestMeta.responseFilterHistory || [];
// Cookie Jar
const activeCookieJar = selectActiveCookieJar(state, props);
// Response stuff
const activeRequestResponses = selectActiveRequestResponses(state, props) || [];
const activeResponse = selectActiveResponse(state, props) || null;

View File

@ -1,5 +1,6 @@
import {createSelector} from 'reselect';
import {fuzzyMatch} from '../../common/misc';
import * as models from '../../models/index';
// ~~~~~~~~~ //
// Selectors //

3
flow-typed/tough-cookie.js vendored Normal file
View File

@ -0,0 +1,3 @@
declare module 'tough-cookie' {
declare module.exports: *
}