// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; import { IconButton, Paper, StyleRulesCallback, withStyles, WithStyles, Tooltip, InputAdornment, Input, } from '@material-ui/core'; import SearchIcon from '@material-ui/icons/Search'; import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'; import { ArvadosTheme } from '~/common/custom-theme'; import { SearchView } from '~/store/search-bar/search-bar-reducer'; import { SearchBarBasicView, SearchBarBasicViewDataProps, SearchBarBasicViewActionProps } from '~/views-components/search-bar/search-bar-basic-view'; import { SearchBarAutocompleteView, SearchBarAutocompleteViewDataProps, SearchBarAutocompleteViewActionProps } from '~/views-components/search-bar/search-bar-autocomplete-view'; import { SearchBarAdvancedView, SearchBarAdvancedViewDataProps, SearchBarAdvancedViewActionProps } from '~/views-components/search-bar/search-bar-advanced-view'; import { KEY_CODE_DOWN, KEY_CODE_ESC, KEY_CODE_UP, KEY_ENTER } from "~/common/codes"; type CssRules = 'container' | 'containerSearchViewOpened' | 'input' | 'view'; const styles: StyleRulesCallback = (theme: ArvadosTheme) => { return { container: { position: 'relative', width: '100%', borderRadius: theme.spacing.unit / 2, zIndex: theme.zIndex.modal, }, containerSearchViewOpened: { position: 'relative', width: '100%', borderRadius: `${theme.spacing.unit / 2}px ${theme.spacing.unit / 2}px 0 0`, zIndex: theme.zIndex.modal, }, input: { border: 'none', padding: `0` }, view: { position: 'absolute', width: '100%', zIndex: 1 } }; }; export type SearchBarDataProps = SearchBarViewDataProps & SearchBarAutocompleteViewDataProps & SearchBarAdvancedViewDataProps & SearchBarBasicViewDataProps; interface SearchBarViewDataProps { searchValue: string; currentView: string; isPopoverOpen: boolean; debounce?: number; } export type SearchBarActionProps = SearchBarViewActionProps & SearchBarAutocompleteViewActionProps & SearchBarAdvancedViewActionProps & SearchBarBasicViewActionProps; interface SearchBarViewActionProps { onChange: (event: React.ChangeEvent) => void; onSubmit: (event: React.FormEvent) => void; onSetView: (currentView: string) => void; closeView: () => void; openSearchView: () => void; loadRecentQueries: () => string[]; moveUp: () => void; moveDown: () => void; setAdvancedDataFromSearchValue: (search: string) => void; } type SearchBarViewProps = SearchBarDataProps & SearchBarActionProps & WithStyles; const handleKeyDown = (e: React.KeyboardEvent, props: SearchBarViewProps) => { if (e.keyCode === KEY_CODE_DOWN) { e.preventDefault(); if (!props.isPopoverOpen) { props.onSetView(SearchView.AUTOCOMPLETE); props.openSearchView(); } else { props.moveDown(); } } else if (e.keyCode === KEY_CODE_UP) { e.preventDefault(); props.moveUp(); } else if (e.keyCode === KEY_CODE_ESC) { e.preventDefault(); props.closeView(); } else if (e.keyCode === KEY_ENTER) { if (props.currentView === SearchView.BASIC) { e.preventDefault(); props.onSearch(props.selectedItem.query); } else if (props.currentView === SearchView.AUTOCOMPLETE) { if (props.selectedItem.id !== props.searchValue) { e.preventDefault(); props.navigateTo(props.selectedItem.id); } } } }; const handleInputClick = (e: React.MouseEvent, props: SearchBarViewProps) => { if (props.searchValue) { props.onSetView(SearchView.AUTOCOMPLETE); props.openSearchView(); } else { props.closeView(); } }; const handleDropdownClick = (e: React.MouseEvent, props: SearchBarViewProps) => { e.stopPropagation(); if (props.isPopoverOpen) { if (props.currentView === SearchView.ADVANCED) { props.closeView(); } else { props.setAdvancedDataFromSearchValue(props.searchValue); props.onSetView(SearchView.ADVANCED); } } else { props.setAdvancedDataFromSearchValue(props.searchValue); props.onSetView(SearchView.ADVANCED); } }; export const SearchBarView = withStyles(styles)( (props: SearchBarViewProps) => { const { classes, isPopoverOpen } = props; return ( <> {isPopoverOpen && }
handleInputClick(e, props)} onKeyDown={e => handleKeyDown(e, props)} startAdornment={ } endAdornment={ handleDropdownClick(e, props)}> } />
{isPopoverOpen && getView({ ...props })}
); } ); const getView = (props: SearchBarViewProps) => { switch (props.currentView) { case SearchView.AUTOCOMPLETE: return ; case SearchView.ADVANCED: return ; default: return ; } }; const Backdrop = withStyles<'backdrop'>(theme => ({ backdrop: { position: 'fixed', top: 0, right: 0, bottom: 0, left: 0, zIndex: theme.zIndex.modal } }))( ({ classes, ...props }: WithStyles<'backdrop'> & React.HTMLProps) =>
);