This commit is contained in:
Nathan Bierema 2020-08-26 23:43:08 -04:00
parent 90dbb8d940
commit 11994b0e95
7 changed files with 77 additions and 37 deletions

View File

@ -2,8 +2,8 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Action, Dispatch } from 'redux'; import { Action, Dispatch } from 'redux';
import * as themes from 'redux-devtools-themes'; import * as themes from 'redux-devtools-themes';
import { Base16Theme } from 'redux-devtools-themes';
import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools'; import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools';
import { Base16Theme } from 'base16';
import { import {
updateScrollTop, updateScrollTop,
startConsecutiveToggle, startConsecutiveToggle,

View File

@ -1,6 +1,5 @@
import React, { CSSProperties } from 'react'; import React, { CSSProperties } from 'react';
import { Base16Theme } from 'base16'; import { Base16Theme } from 'redux-devtools-themes';
import { Action } from 'redux';
import brighten from './brighten'; import brighten from './brighten';
const styles: { base: CSSProperties } = { const styles: { base: CSSProperties } = {

View File

@ -1,9 +1,9 @@
import React, { CSSProperties, PureComponent } from 'react'; import React, { CSSProperties, PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { ActionCreators, LiftedAction } from 'redux-devtools'; import { ActionCreators, LiftedAction } from 'redux-devtools';
import LogMonitorButton from './LogMonitorButton'; import { Base16Theme } from 'redux-devtools-themes';
import { Action, Dispatch } from 'redux'; import { Action, Dispatch } from 'redux';
import { Base16Theme } from 'base16'; import LogMonitorButton from './LogMonitorButton';
import { LogMonitorAction } from './actions'; import { LogMonitorAction } from './actions';
import { LogMonitorState } from './reducers'; import { LogMonitorState } from './reducers';

View File

@ -1,9 +1,11 @@
import React, { PureComponent } from 'react'; import React, { CSSProperties, MouseEventHandler, PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import JSONTree from 'react-json-tree'; import JSONTree, { StylingValue } from 'react-json-tree';
import { Base16Theme } from 'redux-devtools-themes';
import { Action } from 'redux';
import LogMonitorEntryAction from './LogMonitorEntryAction'; import LogMonitorEntryAction from './LogMonitorEntryAction';
const styles = { const styles: { entry: CSSProperties; root: CSSProperties } = {
entry: { entry: {
display: 'block', display: 'block',
WebkitUserSelect: 'none', WebkitUserSelect: 'none',
@ -14,15 +16,40 @@ const styles = {
}, },
}; };
const getDeepItem = (data, path) => const getDeepItem = (data: any, path: (string | number)[]) =>
path.reduce((obj, key) => obj && obj[key], data); path.reduce((obj, key) => obj && obj[key], data);
const dataIsEqual = (data, previousData, keyPath) => { const dataIsEqual = (
data: any,
previousData: unknown,
keyPath: (string | number)[]
) => {
const path = [...keyPath].reverse().slice(1); const path = [...keyPath].reverse().slice(1);
return getDeepItem(data, path) === getDeepItem(previousData, path); return getDeepItem(data, path) === getDeepItem(previousData, path);
}; };
export default class LogMonitorEntry extends PureComponent { interface Props<S, A extends Action<unknown>> {
theme: Base16Theme;
select: (state: any) => unknown;
action: A;
actionId: number;
state: S;
previousState: S | undefined;
collapsed: boolean;
inFuture: boolean;
selected: boolean;
error: string | undefined;
expandActionRoot: boolean;
expandStateRoot: boolean;
markStateDiff: boolean;
onActionClick: (id: number) => void;
onActionShiftClick: (id: number) => void;
}
export default class LogMonitorEntry<
S,
A extends Action<unknown>
> extends PureComponent<Props<S, A>> {
static propTypes = { static propTypes = {
state: PropTypes.object.isRequired, state: PropTypes.object.isRequired,
action: PropTypes.object.isRequired, action: PropTypes.object.isRequired,
@ -36,15 +63,10 @@ export default class LogMonitorEntry extends PureComponent {
selected: PropTypes.bool, selected: PropTypes.bool,
expandActionRoot: PropTypes.bool, expandActionRoot: PropTypes.bool,
expandStateRoot: PropTypes.bool, expandStateRoot: PropTypes.bool,
previousState: PropTypes.object,
}; };
constructor(props) { printState(state: S, error: string | undefined) {
super(props);
this.handleActionClick = this.handleActionClick.bind(this);
this.shouldExpandNode = this.shouldExpandNode.bind(this);
}
printState(state, error) {
let errorText = error; let errorText = error;
if (!errorText) { if (!errorText) {
try { try {
@ -56,7 +78,11 @@ export default class LogMonitorEntry extends PureComponent {
typeof this.props.previousState !== 'undefined' typeof this.props.previousState !== 'undefined'
? this.props.select(this.props.previousState) ? this.props.select(this.props.previousState)
: undefined; : undefined;
const getValueStyle = ({ style }, nodeType, keyPath) => ({ const getValueStyle: StylingValue = (
{ style },
nodeType,
keyPath
) => ({
style: { style: {
...style, ...style,
backgroundColor: dataIsEqual(data, previousData, keyPath) backgroundColor: dataIsEqual(data, previousData, keyPath)
@ -64,7 +90,7 @@ export default class LogMonitorEntry extends PureComponent {
: this.props.theme.base01, : this.props.theme.base01,
}, },
}); });
const getNestedNodeStyle = ({ style }, keyPath) => ({ const getNestedNodeStyle: StylingValue = ({ style }, keyPath) => ({
style: { style: {
...style, ...style,
...(keyPath.length > 1 ? {} : styles.root), ...(keyPath.length > 1 ? {} : styles.root),
@ -72,7 +98,6 @@ export default class LogMonitorEntry extends PureComponent {
}); });
theme = { theme = {
extend: this.props.theme, extend: this.props.theme,
tree: styles.tree,
value: getValueStyle, value: getValueStyle,
nestedNode: getNestedNodeStyle, nestedNode: getNestedNodeStyle,
}; };
@ -109,7 +134,7 @@ export default class LogMonitorEntry extends PureComponent {
); );
} }
handleActionClick(e) { handleActionClick: MouseEventHandler<HTMLDivElement> = (e) => {
const { actionId, onActionClick, onActionShiftClick } = this.props; const { actionId, onActionClick, onActionShiftClick } = this.props;
if (actionId > 0) { if (actionId > 0) {
if (e.shiftKey) { if (e.shiftKey) {
@ -118,11 +143,15 @@ export default class LogMonitorEntry extends PureComponent {
onActionClick(actionId); onActionClick(actionId);
} }
} }
} };
shouldExpandNode(keyName, data, level) { shouldExpandNode = (
keyPath: (string | number)[],
data: any,
level: number
) => {
return this.props.expandStateRoot && level === 0; return this.props.expandStateRoot && level === 0;
} };
render() { render() {
const { const {

View File

@ -1,5 +1,7 @@
import React, { Component } from 'react'; import React, { Component, CSSProperties, MouseEventHandler } from 'react';
import JSONTree from 'react-json-tree'; import JSONTree from 'react-json-tree';
import { Base16Theme } from 'redux-devtools-themes';
import { Action } from 'redux';
const styles = { const styles = {
actionBar: { actionBar: {
@ -14,13 +16,19 @@ const styles = {
}, },
}; };
export default class LogMonitorAction extends Component { interface Props<A extends Action<unknown>> {
constructor(props) { theme: Base16Theme;
super(props); collapsed: boolean;
this.shouldExpandNode = this.shouldExpandNode.bind(this); action: A;
} expandActionRoot: boolean;
onClick: MouseEventHandler<HTMLDivElement>;
style: CSSProperties;
}
renderPayload(payload) { export default class LogMonitorAction<
A extends Action<unknown>
> extends Component<Props<A>> {
renderPayload(payload: Record<string, unknown>) {
return ( return (
<div <div
style={{ style={{
@ -43,9 +51,13 @@ export default class LogMonitorAction extends Component {
); );
} }
shouldExpandNode(keyName, data, level) { shouldExpandNode = (
keyPath: (string | number)[],
data: any,
level: number
) => {
return this.props.expandActionRoot && level === 0; return this.props.expandActionRoot && level === 0;
} };
render() { render() {
const { type, ...payload } = this.props.action; const { type, ...payload } = this.props.action;
@ -58,7 +70,7 @@ export default class LogMonitorAction extends Component {
}} }}
> >
<div style={styles.actionBar} onClick={this.props.onClick}> <div style={styles.actionBar} onClick={this.props.onClick}>
{type !== null && type.toString()} {type !== null && (type as string).toString()}
</div> </div>
{!this.props.collapsed ? this.renderPayload(payload) : ''} {!this.props.collapsed ? this.renderPayload(payload) : ''}
</div> </div>

View File

@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Action } from 'redux'; import { Action } from 'redux';
import { PerformAction } from 'redux-devtools'; import { PerformAction } from 'redux-devtools';
import { Base16Theme } from 'base16'; import { Base16Theme } from 'redux-devtools-themes';
import LogMonitorEntry from './LogMonitorEntry'; import LogMonitorEntry from './LogMonitorEntry';
interface Props<S, A extends Action<unknown>> { interface Props<S, A extends Action<unknown>> {

View File

@ -1,9 +1,9 @@
import { Action } from 'redux';
import { import {
UPDATE_SCROLL_TOP, UPDATE_SCROLL_TOP,
START_CONSECUTIVE_TOGGLE, START_CONSECUTIVE_TOGGLE,
LogMonitorAction, LogMonitorAction,
} from './actions'; } from './actions';
import { Action } from 'redux';
import { LogMonitorProps } from './LogMonitor'; import { LogMonitorProps } from './LogMonitor';
function initialScrollTop<S, A extends Action<unknown>>( function initialScrollTop<S, A extends Action<unknown>>(