You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2022/12/01 20:41:26 UTC
[superset] branch master updated: feat(native-filters): Adjust filter components for horizontal mode (#22273)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina 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 eb6045adfa feat(native-filters): Adjust filter components for horizontal mode (#22273)
eb6045adfa is described below
commit eb6045adfa77e06c8aaf3de217719ca59d4328e1
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Thu Dec 1 21:41:19 2022 +0100
feat(native-filters): Adjust filter components for horizontal mode (#22273)
---
.../src/chart/models/ChartProps.ts | 9 +++
.../src/components/Select/CustomTag.tsx | 77 ++++++++++++++++++++++
.../src/components/Select/Select.stories.tsx | 10 +++
.../src/components/Select/Select.test.tsx | 48 ++++++++++++++
superset-frontend/src/components/Select/Select.tsx | 17 ++++-
superset-frontend/src/components/Select/styles.tsx | 25 ++++++-
superset-frontend/src/components/Select/types.ts | 13 ++++
.../FilterBar/FilterControls/FilterControl.tsx | 2 +-
.../FilterBar/FilterControls/FilterValue.tsx | 12 ++--
.../filters/components/Range/RangeFilterPlugin.tsx | 33 ++++++++--
.../src/filters/components/Range/transformProps.ts | 3 +
.../src/filters/components/Range/types.ts | 3 +
.../components/Select/SelectFilterPlugin.tsx | 15 +++--
.../filters/components/Select/transformProps.ts | 3 +
.../src/filters/components/Select/types.ts | 3 +
.../filters/components/Time/TimeFilterPlugin.tsx | 9 +++
.../src/filters/components/Time/transformProps.ts | 2 +
17 files changed, 265 insertions(+), 19 deletions(-)
diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
index 324c4dfc45..5e4f044942 100644
--- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
+++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
@@ -90,6 +90,8 @@ export interface ChartPropsConfig {
filterState?: FilterState;
/** Set of actual behaviors that this instance of chart should use */
behaviors?: Behavior[];
+ /** Chart display settings related to current view context */
+ displaySettings?: JsonObject;
/** Application section of the chart on the screen (in what components/screen it placed) */
appSection?: AppSection;
/** is the chart refreshing its contents */
@@ -132,6 +134,8 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
behaviors: Behavior[];
+ displaySettings?: JsonObject;
+
appSection?: AppSection;
isRefreshing?: boolean;
@@ -153,6 +157,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
initialValues = {},
queriesData = [],
behaviors = [],
+ displaySettings = {},
width = DEFAULT_WIDTH,
height = DEFAULT_HEIGHT,
appSection,
@@ -174,6 +179,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
this.ownState = ownState;
this.filterState = filterState;
this.behaviors = behaviors;
+ this.displaySettings = displaySettings;
this.appSection = appSection;
this.isRefreshing = isRefreshing;
this.inputRef = inputRef;
@@ -196,6 +202,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
input => input.ownState,
input => input.filterState,
input => input.behaviors,
+ input => input.displaySettings,
input => input.appSection,
input => input.isRefreshing,
input => input.inputRef,
@@ -213,6 +220,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
ownState,
filterState,
behaviors,
+ displaySettings,
appSection,
isRefreshing,
inputRef,
@@ -231,6 +239,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector {
filterState,
width,
behaviors,
+ displaySettings,
appSection,
isRefreshing,
inputRef,
diff --git a/superset-frontend/src/components/Select/CustomTag.tsx b/superset-frontend/src/components/Select/CustomTag.tsx
new file mode 100644
index 0000000000..57aa37c81b
--- /dev/null
+++ b/superset-frontend/src/components/Select/CustomTag.tsx
@@ -0,0 +1,77 @@
+/**
+ * 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 from 'react';
+import { Tag as AntdTag } from 'antd';
+import { styled } from '@superset-ui/core';
+import { useCSSTextTruncation } from 'src/hooks/useTruncation';
+import { Tooltip } from '../Tooltip';
+import { CustomTagProps } from './types';
+
+const StyledTag = styled(AntdTag)`
+ & .ant-tag-close-icon {
+ display: inline-flex;
+ align-items: center;
+ margin-left: ${({ theme }) => theme.gridUnit}px;
+ }
+
+ & .tag-content {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+`;
+
+// TODO: use antd Tag props instead of any. Currently it's causing a typescript error
+const Tag = (props: any) => {
+ const [tagRef, tagIsTruncated] = useCSSTextTruncation<HTMLSpanElement>();
+ return (
+ <Tooltip title={tagIsTruncated ? props.children : null}>
+ <StyledTag {...props} className="ant-select-selection-item">
+ <span className="tag-content" ref={tagRef}>
+ {props.children}
+ </span>
+ </StyledTag>
+ </Tooltip>
+ );
+};
+
+/**
+ * Custom tag renderer dedicated for oneLine mode
+ */
+export const oneLineTagRender = (props: CustomTagProps) => {
+ const { label } = props;
+
+ const onPreventMouseDown = (event: React.MouseEvent<HTMLElement>) => {
+ // if close icon is clicked, stop propagation to avoid opening the dropdown
+ const target = event.target as HTMLElement;
+ if (
+ target.tagName === 'svg' ||
+ target.tagName === 'path' ||
+ (target.tagName === 'span' &&
+ target.className.includes('ant-tag-close-icon'))
+ ) {
+ event.stopPropagation();
+ }
+ };
+
+ return (
+ <Tag onMouseDown={onPreventMouseDown} {...props}>
+ {label}
+ </Tag>
+ );
+};
diff --git a/superset-frontend/src/components/Select/Select.stories.tsx b/superset-frontend/src/components/Select/Select.stories.tsx
index c4802a45e0..4a5d3551f0 100644
--- a/superset-frontend/src/components/Select/Select.stories.tsx
+++ b/superset-frontend/src/components/Select/Select.stories.tsx
@@ -132,6 +132,15 @@ const ARG_TYPES = {
By default label and value.
`,
},
+ oneLine: {
+ defaultValue: false,
+ description: `Sets maxTagCount to 1. The overflow tag is always displayed in
+ the same line, line wrapping is disabled.
+ When the dropdown is open, sets maxTagCount to 0,
+ displays only the overflow tag.
+ Requires '"mode=multiple"'.
+ `,
+ },
};
const mountHeader = (type: String) => {
@@ -197,6 +206,7 @@ InteractiveSelect.args = {
invertSelection: false,
placeholder: 'Select ...',
optionFilterProps: ['value', 'label', 'custom'],
+ oneLine: false,
};
InteractiveSelect.argTypes = {
diff --git a/superset-frontend/src/components/Select/Select.test.tsx b/superset-frontend/src/components/Select/Select.test.tsx
index 06f5f7b8e5..cb4548633e 100644
--- a/superset-frontend/src/components/Select/Select.test.tsx
+++ b/superset-frontend/src/components/Select/Select.test.tsx
@@ -566,6 +566,54 @@ test('finds an element with a numeric value and does not duplicate the options',
expect(await querySelectOption('11')).not.toBeInTheDocument();
});
+test('Renders only 1 tag and an overflow tag in oneLine mode', () => {
+ render(
+ <Select
+ {...defaultProps}
+ value={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
+ mode="multiple"
+ oneLine
+ />,
+ );
+ expect(screen.getByText(OPTIONS[0].label)).toBeVisible();
+ expect(screen.queryByText(OPTIONS[1].label)).not.toBeInTheDocument();
+ expect(screen.queryByText(OPTIONS[2].label)).not.toBeInTheDocument();
+ expect(screen.getByText('+ 2 ...')).toBeVisible();
+});
+
+test('Renders only an overflow tag if dropdown is open in oneLine mode', async () => {
+ render(
+ <Select
+ {...defaultProps}
+ value={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
+ mode="multiple"
+ oneLine
+ />,
+ );
+ await open();
+
+ const withinSelector = within(getElementByClassName('.ant-select-selector'));
+ await waitFor(() => {
+ expect(
+ withinSelector.queryByText(OPTIONS[0].label),
+ ).not.toBeInTheDocument();
+ expect(
+ withinSelector.queryByText(OPTIONS[1].label),
+ ).not.toBeInTheDocument();
+ expect(
+ withinSelector.queryByText(OPTIONS[2].label),
+ ).not.toBeInTheDocument();
+ expect(withinSelector.getByText('+ 3 ...')).toBeVisible();
+ });
+
+ await type('{esc}');
+
+ expect(await withinSelector.findByText(OPTIONS[0].label)).toBeVisible();
+ expect(withinSelector.queryByText(OPTIONS[1].label)).not.toBeInTheDocument();
+ expect(withinSelector.queryByText(OPTIONS[2].label)).not.toBeInTheDocument();
+ expect(withinSelector.getByText('+ 2 ...')).toBeVisible();
+});
+
/*
TODO: Add tests that require scroll interaction. Needs further investigation.
- Fetches more data when scrolling and more data is available
diff --git a/superset-frontend/src/components/Select/Select.tsx b/superset-frontend/src/components/Select/Select.tsx
index 0e490013cf..5550463492 100644
--- a/superset-frontend/src/components/Select/Select.tsx
+++ b/superset-frontend/src/components/Select/Select.tsx
@@ -54,6 +54,7 @@ import {
TOKEN_SEPARATORS,
DEFAULT_SORT_COMPARATOR,
} from './constants';
+import { oneLineTagRender } from './CustomTag';
/**
* This component is a customized version of the Antdesign 4.X Select component
@@ -96,6 +97,8 @@ const Select = forwardRef(
tokenSeparators,
value,
getPopupContainer,
+ oneLine,
+ maxTagCount: propsMaxTagCount,
...props
}: SelectProps,
ref: RefObject<HTMLInputElement>,
@@ -106,6 +109,16 @@ const Select = forwardRef(
const [inputValue, setInputValue] = useState('');
const [isLoading, setIsLoading] = useState(loading);
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
+ const [maxTagCount, setMaxTagCount] = useState(
+ propsMaxTagCount ?? MAX_TAG_COUNT,
+ );
+
+ useEffect(() => {
+ if (oneLine) {
+ setMaxTagCount(isDropdownVisible ? 0 : 1);
+ }
+ }, [isDropdownVisible, oneLine]);
+
const mappedMode = isSingleMode
? undefined
: allowNewOptions
@@ -280,7 +293,7 @@ const Select = forwardRef(
}
headerPosition={headerPosition}
labelInValue={labelInValue}
- maxTagCount={MAX_TAG_COUNT}
+ maxTagCount={maxTagCount}
mode={mappedMode}
notFoundContent={isLoading ? t('Loading...') : notFoundContent}
onDeselect={handleOnDeselect}
@@ -308,6 +321,8 @@ const Select = forwardRef(
<StyledCheckOutlined iconSize="m" />
)
}
+ oneLine={oneLine}
+ tagRender={oneLine ? oneLineTagRender : undefined}
{...props}
ref={ref}
>
diff --git a/superset-frontend/src/components/Select/styles.tsx b/superset-frontend/src/components/Select/styles.tsx
index 2da49d7d6e..784bdc8ae7 100644
--- a/superset-frontend/src/components/Select/styles.tsx
+++ b/superset-frontend/src/components/Select/styles.tsx
@@ -40,9 +40,9 @@ export const StyledContainer = styled.div<{ headerPosition: string }>`
`;
export const StyledSelect = styled(AntdSelect, {
- shouldForwardProp: prop => prop !== 'headerPosition',
-})<{ headerPosition: string }>`
- ${({ theme, headerPosition }) => `
+ shouldForwardProp: prop => prop !== 'headerPosition' && prop !== 'oneLine',
+})<{ headerPosition: string; oneLine?: boolean }>`
+ ${({ theme, headerPosition, oneLine }) => `
flex: ${headerPosition === 'left' ? 1 : 0};
&& .ant-select-selector {
border-radius: ${theme.gridUnit}px;
@@ -52,6 +52,25 @@ export const StyledSelect = styled(AntdSelect, {
.ant-select-arrow .anticon:not(.ant-select-suffix) {
pointer-events: none;
}
+
+ ${
+ oneLine &&
+ `
+ .ant-select-selection-overflow {
+ flex-wrap: nowrap;
+ }
+
+ .ant-select-selection-overflow-item:not(.ant-select-selection-overflow-item-rest):not(.ant-select-selection-overflow-item-suffix) {
+ flex-shrink: 1;
+ min-width: ${theme.gridUnit * 13}px;
+ }
+
+ .ant-select-selection-overflow-item-suffix {
+ flex: unset;
+ min-width: 0px;
+ }
+ `
+ }
`}
`;
diff --git a/superset-frontend/src/components/Select/types.ts b/superset-frontend/src/components/Select/types.ts
index 2c4ccad394..76f7acd0a2 100644
--- a/superset-frontend/src/components/Select/types.ts
+++ b/superset-frontend/src/components/Select/types.ts
@@ -27,6 +27,7 @@ import {
SelectValue as AntdSelectValue,
LabeledValue as AntdLabeledValue,
} from 'antd/lib/select';
+import { TagProps } from 'antd/lib/tag';
export type RawValue = string | number;
@@ -140,6 +141,13 @@ export interface BaseSelectProps extends AntdExposedProps {
b: AntdLabeledValue,
search?: string,
) => number;
+ /**
+ * Sets maxTagCount to 1. The overflow tag is always displayed in
+ * the same line, line wrapping is disabled.
+ * When the dropdown is open, sets maxTagCount to 0,
+ * displays only the overflow tag.
+ */
+ oneLine?: boolean;
suffixIcon?: ReactNode;
@@ -203,3 +211,8 @@ export interface AsyncSelectProps extends BaseSelectProps {
*/
onError?: (error: string) => void;
}
+
+export type CustomTagProps = HTMLSpanElement &
+ TagProps & {
+ label: ReactNode;
+ };
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx
index 47ca4b4a5b..1206755f93 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx
@@ -136,7 +136,7 @@ const HorizontalFormItem = styled(StyledFormItem)`
}
.ant-form-item-control {
- width: ${({ theme }) => theme.gridUnit * 40}px;
+ width: ${({ theme }) => theme.gridUnit * 41}px;
}
`;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
index a08200d83b..5cc9d804e1 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
@@ -253,9 +253,12 @@ const FilterValue: React.FC<FilterControlProps> = ({
[filter.dataMask?.filterState, isMissingRequiredValue],
);
- const formDataWithDisplayParams = useMemo(
- () => ({ ...formData, orientation, overflow }),
- [formData, orientation, overflow],
+ const displaySettings = useMemo(
+ () => ({
+ filterBarOrientation: orientation,
+ isOverflowingFilterBar: overflow,
+ }),
+ [orientation, overflow],
);
if (error) {
@@ -277,7 +280,8 @@ const FilterValue: React.FC<FilterControlProps> = ({
height={HEIGHT}
width="100%"
showOverflow={showOverflow}
- formData={formDataWithDisplayParams}
+ formData={formData}
+ displaySettings={displaySettings}
parentRef={parentRef}
inputRef={inputRef}
// For charts that don't have datasource we need workaround for empty placeholder
diff --git a/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx b/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx
index f3673f223e..9c60e60814 100644
--- a/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Range/RangeFilterPlugin.tsx
@@ -25,8 +25,9 @@ import {
t,
} from '@superset-ui/core';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { AntdSlider } from 'src/components';
import { rgba } from 'emotion-rgba';
+import { AntdSlider } from 'src/components';
+import { FilterBarOrientation } from 'src/dashboard/types';
import { PluginFilterRangeProps } from './types';
import { StatusMessage, StyledFormItem, FilterPluginStyle } from '../common';
import { getRangeExtraFormData } from '../../utils';
@@ -65,8 +66,12 @@ const StyledMinSlider = styled(AntdSlider)<{
`}
`;
-const Wrapper = styled.div<{ validateStatus?: 'error' | 'warning' | 'info' }>`
- ${({ theme, validateStatus }) => `
+const Wrapper = styled.div<{
+ validateStatus?: 'error' | 'warning' | 'info';
+ orientation?: FilterBarOrientation;
+ isOverflowing?: boolean;
+}>`
+ ${({ theme, validateStatus, orientation, isOverflowing }) => `
border: 1px solid transparent;
&:focus {
border: 1px solid
@@ -76,8 +81,18 @@ const Wrapper = styled.div<{ validateStatus?: 'error' | 'warning' | 'info' }>`
${rgba(theme.colors[validateStatus || 'primary']?.base, 0.2)};
}
& .ant-slider {
- margin-top: ${theme.gridUnit}px;
- margin-bottom: ${theme.gridUnit * 5}px;
+ margin-top: ${
+ orientation === FilterBarOrientation.HORIZONTAL ? 0 : theme.gridUnit
+ }px;
+ margin-bottom: ${
+ orientation === FilterBarOrientation.HORIZONTAL ? 0 : theme.gridUnit * 5
+ }px;
+
+ ${
+ orientation === FilterBarOrientation.HORIZONTAL &&
+ !isOverflowing &&
+ `line-height: 1.2;`
+ }
& .ant-slider-track {
background-color: ${
@@ -93,6 +108,10 @@ const Wrapper = styled.div<{ validateStatus?: 'error' | 'warning' | 'info' }>`
${rgba(theme.colors[validateStatus || 'primary']?.base, 0.2)};
}
}
+ & .ant-slider-mark {
+ font-size: ${theme.typography.sizes.s}px;
+ }
+
&:hover {
& .ant-slider-track {
background-color: ${
@@ -155,6 +174,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) {
setFilterActive,
filterState,
inputRef,
+ filterBarOrientation,
+ isOverflowingFilterBar,
} = props;
const [row] = data;
// @ts-ignore
@@ -287,6 +308,8 @@ export default function RangeFilterPlugin(props: PluginFilterRangeProps) {
tabIndex={-1}
ref={inputRef}
validateStatus={filterState.validateStatus}
+ orientation={filterBarOrientation}
+ isOverflowing={isOverflowingFilterBar}
onFocus={setFocusedFilter}
onBlur={unsetFocusedFilter}
onMouseEnter={setFocusedFilter}
diff --git a/superset-frontend/src/filters/components/Range/transformProps.ts b/superset-frontend/src/filters/components/Range/transformProps.ts
index f4c47cec26..48def72cad 100644
--- a/superset-frontend/src/filters/components/Range/transformProps.ts
+++ b/superset-frontend/src/filters/components/Range/transformProps.ts
@@ -29,6 +29,7 @@ export default function transformProps(chartProps: ChartProps) {
behaviors,
filterState,
inputRef,
+ displaySettings,
} = chartProps;
const {
setDataMask = noOp,
@@ -50,5 +51,7 @@ export default function transformProps(chartProps: ChartProps) {
unsetFocusedFilter,
setFilterActive,
inputRef,
+ isOverflowingFilterBar: displaySettings?.isOverflowingFilterBar,
+ filterBarOrientation: displaySettings?.filterBarOrientation,
};
}
diff --git a/superset-frontend/src/filters/components/Range/types.ts b/superset-frontend/src/filters/components/Range/types.ts
index 69ad4d53da..25a18bb3e8 100644
--- a/superset-frontend/src/filters/components/Range/types.ts
+++ b/superset-frontend/src/filters/components/Range/types.ts
@@ -24,6 +24,7 @@ import {
} from '@superset-ui/core';
import { RefObject } from 'react';
import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
+import { FilterBarOrientation } from '../../../dashboard/types';
interface PluginFilterSelectCustomizeProps {
max?: number;
@@ -40,4 +41,6 @@ export type PluginFilterRangeProps = PluginFilterStylesProps & {
filterState: FilterState;
behaviors: Behavior[];
inputRef: RefObject<any>;
+ filterBarOrientation?: FilterBarOrientation;
+ isOverflowingFilterBar?: boolean;
} & PluginFilterHooks;
diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
index 9cea856d47..7337f51689 100644
--- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
@@ -17,6 +17,7 @@
* under the License.
*/
/* eslint-disable no-param-reassign */
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
AppSection,
DataMask,
@@ -31,14 +32,14 @@ import {
tn,
} from '@superset-ui/core';
import { LabeledValue as AntdLabeledValue } from 'antd/lib/select';
-import React, { useCallback, useEffect, useState, useMemo } from 'react';
-import { Select } from 'src/components';
import debounce from 'lodash/debounce';
-import { SLOW_DEBOUNCE } from 'src/constants';
import { useImmerReducer } from 'use-immer';
+import { Select } from 'src/components';
+import { SLOW_DEBOUNCE } from 'src/constants';
import { propertyComparator } from 'src/components/Select/utils';
+import { FilterBarOrientation } from 'src/dashboard/types';
import { PluginFilterSelectProps, SelectValue } from './types';
-import { StyledFormItem, FilterPluginStyle, StatusMessage } from '../common';
+import { FilterPluginStyle, StatusMessage, StyledFormItem } from '../common';
import { getDataRecordFormatter, getSelectExtraFormData } from '../../utils';
type DataMaskAction =
@@ -89,6 +90,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
showOverflow,
parentRef,
inputRef,
+ filterBarOrientation,
} = props;
const {
enableEmptyFilter,
@@ -323,11 +325,14 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
onChange={handleChange}
ref={inputRef}
loading={isRefreshing}
- maxTagCount={5}
+ oneLine={filterBarOrientation === FilterBarOrientation.HORIZONTAL}
invertSelection={inverseSelection}
// @ts-ignore
options={options}
sortComparator={sortComparator}
+ maxTagPlaceholder={(val: AntdLabeledValue[]) => (
+ <span>+{val.length}</span>
+ )}
onDropdownVisibleChange={setFilterActive}
/>
</StyledFormItem>
diff --git a/superset-frontend/src/filters/components/Select/transformProps.ts b/superset-frontend/src/filters/components/Select/transformProps.ts
index 59d9adc57e..a0fafa4a45 100644
--- a/superset-frontend/src/filters/components/Select/transformProps.ts
+++ b/superset-frontend/src/filters/components/Select/transformProps.ts
@@ -29,6 +29,7 @@ export default function transformProps(
hooks,
queriesData,
width,
+ displaySettings,
behaviors,
appSection,
filterState,
@@ -64,5 +65,7 @@ export default function transformProps(
unsetFocusedFilter,
setFilterActive,
inputRef,
+ filterBarOrientation: displaySettings?.filterBarOrientation,
+ isOverflowingFilterBar: displaySettings?.isOverflowingFilterBar,
};
}
diff --git a/superset-frontend/src/filters/components/Select/types.ts b/superset-frontend/src/filters/components/Select/types.ts
index 0497b58e55..e608f59640 100644
--- a/superset-frontend/src/filters/components/Select/types.ts
+++ b/superset-frontend/src/filters/components/Select/types.ts
@@ -27,6 +27,7 @@ import {
ChartDataResponseResult,
} from '@superset-ui/core';
import { RefObject } from 'react';
+import { FilterBarOrientation } from 'src/dashboard/types';
import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
export type SelectValue = (number | string | null)[] | null | undefined;
@@ -61,6 +62,8 @@ export type PluginFilterSelectProps = PluginFilterStylesProps & {
showOverflow: boolean;
parentRef?: RefObject<any>;
inputRef?: RefObject<any>;
+ filterBarOrientation?: FilterBarOrientation;
+ isOverflowingFilterBar?: boolean;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterSelectCustomizeProps = {
diff --git a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
index 82bfc678f0..0d4185b759 100644
--- a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
@@ -23,12 +23,21 @@ import { PluginFilterTimeProps } from './types';
import { FilterPluginStyle } from '../common';
const TimeFilterStyles = styled(FilterPluginStyle)`
+ display: flex;
+ align-items: center;
overflow-x: auto;
+
+ & .ant-tag {
+ margin-right: 0;
+ }
`;
const ControlContainer = styled.div<{
validateStatus?: 'error' | 'warning' | 'info';
}>`
+ display: flex;
+ height: 100%;
+ max-width: 100%;
padding: 2px;
& > span,
& > span:hover {
diff --git a/superset-frontend/src/filters/components/Time/transformProps.ts b/superset-frontend/src/filters/components/Time/transformProps.ts
index 883b6002d8..8262b8f63f 100644
--- a/superset-frontend/src/filters/components/Time/transformProps.ts
+++ b/superset-frontend/src/filters/components/Time/transformProps.ts
@@ -30,6 +30,7 @@ export default function transformProps(chartProps: ChartProps) {
behaviors,
filterState,
inputRef,
+ displaySettings,
} = chartProps;
const {
setDataMask = noOp,
@@ -54,5 +55,6 @@ export default function transformProps(chartProps: ChartProps) {
setFilterActive,
width,
inputRef,
+ filterBarOrientation: displaySettings?.filterBarOrientation,
};
}