From 6c4c706313eb765eb00c639f381646be74f27b69 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Tue, 25 Apr 2017 11:46:02 -0400 Subject: Start moving webapp to Redux (#6140) * Start moving webapp to Redux * Fix localforage import * Updates per feedback * Feedback udpates and a few fixes * Minor updates * Fix statuses, config not loading properly, getMe sanitizing too much * Fix preferences * Fix user autocomplete * Fix sessions and audits * Fix error handling for all redux actions * Use new directory structure for components and containers * Refresh immediately on logout instead of after timeout * Add fetch polyfill --- webapp/store/index.js | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ webapp/store/utils.js | 42 +++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 webapp/store/index.js create mode 100644 webapp/store/utils.js (limited to 'webapp/store') diff --git a/webapp/store/index.js b/webapp/store/index.js new file mode 100644 index 000000000..1af7127e8 --- /dev/null +++ b/webapp/store/index.js @@ -0,0 +1,112 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {batchActions} from 'redux-batched-actions'; +import configureServiceStore from 'mattermost-redux/store'; +import {General, RequestStatus} from 'mattermost-redux/constants'; +import reduxInitialState from 'mattermost-redux/store/initial_state'; +import {createTransform, persistStore} from 'redux-persist'; +import localForage from 'localforage'; + +import {transformSet} from './utils'; + +const usersSetTransform = [ + 'profilesInChannel', + 'profilesNotInChannel', + 'profilesInTeam', + 'profilesNotInTeam' +]; + +const teamSetTransform = [ + 'membersInTeam' +]; + +const setTransforms = [ + ...usersSetTransform, + ...teamSetTransform +]; + +export default function configureStore(initialState) { + const setTransformer = createTransform( + (inboundState, key) => { + if (key === 'entities') { + const state = {...inboundState}; + for (const prop in state) { + if (state.hasOwnProperty(prop)) { + state[prop] = transformSet(state[prop], setTransforms); + } + } + + return state; + } + + return inboundState; + }, + (outboundState, key) => { + if (key === 'entities') { + const state = {...outboundState}; + for (const prop in state) { + if (state.hasOwnProperty(prop)) { + state[prop] = transformSet(state[prop], setTransforms, false); + } + } + + return state; + } + + return outboundState; + } + ); + + const offlineOptions = { + persist: (store, options) => { + const persistor = persistStore(store, {storage: localForage, ...options}, () => { + store.dispatch({ + type: General.STORE_REHYDRATION_COMPLETE, + complete: true + }); + }); + + let purging = false; + + // check to see if the logout request was successful + store.subscribe(() => { + const state = store.getState(); + if (state.requests.users.logout.status === RequestStatus.SUCCESS && !purging) { + purging = true; + + persistor.purge(); + + store.dispatch(batchActions([ + { + type: General.OFFLINE_STORE_RESET, + data: Object.assign({}, reduxInitialState, initialState) + } + ])); + + localStorage.removeItem('currentUserId'); + window.location.href = '/'; + + setTimeout(() => { + purging = false; + }, 500); + } + }); + + return persistor; + }, + persistOptions: { + autoRehydrate: { + log: false + }, + blacklist: ['errors', 'offline', 'requests', 'entities'], + debounce: 500, + transforms: [ + setTransformer + ] + } + }; + + return configureServiceStore({}, {}, offlineOptions); +} + diff --git a/webapp/store/utils.js b/webapp/store/utils.js new file mode 100644 index 000000000..5566f54b8 --- /dev/null +++ b/webapp/store/utils.js @@ -0,0 +1,42 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +function transformFromSet(incoming) { + const state = {...incoming}; + + for (const key in state) { + if (state.hasOwnProperty(key)) { + if (state[key] instanceof Set) { + state[key] = Array.from([...state[key]]); + } + } + } + + return state; +} + +function transformToSet(incoming) { + const state = {...incoming}; + + for (const key in state) { + if (state.hasOwnProperty(key)) { + state[key] = new Set(state[key]); + } + } + + return state; +} + +export function transformSet(incoming, setTransforms, toStorage = true) { + const state = {...incoming}; + + const transformer = toStorage ? transformFromSet : transformToSet; + + for (const key in state) { + if (state.hasOwnProperty(key) && setTransforms.includes(key)) { + state[key] = transformer(state[key]); + } + } + + return state; +} -- cgit v1.2.3-1-g7c22