superglue 0.41.0 → 0.50.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20e7f46b274beaffe44eb96b704678e4eb2ebb43c85607a6b4170974525db452
4
- data.tar.gz: 4e4280233e4e9ed82664aafb9fde2f176471c605142bba3af3326282431e0278
3
+ metadata.gz: '0586b4b5e16fbae55b29d0b9b56fb421fec1f5e0841bea7cb8ed2ee661ad6642'
4
+ data.tar.gz: 01fe043eadc91fb4efe74b96e4e1ce35d01bcb895514d701b6a924ce8c7ed994
5
5
  SHA512:
6
- metadata.gz: ba6cd0dabf868452a22e88533df3b2d76f324078e7d7559917a1b5d5aa181cf3e060ceee6f1ea9271f8a8478fde127636639493914eb38ba6eba583026edeabd
7
- data.tar.gz: 7ebb6ade8ba3a240013f9c55f2b6527423773d8655be5292aedab05e01af089884f8e6f7e93bbb0e45f27c785aebd20c4153e20e93796da3c88e3f0804bb775a
6
+ metadata.gz: dab5eef3eff758a64408a2d239e47d0107b60952cb4eb0dfec97a241f39eeeea644ff67741022550d6ca2847a5773098c72379c2b48a2fafb86f0f0ba6d46980
7
+ data.tar.gz: 10340fee27529540353885d343bd5202a35db8bbd5a403156b53c38e960e1b299dd34d5b8955e831cf0791f0f3ebed35908d3189a828fed3605e51eb4be640c8
@@ -1,10 +1,10 @@
1
- require 'rails/generators'
2
- require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
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('../templates', __FILE__)
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 'rails/generators/named_base'
2
- require 'rails/generators/resource_helpers'
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('../templates', __FILE__)
9
+ source_root File.expand_path("../templates", __FILE__)
11
10
 
12
- argument :attributes, type: :array, default: [], banner: 'field:type field:type'
11
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
13
12
 
14
13
  def create_root_folder
15
- path = File.join('app/views', controller_file_path)
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(index show new edit).each do |view|
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('app/views', controller_file_path, filename)
22
+ template filename, File.join("app/views", controller_file_path, filename)
24
23
  end
25
- template '_form.json.props', File.join('app/views', controller_file_path, '_form.json.props')
24
+ template "_form.json.props", File.join("app/views", controller_file_path, "_form.json.props")
26
25
 
27
- %w(index show new edit).each do |view|
26
+ %w[index show new edit].each do |view|
28
27
  @action_name = view
29
28
  filename = filename_with_js_extensions(view)
30
- template 'web/' + filename, File.join('app/views', controller_file_path, filename)
29
+ template "web/" + filename, File.join("app/views", controller_file_path, filename)
31
30
  end
32
31
 
33
- %w(index show new edit).each do |view|
32
+ %w[index show new edit].each do |view|
34
33
  @action_name = view
35
34
  filename = filename_with_html_extensions(view)
36
- template 'web/' + filename, File.join('app/views', controller_file_path, filename)
35
+ template "web/" + filename, File.join("app/views", controller_file_path, filename)
37
36
  end
38
37
 
39
- %w(index show new edit).each do |view|
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
- def app_js_path
55
- if Rails.version >= "7"
56
- "app/javascript/"
57
- else
58
- "app/javascript/packs"
59
- end
60
- end
45
+ def view_path
46
+ "../views"
47
+ end
61
48
 
62
- def append_mapping(action)
63
- app_js = "#{app_js_path}/application.js"
49
+ def app_js_path
50
+ "app/javascript/"
51
+ end
64
52
 
65
- component_name = [plural_table_name, action].map(&:camelcase).join
53
+ def append_mapping(action)
54
+ app_js = "#{app_js_path}/page_to_page_mapping.js"
66
55
 
67
- inject_into_file app_js, after: "from '@thoughtbot/superglue'" do
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
- inject_into_file app_js, after: 'identifierToComponentMapping = {' do
72
- "\n '#{[controller_file_path, action].join('/')}': #{component_name},"
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
- def action_name
77
- @action_name
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
- def attributes_names
81
- [:id] + super
82
- end
67
+ attr_reader :action_name
83
68
 
84
- def filename_with_extensions(name)
85
- [name, :json, :props] * '.'
86
- end
69
+ def attributes_names
70
+ [:id] + super
71
+ end
87
72
 
88
- def filename_with_js_extensions(name)
89
- [name, :js] * '.'
90
- end
73
+ def filename_with_extensions(name)
74
+ [name, :json, :props].join(".")
75
+ end
91
76
 
92
- def filename_with_html_extensions(name)
93
- [name, :html, :erb] * '.'
94
- end
77
+ def filename_with_js_extensions(name)
78
+ [name, :js].join(".")
79
+ end
95
80
 
96
- def attributes_list_with_timestamps
97
- attributes_list(attributes_names + %w(created_at updated_at))
98
- end
81
+ def filename_with_html_extensions(name)
82
+ [name, :html, :erb].join(".")
83
+ end
99
84
 
100
- def attributes_list(attributes = attributes_names)
101
- if self.attributes.any? {|attr| attr.name == 'password' && attr.type == :digest}
102
- attributes = attributes.reject {|name| %w(password password_confirmation).include? name}
103
- end
85
+ def attributes_list_with_timestamps
86
+ attributes_list(attributes_names + %w[created_at updated_at])
87
+ end
104
88
 
105
- attributes
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
- html = form_with(model: @<%= model_resource_name %>, local: true) do |form|
2
- inner = "".html_safe
3
-
1
+ form_props(model: @<%= model_resource_name %>) do |f|
4
2
  <%- attributes.each do |attr| -%>
5
- inner << form.label(:<%= attr.column_name %>)
6
- inner << form.<%= attr.field_type %>(:<%= attr.column_name %>)
3
+ f.<%= attr.field_type %>(:<%= attr.column_name %>)
7
4
  <%- end -%>
8
- inner << form.submit
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
- content = {
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.delete_<%=singular_table_name%>_path <%=singular_table_name%>_path(<%=singular_table_name%>)
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
- content = {
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 RailsTag from '@thoughtbot/superglue/components/RailsTag'
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
- flash,
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
- <RailsTag {...form} data-sg-visit={true}/>
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
- // import * as actionCreators from 'javascript/packs/action_creators'
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><a href={ <%=singular_table_name%>.delete<%=singular_table_name.camelize%>Path }data-sg-visit={true} data-sg-method={"DELETE"}>Delete</a></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 RailsTag from '@thoughtbot/superglue/components/RailsTag'
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
- flash,
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
- <RailsTag {...form} data-sg-visit={true}/>
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
- // import * as actionCreators from 'javascript/packs/action_creators'
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
- // Example:
2
- //
3
- // export const CLEAR_FORM_ERRORS = 'CLEAR_FORM_ERRORS'
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 { render } from 'react-dom';
7
- import { ApplicationBase, fragmentMiddleware } from '@thoughtbot/superglue';
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
- // Mapping between your props template to Component, you must add to this
12
- // to register any new page level component you create. If you are using the
13
- // scaffold, it will auto append the identifers for you.
14
- //
15
- // e.g {'posts/new': PostNew}
16
- const identifierToComponentMapping = {
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
- render(
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
- buildVisitAndRemote={buildVisitAndRemote}
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
- json.flash flash.to_h
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 'props_template/core_ext'
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
+