diff --git a/dashboard/src/components/Breadcrumb/IssueBreadcrumb.tsx b/dashboard/src/components/Breadcrumb/IssueBreadcrumb.tsx
new file mode 100644
index 00000000..17ad038b
--- /dev/null
+++ b/dashboard/src/components/Breadcrumb/IssueBreadcrumb.tsx
@@ -0,0 +1,42 @@
+import type { MessageDescriptor } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
+
+import { memo, type JSX } from 'react';
+
+import type { LinkProps } from '@tanstack/react-router';
+
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbList,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+} from './Breadcrumb';
+
+const IssueBreadcrumb = ({
+ searchParams,
+ locationMessage,
+}: {
+ searchParams: LinkProps['search'];
+ locationMessage: MessageDescriptor['id'];
+}): JSX.Element => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+export const MemoizedIssueBreadcrumb = memo(IssueBreadcrumb);
diff --git a/dashboard/src/components/IssueTable/IssueTable.tsx b/dashboard/src/components/IssueTable/IssueTable.tsx
index 8d204c3b..0f3331b7 100644
--- a/dashboard/src/components/IssueTable/IssueTable.tsx
+++ b/dashboard/src/components/IssueTable/IssueTable.tsx
@@ -41,6 +41,7 @@ import { valueOrEmpty } from '@/lib/string';
import { TooltipDateTime } from '@/components/TooltipDateTime';
import { shouldShowRelativeDate } from '@/lib/date';
+import { RedirectFrom } from '@/types/general';
const getLinkProps = (
row: Row,
@@ -74,6 +75,8 @@ const getLinkProps = (
params: { issueId: row.original.id },
state: s => ({
...s,
+ id: row.original.id,
+ from: RedirectFrom.Issues,
}),
};
};
diff --git a/dashboard/src/locales/messages/index.ts b/dashboard/src/locales/messages/index.ts
index 53929b81..d846a5f5 100644
--- a/dashboard/src/locales/messages/index.ts
+++ b/dashboard/src/locales/messages/index.ts
@@ -207,6 +207,7 @@ export const messages = {
'issue.firstSeen': 'First seen',
'issue.newIssue': 'New issue: This is the first time this issue was seen',
'issue.noIssueFound': 'No issue found.',
+ 'issue.path': 'Issues',
'issue.searchPlaceholder': 'Search by issue comment with a regex',
'issue.tooltip':
'Issues groups several builds or tests by matching result status and logs.{br}They may also be linked to an external issue tracker or mailing list discussion.',
diff --git a/dashboard/src/pages/IssueDetails/IssueDetails.tsx b/dashboard/src/pages/IssueDetails/IssueDetails.tsx
index 5eb3e2f8..eef11dc6 100644
--- a/dashboard/src/pages/IssueDetails/IssueDetails.tsx
+++ b/dashboard/src/pages/IssueDetails/IssueDetails.tsx
@@ -10,6 +10,7 @@ import { RedirectFrom } from '@/types/general';
import { MemoizedTreeBreadcrumb } from '@/components/Breadcrumb/TreeBreadcrumb';
import { MemoizedHardwareBreadcrumb } from '@/components/Breadcrumb/HardwareBreadcrumb';
import { useSearchStore } from '@/hooks/store/useSearchStore';
+import { MemoizedIssueBreadcrumb } from '@/components/Breadcrumb/IssueBreadcrumb';
const getBuildTableRowLink = (buildId: string): LinkProps => ({
to: '/build/$buildId',
@@ -54,6 +55,15 @@ const IssueDetailsPage = (): JSX.Element => {
/>
);
}
+
+ if (historyState.from === RedirectFrom.Issues) {
+ return (
+
+ );
+ }
}
}, [historyState.from, historyState.id, previousSearch]);
diff --git a/dashboard/src/pages/IssueListing/IssueListingPage.tsx b/dashboard/src/pages/IssueListing/IssueListingPage.tsx
index dcd3774a..7e039648 100644
--- a/dashboard/src/pages/IssueListing/IssueListingPage.tsx
+++ b/dashboard/src/pages/IssueListing/IssueListingPage.tsx
@@ -1,4 +1,6 @@
-import { useMemo, type JSX } from 'react';
+import { useEffect, useMemo, type JSX } from 'react';
+
+import { useSearch } from '@tanstack/react-router';
import QuerySwitcher from '@/components/QuerySwitcher/QuerySwitcher';
@@ -10,6 +12,7 @@ import { useIssueListing } from '@/api/issue';
import { IssueTable } from '@/components/IssueTable/IssueTable';
import { matchesRegexOrIncludes } from '@/lib/string';
import type { IssueListingResponse } from '@/types/issueListing';
+import { useSearchStore } from '@/hooks/store/useSearchStore';
interface IIssueListingPage {
inputFilter: string;
@@ -19,6 +22,13 @@ export const IssueListingPage = ({
inputFilter,
}: IIssueListingPage): JSX.Element => {
const { data, status, error, isLoading } = useIssueListing();
+ const searchParams = useSearch({ from: '/_main/issues' });
+ const updatePreviousSearch = useSearchStore(s => s.updatePreviousSearch);
+
+ useEffect(
+ () => updatePreviousSearch(searchParams),
+ [searchParams, updatePreviousSearch],
+ );
const filteredData = useMemo((): IssueListingResponse => {
if (!data) {
diff --git a/dashboard/src/types/general.ts b/dashboard/src/types/general.ts
index 3e2560a0..19f85e05 100644
--- a/dashboard/src/types/general.ts
+++ b/dashboard/src/types/general.ts
@@ -361,6 +361,7 @@ export const getTargetFilter = (
export enum RedirectFrom {
Tree = 'tree',
Hardware = 'hardware',
+ Issues = 'issues',
}
export type PossibleMonitorPath = '/tree' | '/hardware' | '/issues';