superglue 0.50.0.beta1 → 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: 44a42cb747cff210dd1550dae3f9ddf280e72a2b38ff26b72fa5f2eea2eeadfe
4
- data.tar.gz: f52f207c4be16d576a51c09f0e821c08d9af68b8150bf52d5b007f59e912d936
3
+ metadata.gz: '0586b4b5e16fbae55b29d0b9b56fb421fec1f5e0841bea7cb8ed2ee661ad6642'
4
+ data.tar.gz: 01fe043eadc91fb4efe74b96e4e1ce35d01bcb895514d701b6a924ce8c7ed994
5
5
  SHA512:
6
- metadata.gz: 57a0e0bbfd2fdcc815af7922f3b97042d016fe6f68be3389a83bcb77a5de2e1e68423a172878482533f25b69464c09d0395a116c4e8179a48ffce1d7a681dcd7
7
- data.tar.gz: d8f034124031b598ee70394fd4900e4daab38126458db85f25afb96e9074bb07196d1f01e9975e960768676da469772d7be044ca3ce0915de95f2e129fdc78d7
6
+ metadata.gz: dab5eef3eff758a64408a2d239e47d0107b60952cb4eb0dfec97a241f39eeeea644ff67741022550d6ca2847a5773098c72379c2b48a2fafb86f0f0ba6d46980
7
+ data.tar.gz: 10340fee27529540353885d343bd5202a35db8bbd5a403156b53c38e960e1b299dd34d5b8955e831cf0791f0f3ebed35908d3189a828fed3605e51eb4be640c8
@@ -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,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,17 +1,14 @@
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 %>Edit ({
6
5
  // visit,
7
6
  // remote,
8
7
  form,
9
- flash,
8
+ error,
10
9
  <%= singular_table_name.camelize(:lower) %>Path,
11
10
  <%= plural_table_name.camelize(:lower) %>Path,
12
11
  }) {
13
- const error = flash.form_error
14
-
15
12
  const messagesEl = error && (
16
13
  <div id="error_explanation">
17
14
  <h2>{ error.explanation }</h2>
@@ -1,14 +1,14 @@
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
13
  const deleteForm = <%=singular_table_name.camelize(:lower)%>.deleteForm;
14
14
 
@@ -31,7 +31,7 @@ export default function <%= plural_table_name.camelize %>Index({
31
31
 
32
32
  return (
33
33
  <div>
34
- <p id="notice">{flash.notice}</p>
34
+ <p id="notice">{flash && flash.notice}</p>
35
35
 
36
36
  <h1><%= plural_table_name.capitalize %></h1>
37
37
 
@@ -1,16 +1,13 @@
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 %>New({
6
5
  // visit,
7
6
  // remote
8
7
  form,
9
- flash,
8
+ error,
10
9
  <%= plural_table_name.camelize(:lower) %>Path,
11
10
  }) {
12
- const error = flash.form_error
13
-
14
11
  const messagesEl = error && (
15
12
  <div id="error_explanation">
16
13
  <h2>{ error.explanation }</h2>
@@ -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,13 +1,11 @@
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';
10
7
  import { pageIdentifierToPageComponent } from './page_to_page_mapping';
8
+ import { buildStore } from './store'
11
9
 
12
10
  class Application extends ApplicationBase {
13
11
  mapping() {
@@ -18,27 +16,8 @@ class Application extends ApplicationBase {
18
16
  return buildVisitAndRemote(navRef, store);
19
17
  }
20
18
 
21
- buildStore(initialState, { superglue: superglueReducer, pages: pagesReducer }) {
22
- // Create the store
23
- // See `./reducer.js` for an explaination of the two included reducers
24
- const composeEnhancers =
25
- (this.hasWindow && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
26
- compose;
27
- const reducer = reduceReducers(
28
- combineReducers({
29
- superglue: superglueReducer,
30
- pages: reduceReducers(pagesReducer, applicationPagesReducer),
31
- }),
32
- applicationRootReducer
33
- );
34
-
35
- const store = createStore(
36
- reducer,
37
- initialState,
38
- composeEnhancers(applyMiddleware(thunk, fragmentMiddleware))
39
- );
40
-
41
- return store;
19
+ buildStore(initialState, { superglue, pages}) {
20
+ return buildStore(initialState, superglue, pages);
42
21
  }
43
22
  }
44
23
 
@@ -48,7 +27,8 @@ if (typeof window !== "undefined") {
48
27
  const location = window.location;
49
28
 
50
29
  if (appEl) {
51
- render(
30
+ const root = createRoot(appEl);
31
+ root.render(
52
32
  <Application
53
33
  appEl={appEl}
54
34
  // The base url prefixed to all calls made by the `visit`
@@ -59,11 +39,10 @@ if (typeof window !== "undefined") {
59
39
  initialPage={window.SUPERGLUE_INITIAL_PAGE_STATE}
60
40
  // The initial path of the page, e.g., /foobar
61
41
  path={location.pathname + location.search + location.hash}
62
- buildVisitAndRemote={buildVisitAndRemote}
63
- />,
64
- appEl
42
+ />
65
43
  );
66
44
  }
67
45
  });
68
46
  }
69
47
 
48
+
@@ -21,4 +21,7 @@ end
21
21
  json.restore_strategy 'fromCacheAndRevisitInBackground'
22
22
 
23
23
  json.rendered_at Time.now.to_i
24
- 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
+ })
@@ -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
+
data/lib/install/web.rb CHANGED
@@ -22,11 +22,14 @@ copy_file "#{__dir__}/templates/web/application.js", "#{app_js_path}/application
22
22
  say "Copying page_to_page_mapping.js file to #{app_js_path}"
23
23
  copy_file "#{__dir__}/templates/web/page_to_page_mapping.js", "#{app_js_path}/page_to_page_mapping.js"
24
24
 
25
- say "Copying reducer.js file to #{app_js_path}"
26
- copy_file "#{__dir__}/templates/web/reducer.js", "#{app_js_path}/reducer.js"
25
+ say "Copying flash.js file to #{app_js_path}"
26
+ copy_file "#{__dir__}/templates/web/flash.js", "#{app_js_path}/slices/flash.js"
27
27
 
28
- say "Copying action_creators.js file to #{app_js_path}"
29
- copy_file "#{__dir__}/templates/web/action_creators.js", "#{app_js_path}/action_creators.js"
28
+ say "Copying pages.js file to #{app_js_path}"
29
+ copy_file "#{__dir__}/templates/web/pages.js", "#{app_js_path}/slices/pages.js"
30
+
31
+ say "Copying store.js file to #{app_js_path}"
32
+ copy_file "#{__dir__}/templates/web/store.js", "#{app_js_path}/store.js"
30
33
 
31
34
  say "Copying actions.js file to #{app_js_path}"
32
35
  copy_file "#{__dir__}/templates/web/actions.js", "#{app_js_path}/actions.js"
@@ -46,7 +49,7 @@ add_member_methods
46
49
  say "Installing FormProps"
47
50
  run "bundle add form_props"
48
51
 
49
- say "Installing React, Redux, and Superglue"
50
- run "yarn add history react-redux redux-thunk redux reduce-reducers immer @thoughtbot/superglue --save"
52
+ say "Installing Superglue and friends"
53
+ run "yarn add history react react-dom @reduxjs/toolkit react-redux @thoughtbot/superglue --save"
51
54
 
52
55
  say "Superglue is Installed! 🎉", :green
@@ -1,17 +1,7 @@
1
1
  namespace :superglue do
2
- desc "Verifies if any version of react is in package.json"
3
- task :verify_react do
4
- package_json = JSON.parse(File.read(Rails.root.join("package.json")))
5
-
6
- if package_json["dependencies"]["react"].nil?
7
- warn "React not installed. Did you install React? https://github.com/rails/webpacker#react"
8
- warn "Exiting!" && exit!
9
- end
10
- end
11
-
12
2
  namespace :install do
13
3
  desc "Install everything needed for superglue web"
14
- task "web" => ["superglue:verify_react"] do
4
+ task "web" do
15
5
  template = File.expand_path("../install/web.rb", __dir__)
16
6
  exec "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{template}"
17
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superglue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.50.0.beta1
4
+ version: 0.50.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johny Ho
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-17 00:00:00.000000000 Z
11
+ date: 2023-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0
19
+ version: 7.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.0
26
+ version: 7.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: props_template
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '6.0'
61
+ version: '7.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '6.0'
68
+ version: '7.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '12.0'
83
- - !ruby/object:Gem::Dependency
84
- name: byebug
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '9.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '9.0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: sqlite3
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -172,14 +158,15 @@ files:
172
158
  - lib/generators/rails/templates/web/new.js
173
159
  - lib/generators/rails/templates/web/show.html.erb
174
160
  - lib/generators/rails/templates/web/show.js
175
- - lib/install/templates/web/action_creators.js
176
161
  - lib/install/templates/web/actions.js
177
162
  - lib/install/templates/web/application.js
178
163
  - lib/install/templates/web/application.json.props
179
164
  - lib/install/templates/web/application_visit.js
165
+ - lib/install/templates/web/flash.js
180
166
  - lib/install/templates/web/initializer.rb
181
167
  - lib/install/templates/web/page_to_page_mapping.js
182
- - lib/install/templates/web/reducer.js
168
+ - lib/install/templates/web/pages.js
169
+ - lib/install/templates/web/store.js
183
170
  - lib/install/web.rb
184
171
  - lib/superglue.rb
185
172
  - lib/superglue/helpers.rb
@@ -200,9 +187,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
187
  version: '0'
201
188
  required_rubygems_version: !ruby/object:Gem::Requirement
202
189
  requirements:
203
- - - ">"
190
+ - - ">="
204
191
  - !ruby/object:Gem::Version
205
- version: 1.3.1
192
+ version: '0'
206
193
  requirements: []
207
194
  rubygems_version: 3.4.6
208
195
  signing_key:
@@ -1,14 +0,0 @@
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
- // }
@@ -1,44 +0,0 @@
1
- // Example:
2
- //
3
- // import {
4
- // CLEAR_FORM_ERRORS
5
- // } from './actions'
6
- // import produce from "immer"
7
- //
8
- // export const applicationPagesReducer = (state = {}, action) => {
9
- // switch(action.type) {
10
- // case CLEAR_FORM_ERRORS: {
11
- // const {pageKey} = action.payload
12
- //
13
- // return produce(state, draft => {
14
- // const currentPage = draft[pageKey]
15
- // delete currentPage.errors
16
- // })
17
- // }
18
- // default:
19
- // return state
20
- // }
21
- // }
22
-
23
-
24
- // The applicationPageReducer is for cross page reducers
25
- // Its common to add to this. You'll typically have to pass a pageKey to the
26
- // action payload to distinguish the current page
27
- //
28
- // The pageKey is passed through the props in your component. Access it like
29
- // this: `this.props.pageKey` then dispatch it in an action
30
- export const applicationPagesReducer = (state = {}, action) => {
31
- switch(action.type) {
32
- default:
33
- return state
34
- }
35
- }
36
-
37
- // The applicationRootReducer is for app wide reducers
38
- // Its rare to be adding to this.
39
- export const applicationRootReducer = (state = {}, action) => {
40
- switch(action.type) {
41
- default:
42
- return state
43
- }
44
- }