Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion src/components/orgs/OrgHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { OperationsContext } from '../app/LayoutContext';
import CommonTabs from '../common/CommonTabs';
import DeleteEntityDialog from '../common/DeleteEntityDialog'
import Search from '../search/Search';
import useDefaultFiltersOpen from '../../hooks/useDefaultFiltersOpen';
import Error40X from '../errors/Error40X';
import OrgOverview from './OrgOverview';
import OrgSummary from './OrgSummary';
Expand All @@ -25,6 +26,7 @@ const OrgHome = () => {
const [members, setMembers] = React.useState([])
const [deleteOrg, setDeleteOrg] = React.useState(false)
const [tab, setTab] = React.useState(findTab)
const [defaultFiltersOpen, onFiltersOpenChange] = useDefaultFiltersOpen()
const { setAlert } = React.useContext(OperationsContext);
const { pins: bookmarks, canPin, togglePin, deletePin } = usePins(params?.org ? {type: 'org', id: params.org} : false)

Expand Down Expand Up @@ -108,7 +110,8 @@ const OrgHome = () => {
pins={bookmarks}
canPin={canPin}
onPinToggle={togglePin}
defaultFiltersOpen={false}
defaultFiltersOpen={defaultFiltersOpen}
onFiltersOpenChange={onFiltersOpenChange}
nested
noTabs
filtersHeightToSubtract={280}
Expand Down
5 changes: 4 additions & 1 deletion src/components/repos/RepoHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { WHITE } from '../../common/colors';
import { OperationsContext } from '../app/LayoutContext';
import CommonTabs from '../common/CommonTabs';
import Search from '../search/Search';
import useDefaultFiltersOpen from '../../hooks/useDefaultFiltersOpen';
import DeleteEntityDialog from '../common/DeleteEntityDialog'
import ConceptHome from '../concepts/ConceptHome';
import MappingHome from '../mappings/MappingHome';
Expand Down Expand Up @@ -86,6 +87,7 @@ const RepoHome = () => {
const [showSummary, setShowSummary] = React.useState(true)
const [addReferencesOpen, setAddReferencesOpen] = React.useState(false)
const [searchReloadKey, setSearchReloadKey] = React.useState(0)
const [defaultFiltersOpen, onFiltersOpenChange] = useDefaultFiltersOpen()
const [expansions, setExpansions] = React.useState([])
const [expansionsLoading, setExpansionsLoading] = React.useState(false)
const [selectedExpansion, setSelectedExpansion] = React.useState(false)
Expand Down Expand Up @@ -591,7 +593,8 @@ const RepoHome = () => {
summary={repoSummary || repo?.summary}
resource={tab}
url={getSearchURL()}
defaultFiltersOpen={false}
defaultFiltersOpen={defaultFiltersOpen}
onFiltersOpenChange={onFiltersOpenChange}
nested
repo={repo}
noTabs
Expand Down
5 changes: 4 additions & 1 deletion src/components/search/Search.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,10 @@ const Search = props => {
onSelect={newSelected => onSelectItem(newSelected)}
selectedToShow={showItem}
onShowItemSelect={onShowItemSelect}
onFiltersToggle={() => setOpenFilters(!openFilters)}
onFiltersToggle={() => {
setOpenFilters(!openFilters)
props.onFiltersOpenChange?.(!openFilters)
}}
onDisplayChange={onDisplayChange}
resultContainerStyle={props.resultContainerStyle}
resultSize={props.resultSize}
Expand Down
4 changes: 2 additions & 2 deletions src/components/search/SearchControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ const SearchControls = ({ disabled, onDisplayChange, display, order, orderBy, on
<div className='col-xs-12 padding-0' style={{display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}>
{
hasSortOptions(sortConfig) &&
<Button disabled={Boolean(disabled)} variant='contained' color='default' size='small' style={{textTransform: 'none'}} endIcon={<DownIcon fontSize='inherit' />} onClick={onSortClick}>
<Button disabled={Boolean(disabled)} variant='contained' color='default' size='small' style={{textTransform: 'none', whiteSpace: 'nowrap'}} endIcon={<DownIcon fontSize='inherit' />} onClick={onSortClick}>
{t('search.sort_by')}
</Button>
}
{
showDisplayControl &&
<Button id="display-menu" disabled={Boolean(disabled)} variant='contained' color='default' size='small' style={{textTransform: 'none', marginLeft: '8px'}} endIcon={<DownIcon fontSize='inherit' />} onClick={onDisplayClick}>
<Button id="display-menu" disabled={Boolean(disabled)} variant='contained' color='default' size='small' style={{textTransform: 'none', whiteSpace: 'nowrap', marginLeft: '8px'}} endIcon={<DownIcon fontSize='inherit' />} onClick={onDisplayClick}>
{t('search.display')}
</Button>
}
Expand Down
20 changes: 10 additions & 10 deletions src/components/search/SearchResults.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ import React from 'react';
import { useTranslation } from 'react-i18next'
import { useHistory } from 'react-router-dom';
import Box from '@mui/material/Box';
import Badge from '@mui/material/Badge';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import Button from '@mui/material/Button';
import FilterListIcon from '@mui/icons-material/FilterList';
import AddIcon from '@mui/icons-material/PlaylistAddOutlined';
import RepeatIcon from '@mui/icons-material/Repeat';
import CloneIcon from '@mui/icons-material/ControlPointDuplicate';
import TablePagination from '@mui/material/TablePagination';
import Skeleton from '@mui/material/Skeleton';
import { isNumber, isNaN, flatten, values, uniqBy, compact, pick, keys } from 'lodash'
import { isNumber, isNaN, flatten, values, uniqBy, compact, pick, keys, omit } from 'lodash'
import SearchControls from './SearchControls';
import NoResults from './NoResults';
import TableResults from './TableResults';
Expand All @@ -24,15 +22,18 @@ import CloneToSourceDialog from '../repos/CloneToSourceDialog';
import MappingIcon from '../mappings/MappingIcon';
import GAService from '../../services/GAService';
import { getSortConfig } from './sortConfig'
import { EXCLUDE_FILTER_KEY } from './ResultConstants'
import { resolveColumns } from './columns'
import { isLoggedIn, currentUserHasAccess } from '../../common/utils';
import { createSimilarRepoHref } from '../repos/utils';
import { MAX_SEARCH_RESULT_WINDOW } from '../../common/constants';

const ResultsToolbar = props => {
const { t } = useTranslation()
const { numSelected, title, onFiltersToggle, disabled, isFilterable, onDisplayChange, display, order, orderBy, onOrderByChange, sortConfig, noCardDisplay, toolbarControl, appliedFilters, availableFilterFields, openFilters, bulkActions, leftControls, displayOptions, resource } = props;
const countableFilters = availableFilterFields ? pick(appliedFilters, availableFilterFields) : appliedFilters
const filtersCount = resource === 'references' ? flatten(values(countableFilters))?.length : flatten(values(countableFilters).map(v => values(v))).length
// Reference searches fetch no facets, so their filters can't be narrowed to facet fields.
const countableFilters = (availableFilterFields && resource !== 'references') ? pick(appliedFilters, availableFilterFields) : appliedFilters
const filtersCount = resource === 'references' ? flatten(values(countableFilters))?.length : flatten(values(countableFilters).map(v => values(omit(v, EXCLUDE_FILTER_KEY)))).length
return (
<Toolbar
sx={[{
Expand All @@ -49,11 +50,9 @@ const ResultsToolbar = props => {
>
{
isFilterable &&
<IconButton style={{marginRight: '4px', ...(filtersCount > 0 ? {backgroundColor: 'rgba(73, 69, 79, 0.12)'} : {})}} onClick={onFiltersToggle} disabled={Boolean(disabled)}>
<Badge badgeContent={openFilters ? undefined : filtersCount} color='primary'>
<FilterListIcon sx={{color: '#000'}} />
</Badge>
</IconButton>
<Button disabled={Boolean(disabled)} variant='contained' color='default' size='small' style={{textTransform: 'none', whiteSpace: 'nowrap', flexShrink: 0, marginRight: '4px'}} startIcon={<FilterListIcon fontSize='inherit' />} onClick={onFiltersToggle} aria-expanded={Boolean(openFilters)}>
{t('search.filters')}{filtersCount > 0 ? ` (${filtersCount})` : ''}
</Button>
}
{
leftControls?.length > 0 &&
Expand Down Expand Up @@ -405,6 +404,7 @@ const SearchResults = props => {
numSelected={selected.length}
title={getTitle()}
onFiltersToggle={props.onFiltersToggle}
openFilters={props.openFilters}
disabled={props.noResults}
isFilterable={props.isFilterable}
onDisplayChange={onDisplayChange}
Expand Down
5 changes: 4 additions & 1 deletion src/components/users/UserHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { COLORS } from '../../common/colors'
import APIService from '../../services/APIService'
import CommonTabs from '../common/CommonTabs';
import Search from '../search/Search';
import useDefaultFiltersOpen from '../../hooks/useDefaultFiltersOpen';
import Error40X from '../errors/Error40X';
import UserOverview from './UserOverview';
import UserSummary from './UserSummary'
Expand All @@ -19,6 +20,7 @@ const UserHome = () => {
const params = useParams()
const history = useHistory()
const [tab, setTab] = React.useState(findTab || 'overview')
const [defaultFiltersOpen, onFiltersOpenChange] = useDefaultFiltersOpen()
const [user, setUser] = React.useState({})
const [status, setStatus] = React.useState(false)
const { pins: bookmarks, canPin, togglePin, deletePin } = usePins(params?.user ? {type: 'user', id: params.user} : false)
Expand Down Expand Up @@ -122,7 +124,8 @@ const UserHome = () => {
filtersHeightToSubtract={baseHeightToDeduct}
resultContainerStyle={{height: `calc(var(--app-height) - ${baseHeightToDeduct}px - 88px)`, overflow: 'auto'}}
containerStyle={{padding: 0}}
defaultFiltersOpen={false}
defaultFiltersOpen={defaultFiltersOpen}
onFiltersOpenChange={onFiltersOpenChange}
resultSize='medium'
excludedColumns={['owner']}
/>
Expand Down
16 changes: 16 additions & 0 deletions src/hooks/useDefaultFiltersOpen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import useMediaQuery from '@mui/material/useMediaQuery';

// For pages that embed Search (repo pages, org and user repository lists): the filter
// panel starts open on wide screens and closed on narrow ones. Once the user opens or
// closes it, that choice is kept while the page stays mounted, including when Search
// remounts on a tab or version change. A window resize never opens or closes it.
// Returns [defaultFiltersOpen, onFiltersOpenChange] to pass to Search.
const useDefaultFiltersOpen = () => {
// Search reads defaultFiltersOpen once, when it mounts, so the first render needs the real width.
const isWide = useMediaQuery(theme => theme.breakpoints.up('lg'), {noSsr: true}) // eslint-disable-line spellcheck/spell-checker
const [choice, setChoice] = React.useState(null)
return [choice === null ? isWide : choice, setChoice]
}

export default useDefaultFiltersOpen;
Loading