diff --git a/packages/frontend/src/components/issue-details.tsx b/packages/frontend/src/components/issue-details.tsx index 16b20eb..f9ffa86 100644 --- a/packages/frontend/src/components/issue-details.tsx +++ b/packages/frontend/src/components/issue-details.tsx @@ -280,7 +280,9 @@ export function IssueDetails({ const handleCopyLink = async () => { try { - await navigator.clipboard.writeText(window.location.href); + const url = new URL(window.location.href); + url.searchParams.set("modal", "true"); + await navigator.clipboard.writeText(url.toString()); setLinkCopied(true); if (copyTimeoutRef.current) { window.clearTimeout(copyTimeoutRef.current); diff --git a/packages/frontend/src/components/issue-modal.tsx b/packages/frontend/src/components/issue-modal.tsx index 550632e..583636b 100644 --- a/packages/frontend/src/components/issue-modal.tsx +++ b/packages/frontend/src/components/issue-modal.tsx @@ -19,7 +19,7 @@ export function IssueModal({ issueData: IssueResponse | null; open: boolean; onOpenChange: (open: boolean) => void; - trigger: ReactNode; + trigger?: ReactNode; }) { const selectedOrganisation = useSelectedOrganisation(); const selectedProject = useSelectedProject(); @@ -35,7 +35,7 @@ export function IssueModal({ return ( - {trigger} + {trigger && {trigger}} {issueID(selectedProject.Project.key, issueData.Issue.number)} diff --git a/packages/frontend/src/components/selection-provider.tsx b/packages/frontend/src/components/selection-provider.tsx index 915e61c..f66d9b4 100644 --- a/packages/frontend/src/components/selection-provider.tsx +++ b/packages/frontend/src/components/selection-provider.tsx @@ -39,6 +39,7 @@ const updateUrlParams = (updates: { orgSlug?: string | null; projectKey?: string | null; issueNumber?: number | null; + modal?: boolean | null; }) => { const params = new URLSearchParams(window.location.search); @@ -57,6 +58,11 @@ const updateUrlParams = (updates: { else params.delete("i"); } + if (updates.modal !== undefined) { + if (updates.modal) params.set("modal", "true"); + else params.delete("modal"); + } + const search = params.toString(); const nextUrl = `${window.location.pathname}${search ? `?${search}` : ""}`; window.history.replaceState(null, "", nextUrl); @@ -141,7 +147,7 @@ export function SelectionProvider({ children }: { children: ReactNode }) { localStorage.removeItem("selectedIssueNumber"); } if (!options?.skipUrlUpdate) { - updateUrlParams({ issueNumber: issue?.Issue.number ?? null }); + updateUrlParams({ issueNumber: issue?.Issue.number ?? null, modal: null }); } }, []); diff --git a/packages/frontend/src/pages/Issues.tsx b/packages/frontend/src/pages/Issues.tsx index 29fda80..4d95b85 100644 --- a/packages/frontend/src/pages/Issues.tsx +++ b/packages/frontend/src/pages/Issues.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef } from "react"; import { useLocation } from "react-router-dom"; import { IssueDetailPane } from "@/components/issue-detail-pane"; +import { IssueModal } from "@/components/issue-modal"; import { IssuesTable } from "@/components/issues-table"; import { useSelection } from "@/components/selection-provider"; import TopBar from "@/components/top-bar"; @@ -35,6 +36,9 @@ export default function Issues() { }; }, [location.search]); + const showIssueModal = + new URLSearchParams(window.location.search).get("modal")?.trim().toLowerCase() === "true"; + const { data: organisationsData = [] } = useOrganisations(); const { data: projectsData = [] } = useProjects(selectedOrganisationId); const { data: issuesData = [], isFetched: issuesFetched } = useIssues(selectedProjectId); @@ -170,7 +174,7 @@ export default function Issues() { - {selectedIssue && ( + {selectedIssue && !showIssueModal && ( <> @@ -182,6 +186,18 @@ export default function Issues() { )} )} + + {selectedIssue && showIssueModal && ( + { + if (!open) { + selectIssue(null); + } + }} + /> + )} ); }