21764: Add more type safety to TreePicker
[arvados.git] / services / workbench2 / src / store / data-explorer / data-explorer-middleware.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { Dispatch } from 'redux';
6 import { RootState } from 'store/store';
7 import { ServiceRepository } from 'services/services';
8 import { Middleware } from 'redux';
9 import {
10     dataExplorerActions,
11     bindDataExplorerActions,
12     DataTableRequestState,
13 } from './data-explorer-action';
14 import { getDataExplorer } from './data-explorer-reducer';
15 import { DataExplorerMiddlewareService } from './data-explorer-middleware-service';
16
17 export const dataExplorerMiddleware =
18     (service: DataExplorerMiddlewareService): Middleware =>
19         (api) =>
20             (next) => {
21                 const actions = bindDataExplorerActions(service.getId());
22
23                 return (action) => {
24                     const handleAction =
25                         <T extends { id: string }>(handler: (data: T) => void) =>
26                             (data: T) => {
27                                 next(action);
28                                 if (data.id === service.getId()) {
29                                     handler(data);
30                                 }
31                             };
32                     dataExplorerActions.match(action, {
33                         SET_PAGE: handleAction(() => {
34                             api.dispatch(actions.REQUEST_ITEMS(false));
35                         }),
36                         SET_ROWS_PER_PAGE: handleAction(() => {
37                             api.dispatch(actions.REQUEST_ITEMS(true));
38                         }),
39                         SET_FILTERS: handleAction(() => {
40                             api.dispatch(actions.RESET_PAGINATION());
41                             api.dispatch(actions.REQUEST_ITEMS(true));
42                         }),
43                         TOGGLE_SORT: handleAction(() => {
44                             api.dispatch(actions.REQUEST_ITEMS(true));
45                         }),
46                         SET_EXPLORER_SEARCH_VALUE: handleAction(() => {
47                             api.dispatch(actions.RESET_PAGINATION());
48                             api.dispatch(actions.REQUEST_ITEMS(true));
49                         }),
50                         REQUEST_ITEMS: handleAction(({ criteriaChanged, background }) => {
51                             api.dispatch<any>(async (
52                                 dispatch: Dispatch,
53                                 getState: () => RootState,
54                                 services: ServiceRepository
55                             ) => {
56                                 while (true) {
57                                     let de = getDataExplorer(
58                                         getState().dataExplorer,
59                                         service.getId()
60                                     );
61                                     switch (de.requestState) {
62                                         case DataTableRequestState.IDLE:
63                                             // Start a new request.
64                                             try {
65                                                 dispatch(
66                                                     actions.SET_REQUEST_STATE({
67                                                         requestState: DataTableRequestState.PENDING,
68                                                     })
69                                                 );
70                                                 await service.requestItems(api, criteriaChanged, background);
71                                             } catch {
72                                                 dispatch(
73                                                     actions.SET_REQUEST_STATE({
74                                                         requestState: DataTableRequestState.NEED_REFRESH,
75                                                     })
76                                                 );
77                                             }
78                                             // Now check if the state is still PENDING, if it moved to NEED_REFRESH
79                                             // then we need to reissue requestItems
80                                             de = getDataExplorer(
81                                                 getState().dataExplorer,
82                                                 service.getId()
83                                             );
84                                             const complete =
85                                                 de.requestState === DataTableRequestState.PENDING;
86                                             dispatch(
87                                                 actions.SET_REQUEST_STATE({
88                                                     requestState: DataTableRequestState.IDLE,
89                                                 })
90                                             );
91                                             if (complete) {
92                                                 return;
93                                             }
94                                             break;
95                                         case DataTableRequestState.PENDING:
96                                             // State is PENDING, move it to NEED_REFRESH so that when the current request finishes it starts a new one.
97                                             dispatch(
98                                                 actions.SET_REQUEST_STATE({
99                                                     requestState: DataTableRequestState.NEED_REFRESH,
100                                                 })
101                                             );
102                                             return;
103                                         case DataTableRequestState.NEED_REFRESH:
104                                             // Nothing to do right now.
105                                             return;
106                                     }
107                                 }
108                             });
109                         }),
110                         default: () => next(action),
111                     });
112                 };
113             };