UNPKG

@lyra/form-builder

Version:
300 lines (244 loc) 9.76 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _searchable = require('part:@lyra/components/selects/searchable'); var _searchable2 = _interopRequireDefault(_searchable); var _default = require('part:@lyra/components/formfields/default'); var _default2 = _interopRequireDefault(_default); var _Preview = require('../../Preview'); var _Preview2 = _interopRequireDefault(_Preview); var _subscriptionManager = require('../../utils/subscriptionManager'); var _subscriptionManager2 = _interopRequireDefault(_subscriptionManager); var _PatchEvent = require('../../../PatchEvent'); var _PatchEvent2 = _interopRequireDefault(_PatchEvent); var _linkIcon = require('part:@lyra/base/link-icon'); var _linkIcon2 = _interopRequireDefault(_linkIcon); var _router = require('part:@lyra/base/router'); var _ReferenceInput = require('./styles/ReferenceInput.css'); var _ReferenceInput2 = _interopRequireDefault(_ReferenceInput); var _default3 = require('part:@lyra/components/buttons/default'); var _default4 = _interopRequireDefault(_default3); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /* eslint-disable complexity */ /*:: import type {Reference, Type, Marker} from '../../typedefs'*/ /*:: import type {ObservableI} from '../../typedefs/observable'*/ /*:: type SearchHit = { _id: string, _type: string }*/ /*:: type PreviewSnapshot = { title: string, description: string }*/ /*:: type Props = { value: ?Reference, type: Type, markers: Array<Marker>, readOnly: ?boolean, onSearch: (query: string, type: Type) => ObservableI<Array<SearchHit>>, getPreviewSnapshot: (Reference, Type) => ObservableI<PreviewSnapshot>, onChange: PatchEvent => void, level: number }*/ /*:: type State = { isFetching: boolean, hits: Array<SearchHit>, previewSnapshot: ?PreviewSnapshot, refCache: {[string]: SearchHit} }*/ const MISSING_SNAPSHOT = {}; const getInitialState = () /*: State*/ => { return { isFetching: false, hits: [], previewSnapshot: null, refCache: {} }; }; class ReferenceInput extends _react2.default.Component /*:: <Props, State>*/ { constructor(...args) { var _temp; return _temp = super(...args), this.state = getInitialState(), this.subscriptions = (0, _subscriptionManager2.default)('search', 'previewSnapshot'), this._lastQuery = '', this.handleFocus = () => { if (this._lastQuery) { this.search(this._lastQuery); } }, this.handleChange = (item /*: SearchHit*/) => { const type = this.props.type; this.props.onChange(_PatchEvent2.default.from((0, _PatchEvent.setIfMissing)({ _type: type.name, _ref: item._id }), type.weak === true ? (0, _PatchEvent.set)(true, ['_weak']) : (0, _PatchEvent.unset)(['_weak']), (0, _PatchEvent.set)(item._id, ['_ref']))); }, this.handleFixWeak = () => { const type = this.props.type; this.props.onChange(_PatchEvent2.default.from(type.weak === true ? (0, _PatchEvent.set)(true, ['_weak']) : (0, _PatchEvent.unset)(['_weak']))); }, this.handleClear = () => { this.props.onChange(_PatchEvent2.default.from((0, _PatchEvent.unset)())); }, this.handleSearch = (query /*: string*/) => { this.search(query); }, this.handleOpen = () => { this.search(''); }, this.search = (query /*: string*/) => { var _props = this.props; const type = _props.type, onSearch = _props.onSearch; this.setState({ isFetching: true }); this.subscriptions.replace('search', onSearch(query, type).subscribe((items /*: Array<SearchHit>*/) => { const updatedCache = items.reduce((cache, item) => { cache[item._id] = item; return cache; }, Object.assign({}, this.state.refCache)); this.setState({ hits: items, isFetching: false, refCache: updatedCache }); })); }, this.renderHit = (item /*: SearchHit*/) => { const type = this.getMemberTypeFor(item._type); return _react2.default.createElement(_Preview2.default, { type: type, value: item, layout: 'default' }); }, this.renderOpenItemElement = () => { const value = this.props.value; const previewSnapshot = this.state.previewSnapshot; if (!value || !value._ref || previewSnapshot === MISSING_SNAPSHOT) { return null; } return _react2.default.createElement( _router.IntentLink, { title: previewSnapshot && `Open ${previewSnapshot.title}`, intent: 'edit', params: { id: value._ref } }, _react2.default.createElement(_linkIcon2.default, null) ); }, this.setInput = (input /*: ?SearchableSelect*/) => { this._input = input; }, _temp; } componentWillUnmount() { this.subscriptions.unsubscribeAll(); } componentDidMount() { this.getPreviewSnapshot(this.props.value); } componentWillReceiveProps(nextProps /*: Props*/) { if (nextProps.value !== this.props.value) { this.setState(getInitialState()); this.getPreviewSnapshot(nextProps.value); } } getPreviewSnapshot(value /*: Reference*/) { if (!value || !value._ref) { return; } var _props2 = this.props; const getPreviewSnapshot = _props2.getPreviewSnapshot, type = _props2.type; this.subscriptions.replace('previewSnapshot', getPreviewSnapshot(value, type).subscribe(snapshot => { this.setState({ previewSnapshot: snapshot || MISSING_SNAPSHOT }); })); } getMemberTypeFor(typeName /*: string*/) { const type = this.props.type; return type.to.find(ofType => ofType.type.name === typeName); } focus() { if (this._input) { this._input.focus(); } } render() { var _props3 = this.props; const type = _props3.type, value = _props3.value, level = _props3.level, markers = _props3.markers, readOnly = _props3.readOnly, onSearch = _props3.onSearch, getPreviewSnapshot = _props3.getPreviewSnapshot, rest = _objectWithoutProperties(_props3, ['type', 'value', 'level', 'markers', 'readOnly', 'onSearch', 'getPreviewSnapshot']); var _state = this.state; const previewSnapshot = _state.previewSnapshot, isFetching = _state.isFetching, hits = _state.hits; const valueFromHit = value && hits.find(hit => hit._id === value._ref); const weakIs = value && value._weak ? 'weak' : 'strong'; const weakShouldBe = type.weak === true ? 'weak' : 'strong'; const isMissing = previewSnapshot === MISSING_SNAPSHOT; const hasRef = value && value._ref; const hasWeakMismatch = hasRef && !isMissing && weakIs !== weakShouldBe; const validation = markers.filter(marker => marker.type === 'validation'); const errors = validation.filter(marker => marker.level === 'error'); let inputValue = value ? previewSnapshot && previewSnapshot.title : undefined; if (previewSnapshot && !previewSnapshot.title) { inputValue = 'Untitled document'; } return _react2.default.createElement( _default2.default, { markers: markers, label: type.title, level: level, description: type.description }, _react2.default.createElement( 'div', { className: hasWeakMismatch || isMissing ? _ReferenceInput2.default.hasWarnings : '' }, hasWeakMismatch && _react2.default.createElement( 'div', { className: _ReferenceInput2.default.weakRefMismatchWarning }, 'Warning: This reference is ', _react2.default.createElement( 'em', null, weakIs ), ', but should be', ' ', _react2.default.createElement( 'em', null, weakShouldBe ), ' according to schema.', _react2.default.createElement( 'div', null, _react2.default.createElement( _default4.default, { onClick: this.handleFixWeak }, 'Convert to ', weakShouldBe ) ) ), _react2.default.createElement(_searchable2.default, _extends({}, rest, { placeholder: 'Type to search\u2026', title: isMissing && hasRef ? `Document id: ${value._ref || 'unknown'}` : previewSnapshot && previewSnapshot.description, customValidity: errors.length > 0 ? errors[0].item.message : '', onOpen: this.handleOpen, onFocus: this.handleFocus, onSearch: this.handleSearch, onChange: this.handleChange, onClear: this.handleClear, openItemElement: this.renderOpenItemElement, value: valueFromHit || value, inputValue: isMissing ? '<Unpublished or missing document>' : inputValue, renderItem: this.renderHit, isLoading: isFetching, items: hits, ref: this.setInput, readOnly: readOnly })) ) ); } } exports.default = ReferenceInput;