21364: added backup search when first search after f5 fails Arvados-DCO-1.1-Signed...
authorLisa Knox <lisaknox83@gmail.com>
Fri, 10 May 2024 18:40:42 +0000 (14:40 -0400)
committerLisa Knox <lisaknox83@gmail.com>
Fri, 10 May 2024 18:40:42 +0000 (14:40 -0400)
services/workbench2/src/components/data-explorer/data-explorer.tsx
services/workbench2/src/store/search-bar/search-bar-actions.ts
services/workbench2/src/store/search-bar/search-bar-reducer.ts
services/workbench2/src/store/search-results-panel/search-results-middleware-service.ts
services/workbench2/src/views-components/search-bar/search-bar-view.tsx
services/workbench2/src/views-components/search-bar/search-bar.tsx

index e29ff9c55ea121d86aa06db06795d81d8a309723..1a77dccf61b1081d557ed283fa430f778238b054 100644 (file)
@@ -169,7 +169,6 @@ export const DataExplorer = withStyles(styles)(
                 setCheckedListOnStore,
                 checkedList,
                 working,
-                page,
             } = this.props;
             return (
                 <Paper
index 396c2dfaaecf9253fbe63373e997981d6b81dad9..d624c917d97e96a6456382296f008f78ece83404 100644 (file)
@@ -39,6 +39,7 @@ export const searchBarActions = unionize({
     MOVE_UP: ofType<{}>(),
     MOVE_DOWN: ofType<{}>(),
     SELECT_FIRST_ITEM: ofType<{}>(),
+    SET_SEARCH_OFFSETS: ofType<Record<string, number>>(),
 });
 
 export type SearchBarActions = UnionOf<typeof searchBarActions>;
@@ -430,3 +431,9 @@ export const moveDown = () =>
     (dispatch: Dispatch) => {
         dispatch(searchBarActions.MOVE_DOWN());
     };
+
+export const setSearchOffsets = (sessionId: string, offset: number) => {
+    return (dispatch: Dispatch) => {
+        dispatch(searchBarActions.SET_SEARCH_OFFSETS({id:[sessionId], offset }));
+    };
+}
\ No newline at end of file
index 05b75bf99c4a981f7fda8410d8c73fc74dd3c121..84c17438a772d417eb190277ea607fdc894e880a 100644 (file)
@@ -24,6 +24,7 @@ interface SearchBar {
     savedQueries: SearchBarAdvancedFormData[];
     recentQueries: string[];
     selectedItem: SearchBarSelectedItem;
+    searchOffsets: Record<string, number>;
 }
 
 export enum SearchView {
@@ -43,6 +44,7 @@ const initialState: SearchBar = {
         id: '',
         query: ''
     },
+    searchOffsets: {},
 };
 
 const makeSelectedItem = (id: string, query?: string): SearchBarSelectedItem => ({ id, query: query ? query : id });
@@ -143,5 +145,8 @@ export const searchBarReducer = (state = initialState, action: SearchBarActions)
                 selectedItem
             };
         },
+        SET_SEARCH_OFFSETS: ({id, offset}) => {
+            return {...state, searchOffsets: {...state.searchOffsets, [id]: offset}};
+        },
         default: () => state
     });
index 11462c061883a0551a26c74efc0055268c649c94..2c444813a1c359647456fe10242bf7902c781f18 100644 (file)
@@ -18,6 +18,7 @@ import {
     getSearchSessions,
     queryToFilters,
     getAdvancedDataFromQuery,
+    setSearchOffsets,
 } from 'store/search-bar/search-bar-actions';
 import { getSortColumn } from "store/data-explorer/data-explorer-reducer";
 import { FilterBuilder, joinFilters } from 'services/api/filter-builder';
@@ -28,6 +29,8 @@ import { ResourceKind } from 'models/resource';
 import { ContainerRequestResource } from 'models/container-request';
 import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
 import { dataExplorerActions } from 'store/data-explorer/data-explorer-action';
+import { Session } from 'models/session';
+import { SEARCH_RESULTS_PANEL_ID } from 'store/search-results-panel/search-results-panel-actions';
 
 export class SearchResultsMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -50,7 +53,7 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
             items: [] as GroupContentsResource[],
             kind: '',
             offset: 0,
