Skip to content

Commit

Permalink
Revert "feat: Delete old search components"
Browse files Browse the repository at this point in the history
This reverts commit 158b726.
  • Loading branch information
zatteo committed Dec 20, 2024
1 parent 5cdf986 commit 3feced1
Show file tree
Hide file tree
Showing 15 changed files with 1,101 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/assets/icons/icon-search-empty.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/modules/search/components/AppBarSearch.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { render, screen } from '@testing-library/react'
import React from 'react'

import CozyClient from 'cozy-client'

import AppBarSearch from 'modules/search/components/AppBarSearch'
import AppLike from 'test/components/AppLike'

it('should display the Searchbar', () => {
const client = new CozyClient({})
render(
<AppLike client={client}>
<AppBarSearch />
</AppLike>
)
expect(screen.getByPlaceholderText('Search anything')).toBeInTheDocument()
})
148 changes: 148 additions & 0 deletions src/modules/search/components/BarSearchAutosuggest.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import cx from 'classnames'
import React, { useState } from 'react'
import Autosuggest from 'react-autosuggest'

import { models, useClient } from 'cozy-client'
import { isFlagshipApp } from 'cozy-device-helper'
import { useWebviewIntent } from 'cozy-intent'
import List from 'cozy-ui/transpiled/react/List'

import { SHARED_DRIVES_DIR_ID } from 'constants/config'
import BarSearchInputGroup from 'modules/search/components/BarSearchInputGroup'
import SuggestionItem from 'modules/search/components/SuggestionItem'
import SuggestionListSkeleton from 'modules/search/components/SuggestionListSkeleton'
import useSearch from 'modules/search/hooks/useSearch'

import styles from 'modules/search/components/styles.styl'

const BarSearchAutosuggest = ({ t }) => {
const webviewIntent = useWebviewIntent()
const client = useClient()

const [input, setInput] = useState('')
const [searchTerm, setSearchTerm] = useState('')
const { suggestions, hasSuggestions, isBusy, query, makeIndexes } =
useSearch(searchTerm)
const [focused, setFocused] = useState(false)

const theme = {
container: 'u-w-100',
suggestionsContainer:
styles['bar-search-autosuggest-suggestions-container'],
suggestionsContainerOpen:
styles['bar-search-autosuggest-suggestions-container--open'],
suggestionsList: styles['bar-search-autosuggest-suggestions-list']
}

const onSuggestionsFetchRequested = ({ value }) => {
setSearchTerm(value)
}
const onSuggestionsClearRequested = () => {
setSearchTerm('')
}

const cleanSearch = () => {
setInput('')
setSearchTerm('')
}

const onSuggestionSelected = async (event, { suggestion }) => {
// Open the shared drive in a new tab
if (suggestion.parentUrl?.includes(SHARED_DRIVES_DIR_ID)) {
window.open(`/#/external/${suggestion.id}`, '_blank')
return cleanSearch()
}

let url = `${window.location.origin}/#${suggestion.url}`
if (suggestion.openOn === 'notes') {
url = await models.note.fetchURL(client, {
id: suggestion.url.substr(3)
})
}

if (url) {
if (isFlagshipApp()) {
webviewIntent.call('openApp', url, { slug: suggestion.openOn })
} else {
window.location.assign(url)
}
} else {
// eslint-disable-next-line no-console
console.error(`openSuggestion (${suggestion.name}) could not be executed`)
}
cleanSearch()
}

// We want the user to find folders in which he can then navigate into, so we return the path here
const getSuggestionValue = suggestion => suggestion.subtitle

const renderSuggestion = suggestion => {
return (
<SuggestionItem
suggestion={suggestion}
query={query}
onParentOpened={cleanSearch}
/>
)
}

const inputProps = {
placeholder: t('searchbar.placeholder'),
value: input,
onChange: (event, { newValue }) => {
setInput(newValue)
},
onFocus: () => {
makeIndexes()
setFocused(true)
},
onBlur: () => setFocused(false)
}

const renderInputComponent = inputProps => (
<BarSearchInputGroup isInputNotEmpty={input !== ''} onClean={cleanSearch}>
<input {...inputProps} />
</BarSearchInputGroup>
)

const renderSuggestionsContainer = ({ containerProps, children }) => {
return <List {...containerProps}>{children}</List>
}

const hasNoSearchResult = searchTerm !== '' && focused && !hasSuggestions

return (
<div className={styles['bar-search-container']} role="search">
<Autosuggest
theme={theme}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
renderInputComponent={renderInputComponent}
renderSuggestionsContainer={renderSuggestionsContainer}
inputProps={inputProps}
focusInputOnSuggestionClick={false}
/>
{hasNoSearchResult && !isBusy && (
<div
className={cx(
styles['bar-search-autosuggest-status-container'],
styles['--empty']
)}
>
{t('searchbar.empty', { query })}
</div>
)}
{hasNoSearchResult && isBusy && (
<div className={styles['bar-search-autosuggest-status-container']}>
<SuggestionListSkeleton />
</div>
)}
</div>
)
}

