feat(CalendarFrame): adding previous calendar quarter (#31889)

Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
This commit is contained in:
Alexandru Soare 2025-01-22 18:54:29 +02:00 committed by GitHub
parent b74da7963b
commit e4e07eef5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 139 additions and 2 deletions

View File

@ -39,11 +39,16 @@ export const GlobalStyles = () => (
.echarts-tooltip[style*='visibility: hidden'] { .echarts-tooltip[style*='visibility: hidden'] {
display: none !important; display: none !important;
} }
// Ant Design is applying inline z-index styles causing troubles
// TODO: Remove z-indexes when Ant Design is fully upgraded to v5
// Prefer vanilla Ant Design z-indexes that should work out of the box
.ant-popover, .ant-popover,
.antd5-dropdown, .antd5-dropdown,
.ant-dropdown, .ant-dropdown,
.ant-select-dropdown { .ant-select-dropdown,
z-index: ${theme.zIndex.max}; .antd5-modal-wrap,
.antd5-modal-mask {
z-index: ${theme.zIndex.max} !important;
} }
// TODO: Remove when buttons have been upgraded to Ant Design 5. // TODO: Remove when buttons have been upgraded to Ant Design 5.

View File

@ -0,0 +1,90 @@
/**
* 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 { render, screen, fireEvent } from 'spec/helpers/testing-library';
import { CalendarFrame } from '../components/CalendarFrame';
import { PreviousCalendarWeek, PreviousCalendarQuarter } from '../types';
import { CALENDAR_RANGE_OPTIONS } from '../utils/constants';
describe('CalendarFrame', () => {
it('calls onChange with PreviousCalendarWeek if value is not in CALENDAR_RANGE_SET', () => {
const mockOnChange = jest.fn();
render(<CalendarFrame onChange={mockOnChange} value="invalid-value" />);
expect(mockOnChange).toHaveBeenCalledWith(PreviousCalendarWeek);
});
it('renders null if value is not in CALENDAR_RANGE_SET', () => {
render(<CalendarFrame onChange={jest.fn()} value="invalid-value" />);
expect(
screen.queryByText('Configure Time Range: Previous...'),
).not.toBeInTheDocument();
});
it('renders the correct number of radio options', () => {
render(<CalendarFrame onChange={jest.fn()} value={PreviousCalendarWeek} />);
const radios = screen.getAllByRole('radio');
expect(radios).toHaveLength(CALENDAR_RANGE_OPTIONS.length);
CALENDAR_RANGE_OPTIONS.forEach(option => {
expect(screen.getByText(option.label)).toBeInTheDocument();
});
});
it('calls onChange with the correct value when a radio button is selected', () => {
const mockOnChange = jest.fn();
render(
<CalendarFrame
onChange={mockOnChange}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);
const secondOption = CALENDAR_RANGE_OPTIONS[1];
const radio = screen.getByLabelText(secondOption.label);
fireEvent.click(radio);
expect(mockOnChange).toHaveBeenCalledWith(secondOption.value);
});
it('renders the section title correctly', () => {
render(
<CalendarFrame
onChange={jest.fn()}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);
expect(
screen.getByText('Configure Time Range: Previous...'),
).toBeInTheDocument();
});
it('ensures the third option is PreviousCalendarQuarter', () => {
render(
<CalendarFrame
onChange={jest.fn()}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);
const thirdOption = CALENDAR_RANGE_OPTIONS[2];
expect(thirdOption.value).toBe(PreviousCalendarQuarter);
expect(screen.getByLabelText(thirdOption.label)).toBeInTheDocument();
});
});

View File

@ -80,10 +80,12 @@ export type CommonRangeType =
export const PreviousCalendarWeek = 'previous calendar week'; export const PreviousCalendarWeek = 'previous calendar week';
export const PreviousCalendarMonth = 'previous calendar month'; export const PreviousCalendarMonth = 'previous calendar month';
export const PreviousCalendarQuarter = 'previous calendar quarter';
export const PreviousCalendarYear = 'previous calendar year'; export const PreviousCalendarYear = 'previous calendar year';
export type CalendarRangeType = export type CalendarRangeType =
| typeof PreviousCalendarWeek | typeof PreviousCalendarWeek
| typeof PreviousCalendarMonth | typeof PreviousCalendarMonth
| typeof PreviousCalendarQuarter
| typeof PreviousCalendarYear; | typeof PreviousCalendarYear;
export const CurrentDay = 'Current day'; export const CurrentDay = 'Current day';

View File

@ -21,6 +21,7 @@ import {
SelectOptionType, SelectOptionType,
PreviousCalendarWeek, PreviousCalendarWeek,
PreviousCalendarMonth, PreviousCalendarMonth,
PreviousCalendarQuarter,
PreviousCalendarYear, PreviousCalendarYear,
CommonRangeType, CommonRangeType,
CalendarRangeType, CalendarRangeType,
@ -56,6 +57,7 @@ export const COMMON_RANGE_VALUES_SET = new Set(
export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [ export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [
{ value: PreviousCalendarWeek, label: t('previous calendar week') }, { value: PreviousCalendarWeek, label: t('previous calendar week') },
{ value: PreviousCalendarMonth, label: t('previous calendar month') }, { value: PreviousCalendarMonth, label: t('previous calendar month') },
{ value: PreviousCalendarQuarter, label: t('previous calendar quarter') },
{ value: PreviousCalendarYear, label: t('previous calendar year') }, { value: PreviousCalendarYear, label: t('previous calendar year') },
]; ];
export const CALENDAR_RANGE_VALUES_SET = new Set( export const CALENDAR_RANGE_VALUES_SET = new Set(
@ -119,6 +121,7 @@ export const COMMON_RANGE_SET: Set<CommonRangeType> = new Set([
export const CALENDAR_RANGE_SET: Set<CalendarRangeType> = new Set([ export const CALENDAR_RANGE_SET: Set<CalendarRangeType> = new Set([
PreviousCalendarWeek, PreviousCalendarWeek,
PreviousCalendarMonth, PreviousCalendarMonth,
PreviousCalendarQuarter,
PreviousCalendarYear, PreviousCalendarYear,
]); ]);

View File

@ -369,6 +369,15 @@ def get_since_until( # pylint: disable=too-many-arguments,too-many-locals,too-m
and separator not in time_range and separator not in time_range
): ):
time_range = "DATETRUNC(DATEADD(DATETIME('today'), -1, MONTH), MONTH) : DATETRUNC(DATETIME('today'), MONTH)" # pylint: disable=line-too-long,useless-suppression # noqa: E501 time_range = "DATETRUNC(DATEADD(DATETIME('today'), -1, MONTH), MONTH) : DATETRUNC(DATETIME('today'), MONTH)" # pylint: disable=line-too-long,useless-suppression # noqa: E501
if (
time_range
and time_range.startswith("previous calendar quarter")
and separator not in time_range
):
time_range = (
"DATETRUNC(DATEADD(DATETIME('today'), -1, QUARTER), QUARTER) : "
"DATETRUNC(DATETIME('today'), QUARTER)" # pylint: disable=line-too-long,useless-suppression # noqa: E501
)
if ( if (
time_range time_range
and time_range.startswith("previous calendar year") and time_range.startswith("previous calendar year")

View File

@ -19,6 +19,7 @@ from datetime import date, datetime, timedelta
from typing import Optional from typing import Optional
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import freezegun
import pytest import pytest
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
@ -316,6 +317,33 @@ def test_get_since_until_instant_time_comparison_enabled() -> None:
assert result == expected assert result == expected
def test_previous_calendar_quarter():
with freezegun.freeze_time("2023-01-15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2022, 10, 1), datetime(2023, 1, 1))
assert result == expected
with freezegun.freeze_time("2023, 4, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 1, 1), datetime(2023, 4, 1))
assert result == expected
with freezegun.freeze_time("2023, 8, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 4, 1), datetime(2023, 7, 1))
assert result == expected
with freezegun.freeze_time("2023, 10, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 7, 1), datetime(2023, 10, 1))
assert result == expected
with freezegun.freeze_time("2024, 1, 1"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 10, 1), datetime(2024, 1, 1))
assert result == expected
@patch("superset.utils.date_parser.parse_human_datetime", mock_parse_human_datetime) @patch("superset.utils.date_parser.parse_human_datetime", mock_parse_human_datetime)
def test_datetime_eval() -> None: def test_datetime_eval() -> None:
result = datetime_eval("datetime('now')") result = datetime_eval("datetime('now')")