Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .browserslistrc
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
defaults
>1%
last 5 versions
safari >= 7
Firefox ESR
not ie < 9
13 changes: 0 additions & 13 deletions .postcssrc

This file was deleted.

2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ruby "3.1.2"

gem "cpl", "~> 0.3.3"
gem "react_on_rails", "13.2.0"
gem "shakapacker", "7.0.0"
gem "shakapacker", "7.0.2"

# Bundle edge Rails instead: gem "rails", github: "rails/rails"
gem "listen"
Expand Down
21 changes: 11 additions & 10 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,8 @@ GEM
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.2)
mini_portile2 (2.8.4)
minitest (5.18.1)
net-imap (0.3.6)
minitest (5.19.0)
net-imap (0.3.7)
date
net-protocol
net-pop (0.1.2)
Expand All @@ -180,8 +179,9 @@ GEM
net-smtp (0.3.3)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.3)
mini_portile2 (~> 2.8.2)
nokogiri (1.15.3-arm64-darwin)
racc (~> 1.4)
nokogiri (1.15.3-x86_64-linux)
racc (~> 1.4)
parallel (1.23.0)
parser (3.2.2.3)
Expand Down Expand Up @@ -335,7 +335,7 @@ GEM
websocket (~> 1.0)
semantic_range (3.0.0)
sexp_processor (4.17.0)
shakapacker (7.0.0)
shakapacker (7.0.2)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
Expand Down Expand Up @@ -376,7 +376,7 @@ GEM
bindex (>= 0.4.0)
railties (>= 6.0.0)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
Expand All @@ -385,7 +385,8 @@ GEM
zeitwerk (2.6.9)

PLATFORMS
ruby
arm64-darwin-22
x86_64-linux

DEPENDENCIES
autoprefixer-rails
Expand Down Expand Up @@ -429,7 +430,7 @@ DEPENDENCIES
scss_lint
sdoc
selenium-webdriver (~> 4)
shakapacker (= 7.0.0)
shakapacker (= 7.0.2)
spring
spring-commands-rspec
uglifier
Expand All @@ -439,4 +440,4 @@ RUBY VERSION
ruby 3.1.2p20

