Skip to content

Commit 72ddf80

Browse files
Antonio-RiveroMartneznyohasstium
authored andcommitted
feat(time_comparison): Support all date formats when computing custom and inherit offsets (apache#30002)
1 parent 266872f commit 72ddf80

File tree

10 files changed

+217
-168
lines changed

10 files changed

+217
-168
lines changed

superset-frontend/packages/superset-ui-chart-controls/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,5 @@ export const DEFAULT_XAXIS_SORT_SERIES_DATA: SortSeriesData = {
7878
sort_series_type: SortSeriesType.Name,
7979
sort_series_ascending: true,
8080
};
81+
82+
export const DEFAULT_DATE_PATTERN = /\d{4}-\d{2}-\d{2}/g;

superset-frontend/packages/superset-ui-core/src/time-comparison/getTimeOffset.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@ import { ensureIsArray } from '../utils';
2121
import { customTimeRangeDecode } from './customTimeRangeDecode';
2222

2323
const DAY_IN_MS = 24 * 60 * 60 * 1000;
24+
2425
export const parseDttmToDate = (
2526
dttm: string,
2627
isEndDate = false,
2728
computingShifts = false,
2829
) => {
2930
const now = new Date();
30-
if (
31-
dttm === 'now' ||
32-
dttm === 'today' ||
33-
dttm === 'No filter' ||
34-
dttm === ''
35-
) {
31+
if (dttm === 'now' || dttm === 'No filter' || dttm === '') {
32+
return now;
33+
}
34+
35+
if (dttm === 'today') {
36+
now.setHours(0, 0, 0, 0);
3637
return now;
3738
}
3839

@@ -280,9 +281,12 @@ export const getTimeOffset = ({
280281

281282
const customShift =
282283
customStartDateTime &&
284+
filterStartDateTime &&
283285
Math.round((filterStartDateTime - customStartDateTime) / DAY_IN_MS);
284286
const inInheritShift =
285287
isInherit &&
288+
filterEndDateTime &&
289+
filterStartDateTime &&
286290
Math.round((filterEndDateTime - filterStartDateTime) / DAY_IN_MS);
287291

288292
const newShifts = ensureIsArray(shifts)
@@ -292,7 +296,7 @@ export const getTimeOffset = ({
292296
if (includeFutureOffsets && customShift < 0) {
293297
return `${customShift * -1} days after`;
294298
}
295-
if (customShift >= 0) {
299+
if (customShift >= 0 && filterStartDateTime) {
296300
return `${customShift} days ago`;
297301
}
298302
}

superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/PopKPI.tsx

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
t,
2727
useTheme,
2828
} from '@superset-ui/core';
29-
import { Tooltip } from '@superset-ui/chart-controls';
29+
import { DEFAULT_DATE_PATTERN, Tooltip } from '@superset-ui/chart-controls';
3030
import { isEmpty } from 'lodash';
3131
import {
3232
ColorSchemeEnum,
@@ -90,27 +90,33 @@ export default function PopKPI(props: PopKPIProps) {
9090
if (!currentTimeRangeFilter || (!shift && !startDateOffset)) {
9191
setComparisonRange('');
9292
} else if (!isEmpty(shift) || startDateOffset) {
93-
const newShift = getTimeOffset({
94-
timeRangeFilter: {
95-
...currentTimeRangeFilter,
96-
comparator:
97-
dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
98-
},
99-
shifts: ensureIsArray(shift),
100-
startDate: startDateOffset || '',
101-
});
10293
const promise: any = fetchTimeRange(
10394
dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
10495
currentTimeRangeFilter.subject,
105-
newShift || [],
10696
);
10797
Promise.resolve(promise).then((res: any) => {
108-
const response: string[] = ensureIsArray(res.value);
109-
const firstRange: string = response.flat()[0];
110-
const rangeText = firstRange.split('vs\n');
111-
setComparisonRange(
112-
rangeText.length > 1 ? rangeText[1].trim() : rangeText[0],
113-
);
98+
const dates = res?.value?.match(DEFAULT_DATE_PATTERN);
99+
const [parsedStartDate, parsedEndDate] = dates ?? [];
100+
const newShift = getTimeOffset({
101+
timeRangeFilter: {
102+
...currentTimeRangeFilter,
103+
comparator: `${parsedStartDate} : ${parsedEndDate}`,
104+
},
105+
shifts: ensureIsArray(shift),
106+
startDate: startDateOffset || '',
107+
});
108+
fetchTimeRange(
109+
dashboardTimeRange ?? (currentTimeRangeFilter as any).comparator,
110+
currentTimeRangeFilter.subject,
111+
ensureIsArray(newShift),
112+
).then(res => {
113+
const response: string[] = ensureIsArray(res.value);
114+
const firstRange: string = response.flat()[0];
115+
const rangeText = firstRange.split('vs\n');
116+
setComparisonRange(
117+
rangeText.length > 1 ? rangeText[1].trim() : rangeText[0],
118+
);
119+
});
114120
});
115121
}
116122
}, [currentTimeRangeFilter, shift, startDateOffset, dashboardTimeRange]);

superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/buildQuery.ts

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ import {
2121
QueryFormData,
2222
PostProcessingRule,
2323
ensureIsArray,
24-
SimpleAdhocFilter,
25-
getTimeOffset,
26-
parseDttmToDate,
2724
} from '@superset-ui/core';
2825
import {
2926
isTimeComparison,
@@ -37,43 +34,30 @@ export default function buildQuery(formData: QueryFormData) {
3734
const queryContextA = buildQueryContext(formData, baseQueryObject => {
3835
const postProcessing: PostProcessingRule[] = [];
3936
postProcessing.push(timeCompareOperator(formData, baseQueryObject));
40-
const TimeRangeFilters =
41-
formData.adhoc_filters?.filter(
42-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
43-
) || [];
4437

45-
// In case the viz is using all version of controls, we try to load them
46-
const previousCustomTimeRangeFilters: any =
47-
formData.adhoc_custom?.filter(
48-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
49-
) || [];
38+
const nonCustomNorInheritShifts = ensureIsArray(
39+
formData.time_compare,
40+
).filter((shift: string) => shift !== 'custom' && shift !== 'inherit');
41+
const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
42+
(shift: string) => shift === 'custom' || shift === 'inherit',
43+
);
44+
45+
let timeOffsets: string[] = [];
5046

51-
let previousCustomStartDate = '';
52-
if (
53-
!isEmpty(previousCustomTimeRangeFilters) &&
54-
previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
55-
) {
56-
previousCustomStartDate =
57-
previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
47+
// Shifts for non-custom or non inherit time comparison
48+
if (!isEmpty(nonCustomNorInheritShifts)) {
49+
timeOffsets = nonCustomNorInheritShifts;
5850
}
5951

60-
const timeOffsets = ensureIsArray(
61-
isTimeComparison(formData, baseQueryObject)
62-
? getTimeOffset({
63-
timeRangeFilter: {
64-
...TimeRangeFilters[0],
65-
comparator:
66-
baseQueryObject?.time_range ??
67-
(TimeRangeFilters[0] as any)?.comparator,
68-
},
69-
shifts: formData.time_compare,
70-
startDate:
71-
previousCustomStartDate && !formData.start_date_offset
72-
? parseDttmToDate(previousCustomStartDate)?.toUTCString()
73-
: formData.start_date_offset,
74-
})
75-
: [],
76-
);
52+
// Shifts for custom or inherit time comparison
53+
if (!isEmpty(customOrInheritShifts)) {
54+
if (customOrInheritShifts.includes('custom')) {
55+
timeOffsets = timeOffsets.concat([formData.start_date_offset]);
56+
}
57+
if (customOrInheritShifts.includes('inherit')) {
58+
timeOffsets = timeOffsets.concat(['inherit']);
59+
}
60+
}
7761
return [
7862
{
7963
...baseQueryObject,

superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ import {
2424
getNumberFormatter,
2525
SimpleAdhocFilter,
2626
ensureIsArray,
27-
getTimeOffset,
28-
parseDttmToDate,
2927
} from '@superset-ui/core';
30-
import { isEmpty } from 'lodash';
3128
import { getComparisonFontSize, getHeaderFontSize } from './utils';
3229

3330
export const parseMetricValue = (metricValue: number | string | null) => {
@@ -99,37 +96,16 @@ export default function transformProps(chartProps: ChartProps) {
9996
(adhoc_filter: SimpleAdhocFilter) =>
10097
adhoc_filter.operator === 'TEMPORAL_RANGE',
10198
)?.[0];
102-
// In case the viz is using all version of controls, we try to load them
103-
const previousCustomTimeRangeFilters: any =
104-
chartProps.rawFormData?.adhoc_custom?.filter(
105-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
106-
) || [];
10799

108-
let previousCustomStartDate = '';
109-
if (
110-
!isEmpty(previousCustomTimeRangeFilters) &&
111-
previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
112-
) {
113-
previousCustomStartDate =
114-
previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
115-
}
116100
const isCustomOrInherit =
117101
timeComparison === 'custom' || timeComparison === 'inherit';
118102
let dataOffset: string[] = [];
119103
if (isCustomOrInherit) {
120-
dataOffset = getTimeOffset({
121-
timeRangeFilter: {
122-
...currentTimeRangeFilter,
123-
comparator:
124-
formData?.extraFormData?.time_range ??
125-
(currentTimeRangeFilter as any)?.comparator,
126-
},
127-
shifts: ensureIsArray(timeComparison),
128-
startDate:
129-
previousCustomStartDate && !startDateOffset
130-
? parseDttmToDate(previousCustomStartDate)?.toUTCString()
131-
: startDateOffset,
132-
});
104+
if (timeComparison && timeComparison === 'custom') {
105+
dataOffset = [startDateOffset];
106+
} else {
107+
dataOffset = ensureIsArray(timeComparison) || [];
108+
}
133109
}
134110

135111
const { value1, value2 } = data.reduce(

superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,10 @@ import {
2121
buildQueryContext,
2222
ensureIsArray,
2323
getMetricLabel,
24-
getTimeOffset,
2524
isPhysicalColumn,
26-
parseDttmToDate,
2725
QueryMode,
2826
QueryObject,
2927
removeDuplicates,
30-
SimpleAdhocFilter,
3128
} from '@superset-ui/core';
3229
import { PostProcessingRule } from '@superset-ui/core/src/query/types/PostProcessing';
3330
import { BuildQuery } from '@superset-ui/core/src/chart/registries/ChartBuildQueryRegistrySingleton';
@@ -87,43 +84,35 @@ const buildQuery: BuildQuery<TableChartFormData> = (
8784
let { metrics, orderby = [], columns = [] } = baseQueryObject;
8885
const { extras = {} } = baseQueryObject;
8986
let postProcessing: PostProcessingRule[] = [];
90-
const TimeRangeFilters =
91-
formData.adhoc_filters?.filter(
92-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
93-
) || [];
87+
const nonCustomNorInheritShifts = ensureIsArray(
88+
formData.time_compare,
89+
).filter((shift: string) => shift !== 'custom' && shift !== 'inherit');
90+
const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
91+
(shift: string) => shift === 'custom' || shift === 'inherit',
92+
);
9493

95-
// In case the viz is using all version of controls, we try to load them
96-
const previousCustomTimeRangeFilters: any =
97-
formData.adhoc_custom?.filter(
98-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
99-
) || [];
94+
let timeOffsets: string[] = [];
10095

101-
let previousCustomStartDate = '';
96+
// Shifts for non-custom or non inherit time comparison
10297
if (
103-
!isEmpty(previousCustomTimeRangeFilters) &&
104-
previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
98+
isTimeComparison(formData, baseQueryObject) &&
99+
!isEmpty(nonCustomNorInheritShifts)
105100
) {
106-
previousCustomStartDate =
107-
previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
101+
timeOffsets = nonCustomNorInheritShifts;
108102
}
109103

110-
const timeOffsets = ensureIsArray(
111-
isTimeComparison(formData, baseQueryObject)
112-
? getTimeOffset({
113-
timeRangeFilter: {
114-
...TimeRangeFilters[0],
115-
comparator:
116-
baseQueryObject?.time_range ??
117-
(TimeRangeFilters[0] as any)?.comparator,
118-
},
119-
shifts: formData.time_compare,
120-
startDate:
121-
previousCustomStartDate && !formData.start_date_offset
122-
? parseDttmToDate(previousCustomStartDate)?.toUTCString()
123-
: formData.start_date_offset,
124-
})
125-
: [],
126-
);
104+
// Shifts for custom or inherit time comparison
105+
if (
106+
isTimeComparison(formData, baseQueryObject) &&
107+
!isEmpty(customOrInheritShifts)
108+
) {
109+
if (customOrInheritShifts.includes('custom')) {
110+
timeOffsets = timeOffsets.concat([formData.start_date_offset]);
111+
}
112+
if (customOrInheritShifts.includes('inherit')) {
113+
timeOffsets = timeOffsets.concat(['inherit']);
114+
}
115+
}
127116

128117
let temporalColumnAdded = false;
129118
let temporalColumn = null;

superset-frontend/plugins/plugin-chart-table/src/transformProps.ts

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ import {
3535
SMART_DATE_ID,
3636
TimeFormats,
3737
TimeFormatter,
38-
SimpleAdhocFilter,
39-
getTimeOffset,
40-
parseDttmToDate,
4138
} from '@superset-ui/core';
4239
import {
4340
ColorFormatters,
@@ -597,37 +594,29 @@ const transformProps = (
597594
};
598595

599596
const timeGrain = extractTimegrain(formData);
600-
const TimeRangeFilters =
601-
chartProps.rawFormData?.adhoc_filters?.filter(
602-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
603-
) || [];
604-
const previousCustomTimeRangeFilters: any =
605-
chartProps.rawFormData?.adhoc_custom?.filter(
606-
(filter: SimpleAdhocFilter) => filter.operator === 'TEMPORAL_RANGE',
607-
) || [];
608-
609-
let previousCustomStartDate = '';
610-
if (
611-
!isEmpty(previousCustomTimeRangeFilters) &&
612-
previousCustomTimeRangeFilters[0]?.comparator !== 'No Filter'
613-
) {
614-
previousCustomStartDate =
615-
previousCustomTimeRangeFilters[0]?.comparator.split(' : ')[0];
597+
598+
const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter(
599+
(shift: string) => shift !== 'custom' && shift !== 'inherit',
600+
);
601+
const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
602+
(shift: string) => shift === 'custom' || shift === 'inherit',
603+
);
604+
605+
let timeOffsets: string[] = [];
606+
607+
if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) {
608+
timeOffsets = nonCustomNorInheritShifts;
616609
}
617610

618-
const timeOffsets = getTimeOffset({
619-
timeRangeFilter: {
620-
...TimeRangeFilters[0],
621-
comparator:
622-
formData?.extra_form_data?.time_range ??
623-
(TimeRangeFilters[0] as any)?.comparator,
624-
},
625-
shifts: formData.time_compare,
626-
startDate:
627-
previousCustomStartDate && !formData.start_date_offset
628-
? parseDttmToDate(previousCustomStartDate)?.toUTCString()
629-
: formData.start_date_offset,
630-
});
611+
// Shifts for custom or inherit time comparison
612+
if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) {
613+
if (customOrInheritShifts.includes('custom')) {
614+
timeOffsets = timeOffsets.concat([formData.start_date_offset]);
615+
}
616+
if (customOrInheritShifts.includes('inherit')) {
617+
timeOffsets = timeOffsets.concat(['inherit']);
618+
}
619+
}
631620
const comparisonSuffix = isUsingTimeComparison
632621
? ensureIsArray(timeOffsets)[0]
633622
: '';

0 commit comments

Comments
 (0)