* Display suggested badges * E2e test for badge suggestion * Suggest resource returns example with pattern * Do not require preview in MarkupModalContent * Skip integration test for suggestion * Unmodifiable path in customizer * Use suggested link * Allow to change suggested badges * Enable skipped test * Enable skipped test * Code refactoring * Code refactoring * Code refactoring * Code refactoring * Code refactoring * Code refactoring * Unused code removed * Unused code removed * getExampleWithServiceByPattern helper added * BadgeExamples uses examples instead of services definitions * Revert "getExampleWithServiceByPattern helper added" This reverts commit80839fd705. * style removed from example * example.exact replaced with preview.buildFromExample * keywords are required again * Code refactoring * More e2e tests for suggestion feature * Code refactoring * Build add with a base url * showActualParams -> isPrefilled * A new schema for BadgeExamples * Link moved to queryParams * Updated documentation for the suggest reponse format * Link moved to queryParams - another test updated * Revert "Link moved to queryParams - another test updated" This reverts commitb5f811bb07. * Revert "Link moved to queryParams" This reverts commit3b54c6d2b4. * Disable changes in path in suggested badges * 'link' element documentation restored
113 lines
2.7 KiB
JavaScript
113 lines
2.7 KiB
JavaScript
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>
|
|
)
|
|
}
|
|
}
|