superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kri...@apache.org
Subject [incubator-superset] branch master updated: Fix Text field to edit SQL snippet of a metric is not large enough (#6702)
Date Thu, 17 Jan 2019 07:28:44 GMT
This is an automated email from the ASF dual-hosted git repository.

kristw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 30c9119  Fix Text field to edit SQL snippet of a metric is not large enough (#6702)
30c9119 is described below

commit 30c911919efd28f8104b4e720db2d02df9cdb9df
Author: Christopher Council <soboko@users.noreply.github.com>
AuthorDate: Wed Jan 16 23:28:38 2019 -0800

    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
---
 superset/assets/src/components/EditableTitle.jsx   | 67 +++++++++++++++++-----
 .../assets/src/datasource/DatasourceEditor.jsx     |  4 +-
 superset/assets/stylesheets/superset.less          | 29 +++++++++-
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/superset/assets/src/components/EditableTitle.jsx b/superset/assets/src/components/EditableTitle.jsx
index 1ef6e70..87a5160 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: '<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>
diff --git a/superset/assets/src/datasource/DatasourceEditor.jsx b/superset/assets/src/datasource/DatasourceEditor.jsx
index f398ab1..cbc46c8 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) => <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
diff --git a/superset/assets/stylesheets/superset.less b/superset/assets/stylesheets/superset.less
index 5e0e90e..5d44428 100644
--- a/superset/assets/stylesheets/superset.less
+++ b/superset/assets/stylesheets/superset.less
@@ -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;


Mime
View raw message