From 30c911919efd28f8104b4e720db2d02df9cdb9df Mon Sep 17 00:00:00 2001 From: Christopher Council Date: Wed, 16 Jan 2019 23:28:38 -0800 Subject: [PATCH] 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 --- .../assets/src/components/EditableTitle.jsx | 69 +++++++++++++++---- .../src/datasource/DatasourceEditor.jsx | 4 +- superset/assets/stylesheets/superset.less | 29 +++++++- 3 files changed, 84 insertions(+), 18 deletions(-) diff --git a/superset/assets/src/components/EditableTitle.jsx b/superset/assets/src/components/EditableTitle.jsx index 1ef6e70c8..87a5160ca 100644 --- a/superset/assets/src/components/EditableTitle.jsx +++ b/superset/assets/src/components/EditableTitle.jsx @@ -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: '', 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 = ( - + ) : ( + ); - if (this.props.showTooltip && !this.state.isEditing) { + if (showTooltip && !isEditing) { input = ( {input} @@ -168,10 +206,11 @@ export default class EditableTitle extends React.PureComponent { {input} diff --git a/superset/assets/src/datasource/DatasourceEditor.jsx b/superset/assets/src/datasource/DatasourceEditor.jsx index f398ab16d..cbc46c866 100644 --- a/superset/assets/src/datasource/DatasourceEditor.jsx +++ b/superset/assets/src/datasource/DatasourceEditor.jsx @@ -43,7 +43,6 @@ import withToasts from '../messageToasts/enhancers/withToasts'; import './main.css'; const checkboxGenerator = (d, 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) => (