mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Fix crash when navigating away from chart explorer search page (#1278)
This commit is contained in:
parent
065cabdb47
commit
6262ced8ce
2 changed files with 49 additions and 16 deletions
5
.changeset/nasty-fans-run.md
Normal file
5
.changeset/nasty-fans-run.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hyperdx/app": patch
|
||||
---
|
||||
|
||||
fix: Fix crash when navigating away from chart explorer search page
|
||||
|
|
@ -7,6 +7,7 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { omit } from 'lodash';
|
||||
import {
|
||||
Control,
|
||||
Controller,
|
||||
|
|
@ -385,6 +386,10 @@ export type SavedChartConfigWithSelectArray = Omit<
|
|||
select: Exclude<SavedChartConfig['select'], string>;
|
||||
};
|
||||
|
||||
type SavedChartConfigWithSeries = SavedChartConfig & {
|
||||
series: SavedChartConfigWithSelectArray['select'];
|
||||
};
|
||||
|
||||
export default function EditTimeChartForm({
|
||||
dashboardId,
|
||||
chartConfig,
|
||||
|
|
@ -414,10 +419,20 @@ export default function EditTimeChartForm({
|
|||
'data-testid'?: string;
|
||||
submitRef?: React.MutableRefObject<(() => void) | undefined>;
|
||||
}) {
|
||||
// useFieldArray only supports array type fields, and select can be either a string or array.
|
||||
// To solve for this, we maintain an extra form field called 'series' which is always an array.
|
||||
const configWithSeries: SavedChartConfigWithSeries = useMemo(
|
||||
() => ({
|
||||
...chartConfig,
|
||||
series: Array.isArray(chartConfig.select) ? chartConfig.select : [],
|
||||
}),
|
||||
[chartConfig],
|
||||
);
|
||||
|
||||
const { control, watch, setValue, handleSubmit, register } =
|
||||
useForm<SavedChartConfig>({
|
||||
defaultValues: chartConfig,
|
||||
values: chartConfig,
|
||||
useForm<SavedChartConfigWithSeries>({
|
||||
defaultValues: configWithSeries,
|
||||
values: configWithSeries,
|
||||
resolver: zodResolver(zSavedChartConfig),
|
||||
});
|
||||
|
||||
|
|
@ -427,8 +442,8 @@ export default function EditTimeChartForm({
|
|||
remove: removeSeries,
|
||||
swap: swapSeries,
|
||||
} = useFieldArray({
|
||||
control: control as Control<SavedChartConfigWithSelectArray>,
|
||||
name: 'select',
|
||||
control: control as Control<SavedChartConfigWithSeries>,
|
||||
name: 'series',
|
||||
});
|
||||
|
||||
const select = watch('select');
|
||||
|
|
@ -492,11 +507,18 @@ export default function EditTimeChartForm({
|
|||
|
||||
const onSubmit = useCallback(() => {
|
||||
handleSubmit(form => {
|
||||
setChartConfig(form);
|
||||
// Merge the series and select fields back together, and prevent the series field from being submitted
|
||||
const config = {
|
||||
...omit(form, ['series']),
|
||||
select:
|
||||
form.displayType === DisplayType.Search ? form.select : form.series,
|
||||
};
|
||||
|
||||
setChartConfig(config);
|
||||
if (tableSource != null) {
|
||||
const isSelectEmpty = !form.select || form.select.length === 0; // select is string or array
|
||||
const isSelectEmpty = !config.select || config.select.length === 0; // select is string or array
|
||||
const newConfig = {
|
||||
...form,
|
||||
...config,
|
||||
from: tableSource.from,
|
||||
timestampValueExpression: tableSource.timestampValueExpression,
|
||||
dateRange,
|
||||
|
|
@ -505,7 +527,7 @@ export default function EditTimeChartForm({
|
|||
metricTables: tableSource.metricTables,
|
||||
select: isSelectEmpty
|
||||
? tableSource.defaultTableSelectExpression || ''
|
||||
: form.select,
|
||||
: config.select,
|
||||
};
|
||||
setQueriedConfig(
|
||||
// WARNING: DON'T JUST ASSIGN OBJECTS OR DO SPREAD OPERATOR STUFF WHEN
|
||||
|
|
@ -525,12 +547,15 @@ export default function EditTimeChartForm({
|
|||
}, [onSubmit, submitRef]);
|
||||
|
||||
const handleSave = useCallback(
|
||||
(v: SavedChartConfig) => {
|
||||
(v: SavedChartConfigWithSeries) => {
|
||||
// If the chart type is search, we need to ensure the select is a string
|
||||
if (displayType === DisplayType.Search && typeof v.select !== 'string') {
|
||||
v.select = '';
|
||||
} else if (displayType !== DisplayType.Search) {
|
||||
v.select = v.series;
|
||||
}
|
||||
onSave?.(v);
|
||||
// Avoid saving the series field. Series should be persisted in the select field.
|
||||
onSave?.(omit(v, ['series']));
|
||||
},
|
||||
[onSave, displayType],
|
||||
);
|
||||
|
|
@ -543,17 +568,20 @@ export default function EditTimeChartForm({
|
|||
if (name === 'displayType' && type === 'change') {
|
||||
if (_.displayType === DisplayType.Search && typeof select !== 'string') {
|
||||
setValue('select', '');
|
||||
setValue('series', []);
|
||||
}
|
||||
if (_.displayType !== DisplayType.Search && typeof select === 'string') {
|
||||
setValue('where', '');
|
||||
setValue('select', [
|
||||
const defaultSeries: SavedChartConfigWithSelectArray['select'] = [
|
||||
{
|
||||
aggFn: 'count',
|
||||
aggCondition: '',
|
||||
aggConditionLanguage: 'lucene',
|
||||
valueExpression: '',
|
||||
},
|
||||
]);
|
||||
];
|
||||
setValue('where', '');
|
||||
setValue('select', defaultSeries);
|
||||
setValue('series', defaultSeries);
|
||||
}
|
||||
onSubmit();
|
||||
}
|
||||
|
|
@ -711,7 +739,7 @@ export default function EditTimeChartForm({
|
|||
index={index}
|
||||
key={field.id}
|
||||
parentRef={parentRef}
|
||||
namePrefix={`select.${index}.`}
|
||||
namePrefix={`series.${index}.`}
|
||||
onRemoveSeries={removeSeries}
|
||||
length={fields.length}
|
||||
onSwapSeries={swapSeries}
|
||||
|
|
@ -773,7 +801,7 @@ export default function EditTimeChartForm({
|
|||
Add Series
|
||||
</Button>
|
||||
)}
|
||||
{select.length == 2 && displayType !== DisplayType.Number && (
|
||||
{fields.length == 2 && displayType !== DisplayType.Number && (
|
||||
<Switch
|
||||
label="As Ratio"
|
||||
size="sm"
|
||||
|
|
|
|||
Loading…
Reference in a new issue