// eslint-disable-next-line filenames/match-exported
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import autobind from 'autobind-decorator';
import { DragSource, DropTarget } from 'react-dnd';
import classnames from 'classnames';
import FileInputButton from '../base/file-input-button';
import { Dropdown, DropdownButton, DropdownItem } from '../base/dropdown/index';
import PromptButton from '../base/prompt-button';
import CodePromptModal from '../modals/code-prompt-modal';
import Button from '../base/button';
import OneLineEditor from '../codemirror/one-line-editor';
import { showModal } from '../modals/index';
import { describeByteSize } from '../../../common/misc';
@autobind
class KeyValueEditorRow extends PureComponent {
constructor(props) {
super(props);
this._nameInput = null;
this._valueInput = null;
this.state = {
dragDirection: 0,
};
}
focusNameEnd() {
if (this._nameInput) {
this._nameInput.focusEnd();
}
}
focusValueEnd() {
if (this._valueInput) {
this._valueInput.focusEnd();
}
}
setDragDirection(dragDirection) {
if (dragDirection !== this.state.dragDirection) {
this.setState({ dragDirection });
}
}
_setNameInputRef(n) {
this._nameInput = n;
}
_setValueInputRef(n) {
this._valueInput = n;
}
_sendChange(patch) {
const pair = Object.assign({}, this.props.pair, patch);
this.props.onChange && this.props.onChange(pair);
}
_handleNameChange(name) {
this._sendChange({ name });
}
_handleValuePaste(e) {
if (!this.props.allowMultiline) {
return;
}
const value = e.clipboardData.getData('text/plain');
if (value && value.includes('\n')) {
e.preventDefault();
// Insert the pasted text into the current selection. Unfortunately, this
// is the easiest way to do this.
const currentValue = this._valueInput.getValue();
const prefix = currentValue.slice(0, this._valueInput.getSelectionStart());
const suffix = currentValue.slice(this._valueInput.getSelectionEnd());
const finalValue = `${prefix}${value}${suffix}`;
// Update type and value
this._handleTypeChange({ type: 'text', multiline: 'text/plain' });
this._handleValueChange(finalValue);
}
}
_handleValueChange(value) {
this._sendChange({ value });
}
_handleFileNameChange(fileName) {
this._sendChange({ fileName });
}
_handleTypeChange(def) {
// Remove newlines if converting to text
let value = this.props.pair.value || '';
if (def.type === 'text' && !def.multiline && value.includes('\n')) {
value = value.replace(/\n/g, '');
}
this._sendChange({ type: def.type, multiline: def.multiline, value });
}
_handleDisableChange(disabled) {
this._sendChange({ disabled });
}
_handleFocusName(e) {
this.props.onFocusName(this.props.pair, e);
}
_handleFocusValue(e) {
this.props.onFocusValue(this.props.pair, e);
}
_handleBlurName(e) {
if (this.props.onBlurName) {
this.props.onBlurName(this.props.pair, e);
}
}
_handleBlurValue(e) {
if (this.props.onBlurName) {
this.props.onBlurValue(this.props.pair, e);
}
}
_handleDelete() {
if (this.props.onDelete) {
this.props.onDelete(this.props.pair);
}
}
_handleKeyDown(e, value) {
if (this.props.onKeyDown) {
this.props.onKeyDown(this.props.pair, e, value);
}
}
_handleAutocompleteNames() {
const { handleGetAutocompleteNameConstants } = this.props;
if (handleGetAutocompleteNameConstants) {
return handleGetAutocompleteNameConstants(this.props.pair);
}
}
_handleAutocompleteValues() {
const { handleGetAutocompleteValueConstants } = this.props;
if (handleGetAutocompleteValueConstants) {
return handleGetAutocompleteValueConstants(this.props.pair);
}
}
_handleEditMultiline() {
const { pair, handleRender, handleGetRenderContext } = this.props;
showModal(CodePromptModal, {
submitName: 'Done',
title: `Edit ${pair.name}`,
defaultValue: pair.value,
onChange: this._handleValueChange,
enableRender: handleRender || handleGetRenderContext,
mode: pair.multiline || 'text/plain',
onModeChange: mode => {
this._handleTypeChange(Object.assign({}, pair, { multiline: mode }));
},
});
}
renderPairValue() {
const {
pair,
readOnly,
forceInput,
valueInputType,
valuePlaceholder,
handleRender,
handleGetRenderContext,
nunjucksPowerUserMode,
isVariableUncovered,
} = this.props;
if (pair.type === 'file') {
return (