2020-09-22 04:23:38 +03:00
|
|
|
import React, { CSSProperties, PureComponent } from 'react';
|
2020-08-04 23:13:22 +03:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import * as themes from 'redux-devtools-themes';
|
2020-09-22 04:23:38 +03:00
|
|
|
import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools';
|
2020-08-04 23:13:22 +03:00
|
|
|
import deepmerge from 'deepmerge';
|
2020-09-22 04:23:38 +03:00
|
|
|
import { Action, Dispatch } from 'redux';
|
|
|
|
import { Base16Theme } from 'react-base16-styling';
|
2020-08-04 23:13:22 +03:00
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
import reducer, { ChartMonitorState } from './reducers';
|
|
|
|
import Chart, { Props } from './Chart';
|
|
|
|
import { Primitive } from 'd3';
|
2020-10-26 02:32:04 +03:00
|
|
|
import { NodeWithId } from 'd3-state-visualizer/lib/charts/tree/tree';
|
2020-09-22 04:23:38 +03:00
|
|
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
2020-08-04 23:13:22 +03:00
|
|
|
const { reset, rollback, commit, sweep, toggleAction } = ActionCreators;
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
const styles: { container: CSSProperties } = {
|
2020-08-04 23:13:22 +03:00
|
|
|
container: {
|
|
|
|
fontFamily: 'monaco, Consolas, Lucida Console, monospace',
|
|
|
|
position: 'relative',
|
|
|
|
overflowY: 'hidden',
|
|
|
|
width: '100%',
|
|
|
|
height: '100%',
|
2020-08-08 23:26:39 +03:00
|
|
|
minWidth: 300,
|
|
|
|
},
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
function invertColors(theme: Base16Theme) {
|
2020-08-04 23:13:22 +03:00
|
|
|
return {
|
|
|
|
...theme,
|
|
|
|
base00: theme.base07,
|
|
|
|
base01: theme.base06,
|
|
|
|
base02: theme.base05,
|
|
|
|
base03: theme.base04,
|
|
|
|
base04: theme.base03,
|
|
|
|
base05: theme.base02,
|
|
|
|
base06: theme.base01,
|
2020-08-08 23:26:39 +03:00
|
|
|
base07: theme.base00,
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
export interface ChartMonitorProps<S, A extends Action<unknown>>
|
|
|
|
extends LiftedState<S, A, ChartMonitorState> {
|
|
|
|
dispatch: Dispatch<LiftedAction<S, A, ChartMonitorState>>;
|
|
|
|
preserveScrollTop: boolean;
|
|
|
|
select: (state: S) => unknown;
|
|
|
|
theme: keyof typeof themes | Base16Theme;
|
|
|
|
invertTheme: boolean;
|
|
|
|
|
|
|
|
state: S | null;
|
|
|
|
isSorted: boolean;
|
|
|
|
heightBetweenNodesCoeff: number;
|
|
|
|
widthBetweenNodesCoeff: number;
|
2020-10-26 02:32:04 +03:00
|
|
|
onClickText: (datum: NodeWithId) => void;
|
2020-09-22 04:23:38 +03:00
|
|
|
tooltipOptions: unknown;
|
|
|
|
style: {
|
|
|
|
width: number;
|
|
|
|
height: number;
|
|
|
|
node: {
|
|
|
|
colors: {
|
|
|
|
default: string;
|
|
|
|
collapsed: string;
|
|
|
|
parent: string;
|
|
|
|
};
|
|
|
|
radius: number;
|
|
|
|
};
|
|
|
|
text: {
|
|
|
|
colors: {
|
|
|
|
default: string;
|
|
|
|
hover: string;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
defaultIsVisible?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ChartMonitor<S, A extends Action<unknown>> extends PureComponent<
|
|
|
|
ChartMonitorProps<S, A>
|
|
|
|
> {
|
2020-08-04 23:13:22 +03:00
|
|
|
static update = reducer;
|
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
dispatch: PropTypes.func,
|
|
|
|
computedStates: PropTypes.array,
|
|
|
|
currentStateIndex: PropTypes.number,
|
|
|
|
actionsById: PropTypes.object,
|
|
|
|
stagedActionIds: PropTypes.array,
|
|
|
|
skippedActionIds: PropTypes.array,
|
|
|
|
monitorState: PropTypes.shape({
|
2020-08-08 23:26:39 +03:00
|
|
|
initialScrollTop: PropTypes.number,
|
2020-08-04 23:13:22 +03:00
|
|
|
}),
|
|
|
|
|
|
|
|
preserveScrollTop: PropTypes.bool,
|
|
|
|
select: PropTypes.func.isRequired,
|
2020-08-05 16:12:31 +03:00
|
|
|
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
2020-08-08 23:26:39 +03:00
|
|
|
invertTheme: PropTypes.bool,
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static defaultProps = {
|
2020-09-22 04:23:38 +03:00
|
|
|
select: (state: unknown) => state,
|
2020-08-04 23:13:22 +03:00
|
|
|
theme: 'nicinabox',
|
|
|
|
preserveScrollTop: true,
|
2020-08-08 23:26:39 +03:00
|
|
|
invertTheme: false,
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
handleRollback = () => {
|
2020-08-04 23:13:22 +03:00
|
|
|
this.props.dispatch(rollback());
|
2020-09-22 04:23:38 +03:00
|
|
|
};
|
2020-08-04 23:13:22 +03:00
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
handleSweep = () => {
|
2020-08-04 23:13:22 +03:00
|
|
|
this.props.dispatch(sweep());
|
2020-09-22 04:23:38 +03:00
|
|
|
};
|
2020-08-04 23:13:22 +03:00
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
handleCommit = () => {
|
2020-08-04 23:13:22 +03:00
|
|
|
this.props.dispatch(commit());
|
2020-09-22 04:23:38 +03:00
|
|
|
};
|
2020-08-04 23:13:22 +03:00
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
handleToggleAction = (id: number) => {
|
2020-08-04 23:13:22 +03:00
|
|
|
this.props.dispatch(toggleAction(id));
|
2020-09-22 04:23:38 +03:00
|
|
|
};
|
2020-08-04 23:13:22 +03:00
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
handleReset = () => {
|
2020-08-04 23:13:22 +03:00
|
|
|
this.props.dispatch(reset());
|
2020-09-22 04:23:38 +03:00
|
|
|
};
|
2020-08-04 23:13:22 +03:00
|
|
|
|
|
|
|
getTheme() {
|
2020-09-22 04:23:38 +03:00
|
|
|
const { theme, invertTheme } = this.props;
|
2020-08-04 23:13:22 +03:00
|
|
|
if (typeof theme !== 'string') {
|
|
|
|
return invertTheme ? invertColors(theme) : theme;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof themes[theme] !== 'undefined') {
|
|
|
|
return invertTheme ? invertColors(themes[theme]) : themes[theme];
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:12:31 +03:00
|
|
|
console.warn(
|
|
|
|
'DevTools theme ' + theme + ' not found, defaulting to nicinabox'
|
|
|
|
);
|
2020-08-04 23:13:22 +03:00
|
|
|
return invertTheme ? invertColors(themes.nicinabox) : themes.nicinabox;
|
|
|
|
}
|
|
|
|
|
|
|
|
getChartStyle() {
|
|
|
|
const theme = this.getTheme();
|
|
|
|
|
|
|
|
return {
|
|
|
|
width: '100%',
|
|
|
|
height: '100%',
|
|
|
|
node: {
|
|
|
|
colors: {
|
2020-08-05 16:12:31 +03:00
|
|
|
default: theme.base0B,
|
2020-08-04 23:13:22 +03:00
|
|
|
collapsed: theme.base0B,
|
2020-08-08 23:26:39 +03:00
|
|
|
parent: theme.base0E,
|
2020-08-04 23:13:22 +03:00
|
|
|
},
|
2020-08-08 23:26:39 +03:00
|
|
|
radius: 7,
|
2020-08-04 23:13:22 +03:00
|
|
|
},
|
|
|
|
text: {
|
|
|
|
colors: {
|
2020-08-05 16:12:31 +03:00
|
|
|
default: theme.base0D,
|
2020-08-08 23:26:39 +03:00
|
|
|
hover: theme.base06,
|
|
|
|
},
|
|
|
|
},
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
getChartOptions(props = this.props): Props<S, A> {
|
2020-08-04 23:13:22 +03:00
|
|
|
const { computedStates } = props;
|
|
|
|
const theme = this.getTheme();
|
|
|
|
|
|
|
|
const tooltipOptions = {
|
|
|
|
disabled: false,
|
2020-08-05 16:12:31 +03:00
|
|
|
offset: { left: 30, top: 10 },
|
2020-08-04 23:13:22 +03:00
|
|
|
indentationSize: 2,
|
|
|
|
style: {
|
|
|
|
'background-color': theme.base06,
|
2020-08-05 16:12:31 +03:00
|
|
|
opacity: '0.7',
|
2020-08-04 23:13:22 +03:00
|
|
|
'border-radius': '5px',
|
2020-08-08 23:26:39 +03:00
|
|
|
padding: '5px',
|
|
|
|
},
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
const defaultOptions = {
|
2020-08-05 16:12:31 +03:00
|
|
|
state: computedStates.length
|
|
|
|
? computedStates[props.currentStateIndex].state
|
|
|
|
: null,
|
2020-08-04 23:13:22 +03:00
|
|
|
isSorted: false,
|
|
|
|
heightBetweenNodesCoeff: 1,
|
|
|
|
widthBetweenNodesCoeff: 1.3,
|
|
|
|
tooltipOptions,
|
2020-09-22 04:23:38 +03:00
|
|
|
style: (this.getChartStyle() as unknown) as
|
|
|
|
| { [key: string]: Primitive }
|
|
|
|
| undefined,
|
2020-08-04 23:13:22 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
return deepmerge(defaultOptions, props);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const theme = this.getTheme();
|
|
|
|
|
2020-09-22 04:23:38 +03:00
|
|
|
const ChartAsAny = Chart as any;
|
2020-08-04 23:13:22 +03:00
|
|
|
return (
|
2020-08-05 16:12:31 +03:00
|
|
|
<div style={{ ...styles.container, backgroundColor: theme.base07 }}>
|
2020-09-22 04:23:38 +03:00
|
|
|
<ChartAsAny {...this.getChartOptions()} />
|
2020-08-04 23:13:22 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default ChartMonitor;
|