You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by yo...@apache.org on 2022/10/12 00:38:47 UTC

[superset] branch master updated: refactor: preparation for time section migration (#21766)

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 8f61e3c5d9 refactor: preparation for time section migration (#21766)
8f61e3c5d9 is described below

commit 8f61e3c5d9fd0332ed76001c9ac8bd8d569f2d8d
Author: Yongjie Zhao <yo...@apache.org>
AuthorDate: Wed Oct 12 08:38:30 2022 +0800

    refactor: preparation for time section migration (#21766)
---
 .../superset-ui-chart-controls/src/index.ts        |   2 +-
 .../src/sections/echartsTimeSeriesQuery.tsx        |  15 +--
 .../src/sections/sections.tsx                      |   8 +-
 .../src/shared-controls/dndControls.tsx            |   5 +-
 .../src/shared-controls/index.tsx                  |  11 +--
 .../src/shared-controls/mixins.tsx                 |   5 +-
 .../superset-ui-chart-controls/test/fixtures.ts    |  10 +-
 .../test/utils/getTemporalColumns.test.ts          |   2 +-
 .../superset-ui-core/src/query/constants.ts        |  18 ++--
 .../superset-ui-core/src/query/getXAxis.ts         |   6 ++
 .../packages/superset-ui-core/src/query/index.ts   |   2 +-
 .../superset-ui-core/src/query/types/Column.ts     |   6 ++
 .../BigNumberWithTrendline/controlPanel.tsx        |  15 +--
 .../src/MixedTimeseries/controlPanel.tsx           |   9 +-
 .../src/MixedTimeseries/index.ts                   |   9 +-
 .../src/Timeseries/Area/index.ts                   |   7 +-
 .../src/Timeseries/Regular/Bar/index.ts            |   7 +-
 .../src/Timeseries/Regular/Line/index.ts           |   7 +-
 .../src/Timeseries/Regular/Scatter/index.ts        |   7 +-
 .../src/Timeseries/Regular/SmoothLine/index.ts     |   7 +-
 .../src/Timeseries/Step/index.ts                   |   7 +-
 .../plugin-chart-echarts/src/Timeseries/index.ts   |   9 +-
 .../src/plugin/buildQuery.ts                       |   7 +-
 .../src/plugin/controlPanel.tsx                    |   9 +-
 .../plugins/plugin-chart-table/src/buildQuery.ts   |   5 +-
 .../plugin-chart-table/src/controlPanel.tsx        |   7 +-
 .../dashboard/components/FiltersBadge/selectors.ts |   3 +-
 .../nativeFilters/FilterBar/FilterBar.test.tsx     |   2 +-
 .../controls/DateFilterControl/DateFilterLabel.tsx | 103 +++++++--------------
 .../DateFilterControl/components/AdvancedFrame.tsx |  24 ++---
 .../components/controls/DateFilterControl/index.ts |   5 +
 .../components/controls/DateFilterControl/types.ts |  11 +++
 .../controls/DateFilterControl/utils/constants.ts  |   6 ++
 .../DateFilterControl/utils/dateFilterUtils.ts     |  56 ++++++++++-
 .../DndAdhocFilterOption.tsx                       |  69 ++++++++++++++
 .../DndColumnSelectControl/DndFilterSelect.tsx     |  44 +++------
 .../index.tsx                                      |  76 +++++++--------
 .../AdhocFilterOption/AdhocFilterOption.test.tsx   |  20 ++--
 .../FilterControl/AdhocFilterOption/index.jsx      |  86 -----------------
 .../FilterControl/AdhocFilterOption/index.tsx      |  77 +++++++++++++++
 superset-frontend/src/explore/constants.ts         |   4 -
 .../getFormDataWithDashboardContext.ts             |   2 +-
 .../filters/components/Time/TimeFilterPlugin.tsx   |   3 +-
 43 files changed, 416 insertions(+), 377 deletions(-)

diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts
index 6d22c2a7ce..6aac9b5004 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts
@@ -37,4 +37,4 @@ export { legacySortBy } from './shared-controls/legacySortBy';
 export * from './shared-controls/emitFilterControl';
 export * from './shared-controls/components';
 export * from './types';
-export { xAxisMixin, temporalColumnMixin } from './shared-controls/mixins';
+export * from './shared-controls/mixins';
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/sections/echartsTimeSeriesQuery.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/sections/echartsTimeSeriesQuery.tsx
index 6fe14d3457..ac947abede 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/sections/echartsTimeSeriesQuery.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/sections/echartsTimeSeriesQuery.tsx
@@ -16,12 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import {
-  ContributionType,
-  FeatureFlag,
-  isFeatureEnabled,
-  t,
-} from '@superset-ui/core';
+import { ContributionType, hasGenericChartAxes, t } from '@superset-ui/core';
 import { ControlPanelSectionConfig } from '../types';
 import { emitFilterControl } from '../shared-controls/emitFilterControl';
 
@@ -29,12 +24,8 @@ export const echartsTimeSeriesQuery: ControlPanelSectionConfig = {
   label: t('Query'),
   expanded: true,
   controlSetRows: [
-    [isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) ? 'x_axis' : null],
-    [
-      isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-        ? 'time_grain_sqla'
-        : null,
-    ],
+    [hasGenericChartAxes ? 'x_axis' : null],
+    [hasGenericChartAxes ? 'time_grain_sqla' : null],
     ['metrics'],
     ['groupby'],
     [
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/sections/sections.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/sections/sections.tsx
index 4f4efdb82f..6214e2ba9c 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/sections/sections.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/sections/sections.tsx
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core';
+import { hasGenericChartAxes, t } from '@superset-ui/core';
 import { ControlPanelSectionConfig } from '../types';
 
 // A few standard controls sections that are used internally.
@@ -42,11 +42,7 @@ export const genericTime: ControlPanelSectionConfig = {
   ...baseTimeSection,
   controlSetRows: [
     ['granularity_sqla'],
-    [
-      isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-        ? null
-        : 'time_grain_sqla',
-    ],
+    [hasGenericChartAxes ? null : 'time_grain_sqla'],
     ['time_range'],
   ],
 };
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/dndControls.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/dndControls.tsx
index 7748777dfd..cf1cee2c16 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/dndControls.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/dndControls.tsx
@@ -30,6 +30,7 @@ import {
   SharedControlConfig,
   Dataset,
   Metric,
+  isDataset,
 } from '../types';
 import { DATASET_TIME_COLUMN_OPTION, TIME_FILTER_LABELS } from '../constants';
 import {
@@ -138,8 +139,8 @@ export const dndAdhocFilterControl: SharedControlConfig<
   default: [],
   description: '',
   mapStateToProps: ({ datasource, form_data }) => ({
-    columns: datasource?.columns[0]?.hasOwnProperty('filterable')
-      ? (datasource as Dataset)?.columns.filter(c => c.filterable)
+    columns: isDataset(datasource)
+      ? datasource.columns.filter(c => c.filterable)
       : datasource?.columns || [],
     savedMetrics: defineSavedMetrics(datasource),
     // current active adhoc metrics
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/index.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/index.tsx
index 89f6edba1b..de94c4e16c 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/index.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/index.tsx
@@ -35,11 +35,9 @@
  */
 import { isEmpty } from 'lodash';
 import {
-  FeatureFlag,
   t,
   getCategoricalSchemeRegistry,
   getSequentialSchemeRegistry,
-  isFeatureEnabled,
   SequentialScheme,
   legacyValidateInteger,
   ComparisionType,
@@ -47,6 +45,8 @@ import {
   isPhysicalColumn,
   ensureIsArray,
   isDefined,
+  hasGenericChartAxes,
+  NO_TIME_RANGE,
 } from '@superset-ui/core';
 
 import {
@@ -205,7 +205,7 @@ const time_grain_sqla: SharedControlConfig<'SelectControl'> = {
     choices: (datasource as Dataset)?.time_grain_sqla || [],
   }),
   visibility: ({ controls }) => {
-    if (!isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)) {
+    if (!hasGenericChartAxes) {
       return true;
     }
 
@@ -227,7 +227,7 @@ const time_range: SharedControlConfig<'DateFilterControl'> = {
   type: 'DateFilterControl',
   freeForm: true,
   label: TIME_FILTER_LABELS.time_range,
-  default: t('No filter'), // this value is translated, but the backend wouldn't understand a translated value?
+  default: NO_TIME_RANGE, // this value is an empty filter constant so shouldn't translate it.
   description: t(
     'The time range for the visualization. All relative times, e.g. "Last month", ' +
       '"Last 7 days", "now", etc. are evaluated on the server using the server\'s ' +
@@ -236,9 +236,6 @@ const time_range: SharedControlConfig<'DateFilterControl'> = {
       "using the engine's local timezone. Note one can explicitly set the timezone " +
       'per the ISO 8601 format if specifying either the start and/or end time.',
   ),
-  mapStateToProps: ({ datasource }) => ({
-    datasource,
-  }),
 };
 
 const row_limit: SharedControlConfig<'SelectControl'> = {
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/mixins.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/mixins.tsx
index 2939bb2b43..c268104d3d 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/mixins.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/mixins.tsx
@@ -17,8 +17,7 @@
  * under the License.
  */
 import {
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   QueryFormData,
   t,
   validateNonEmpty,
@@ -41,7 +40,7 @@ export const xAxisMixin = {
   validators: [validateNonEmpty],
   initialValue: (control: ControlState, state: ControlPanelState | null) => {
     if (
-      isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) &&
+      hasGenericChartAxes &&
       state?.form_data?.granularity_sqla &&
       !state.form_data?.x_axis &&
       !control?.value
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/fixtures.ts b/superset-frontend/packages/superset-ui-chart-controls/test/fixtures.ts
index d694bde883..92ce4af405 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/fixtures.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/fixtures.ts
@@ -23,7 +23,7 @@ export const TestDataset: Dataset = {
   column_format: {},
   columns: [
     {
-      advanced_data_type: null,
+      advanced_data_type: undefined,
       certification_details: null,
       certified_by: null,
       column_name: 'num',
@@ -41,7 +41,7 @@ export const TestDataset: Dataset = {
       warning_markdown: null,
     },
     {
-      advanced_data_type: null,
+      advanced_data_type: undefined,
       certification_details: null,
       certified_by: null,
       column_name: 'gender',
@@ -59,7 +59,7 @@ export const TestDataset: Dataset = {
       warning_markdown: null,
     },
     {
-      advanced_data_type: null,
+      advanced_data_type: undefined,
       certification_details: null,
       certified_by: null,
       column_name: 'state',
@@ -77,7 +77,7 @@ export const TestDataset: Dataset = {
       warning_markdown: null,
     },
     {
-      advanced_data_type: null,
+      advanced_data_type: undefined,
       certification_details: null,
       certified_by: null,
       column_name: 'ds',
@@ -95,7 +95,7 @@ export const TestDataset: Dataset = {
       warning_markdown: null,
     },
     {
-      advanced_data_type: null,
+      advanced_data_type: undefined,
       certification_details: null,
       certified_by: null,
       column_name: 'name',
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/utils/getTemporalColumns.test.ts b/superset-frontend/packages/superset-ui-chart-controls/test/utils/getTemporalColumns.test.ts
index 79dee957d1..8b94752c89 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/utils/getTemporalColumns.test.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/utils/getTemporalColumns.test.ts
@@ -24,7 +24,7 @@ test('get temporal columns from a Dataset', () => {
   expect(getTemporalColumns(TestDataset)).toEqual({
     temporalColumns: [
       {
-        advanced_data_type: null,
+        advanced_data_type: undefined,
         certification_details: null,
         certified_by: null,
         column_name: 'ds',
diff --git a/superset-frontend/packages/superset-ui-core/src/query/constants.ts b/superset-frontend/packages/superset-ui-core/src/query/constants.ts
index 9b9398b31a..812ad0990c 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/constants.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/constants.ts
@@ -1,11 +1,3 @@
-import {
-  ExtraFormDataAppend,
-  ExtraFormDataOverrideExtras,
-  ExtraFormDataOverrideRegular,
-  ExtraFormDataOverride,
-  QueryObject,
-} from './types';
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -24,7 +16,17 @@ import {
  * specific language governing permissions and limitations
  * under the License.
  */
+import {
+  ExtraFormDataAppend,
+  ExtraFormDataOverrideExtras,
+  ExtraFormDataOverrideRegular,
+  ExtraFormDataOverride,
+  QueryObject,
+} from './types';
+
 export const DTTM_ALIAS = '__timestamp';
+export const DEFAULT_TIME_RANGE = 'No filter'; // TODO: make this configurable per Superset installation
+export const NO_TIME_RANGE = 'No filter';
 
 export const EXTRA_FORM_DATA_OVERRIDE_EXTRA_KEYS: (keyof ExtraFormDataOverrideExtras)[] =
   ['relative_start', 'relative_end', 'time_grain_sqla'];
diff --git a/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts b/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
index 2413ef5166..8510f7d694 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
@@ -18,6 +18,8 @@
  */
 import {
   DTTM_ALIAS,
+  FeatureFlag,
+  isFeatureEnabled,
   getColumnLabel,
   isQueryFormColumn,
   QueryFormData,
@@ -26,6 +28,10 @@ import {
 export const isXAxisSet = (formData: QueryFormData) =>
   isQueryFormColumn(formData.x_axis);
 
+export const hasGenericChartAxes = isFeatureEnabled(
+  FeatureFlag.GENERIC_CHART_AXES,
+);
+
 export const getXAxis = (formData: QueryFormData): string | undefined => {
   // The formData should be "raw form_data" -- the snake_case version of formData rather than camelCase.
   if (!(formData.granularity_sqla || formData.x_axis)) {
diff --git a/superset-frontend/packages/superset-ui-core/src/query/index.ts b/superset-frontend/packages/superset-ui-core/src/query/index.ts
index c3d9bc1bd8..21c775ad6b 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/index.ts
@@ -29,7 +29,7 @@ export { default as getMetricLabel } from './getMetricLabel';
 export { default as DatasourceKey } from './DatasourceKey';
 export { default as normalizeOrderBy } from './normalizeOrderBy';
 export { normalizeTimeColumn } from './normalizeTimeColumn';
-export { getXAxis, isXAxisSet } from './getXAxis';
+export { getXAxis, isXAxisSet, hasGenericChartAxes } from './getXAxis';
 
 export * from './types/AnnotationLayer';
 export * from './types/QueryFormData';
diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Column.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Column.ts
index 693bf5e54a..15a5f29de6 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/Column.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/Column.ts
@@ -52,6 +52,12 @@ export interface Column {
   expression?: string | null;
   database_expression?: string | null;
   python_date_format?: string | null;
+
+  // used for advanced_data_type
+  optionName?: string;
+  filterBy?: string;
+  value?: string;
+  advanced_data_type?: string;
 }
 
 export function isPhysicalColumn(column?: any): column is PhysicalColumn {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx
index 7c46ca6a5f..71414105ad 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx
@@ -16,12 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import {
-  FeatureFlag,
-  isFeatureEnabled,
-  smartDateFormatter,
-  t,
-} from '@superset-ui/core';
+import { hasGenericChartAxes, smartDateFormatter, t } from '@superset-ui/core';
 import {
   ControlPanelConfig,
   D3_FORMAT_DOCS,
@@ -41,12 +36,8 @@ const config: ControlPanelConfig = {
       label: t('Query'),
       expanded: true,
       controlSetRows: [
-        [isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) ? 'x_axis' : null],
-        [
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-            ? 'time_grain_sqla'
-            : null,
-        ],
+        [hasGenericChartAxes ? 'x_axis' : null],
+        [hasGenericChartAxes ? 'time_grain_sqla' : null],
         ['metric'],
         ['adhoc_filters'],
       ],
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
index 00f2d9ed8f..619290a696 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
@@ -17,12 +17,7 @@
  * under the License.
  */
 import React from 'react';
-import {
-  ensureIsArray,
-  FeatureFlag,
-  isFeatureEnabled,
-  t,
-} from '@superset-ui/core';
+import { ensureIsArray, hasGenericChartAxes, t } from '@superset-ui/core';
 import { cloneDeep } from 'lodash';
 import {
   ControlPanelConfig,
@@ -292,7 +287,7 @@ function createAdvancedAnalyticsSection(
 const config: ControlPanelConfig = {
   controlPanelSections: [
     sections.genericTime,
-    isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+    hasGenericChartAxes
       ? {
           label: t('Shared query fields'),
           expanded: true,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
index 221e45bfd1..2f6a9fc577 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import buildQuery from './buildQuery';
@@ -57,7 +56,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Visualize two different series using the same x-axis. Note that both series can be visualized with a different chart type (e.g. 1 using bars and 1 using a line).',
             )
@@ -70,9 +69,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-          ? t('Mixed Chart')
-          : t('Mixed Time-Series'),
+        name: hasGenericChartAxes ? t('Mixed Chart') : t('Mixed Time-Series'),
         thumbnail,
         tags: [
           t('Advanced-Analytics'),
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/index.ts
index ee7c89993c..8b1407b120 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/index.ts
@@ -22,8 +22,7 @@ import {
   ChartPlugin,
   AnnotationType,
   Behavior,
-  isFeatureEnabled,
-  FeatureFlag,
+  hasGenericChartAxes,
 } from '@superset-ui/core';
 import buildQuery from '../buildQuery';
 import controlPanel from './controlPanel';
@@ -54,7 +53,7 @@ export default class EchartsAreaChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Area charts are similar to line charts in that they represent variables with the same scale, but area charts stack the metrics on top of each other.',
             )
@@ -68,7 +67,7 @@ export default class EchartsAreaChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Area Chart v2')
           : t('Time-series Area Chart'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/index.ts
index 2c74e6ac69..cc63d99dee 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import {
@@ -60,7 +59,7 @@ export default class EchartsTimeseriesBarChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t('Bar Charts are used to show metrics as a series of bars.')
           : t(
               'Time-series Bar Charts are used to show the changes in a metric over time as a series of bars.',
@@ -76,7 +75,7 @@ export default class EchartsTimeseriesBarChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Bar Chart v2')
           : t('Time-series Bar Chart v2'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/index.ts
index 957d460547..e00f2328fb 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import {
@@ -59,7 +58,7 @@ export default class EchartsTimeseriesLineChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Line chart is used to visualize measurements taken over a given category. Line chart is a type of chart which displays information as a series of data points connected by straight line segments. It is a basic type of chart common in many fields.',
             )
@@ -73,7 +72,7 @@ export default class EchartsTimeseriesLineChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Line Chart v2')
           : t('Time-series Line Chart'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/index.ts
index fc544bdf73..758b75d0ef 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import {
@@ -58,7 +57,7 @@ export default class EchartsTimeseriesScatterChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Scatter Plot has the horizontal axis in linear units, and the points are connected in order. It shows a statistical relationship between two variables.',
             )
@@ -72,7 +71,7 @@ export default class EchartsTimeseriesScatterChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Scatter Plot')
           : t('Time-series Scatter Plot'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/index.ts
index c1b8ca47b1..53c7cdeea7 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import {
@@ -58,7 +57,7 @@ export default class EchartsTimeseriesSmoothLineChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Smooth-line is a variation of the line chart. Without angles and hard edges, Smooth-line sometimes looks smarter and more professional.',
             )
@@ -72,7 +71,7 @@ export default class EchartsTimeseriesSmoothLineChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Smooth Line')
           : t('Time-series Smooth Line'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts
index 4889233ae0..c565a74d93 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import {
@@ -49,7 +48,7 @@ export default class EchartsTimeseriesStepChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Stepped-line graph (also called step chart) is a variation of line chart but with the line forming a series of steps between data points. A step chart can be useful when you want to show the changes that occur at irregular intervals.',
             )
@@ -63,7 +62,7 @@ export default class EchartsTimeseriesStepChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        name: hasGenericChartAxes
           ? t('Stepped Line')
           : t('Time-series Stepped Line'),
         tags: [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/index.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/index.ts
index cbdd5cb41b..e0532e848b 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/index.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/index.ts
@@ -21,8 +21,7 @@ import {
   Behavior,
   ChartMetadata,
   ChartPlugin,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   t,
 } from '@superset-ui/core';
 import buildQuery from './buildQuery';
@@ -48,7 +47,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
         behaviors: [Behavior.INTERACTIVE_CHART],
         category: t('Evolution'),
         credits: ['https://echarts.apache.org'],
-        description: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        description: hasGenericChartAxes
           ? t(
               'Swiss army knife for visualizing data. Choose between  step, line, scatter, and bar charts. This viz type has many customization options as well.',
             )
@@ -62,9 +61,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
           AnnotationType.Interval,
           AnnotationType.Timeseries,
         ],
-        name: isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-          ? t('Generic Chart')
-          : t('Time-series Chart'),
+        name: hasGenericChartAxes ? t('Generic Chart') : t('Time-series Chart'),
         tags: [
           t('Advanced-Analytics'),
           t('Aesthetic'),
diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts
index 8068ace2fd..b4bff7b45c 100644
--- a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts
@@ -22,8 +22,7 @@ import {
   AdhocColumn,
   buildQueryContext,
   ensureIsArray,
-  FeatureFlag,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   isPhysicalColumn,
   QueryFormColumn,
   QueryFormOrderBy,
@@ -42,7 +41,7 @@ export default function buildQuery(formData: PivotTableQueryFormData) {
     if (
       isPhysicalColumn(col) &&
       formData.time_grain_sqla &&
-      isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) &&
+      hasGenericChartAxes &&
       formData?.datetime_columns_lookup?.[col]
     ) {
       return {
@@ -66,7 +65,7 @@ export default function buildQuery(formData: PivotTableQueryFormData) {
     }
     return [
       {
-        ...(isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+        ...(hasGenericChartAxes
           ? omit(baseQueryObject, ['extras.time_grain_sqla'])
           : baseQueryObject),
         orderby: orderBy,
diff --git a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx
index fe69188b25..7287d2b9b2 100644
--- a/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-pivot-table/src/plugin/controlPanel.tsx
@@ -19,9 +19,8 @@
 import React from 'react';
 import {
   ensureIsArray,
-  FeatureFlag,
+  hasGenericChartAxes,
   isAdhocColumn,
-  isFeatureEnabled,
   isPhysicalColumn,
   QueryFormMetric,
   smartDateFormatter,
@@ -68,7 +67,7 @@ const config: ControlPanelConfig = {
           },
         ],
         [
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
+          hasGenericChartAxes
             ? {
                 name: 'time_grain_sqla',
                 config: {
@@ -98,9 +97,7 @@ const config: ControlPanelConfig = {
                 },
               }
             : null,
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)
-            ? 'datetime_columns_lookup'
-            : null,
+          hasGenericChartAxes ? 'datetime_columns_lookup' : null,
         ],
         [
           {
diff --git a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
index cf074310da..6e12123dce 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
@@ -20,9 +20,8 @@ import {
   AdhocColumn,
   buildQueryContext,
   ensureIsArray,
-  FeatureFlag,
   getMetricLabel,
-  isFeatureEnabled,
+  hasGenericChartAxes,
   isPhysicalColumn,
   QueryMode,
   QueryObject,
@@ -104,7 +103,7 @@ const buildQuery: BuildQuery<TableChartFormData> = (
         if (
           isPhysicalColumn(col) &&
           formData.time_grain_sqla &&
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) &&
+          hasGenericChartAxes &&
           formData?.datetime_columns_lookup?.[col]
         ) {
           return {
diff --git a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx
index e26481964d..f2d3740a78 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-table/src/controlPanel.tsx
@@ -23,6 +23,7 @@ import {
   ensureIsArray,
   FeatureFlag,
   GenericDataType,
+  hasGenericChartAxes,
   isAdhocColumn,
   isFeatureEnabled,
   isPhysicalColumn,
@@ -189,7 +190,7 @@ const config: ControlPanelConfig = {
           },
         ],
         [
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) && isAggMode
+          hasGenericChartAxes && isAggMode
             ? {
                 name: 'time_grain_sqla',
                 config: {
@@ -217,9 +218,7 @@ const config: ControlPanelConfig = {
                 },
               }
             : null,
-          isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) && isAggMode
-            ? 'datetime_columns_lookup'
-            : null,
+          hasGenericChartAxes && isAggMode ? 'datetime_columns_lookup' : null,
         ],
         [
           {
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
index 855ca303db..c0916b9960 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
@@ -25,8 +25,9 @@ import {
   FilterState,
   isFeatureEnabled,
   NativeFilterType,
+  NO_TIME_RANGE,
 } from '@superset-ui/core';
-import { NO_TIME_RANGE, TIME_FILTER_MAP } from 'src/explore/constants';
+import { TIME_FILTER_MAP } from 'src/explore/constants';
 import { getChartIdsInFilterBoxScope } from 'src/dashboard/util/activeDashboardFilters';
 import { ChartConfiguration } from 'src/dashboard/reducers/types';
 import { Layout } from 'src/dashboard/types';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx
index de7d6af99c..d14a94f8d3 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx
@@ -26,7 +26,7 @@ import { testWithId } from 'src/utils/testUtils';
 import { FeatureFlag } from 'src/featureFlags';
 import { Preset } from '@superset-ui/core';
 import { TimeFilterPlugin, SelectFilterPlugin } from 'src/filters/components';
-import { DATE_FILTER_CONTROL_TEST_ID } from 'src/explore/components/controls/DateFilterControl/DateFilterLabel';
+import { DATE_FILTER_CONTROL_TEST_ID } from 'src/explore/components/controls/DateFilterControl';
 import fetchMock from 'fetch-mock';
 import { waitFor } from '@testing-library/react';
 import FilterBar, { FILTER_BAR_TEST_ID } from '.';
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
index d8580fcbe1..b4cd377caf 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
@@ -17,17 +17,14 @@
  * under the License.
  */
 import React, { useState, useEffect, useMemo } from 'react';
-import rison from 'rison';
-import { css, SupersetClient, styled, t, useTheme } from '@superset-ui/core';
 import {
-  buildTimeRangeString,
-  formatTimeRange,
-  COMMON_RANGE_VALUES_SET,
-  CALENDAR_RANGE_VALUES_SET,
-  FRAME_OPTIONS,
-  customTimeRangeDecode,
-} from 'src/explore/components/controls/DateFilterControl/utils';
-import { getClientErrorObject } from 'src/utils/getClientErrorObject';
+  css,
+  styled,
+  t,
+  useTheme,
+  DEFAULT_TIME_RANGE,
+  NO_TIME_RANGE,
+} from '@superset-ui/core';
 import Button from 'src/components/Button';
 import ControlHeader from 'src/explore/components/ControlHeader';
 import Label, { Type } from 'src/components/Label';
@@ -35,14 +32,18 @@ import { Divider } from 'src/components';
 import Icons from 'src/components/Icons';
 import Select from 'src/components/Select/Select';
 import { Tooltip } from 'src/components/Tooltip';
-import { DEFAULT_TIME_RANGE } from 'src/explore/constants';
 import { useDebouncedEffect } from 'src/explore/exploreUtils';
 import { SLOW_DEBOUNCE } from 'src/constants';
-import { testWithId } from 'src/utils/testUtils';
 import { noOp } from 'src/utils/common';
-import { FrameType } from './types';
 import ControlPopover from '../ControlPopover/ControlPopover';
 
+import { DateFilterControlProps, FrameType } from './types';
+import {
+  fetchTimeRange,
+  FRAME_OPTIONS,
+  getDateFilterControlTestId,
+  guessFrame,
+} from './utils';
 import {
   CommonFrame,
   CalendarFrame,
@@ -50,42 +51,6 @@ import {
   AdvancedFrame,
 } from './components';
 
-const guessFrame = (timeRange: string): FrameType => {
-  if (COMMON_RANGE_VALUES_SET.has(timeRange)) {
-    return 'Common';
-  }
-  if (CALENDAR_RANGE_VALUES_SET.has(timeRange)) {
-    return 'Calendar';
-  }
-  if (timeRange === 'No filter') {
-    return 'No filter';
-  }
-  if (customTimeRangeDecode(timeRange).matchedFlag) {
-    return 'Custom';
-  }
-  return 'Advanced';
-};
-
-const fetchTimeRange = async (timeRange: string) => {
-  const query = rison.encode_uri(timeRange);
-  const endpoint = `/api/v1/time_range/?q=${query}`;
-  try {
-    const response = await SupersetClient.get({ endpoint });
-    const timeRangeString = buildTimeRangeString(
-      response?.json?.result?.since || '',
-      response?.json?.result?.until || '',
-    );
-    return {
-      value: formatTimeRange(timeRangeString),
-    };
-  } catch (response) {
-    const clientError = await getClientErrorObject(response);
-    return {
-      error: clientError.message || clientError.error,
-    };
-  }
-};
-
 const StyledPopover = styled(ControlPopover)``;
 const StyledRangeType = styled(Select)`
   width: 272px;
@@ -161,20 +126,6 @@ const IconWrapper = styled.span`
   }
 `;
 
-interface DateFilterControlProps {
-  name: string;
-  onChange: (timeRange: string) => void;
-  value?: string;
-  type?: Type;
-  onOpenPopover?: () => void;
-  onClosePopover?: () => void;
-}
-
-export const DATE_FILTER_CONTROL_TEST_ID = 'date-filter-control';
-export const getDateFilterControlTestId = testWithId(
-  DATE_FILTER_CONTROL_TEST_ID,
-);
-
 export default function DateFilterLabel(props: DateFilterControlProps) {
   const {
     value = DEFAULT_TIME_RANGE,
@@ -195,6 +146,12 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
   const [tooltipTitle, setTooltipTitle] = useState<string>(value);
 
   useEffect(() => {
+    if (value === NO_TIME_RANGE) {
+      setActualTimeRange(NO_TIME_RANGE);
+      setTooltipTitle(NO_TIME_RANGE);
+      setValidTimeRange(true);
+      return;
+    }
     fetchTimeRange(value).then(({ value: actualRange, error }) => {
       if (error) {
         setEvalResponse(error || '');
@@ -235,6 +192,12 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
 
   useDebouncedEffect(
     () => {
+      if (timeRangeValue === NO_TIME_RANGE) {
+        setEvalResponse(NO_TIME_RANGE);
+        setLastFetchedTimeRange(NO_TIME_RANGE);
+        setValidTimeRange(true);
+        return;
+      }
       if (lastFetchedTimeRange !== timeRangeValue) {
         fetchTimeRange(timeRangeValue).then(({ value: actualRange, error }) => {
           if (error) {
@@ -279,11 +242,11 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
     }
   };
 
-  function onChangeFrame(value: string) {
-    if (value === 'No filter') {
-      setTimeRangeValue('No filter');
+  function onChangeFrame(value: FrameType) {
+    if (value === NO_TIME_RANGE) {
+      setTimeRangeValue(NO_TIME_RANGE);
     }
-    setFrame(value as FrameType);
+    setFrame(value);
   }
 
   const theme = useTheme();
@@ -354,10 +317,6 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
     </IconWrapper>
   );
 
-  const overlayStyle = {
-    width: '600px',
-  };
-
   return (
     <>
       <ControlHeader {...props} />
@@ -369,7 +328,7 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
         defaultVisible={show}
         visible={show}
         onVisibleChange={togglePopover}
-        overlayStyle={overlayStyle}
+        overlayStyle={{ width: '600px' }}
       >
         <Tooltip placement="top" title={tooltipTitle}>
           <Label className="pointer" data-test="time-range-trigger">
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
index f865b703a7..77f42598ac 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/components/AdvancedFrame.tsx
@@ -24,20 +24,20 @@ import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
 import { FrameComponentProps } from 'src/explore/components/controls/DateFilterControl/types';
 import DateFunctionTooltip from './DateFunctionTooltip';
 
-export function AdvancedFrame(props: FrameComponentProps) {
-  function getAdvancedRange(value: string): string {
-    if (value.includes(SEPARATOR)) {
-      return value;
-    }
-    if (value.startsWith('Last')) {
-      return [value, ''].join(SEPARATOR);
-    }
-    if (value.startsWith('Next')) {
-      return ['', value].join(SEPARATOR);
-    }
-    return SEPARATOR;
+function getAdvancedRange(value: string): string {
+  if (value.includes(SEPARATOR)) {
+    return value;
   }
+  if (value.startsWith('Last')) {
+    return [value, ''].join(SEPARATOR);
+  }
+  if (value.startsWith('Next')) {
+    return ['', value].join(SEPARATOR);
+  }
+  return SEPARATOR;
+}
 
+export function AdvancedFrame(props: FrameComponentProps) {
   const advancedRange = getAdvancedRange(props.value || '');
   const [since, until] = advancedRange.split(SEPARATOR);
   if (advancedRange !== props.value) {
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/index.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/index.ts
index da29085f8b..199ecdc559 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/index.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/index.ts
@@ -17,3 +17,8 @@
  * under the License.
  */
 export { default } from './DateFilterLabel';
+export {
+  DATE_FILTER_CONTROL_TEST_ID,
+  fetchTimeRange,
+  guessFrame,
+} from './utils';
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
index 0fcdfca786..b7c69ea0cb 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
@@ -16,6 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { Type } from 'src/components/Label';
+
 export type SelectOptionType = {
   value: string;
   label: string;
@@ -89,3 +91,12 @@ export type FrameComponentProps = {
   onChange: (timeRange: string) => void;
   value: string;
 };
+
+export interface DateFilterControlProps {
+  name: string;
+  onChange: (timeRange: string) => void;
+  value?: string;
+  type?: Type;
+  onOpenPopover?: () => void;
+  onClosePopover?: () => void;
+}
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
index ca4a1f344d..1424ab918d 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
@@ -26,6 +26,7 @@ import {
   CommonRangeType,
   CalendarRangeType,
 } from 'src/explore/components/controls/DateFilterControl/types';
+import { testWithId } from 'src/utils/testUtils';
 
 export const FRAME_OPTIONS: SelectOptionType[] = [
   { value: 'Common', label: t('Last') },
@@ -131,3 +132,8 @@ export const LOCALE_MAPPING = {
   sl: 'sl_SI',
   nl: 'nl_NL',
 };
+
+export const DATE_FILTER_CONTROL_TEST_ID = 'date-filter-control';
+export const getDateFilterControlTestId = testWithId(
+  DATE_FILTER_CONTROL_TEST_ID,
+);
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
index fc14dd9855..05317d48e0 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
@@ -16,6 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import rison from 'rison';
+import { SupersetClient, NO_TIME_RANGE } from '@superset-ui/core';
+import { getClientErrorObject } from 'src/utils/getClientErrorObject';
+import {
+  COMMON_RANGE_VALUES_SET,
+  CALENDAR_RANGE_VALUES_SET,
+  customTimeRangeDecode,
+} from '.';
+import { FrameType } from '../types';
+
 export const SEPARATOR = ' : ';
 
 export const buildTimeRangeString = (since: string, until: string): string =>
@@ -24,11 +34,53 @@ export const buildTimeRangeString = (since: string, until: string): string =>
 const formatDateEndpoint = (dttm: string, isStart?: boolean): string =>
   dttm.replace('T00:00:00', '') || (isStart ? '-∞' : '∞');
 
-export const formatTimeRange = (timeRange: string) => {
+export const formatTimeRange = (
+  timeRange: string,
+  columnPlaceholder = 'col',
+) => {
   const splitDateRange = timeRange.split(SEPARATOR);
   if (splitDateRange.length === 1) return timeRange;
   return `${formatDateEndpoint(
     splitDateRange[0],
     true,
-  )} ≤ col < ${formatDateEndpoint(splitDateRange[1])}`;
+  )} ≤ ${columnPlaceholder} < ${formatDateEndpoint(splitDateRange[1])}`;
+};
+
+export const guessFrame = (timeRange: string): FrameType => {
+  if (COMMON_RANGE_VALUES_SET.has(timeRange)) {
+    return 'Common';
+  }
+  if (CALENDAR_RANGE_VALUES_SET.has(timeRange)) {
+    return 'Calendar';
+  }
+  if (timeRange === NO_TIME_RANGE) {
+    return 'No filter';
+  }
+  if (customTimeRangeDecode(timeRange).matchedFlag) {
+    return 'Custom';
+  }
+  return 'Advanced';
+};
+
+export const fetchTimeRange = async (
+  timeRange: string,
+  columnPlaceholder = 'col',
+) => {
+  const query = rison.encode_uri(timeRange);
+  const endpoint = `/api/v1/time_range/?q=${query}`;
+  try {
+    const response = await SupersetClient.get({ endpoint });
+    const timeRangeString = buildTimeRangeString(
+      response?.json?.result?.since || '',
+      response?.json?.result?.until || '',
+    );
+    return {
+      value: formatTimeRange(timeRangeString, columnPlaceholder),
+    };
+  } catch (response) {
+    const clientError = await getClientErrorObject(response);
+    return {
+      error: clientError.message || clientError.error || response.statusText,
+    };
+  }
 };
diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndAdhocFilterOption.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndAdhocFilterOption.tsx
new file mode 100644
index 0000000000..714855d43f
--- /dev/null
+++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndAdhocFilterOption.tsx
@@ -0,0 +1,69 @@
+/**
+ * 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 { DndItemType } from 'src/explore/components/DndItemType';
+import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
+import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
+import { OptionSortType } from 'src/explore/types';
+import OptionWrapper from './OptionWrapper';
+
+export interface DndAdhocFilterOptionProps {
+  adhocFilter: AdhocFilter;
+  onFilterEdit: (changedFilter: AdhocFilter) => void;
+  onClickClose: (index: number) => void;
+  onShiftOptions: (dragIndex: number, hoverIndex: number) => void;
+  options: OptionSortType[];
+  datasource: Record<string, any>;
+  partitionColumn?: string;
+  index: number;
+}
+
+export default function DndAdhocFilterOption({
+  adhocFilter,
+  options,
+  datasource,
+  onFilterEdit,
+  onShiftOptions,
+  onClickClose,
+  partitionColumn,
+  index,
+}: DndAdhocFilterOptionProps) {
+  return (
+    <AdhocFilterPopoverTrigger
+      key={index}
+      adhocFilter={adhocFilter}
+      options={options}
+      datasource={datasource}
+      onFilterEdit={onFilterEdit}
+      partitionColumn={partitionColumn}
+    >
+      <OptionWrapper
+        key={index}
+        index={index}
+        label={adhocFilter.getDefaultLabel()}
+        tooltipTitle={adhocFilter.getTooltipTitle()}
+        clickClose={onClickClose}
+        onShiftOptions={onShiftOptions}
+        type={DndItemType.FilterOption}
+        withCaret
+        isExtra={adhocFilter.isExtra}
+      />
+    </AdhocFilterPopoverTrigger>
+  );
+}
diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.tsx
index 58923f118d..5d023faedb 100644
--- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.tsx
+++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.tsx
@@ -35,7 +35,6 @@ import {
 import { Datasource, OptionSortType } from 'src/explore/types';
 import { OptionValueType } from 'src/explore/components/controls/DndColumnSelectControl/types';
 import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
-import OptionWrapper from 'src/explore/components/controls/DndColumnSelectControl/OptionWrapper';
 import DndSelectLabel from 'src/explore/components/controls/DndColumnSelectControl/DndSelectLabel';
 import AdhocFilter, {
   CLAUSES,
@@ -50,6 +49,7 @@ import {
 import { DndItemType } from 'src/explore/components/DndItemType';
 import { ControlComponentProps } from 'src/explore/components/Control';
 import AdhocFilterControl from '../FilterControl/AdhocFilterControl';
+import DndAdhocFilterOption from './DndAdhocFilterOption';
 
 const EMPTY_OBJECT = {};
 const DND_ACCEPTED_TYPES = [
@@ -296,32 +296,18 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
 
   const valuesRenderer = useCallback(
     () =>
-      values.map((adhocFilter: AdhocFilter, index: number) => {
-        const label = adhocFilter.getDefaultLabel();
-        const tooltipTitle = adhocFilter.getTooltipTitle();
-        return (
-          <AdhocFilterPopoverTrigger
-            key={index}
-            adhocFilter={adhocFilter}
-            options={options}
-            datasource={datasource}
-            onFilterEdit={onFilterEdit}
-            partitionColumn={partitionColumn}
-          >
-            <OptionWrapper
-              key={index}
-              index={index}
-              label={label}
-              tooltipTitle={tooltipTitle}
-              clickClose={onClickClose}
-              onShiftOptions={onShiftOptions}
-              type={DndItemType.FilterOption}
-              withCaret
-              isExtra={adhocFilter.isExtra}
-            />
-          </AdhocFilterPopoverTrigger>
-        );
-      }),
+      values.map((adhocFilter: AdhocFilter, index: number) => (
+        <DndAdhocFilterOption
+          index={index}
+          adhocFilter={adhocFilter}
+          options={options}
+          datasource={datasource}
+          onFilterEdit={onFilterEdit}
+          partitionColumn={partitionColumn}
+          onClickClose={onClickClose}
+          onShiftOptions={onShiftOptions}
+        />
+      )),
     [
       onClickClose,
       onFilterEdit,
@@ -401,9 +387,7 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
         visible={newFilterPopoverVisible}
         togglePopover={togglePopover}
         closePopover={closePopover}
-      >
-        <div />
-      </AdhocFilterPopoverTrigger>
+      />
     </>
   );
 };
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx
index 773e58c3e4..225efd5201 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx
@@ -39,6 +39,7 @@ import { Tooltip } from 'src/components/Tooltip';
 import { Input } from 'src/components/Input';
 import { optionLabel } from 'src/utils/common';
 import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
+import { ColumnMeta } from '@superset-ui/chart-controls';
 import useAdvancedDataTypes from './useAdvancedDataTypes';
 
 const StyledInput = styled(Input)`
@@ -61,20 +62,9 @@ const SelectWithLabel = styled(Select)<{ labelText: string }>`
   }
 `;
 
-export interface SimpleColumnType {
-  id: number;
-  column_name: string;
-  expression?: string;
-  type: string;
-  optionName?: string;
-  filterBy?: string;
-  value?: string;
-  advanced_data_type?: string;
-}
-
 export interface SimpleExpressionType {
   expressionType: keyof typeof EXPRESSION_TYPES;
-  column: SimpleColumnType;
+  column: ColumnMeta;
   aggregate: keyof typeof AGGREGATES;
   label: string;
 }
@@ -89,7 +79,7 @@ export interface MetricColumnType {
 }
 
 export type ColumnType =
-  | SimpleColumnType
+  | ColumnMeta
   | SimpleExpressionType
   | SQLExpressionType
   | MetricColumnType;
@@ -100,7 +90,7 @@ export interface Props {
   options: ColumnType[];
   datasource: {
     id: string;
-    columns: SimpleColumnType[];
+    columns: ColumnMeta[];
     type: string;
     filter_select: boolean;
   };
@@ -410,31 +400,35 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
     }
   }, [props.adhocFilter.comparator]);
 
-  return (
+  // another name for columns, just for following previous naming.
+  const subjectComponent = (
+    <Select
+      css={(theme: SupersetTheme) => ({
+        marginTop: theme.gridUnit * 4,
+        marginBottom: theme.gridUnit * 4,
+      })}
+      data-test="select-element"
+      options={columns.map(column => ({
+        value:
+          ('column_name' in column && column.column_name) ||
+          ('optionName' in column && column.optionName) ||
+          '',
+        label:
+          ('saved_metric_name' in column && column.saved_metric_name) ||
+          ('column_name' in column && column.column_name) ||
+          ('label' in column && column.label),
+        key:
+          ('id' in column && column.id) ||
+          ('optionName' in column && column.optionName) ||
+          undefined,
+        customLabel: renderSubjectOptionLabel(column),
+      }))}
+      {...subjectSelectProps}
+    />
+  );
+
+  const operatorsAndOperandComponent = (
     <>
-      <Select
-        css={(theme: SupersetTheme) => ({
-          marginTop: theme.gridUnit * 4,
-          marginBottom: theme.gridUnit * 4,
-        })}
-        data-test="select-element"
-        options={columns.map(column => ({
-          value:
-            ('column_name' in column && column.column_name) ||
-            ('optionName' in column && column.optionName) ||
-            '',
-          label:
-            ('saved_metric_name' in column && column.saved_metric_name) ||
-            ('column_name' in column && column.column_name) ||
-            ('label' in column && column.label),
-          key:
-            ('id' in column && column.id) ||
-            ('optionName' in column && column.optionName) ||
-            undefined,
-          customLabel: renderSubjectOptionLabel(column),
-        }))}
-        {...subjectSelectProps}
-      />
       <Select
         css={(theme: SupersetTheme) => ({ marginBottom: theme.gridUnit * 4 })}
         options={(props.operators ?? OPERATORS_OPTIONS)
@@ -484,6 +478,12 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
       )}
     </>
   );
+  return (
+    <>
+      {subjectComponent}
+      {operatorsAndOperandComponent}
+    </>
+  );
 };
 
 export default AdhocFilterEditPopoverSimpleTabContent;
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/AdhocFilterOption.test.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/AdhocFilterOption.test.tsx
index 34ec66d087..888eb5a8c3 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/AdhocFilterOption.test.tsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/AdhocFilterOption.test.tsx
@@ -25,7 +25,7 @@ import AdhocFilter, {
   EXPRESSION_TYPES,
   CLAUSES,
 } from 'src/explore/components/controls/FilterControl/AdhocFilter';
-import AdhocFilterOption from '.';
+import AdhocFilterOption, { AdhocFilterOptionProps } from '.';
 
 const simpleAdhocFilter = new AdhocFilter({
   expressionType: EXPRESSION_TYPES.SIMPLE,
@@ -44,18 +44,18 @@ const options = [
 const mockedProps = {
   adhocFilter: simpleAdhocFilter,
   onFilterEdit: jest.fn(),
+  onRemoveFilter: jest.fn(),
   options,
+  sections: [],
+  operators: [],
+  datasource: {},
+  partitionColumn: '',
+  onMoveLabel: jest.fn(),
+  onDropLabel: jest.fn(),
+  index: 1,
 };
 
-const setup = (props: {
-  adhocFilter: typeof simpleAdhocFilter;
-  onFilterEdit: () => void;
-  options: {
-    type: string;
-    column_name: string;
-    id: number;
-  }[];
-}) => (
+const setup = (props: AdhocFilterOptionProps) => (
   <DndProvider backend={HTML5Backend}>
     <AdhocFilterOption {...props} />
   </DndProvider>
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.jsx
deleted file mode 100644
index c9f90b7b29..0000000000
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.jsx
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * 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 PropTypes from 'prop-types';
-import adhocMetricType from 'src/explore/components/controls/MetricControl/adhocMetricType';
-import { OptionControlLabel } from 'src/explore/components/controls/OptionControls';
-import { DndItemType } from 'src/explore/components/DndItemType';
-import columnType from 'src/explore/components/controls/FilterControl/columnType';
-import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
-import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
-
-const propTypes = {
-  adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
-  onFilterEdit: PropTypes.func.isRequired,
-  onRemoveFilter: PropTypes.func,
-  options: PropTypes.arrayOf(
-    PropTypes.oneOfType([
-      columnType,
-      PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
-      adhocMetricType,
-    ]),
-  ).isRequired,
-  sections: PropTypes.arrayOf(PropTypes.string),
-  operators: PropTypes.arrayOf(PropTypes.string),
-  datasource: PropTypes.object,
-  partitionColumn: PropTypes.string,
-  onMoveLabel: PropTypes.func,
-  onDropLabel: PropTypes.func,
-  index: PropTypes.number,
-};
-
-const AdhocFilterOption = ({
-  adhocFilter,
-  options,
-  datasource,
-  onFilterEdit,
-  onRemoveFilter,
-  partitionColumn,
-  onMoveLabel,
-  onDropLabel,
-  index,
-  sections,
-  operators,
-}) => (
-  <AdhocFilterPopoverTrigger
-    sections={sections}
-    operators={operators}
-    adhocFilter={adhocFilter}
-    options={options}
-    datasource={datasource}
-    onFilterEdit={onFilterEdit}
-    partitionColumn={partitionColumn}
-  >
-    <OptionControlLabel
-      label={adhocFilter.getDefaultLabel()}
-      tooltipTitle={adhocFilter.getTooltipTitle()}
-      onRemove={onRemoveFilter}
-      onMoveLabel={onMoveLabel}
-      onDropLabel={onDropLabel}
-      index={index}
-      type={DndItemType.FilterOption}
-      withCaret
-      isExtra={adhocFilter.isExtra}
-    />
-  </AdhocFilterPopoverTrigger>
-);
-
-export default AdhocFilterOption;
-
-AdhocFilterOption.propTypes = propTypes;
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.tsx
new file mode 100644
index 0000000000..f1f1c902b0
--- /dev/null
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterOption/index.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 { OptionControlLabel } from 'src/explore/components/controls/OptionControls';
+import { DndItemType } from 'src/explore/components/DndItemType';
+import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
+import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
+import { OptionSortType } from 'src/explore/types';
+import { Operators } from 'src/explore/constants';
+
+export interface AdhocFilterOptionProps {
+  adhocFilter: AdhocFilter;
+  onFilterEdit: () => void;
+  onRemoveFilter: () => void;
+  options: OptionSortType[];
+  sections: string[];
+  operators: Operators[];
+  datasource: Record<string, any>;
+  partitionColumn: string;
+  onMoveLabel: () => void;
+  onDropLabel: () => void;
+  index: number;
+}
+
+export default function AdhocFilterOption({
+  adhocFilter,
+  options,
+  datasource,
+  onFilterEdit,
+  onRemoveFilter,
+  partitionColumn,
+  onMoveLabel,
+  onDropLabel,
+  index,
+  sections,
+  operators,
+}: AdhocFilterOptionProps) {
+  return (
+    <AdhocFilterPopoverTrigger
+      sections={sections}
+      operators={operators}
+      adhocFilter={adhocFilter}
+      options={options}
+      datasource={datasource}
+      onFilterEdit={onFilterEdit}
+      partitionColumn={partitionColumn}
+    >
+      <OptionControlLabel
+        label={adhocFilter.getDefaultLabel()}
+        tooltipTitle={adhocFilter.getTooltipTitle()}
+        onRemove={onRemoveFilter}
+        onMoveLabel={onMoveLabel}
+        onDropLabel={onDropLabel}
+        index={index}
+        type={DndItemType.FilterOption}
+        withCaret
+        isExtra={adhocFilter.isExtra}
+      />
+    </AdhocFilterPopoverTrigger>
+  );
+}
diff --git a/superset-frontend/src/explore/constants.ts b/superset-frontend/src/explore/constants.ts
index bc143743ca..56b8ca055f 100644
--- a/superset-frontend/src/explore/constants.ts
+++ b/superset-frontend/src/explore/constants.ts
@@ -142,10 +142,6 @@ export const TIME_FILTER_MAP = {
   granularity: '__granularity',
 };
 
-// TODO: make this configurable per Superset installation
-export const DEFAULT_TIME_RANGE = 'No filter';
-export const NO_TIME_RANGE = 'No filter';
-
 export enum FILTER_BOX_MIGRATION_STATES {
   CONVERTED = 'CONVERTED',
   NOOP = 'NOOP',
diff --git a/superset-frontend/src/explore/controlUtils/getFormDataWithDashboardContext.ts b/superset-frontend/src/explore/controlUtils/getFormDataWithDashboardContext.ts
index 28bdd68a90..f6cc31fe6f 100644
--- a/superset-frontend/src/explore/controlUtils/getFormDataWithDashboardContext.ts
+++ b/superset-frontend/src/explore/controlUtils/getFormDataWithDashboardContext.ts
@@ -29,8 +29,8 @@ import {
   AdhocFilter,
   isFreeFormAdhocFilter,
   isSimpleAdhocFilter,
+  NO_TIME_RANGE,
 } from '@superset-ui/core';
-import { NO_TIME_RANGE } from '../constants';
 
 const simpleFilterToAdhoc = (
   filterClause: QueryObjectFilterClause,
diff --git a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
index fabc9f136c..b97ce0bc6c 100644
--- a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
+++ b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx
@@ -16,10 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { styled } from '@superset-ui/core';
+import { styled, NO_TIME_RANGE } from '@superset-ui/core';
 import React, { useCallback, useEffect } from 'react';
 import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
-import { NO_TIME_RANGE } from 'src/explore/constants';
 import { PluginFilterTimeProps } from './types';
 import { FilterPluginStyle } from '../common';