Autoselect active env in editor and update flow (#497)

This commit is contained in:
Gregory Schier 2017-09-25 23:32:58 +02:00 committed by GitHub
parent 84fca15bb9
commit a2517713c5
38 changed files with 595 additions and 551 deletions

View File

@ -14,7 +14,8 @@
"__DEV__": true,
"fail": true,
"HTMLDivElement": true,
"HTMLElement": true
"HTMLElement": true,
"HTMLInputElement": true
},
"env": {
"jest/globals": true
@ -23,7 +24,6 @@
"no-duplicate-imports": "off",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/prop-types": "error",
"filenames/match-exported": ["error", "kebab"]
},
"settings": {

View File

@ -8,6 +8,7 @@ import {setDefaultProtocol} from './misc';
import * as db from './database';
import * as templating from '../templating';
import type {CookieJar} from '../models/cookie-jar';
import type {Environment} from '../models/environment';
export const KEEP_ON_ERROR = 'keep';
export const THROW_ON_ERROR = 'throw';
@ -19,23 +20,23 @@ export type RenderedRequest = Request & {
export async function buildRenderContext (
ancestors: Array<BaseModel> | null,
rootEnvironment: {data: Object},
subEnvironment: {data: Object},
rootEnvironment: Environment | null,
subEnvironment: Environment | null,
baseContext: Object = {}
): Object {
const environments = [];
const envObjects = [];
if (rootEnvironment) {
environments.push(rootEnvironment.data);
envObjects.push(rootEnvironment.data);
}
if (subEnvironment) {
environments.push(subEnvironment.data);
envObjects.push(subEnvironment.data);
}
for (const doc of (ancestors || []).reverse()) {
if (typeof doc.environment === 'object' && doc.environment !== null) {
environments.push(doc.environment);
envObjects.push(doc.environment);
}
}
@ -44,13 +45,13 @@ export async function buildRenderContext (
// Do an Object.assign, but render each property as it overwrites. This
// way we can keep same-name variables from the parent context.
const renderContext = baseContext;
for (const environment: Object of environments) {
for (const envObject: Object of envObjects) {
// Sort the keys that may have Nunjucks last, so that other keys get
// defined first. Very important if env variables defined in same obj
// (eg. {"foo": "{{ bar }}", "bar": "Hello World!"})
const keys = Object.keys(environment).sort((k1, k2) => {
if (typeof environment[k1] === 'string') {
return environment[k1].match(/({{)/) ? 1 : -1;
const keys = Object.keys(envObject).sort((k1, k2) => {
if (typeof envObject[k1] === 'string') {
return envObject[k1].match(/({{)/) ? 1 : -1;
} else {
return 0;
}
@ -70,14 +71,14 @@ export async function buildRenderContext (
*/
if (typeof renderContext[key] === 'string') {
renderContext[key] = await render(
environment[key],
envObject[key],
renderContext,
null,
KEEP_ON_ERROR,
'Environment'
);
} else {
renderContext[key] = environment[key];
renderContext[key] = envObject[key];
}
}
}
@ -192,7 +193,7 @@ export async function getRenderContext (
}
const workspace = ancestors.find(doc => doc.type === models.workspace.type);
const rootEnvironment = await models.environment.getOrCreateForWorkspace(workspace);
const rootEnvironment = await models.environment.getOrCreateForWorkspaceId(workspace ? workspace._id : 'n/a');
const subEnvironment = await models.environment.getById(environmentId);
// Add meta data helper function

View File

@ -1,9 +1,22 @@
// @flow
import * as db from '../common/database';
import type {BaseModel} from './index';
import type {Workspace} from './workspace';
export const name = 'Environment';
export const type = 'Environment';
export const prefix = 'env';
export const canDuplicate = true;
type BaseEnvironment = {
name: string,
data: Object,
color: string | null,
isPrivate: boolean
};
export type Environment = BaseModel & BaseEnvironment;
export function init () {
return {
name: 'New Environment',
@ -13,27 +26,27 @@ export function init () {
};
}
export function migrate (doc) {
export function migrate (doc: Environment): Environment {
return doc;
}
export function create (patch = {}) {
export function create (patch: Object = {}): Promise<Environment> {
if (!patch.parentId) {
throw new Error('New Environment missing `parentId`', patch);
throw new Error(`New Environment missing \`parentId\`: ${JSON.stringify(patch)}`);
}
return db.docCreate(type, patch);
}
export function update (environment, patch) {
export function update (environment: Environment, patch: Object): Promise<Environment> {
return db.docUpdate(environment, patch);
}
export function findByParentId (parentId) {
export function findByParentId (parentId: string): Promise<Array<Environment>> {
return db.find(type, {parentId});
}
export async function getOrCreateForWorkspaceId (workspaceId) {
export async function getOrCreateForWorkspaceId (workspaceId: string): Promise<Environment> {
let environment = await db.getWhere(type, {
parentId: workspaceId
});
@ -48,18 +61,18 @@ export async function getOrCreateForWorkspaceId (workspaceId) {
return environment;
}
export async function getOrCreateForWorkspace (workspace) {
export async function getOrCreateForWorkspace (workspace: Workspace): Promise<Environment> {
return getOrCreateForWorkspaceId(workspace._id);
}
export function getById (id) {
export function getById (id: string): Promise<Environment | null> {
return db.get(type, id);
}
export function remove (environment) {
export function remove (environment: Environment): Promise<void> {
return db.remove(environment);
}
export function all () {
export function all (): Promise<Array<Environment>> {
return db.all(type);
}

View File

@ -20,7 +20,7 @@ type BaseWorkspace = {
}>
};
export type Workspace = BaseWorkspace & BaseModel;
export type Workspace = BaseModel & BaseWorkspace;
export function init () {
return {
@ -32,7 +32,7 @@ export function init () {
};
}
export async function migrate (doc: Object) {
export async function migrate (doc: Workspace): Promise<Workspace> {
// There was a bug on import that would set this to the current workspace ID.
// Let's remove it here so that nothing bad happens.
if (doc.parentId !== null) {

View File

@ -1,5 +1,5 @@
// @flow
import React, {PureComponent} from 'react';
import * as React from 'react';
import type {Hotkey as HotkeyType} from '../../../../common/hotkeys';
import Hotkey from '../../hotkey';
@ -7,9 +7,7 @@ type Props = {
hotkey: HotkeyType,
};
class DropdownHint extends PureComponent {
props: Props;
class DropdownHint extends React.PureComponent<Props> {
render () {
const {hotkey} = this.props;
return (

View File

@ -1,5 +1,5 @@
// @flow
import React, {PureComponent} from 'react';
import React from 'react';
import uuid from 'uuid';
import * as toughCookie from 'tough-cookie';
import autobind from 'autobind-decorator';
@ -8,17 +8,17 @@ import PromptButton from './base/prompt-button';
import RenderedText from './rendered-text';
import type {Cookie} from '../../models/cookie-jar';
@autobind
class CookieList extends PureComponent {
props: {
onCookieAdd: Function,
onCookieDelete: Function,
cookies: Array<Cookie>,
newCookieDomainName: string,
handleShowModifyCookieModal: Function,
handleRender: Function
};
type Props = {
onCookieAdd: Function,
onCookieDelete: Function,
cookies: Array<Cookie>,
newCookieDomainName: string,
handleShowModifyCookieModal: Function,
handleRender: Function
};
@autobind
class CookieList extends React.PureComponent<Props> {
_handleCookieAdd () {
const newCookie: Cookie = {
id: uuid.v4(),

View File

@ -1,5 +1,5 @@
// @flow
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import {Dropdown, DropdownButton, DropdownDivider, DropdownItem} from '../base/dropdown';
import {trackEvent} from '../../../analytics/index';
@ -8,20 +8,20 @@ import {showModal} from '../modals/index';
import AlertModal from '../modals/alert-modal';
import type {Request, RequestBody} from '../../../models/request';
type Props = {
onChange: Function,
contentType: string | null,
children: ?React.Node,
// Optional
className?: string,
request?: Request
};
const EMPTY_MIME_TYPE = null;
@autobind
class ContentTypeDropdown extends React.PureComponent {
props: {
onChange: Function,
contentType: string | null,
children: React.Children,
// Optional
className?: string,
request?: Request
};
class ContentTypeDropdown extends React.PureComponent<Props> {
async _checkMimeTypeChange (body: RequestBody, mimeType: string | null) {
// Nothing to do
if (body.mimeType === mimeType) {

View File

@ -1,7 +1,7 @@
// @flow
import React, {PureComponent} from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import {Dropdown, DropdownDivider, DropdownItem, DropdownButton} from '../base/dropdown';
import {Dropdown, DropdownButton, DropdownDivider, DropdownItem} from '../base/dropdown';
import {showModal} from '../modals';
import * as syncStorage from '../../../sync/storage';
import * as session from '../../../sync/session';
@ -18,18 +18,17 @@ type Props = {
className?: string
};
@autobind
class SyncDropdown extends PureComponent {
props: Props;
state: {
loggedIn: boolean | null,
loading: boolean,
resourceGroupId: string | null,
syncMode: string | null,
syncPercent: number,
workspaceName: string
};
type State = {
loggedIn: boolean | null,
loading: boolean,
resourceGroupId: string | null,
syncMode: string | null,
syncPercent: number,
workspaceName: string
};
@autobind
class SyncDropdown extends React.PureComponent<Props, State> {
_hasPrompted: boolean;
_isMounted: boolean;

View File

@ -1,22 +1,22 @@
// @flow
import type {Request} from '../../../../models/request';
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import OneLineEditor from '../../codemirror/one-line-editor';
import * as misc from '../../../../common/misc';
import {HAWK_ALGORITHM_SHA1, HAWK_ALGORITHM_SHA256} from '../../../../common/constants';
import HelpTooltip from '../../help-tooltip';
@autobind
class HawkAuth extends React.PureComponent {
props: {
request: Request,
handleRender: Function,
handleGetRenderContext: Function,
onChange: Function
};
type Props = {
request: Request,
handleRender: Function,
handleGetRenderContext: Function,
onChange: Function
};
@autobind
class HawkAuth extends React.PureComponent<Props> {
_handleChangeProperty: Function;
constructor (props: any) {
@ -43,7 +43,7 @@ class HawkAuth extends React.PureComponent {
this._handleChangeProperty('algorithm', value);
}
renderHawkAuthenticationFields (): Array<React.Element<*>> {
renderHawkAuthenticationFields (): React.Node {
const hawkAuthId = this.renderInputRow(
'Auth ID',
'id',

View File

@ -2,7 +2,7 @@
import type {Request} from '../../../../models/request';
import type {OAuth2Token} from '../../../../models/o-auth-2-token';
import React from 'react';
import * as React from 'react';
import classnames from 'classnames';
import autobind from 'autobind-decorator';
import OneLineEditor from '../../codemirror/one-line-editor';
@ -18,31 +18,31 @@ import HelpTooltip from '../../help-tooltip';
import PromptButton from '../../base/prompt-button';
import TimeFromNow from '../../time-from-now';
type Props = {
handleRender: Function,
handleGetRenderContext: Function,
handleUpdateSettingsShowPasswords: Function,
onChange: Function,
request: Request,
showPasswords: boolean,
// Optional
oAuth2Token: OAuth2Token | null
};
type State = {
error: string,
loading: boolean,
showAdvanced: boolean
};
const getAuthorizationUrls = () => authorizationUrls;
const getAccessTokenUrls = () => accessTokenUrls;
let showAdvanced = false;
@autobind
class OAuth2Auth extends React.PureComponent {
props: {
handleRender: Function,
handleGetRenderContext: Function,
handleUpdateSettingsShowPasswords: Function,
onChange: Function,
request: Request,
showPasswords: boolean,
// Optional
oAuth2Token: OAuth2Token | null
};
state: {
error: string,
loading: boolean,
showAdvanced: boolean
};
class OAuth2Auth extends React.PureComponent<Props, State> {
_handleChangeProperty: Function;
constructor (props: any) {
@ -63,9 +63,9 @@ class OAuth2Auth extends React.PureComponent {
this.setState({showAdvanced});
}
async _handleUpdateAccessToken (e: Event & {target: HTMLButtonElement}): Promise<void> {
async _handleUpdateAccessToken (e: SyntheticEvent<HTMLInputElement>): Promise<void> {
const {oAuth2Token} = this.props;
const accessToken = e.target.value;
const accessToken = e.currentTarget.value;
if (oAuth2Token) {
await models.oAuth2Token.update(oAuth2Token, {accessToken});
@ -74,9 +74,9 @@ class OAuth2Auth extends React.PureComponent {
}
}
async _handleUpdateRefreshToken (e: Event & {target: HTMLButtonElement}): Promise<void> {
async _handleUpdateRefreshToken (e: SyntheticEvent<HTMLInputElement>): Promise<void> {
const {oAuth2Token} = this.props;
const refreshToken = e.target.value;
const refreshToken = e.currentTarget.value;
if (oAuth2Token) {
await models.oAuth2Token.update(oAuth2Token, {refreshToken});
@ -118,8 +118,8 @@ class OAuth2Auth extends React.PureComponent {
this._handleChangeProperty('clientId', value);
}
_handleChangeCredentialsInBody (e: Event & {target: HTMLButtonElement}): void {
this._handleChangeProperty('credentialsInBody', e.target.value === 'true');
_handleChangeCredentialsInBody (e: SyntheticEvent<HTMLInputElement>): void {
this._handleChangeProperty('credentialsInBody', e.currentTarget.value === 'true');
}
_handleChangeClientSecret (value: string): void {
@ -158,9 +158,9 @@ class OAuth2Auth extends React.PureComponent {
this._handleChangeProperty('tokenPrefix', value);
}
_handleChangeGrantType (e: Event & {target: HTMLButtonElement}): void {
trackEvent('OAuth 2', 'Change Grant Type', e.target.value);
this._handleChangeProperty('grantType', e.target.value);
_handleChangeGrantType (e: SyntheticEvent<HTMLInputElement>): void {
trackEvent('OAuth 2', 'Change Grant Type', e.currentTarget.value);
this._handleChangeProperty('grantType', e.currentTarget.value);
}
renderInputRow (
@ -430,7 +430,7 @@ class OAuth2Auth extends React.PureComponent {
)}
{/* Handle minor errors */}
{(tok && tok.error) && (
{tok && tok.error ? (
<div className="notice error margin-bottom">
<h2 className="no-margin-top txt-lg force-wrap">
{tok.error}
@ -446,7 +446,7 @@ class OAuth2Auth extends React.PureComponent {
)}
</p>
</div>
)}
) : null}
<div className="form-control form-control--outlined">
<label>
<small>
@ -468,11 +468,11 @@ class OAuth2Auth extends React.PureComponent {
</label>
</div>
<div className="pad-top text-right">
{tok && (
{tok ? (
<PromptButton className="btn btn--clicky" onClick={this._handleClearTokens}>
Clear
</PromptButton>
)}
) : null}
&nbsp;&nbsp;
<button className="btn btn--clicky"
onClick={this._handleRefreshToken}

View File

@ -2,7 +2,7 @@
import type {Request} from '../../../../models/request';
import classnames from 'classnames';
import {newBodyRaw} from '../../../../models/request';
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import {parse, print} from 'graphql';
import {introspectionQuery} from 'graphql/utilities/introspectionQuery';
@ -44,19 +44,19 @@ type Props = {
className?: string
};
type State = {
body: GraphQLBody,
schema: Object | null,
schemaFetchError: string,
schemaLastFetchTime: number,
schemaIsFetching: boolean,
hideSchemaFetchErrors: boolean,
variablesSyntaxError: string,
forceRefreshKey: number
}
@autobind
class GraphQLEditor extends React.PureComponent {
props: Props;
state: {
body: GraphQLBody,
schema: Object | null,
schemaFetchError: string,
schemaLastFetchTime: number,
schemaIsFetching: boolean,
hideSchemaFetchErrors: boolean,
variablesSyntaxError: string,
forceRefreshKey: number
};
class GraphQLEditor extends React.PureComponent<Props, State> {
_isMounted: boolean;
constructor (props: Props) {
@ -297,7 +297,8 @@ class GraphQLEditor extends React.PureComponent {
</div>
<div className="graphql-editor__schema-notice">
{this.renderSchemaFetchMessage()}
<button className={classnames('icon space-left', {'fa-spin': schemaIsFetching})} onClick={this._handleRefreshSchema}>
<button className={classnames('icon space-left', {'fa-spin': schemaIsFetching})}
onClick={this._handleRefreshSchema}>
<i className="fa fa-refresh"/>
</button>
</div>

View File

@ -1,23 +1,24 @@
// @flow
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import Tooltip from './tooltip';
type Props = {
children: React.Node,
// Optional
position?: string,
className?: string,
style?: Object,
info?: boolean
};
@autobind
class HelpTooltip extends React.PureComponent {
props: {
children: React.Children,
// Optional
position?: string,
className?: string,
info?: boolean
};
class HelpTooltip extends React.PureComponent<Props> {
render () {
const {children, className, info, ...props} = this.props;
const {children, className, style, info} = this.props;
return (
<Tooltip {...props} position="top" className={className} message={children}>
<Tooltip position="top" className={className} message={children} style={style}>
<i className={'fa ' + (info ? 'fa-info-circle' : 'fa-question-circle')}/>
</Tooltip>
);

View File

@ -1,9 +1,9 @@
// @flow
import React from 'react';
import * as React from 'react';
import classnames from 'classnames';
import type {Hotkey as HotkeyType} from '../../common/hotkeys';
import {ALT_SYM, CTRL_SYM, isMac, joinHotKeys, MOD_SYM, SHIFT_SYM} from '../../common/constants';
import * as hotkeys from '../../common/hotkeys';
import {ALT_SYM, CTRL_SYM, isMac, joinHotKeys, MOD_SYM, SHIFT_SYM} from '../../common/constants';
type Props = {
hotkey: HotkeyType,
@ -12,9 +12,7 @@ type Props = {
className?: string
};
class Hotkey extends React.PureComponent {
props: Props;
class Hotkey extends React.PureComponent<Props> {
render () {
const {hotkey, className} = this.props;
const {alt, shift, meta} = hotkey;

View File

@ -1,21 +1,19 @@
// @flow
import React from 'react';
import * as React from 'react';
import ReactDOM from 'react-dom';
import autobind from 'autobind-decorator';
import {isMac} from '../../common/constants';
type Props = {
onKeydown: Function,
children: React.Children,
children?: React.Node,
disabled?: boolean,
scoped?: boolean,
stopMetaPropagation?: boolean
};
@autobind
class KeydownBinder extends React.Component {
props: Props;
class KeydownBinder extends React.PureComponent<Props> {
_handleKeydown (e: KeyboardEvent) {
const {stopMetaPropagation, onKeydown, disabled} = this.props;

View File

@ -29,10 +29,6 @@ class ChangelogModal extends PureComponent {
this.modal.hide();
}
toggle () {
this.modal.toggle();
}
async componentDidMount () {
let changelog;
try {

View File

@ -1,5 +1,5 @@
// @flow
import React, {PureComponent} from 'react';
import * as React from 'react';
import {Tab, TabList, TabPanel, Tabs} from 'react-tabs';
import autobind from 'autobind-decorator';
import deepEqual from 'deep-equal';
@ -17,20 +17,20 @@ import {cookieToString} from '../../../common/cookies';
import type {Cookie, CookieJar} from '../../../models/cookie-jar';
import type {Workspace} from '../../../models/workspace';
type Props = {
handleRender: Function,
handleGetRenderContext: Function,
workspace: Workspace,
cookieJar: CookieJar
};
type State = {
cookie: Cookie | null,
rawValue: string
};
@autobind
class CookieModifyModal extends PureComponent {
props: {
handleRender: Function,
handleGetRenderContext: Function,
workspace: Workspace,
cookieJar: CookieJar
};
state: {
cookie: Cookie | null,
rawValue: string
};
class CookieModifyModal extends React.PureComponent<Props, State> {
modal: Modal | null;
_rawTimeout: number | null;
_cookieUpdateTimeout: number | null;
@ -78,7 +78,11 @@ class CookieModifyModal extends PureComponent {
await models.cookieJar.update(cookieJar);
}
_handleChangeRawValue (e: Event & {target: HTMLInputElement}) {
_handleChangeRawValue (e: Event) {
if (!(e.target instanceof HTMLInputElement)) {
return;
}
const value = e.target.value;
clearTimeout(this._rawTimeout);
@ -124,19 +128,21 @@ class CookieModifyModal extends PureComponent {
return cookie;
}
_handleChange (field: string, eventOrValue: string | Event & {target: HTMLInputElement}) {
_handleChange (field: string, eventOrValue: string | Event) {
const {cookie} = this.state;
let value;
if (typeof eventOrValue === 'string') {
value = eventOrValue.trim();
} else {
} else if (eventOrValue.target instanceof HTMLInputElement) {
if (eventOrValue.target.type === 'checkbox') {
value = eventOrValue.target.checked;
} else {
value = eventOrValue.target.value.trim();
}
} else {
// Should never happen
}
const newCookie = Object.assign({}, cookie, {[field]: value});

View File

@ -13,20 +13,20 @@ import type {Cookie, CookieJar} from '../../../models/cookie-jar';
import type {Workspace} from '../../../models/workspace';
import {fuzzyMatch} from '../../../common/misc';
type Props = {
handleShowModifyCookieModal: Function,
handleRender: Function,
cookieJar: CookieJar,
workspace: Workspace
};
type State = {
filter: string,
visibleCookieIndexes: Array<number> | null
};
@autobind
class CookiesModal extends PureComponent {
props: {
handleShowModifyCookieModal: Function,
handleRender: Function,
cookieJar: CookieJar,
workspace: Workspace
};
state: {
filter: string,
visibleCookieIndexes: Array<number> | null
};
class CookiesModal extends PureComponent<Props, State> {
modal: Modal | null;
filterInput: HTMLInputElement | null;
@ -39,7 +39,7 @@ class CookiesModal extends PureComponent {
};
}
_setModalRef (n: React.Element<*> | null) {
_setModalRef (n: React.Component<*> | null) {
this.modal = n;
}
@ -72,7 +72,11 @@ class CookiesModal extends PureComponent {
trackEvent('Cookie', 'Delete');
}
async _handleFilterChange (e: Event & {target: HTMLInputElement}) {
async _handleFilterChange (e: Event) {
if (!(e.target instanceof HTMLInputElement)) {
return;
}
const filter = e.target.value;
this._applyFilter(filter, this.props.cookieJar.cookies);
}

View File

@ -55,11 +55,6 @@ class EnvironmentEditModal extends PureComponent {
this.modal.hide();
}
toggle (requestGroup) {
this.modal.toggle();
this.setState({requestGroup});
}
render () {
const {
editorKeyMap,

View File

@ -28,14 +28,6 @@ export function showModal (modalCls, ...args) {
return _getModal(modalCls).show(...args);
}
export function toggleModal (modalCls, ...args) {
return _getModal(modalCls).toggle(...args);
}
export function hideModal (modalCls) {
return _getModal(modalCls).hide();
}
export function hideAllModals () {
for (const key of Object.keys(modals)) {
const modal = modals[key];

View File

@ -83,11 +83,6 @@ class SettingsModal extends PureComponent {
this.modal.hide();
}
toggle (currentTabIndex = 0) {
this.setState({currentTabIndex});
this.modal.toggle();
}
render () {
const {settings} = this.props;
const {currentTabIndex} = this.state;

View File

@ -1,5 +1,5 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
// @flow
import * as React from 'react';
import autobind from 'autobind-decorator';
import classnames from 'classnames';
import {Dropdown, DropdownButton, DropdownItem} from '../base/dropdown';
@ -15,70 +15,110 @@ import ModalFooter from '../base/modal-footer';
import * as models from '../../../models';
import {trackEvent} from '../../../analytics/index';
import {DEBOUNCE_MILLIS} from '../../../common/constants';
import type {Workspace} from '../../../models/workspace';
import type {Environment} from '../../../models/environment';
type Props = {
activeEnvironment: Environment | null,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
lineWrapping: boolean,
render: Function,
getRenderContext: Function
};
type State = {
workspace: Workspace | null,
isValid: boolean,
subEnvironments: Array<Environment>,
rootEnvironment: Environment | null,
selectedEnvironmentId: string | null
};
@autobind
class WorkspaceEnvironmentsEditModal extends PureComponent {
constructor (props) {
class WorkspaceEnvironmentsEditModal extends React.PureComponent<Props, State> {
environmentEditorRef: EnvironmentEditor | null;
colorChangeTimeout: any;
modal: Modal;
constructor (props: Props) {
super(props);
this.state = {
workspace: null,
isValid: true,
subEnvironments: [],
rootEnvironment: null,
activeEnvironmentId: null
selectedEnvironmentId: null
};
this.colorChangeTimeout = null;
}
hide () {
this.modal.hide();
this.modal && this.modal.hide();
}
_setEditorRef (n) {
this._envEditor = n;
_setEditorRef (n: EnvironmentEditor) {
this.environmentEditorRef = n;
}
_setModalRef (n) {
_setModalRef (n: Modal | null) {
this.modal = n;
}
async show (workspace) {
async show (workspace: Workspace) {
const {activeEnvironment} = this.props;
// Default to showing the currently active environment
if (activeEnvironment) {
this.setState({selectedEnvironmentId: activeEnvironment._id});
}
await this._load(workspace);
this.modal.show();
this.modal && this.modal.show();
trackEvent('Environment Editor', 'Show');
}
async toggle (workspace) {
this.modal.toggle();
await this._load(workspace);
}
async _load (workspace: Workspace | null, environmentToActivate: Environment | null = null) {
if (!workspace) {
console.warn('Failed to reload environment editor without Workspace');
return;
}
async _load (workspace, environmentToActivate = null) {
const rootEnvironment = await models.environment.getOrCreateForWorkspace(workspace);
const subEnvironments = await models.environment.findByParentId(rootEnvironment._id);
let activeEnvironmentId;
let selectedEnvironmentId;
if (environmentToActivate) {
activeEnvironmentId = environmentToActivate._id;
selectedEnvironmentId = environmentToActivate._id;
} else if (this.state.workspace && workspace._id !== this.state.workspace._id) {
// We've changed workspaces, so load the root one
activeEnvironmentId = rootEnvironment._id;
selectedEnvironmentId = rootEnvironment._id;
} else {
// We haven't changed workspaces, so try loading the last environment, and fall back
// to the root one
activeEnvironmentId = this.state.activeEnvironmentId || rootEnvironment._id;
selectedEnvironmentId = this.state.selectedEnvironmentId || rootEnvironment._id;
}
this.setState({
workspace,
rootEnvironment,
subEnvironments,
activeEnvironmentId
selectedEnvironmentId
});
}
async _handleAddEnvironment (isPrivate = false) {
async _handleAddEnvironment (isPrivate: boolean = false) {
const {rootEnvironment, workspace} = this.state;
if (!rootEnvironment) {
console.warn('Failed to add environment. Unknown root environment');
return;
}
const parentId = rootEnvironment._id;
const environment = await models.environment.create({parentId, isPrivate});
await this._load(workspace, environment);
@ -89,9 +129,9 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
);
}
async _handleShowEnvironment (environment) {
async _handleShowEnvironment (environment: Environment) {
// Don't allow switching if the current one has errors
if (!this._envEditor.isValid()) {
if (this.environmentEditorRef && !this.environmentEditorRef.isValid()) {
return;
}
@ -100,11 +140,12 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
}
const {workspace} = this.state;
await this._load(workspace, environment);
trackEvent('Environment Editor', 'Show Environment');
}
async _handleDeleteEnvironment (environment) {
async _handleDeleteEnvironment (environment: Environment) {
const {rootEnvironment, workspace} = this.state;
// Don't delete the root environment
@ -114,26 +155,30 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
// Delete the current one, then activate the root environment
await models.environment.remove(environment);
await this._load(workspace, rootEnvironment);
trackEvent('Environment', 'Delete');
}
async _handleChangeEnvironmentName (environment, name) {
async _handleChangeEnvironmentName (environment: Environment, name: string) {
const {workspace} = this.state;
// NOTE: Fetch the environment first because it might not be up to date.
// For example, editing the body updates silently.
const realEnvironment = await models.environment.getById(environment._id);
if (!realEnvironment) {
return;
}
await models.environment.update(realEnvironment, {name});
await this._load(workspace);
trackEvent('Environment', 'Rename');
}
_handleChangeEnvironmentColor (environment, color) {
clearTimeout(this._colorChangeTimeout);
this._colorChangeTimeout = setTimeout(async () => {
_handleChangeEnvironmentColor (environment: Environment, color: string | null) {
clearTimeout(this.colorChangeTimeout);
this.colorChangeTimeout = setTimeout(async () => {
const {workspace} = this.state;
await models.environment.update(environment, {color});
await this._load(workspace);
@ -143,7 +188,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
}
_didChange () {
const isValid = this._envEditor.isValid();
const isValid = this.environmentEditorRef ? this.environmentEditorRef.isValid() : false;
if (this.state.isValid !== isValid) {
this.setState({isValid});
@ -152,27 +197,27 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
this._saveChanges();
}
_getActiveEnvironment () {
const {activeEnvironmentId, subEnvironments, rootEnvironment} = this.state;
if (rootEnvironment && rootEnvironment._id === activeEnvironmentId) {
_getActiveEnvironment (): Environment | null {
const {selectedEnvironmentId, subEnvironments, rootEnvironment} = this.state;
if (rootEnvironment && rootEnvironment._id === selectedEnvironmentId) {
return rootEnvironment;
} else {
return subEnvironments.find(e => e._id === activeEnvironmentId);
return subEnvironments.find(e => e._id === selectedEnvironmentId) || null;
}
}
_handleUnsetColor (environment) {
_handleUnsetColor (environment: Environment) {
this._handleChangeEnvironmentColor(environment, null);
}
async _handleClickColorChange (environment, e) {
async _handleClickColorChange (environment: Environment) {
let el = document.querySelector('#env-color-picker');
if (!el) {
el = document.createElement('input');
el.id = 'env-color-picker';
el.type = 'color';
document.body.appendChild(el);
document.body && document.body.appendChild(el);
}
let color = environment.color || '#7d69cb';
@ -181,9 +226,11 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
await this._handleChangeEnvironmentColor(environment, color);
}
el.value = color;
el.addEventListener('input', e => {
this._handleChangeEnvironmentColor(environment, e.target.value);
el.setAttribute('value', color);
el.addEventListener('input', (e: Event) => {
if (e.target instanceof HTMLInputElement) {
this._handleChangeEnvironmentColor(environment, e.target && e.target.value);
}
});
el.click();
@ -191,14 +238,16 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
_saveChanges () {
// Only save if it's valid
if (!this._envEditor.isValid()) {
if (!this.environmentEditorRef || !this.environmentEditorRef.isValid()) {
return;
}
const data = this._envEditor.getValue();
const data = this.environmentEditorRef.getValue();
const activeEnvironment = this._getActiveEnvironment();
models.environment.update(activeEnvironment, {data});
if (activeEnvironment) {
models.environment.update(activeEnvironment, {data});
}
}
render () {
@ -285,11 +334,12 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
<h1>
<Editable singleClick
className="wide"
onSubmit={name => this._handleChangeEnvironmentName(activeEnvironment, name)}
onSubmit={
name => activeEnvironment && this._handleChangeEnvironmentName(activeEnvironment, name)}
value={activeEnvironment ? activeEnvironment.name : ''}/>
</h1>
{activeEnvironment && rootEnvironment !== activeEnvironment && (
{activeEnvironment && rootEnvironment !== activeEnvironment ? (
<Dropdown className="space-right" right>
<DropdownButton className="btn btn--clicky">
{activeEnvironment.color && (
@ -311,16 +361,16 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
Unset Color
</DropdownItem>
</Dropdown>
)}
) : null}
{activeEnvironment && rootEnvironment !== activeEnvironment && (
{activeEnvironment && rootEnvironment !== activeEnvironment ? (
<PromptButton
value={activeEnvironment}
onClick={this._handleDeleteEnvironment}
className="btn btn--clicky">
<i className="fa fa-trash-o"/>
</PromptButton>
)}
) : null}
</div>
<div className="env-modal__editor">
<EnvironmentEditor
@ -354,16 +404,4 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
}
}
WorkspaceEnvironmentsEditModal.propTypes = {
onChange: PropTypes.func.isRequired,
editorFontSize: PropTypes.number.isRequired,
editorIndentSize: PropTypes.number.isRequired,
editorKeyMap: PropTypes.string.isRequired,
render: PropTypes.func.isRequired,
getRenderContext: PropTypes.func.isRequired,
lineWrapping: PropTypes.bool.isRequired
};
export default WorkspaceEnvironmentsEditModal;
export let show = null;

View File

@ -131,19 +131,6 @@ class WorkspaceSettingsModal extends PureComponent {
trackEvent('Certificates', 'Toggle');
}
toggle (workspace) {
this.modal.toggle();
this.setState({
workspace,
showAddCertificateForm: false,
crtPath: '',
keyPath: '',
pfxPath: '',
host: '',
passphrase: ''
});
}
show () {
const hasDescription = !!this.props.workspace.description;
this.setState({

View File

@ -1,18 +1,18 @@
// @flow
import React from 'react';
import * as React from 'react';
class RenderedText extends React.PureComponent {
props: {
component: string,
children: string,
render: Function,
props?: Object
};
type Props = {
component: string,
children: string,
render: Function,
props?: Object
};
state: {
renderedText: string
};
type State = {
renderedText: string
};
class RenderedText extends React.PureComponent<Props, State> {
constructor (props: any) {
super(props);
this.state = {

View File

@ -3,7 +3,7 @@ import type {Request} from '../../models/request';
import type {Workspace} from '../../models/workspace';
import type {OAuth2Token} from '../../models/o-auth-2-token';
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import {Tab, TabList, TabPanel, Tabs} from 'react-tabs';
import ContentTypeDropdown from './dropdowns/content-type-dropdown';
@ -26,46 +26,46 @@ import MarkdownPreview from './markdown-preview';
import type {Settings} from '../../models/settings';
import * as hotkeys from '../../common/hotkeys';
type Props = {
// Functions
forceUpdateRequest: Function,
handleSend: Function,
handleSendAndDownload: Function,
handleCreateRequest: Function,
handleGenerateCode: Function,
handleRender: Function,
handleGetRenderContext: Function,
updateRequestUrl: Function,
updateRequestMethod: Function,
updateRequestBody: Function,
updateRequestParameters: Function,
updateRequestAuthentication: Function,
updateRequestHeaders: Function,
updateRequestMimeType: Function,
updateSettingsShowPasswords: Function,
updateSettingsUseBulkHeaderEditor: Function,
handleImport: Function,
handleImportFile: Function,
// Other
useBulkHeaderEditor: boolean,
showPasswords: boolean,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
editorLineWrapping: boolean,
workspace: Workspace,
settings: Settings,
environmentId: string,
forceRefreshCounter: number,
// Optional
request: ?Request,
oAuth2Token: ?OAuth2Token
};
@autobind
class RequestPane extends React.PureComponent {
props: {
// Functions
forceUpdateRequest: Function,
handleSend: Function,
handleSendAndDownload: Function,
handleCreateRequest: Function,
handleGenerateCode: Function,
handleRender: Function,
handleGetRenderContext: Function,
updateRequestUrl: Function,
updateRequestMethod: Function,
updateRequestBody: Function,
updateRequestParameters: Function,
updateRequestAuthentication: Function,
updateRequestHeaders: Function,
updateRequestMimeType: Function,
updateSettingsShowPasswords: Function,
updateSettingsUseBulkHeaderEditor: Function,
handleImport: Function,
handleImportFile: Function,
// Other
useBulkHeaderEditor: boolean,
showPasswords: boolean,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
editorLineWrapping: boolean,
workspace: Workspace,
settings: Settings,
environmentId: string,
forceRefreshCounter: number,
// Optional
request: ?Request,
oAuth2Token: ?OAuth2Token
};
class RequestPane extends React.PureComponent<Props> {
_handleUpdateRequestUrlTimeout: number;
_handleEditDescriptionAdd () {
@ -267,7 +267,7 @@ class RequestPane extends React.PureComponent {
<TabList>
<Tab>
<ContentTypeDropdown onChange={updateRequestMimeType}
contentType={request.body.mimeType}
contentType={request.body.mimeType || ''}
request={request}
className="tall">
{typeof request.body.mimeType === 'string'

View File

@ -2,7 +2,7 @@
import type {Request} from '../../models/request';
import type {Response} from '../../models/response';
import React, {PureComponent} from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import fs from 'fs';
import mime from 'mime-types';
@ -27,34 +27,34 @@ import {trackEvent} from '../../analytics';
import Hotkey from './hotkey';
import * as hotkeys from '../../common/hotkeys';
type Props = {
// Functions
handleSetFilter: Function,
showCookiesModal: Function,
handleSetPreviewMode: Function,
handleSetActiveResponse: Function,
handleDeleteResponses: Function,
handleDeleteResponse: Function,
handleShowRequestSettings: Function,
// Required
previewMode: string,
filter: string,
filterHistory: Array<string>,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
editorLineWrapping: boolean,
loadStartTime: number,
responses: Array<Object>,
// Other
request: ?Request,
response: ?Response
};
@autobind
class ResponsePane extends PureComponent {
props: {
// Functions
handleSetFilter: Function,
showCookiesModal: Function,
handleSetPreviewMode: Function,
handleSetActiveResponse: Function,
handleDeleteResponses: Function,
handleDeleteResponse: Function,
handleShowRequestSettings: Function,
// Required
previewMode: string,
filter: string,
filterHistory: Array<string>,
editorFontSize: number,
editorIndentSize: number,
editorKeyMap: string,
editorLineWrapping: boolean,
loadStartTime: number,
responses: Array<Object>,
// Other
request: ?Request,
response: ?Response
};
class ResponsePane extends React.PureComponent<Props> {
_handleGetResponseBody (): Buffer | null {
if (!this.props.response) {
return null;

View File

@ -1,7 +1,7 @@
// @flow
import type {Plugin} from '../../../plugins/index';
import {getPlugins} from '../../../plugins/index';
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import * as electron from 'electron';
import Button from '../base/button';
@ -14,16 +14,16 @@ import Link from '../base/link';
import {delay} from '../../../common/misc';
import {PLUGIN_PATH} from '../../../common/constants';
@autobind
class Plugins extends React.PureComponent {
state: {
plugins: Array<Plugin>,
npmPluginValue: string,
error: string,
isInstallingFromNpm: boolean,
isRefreshingPlugins: boolean
};
type State = {
plugins: Array<Plugin>,
npmPluginValue: string,
error: string,
isInstallingFromNpm: boolean,
isRefreshingPlugins: boolean
};
@autobind
class Plugins extends React.PureComponent<void, State> {
_isMounted: boolean;
constructor (props: any) {
@ -41,8 +41,10 @@ class Plugins extends React.PureComponent {
this.setState({error: ''});
}
_handleAddNpmPluginChange (e: Event & {target: HTMLButtonElement}) {
this.setState({npmPluginValue: e.target.value});
_handleAddNpmPluginChange (e: Event) {
if (e.target instanceof HTMLInputElement) {
this.setState({npmPluginValue: e.target.value});
}
}
async _handleAddFromNpm (e: Event): Promise<void> {

View File

@ -1,5 +1,5 @@
// @flow
import React from 'react';
import * as React from 'react';
import SidebarRequestRow from './sidebar-request-row';
import SidebarRequestGroupRow from './sidebar-request-group-row';
import * as models from '../../../models/index';
@ -31,9 +31,7 @@ type Props = {
activeRequest?: Request
};
class SidebarChildren extends React.PureComponent {
props: Props;
class SidebarChildren extends React.PureComponent<Props> {
_renderChildren (children: Array<Child>) {
const {
handleCreateRequest,

View File

@ -1,19 +1,19 @@
// @flow
import React from 'react';
import * as React from 'react';
import classnames from 'classnames';
import * as misc from '../../../common/misc';
import Tooltip from '../tooltip';
class SizeTag extends React.PureComponent {
props: {
bytesRead: number,
bytesContent: number,
type Props = {
bytesRead: number,
bytesContent: number,
// Optional
small?: boolean,
className?: string
};
// Optional
small?: boolean,
className?: string
};
class SizeTag extends React.PureComponent<Props> {
render () {
const {bytesRead, bytesContent, small, className} = this.props;
const responseSizeReadString = misc.describeByteSize(bytesRead);

View File

@ -1,18 +1,18 @@
// @flow
import React, {PureComponent} from 'react';
import * as React from 'react';
import classnames from 'classnames';
import {RESPONSE_CODE_DESCRIPTIONS, RESPONSE_CODE_REASONS} from '../../../common/constants';
import Tooltip from '../tooltip';
class StatusTag extends PureComponent {
props: {
statusCode: number,
type Props = {
statusCode: number,
// Optional
small?: boolean,
statusMessage?: string
};
// Optional
small?: boolean,
statusMessage?: string
};
class StatusTag extends React.PureComponent<Props> {
render () {
const {statusMessage, statusCode, small} = this.props;

View File

@ -1,17 +1,17 @@
// @flow
import React, {PureComponent} from 'react';
import * as React from 'react';
import classnames from 'classnames';
import Tooltip from '../tooltip';
class TimeTag extends PureComponent {
props: {
milliseconds: number,
type Props = {
milliseconds: number,
// Optional
small?: boolean,
className?: string
};
// Optional
small?: boolean,
className?: string
};
class TimeTag extends React.PureComponent<Props> {
render () {
const {
milliseconds,

View File

@ -1,18 +1,18 @@
// @flow
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import moment from 'moment';
type Props = {
timestamp: number
};
type State = {
text: string
};
@autobind
class TimeFromNow extends React.PureComponent {
props: {
timestamp: number
};
state: {
text: string
};
class TimeFromNow extends React.PureComponent<Props, State> {
_interval: any;
constructor (props: any) {

View File

@ -1,30 +1,30 @@
// @flow
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import classnames from 'classnames';
import ReactDOM from 'react-dom';
type Props = {
children: React.Node,
message: React.Node,
position: 'bottom' | 'top' | 'right' | 'left',
// Optional
className?: string,
delay?: number
};
type State = {
visible: boolean
};
@autobind
class Tooltip extends React.PureComponent {
props: {
children: React.Children,
message: React.Children | string,
position: 'bottom' | 'top' | 'right' | 'left',
// Optional
className?: string,
delay?: number
};
state: {
visible: boolean
};
class Tooltip extends React.PureComponent<Props, State> {
_showTimeout: number;
// TODO: Figure out what type these should be
_tooltip: any;
_bubble: any;
_tooltip: ?HTMLDivElement;
_bubble: ?HTMLDivElement;
constructor (props: any) {
super(props);
@ -40,11 +40,11 @@ class Tooltip extends React.PureComponent {
};
}
_setTooltipRef (n: React.Element<*>): void {
_setTooltipRef (n: ?HTMLDivElement) {
this._tooltip = n;
}
_setBubbleRef (n: React.Element<*>): void {
_setBubbleRef (n: ?HTMLDivElement) {
this._bubble = n;
}
@ -54,14 +54,14 @@ class Tooltip extends React.PureComponent {
_handleMouseEnter (e: MouseEvent): void {
this._showTimeout = setTimeout((): void => {
const tooltip = ReactDOM.findDOMNode(this._tooltip);
const bubble = ReactDOM.findDOMNode(this._bubble);
const tooltip = this._tooltip;
const bubble = this._bubble;
if (!tooltip || !(tooltip instanceof HTMLDivElement)) {
if (!tooltip) {
return;
}
if (!bubble || !(bubble instanceof HTMLDivElement)) {
if (!bubble) {
return;
}
@ -95,8 +95,8 @@ class Tooltip extends React.PureComponent {
clearTimeout(this._showTimeout);
this.setState({visible: false});
const bubble = ReactDOM.findDOMNode(this._bubble);
if (!bubble || !(bubble instanceof HTMLDivElement)) {
const bubble = this._bubble;
if (!bubble) {
return;
}

View File

@ -6,7 +6,7 @@ import type {Workspace} from '../../models/workspace';
import type {Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter} from '../../models/request';
import {updateMimeType} from '../../models/request';
import React from 'react';
import * as React from 'react';
import autobind from 'autobind-decorator';
import classnames from 'classnames';
import {registerModal, showModal} from './modals/index';
@ -40,6 +40,77 @@ import * as models from '../../models/index';
import {trackEvent} from '../../analytics/index';
import * as importers from 'insomnia-importers';
import type {CookieJar} from '../../models/cookie-jar';
import type {Environment} from '../../models/environment';
type Props = {
// Helper Functions
handleActivateRequest: Function,
handleSetSidebarFilter: Function,
handleToggleMenuBar: Function,
handleImportFileToWorkspace: Function,
handleImportUriToWorkspace: Function,
handleExportFile: Function,
handleSetActiveWorkspace: Function,
handleSetActiveEnvironment: Function,
handleMoveDoc: Function,
handleCreateRequest: Function,
handleDuplicateRequest: Function,
handleDuplicateRequestGroup: Function,
handleDuplicateWorkspace: Function,
handleCreateRequestGroup: Function,
handleGenerateCodeForActiveRequest: Function,
handleGenerateCode: Function,
handleCopyAsCurl: Function,
handleCreateRequestForWorkspace: Function,
handleSetRequestPaneRef: Function,
handleSetResponsePaneRef: Function,
handleSetResponsePreviewMode: Function,
handleRender: Function,
handleGetRenderContext: Function,
handleSetResponseFilter: Function,
handleSetActiveResponse: Function,
handleSetSidebarRef: Function,
handleStartDragSidebar: Function,
handleResetDragSidebar: Function,
handleStartDragPaneHorizontal: Function,
handleStartDragPaneVertical: Function,
handleResetDragPaneHorizontal: Function,
handleResetDragPaneVertical: Function,
handleSetRequestGroupCollapsed: Function,
handleSendRequestWithEnvironment: Function,
handleSendAndDownloadRequestWithEnvironment: Function,
// Properties
loadStartTime: number,
isLoading: boolean,
paneWidth: number,
paneHeight: number,
responsePreviewMode: string,
responseFilter: string,
responseFilterHistory: Array<string>,
sidebarWidth: number,
sidebarHidden: boolean,
sidebarFilter: string,
sidebarChildren: Array<Object>,
settings: Settings,
workspaces: Array<Workspace>,
unseenWorkspaces: Array<Workspace>,
workspaceChildren: Array<Object>,
environments: Array<Object>,
activeRequestResponses: Array<Response>,
activeWorkspace: Workspace,
activeCookieJar: CookieJar,
activeEnvironment: Environment | null,
// Optional
oAuth2Token: ?OAuth2Token,
activeRequest: ?Request,
activeResponse: ?Response,
};
type State = {
forceRefreshKey: number
};
const rUpdate = (request, ...args) => {
if (!request) {
@ -52,77 +123,7 @@ const rUpdate = (request, ...args) => {
const sUpdate = models.settings.update;
@autobind
class Wrapper extends React.PureComponent {
props: {
// Helper Functions
handleActivateRequest: Function,
handleSetSidebarFilter: Function,
handleToggleMenuBar: Function,
handleImportFileToWorkspace: Function,
handleImportUriToWorkspace: Function,
handleExportFile: Function,
handleSetActiveWorkspace: Function,
handleSetActiveEnvironment: Function,
handleMoveDoc: Function,
handleCreateRequest: Function,
handleDuplicateRequest: Function,
handleDuplicateRequestGroup: Function,
handleDuplicateWorkspace: Function,
handleCreateRequestGroup: Function,
handleGenerateCodeForActiveRequest: Function,
handleGenerateCode: Function,
handleCopyAsCurl: Function,
handleCreateRequestForWorkspace: Function,
handleSetRequestPaneRef: Function,
handleSetResponsePaneRef: Function,
handleSetResponsePreviewMode: Function,
handleRender: Function,
handleGetRenderContext: Function,
handleSetResponseFilter: Function,
handleSetActiveResponse: Function,
handleSetSidebarRef: Function,
handleStartDragSidebar: Function,
handleResetDragSidebar: Function,
handleStartDragPaneHorizontal: Function,
handleStartDragPaneVertical: Function,
handleResetDragPaneHorizontal: Function,
handleResetDragPaneVertical: Function,
handleSetRequestGroupCollapsed: Function,
handleSendRequestWithEnvironment: Function,
handleSendAndDownloadRequestWithEnvironment: Function,
// Properties
loadStartTime: number,
isLoading: boolean,
paneWidth: number,
paneHeight: number,
responsePreviewMode: string,
responseFilter: string,
responseFilterHistory: Array<string>,
sidebarWidth: number,
sidebarHidden: boolean,
sidebarFilter: string,
sidebarChildren: Array<Object>,
settings: Settings,
workspaces: Array<Workspace>,
unseenWorkspaces: Array<Workspace>,
workspaceChildren: Array<Object>,
environments: Array<Object>,
activeRequestResponses: Array<Response>,
activeWorkspace: Workspace,
activeCookieJar: CookieJar,
// Optional
oAuth2Token: ?OAuth2Token,
activeRequest: ?Request,
activeResponse: ?Response,
activeEnvironment: ?Object
};
state: {
forceRefreshKey: number
};
class Wrapper extends React.PureComponent<Props, State> {
constructor (props: any) {
super(props);
this.state = {
@ -616,6 +617,7 @@ class Wrapper extends React.PureComponent {
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
activeEnvironment={activeEnvironment}
render={handleRender}
getRenderContext={handleGetRenderContext}
/>

View File

@ -1,4 +1,4 @@
import React from 'react';
import * as React from 'react';
import ReactDOM from 'react-dom';
import {AppContainer} from 'react-hot-loader';
import {Provider} from 'react-redux';

View File

@ -1,5 +1,5 @@
import electron from 'electron';
import React from 'react';
import * as React from 'react';
import {combineReducers} from 'redux';
import fs from 'fs';
import path from 'path';

View File

@ -1,3 +1,5 @@
import * as React from 'react';
declare module 'react-tabs' {
declare module.exports: {
Tab: React.Element<*>,

102
package-lock.json generated
View File

@ -382,6 +382,16 @@
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
"dev": true
},
"array-includes": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
"integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
"dev": true,
"requires": {
"define-properties": "1.1.2",
"es-abstract": "1.8.2"
}
},
"array-map": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz",
@ -412,16 +422,6 @@
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
},
"array.prototype.find": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz",
"integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=",
"dev": true,
"requires": {
"define-properties": "1.1.2",
"es-abstract": "1.7.0"
}
},
"arrify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
@ -3466,15 +3466,24 @@
}
},
"es-abstract": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz",
"integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=",
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.2.tgz",
"integrity": "sha512-dvhwFL3yjQxNNsOWx6exMlaDrRHCRGMQlnx5lsXDCZ/J7G/frgIIl94zhZSp/galVAYp7VzPi1OrAHta89/yGQ==",
"dev": true,
"requires": {
"es-to-primitive": "1.1.1",
"function-bind": "1.1.0",
"function-bind": "1.1.1",
"has": "1.0.1",
"is-callable": "1.1.3",
"is-regex": "1.0.4"
},
"dependencies": {
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
}
}
},
"es-to-primitive": {
@ -3731,9 +3740,9 @@
}
},
"eslint-plugin-flowtype": {
"version": "2.35.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.35.0.tgz",
"integrity": "sha512-zjXGjOsHds8b84C0Ad3VViKh+sUA9PeXKHwPRlSLwwSX0v1iUJf/6IX7wxc+w2T2tnDH8PT6B/YgtcEuNI3ssA==",
"version": "2.36.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.36.0.tgz",
"integrity": "sha512-f127/0KsOXlsszisFoBLTHp4eWrqPPHEExfn2O+wHr4LHRMoC17H4/Yvutk0Tbs3LZvhB/4chujAbchMb9yQnQ==",
"dev": true,
"requires": {
"lodash": "4.17.4"
@ -3770,16 +3779,33 @@
"dev": true
},
"eslint-plugin-react": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.0.tgz",
"integrity": "sha1-nEi0jRAVVLU1VBPnxkI4q95u8e8=",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz",
"integrity": "sha512-tvjU9u3VqmW2vVuYnE8Qptq+6ji4JltjOjJ9u7VAOxVYkUkyBZWRvNYKbDv5fN+L6wiA+4we9+qQahZ0m63XEA==",
"dev": true,
"requires": {
"array.prototype.find": "2.0.4",
"doctrine": "1.5.0",
"doctrine": "2.0.0",
"has": "1.0.1",
"jsx-ast-utils": "1.4.1",
"object.assign": "4.0.4"
"jsx-ast-utils": "2.0.1",
"prop-types": "15.5.10"
},
"dependencies": {
"doctrine": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
"integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
"dev": true,
"requires": {
"esutils": "2.0.2",
"isarray": "1.0.0"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
}
}
},
"eslint-plugin-standard": {
@ -4292,9 +4318,9 @@
"dev": true
},
"flow-bin": {
"version": "0.50.0",
"resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.50.0.tgz",
"integrity": "sha1-1M2yQw3uGjWZ8Otv5VEUbjAnJWo=",
"version": "0.55.0",
"resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.55.0.tgz",
"integrity": "sha1-kIPakye9jKtrQHbWPYXyJHp+rhs=",
"dev": true
},
"for-in": {
@ -7973,10 +7999,13 @@
"integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c="
},
"jsx-ast-utils": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
"integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=",
"dev": true
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
"integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
"dev": true,
"requires": {
"array-includes": "3.0.3"
}
},
"kind-of": {
"version": "3.2.2",
@ -9039,17 +9068,6 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
},
"object.assign": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz",
"integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=",
"dev": true,
"requires": {
"define-properties": "1.1.2",
"function-bind": "1.1.0",
"object-keys": "1.0.11"
}
},
"object.omit": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",

View File

@ -184,15 +184,15 @@
"eslint-config-semistandard": "^7.0.0",
"eslint-config-standard": "^7.0.0",
"eslint-plugin-filenames": "^1.1.0",
"eslint-plugin-flowtype": "^2.35.0",
"eslint-plugin-flowtype": "^2.36.0",
"eslint-plugin-html": "^2.0.1",
"eslint-plugin-jest": "^19.0.1",
"eslint-plugin-json": "^1.2.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "^6.10.0",
"eslint-plugin-react": "^7.4.0",
"eslint-plugin-standard": "^2.1.1",
"file-loader": "^0.10.1",
"flow-bin": "^0.50.0",
"flow-bin": "^0.55.0",
"jest": "^19.0.2",
"less": "^2.7.2",
"less-loader": "^2.2.3",