From a2517713c5eaedf356aaf7bf62c50418aad76219 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 25 Sep 2017 23:32:58 +0200 Subject: [PATCH] Autoselect active env in editor and update flow (#497) --- .eslintrc | 4 +- app/common/render.js | 27 +-- app/models/environment.js | 33 ++-- app/models/workspace.js | 4 +- .../components/base/dropdown/dropdown-hint.js | 6 +- app/ui/components/cookie-list.js | 22 +-- .../dropdowns/content-type-dropdown.js | 24 +-- app/ui/components/dropdowns/sync-dropdown.js | 25 ++- app/ui/components/editors/auth/hawk-auth.js | 20 +-- .../components/editors/auth/o-auth-2-auth.js | 66 ++++---- .../editors/body/graph-ql-editor.js | 29 ++-- app/ui/components/help-tooltip.js | 27 +-- app/ui/components/hotkey.js | 8 +- app/ui/components/keydown-binder.js | 8 +- app/ui/components/modals/changelog-modal.js | 4 - .../components/modals/cookie-modify-modal.js | 40 +++-- app/ui/components/modals/cookies-modal.js | 34 ++-- .../modals/environment-edit-modal.js | 5 - app/ui/components/modals/index.js | 8 - app/ui/components/modals/settings-modal.js | 5 - .../workspace-environments-edit-modal.js | 160 +++++++++++------- .../modals/workspace-settings-modal.js | 13 -- app/ui/components/rendered-text.js | 22 +-- app/ui/components/request-pane.js | 82 ++++----- app/ui/components/response-pane.js | 56 +++--- app/ui/components/settings/plugins.js | 26 +-- app/ui/components/sidebar/sidebar-children.js | 6 +- app/ui/components/tags/size-tag.js | 18 +- app/ui/components/tags/status-tag.js | 16 +- app/ui/components/tags/time-tag.js | 16 +- app/ui/components/time-from-now.js | 20 +-- app/ui/components/tooltip.js | 52 +++--- app/ui/components/wrapper.js | 146 ++++++++-------- app/ui/index.js | 2 +- app/ui/redux/modules/global.js | 2 +- flow-typed/react-tabs.js | 2 + package-lock.json | 102 ++++++----- package.json | 6 +- 38 files changed, 595 insertions(+), 551 deletions(-) diff --git a/.eslintrc b/.eslintrc index f8afba46d..40c17b68c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -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": { diff --git a/app/common/render.js b/app/common/render.js index a9cc9c039..aff4c5a46 100644 --- a/app/common/render.js +++ b/app/common/render.js @@ -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 | 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 diff --git a/app/models/environment.js b/app/models/environment.js index f3b645003..415e32ccc 100644 --- a/app/models/environment.js +++ b/app/models/environment.js @@ -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 { 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 { return db.docUpdate(environment, patch); } -export function findByParentId (parentId) { +export function findByParentId (parentId: string): Promise> { return db.find(type, {parentId}); } -export async function getOrCreateForWorkspaceId (workspaceId) { +export async function getOrCreateForWorkspaceId (workspaceId: string): Promise { 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 { return getOrCreateForWorkspaceId(workspace._id); } -export function getById (id) { +export function getById (id: string): Promise { return db.get(type, id); } -export function remove (environment) { +export function remove (environment: Environment): Promise { return db.remove(environment); } -export function all () { +export function all (): Promise> { return db.all(type); } diff --git a/app/models/workspace.js b/app/models/workspace.js index 16fa93533..58bb8df44 100644 --- a/app/models/workspace.js +++ b/app/models/workspace.js @@ -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 { // 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) { diff --git a/app/ui/components/base/dropdown/dropdown-hint.js b/app/ui/components/base/dropdown/dropdown-hint.js index c7378aec8..b9f865407 100644 --- a/app/ui/components/base/dropdown/dropdown-hint.js +++ b/app/ui/components/base/dropdown/dropdown-hint.js @@ -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 { render () { const {hotkey} = this.props; return ( diff --git a/app/ui/components/cookie-list.js b/app/ui/components/cookie-list.js index e7a0ce7fc..1836b138b 100644 --- a/app/ui/components/cookie-list.js +++ b/app/ui/components/cookie-list.js @@ -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, - newCookieDomainName: string, - handleShowModifyCookieModal: Function, - handleRender: Function - }; +type Props = { + onCookieAdd: Function, + onCookieDelete: Function, + cookies: Array, + newCookieDomainName: string, + handleShowModifyCookieModal: Function, + handleRender: Function +}; +@autobind +class CookieList extends React.PureComponent { _handleCookieAdd () { const newCookie: Cookie = { id: uuid.v4(), diff --git a/app/ui/components/dropdowns/content-type-dropdown.js b/app/ui/components/dropdowns/content-type-dropdown.js index 749726fdb..1c903598c 100644 --- a/app/ui/components/dropdowns/content-type-dropdown.js +++ b/app/ui/components/dropdowns/content-type-dropdown.js @@ -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 { async _checkMimeTypeChange (body: RequestBody, mimeType: string | null) { // Nothing to do if (body.mimeType === mimeType) { diff --git a/app/ui/components/dropdowns/sync-dropdown.js b/app/ui/components/dropdowns/sync-dropdown.js index 03bc167bd..6d7cdb873 100644 --- a/app/ui/components/dropdowns/sync-dropdown.js +++ b/app/ui/components/dropdowns/sync-dropdown.js @@ -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 { _hasPrompted: boolean; _isMounted: boolean; diff --git a/app/ui/components/editors/auth/hawk-auth.js b/app/ui/components/editors/auth/hawk-auth.js index c1e731f7d..480d24eb3 100644 --- a/app/ui/components/editors/auth/hawk-auth.js +++ b/app/ui/components/editors/auth/hawk-auth.js @@ -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 { _handleChangeProperty: Function; constructor (props: any) { @@ -43,7 +43,7 @@ class HawkAuth extends React.PureComponent { this._handleChangeProperty('algorithm', value); } - renderHawkAuthenticationFields (): Array> { + renderHawkAuthenticationFields (): React.Node { const hawkAuthId = this.renderInputRow( 'Auth ID', 'id', diff --git a/app/ui/components/editors/auth/o-auth-2-auth.js b/app/ui/components/editors/auth/o-auth-2-auth.js index 9e9ba3a19..0c30ef2b5 100644 --- a/app/ui/components/editors/auth/o-auth-2-auth.js +++ b/app/ui/components/editors/auth/o-auth-2-auth.js @@ -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 { _handleChangeProperty: Function; constructor (props: any) { @@ -63,9 +63,9 @@ class OAuth2Auth extends React.PureComponent { this.setState({showAdvanced}); } - async _handleUpdateAccessToken (e: Event & {target: HTMLButtonElement}): Promise { + async _handleUpdateAccessToken (e: SyntheticEvent): Promise { 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 { + async _handleUpdateRefreshToken (e: SyntheticEvent): Promise { 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): 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): 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 ? (

{tok.error} @@ -446,7 +446,7 @@ class OAuth2Auth extends React.PureComponent { )}

