mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 02:33:01 +00:00
deep link support for org, project, issue
allows for sharing of issues
This commit is contained in:
@@ -7,7 +7,7 @@ import type {
|
|||||||
ProjectResponse,
|
ProjectResponse,
|
||||||
UserRecord,
|
UserRecord,
|
||||||
} from "@issue/shared";
|
} from "@issue/shared";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import AccountDialog from "@/components/account-dialog";
|
import AccountDialog from "@/components/account-dialog";
|
||||||
import { CreateIssue } from "@/components/create-issue";
|
import { CreateIssue } from "@/components/create-issue";
|
||||||
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
||||||
@@ -47,6 +47,28 @@ export default function App() {
|
|||||||
|
|
||||||
const [members, setMembers] = useState<UserRecord[]>([]);
|
const [members, setMembers] = useState<UserRecord[]>([]);
|
||||||
|
|
||||||
|
const deepLinkParams = useMemo(() => {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const orgSlug = params.get("o")?.trim().toLowerCase() ?? "";
|
||||||
|
const projectKey = params.get("p")?.trim().toLowerCase() ?? "";
|
||||||
|
const issueParam = params.get("i")?.trim() ?? "";
|
||||||
|
const issueNumber = issueParam === "" ? null : Number.parseInt(issueParam, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
orgSlug,
|
||||||
|
projectKey,
|
||||||
|
issueNumber: issueNumber != null && Number.isNaN(issueNumber) ? null : issueNumber,
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const deepLinkStateRef = useRef({
|
||||||
|
appliedOrg: false,
|
||||||
|
appliedProject: false,
|
||||||
|
appliedIssue: false,
|
||||||
|
orgMatched: false,
|
||||||
|
projectMatched: false,
|
||||||
|
});
|
||||||
|
|
||||||
const refetchOrganisations = async (options?: { selectOrganisationId?: number }) => {
|
const refetchOrganisations = async (options?: { selectOrganisationId?: number }) => {
|
||||||
try {
|
try {
|
||||||
await organisation.byUser({
|
await organisation.byUser({
|
||||||
@@ -66,11 +88,28 @@ export default function App() {
|
|||||||
selected = created;
|
selected = created;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const savedId = localStorage.getItem("selectedOrganisationId");
|
const deepLinkState = deepLinkStateRef.current;
|
||||||
if (savedId) {
|
if (deepLinkParams.orgSlug && !deepLinkState.appliedOrg) {
|
||||||
const saved = organisations.find((o) => o.Organisation.id === Number(savedId));
|
const match = organisations.find(
|
||||||
if (saved) {
|
(org) => org.Organisation.slug.toLowerCase() === deepLinkParams.orgSlug,
|
||||||
selected = saved;
|
);
|
||||||
|
deepLinkState.appliedOrg = true;
|
||||||
|
deepLinkState.orgMatched = Boolean(match);
|
||||||
|
if (match) {
|
||||||
|
selected = match;
|
||||||
|
localStorage.setItem("selectedOrganisationId", `${match.Organisation.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selected) {
|
||||||
|
const savedId = localStorage.getItem("selectedOrganisationId");
|
||||||
|
if (savedId) {
|
||||||
|
const saved = organisations.find(
|
||||||
|
(o) => o.Organisation.id === Number(savedId),
|
||||||
|
);
|
||||||
|
if (saved) {
|
||||||
|
selected = saved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,11 +152,30 @@ export default function App() {
|
|||||||
selected = created;
|
selected = created;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const savedId = localStorage.getItem("selectedProjectId");
|
const deepLinkState = deepLinkStateRef.current;
|
||||||
if (savedId) {
|
if (
|
||||||
const saved = projects.find((p) => p.Project.id === Number(savedId));
|
deepLinkParams.projectKey &&
|
||||||
if (saved) {
|
deepLinkState.orgMatched &&
|
||||||
selected = saved;
|
!deepLinkState.appliedProject
|
||||||
|
) {
|
||||||
|
const match = projects.find(
|
||||||
|
(proj) => proj.Project.key.toLowerCase() === deepLinkParams.projectKey,
|
||||||
|
);
|
||||||
|
deepLinkState.appliedProject = true;
|
||||||
|
deepLinkState.projectMatched = Boolean(match);
|
||||||
|
if (match) {
|
||||||
|
selected = match;
|
||||||
|
localStorage.setItem("selectedProjectId", `${match.Project.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selected) {
|
||||||
|
const savedId = localStorage.getItem("selectedProjectId");
|
||||||
|
if (savedId) {
|
||||||
|
const saved = projects.find((p) => p.Project.id === Number(savedId));
|
||||||
|
if (saved) {
|
||||||
|
selected = saved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,6 +237,19 @@ export default function App() {
|
|||||||
const issues = data as IssueResponse[];
|
const issues = data as IssueResponse[];
|
||||||
issues.reverse(); // newest at the bottom, but if the order has been rearranged, respect that
|
issues.reverse(); // newest at the bottom, but if the order has been rearranged, respect that
|
||||||
setIssues(issues);
|
setIssues(issues);
|
||||||
|
|
||||||
|
const deepLinkState = deepLinkStateRef.current;
|
||||||
|
if (
|
||||||
|
deepLinkParams.issueNumber != null &&
|
||||||
|
deepLinkState.projectMatched &&
|
||||||
|
!deepLinkState.appliedIssue
|
||||||
|
) {
|
||||||
|
const match = issues.find(
|
||||||
|
(issue) => issue.Issue.number === deepLinkParams.issueNumber,
|
||||||
|
);
|
||||||
|
deepLinkState.appliedIssue = true;
|
||||||
|
setSelectedIssue(match ?? null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error("error fetching issues:", error);
|
console.error("error fetching issues:", error);
|
||||||
|
|||||||
Reference in New Issue
Block a user