mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
## Summary This PR makes a few minor improvements to dashboard tiles and the chart editor ### Hide the "Add Alert" button on dashboard tiles based on raw SQL These tiles don't yet support alerts <img width="766" height="424" alt="Screenshot 2026-04-03 at 8 37 36 AM" src="https://github.com/user-attachments/assets/4405c5bb-419d-4ae8-a121-7ddcd2623d87" /> <img width="767" height="447" alt="Screenshot 2026-04-03 at 8 37 42 AM" src="https://github.com/user-attachments/assets/c9b27e7a-9a2b-4f23-863b-d1679d3ea770" /> Closes HDX-3910 ### Hide the "Group By" button on the Attribute explorer for Number Charts Number charts don't support Group By <img width="1224" height="475" alt="Screenshot 2026-04-03 at 8 41 10 AM" src="https://github.com/user-attachments/assets/e854ff39-09b6-4452-b008-cd7bc1e26d09" /> <img width="1219" height="501" alt="Screenshot 2026-04-03 at 8 41 00 AM" src="https://github.com/user-attachments/assets/4180a784-2b1c-4353-a84f-b25f367ff36c" /> <img width="1224" height="476" alt="Screenshot 2026-04-03 at 8 41 02 AM" src="https://github.com/user-attachments/assets/89780bea-d53a-4287-8056-e73c8ce6927f" /> <img width="1227" height="485" alt="Screenshot 2026-04-03 at 8 40 56 AM" src="https://github.com/user-attachments/assets/197cbcdd-4264-45d5-a0f0-10e4c67ab67d" /> Closes HDX-3871 ### Disable the "Custom" Aggregation for Metric queries These were already broken because there was no input available for the user to provide the custom aggregation. Custom aggregations don't make much sense for metric sources, since the queries we build for metrics would be very difficult for users to build custom aggregations on. We also now have SQL-based charts if users want to do custom aggregations on metric sources. <img width="459" height="581" alt="Screenshot 2026-04-03 at 9 03 40 AM" src="https://github.com/user-attachments/assets/5230627c-5f51-4640-9b16-4719f9a1ca91" /> Closes HDX-3799 ### How to test locally or on Vercel These can be tested in the preview environment (except for the alert button, that must be tested locally)
106 lines
2.4 KiB
TypeScript
106 lines
2.4 KiB
TypeScript
import { useCallback, useMemo } from 'react';
|
|
import { useController, UseControllerProps } from 'react-hook-form';
|
|
import { Select } from '@mantine/core';
|
|
|
|
import { AGG_FNS } from '@/ChartUtils';
|
|
|
|
type AggFnValues = (typeof AGG_FNS)[number]['value'];
|
|
|
|
type OnChangeValue =
|
|
| { aggFn?: AggFnValues }
|
|
| { aggFn: 'quantile'; level: number };
|
|
function AggFnSelect({
|
|
value,
|
|
defaultValue,
|
|
onChange,
|
|
hideCustom,
|
|
}: {
|
|
value: string;
|
|
defaultValue: string;
|
|
onChange: (value: OnChangeValue) => void;
|
|
hideCustom?: boolean;
|
|
}) {
|
|
const _onChange = useCallback(
|
|
(value: string | null) => {
|
|
if (value == null) {
|
|
onChange({});
|
|
} else if (['p50', 'p90', 'p95', 'p99'].includes(value)) {
|
|
onChange({
|
|
aggFn: 'quantile',
|
|
level: Number.parseFloat(value.replace('p', '0.')),
|
|
});
|
|
} else {
|
|
// @ts-ignore
|
|
onChange({ aggFn: value });
|
|
}
|
|
},
|
|
[onChange],
|
|
);
|
|
|
|
return (
|
|
<Select
|
|
withScrollArea={false}
|
|
searchable
|
|
value={value}
|
|
defaultValue={defaultValue}
|
|
onChange={_onChange}
|
|
data={hideCustom ? AGG_FNS.filter(fn => fn.value !== 'none') : AGG_FNS}
|
|
data-testid="agg-fn-select"
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function AggFnSelectControlled({
|
|
aggFnName,
|
|
quantileLevelName,
|
|
defaultValue,
|
|
hideCustom,
|
|
...props
|
|
}: {
|
|
defaultValue: string;
|
|
aggFnName: string;
|
|
quantileLevelName: string;
|
|
hideCustom?: boolean;
|
|
} & Omit<UseControllerProps<any>, 'name'>) {
|
|
const {
|
|
field: { onChange: onAggFnChange, value: aggFnValue },
|
|
} = useController({
|
|
...props,
|
|
name: aggFnName,
|
|
});
|
|
|
|
const {
|
|
field: { onChange: onQuantileLevelChange, value: quantileLevelValue },
|
|
} = useController({
|
|
...props,
|
|
name: quantileLevelName,
|
|
});
|
|
|
|
const onChange = useCallback(
|
|
(value: OnChangeValue) => {
|
|
if (value.aggFn === 'quantile') {
|
|
onQuantileLevelChange(value.level);
|
|
onAggFnChange(value.aggFn);
|
|
} else {
|
|
onAggFnChange(value.aggFn);
|
|
}
|
|
},
|
|
[onAggFnChange, onQuantileLevelChange],
|
|
);
|
|
|
|
const value = useMemo(() => {
|
|
if (aggFnValue === 'quantile') {
|
|
return `p${Math.round(quantileLevelValue * 100)}`;
|
|
}
|
|
return aggFnValue;
|
|
}, [aggFnValue, quantileLevelValue]);
|
|
|
|
return (
|
|
<AggFnSelect
|
|
value={value}
|
|
defaultValue={defaultValue}
|
|
onChange={onChange}
|
|
hideCustom={hideCustom}
|
|
/>
|
|
);
|
|
}
|