Skip to content

Commit

Permalink
The "MORE" content-type filter contains all not-hidden items. (#1580)
Browse files Browse the repository at this point in the history
* (temporary) Fetch content types.

* Use "HideByDefault" category and refactor.

* E2e tests of the type filter "More".

* refactor

* Use fallback if there is no Categories field.

* some fixes

* sort by displayname

* sort ctds by name

* sorty on client side

---------

Co-authored-by: Ádám Hassan <[email protected]>
Co-authored-by: vargajoe <[email protected]>
  • Loading branch information
3 people authored Nov 20, 2023
1 parent 9d9acc6 commit 14d7b49
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 25 deletions.
48 changes: 48 additions & 0 deletions apps/sensenet/cypress/e2e/search/search.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,52 @@ describe('Search', () => {
.then((fullname) => expect(fullname).to.eq('Business Cat'))
})
})

context('more contentTypes filter', () => {
const term = 'admin*'
before(() => {
cy.login()
cy.visit(pathWithQueryParams({ path: '/', newParams: { repoUrl: Cypress.env('repoUrl') } }))
})
beforeEach(() => {
cy.get('[data-test="sensenet-logo"]').click()
cy.get('[data-test="search-button"]')
.click()
.get('[data-test="command-box"] input')
.type(term, { delay: 250 })
.get('[data-test="search-suggestion-list"] ul')
.children()
.as('search')
.first()
.click()
.location()
.should((loc) => {
expect(loc.pathname).to.eq(PATHS.search.appPath)
expect(loc.search).to.eq(`?term=${term}`)
})
})

it('result contains users and groups', () => {
cy.get('[data-test="table-cell-admin"]').should('exist')
cy.get('[data-test="table-cell-administrators"]').should('exist')
cy.get('[data-test="table-cell-captain-picard"]').should('not.exist')
})

it('the "more" menu contains more than 20 items including "group" and "user"', () => {
cy.get('[data-test="more-type-filter-button"]').click()
cy.get('[id="more-type-filter"]').contains('li', 'User')
cy.get('[id="more-type-filter"]').contains('li', 'Group')
cy.get('[data-test="more-menu-item-user"]').parent().children().its('length').should('be.gt', 20)
// press <ESC> to hide the menu to unblock the UI
cy.get('body').trigger('keydown', { keyCode: 27 })
})

it('result contains one user after use the filter', () => {
cy.get('[data-test="more-type-filter-button"]').click().get('[data-test="more-menu-item-user"]').click()
// "MORE" changed to "USER"
cy.get('[data-test="more-type-filter-button"]').contains('User')
// "Administrators" disappeared
cy.get('[data-test="table-cell-administrators"]').should('not.exist')
})
})
})
79 changes: 63 additions & 16 deletions apps/sensenet/src/components/search/filters/type-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import Image from '@material-ui/icons/Image'
import InsertDriveFile from '@material-ui/icons/InsertDriveFile'
import Person from '@material-ui/icons/Person'
import Search from '@material-ui/icons/Search'
import React, { useState } from 'react'
import { ConstantContent } from '@sensenet/client-core'
import { GenericContent } from '@sensenet/default-content-types'
import { useRepository } from '@sensenet/hooks-react'
import React, { useEffect, useState } from 'react'
import { useSearch } from '../../../context/search'
import { useLocalization } from '../../../hooks'

Expand Down Expand Up @@ -75,14 +78,54 @@ const useStyles = makeStyles(() => {
})
})

type moreOptionsItem = {
name: string
type: string
}

export const TypeFilter = () => {
const repo = useRepository()
const classes = useStyles()
const localization = useLocalization().search.filters.type
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)

const searchState = useSearch()
const [otherContentTypes, setOtherContentTypes] = useState<moreOptionsItem[]>([])

useEffect(() => {
const ac = new AbortController()
const categoryField = repo.schemas.getFieldTypeByName('Categories')
const fetchData = async () => {
try {
if (categoryField) {
const response = await repo.loadCollection<GenericContent>({
path: ConstantContent.PORTAL_ROOT.Path,
oDataOptions: {
query: "-Categories:'*HideByDefault*' +TypeIs:'ContentType' .AUTOFILTERS:OFF",
select: ['Type', 'DisplayName'],
orderby: 'Name',
},
requestInit: { signal: ac.signal },
})
const items: moreOptionsItem[] = response.d.results.map((item) => ({
name: item.DisplayName ?? item.Name,
type: item.Name,
}))
setOtherContentTypes(items)
} else {
setOtherContentTypes(moreOptions)
}
} catch (error) {
console.error('Error fetching data:', error)
}
}
fetchData()

return () => {
ac.abort()
}
}, [repo])

const [[activeFromMore], othersFromMore] = moreOptions.reduce(
const [[activeFromMore], othersFromMore] = otherContentTypes.reduce(
([pass, fail], filter) => {
return filter.name === searchState.filters.type.name ? [[...pass, filter], fail] : [pass, [...fail, filter]]
},
Expand All @@ -108,6 +151,7 @@ export const TypeFilter = () => {
))}

<Button
data-test="more-type-filter-button"
aria-controls="more-type-filter"
aria-haspopup="true"
variant="outlined"
Expand All @@ -116,7 +160,7 @@ export const TypeFilter = () => {
onClick={(event) => {
setAnchorEl(event.currentTarget)
}}>
{activeFromMore ? localization[activeFromMore.name as keyof typeof localization] : localization.more}
{activeFromMore ? activeFromMore.name : localization.more}
</Button>
<Menu
id="more-type-filter"
Expand All @@ -133,18 +177,21 @@ export const TypeFilter = () => {
vertical: 'top',
horizontal: 'right',
}}>
{(othersFromMore as Filter[]).map((filter) => (
<MenuItem
key={filter.name}
onClick={() => {
setAnchorEl(null)
searchState.setFilters((filters) =>
filters.type.name === filter.name ? filters : { ...filters, type: filter },
)
}}>
{localization[filter.name as keyof typeof localization]}
</MenuItem>
))}
{(othersFromMore as Filter[])
.sort((a, b) => a.name.localeCompare(b.name))
.map((filter) => (
<MenuItem
key={filter.name}
data-test={`more-menu-item-${filter.name.toLowerCase()}`}
onClick={() => {
setAnchorEl(null)
searchState.setFilters((filters) =>
filters.type.name === filter.name ? filters : { ...filters, type: filter },
)
}}>
{filter.name}
</MenuItem>
))}
</Menu>
</div>
)
Expand Down
16 changes: 7 additions & 9 deletions apps/sensenet/src/components/search/search-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,13 @@ export const SearchBar = () => {
className={classes.inputButton}
aria-label={localization.clearTerm}
title={localization.clearTerm}
onClick={() => null}>
<Cancel
onClick={() => {
if (searchInputRef.current) {
searchInputRef.current.value = ''
}
searchState.setTerm('')
}}
/>
onClick={() => {
if (searchInputRef.current) {
searchInputRef.current.value = ''
}
searchState.setTerm('')
}}>
<Cancel />
</IconButton>
)}
<IconButton
Expand Down

0 comments on commit 14d7b49

Please sign in to comment.