Skip to content

Show Redux Dev Tools in a New Window #261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.0.0
5.5.0
5 changes: 0 additions & 5 deletions app/assets/javascripts/rails_startup.js

This file was deleted.

5 changes: 5 additions & 0 deletions app/controllers/comments_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
before_action :set_comments_count

# GET /comments
# GET /comments.json
Expand Down Expand Up @@ -68,6 +69,10 @@ def set_comment
@comment = Comment.find(params[:id])
end

def set_comments_count
@comments_count = Comment.all.order("id DESC").size
end

# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:author, :text)
Expand Down
7 changes: 6 additions & 1 deletion app/controllers/pages_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
class PagesController < ApplicationController
before_action :set_comments
before_action :set_comments_count

def index
# NOTE: The below notes apply if you want to set the value of the props in the controller, as
# compared to he view. However, it's more convenient to use Jbuilder from the view. See
# compared to the view. However, it's more convenient to use Jbuilder from the view. See
# app/views/pages/index.html.erb:20
#
# <%= react_component('App', props: render(template: "/comments/index.json.jbuilder"),
Expand Down Expand Up @@ -34,4 +35,8 @@ def simple
def set_comments
@comments = Comment.all.order("id DESC")
end

def set_comments_count
@comments_count = Comment.all.order("id DESC").size
end
end
27 changes: 1 addition & 26 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,7 @@
<%= csrf_meta_tags %>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://www.shakacode.com">ShakaCode</a>
</div>

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><%= link_to "React Router Demo", root_path %></li>
<li><%= link_to "React Demo", no_router_path %></li>
<li><%= link_to "Simple React", simple_path %></li>
<li><%= link_to "Classic Rails", comments_path %></li>
<li><%= link_to "Source on Github", "https://github.com/shakacode/react-webpack-rails-tutorial" %></li>
<li><%= link_to "Tutorial Article", "http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/" %></li>
<li><%= link_to "Forum Discussion", "http://forum.shakacode.com/t/fast-rich-client-rails-development-with-webpack-and-the-es6-transpiler/82/22" %></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<%= react_component 'Navigationbar', props: { comments_count: @comments_count } %>

<div class="container">
<%= yield %>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import BaseComponent from 'libs/components/BaseComponent';

export default class Navigationbar extends BaseComponent {
static propTypes = {
data: PropTypes.object.isRequired,
};

constructor(props) {
super(props);
// set @comment_count prop to state
// for updating the count of comments
this.state = {
comment_count: this.props.comments_count
};
}

componentDidUpdate() {
if (this.props.data) {
this.setState({comment_count: this.props.data.get('$$comments').size});
}
}

render() {
return (
<nav className="navbar navbar-default" role="navigation">
<div className="container">
<div className="navbar-header">
<button
type="button"
className="navbar-toggle"
data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1"
>
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar" />
<span className="icon-bar" />
<span className="icon-bar" />
</button>
<a className="navbar-brand" href="http://www.shakacode.com">ShakaCode</a>
</div>
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul className="nav navbar-nav">
<li className="active"><a href="/">React Router Demo</a></li>
<li><a href="/no-router">React Demo</a></li>
<li><a href="/simple">Simple React</a></li>
<li><a href="/comments">Classic Rails</a></li>
<li>
<a href={
'https://github.com/' +
'shakacode/react-webpack-rails-tutorial'
}>
Source on Github
</a>
</li>
<li>
<a href={
'http://www.railsonmaui.com/' +
'blog/2014/10/03/integrating' +
'-webpack-and-the-es6-transpiler' +
'-into-an-existing-rails-project/'
}>Tutorial Article</a>
</li>
<li>
<a href={
'http://forum.shakacode.com/' +
't/fast-rich-client-rails-development' +
'-with-webpack-and-the-es6-transpiler/82/22'
}>Forum Discussion</a>
</li>
<li>
Comments: {this.state.comment_count}
</li>
</ul>
</div>
</div>
</nav>
);
}
}
24 changes: 24 additions & 0 deletions client/app/bundles/comments/containers/DevTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

// Exported from redux-devtools
import { createDevTools } from 'redux-devtools';

// Monitors are separate packages, and you can make a custom one
import LogMonitor from 'redux-devtools-log-monitor';
import DockMonitor from 'redux-devtools-dock-monitor';

// createDevTools takes a monitor and produces a DevTools component
const DevTools = createDevTools(

// Monitors are individually adjustable with props.
// Consult their repositories to learn about those props.
// Here, we put LogMonitor inside a DockMonitor.
<DockMonitor
toggleVisibilityKey="ctrl-h"
changePositionKey="ctrl-q"
>
<LogMonitor theme="tomorrow" />
</DockMonitor>
);

