github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/redux/store.ts (about) 1 import { 2 persistStore, 3 persistReducer, 4 FLUSH, 5 REHYDRATE, 6 PAUSE, 7 PERSIST, 8 PURGE, 9 REGISTER, 10 } from 'redux-persist'; 11 12 // eslint-disable-next-line @typescript-eslint/ban-ts-comment 13 // @ts-ignore: Until we rewrite FlamegraphRenderer in typescript this will do 14 import ReduxQuerySync from 'redux-query-sync'; 15 import { configureStore, combineReducers, Middleware } from '@reduxjs/toolkit'; 16 17 import history from '../util/history'; 18 19 import settingsReducer from './reducers/settings'; 20 import userReducer from './reducers/user'; 21 import continuousReducer, { 22 actions as continuousActions, 23 } from './reducers/continuous'; 24 import tracingReducer, { actions as tracingActions } from './reducers/tracing'; 25 import serviceDiscoveryReducer from './reducers/serviceDiscovery'; 26 import adhocReducer from './reducers/adhoc'; 27 import uiStore, { persistConfig as uiPersistConfig } from './reducers/ui'; 28 29 const reducer = combineReducers({ 30 settings: settingsReducer, 31 user: userReducer, 32 serviceDiscovery: serviceDiscoveryReducer, 33 ui: persistReducer(uiPersistConfig, uiStore), 34 continuous: continuousReducer, 35 tracing: tracingReducer, 36 adhoc: adhocReducer, 37 }); 38 39 // Most times we will display a (somewhat) user friendly message toast 40 // But it's still useful to have the actual error logged to the console 41 export const logErrorMiddleware: Middleware = () => (next) => (action) => { 42 next(action); 43 if (action?.error) { 44 console.error(action.error); 45 } 46 }; 47 48 const store = configureStore({ 49 reducer, 50 // https://github.com/reduxjs/redux-toolkit/issues/587#issuecomment-824927971 51 middleware: (getDefaultMiddleware) => 52 getDefaultMiddleware({ 53 serializableCheck: { 54 ignoredActionPaths: ['error'], 55 56 // Based on this issue: https://github.com/rt2zz/redux-persist/issues/988 57 // and this guide https://redux-toolkit.js.org/usage/usage-guide#use-with-redux-persist 58 ignoredActions: [ 59 FLUSH, 60 REHYDRATE, 61 PAUSE, 62 PERSIST, 63 PURGE, 64 REGISTER, 65 'adhoc/uploadFile/pending', 66 'adhoc/uploadFile/fulfilled', 67 ], 68 }, 69 }).concat([logErrorMiddleware]), 70 }); 71 72 export const persistor = persistStore(store); 73 74 // This is a bi-directional sync between the query parameters and the redux store 75 // It works as follows: 76 // * When URL query changes, It will dispatch the action 77 // * When the store changes (the field set in selector), the query param is updated 78 // For more info see the implementation at 79 // https://github.com/Treora/redux-query-sync/blob/master/src/redux-query-sync.js 80 ReduxQuerySync({ 81 store, 82 params: { 83 from: { 84 defaultValue: 'now-1h', 85 selector: (state: RootState) => state.continuous.from, 86 action: continuousActions.setFrom, 87 }, 88 until: { 89 defaultValue: 'now', 90 selector: (state: RootState) => state.continuous.until, 91 action: continuousActions.setUntil, 92 }, 93 leftFrom: { 94 defaultValue: 'now-1h', 95 selector: (state: RootState) => state.continuous.leftFrom, 96 action: continuousActions.setLeftFrom, 97 }, 98 leftUntil: { 99 defaultValue: 'now-30m', 100 selector: (state: RootState) => state.continuous.leftUntil, 101 action: continuousActions.setLeftUntil, 102 }, 103 rightFrom: { 104 defaultValue: 'now-30m', 105 selector: (state: RootState) => state.continuous.rightFrom, 106 action: continuousActions.setRightFrom, 107 }, 108 rightUntil: { 109 defaultValue: 'now', 110 selector: (state: RootState) => state.continuous.rightUntil, 111 action: continuousActions.setRightUntil, 112 }, 113 query: { 114 defaultvalue: '', 115 selector: (state: RootState) => state.continuous.query, 116 action: continuousActions.setQuery, 117 }, 118 queryID: { 119 defaultvalue: '', 120 selector: (state: RootState) => state.tracing.queryID, 121 action: tracingActions.setQueryID, 122 }, 123 rightQuery: { 124 defaultvalue: '', 125 selector: (state: RootState) => state.continuous.rightQuery, 126 action: continuousActions.setRightQuery, 127 }, 128 leftQuery: { 129 defaultvalue: '', 130 selector: (state: RootState) => state.continuous.leftQuery, 131 action: continuousActions.setLeftQuery, 132 }, 133 maxNodes: { 134 defaultValue: '0', 135 selector: (state: RootState) => state.continuous.maxNodes, 136 action: continuousActions.setMaxNodes, 137 }, 138 groupBy: { 139 defaultValue: '', 140 selector: (state: RootState) => 141 state.continuous.tagExplorerView.groupByTag, 142 action: continuousActions.setTagExplorerViewGroupByTag, 143 }, 144 groupByValue: { 145 defaultValue: '', 146 selector: (state: RootState) => 147 state.continuous.tagExplorerView.groupByTagValue, 148 action: continuousActions.setTagExplorerViewGroupByTagValue, 149 }, 150 }, 151 initialTruth: 'location', 152 replaceState: false, 153 history, 154 }); 155 export default store; 156 157 // Infer the `RootState` and `AppDispatch` types from the store itself 158 export type RootState = ReturnType<typeof store.getState>; 159 // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} 160 export type AppDispatch = typeof store.dispatch;