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

yongjiezhao 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 4234031  feat(explore): UX improvements for drag'n'dropping time 
column (#15740)
4234031 is described below

commit 4234031cbaa537ff148c367c8a1e739e819aaff7
Author: Kamil Gabryjelski <[email protected]>
AuthorDate: Sun Jul 18 19:52:34 2021 +0200

    feat(explore): UX improvements for drag'n'dropping time column (#15740)
---
 .../explore/components/DatasourcePanel/index.tsx   | 22 +++++++++++--
 .../DndColumnSelectControl/DndColumnSelect.tsx     | 23 +++++++++++---
 .../DndColumnSelectControl/DndMetricSelect.tsx     |  4 +--
 .../controls/DndColumnSelectControl/Option.tsx     | 36 +++++++++++++---------
 .../DndColumnSelectControl/OptionWrapper.tsx       |  2 ++
 .../controls/DndColumnSelectControl/types.ts       |  3 ++
 6 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx 
b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
index 1c88fdd..2c5caa6 100644
--- a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
+++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
 import { styled, t } from '@superset-ui/core';
 import Collapse from 'src/components/Collapse';
 import { ControlConfig, DatasourceMeta } from '@superset-ui/chart-controls';
 import { debounce } from 'lodash';
 import { matchSorter, rankings } from 'match-sorter';
 import { FAST_DEBOUNCE } from 'src/constants';
-import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
+import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
 import { ExploreActions } from 'src/explore/actions/exploreActions';
 import Control from 'src/explore/components/Control';
 import DatasourcePanelDragWrapper from './DatasourcePanelDragWrapper';
@@ -119,7 +119,23 @@ export default function DataSourcePanel({
   controls: { datasource: datasourceControl },
   actions,
 }: Props) {
-  const { columns, metrics } = datasource;
+  const { columns: _columns, metrics } = datasource;
+
+  // display temporal column first
+  const columns = useMemo(
+    () =>
+      [..._columns].sort((col1, col2) => {
+        if (col1.is_dttm && !col2.is_dttm) {
+          return -1;
+        }
+        if (col2.is_dttm && !col1.is_dttm) {
+          return 1;
+        }
+        return 0;
+      }),
+    [_columns],
+  );
+
   const [inputValue, setInputValue] = useState('');
   const [lists, setList] = useState({
     columns,
diff --git 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.tsx
 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.tsx
index 29cd738..d677aa2 100644
--- 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.tsx
@@ -29,7 +29,14 @@ import { DndItemType } from 
'src/explore/components/DndItemType';
 import { StyledColumnOption } from 'src/explore/components/optionRenderers';
 
 export const DndColumnSelect = (props: LabelProps) => {
-  const { value, options, multi = true, onChange } = props;
+  const {
+    value,
+    options,
+    multi = true,
+    onChange,
+    canDelete = true,
+    ghostButtonText,
+  } = props;
   const optionSelector = new OptionSelector(options, multi, value);
 
   // synchronize values in case of dataset changes
@@ -66,9 +73,12 @@ export const DndColumnSelect = (props: LabelProps) => {
     onChange(optionSelector.getValues());
   };
 
-  const canDrop = (item: DatasourcePanelDndItem) =>
-    (multi || optionSelector.values.length === 0) &&
-    !optionSelector.has((item.value as ColumnMeta).column_name);
+  const canDrop = (item: DatasourcePanelDndItem) => {
+    const columnName = (item.value as ColumnMeta).column_name;
+    return (
+      columnName in optionSelector.options && !optionSelector.has(columnName)
+    );
+  };
 
   const onClickClose = (index: number) => {
     optionSelector.del(index);
@@ -88,6 +98,7 @@ export const DndColumnSelect = (props: LabelProps) => {
         clickClose={onClickClose}
         onShiftOptions={onShiftOptions}
         type={DndItemType.ColumnOption}
+        canDelete={canDelete}
       >
         <StyledColumnOption column={column} showType />
       </OptionWrapper>
@@ -100,7 +111,9 @@ export const DndColumnSelect = (props: LabelProps) => {
       valuesRenderer={valuesRenderer}
       accept={DndItemType.Column}
       displayGhostButton={multi || optionSelector.values.length === 0}
-      ghostButtonText={tn('Drop column', 'Drop columns', multi ? 2 : 1)}
+      ghostButtonText={
+        ghostButtonText || tn('Drop column', 'Drop columns', multi ? 2 : 1)
+      }
       {...props}
     />
   );
diff --git 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndMetricSelect.tsx
 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndMetricSelect.tsx
index a3daeaf..9b38c15 100644
--- 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndMetricSelect.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndMetricSelect.tsx
@@ -157,11 +157,11 @@ export const DndMetricSelect = (props: any) => {
   const canDrop = (item: DatasourcePanelDndItem) => {
     const isMetricAlreadyInValues =
       item.type === 'metric' ? value.includes(item.value.metric_name) : false;
-    return (props.multi || value.length === 0) && !isMetricAlreadyInValues;
+    return !isMetricAlreadyInValues;
   };
 
   const onNewMetric = (newMetric: Metric) => {
-    const newValue = [...value, newMetric];
+    const newValue = props.isMulti ? [...value, newMetric] : [newMetric];
     setValue(newValue);
     handleChange(newValue);
   };
diff --git 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/Option.tsx
 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/Option.tsx
index 11c68a6..50e1bfe 100644
--- 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/Option.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/Option.tsx
@@ -32,22 +32,28 @@ const StyledInfoTooltipWithTrigger = 
styled(InfoTooltipWithTrigger)`
   margin: 0 ${({ theme }) => theme.gridUnit}px;
 `;
 
-export default function Option(props: OptionProps) {
+export default function Option({
+  children,
+  index,
+  clickClose,
+  withCaret,
+  isExtra,
+  canDelete = true,
+}: OptionProps) {
   const theme = useTheme();
   return (
-    <OptionControlContainer
-      data-test="option-label"
-      withCaret={props.withCaret}
-    >
-      <CloseContainer
-        role="button"
-        data-test="remove-control-button"
-        onClick={() => props.clickClose(props.index)}
-      >
-        <Icons.XSmall iconColor={theme.colors.grayscale.light1} />
-      </CloseContainer>
-      <Label data-test="control-label">{props.children}</Label>
-      {props.isExtra && (
+    <OptionControlContainer data-test="option-label" withCaret={withCaret}>
+      {canDelete && (
+        <CloseContainer
+          role="button"
+          data-test="remove-control-button"
+          onClick={() => clickClose(index)}
+        >
+          <Icons.XSmall iconColor={theme.colors.grayscale.light1} />
+        </CloseContainer>
+      )}
+      <Label data-test="control-label">{children}</Label>
+      {isExtra && (
         <StyledInfoTooltipWithTrigger
           icon="exclamation-triangle"
           placement="top"
@@ -58,7 +64,7 @@ export default function Option(props: OptionProps) {
               `)}
         />
       )}
-      {props.withCaret && (
+      {withCaret && (
         <CaretContainer>
           <Icons.CaretRight iconColor={theme.colors.grayscale.light1} />
         </CaretContainer>
diff --git 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/OptionWrapper.tsx
 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/OptionWrapper.tsx
index 40da4c4..62230c5 100644
--- 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/OptionWrapper.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/OptionWrapper.tsx
@@ -44,6 +44,7 @@ export default function OptionWrapper(
     clickClose,
     withCaret,
     isExtra,
+    canDelete = true,
     children,
     ...rest
   } = props;
@@ -113,6 +114,7 @@ export default function OptionWrapper(
         clickClose={clickClose}
         withCaret={withCaret}
         isExtra={isExtra}
+        canDelete={canDelete}
       >
         {children}
       </Option>
diff --git 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts
 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts
index da2c51a..2d7142e 100644
--- 
a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts
+++ 
b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts
@@ -28,6 +28,7 @@ export interface OptionProps {
   clickClose: (index: number) => void;
   withCaret?: boolean;
   isExtra?: boolean;
+  canDelete?: boolean;
 }
 
 export interface OptionItemInterface {
@@ -41,6 +42,8 @@ export interface LabelProps<T = string[] | string> {
   onChange: (value?: T) => void;
   options: { string: ColumnMeta };
   multi?: boolean;
+  canDelete?: boolean;
+  ghostButtonText?: string;
 }
 
 export interface DndColumnSelectProps<

Reply via email to