Compare commits

...
Author SHA1 Message Date
sadpandajoe 835b86d243 chore: remove non-source investigation notes file
RCA.md was committed alongside a regression test but is not a source
file and should not ship in the product tree.
2026-09-07 04:16:29 +00:00
sadpandajoeandClaude Sonnet 5 cfcec02cd1 fix(explore): keep edits to a dashboard-inherited filter when saving
Adhoc filters that Explore merges in from a dashboard's context are
flagged isExtra so the save flow can drop them and keep them out of the
chart's own saved config. Editing one of these filters (e.g. changing an
inherited Time Range) preserved that flag instead of clearing it, so the
save path treated the edit as untouched dashboard state and discarded it,
restoring the chart's previous value instead of the one the user picked.

Clear isExtra whenever the user changes a filter's subject, operator,
comparator, or date range, so a deliberate edit is saved like any other
filter change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 19:42:11 +00:00
sadpandajoeandClaude Sonnet 5 3a5f0ef98f test(explore): add regression guard for editing dashboard-inherited filters
Editing a filter pill that Explore inherited from a dashboard (e.g. its
Time Range) currently leaves it flagged isExtra, so the save path treats
the edit as if the user never touched it and discards the new value.
Add RCA.md documenting the mechanism and a failing guard pinning the bug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 19:41:46 +00:00
2 changed files with 47 additions and 0 deletions
@@ -438,6 +438,47 @@ test('passes the new adhocFilter to onChange after onComparatorChange', () => {
).toEqual(simpleAdhocFilter.duplicateWith({ comparator: '20' }));
});
test('editing a dashboard-inherited time range filter clears isExtra so the new value is kept on save', () => {
const inheritedTimeFilter = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'ds',
operator: Operators.TemporalRange,
comparator: '2024-01-01 : 2024-02-01',
clause: Clauses.Where,
isExtra: true,
});
const props = setup({ adhocFilter: inheritedTimeFilter });
const { onDatePickerChange } = useSimpleTabFilterProps(
props as unknown as Props,
);
onDatePickerChange('ds', '2025-01-01 : 2025-02-01');
const editedFilter =
props.onChange.mock.calls[props.onChange.mock.calls.length - 1][0];
expect(editedFilter.comparator).toEqual('2025-01-01 : 2025-02-01');
expect(editedFilter.isExtra).toBe(false);
});
test('editing a dashboard-inherited filter comparator clears isExtra so the new value is kept on save', () => {
const inheritedFilter = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'value',
operatorId: Operators.GreaterThan,
operator: OPERATOR_ENUM_TO_OPERATOR_TYPE[Operators.GreaterThan].operation,
comparator: '10',
clause: Clauses.Where,
isExtra: true,
});
const props = setup({ adhocFilter: inheritedFilter });
const { onComparatorChange } = useSimpleTabFilterProps(
props as unknown as Props,
);
onComparatorChange('20');
const editedFilter =
props.onChange.mock.calls[props.onChange.mock.calls.length - 1][0];
expect(editedFilter.comparator).toEqual('20');
expect(editedFilter.isExtra).toBe(false);
});
test('will filter operators for table datasources', () => {
const props = setup({ datasource: { type: 'table' as const } });
const { isOperatorRelevant } = useSimpleTabFilterProps(
@@ -270,6 +270,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
expressionType: ExpressionTypes.Simple,
operatorId,
comparator,
isExtra: false,
}),
);
};
@@ -324,6 +325,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
operator: OPERATOR_ENUM_TO_OPERATOR_TYPE[operatorId].operation,
expressionType: ExpressionTypes.Sql,
datasource: props.datasource,
isExtra: false,
}),
);
} else {
@@ -333,6 +335,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
operator: OPERATOR_ENUM_TO_OPERATOR_TYPE[operatorId].operation,
comparator: newComparator,
expressionType: ExpressionTypes.Simple,
isExtra: false,
}),
);
}
@@ -342,6 +345,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
props.adhocFilter.duplicateWith({
comparator,
expressionType: ExpressionTypes.Simple,
isExtra: false,
}),
);
};
@@ -350,6 +354,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
props.adhocFilter.duplicateWith({
operatorId: undefined,
operator: undefined,
isExtra: false,
}),
);
};
@@ -360,6 +365,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
operator: Operators.TemporalRange,
comparator: timeRange,
expressionType: ExpressionTypes.Simple,
isExtra: false,
}),
);
};