Files
shields/frontend/components/customizer/customizer.js
2019-02-18 18:01:44 -05:00

160 lines
4.1 KiB
JavaScript

import React from 'react'
import PropTypes from 'prop-types'
import clipboardCopy from 'clipboard-copy'
import { staticBadgeUrl } from '../../lib/badge-url'
import { generateMarkup } from '../../lib/generate-image-markup'
import { Badge } from '../common'
import PathBuilder from './path-builder'
import QueryStringBuilder from './query-string-builder'
import RequestMarkupButtom from './request-markup-button'
import CopiedContentIndicator from './copied-content-indicator'
export default class Customizer extends React.Component {
static propTypes = {
// This is an item from the `examples` array within the
// `serviceDefinition` schema.
// https://github.com/badges/shields/blob/master/services/service-definitions.js
baseUrl: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
pattern: PropTypes.string.isRequired,
exampleNamedParams: PropTypes.object.isRequired,
exampleQueryParams: PropTypes.object.isRequired,
initialStyle: PropTypes.string,
}
indicatorRef = React.createRef()
state = {
path: '',
link: '',
message: undefined,
}
get baseUrl() {
const { baseUrl } = this.props
if (baseUrl) {
return baseUrl
} else {
// Default to the current hostname for when there is no `BASE_URL` set
// at build time (as in most PaaS deploys).
const { protocol, hostname } = window.location
return `${protocol}//${hostname}`
}
}
generateBuiltBadgeUrl() {
const { baseUrl } = this
const { path, queryString } = this.state
const suffix = queryString ? `?${queryString}` : ''
return `${baseUrl}${path}.svg${suffix}`
}
renderLivePreview() {
// There are some usability issues here. It would be better if the message
// changed from a validation error to a loading message once the
// parameters were filled in, and also switched back to loading when the
// parameters changed.
const { baseUrl } = this.props
const { pathIsComplete } = this.state
let src
if (pathIsComplete) {
src = this.generateBuiltBadgeUrl()
} else {
src = staticBadgeUrl(
baseUrl,
'preview',
'some parameters missing',
'lightgray'
)
}
return (
<p>
<Badge display="block" src={src} />
</p>
)
}
copyMarkup = async markupFormat => {
const { title } = this.props
const { link } = this.state
const builtBadgeUrl = this.generateBuiltBadgeUrl()
const markup = generateMarkup({
badgeUrl: builtBadgeUrl,
link,
title,
markupFormat,
})
try {
await clipboardCopy(markup)
} catch (e) {
this.setState({
message: 'Copy failed',
markup,
})
return
}
this.setState({ markup })
this.indicatorRef.current.trigger()
}
renderMarkupAndLivePreview() {
const { indicatorRef } = this
const { markup, message, pathIsComplete } = this.state
return (
<div>
{this.renderLivePreview()}
<CopiedContentIndicator ref={indicatorRef} copiedContent="Copied">
<RequestMarkupButtom
isDisabled={!pathIsComplete}
onMarkupRequested={this.copyMarkup}
/>
</CopiedContentIndicator>
{message && (
<div>
<p>{message}</p>
<p>Markup: {markup}</p>
</div>
)}
</div>
)
}
handlePathChange = ({ path, isComplete }) => {
this.setState({ path, pathIsComplete: isComplete })
}
handleQueryStringChange = ({ queryString, isComplete }) => {
this.setState({ queryString })
}
render() {
const {
pattern,
exampleNamedParams,
exampleQueryParams,
initialStyle,
} = this.props
return (
<form action="">
<PathBuilder
pattern={pattern}
exampleParams={exampleNamedParams}
onChange={this.handlePathChange}
/>
<QueryStringBuilder
exampleParams={exampleQueryParams}
initialStyle={initialStyle}
onChange={this.handleQueryStringChange}
/>
<div>{this.renderMarkupAndLivePreview()}</div>
</form>
)
}
}