export default DevTools;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import Navigationbar from '../components/Navigationbar/Navigationbar';
import CommentScreen from '../components/CommentScreen/CommentScreen';
import * as commentsActionCreators from '../actions/commentsActionCreators';
import BaseComponent from 'libs/components/BaseComponent';
Expand All @@ -21,7 +22,10 @@ class NonRouterCommentsContainer extends BaseComponent {
const { dispatch, data } = this.props;
const actions = bindActionCreators(commentsActionCreators, dispatch);
return (
<CommentScreen {...{ actions, data }} />
<div>
<Navigationbar {...{ actions, data }} />
<CommentScreen {...{ actions, data }} />
</div>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import Navigationbar from '../components/Navigationbar/Navigationbar';
import CommentScreen from '../components/CommentScreen/CommentScreen';
import * as commentsActionCreators from '../actions/commentsActionCreators';
import BaseComponent from 'libs/components/BaseComponent';
Expand All @@ -26,7 +27,10 @@ class RouterCommentsContainer extends BaseComponent {
const locationState = this.props.location.state;

return (
<CommentScreen {...{ actions, data, locationState }} />
<div>
<Navigationbar {...{ actions, data, locationState }} />
<CommentScreen {...{ actions, data, locationState }} />
</div>
);
}
}
Expand Down
19 changes: 19 additions & 0 deletions client/app/bundles/comments/containers/showDevTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { render } from 'react-dom';
import DevTools from './DevTools';

export default function showDevTools(store) {
const popup = window.open(null, 'Redux DevTools',
'menubar=no,location=no,resizable=yes,scrollbars=no,status=no');

// Reload in case it already exists
popup.location.reload();

setTimeout(() => {
popup.document.write('<div id="react-devtools-root"></div>');
render(
<DevTools store={store} />,
popup.document.getElementById('react-devtools-root')
);
}, 10);
}
7 changes: 6 additions & 1 deletion client/app/bundles/comments/startup/ClientApp.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import { Provider } from 'react-redux';

import createStore from '../store/commentsStore';
import NonRouterCommentsContainer from '../containers/NonRouterCommentsContainer';

export default props => {
const store = createStore(props);

if (process.env.NODE_ENV !== 'production') {
const showDevTools = require('../containers/showDevTools');
showDevTools(store);
}

return (
<Provider store={store}>
<NonRouterCommentsContainer />
Expand Down
24 changes: 24 additions & 0 deletions client/app/bundles/comments/startup/ClientReduxSharedStoreApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Top level component for client side.
// Compare this to the ./ServerApp.jsx file which is used for server side rendering.

import React from 'react';
import ReactOnRails from 'react-on-rails';
import RouterCommentsContainer from '../containers/RouterCommentsContainer';
import { Provider } from 'react-redux';

/*
* Export a function that returns a ReactComponent, depending on a store named SharedReduxStore.
* This is used for the client rendering hook after the page html is rendered.
* React will see that the state is the same and not do anything.
*/
export default () => {

// This is where we get the existing store.
const store = ReactOnRails.getStore('routerCommentsStore');

return (
<Provider store={store}>
<RouterCommentsContainer />
</Provider>
);
};
7 changes: 6 additions & 1 deletion client/app/bundles/comments/startup/ServerApp.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import { Provider } from 'react-redux';

import createStore from '../store/commentsStore';
import NonRouterCommentsContainer from '../containers/NonRouterCommentsContainer';

export default props => {
const store = createStore(props);

if (process.env.NODE_ENV !== 'production') {
const showDevTools = require('../containers/showDevTools');
showDevTools(store);
}

return (
<Provider store={store}>
<NonRouterCommentsContainer />
Expand Down
24 changes: 24 additions & 0 deletions client/app/bundles/comments/startup/ServerReduxSharedStoreApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Top level component for client side.
// Compare this to the ./ServerApp.jsx file which is used for server side rendering.

import React from 'react';
import ReactOnRails from 'react-on-rails';
import RouterCommentsContainer from '../containers/RouterCommentsContainer';
import { Provider } from 'react-redux';

/*
* Export a function that returns a ReactComponent, depending on a store named SharedReduxStore.
* This is used for the client rendering hook after the page html is rendered.
* React will see that the state is the same and not do anything.
*/
export default () => {

// This is where we get the existing store.
const store = ReactOnRails.getStore('routerCommentsStore');

return (
<Provider store={store}>
<RouterCommentsContainer />
</Provider>
);
};
21 changes: 14 additions & 7 deletions client/app/bundles/comments/startup/clientRegistration.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import App from './ClientApp';
import RouterApp from './ClientRouterApp';
import Navigationbar from '../components/Navigationbar/Navigationbar';
import SimpleCommentScreen from '../components/SimpleCommentScreen/SimpleCommentScreen';
import routerCommentsStore from '../store/routerCommentsStore';
import ReduxSharedStoreApp from './ClientReduxSharedStoreApp';
import ReactOnRails from 'react-on-rails';

ReactOnRails.setOptions({
traceTurbolinks: TRACE_TURBOLINKS, // eslint-disable-line no-undef
});

ReactOnRails.register(
{
App,
RouterApp,
SimpleCommentScreen,
}
);
ReactOnRails.register({
App,
RouterApp,
ReduxSharedStoreApp,
SimpleCommentScreen,
Navigationbar,
});

ReactOnRails.registerStore({
routerCommentsStore,
});
9 changes: 9 additions & 0 deletions client/app/bundles/comments/startup/serverRegistration.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
import App from './ServerApp';
import RouterApp from './ServerRouterApp';
import ReactOnRails from 'react-on-rails';
import Navigationbar from '../components/Navigationbar/Navigationbar';
import routerCommentsStore from '../store/routerCommentsStore';
import ReduxSharedStoreApp from './ServerReduxSharedStoreApp';

ReactOnRails.register(
{
App,
RouterApp,
ReduxSharedStoreApp,
Navigationbar,
}
);

ReactOnRails.registerStore({
routerCommentsStore,
});
Loading