1
0
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:
Onuwa Nnachi Isaac 2019-09-13 00:51:26 +01:00 committed by Andy Tudhope
parent e6e63f3b2a
commit 38cc479a54
10 changed files with 138 additions and 125 deletions

0
logs.log Normal file
View File

View File

@ -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,

View File

@ -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

View File

@ -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 = {

View File

@ -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;
}

View File

@ -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} &nbsp;&rarr;
&nbsp;&rarr; </a>
</a>
</>
</div> </div>
</div> </div>
) )

View File

@ -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"

View File

@ -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;
} }

View File

@ -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 />

View File

@ -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;
} }