1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { Dispatch } from 'redux';
6 import { RootState } from 'store/store';
7 import { ServiceRepository } from 'services/services';
8 import { Middleware } from 'redux';
11 bindDataExplorerActions,
12 DataTableRequestState,
13 couldNotFetchItemsAvailable,
14 } from './data-explorer-action';
15 import { getDataExplorer } from './data-explorer-reducer';
16 import { DataExplorerMiddlewareService } from './data-explorer-middleware-service';
18 export const dataExplorerMiddleware =
19 (service: DataExplorerMiddlewareService): Middleware =>
22 const actions = bindDataExplorerActions(service.getId());
26 <T extends { id: string }>(handler: (data: T) => void) =>
29 if (data.id === service.getId()) {
33 dataExplorerActions.match(action, {
34 SET_PAGE: handleAction(() => {
35 api.dispatch(actions.REQUEST_ITEMS(false));
37 SET_ROWS_PER_PAGE: handleAction(() => {
38 api.dispatch(actions.REQUEST_ITEMS(true));
40 SET_FILTERS: handleAction(() => {
41 api.dispatch(actions.RESET_PAGINATION());
42 api.dispatch(actions.SET_LOADING_ITEMS_AVAILABLE(true));
43 api.dispatch(actions.REQUEST_ITEMS(true));
45 TOGGLE_SORT: handleAction(() => {
46 api.dispatch(actions.REQUEST_ITEMS(true));
48 SET_EXPLORER_SEARCH_VALUE: handleAction(() => {
49 api.dispatch(actions.RESET_PAGINATION());
50 api.dispatch(actions.SET_LOADING_ITEMS_AVAILABLE(true));
51 api.dispatch(actions.REQUEST_ITEMS(true));
53 REQUEST_ITEMS: handleAction(({ criteriaChanged = true, background }) => {
54 api.dispatch<any>(async (
56 getState: () => RootState,
57 services: ServiceRepository
60 let de = getDataExplorer(
61 getState().dataExplorer,
64 switch (de.requestState) {
65 case DataTableRequestState.IDLE:
66 // Start a new request.
69 actions.SET_REQUEST_STATE({
70 requestState: DataTableRequestState.PENDING,
75 const result = service.requestItems(api, criteriaChanged, background);
77 // Enable loading indicator on non-background fetches
80 dataExplorerActions.SET_LOADING_ITEMS_AVAILABLE({
82 loadingItemsAvailable: true
88 const count = service.requestCount(api, criteriaChanged, background)
90 // Show error toast if count fetch failed
91 // This catch block also prevents a failed count request
92 // from triggring data explorer load failure / reload
93 couldNotFetchItemsAvailable();
96 // Turn off itemsAvailable loading indicator when done
98 dataExplorerActions.SET_LOADING_ITEMS_AVAILABLE({
100 loadingItemsAvailable: false
105 // Await results and count
106 await Promise.all([result, count]);
110 actions.SET_REQUEST_STATE({
111 requestState: DataTableRequestState.NEED_REFRESH,
115 // Now check if the state is still PENDING, if it moved to NEED_REFRESH
116 // then we need to reissue requestItems
117 de = getDataExplorer(
118 getState().dataExplorer,
122 de.requestState === DataTableRequestState.PENDING;
124 actions.SET_REQUEST_STATE({
125 requestState: DataTableRequestState.IDLE,
132 case DataTableRequestState.PENDING:
133 // State is PENDING, move it to NEED_REFRESH so that when the current request finishes it starts a new one.
135 actions.SET_REQUEST_STATE({
136 requestState: DataTableRequestState.NEED_REFRESH,
140 case DataTableRequestState.NEED_REFRESH:
141 // Nothing to do right now.
147 default: () => next(action),