BUNDLED WITH
2.4.7
2.4.17
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[![Code Climate](https://codeclimate.com/github/shakacode/react-webpack-rails-tutorial/badges/gpa.svg)](https://codeclimate.com/github/shakacode/react-webpack-rails-tutorial) [![Coverage Status](https://coveralls.io/repos/shakacode/react-webpack-rails-tutorial/badge.svg?branch=master&service=github)](https://coveralls.io/github/shakacode/react-webpack-rails-tutorial?branch=master)

# React, Redux, React-Bootstrap, ES7, Webpack, Ruby on Rails Demo

* Server-Side Rendering of React via the [react_on_rails gem](https://github.com/shakacode/react_on_rails)
* Live at [www.reactrails.com](http://www.reactrails.com/)
* Live at [www.reactrails.com](http://www.reactrails.com/)

## Control Plane Deployment Example

[Control Plane](https://controlplane.com) offers a viable, cost-saving alternative to Heroku, especially when using the [cpl gem](https://rubygems.org/gems/cpl) to deploy to Control Plane.
[Control Plane](https://controlplane.com) offers a viable, cost-saving alternative to Heroku, especially when using the [cpl gem](https://rubygems.org/gems/cpl) to deploy to Control Plane.

ShakaCode recently migrated [HiChee.com](https://hichee.com) to Control Plane, resulting in a two-thirds reduction in server hosting costs!

Expand All @@ -20,7 +20,7 @@ in https://github.com/shakacode/heroku-to-control-plane.

## React on Rails Pro and ShakaCode Pro Support

React on Rails Pro provides Node server rendering and other performance enhancements for React on Rails.
React on Rails Pro provides Node server rendering and other performance enhancements for React on Rails.

[![2018-09-11_10-31-11](https://user-images.githubusercontent.com/1118459/45467845-5bcc7400-b6bd-11e8-91e1-e0cf806d4ea4.png)](https://blog.shakacode.com/hvmns-90-reduction-in-server-response-time-from-react-on-rails-pro-eb08226687db)

Expand All @@ -34,7 +34,7 @@ For more information, see the [React on Rails Pro Docs](https://www.shakacode.co
* Upgrading your app to use the current Webpack setup that skips the Sprockets asset pipeline.
* Better performance client and server side.

ShakaCode can also help you with your custom software development needs. We specialize in marketplace and e-commerce applications that utilize both Rails and React. We can even leverage our code for [HiChee.com](https://hichee.com) for your app!
ShakaCode can also help you with your custom software development needs. We specialize in marketplace and e-commerce applications that utilize both Rails and React. We can even leverage our code for [HiChee.com](https://hichee.com) for your app!

See the [ShakaCode Client Engagement Model](https://www.shakacode.com/blog/client-engagement-model/) article to learn how we can work together.

Expand Down Expand Up @@ -195,8 +195,8 @@ export default class CommentBox extends React.Component {
const cssTransitionGroupClassNames = {
enter: css.elementEnter,
enterActive: css.elementEnterActive,
leave: css.elementLeave,
leaveActive: css.elementLeaveActive,
exit: css.elementLeave,
exitActive: css.elementLeaveActive,
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ class CommentBox extends BaseComponent {
const cssTransitionGroupClassNames = {
enter: css.elementEnter,
enterActive: css.elementEnterActive,
leave: css.elementLeave,
leaveActive: css.elementLeaveActive,
exit: css.elementLeave,
exitActive: css.elementLeaveActive,
};
const locale = data.get('locale') || defaultLocale;
/* eslint-disable no-script-url */
Expand All @@ -105,7 +105,7 @@ class CommentBox extends BaseComponent {
</ul>
<CommentForm
isSaving={data.get('isSaving')}
error={data.get('submitCommentError')}
error={{ error: data.get('submitCommentError'), nodeRef: React.createRef(null) }}
actions={actions}
cssTransitionGroupClassNames={cssTransitionGroupClassNames}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Button from 'react-bootstrap/lib/Button';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import Alert from 'react-bootstrap/lib/Alert';
import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import _ from 'lodash';
import { injectIntl } from 'react-intl';
import { defaultMessages } from 'libs/i18n/default';
Expand Down Expand Up @@ -259,20 +259,27 @@ class CommentForm extends BaseComponent {
}

errorWarning() {
const { error } = this.props;
const { error, cssTransitionGroupClassNames } = this.props;

// If there is no error, there is nothing to add to the DOM
if (!error) return null;
if (!error.error) return null;

const errorData = error.response && error.response.data;
const errorData = error.error.response && error.error.response.data;

const errorElements = _.transform(
errorData,
(result, errorText, errorFor) => {
result.push(
<li key={errorFor}>
<b>{_.upperFirst(errorFor)}:</b> {errorText}
</li>,
<CSSTransition
key={errorFor}
nodeRef={error.nodeRef}
timeout={500}
classNames={cssTransitionGroupClassNames}
>
<li ref={error.nodeRef}>
<b>{_.upperFirst(errorFor)}:</b> {errorText}
</li>
</CSSTransition>,
);
},
[],
Expand Down Expand Up @@ -302,22 +309,15 @@ class CommentForm extends BaseComponent {
throw new Error(`Unknown form mode: ${this.state.formMode}.`);
}

const { cssTransitionGroupClassNames } = this.props;
const { formatMessage } = this.props.intl;

// For animation with ReactCSSTransitionGroup
// https://facebook.github.io/react/docs/animation.html
// For animation with TransitionGroup
// https://reactcommunity.org/react-transition-group/transition-group
// The 500 must correspond to the 0.5s in:
// client/app/bundles/comments/components/CommentBox/CommentBox.module.scss:6
return (
<div>
<ReactCSSTransitionGroup
transitionName={cssTransitionGroupClassNames}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{this.errorWarning()}
</ReactCSSTransitionGroup>
<TransitionGroup component={null}>{this.errorWarning()}</TransitionGroup>

<Nav bsStyle="pills" activeKey={this.state.formMode} onSelect={this.handleSelect}>
<NavItem eventKey={0}>{formatMessage(defaultMessages.formHorizontal)}</NavItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import BaseComponent from 'libs/components/BaseComponent';
import React from 'react';
import PropTypes from 'prop-types';

import { marked } from 'marked';
import sanitizeHtml from 'sanitize-html';
import css from './Comment.module.scss';

export default class Comment extends BaseComponent {
static propTypes = {
author: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
};
const Comment = React.forwardRef((props, ref) => {
const { author, text } = props;
const rawMarkup = marked(text, { gfm: true, sanitize: true });
const sanitizedRawMarkup = sanitizeHtml(rawMarkup);

render() {
const { author, text } = this.props;
const rawMarkup = marked(text, { gfm: true });
const sanitizedRawMarkup = sanitizeHtml(rawMarkup);
/* eslint-disable react/no-danger */
return (
<div ref={ref} className={css.comment}>
<h2 className={`${css.commentAuthor} js-comment-author`}>{author}</h2>
<span dangerouslySetInnerHTML={{ __html: sanitizedRawMarkup }} className="js-comment-text" />
</div>
);
});

/* eslint-disable react/no-danger */
return (
<div className={css.comment}>
<h2 className={`${css.commentAuthor} js-comment-author`}>{author}</h2>
<span dangerouslySetInnerHTML={{ __html: sanitizedRawMarkup }} className="js-comment-text" />
</div>
);
}
}
Comment.displayName = 'Comment';

Comment.propTypes = {
author: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
};

export default React.memo(Comment);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Alert from 'react-bootstrap/lib/Alert';
import Immutable from 'immutable';
import React from 'react';
import PropTypes from 'prop-types';
import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import _ from 'lodash';
import BaseComponent from '../../../../../libs/components/BaseComponent.jsx';

Expand All @@ -25,13 +25,25 @@ export default class CommentList extends BaseComponent {
}

errorWarning() {
const { error, cssTransitionGroupClassNames } = this.props;

// If there is no error, there is nothing to add to the DOM
if (!this.props.error) return null;
if (!error) return null;

const nodeRef = React.createRef(null);

return (
<Alert bsStyle="danger" key="commentFetchError">
<strong>Comments could not be retrieved. </strong>A server error prevented loading comments. Please
try again.
</Alert>
<CSSTransition
key="commentFetchError"
nodeRef={nodeRef}
timeout={500}
classNames={cssTransitionGroupClassNames}
>
<Alert ref={nodeRef} bsStyle="danger">
<strong>Comments could not be retrieved. </strong>A server error prevented loading comments. Please
try again.
</Alert>
</CSSTransition>
);
}

Expand All @@ -41,36 +53,32 @@ export default class CommentList extends BaseComponent {
// `key` is a React-specific concept and is not mandatory for the
// purpose of this tutorial. if you're curious, see more here:
// http://facebook.github.io/react/docs/multiple-components.html#dynamic-children
<Comment
<CSSTransition
key={$$comment.get('id') || index}
author={$$comment.get('author')}
text={$$comment.get('text')}
/>
nodeRef={$$comment.get('nodeRef')}
timeout={500}
classNames={cssTransitionGroupClassNames}
>
<Comment
key={$$comment.get('id') || index}
author={$$comment.get('author')}
text={$$comment.get('text')}
ref={$$comment.get('nodeRef')}
/>
</CSSTransition>
));

// For animation with ReactCSSTransitionGroup
// https://facebook.github.io/react/docs/animation.html
// For animation with TransitionGroup
// https://reactcommunity.org/react-transition-group/transition-group
// The 500 must correspond to the 0.5s in:
// client/app/bundles/comments/components/CommentBox/CommentBox.module.scss:6
return (
<div>
<ReactCSSTransitionGroup
transitionName={cssTransitionGroupClassNames}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{this.errorWarning()}
</ReactCSSTransitionGroup>
{this.errorWarning()}

<ReactCSSTransitionGroup
transitionName={cssTransitionGroupClassNames}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
className="commentList"
component="div"
>
<TransitionGroup className="commentList" component="div">
{commentNodes}
</ReactCSSTransitionGroup>
</TransitionGroup>
</div>
);
}
Expand Down
Loading