fix: Enlarged select filter value (#15373)
* fix: Enlarged select filter value
* fix: Makes the label take the whole width
* fix: Moves the required icon before the cascade icon
* fix: Fixes the cascading icon overlap with big texts
(cherry picked from commit 819118be13147129a42230bbeb893c6cf7e387f1)
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 480bde3..db57fdf 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControl.tsx
@@ -18,11 +18,24 @@
*/
import React from 'react';
import { styled } from '@superset-ui/core';
+import { Form, FormItem } from 'src/components/Form';
import FilterValue from './FilterValue';
import { FilterProps } from './types';
+import { checkIsMissingRequiredValue } from '../utils';
+
+const StyledFormItem = styled(FormItem)`
+ & label {
+ width: 100%;
+ padding-right: ${({ theme }) => theme.gridUnit * 11}px;
+ }
+`;
+
+const StyledIcon = styled.div`
+ position: absolute;
+ right: 0;
+`;
const StyledFilterControlTitle = styled.h4`
- width: 100%;
font-size: ${({ theme }) => theme.typography.sizes.s}px;
color: ${({ theme }) => theme.colors.grayscale.dark1};
margin: 0;
@@ -37,7 +50,7 @@
margin-bottom: ${({ theme }) => theme.gridUnit}px;
`;
-const StyledFilterControlContainer = styled.div`
+const StyledFilterControlContainer = styled(Form)`
width: 100%;
`;
@@ -50,21 +63,34 @@
inView,
}) => {
const { name = '<undefined>' } = filter;
+
+ const isMissingRequiredValue = checkIsMissingRequiredValue(
+ filter,
+ filter.dataMask?.filterState,
+ );
+
return (
- <StyledFilterControlContainer>
- <StyledFilterControlTitleBox>
- <StyledFilterControlTitle data-test="filter-control-name">
- {name}
- </StyledFilterControlTitle>
- <div data-test="filter-icon">{icon}</div>
- </StyledFilterControlTitleBox>
- <FilterValue
- dataMaskSelected={dataMaskSelected}
- filter={filter}
- directPathToChild={directPathToChild}
- onFilterSelectionChange={onFilterSelectionChange}
- inView={inView}
- />
+ <StyledFilterControlContainer layout="vertical">
+ <StyledFormItem
+ label={
+ <StyledFilterControlTitleBox>
+ <StyledFilterControlTitle data-test="filter-control-name">
+ {name}
+ </StyledFilterControlTitle>
+ <StyledIcon data-test="filter-icon">{icon}</StyledIcon>
+ </StyledFilterControlTitleBox>
+ }
+ required={filter?.controlValues?.enableEmptyFilter}
+ validateStatus={isMissingRequiredValue ? 'error' : undefined}
+ >
+ <FilterValue
+ dataMaskSelected={dataMaskSelected}
+ filter={filter}
+ directPathToChild={directPathToChild}
+ onFilterSelectionChange={onFilterSelectionChange}
+ inView={inView}
+ />
+ </StyledFormItem>
</StyledFilterControlContainer>
);
};
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 da66478..d756481 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
@@ -19,10 +19,10 @@
import React, { useEffect, useRef, useState } from 'react';
import {
QueryFormData,
- styled,
SuperChart,
DataMask,
t,
+ styled,
Behavior,
ChartDataResponseResult,
JsonObject,
@@ -43,13 +43,14 @@
import { FilterProps } from './types';
import { getFormData } from '../../utils';
import { useCascadingFilters } from './state';
-import { checkIsMissingRequiredValue } from '../utils';
-const FilterItem = styled.div`
- min-height: ${({ theme }) => theme.gridUnit * 11}px;
- padding-bottom: ${({ theme }) => theme.gridUnit * 3}px;
- & > div > div {
- height: auto;
+const HEIGHT = 32;
+
+// Overrides superset-ui height with min-height
+const StyledDiv = styled.div`
+ & > div {
+ height: auto !important;
+ min-height: ${HEIGHT}px;
}
`;
@@ -184,35 +185,27 @@
);
}
- const isMissingRequiredValue = checkIsMissingRequiredValue(
- filter,
- filter.dataMask?.filterState,
- );
-
return (
- <FilterItem data-test="form-item-value">
+ <StyledDiv data-test="form-item-value">
{isLoading ? (
<Loading position="inline-centered" />
) : (
<SuperChart
- height={50}
+ height={HEIGHT}
width="100%"
formData={formData}
// For charts that don't have datasource we need workaround for empty placeholder
queriesData={hasDataSource ? state : [{ data: [{}] }]}
chartType={filterType}
behaviors={[Behavior.NATIVE_FILTER]}
- filterState={{
- ...filter.dataMask?.filterState,
- validateMessage: isMissingRequiredValue && t('Value is required'),
- }}
+ filterState={{ ...filter.dataMask?.filterState }}
ownState={filter.dataMask?.ownState}
enableNoResults={metadata?.enableNoResults}
isRefreshing={isRefreshing}
hooks={{ setDataMask, setFocusedFilter, unsetFocusedFilter }}
/>
)}
- </FilterItem>
+ </StyledDiv>
);
};
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
index 85d5580..0b22dc7 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DefaultValue.tsx
@@ -22,7 +22,6 @@
SetDataMaskHook,
SuperChart,
AppSection,
- t,
} from '@superset-ui/core';
import { FormInstance } from 'antd/lib/form';
import Loading from 'src/components/Loading';
@@ -57,10 +56,6 @@
setLoading(true);
}
}, [hasDataset, queriesData]);
- const value = formFilter.defaultDataMask?.filterState.value;
- const isMissingRequiredValue =
- (value === null || value === undefined) &&
- formFilter?.controlValues?.enableEmptyFilter;
return loading ? (
<Loading position="inline-centered" />
) : (
@@ -79,7 +74,6 @@
enableNoResults={enableNoResults}
filterState={{
...formFilter.defaultDataMask?.filterState,
- validateMessage: isMissingRequiredValue && t('Value is required'),
}}
/>
);
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 449b5949..e6f7bd5 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -130,14 +130,24 @@
`;
export const StyledRowSubFormItem = styled(FormItem)`
+ min-width: 50%;
+
& .ant-form-item-label {
padding-bottom: 0;
}
+ .ant-form-item {
+ margin-bottom: 0;
+ }
+
.ant-form-item-control-input-content > div > div {
height: auto;
}
+ .ant-form-item-extra {
+ display: none;
+ }
+
& .ant-form-item-control-input {
height: auto;
}
@@ -749,7 +759,9 @@
if (hasValue) {
return Promise.resolve();
}
- return Promise.reject();
+ return Promise.reject(
+ new Error(t('Default value is required')),
+ );
},
},
]}
@@ -958,7 +970,7 @@
onChange={checked => onSortChanged(checked || undefined)}
initialValue={hasSorting}
>
- <StyledFormItem
+ <StyledRowFormItem
name={[
'filters',
filterId,
@@ -986,7 +998,7 @@
onSortChanged(value)
}
/>
- </StyledFormItem>
+ </StyledRowFormItem>
{hasMetrics && (
<StyledRowSubFormItem
name={['filters', filterId, 'sortMetric']}
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
index 6cb292d..fa6058d 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/state.ts
@@ -54,8 +54,7 @@
filterToEdit?: Filter,
) => {
const [hasDefaultValue, setHasPartialDefaultValue] = useState(
- !!filterToEdit?.defaultDataMask?.filterState?.value ||
- formFilter?.controlValues?.enableEmptyFilter,
+ !!filterToEdit?.defaultDataMask?.filterState?.value,
);
const [isRequired, setisRequired] = useState(
formFilter?.controlValues?.enableEmptyFilter,
diff --git a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
index 9cf1b2e..7e4ffaa 100644
--- a/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
@@ -26,11 +26,9 @@
GenericDataType,
JsonObject,
smartDateDetailedFormatter,
- styled,
t,
tn,
} from '@superset-ui/core';
-import { FormItem } from 'src/components/Form';
import React, {
RefObject,
ReactElement,
@@ -82,10 +80,6 @@
}
}
-const Error = styled.div`
- color: ${({ theme }) => theme.colors.error.base};
-`;
-
export default function PluginFilterSelect(props: PluginFilterSelectProps) {
const {
coltypeMap,
@@ -279,57 +273,52 @@
return (
<Styles height={height} width={width}>
- <FormItem
- validateStatus={filterState.validateMessage && 'error'}
- extra={<Error>{filterState.validateMessage}</Error>}
+ <StyledSelect
+ allowClear
+ // @ts-ignore
+ value={filterState.value || []}
+ disabled={isDisabled}
+ showSearch={showSearch}
+ mode={multiSelect ? 'multiple' : undefined}
+ placeholder={placeholderText}
+ onSearch={searchWrapper}
+ onSelect={clearSuggestionSearch}
+ onBlur={handleBlur}
+ onDropdownVisibleChange={setIsDropdownVisible}
+ dropdownRender={(
+ originNode: ReactElement & { ref?: RefObject<HTMLElement> },
+ ) => {
+ if (isDropdownVisible && !wasDropdownVisible) {
+ originNode.ref?.current?.scrollTo({ top: 0 });
+ }
+ return originNode;
+ }}
+ onFocus={setFocusedFilter}
+ // @ts-ignore
+ onChange={handleChange}
+ ref={inputRef}
+ loading={isRefreshing}
+ maxTagCount={5}
+ menuItemSelectedIcon={<Icon iconSize="m" />}
>
- <StyledSelect
- allowClear
- // @ts-ignore
- value={filterState.value || []}
- disabled={isDisabled}
- showSearch={showSearch}
- mode={multiSelect ? 'multiple' : undefined}
- placeholder={placeholderText}
- onSearch={searchWrapper}
- onSelect={clearSuggestionSearch}
- onBlur={handleBlur}
- onDropdownVisibleChange={setIsDropdownVisible}
- dropdownRender={(
- originNode: ReactElement & { ref?: RefObject<HTMLElement> },
- ) => {
- if (isDropdownVisible && !wasDropdownVisible) {
- originNode.ref?.current?.scrollTo({ top: 0 });
- }
- return originNode;
- }}
- onFocus={setFocusedFilter}
- // @ts-ignore
- onChange={handleChange}
- ref={inputRef}
- loading={isRefreshing}
- maxTagCount={5}
- menuItemSelectedIcon={<Icon iconSize="m" />}
- >
- {sortedData.map(row => {
- const [value] = groupby.map(col => row[col]);
- return (
- // @ts-ignore
- <Option key={`${value}`} value={value}>
- {labelFormatter(value, datatype)}
- </Option>
- );
- })}
- {currentSuggestionSearch &&
- !ensureIsArray(filterState.value).some(
- suggestion => suggestion === currentSuggestionSearch,
- ) && (
- <Option value={currentSuggestionSearch}>
- {`${t('Create "%s"', currentSuggestionSearch)}`}
- </Option>
- )}
- </StyledSelect>
- </FormItem>
+ {sortedData.map(row => {
+ const [value] = groupby.map(col => row[col]);
+ return (
+ // @ts-ignore
+ <Option key={`${value}`} value={value}>
+ {labelFormatter(value, datatype)}
+ </Option>
+ );
+ })}
+ {currentSuggestionSearch &&
+ !ensureIsArray(filterState.value).some(
+ suggestion => suggestion === currentSuggestionSearch,
+ ) && (
+ <Option value={currentSuggestionSearch}>
+ {`${t('Create "%s"', currentSuggestionSearch)}`}
+ </Option>
+ )}
+ </StyledSelect>
</Styles>
);
}
diff --git a/superset-frontend/src/filters/components/common.ts b/superset-frontend/src/filters/components/common.ts
index 1a57f2a..5d0046e 100644
--- a/superset-frontend/src/filters/components/common.ts
+++ b/superset-frontend/src/filters/components/common.ts
@@ -21,7 +21,7 @@
import { PluginFilterStylesProps } from './types';
export const Styles = styled.div<PluginFilterStylesProps>`
- height: ${({ height }) => height}px;
+ min-height: ${({ height }) => height}px;
width: ${({ width }) => width}px;
`;