mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
live filtering of search results
This commit is contained in:
parent
bab254e106
commit
e9dfd37e3d
2740
client/__fixtures__/search.json
Normal file
2740
client/__fixtures__/search.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,16 +1,12 @@
|
|||||||
|
import searchMock from '../__fixtures__/search.json'
|
||||||
|
|
||||||
const oceanMock = {
|
const oceanMock = {
|
||||||
ocean: {
|
ocean: {
|
||||||
accounts: {
|
accounts: {
|
||||||
list: () => ['xxx', 'xxx']
|
list: () => ['xxx', 'xxx']
|
||||||
},
|
},
|
||||||
aquarius: {
|
aquarius: {
|
||||||
queryMetadata: () => {
|
queryMetadata: () => searchMock
|
||||||
return {
|
|
||||||
results: [],
|
|
||||||
totalResults: 1,
|
|
||||||
totalPages: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
assets: {
|
assets: {
|
||||||
query: () => {
|
query: () => {
|
||||||
|
@ -17,6 +17,8 @@ const AssetTeaser = ({
|
|||||||
list?: boolean
|
list?: boolean
|
||||||
minimal?: boolean
|
minimal?: boolean
|
||||||
}) => {
|
}) => {
|
||||||
|
if (!asset.findServiceByType) return null
|
||||||
|
|
||||||
const { attributes } = asset.findServiceByType('metadata')
|
const { attributes } = asset.findServiceByType('metadata')
|
||||||
const { main, additionalInformation } = attributes
|
const { main, additionalInformation } = attributes
|
||||||
|
|
||||||
|
39
client/src/routes/Search/FilterItem.module.scss
Normal file
39
client/src/routes/Search/FilterItem.module.scss
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@import '../../styles/variables';
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.option {
|
||||||
|
padding-top: $spacer / 10;
|
||||||
|
padding-bottom: $spacer / 10;
|
||||||
|
padding-right: $spacer / 6;
|
||||||
|
text-align: left;
|
||||||
|
color: $brand-grey-light;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
transition: .1s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
composes: item;
|
||||||
|
|
||||||
|
.option {
|
||||||
|
color: $brand-grey-dark;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
border-left: .3rem solid $brand-black;
|
||||||
|
padding-left: $spacer / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: $spacer / 10;
|
||||||
|
font-size: $font-size-h3;
|
||||||
|
color: inherit;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
51
client/src/routes/Search/FilterItem.tsx
Normal file
51
client/src/routes/Search/FilterItem.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import shortid from 'shortid'
|
||||||
|
import Button from '../../components/atoms/Button'
|
||||||
|
import styles from './FilterItem.module.scss'
|
||||||
|
|
||||||
|
export default function FilterItem({
|
||||||
|
isActive,
|
||||||
|
filter,
|
||||||
|
filterByCategory,
|
||||||
|
filterByLicense,
|
||||||
|
option
|
||||||
|
}: {
|
||||||
|
isActive: boolean
|
||||||
|
filter: any
|
||||||
|
option: string
|
||||||
|
filterByCategory(category: string): void
|
||||||
|
filterByLicense(license: string): void
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={shortid.generate()}
|
||||||
|
className={isActive ? styles.active : styles.item}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
link
|
||||||
|
className={styles.option}
|
||||||
|
onClick={() =>
|
||||||
|
filter.label === 'Category'
|
||||||
|
? filterByCategory(option)
|
||||||
|
: filterByLicense(option)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{option}{' '}
|
||||||
|
</Button>
|
||||||
|
{isActive && (
|
||||||
|
<Button
|
||||||
|
link
|
||||||
|
className={styles.cancel}
|
||||||
|
title="Clear"
|
||||||
|
onClick={() =>
|
||||||
|
filter.label === 'Category'
|
||||||
|
? filterByCategory('')
|
||||||
|
: filterByLicense('')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
@ -3,43 +3,9 @@
|
|||||||
.filter {
|
.filter {
|
||||||
ul {
|
ul {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|
||||||
li {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.option {
|
|
||||||
padding-top: $spacer / 10;
|
|
||||||
padding-bottom: $spacer / 10;
|
|
||||||
padding-right: $spacer / 6;
|
|
||||||
text-align: left;
|
|
||||||
color: $brand-grey-light;
|
|
||||||
font-size: $font-size-small;
|
|
||||||
transition: .1s ease-out;
|
|
||||||
|
|
||||||
.active & {
|
|
||||||
color: $brand-grey-dark;
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
border-left: .3rem solid $brand-black;
|
|
||||||
padding-left: $spacer / 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: $spacer / 10;
|
|
||||||
font-size: $font-size-h3;
|
|
||||||
color: inherit;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filterTitle {
|
.filterTitle {
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
color: $brand-grey-light;
|
color: $brand-grey-light;
|
||||||
|
22
client/src/routes/Search/Filters.test.tsx
Normal file
22
client/src/routes/Search/Filters.test.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { User } from '../../context'
|
||||||
|
import { userMockConnected } from '../../../__mocks__/user-mock'
|
||||||
|
import Filters from './Filters'
|
||||||
|
|
||||||
|
describe('Filters', () => {
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const { debug, container } = render(
|
||||||
|
<User.Provider value={userMockConnected}>
|
||||||
|
<Filters
|
||||||
|
category="Architecture"
|
||||||
|
license="Public"
|
||||||
|
results={[]}
|
||||||
|
filterByCategory={() => null}
|
||||||
|
filterByLicense={() => null}
|
||||||
|
/>
|
||||||
|
</User.Provider>
|
||||||
|
)
|
||||||
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
@ -1,8 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import shortid from 'shortid'
|
import shortid from 'shortid'
|
||||||
import Button from '../../components/atoms/Button'
|
|
||||||
import styles from './Filters.module.scss'
|
import styles from './Filters.module.scss'
|
||||||
import data from '../../data/form-publish.json'
|
import data from '../../data/form-publish.json'
|
||||||
|
import FilterItem from './FilterItem'
|
||||||
|
import { DDO } from '@oceanprotocol/squid'
|
||||||
|
|
||||||
const { steps } = data
|
const { steps } = data
|
||||||
|
|
||||||
@ -19,10 +20,11 @@ const labelLicense =
|
|||||||
steps[2].fields.license.label
|
steps[2].fields.license.label
|
||||||
|
|
||||||
function getFilterMetadata(results: any[]) {
|
function getFilterMetadata(results: any[]) {
|
||||||
const filterCategories: string[] = []
|
let filterCategories: string[] = []
|
||||||
const filterLicenses: string[] = []
|
let filterLicenses: string[] = []
|
||||||
|
|
||||||
results.map(asset => {
|
results.map((asset: DDO) => {
|
||||||
|
if (!asset.findServiceByType) return null
|
||||||
const { metadata } = asset.findServiceByType('Metadata')
|
const { metadata } = asset.findServiceByType('Metadata')
|
||||||
const { categories, license } = metadata.base
|
const { categories, license } = metadata.base
|
||||||
categories && filterCategories.push(categories[0])
|
categories && filterCategories.push(categories[0])
|
||||||
@ -30,6 +32,10 @@ function getFilterMetadata(results: any[]) {
|
|||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// remove duplicates
|
||||||
|
filterCategories = Array.from(new Set(filterCategories))
|
||||||
|
filterLicenses = Array.from(new Set(filterLicenses))
|
||||||
|
|
||||||
return { filterCategories, filterLicenses }
|
return { filterCategories, filterLicenses }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,14 +43,14 @@ export default function Filters({
|
|||||||
category,
|
category,
|
||||||
license,
|
license,
|
||||||
results,
|
results,
|
||||||
setCategory,
|
filterByCategory,
|
||||||
setLicense
|
filterByLicense
|
||||||
}: {
|
}: {
|
||||||
category: string
|
category: string
|
||||||
license: string
|
license: string
|
||||||
results: any[]
|
results: any[]
|
||||||
setCategory(category: string): void
|
filterByCategory(category: string): void
|
||||||
setLicense(license: string): void
|
filterByLicense(license: string): void
|
||||||
}) {
|
}) {
|
||||||
const { filterCategories, filterLicenses } = getFilterMetadata(results)
|
const { filterCategories, filterLicenses } = getFilterMetadata(results)
|
||||||
|
|
||||||
@ -70,41 +76,13 @@ export default function Filters({
|
|||||||
license === option
|
license === option
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<FilterItem
|
||||||
key={shortid.generate()}
|
isActive={isActive}
|
||||||
className={
|
filter={filter}
|
||||||
isActive
|
filterByCategory={filterByCategory}
|
||||||
? styles.active
|
filterByLicense={filterByLicense}
|
||||||
: undefined
|
option={option}
|
||||||
}
|
/>
|
||||||
>
|
|
||||||
<Button
|
|
||||||
link
|
|
||||||
className={styles.option}
|
|
||||||
onClick={() =>
|
|
||||||
filter.label === 'Category'
|
|
||||||
? setCategory(option)
|
|
||||||
: setLicense(option)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{option}{' '}
|
|
||||||
</Button>
|
|
||||||
{isActive && (
|
|
||||||
<Button
|
|
||||||
link
|
|
||||||
className={styles.cancel}
|
|
||||||
title="Clear"
|
|
||||||
onClick={() =>
|
|
||||||
filter.label ===
|
|
||||||
'Category'
|
|
||||||
? setCategory('')
|
|
||||||
: setLicense('')
|
|
||||||
}
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
|
32
client/src/routes/Search/Results.module.scss
Normal file
32
client/src/routes/Search/Results.module.scss
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@import '../../styles/variables';
|
||||||
|
|
||||||
|
.resultsTitle {
|
||||||
|
color: $brand-grey-light;
|
||||||
|
font-size: $font-size-h3;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: $spacer;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $brand-grey-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.results {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-gap: $spacer;
|
||||||
|
|
||||||
|
@media (min-width: $break-point--medium) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: $break-point--large) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: $spacer * 4;
|
||||||
|
color: $brand-grey-light;
|
||||||
|
}
|
46
client/src/routes/Search/Results.tsx
Normal file
46
client/src/routes/Search/Results.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import shortid from 'shortid'
|
||||||
|
import AssetTeaser from '../../components/molecules/AssetTeaser'
|
||||||
|
import Pagination from '../../components/molecules/Pagination'
|
||||||
|
import styles from './Results.module.scss'
|
||||||
|
|
||||||
|
export default function Results({
|
||||||
|
title,
|
||||||
|
results,
|
||||||
|
totalResults,
|
||||||
|
totalPages,
|
||||||
|
currentPage,
|
||||||
|
handlePageClick
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
results: any[]
|
||||||
|
totalResults: number
|
||||||
|
totalPages: number
|
||||||
|
currentPage: number
|
||||||
|
handlePageClick(data: { selected: number }): Promise<any>
|
||||||
|
}) {
|
||||||
|
return results && results.length ? (
|
||||||
|
<>
|
||||||
|
<h2 className={styles.resultsTitle}>
|
||||||
|
{totalResults} results for <span>{title}</span>
|
||||||
|
</h2>
|
||||||
|
<div className={styles.results}>
|
||||||
|
{results.map((asset: any) => (
|
||||||
|
<AssetTeaser key={shortid.generate()} asset={asset} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
totalPages={totalPages}
|
||||||
|
currentPage={currentPage}
|
||||||
|
handlePageClick={handlePageClick}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className={styles.empty}>
|
||||||
|
<p>No Data Sets Found.</p>
|
||||||
|
<Link to="/publish">+ Publish A Data Set</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -9,16 +9,16 @@ export default function Sidebar({
|
|||||||
category,
|
category,
|
||||||
license,
|
license,
|
||||||
results,
|
results,
|
||||||
setCategory,
|
filterByCategory,
|
||||||
setLicense
|
filterByLicense
|
||||||
}: {
|
}: {
|
||||||
search: string
|
search: string
|
||||||
inputChange: any
|
inputChange: any
|
||||||
category: string
|
category: string
|
||||||
license: string
|
license: string
|
||||||
results: any[]
|
results: any[]
|
||||||
setCategory(category: string): void
|
filterByCategory(category: string): void
|
||||||
setLicense(license: string): void
|
filterByLicense(license: string): void
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<aside className={styles.sidebar}>
|
<aside className={styles.sidebar}>
|
||||||
@ -40,8 +40,8 @@ export default function Sidebar({
|
|||||||
category={category}
|
category={category}
|
||||||
license={license}
|
license={license}
|
||||||
results={results}
|
results={results}
|
||||||
setCategory={setCategory}
|
filterByCategory={filterByCategory}
|
||||||
setLicense={setLicense}
|
filterByLicense={filterByLicense}
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
|
@ -9,34 +9,3 @@
|
|||||||
grid-template-columns: 1fr 3fr;
|
grid-template-columns: 1fr 3fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.resultsTitle {
|
|
||||||
color: $brand-grey-light;
|
|
||||||
font-size: $font-size-h3;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: $spacer;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: $brand-grey-dark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.results {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-gap: $spacer;
|
|
||||||
|
|
||||||
@media (min-width: $break-point--medium) {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: $break-point--large) {
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: $spacer * 4;
|
|
||||||
color: $brand-grey-light;
|
|
||||||
}
|
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import React, { PureComponent, ChangeEvent } from 'react'
|
import React, { PureComponent, ChangeEvent } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
|
||||||
import queryString from 'query-string'
|
import queryString from 'query-string'
|
||||||
import { History, Location } from 'history'
|
import { History, Location } from 'history'
|
||||||
import shortid from 'shortid'
|
import { Logger, DDO } from '@oceanprotocol/squid'
|
||||||
import { Logger } from '@oceanprotocol/squid'
|
|
||||||
import Spinner from '../../components/atoms/Spinner'
|
import Spinner from '../../components/atoms/Spinner'
|
||||||
import Route from '../../components/templates/Route'
|
import Route from '../../components/templates/Route'
|
||||||
import { User } from '../../context'
|
import { User } from '../../context'
|
||||||
import AssetTeaser from '../../components/molecules/AssetTeaser'
|
|
||||||
import Pagination from '../../components/molecules/Pagination'
|
|
||||||
import styles from './index.module.scss'
|
|
||||||
import Content from '../../components/atoms/Content'
|
import Content from '../../components/atoms/Content'
|
||||||
import withTracker from '../../hoc/withTracker'
|
import withTracker from '../../hoc/withTracker'
|
||||||
import Sidebar from './Sidebar'
|
import Sidebar from './Sidebar'
|
||||||
|
import Results from './Results'
|
||||||
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
interface SearchProps {
|
interface SearchProps {
|
||||||
location: Location
|
location: Location
|
||||||
@ -21,6 +18,7 @@ interface SearchProps {
|
|||||||
|
|
||||||
interface SearchState {
|
interface SearchState {
|
||||||
results: any[]
|
results: any[]
|
||||||
|
resultsFiltered: any[]
|
||||||
totalResults: number
|
totalResults: number
|
||||||
offset: number
|
offset: number
|
||||||
totalPages: number
|
totalPages: number
|
||||||
@ -38,6 +36,7 @@ class Search extends PureComponent<SearchProps, SearchState> {
|
|||||||
|
|
||||||
public state = {
|
public state = {
|
||||||
results: [],
|
results: [],
|
||||||
|
resultsFiltered: [],
|
||||||
totalResults: 0,
|
totalResults: 0,
|
||||||
offset: 25,
|
offset: 25,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
@ -112,6 +111,7 @@ class Search extends PureComponent<SearchProps, SearchState> {
|
|||||||
const search = await ocean.assets.query(searchQuery)
|
const search = await ocean.assets.query(searchQuery)
|
||||||
this.setState({
|
this.setState({
|
||||||
results: search.results,
|
results: search.results,
|
||||||
|
resultsFiltered: search.results,
|
||||||
totalResults: search.totalResults,
|
totalResults: search.totalResults,
|
||||||
totalPages: search.totalPages,
|
totalPages: search.totalPages,
|
||||||
isLoading: false
|
isLoading: false
|
||||||
@ -161,32 +161,37 @@ class Search extends PureComponent<SearchProps, SearchState> {
|
|||||||
this.setState({ category, isLoading: true }, () => this.searchAssets())
|
this.setState({ category, isLoading: true }, () => this.searchAssets())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public filterByCategory = (category: string) => {
|
||||||
|
const resultsFiltered: any[] = this.state.results.filter(
|
||||||
|
(asset: DDO) => {
|
||||||
|
const { metadata } = asset.findServiceByType('Metadata')
|
||||||
|
const { categories } = metadata.base
|
||||||
|
if (!categories) return true
|
||||||
|
|
||||||
|
return category === '' ? true : categories.includes(category)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
this.setState({ resultsFiltered, category })
|
||||||
|
}
|
||||||
|
|
||||||
|
public filterByLicense = (name: string) => {
|
||||||
|
const resultsFiltered: any[] = this.state.results.filter(
|
||||||
|
(asset: any) => {
|
||||||
|
const { metadata } = asset.findServiceByType('Metadata')
|
||||||
|
const { license } = metadata.base
|
||||||
|
|
||||||
|
return name === '' ? true : license === name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
this.setState({ resultsFiltered, license: name })
|
||||||
|
}
|
||||||
|
|
||||||
public setLicense = (license: string) => {
|
public setLicense = (license: string) => {
|
||||||
this.setState({ license, isLoading: true }, () => this.searchAssets())
|
this.setState({ license, isLoading: true }, () => this.searchAssets())
|
||||||
}
|
}
|
||||||
|
|
||||||
public renderResults = () =>
|
|
||||||
this.state.results && this.state.results.length ? (
|
|
||||||
<>
|
|
||||||
<div className={styles.results}>
|
|
||||||
{this.state.results.map((asset: any) => (
|
|
||||||
<AssetTeaser key={shortid.generate()} asset={asset} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Pagination
|
|
||||||
totalPages={this.state.totalPages}
|
|
||||||
currentPage={this.state.currentPage}
|
|
||||||
handlePageClick={this.handlePageClick}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className={styles.empty}>
|
|
||||||
<p>No Data Sets Found.</p>
|
|
||||||
<Link to="/publish">+ Publish A Data Set</Link>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {
|
const {
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -194,7 +199,10 @@ class Search extends PureComponent<SearchProps, SearchState> {
|
|||||||
totalResults,
|
totalResults,
|
||||||
search,
|
search,
|
||||||
category,
|
category,
|
||||||
license
|
license,
|
||||||
|
resultsFiltered,
|
||||||
|
totalPages,
|
||||||
|
currentPage
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -207,26 +215,24 @@ class Search extends PureComponent<SearchProps, SearchState> {
|
|||||||
category={category}
|
category={category}
|
||||||
results={results}
|
results={results}
|
||||||
license={license}
|
license={license}
|
||||||
setCategory={this.setCategory}
|
filterByCategory={this.filterByCategory}
|
||||||
setLicense={this.setLicense}
|
filterByLicense={this.filterByLicense}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Spinner message="Searching..." />
|
<Spinner message="Searching..." />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Results
|
||||||
<h2 className={styles.resultsTitle}>
|
title={decodeURIComponent(
|
||||||
{totalResults} results for{' '}
|
search || category
|
||||||
<span>
|
)}
|
||||||
{decodeURIComponent(
|
results={resultsFiltered}
|
||||||
search || category
|
totalResults={totalResults}
|
||||||
)}
|
totalPages={totalPages}
|
||||||
</span>
|
currentPage={currentPage}
|
||||||
</h2>
|
handlePageClick={this.handlePageClick}
|
||||||
|
/>
|
||||||
{this.renderResults()}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user