diff --git a/frontend/dashboard/app/[teamId]/apps/page.tsx b/frontend/dashboard/app/[teamId]/apps/page.tsx index 8e406ba67..3c9ace435 100644 --- a/frontend/dashboard/app/[teamId]/apps/page.tsx +++ b/frontend/dashboard/app/[teamId]/apps/page.tsx @@ -160,6 +160,7 @@ export default function Apps({ params }: { params: { teamId: string } }) { showLocales={false} showDeviceManufacturers={false} showDeviceNames={false} + showUdAttrs={false} showFreeText={false} onFiltersChanged={(updatedFilters) => setFilters(updatedFilters)} /> diff --git a/frontend/dashboard/app/[teamId]/overview/page.tsx b/frontend/dashboard/app/[teamId]/overview/page.tsx index 1f05e1ed3..dd2975f9f 100644 --- a/frontend/dashboard/app/[teamId]/overview/page.tsx +++ b/frontend/dashboard/app/[teamId]/overview/page.tsx @@ -35,6 +35,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { showDeviceManufacturers={false} showDeviceNames={false} showFreeText={false} + showUdAttrs={false} onFiltersChanged={(updatedFilters) => setFilters(updatedFilters)} />
diff --git a/frontend/dashboard/app/[teamId]/sessions/page.tsx b/frontend/dashboard/app/[teamId]/sessions/page.tsx index 15b649a76..1e4876b66 100644 --- a/frontend/dashboard/app/[teamId]/sessions/page.tsx +++ b/frontend/dashboard/app/[teamId]/sessions/page.tsx @@ -76,6 +76,7 @@ export default function SessionsOverview({ params }: { params: { teamId: string showLocales={true} showDeviceManufacturers={true} showDeviceNames={true} + showUdAttrs={true} showFreeText={true} onFiltersChanged={(updatedFilters) => setFilters(updatedFilters)} /> diff --git a/frontend/dashboard/app/[teamId]/traces/page.tsx b/frontend/dashboard/app/[teamId]/traces/page.tsx index 30ac196a3..55988aa4c 100644 --- a/frontend/dashboard/app/[teamId]/traces/page.tsx +++ b/frontend/dashboard/app/[teamId]/traces/page.tsx @@ -76,6 +76,7 @@ export default function TracesOverview({ params }: { params: { teamId: string } showLocales={true} showDeviceManufacturers={true} showDeviceNames={true} + showUdAttrs={false} showFreeText={false} onFiltersChanged={(updatedFilters) => setFilters(updatedFilters)} /> diff --git a/frontend/dashboard/app/api/api_calls.ts b/frontend/dashboard/app/api/api_calls.ts index c93984563..653a4d39d 100644 --- a/frontend/dashboard/app/api/api_calls.ts +++ b/frontend/dashboard/app/api/api_calls.ts @@ -819,6 +819,11 @@ export class OsVersion { } } +export type UserDefAttr = { + key: string + type: string +} + export const saveListFiltersToServer = async (filters: Filters) => { if (filters.versions.length === 0 && filters.osVersions.length === 0 && @@ -828,29 +833,48 @@ export const saveListFiltersToServer = async (filters: Filters) => { filters.networkGenerations.length === 0 && filters.locales.length === 0 && filters.deviceManufacturers.length === 0 && - filters.deviceNames.length === 0 + filters.deviceNames.length === 0 && + filters.udAttrMatchers.length === 0 ) { return null } const origin = process.env.NEXT_PUBLIC_API_BASE_URL let url = `${origin}/apps/${filters.app.id}/shortFilters` + + const udExpression = { + and: filters.udAttrMatchers.map(matcher => ({ + cmp: { + key: matcher.key, + type: matcher.type, + op: matcher.op, + value: String(matcher.value) + } + })) + }; + + const bodyFilters: any = { + versions: filters.versions.map((v) => v.name), + version_codes: filters.versions.map((v) => v.code), + os_names: filters.osVersions.map((v) => v.name), + os_versions: filters.osVersions.map((v) => v.version), + countries: filters.countries, + network_providers: filters.networkProviders, + network_types: filters.networkTypes, + network_generations: filters.networkGenerations, + locales: filters.locales, + device_manufacturers: filters.deviceManufacturers, + device_names: filters.deviceNames, + }; + + if (filters.udAttrMatchers.length > 0) { + bodyFilters.ud_expression = JSON.stringify(udExpression); + } + const opts = { method: 'POST', body: JSON.stringify({ - filters: { - versions: filters.versions.map((v) => v.name), - version_codes: filters.versions.map((v) => v.code), - os_names: filters.osVersions.map((v) => v.name), - os_versions: filters.osVersions.map((v) => v.version), - countries: filters.countries, - network_providers: filters.networkProviders, - network_types: filters.networkTypes, - network_generations: filters.networkGenerations, - locales: filters.locales, - device_manufacturers: filters.deviceManufacturers, - device_names: filters.deviceNames - } + filters: bodyFilters }) } @@ -1081,13 +1105,16 @@ export const fetchFiltersFromServer = async (selectedApp: typeof emptyApp, filte let url = `${origin}/apps/${selectedApp.id}/filters` + // fetch the user defined attributes + url += '?ud_attr_keys=1' + // if filter is for Crashes or Anrs, we append a query param indicating it if (filtersApiType === FiltersApiType.Crash) { - url += '?crash=1' + url += '&crash=1' } else if (filtersApiType === FiltersApiType.Anr) { - url += '?anr=1' + url += '&anr=1' } else if (filtersApiType === FiltersApiType.Span) { - url += '?span=1' + url += '&span=1' } try { diff --git a/frontend/dashboard/app/components/dropdown_select.tsx b/frontend/dashboard/app/components/dropdown_select.tsx index 8174d4796..f89579865 100644 --- a/frontend/dashboard/app/components/dropdown_select.tsx +++ b/frontend/dashboard/app/components/dropdown_select.tsx @@ -143,7 +143,7 @@ const DropdownSelect: React.FC