- )} + ) : null}
- {tok && ( + {tok ? ( Clear - )} + ) : null}   
{this.renderSchemaFetchMessage()} -
diff --git a/app/ui/components/help-tooltip.js b/app/ui/components/help-tooltip.js index e884a26a5..e19e05bf9 100644 --- a/app/ui/components/help-tooltip.js +++ b/app/ui/components/help-tooltip.js @@ -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 { render () { - const {children, className, info, ...props} = this.props; + const {children, className, style, info} = this.props; return ( - + ); diff --git a/app/ui/components/hotkey.js b/app/ui/components/hotkey.js index 5a83eb4b1..9867353c3 100644 --- a/app/ui/components/hotkey.js +++ b/app/ui/components/hotkey.js @@ -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 { render () { const {hotkey, className} = this.props; const {alt, shift, meta} = hotkey; diff --git a/app/ui/components/keydown-binder.js b/app/ui/components/keydown-binder.js index a2c4012b4..866af4793 100644 --- a/app/ui/components/keydown-binder.js +++ b/app/ui/components/keydown-binder.js @@ -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 { _handleKeydown (e: KeyboardEvent) { const {stopMetaPropagation, onKeydown, disabled} = this.props; diff --git a/app/ui/components/modals/changelog-modal.js b/app/ui/components/modals/changelog-modal.js index b14d83b28..69d386837 100644 --- a/app/ui/components/modals/changelog-modal.js +++ b/app/ui/components/modals/changelog-modal.js @@ -29,10 +29,6 @@ class ChangelogModal extends PureComponent { this.modal.hide(); } - toggle () { - this.modal.toggle(); - } - async componentDidMount () { let changelog; try { diff --git a/app/ui/components/modals/cookie-modify-modal.js b/app/ui/components/modals/cookie-modify-modal.js index 70c528abf..7b8c00c8c 100644 --- a/app/ui/components/modals/cookie-modify-modal.js +++ b/app/ui/components/modals/cookie-modify-modal.js @@ -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 { 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}); diff --git a/app/ui/components/modals/cookies-modal.js b/app/ui/components/modals/cookies-modal.js index 317f30114..e1fa404b0 100644 --- a/app/ui/components/modals/cookies-modal.js +++ b/app/ui/components/modals/cookies-modal.js @@ -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 | null +}; + @autobind -class CookiesModal extends PureComponent { - props: { - handleShowModifyCookieModal: Function, - handleRender: Function, - cookieJar: CookieJar, - workspace: Workspace - }; - - state: { - filter: string, - visibleCookieIndexes: Array | null - }; - +class CookiesModal extends PureComponent { 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); } diff --git a/app/ui/components/modals/environment-edit-modal.js b/app/ui/components/modals/environment-edit-modal.js index d102af4cf..dba193599 100644 --- a/app/ui/components/modals/environment-edit-modal.js +++ b/app/ui/components/modals/environment-edit-modal.js @@ -55,11 +55,6 @@ class EnvironmentEditModal extends PureComponent { this.modal.hide(); } - toggle (requestGroup) { - this.modal.toggle(); - this.setState({requestGroup}); - } - render () { const { editorKeyMap, diff --git a/app/ui/components/modals/index.js b/app/ui/components/modals/index.js index 0edd096e4..009351934 100644 --- a/app/ui/components/modals/index.js +++ b/app/ui/components/modals/index.js @@ -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]; diff --git a/app/ui/components/modals/settings-modal.js b/app/ui/components/modals/settings-modal.js index 2c4aca2ef..796593789 100644 --- a/app/ui/components/modals/settings-modal.js +++ b/app/ui/components/modals/settings-modal.js @@ -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; diff --git a/app/ui/components/modals/workspace-environments-edit-modal.js b/app/ui/components/modals/workspace-environments-edit-modal.js index 0a9caa9dd..8cb43cd79 100644 --- a/app/ui/components/modals/workspace-environments-edit-modal.js +++ b/app/ui/components/modals/workspace-environments-edit-modal.js @@ -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, + rootEnvironment: Environment | null, + selectedEnvironmentId: string | null +}; @autobind -class WorkspaceEnvironmentsEditModal extends PureComponent { - constructor (props) { +class WorkspaceEnvironmentsEditModal extends React.PureComponent { + 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 {

this._handleChangeEnvironmentName(activeEnvironment, name)} + onSubmit={ + name => activeEnvironment && this._handleChangeEnvironmentName(activeEnvironment, name)} value={activeEnvironment ? activeEnvironment.name : ''}/>

- {activeEnvironment && rootEnvironment !== activeEnvironment && ( + {activeEnvironment && rootEnvironment !== activeEnvironment ? ( {activeEnvironment.color && ( @@ -311,16 +361,16 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { Unset Color - )} + ) : null} - {activeEnvironment && rootEnvironment !== activeEnvironment && ( + {activeEnvironment && rootEnvironment !== activeEnvironment ? ( - )} + ) : null}
{ constructor (props: any) { super(props); this.state = { diff --git a/app/ui/components/request-pane.js b/app/ui/components/request-pane.js index 1186e1143..3cd90f987 100644 --- a/app/ui/components/request-pane.js +++ b/app/ui/components/request-pane.js @@ -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 { _handleUpdateRequestUrlTimeout: number; _handleEditDescriptionAdd () { @@ -267,7 +267,7 @@ class RequestPane extends React.PureComponent { {typeof request.body.mimeType === 'string' diff --git a/app/ui/components/response-pane.js b/app/ui/components/response-pane.js index a275b99b2..8cde30619 100644 --- a/app/ui/components/response-pane.js +++ b/app/ui/components/response-pane.js @@ -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, + editorFontSize: number, + editorIndentSize: number, + editorKeyMap: string, + editorLineWrapping: boolean, + loadStartTime: number, + responses: Array, + + // 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, - editorFontSize: number, - editorIndentSize: number, - editorKeyMap: string, - editorLineWrapping: boolean, - loadStartTime: number, - responses: Array, - - // Other - request: ?Request, - response: ?Response - }; - +class ResponsePane extends React.PureComponent { _handleGetResponseBody (): Buffer | null { if (!this.props.response) { return null; diff --git a/app/ui/components/settings/plugins.js b/app/ui/components/settings/plugins.js index 73d75c5a1..f17468b07 100644 --- a/app/ui/components/settings/plugins.js +++ b/app/ui/components/settings/plugins.js @@ -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, - npmPluginValue: string, - error: string, - isInstallingFromNpm: boolean, - isRefreshingPlugins: boolean - }; +type State = { + plugins: Array, + npmPluginValue: string, + error: string, + isInstallingFromNpm: boolean, + isRefreshingPlugins: boolean +}; +@autobind +class Plugins extends React.PureComponent { _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 { diff --git a/app/ui/components/sidebar/sidebar-children.js b/app/ui/components/sidebar/sidebar-children.js index 7d68994c3..c25cc14f1 100644 --- a/app/ui/components/sidebar/sidebar-children.js +++ b/app/ui/components/sidebar/sidebar-children.js @@ -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 { _renderChildren (children: Array) { const { handleCreateRequest, diff --git a/app/ui/components/tags/size-tag.js b/app/ui/components/tags/size-tag.js index aa8847120..204334b24 100644 --- a/app/ui/components/tags/size-tag.js +++ b/app/ui/components/tags/size-tag.js @@ -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 { render () { const {bytesRead, bytesContent, small, className} = this.props; const responseSizeReadString = misc.describeByteSize(bytesRead); diff --git a/app/ui/components/tags/status-tag.js b/app/ui/components/tags/status-tag.js index b2f3f6657..fe36e3908 100644 --- a/app/ui/components/tags/status-tag.js +++ b/app/ui/components/tags/status-tag.js @@ -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 { render () { const {statusMessage, statusCode, small} = this.props; diff --git a/app/ui/components/tags/time-tag.js b/app/ui/components/tags/time-tag.js index 15350b110..504bbf1cf 100644 --- a/app/ui/components/tags/time-tag.js +++ b/app/ui/components/tags/time-tag.js @@ -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 { render () { const { milliseconds, diff --git a/app/ui/components/time-from-now.js b/app/ui/components/time-from-now.js index d736984d2..5f175e269 100644 --- a/app/ui/components/time-from-now.js +++ b/app/ui/components/time-from-now.js @@ -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 { _interval: any; constructor (props: any) { diff --git a/app/ui/components/tooltip.js b/app/ui/components/tooltip.js index 7aa165c1c..344cf981c 100644 --- a/app/ui/components/tooltip.js +++ b/app/ui/components/tooltip.js @@ -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 { _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; } diff --git a/app/ui/components/wrapper.js b/app/ui/components/wrapper.js index c850f58d9..df732ef80 100644 --- a/app/ui/components/wrapper.js +++ b/app/ui/components/wrapper.js @@ -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, + sidebarWidth: number, + sidebarHidden: boolean, + sidebarFilter: string, + sidebarChildren: Array, + settings: Settings, + workspaces: Array, + unseenWorkspaces: Array, + workspaceChildren: Array, + environments: Array, + activeRequestResponses: Array, + 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, - sidebarWidth: number, - sidebarHidden: boolean, - sidebarFilter: string, - sidebarChildren: Array, - settings: Settings, - workspaces: Array, - unseenWorkspaces: Array, - workspaceChildren: Array, - environments: Array, - activeRequestResponses: Array, - activeWorkspace: Workspace, - activeCookieJar: CookieJar, - - // Optional - oAuth2Token: ?OAuth2Token, - activeRequest: ?Request, - activeResponse: ?Response, - activeEnvironment: ?Object - }; - - state: { - forceRefreshKey: number - }; - +class Wrapper extends React.PureComponent { 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} /> diff --git a/app/ui/index.js b/app/ui/index.js index d016d4029..816c84f92 100644 --- a/app/ui/index.js +++ b/app/ui/index.js @@ -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'; diff --git a/app/ui/redux/modules/global.js b/app/ui/redux/modules/global.js index aee489c19..645b27ecf 100644 --- a/app/ui/redux/modules/global.js +++ b/app/ui/redux/modules/global.js @@ -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'; diff --git a/flow-typed/react-tabs.js b/flow-typed/react-tabs.js index 352b20e90..0ff97b823 100644 --- a/flow-typed/react-tabs.js +++ b/flow-typed/react-tabs.js @@ -1,3 +1,5 @@ +import * as React from 'react'; + declare module 'react-tabs' { declare module.exports: { Tab: React.Element<*>, diff --git a/package-lock.json b/package-lock.json index 551873656..75e8888b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index e6331afb5..dc9c7f3aa 100644 --- a/package.json +++ b/package.json @@ -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",