modal search param for copied issue links

This commit is contained in:
2026-01-26 19:38:02 +00:00
parent 7d9c58390c
commit 3aed8b21b6
4 changed files with 29 additions and 5 deletions

View File

@@ -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);

View File

@@ -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 (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogTrigger asChild>{trigger}</DialogTrigger>
{trigger && <DialogTrigger asChild>{trigger}</DialogTrigger>}
<DialogContent className="w-lg p-0" showCloseButton={false}>
<DialogTitle className="sr-only">
{issueID(selectedProject.Project.key, issueData.Issue.number)}

View File

@@ -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 });
}
}, []);

View File

@@ -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() {
</div>
</ResizablePanel>
{selectedIssue && (
{selectedIssue && !showIssueModal && (
<>
<ResizableSeparator />
<ResizablePanel id={"right"} defaultSize={"30%"} minSize={363} maxSize={"60%"}>
@@ -182,6 +186,18 @@ export default function Issues() {
)}
</ResizablePanelGroup>
)}
{selectedIssue && showIssueModal && (
<IssueModal
issueData={selectedIssue}
open={true}
onOpenChange={(open) => {
if (!open) {
selectIssue(null);
}
}}
/>
)}
</main>
);
}