feat(native-filters): Adjust filter components for horizontal mode (#22273)
This commit is contained in:
parent
2bdf22b215
commit
eb6045adfa
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
`
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ const HorizontalFormItem = styled(StyledFormItem)`
|
|||
}
|
||||
|
||||
.ant-form-item-control {
|
||||
width: ${({ theme }) => theme.gridUnit * 40}px;
|
||||
width: ${({ theme }) => theme.gridUnit * 41}px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue