mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Support JSON keys in dashboard filters (#1271)
This commit is contained in:
parent
2dc0079b08
commit
2d27fe27c1
5 changed files with 36 additions and 6 deletions
5
.changeset/fifty-garlics-kiss.md
Normal file
5
.changeset/fifty-garlics-kiss.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hyperdx/app": patch
|
||||
---
|
||||
|
||||
fix: Support JSON keys in dashboard filters
|
||||
|
|
@ -1083,7 +1083,6 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
|
|||
<Tooltip withArrow label="Edit Filters" fz="xs" color="gray">
|
||||
<Button
|
||||
variant="outline"
|
||||
type="submit"
|
||||
color="gray"
|
||||
px="xs"
|
||||
mr={6}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,19 @@ describe('searchFilters', () => {
|
|||
{ type: 'sql', condition: "a NOT IN ('c')" },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should wrap keys with toString() when specified', () => {
|
||||
const filters = {
|
||||
'json.key': {
|
||||
included: new Set<string>(['value']),
|
||||
excluded: new Set<string>(['other value']),
|
||||
},
|
||||
};
|
||||
expect(filtersToQuery(filters, { stringifyKeys: true })).toEqual([
|
||||
{ type: 'sql', condition: "toString(json.key) IN ('value')" },
|
||||
{ type: 'sql', condition: "toString(json.key) NOT IN ('other value')" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseQuery', () => {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ const useDashboardFilters = (filters: DashboardFilter[]) => {
|
|||
};
|
||||
}
|
||||
|
||||
return filtersToQuery(filterValues);
|
||||
return filtersToQuery(
|
||||
filterValues,
|
||||
{ stringifyKeys: false }, // Don't wrap keys with toString(), to preserve exact key names in URL query parameters
|
||||
);
|
||||
});
|
||||
},
|
||||
[setFilterQueries],
|
||||
|
|
@ -42,7 +45,12 @@ const useDashboardFilters = (filters: DashboardFilter[]) => {
|
|||
|
||||
return {
|
||||
valuesForExistingFilters,
|
||||
queriesForExistingFilters: filtersToQuery(valuesForExistingFilters),
|
||||
queriesForExistingFilters: filtersToQuery(
|
||||
valuesForExistingFilters,
|
||||
// Wrap keys in `toString()` to support JSON/Dynamic-type columns.
|
||||
// All keys can be stringified, since filter select values are stringified as well.
|
||||
{ stringifyKeys: true },
|
||||
),
|
||||
};
|
||||
}, [filterQueries, filters]);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,17 +11,22 @@ export type FilterState = {
|
|||
};
|
||||
};
|
||||
|
||||
export const filtersToQuery = (filters: FilterState): Filter[] => {
|
||||
export const filtersToQuery = (
|
||||
filters: FilterState,
|
||||
{ stringifyKeys = false }: { stringifyKeys?: boolean } = {},
|
||||
): Filter[] => {
|
||||
return Object.entries(filters)
|
||||
.filter(
|
||||
([_, values]) => values.included.size > 0 || values.excluded.size > 0,
|
||||
)
|
||||
.flatMap(([key, values]) => {
|
||||
const conditions = [];
|
||||
const actualKey = stringifyKeys ? `toString(${key})` : key;
|
||||
|
||||
if (values.included.size > 0) {
|
||||
conditions.push({
|
||||
type: 'sql' as const,
|
||||
condition: `${key} IN (${Array.from(values.included)
|
||||
condition: `${actualKey} IN (${Array.from(values.included)
|
||||
.map(v => `'${v}'`)
|
||||
.join(', ')})`,
|
||||
});
|
||||
|
|
@ -29,7 +34,7 @@ export const filtersToQuery = (filters: FilterState): Filter[] => {
|
|||
if (values.excluded.size > 0) {
|
||||
conditions.push({
|
||||
type: 'sql' as const,
|
||||
condition: `${key} NOT IN (${Array.from(values.excluded)
|
||||
condition: `${actualKey} NOT IN (${Array.from(values.excluded)
|
||||
.map(v => `'${v}'`)
|
||||
.join(', ')})`,
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue