diff --git a/superglue/lib/action_creators/requests.js b/superglue/lib/action_creators/requests.js index b459d430..e9143a3b 100644 --- a/superglue/lib/action_creators/requests.js +++ b/superglue/lib/action_creators/requests.js @@ -8,7 +8,6 @@ import { removePropsAt, } from '../utils' import { - CLEAR_FLASH, BEFORE_FETCH, BEFORE_VISIT, BEFORE_REMOTE, @@ -66,15 +65,6 @@ function buildMeta(pageKey, page, state) { } } -export function clearFlash({ pageKey }) { - return { - type: CLEAR_FLASH, - payload: { - pageKey, - }, - } -} - export function remote( path, { @@ -95,8 +85,9 @@ export function remote( body, }) pageKey = pageKey || getState().superglue.currentPageKey + const currentPageKey = getState().superglue.currentPageKey - dispatch(beforeRemote({ fetchArgs })) + dispatch(beforeRemote({ currentPageKey, fetchArgs })) dispatch(beforeFetch({ fetchArgs })) return fetch(...fetchArgs) @@ -142,9 +133,6 @@ export function visit( let pageKey = urlToPageKey(path) return (dispatch, getState) => { - const currentKey = getState().superglue.currentPageKey - dispatch(clearFlash({ pageKey: currentKey })) - placeholderKey = placeholderKey && urlToPageKey(placeholderKey) const hasPlaceholder = !!getState().pages[placeholderKey] @@ -175,7 +163,8 @@ export function visit( signal, }) - dispatch(beforeVisit({ fetchArgs })) + const currentPageKey = getState().superglue.currentPageKey + dispatch(beforeVisit({ currentPageKey, fetchArgs })) dispatch(beforeFetch({ fetchArgs })) lastVisitController.abort() diff --git a/superglue/lib/actions.js b/superglue/lib/actions.js index fa4b22b5..525f1cd1 100644 --- a/superglue/lib/actions.js +++ b/superglue/lib/actions.js @@ -4,7 +4,6 @@ export const BEFORE_REMOTE = '@@superglue/BEFORE_REMOTE' export const SAVE_RESPONSE = '@@superglue/SAVE_RESPONSE' export const HANDLE_GRAFT = '@@superglue/HANDLE_GRAFT' -export const CLEAR_FLASH = '@@superglue/CLEAR_FLASH' export const SUPERGLUE_ERROR = '@@superglue/ERROR' export const GRAFTING_ERROR = '@@superglue/GRAFTING_ERROR' diff --git a/superglue/lib/index.js b/superglue/lib/index.js index bfca6fd0..bae238f7 100644 --- a/superglue/lib/index.js +++ b/superglue/lib/index.js @@ -27,6 +27,7 @@ export { REMOVE_PAGE, GRAFTING_ERROR, GRAFTING_SUCCESS, + HISTORY_CHANGE, } from './actions' export { @@ -46,8 +47,11 @@ export { getIn } from './utils/immutability' export { urlToPageKey } function pageToInitialState(key, page) { + const slices = page.slices || {} + return { pages: { [key]: page }, + ...slices, } } diff --git a/superglue/lib/reducers/index.js b/superglue/lib/reducers/index.js index 860a4cc6..a2a518c5 100644 --- a/superglue/lib/reducers/index.js +++ b/superglue/lib/reducers/index.js @@ -1,7 +1,6 @@ import { setIn, getIn, urlToPageKey } from '../utils' import { REMOVE_PAGE, - CLEAR_FLASH, SAVE_RESPONSE, HANDLE_GRAFT, HISTORY_CHANGE, @@ -96,15 +95,6 @@ export function appendReceivedFragmentsOntoPage( return nextState } -export function addFlash(state, pageKey, receivedFlash) { - const nextState = { ...state } - const nextPage = { ...state[pageKey] } - nextPage.flash = { ...nextPage.flash, ...receivedFlash } - nextState[pageKey] = nextPage - - return nextState -} - export function graftNodeOntoPage(state, pageKey, node, pathToNode) { if (!node) { console.warn( @@ -132,7 +122,6 @@ export function handleGraft(state, pageKey, page) { data: receivedNode, path: pathToNode, fragments: receivedFragments = [], - flash: receivedFlash, } = page return [ @@ -144,7 +133,6 @@ export function handleGraft(state, pageKey, page) { pageKey, receivedFragments ), - (nextState) => addFlash(nextState, pageKey, receivedFlash), ].reduce((memo, fn) => fn(memo), state) } @@ -185,16 +173,6 @@ export function pageReducer(state = {}, action) { return nextState } - case CLEAR_FLASH: { - const { pageKey } = action.payload - const nextState = { ...state } - const nextPage = { ...state[pageKey] } - - nextPage.flash = {} - nextState[pageKey] = nextPage - - return nextState - } case COPY_PAGE: { const nextState = { ...state } const { from, to } = action.payload diff --git a/superglue/lib/utils/react.js b/superglue/lib/utils/react.js index f747de8b..7c061cd3 100644 --- a/superglue/lib/utils/react.js +++ b/superglue/lib/utils/react.js @@ -14,12 +14,11 @@ export function mapStateToProps( let params = ownProps const csrfToken = state.superglue.csrfToken pageKey = urlToPageKey(pageKey) - const { data, flash, fragments } = state.pages[pageKey] || { + const { data, fragments } = state.pages[pageKey] || { data: {}, - flash: {}, fragments: [], } - return { ...data, ...params, pageKey, csrfToken, flash, fragments } + return { ...data, ...params, pageKey, csrfToken, fragments } } export const mapDispatchToProps = { diff --git a/superglue/spec/features/navigation.spec.js b/superglue/spec/features/navigation.spec.js index 7d0ca846..1f87c358 100644 --- a/superglue/spec/features/navigation.spec.js +++ b/superglue/spec/features/navigation.spec.js @@ -71,7 +71,6 @@ describe('start', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -106,7 +105,6 @@ describe('start', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -137,7 +135,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -165,7 +162,6 @@ describe('navigation', () => { const pageState = { data: { heading: 'Some heading 2' }, - flash: {}, csrfToken: 'token', assets: ['application-123.js', 'application-123.js'], componentIdentifier: 'about', @@ -194,7 +190,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -230,7 +225,6 @@ describe('navigation', () => { const pageState = { data: { heading: 'Some heading 2' }, - flash: {}, csrfToken: 'token', assets: ['application-123.js', 'application-123.js'], componentIdentifier: 'about', @@ -272,7 +266,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -315,7 +308,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -369,7 +361,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -419,7 +410,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -496,7 +486,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -540,7 +529,6 @@ describe('navigation', () => { data: { heading: 'this is page 1', }, - flash: {}, componentIdentifier: 'home', assets: ['123.js', '123.css'], fragments: [], @@ -561,7 +549,6 @@ describe('navigation', () => { const pageState = { data: { heading: 'Some heading 2' }, - flash: {}, csrfToken: 'token', assets: ['application-123.js', 'application-123.js'], componentIdentifier: 'about', @@ -591,7 +578,6 @@ describe('navigation', () => { heading: 'this is page 1', address: undefined, }, - flash: {}, fragments: [], componentIdentifier: 'home', } diff --git a/superglue/spec/fixtures.js b/superglue/spec/fixtures.js index 1911b76a..5832d471 100644 --- a/superglue/spec/fixtures.js +++ b/superglue/spec/fixtures.js @@ -5,7 +5,6 @@ export const visitSuccess = () => { csrfToken: 'token', assets: ['application-123.js', 'application-123.js'], componentIdentifier: 'about', - flash: {}, fragments: [], }), headers: { @@ -23,7 +22,6 @@ export const graftSuccessWithNewZip = () => { path: 'data.address', csrfToken: 'token', assets: ['application-new123.js', 'application-new123.js'], - flash: {}, fragments: [], }), headers: { diff --git a/superglue/spec/lib/action_creators.spec.js b/superglue/spec/lib/action_creators.spec.js index 7f21edd3..6cac93d9 100644 --- a/superglue/spec/lib/action_creators.spec.js +++ b/superglue/spec/lib/action_creators.spec.js @@ -272,6 +272,7 @@ describe('action creators', () => { { type: '@@superglue/BEFORE_REMOTE', payload: { + currentPageKey: "/bar", fetchArgs: [ '/foo?props_at=data.body&__=0', { @@ -327,6 +328,7 @@ describe('action creators', () => { { type: '@@superglue/BEFORE_REMOTE', payload: { + currentPageKey: "/bar", fetchArgs: [ '/foo?props_at=data.body.aside.top&__=0', { @@ -780,7 +782,7 @@ describe('action creators', () => { const expectedActions = [ { type: '@@superglue/BEFORE_REMOTE', - payload: { fetchArgs: ['/foo?__=0', expect.any(Object)] }, + payload: { currentPageKey: "/bar", fetchArgs: ['/foo?__=0', expect.any(Object)] }, }, { type: '@@superglue/BEFORE_FETCH', @@ -856,7 +858,7 @@ describe('action creators', () => { const expectedActions = [ { type: '@@superglue/BEFORE_REMOTE', - payload: { fetchArgs: ['/foo?__=0', expect.any(Object)] }, + payload: { currentPageKey: '/bar', fetchArgs: ['/foo?__=0', expect.any(Object)] }, }, { type: '@@superglue/BEFORE_FETCH', @@ -987,7 +989,7 @@ describe('action creators', () => { const expectedActions = [ { type: '@@superglue/BEFORE_REMOTE', - payload: { fetchArgs: ['/foo?__=0', expect.any(Object)] }, + payload: { currentPageKey: "/bar", fetchArgs: ['/foo?__=0', expect.any(Object)] }, }, { type: '@@superglue/BEFORE_FETCH', @@ -1021,7 +1023,7 @@ describe('action creators', () => { const expectedActions = [ { type: '@@superglue/BEFORE_REMOTE', - payload: { fetchArgs: ['/foo?__=0', expect.any(Object)] }, + payload: { currentPageKey: "/bar", fetchArgs: ['/foo?__=0', expect.any(Object)] }, }, { type: '@@superglue/BEFORE_FETCH', @@ -1060,7 +1062,7 @@ describe('action creators', () => { const expectedActions = [ { type: '@@superglue/BEFORE_REMOTE', - payload: { fetchArgs: ['/foo?__=0', expect.any(Object)] }, + payload: { currentPageKey: "/bar", fetchArgs: ['/foo?__=0', expect.any(Object)] }, }, { type: '@@superglue/BEFORE_FETCH', @@ -1316,7 +1318,6 @@ describe('action creators', () => { data: { address: {}, }, - flash: {}, csrfToken: 'token', assets: [ 'application-new123.js', @@ -1333,10 +1334,6 @@ describe('action creators', () => { fetchMock.mock('/details?props_at=data.address&__=0', mockResponse) const expectedActions = [ - { - type: '@@superglue/CLEAR_FLASH', - payload: { pageKey: '/current' }, - }, { type: '@@superglue/COPY_PAGE', payload: { from: '/current', to: '/details' }, diff --git a/superglue/spec/lib/reducers.spec.js b/superglue/spec/lib/reducers.spec.js index 90ea785f..8f204f1b 100644 --- a/superglue/spec/lib/reducers.spec.js +++ b/superglue/spec/lib/reducers.spec.js @@ -83,7 +83,6 @@ describe('reducers', () => { a: { b: { c: {} } }, }, fragments: [], - flash: {}, }, } @@ -97,7 +96,6 @@ describe('reducers', () => { path: 'data.a.b.c', }, ], - flash: {}, } const nextState = pageReducer(prevState, { @@ -120,7 +118,6 @@ describe('reducers', () => { path: 'data.a.b.c', }, ], - flash: {}, }, }) }) @@ -138,7 +135,6 @@ describe('reducers', () => { path: 'data.a.b.c', }, ], - flash: {}, }, } const receivedPage = { @@ -151,7 +147,6 @@ describe('reducers', () => { path: 'data.a.b.c', }, ], - flash: {}, } const nextState = pageReducer(prevState, { @@ -174,7 +169,6 @@ describe('reducers', () => { path: 'data.a.b.c', }, ], - flash: {}, }, }) }) @@ -189,7 +183,6 @@ describe('reducers', () => { d: { e: { f: {} } }, }, fragments: [], - flash: {}, }, } @@ -203,7 +196,6 @@ describe('reducers', () => { path: 'data.d.e.f', }, ], - flash: {}, } const nextState = pageReducer(prevState, { @@ -227,7 +219,6 @@ describe('reducers', () => { path: 'data.d.e.f', }, ], - flash: {}, }, }) }) @@ -246,7 +237,6 @@ describe('reducers', () => { path: 'data.d.e.f', }, ], - flash: {}, }, } @@ -254,7 +244,6 @@ describe('reducers', () => { data: {}, path: 'data.a.b.c', fragments: [], - flash: {}, } const nextState = pageReducer(prevState, { @@ -275,13 +264,11 @@ describe('reducers', () => { '/foo': { data: { a: { b: { c: {} } } }, fragments: [], - flash: {}, }, } const receivedPage = { data: { foo: 1 }, fragments: [], - flash: {}, } const pageKey = '/foo' @@ -301,7 +288,6 @@ describe('reducers', () => { '/foo': { data: { a: { b: { c: {} } } }, fragments: [], - flash: {}, }, } @@ -309,7 +295,6 @@ describe('reducers', () => { data: { foo: 1 }, path: 'data.a.b.c', fragments: [], - flash: {}, } const nextState = pageReducer(prevState, { @@ -324,7 +309,6 @@ describe('reducers', () => { '/foo': { data: { a: { b: { c: { foo: 1 } } } }, fragments: [], - flash: {}, }, }) }) @@ -359,13 +343,11 @@ describe('reducers', () => { '/foo': { data: { a: { b: { c: {} } } }, fragments: [], - flash: {}, }, } const receivedPage = { path: 'data.a.b.c', - flash: {}, } const nextState = pageReducer(prevState, { diff --git a/superglue/spec/lib/utils/react.spec.js b/superglue/spec/lib/utils/react.spec.js index 001bd774..196b04c6 100644 --- a/superglue/spec/lib/utils/react.spec.js +++ b/superglue/spec/lib/utils/react.spec.js @@ -6,7 +6,6 @@ describe('mapStateToToProps', () => { pages: { '/foo': { data: { heading: 'hi' }, - flash: {}, }, }, superglue: { @@ -19,7 +18,6 @@ describe('mapStateToToProps', () => { heading: 'hi', pageKey: '/foo', csrfToken: 'token123', - flash: {}, }) }) }) diff --git a/superglue_rails/lib/generators/rails/templates/edit.json.props b/superglue_rails/lib/generators/rails/templates/edit.json.props index 6173407f..455957d4 100644 --- a/superglue_rails/lib/generators/rails/templates/edit.json.props +++ b/superglue_rails/lib/generators/rails/templates/edit.json.props @@ -1,10 +1,8 @@ if @post.errors.any? - content = { + json.errors({ explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:", messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}} - } - - flash.now[:form_error] = content + }) end json.form(partial: 'form') do diff --git a/superglue_rails/lib/generators/rails/templates/new.json.props b/superglue_rails/lib/generators/rails/templates/new.json.props index 6cd98c5c..4fe6e0b3 100644 --- a/superglue_rails/lib/generators/rails/templates/new.json.props +++ b/superglue_rails/lib/generators/rails/templates/new.json.props @@ -1,10 +1,8 @@ if @post.errors.any? - content = { + json.errors({ explanation: "#{pluralize(@<%= singular_table_name %>.errors.count, "error")} prohibited this post from being saved:", messages: @<%= singular_table_name %>.errors.full_messages.map{|msg| {body: msg}} - } - - flash.now[:form_error] = content + }) end json.form(partial: 'form') do diff --git a/superglue_rails/lib/generators/rails/templates/web/edit.js b/superglue_rails/lib/generators/rails/templates/web/edit.js index 048a114c..f06e944a 100644 --- a/superglue_rails/lib/generators/rails/templates/web/edit.js +++ b/superglue_rails/lib/generators/rails/templates/web/edit.js @@ -1,17 +1,14 @@ import React from 'react' -// import * as actionCreators from 'javascript/packs/action_creators' -// import {useDispatch} from 'react-redux' +// import { useSelector } from 'react-redux' export default function <%= plural_table_name.camelize %>Edit ({ // visit, // remote, form, - flash, + error, <%= singular_table_name.camelize(:lower) %>Path, <%= plural_table_name.camelize(:lower) %>Path, }) { - const error = flash.form_error - const messagesEl = error && (
{flash.notice}
+{flash && flash.notice}
{flash && flash.notice}
diff --git a/superglue_rails/lib/install/templates/web/action_creators.js b/superglue_rails/lib/install/templates/web/action_creators.js deleted file mode 100644 index 323a233a..00000000 --- a/superglue_rails/lib/install/templates/web/action_creators.js +++ /dev/null @@ -1,14 +0,0 @@ -// Example: -// -// import { -// CLEAR_FORM_ERRORS -// } from './actions' -// -// export function clearFormErrors(pageKey) { -// return { -// type: CLEAR_FORM_ERRORS, -// payload: { -// pageKey, -// } -// } -// } diff --git a/superglue_rails/lib/install/templates/web/actions.js b/superglue_rails/lib/install/templates/web/actions.js index 422e6a90..aff6aa1d 100644 --- a/superglue_rails/lib/install/templates/web/actions.js +++ b/superglue_rails/lib/install/templates/web/actions.js @@ -1,3 +1,6 @@ -// Example: -// -// export const CLEAR_FORM_ERRORS = 'CLEAR_FORM_ERRORS' +import { createAction } from '@reduxjs/toolkit' +import { SAVE_RESPONSE, BEFORE_VISIT, UPDATE_FRAGMENTS } from '@thoughtbot/superglue' + +export const saveResponse = createAction(SAVE_RESPONSE) +export const beforeVisit = createAction(BEFORE_VISIT) +export const updateFragments = createAction(UPDATE_FRAGMENTS) diff --git a/superglue_rails/lib/install/templates/web/application.js b/superglue_rails/lib/install/templates/web/application.js index 6ee07bb2..fbfb90ae 100644 --- a/superglue_rails/lib/install/templates/web/application.js +++ b/superglue_rails/lib/install/templates/web/application.js @@ -1,13 +1,11 @@ import React from 'react'; -import { combineReducers, createStore, applyMiddleware, compose } from 'redux'; -import reduceReducers from 'reduce-reducers'; import thunk from 'redux-thunk'; import { Provider } from 'react-redux'; -import { render } from 'react-dom'; -import { ApplicationBase, fragmentMiddleware } from '@thoughtbot/superglue'; -import { applicationRootReducer, applicationPagesReducer } from './reducer'; +import { createRoot } from 'react-dom/client'; +import { ApplicationBase } from '@thoughtbot/superglue'; import { buildVisitAndRemote } from './application_visit'; import { pageIdentifierToPageComponent } from './page_to_page_mapping'; +import { buildStore } from './store' class Application extends ApplicationBase { mapping() { @@ -18,27 +16,8 @@ class Application extends ApplicationBase { return buildVisitAndRemote(navRef, store); } - buildStore(initialState, { superglue: superglueReducer, pages: pagesReducer }) { - // Create the store - // See `./reducer.js` for an explaination of the two included reducers - const composeEnhancers = - (this.hasWindow && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || - compose; - const reducer = reduceReducers( - combineReducers({ - superglue: superglueReducer, - pages: reduceReducers(pagesReducer, applicationPagesReducer), - }), - applicationRootReducer - ); - - const store = createStore( - reducer, - initialState, - composeEnhancers(applyMiddleware(thunk, fragmentMiddleware)) - ); - - return store; + buildStore(initialState, { superglue, pages}) { + return buildStore(initialState, superglue, pages); } } @@ -48,7 +27,8 @@ if (typeof window !== "undefined") { const location = window.location; if (appEl) { - render( + const root = createRoot(appEl); + root.render(