Skip to content

Commit 50ba92a

Browse files
authored
feat: Add filters to the Services dashboard (#1494)
Closes HDX-3015 # Summary This PR adds custom filters to the services dashboard. Notes: - These filters are per-source, per-dashboard. Different sources have different schemas, so we must store them per-source to avoid invalid filters being available for some sources. - These filters are stored in a new collection in MongoDB (PresetDashboardFilters) and accessed via a new set of CRUD APIs - The UI is 99% re-used from the existing custom dashboard filters ## Demo https://github.com/user-attachments/assets/82a4a55f-9b8b-46eb-be24-82254a86eed3
1 parent 68918e4 commit 50ba92a

File tree

13 files changed

+1413
-33
lines changed

13 files changed

+1413
-33
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@hyperdx/common-utils": patch
3+
"@hyperdx/api": patch
4+
"@hyperdx/app": patch
5+
---
6+
7+
feat: Add custom filters to the services dashboard"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
PresetDashboard,
3+
PresetDashboardFilter,
4+
} from '@hyperdx/common-utils/dist/types';
5+
import mongoose from 'mongoose';
6+
7+
import { ObjectId } from '@/models';
8+
import PresetDashboardFilterModel from '@/models/presetDashboardFilter';
9+
10+
export async function getPresetDashboardFilters(
11+
teamId: string | ObjectId,
12+
source: string | ObjectId,
13+
presetDashboard: PresetDashboard,
14+
) {
15+
return await PresetDashboardFilterModel.find({
16+
team: new mongoose.Types.ObjectId(teamId),
17+
source: new mongoose.Types.ObjectId(source),
18+
presetDashboard,
19+
});
20+
}
21+
22+
export const createPresetDashboardFilter = async (
23+
teamId: string | ObjectId,
24+
presetDashboardFilter: PresetDashboardFilter,
25+
) => {
26+
const newPresetDashboardFilter = new PresetDashboardFilterModel({
27+
...presetDashboardFilter,
28+
team: new mongoose.Types.ObjectId(teamId),
29+
});
30+
31+
return newPresetDashboardFilter.save();
32+
};
33+
34+
export const updatePresetDashboardFilter = async (
35+
teamId: string | ObjectId,
36+
presetDashboardFilter: PresetDashboardFilter,
37+
) => {
38+
return await PresetDashboardFilterModel.findOneAndUpdate(
39+
{
40+
_id: new mongoose.Types.ObjectId(presetDashboardFilter.id),
41+
team: new mongoose.Types.ObjectId(teamId),
42+
},
43+
{
44+
...presetDashboardFilter,
45+
_id: new mongoose.Types.ObjectId(presetDashboardFilter.id),
46+
team: new mongoose.Types.ObjectId(teamId),
47+
},
48+
{ new: true },
49+
);
50+
};
51+
52+
export const deletePresetDashboardFilter = async (
53+
teamId: string | ObjectId,
54+
presetDashboard: PresetDashboard,
55+
presetDashboardFilterId: string | ObjectId,
56+
) => {
57+
return await PresetDashboardFilterModel.findOneAndDelete({
58+
_id: new mongoose.Types.ObjectId(presetDashboardFilterId),
59+
team: new mongoose.Types.ObjectId(teamId),
60+
presetDashboard,
61+
});
62+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {
2+
MetricsDataType,
3+
PresetDashboard,
4+
PresetDashboardFilter,
5+
} from '@hyperdx/common-utils/dist/types';
6+
import mongoose, { Schema } from 'mongoose';
7+
8+
import type { ObjectId } from '.';
9+
10+
export interface IPresetDashboardFilter
11+
extends Omit<PresetDashboardFilter, 'source'> {
12+
_id: ObjectId;
13+
team: ObjectId;
14+
source: ObjectId;
15+
}
16+
17+
const PresetDashboardFilterSchema = new Schema<IPresetDashboardFilter>(
18+
{
19+
name: {
20+
type: String,
21+
required: true,
22+
},
23+
team: {
24+
type: mongoose.Schema.Types.ObjectId,
25+
required: true,
26+
ref: 'Team',
27+
},
28+
source: {
29+
type: mongoose.Schema.Types.ObjectId,
30+
required: true,
31+
ref: 'Source',
32+
},
33+
sourceMetricType: {
34+
type: String,
35+
required: false,
36+
enum: Object.values(MetricsDataType),
37+
},
38+
presetDashboard: {
39+
type: String,
40+
required: true,
41+
enum: Object.values(PresetDashboard),
42+
},
43+
type: { type: String, required: true },
44+
expression: { type: String, required: true },
45+
},
46+
{
47+
timestamps: true,
48+
toJSON: { getters: true },
49+
},
50+
);
51+
52+
export default mongoose.model<IPresetDashboardFilter>(
53+
'PresetDashboardFilter',
54+
PresetDashboardFilterSchema,
55+
);

0 commit comments

Comments
 (0)