-
Notifications
You must be signed in to change notification settings - Fork 383
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
demo react-over-hotwired and proof #1508 fixed #592
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<%= form_for(@comment, html: { class: "flex flex-col gap-4" }) do |f| %> | ||
<% if @comment.errors.any? %> | ||
<div id="error_explanation" class="prose bg-pink-100 p-4 mb-4 border border-pink-200 rounded text-red-800 prose-strong:text-red-800 prose-ul:my-1"> | ||
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being saved:</h2> | ||
|
||
<ul> | ||
<% comment.errors.full_messages.each do |message| %> | ||
<li><%= message %></li> | ||
<% end %> | ||
</ul> | ||
</div> | ||
<% end %> | ||
|
||
<div class="field"> | ||
<%= f.label :author, 'Your Name' %><br> | ||
<%= f.text_field :author, class: "px-3 py-1 leading-4 border border-gray-300 rounded" %> | ||
</div> | ||
<div class="field"> | ||
<%= f.label :text, 'Say something using markdown...' %><br> | ||
<%= f.text_area :text, class: "px-3 py-1 leading-4 border border-gray-300 rounded" %> | ||
</div> | ||
<div class="actions"> | ||
<%= f.submit 'Post', class: "self-start px-3 py-1 font-semibold border-0 rounded text-sky-50 bg-sky-600 hover:bg-sky-800 cursor-pointer" %> | ||
</div> | ||
|
||
<h1>Below is a react component which render inside a form (that will proof #1508 is fixed), You can turn-off the flag `force_load` and this below form will not show. </h1> | ||
<div class="mx-10 border border-red-600 rounded"> | ||
<%= react_component('HotwiredCommentForm', props: { }, prerender: false, force_load: true) %> | ||
</div> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<%= turbo_stream.prepend "comments" do %> | ||
<div> | ||
<h2 class="text-blue-800"><%= @comment.author %></h2> | ||
<span><%= markdown_to_html(@comment.text) %></span> | ||
</div> | ||
<% end %> | ||
|
||
<%= turbo_stream.update "comment-form" do %> | ||
<%= link_to "New Comment", new_comment_path, data: {turbo_stream: true} %> | ||
<% end %> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are missing EOL on new files. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<%= turbo_stream.update "comment-form" do %> | ||
<div class="p-5 m-5 border border-red-600 rounded"> | ||
<h2>New Comment</h2> | ||
|
||
<%= react_component('HotwiredCommentForm', props: { }, prerender: false, force_load: true) %> | ||
</div> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<%= turbo_stream.replace dom_id(@comment), target: '_top' do %> | ||
<%= render partial: 'form_1508' %> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<h2>Demo React Over Hotwired</h2> | ||
|
||
<%= react_component('HotwiredCommentScreen', props: @props, prerender: false) %> | ||
|
||
|
||
<%= turbo_frame_tag "new_comment" do %> | ||
<%= link_to "proof that #1508 fixed", "/test_1508", data: {turbo_stream: true} %> | ||
<% end %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// eslint-disable-next-line max-classes-per-file | ||
import React from 'react'; | ||
import request from 'axios'; | ||
import Immutable from 'immutable'; | ||
import _ from 'lodash'; | ||
import ReactOnRails from 'react-on-rails'; | ||
import { IntlProvider, injectIntl } from 'react-intl'; | ||
import BaseComponent from 'libs/components/BaseComponent'; | ||
import SelectLanguage from 'libs/i18n/selectLanguage'; | ||
import { defaultMessages, defaultLocale } from 'libs/i18n/default'; | ||
import { translations } from 'libs/i18n/translations'; | ||
|
||
import { Turbo } from '@hotwired/turbo-rails'; | ||
import CommentForm from '../CommentBox/CommentForm/CommentForm'; | ||
import css from './HotwiredCommentScreen.module.scss'; | ||
|
||
class HotwiredCommentForm extends BaseComponent { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
isSaving: false, | ||
submitCommentError: null, | ||
}; | ||
|
||
_.bindAll(this, 'handleCommentSubmit'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using arrow functions for method bindings instead of lodash's Arrow functions can make the code cleaner and reduce the dependency on lodash for this purpose. Here's how you can refactor the handleCommentSubmit = (comment) => {
// method body remains the same
} |
||
} | ||
|
||
componentDidMount() { | ||
} | ||
|
||
handleCommentSubmit(comment) { | ||
this.setState({ isSaving: true }); | ||
|
||
const requestConfig = { | ||
responseType: 'text/vnd.turbo-stream.html', | ||
headers: ReactOnRails.authenticityHeaders(), | ||
}; | ||
|
||
return request | ||
.post('comments.turbo_stream', { comment }, requestConfig) | ||
.then(r => r.data) | ||
.then(html => { | ||
Turbo.renderStreamMessage(html) | ||
}) | ||
.then(() => { | ||
const { $$comments } = this.state; | ||
const $$comment = Immutable.fromJS(comment); | ||
|
||
this.setState({ | ||
$$comments: $$comments.unshift($$comment), | ||
submitCommentError: null, | ||
isSaving: false, | ||
}); | ||
}) | ||
.catch((error) => { | ||
this.setState({ | ||
submitCommentError: error, | ||
isSaving: false, | ||
}); | ||
}); | ||
} | ||
|
||
render() { | ||
const { handleSetLocale, locale, intl } = this.props; | ||
const cssTransitionGroupClassNames = { | ||
enter: css.elementEnter, | ||
enterActive: css.elementEnterActive, | ||
exit: css.elementLeave, | ||
exitActive: css.elementLeaveActive, | ||
}; | ||
|
||
return ( | ||
<div className="commentBox prose max-w-none prose-a:text-sky-700 prose-li:my-0"> | ||
{SelectLanguage(handleSetLocale, locale)} | ||
|
||
<CommentForm | ||
isSaving={this.state.isSaving} | ||
actions={{ submitComment: this.handleCommentSubmit }} | ||
error={{ error: this.state.submitCommentError, nodeRef: React.createRef(null) }} | ||
cssTransitionGroupClassNames={cssTransitionGroupClassNames} | ||
/> | ||
|
||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default class I18nWrapper extends BaseComponent { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
locale: defaultLocale, | ||
}; | ||
|
||
_.bindAll(this, 'handleSetLocale'); | ||
} | ||
|
||
handleSetLocale(locale) { | ||
this.setState({ locale }); | ||
} | ||
|
||
render() { | ||
const { locale } = this.state; | ||
const messages = translations[locale]; | ||
const InjectedHotwiredCommentForm = injectIntl(HotwiredCommentForm); | ||
|
||
return ( | ||
<IntlProvider locale={locale} key={locale} messages={messages}> | ||
<InjectedHotwiredCommentForm | ||
/* eslint-disable-next-line react/jsx-props-no-spreading */ | ||
{...this.props} | ||
locale={locale} | ||
handleSetLocale={this.handleSetLocale} | ||
/> | ||
</IntlProvider> | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// eslint-disable-next-line max-classes-per-file | ||
import React from 'react'; | ||
import Immutable from 'immutable'; | ||
import ReactOnRails from 'react-on-rails'; | ||
import { IntlProvider, injectIntl } from 'react-intl'; | ||
import BaseComponent from 'libs/components/BaseComponent'; | ||
import SelectLanguage from 'libs/i18n/selectLanguage'; | ||
import { defaultMessages, defaultLocale } from 'libs/i18n/default'; | ||
import { translations } from 'libs/i18n/translations'; | ||
|
||
import CommentList from '../CommentBox/CommentList/CommentList'; | ||
import css from './HotwiredCommentScreen.module.scss'; | ||
|
||
class HotwiredCommentScreen extends BaseComponent { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
$$comments: Immutable.fromJS(props.comments), | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
} | ||
|
||
render() { | ||
const { handleSetLocale, locale, intl } = this.props; | ||
const { formatMessage } = intl; | ||
const cssTransitionGroupClassNames = { | ||
enter: css.elementEnter, | ||
enterActive: css.elementEnterActive, | ||
exit: css.elementLeave, | ||
exitActive: css.elementLeaveActive, | ||
}; | ||
|
||
return ( | ||
<div className="commentBox prose max-w-none prose-a:text-sky-700 prose-li:my-0"> | ||
<turbo-frame id="comment-box"> | ||
<h2>{formatMessage(defaultMessages.comments)}</h2> | ||
{SelectLanguage(handleSetLocale, locale)} | ||
|
||
<CommentList | ||
$$comments={this.state.$$comments} | ||
cssTransitionGroupClassNames={cssTransitionGroupClassNames} | ||
/> | ||
|
||
<div id="comment-form"> | ||
<a data-turbo-stream="true" href="/comments/new">New Comment</a> | ||
</div> | ||
</turbo-frame> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default class I18nWrapper extends BaseComponent { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
locale: defaultLocale, | ||
}; | ||
|
||
_.bindAll(this, 'handleSetLocale'); | ||
} | ||
|
||
handleSetLocale(locale) { | ||
this.setState({ locale }); | ||
} | ||
|
||
render() { | ||
const { locale } = this.state; | ||
const messages = translations[locale]; | ||
const InjectedHotwiredCommentScreen = injectIntl(HotwiredCommentScreen); | ||
|
||
return ( | ||
<IntlProvider locale={locale} key={locale} messages={messages}> | ||
<InjectedHotwiredCommentScreen | ||
/* eslint-disable-next-line react/jsx-props-no-spreading */ | ||
{...this.props} | ||
locale={locale} | ||
handleSetLocale={this.handleSetLocale} | ||
/> | ||
</IntlProvider> | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
.elementEnter { | ||
opacity: 0.01; | ||
|
||
&.elementEnterActive { | ||
opacity: 1; | ||
transition: opacity $animation-duration ease-in; | ||
} | ||
} | ||
|
||
.elementLeave { | ||
opacity: 1; | ||
|
||
&.elementLeaveActive { | ||
opacity: 0.01; | ||
transition: opacity $animation-duration ease-in; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have this change locally only
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's just a demo to prove 1508, and it depends on the branch
[react_on_hotwired](theforestvn88:react_over_hotwired)
which has not been merged so it linked to the locallybuild
of that branch.anyway, i don't think this PR should be merged so we don't need to be serious about this.