1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
6 getQueryFromAdvancedData,
9 } from 'store/search-bar/search-bar-actions';
10 import { GroupContentsResource } from 'services/groups-service/groups-service';
11 import { SearchBarAdvancedFormData } from 'models/search-bar';
13 type SearchResult = GroupContentsResource;
14 export type SearchBarSelectedItem = {
22 searchResults: SearchResult[];
24 savedQueries: SearchBarAdvancedFormData[];
25 recentQueries: string[];
26 selectedItem: SearchBarSelectedItem;
27 searchOffsets: Record<string, number>;
30 export enum SearchView {
32 ADVANCED = 'advanced',
33 AUTOCOMPLETE = 'autocomplete'
36 const initialState: SearchBar = {
37 currentView: SearchView.BASIC,
50 const makeSelectedItem = (id: string, query?: string): SearchBarSelectedItem => ({ id, query: query ? query : id });
52 const makeQueryList = (recentQueries: string[], savedQueries: SearchBarAdvancedFormData[]) => {
53 const recentIds = recentQueries.map((q, idx) => makeSelectedItem(`RQ-${idx}-${q}`, q));
54 const savedIds = savedQueries.map((q, idx) => makeSelectedItem(`SQ-${idx}-${q.queryName}`, getQueryFromAdvancedData(q)));
55 return recentIds.concat(savedIds);
58 export const searchBarReducer = (state = initialState, action: SearchBarActions): SearchBar =>
59 searchBarActions.match(action, {
60 SET_CURRENT_VIEW: currentView => ({
65 OPEN_SEARCH_VIEW: () => ({ ...state, open: true }),
66 CLOSE_SEARCH_VIEW: () => ({ ...state, open: false }),
67 SET_SEARCH_RESULTS: searchResults => ({
70 selectedItem: makeSelectedItem(searchResults.length > 0
71 ? searchResults.findIndex(r => r.uuid === state.selectedItem.id) >= 0
72 ? state.selectedItem.id
77 SET_SEARCH_VALUE: searchValue => ({
81 SET_SAVED_QUERIES: savedQueries => ({ ...state, savedQueries }),
82 SET_RECENT_QUERIES: recentQueries => ({ ...state, recentQueries }),
83 UPDATE_SAVED_QUERY: searchQuery => ({ ...state, savedQueries: searchQuery }),
84 SET_SELECTED_ITEM: item => ({ ...state, selectedItem: makeSelectedItem(item) }),
86 let selectedItem = state.selectedItem;
87 if (state.currentView === SearchView.AUTOCOMPLETE) {
88 const idx = state.searchResults.findIndex(r => r.uuid === selectedItem.id);
90 selectedItem = makeSelectedItem(state.searchResults[idx - 1].uuid);
92 selectedItem = makeSelectedItem(state.searchValue);
94 } else if (state.currentView === SearchView.BASIC) {
95 const items = makeQueryList(state.recentQueries, state.savedQueries);
97 const idx = items.findIndex(i => i.id === selectedItem.id);
99 selectedItem = items[idx - 1];
108 let selectedItem = state.selectedItem;
109 if (state.currentView === SearchView.AUTOCOMPLETE) {
110 const idx = state.searchResults.findIndex(r => r.uuid === selectedItem.id);
111 if (idx >= 0 && idx < state.searchResults.length - 1) {
112 selectedItem = makeSelectedItem(state.searchResults[idx + 1].uuid);
113 } else if (idx < 0 && state.searchResults.length > 0) {
114 selectedItem = makeSelectedItem(state.searchResults[0].uuid);
116 } else if (state.currentView === SearchView.BASIC) {
117 const items = makeQueryList(state.recentQueries, state.savedQueries);
119 const idx = items.findIndex(i => i.id === selectedItem.id);
120 if (idx >= 0 && idx < items.length - 1) {
121 selectedItem = items[idx + 1];
124 if (idx < 0 && items.length > 0) {
125 selectedItem = items[0];
133 SELECT_FIRST_ITEM: () => {
134 let selectedItem = state.selectedItem;
135 if (state.currentView === SearchView.AUTOCOMPLETE) {
136 selectedItem = makeSelectedItem(state.searchValue);
137 } else if (state.currentView === SearchView.BASIC) {
138 const items = makeQueryList(state.recentQueries, state.savedQueries);
139 if (items.length > 0) {
140 selectedItem = items[0];
148 SET_SEARCH_OFFSETS: ({id, offset}) => {
149 return {...state, searchOffsets: {...state.searchOffsets, [id]: offset}};