@bigfishtv/cockpit
Version:
124 lines (107 loc) • 3.46 kB
JavaScript
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import keycode from 'keycode'
import { titleCase } from '../../utils/stringUtils'
import Button from '../button/Button'
import AutosuggestInput from '../input/AutosuggestInput'
import Icon from '../Icon'
const DefaultCell = ({ defaultValue, model, onChange, onEdit }) => (
<div className="cell" onDoubleClick={onEdit}>
<div className="cell-icon">
<Icon name="link" size="18" />
</div>
<div className="cell-content">{defaultValue ? defaultValue : titleCase(model)}</div>
<div className="cell-control">
<Button size="icon" onClick={() => onChange(null)}>
<Icon name="close" size="18" />
</Button>
</div>
</div>
)
export default class AutosuggestModelInput extends Component {
static propTypes = {
model: PropTypes.string.isRequired,
queryUrl: PropTypes.string,
onChange: PropTypes.func,
autoSaveInput: PropTypes.bool,
autoSaveTransform: PropTypes.func,
}
static defaultProps = {
Cell: DefaultCell,
onAdd: () => console.warn('[ModelAutosuggestInput] no onAdd prop provided'),
onEdit: () => console.warn('[ModelAutosuggestInput] no onEdit prop provided'),
renderSuggestion: (suggestion, input) => <div>{suggestion.name || suggestion.title || suggestion.toString()}</div>,
autoSaveInput: false,
autoSaveTransform: value => value,
}
constructor(props) {
super(props)
this.inputFocused = false
this.suggestionsTotal = 0
this.state = { input: '' }
}
componentDidMount() {
window.addEventListener('keydown', this.handleKeyDown)
}
handleKeyDown = event => {
const { autoSaveInput } = this.props
if (keycode(event) == 'enter' && autoSaveInput && this.inputFocused && this.state.input && !this.suggestionsTotal) {
event.preventDefault()
this.handleAdd()
}
}
handleSuggestion(suggestion, event) {
this.props.onChange(suggestion)
}
handleAdd = () => {
Promise.resolve(this.props.autoSaveTransform(this.state.input))
.then(transformedInput => {
this.handleSuggestion(transformedInput)
this.props.onAdd(transformedInput)
})
.catch(error => {
alert(error.message)
})
}
handleRemove() {
if ('formValue' in this.props) this.props.formValue.update(null)
else console.warn('[ModelAutosuggestInput] no onRemove prop provided')
}
queryUrl(props) {
return props.queryUrl ? props.queryUrl : props.model ? '/admin/' + props.model + '/search.json' : null
}
render() {
const { Cell, model, onAdd, renderSuggestion, autoSaveInput, autoSaveTransform, onRemove, ...rest } = this.props
if (!this.props.value) {
return (
<div className="input-group">
<AutosuggestInput
{...rest}
queryUrl={this.queryUrl(this.props)}
onChange={this.props.onChange}
renderSuggestion={renderSuggestion}
onSuggestionsChange={suggestions => (this.suggestionsTotal = suggestions.length)}
onInputChange={input => this.setState({ input })}
onInputFocus={() => (this.inputFocused = true)}
onInputBlur={() => (this.inputFocused = false)}
/>
{autoSaveInput && this.state.input && !this.suggestionsTotal && (
<Button text="Add" onClick={this.handleAdd} />
)}
</div>
)
}
if (model) {
return (
<Cell
value={this.props.value}
model={model}
onDoubleClick={this.props.onEdit}
onRemove={onRemove ? onRemove : () => this.handleRemove()}
{...rest}
/>
)
}
return null
}
}