Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalog, Search: add help dropdown to the index landing page #1838

Merged
merged 16 commits into from
Nov 2, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions catalog/app/containers/NavBar/Help.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import cx from 'classnames'
import * as React from 'react'
import * as M from '@material-ui/core'
import * as Lab from '@material-ui/lab'
Expand All @@ -9,14 +8,6 @@ const ES_V = '6.7'
const ES_REF = `https://www.elastic.co/guide/en/elasticsearch/reference/${ES_V}/query-dsl-query-string-query.html#query-string-syntax`

const useStyles = M.makeStyles((t) => ({
root: {
padding: `0 ${t.spacing(4)}px`,
overflowY: 'auto',

[t.breakpoints.down('xs')]: {
padding: `0 ${t.spacing(1)}px`,
},
},
group: {
marginTop: t.spacing(2),
},
Expand Down Expand Up @@ -247,11 +238,15 @@ function DocsExternalLink() {
)
}

export default function Help({ className, onQuery, ...props }) {
function normalizeSyntaxItem(s) {
return `${s.replace(/\s/g, '')} `
}

export default function Help({ className, onQuery }) {
const classes = useStyles()

return (
<M.Paper className={cx(classes.root, className)} {...props}>
<div className={className}>
<Lab.TreeView
defaultCollapseIcon={<M.Icon>arrow_drop_down</M.Icon>}
defaultExpandIcon={<M.Icon>arrow_right</M.Icon>}
Expand All @@ -277,7 +272,7 @@ export default function Help({ className, onQuery, ...props }) {
key={item.syntax}
className={classes.item}
button
onClick={() => onQuery(item.syntax)}
onClick={() => onQuery(normalizeSyntaxItem(item.syntax))}
>
<Item item={item} />
</M.ListItem>
Expand All @@ -288,6 +283,6 @@ export default function Help({ className, onQuery, ...props }) {
</Lab.TreeView>

<DocsExternalLink />
</M.Paper>
</div>
)
}
19 changes: 14 additions & 5 deletions catalog/app/containers/NavBar/Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ const useStyles = M.makeStyles((t) => ({
opacity: 0.8,
},
help: {
left: 0,
maxHeight: '400px',
maxHeight: t.spacing(50),
overflowY: 'auto',
padding: t.spacing(0, 4),

[t.breakpoints.down('xs')]: {
padding: t.spacing(0, 1),
},
},
helpWrapper: {
left: 0,
position: 'absolute',
right: 0,
top: t.spacing(5),
Expand Down Expand Up @@ -109,6 +116,7 @@ function SearchBox({
const {
disabled: disabledCls,
expanded: expandedCls,
helpWrapper: helpWrapperCls,
help: helpCls,
hidden: hiddenCls,
iconized: iconizedCls,
Expand All @@ -129,7 +137,9 @@ function SearchBox({
<div className={wrapperCls}>
<M.MuiThemeProvider theme={style.appTheme}>
<M.Fade in={helpOpened}>
<SearchHelp className={helpCls} onQuery={onQuery} />
<M.Paper className={helpWrapperCls}>
<SearchHelp className={helpCls} onQuery={onQuery} />
</M.Paper>
</M.Fade>
</M.MuiThemeProvider>

Expand Down Expand Up @@ -208,8 +218,7 @@ function State({ query, makeUrl, children, onFocus, onBlur }) {

const handleQuery = React.useCallback(
(strPart) => {
const normalized = strPart.replace(/\s/g, '')
change(`${value} ${normalized}`)
change(`${value} ${strPart}`)
},
[value],
)
Expand Down
127 changes: 93 additions & 34 deletions catalog/app/website/pages/OpenLanding/Search/Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { push } from 'connected-react-router/esm/immutable'
import * as React from 'react'
import * as redux from 'react-redux'
import * as M from '@material-ui/core'
import { fade } from '@material-ui/core/styles'
import * as Lab from '@material-ui/lab'

import * as style from 'constants/style'
import * as BucketConfig from 'utils/BucketConfig'
import * as NamedRoutes from 'utils/NamedRoutes'
import img2x from 'utils/img2x'

import SearchHelp from 'containers/NavBar/Help'
import Dots from 'website/components/Backgrounds/Dots'

import bg from './search-bg.png'
Expand All @@ -30,6 +32,24 @@ const useStyles = M.makeStyles((t) => ({
top: 0,
},
},
help: {
maxHeight: '490px',
overflowY: 'auto',
padding: t.spacing(0, 2),

[t.breakpoints.down('xs')]: {
maxHeight: '400px',
padding: t.spacing(0, 2),
},
},
helpWrapper: {
borderRadius: t.spacing(0.5),
marginTop: t.spacing(8),
maxWidth: 690,
position: 'absolute',
width: '100%',
zIndex: 1,
},
inner: {
alignItems: 'center',
display: 'flex',
Expand All @@ -48,34 +68,40 @@ const useStyles = M.makeStyles((t) => ({
fontSize: t.typography.pxToRem(20),
lineHeight: t.typography.pxToRem(60),
maxWidth: 750,
overflow: 'hidden',
paddingLeft: 0,
width: '100%',
},
inputInput: {
height: 'auto',
paddingBottom: 0,
paddingLeft: t.spacing(9),
paddingLeft: t.spacing(15),
paddingRight: t.spacing(4),
paddingTop: 0,
},
adornment: {
inputOptions: {
borderColor: t.palette.grey[300],
borderRadius: 0,
borderWidth: '0 1px 0 0',
color: t.palette.grey[600],
justifyContent: 'center',
left: t.spacing(3),
pointerEvents: 'none',
position: 'absolute',
paddingBottom: t.spacing(1.5),
paddingLeft: t.spacing(3),
paddingRight: t.spacing(1.5),
paddingTop: t.spacing(1.5),
},
hintContainer: {
maxWidth: 750,
position: 'relative',
inputOptionsSelected: {
boxShadow: 'inset -1px 0 4px rgba(0, 0, 0, 0.2)',
},
inputWrapper: {
display: 'flex',
justifyContent: 'center',
width: '100%',
},
hint: {
...t.typography.body2,
color: fade(t.palette.common.white, 0.6),
lineHeight: 1,
adornment: {
justifyContent: 'center',
position: 'absolute',
right: 30,
top: 12,
height: 'auto',
maxHeight: '100%',
},
stats: {
display: 'flex',
Expand Down Expand Up @@ -123,11 +149,23 @@ export default function Search() {
const bucketCount = BucketConfig.useRelevantBucketConfigs().length

const [value, change] = React.useState('')
const [helpOpened, setHelpOpened] = React.useState(false)

const onChange = React.useCallback((evt) => {
change(evt.target.value)
}, [])

const onQuery = React.useCallback(
(strPart) => {
change(`${value} ${strPart}`)
},
[value],
)

const onToggleOptions = React.useCallback(() => setHelpOpened(!helpOpened), [
helpOpened,
])

const onKeyDown = React.useCallback(
(evt) => {
// eslint-disable-next-line default-case
Expand All @@ -148,24 +186,45 @@ export default function Search() {
<Dots />
<M.Container maxWidth="lg" className={classes.container}>
<div className={classes.inner}>
<M.InputBase
{...{ value, onChange, onKeyDown }}
startAdornment={
<M.InputAdornment className={classes.adornment}>
<M.Icon fontSize="large">search</M.Icon>
</M.InputAdornment>
}
classes={{ root: classes.inputRoot, input: classes.inputInput }}
placeholder="Search"
/>
<div className={classes.hintContainer}>
<a
className={classes.hint}
href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-simple-query-string-query.html#_simple_query_string_syntax"
>
Search syntax
</a>
</div>
<M.ClickAwayListener onClickAway={() => setHelpOpened(false)}>
<div className={classes.inputWrapper}>
<M.InputBase
{...{ value, onChange, onKeyDown }}
startAdornment={
<M.InputAdornment className={classes.adornment}>
<M.MuiThemeProvider theme={style.appTheme}>
<Lab.ToggleButton
className={classes.inputOptions}
size="large"
value="help"
selected={helpOpened}
onChange={onToggleOptions}
classes={{
selected: classes.inputOptionsSelected,
}}
>
<M.Icon fontSize="large">search</M.Icon>
<M.Icon fontSize="large">
{helpOpened ? 'arrow_drop_up' : 'arrow_drop_down'}
</M.Icon>
</Lab.ToggleButton>
</M.MuiThemeProvider>
</M.InputAdornment>
}
classes={{ root: classes.inputRoot, input: classes.inputInput }}
placeholder="Search"
/>

<M.MuiThemeProvider theme={style.appTheme}>
<M.Fade in={helpOpened}>
<M.Paper className={classes.helpWrapper}>
<SearchHelp className={classes.help} onQuery={onQuery} />
</M.Paper>
</M.Fade>
</M.MuiThemeProvider>
</div>
</M.ClickAwayListener>

<div className={classes.stats}>
<div className={classes.stat}>
<div className={classes.statValue}>10.2 Billion</div>
Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

## Catalog, Lambdas
* [Added] Retry logic for failed queries, minimize load on ES for sample, images
* [Added] Search help dropdown for the index landing page ([1838](https://github.com/quiltdata/quilt/pull/1838))
fiskus marked this conversation as resolved.
Show resolved Hide resolved
overviews ([#1864](https://github.com/quiltdata/quilt/pull/1864/))
* [Fixed] Incomplete package stats for empty packages in es/indexer Lambda ([#1869](https://github.com/quiltdata/quilt/pull/1869))

Expand Down