fixed url keys not updating properly

This commit is contained in:
Oliver Bryan
2026-01-21 19:27:21 +00:00
parent 8f87fc8acf
commit a1897800d8
3 changed files with 81 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
import type { IssueResponse, OrganisationResponse, ProjectResponse } from "@sprint/shared";
import type { ReactNode } from "react";
import { createContext, useCallback, useContext, useMemo, useState } from "react";
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
type SelectionContextValue = {
selectedOrganisationId: number | null;
@@ -29,6 +29,12 @@ const readStoredId = (key: string) => {
return Number.isNaN(parsed) ? null : parsed;
};
const readStoredString = (key: string) => {
const value = localStorage.getItem(key);
if (!value) return null;
return value.trim() || null;
};
const updateUrlParams = (updates: {
orgSlug?: string | null;
projectKey?: string | null;
@@ -87,7 +93,14 @@ export function SelectionProvider({ children }: { children: ReactNode }) {
setSelectedIssueId(null);
if (id != null) localStorage.setItem("selectedOrganisationId", `${id}`);
else localStorage.removeItem("selectedOrganisationId");
if (organisation) {
localStorage.setItem("selectedOrganisationSlug", organisation.Organisation.slug.toLowerCase());
} else {
localStorage.removeItem("selectedOrganisationSlug");
}
localStorage.removeItem("selectedProjectId");
localStorage.removeItem("selectedProjectKey");
localStorage.removeItem("selectedIssueNumber");
if (!options?.skipUrlUpdate) {
updateUrlParams({
orgSlug: organisation?.Organisation.slug.toLowerCase() ?? null,
@@ -105,6 +118,12 @@ export function SelectionProvider({ children }: { children: ReactNode }) {
setSelectedIssueId(null);
if (id != null) localStorage.setItem("selectedProjectId", `${id}`);
else localStorage.removeItem("selectedProjectId");
if (project) {
localStorage.setItem("selectedProjectKey", project.Project.key.toLowerCase());
} else {
localStorage.removeItem("selectedProjectKey");
}
localStorage.removeItem("selectedIssueNumber");
if (!options?.skipUrlUpdate) {
updateUrlParams({
projectKey: project?.Project.key.toLowerCase() ?? null,
@@ -116,11 +135,45 @@ export function SelectionProvider({ children }: { children: ReactNode }) {
const selectIssue = useCallback((issue: IssueResponse | null, options?: SelectionOptions) => {
const id = issue?.Issue.id ?? null;
setSelectedIssueId(id);
if (issue) {
localStorage.setItem("selectedIssueNumber", `${issue.Issue.number}`);
} else {
localStorage.removeItem("selectedIssueNumber");
}
if (!options?.skipUrlUpdate) {
updateUrlParams({ issueNumber: issue?.Issue.number ?? null });
}
}, []);
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const allowIssue = window.location.pathname.startsWith("/issues");
const updates: {
orgSlug?: string | null;
projectKey?: string | null;
issueNumber?: number | null;
} = {};
if (!params.get("o")) {
const storedOrgSlug = readStoredString("selectedOrganisationSlug");
if (storedOrgSlug) updates.orgSlug = storedOrgSlug;
}
if (!params.get("p")) {
const storedProjectKey = readStoredString("selectedProjectKey");
if (storedProjectKey) updates.projectKey = storedProjectKey;
}
if (allowIssue && !params.get("i")) {
const storedIssueNumber = readStoredId("selectedIssueNumber");
if (storedIssueNumber != null) updates.issueNumber = storedIssueNumber;
}
if (Object.keys(updates).length > 0) {
updateUrlParams(updates);
}
}, []);
const value = useMemo<SelectionContextValue>(
() => ({
selectedOrganisationId,

View File

@@ -27,7 +27,7 @@ import { useOrganisations } from "@/lib/query/hooks";
export default function TopBar({ showIssueForm = true }: { showIssueForm?: boolean }) {
const { user } = useAuthenticatedSession();
const { selectedOrganisationId, selectedProjectId } = useSelection();
const { selectedOrganisationId, selectedProjectId, selectIssue } = useSelection();
const { data: organisationsData = [] } = useOrganisations();
const location = useLocation();
const navigate = useNavigate();
@@ -56,7 +56,29 @@ export default function TopBar({ showIssueForm = true }: { showIssueForm?: boole
{selectedOrganisationId && <ProjectSelect showLabel />}
{selectedOrganisationId && (
<Tabs value={activeView} onValueChange={(value) => navigate(`/${value}`)}>
<Tabs
value={activeView}
onValueChange={(value) => {
const orgSlug = localStorage.getItem("selectedOrganisationSlug")?.trim() ?? "";
const projectKey = localStorage.getItem("selectedProjectKey")?.trim() ?? "";
const issueNumber = localStorage.getItem("selectedIssueNumber")?.trim() ?? "";
const params = new URLSearchParams();
if (orgSlug) params.set("o", orgSlug.toLowerCase());
if (projectKey) params.set("p", projectKey.toLowerCase());
if (value === "issues" && issueNumber) {
params.set("i", issueNumber);
}
if (value === "timeline") {
localStorage.removeItem("selectedIssueNumber");
selectIssue(null, { skipUrlUpdate: true });
}
const search = params.toString();
navigate(`/${value}${search ? `?${search}` : ""}`);
}}
>
<TabsList>
<TabsTrigger value="issues">Issues</TabsTrigger>
<TabsTrigger value="timeline">Timeline</TabsTrigger>

View File

@@ -21,7 +21,10 @@ export function clearAuth(): void {
sessionStorage.removeItem("csrfToken");
localStorage.removeItem("user");
localStorage.removeItem("selectedOrganisationId");
localStorage.removeItem("selectedOrganisationSlug");
localStorage.removeItem("selectedProjectId");
localStorage.removeItem("selectedProjectKey");
localStorage.removeItem("selectedIssueNumber");
}
export function capitalise(str: string) {