提交 30c91191 编写于 作者: C Christopher Council 提交者: Krist Wongsuphasawat

Fix Text field to edit SQL snippet of a metric is not large enough (#6702)

* Fix Text field to edit SQL snippet of a metric is not large enough for entire snippet
* Fix Airbnb bug PRODUCT-62223 
上级 88964b7d
......@@ -25,19 +25,23 @@ import TooltipWrapper from './TooltipWrapper';
const propTypes = {
title: PropTypes.string,
canEdit: PropTypes.bool,
multiLine: PropTypes.bool,
onSaveTitle: PropTypes.func,
noPermitTooltip: PropTypes.string,
showTooltip: PropTypes.bool,
emptyText: PropTypes.node,
style: PropTypes.object,
extraClasses: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.string]),
};
const defaultProps = {
title: t('Title'),
canEdit: false,
multiLine: false,
showTooltip: true,
onSaveTitle: () => {},
emptyText: '<empty>',
style: null,
extraClasses: null,
};
export default class EditableTitle extends React.PureComponent {
......@@ -53,6 +57,9 @@ export default class EditableTitle extends React.PureComponent {
this.handleChange = this.handleChange.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
// Used so we can access the DOM element if a user clicks on this component.
this.contentRef = React.createRef();
}
componentWillReceiveProps(nextProps) {
......@@ -68,7 +75,13 @@ export default class EditableTitle extends React.PureComponent {
if (!this.props.canEdit || this.state.isEditing) {
return;
}
this.setState({ isEditing: true });
// For multi-line values, save the actual rendered size of the displayed text.
// Later, if a textarea is constructed for editing the value, we'll need this.
const contentBoundingRect = (this.contentRef.current) ?
this.contentRef.current.getBoundingClientRect() : null;
this.setState({ isEditing: true, contentBoundingRect });
}
handleBlur() {
......@@ -134,18 +147,43 @@ export default class EditableTitle extends React.PureComponent {
}
render() {
const { isEditing, title, contentBoundingRect } = this.state;
const { emptyText, multiLine, showTooltip, canEdit,
noPermitTooltip, style, extraClasses } = this.props;
let value;
if (this.state.title) {
value = this.state.title;
} else if (!this.state.isEditing) {
value = this.props.emptyText;
if (title) {
value = title;
} else if (!isEditing) {
value = emptyText;
}
let input = (
// Construct an inline style based on previously-saved height of the rendered label. Only
// used in multi-line contexts.
const editStyle = (isEditing && contentBoundingRect) ? { height: `${contentBoundingRect.height}px` } : null;
// Create a textarea when we're editing a multi-line value, otherwise create an input (which may
// be text or a button).
let input = multiLine && isEditing ? (
<textarea
ref={this.contentRef}
required
value={value}
className={!title ? 'text-muted' : null}
onKeyUp={this.handleKeyUp}
onChange={this.handleChange}
onBlur={this.handleBlur}
onClick={this.handleClick}
onKeyPress={this.handleKeyPress}
style={editStyle}
/>
) : (
<input
ref={this.contentRef}
required
type={this.state.isEditing ? 'text' : 'button'}
type={isEditing ? 'text' : 'button'}
value={value}
className={!this.state.title ? 'text-muted' : null}
className={!title ? 'text-muted' : null}
onKeyUp={this.handleKeyUp}
onChange={this.handleChange}
onBlur={this.handleBlur}
......@@ -153,12 +191,12 @@ export default class EditableTitle extends React.PureComponent {
onKeyPress={this.handleKeyPress}
/>
);
if (this.props.showTooltip && !this.state.isEditing) {
if (showTooltip && !isEditing) {
input = (
<TooltipWrapper
label="title"
tooltip={this.props.canEdit ? t('click to edit') :
this.props.noPermitTooltip || t('You don\'t have the rights to alter this title.')}
tooltip={canEdit ? t('click to edit') :
noPermitTooltip || t('You don\'t have the rights to alter this title.')}
>
{input}
</TooltipWrapper>
......@@ -168,10 +206,11 @@ export default class EditableTitle extends React.PureComponent {
<span
className={cx(
'editable-title',
this.props.canEdit && 'editable-title--editable',
this.state.isEditing && 'editable-title--editing',
extraClasses,
canEdit && 'editable-title--editable',
isEditing && 'editable-title--editing',
)}
style={this.props.style}
style={style}
>
{input}
</span>
......
......@@ -43,7 +43,6 @@ import withToasts from '../messageToasts/enhancers/withToasts';
import './main.css';
const checkboxGenerator = (d, onChange) => <CheckboxControl value={d} onChange={onChange} />;
const styleMonospace = { fontFamily: 'monospace' };
const DATA_TYPES = ['STRING', 'NUMBER', 'DATETIME'];
function CollectionTabTitle({ title, collection }) {
......@@ -540,7 +539,8 @@ export class DatasourceEditor extends React.PureComponent {
canEdit
title={v}
onSaveTitle={onChange}
style={styleMonospace}
extraClasses={['datasource-sql-expression']}
multiLine
/>),
description: (v, onChange, label) => (
<StackedField
......
@import './less/index.less';
@import "./less/cosmo/variables.less";
@datasource-sql-expression-width: 450px;
body {
margin: 0px !important;
margin: 0 !important;
}
.caret {
......@@ -230,12 +232,37 @@ table.table-no-hover tr:hover {
cursor: initial;
}
.editable-title textarea {
outline: none;
background: transparent;
box-shadow: none;
cursor: initial;
border: 1px solid #ccc;
border-radius: 2px;
}
.editable-title input[type="text"] {
border: 1px solid #ccc;
border-radius: 2px;
padding: 2px;
}
.editable-title.datasource-sql-expression {
font-family: @font-family-monospace;
font-size: 95%;
display: inline-block;
min-width: @datasource-sql-expression-width;
}
.editable-title.datasource-sql-expression input {
width: 95%;
padding-bottom: 5px;
}
.editable-title.datasource-sql-expression textarea {
width: 95%;
}
.editable-title input[type="button"] {
border-color: transparent;
background: transparent;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册