e1f4ef2a7bb6068d1cc0462e0f7a2335408271c0
[arvados-workbench2.git] / src / store / data-explorer / data-explorer-reducer.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import {
6   DataColumn,
7   resetSortDirection,
8   SortDirection,
9   toggleSortDirection,
10 } from 'components/data-table/data-column';
11 import {
12   DataExplorerAction,
13   dataExplorerActions,
14   DataTableRequestState,
15 } from './data-explorer-action';
16 import {
17   DataColumns,
18   DataTableFetchMode,
19 } from 'components/data-table/data-table';
20 import { DataTableFilters } from 'components/data-table-filters/data-table-filters-tree';
21
22 export interface DataExplorer {
23   fetchMode: DataTableFetchMode;
24   columns: DataColumns<any>;
25   items: any[];
26   itemsAvailable: number;
27   page: number;
28   rowsPerPage: number;
29   rowsPerPageOptions: number[];
30   searchValue: string;
31   working?: boolean;
32   requestState: DataTableRequestState;
33 }
34
35 export const initialDataExplorer: DataExplorer = {
36   fetchMode: DataTableFetchMode.PAGINATED,
37   columns: [],
38   items: [],
39   itemsAvailable: 0,
40   page: 0,
41   rowsPerPage: 50,
42   rowsPerPageOptions: [10, 20, 50, 100, 200, 500],
43   searchValue: '',
44   requestState: DataTableRequestState.IDLE,
45 };
46
47 export type DataExplorerState = Record<string, DataExplorer>;
48
49 export const dataExplorerReducer = (
50   state: DataExplorerState = {},
51   action: DataExplorerAction
52 ) => {
53   //   console.log('DATA_EXPLORERE_REDUCER, satate:', state);
54   return dataExplorerActions.match(action, {
55     CLEAR: ({ id }) =>
56       update(state, id, (explorer) => ({
57         ...explorer,
58         page: 0,
59         itemsAvailable: 0,
60         items: [],
61       })),
62
63     RESET_PAGINATION: ({ id }) =>
64       update(state, id, (explorer) => ({ ...explorer, page: 0 })),
65
66     SET_FETCH_MODE: ({ id, fetchMode }) =>
67       update(state, id, (explorer) => ({ ...explorer, fetchMode })),
68
69     SET_COLUMNS: ({ id, columns }) => update(state, id, setColumns(columns)),
70
71     SET_FILTERS: ({ id, columnName, filters }) =>
72       update(state, id, mapColumns(setFilters(columnName, filters))),
73
74     SET_ITEMS: ({ id, items, itemsAvailable, page, rowsPerPage }) =>
75       update(state, id, (explorer) => ({
76         ...explorer,
77         items,
78         itemsAvailable,
79         page: page || 0,
80         rowsPerPage,
81       })),
82
83     APPEND_ITEMS: ({ id, items, itemsAvailable, page, rowsPerPage }) =>
84       update(state, id, (explorer) => ({
85         ...explorer,
86         items: state[id].items.concat(items),
87         itemsAvailable: state[id].itemsAvailable + itemsAvailable,
88         page,
89         rowsPerPage,
90       })),
91
92     SET_PAGE: ({ id, page }) =>
93       update(state, id, (explorer) => ({ ...explorer, page })),
94
95     SET_ROWS_PER_PAGE: ({ id, rowsPerPage }) =>
96       update(state, id, (explorer) => ({ ...explorer, rowsPerPage })),
97
98     SET_EXPLORER_SEARCH_VALUE: ({ id, searchValue }) =>
99       update(state, id, (explorer) => ({ ...explorer, searchValue })),
100
101     SET_REQUEST_STATE: ({ id, requestState }) =>
102       update(state, id, (explorer) => ({ ...explorer, requestState })),
103
104     TOGGLE_SORT: ({ id, columnName }) =>
105       update(state, id, mapColumns(toggleSort(columnName))),
106
107     TOGGLE_COLUMN: ({ id, columnName }) =>
108       update(state, id, mapColumns(toggleColumn(columnName))),
109
110     default: () => state,
111   });
112 };
113 export const getDataExplorer = (state: DataExplorerState, id: string) => {
114   const returnValue = state[id] || initialDataExplorer;
115   //lisa
116   //   console.log('GETDATAEXPLORER RETURN:', state[id]);
117   return returnValue;
118 };
119
120 export const getSortColumn = (dataExplorer: DataExplorer) =>
121   dataExplorer.columns.find(
122     (c: any) => !!c.sortDirection && c.sortDirection !== SortDirection.NONE
123   );
124
125 const update = (
126   state: DataExplorerState,
127   id: string,
128   updateFn: (dataExplorer: DataExplorer) => DataExplorer
129 ) => ({ ...state, [id]: updateFn(getDataExplorer(state, id)) });
130
131 const canUpdateColumns = (
132   prevColumns: DataColumns<any>,
133   nextColumns: DataColumns<any>
134 ) => {
135   if (prevColumns.length !== nextColumns.length) {
136     return true;
137   }
138   for (let i = 0; i < nextColumns.length; i++) {
139     const pc = prevColumns[i];
140     const nc = nextColumns[i];
141     if (pc.key !== nc.key || pc.name !== nc.name) {
142       return true;
143     }
144   }
145   return false;
146 };
147
148 const setColumns =
149   (columns: DataColumns<any>) => (dataExplorer: DataExplorer) => ({
150     ...dataExplorer,
151     columns: canUpdateColumns(dataExplorer.columns, columns)
152       ? columns
153       : dataExplorer.columns,
154   });
155
156 const mapColumns =
157   (mapFn: (column: DataColumn<any>) => DataColumn<any>) =>
158   (dataExplorer: DataExplorer) => ({
159     ...dataExplorer,
160     columns: dataExplorer.columns.map(mapFn),
161   });
162
163 const toggleSort = (columnName: string) => (column: DataColumn<any>) =>
164   column.name === columnName
165     ? toggleSortDirection(column)
166     : resetSortDirection(column);
167
168 const toggleColumn = (columnName: string) => (column: DataColumn<any>) =>
169   column.name === columnName
170     ? { ...column, selected: !column.selected }
171     : column;
172
173 const setFilters =
174   (columnName: string, filters: DataTableFilters) =>
175   (column: DataColumn<any>) =>
176     column.name === columnName ? { ...column, filters } : column;