feat(Flash): Get flash messages on load
This commit is contained in:
@ -4,8 +4,8 @@ import { CloseButton } from 'react-bootstrap';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import ns from './ns.json';
|
||||
import { alertTypes } from './redux/utils.js';
|
||||
import {
|
||||
alertTypes,
|
||||
latestMessageSelector,
|
||||
clickOnClose
|
||||
} from './redux';
|
||||
|
17
common/app/Flash/redux/get-messages-epic.js
Normal file
17
common/app/Flash/redux/get-messages-epic.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { Observable } from 'rx';
|
||||
import { ofType } from 'redux-epic';
|
||||
|
||||
import {
|
||||
fetchMessagesComplete,
|
||||
fetchMessagesError
|
||||
} from './';
|
||||
import { types as app } from '../../redux';
|
||||
import { getJSON$ } from '../../../utils/ajax-stream.js';
|
||||
|
||||
export default function getMessagesEpic(actions) {
|
||||
return actions::ofType(app.appMounted)
|
||||
.flatMap(() => getJSON$('/api/users/get-messages')
|
||||
.map(fetchMessagesComplete)
|
||||
.catch(err => Observable.of(fetchMessagesError(err)))
|
||||
);
|
||||
}
|
@ -2,45 +2,25 @@ import _ from 'lodash/fp';
|
||||
import {
|
||||
createTypes,
|
||||
createAction,
|
||||
createAsyncTypes,
|
||||
composeReducers,
|
||||
handleActions
|
||||
} from 'berkeleys-redux-utils';
|
||||
|
||||
import * as utils from './utils.js';
|
||||
import getMessagesEpic from './get-messages-epic.js';
|
||||
import ns from '../ns.json';
|
||||
|
||||
export const alertTypes = _.keyBy(_.identity)([
|
||||
'success',
|
||||
'info',
|
||||
'warning',
|
||||
'danger'
|
||||
]);
|
||||
export const normalizeAlertType = alertType => alertTypes[alertType] || 'info';
|
||||
|
||||
export const getFlashAction = _.flow(
|
||||
_.property('meta'),
|
||||
_.property('flash')
|
||||
);
|
||||
|
||||
export const isFlashAction = _.flow(
|
||||
getFlashAction,
|
||||
Boolean
|
||||
);
|
||||
|
||||
export const epics = [getMessagesEpic];
|
||||
export const types = createTypes([
|
||||
'clickOnClose',
|
||||
'messagesFoundOnBoot'
|
||||
'messagesFoundOnBoot',
|
||||
createAsyncTypes('fetchMessages')
|
||||
], ns);
|
||||
|
||||
export const clickOnClose = createAction(types.clickOnClose, _.noop);
|
||||
export const messagesFoundOnBoot = createAction(types.messagesFoundOnBoot);
|
||||
|
||||
export const expressToStack = _.flow(
|
||||
_.toPairs,
|
||||
_.flatMap(([ type, messages ]) => messages.map(({ msg }) => ({
|
||||
message: msg,
|
||||
alertType: normalizeAlertType(type)
|
||||
})))
|
||||
);
|
||||
export const fetchMessagesComplete = createAction(types.fetchMessages.complete);
|
||||
export const fetchMessagesError = createAction(types.fetchMessages.error);
|
||||
|
||||
const defaultState = [];
|
||||
|
||||
@ -57,20 +37,20 @@ export default composeReducers(
|
||||
handleActions(
|
||||
() => ({
|
||||
[types.clickOnClose]: _.tail,
|
||||
[types.messagesFoundOnBoot]: (state, { payload }) => [
|
||||
[types.fetchMessages.complete]: (state, { payload }) => [
|
||||
...state,
|
||||
...expressToStack(payload)
|
||||
...utils.expressToStack(payload)
|
||||
]
|
||||
}),
|
||||
defaultState,
|
||||
),
|
||||
function metaReducer(state = defaultState, action) {
|
||||
if (isFlashAction(action)) {
|
||||
const { payload: { alertType, message } } = getFlashAction(action);
|
||||
if (utils.isFlashAction(action)) {
|
||||
const { payload: { alertType, message } } = utils.getFlashAction(action);
|
||||
return [
|
||||
...state,
|
||||
{
|
||||
alertType: normalizeAlertType(alertType),
|
||||
alertType: utils.normalizeAlertType(alertType),
|
||||
message: _.escape(message)
|
||||
}
|
||||
];
|
||||
|
29
common/app/Flash/redux/utils.js
Normal file
29
common/app/Flash/redux/utils.js
Normal file
@ -0,0 +1,29 @@
|
||||
import _ from 'lodash/fp';
|
||||
|
||||
export const alertTypes = _.keyBy(_.identity)([
|
||||
'success',
|
||||
'info',
|
||||
'warning',
|
||||
'danger'
|
||||
]);
|
||||
|
||||
export const normalizeAlertType = alertType => alertTypes[alertType] || 'info';
|
||||
|
||||
export const getFlashAction = _.flow(
|
||||
_.property('meta'),
|
||||
_.property('flash')
|
||||
);
|
||||
|
||||
export const isFlashAction = _.flow(
|
||||
getFlashAction,
|
||||
Boolean
|
||||
);
|
||||
|
||||
export const expressToStack = _.flow(
|
||||
_.toPairs,
|
||||
_.flatMap(([ type, messages ]) => messages.map(({ msg }) => ({
|
||||
message: msg,
|
||||
alertType: normalizeAlertType(type)
|
||||
})))
|
||||
);
|
||||
|
@ -1,15 +1,17 @@
|
||||
import { epics as app } from './redux';
|
||||
import { epics as challenge } from './routes/Challenges/redux';
|
||||
import { epics as settings } from './routes/Settings/redux';
|
||||
import { epics as nav } from './Nav/redux';
|
||||
import { epics as flash } from './Flash/redux';
|
||||
import { epics as map } from './Map/redux';
|
||||
import { epics as nav } from './Nav/redux';
|
||||
import { epics as panes } from './Panes/redux';
|
||||
import { epics as settings } from './routes/Settings/redux';
|
||||
|
||||
export default [
|
||||
...app,
|
||||
...challenge,
|
||||
...settings,
|
||||
...nav,
|
||||
...flash,
|
||||
...map,
|
||||
...panes
|
||||
...nav,
|
||||
...panes,
|
||||
...settings
|
||||
];
|
||||
|
@ -776,9 +776,7 @@ module.exports = function(User) {
|
||||
});
|
||||
};
|
||||
|
||||
User.getMessages = function getMessages(messages) {
|
||||
return Promise.resolve(messages);
|
||||
};
|
||||
User.getMessages = messages => Promise.resolve(messages);
|
||||
|
||||
User.remoteMethod('getMessages', {
|
||||
http: {
|
||||
@ -788,11 +786,7 @@ module.exports = function(User) {
|
||||
accepts: {
|
||||
arg: 'messages',
|
||||
type: 'object',
|
||||
http: ctx => {
|
||||
const messages = ctx.req.flash();
|
||||
console.log('messages: ', messages);
|
||||
return messages;
|
||||
}
|
||||
http: ctx => ctx.req.flash()
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
|
@ -9,7 +9,10 @@ export default function sessionsMiddleware() {
|
||||
return session({
|
||||
// 900 day session cookie
|
||||
cookie: { maxAge: 900 * 24 * 60 * 60 * 1000 },
|
||||
resave: true,
|
||||
// resave forces session to be resaved
|
||||
// regardless of whether it was modified
|
||||
// this causes race conditions during parallel req
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
secret: sessionSecret,
|
||||
store: new MongoStore({ url })
|
||||
|
Reference in New Issue
Block a user