feat(Flash): Get flash messages on load

This commit is contained in:
Berkeley Martinez
2018-01-12 11:09:09 -08:00
parent 387eafbf33
commit 2bb27e8dc6
7 changed files with 73 additions and 48 deletions

View File

@ -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';

View 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)))
);
}

View File

@ -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)
}
];

View 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)
})))
);

View File

@ -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
];

View File

@ -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: [
{

View File

@ -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 })