Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions static/app/utils/discover/fieldRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1425,8 +1425,9 @@ function getDashboardUrl(
linkedDashboard => linkedDashboard.field === field
);
if (dashboardLink && dashboardLink.dashboardId !== '-1') {
const newTemporaryFilters: GlobalFilter[] =
dashboardFilters[DashboardFilterKeys.GLOBAL_FILTER] ?? [];
const newTemporaryFilters: GlobalFilter[] = [
...(dashboardFilters[DashboardFilterKeys.GLOBAL_FILTER] ?? []),
].filter(filter => Boolean(filter.value));

// Format the value as a proper filter condition string
const mutableSearch = new MutableSearch('');
Expand Down
15 changes: 13 additions & 2 deletions static/app/views/dashboards/filtersBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,21 @@ export default function FiltersBar({
[];

if (hasDrillDownFlowsFeature) {
return [
...globalFilters,
const finalFilters = [...globalFilters];
const temporaryFilters = [
...(dashboardFiltersFromURL?.[DashboardFilterKeys.TEMPORARY_FILTERS] ?? []),
];
finalFilters.forEach(filter => {
// if a temporary filter exists for the same dataset and key, override it and delete it from the temporary filters to avoid duplicates
const temporaryFilter = temporaryFilters.find(
tf => tf.dataset === filter.dataset && tf.tag.key === filter.tag.key
);
if (temporaryFilter) {
filter.value = temporaryFilter.value;
temporaryFilters.splice(temporaryFilters.indexOf(temporaryFilter), 1);
}
});
return [...finalFilters, ...temporaryFilters];
}

return globalFilters;
Expand Down
38 changes: 35 additions & 3 deletions static/app/views/dashboards/prebuiltDashboardRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import LoadingContainer from 'sentry/components/loading/loadingContainer';
import {defined} from 'sentry/utils';
import {useApiQuery} from 'sentry/utils/queryClient';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import useRouter from 'sentry/utils/useRouter';
import DashboardDetail from 'sentry/views/dashboards/detail';
import {DashboardState, type DashboardDetails} from 'sentry/views/dashboards/types';
Expand Down Expand Up @@ -59,6 +61,8 @@ export function PrebuiltDashboardRenderer({prebuiltId}: PrebuiltDashboardRendere

const usePopulateLinkedDashboards = (dashboard: PrebuiltDashboard) => {
const {widgets} = dashboard;
const organization = useOrganization();

const linkedDashboardsWithStaticDashboardIds = widgets
.flatMap(widget => {
return widget.queries
Expand All @@ -67,11 +71,39 @@ const usePopulateLinkedDashboards = (dashboard: PrebuiltDashboard) => {
})
.filter(linkedDashboard => linkedDashboard.staticDashboardId !== undefined);

if (!linkedDashboardsWithStaticDashboardIds.length) {
const hasLinkedDashboards = linkedDashboardsWithStaticDashboardIds.length > 0;
const path = `/organizations/${organization.slug}/dashboards/`;

const {data, isLoading} = useApiQuery<DashboardDetails[]>(
[
path,
{
query: {
prebuiltId: linkedDashboardsWithStaticDashboardIds.map(
d => d.staticDashboardId
),
},
},
],
{
enabled: hasLinkedDashboards,
staleTime: 0,
retry: false,
}
);

if (!hasLinkedDashboards) {
return {dashboard, isLoading: false};
}

// TODO we should fetch the real dashboard id here, this requires BROWSE-128
linkedDashboardsWithStaticDashboardIds.forEach(linkedDashboard => {
const dasboardId = data?.find(
d => d.prebuiltId === linkedDashboard.staticDashboardId
)?.id;
if (dasboardId) {
linkedDashboard.dashboardId = dasboardId;
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Mutation of static dashboard configuration

The code directly modifies properties of linkedDashboard objects within the component body. Since these objects reference the static PREBUILT_DASHBOARDS configuration, this side effect persists globally, potentially causing incorrect dashboard IDs to persist across organization changes. Side effects should not occur during render; use state or memoization to handle the updated data.

Fix in Cursor Fix in Web


return {dashboard, isLoading: false};
return {dashboard, isLoading};
};
Loading