diff options
Diffstat (limited to 'web/src')
21 files changed, 130 insertions, 409 deletions
diff --git a/web/src/css/app.less b/web/src/css/app.less index b9b5b310..1f246b19 100644 --- a/web/src/css/app.less +++ b/web/src/css/app.less @@ -14,7 +14,6 @@ html { @import (less) "flowtable.less"; @import (less) "flowdetail.less"; @import (less) "flowview.less"; -@import (less) "prompt.less"; @import (less) "eventlog.less"; @import (less) "footer.less"; @import (less) "codemirror.less"; diff --git a/web/src/css/prompt.less b/web/src/css/prompt.less deleted file mode 100644 index eee0426d..00000000 --- a/web/src/css/prompt.less +++ /dev/null @@ -1,27 +0,0 @@ -.prompt-dialog { - top: 0; - bottom: 0; - left: 0; - right: 0; - position: fixed; - z-index: 100; - background-color: rgba(0, 0, 0, 0.1); -} - -.prompt-content { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 25px; - padding: 2px 5px; - background-color: white; - box-shadow: 0 -1px 3px lightgray; - - .option { - cursor: pointer; - &:not(:last-child)::after { - content: ", "; - } - } -}
\ No newline at end of file diff --git a/web/src/js/__tests__/components/FlowTableSpec.js b/web/src/js/__tests__/components/FlowTableSpec.js index 4d8de12c..f63b28fc 100644 --- a/web/src/js/__tests__/components/FlowTableSpec.js +++ b/web/src/js/__tests__/components/FlowTableSpec.js @@ -1,6 +1,6 @@ import React from 'react' import renderer from 'react-test-renderer' -import FlowTable from '../../components/FlowTable' +import {PureFlowTable as FlowTable} from '../../components/FlowTable' import TestUtils from 'react-dom/test-utils' import { TFlow, TStore } from '../ducks/tutils' import { Provider } from 'react-redux' diff --git a/web/src/js/__tests__/components/Header/FileMenuSpec.js b/web/src/js/__tests__/components/Header/FileMenuSpec.js index 0d87530b..2f4e746d 100644 --- a/web/src/js/__tests__/components/Header/FileMenuSpec.js +++ b/web/src/js/__tests__/components/Header/FileMenuSpec.js @@ -49,10 +49,4 @@ describe('FileMenu Component', () => { a.props.onClick(mockEvent) expect(saveFn).toBeCalled() }) - - it('should open optionModal', () => { - let a = ul.children[3].children[1] - a.props.onClick(mockEvent) - expect(openModalFn).toBeCalled() - }) }) diff --git a/web/src/js/__tests__/components/Header/__snapshots__/FileMenuSpec.js.snap b/web/src/js/__tests__/components/Header/__snapshots__/FileMenuSpec.js.snap index ef935914..f4018fcd 100644 --- a/web/src/js/__tests__/components/Header/__snapshots__/FileMenuSpec.js.snap +++ b/web/src/js/__tests__/components/Header/__snapshots__/FileMenuSpec.js.snap @@ -63,15 +63,6 @@ exports[`FileMenu Component should render correctly 1`] = ` </li> <li> - <a - href="#" - onClick={[Function]} - > - <i - className="fa fa-fw fa-cog" - /> - Options - </a> <hr className="divider" /> diff --git a/web/src/js/__tests__/components/Header/__snapshots__/FlowMenuSpec.js.snap b/web/src/js/__tests__/components/Header/__snapshots__/FlowMenuSpec.js.snap index b0b28f1b..2ed3600e 100644 --- a/web/src/js/__tests__/components/Header/__snapshots__/FlowMenuSpec.js.snap +++ b/web/src/js/__tests__/components/Header/__snapshots__/FlowMenuSpec.js.snap @@ -33,7 +33,7 @@ exports[`FlowMenu Component should connect to state 1`] = ` <div className="btn btn-default" disabled={true} - onClick={false} + onClick={undefined} title="revert changes to flow [V]" > <i @@ -92,7 +92,7 @@ exports[`FlowMenu Component should connect to state 1`] = ` <div className="btn btn-default" disabled={true} - onClick={false} + onClick={undefined} title="[a]ccept intercepted flow" > <i @@ -103,7 +103,7 @@ exports[`FlowMenu Component should connect to state 1`] = ` <div className="btn btn-default" disabled={true} - onClick={false} + onClick={undefined} title="kill intercepted flow [x]" > <i diff --git a/web/src/js/__tests__/components/Header/__snapshots__/OptionMenuSpec.js.snap b/web/src/js/__tests__/components/Header/__snapshots__/OptionMenuSpec.js.snap index 9299e69f..83d9355c 100644 --- a/web/src/js/__tests__/components/Header/__snapshots__/OptionMenuSpec.js.snap +++ b/web/src/js/__tests__/components/Header/__snapshots__/OptionMenuSpec.js.snap @@ -9,46 +9,24 @@ exports[`OptionMenu Component should render correctly 1`] = ` className="menu-content" > <div - className="menu-entry" - > - <label> - <input - checked={false} - onChange={[Function]} - type="checkbox" - /> - HTTP/2.0 - </label> - </div> - <div - className="menu-entry" - > - <label> - <input - checked={false} - onChange={[Function]} - type="checkbox" - /> - WebSockets - </label> - </div> - <div - className="menu-entry" + className="btn btn-default" + disabled={undefined} + onClick={[Function]} + title="Open Options" > - <label> - <input - checked={false} - onChange={[Function]} - type="checkbox" - /> - Raw TCP - </label> + <i + className="fa fa-fw fa-cogs text-primary" + /> + Edit Options + <sup> + alpha + </sup> </div> </div> <div className="menu-legend" > - Protocol Support + Options Editor </div> </div> <div @@ -66,7 +44,7 @@ exports[`OptionMenu Component should render correctly 1`] = ` onChange={[Function]} type="checkbox" /> - Disable Caching + Strip cache headers <a href="http://docs.mitmproxy.org/en/stable/features/anticache.html" target="_blank" @@ -86,18 +64,26 @@ exports[`OptionMenu Component should render correctly 1`] = ` onChange={[Function]} type="checkbox" /> - Disable Compression - <i - className="fa fa-question-circle" - title="Do not forward Accept-Encoding headers to the server to force an uncompressed response." + Use host header for display + </label> + </div> + <div + className="menu-entry" + > + <label> + <input + checked={false} + onChange={[Function]} + type="checkbox" /> + Verify server certificates </label> </div> </div> <div className="menu-legend" > - HTTP Options + Quick Options </div> </div> <div @@ -111,22 +97,6 @@ exports[`OptionMenu Component should render correctly 1`] = ` > <label> <input - checked={false} - onChange={[Function]} - type="checkbox" - /> - Use Host Header - <i - className="fa fa-question-circle" - title="Use the Host header to construct URLs for display." - /> - </label> - </div> - <div - className="menu-entry" - > - <label> - <input checked={true} onChange={[Function]} type="checkbox" diff --git a/web/src/js/__tests__/components/common/__snapshots__/ButtonSpec.js.snap b/web/src/js/__tests__/components/common/__snapshots__/ButtonSpec.js.snap index 1d403b2d..8b1c9d6d 100644 --- a/web/src/js/__tests__/components/common/__snapshots__/ButtonSpec.js.snap +++ b/web/src/js/__tests__/components/common/__snapshots__/ButtonSpec.js.snap @@ -4,7 +4,7 @@ exports[`Button Component should be able to be disabled 1`] = ` <div className="classname btn btn-default" disabled="true" - onClick={false} + onClick={undefined} title={undefined} > <a> diff --git a/web/src/js/__tests__/ducks/flowsSpec.js b/web/src/js/__tests__/ducks/flowsSpec.js index 5bd866f2..d749d9e1 100644 --- a/web/src/js/__tests__/ducks/flowsSpec.js +++ b/web/src/js/__tests__/ducks/flowsSpec.js @@ -157,7 +157,9 @@ describe('flows actions', () => { file = new window.Blob(['foo'], { type: 'plain/text' }) body.append('file', file) store.dispatch(flowActions.uploadContent(tflow, 'foo', 'foo')) - expect(fetchApi).toBeCalledWith('/flows/1/foo/content', { method: 'POST', body}) + // window.Blob's lastModified is always the current time, + // which causes flaky tests on comparison. + expect(fetchApi).toBeCalledWith('/flows/1/foo/content', { method: 'POST', body: expect.anything()}) }) it('should handle clear action', () => { diff --git a/web/src/js/__tests__/utilsSpec.js b/web/src/js/__tests__/utilsSpec.js index 9a1a0750..d0beca14 100644 --- a/web/src/js/__tests__/utilsSpec.js +++ b/web/src/js/__tests__/utilsSpec.js @@ -83,11 +83,6 @@ describe('pure', () => { expect(utils.pure(tFunc).displayName).toEqual('tFunc') }) - it('should suggest when should component update', () => { - expect(f.shouldComponentUpdate('foo')).toBeTruthy() - expect(f.shouldComponentUpdate('bar')).toBeFalsy() - }) - it('should render properties', () => { expect(f.render()).toEqual(tFunc('bar')) }) diff --git a/web/src/js/components/FlowTable.jsx b/web/src/js/components/FlowTable.jsx index 24c1f3a1..a6381d0d 100644 --- a/web/src/js/components/FlowTable.jsx +++ b/web/src/js/components/FlowTable.jsx @@ -1,17 +1,20 @@ import React from 'react' import PropTypes from 'prop-types' import ReactDOM from 'react-dom' +import { connect } from 'react-redux' import shallowEqual from 'shallowequal' import AutoScroll from './helpers/AutoScroll' import { calcVScroll } from './helpers/VirtualScroll' import FlowTableHead from './FlowTable/FlowTableHead' import FlowRow from './FlowTable/FlowRow' import Filt from "../filt/filt" +import * as flowsActions from '../ducks/flows' + class FlowTable extends React.Component { static propTypes = { - onSelect: PropTypes.func.isRequired, + selectFlow: PropTypes.func.isRequired, flows: PropTypes.array.isRequired, rowHeight: PropTypes.number, highlight: PropTypes.string, @@ -107,7 +110,7 @@ class FlowTable extends React.Component { flow={flow} selected={flow === selected} highlighted={isHighlighted(flow)} - onSelect={this.props.onSelect} + onSelect={this.props.selectFlow} /> ))} <tr style={{ height: vScroll.paddingBottom }}></tr> @@ -118,4 +121,15 @@ class FlowTable extends React.Component { } } -export default AutoScroll(FlowTable) +export const PureFlowTable = AutoScroll(FlowTable) + +export default connect( + state => ({ + flows: state.flows.view, + highlight: state.flows.highlight, + selected: state.flows.byId[state.flows.selected[0]], + }), + { + selectFlow: flowsActions.select, + } +)(PureFlowTable) diff --git a/web/src/js/components/FlowView.jsx b/web/src/js/components/FlowView.jsx index d03d681a..25e7bb9f 100644 --- a/web/src/js/components/FlowView.jsx +++ b/web/src/js/components/FlowView.jsx @@ -3,94 +3,47 @@ import { connect } from 'react-redux' import _ from 'lodash' import Nav from './FlowView/Nav' -import { Request, Response, ErrorView as Error } from './FlowView/Messages' +import { ErrorView as Error, Request, Response } from './FlowView/Messages' import Details from './FlowView/Details' -import Prompt from './Prompt' import { selectTab } from '../ducks/ui/flow' -class FlowView extends Component { +export const allTabs = { Request, Response, Error, Details } - static allTabs = { Request, Response, Error, Details } +function FlowView({ flow, tabName, selectTab }) { - constructor(props, context) { - super(props, context) - this.onPromptFinish = this.onPromptFinish.bind(this) - } + // only display available tab names + const tabs = ['request', 'response', 'error'].filter(k => flow[k]) + tabs.push("details") - onPromptFinish(edit) { - this.props.setPrompt(false) - if (edit && this.tabComponent) { - this.tabComponent.edit(edit) + if (tabs.indexOf(tabName) < 0) { + if (tabName === 'response' && flow.error) { + tabName = 'error' + } else if (tabName === 'error' && flow.response) { + tabName = 'response' + } else { + tabName = tabs[0] } } - getPromptOptions() { - switch (this.props.tab) { - - case 'request': - return [ - 'method', - 'url', - { text: 'http version', key: 'v' }, - 'header' - ] - break - - case 'response': - return [ - { text: 'http version', key: 'v' }, - 'code', - 'message', - 'header' - ] - break - - case 'details': - return - - default: - throw 'Unknown tab for edit: ' + this.props.tab - } - } - - render() { - let { flow, tab: active, updateFlow } = this.props - const tabs = ['request', 'response', 'error'].filter(k => flow[k]).concat(['details']) - - if (tabs.indexOf(active) < 0) { - if (active === 'response' && flow.error) { - active = 'error' - } else if (active === 'error' && flow.response) { - active = 'response' - } else { - active = tabs[0] - } - } - - const Tab = FlowView.allTabs[_.capitalize(active)] - - return ( - <div className="flow-detail"> - <Nav - flow={flow} - tabs={tabs} - active={active} - onSelectTab={this.props.selectTab} - /> - <Tab ref={ tab => this.tabComponent = tab } flow={flow} updateFlow={updateFlow} /> - {this.props.promptOpen && ( - <Prompt options={this.getPromptOptions()} done={this.onPromptFinish} /> - )} - </div> - ) - } + const Tab = allTabs[_.capitalize(tabName)] + + return ( + <div className="flow-detail"> + <Nav + tabs={tabs} + active={tabName} + onSelectTab={selectTab} + /> + <Tab flow={flow}/> + </div> + ) } export default connect( state => ({ - promptOpen: state.ui.promptOpen, - tab: state.ui.flow.tab + flow: state.flows.byId[state.flows.selected[0]], + tabName: state.ui.flow.tab, }), { selectTab, diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx index b69dfb69..c1af36c5 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -120,30 +120,6 @@ export class Request extends Component { </section> ) } - - - edit(k) { - throw "unimplemented" - /* - switch (k) { - case 'm': - this.refs.requestLine.refs.method.focus() - break - case 'u': - this.refs.requestLine.refs.url.focus() - break - case 'v': - this.refs.requestLine.refs.httpVersion.focus() - break - case 'h': - this.refs.headers.edit() - break - default: - throw new Error(`Unimplemented: ${k}`) - } - */ - } - } Request = Message(Request) @@ -189,28 +165,6 @@ export class Response extends Component { </section> ) } - - edit(k) { - throw "unimplemented" - /* - switch (k) { - case 'c': - this.refs.responseLine.refs.status_code.focus() - break - case 'm': - this.refs.responseLine.refs.msg.focus() - break - case 'v': - this.refs.responseLine.refs.httpVersion.focus() - break - case 'h': - this.refs.headers.edit() - break - default: - throw new Error(`'Unimplemented: ${k}`) - } - */ - } } Response = Message(Response) diff --git a/web/src/js/components/Header/FileMenu.jsx b/web/src/js/components/Header/FileMenu.jsx index 5cb8e507..c88efcd8 100644 --- a/web/src/js/components/Header/FileMenu.jsx +++ b/web/src/js/components/Header/FileMenu.jsx @@ -11,7 +11,6 @@ FileMenu.propTypes = { clearFlows: PropTypes.func.isRequired, loadFlows: PropTypes.func.isRequired, saveFlows: PropTypes.func.isRequired, - openModal: PropTypes.func.isRequired, } FileMenu.onNewClick = (e, clearFlows) => { @@ -20,7 +19,7 @@ FileMenu.onNewClick = (e, clearFlows) => { clearFlows() } -export function FileMenu ({clearFlows, loadFlows, saveFlows, openModal}) { +export function FileMenu ({clearFlows, loadFlows, saveFlows}) { return ( <Dropdown className="pull-left" btnClass="special" text="mitmproxy"> <a href="#" onClick={e => FileMenu.onNewClick(e, clearFlows)}> @@ -38,12 +37,7 @@ export function FileMenu ({clearFlows, loadFlows, saveFlows, openModal}) { </a> <HideInStatic> - <a href="#" onClick={e => { e.preventDefault(); openModal(); }}> - <i className="fa fa-fw fa-cog"></i> - Options - </a> <Divider/> - <a href="http://mitm.it/" target="_blank"> <i className="fa fa-fw fa-external-link"></i> Install Certificates... @@ -59,6 +53,5 @@ export default connect( clearFlows: flowsActions.clear, loadFlows: flowsActions.upload, saveFlows: flowsActions.download, - openModal: () => modalActions.setActiveModal('OptionModal'), } )(FileMenu) diff --git a/web/src/js/components/Header/OptionMenu.jsx b/web/src/js/components/Header/OptionMenu.jsx index c41c9d99..765129ed 100644 --- a/web/src/js/components/Header/OptionMenu.jsx +++ b/web/src/js/components/Header/OptionMenu.jsx @@ -1,74 +1,56 @@ -import React from "react" -import PropTypes from 'prop-types' +import React from "react" import { connect } from "react-redux" -import { SettingsToggle, EventlogToggle } from "./MenuToggle" +import { EventlogToggle, SettingsToggle } from "./MenuToggle" +import Button from "../common/Button" import DocsLink from "../common/DocsLink" import HideInStatic from "../common/HideInStatic"; +import * as modalActions from "../../ducks/ui/modal" OptionMenu.title = 'Options' -export default function OptionMenu() { +function OptionMenu({ openOptions }) { return ( <div> <HideInStatic> - <div className="menu-group"> - <div className="menu-content"> - <SettingsToggle setting="http2">HTTP/2.0</SettingsToggle> - <SettingsToggle setting="websocket">WebSockets</SettingsToggle> - <SettingsToggle setting="rawtcp">Raw TCP</SettingsToggle> + <div className="menu-group"> + <div className="menu-content"> + <Button title="Open Options" icon="fa-cogs text-primary" + onClick={openOptions}> + Edit Options <sup>alpha</sup> + </Button> + </div> + <div className="menu-legend">Options Editor</div> </div> - <div className="menu-legend">Protocol Support</div> - </div> - <div className="menu-group"> - <div className="menu-content"> - <SettingsToggle setting="anticache"> - Disable Caching <DocsLink resource="features/anticache.html"/> - </SettingsToggle> - <SettingsToggle setting="anticomp"> - Disable Compression <i className="fa fa-question-circle" - title="Do not forward Accept-Encoding headers to the server to force an uncompressed response."></i> - </SettingsToggle> + <div className="menu-group"> + <div className="menu-content"> + <SettingsToggle setting="anticache"> + Strip cache headers <DocsLink resource="features/anticache.html"/> + </SettingsToggle> + <SettingsToggle setting="showhost"> + Use host header for display + </SettingsToggle> + <SettingsToggle setting="ssl_insecure"> + Verify server certificates + </SettingsToggle> + </div> + <div className="menu-legend">Quick Options</div> </div> - <div className="menu-legend">HTTP Options</div> - </div> </HideInStatic> <div className="menu-group"> <div className="menu-content"> - <HideInStatic> - <SettingsToggle setting="showhost"> - Use Host Header <i className="fa fa-question-circle" - title="Use the Host header to construct URLs for display."></i> - </SettingsToggle> - </HideInStatic> - <EventlogToggle/> </div> <div className="menu-legend">View Options</div> </div> - { /* - <ToggleButton text="no_upstream_cert" - checked={settings.no_upstream_cert} - onToggle={() => updateSettings({ no_upstream_cert: !settings.no_upstream_cert })} - /> - <ToggleInputButton name="stickyauth" placeholder="Sticky auth filter" - checked={!!settings.stickyauth} - txt={settings.stickyauth} - onToggleChanged={txt => updateSettings({ stickyauth: !settings.stickyauth ? txt : null })} - /> - <ToggleInputButton name="stickycookie" placeholder="Sticky cookie filter" - checked={!!settings.stickycookie} - txt={settings.stickycookie} - onToggleChanged={txt => updateSettings({ stickycookie: !settings.stickycookie ? txt : null })} - /> - <ToggleInputButton name="stream_large_bodies" placeholder="stream..." - checked={!!settings.stream_large_bodies} - txt={settings.stream_large_bodies} - inputType="number" - onToggleChanged={txt => updateSettings({ stream_large_bodies: !settings.stream_large_bodies ? txt : null })} - /> - */} </div> ) } + +export default connect( + null, + { + openOptions: () => modalActions.setActiveModal('OptionModal') + } +)(OptionMenu) diff --git a/web/src/js/components/MainView.jsx b/web/src/js/components/MainView.jsx index e2bedc88..03bfce7f 100644 --- a/web/src/js/components/MainView.jsx +++ b/web/src/js/components/MainView.jsx @@ -1,54 +1,27 @@ -import React, { Component } from 'react' +import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import Splitter from './common/Splitter' import FlowTable from './FlowTable' import FlowView from './FlowView' -import * as flowsActions from '../ducks/flows' -class MainView extends Component { - - static propTypes = { - highlight: PropTypes.string, - sort: PropTypes.object, - } +MainView.propTypes = { + hasSelection: PropTypes.bool.isRequired, +} - render() { - const { flows, selectedFlow, highlight } = this.props - return ( - <div className="main-view"> - <FlowTable - ref="flowTable" - flows={flows} - selected={selectedFlow} - highlight={highlight} - onSelect={this.props.selectFlow} - /> - {selectedFlow && [ - <Splitter key="splitter"/>, - <FlowView - key="flowDetails" - ref="flowDetails" - tab={this.props.tab} - updateFlow={data => this.props.updateFlow(selectedFlow, data)} - flow={selectedFlow} - /> - ]} - </div> - ) - } +function MainView({ hasSelection }) { + return ( + <div className="main-view"> + <FlowTable/> + {hasSelection && <Splitter key="splitter"/>} + {hasSelection && <FlowView key="flowDetails"/>} + </div> + ) } export default connect( state => ({ - flows: state.flows.view, - filter: state.flows.filter, - highlight: state.flows.highlight, - selectedFlow: state.flows.byId[state.flows.selected[0]], - tab: state.ui.flow.tab, + hasSelection: !!state.flows.byId[state.flows.selected[0]] }), - { - selectFlow: flowsActions.select, - updateFlow: flowsActions.update, - } + {} )(MainView) diff --git a/web/src/js/components/Modal/OptionModal.jsx b/web/src/js/components/Modal/OptionModal.jsx index 82ef8350..fed0048d 100644 --- a/web/src/js/components/Modal/OptionModal.jsx +++ b/web/src/js/components/Modal/OptionModal.jsx @@ -53,7 +53,7 @@ class PureOptionModal extends Component { } componentWillUnmount(){ - this.props.save() + // this.props.save() } render() { diff --git a/web/src/js/components/Prompt.jsx b/web/src/js/components/Prompt.jsx deleted file mode 100755 index 77b07027..00000000 --- a/web/src/js/components/Prompt.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import ReactDOM from 'react-dom' -import _ from 'lodash' - -import {Key} from '../utils.js' - -Prompt.propTypes = { - options: PropTypes.array.isRequired, - done: PropTypes.func.isRequired, - prompt: PropTypes.string, -} - -export default function Prompt({ prompt, done, options }) { - const opts = [] - - for (let i = 0; i < options.length; i++) { - let opt = options[i] - if (_.isString(opt)) { - let str = opt - while (str.length > 0 && keyTaken(str[0])) { - str = str.substr(1) - } - opt = { text: opt, key: str[0] } - } - if (!opt.text || !opt.key || keyTaken(opt.key)) { - throw 'invalid options' - } - opts.push(opt) - } - - function keyTaken(k) { - return _.map(opts, 'key').includes(k) - } - - function onKeyDown(event) { - event.stopPropagation() - event.preventDefault() - const key = opts.find(opt => Key[opt.key.toUpperCase()] === event.keyCode) - if (!key && event.keyCode !== Key.ESC && event.keyCode !== Key.ENTER) { - return - } - done(key.key || false) - } - - return ( - <div tabIndex="0" onKeyDown={onKeyDown} className="prompt-dialog"> - <div className="prompt-content"> - {prompt || <strong>Select: </strong> } - {opts.map(opt => { - const idx = opt.text.indexOf(opt.key) - function onClick(event) { - done(opt.key) - event.stopPropagation() - } - return ( - <span key={opt.key} className="option" onClick={onClick}> - {idx !== -1 ? opt.text.substring(0, idx) : opt.text + '('} - <strong className="text-primary">{opt.key}</strong> - {idx !== -1 ? opt.text.substring(idx + 1) : ')'} - </span> - ) - })} - </div> - </div> - ) -} diff --git a/web/src/js/components/ProxyApp.jsx b/web/src/js/components/ProxyApp.jsx index 8c3970bc..15384e02 100644 --- a/web/src/js/components/ProxyApp.jsx +++ b/web/src/js/components/ProxyApp.jsx @@ -20,7 +20,7 @@ class ProxyAppMain extends Component { } render() { - const { showEventLog, location, filter, highlight } = this.props + const { showEventLog } = this.props return ( <div id="container" tabIndex="0"> <Header/> diff --git a/web/src/js/components/common/Button.jsx b/web/src/js/components/common/Button.jsx index e02ae010..02dab305 100644 --- a/web/src/js/components/common/Button.jsx +++ b/web/src/js/components/common/Button.jsx @@ -12,7 +12,7 @@ Button.propTypes = { export default function Button({ onClick, children, icon, disabled, className, title }) { return ( <div className={classnames(className, 'btn btn-default')} - onClick={!disabled && onClick} + onClick={disabled ? undefined : onClick} disabled={disabled} title={title}> {icon && (<i className={"fa fa-fw " + icon}/> )} diff --git a/web/src/js/utils.js b/web/src/js/utils.js index 7c1719ae..80f0c42a 100644 --- a/web/src/js/utils.js +++ b/web/src/js/utils.js @@ -1,6 +1,5 @@ import _ from 'lodash' import React from 'react' -import shallowEqual from 'shallowequal' window._ = _; window.React = React; @@ -126,13 +125,9 @@ export function getDiff(obj1, obj2) { return result } -export const pure = renderFn => class extends React.Component { +export const pure = renderFn => class extends React.PureComponent { static displayName = renderFn.name - shouldComponentUpdate(nextProps) { - return !shallowEqual(this.props, nextProps) - } - render() { return renderFn(this.props) } |