Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor dynamic page titles #701

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions frontend/src/Components/PageNav.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
import { useState, useEffect, useRef } from 'react';
import { useEffect, useRef } from 'react';
import { isAdministrator, useAuth } from '@/useAuth';
import { Bars3Icon, BuildingOffice2Icon } from '@heroicons/react/24/solid';
import ULIComponent from '@/Components/ULIComponent.tsx';
import { Facility, TitleHandler } from '@/common';
import { useMatches, useLoaderData } from 'react-router-dom';
import API from '@/api/api';

let setGlobalPageTitle: (newTitle: string) => void;

export default function PageNav({
showOpenMenu,
onShowNav
onShowNav,
globalPageTitle
}: {
showOpenMenu: boolean;
onShowNav?: () => void;
globalPageTitle: string;
}) {
const { user } = useAuth();
const detailsRef = useRef<HTMLDetailsElement>(null);
const facilityNames = useLoaderData() as Facility[] | null;
const matches = useMatches();
const currentRoute = matches[matches.length - 1];
const pageTitle = (currentRoute?.handle as TitleHandler)?.title;
const [globalPageTitle, _setGlobalPageTitle] = useState<string>(
pageTitle || 'Library Viewer'
);
setGlobalPageTitle = _setGlobalPageTitle;

useEffect(() => {
const closeDropdown = ({ target }: MouseEvent) => {
Expand Down Expand Up @@ -54,7 +50,9 @@ export default function PageNav({

return (
<div className="px-2 py-3 flex justify-between items-center">
<div className={`flex items-center gap-3 ${showOpenMenu ? 'px-3' : ''}`}>
<div
className={`flex items-center gap-3 ${showOpenMenu ? 'px-3' : ''}`}
>
{showOpenMenu ? (
<ULIComponent
onClick={onShowNav}
Expand Down Expand Up @@ -115,4 +113,3 @@ export default function PageNav({
</div>
);
}
export { setGlobalPageTitle };
10 changes: 8 additions & 2 deletions frontend/src/Layouts/AuthenticatedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export default function AuthenticatedLayout() {
const matches = useMatches() as CustomRouteMatch[];
const currentMatch = matches.find((match) => match?.handle?.title);
const title = currentMatch?.handle?.title ?? 'UnlockEd';
// ✅ Move global page title state to AuthenticatedLayout
const [globalPageTitle, setGlobalPageTitle] = useState<string>(title);

// We have three states we need to factor for.
// 1. If the nav is open & pinned (Large screens only & uses lg:drawer-open)
// 2. If the nav is open & not pinned (Large screens only)
Expand All @@ -37,7 +40,8 @@ export default function AuthenticatedLayout() {
setIsNavOpen(newPinnedState);
localStorage.setItem('navPinned', JSON.stringify(newPinnedState));
};

// Can i pass a title to page nave from auth layout
// can i get a way form outlet to bubble that up
return (
<div className="font-lato">
<div title={title} />
Expand All @@ -47,9 +51,11 @@ export default function AuthenticatedLayout() {
<PageNav
showOpenMenu={!isNavPinned}
onShowNav={showNav}
globalPageTitle={globalPageTitle}
/>
<div className="grow">
<Outlet />
{/* Needs to send data up to auth layout how to bubble up from outlet*/}
<Outlet context={{ setGlobalPageTitle }} />
</div>
</main>
</div>
Expand Down
45 changes: 29 additions & 16 deletions frontend/src/Pages/LibraryViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import Error from '@/Pages/Error';
import API from '@/api/api';
import { Library, ServerResponseOne } from '@/common';
import { usePathValue } from '@/Context/PathValueCtx';
import { setGlobalPageTitle } from '@/Components/PageNav';
import { LibrarySearchBar } from '@/Components/inputs';
import LibrarySearchResultsModal from '@/Components/LibrarySearchResultsModal';
import { useOutletContext } from 'react-router-dom';

interface UrlNavState {
url?: string;
}

interface OutletContextType {
setGlobalPageTitle: React.Dispatch<React.SetStateAction<string>>;
}
export default function LibraryViewer() {
const { id: libraryId } = useParams();
const [src, setSrc] = useState<string>('');
Expand All @@ -24,6 +26,7 @@ export default function LibraryViewer() {
const navigate = useNavigate();
const location = useLocation() as { state: UrlNavState };
const { url } = location.state || {};
const { setGlobalPageTitle } = useOutletContext<OutletContextType>();
const openModal = () => {
if (modalRef.current) {
modalRef.current.style.visibility = 'visible';
Expand All @@ -36,15 +39,19 @@ export default function LibraryViewer() {
modalRef.current.close();
}
};
const handleSearchResultClick = (url: string, title: string, libId?: number) => {
if(Number(libraryId) === libId){
const handleSearchResultClick = (
url: string,
title: string,
libId?: number
) => {
if (Number(libraryId) === libId) {
setSrc(url);
}else{
} else {
navigate(
`/viewer/libraries/${libId}`,

{
state: { url: url, title: title },
state: { url: url, title: title },
replace: true
}
);
Expand All @@ -57,7 +64,7 @@ export default function LibraryViewer() {
if (!modalRef.current.open) {
openModal();
}
//needed a way to call
//needed a way to call
modalRef.current.dispatchEvent(
new CustomEvent('executeHandleSearch', {
detail: {
Expand All @@ -74,22 +81,25 @@ export default function LibraryViewer() {
const fetchLibraryData = async () => {
setIsLoading(true);
try {
console.log('Fetching library data...');
const resp = (await API.get(
`libraries/${libraryId}`
)) as ServerResponseOne<Library>;

console.log('Response:', resp);

if (resp.success) {
const title = resp.data.title;
setGlobalPageTitle(title);
setGlobalPageTitle(title); // <-- This line sets the global page title after fetching data
setSearchPlaceholder('Search ' + title);
setPathVal([
{ path_id: ':library_name', value: title }
]);
setPathVal([{ path_id: ':library_name', value: title }]);
}

const response = await fetch(
`/api/proxy/libraries/${libraryId}/`
);
if (response.ok) {
if (url && url !== "") {
if (url && url !== '') {
setSrc(url);
} else {
setSrc(response.url);
Expand All @@ -99,17 +109,20 @@ export default function LibraryViewer() {
} else {
setError('Error loading library');
}
} catch {
} catch (err) {
console.error('Error fetching library data:', err);
setError('Error loading library');
} finally {
setIsLoading(false);
}
};
void fetchLibraryData();

void fetchLibraryData(); // <-- Triggering the library data fetch when component mounts
return () => {
sessionStorage.removeItem('tag');
};
}, [libraryId]);
}, [libraryId, setGlobalPageTitle]); // <-- Added setGlobalPageTitle to dependency array

return (
<div>
<div className="px-5 pb-4">
Expand Down
Loading