This is an automated email from the ASF dual-hosted git repository.
arivero pushed a commit to branch time_comparison_zeros
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/time_comparison_zeros by this
push:
new 11b4e7360e Time Comparison:
11b4e7360e is described below
commit 11b4e7360e5870e4260835e3aa71175e50a66175
Author: Antonio Rivero <[email protected]>
AuthorDate: Thu Aug 22 12:19:33 2024 +0200
Time Comparison:
- Stop processing offsets in the frontend for custom or inherit and instead
use the backend so we avoid limitations on date formats and human readable
- If offset is a predefined one (not custom nor inherit) do not compute the
offset sine it's the same value
- No need to add extra date formats when computing the offset now since it
is always calle dafter parsing the date
---
.../src/time-comparison/getTimeOffset.ts | 33 +++---------
.../BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx | 39 ++++++++------
.../BigNumberPeriodOverPeriod/buildQuery.ts | 59 +++++++--------------
.../BigNumberPeriodOverPeriod/transformProps.ts | 39 ++------------
.../plugins/plugin-chart-table/src/buildQuery.ts | 61 ++++++++--------------
.../plugin-chart-table/src/transformProps.ts | 56 +++++++-------------
.../components/controls/ComparisonRangeLabel.tsx | 32 +++++++-----
.../components/controls/TimeOffsetControl.tsx | 26 ++++-----
8 files changed, 122 insertions(+), 223 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-core/src/time-comparison/getTimeOffset.ts
b/superset-frontend/packages/superset-ui-core/src/time-comparison/getTimeOffset.ts
index 15a5f9980f..b8f970dc10 100644
---
a/superset-frontend/packages/superset-ui-core/src/time-comparison/getTimeOffset.ts
+++
b/superset-frontend/packages/superset-ui-core/src/time-comparison/getTimeOffset.ts
@@ -22,27 +22,6 @@ import { customTimeRangeDecode } from
'./customTimeRangeDecode';
const DAY_IN_MS = 24 * 60 * 60 * 1000;
-export const parseDateParts = (dateParts: string[]) => {
- const parts = ensureIsArray(dateParts);
- if (parts.length === 3) {
- const [a, b, c] = parts;
- const parsedA = parseInt(a, 10);
- const parsedB = parseInt(b, 10);
- const parsedC = parseInt(c, 10);
- if (parsedA > 31)
- return { year: parsedA, month: parsedB - 1, day: parsedC }; // a is
year: YYYY-MM-DD
- if (parsedC > 31)
- return { year: parsedC, month: parsedA - 1, day: parsedB }; // c is
year: MM-DD-YYYY
- } else if (parts.length === 2) {
- const [a, b] = parts;
- const parsedA = parseInt(a, 10);
- const parsedB = parseInt(b, 10);
- if (parsedA > 31) return { year: parsedA, month: parsedB - 1, day: 0 }; //
a is year: YYYY-MM
- return { year: parsedB, month: parsedA - 1, day: 0 }; // b is year: MM-YYYY
- }
- return { year: 0, month: 0, day: 0 };
-};
-
export const parseDttmToDate = (
dttm: string,
isEndDate = false,
@@ -141,11 +120,15 @@ export const parseDttmToDate = (
if (parts.length === 1) {
parsed = new Date(Date.UTC(parseInt(parts[0], 10), 0));
} else if (parts.length === 2) {
- const parsedParts = parseDateParts(parts);
- parsed = new Date(Date.UTC(parsedParts.year, parsedParts.month));
+ parsed = new Date(
+ Date.UTC(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1),
+ );
} else if (parts.length === 3) {
- const parsedParts = parseDateParts(parts);
- parsed = new Date(parsedParts.year, parsedParts.month, parsedParts.day);
+ parsed = new Date(
+ parseInt(parts[0], 10),
+ parseInt(parts[1], 10) - 1,
+ parseInt(parts[2], 10),
+ );
} else {
parsed = new Date(dttm);
}
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx
index 7107ddff18..a2ebad8a03 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx
@@ -90,27 +90,34 @@ export default function PopKPI(props: PopKPIProps) {
if (!currentTimeRangeFilter || (!shift && !startDateOffset)) {
setComparisonRange('');
} else if (!isEmpty(shift) || startDateOffset) {
- const newShift = getTimeOffset({
- timeRangeFilter: {
- ...currentTimeRangeFilter,
- comparator:
- dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
- },
- shifts: ensureIsArray(shift),
- startDate: startDateOffset || '',
- });
const promise: any = fetchTimeRange(
dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
currentTimeRangeFilter.subject,
- newShift || [],
);
Promise.resolve(promise).then((res: any) => {
- const response: string[] = ensureIsArray(res.value);
- const firstRange: string = response.flat()[0];
- const rangeText = firstRange.split('vs\n');
- setComparisonRange(
- rangeText.length > 1 ? rangeText[1].trim() : rangeText[0],
- );
+ const datePattern = /\d{4}-\d{2}-\d{2}/g;
+ const dates = res?.value?.match(datePattern);
+ const [parsedStartDate, parsedEndDate] = dates ?? [];
+ const newShift = getTimeOffset({
+ timeRangeFilter: {
+ ...currentTimeRangeFilter,
+ comparator: `${parsedStartDate} : ${parsedEndDate}`,
+ },
+ shifts: ensureIsArray(shift),
+ startDate: startDateOffset || '',
+ });
+ fetchTimeRange(
+ dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
+ currentTimeRangeFilter.subject,
+ ensureIsArray(newShift),
+ ).then(res => {
+ const response: string[] = ensureIsArray(res.value);
+ const firstRange: string = response.flat()[0];
+ const rangeText = firstRange.split('vs\n');
+ setComparisonRange(
+ rangeText.length > 1 ? rangeText[1].trim() : rangeText[0],
+ );
+ });
});
}
}, [currentTimeRangeFilter, shift, startDateOffset, dashboardTimeRange]);
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/buildQuery.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/buildQuery.ts
index 2c680b8310..e230097e26 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/buildQuery.ts
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/buildQuery.ts
@@ -21,9 +21,6 @@ import {
QueryFormData,
PostProcessingRule,
ensureIsArray,
- SimpleAdhocFilter,
- getTimeOffset,
- parseDttmToDate,
} from '@superset-ui/core';
import {
isTimeComparison,
@@ -37,48 +34,28 @@ export default function buildQuery(formData: QueryFormData)
{
const queryContextA = buildQueryContext(formData, baseQueryObject => {
const postProcessing: PostProcessingRule[] = [];
postProcessing.push(timeCompareOperator(formData, baseQueryObject));
- const TimeRangeFilters =
- formData.adhoc_filters?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
- // In case the viz is using all version of controls, we try to load them
- const previousCustomTimeRangeFilters: any =
- formData.adhoc_custom?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
+ const nonCustomNorInheritShifts = ensureIsArray(
+ formData.time_compare,
+ ).filter((shift: string) => shift !== 'custom' && shift !== 'inherit');
+ const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
+ (shift: string) => shift === 'custom' || shift === 'inherit',
+ );
+
+ let timeOffsets: string[] = [];
- let previousCustomStartDate = '';
- if (
- !isEmpty(previousCustomTimeRangeFilters) &&
- previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
- ) {
- previousCustomStartDate =
- previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
+ // Shifts for non-custom or non inherit time comparison
+ if (!isEmpty(nonCustomNorInheritShifts)) {
+ timeOffsets = nonCustomNorInheritShifts;
}
- let timeOffsets = ensureIsArray(
- isTimeComparison(formData, baseQueryObject)
- ? getTimeOffset({
- timeRangeFilter: {
- ...TimeRangeFilters[0],
- comparator:
- baseQueryObject?.time_range ??
- (TimeRangeFilters[0] as any)?.comparator,
- },
- shifts: formData.time_compare,
- startDate:
- previousCustomStartDate && !formData.start_date_offset
- ? parseDttmToDate(previousCustomStartDate)?.toUTCString()
- : formData.start_date_offset,
- })
- : [],
- );
- if (isEmpty(timeOffsets)) {
- if (formData.time_compare && formData.time_compare === 'custom') {
- timeOffsets = [formData.start_date_offset];
- } else {
- timeOffsets = ensureIsArray(formData.time_compare) || [];
+ // Shifts for custom or inherit time comparison
+ if (!isEmpty(customOrInheritShifts)) {
+ if (customOrInheritShifts.includes('custom')) {
+ timeOffsets = timeOffsets.concat([formData.start_date_offset]);
+ }
+ if (customOrInheritShifts.includes('inherit')) {
+ timeOffsets = timeOffsets.concat(['inherit']);
}
}
return [
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
index 3381e26a8a..e04dda0763 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
@@ -24,10 +24,7 @@ import {
getNumberFormatter,
SimpleAdhocFilter,
ensureIsArray,
- getTimeOffset,
- parseDttmToDate,
} from '@superset-ui/core';
-import { isEmpty } from 'lodash';
import { getComparisonFontSize, getHeaderFontSize } from './utils';
export const parseMetricValue = (metricValue: number | string | null) => {
@@ -99,43 +96,15 @@ export default function transformProps(chartProps:
ChartProps) {
(adhoc_filter: SimpleAdhocFilter) =>
adhoc_filter.operator === 'TEMPORAL_RANGE',
)?.[0];
- // In case the viz is using all version of controls, we try to load them
- const previousCustomTimeRangeFilters: any =
- chartProps.rawFormData?.adhoc_custom?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
- let previousCustomStartDate = '';
- if (
- !isEmpty(previousCustomTimeRangeFilters) &&
- previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
- ) {
- previousCustomStartDate =
- previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
- }
const isCustomOrInherit =
timeComparison === 'custom' || timeComparison === 'inherit';
let dataOffset: string[] = [];
if (isCustomOrInherit) {
- dataOffset = getTimeOffset({
- timeRangeFilter: {
- ...currentTimeRangeFilter,
- comparator:
- formData?.extraFormData?.time_range ??
- (currentTimeRangeFilter as any)?.comparator,
- },
- shifts: ensureIsArray(timeComparison),
- startDate:
- previousCustomStartDate && !startDateOffset
- ? parseDttmToDate(previousCustomStartDate)?.toUTCString()
- : startDateOffset,
- });
- if (isEmpty(dataOffset)) {
- if (timeComparison && timeComparison === 'custom') {
- dataOffset = [startDateOffset];
- } else {
- dataOffset = ensureIsArray(timeComparison) || [];
- }
+ if (timeComparison && timeComparison === 'custom') {
+ dataOffset = [startDateOffset];
+ } else {
+ dataOffset = ensureIsArray(timeComparison) || [];
}
}
diff --git a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
index a3c7c37937..d63cf9ec38 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts
@@ -21,13 +21,10 @@ import {
buildQueryContext,
ensureIsArray,
getMetricLabel,
- getTimeOffset,
isPhysicalColumn,
- parseDttmToDate,
QueryMode,
QueryObject,
removeDuplicates,
- SimpleAdhocFilter,
} from '@superset-ui/core';
import { PostProcessingRule } from
'@superset-ui/core/src/query/types/PostProcessing';
import { BuildQuery } from
'@superset-ui/core/src/chart/registries/ChartBuildQueryRegistrySingleton';
@@ -87,49 +84,33 @@ const buildQuery: BuildQuery<TableChartFormData> = (
let { metrics, orderby = [], columns = [] } = baseQueryObject;
const { extras = {} } = baseQueryObject;
let postProcessing: PostProcessingRule[] = [];
- const TimeRangeFilters =
- formData.adhoc_filters?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
+ const nonCustomNorInheritShifts = ensureIsArray(
+ formData.time_compare,
+ ).filter((shift: string) => shift !== 'custom' && shift !== 'inherit');
+ const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
+ (shift: string) => shift === 'custom' || shift === 'inherit',
+ );
- // In case the viz is using all version of controls, we try to load them
- const previousCustomTimeRangeFilters: any =
- formData.adhoc_custom?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
+ let timeOffsets: string[] = [];
- let previousCustomStartDate = '';
+ // Shifts for non-custom or non inherit time comparison
if (
- !isEmpty(previousCustomTimeRangeFilters) &&
- previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
+ isTimeComparison(formData, baseQueryObject) &&
+ !isEmpty(nonCustomNorInheritShifts)
) {
- previousCustomStartDate =
- previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
+ timeOffsets = nonCustomNorInheritShifts;
}
- let timeOffsets = ensureIsArray(
- isTimeComparison(formData, baseQueryObject)
- ? getTimeOffset({
- timeRangeFilter: {
- ...TimeRangeFilters[0],
- comparator:
- baseQueryObject?.time_range ??
- (TimeRangeFilters[0] as any)?.comparator,
- },
- shifts: formData.time_compare,
- startDate:
- previousCustomStartDate && !formData.start_date_offset
- ? parseDttmToDate(previousCustomStartDate)?.toUTCString()
- : formData.start_date_offset,
- })
- : [],
- );
-
- if (isEmpty(timeOffsets)) {
- if (formData.time_compare && formData.time_compare === 'custom') {
- timeOffsets = [formData.start_date_offset];
- } else {
- timeOffsets = ensureIsArray(formData.time_compare) || [];
+ // Shifts for custom or inherit time comparison
+ if (
+ isTimeComparison(formData, baseQueryObject) &&
+ !isEmpty(customOrInheritShifts)
+ ) {
+ if (customOrInheritShifts.includes('custom')) {
+ timeOffsets = timeOffsets.concat([formData.start_date_offset]);
+ }
+ if (customOrInheritShifts.includes('inherit')) {
+ timeOffsets = timeOffsets.concat(['inherit']);
}
}
diff --git a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts
b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts
index d11d7ed972..48871e4ea4 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts
@@ -35,9 +35,6 @@ import {
SMART_DATE_ID,
TimeFormats,
TimeFormatter,
- SimpleAdhocFilter,
- getTimeOffset,
- parseDttmToDate,
} from '@superset-ui/core';
import {
ColorFormatters,
@@ -597,42 +594,27 @@ const transformProps = (
};
const timeGrain = extractTimegrain(formData);
- const TimeRangeFilters =
- chartProps.rawFormData?.adhoc_filters?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
- const previousCustomTimeRangeFilters: any =
- chartProps.rawFormData?.adhoc_custom?.filter(
- (filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
- ) || [];
-
- let previousCustomStartDate = '';
- if (
- !isEmpty(previousCustomTimeRangeFilters) &&
- previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
- ) {
- previousCustomStartDate =
- previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
+
+ const nonCustomNorInheritShifts =
ensureIsArray(formData.time_compare).filter(
+ (shift: string) => shift !== 'custom' && shift !== 'inherit',
+ );
+ const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
+ (shift: string) => shift === 'custom' || shift === 'inherit',
+ );
+
+ let timeOffsets: string[] = [];
+
+ if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) {
+ timeOffsets = nonCustomNorInheritShifts;
}
- let timeOffsets = getTimeOffset({
- timeRangeFilter: {
- ...TimeRangeFilters[0],
- comparator:
- formData?.extra_form_data?.time_range ??
- (TimeRangeFilters[0] as any)?.comparator,
- },
- shifts: formData.time_compare,
- startDate:
- previousCustomStartDate && !formData.start_date_offset
- ? parseDttmToDate(previousCustomStartDate)?.toUTCString()
- : formData.start_date_offset,
- });
- if (isEmpty(timeOffsets)) {
- if (formData.time_compare && formData.time_compare === 'custom') {
- timeOffsets = [formData.start_date_offset];
- } else {
- timeOffsets = ensureIsArray(formData.time_compare) || [];
+ // Shifts for custom or inherit time comparison
+ if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) {
+ if (customOrInheritShifts.includes('custom')) {
+ timeOffsets = timeOffsets.concat([formData.start_date_offset]);
+ }
+ if (customOrInheritShifts.includes('inherit')) {
+ timeOffsets = timeOffsets.concat(['inherit']);
}
}
const comparisonSuffix = isUsingTimeComparison
diff --git
a/superset-frontend/src/explore/components/controls/ComparisonRangeLabel.tsx
b/superset-frontend/src/explore/components/controls/ComparisonRangeLabel.tsx
index f5ac1e961c..7385431e0b 100644
--- a/superset-frontend/src/explore/components/controls/ComparisonRangeLabel.tsx
+++ b/superset-frontend/src/explore/components/controls/ComparisonRangeLabel.tsx
@@ -108,24 +108,28 @@ export const ComparisonRangeLabel = ({
);
}
const promises = currentTimeRangeFilters.map(filter => {
- const newShifts = getTimeOffset({
- timeRangeFilter: filter,
- shifts: shiftsArray,
- startDate: useStartDate,
- includeFutureOffsets: false, // So we don't trigger requests for
future dates
- });
+ const nonCustomNorInheritShifts =
+ shiftsArray.filter(
+ (shift: string) => shift !== 'custom' && shift !== 'inherit',
+ ) || [];
+ const customOrInheritShifts =
+ shiftsArray.filter(
+ (shift: string) => shift === 'custom' || shift === 'inherit',
+ ) || [];
- if (!isEmpty(newShifts)) {
+ // There's no custom or inherit to compute, so we can just fetch the
time range
+ if (isEmpty(customOrInheritShifts)) {
return fetchTimeRange(
filter.comparator,
filter.subject,
- ensureIsArray(newShifts),
+ ensureIsArray(nonCustomNorInheritShifts),
);
}
- // Need to parse Human readable dates to actual dates
+ // Need to compute custom or inherit shifts first and then mix with
the non custom or inherit shifts
if (
- (ensureIsArray(shifts)[0] === 'custom' && startDate) ||
- ensureIsArray(shifts)[0] !== 'custom'
+ (ensureIsArray(customOrInheritShifts).includes('custom') &&
+ startDate) ||
+ ensureIsArray(customOrInheritShifts).includes('inherit')
) {
return fetchTimeRange(filter.comparator, filter.subject).then(res =>
{
const datePattern = /\d{4}-\d{2}-\d{2}/g;
@@ -143,14 +147,16 @@ export const ComparisonRangeLabel = ({
...filter,
comparator: `${parsedStartDate} : ${parsedEndDate}`,
},
- shifts: shiftsArray,
+ shifts: customOrInheritShifts,
startDate: useStartDate,
includeFutureOffsets: false, // So we don't trigger requests
for future dates
});
return fetchTimeRange(
filter.comparator,
filter.subject,
- ensureIsArray(postProcessedShifts),
+ ensureIsArray(
+ postProcessedShifts.concat(nonCustomNorInheritShifts),
+ ),
);
}
}
diff --git
a/superset-frontend/src/explore/components/controls/TimeOffsetControl.tsx
b/superset-frontend/src/explore/components/controls/TimeOffsetControl.tsx
index 2cbf500e69..631a9e04da 100644
--- a/superset-frontend/src/explore/components/controls/TimeOffsetControl.tsx
+++ b/superset-frontend/src/explore/components/controls/TimeOffsetControl.tsx
@@ -131,22 +131,16 @@ export default function TimeOffsetControls({
useEffect(() => {
if (!isEmpty(currentTimeRangeFilters)) {
- customTimeRange(currentTimeRangeFilters[0]?.comparator ?? '');
- const date = currentTimeRangeFilters[0]?.comparator.split(' : ')[0];
- const parsedDate = parseDttmToDate(date);
- if (parsedDate) {
- setFormatedFilterDate(moment(parseDttmToDate(date)));
- } else {
- fetchTimeRange(
- currentTimeRangeFilters[0]?.comparator,
- currentTimeRangeFilters[0]?.subject,
- ).then(res => {
- const datePattern = /\d{4}-\d{2}-\d{2}/g;
- const dates = res?.value?.match(datePattern);
- const [startDate, _] = dates ?? [];
- setFormatedFilterDate(moment(parseDttmToDate(startDate)));
- });
- }
+ fetchTimeRange(
+ currentTimeRangeFilters[0]?.comparator,
+ currentTimeRangeFilters[0]?.subject,
+ ).then(res => {
+ const datePattern = /\d{4}-\d{2}-\d{2}/g;
+ const dates = res?.value?.match(datePattern);
+ const [startDate, endDate] = dates ?? [];
+ customTimeRange(`${startDate} : ${endDate}` ?? '');
+ setFormatedFilterDate(moment(parseDttmToDate(startDate)));
+ });
} else {
setCustomStartDateInFilter(undefined);
setFormatedFilterDate(moment(parseDttmToDate('')));