diff --git a/src/client/components/main_layout/SearchField.js b/src/client/components/main_layout/SearchField.js new file mode 100644 index 0000000000000000000000000000000000000000..5743237d63fe2229c4233a2b831d7edb79f652af --- /dev/null +++ b/src/client/components/main_layout/SearchField.js @@ -0,0 +1,124 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import IconButton from '@material-ui/core/IconButton'; +import SearchIcon from '@material-ui/icons/Search'; +import Input from '@material-ui/core/Input'; +import InputLabel from '@material-ui/core/InputLabel'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import FormControl from '@material-ui/core/FormControl'; +import CircularProgress from '@material-ui/core/CircularProgress'; + +const styles = theme => ({ + textSearch: { + margin: theme.spacing.unit, + }, +}); + +class SearchField extends React.Component { + state = { + value: '', + }; + + componentDidUpdate = prevProps => { + if (prevProps.search.query != this.props.search.query) { + this.setState({ + value: this.props.search.query + }); + } + } + + handleChange = (event) => { + this.setState({ value: event.target.value }); + }; + + handleMouseDown = (event) => { + event.preventDefault(); + }; + + handleOnKeyDown = (event) => { + if (event.key === 'Enter' && this.hasDatasets() && this.hasValidQuery()) { + this.props.clearResults(); + this.props.updateQuery(this.state.value); + this.props.fetchResults('text', this.state.value); + } + }; + + handleClick = () => { + if (this.hasDatasets() && this.hasValidQuery()) { + this.props.clearResults(); + this.props.updateQuery(this.state.value); + this.props.fetchResults('text', this.state.value); + } + }; + + hasDatasets = () => { + let hasDs = false; + Object.values(this.props.datasets).forEach(value => { + if (value.selected) { + hasDs = true; + } + }); + return hasDs; + } + + hasValidQuery = () => { + return this.state.value.length > 2; + } + + render() { + const { classes, strings } = this.props; + let searchButton = null; + if (this.props.search.textResultsFetching) { + searchButton = ( + <IconButton + aria-label="Search places" + > + <CircularProgress size={24} /> + </IconButton> + ); + } else { + searchButton = ( + <IconButton + aria-label="Search" + onClick={this.handleClick} + onMouseDown={this.handleMouseDown} + > + <SearchIcon /> + </IconButton> + ); + } + + return ( + <div className={classes.root}> + <FormControl className={classes.textSearch}> + <InputLabel htmlFor="adornment-search">{strings.searchPlaceNames}</InputLabel> + <Input + id="adornment-search" + type='text' + value={this.state.value} + onChange={this.handleChange} + onKeyDown={this.handleOnKeyDown} + endAdornment={ + <InputAdornment position="end"> + {searchButton} + </InputAdornment> + } + /> + </FormControl> + </div> + ); + } +} + +SearchField.propTypes = { + classes: PropTypes.object.isRequired, + search: PropTypes.object.isRequired, + fetchResults: PropTypes.func.isRequired, + clearResults: PropTypes.func.isRequired, + updateQuery: PropTypes.func.isRequired, + datasets: PropTypes.object.isRequired, + strings: PropTypes.object.isRequired +}; + +export default withStyles(styles)(SearchField); diff --git a/src/client/components/main_layout/TopBar.js b/src/client/components/main_layout/TopBar.js index b294f68e7476fe0f26dac7fb3084ecf0f918b5eb..994b16631c831d3a4a30f5887e7adc24f3679705 100644 --- a/src/client/components/main_layout/TopBar.js +++ b/src/client/components/main_layout/TopBar.js @@ -5,16 +5,11 @@ import Toolbar from '@material-ui/core/Toolbar'; import IconButton from '@material-ui/core/IconButton'; import Typography from '@material-ui/core/Typography'; import InputBase from '@material-ui/core/InputBase'; -import Badge from '@material-ui/core/Badge'; import MenuItem from '@material-ui/core/MenuItem'; import Menu from '@material-ui/core/Menu'; import { fade } from '@material-ui/core/styles/colorManipulator'; import { withStyles } from '@material-ui/core/styles'; -//§import MenuIcon from '@material-ui/icons/Menu'; import SearchIcon from '@material-ui/icons/Search'; -import AccountCircle from '@material-ui/icons/AccountCircle'; -import MailIcon from '@material-ui/icons/Mail'; -import NotificationsIcon from '@material-ui/icons/Notifications'; import MoreIcon from '@material-ui/icons/MoreVert'; import Button from '@material-ui/core/Button'; import { Link, NavLink } from 'react-router-dom'; @@ -119,23 +114,12 @@ class TopBar extends React.Component { }; render() { - const { anchorEl, mobileMoreAnchorEl } = this.state; + const { mobileMoreAnchorEl } = this.state; const { classes } = this.props; - const isMenuOpen = Boolean(anchorEl); const isMobileMenuOpen = Boolean(mobileMoreAnchorEl); - const renderMenu = ( - <Menu - anchorEl={anchorEl} - anchorOrigin={{ vertical: 'top', horizontal: 'right' }} - transformOrigin={{ vertical: 'top', horizontal: 'right' }} - open={isMenuOpen} - onClose={this.handleMenuClose} - > - <MenuItem onClick={this.handleMenuClose}>Profile</MenuItem> - <MenuItem onClick={this.handleMenuClose}>My account</MenuItem> - </Menu> - ); + const perspectives = [ 'manuscripts', 'works', 'events', 'people', + 'organizations', 'places' ]; const renderMobileMenu = ( <Menu @@ -145,76 +129,18 @@ class TopBar extends React.Component { open={isMobileMenuOpen} onClose={this.handleMobileMenuClose} > - <MenuItem> - <IconButton color="inherit"> - <Badge badgeContent={4} color="secondary"> - <MailIcon /> - </Badge> - </IconButton> - <p>Messages</p> - </MenuItem> - <MenuItem> - <IconButton color="inherit"> - <Badge badgeContent={11} color="secondary"> - <NotificationsIcon /> - </Badge> - </IconButton> - <p>Notifications</p> - </MenuItem> - <MenuItem onClick={this.handleProfileMenuOpen}> - <IconButton color="inherit"> - <AccountCircle /> - </IconButton> - <p>Profile</p> - </MenuItem> + {perspectives.map(perspective => + <MenuItem + key={perspective} + component={Link} + to={`/${perspective}`} + > + {perspective.toUpperCase()} + </MenuItem> + )} </Menu> ); - const ManuscriptsLink = props => ( - <NavLink - to="/manuscripts" - className={classes.appBarButton} - isActive={(match, location) => location.pathname.startsWith('/manuscripts')} - activeClassName={classes.appBarButtonActive} - {...props} - />); - - const WorksLink = props => ( - <NavLink - to="/works" - className={classes.appBarButton} - isActive={(match, location) => location.pathname.startsWith('/works')} - activeClassName={classes.appBarButtonActive} - {...props} - />); - - const PeopleLink = props => ( - <NavLink - to="/people" - className={classes.appBarButton} - isActive={(match, location) => location.pathname.startsWith('/people')} - activeClassName={classes.appBarButtonActive} - {...props} - />); - - const OrganizationsLink = props => ( - <NavLink - to="/organizations" - className={classes.appBarButton} - isActive={(match, location) => location.pathname.startsWith('/organizations')} - activeClassName={classes.appBarButtonActive} - {...props} - />); - - const PlacesLink = props => ( - <NavLink - to="/places" - className={classes.appBarButton} - isActive={(match, location) => location.pathname.startsWith('/places')} - activeClassName={classes.appBarButtonActive} - {...props} - />); - return ( <div className={classes.root}> <AppBar position="absolute"> @@ -243,32 +169,18 @@ class TopBar extends React.Component { </div> <div className={classes.grow} /> <div className={classes.sectionDesktop}> - <Button - className={classes.appBarButton} - component={ManuscriptsLink}> - manuscripts - </Button> - <Button - className={classes.appBarButton} - component={WorksLink}> - works - </Button> - <Button disabled className={classes.appBarButton}>Events</Button> - <Button - className={classes.appBarButton} - component={PeopleLink}> - people - </Button> - <Button - className={classes.appBarButton} - component={OrganizationsLink}> - organizations - </Button> - <Button - className={classes.appBarButton} - component={PlacesLink}> - places - </Button> + {perspectives.map(perspective => + <Button + key={perspective} + className={classes.appBarButton} + component={NavLink} + to={`/${perspective}`} + isActive={(match, location) => location.pathname.startsWith(`/${perspective}`)} + activeClassName={classes.appBarButtonActive} + > + {perspective} + </Button> + )} </div> <div className={classes.sectionMobile}> <IconButton aria-haspopup="true" onClick={this.handleMobileMenuOpen} color="inherit"> @@ -277,7 +189,6 @@ class TopBar extends React.Component { </div> </Toolbar> </AppBar> - {renderMenu} {renderMobileMenu} </div> ); @@ -289,42 +200,3 @@ TopBar.propTypes = { }; export default withStyles(styles)(TopBar); - -// <IconButton -// className={classes.menuButton} -// color="inherit" -// aria-label="Menu" -// onClick={this.handleClick} -// > -// <MenuIcon /> -// </IconButton> -// -// <Menu -// id="simple-menu" -// anchorEl={anchorEl} -// open={Boolean(anchorEl)} -// onClose={this.handleClose} -// > -// <div className={classes.menuContent}> -// -// -// <FormControl component="fieldset" className={classes.formControl}> -// <FormLabel component="legend">Map mode</FormLabel> -// <RadioGroup -// className={classes.formGroup} -// aria-label="Map mode" -// name="map" -// value={this.props.mapMode} -// onChange={this.handleChange} -// > -// <FormControlLabel value="cluster" control={<Radio />} label="Clustered markers" /> -// <FormControlLabel value="noCluster" control={<Radio />} label="Markers" /> -// -// </RadioGroup> -// </FormControl> -// -// -// -// </div> -// -// </Menu>