Skip to content

Commit

Permalink
Merge pull request #261 from seoyoochan/feature/ReduxDevTools
Browse files Browse the repository at this point in the history
Show Redux Dev Tools in a New Window
  • Loading branch information
seoyoochan committed Mar 28, 2016
2 parents ee23eb4 + 312bf19 commit 7f5634c
Show file tree
Hide file tree
Showing 19 changed files with 239 additions and 46 deletions.
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

0 comments on commit 7f5634c

Please sign in to comment.