Add arrow navigation in autocomplete view
[arvados-workbench2.git] / src / store / search-bar / search-bar-reducer.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { searchBarActions, SearchBarActions } from '~/store/search-bar/search-bar-actions';
6 import { GroupContentsResource } from '~/services/groups-service/groups-service';
7 import { SearchBarAdvanceFormData } from '~/models/search-bar';
8
9 type SearchResult = GroupContentsResource;
10
11 interface SearchBar {
12     currentView: string;
13     open: boolean;
14     searchResults: SearchResult[];
15     searchValue: string;
16     savedQueries: SearchBarAdvanceFormData[];
17     selectedItem: string;
18 }
19
20 export enum SearchView {
21     BASIC = 'basic',
22     ADVANCED = 'advanced',
23     AUTOCOMPLETE = 'autocomplete'
24 }
25
26 const initialState: SearchBar = {
27     currentView: SearchView.BASIC,
28     open: false,
29     searchResults: [],
30     searchValue: '',
31     savedQueries: [],
32     selectedItem: ''
33 };
34
35 export const searchBarReducer = (state = initialState, action: SearchBarActions): SearchBar =>
36     searchBarActions.match(action, {
37         SET_CURRENT_VIEW: currentView => ({
38             ...state,
39             currentView,
40             open: true
41         }),
42         OPEN_SEARCH_VIEW: () => ({ ...state, open: true }),
43         CLOSE_SEARCH_VIEW: () => ({ ...state, open: false }),
44         SET_SEARCH_RESULTS: searchResults => ({
45             ...state,
46             searchResults,
47             selectedItem: searchResults.length > 0
48                 ? searchResults.findIndex(r => r.uuid === state.selectedItem) >= 0
49                     ? state.selectedItem
50                     : state.searchValue
51                 : state.searchValue
52         }),
53         SET_SEARCH_VALUE: searchValue => ({
54             ...state,
55             searchValue,
56             selectedItem: state.searchValue === state.selectedItem
57                 ? searchValue
58                 : state.selectedItem
59         }),
60         SET_SAVED_QUERIES: savedQueries => ({ ...state, savedQueries }),
61         UPDATE_SAVED_QUERY: searchQuery => ({ ...state, savedQueries: searchQuery }),
62         SET_SELECTED_ITEM: item => ({ ...state, selectedItem: item }),
63         MOVE_UP: () => {
64             let selectedItem = state.selectedItem;
65             if (state.currentView === SearchView.AUTOCOMPLETE) {
66                 const idx = state.searchResults.findIndex(r => r.uuid === selectedItem);
67                 if (idx > 0) {
68                     selectedItem = state.searchResults[idx - 1].uuid;
69                 } else {
70                     selectedItem = state.searchValue;
71                 }
72             }
73             return {
74                 ...state,
75                 selectedItem
76             };
77         },
78         MOVE_DOWN: () => {
79             let selectedItem = state.selectedItem;
80             if (state.currentView === SearchView.AUTOCOMPLETE) {
81                 const idx = state.searchResults.findIndex(r => r.uuid === selectedItem);
82                 if (idx >= 0 && idx < state.searchResults.length - 1) {
83                     selectedItem = state.searchResults[idx + 1].uuid;
84                 } else if (idx < 0 && state.searchResults.length > 0) {
85                     selectedItem = state.searchResults[0].uuid;
86                 }
87             }
88             return {
89                 ...state,
90                 selectedItem
91             };
92         },
93         default: () => state
94     });