mirror of
https://github.com/dap-ps/discover.git
synced 2025-02-12 01:06:49 +00:00
Rework desktop search experience
This commit is contained in:
parent
e6e63f3b2a
commit
38cc479a54
@ -67,7 +67,7 @@ class DiscoverService extends BlockchainService {
|
|||||||
.call({ from: this.sharedContext.account })
|
.call({ from: this.sharedContext.account })
|
||||||
|
|
||||||
const dappMetadata = dappsCache[dapp.metadata]
|
const dappMetadata = dappsCache[dapp.metadata]
|
||||||
if (dappMetadata) {
|
if (typeof dappMetadata !== 'undefined') {
|
||||||
delete dappsCache[dapp.metadata]
|
delete dappsCache[dapp.metadata]
|
||||||
dapp.metadata = dappMetadata.details
|
dapp.metadata = dappMetadata.details
|
||||||
dapp.metadata.status = dappMetadata.status
|
dapp.metadata.status = dappMetadata.status
|
||||||
@ -79,7 +79,7 @@ class DiscoverService extends BlockchainService {
|
|||||||
Object.keys(dappsCache).forEach(metadataHash => {
|
Object.keys(dappsCache).forEach(metadataHash => {
|
||||||
const dappMetadata = dappsCache[metadataHash]
|
const dappMetadata = dappsCache[metadataHash]
|
||||||
|
|
||||||
if (dappMetadata.status == 'APPROVED') {
|
if (dappMetadata.status == 'NEW') {
|
||||||
dapps.push({
|
dapps.push({
|
||||||
developer: '',
|
developer: '',
|
||||||
id: dappMetadata.compressedMetadata,
|
id: dappMetadata.compressedMetadata,
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
const axios = require('axios');
|
const axios = require('axios')
|
||||||
|
|
||||||
const DEFAULT_HEADERS = {
|
const DEFAULT_HEADERS = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json',
|
||||||
};
|
}
|
||||||
|
|
||||||
const executeRequest = async function(method, url, reqStruct) {
|
const executeRequest = async function(method, url, reqStruct) {
|
||||||
return axios({
|
return axios({
|
||||||
method,
|
method,
|
||||||
url,
|
url: `http://localhost:4000${url}`,
|
||||||
data: {
|
data: {
|
||||||
...reqStruct.body
|
...reqStruct.body,
|
||||||
},
|
},
|
||||||
headers: {
|
headers: {
|
||||||
...DEFAULT_HEADERS,
|
...DEFAULT_HEADERS,
|
||||||
...reqStruct.headers
|
...reqStruct.headers,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
class HTTPClient {
|
class HTTPClient {
|
||||||
static async postRequest(url, body, headers = '') {
|
static async postRequest(url, body, headers = '') {
|
||||||
return executeRequest('POST', url, { body, headers });
|
return executeRequest('POST', url, { body, headers })
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getRequest(url, headers = '') {
|
static async getRequest(url, headers = '') {
|
||||||
return executeRequest('GET', url, { headers });
|
return executeRequest('GET', url, { headers })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HTTPClient;
|
export default HTTPClient
|
||||||
|
@ -30,24 +30,23 @@ class Search extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { searchStyle, onSearch, searchResultStyle } = this.props
|
const { searchStyle, searchResultStyle } = this.props
|
||||||
const { dapps, isSearching } = this.state
|
const { dapps, isSearching } = this.state
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={styles.search_container}>
|
||||||
<div className={styles.container}>
|
<img src={searchIcon} alt="Search Icon" width="16" height="16" />
|
||||||
<img src={searchIcon} alt="Search Icon" width="16" height="16" />
|
<input
|
||||||
<input
|
type="text"
|
||||||
type="text"
|
onChange={e => this.handleChange(e)}
|
||||||
onChange={e => this.handleChange(e)}
|
className={[styles.search, searchStyle].join(' ')}
|
||||||
className={[styles.search, searchStyle].join(' ')}
|
placeholder="Search Dapps"
|
||||||
placeholder="Search Dapps"
|
/>
|
||||||
onSearch={onSearch(isSearching)}
|
{isSearching && (
|
||||||
/>
|
<div className={[styles.searchResults, searchResultStyle].join(' ')}>
|
||||||
</div>
|
<SearchResultItem showActionButtons={false} dapps={dapps} />
|
||||||
<div className={[styles.searchResults, searchResultStyle].join(' ')}>
|
</div>
|
||||||
<SearchResultItem showActionButtons={false} dapps={dapps} />
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +55,6 @@ Search.propTypes = {
|
|||||||
searchStyle: PropTypes.string,
|
searchStyle: PropTypes.string,
|
||||||
searchResultStyle: PropTypes.string,
|
searchResultStyle: PropTypes.string,
|
||||||
dappState: PropTypes.instanceOf(DappState).isRequired,
|
dappState: PropTypes.instanceOf(DappState).isRequired,
|
||||||
onSearch: PropTypes.func.isRequired,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Search.defaultProps = {
|
Search.defaultProps = {
|
||||||
|
@ -1,29 +1,96 @@
|
|||||||
@import '../../styles/_variables.scss';
|
@import '../../styles/_variables.scss';
|
||||||
|
|
||||||
.container {
|
@media (min-width: $desktop) {
|
||||||
display: flex;
|
.search_container {
|
||||||
flex: 1;
|
height: calculateRem(20);
|
||||||
border: 1px solid #eef2f5;
|
cursor: pointer;
|
||||||
border-radius: calculateRem(4);
|
border-radius: calculateRem(40);
|
||||||
overflow: hidden;
|
background: #ffffff;
|
||||||
margin: calculateRem(16);
|
padding: calculateRem(10);
|
||||||
img {
|
position: absolute;
|
||||||
padding: calculateRem(5);
|
box-shadow: 0px 4px 12px rgba(0, 34, 51, 0.08),
|
||||||
align-self: center;
|
0px 2px 4px rgba(0, 34, 51, 0.16);
|
||||||
|
right: calculateRem(20);
|
||||||
|
top: calculateRem(60);
|
||||||
|
display: flex;
|
||||||
|
z-index: 1;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
width: calculateRem(240);
|
||||||
|
.search {
|
||||||
|
width: calculateRem(240);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.searchResults {
|
||||||
|
z-index: 99;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: calculateRem(39);
|
||||||
|
background: #ffffff;
|
||||||
|
left: 0;
|
||||||
|
border-bottom-left-radius: calculateRem(5);
|
||||||
|
border-bottom-right-radius: calculateRem(5);
|
||||||
|
box-shadow: 0 0 0 rgba(0, 34, 51, 0.08),
|
||||||
|
0px 2px 4px rgba(0, 34, 51, 0.16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-size: calculateRem(15);
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
display: none;
|
||||||
|
outline: none;
|
||||||
|
transition: 0.4s;
|
||||||
|
line-height: calculateRem(15);
|
||||||
|
width: 0px;
|
||||||
|
&::placeholder {
|
||||||
|
color: #939ba1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.searchResults {
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
@media (max-width: $desktop) {
|
||||||
font-family: 'Inter';
|
.search_container {
|
||||||
font-size: calculateRem(15);
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border: none;
|
border: 1px solid #eef2f5;
|
||||||
outline: none;
|
border-radius: calculateRem(4);
|
||||||
&::placeholder {
|
overflow: hidden;
|
||||||
color: #939ba1;
|
margin: calculateRem(16);
|
||||||
|
img {
|
||||||
|
padding: calculateRem(5);
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-size: calculateRem(15);
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
&::placeholder {
|
||||||
|
color: #939ba1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchResults {
|
||||||
|
z-index: 99;
|
||||||
|
top: calculateRem(100);
|
||||||
|
width: 92vw;
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-attachment: fixed;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchResults {
|
|
||||||
z-index: 99;
|
|
||||||
}
|
|
||||||
|
@ -21,19 +21,17 @@ const SearchResultItem = props => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.column}>
|
<div className={styles.column}>
|
||||||
<>
|
<h2 className={styles.header}>{name}</h2>
|
||||||
<h2 className={styles.header}>{name}</h2>
|
<p
|
||||||
<p
|
className={styles.description}
|
||||||
className={styles.description}
|
style={{ WebkitBoxOrient: 'vertical' }}
|
||||||
style={{ WebkitBoxOrient: 'vertical' }}
|
>
|
||||||
>
|
{description}
|
||||||
{description}
|
</p>
|
||||||
</p>
|
<a className={styles.link} href={url}>
|
||||||
<a className={styles.link} href={{ url }}>
|
{url}
|
||||||
{url}
|
→
|
||||||
→
|
</a>
|
||||||
</a>
|
|
||||||
</>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,6 @@ import React from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import CategoryIcon from '../../common/components/CategoryIcon'
|
import CategoryIcon from '../../common/components/CategoryIcon'
|
||||||
import ViewAll from '../../common/components/ViewAll'
|
import ViewAll from '../../common/components/ViewAll'
|
||||||
import Search from '../../common/components/Search'
|
|
||||||
import categories from '../../common/utils/categories'
|
import categories from '../../common/utils/categories'
|
||||||
import humanise from '../../common/utils/humanise'
|
import humanise from '../../common/utils/humanise'
|
||||||
import dropdownArrows from '../../common/assets/images/dropdown-arrows.svg'
|
import dropdownArrows from '../../common/assets/images/dropdown-arrows.svg'
|
||||||
@ -11,14 +10,13 @@ import styles from './CategorySelector.module.scss'
|
|||||||
class CategorySelector extends React.Component {
|
class CategorySelector extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = { open: false, isSearching: false }
|
this.state = { open: false }
|
||||||
this.toggle = this.toggle.bind(this)
|
this.toggle = this.toggle.bind(this)
|
||||||
this.updateCategory = this.updateCategory.bind(this)
|
this.updateCategory = this.updateCategory.bind(this)
|
||||||
this.container = React.createRef()
|
this.container = React.createRef()
|
||||||
this.onClickSubmit = this.onClickSubmit.bind(this)
|
this.onClickSubmit = this.onClickSubmit.bind(this)
|
||||||
this.onClickHighestRanked = this.onClickHighestRanked.bind(this)
|
this.onClickHighestRanked = this.onClickHighestRanked.bind(this)
|
||||||
this.onClickRecentlyAdded = this.onClickRecentlyAdded.bind(this)
|
this.onClickRecentlyAdded = this.onClickRecentlyAdded.bind(this)
|
||||||
this.onSearch = this.onSearch.bind(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -45,10 +43,6 @@ class CategorySelector extends React.Component {
|
|||||||
this.setState({ open: false })
|
this.setState({ open: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch(isSearching) {
|
|
||||||
this.setState({ isSearching })
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickHighestRanked(e) {
|
onClickHighestRanked(e) {
|
||||||
const { onClickCloseDesktopMenu } = this.props
|
const { onClickCloseDesktopMenu } = this.props
|
||||||
onClickCloseDesktopMenu()
|
onClickCloseDesktopMenu()
|
||||||
@ -83,7 +77,6 @@ class CategorySelector extends React.Component {
|
|||||||
showSubmitDApp,
|
showSubmitDApp,
|
||||||
} = this.props
|
} = this.props
|
||||||
let { open } = this.state
|
let { open } = this.state
|
||||||
const { isSearching } = this.state
|
|
||||||
if (alwaysOpen === true) open = true
|
if (alwaysOpen === true) open = true
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -92,22 +85,11 @@ class CategorySelector extends React.Component {
|
|||||||
style={open ? { visible: 'block' } : { display: 'none' }}
|
style={open ? { visible: 'block' } : { display: 'none' }}
|
||||||
className={styles.open}
|
className={styles.open}
|
||||||
>
|
>
|
||||||
<Search
|
<div className={styles.openHeader}>
|
||||||
searchStyle={styles.search}
|
|
||||||
onSearch={this.onSearch}
|
|
||||||
searchResultStyle={styles.searchResult}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={styles.openHeader}
|
|
||||||
style={isSearching ? { display: 'none' } : { display: 'flex' }}
|
|
||||||
>
|
|
||||||
<h2>Categories</h2>
|
<h2>Categories</h2>
|
||||||
<ViewAll size="small" />
|
<ViewAll size="small" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className={styles.categories}>
|
||||||
className={styles.categories}
|
|
||||||
style={isSearching ? { display: 'none' } : { display: 'block' }}
|
|
||||||
>
|
|
||||||
{categories.map(c => (
|
{categories.map(c => (
|
||||||
<button
|
<button
|
||||||
className={
|
className={
|
||||||
@ -127,10 +109,7 @@ class CategorySelector extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showLists && (
|
{showLists && (
|
||||||
<div
|
<div className={styles.categories}>
|
||||||
className={styles.categories}
|
|
||||||
style={isSearching ? { display: 'none' } : { display: 'block' }}
|
|
||||||
>
|
|
||||||
<div className={`${styles.openHeader} ${styles.spacing}`}>
|
<div className={`${styles.openHeader} ${styles.spacing}`}>
|
||||||
<h2>Lists</h2>
|
<h2>Lists</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -182,7 +161,6 @@ class CategorySelector extends React.Component {
|
|||||||
className={`${styles.openButton} ${styles.submitDapp}`}
|
className={`${styles.openButton} ${styles.submitDapp}`}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={this.onClickSubmit}
|
onClick={this.onClickSubmit}
|
||||||
style={isSearching ? { display: 'none' } : { display: 'flex' }}
|
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
width="20"
|
width="20"
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
@import '../../common/styles/variables';
|
@import '../../common/styles/variables';
|
||||||
|
|
||||||
.search {
|
|
||||||
width: 85%;
|
|
||||||
margin: calculateRem(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResult {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.categories {
|
.categories {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,11 @@ import DesktopMenu from '../DesktopMenu/DesktopMenu.container'
|
|||||||
class Home extends React.Component {
|
class Home extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {}
|
||||||
isSearching: false,
|
|
||||||
}
|
|
||||||
this.onSearch = this.onSearch.bind(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch(isSearching) {
|
|
||||||
this.setState({ isSearching })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dapps } = this.props
|
const { dapps } = this.props
|
||||||
const { isSearching } = this.state
|
|
||||||
const loaded = dapps.loaded
|
const loaded = dapps.loaded
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -37,13 +29,10 @@ class Home extends React.Component {
|
|||||||
<h2 className={styles.headline}>Discover</h2>
|
<h2 className={styles.headline}>Discover</h2>
|
||||||
</div>
|
</div>
|
||||||
<DesktopMenu />
|
<DesktopMenu />
|
||||||
<div className={styles.mobileSearch}>
|
<Search
|
||||||
<Search
|
searchStyle={styles.search}
|
||||||
searchStyle={styles.search}
|
searchResultStyle={styles.searchResult}
|
||||||
searchResultStyle={styles.searchResult}
|
/>
|
||||||
onSearch={this.onSearch}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<FeaturedDapps featured={featured} />
|
<FeaturedDapps featured={featured} />
|
||||||
<Categories />
|
<Categories />
|
||||||
<HighestRanked />
|
<HighestRanked />
|
||||||
|
@ -10,10 +10,6 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobileSearch {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -22,11 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $desktop) {
|
@media (max-width: $desktop) {
|
||||||
.mobileSearch {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.searchResult {
|
.searchResult {
|
||||||
width: 98vw;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user