diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 19daacaa..00000000 --- a/.yarnrc +++ /dev/null @@ -1 +0,0 @@ -workspaces-experimental true diff --git a/packages/redux-devtools-chart-monitor/.babelrc b/packages/redux-devtools-chart-monitor/.babelrc new file mode 100644 index 00000000..645cc56e --- /dev/null +++ b/packages/redux-devtools-chart-monitor/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-export-default-from"] +} diff --git a/packages/redux-devtools-chart-monitor/README.md b/packages/redux-devtools-chart-monitor/README.md new file mode 100644 index 00000000..b70efd0b --- /dev/null +++ b/packages/redux-devtools-chart-monitor/README.md @@ -0,0 +1,74 @@ +Redux DevTools Chart Monitor +========================= + +A chart monitor for [Redux DevTools](https://github.com/gaearon/redux-devtools). Created by [@romseguy](https://github.com/romseguy) and merged from [`reduxjs/redux-devtools-chart-monitor`](https://github.com/reduxjs/redux-devtools-chart-monitor). + +It shows a real-time view of the store aka the current state of the app. + +:rocket: Now with immutable-js support. + +[Demo](http://romseguy.github.io/redux-store-visualizer/) [(Source)](https://github.com/romseguy/redux-store-visualizer) + +![Chart Monitor](https://camo.githubusercontent.com/19aebaeba929e97f97225115c49dc994299cb76e/687474703a2f2f692e696d6775722e636f6d2f4d53677655366c2e676966) + +### Installation + +``` +yarn add --dev redux-devtools-chart-monitor +``` + +### Usage + +You can use `ChartMonitor` as the only monitor in your app: + +##### `containers/DevTools.js` + +```js +import React from 'react'; +import { createDevTools } from 'redux-devtools'; +import ChartMonitor from 'redux-devtools-chart-monitor'; + +export default createDevTools( + +); +``` + +Then you can render `` to any place inside app or even into a separate popup window. + +Alternatively, you can use it together with [`DockMonitor`](https://github.com/gaearon/redux-devtools-dock-monitor) to make it dockable. +Consult the [`DockMonitor` README](https://github.com/gaearon/redux-devtools-dock-monitor) for details of this approach. + +[Read how to start using Redux DevTools.](https://github.com/reduxjs/redux-devtools) + +### Features + +### Props + +#### ChartMonitor props + +You can read the React component [propTypes](https://github.com/reduxjs/redux-devtools/blob/master/packages/redux-devtools-chart-monitor/src/Chart.js#L11) in addition to the details below: + +Name | Description +------------- | ------------- +`defaultIsVisible` | By default, set to `true`. +`transitionDuration` | By default, set to `750`, in milliseconds. +`heightBetweenNodesCoeff` | By default, set to `1`. +`widthBetweenNodesCoeff` | By default, set to `1.3`. +`isSorted` | By default, set to `false`. +`style` | {
  width: '100%', height: '100%', // i.e fullscreen for [`DockMonitor`](https://github.com/gaearon/redux-devtools-dock-monitor)
  text: {
    colors: {
      'default': `theme.base0D`,
      hover: `theme.base06`
    }
  },
  node: {
    colors: {
      'default': `theme.base0B`,
      collapsed: `theme.base0B`,
      parent: `theme.base0E`
    },
    radius: 7
  }
} +`onClickText` | Function called with a reference to the clicked node as first argument when clicking on the text next to a node. +`tooltipOptions` | {
  disabled: false,
  indentationSize: 2,
  style: {
    'background-color': `theme.base06`,
    'opacity': '0.7',
    'border-radius': '5px',
    'padding': '5px'
  }
}
[More info](https://github.com/reduxjs/redux-devtools/tree/master/packages/d3tooltip#api). + + + +#### Redux DevTools props + +Name | Description +------------- | ------------- +`theme` | Either a string referring to one of the themes provided by [redux-devtools-themes](https://github.com/gaearon/redux-devtools-themes) (feel free to contribute!) or a custom object of the same format. Optional. By default, set to [`'nicinabox'`](https://github.com/gaearon/redux-devtools-themes/blob/master/src/nicinabox.js). +`invertTheme` | Boolean value that will invert the colors of the selected theme. Optional. By default, set to `false` +`select` | A function that selects the slice of the state for DevTools to show. For example, `state => state.thePart.iCare.about`. Optional. By default, set to `state => state`. + +### License + +MIT diff --git a/packages/redux-devtools-chart-monitor/package.json b/packages/redux-devtools-chart-monitor/package.json new file mode 100644 index 00000000..4adcb87b --- /dev/null +++ b/packages/redux-devtools-chart-monitor/package.json @@ -0,0 +1,55 @@ +{ + "name": "redux-devtools-chart-monitor", + "version": "1.7.0", + "description": "Chart monitor for Redux DevTools", + "main": "lib/index.js", + "scripts": { + "clean": "rimraf lib", + "build": "babel src --out-dir lib", + "prepare": "npm run build", + "prepublishOnly": "npm run lint && npm run clean && npm run build" + }, + "files": [ + "lib", + "src" + ], + "repository": { + "type": "git", + "url": "https://github.com/reduxjs/redux-devtools.git" + }, + "keywords": [ + "redux", + "devtools", + "flux", + "react", + "chart" + ], + "author": "romseguy", + "license": "MIT", + "bugs": { + "url": "https://github.com/reduxjs/redux-devtools/issues" + }, + "homepage": "https://github.com/reduxjs/redux-devtools", + "devDependencies": { + "@babel/cli": "^7.10.5", + "@babel/core": "^7.11.0", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-export-default-from": "^7.10.4", + "@babel/preset-env": "^7.11.0", + "@babel/preset-react": "^7.10.4", + "babel-loader": "^8.1.0", + "rimraf": "^2.7.1" + }, + "peerDependencies": { + "react": "^16.3.0", + "react-dom": "^16.3.0", + "redux-devtools": "^3.0.0" + }, + "dependencies": { + "d3-state-visualizer": "^1.3.2", + "deepmerge": "^0.2.10", + "prop-types": "^15.7.2", + "react-pure-render": "^1.0.2", + "redux-devtools-themes": "^1.0.0" + } +} diff --git a/packages/redux-devtools-chart-monitor/src/Chart.js b/packages/redux-devtools-chart-monitor/src/Chart.js new file mode 100644 index 00000000..9e01b81c --- /dev/null +++ b/packages/redux-devtools-chart-monitor/src/Chart.js @@ -0,0 +1,86 @@ +import React, { Component, createRef } from 'react'; +import PropTypes from 'prop-types'; +import { tree } from 'd3-state-visualizer'; + +const wrapperStyle = { + width: '100%', + height: '100%' +}; + +class Chart extends Component { + static propTypes = { + state: PropTypes.object, + rootKeyName: PropTypes.string, + pushMethod: PropTypes.oneOf(['push', 'unshift']), + tree: PropTypes.shape({ + name: PropTypes.string, + children: PropTypes.array + }), + id: PropTypes.string, + style: PropTypes.shape({ + node: PropTypes.shape({ + colors: PropTypes.shape({ + 'default': PropTypes.string, + parent: PropTypes.string, + collapsed: PropTypes.string + }), + radius: PropTypes.number + }), + text: PropTypes.shape({ + colors: PropTypes.shape({ + 'default': PropTypes.string, + hover: PropTypes.string + }) + }), + link: PropTypes.object + }), + size: PropTypes.number, + aspectRatio: PropTypes.number, + margin: PropTypes.shape({ + top: PropTypes.number, + right: PropTypes.number, + bottom: PropTypes.number, + left: PropTypes.number + }), + isSorted: PropTypes.bool, + heightBetweenNodesCoeff: PropTypes.number, + widthBetweenNodesCoeff: PropTypes.number, + transitionDuration: PropTypes.number, + onClickText: PropTypes.func, + tooltipOptions: PropTypes.shape({ + disabled: PropTypes.bool, + left: PropTypes.number, + top: PropTypes.number, + offset: PropTypes.shape({ + left: PropTypes.number, + top: PropTypes.number + }), + indentationSize: PropTypes.number, + style: PropTypes.object + }) + }; + + divRef = createRef(); + + componentDidMount() { + const { select, state, defaultIsVisible } = this.props; + this.renderChart = tree(this.divRef.current, this.props); + if (defaultIsVisible) { + this.renderChart(select(state)); + } + } + + UNSAFE_componentWillReceiveProps(nextProps) { + const { state, select, monitorState } = nextProps; + + if (monitorState.isVisible !== false) { + this.renderChart(select(state)); + } + } + + render() { + return
; + } +} + +export default Chart; diff --git a/packages/redux-devtools-chart-monitor/src/ChartMonitor.js b/packages/redux-devtools-chart-monitor/src/ChartMonitor.js new file mode 100644 index 00000000..e6602913 --- /dev/null +++ b/packages/redux-devtools-chart-monitor/src/ChartMonitor.js @@ -0,0 +1,175 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import shouldPureComponentUpdate from 'react-pure-render/function'; +import * as themes from 'redux-devtools-themes'; +import { ActionCreators } from 'redux-devtools'; +import deepmerge from 'deepmerge'; + +import reducer from './reducers'; +import Chart from './Chart'; +const { reset, rollback, commit, sweep, toggleAction } = ActionCreators; + +const styles = { + container: { + fontFamily: 'monaco, Consolas, Lucida Console, monospace', + position: 'relative', + overflowY: 'hidden', + width: '100%', + height: '100%', + minWidth: 300 + } +}; + +function invertColors(theme) { + return { + ...theme, + base00: theme.base07, + base01: theme.base06, + base02: theme.base05, + base03: theme.base04, + base04: theme.base03, + base05: theme.base02, + base06: theme.base01, + base07: theme.base00 + }; +} + +class ChartMonitor extends Component { + 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({ + initialScrollTop: PropTypes.number + }), + + preserveScrollTop: PropTypes.bool, + select: PropTypes.func.isRequired, + theme: PropTypes.oneOfType([ + PropTypes.object, + PropTypes.string + ]), + invertTheme: PropTypes.bool + }; + + static defaultProps = { + select: (state) => state, + theme: 'nicinabox', + preserveScrollTop: true, + invertTheme: false + }; + + shouldComponentUpdate = shouldPureComponentUpdate; + + constructor(props) { + super(props); + this.handleToggleAction = this.handleToggleAction.bind(this); + this.handleReset = this.handleReset.bind(this); + this.handleRollback = this.handleRollback.bind(this); + this.handleSweep = this.handleSweep.bind(this); + this.handleCommit = this.handleCommit.bind(this); + } + + handleRollback() { + this.props.dispatch(rollback()); + } + + handleSweep() { + this.props.dispatch(sweep()); + } + + handleCommit() { + this.props.dispatch(commit()); + } + + handleToggleAction(id) { + this.props.dispatch(toggleAction(id)); + } + + handleReset() { + this.props.dispatch(reset()); + } + + getTheme() { + let { theme, invertTheme } = this.props; + if (typeof theme !== 'string') { + return invertTheme ? invertColors(theme) : theme; + } + + if (typeof themes[theme] !== 'undefined') { + return invertTheme ? invertColors(themes[theme]) : themes[theme]; + } + + // eslint-disable-next-line no-console + console.warn('DevTools theme ' + theme + ' not found, defaulting to nicinabox'); + return invertTheme ? invertColors(themes.nicinabox) : themes.nicinabox; + } + + getChartStyle() { + const theme = this.getTheme(); + + return { + width: '100%', + height: '100%', + node: { + colors: { + 'default': theme.base0B, + collapsed: theme.base0B, + parent: theme.base0E + }, + radius: 7 + }, + text: { + colors: { + 'default': theme.base0D, + hover: theme.base06 + } + } + }; + } + + getChartOptions(props = this.props) { + const { computedStates } = props; + const theme = this.getTheme(); + + const tooltipOptions = { + disabled: false, + offset: {left: 30, top: 10}, + indentationSize: 2, + style: { + 'background-color': theme.base06, + 'opacity': '0.7', + 'border-radius': '5px', + 'padding': '5px' + } + }; + + const defaultOptions = { + state: computedStates.length ? computedStates[props.currentStateIndex].state : null, + isSorted: false, + heightBetweenNodesCoeff: 1, + widthBetweenNodesCoeff: 1.3, + tooltipOptions, + style: this.getChartStyle() + }; + + return deepmerge(defaultOptions, props); + } + + render() { + const theme = this.getTheme(); + + return ( +
+ +
+ ); + } +} + +export default ChartMonitor; diff --git a/packages/redux-devtools-chart-monitor/src/actions.js b/packages/redux-devtools-chart-monitor/src/actions.js new file mode 100644 index 00000000..ec09b91b --- /dev/null +++ b/packages/redux-devtools-chart-monitor/src/actions.js @@ -0,0 +1 @@ +export const TOGGLE_VISIBILITY = '@@redux-devtools-log-monitor/TOGGLE_VISIBILITY'; diff --git a/packages/redux-devtools-chart-monitor/src/index.js b/packages/redux-devtools-chart-monitor/src/index.js new file mode 100644 index 00000000..47f35f02 --- /dev/null +++ b/packages/redux-devtools-chart-monitor/src/index.js @@ -0,0 +1 @@ +export default from './ChartMonitor'; diff --git a/packages/redux-devtools-chart-monitor/src/reducers.js b/packages/redux-devtools-chart-monitor/src/reducers.js new file mode 100644 index 00000000..7d31752a --- /dev/null +++ b/packages/redux-devtools-chart-monitor/src/reducers.js @@ -0,0 +1,19 @@ +import { TOGGLE_VISIBILITY } from './actions'; + +function toggleVisibility(props, state = props.defaultIsVisible, action) { + if (action.type === TOGGLE_VISIBILITY) { + return !state; + } + + if (props.defaultIsVisible !== undefined) { + return props.defaultIsVisible; + } + + return true; +} + +export default function reducer(props, state = {}, action) { + return { + isVisible: toggleVisibility(props, state.isVisible, action) + }; +} diff --git a/yarn.lock b/yarn.lock index 7acd361b..1855327d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5860,7 +5860,7 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= -d3-state-visualizer@^1.3.1, d3-state-visualizer@^1.3.2: +d3-state-visualizer@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/d3-state-visualizer/-/d3-state-visualizer-1.3.2.tgz#8e3ac418aa7ee7e3f46025309f9d1c215ee385eb" integrity sha512-XgTRC6FXeoTt8l79cc2f3Zaah+K7DUQb3GL0zfbvoIi7zWWHV4l7OfuX9/JxxvwilKApMZwHMBJ7cJ2yWAc5IQ== @@ -13734,17 +13734,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redux-devtools-chart-monitor@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/redux-devtools-chart-monitor/-/redux-devtools-chart-monitor-1.7.0.tgz#bf6356f480142e3576f5bbbeead433a1598c5e7f" - integrity sha512-1knxXASbo7ukukyf1rGNnME7gOgKY1XVZ4hoSzUjY6QFIC8iEneivXznCupxjfX5TDXLjZgQrFBrbGano1WK7g== - dependencies: - d3-state-visualizer "^1.3.1" - deepmerge "^0.2.10" - prop-types "^15.6.0" - react-pure-render "^1.0.2" - redux-devtools-themes "^1.0.0" - redux-devtools-dock-monitor@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/redux-devtools-dock-monitor/-/redux-devtools-dock-monitor-1.1.3.tgz#1205e823c82536570aac8551a1c4b70972cba6aa"