superglue 0.41.0 → 0.50.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 +4 -4
- data/lib/generators/rails/scaffold_controller_generator.rb +3 -3
- data/lib/generators/rails/superglue_generator.rb +49 -60
- data/lib/generators/rails/templates/_form.json.props +3 -10
- data/lib/generators/rails/templates/edit.json.props +2 -4
- data/lib/generators/rails/templates/index.json.props +3 -1
- data/lib/generators/rails/templates/new.json.props +2 -4
- data/lib/generators/rails/templates/web/edit.js +11 -7
- data/lib/generators/rails/templates/web/index.js +12 -5
- data/lib/generators/rails/templates/web/new.js +11 -7
- data/lib/generators/rails/templates/web/show.js +3 -3
- data/lib/install/templates/web/actions.js +6 -3
- data/lib/install/templates/web/application.js +20 -47
- data/lib/install/templates/web/application.json.props +5 -6
- data/lib/install/templates/web/flash.js +19 -0
- data/lib/install/templates/web/initializer.rb +1 -1
- data/lib/install/templates/web/page_to_page_mapping.js +12 -0
- data/lib/install/templates/web/pages.js +15 -0
- data/lib/install/templates/web/store.js +32 -0
- data/lib/install/web.rb +15 -19
- data/lib/superglue/helpers.rb +7 -517
- data/lib/superglue/redirection.rb +1 -2
- data/lib/superglue.rb +6 -6
- data/lib/tasks/install.rake +1 -12
- metadata +20 -40
- data/lib/install/templates/web/action_creators.js +0 -14
- data/lib/install/templates/web/reducer.js +0 -44
- data/test/engine_test.rb +0 -7
- data/test/helpers_test.rb +0 -23
- data/test/render_test.rb +0 -81
- data/test/test_helper.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0586b4b5e16fbae55b29d0b9b56fb421fec1f5e0841bea7cb8ed2ee661ad6642'
|
4
|
+
data.tar.gz: 01fe043eadc91fb4efe74b96e4e1ce35d01bcb895514d701b6a924ce8c7ed994
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dab5eef3eff758a64408a2d239e47d0107b60952cb4eb0dfec97a241f39eeeea644ff67741022550d6ca2847a5773098c72379c2b48a2fafb86f0f0ba6d46980
|
7
|
+
data.tar.gz: 10340fee27529540353885d343bd5202a35db8bbd5a403156b53c38e960e1b299dd34d5b8955e831cf0791f0f3ebed35908d3189a828fed3605e51eb4be640c8
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "rails/generators"
|
2
|
+
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
|
3
3
|
|
4
4
|
module Rails
|
5
5
|
module Generators
|
6
6
|
class ScaffoldControllerGenerator
|
7
|
-
source_paths << File.expand_path(
|
7
|
+
source_paths << File.expand_path("../templates", __FILE__)
|
8
8
|
|
9
9
|
hook_for :superglue, type: :boolean, default: true
|
10
10
|
end
|
@@ -1,109 +1,98 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require 'rails/version'
|
1
|
+
require "rails/generators/named_base"
|
2
|
+
require "rails/generators/resource_helpers"
|
4
3
|
|
5
4
|
module Rails
|
6
5
|
module Generators
|
7
6
|
class SuperglueGenerator < NamedBase
|
8
7
|
include Rails::Generators::ResourceHelpers
|
9
8
|
|
10
|
-
source_root File.expand_path(
|
9
|
+
source_root File.expand_path("../templates", __FILE__)
|
11
10
|
|
12
|
-
argument :attributes, type: :array, default: [], banner:
|
11
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
13
12
|
|
14
13
|
def create_root_folder
|
15
|
-
path = File.join(
|
14
|
+
path = File.join("app/views", controller_file_path)
|
16
15
|
empty_directory path unless File.directory?(path)
|
17
16
|
end
|
18
17
|
|
19
18
|
def copy_view_files
|
20
|
-
%w
|
19
|
+
%w[index show new edit].each do |view|
|
21
20
|
@action_name = view
|
22
21
|
filename = filename_with_extensions(view)
|
23
|
-
template filename, File.join(
|
22
|
+
template filename, File.join("app/views", controller_file_path, filename)
|
24
23
|
end
|
25
|
-
template
|
24
|
+
template "_form.json.props", File.join("app/views", controller_file_path, "_form.json.props")
|
26
25
|
|
27
|
-
%w
|
26
|
+
%w[index show new edit].each do |view|
|
28
27
|
@action_name = view
|
29
28
|
filename = filename_with_js_extensions(view)
|
30
|
-
template
|
29
|
+
template "web/" + filename, File.join("app/views", controller_file_path, filename)
|
31
30
|
end
|
32
31
|
|
33
|
-
%w
|
32
|
+
%w[index show new edit].each do |view|
|
34
33
|
@action_name = view
|
35
34
|
filename = filename_with_html_extensions(view)
|
36
|
-
template
|
35
|
+
template "web/" + filename, File.join("app/views", controller_file_path, filename)
|
37
36
|
end
|
38
37
|
|
39
|
-
%w
|
38
|
+
%w[index show new edit].each do |view|
|
40
39
|
append_mapping(view)
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
43
|
protected
|
46
|
-
def view_path
|
47
|
-
if Rails.version >= "7"
|
48
|
-
"../views"
|
49
|
-
else
|
50
|
-
"../../views"
|
51
|
-
end
|
52
|
-
end
|
53
44
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
"app/javascript/packs"
|
59
|
-
end
|
60
|
-
end
|
45
|
+
def view_path
|
46
|
+
"../views"
|
47
|
+
end
|
61
48
|
|
62
|
-
|
63
|
-
|
49
|
+
def app_js_path
|
50
|
+
"app/javascript/"
|
51
|
+
end
|
64
52
|
|
65
|
-
|
53
|
+
def append_mapping(action)
|
54
|
+
app_js = "#{app_js_path}/page_to_page_mapping.js"
|
66
55
|
|
67
|
-
|
68
|
-
"\nimport #{component_name} from '#{view_path}/#{controller_file_path}/#{action}'"
|
69
|
-
end
|
56
|
+
component_name = [plural_table_name, action].map(&:camelcase).join
|
70
57
|
|
71
|
-
|
72
|
-
|
73
|
-
end
|
58
|
+
prepend_to_file app_js do
|
59
|
+
"\nimport #{component_name} from '#{view_path}/#{controller_file_path}/#{action}'"
|
74
60
|
end
|
75
61
|
|
76
|
-
|
77
|
-
|
62
|
+
inject_into_file app_js, after: "pageIdentifierToPageComponent = {" do
|
63
|
+
"\n '#{[controller_file_path, action].join("/")}': #{component_name},"
|
78
64
|
end
|
65
|
+
end
|
79
66
|
|
80
|
-
|
81
|
-
[:id] + super
|
82
|
-
end
|
67
|
+
attr_reader :action_name
|
83
68
|
|
84
|
-
|
85
|
-
|
86
|
-
|
69
|
+
def attributes_names
|
70
|
+
[:id] + super
|
71
|
+
end
|
87
72
|
|
88
|
-
|
89
|
-
|
90
|
-
|
73
|
+
def filename_with_extensions(name)
|
74
|
+
[name, :json, :props].join(".")
|
75
|
+
end
|
91
76
|
|
92
|
-
|
93
|
-
|
94
|
-
|
77
|
+
def filename_with_js_extensions(name)
|
78
|
+
[name, :js].join(".")
|
79
|
+
end
|
95
80
|
|
96
|
-
|
97
|
-
|
98
|
-
|
81
|
+
def filename_with_html_extensions(name)
|
82
|
+
[name, :html, :erb].join(".")
|
83
|
+
end
|
99
84
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
85
|
+
def attributes_list_with_timestamps
|
86
|
+
attributes_list(attributes_names + %w[created_at updated_at])
|
87
|
+
end
|
104
88
|
|
105
|
-
|
89
|
+
def attributes_list(attributes = attributes_names)
|
90
|
+
if self.attributes.any? { |attr| attr.name == "password" && attr.type == :digest }
|
91
|
+
attributes = attributes.reject { |name| %w[password password_confirmation].include? name }
|
106
92
|
end
|
93
|
+
|
94
|
+
attributes
|
95
|
+
end
|
107
96
|
end
|
108
97
|
end
|
109
98
|
end
|
@@ -1,13 +1,6 @@
|
|
1
|
-
|
2
|
-
inner = "".html_safe
|
3
|
-
|
1
|
+
form_props(model: @<%= model_resource_name %>) do |f|
|
4
2
|
<%- attributes.each do |attr| -%>
|
5
|
-
|
6
|
-
inner << form.<%= attr.field_type %>(:<%= attr.column_name %>)
|
3
|
+
f.<%= attr.field_type %>(:<%= attr.column_name %>)
|
7
4
|
<%- end -%>
|
8
|
-
|
9
|
-
|
10
|
-
inner
|
5
|
+
f.submit
|
11
6
|
end
|
12
|
-
|
13
|
-
json.html html
|
@@ -1,10 +1,8 @@
|
|
1
1
|
if @post.errors.any?
|
2
|
-
|
2
|
+
json.errors({
|
3
3
|
explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:",
|
4
4
|
messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}}
|
5
|
-
}
|
6
|
-
|
7
|
-
flash.now[:form_error] = content
|
5
|
+
})
|
8
6
|
end
|
9
7
|
|
10
8
|
json.form(partial: 'form') do
|
@@ -5,7 +5,9 @@ json.<%= plural_table_name %> do
|
|
5
5
|
<%- end -%>
|
6
6
|
json.edit_<%=singular_table_name%>_path edit_<%=singular_table_name%>_path(<%=singular_table_name%>)
|
7
7
|
json.<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
|
8
|
-
json.
|
8
|
+
json.delete_form do
|
9
|
+
form_props(model: <%=singular_table_name%>, method: :delete)
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
@@ -1,10 +1,8 @@
|
|
1
1
|
if @post.errors.any?
|
2
|
-
|
2
|
+
json.errors({
|
3
3
|
explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:",
|
4
4
|
messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}}
|
5
|
-
}
|
6
|
-
|
7
|
-
flash.now[:form_error] = content
|
5
|
+
})
|
8
6
|
end
|
9
7
|
|
10
8
|
json.form(partial: 'form') do
|
@@ -1,18 +1,14 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
import
|
3
|
-
// import * as actionCreators from 'javascript/packs/action_creators'
|
4
|
-
// import {useDispatch} from 'react-redux'
|
2
|
+
// import { useSelector } from 'react-redux'
|
5
3
|
|
6
4
|
export default function <%= plural_table_name.camelize %>Edit ({
|
7
5
|
// visit,
|
8
6
|
// remote,
|
9
7
|
form,
|
10
|
-
|
8
|
+
error,
|
11
9
|
<%= singular_table_name.camelize(:lower) %>Path,
|
12
10
|
<%= plural_table_name.camelize(:lower) %>Path,
|
13
11
|
}) {
|
14
|
-
const error = flash.form_error
|
15
|
-
|
16
12
|
const messagesEl = error && (
|
17
13
|
<div id="error_explanation">
|
18
14
|
<h2>{ error.explanation }</h2>
|
@@ -23,7 +19,15 @@ export default function <%= plural_table_name.camelize %>Edit ({
|
|
23
19
|
return (
|
24
20
|
<div>
|
25
21
|
{messagesEl}
|
26
|
-
<
|
22
|
+
<form {...form.props} data-sg-visit={true}>
|
23
|
+
{Object.values(form.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
|
24
|
+
<%- attributes.each do |attr| -%>
|
25
|
+
<input {...form.inputs.<%= attr.column_name %>} type="text"/>
|
26
|
+
<label htmlFor={form.inputs.<%= attr.column_name %>.id}><%= attr.column_name %></label>
|
27
|
+
<%- end -%>
|
28
|
+
<button {...form.inputs.submit} type="submit"> {...form.inputs.submit.text} </button>
|
29
|
+
</form>
|
30
|
+
|
27
31
|
<a href={<%= singular_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Show</a>
|
28
32
|
<a href={<%= plural_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Back</a>
|
29
33
|
</div>
|
@@ -1,15 +1,17 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
|
3
|
-
// import {useDispatch} from 'react-redux'
|
2
|
+
import { useSelector } from 'react-redux'
|
4
3
|
|
5
4
|
export default function <%= plural_table_name.camelize %>Index({
|
6
5
|
// visit,
|
7
6
|
// remote,
|
8
|
-
flash,
|
9
7
|
new<%= singular_table_name.camelize %>Path,
|
10
8
|
<%= plural_table_name.camelize(:lower) %> = [],
|
11
9
|
}) {
|
10
|
+
const flash = useSelector((state) => state.flash)
|
11
|
+
|
12
12
|
const <%= singular_table_name.camelize(:lower) %>Items = <%= plural_table_name.camelize(:lower) %>.map((<%= singular_table_name.camelize(:lower) %>, key) => {
|
13
|
+
const deleteForm = <%=singular_table_name.camelize(:lower)%>.deleteForm;
|
14
|
+
|
13
15
|
return (
|
14
16
|
<tr key={<%= singular_table_name.camelize(:lower) %>.id}>
|
15
17
|
<%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
|
@@ -17,14 +19,19 @@ export default function <%= plural_table_name.camelize %>Index({
|
|
17
19
|
<%- end -%>
|
18
20
|
<td><a href={ <%=singular_table_name%>.<%=singular_table_name.camelize(:lower)%>Path } data-sg-visit={true}>Show</a></td>
|
19
21
|
<td><a href={ <%=singular_table_name%>.edit<%=singular_table_name.camelize%>Path } data-sg-visit={true}>Edit</a></td>
|
20
|
-
<td
|
22
|
+
<td>
|
23
|
+
<form {...deleteForm.props} data-sg-visit={true}>
|
24
|
+
{Object.values(deleteForm.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
|
25
|
+
<button type="submit">Delete</button>
|
26
|
+
</form>
|
27
|
+
</td>
|
21
28
|
</tr>
|
22
29
|
)
|
23
30
|
})
|
24
31
|
|
25
32
|
return (
|
26
33
|
<div>
|
27
|
-
<p id="notice">{flash.notice}</p>
|
34
|
+
<p id="notice">{flash && flash.notice}</p>
|
28
35
|
|
29
36
|
<h1><%= plural_table_name.capitalize %></h1>
|
30
37
|
|
@@ -1,17 +1,13 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
import
|
3
|
-
// import * as actionCreators from 'javascript/packs/action_creators'
|
4
|
-
// import { useDispatch } from 'react-redux'
|
2
|
+
// import { useSelector } from 'react-redux'
|
5
3
|
|
6
4
|
export default function <%= plural_table_name.camelize %>New({
|
7
5
|
// visit,
|
8
6
|
// remote
|
9
7
|
form,
|
10
|
-
|
8
|
+
error,
|
11
9
|
<%= plural_table_name.camelize(:lower) %>Path,
|
12
10
|
}) {
|
13
|
-
const error = flash.form_error
|
14
|
-
|
15
11
|
const messagesEl = error && (
|
16
12
|
<div id="error_explanation">
|
17
13
|
<h2>{ error.explanation }</h2>
|
@@ -22,7 +18,15 @@ export default function <%= plural_table_name.camelize %>New({
|
|
22
18
|
return (
|
23
19
|
<div>
|
24
20
|
{messagesEl}
|
25
|
-
<
|
21
|
+
<form {...form.props} data-sg-visit={true}>
|
22
|
+
{Object.values(form.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
|
23
|
+
<%- attributes.each do |attr| -%>
|
24
|
+
<input {...form.inputs.<%= attr.column_name %>} type="text"/>
|
25
|
+
<label htmlFor={form.inputs.<%= attr.column_name %>.id}><%= attr.column_name %></label>
|
26
|
+
<%- end -%>
|
27
|
+
<button {...form.inputs.submit} type="submit"> {...form.inputs.submit.text} </button>
|
28
|
+
</form>
|
29
|
+
|
26
30
|
<a href={<%= plural_table_name.camelize(:lower) %>Path} data-sg-visit={true}>Back</a>
|
27
31
|
</div>
|
28
32
|
)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
|
3
|
-
// import {useDispatch} from 'react-redux'
|
2
|
+
import { useSelector } from 'react-redux'
|
4
3
|
|
5
4
|
export default function <%= plural_table_name.camelize %>Show({
|
6
5
|
// visit,
|
7
6
|
// remote,
|
8
|
-
flash,
|
9
7
|
<%- attributes_list_with_timestamps.select{|attr| attr != :id }.each do |attr| -%>
|
10
8
|
<%=attr.camelize(:lower)%>,
|
11
9
|
<%- end -%>
|
12
10
|
edit<%= singular_table_name.camelize %>Path,
|
13
11
|
<%= plural_table_name.camelize(:lower) %>Path
|
14
12
|
}) {
|
13
|
+
const flash = useSelector((state) => state.flash)
|
14
|
+
|
15
15
|
return (
|
16
16
|
<div>
|
17
17
|
<p id="notice">{flash && flash.notice}</p>
|
@@ -1,3 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import { createAction } from '@reduxjs/toolkit'
|
2
|
+
import { SAVE_RESPONSE, BEFORE_VISIT, UPDATE_FRAGMENTS } from '@thoughtbot/superglue'
|
3
|
+
|
4
|
+
export const saveResponse = createAction(SAVE_RESPONSE)
|
5
|
+
export const beforeVisit = createAction(BEFORE_VISIT)
|
6
|
+
export const updateFragments = createAction(UPDATE_FRAGMENTS)
|
@@ -1,20 +1,25 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { combineReducers, createStore, applyMiddleware, compose } from 'redux';
|
3
|
-
import reduceReducers from 'reduce-reducers';
|
4
2
|
import thunk from 'redux-thunk';
|
5
3
|
import { Provider } from 'react-redux';
|
6
|
-
import {
|
7
|
-
import { ApplicationBase
|
8
|
-
import { applicationRootReducer, applicationPagesReducer } from './reducer';
|
4
|
+
import { createRoot } from 'react-dom/client';
|
5
|
+
import { ApplicationBase } from '@thoughtbot/superglue';
|
9
6
|
import { buildVisitAndRemote } from './application_visit';
|
7
|
+
import { pageIdentifierToPageComponent } from './page_to_page_mapping';
|
8
|
+
import { buildStore } from './store'
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
class Application extends ApplicationBase {
|
11
|
+
mapping() {
|
12
|
+
return pageIdentifierToPageComponent;
|
13
|
+
}
|
14
|
+
|
15
|
+
visitAndRemote(navRef, store) {
|
16
|
+
return buildVisitAndRemote(navRef, store);
|
17
|
+
}
|
18
|
+
|
19
|
+
buildStore(initialState, { superglue, pages}) {
|
20
|
+
return buildStore(initialState, superglue, pages);
|
21
|
+
}
|
22
|
+
}
|
18
23
|
|
19
24
|
if (typeof window !== "undefined") {
|
20
25
|
document.addEventListener("DOMContentLoaded", function () {
|
@@ -22,7 +27,8 @@ if (typeof window !== "undefined") {
|
|
22
27
|
const location = window.location;
|
23
28
|
|
24
29
|
if (appEl) {
|
25
|
-
|
30
|
+
const root = createRoot(appEl);
|
31
|
+
root.render(
|
26
32
|
<Application
|
27
33
|
appEl={appEl}
|
28
34
|
// The base url prefixed to all calls made by the `visit`
|
@@ -33,43 +39,10 @@ if (typeof window !== "undefined") {
|
|
33
39
|
initialPage={window.SUPERGLUE_INITIAL_PAGE_STATE}
|
34
40
|
// The initial path of the page, e.g., /foobar
|
35
41
|
path={location.pathname + location.search + location.hash}
|
36
|
-
|
37
|
-
/>,
|
38
|
-
appEl
|
42
|
+
/>
|
39
43
|
);
|
40
44
|
}
|
41
45
|
});
|
42
46
|
}
|
43
47
|
|
44
|
-
export default class Application extends ApplicationBase {
|
45
|
-
mapping() {
|
46
|
-
return identifierToComponentMapping;
|
47
|
-
}
|
48
|
-
|
49
|
-
visitAndRemote(navRef, store) {
|
50
|
-
return buildVisitAndRemote(navRef, store);
|
51
|
-
}
|
52
48
|
|
53
|
-
buildStore(initialState, { superglue: superglueReducer, pages: pagesReducer }) {
|
54
|
-
// Create the store
|
55
|
-
// See `./reducer.js` for an explaination of the two included reducers
|
56
|
-
const composeEnhancers =
|
57
|
-
(this.hasWindow && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
|
58
|
-
compose;
|
59
|
-
const reducer = reduceReducers(
|
60
|
-
combineReducers({
|
61
|
-
superglue: superglueReducer,
|
62
|
-
pages: reduceReducers(pagesReducer, applicationPagesReducer),
|
63
|
-
}),
|
64
|
-
applicationRootReducer
|
65
|
-
);
|
66
|
-
|
67
|
-
const store = createStore(
|
68
|
-
reducer,
|
69
|
-
initialState,
|
70
|
-
composeEnhancers(applyMiddleware(thunk, fragmentMiddleware))
|
71
|
-
);
|
72
|
-
|
73
|
-
return store;
|
74
|
-
}
|
75
|
-
}
|
@@ -7,11 +7,7 @@ end
|
|
7
7
|
json.component_identifier local_assigns[:virtual_path_of_template]
|
8
8
|
json.defers json.deferred!
|
9
9
|
json.fragments json.fragments!
|
10
|
-
json.assets [
|
11
|
-
# Uncomment for webpacker support
|
12
|
-
# asset_pack_path('application.js'),
|
13
|
-
asset_path('application.css')
|
14
|
-
]
|
10
|
+
json.assets [ asset_path('application.js') ]
|
15
11
|
|
16
12
|
if protect_against_forgery?
|
17
13
|
json.csrf_token form_authenticity_token
|
@@ -25,4 +21,7 @@ end
|
|
25
21
|
json.restore_strategy 'fromCacheAndRevisitInBackground'
|
26
22
|
|
27
23
|
json.rendered_at Time.now.to_i
|
28
|
-
|
24
|
+
|
25
|
+
json.slices do
|
26
|
+
json.flash flash.to_h
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { createSlice } from '@reduxjs/toolkit'
|
2
|
+
import { saveResponse, beforeVisit } from '../actions'
|
3
|
+
|
4
|
+
export const flashSlice = createSlice({
|
5
|
+
name: 'flash',
|
6
|
+
initialState: {},
|
7
|
+
extraReducers: (builder) => {
|
8
|
+
builder.addCase(beforeVisit, (state, action) => {
|
9
|
+
return {}
|
10
|
+
})
|
11
|
+
builder.addCase(saveResponse, (state, action) => {
|
12
|
+
const { page } = action.payload;
|
13
|
+
|
14
|
+
return {
|
15
|
+
...state, ...page.slices.flash
|
16
|
+
}
|
17
|
+
})
|
18
|
+
}
|
19
|
+
})
|
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "props_template/core_ext"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
// import your page component
|
2
|
+
// e.g import PostsEdit from '../views/posts/edit'
|
3
|
+
|
4
|
+
|
5
|
+
// Mapping between your props template to Component, you must add to this
|
6
|
+
// to register any new page level component you create. If you are using the
|
7
|
+
// scaffold, it will auto append the identifers for you.
|
8
|
+
//
|
9
|
+
// e.g {'posts/new': PostNew}
|
10
|
+
export const pageIdentifierToPageComponent = {
|
11
|
+
};
|
12
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { createSlice } from '@reduxjs/toolkit'
|
2
|
+
import { saveResponse, beforeVisit } from '../actions'
|
3
|
+
|
4
|
+
export const pagesSlice = createSlice({
|
5
|
+
name: 'pages',
|
6
|
+
// extraReducers: (builder) => {
|
7
|
+
// builder.addCase(beforeVisit, (state, action) => {
|
8
|
+
// const {currentPageKey} = action.payload
|
9
|
+
//
|
10
|
+
// const currentPage = draft[currentPageKey]
|
11
|
+
// delete currentPage.error
|
12
|
+
// })
|
13
|
+
// }
|
14
|
+
})
|
15
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { configureStore } from '@reduxjs/toolkit'
|
2
|
+
import { pagesSlice } from "./slices/pages"
|
3
|
+
import { flashSlice } from "./slices/flash"
|
4
|
+
import {
|
5
|
+
BEFORE_VISIT,
|
6
|
+
BEFORE_FETCH,
|
7
|
+
BEFORE_REMOTE,
|
8
|
+
fragmentMiddleware
|
9
|
+
} from '@thoughtbot/superglue'
|
10
|
+
|
11
|
+
export const buildStore = (initialState, superglueReducer, supergluePagesReducer) => {
|
12
|
+
|
13
|
+
return configureStore({
|
14
|
+
preloadedState: initialState,
|
15
|
+
devTools: process.env.NODE_ENV !== 'production',
|
16
|
+
middleware: (getDefaultMiddleware) =>
|
17
|
+
getDefaultMiddleware({
|
18
|
+
serializableCheck: {
|
19
|
+
ignoredActions: [BEFORE_VISIT, BEFORE_FETCH, BEFORE_REMOTE],
|
20
|
+
},
|
21
|
+
}).concat(fragmentMiddleware),
|
22
|
+
reducer: {
|
23
|
+
superglue: superglueReducer,
|
24
|
+
pages: (state, action) => {
|
25
|
+
const nextState = supergluePagesReducer(state, action)
|
26
|
+
return pagesSlice.reducer(nextState, action)
|
27
|
+
},
|
28
|
+
flash: flashSlice.reducer
|
29
|
+
},
|
30
|
+
});
|
31
|
+
};
|
32
|
+
|