You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by vi...@apache.org on 2023/04/20 14:03:28 UTC

[superset] branch master updated: feat(adhoc-column): add resize option (#23748)

This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/master by this push:
     new 60c9d68403 feat(adhoc-column): add resize option (#23748)
60c9d68403 is described below

commit 60c9d68403b0bcefcc4ff7460ef4fde952d8f293
Author: Ville Brofeldt <33...@users.noreply.github.com>
AuthorDate: Thu Apr 20 17:03:18 2023 +0300

    feat(adhoc-column): add resize option (#23748)
---
 .../DndColumnSelectControl/ColumnSelectPopover.tsx |  15 ++-
 .../DndColumnSelectControl/useResizeButton.tsx     | 139 +++++++++++++++++++++
 .../FilterControl/AdhocFilterEditPopover/index.jsx |   2 +-
 .../MetricControl/AdhocMetricEditPopover/index.jsx |   2 +-
 superset-frontend/src/explore/constants.ts         |   2 -
 5 files changed, 152 insertions(+), 8 deletions(-)

diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx
index dbbc8fe948..4806e5394a 100644
--- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx
+++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx
@@ -46,9 +46,10 @@ import { EmptyStateSmall } from 'src/components/EmptyState';
 import { StyledColumnOption } from 'src/explore/components/optionRenderers';
 import {
   POPOVER_INITIAL_HEIGHT,
-  UNRESIZABLE_POPOVER_WIDTH,
+  POPOVER_INITIAL_WIDTH,
 } from 'src/explore/constants';
 import { ExplorePageState } from 'src/explore/types';
+import useResizeButton from './useResizeButton';
 
 const StyledSelect = styled(Select)`
   .metric-option {
@@ -117,6 +118,11 @@ const ColumnSelectPopover = ({
     ColumnMeta | undefined
   >(initialSimpleColumn);
 
+  const [resizeButton, width, height] = useResizeButton(
+    POPOVER_INITIAL_WIDTH,
+    POPOVER_INITIAL_HEIGHT,
+  );
+
   const sqlEditorRef = useRef(null);
 
   const [calculatedColumns, simpleColumns] = useMemo(
@@ -258,8 +264,8 @@ const ColumnSelectPopover = ({
         className="adhoc-metric-edit-tabs"
         allowOverflow
         css={css`
-          height: ${POPOVER_INITIAL_HEIGHT}px;
-          width: ${UNRESIZABLE_POPOVER_WIDTH}px;
+          height: ${height}px;
+          width: ${width}px;
         `}
       >
         <Tabs.TabPane key="saved" tab={t('Saved')}>
@@ -393,7 +399,7 @@ const ColumnSelectPopover = ({
             showLoadingForImport
             onChange={onSqlExpressionChange}
             width="100%"
-            height={`${POPOVER_INITIAL_HEIGHT - 80}px`}
+            height={`${height - 80}px`}
             showGutter={false}
             editorProps={{ $blockScrolling: true }}
             enableLiveAutocompletion
@@ -417,6 +423,7 @@ const ColumnSelectPopover = ({
         >
           {t('Save')}
         </Button>
+        {resizeButton}
       </div>
     </Form>
   );
diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/useResizeButton.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/useResizeButton.tsx
new file mode 100644
index 0000000000..71d5047c6a
--- /dev/null
+++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/useResizeButton.tsx
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback, useEffect, useState } from 'react';
+import throttle from 'lodash/throttle';
+import {
+  POPOVER_INITIAL_HEIGHT,
+  POPOVER_INITIAL_WIDTH,
+} from 'src/explore/constants';
+
+const RESIZE_THROTTLE_MS = 50;
+
+export default function useResizeButton(
+  minWidth: number,
+  minHeight: number,
+): [JSX.Element, number, number] {
+  const [width, setWidth] = useState(POPOVER_INITIAL_WIDTH);
+  const [height, setHeight] = useState(POPOVER_INITIAL_HEIGHT);
+  const [clientX, setClientX] = useState(0);
+  const [clientY, setClientY] = useState(0);
+  const [dragStartX, setDragStartX] = useState(0);
+  const [dragStartY, setDragStartY] = useState(0);
+  const [dragStartWidth, setDragStartWidth] = useState(width);
+  const [dragStartHeight, setDragStartHeight] = useState(height);
+  const [isDragging, setIsDragging] = useState(false);
+
+  const onMouseMove = useCallback((ev: MouseEvent): void => {
+    ev.preventDefault();
+    setClientX(ev.clientX);
+    setClientY(ev.clientY);
+  }, []);
+
+  const onMouseUp = useCallback(() => {
+    setIsDragging(false);
+  }, []);
+
+  const onDragDown = useCallback((ev: React.MouseEvent): void => {
+    setDragStartX(ev.clientX);
+    setDragStartY(ev.clientY);
+    setIsDragging(true);
+  }, []);
+
+  useEffect(() => {
+    if (isDragging) {
+      document.addEventListener('mousemove', onMouseMove);
+    } else {
+      setDragStartWidth(width);
+      setDragStartHeight(height);
+      document.removeEventListener('mousemove', onMouseMove);
+    }
+  }, [onMouseMove, isDragging]);
+
+  const handleResize = useCallback(
+    throttle(
+      ({
+        dragStartX,
+        dragStartY,
+        dragStartWidth,
+        dragStartHeight,
+        clientX,
+        clientY,
+        minWidth,
+        minHeight,
+      }: {
+        dragStartX: number;
+        dragStartY: number;
+        dragStartWidth: number;
+        dragStartHeight: number;
+        clientX: number;
+        clientY: number;
+        minWidth: number;
+        minHeight: number;
+      }): void => {
+        setWidth(Math.max(dragStartWidth + (clientX - dragStartX), minWidth));
+        setHeight(
+          Math.max(dragStartHeight + (clientY - dragStartY), minHeight),
+        );
+      },
+      RESIZE_THROTTLE_MS,
+    ),
+    [setHeight, setWidth],
+  );
+
+  useEffect(() => {
+    if (isDragging) {
+      handleResize({
+        dragStartX,
+        dragStartY,
+        dragStartWidth,
+        dragStartHeight,
+        clientX,
+        clientY,
+        minWidth,
+        minHeight,
+      });
+    }
+  }, [
+    isDragging,
+    clientX,
+    clientY,
+    dragStartWidth,
+    dragStartHeight,
+    dragStartX,
+    dragStartY,
+  ]);
+
+  useEffect(() => {
+    document.addEventListener('mouseup', onMouseUp);
+    return () => document.removeEventListener('mouseup', onMouseUp);
+  }, [onMouseUp]);
+
+  return [
+    <i
+      role="button"
+      aria-label="Resize"
+      tabIndex={0}
+      onMouseDown={onDragDown}
+      className="fa fa-expand edit-popover-resize text-muted"
+    />,
+    width,
+    height,
+  ];
+}
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopover/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopover/index.jsx
index 7820ceb9d4..34be012f5e 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopover/index.jsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopover/index.jsx
@@ -150,7 +150,7 @@ export default class AdhocFilterEditPopover extends React.Component {
         POPOVER_INITIAL_WIDTH,
       ),
       height: Math.max(
-        this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
+        this.dragStartHeight + (e.clientY - this.dragStartY),
         POPOVER_INITIAL_HEIGHT,
       ),
     });
diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx
index 9ed817f283..d796d6e8a6 100644
--- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx
+++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx
@@ -248,7 +248,7 @@ export default class AdhocMetricEditPopover extends React.PureComponent {
         POPOVER_INITIAL_WIDTH,
       ),
       height: Math.max(
-        this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
+        this.dragStartHeight + (e.clientY - this.dragStartY),
         POPOVER_INITIAL_HEIGHT,
       ),
     });
diff --git a/superset-frontend/src/explore/constants.ts b/superset-frontend/src/explore/constants.ts
index 58c90cfba3..e01dae4935 100644
--- a/superset-frontend/src/explore/constants.ts
+++ b/superset-frontend/src/explore/constants.ts
@@ -158,6 +158,4 @@ export const TIME_FILTER_MAP = {
 
 export const POPOVER_INITIAL_HEIGHT = 240;
 export const POPOVER_INITIAL_WIDTH = 320;
-export const UNRESIZABLE_POPOVER_WIDTH = 296;
-
 export const UNSAVED_CHART_ID = 0;