export default BarSearchAutosuggest
43 changes: 43 additions & 0 deletions src/modules/search/components/BarSearchInputGroup.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'

import Icon from 'cozy-ui/transpiled/react/Icon'
import IconButton from 'cozy-ui/transpiled/react/IconButton'
import CrossCircleOutlineIcon from 'cozy-ui/transpiled/react/Icons/CrossCircleOutline'
import Magnifier from 'cozy-ui/transpiled/react/Icons/Magnifier'
import InputGroup from 'cozy-ui/transpiled/react/InputGroup'

import styles from 'modules/search/components/styles.styl'

const BarSearchInputGroup = ({
children,
isMobile,
onClean,
isInputNotEmpty
}) => {
return (
<InputGroup
fullwidth={true}
className={styles['bar-search-input-group']}
prepend={
!isMobile ? (
<Icon
icon={Magnifier}
className={styles['bar-search-input-group-append']}
aria-hidden="true"
/>
) : null
}
append={
isInputNotEmpty ? (
<IconButton size="medium" onClick={onClean}>
<Icon icon={CrossCircleOutlineIcon} />
</IconButton>
) : null
}
>
{children}
</InputGroup>
)
}

export default BarSearchInputGroup
44 changes: 44 additions & 0 deletions src/modules/search/components/SearchEmpty.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'

import Grid from 'cozy-ui/transpiled/react/Grid'
import Icon from 'cozy-ui/transpiled/react/Icon'
import Typography from 'cozy-ui/transpiled/react/Typography'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'

import searchEmptyIllustration from 'assets/icons/icon-search-empty.svg'

const SearchEmpty = ({ query }) => {
const { t } = useI18n()

return (
<Grid
container
direction="column"
justifyContent="center"
alignItems="center"
className="u-m-auto u-maw-5 u-ta-center"
spacing={1}
>
<Grid item>
<Icon
width={96}
height={96}
icon={searchEmptyIllustration}
aria-hidden="true"
/>
</Grid>
<Grid item>
<Typography variant="h3">
{t('search.empty.title', { query })}
</Typography>
</Grid>
<Grid item>
<Typography variant="body1" color="textSecondary">
{t('search.empty.subtitle', { query })}
</Typography>
</Grid>
</Grid>
)
}

export default SearchEmpty
63 changes: 63 additions & 0 deletions src/modules/search/components/SuggestionItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useCallback } from 'react'

import ListItem from 'cozy-ui/transpiled/react/ListItem'
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'

import { SHARED_DRIVES_DIR_ID } from 'constants/config'
import FileIconMime from 'modules/filelist/icons/FileIconMime'
import FileIconShortcut from 'modules/filelist/icons/FileIconShortcut'
import SuggestionItemTextHighlighted from 'modules/search/components/SuggestionItemTextHighlighted'
import SuggestionItemTextSecondary from 'modules/search/components/SuggestionItemTextSecondary'

const SuggestionItem = ({
suggestion,
query,
onClick,
onParentOpened,
isMobile = false
}) => {
const openSuggestion = useCallback(() => {
if (typeof onClick == 'function') {
onClick(suggestion)
}
}, [onClick, suggestion])

const file = {
class: suggestion.class,
type: suggestion.type,
mime: suggestion.mime,
name: suggestion.title.replace(/\.url$/, ''), // Not using `splitFileName()` because we don't have access to the full file here.
parentUrl: suggestion.parentUrl
}

return (
<ListItem button onClick={openSuggestion}>
<ListItemIcon>
{file.class === 'shortcut' ? (
<FileIconShortcut file={file} />
) : (
<FileIconMime file={file} isEncrypted={suggestion.isEncrypted} />
)}
</ListItemIcon>
<ListItemText
primary={
<SuggestionItemTextHighlighted text={file.name} query={query} />
}
secondary={
file.parentUrl?.includes(SHARED_DRIVES_DIR_ID) ? null : (
<SuggestionItemTextSecondary
text={suggestion.subtitle}
url={suggestion.parentUrl}
query={query}
onOpened={onParentOpened}
isMobile={isMobile}
/>
)
}
/>
</ListItem>
)
}

export default SuggestionItem
44 changes: 44 additions & 0 deletions src/modules/search/components/SuggestionItemSkeleton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'

import ListItem from 'cozy-ui/transpiled/react/ListItem'
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
import Skeleton from 'cozy-ui/transpiled/react/Skeleton'

const SuggestionItemSkeleton = () => {
return (
<ListItem>
<ListItemIcon>
<Skeleton
width={32}
height={32}
variant="rect"
animation="wave"
className="u-bdrs-4"
/>
</ListItemIcon>
<ListItemText
primary={
<Skeleton
width={196}
height={8}
variant="rect"
animation="wave"
className="u-bdrs-3 u-mb-half"
/>
}
secondary={
<Skeleton
width={96}
height={8}
variant="rect"
animation="wave"
className="u-bdrs-3"
/>
}
/>
</ListItem>
)
}

export default SuggestionItemSkeleton
Loading

0 comments on commit 3feced1

Please sign in to comment.