mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-21 22:57:59 -04:00
Even more robust cookie editing
This commit is contained in:
@@ -10,6 +10,7 @@ import * as models from '../models/index';
|
||||
import AlertModal from '../ui/components/modals/alert-modal';
|
||||
import {showModal} from '../ui/components/modals/index';
|
||||
import {trackEvent} from '../analytics/index';
|
||||
import {workspace} from '../models/index';
|
||||
|
||||
export const CHANGE_INSERT = 'insert';
|
||||
export const CHANGE_UPDATE = 'update';
|
||||
@@ -40,7 +41,7 @@ function getDBFilePath (modelType) {
|
||||
* @param forceReset
|
||||
* @returns {null}
|
||||
*/
|
||||
export function init (types: Array<string>, config: Object = {}, forceReset: boolean = false) {
|
||||
export async function init (types: Array<string>, config: Object = {}, forceReset: boolean = false) {
|
||||
if (forceReset) {
|
||||
changeListeners = [];
|
||||
db = {};
|
||||
@@ -89,6 +90,12 @@ export function init (types: Array<string>, config: Object = {}, forceReset: boo
|
||||
db[modelType] = collection;
|
||||
}
|
||||
|
||||
// Make sure CookieJars and environments exist for all workspaces
|
||||
for (const workspace of await models.workspace.all()) {
|
||||
await models.cookieJar.getOrCreateForParentId(workspace._id);
|
||||
await models.environment.getOrCreateForWorkspace(workspace);
|
||||
}
|
||||
|
||||
console.log(`[db] Initialized DB at ${getDBFilePath('$TYPE')}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
// @flow
|
||||
import * as db from '../common/database';
|
||||
import type {BaseModel} from './index';
|
||||
|
||||
import uuid from 'uuid';
|
||||
export const name = 'Cookie Jar';
|
||||
export const type = 'CookieJar';
|
||||
export const prefix = 'jar';
|
||||
export const canDuplicate = true;
|
||||
|
||||
export type Cookie = {
|
||||
id: string,
|
||||
domain: string,
|
||||
path: string,
|
||||
key: string,
|
||||
value: string,
|
||||
expires: number,
|
||||
expires: number | null,
|
||||
httpOnly: boolean,
|
||||
secure: boolean
|
||||
}
|
||||
@@ -32,6 +33,7 @@ export function init () {
|
||||
}
|
||||
|
||||
export function migrate (doc: CookieJar): CookieJar {
|
||||
doc = migrateCookieId(doc);
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -59,3 +61,13 @@ export function getById (id: string) {
|
||||
export function update (cookieJar: CookieJar, patch: Object = {}) {
|
||||
return db.docUpdate(cookieJar, patch);
|
||||
}
|
||||
|
||||
/** Ensure every cookie has an ID property */
|
||||
function migrateCookieId (cookieJar: CookieJar) {
|
||||
for (const cookie of cookieJar.cookies) {
|
||||
if (!cookie.id) {
|
||||
cookie.id = uuid.v4();
|
||||
}
|
||||
}
|
||||
return cookieJar;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// @flow
|
||||
import React, {PureComponent} from 'react';
|
||||
import uuid from 'uuid';
|
||||
import * as toughCookie from 'tough-cookie';
|
||||
import autobind from 'autobind-decorator';
|
||||
import {Cookie} from 'tough-cookie';
|
||||
|
||||
import {cookieToString} from '../../common/cookies';
|
||||
import PromptButton from './base/prompt-button';
|
||||
import RenderedText from './rendered-text';
|
||||
import type {Cookie} from '../../models/cookie-jar';
|
||||
|
||||
@autobind
|
||||
class CookieList extends PureComponent {
|
||||
@@ -19,14 +20,16 @@ class CookieList extends PureComponent {
|
||||
};
|
||||
|
||||
_handleCookieAdd () {
|
||||
const newCookie = new Cookie({
|
||||
const newCookie: Cookie = {
|
||||
id: uuid.v4(),
|
||||
key: 'foo',
|
||||
value: 'bar',
|
||||
domain: this.props.newCookieDomainName,
|
||||
expires: null,
|
||||
path: '/',
|
||||
secure: false,
|
||||
httpOnly: false
|
||||
});
|
||||
};
|
||||
|
||||
this.props.onCookieAdd(newCookie);
|
||||
}
|
||||
@@ -60,7 +63,7 @@ class CookieList extends PureComponent {
|
||||
</thead>
|
||||
<tbody key={cookies.length}>
|
||||
{cookies.map((cookie, i) => {
|
||||
const cookieString = cookieToString(Cookie.fromJSON(JSON.stringify(cookie)));
|
||||
const cookieString = cookieToString(toughCookie.Cookie.fromJSON(cookie));
|
||||
|
||||
return (
|
||||
<tr className="selectable" key={i}>
|
||||
|
||||
@@ -1,257 +1,270 @@
|
||||
// @flow
|
||||
import React, {PureComponent} from 'react';
|
||||
import {Tabs, TabList, Tab, TabPanel} from 'react-tabs';
|
||||
import autobind from 'autobind-decorator';
|
||||
import deepEqual from 'deep-equal';
|
||||
import * as toughCookie from 'tough-cookie';
|
||||
import * as models from '../../../models';
|
||||
import clone from 'clone';
|
||||
import {DEBOUNCE_MILLIS} from '../../../common/constants';
|
||||
import {trackEvent} from '../../../analytics/index';
|
||||
import Modal from '../base/modal';
|
||||
import ModalBody from '../base/modal-body';
|
||||
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 {
|
||||
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 = {
|
||||
cookie: null,
|
||||
rawValue: '',
|
||||
isValid: {
|
||||
key: true,
|
||||
value: true,
|
||||
domain: true,
|
||||
path: true,
|
||||
expires: true
|
||||
}
|
||||
};
|
||||
|
||||
this._rawTimeout = null;
|
||||
this._cookieUpdateTimeout = null;
|
||||
}
|
||||
|
||||
_setModalRef (n: Modal | null) {
|
||||
this.modal = n;
|
||||
}
|
||||
|
||||
async show (cookie: Cookie) {
|
||||
// Dunno why this is sent as an array
|
||||
cookie = cookie[0] || cookie;
|
||||
this.setState({cookie});
|
||||
|
||||
this.modal && this.modal.show();
|
||||
|
||||
trackEvent('Cookie Modifier', 'Show');
|
||||
}
|
||||
|
||||
hide () {
|
||||
this.modal && this.modal.hide();
|
||||
}
|
||||
|
||||
async _saveChanges (cookieJar: CookieJar) {
|
||||
await models.cookieJar.update(cookieJar);
|
||||
}
|
||||
|
||||
_handleChangeRawValue (e: Event & {target: HTMLInputElement}) {
|
||||
const value = e.target.value;
|
||||
|
||||
clearTimeout(this._rawTimeout);
|
||||
this._rawTimeout = setTimeout(async () => {
|
||||
const cookie = toughCookie.Cookie.parse(value);
|
||||
if (!this.state.cookie) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._handleCookieUpdate(this.state.cookie, cookie);
|
||||
}, DEBOUNCE_MILLIS);
|
||||
}
|
||||
|
||||
async _handleCookieUpdate (oldCookie: Cookie, cookie: Cookie) {
|
||||
// Clone so we don't modify the original
|
||||
const cookieJar = clone(this.props.cookieJar);
|
||||
|
||||
const {cookies} = cookieJar;
|
||||
const index = cookies.findIndex(c => deepEqual(c, oldCookie));
|
||||
|
||||
cookieJar.cookies = [
|
||||
...cookies.slice(0, index),
|
||||
cookie,
|
||||
...cookies.slice(index + 1)
|
||||
];
|
||||
|
||||
this.setState({cookie});
|
||||
|
||||
await this._saveChanges(cookieJar);
|
||||
trackEvent('Cookie', 'Update');
|
||||
}
|
||||
|
||||
_handleChange (field: string, eventOrValue: Event & {target: HTMLInputElement}) {
|
||||
const {cookie} = this.state;
|
||||
let valid = true;
|
||||
|
||||
const value = typeof eventOrValue === 'object'
|
||||
? eventOrValue.target.checked
|
||||
: eventOrValue;
|
||||
|
||||
if (valid) {
|
||||
const newCookie = Object.assign({}, cookie, {[field]: value});
|
||||
|
||||
clearTimeout(this._cookieUpdateTimeout);
|
||||
this._cookieUpdateTimeout = setTimeout(async () => {
|
||||
if (cookie) {
|
||||
await this._handleCookieUpdate(cookie, newCookie);
|
||||
this.setState({cookie: newCookie});
|
||||
}
|
||||
}, DEBOUNCE_MILLIS * 2);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isValid: {
|
||||
...this.state.isValid,
|
||||
[field]: valid
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_capitalize (str: string) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
_getRawCookieString () {
|
||||
const {cookie} = this.state;
|
||||
|
||||
if (!cookie) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
return cookieToString(toughCookie.Cookie.fromJSON(JSON.stringify(cookie)));
|
||||
} catch (err) {
|
||||
console.warn('Failed to parse cookie string', err);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
cookieJar,
|
||||
handleRender,
|
||||
handleGetRenderContext
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
isValid,
|
||||
cookie
|
||||
} = this.state;
|
||||
|
||||
const textFields = ['key', 'value', 'domain', 'path', 'expires'];
|
||||
const checkFields = ['secure', 'httpOnly'];
|
||||
|
||||
return (
|
||||
<Modal ref={this._setModalRef} {...this.props}>
|
||||
<ModalHeader>Edit Cookie</ModalHeader>
|
||||
<ModalBody className="cookie-modify">
|
||||
{cookieJar && cookie && (
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab>
|
||||
<button>Friendly</button>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button>Raw</button>
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel>
|
||||
<div className="pad">
|
||||
{textFields.map((field, i) => {
|
||||
const val = (cookie[field] || '').toString();
|
||||
|
||||
return (
|
||||
<div className="form-control form-control--outlined" key={i}>
|
||||
<label>{this._capitalize(field)}
|
||||
<OneLineEditor
|
||||
className={isValid[field] ? '' : 'input--error'}
|
||||
forceEditor
|
||||
type="text"
|
||||
render={handleRender}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
defaultValue={val || ''}
|
||||
onChange={value => this._handleChange(field, value)}/>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="pad no-pad-top cookie-modify__checkboxes row-around txt-lg">
|
||||
{checkFields.map((field, i) => {
|
||||
const checked = !!cookie[field];
|
||||
|
||||
return (
|
||||
<label key={i}>{this._capitalize(field)}
|
||||
<input
|
||||
className="space-left"
|
||||
type="checkbox"
|
||||
name={field}
|
||||
defaultChecked={checked || false}
|
||||
onChange={e => this._handleChange(field, e)}
|
||||
/>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel className="react-tabs__tab-panel pad">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>Raw Cookie String
|
||||
<input type="text"
|
||||
onChange={this._handleChangeRawValue}
|
||||
defaultValue={this._getRawCookieString()}/>
|
||||
</label>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<button className="btn" onClick={this.hide}>
|
||||
Done
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// export CookieModifyModal;
|
||||
export default CookieModifyModal;
|
||||
// @flow
|
||||
import React, {PureComponent} from 'react';
|
||||
import uuid from 'uuid';
|
||||
import {Tabs, TabList, Tab, TabPanel} from 'react-tabs';
|
||||
import autobind from 'autobind-decorator';
|
||||
import deepEqual from 'deep-equal';
|
||||
import * as toughCookie from 'tough-cookie';
|
||||
import * as models from '../../../models';
|
||||
import clone from 'clone';
|
||||
import {DEBOUNCE_MILLIS} from '../../../common/constants';
|
||||
import {trackEvent} from '../../../analytics/index';
|
||||
import Modal from '../base/modal';
|
||||
import ModalBody from '../base/modal-body';
|
||||
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 {
|
||||
props: {
|
||||
handleRender: Function,
|
||||
handleGetRenderContext: Function,
|
||||
workspace: Workspace,
|
||||
cookieJar: CookieJar
|
||||
};
|
||||
|
||||
state: {
|
||||
cookie: Cookie | null,
|
||||
rawValue: string
|
||||
};
|
||||
|
||||
modal: Modal | null;
|
||||
_rawTimeout: number | null;
|
||||
_cookieUpdateTimeout: number | null;
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
cookie: null,
|
||||
rawValue: ''
|
||||
};
|
||||
|
||||
this._rawTimeout = null;
|
||||
this._cookieUpdateTimeout = null;
|
||||
}
|
||||
|
||||
_setModalRef (n: Modal | null) {
|
||||
this.modal = n;
|
||||
}
|
||||
|
||||
async show (cookie: Cookie) {
|
||||
// Dunno why this is sent as an array
|
||||
cookie = cookie[0] || cookie;
|
||||
|
||||
const {cookieJar} = this.props;
|
||||
const oldCookie = cookieJar.cookies.find(c => deepEqual(c, cookie));
|
||||
|
||||
if (!oldCookie) {
|
||||
// Cookie not found in jar
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({cookie});
|
||||
|
||||
this.modal && this.modal.show();
|
||||
|
||||
trackEvent('Cookie Modifier', 'Show');
|
||||
}
|
||||
|
||||
hide () {
|
||||
this.modal && this.modal.hide();
|
||||
}
|
||||
|
||||
async _saveChanges (cookieJar: CookieJar) {
|
||||
await models.cookieJar.update(cookieJar);
|
||||
}
|
||||
|
||||
_handleChangeRawValue (e: Event & {target: HTMLInputElement}) {
|
||||
const value = e.target.value;
|
||||
|
||||
clearTimeout(this._rawTimeout);
|
||||
this._rawTimeout = setTimeout(async () => {
|
||||
const cookie = toughCookie.Cookie.parse(value);
|
||||
if (!this.state.cookie) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._handleCookieUpdate(cookie);
|
||||
}, DEBOUNCE_MILLIS * 2);
|
||||
}
|
||||
|
||||
async _handleCookieUpdate (newCookie: Cookie) {
|
||||
const cookie = clone(newCookie);
|
||||
|
||||
// Sanitize expires field
|
||||
const expires = (new Date(cookie.expires || '')).getTime();
|
||||
if (isNaN(expires)) {
|
||||
delete cookie.expires;
|
||||
} else {
|
||||
cookie.expires = expires;
|
||||
}
|
||||
|
||||
// Clone so we don't modify the original
|
||||
const cookieJar = clone(this.props.cookieJar);
|
||||
|
||||
const {cookies} = cookieJar;
|
||||
|
||||
const index = cookies.findIndex(c => c.id === cookie.id);
|
||||
|
||||
cookieJar.cookies = [
|
||||
...cookies.slice(0, index),
|
||||
cookie,
|
||||
...cookies.slice(index + 1)
|
||||
];
|
||||
|
||||
this.setState({cookie});
|
||||
|
||||
await this._saveChanges(cookieJar);
|
||||
trackEvent('Cookie', 'Update');
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
_handleChange (field: string, eventOrValue: string | Event & {target: HTMLInputElement}) {
|
||||
const {cookie} = this.state;
|
||||
|
||||
let value;
|
||||
|
||||
if (typeof eventOrValue === 'string') {
|
||||
value = eventOrValue.trim();
|
||||
} else {
|
||||
if (eventOrValue.target.type === 'checkbox') {
|
||||
value = eventOrValue.target.checked;
|
||||
} else {
|
||||
value = eventOrValue.target.value.trim();
|
||||
}
|
||||
}
|
||||
|
||||
const newCookie = Object.assign({}, cookie, {[field]: value});
|
||||
|
||||
clearTimeout(this._cookieUpdateTimeout);
|
||||
this._cookieUpdateTimeout = setTimeout(async () => {
|
||||
await this._handleCookieUpdate(newCookie);
|
||||
this.setState({cookie: newCookie});
|
||||
}, DEBOUNCE_MILLIS * 2);
|
||||
}
|
||||
|
||||
_capitalize (str: string) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
_getRawCookieString () {
|
||||
const {cookie} = this.state;
|
||||
|
||||
if (!cookie) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
return cookieToString(toughCookie.Cookie.fromJSON(JSON.stringify(cookie)));
|
||||
} catch (err) {
|
||||
console.warn('Failed to parse cookie string', err);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
_renderInputField (field: string, error: string | null = null) {
|
||||
const {cookie} = this.state;
|
||||
const {handleRender, handleGetRenderContext} = this.props;
|
||||
|
||||
if (!cookie) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const val = (cookie[field] || '').toString();
|
||||
|
||||
return (
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
{this._capitalize(field)} <span className="danger">{error}</span>
|
||||
<OneLineEditor
|
||||
render={handleRender}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
defaultValue={val || ''}
|
||||
onChange={value => this._handleChange(field, value)}/>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {cookieJar} = this.props;
|
||||
const {cookie} = this.state;
|
||||
const checkFields = ['secure', 'httpOnly'];
|
||||
|
||||
return (
|
||||
<Modal ref={this._setModalRef} {...this.props}>
|
||||
<ModalHeader>Edit Cookie</ModalHeader>
|
||||
<ModalBody className="cookie-modify">
|
||||
{cookieJar && cookie && (
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab>
|
||||
<button>Friendly</button>
|
||||
</Tab>
|
||||
<Tab>
|
||||
<button>Raw</button>
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel>
|
||||
<div className="pad">
|
||||
<div className="form-row">
|
||||
{this._renderInputField('key')}
|
||||
{this._renderInputField('value')}
|
||||
</div>
|
||||
<div className="form-row">
|
||||
{this._renderInputField('domain')}
|
||||
{this._renderInputField('path')}
|
||||
</div>
|
||||
{this._renderInputField(
|
||||
'expires',
|
||||
isNaN(new Date(cookie.expires || 0).getTime()) ? 'Invalid Date' : null
|
||||
)}
|
||||
</div>
|
||||
<div className="pad no-pad-top cookie-modify__checkboxes row-around txt-lg">
|
||||
{checkFields.map((field, i) => {
|
||||
const checked = !!cookie[field];
|
||||
|
||||
return (
|
||||
<label key={i}>{this._capitalize(field)}
|
||||
<input
|
||||
className="space-left"
|
||||
type="checkbox"
|
||||
name={field}
|
||||
defaultChecked={checked || false}
|
||||
onChange={e => this._handleChange(field, e)}
|
||||
/>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel className="react-tabs__tab-panel pad">
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>Raw Cookie String
|
||||
<input type="text"
|
||||
onChange={this._handleChangeRawValue}
|
||||
defaultValue={this._getRawCookieString()}/>
|
||||
</label>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<button className="btn" onClick={this.hide}>
|
||||
Done
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// export CookieModifyModal;
|
||||
export default CookieModifyModal;
|
||||
|
||||
@@ -39,13 +39,6 @@ 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;
|
||||
}
|
||||
@@ -115,8 +108,6 @@ class CookiesModal extends PureComponent {
|
||||
visibleCookieIndexes = null;
|
||||
}
|
||||
|
||||
console.log('APPLIED FILTER', filter, visibleCookieIndexes);
|
||||
|
||||
this.setState({filter, visibleCookieIndexes});
|
||||
}
|
||||
|
||||
@@ -132,7 +123,8 @@ class CookiesModal extends PureComponent {
|
||||
}
|
||||
|
||||
async show () {
|
||||
await this._ensureCookieJarExists();
|
||||
// Opened without cookie jar. Bail out and create one
|
||||
const {cookieJar, workspace} = this.props;
|
||||
|
||||
setTimeout(() => {
|
||||
this.filterInput && this.filterInput.focus();
|
||||
|
||||
@@ -536,6 +536,7 @@ class Wrapper extends React.PureComponent {
|
||||
workspace={activeWorkspace}
|
||||
cookieJar={activeCookieJar}
|
||||
/>
|
||||
|
||||
<CookieModifyModal
|
||||
handleRender={handleRender}
|
||||
handleGetRenderContext={handleGetRenderContext}
|
||||
@@ -543,6 +544,7 @@ class Wrapper extends React.PureComponent {
|
||||
cookieJar={activeCookieJar}
|
||||
workspace={activeWorkspace}
|
||||
/>
|
||||
|
||||
<NunjucksModal
|
||||
uniqueKey={`key::${this.state.forceRefreshKey}`}
|
||||
ref={registerModal}
|
||||
|
||||
@@ -4,15 +4,17 @@ import {AppContainer} from 'react-hot-loader';
|
||||
import {Provider} from 'react-redux';
|
||||
import {DragDropContext} from 'react-dnd';
|
||||
import App from './containers/app';
|
||||
import * as models from '../models';
|
||||
import {types as modelTypes} from '../models';
|
||||
import {init as initStore} from './redux/modules';
|
||||
import {init as initDB} from '../common/database';
|
||||
import {init as initSync} from '../sync';
|
||||
import {init as initAnalytics} from '../analytics';
|
||||
import {init as initPlugins} from '../plugins';
|
||||
import {types as modelTypes} from '../models';
|
||||
import {getAccountId} from '../sync/session';
|
||||
import DNDBackend from './dnd-backend';
|
||||
import './css/index.less';
|
||||
import {isDevelopment} from '../common/constants';
|
||||
|
||||
(async function () {
|
||||
await initDB(modelTypes());
|
||||
@@ -47,3 +49,8 @@ import './css/index.less';
|
||||
// Do things that can wait
|
||||
process.nextTick(initSync);
|
||||
})();
|
||||
|
||||
// Export some useful things for dev
|
||||
if (isDevelopment()) {
|
||||
window.models = models;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user