This is an automated email from the ASF dual-hosted git repository.

rusackas 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 066f6b1f8a feat: add Current time-range options for time filter 
(#28637)
066f6b1f8a is described below

commit 066f6b1f8a0eeb10160439da29c1853c3dbe1a8b
Author: Pranav Sadagopan <[email protected]>
AuthorDate: Fri Jun 7 01:37:09 2024 +0530

    feat: add Current time-range options for time filter (#28637)
    
    Co-authored-by: Evan Rusackas <[email protected]>
---
 .../controls/DateFilterControl/DateFilterLabel.tsx |  8 +++
 .../components/CurrentCalendarFrame.tsx            | 65 ++++++++++++++++++++++
 .../controls/DateFilterControl/components/index.ts |  1 +
 .../CurrentCalendarFrame.test.tsx}                 | 24 ++++++--
 .../components/controls/DateFilterControl/types.ts | 13 +++++
 .../controls/DateFilterControl/utils/constants.ts  | 31 +++++++++--
 .../DateFilterControl/utils/dateFilterUtils.ts     |  4 ++
 superset/utils/date_parser.py                      | 30 ++++++++++
 tests/unit_tests/utils/date_parser_tests.py        | 20 +++++++
 9 files changed, 187 insertions(+), 9 deletions(-)

diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
index edfcf9b238..e5ef553267 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
@@ -53,6 +53,7 @@ import {
   AdvancedFrame,
   DateLabel,
 } from './components';
+import { CurrentCalendarFrame } from './components/CurrentCalendarFrame';
 
 const StyledRangeType = styled(Select)`
   width: 272px;
@@ -201,6 +202,7 @@ export default function DateFilterLabel(props: 
DateFilterControlProps) {
         if (
           guessedFrame === 'Common' ||
           guessedFrame === 'Calendar' ||
+          guessedFrame === 'Current' ||
           guessedFrame === 'No filter'
         ) {
           setActualTimeRange(value);
@@ -296,6 +298,12 @@ export default function DateFilterLabel(props: 
DateFilterControlProps) {
       {frame === 'Calendar' && (
         <CalendarFrame value={timeRangeValue} onChange={setTimeRangeValue} />
       )}
+      {frame === 'Current' && (
+        <CurrentCalendarFrame
+          value={timeRangeValue}
+          onChange={setTimeRangeValue}
+        />
+      )}
       {frame === 'Advanced' && (
         <AdvancedFrame value={timeRangeValue} onChange={setTimeRangeValue} />
       )}
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
new file mode 100644
index 0000000000..78fcacf5c0
--- /dev/null
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
@@ -0,0 +1,65 @@
+/**
+ * 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, { useEffect } from 'react';
+import { t } from '@superset-ui/core';
+import { Radio } from 'src/components/Radio';
+import {
+  CURRENT_RANGE_OPTIONS,
+  CURRENT_CALENDAR_RANGE_SET,
+} from 'src/explore/components/controls/DateFilterControl/utils';
+import { CurrentRangeType, CurrentWeek, FrameComponentProps } from '../types';
+
+export function CurrentCalendarFrame({ onChange, value }: FrameComponentProps) 
{
+  useEffect(() => {
+    if (!CURRENT_CALENDAR_RANGE_SET.has(value as CurrentRangeType)) {
+      onChange(CurrentWeek);
+    }
+  }, [value]);
+
+  if (!CURRENT_CALENDAR_RANGE_SET.has(value as CurrentRangeType)) {
+    return null;
+  }
+
+  return (
+    <>
+      <div className="section-title">
+        {t('Configure Time Range: Current...')}
+      </div>
+      <Radio.Group
+        value={value}
+        onChange={(e: any) => {
+          let newValue = e.target.value;
+          // Sanitization: Trim whitespace
+          newValue = newValue.trim();
+          // Validation: Check if the value is non-empty
+          if (newValue === '') {
+            return;
+          }
+          onChange(newValue);
+        }}
+      >
+        {CURRENT_RANGE_OPTIONS.map(({ value, label }) => (
+          <Radio key={value} value={value} className="vertical-radio">
+            {label}
+          </Radio>
+        ))}
+      </Radio.Group>
+    </>
+  );
+}
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
index 0d46ee7a97..29449c74d3 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
@@ -18,6 +18,7 @@
  */
 export { CommonFrame } from './CommonFrame';
 export { CalendarFrame } from './CalendarFrame';
+export { CurrentCalendarFrame } from './CurrentCalendarFrame';
 export { CustomFrame } from './CustomFrame';
 export { AdvancedFrame } from './AdvancedFrame';
 export { DateLabel } from './DateLabel';
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CurrentCalendarFrame.test.tsx
similarity index 51%
copy from 
superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
copy to 
superset-frontend/src/explore/components/controls/DateFilterControl/tests/CurrentCalendarFrame.test.tsx
index 0d46ee7a97..ae33aa119e 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/index.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CurrentCalendarFrame.test.tsx
@@ -16,8 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-export { CommonFrame } from './CommonFrame';
-export { CalendarFrame } from './CalendarFrame';
-export { CustomFrame } from './CustomFrame';
-export { AdvancedFrame } from './AdvancedFrame';
-export { DateLabel } from './DateLabel';
+import React from 'react';
+import { render } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect'; // For advanced DOM 
assertions
+import { CurrentCalendarFrame } from '../components/CurrentCalendarFrame';
+import { CurrentWeek } from '../types';
+
+const mockOnChange = jest.fn();
+
+test('calls onChange(CurrentWeek) when value is invalid', () => {
+  render(<CurrentCalendarFrame onChange={mockOnChange} value="InvalidValue" 
/>);
+  expect(mockOnChange).toHaveBeenCalledWith(CurrentWeek);
+});
+
+test('returns null if value is not a valid CurrentRangeType', () => {
+  const { container } = render(
+    <CurrentCalendarFrame onChange={mockOnChange} value="InvalidValue" />,
+  );
+  expect(container.childNodes.length).toBe(0);
+});
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts 
b/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
index ce5e812769..7062b48580 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
@@ -24,6 +24,7 @@ export type SelectOptionType = {
 export type FrameType =
   | 'Common'
   | 'Calendar'
+  | 'Current'
   | 'Custom'
   | 'Advanced'
   | 'No filter';
@@ -85,6 +86,18 @@ export type CalendarRangeType =
   | typeof PreviousCalendarMonth
   | typeof PreviousCalendarYear;
 
+export const CurrentDay = 'Current day';
+export const CurrentWeek = 'Current week';
+export const CurrentMonth = 'Current month';
+export const CurrentYear = 'Current year';
+export const CurrentQuarter = 'Current quarter';
+export type CurrentRangeType =
+  | typeof CurrentDay
+  | typeof CurrentWeek
+  | typeof CurrentMonth
+  | typeof CurrentQuarter
+  | typeof CurrentYear;
+
 export type FrameComponentProps = {
   onChange: (timeRange: string) => void;
   value: string;
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 ddd9bf2e58..cad7a0e816 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
@@ -25,11 +25,18 @@ import {
   PreviousCalendarYear,
   CommonRangeType,
   CalendarRangeType,
+  CurrentRangeType,
+  CurrentWeek,
+  CurrentMonth,
+  CurrentYear,
+  CurrentQuarter,
+  CurrentDay,
 } from 'src/explore/components/controls/DateFilterControl/types';
 
 export const FRAME_OPTIONS: SelectOptionType[] = [
   { value: 'Common', label: t('Last') },
   { value: 'Calendar', label: t('Previous') },
+  { value: 'Current', label: t('Current') },
   { value: 'Custom', label: t('Custom') },
   { value: 'Advanced', label: t('Advanced') },
   { value: 'No filter', label: t('No filter') },
@@ -48,16 +55,24 @@ export const COMMON_RANGE_VALUES_SET = new Set(
 
 export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [
   { value: PreviousCalendarWeek, label: t('previous calendar week') },
-  {
-    value: PreviousCalendarMonth,
-    label: t('previous calendar month'),
-  },
+  { value: PreviousCalendarMonth, label: t('previous calendar month') },
   { value: PreviousCalendarYear, label: t('previous calendar year') },
 ];
 export const CALENDAR_RANGE_VALUES_SET = new Set(
   CALENDAR_RANGE_OPTIONS.map(({ value }) => value),
 );
 
+export const CURRENT_RANGE_OPTIONS: SelectOptionType[] = [
+  { value: CurrentDay, label: t('Current day') },
+  { value: CurrentWeek, label: t('Current week') },
+  { value: CurrentMonth, label: t('Current month') },
+  { value: CurrentQuarter, label: t('Current quarter') },
+  { value: CurrentYear, label: t('Current year') },
+];
+export const CURRENT_RANGE_VALUES_SET = new Set(
+  CURRENT_RANGE_OPTIONS.map(({ value }) => value),
+);
+
 const GRAIN_OPTIONS = [
   { value: 'second', label: (rel: string) => t('Seconds %s', rel) },
   { value: 'minute', label: (rel: string) => t('Minutes %s', rel) },
@@ -107,6 +122,14 @@ export const CALENDAR_RANGE_SET: Set<CalendarRangeType> = 
new Set([
   PreviousCalendarYear,
 ]);
 
+export const CURRENT_CALENDAR_RANGE_SET: Set<CurrentRangeType> = new Set([
+  CurrentDay,
+  CurrentWeek,
+  CurrentMonth,
+  CurrentQuarter,
+  CurrentYear,
+]);
+
 export const MOMENT_FORMAT = 'YYYY-MM-DD[T]HH:mm:ss';
 export const SEVEN_DAYS_AGO = moment()
   .utc()
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 4be932e34a..835492e40b 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
@@ -21,6 +21,7 @@ import { useSelector } from 'react-redux';
 import {
   COMMON_RANGE_VALUES_SET,
   CALENDAR_RANGE_VALUES_SET,
+  CURRENT_RANGE_VALUES_SET,
   customTimeRangeDecode,
 } from '.';
 import { FrameType } from '../types';
@@ -32,6 +33,9 @@ export const guessFrame = (timeRange: string): FrameType => {
   if (CALENDAR_RANGE_VALUES_SET.has(timeRange)) {
     return 'Calendar';
   }
+  if (CURRENT_RANGE_VALUES_SET.has(timeRange)) {
+    return 'Current';
+  }
   if (timeRange === NO_TIME_RANGE) {
     return 'No filter';
   }
diff --git a/superset/utils/date_parser.py b/superset/utils/date_parser.py
index bffe50c624..a3736b0ab0 100644
--- a/superset/utils/date_parser.py
+++ b/superset/utils/date_parser.py
@@ -207,6 +207,36 @@ def get_since_until(  # pylint: 
disable=too-many-arguments,too-many-locals,too-m
         and separator not in time_range
     ):
         time_range = "DATETRUNC(DATEADD(DATETIME('today'), -1, YEAR), YEAR) : 
DATETRUNC(DATETIME('today'), YEAR)"  # pylint: 
disable=line-too-long,useless-suppression
+    if (
+        time_range
+        and time_range.startswith("Current day")
+        and separator not in time_range
+    ):
+        time_range = "DATETRUNC(DATEADD(DATETIME('today'), 0, DAY), DAY) : 
DATETRUNC(DATEADD(DATETIME('today'), 1, DAY), DAY)"  # pylint: 
disable=line-too-long,useless-suppression
+    if (
+        time_range
+        and time_range.startswith("Current week")
+        and separator not in time_range
+    ):
+        time_range = "DATETRUNC(DATEADD(DATETIME('today'), 0, WEEK), WEEK) : 
DATETRUNC(DATEADD(DATETIME('today'), 1, WEEK), WEEK)"  # pylint: 
disable=line-too-long,useless-suppression
+    if (
+        time_range
+        and time_range.startswith("Current month")
+        and separator not in time_range
+    ):
+        time_range = "DATETRUNC(DATEADD(DATETIME('today'), 0, MONTH), MONTH) : 
DATETRUNC(DATEADD(DATETIME('today'), 1, MONTH), MONTH)"  # pylint: 
disable=line-too-long,useless-suppression
+    if (
+        time_range
+        and time_range.startswith("Current quarter")
+        and separator not in time_range
+    ):
+        time_range = "DATETRUNC(DATEADD(DATETIME('today'), 0, QUARTER), 
QUARTER) : DATETRUNC(DATEADD(DATETIME('today'), 1, QUARTER), QUARTER)"  # 
pylint: disable=line-too-long,useless-suppression
+    if (
+        time_range
+        and time_range.startswith("Current year")
+        and separator not in time_range
+    ):
+        time_range = "DATETRUNC(DATEADD(DATETIME('today'), 0, YEAR), YEAR) : 
DATETRUNC(DATEADD(DATETIME('today'), 1, YEAR), YEAR)"  # pylint: 
disable=line-too-long,useless-suppression
 
     if time_range and separator in time_range:
         time_range_lookup = [
diff --git a/tests/unit_tests/utils/date_parser_tests.py 
b/tests/unit_tests/utils/date_parser_tests.py
index e007c17e82..a5a3f8b0ac 100644
--- a/tests/unit_tests/utils/date_parser_tests.py
+++ b/tests/unit_tests/utils/date_parser_tests.py
@@ -160,6 +160,26 @@ def test_get_since_until() -> None:
     expected = datetime(2015, 1, 1, 0, 0, 0), datetime(2016, 1, 1, 0, 0, 0)
     assert result == expected
 
+    result = get_since_until("Current day")
+    expected = datetime(2016, 11, 7, 0, 0, 0), datetime(2016, 11, 8, 0, 0, 0)
+    assert result == expected
+
+    result = get_since_until("Current week")
+    expected = datetime(2016, 11, 7, 0, 0, 0), datetime(2016, 11, 14, 0, 0, 0)
+    assert result == expected
+
+    result = get_since_until("Current month")
+    expected = datetime(2016, 11, 1, 0, 0, 0), datetime(2016, 12, 1, 0, 0, 0)
+    assert result == expected
+
+    result = get_since_until("Current quarter")
+    expected = datetime(2016, 10, 1, 0, 0, 0), datetime(2017, 1, 1, 0, 0, 0)
+    assert result == expected
+
+    result = get_since_until("Current year")
+    expected = expected = datetime(2016, 1, 1, 0, 0, 0), datetime(2017, 1, 1, 
0, 0, 0)
+    assert result == expected
+
     # Tests for our new instant_time_comparison logic and Feature Flag off
     result = get_since_until(
         time_range="2000-01-01T00:00:00 : 2018-01-01T00:00:00",

Reply via email to