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
This commit is contained in:
parent
88964b7dfc
commit
30c911919e
|
|
@ -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 = (
|
||||
<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
|
||||
type={this.state.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}
|
||||
onClick={this.handleClick}
|
||||
onKeyPress={this.handleKeyPress}
|
||||
style={editStyle}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
ref={this.contentRef}
|
||||
required
|
||||
type={isEditing ? 'text' : 'button'}
|
||||
value={value}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
@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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue