superglue 0.53.2 → 1.0.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/superglue/install/install_generator.rb +119 -0
  3. data/lib/{install/templates/web → generators/superglue/install/templates}/application.json.props +2 -2
  4. data/lib/generators/superglue/install/templates/js/application.jsx +35 -0
  5. data/lib/generators/superglue/install/templates/js/application_visit.js +113 -0
  6. data/lib/generators/superglue/install/templates/js/components.js +2 -0
  7. data/lib/generators/superglue/install/templates/js/flash.js +44 -0
  8. data/lib/generators/superglue/install/templates/js/inputs.jsx +302 -0
  9. data/lib/generators/superglue/install/templates/js/jsconfig.json +9 -0
  10. data/lib/generators/superglue/install/templates/js/layout.jsx +16 -0
  11. data/lib/generators/superglue/install/templates/js/page_to_page_mapping.js +35 -0
  12. data/lib/generators/superglue/install/templates/js/store.js +30 -0
  13. data/lib/{install/templates/web/application.js → generators/superglue/install/templates/ts/application.tsx} +10 -16
  14. data/lib/generators/superglue/install/templates/ts/application_visit.ts +122 -0
  15. data/lib/generators/superglue/install/templates/ts/components.ts +2 -0
  16. data/lib/generators/superglue/install/templates/ts/flash.ts +46 -0
  17. data/lib/generators/superglue/install/templates/ts/inputs.tsx +547 -0
  18. data/lib/generators/superglue/install/templates/ts/layout.tsx +16 -0
  19. data/lib/generators/superglue/install/templates/ts/page_to_page_mapping.ts +34 -0
  20. data/lib/generators/superglue/install/templates/ts/store.ts +34 -0
  21. data/lib/generators/superglue/install/templates/ts/tsconfig.json +27 -0
  22. data/lib/generators/superglue/scaffold/scaffold_generator.rb +16 -0
  23. data/lib/generators/superglue/scaffold_controller/scaffold_controller_generator.rb +61 -0
  24. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/edit.html.erb +1 -1
  25. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/index.html.erb +1 -1
  26. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/new.html.erb +1 -1
  27. data/lib/generators/{rails/templates/web → superglue/view_collection/templates/erb}/show.html.erb +1 -1
  28. data/lib/generators/superglue/view_collection/templates/js/edit.jsx +40 -0
  29. data/lib/generators/superglue/view_collection/templates/js/index.jsx +62 -0
  30. data/lib/generators/superglue/view_collection/templates/js/new.jsx +38 -0
  31. data/lib/generators/superglue/view_collection/templates/js/show.jsx +26 -0
  32. data/lib/generators/superglue/view_collection/templates/props/edit.json.props +9 -0
  33. data/lib/generators/superglue/view_collection/templates/props/index.json.props +14 -0
  34. data/lib/generators/superglue/view_collection/templates/props/new.json.props +10 -0
  35. data/lib/generators/superglue/view_collection/templates/props/show.json.props +6 -0
  36. data/lib/generators/superglue/view_collection/templates/ts/edit.tsx +54 -0
  37. data/lib/generators/superglue/view_collection/templates/ts/index.tsx +77 -0
  38. data/lib/generators/superglue/view_collection/templates/ts/new.tsx +50 -0
  39. data/lib/generators/superglue/view_collection/templates/ts/show.tsx +37 -0
  40. data/lib/generators/superglue/view_collection/view_collection_generator.rb +180 -0
  41. data/lib/superglue/helpers.rb +1 -1
  42. data/lib/superglue.rb +2 -1
  43. metadata +60 -43
  44. data/lib/generators/rails/scaffold_controller_generator.rb +0 -12
  45. data/lib/generators/rails/superglue_generator.rb +0 -98
  46. data/lib/generators/rails/templates/controller.rb.tt +0 -82
  47. data/lib/generators/rails/templates/edit.json.props +0 -12
  48. data/lib/generators/rails/templates/index.json.props +0 -14
  49. data/lib/generators/rails/templates/new.json.props +0 -13
  50. data/lib/generators/rails/templates/show.json.props +0 -6
  51. data/lib/generators/rails/templates/web/edit.js +0 -35
  52. data/lib/generators/rails/templates/web/index.js +0 -56
  53. data/lib/generators/rails/templates/web/new.js +0 -33
  54. data/lib/generators/rails/templates/web/show.js +0 -28
  55. data/lib/install/templates/web/actions.js +0 -6
  56. data/lib/install/templates/web/application_visit.js +0 -65
  57. data/lib/install/templates/web/flash.js +0 -19
  58. data/lib/install/templates/web/page_to_page_mapping.js +0 -12
  59. data/lib/install/templates/web/pages.js +0 -15
  60. data/lib/install/templates/web/store.js +0 -32
  61. data/lib/install/web.rb +0 -55
  62. data/lib/tasks/install.rake +0 -9
  63. /data/lib/{install/templates/web → generators/superglue/install/templates}/initializer.rb +0 -0
  64. /data/lib/generators/{rails/templates → superglue/view_collection/templates/props}/_form.json.props +0 -0
