18972: Records the last refresh click on localStorage for others to act on.
[arvados-workbench2.git] / src / store / store.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { createStore, applyMiddleware, compose, Middleware, combineReducers, Store, Action, Dispatch } from 'redux';
6 import { routerMiddleware, routerReducer } from "react-router-redux";
7 import thunkMiddleware from 'redux-thunk';
8 import { History } from "history";
9 import { handleRedirects } from '../common/redirect-to';
10
11 import { authReducer } from "./auth/auth-reducer";
12 import { authMiddleware } from "./auth/auth-middleware";
13 import { dataExplorerReducer } from './data-explorer/data-explorer-reducer';
14 import { detailsPanelReducer } from './details-panel/details-panel-reducer';
15 import { contextMenuReducer } from './context-menu/context-menu-reducer';
16 import { reducer as formReducer } from 'redux-form';
17 import { favoritesReducer } from './favorites/favorites-reducer';
18 import { snackbarReducer } from './snackbar/snackbar-reducer';
19 import { collectionPanelFilesReducer } from './collection-panel/collection-panel-files/collection-panel-files-reducer';
20 import { dataExplorerMiddleware } from "./data-explorer/data-explorer-middleware";
21 import { FAVORITE_PANEL_ID } from "./favorite-panel/favorite-panel-action";
22 import { PROJECT_PANEL_ID } from "./project-panel/project-panel-action";
23 import { ProjectPanelMiddlewareService } from "./project-panel/project-panel-middleware-service";
24 import { FavoritePanelMiddlewareService } from "./favorite-panel/favorite-panel-middleware-service";
25 import { AllProcessesPanelMiddlewareService } from "./all-processes-panel/all-processes-panel-middleware-service";
26 import { collectionPanelReducer } from './collection-panel/collection-panel-reducer';
27 import { dialogReducer } from './dialog/dialog-reducer';
28 import { ServiceRepository } from "services/services";
29 import { treePickerReducer } from './tree-picker/tree-picker-reducer';
30 import { resourcesReducer } from 'store/resources/resources-reducer';
31 import { propertiesReducer } from './properties/properties-reducer';
32 import { fileUploaderReducer } from './file-uploader/file-uploader-reducer';
33 import { TrashPanelMiddlewareService } from "store/trash-panel/trash-panel-middleware-service";
34 import { TRASH_PANEL_ID } from "store/trash-panel/trash-panel-action";
35 import { processLogsPanelReducer } from './process-logs-panel/process-logs-panel-reducer';
36 import { processPanelReducer } from 'store/process-panel/process-panel-reducer';
37 import { SHARED_WITH_ME_PANEL_ID } from 'store/shared-with-me-panel/shared-with-me-panel-actions';
38 import { SharedWithMeMiddlewareService } from './shared-with-me-panel/shared-with-me-middleware-service';
39 import { progressIndicatorReducer } from './progress-indicator/progress-indicator-reducer';
40 import { runProcessPanelReducer } from 'store/run-process-panel/run-process-panel-reducer';
41 import { WorkflowMiddlewareService } from './workflow-panel/workflow-middleware-service';
42 import { WORKFLOW_PANEL_ID } from './workflow-panel/workflow-panel-actions';
43 import { appInfoReducer } from 'store/app-info/app-info-reducer';
44 import { searchBarReducer } from './search-bar/search-bar-reducer';
45 import { SEARCH_RESULTS_PANEL_ID } from 'store/search-results-panel/search-results-panel-actions';
46 import { SearchResultsMiddlewareService } from './search-results-panel/search-results-middleware-service';
47 import { virtualMachinesReducer } from "store/virtual-machines/virtual-machines-reducer";
48 import { repositoriesReducer } from 'store/repositories/repositories-reducer';
49 import { keepServicesReducer } from 'store/keep-services/keep-services-reducer';
50 import { UserMiddlewareService } from 'store/users/user-panel-middleware-service';
51 import { USERS_PANEL_ID } from 'store/users/users-actions';
52 import { UserProfileGroupsMiddlewareService } from 'store/user-profile/user-profile-groups-middleware-service';
53 import { USER_PROFILE_PANEL_ID } from 'store/user-profile/user-profile-actions'
54 import { GroupsPanelMiddlewareService } from 'store/groups-panel/groups-panel-middleware-service';
55 import { GROUPS_PANEL_ID } from 'store/groups-panel/groups-panel-actions';
56 import { GroupDetailsPanelMembersMiddlewareService } from 'store/group-details-panel/group-details-panel-members-middleware-service';
57 import { GroupDetailsPanelPermissionsMiddlewareService } from 'store/group-details-panel/group-details-panel-permissions-middleware-service';
58 import { GROUP_DETAILS_MEMBERS_PANEL_ID, GROUP_DETAILS_PERMISSIONS_PANEL_ID } from 'store/group-details-panel/group-details-panel-actions';
59 import { LINK_PANEL_ID } from 'store/link-panel/link-panel-actions';
60 import { LinkMiddlewareService } from 'store/link-panel/link-panel-middleware-service';
61 import { API_CLIENT_AUTHORIZATION_PANEL_ID } from 'store/api-client-authorizations/api-client-authorizations-actions';
62 import { ApiClientAuthorizationMiddlewareService } from 'store/api-client-authorizations/api-client-authorizations-middleware-service';
63 import { PublicFavoritesMiddlewareService } from 'store/public-favorites-panel/public-favorites-middleware-service';
64 import { PUBLIC_FAVORITE_PANEL_ID } from 'store/public-favorites-panel/public-favorites-action';
65 import { publicFavoritesReducer } from 'store/public-favorites/public-favorites-reducer';
66 import { linkAccountPanelReducer } from './link-account-panel/link-account-panel-reducer';
67 import { CollectionsWithSameContentAddressMiddlewareService } from 'store/collections-content-address-panel/collections-content-address-middleware-service';
68 import { COLLECTIONS_CONTENT_ADDRESS_PANEL_ID } from 'store/collections-content-address-panel/collections-content-address-panel-actions';
69 import { ownerNameReducer } from 'store/owner-name/owner-name-reducer';
70 import { SubprocessMiddlewareService } from 'store/subprocess-panel/subprocess-panel-middleware-service';
71 import { SUBPROCESS_PANEL_ID } from 'store/subprocess-panel/subprocess-panel-actions';
72 import { ALL_PROCESSES_PANEL_ID } from './all-processes-panel/all-processes-panel-action';
73 import { Config } from 'common/config';
74 import { pluginConfig } from 'plugins';
75 import { MiddlewareListReducer } from 'common/plugintypes';
76
77 declare global {
78     interface Window {
79       __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
80     }
81 }
82
83 const composeEnhancers =
84     (process.env.NODE_ENV === 'development' &&
85         window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
86     compose;
87
88 export type RootState = ReturnType<ReturnType<typeof createRootReducer>>;
89
90 export type RootStore = Store<RootState, Action> & { dispatch: Dispatch<any> };
91
92 export function configureStore(history: History, services: ServiceRepository, config: Config): RootStore {
93     const rootReducer = createRootReducer(services);
94
95     const projectPanelMiddleware = dataExplorerMiddleware(
96         new ProjectPanelMiddlewareService(services, PROJECT_PANEL_ID)
97     );
98     const favoritePanelMiddleware = dataExplorerMiddleware(
99         new FavoritePanelMiddlewareService(services, FAVORITE_PANEL_ID)
100     );
101     const allProcessessPanelMiddleware = dataExplorerMiddleware(
102         new AllProcessesPanelMiddlewareService(services, ALL_PROCESSES_PANEL_ID)
103     );
104     const trashPanelMiddleware = dataExplorerMiddleware(
105         new TrashPanelMiddlewareService(services, TRASH_PANEL_ID)
106     );
107     const searchResultsPanelMiddleware = dataExplorerMiddleware(
108         new SearchResultsMiddlewareService(services, SEARCH_RESULTS_PANEL_ID)
109     );
110     const sharedWithMePanelMiddleware = dataExplorerMiddleware(
111         new SharedWithMeMiddlewareService(services, SHARED_WITH_ME_PANEL_ID)
112     );
113     const workflowPanelMiddleware = dataExplorerMiddleware(
114         new WorkflowMiddlewareService(services, WORKFLOW_PANEL_ID)
115     );
116     const userPanelMiddleware = dataExplorerMiddleware(
117         new UserMiddlewareService(services, USERS_PANEL_ID)
118     );
119     const userProfileGroupsMiddleware = dataExplorerMiddleware(
120         new UserProfileGroupsMiddlewareService(services, USER_PROFILE_PANEL_ID)
121     );
122     const groupsPanelMiddleware = dataExplorerMiddleware(
123         new GroupsPanelMiddlewareService(services, GROUPS_PANEL_ID)
124     );
125     const groupDetailsPanelMembersMiddleware = dataExplorerMiddleware(
126         new GroupDetailsPanelMembersMiddlewareService(services, GROUP_DETAILS_MEMBERS_PANEL_ID)
127     );
128     const groupDetailsPanelPermissionsMiddleware = dataExplorerMiddleware(
129         new GroupDetailsPanelPermissionsMiddlewareService(services, GROUP_DETAILS_PERMISSIONS_PANEL_ID)
130     );
131     const linkPanelMiddleware = dataExplorerMiddleware(
132         new LinkMiddlewareService(services, LINK_PANEL_ID)
133     );
134     const apiClientAuthorizationMiddlewareService = dataExplorerMiddleware(
135         new ApiClientAuthorizationMiddlewareService(services, API_CLIENT_AUTHORIZATION_PANEL_ID)
136     );
137     const publicFavoritesMiddleware = dataExplorerMiddleware(
138         new PublicFavoritesMiddlewareService(services, PUBLIC_FAVORITE_PANEL_ID)
139     );
140     const collectionsContentAddress = dataExplorerMiddleware(
141         new CollectionsWithSameContentAddressMiddlewareService(services, COLLECTIONS_CONTENT_ADDRESS_PANEL_ID)
142     );
143     const subprocessMiddleware = dataExplorerMiddleware(
144         new SubprocessMiddlewareService(services, SUBPROCESS_PANEL_ID)
145     );
146     const redirectToMiddleware = (store: any) => (next: any) => (action: any) => {
147         const state = store.getState();
148
149         if (state.auth && state.auth.apiToken) {
150             handleRedirects(state.auth.apiToken, config);
151         }
152
153         return next(action);
154     };
155
156     let middlewares: Middleware[] = [
157         routerMiddleware(history),
158         thunkMiddleware.withExtraArgument(services),
159         authMiddleware(services),
160         projectPanelMiddleware,
161         favoritePanelMiddleware,
162         allProcessessPanelMiddleware,
163         trashPanelMiddleware,
164         searchResultsPanelMiddleware,
165         sharedWithMePanelMiddleware,
166         workflowPanelMiddleware,
167         userPanelMiddleware,
168         userProfileGroupsMiddleware,
169         groupsPanelMiddleware,
170         groupDetailsPanelMembersMiddleware,
171         groupDetailsPanelPermissionsMiddleware,
172         linkPanelMiddleware,
173         apiClientAuthorizationMiddlewareService,
174         publicFavoritesMiddleware,
175         collectionsContentAddress,
176         subprocessMiddleware,
177     ];
178
179     const reduceMiddlewaresFn: (a: Middleware[],
180         b: MiddlewareListReducer) => Middleware[] = (a, b) => b(a, services);
181
182     middlewares = pluginConfig.middlewares.reduce(reduceMiddlewaresFn, middlewares);
183
184     const enhancer = composeEnhancers(applyMiddleware(redirectToMiddleware, ...middlewares));
185     return createStore(rootReducer, enhancer);
186 }
187
188 const createRootReducer = (services: ServiceRepository) => combineReducers({
189     auth: authReducer(services),
190     collectionPanel: collectionPanelReducer,
191     collectionPanelFiles: collectionPanelFilesReducer,
192     contextMenu: contextMenuReducer,
193     dataExplorer: dataExplorerReducer,
194     detailsPanel: detailsPanelReducer,
195     dialog: dialogReducer,
196     favorites: favoritesReducer,
197     ownerName: ownerNameReducer,
198     publicFavorites: publicFavoritesReducer,
199     form: formReducer,
200     processLogsPanel: processLogsPanelReducer,
201     properties: propertiesReducer,
202     resources: resourcesReducer,
203     router: routerReducer,
204     snackbar: snackbarReducer,
205     treePicker: treePickerReducer,
206     fileUploader: fileUploaderReducer,
207     processPanel: processPanelReducer,
208     progressIndicator: progressIndicatorReducer,
209     runProcessPanel: runProcessPanelReducer,
210     appInfo: appInfoReducer,
211     searchBar: searchBarReducer,
212     virtualMachines: virtualMachinesReducer,
213     repositories: repositoriesReducer,
214     keepServices: keepServicesReducer,
215     linkAccountPanel: linkAccountPanelReducer
216 });