breezy 0.11.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/lib/breezy.rb +10 -15
- data/lib/breezy/helpers.rb +541 -11
- data/lib/breezy/redirection.rb +30 -0
- data/lib/breezy/xhr_headers.rb +0 -10
- data/lib/generators/rails/breezy_generator.rb +13 -6
- data/lib/generators/rails/templates/_form.json.props +13 -0
- data/lib/generators/rails/templates/controller.rb.tt +0 -3
- data/lib/generators/rails/templates/edit.json.props +14 -0
- data/lib/generators/rails/templates/{index.js.props → index.json.props} +1 -2
- data/lib/generators/rails/templates/new.json.props +15 -0
- data/lib/generators/rails/templates/{show.js.props → show.json.props} +0 -2
- data/lib/generators/rails/templates/web/edit.html.erb +7 -0
- data/lib/generators/rails/templates/web/edit.jsx +21 -28
- data/lib/generators/rails/templates/web/index.html.erb +7 -0
- data/lib/generators/rails/templates/web/index.jsx +10 -7
- data/lib/generators/rails/templates/web/new.html.erb +7 -0
- data/lib/generators/rails/templates/web/new.jsx +18 -25
- data/lib/generators/rails/templates/web/show.html.erb +7 -0
- data/lib/generators/rails/templates/web/show.jsx +3 -4
- data/lib/install/templates/web/action_creators.js +14 -12
- data/lib/install/templates/web/actions.js +4 -1
- data/lib/install/templates/web/application.js +172 -46
- data/lib/install/templates/web/application.json.props +26 -0
- data/lib/install/templates/web/application_visit.js +65 -0
- data/lib/install/templates/web/initializer.rb +1 -6
- data/lib/install/templates/web/reducer.js +62 -9
- data/lib/install/web.rb +18 -55
- data/lib/tasks/install.rake +11 -7
- data/test/helpers_test.rb +9 -17
- data/test/render_test.rb +25 -92
- data/test/test_helper.rb +2 -2
- metadata +31 -34
- data/app/views/breezy/response.html.erb +0 -0
- data/lib/breezy/configuration.rb +0 -35
- data/lib/breezy/render.rb +0 -37
- data/lib/generators/rails/templates/edit.js.props +0 -16
- data/lib/generators/rails/templates/new.js.props +0 -4
- data/lib/generators/rails/templates/web/base.jsx +0 -11
- data/lib/generators/rails/templates/web/form.jsx +0 -31
- data/lib/install/templates/web/babelrc +0 -35
- data/test/breezy_test.rb +0 -125
- data/test/configuration_test.rb +0 -36
@@ -0,0 +1,30 @@
|
|
1
|
+
module Breezy
|
2
|
+
module Redirection
|
3
|
+
def _compute_redirect_to_location(request, options)
|
4
|
+
computed_location = URI.parse(super)
|
5
|
+
next_param = Rack::Utils
|
6
|
+
.parse_nested_query(computed_location.query)
|
7
|
+
|
8
|
+
if request.params[:__] == "0"
|
9
|
+
computed_location.query = next_param.merge({__: "0"}).to_query
|
10
|
+
end
|
11
|
+
|
12
|
+
computed_location.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def redirect_back_with_bzq(opts)
|
16
|
+
if request.referrer && params[:bzq]
|
17
|
+
referrer_url = URI.parse(request.referrer)
|
18
|
+
referrer_url.query = Rack::Utils
|
19
|
+
.parse_nested_query(referrer_url.query)
|
20
|
+
.merge({bzq: params[:bzq]})
|
21
|
+
.to_query
|
22
|
+
|
23
|
+
redirect_to referrer_url.to_s, opts
|
24
|
+
else
|
25
|
+
redirect_back(opts)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/lib/breezy/xhr_headers.rb
CHANGED
@@ -17,17 +17,7 @@ module Breezy
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
if request.xhr? && request.headers["X-BREEZY-REQUEST"]
|
21
|
-
self.status = 200
|
22
|
-
response.headers["X-BREEZY-LOCATION"] = url
|
23
|
-
end
|
24
|
-
|
25
20
|
url
|
26
21
|
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def set_response_url
|
30
|
-
response.headers['X-RESPONSE-URL'] = request.fullpath
|
31
|
-
end
|
32
22
|
end
|
33
23
|
end
|
@@ -21,6 +21,7 @@ module Rails
|
|
21
21
|
filename = filename_with_extensions(view)
|
22
22
|
template filename, File.join('app/views', controller_file_path, filename)
|
23
23
|
end
|
24
|
+
template '_form.json.props', File.join('app/views', controller_file_path, '_form.json.props')
|
24
25
|
|
25
26
|
%w(index show new edit).each do |view|
|
26
27
|
@action_name = view
|
@@ -28,9 +29,11 @@ module Rails
|
|
28
29
|
template 'web/' + filename, File.join('app/views', controller_file_path, filename)
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
%w(index show new edit).each do |view|
|
33
|
+
@action_name = view
|
34
|
+
filename = filename_with_html_extensions(view)
|
35
|
+
template 'web/' + filename, File.join('app/views', controller_file_path, filename)
|
36
|
+
end
|
34
37
|
|
35
38
|
%w(index show new edit).each do |view|
|
36
39
|
append_mapping(view)
|
@@ -48,8 +51,8 @@ module Rails
|
|
48
51
|
"\nimport #{component_name} from 'views/#{controller_file_path}/#{action}'"
|
49
52
|
end
|
50
53
|
|
51
|
-
inject_into_file app_js, after: '
|
52
|
-
"\n
|
54
|
+
inject_into_file app_js, after: 'identifierToComponentMapping = {' do
|
55
|
+
"\n '#{[controller_file_path, action].join('/')}': #{component_name},"
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -62,13 +65,17 @@ module Rails
|
|
62
65
|
end
|
63
66
|
|
64
67
|
def filename_with_extensions(name)
|
65
|
-
[name, :
|
68
|
+
[name, :json, :props] * '.'
|
66
69
|
end
|
67
70
|
|
68
71
|
def filename_with_jsx_extensions(name)
|
69
72
|
[name, :jsx] * '.'
|
70
73
|
end
|
71
74
|
|
75
|
+
def filename_with_html_extensions(name)
|
76
|
+
[name, :html, :erb] * '.'
|
77
|
+
end
|
78
|
+
|
72
79
|
def attributes_list_with_timestamps
|
73
80
|
attributes_list(attributes_names + %w(created_at updated_at))
|
74
81
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
html = form_with(model: @<%= model_resource_name %>, local: true) do |form|
|
2
|
+
inner = "".html_safe
|
3
|
+
|
4
|
+
<%- attributes.each do |attr| -%>
|
5
|
+
inner << form.label(:<%= attr.column_name %>)
|
6
|
+
inner << form.<%= attr.field_type %>(:<%= attr.column_name %>)
|
7
|
+
<%- end -%>
|
8
|
+
inner << form.submit
|
9
|
+
|
10
|
+
inner
|
11
|
+
end
|
12
|
+
|
13
|
+
json.html html
|
@@ -5,9 +5,6 @@ require_dependency "<%= namespaced_path %>/application_controller"
|
|
5
5
|
<% module_namespacing do -%>
|
6
6
|
class <%= controller_class_name %>Controller < ApplicationController
|
7
7
|
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
|
8
|
-
# `use_breezy` enables breezy functionality
|
9
|
-
# on application.html.erb
|
10
|
-
before_action :use_breezy
|
11
8
|
|
12
9
|
# GET <%= route_url %>
|
13
10
|
def index
|
@@ -0,0 +1,14 @@
|
|
1
|
+
if @post.errors.any?
|
2
|
+
content = {
|
3
|
+
explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:",
|
4
|
+
messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}}
|
5
|
+
}
|
6
|
+
|
7
|
+
flash.now[:form_error] = content
|
8
|
+
end
|
9
|
+
|
10
|
+
json.form(partial: 'form') do
|
11
|
+
end
|
12
|
+
|
13
|
+
json.<%= singular_table_name%>_path <%= singular_table_name%>_path(@<%=singular_table_name%>)
|
14
|
+
json.<%= plural_table_name %>_path <%= plural_table_name %>_path
|
@@ -1,5 +1,3 @@
|
|
1
|
-
json.flash flash.to_h
|
2
|
-
|
3
1
|
json.<%= plural_table_name %> do
|
4
2
|
json.array! @<%= plural_table_name %> do |<%= singular_table_name %>|
|
5
3
|
<%- attributes_list_with_timestamps.each do |attr| -%>
|
@@ -7,6 +5,7 @@ json.<%= plural_table_name %> do
|
|
7
5
|
<%- end -%>
|
8
6
|
json.edit_<%=singular_table_name%>_path edit_<%=singular_table_name%>_path(<%=singular_table_name%>)
|
9
7
|
json.<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
|
8
|
+
json.delete_<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
if @post.errors.any?
|
2
|
+
content = {
|
3
|
+
explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:",
|
4
|
+
messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}}
|
5
|
+
}
|
6
|
+
|
7
|
+
flash.now[:form_error] = content
|
8
|
+
end
|
9
|
+
|
10
|
+
json.form(partial: 'form') do
|
11
|
+
end
|
12
|
+
|
13
|
+
json.<%= plural_table_name %>_path <%= plural_table_name %>_path
|
14
|
+
|
15
|
+
|
@@ -1,39 +1,32 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
|
3
3
|
import {connect} from 'react-redux'
|
4
|
-
import
|
5
|
-
import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
|
4
|
+
import RailsTag from '@jho406/breezy/dist/RailsTag'
|
6
5
|
import * as applicationActionCreators from 'javascript/packs/action_creators'
|
7
6
|
|
8
|
-
class <%= plural_table_name.camelize %>Edit extends
|
9
|
-
formRef = React.createRef()
|
10
|
-
|
11
|
-
handleSubmit = (values, {setSubmitting}) => {
|
12
|
-
this.props.clearFormErrors(this.props.pageKey)
|
13
|
-
|
14
|
-
const options = {
|
15
|
-
method:'PUT',
|
16
|
-
body: JSON.stringify(values),
|
17
|
-
}
|
18
|
-
|
19
|
-
this.enhancedVisit(this.props.<%= singular_table_name.camelize(:lower) %>, options).then( rsp => {
|
20
|
-
setSubmitting(false)
|
21
|
-
if (this.props.errors) {
|
22
|
-
this.formRef.current.setErrors(this.props.errors)
|
23
|
-
}
|
24
|
-
})
|
25
|
-
}
|
26
|
-
|
7
|
+
class <%= plural_table_name.camelize %>Edit extends React.Component {
|
27
8
|
render () {
|
9
|
+
const {
|
10
|
+
form,
|
11
|
+
flash,
|
12
|
+
<%= singular_table_name.camelize(:lower) %>Path,
|
13
|
+
<%= plural_table_name.camelize(:lower) %>Path,
|
14
|
+
} = this.props
|
15
|
+
const error = flash.form_error
|
16
|
+
|
17
|
+
const messagesEl = error && (
|
18
|
+
<div id="error_explanation">
|
19
|
+
<h2>{ error.explanation }</h2>
|
20
|
+
<ul>{ error.messages.map(({body})=> <li key={body}>{body}</li>) }</ul>
|
21
|
+
</div>
|
22
|
+
)
|
23
|
+
|
28
24
|
return (
|
29
25
|
<div>
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
/>
|
35
|
-
<a onClick={ e => this.enhancedVisit(this.props.<%= singular_table_name.camelize(:lower) %>Path)}>Show</a>
|
36
|
-
<a onClick={ e => this.enhancedVisit(this.props.<%= plural_table_name.camelize(:lower) %>Path)}>Back</a>
|
26
|
+
{messagesEl}
|
27
|
+
<RailsTag {...form} data-bz-visit={true}/>
|
28
|
+
<a href={<%= singular_table_name.camelize(:lower) %>Path} data-bz-visit={true}>Show</a>
|
29
|
+
<a href={<%= plural_table_name.camelize(:lower) %>Path} data-bz-visit={true}>Back</a>
|
37
30
|
</div>
|
38
31
|
)
|
39
32
|
}
|
@@ -1,30 +1,33 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
|
3
3
|
import { connect } from 'react-redux'
|
4
|
-
import BaseScreen from 'components/BaseScreen'
|
5
4
|
|
6
|
-
class <%= plural_table_name.camelize %>Index extends
|
5
|
+
class <%= plural_table_name.camelize %>Index extends React.Component {
|
7
6
|
static defaultProps = {
|
8
7
|
<%= plural_table_name.camelize(:lower) %>: []
|
9
8
|
}
|
10
9
|
|
11
10
|
render () {
|
11
|
+
const {
|
12
|
+
flash,
|
13
|
+
new<%= singular_table_name.camelize %>Path,
|
14
|
+
} = this.props
|
12
15
|
const <%= singular_table_name.camelize(:lower) %>Items = this.props.<%= plural_table_name.camelize(:lower) %>.map((<%= singular_table_name.camelize(:lower) %>, key) => {
|
13
16
|
return (
|
14
17
|
<tr key={<%= singular_table_name.camelize(:lower) %>.id}>
|
15
18
|
<%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
|
16
19
|
<td>{<%=singular_table_name.camelize(:lower)%>.<%=attr.camelize(:lower)%>}</td>
|
17
20
|
<%- end -%>
|
18
|
-
<td><a
|
19
|
-
<td><a
|
20
|
-
<td><a
|
21
|
+
<td><a href={ <%=singular_table_name%>.<%=singular_table_name.camelize(:lower)%>Path } data-bz-visit={true}>Show</a></td>
|
22
|
+
<td><a href={ <%=singular_table_name%>.edit<%=singular_table_name.camelize%>Path } data-bz-visit={true}>Edit</a></td>
|
23
|
+
<td><a href={ <%=singular_table_name%>.delete<%=singular_table_name.camelize%>Path }data-bz-visit={true} data-bz-method={"DELETE"}>Delete</a></td>
|
21
24
|
</tr>
|
22
25
|
)
|
23
26
|
})
|
24
27
|
|
25
28
|
return (
|
26
29
|
<div>
|
27
|
-
<p id="notice">{
|
30
|
+
<p id="notice">{flash.notice}</p>
|
28
31
|
|
29
32
|
<h1><%= plural_table_name.capitalize %></h1>
|
30
33
|
|
@@ -43,7 +46,7 @@ class <%= plural_table_name.camelize %>Index extends BaseScreen {
|
|
43
46
|
</tbody>
|
44
47
|
</table>
|
45
48
|
<br />
|
46
|
-
<a
|
49
|
+
<a href={new<%= singular_table_name.camelize %>Path} data-bz-visit={true}>New <%= singular_table_name.capitalize %></a>
|
47
50
|
</div>
|
48
51
|
)
|
49
52
|
}
|
@@ -1,37 +1,30 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
|
3
3
|
import {connect} from 'react-redux'
|
4
|
-
import
|
5
|
-
import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
|
4
|
+
import RailsTag from '@jho406/breezy/dist/RailsTag'
|
6
5
|
import * as applicationActionCreators from 'javascript/packs/action_creators'
|
7
6
|
|
8
|
-
class <%= plural_table_name.camelize %>New extends
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
body: JSON.stringify(values),
|
17
|
-
}
|
7
|
+
class <%= plural_table_name.camelize %>New extends React.Component {
|
8
|
+
render () {
|
9
|
+
const {
|
10
|
+
form,
|
11
|
+
flash,
|
12
|
+
<%= plural_table_name.camelize(:lower) %>Path,
|
13
|
+
} = this.props
|
14
|
+
const error = flash.form_error
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
}
|
16
|
+
const messagesEl = error && (
|
17
|
+
<div id="error_explanation">
|
18
|
+
<h2>{ error.explanation }</h2>
|
19
|
+
<ul>{ error.messages.map(({body})=> <li key={body}>{body}</li>) }</ul>
|
20
|
+
</div>
|
21
|
+
)
|
26
22
|
|
27
|
-
render () {
|
28
23
|
return (
|
29
24
|
<div>
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
/>
|
34
|
-
<a onClick={ e => this.enhancedVisit(this.props.<%= plural_table_name.camelize(:lower) %>Path)}>Back</a>
|
25
|
+
{messagesEl}
|
26
|
+
<RailsTag {...this.props.form} data-bz-visit={true}/>
|
27
|
+
<a href={<%= plural_table_name.camelize(:lower) %>Path} data-bz-visit={true}>Back</a>
|
35
28
|
</div>
|
36
29
|
)
|
37
30
|
}
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
|
3
3
|
import { connect } from 'react-redux'
|
4
|
-
import BaseScreen from 'components/BaseScreen'
|
5
4
|
|
6
|
-
class <%= plural_table_name.camelize %>Show extends
|
5
|
+
class <%= plural_table_name.camelize %>Show extends React.Component {
|
7
6
|
render () {
|
8
7
|
return (
|
9
8
|
<div>
|
@@ -14,8 +13,8 @@ class <%= plural_table_name.camelize %>Show extends BaseScreen {
|
|
14
13
|
{this.props.<%=attr.camelize(:lower)%>}
|
15
14
|
</p>
|
16
15
|
<%- end -%>
|
17
|
-
<a
|
18
|
-
<a
|
16
|
+
<a href={ this.props.edit<%= singular_table_name.camelize %>Path } data-bz-visit={true}>Edit</a>
|
17
|
+
<a href={ this.props.<%= plural_table_name.camelize(:lower) %>Path } data-bz-visit={true}>Back</a>
|
19
18
|
</div>
|
20
19
|
)
|
21
20
|
}
|
@@ -1,12 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
1
|
+
// Example:
|
2
|
+
//
|
3
|
+
// import {
|
4
|
+
// CLEAR_FORM_ERRORS
|
5
|
+
// } from './actions'
|
6
|
+
//
|
7
|
+
// export function clearFormErrors(pageKey) {
|
8
|
+
// return {
|
9
|
+
// type: CLEAR_FORM_ERRORS,
|
10
|
+
// payload: {
|
11
|
+
// pageKey,
|
12
|
+
// }
|
13
|
+
// }
|
14
|
+
// }
|
@@ -4,61 +4,187 @@ import reduceReducers from 'reduce-reducers'
|
|
4
4
|
import thunk from 'redux-thunk'
|
5
5
|
import { Provider } from 'react-redux'
|
6
6
|
import { render } from 'react-dom'
|
7
|
-
import
|
8
|
-
import
|
7
|
+
import { createBrowserHistory, createMemoryHistory } from 'history'
|
8
|
+
import { start } from '@jho406/breezy'
|
9
9
|
import Nav from '@jho406/breezy/dist/NavComponent'
|
10
|
-
import
|
10
|
+
import ujsHandlers from '@jho406/breezy/dist/utils/ujs'
|
11
|
+
import { persistStore, persistReducer } from 'redux-persist'
|
12
|
+
import storage from 'redux-persist/lib/storage'
|
13
|
+
import { applicationRootReducer, applicationPagesReducer } from './reducer'
|
14
|
+
import { buildVisitAndRemote } from './application_visit'
|
11
15
|
|
16
|
+
if(typeof window !== 'undefined' ) {
|
17
|
+
document.addEventListener("DOMContentLoaded", function() {
|
18
|
+
const appEl = document.getElementById('app')
|
19
|
+
const location = window.location
|
12
20
|
|
13
|
-
|
14
|
-
|
15
|
-
|
21
|
+
if (appEl) {
|
22
|
+
render(
|
23
|
+
<Application
|
24
|
+
appEl={appEl}
|
25
|
+
// The base url is an optional prefix to all calls made by the `visit`
|
26
|
+
// and `remote` thunks.
|
27
|
+
baseUrl={''}
|
28
|
+
// The global var BREEZY_INITIAL_PAGE_STATE is set by your erb
|
29
|
+
// template, e.g., index.html.erb
|
30
|
+
initialPage={window.BREEZY_INITIAL_PAGE_STATE}
|
31
|
+
// The initial path of the page, e.g., /foobar
|
32
|
+
path={location.pathname + location.search + location.hash}
|
33
|
+
/>, appEl)
|
34
|
+
}
|
35
|
+
})
|
16
36
|
}
|
17
37
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
//
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
}
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
export default class Application extends React.Component {
|
39
|
+
constructor(props) {
|
40
|
+
super(props)
|
41
|
+
this.hasWindow = typeof window !== 'undefined'
|
42
|
+
|
43
|
+
// Mapping between your props template to Component, you must add to this
|
44
|
+
// to register any new page level component you create. If you are using the
|
45
|
+
// scaffold, it will auto append the identifers for you.
|
46
|
+
//
|
47
|
+
// e.g {'posts/new': PostNew}
|
48
|
+
this.identifierToComponentMapping = {
|
49
|
+
}
|
50
|
+
|
51
|
+
// Create a navigator Ref for UJS attributes and to enhance the base `visit`
|
52
|
+
// and `visit` thunks
|
53
|
+
this.navigatorRef = React.createRef()
|
54
|
+
|
55
|
+
// Start Breezy and return an object to prepare the Redux store
|
56
|
+
const breezy = start({
|
57
|
+
initialPage: this.props.initialPage,
|
58
|
+
baseUrl: this.props.baseUrl,
|
59
|
+
path: this.props.path,
|
60
|
+
fetch: this.hasWindow ? window.fetch : undefined,
|
61
|
+
})
|
62
|
+
this.breezy = breezy
|
63
|
+
|
64
|
+
// Build the store and pass Breezy's provided reducer to be combined with
|
65
|
+
// your reducers located at `application_reducer.js`
|
66
|
+
const {initialState, reducer} = breezy
|
67
|
+
this.store = this.buildStore(initialState, reducer)
|
68
|
+
|
69
|
+
// Fire initial events and populate the store
|
70
|
+
breezy.prepareStore(this.store)
|
71
|
+
|
72
|
+
// Build visit and remote thunks
|
73
|
+
// Your modified `visit` and `remote` will get passed below to the
|
74
|
+
// NavComponent then to your components through the provided
|
75
|
+
// mapDispatchToProps.
|
76
|
+
//
|
77
|
+
// You can access them via `this.props.visit` or `this.props.remote`. In
|
78
|
+
// your page components
|
79
|
+
const {visit, remote} = buildVisitAndRemote(this.navigatorRef, this.store)
|
80
|
+
this.visit = visit
|
81
|
+
this.remote = remote
|
82
|
+
}
|
83
|
+
|
84
|
+
componentDidMount() {
|
85
|
+
const { appEl } = this.props
|
86
|
+
// Create the ujs event handlers. You can change the ujsAttributePrefix
|
87
|
+
// in the event the data attribute conflicts with another.
|
88
|
+
this.ujsHandlers = ujsHandlers({
|
89
|
+
visit: this.visit,
|
90
|
+
remote: this.remote,
|
91
|
+
store: this.store,
|
92
|
+
ujsAttributePrefix: 'data-bz'
|
93
|
+
})
|
94
|
+
const {onClick, onSubmit} = this.ujsHandlers
|
95
|
+
|
96
|
+
appEl.addEventListener('click', onClick)
|
97
|
+
appEl.addEventListener('submit', onSubmit)
|
98
|
+
}
|
99
|
+
|
100
|
+
componentWillUnmount() {
|
101
|
+
const { appEl } = this.props
|
102
|
+
const {onClick, onSubmit} = this.ujsHandlers
|
103
|
+
|
104
|
+
appEl.removeEventListener('click', onClick)
|
105
|
+
appEl.removeEventListener('submit', onSubmit)
|
106
|
+
this.breezy.stop()
|
107
|
+
}
|
108
|
+
|
109
|
+
buildStore(initialState, {breezy: breezyReducer, pages: pagesReducer}) {
|
110
|
+
// Create the store
|
111
|
+
// See `./reducer.js` for an explaination of the two included reducers
|
112
|
+
const composeEnhancers = (this.hasWindow && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
|
113
|
+
const reducer = this.wrapWithPersistReducer(
|
114
|
+
reduceReducers(
|
115
|
+
combineReducers({
|
116
|
+
breezy: breezyReducer,
|
117
|
+
pages: reduceReducers(pagesReducer, applicationPagesReducer),
|
118
|
+
}),
|
119
|
+
applicationRootReducer
|
120
|
+
)
|
121
|
+
)
|
122
|
+
const store = createStore(
|
123
|
+
reducer,
|
124
|
+
initialState,
|
125
|
+
composeEnhancers(applyMiddleware(thunk))
|
126
|
+
)
|
127
|
+
|
128
|
+
if(this.hasWindow) {
|
129
|
+
// Persist the store using Redux-Persist
|
130
|
+
persistStore(store)
|
131
|
+
}
|
132
|
+
|
133
|
+
return store
|
134
|
+
}
|
135
|
+
|
136
|
+
wrapWithPersistReducer(reducers) {
|
137
|
+
// Redux Persist settings
|
138
|
+
// The key is set to the stringified JS asset path to remove the need for
|
139
|
+
// migrations when hydrating.
|
140
|
+
if (!this.hasWindow) {
|
141
|
+
return reducers
|
142
|
+
}
|
143
|
+
const prefix = 'breezy'
|
144
|
+
const persistKey = prefix + this.props.initialPage.assets.filter( asset => asset.endsWith('.js')).join(",")
|
145
|
+
const persistConfig = {
|
146
|
+
key: persistKey,
|
147
|
+
storage,
|
148
|
+
}
|
149
|
+
|
150
|
+
// Remove older storage items that were used by previous JS assets
|
151
|
+
if (this.hasWindow) {
|
152
|
+
const storedKeys = Object.keys(localStorage)
|
153
|
+
storedKeys.forEach((key) => {
|
154
|
+
if (key.startsWith(`persist:${prefix}`) && key !== persistKey) {
|
155
|
+
localStorage.removeItem(key)
|
156
|
+
}
|
157
|
+
})
|
158
|
+
}
|
159
|
+
|
160
|
+
return persistReducer(persistConfig, reducers)
|
161
|
+
}
|
162
|
+
|
163
|
+
createHistory() {
|
164
|
+
if(this.hasWindow) {
|
165
|
+
// This is used for client side rendering
|
166
|
+
return createBrowserHistory({})
|
167
|
+
} else {
|
168
|
+
// This is used for server side rendering
|
169
|
+
return createMemoryHistory({})
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
50
173
|
render() {
|
51
|
-
|
174
|
+
const history = this.createHistory()
|
175
|
+
|
176
|
+
// The Nav component is pretty bare and can be inherited from for custom
|
177
|
+
// behavior or replaced with your own.
|
178
|
+
return <Provider store={this.store}>
|
52
179
|
<Nav
|
53
|
-
store={store}
|
54
|
-
|
180
|
+
store={this.store}
|
181
|
+
ref={this.navigatorRef}
|
182
|
+
visit={this.visit}
|
183
|
+
remote={this.remote}
|
184
|
+
mapping={this.identifierToComponentMapping}
|
55
185
|
history={history}
|
56
|
-
initialPageKey={initialPageKey}
|
186
|
+
initialPageKey={this.breezy.initialPageKey}
|
57
187
|
/>
|
58
188
|
</Provider>
|
59
189
|
}
|
60
190
|
}
|
61
|
-
|
62
|
-
document.addEventListener("DOMContentLoaded", function() {
|
63
|
-
render(<App mapping={screenToComponentMapping}/>, document.getElementById('app'))
|
64
|
-
})
|