@@ -1,56 +0,0 @@
1
- import React from 'react'
2
- import { useSelector } from 'react-redux'
3
-
4
- export default function <%= plural_table_name.camelize %>Index({
5
- // visit,
6
- // remote,
7
- new<%= singular_table_name.camelize %>Path,
8
- <%= plural_table_name.camelize(:lower) %> = [],
9
- }) {
10
- const flash = useSelector((state) => state.flash)
11
-
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
-
15
- return (
16
- <tr key={<%= singular_table_name.camelize(:lower) %>.id}>
17
- <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
18
- <td>{<%=singular_table_name.camelize(:lower)%>.<%=attr.camelize(:lower)%>}</td>
19
- <%- end -%>
20
- <td><a href={ <%=singular_table_name%>.<%=singular_table_name.camelize(:lower)%>Path } data-sg-visit>Show</a></td>
21
- <td><a href={ <%=singular_table_name%>.edit<%=singular_table_name.camelize%>Path } data-sg-visit>Edit</a></td>
22
- <td>
23
- <form {...deleteForm.props} data-sg-visit>
24
- {Object.values(deleteForm.extras).map((hiddenProps) => (<input {...hiddenProps} key={hiddenProps.id} type="hidden"/>))}
25
- <button type="submit">Delete</button>
26
- </form>
27
- </td>
28
- </tr>
29
- )
30
- })
31
-
32
- return (
33
- <div>
34
- <p id="notice">{flash && flash.notice}</p>
35
-
36
- <h1><%= plural_table_name.capitalize %></h1>
37
-
38
- <table>
39
- <thead>
40
- <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
41
- <tr><th><%=attr.capitalize%></th></tr>
42
- <%- end -%>
43
- <tr>
44
- <th colSpan="3"></th>
45
- </tr>
46
- </thead>
47
-
48
- <tbody>
49
- {<%= singular_table_name %>Items}
50
- </tbody>
51
- </table>
52
- <br />
53
- <a href={new<%= singular_table_name.camelize %>Path} data-sg-visit>New <%= singular_table_name.capitalize %></a>
54
- </div>
55
- )
56
- }
@@ -1,33 +0,0 @@
1
- import React from 'react'
2
- // import { useSelector } from 'react-redux'
3
-
4
- export default function <%= plural_table_name.camelize %>New({
5
- // visit,
6
- // remote
7
- form,
8
- errors,
9
- <%= plural_table_name.camelize(:lower) %>Path,
10
- }) {
11
- const messagesEl = errors && (
12
- <div id="error_explanation">
13
- <h2>{ errors.explanation }</h2>
14
- <ul>{ errors.messages.map(({body})=> <li key={body}>{body}</li>) }</ul>
15
- </div>
16
- )
17
-
18
- return (
19
- <div>
20
- {messagesEl}
21
- <form {...form.props} data-sg-visit>
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
-
30
- <a href={<%= plural_table_name.camelize(:lower) %>Path} data-sg-visit>Back</a>
31
- </div>
32
- )
33
- }
@@ -1,28 +0,0 @@
1
- import React from 'react'
2
- import { useSelector } from 'react-redux'
3
-
4
- export default function <%= plural_table_name.camelize %>Show({
5
- // visit,
6
- // remote,
7
- <%- attributes_list_with_timestamps.select{|attr| attr != :id }.each do |attr| -%>
8
- <%=attr.camelize(:lower)%>,
9
- <%- end -%>
10
- edit<%= singular_table_name.camelize %>Path,
11
- <%= plural_table_name.camelize(:lower) %>Path
12
- }) {
13
- const flash = useSelector((state) => state.flash)
14
-
15
- return (
16
- <div>
17
- <p id="notice">{flash && flash.notice}</p>
18
- <%- attributes_list_with_timestamps.select{|attr| attr != :id }.each do |attr| -%>
19
- <p>
20
- <strong><%= attr.capitalize %>:</strong>
21
- {<%=attr.camelize(:lower)%>}
22
- </p>
23
- <%- end -%>
24
- <a href={ edit<%= singular_table_name.camelize %>Path } data-sg-visit>Edit</a>
25
- <a href={ <%= plural_table_name.camelize(:lower) %>Path } data-sg-visit>Back</a>
26
- </div>
27
- )
28
- }
@@ -1,6 +0,0 @@
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,65 +0,0 @@
1
- import { visit, remote } from '@thoughtbot/superglue/action_creators'
2
-
3
- export function buildVisitAndRemote(ref, store) {
4
- const appRemote = (...args) => {
5
- return store.dispatch(remote(...args))
6
- }
7
-
8
- const appVisit = (...args) => {
9
- // Do something before
10
- // e.g, show loading state, you can access the current pageKey
11
- // via store.getState().superglue.currentPageKey
12
- let { action } = args
13
-
14
- return store
15
- .dispatch(visit(...args))
16
- .then((meta) => {
17
- // The assets fingerprints changed, instead of transitioning
18
- // just go to the URL directly to retrieve new assets
19
- if (meta.needsRefresh) {
20
- window.location = meta.url
21
- return
22
- }
23
-
24
- ref.current.navigateTo(meta.pageKey, {
25
- action: meta.suggestedAction,
26
- })
27
-
28
- // always return meta
29
- return meta
30
- })
31
- .finally(() => {
32
- // Do something after
33
- // e.g, hide loading state, you can access the changed pageKey
34
- // via getState().superglue.currentPageKey
35
- })
36
- .catch((err) => {
37
- const response = err.response
38
-
39
- if (!response) {
40
- console.error(err)
41
- return
42
- }
43
-
44
- if (response.ok) {
45
- // err gets thrown, but if the response is ok,
46
- // it must be an html body that
47
- // superglue can't parse, just go to the location
48
- window.location = response.url
49
- } else {
50
- if (response.status >= 400 && response.status < 500) {
51
- window.location = '/400.html'
52
- return
53
- }
54
-
55
- if (response.status >= 500) {
56
- window.location = '/500.html'
57
- return
58
- }
59
- }
60
- })
61
- }
62
-
63
- return { visit: appVisit, remote: appRemote }
64
- }
65
-
@@ -1,19 +0,0 @@
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,12 +0,0 @@
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
-
@@ -1,15 +0,0 @@
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
-
@@ -1,32 +0,0 @@
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 DELETED
@@ -1,55 +0,0 @@
1
- def add_member_methods
2
- inject_into_file "app/models/application_record.rb", after: "class ApplicationRecord < ActiveRecord::Base\n" do
3
- <<-RUBY
4
- def self.member_at(index)
5
- offset(index).limit(1).first
6
- end
7
-
8
- def self.member_by(attr, value)
9
- find_by(Hash[attr, value])
10
- end
11
- RUBY
12
- end
13
- end
14
-
15
- def app_js_path
16
- "app/javascript/"
17
- end
18
-
19
- say "Copying application.js file to #{app_js_path}"
20
- copy_file "#{__dir__}/templates/web/application.js", "#{app_js_path}/application.js"
21
-
22
- say "Copying page_to_page_mapping.js file to #{app_js_path}"
23
- copy_file "#{__dir__}/templates/web/page_to_page_mapping.js", "#{app_js_path}/page_to_page_mapping.js"
24
-
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
-
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"
33
-
34
- say "Copying actions.js file to #{app_js_path}"
35
- copy_file "#{__dir__}/templates/web/actions.js", "#{app_js_path}/actions.js"
36
-
37
- say "Copying application_visit.js file to #{app_js_path}"
38
- copy_file "#{__dir__}/templates/web/application_visit.js", "#{app_js_path}/application_visit.js"
39
-
40
- say "Copying Superglue initializer"
41
- copy_file "#{__dir__}/templates/web/initializer.rb", "config/initializers/superglue.rb"
42
-
43
- say "Copying application.json.props"
44
- copy_file "#{__dir__}/templates/web/application.json.props", "app/views/layouts/application.json.props"
45
-
46
- say "Adding required member methods to ApplicationRecord"
47
- add_member_methods
48
-
49
- say "Installing FormProps"
50
- run "bundle add form_props"
51
-
52
- say "Installing Superglue and friends"
53
- run "yarn add history react react-dom @reduxjs/toolkit react-redux @thoughtbot/superglue --save"
54
-
55
- say "Superglue is Installed! 🎉", :green
@@ -1,9 +0,0 @@
1
- namespace :superglue do
2
- namespace :install do
3
- desc "Install everything needed for superglue web"
4
- task "web" do
5
- template = File.expand_path("../install/web.rb", __dir__)
6
- exec "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{template}"
7
- end
8
- end
9
- end