SET_SELECTED_ITEM: ofType<string>(),
MOVE_UP: ofType<{}>(),
MOVE_DOWN: ofType<{}>(),
- SELECT_FIRST_ITEM: ofType<{}>()
+ SELECT_FIRST_ITEM: ofType<{}>(),
+ SET_IS_SEARCHING: ofType<boolean>(),
});
export type SearchBarActions = UnionOf<typeof searchBarActions>;
savedQueries: SearchBarAdvancedFormData[];
recentQueries: string[];
selectedItem: SearchBarSelectedItem;
+ isSearching: boolean;
}
export enum SearchView {
selectedItem: {
id: '',
query: ''
- }
+ },
+ isSearching: false,
};
const makeSelectedItem = (id: string, query?: string): SearchBarSelectedItem => ({ id, query: query ? query : id });
selectedItem
};
},
+ SET_IS_SEARCHING: isSearching => ({ ...state, isSearching }),
default: () => state
});
import {
getSearchSessions,
queryToFilters,
- getAdvancedDataFromQuery
+ getAdvancedDataFromQuery,
+ searchBarActions
} from 'store/search-bar/search-bar-actions';
import { getSortColumn } from "store/data-explorer/data-explorer-reducer";
import { FilterBuilder, joinFilters } from 'services/api/filter-builder';
api.dispatch(setItems(initial));
}
+ const numberOfSessions = sessions.length;
+ let numberOfResolvedResponses = 0;
+ api.dispatch(searchBarActions.SET_IS_SEARCHING(true));
+
sessions.forEach(session => {
const params = getParams(dataExplorer, searchValue, session.apiRevision);
this.services.groupsService.contents('', params, session)
.then((response) => {
api.dispatch(updateResources(response.items));
api.dispatch(appendItems(response));
+ numberOfResolvedResponses++;
+ if (numberOfResolvedResponses === numberOfSessions) {
+ api.dispatch(searchBarActions.SET_IS_SEARCHING(false));
+ }
// 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[];
.then((containers) => {
api.dispatch(updateResources(containers.items));
});
- }).catch(() => {
- api.dispatch(couldNotFetchSearchResults(session.clusterId));
- });
- }
+ }).catch(() => {
+ api.dispatch(couldNotFetchSearchResults(session.clusterId));
+ api.dispatch(searchBarActions.SET_IS_SEARCHING(false));
+ });
+ }
);
}
}
import { getSearchSessions } from 'store/search-bar/search-bar-actions';
import { camelCase } from 'lodash';
import { GroupContentsResource } from 'services/groups-service/groups-service';
+import { PendingIcon } from 'components/icon/icon';
export enum SearchResultsPanelColumnNames {
CLUSTER = "Cluster",
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedItem]);
+ const prevIsSearching = React.useRef<boolean>(props.isSearching);
+ const [isLoaded, setIsLoaded] = React.useState<boolean>(false);
+
+ useEffect(() => {
+ if(prevIsSearching.current === true && props.isSearching === false) {
+ setIsLoaded(true);
+ props.stopSpinner();
+ }
+ if(props.isSearching === true) {
+ setIsLoaded(false);
+ props.startSpinner();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [props.isSearching]);
+
const onItemClick = useCallback((uuid) => {
setSelectedItem(uuid);
props.onItemClick(uuid);
contextMenuColumn={false}
elementPath={`/ ${itemPath.reverse().join(' / ')}`}
hideSearchInput
+ defaultViewIcon={isLoaded && props.numberOfItems === 0 ? undefined : PendingIcon}
+ defaultViewMessages={isLoaded && props.numberOfItems === 0 ? ['No items found'] : ['Loading data, please wait']}
title={
<div>
{loggedIn.length === 1 ?
import { Config } from 'common/config';
import { Session } from "models/session";
import { toggleOne, deselectAllOthers } from "store/multiselect/multiselect-actions";
+import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
+import { SEARCH_RESULTS_PANEL_ID } from 'store/search-results-panel/search-results-panel-actions';
export interface SearchResultsPanelDataProps {
data: SearchBarAdvancedFormData;
sessions: Session[];
remoteHostsConfig: { [key: string]: Config };
localCluster: string;
+ numberOfItems: number;
+ isSearching: boolean;
}
export interface SearchResultsPanelActionProps {
onContextMenu: (event: React.MouseEvent<HTMLElement>, item: string) => void;
onDialogOpen: (ownerUuid: string) => void;
onItemDoubleClick: (item: string) => void;
+ startSpinner: () => void;
+ stopSpinner: () => void;
}
export type SearchResultsPanelProps = SearchResultsPanelDataProps & SearchResultsPanelActionProps;
const mapStateToProps = (rootState: RootState) => {
+ const { dataExplorer, searchBar } = rootState;
+ const numberOfItems = dataExplorer[SEARCH_RESULTS_PANEL_ID].items.length;
return {
user: rootState.auth.user,
sessions: rootState.auth.sessions,
remoteHostsConfig: rootState.auth.remoteHostsConfig,
localCluster: rootState.auth.localCluster,
+ numberOfItems,
+ isSearching: searchBar.isSearching,
};
};
},
onItemDoubleClick: uuid => {
dispatch<any>(navigateTo(uuid));
- }
+ },
+ startSpinner: () => {
+ dispatch<any>(progressIndicatorActions.START_WORKING(SEARCH_RESULTS_PANEL_ID));
+ },
+ stopSpinner: () => {
+ dispatch<any>(progressIndicatorActions.STOP_WORKING(SEARCH_RESULTS_PANEL_ID));
+ },
});
export const SearchResultsPanel = connect(mapStateToProps, mapDispatchToProps)(SearchResultsPanelView);