Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / framework / src / components / material-table / utilities.ts
1 /**
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt odlux
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 import { Action, IActionHandler } from '../../flux/action';
19 import { Dispatch } from '../../flux/store';
20
21 import { AddErrorInfoAction } from '../../actions/errorActions';
22 import { IApplicationStoreState } from '../../store/applicationStore';
23
24 export const RowDisabled = Symbol("RowDisabled");
25 import { DataCallback } from ".";
26
27 export interface IExternalTableState<TData> {
28   order: 'asc' | 'desc';
29   orderBy: string | null;
30   selected: any[] | null;
31   hiddenColumns: string[]
32   rows: (TData & { [RowDisabled]?: boolean })[];
33   total: number;
34   page: number;
35   rowsPerPage: number;
36   loading: boolean;
37   showFilter: boolean;
38   filter: { [property: string]: string };
39   preFilter: { [property: string]: string };
40 }
41
42 export type ExternalMethodes<TData> = {
43   reloadAction: (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => Promise<void | AddErrorInfoAction>;
44   createActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
45     onRefresh: () => void;
46     onHandleRequestSort: (orderBy: string) => void;
47     onHandleExplicitRequestSort: (property: string, sortOrder: "asc" | "desc") => void;
48     onToggleFilter: (refresh?: boolean | undefined) => void;
49     onFilterChanged: (property: string, filterTerm: string) => void;
50     onHandleChangePage: (page: number) => void;
51     onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
52     onHideColumns: (columnName: string[]) => void;
53     onShowColumns: (columnName: string[]) => void;
54     onClearFilters: () => void;
55   },
56  createPreActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
57   onPreFilterChanged: (preFilter: {
58       [key: string]: string;
59   }) => void;
60  };
61  createProperties: (state: IApplicationStoreState) => IExternalTableState<TData>;
62  actionHandler: IActionHandler<IExternalTableState<TData>, Action>;
63 }
64
65
66 /** Create an actionHandler and actions for external table states. */
67 export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>) : ExternalMethodes<TData> ;
68 export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>, disableRow: (data: TData) => boolean) : ExternalMethodes<TData>;
69 export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>, disableRow?: (data: TData) => boolean) : ExternalMethodes<TData> {
70
71   //#region Actions
72   abstract class TableAction extends Action { }
73
74
75   class RequestSortAction extends TableAction {
76     constructor(public orderBy: string) {
77       super();
78     }
79   }
80
81   class RequestExplicitSortAction extends TableAction {
82     constructor(public propertyName: string, public sortOrder: "asc" | "desc") {
83       super();
84     }
85   }
86
87   class SetSelectedAction extends TableAction {
88     constructor(public selected: TData[] | null) {
89       super();
90     }
91   }
92
93   class SetPageAction extends TableAction {
94     constructor(public page: number) {
95       super();
96     }
97   }
98
99   class SetRowsPerPageAction extends TableAction {
100     constructor(public rowsPerPage: number) {
101       super();
102     }
103   }
104
105   class SetPreFilterChangedAction extends TableAction {
106     constructor(public preFilter: { [key: string]: string }) {
107       super();
108     }
109   }
110
111   class SetFilterChangedAction extends TableAction {
112     constructor(public filter: { [key: string]: string }) {
113       super();
114     }
115   }
116
117   class SetShowFilterAction extends TableAction {
118     constructor(public show: boolean) {
119       super();
120     }
121   }
122
123   class RefreshAction extends TableAction {
124     constructor() {
125       super();
126     }
127   }
128
129   class SetResultAction extends TableAction {
130     constructor(public result: { page: number, total: number, rows: TData[] }) {
131       super();
132     }
133   }
134
135   class HideColumnsAction extends TableAction{
136     constructor(public property: string[]){
137       super();
138     }
139   }
140
141   class ShowColumnsAction extends TableAction{
142     constructor(public property: string[]){
143       super();
144     }
145   }
146
147   // #endregion
148
149   //#region Action Handler
150   const externalTableStateInit: IExternalTableState<TData> = {
151     order: 'asc',
152     orderBy: null,
153     selected: null,
154     hiddenColumns:[],
155     rows: [],
156     total: 0,
157     page: 0,
158     rowsPerPage: 10,
159     loading: false,
160     showFilter: false,
161     filter: {},
162     preFilter: {}
163   };
164
165   const externalTableStateActionHandler: IActionHandler<IExternalTableState<TData>> = (state = externalTableStateInit, action) => {
166     if (!(action instanceof TableAction)) return state;
167     if (action instanceof RefreshAction) {
168       state = {
169         ...state,
170         loading: true
171       }
172     } else if (action instanceof SetResultAction) {
173       state = {
174         ...state,
175         loading: false,
176         rows: disableRow 
177           ? action.result.rows.map((row: TData) => ({...row, [RowDisabled]: disableRow(row) })) 
178           : action.result.rows,
179         total: action.result.total,
180         page: action.result.page,
181       }
182     } else if (action instanceof RequestSortAction) {
183       state = {
184         ...state,
185         loading: true,
186         orderBy: state.orderBy === action.orderBy && state.order === 'desc' ? null : action.orderBy,
187         order: state.orderBy === action.orderBy && state.order === 'asc' ? 'desc' : 'asc',
188       }
189     } else if (action instanceof RequestExplicitSortAction) {
190       state = {
191         ...state,
192         loading: true,
193         orderBy: action.propertyName,
194         order: action.sortOrder
195       }
196     }
197     else if (action instanceof SetShowFilterAction) {
198       state = {
199         ...state,
200         loading: true,
201         showFilter: action.show
202       }
203     } else if (action instanceof SetPreFilterChangedAction) {
204       state = {
205         ...state,
206         loading: true,
207         preFilter: action.preFilter
208       }
209     } else if (action instanceof SetFilterChangedAction) {
210       state = {
211         ...state,
212         loading: true,
213         filter: action.filter
214       }
215     } else if (action instanceof SetPageAction) {
216       state = {
217         ...state,
218         loading: true,
219         page: action.page
220       }
221     } else if (action instanceof SetRowsPerPageAction) {
222       state = {
223         ...state,
224         loading: true,
225         rowsPerPage: action.rowsPerPage
226       }
227     }
228     else if (action instanceof HideColumnsAction){
229       
230       //merge arrays, remove duplicates
231       const newArray = [...new Set([...state.hiddenColumns, ...action.property])]
232       state = {...state, hiddenColumns: newArray};
233     }
234     else if(action instanceof ShowColumnsAction){
235
236       const newArray = state.hiddenColumns.filter(el=> !action.property.includes(el));
237       state = {...state, hiddenColumns: newArray};
238     }
239
240     return state;
241   }
242
243   //const createTableAction(tableAction)
244
245   //#endregion
246   const reloadAction = (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
247     dispatch(new RefreshAction());
248     const ownState = selectState(getAppState());
249     const filter = { ...ownState.preFilter, ...(ownState.showFilter && ownState.filter || {}) };
250     return Promise.resolve(callback(ownState.page, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result => {
251
252       if (ownState.page > 0 && ownState.rowsPerPage * ownState.page > result.total) { //if result is smaller than the currently shown page, new search and repaginate
253
254         let newPage = Math.floor(result.total / ownState.rowsPerPage);
255
256         Promise.resolve(callback(newPage, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result1 => {
257           dispatch(new SetResultAction(result1));
258         });
259
260
261       } else {
262         dispatch(new SetResultAction(result));
263       }
264
265
266     }).catch(error => dispatch(new AddErrorInfoAction(error)));
267   };
268
269   const createPreActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
270     return {
271       onPreFilterChanged: (preFilter: { [key: string]: string }) => {
272         dispatch(new SetPreFilterChangedAction(preFilter));
273         (!skipRefresh) && dispatch(reloadAction);
274       }
275     };
276   }
277
278   const createActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
279     return {
280       onRefresh: () => {
281         dispatch(reloadAction);
282       },
283       onHandleRequestSort: (orderBy: string) => {
284         dispatch((dispatch: Dispatch) => {
285           dispatch(new RequestSortAction(orderBy));
286           (!skipRefresh) && dispatch(reloadAction);
287         });
288       },
289       onHandleExplicitRequestSort: (property: string, sortOrder: "asc" | "desc") => {
290         dispatch((dispatch: Dispatch) => {
291           dispatch(new RequestExplicitSortAction(property, sortOrder));
292           (!skipRefresh) && dispatch(reloadAction);
293         });
294       },
295       onToggleFilter: (refresh?: boolean) => {
296         dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
297           const { showFilter } = selectState(getAppState());
298           dispatch(new SetShowFilterAction(!showFilter));
299           if (!skipRefresh && (refresh === undefined || refresh))
300             dispatch(reloadAction);
301         });
302       },
303       onFilterChanged: (property: string, filterTerm: string) => {
304         dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
305           let { filter } = selectState(getAppState());
306           filter = { ...filter, [property]: filterTerm };
307           dispatch(new SetFilterChangedAction(filter));
308           (!skipRefresh) && dispatch(reloadAction);
309         });
310       },
311       onHandleChangePage: (page: number) => {
312         dispatch((dispatch: Dispatch) => {
313           dispatch(new SetPageAction(page));
314           (!skipRefresh) && dispatch(reloadAction);
315         });
316       },
317       onHandleChangeRowsPerPage: (rowsPerPage: number | null) => {
318         dispatch((dispatch: Dispatch) => {
319           dispatch(new SetRowsPerPageAction(rowsPerPage || 10));
320           (!skipRefresh) && dispatch(reloadAction);
321         });
322       },
323       onHideColumns: (columnName: string[]) =>{
324         dispatch((dispatch: Dispatch) => {
325           dispatch(new HideColumnsAction(columnName));
326         })
327       },
328       onShowColumns: (columnName: string[]) =>{
329         dispatch((dispatch: Dispatch) => {
330           dispatch(new ShowColumnsAction(columnName));
331         })
332       },
333       onClearFilters: () => {
334         dispatch((dispatch: Dispatch) => {
335           let filter = { };
336           dispatch(new SetFilterChangedAction(filter));
337         });
338       },
339       // selected:
340     };
341   };
342
343   const createProperties = (state: IApplicationStoreState) => {
344     return {
345       ...selectState(state)
346     }
347   }
348
349   return {
350     reloadAction: reloadAction,
351     createActions: createActions,
352     createProperties: createProperties,
353     createPreActions: createPreActions,
354     actionHandler: externalTableStateActionHandler,
355   }
356 }
357