-            limit: 10
+            limit: 50
         };
 
         if (criteriaChanged) {
@@ -69,6 +72,9 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
 
         sessions.forEach(session => {
             const params = getParams(dataExplorer, searchValue, session.apiRevision);
+            //this prevents double fetching of the same search results when a new session is logged in
+            api.dispatch<any>(setSearchOffsets(session.clusterId, params.offset ));
+
             this.services.groupsService.contents('', params, session)
                 .then((response) => {
                     api.dispatch(updateResources(response.items));
@@ -100,6 +106,48 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
     }
 }
 
+export const searchSingleCluster = (session: Session, searchValue: string) => 
+    (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+        const state = getState();
+        const dataExplorer = getDataExplorer(state.dataExplorer, SEARCH_RESULTS_PANEL_ID);
+
+        if (searchValue.trim() === '') {
+            return;
+        }
+
+        const params = getParams(dataExplorer, searchValue, session.apiRevision);
+        
+        // If the clusterId & search offset has already been fetched, we don't need to fetch the results again
+        if(state.searchBar.searchOffsets[session.clusterId] === params.offset) {
+            return;
+        }
+
+        dispatch(progressIndicatorActions.START_WORKING(SEARCH_RESULTS_PANEL_ID))
+
+        services.groupsService.contents('', params, session)
+            .then((response) => {
+                dispatch<any>(setSearchOffsets(session.clusterId, params.offset ));
+                dispatch(updateResources(response.items));
+                dispatch(appendItems(response));
+                // Request all containers for process status to be available
+                const containerRequests = response.items.filter((item) => item.kind === ResourceKind.CONTAINER_REQUEST) as ContainerRequestResource[];
+                const containerUuids = containerRequests.map(container => container.containerUuid).filter(uuid => uuid !== null) as string[];
+                containerUuids.length && services.containerService
+                    .list({
+                        filters: new FilterBuilder()
+                            .addIn('uuid', containerUuids)
+                            .getFilters()
+                    }, false)
+                    .then((containers) => {
+                        dispatch(updateResources(containers.items));
+                    });
+                }).catch(() => {
+                    dispatch(couldNotFetchSearchResults(session.clusterId));
+                    dispatch(progressIndicatorActions.STOP_WORKING(SEARCH_RESULTS_PANEL_ID))
+                });
+        dispatch(progressIndicatorActions.STOP_WORKING(SEARCH_RESULTS_PANEL_ID))
+}
+
 const typeFilters = (columns: DataColumns<string, GroupContentsResource>) => serializeResourceTypeFilters(getDataExplorerColumnFilters(columns, ProjectPanelColumnNames.TYPE));
 
 export const getParams = (dataExplorer: DataExplorer, query: string, apiRevision: number) => ({
@@ -142,10 +190,6 @@ export const setItems = (listResults: ListResults<GroupContentsResource>) =>
 const resetItemsAvailable = () =>
     searchResultsPanelActions.RESET_ITEMS_AVAILABLE();
 
-const setItemsAvailable = (id: string, itemsAvailable: number) => {
-
-}
-
 export const appendItems = (listResults: ListResults<GroupContentsResource>) =>
     searchResultsPanelActions.APPEND_ITEMS({
         ...listResultsToDataExplorerItemsMeta(listResults),
index eba281c9f0854c275454f61ee91142d7d59ab110..0c08e38b7d860533dd9ad7203a46ce0876f0649d 100644 (file)
@@ -24,6 +24,7 @@ import { KEY_CODE_DOWN, KEY_CODE_ESC, KEY_CODE_UP, KEY_ENTER } from "common/code
 import { debounce } from "debounce";
 import { Vocabulary } from "models/vocabulary";
 import { connectVocabulary } from "../resource-properties-form/property-field-common";
+import { Session } from "models/session";
 
 type CssRules = "container" | "containerSearchViewOpened" | "input" | "view";
 
@@ -64,6 +65,7 @@ interface SearchBarViewDataProps {
     isPopoverOpen: boolean;
     debounce?: number;
     vocabulary?: Vocabulary;
+    sessions: Session[];
 }
 
 export type SearchBarActionProps = SearchBarViewActionProps &
@@ -81,6 +83,7 @@ interface SearchBarViewActionProps {
     moveUp: () => void;
     moveDown: () => void;
     setAdvancedDataFromSearchValue: (search: string, vocabulary?: Vocabulary) => void;
+    searchSingleCluster: (session: Session, searchValue: string) => any;
 }
 
 type SearchBarViewProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
@@ -137,6 +140,10 @@ export const SearchBarView = compose(
     withStyles(styles)
 )(
     class extends React.Component<SearchBarViewProps> {
+        state={
+            loggedInSessions: [],
+        }
+
         debouncedSearch = debounce(() => {
             this.props.onSearch(this.props.searchValue);
         }, 1000);
@@ -151,6 +158,21 @@ export const SearchBarView = compose(
             this.props.onSubmit(event);
         };
 
+        componentDidMount(): void {
+            this.setState({ loggedInSessions: this.props.sessions.filter((ss) => ss.loggedIn && ss.userIsActive)});
+        }
+
+        componentDidUpdate( prevProps: Readonly<SearchBarViewProps>, prevState: Readonly<{loggedInSessions: Session[]}>, snapshot?: any ): void {
+            if (prevProps.sessions !== this.props.sessions) {
+                this.setState({ loggedInSessions: this.props.sessions.filter((ss) => ss.loggedIn)});
+            }
+            //if a new session is logged in after a search is started, search the new cluster and append those to the results
+            if(prevState.loggedInSessions.length !== this.state.loggedInSessions.length){
+                const newLogin = this.state.loggedInSessions.filter((ss) => !prevState.loggedInSessions.includes(ss));
+                this.props.searchSingleCluster(newLogin[0], this.props.searchValue);
+            }
+        }
+
         componentWillUnmount() {
             this.debouncedSearch.clear();
         }
index 6a4d2a620e1fbf8ccd2cb3d4a209130cf75ce07e..92175b6ec4200ceef5662e361f0b038e684cca53 100644 (file)
@@ -21,8 +21,10 @@ import {
 import { SearchBarView, SearchBarActionProps, SearchBarDataProps } from 'views-components/search-bar/search-bar-view';
 import { SearchBarAdvancedFormData } from 'models/search-bar';
 import { Vocabulary } from 'models/vocabulary';
+import { searchSingleCluster } from 'store/search-results-panel/search-results-middleware-service';
+import { Session } from 'models/session';
 
-const mapStateToProps = ({ searchBar, form }: RootState): SearchBarDataProps => {
+const mapStateToProps = ({ searchBar, form , auth }: RootState): SearchBarDataProps => {
     return {
         searchValue: searchBar.searchValue,
         currentView: searchBar.currentView,
@@ -33,7 +35,8 @@ const mapStateToProps = ({ searchBar, form }: RootState): SearchBarDataProps =>
         tags: form[SEARCH_BAR_ADVANCED_FORM_NAME],
         saveQuery: form[SEARCH_BAR_ADVANCED_FORM_NAME] &&
             form[SEARCH_BAR_ADVANCED_FORM_NAME].values &&
-            form[SEARCH_BAR_ADVANCED_FORM_NAME].values!.saveQuery
+            form[SEARCH_BAR_ADVANCED_FORM_NAME].values!.saveQuery,
+        sessions: auth.sessions,
     };
 };
 
@@ -51,7 +54,8 @@ const mapDispatchToProps = (dispatch: Dispatch): SearchBarActionProps => ({
     editSavedQuery: (data: SearchBarAdvancedFormData) => dispatch<any>(editSavedQuery(data)),
     moveUp: () => dispatch<any>(moveUp()),
     moveDown: () => dispatch<any>(moveDown()),
-    setAdvancedDataFromSearchValue: (search: string, vocabulary: Vocabulary) => dispatch<any>(setAdvancedDataFromSearchValue(search, vocabulary))
+    setAdvancedDataFromSearchValue: (search: string, vocabulary: Vocabulary) => dispatch<any>(setAdvancedDataFromSearchValue(search, vocabulary)),
+    searchSingleCluster: (session: Session, searchValue: string) => {dispatch<any>(searchSingleCluster(session, searchValue))},
 });
 
 export const SearchBar = connect(mapStateToProps, mapDispatchToProps)(SearchBarView);