forked from badges/shields
-
Notifications
You must be signed in to change notification settings - Fork 1
/
suggestion-and-search.js
112 lines (98 loc) · 2.74 KB
/
suggestion-and-search.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import React from 'react'
import PropTypes from 'prop-types'
import fetchPonyfill from 'fetch-ponyfill'
import debounce from 'lodash.debounce'
import BadgeExamples from './badge-examples'
import { BlockInput } from './common'
export default class SuggestionAndSearch extends React.Component {
static propTypes = {
queryChanged: PropTypes.func.isRequired,
onBadgeClick: PropTypes.func.isRequired,
baseUrl: PropTypes.string.isRequired,
}
constructor(props) {
super(props)
this.queryChangedDebounced = debounce(props.queryChanged, 50, {
leading: true,
})
}
state = {
isUrl: false,
inProgress: false,
projectUrl: null,
suggestions: [],
}
queryChanged(query) {
const isUrl = query.startsWith('https://') || query.startsWith('http://')
this.setState({
isUrl,
projectUrl: isUrl ? query : null,
})
this.queryChangedDebounced(query)
}
getSuggestions() {
this.setState({ inProgress: true }, async () => {
const { baseUrl } = this.props
const { projectUrl } = this.state
const url = `${baseUrl}/$suggest/v1?url=${encodeURIComponent(projectUrl)}`
const fetch = window.fetch || fetchPonyfill
const res = await fetch(url)
let suggestions
try {
const json = await res.json()
// This doesn't validate the response. The default value here prevents
// a crash if the server returns {"err":"Disallowed"}.
suggestions = json.suggestions || []
} catch (e) {
suggestions = []
}
this.setState({ inProgress: false, suggestions })
})
}
renderSuggestions() {
const { baseUrl } = this.props
let { suggestions } = this.state
if (suggestions.length === 0) {
return null
}
suggestions = suggestions.map(
({ title, link, example, preview, documentation }) => ({
title,
link,
example,
preview: { ...preview, buildFromExample: true },
documentation,
})
)
return (
<BadgeExamples
baseUrl={baseUrl}
examples={suggestions}
onClick={this.props.onBadgeClick}
/>
)
}
render() {
return (
<section>
<form action="javascript:void 0" autoComplete="off">
<BlockInput
autoFocus
autofill="off"
onChange={event => this.queryChanged(event.target.value)}
placeholder="search / project URL"
/>
<br />
<button
disabled={this.state.inProgress}
hidden={!this.state.isUrl}
onClick={event => this.getSuggestions(event.target.value)}
>
Suggest badges
</button>
</form>
{this.renderSuggestions()}
</section>
)
}
}