Skip to content

Commit db95a93

Browse files
authored
feat(native-filters): allow cascading from time and numeric filters (#23319)
1 parent 63513a5 commit db95a93

File tree

4 files changed

+68
-47
lines changed

4 files changed

+68
-47
lines changed

superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { useToasts } from 'src/components/MessageToasts/withToasts';
2424
import { getClientErrorObject } from 'src/utils/getClientErrorObject';
2525
import { cacheWrapper } from 'src/utils/cacheWrapper';
2626
import { NativeFiltersForm } from '../types';
27-
import { doesColumnMatchFilterType } from './utils';
2827

2928
interface ColumnSelectProps {
3029
allowClear?: boolean;
@@ -84,10 +83,7 @@ export function ColumnSelect({
8483
);
8584

8685
useEffect(() => {
87-
if (
88-
currentColumn &&
89-
!doesColumnMatchFilterType(currentFilterType, currentColumn)
90-
) {
86+
if (currentColumn && !filterValues(currentColumn)) {
9187
resetColumnField();
9288
}
9389
}, [currentColumn, currentFilterType, resetColumnField]);

superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DependencyList.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@ import { Select } from 'src/components';
2323
import { CollapsibleControl } from './CollapsibleControl';
2424

2525
interface DependencyListProps {
26-
availableFilters: { label: string; value: string }[];
26+
availableFilters: {
27+
label: string;
28+
value: string;
29+
type: string | undefined;
30+
}[];
2731
dependencies: string[];
2832
onDependenciesChange: (dependencies: string[]) => void;
2933
getDependencySuggestion: () => string;
34+
children?: JSX.Element;
3035
}
3136

3237
const MainPanel = styled.div`
@@ -176,6 +181,7 @@ const DependencyList = ({
176181
dependencies = [],
177182
onDependenciesChange,
178183
getDependencySuggestion,
184+
children,
179185
}: DependencyListProps) => {
180186
const hasAvailableFilters = availableFilters.length > 0;
181187
const hasDependencies = dependencies.length > 0;
@@ -205,6 +211,7 @@ const DependencyList = ({
205211
onDependenciesChange={onDependenciesChange}
206212
getDependencySuggestion={getDependencySuggestion}
207213
/>
214+
{children}
208215
</CollapsibleControl>
209216
</MainPanel>
210217
);

superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,9 @@ export interface FiltersConfigFormProps {
299299
removedFilters: Record<string, FilterRemoval>;
300300
restoreFilter: (filterId: string) => void;
301301
form: FormInstance<NativeFiltersForm>;
302-
getAvailableFilters: (filterId: string) => { label: string; value: string }[];
302+
getAvailableFilters: (
303+
filterId: string,
304+
) => { label: string; value: string; type: string | undefined }[];
303305
handleActiveFilterPanelChange: (activeFilterPanel: string | string[]) => void;
304306
activeFilterPanelKeys: string | string[];
305307
isActive: boolean;
@@ -654,6 +656,9 @@ const FiltersConfigForm = (
654656

655657
const availableFilters = getAvailableFilters(filterId);
656658
const hasAvailableFilters = availableFilters.length > 0;
659+
const hasTimeDependency = availableFilters
660+
.filter(filter => filter.type === 'filter_time')
661+
.some(filter => dependencies.includes(filter.value));
657662

658663
useEffect(() => {
659664
if (datasetId) {
@@ -736,6 +741,42 @@ const FiltersConfigForm = (
736741
return <RemovedFilter onClick={() => restoreFilter(filterId)} />;
737742
}
738743

744+
const timeColumn = (
745+
<StyledRowFormItem
746+
name={['filters', filterId, 'granularity_sqla']}
747+
label={
748+
<>
749+
<StyledLabel>{t('Time column')}</StyledLabel>&nbsp;
750+
<InfoTooltipWithTrigger
751+
placement="top"
752+
tooltip={
753+
hasTimeDependency
754+
? t('Time column to apply dependent temporal filter to')
755+
: t('Time column to apply time range to')
756+
}
757+
/>
758+
</>
759+
}
760+
initialValue={filterToEdit?.granularity_sqla}
761+
>
762+
<ColumnSelect
763+
allowClear
764+
form={form}
765+
formField="granularity_sqla"
766+
filterId={filterId}
767+
filterValues={(column: Column) => !!column.is_dttm}
768+
datasetId={datasetId}
769+
onChange={column => {
770+
// We need reset default value when when column changed
771+
setNativeFilterFieldValues(form, filterId, {
772+
granularity_sqla: column,
773+
});
774+
forceUpdate();
775+
}}
776+
/>
777+
</StyledRowFormItem>
778+
);
779+
739780
return (
740781
<StyledTabs
741782
activeKey={activeTabKey}
@@ -892,7 +933,9 @@ const FiltersConfigForm = (
892933
getDependencySuggestion={() =>
893934
getDependencySuggestion(filterId)
894935
}
895-
/>
936+
>
937+
{hasTimeDependency ? timeColumn : undefined}
938+
</DependencyList>
896939
</StyledRowFormItem>
897940
)}
898941
{hasDataset && hasAdditionalFilters && (
@@ -966,39 +1009,9 @@ const FiltersConfigForm = (
9661009
/>
9671010
</StyledRowFormItem>
9681011
)}
969-
{hasTimeRange && (
970-
<StyledRowFormItem
971-
name={['filters', filterId, 'granularity_sqla']}
972-
label={
973-
<>
974-
<StyledLabel>{t('Time column')}</StyledLabel>&nbsp;
975-
<InfoTooltipWithTrigger
976-
placement="top"
977-
tooltip={t(
978-
'Optional time column if time range should apply to another column than the default time column',
979-
)}
980-
/>
981-
</>
982-
}
983-
initialValue={filterToEdit?.granularity_sqla}
984-
>
985-
<ColumnSelect
986-
allowClear
987-
form={form}
988-
formField="granularity_sqla"
989-
filterId={filterId}
990-
filterValues={(column: Column) => !!column.is_dttm}
991-
datasetId={datasetId}
992-
onChange={column => {
993-
// We need reset default value when when column changed
994-
setNativeFilterFieldValues(form, filterId, {
995-
granularity_sqla: column,
996-
});
997-
forceUpdate();
998-
}}
999-
/>
1000-
</StyledRowFormItem>
1001-
)}
1012+
{hasTimeRange && !hasTimeDependency
1013+
? timeColumn
1014+
: undefined}
10021015
</CollapsibleControl>
10031016
</CleanFormItem>
10041017
)}

superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ export interface FiltersConfigModalProps {
8989
onSave: (filterConfig: FilterConfiguration) => Promise<void>;
9090
onCancel: () => void;
9191
}
92-
export const ALLOW_DEPENDENCIES = ['filter_select'];
92+
export const ALLOW_DEPENDENCIES = [
93+
'filter_range',
94+
'filter_select',
95+
'filter_time',
96+
];
9397

9498
const DEFAULT_EMPTY_FILTERS: string[] = [];
9599
const DEFAULT_REMOVED_FILTERS: Record<string, FilterRemoval> = {};
@@ -287,11 +291,12 @@ function FiltersConfigModal({
287291
const getAvailableFilters = useCallback(
288292
(filterId: string) =>
289293
filterIds
290-
.filter(key => key !== filterId)
291-
.filter(filterId => canBeUsedAsDependency(filterId))
292-
.map(key => ({
293-
label: getFilterTitle(key),
294-
value: key,
294+
.filter(id => id !== filterId)
295+
.filter(id => canBeUsedAsDependency(id))
296+
.map(id => ({
297+
label: getFilterTitle(id),
298+
value: id,
299+
type: filterConfigMap[id]?.filterType,
295300
})),
296301
[canBeUsedAsDependency, filterIds, getFilterTitle],
297302
);

0 commit comments

Comments
 (0)