Skip to content

Commit

Permalink
Refactor interior page logic
Browse files Browse the repository at this point in the history
  • Loading branch information
pookmish committed Mar 3, 2024
1 parent 2b647da commit c158cdd
Show file tree
Hide file tree
Showing 9 changed files with 1,082 additions and 140 deletions.
2 changes: 1 addition & 1 deletion .storybook/stories/menu/SideMenu.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ export const SideNavComponent: Story = {
{id: "2", title: "Second Item", url: "/bar", ...defaultMenuProps},
{id: "3", title: "Third Item", url: "/baz", ...defaultMenuProps},
],
currentPath: "/foo/baz/bin",
activeTrail: ["4", "6", "8"],
},
};
893 changes: 893 additions & 0 deletions .yarn/releases/yarn-4.1.0.cjs

Large diffs are not rendered by default.

31 changes: 28 additions & 3 deletions app/sitemap.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import {MetadataRoute} from "next";
import {getAllNodePaths} from "@lib/gql/fetcher";
import {graphqlClient} from "@lib/gql/fetcher";
import {headers} from "next/headers";
import {NodeUnion} from "@lib/gql/__generated__/drupal";

const Sitemap = async (): Promise<MetadataRoute.Sitemap> => {
const nodePaths = await getAllNodePaths()
return nodePaths.map(path => ({url: path}));
const nodeQuery = await graphqlClient({next: {tags: ['paths']}}).AllNodes();
const nodes: NodeUnion[] = [];

nodeQuery.nodeStanfordCourses.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordEventSeriesItems.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordEvents.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordNewsItems.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordPages.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordPeople.nodes.map(node => nodes.push(node as NodeUnion));
nodeQuery.nodeStanfordPolicies.nodes.map(node => nodes.push(node as NodeUnion));


const sitemap: MetadataRoute.Sitemap = [];
const domain = 'https://' + headers().get('host');

nodes.map(node => sitemap.push({
url: `${domain}${node.path}`,
lastModified: new Date(node.changed.time),
priority: node.__typename === "NodeStanfordPage" ? 1 : .8,
changeFrequency: node.__typename === "NodeStanfordPage" ? "weekly": "monthly"
}));

return sitemap;
}


export default Sitemap;
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,26 @@
"@heroicons/react": "^2.1.1",
"@js-temporal/polyfill": "^0.4.4",
"@mui/base": "^5.0.0-beta.37",
"@next/third-parties": "^14.1.0",
"@next/third-parties": "^14.1.1",
"@tailwindcss/container-queries": "^0.1.1",
"@types/node": "^20.11.22",
"@types/react": "^18.2.60",
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"@uidotdev/usehooks": "^2.4.1",
"algoliasearch": "^4.22.1",
"autoprefixer": "^10.4.17",
"autoprefixer": "^10.4.18",
"axios": "^1.6.7",
"clsx": "^2.1.0",
"decanter": "^7.2.0",
"drupal-jsonapi-params": "^2.3.1",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.0",
"eslint-config-next": "^14.1.1",
"graphql": "^16.8.1",
"graphql-request": "^6.1.0",
"graphql-tag": "^2.12.6",
"html-entities": "^2.4.0",
"html-react-parser": "^5.1.8",
"next": "^14.1.0",
"next": "^14.1.1",
"next-drupal": "^1.6.0",
"postcss": "^8.4.35",
"qs": "^6.11.2",
Expand All @@ -51,15 +51,15 @@
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3",
"usehooks-ts": "^2.15.1",
"zustand": "^4.5.1"
"zustand": "^4.5.2"
},
"devDependencies": {
"@graphql-codegen/add": "^5.0.2",
"@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/import-types-preset": "^3.0.0",
"@graphql-codegen/typescript-graphql-request": "^6.2.0",
"@graphql-codegen/typescript-operations": "^4.2.0",
"@next/bundle-analyzer": "^14.1.0",
"@next/bundle-analyzer": "^14.1.1",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
Expand Down
20 changes: 17 additions & 3 deletions src/components/layouts/interior-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,35 @@ import SideNav from "@components/menu/side-nav";
import {HtmlHTMLAttributes} from "react";
import {isDraftMode} from "@lib/drupal/utils";
import {MenuAvailable} from "@lib/gql/__generated__/drupal.d";
import useActiveTrail from "@lib/hooks/useActiveTrail";

type Props = HtmlHTMLAttributes<HTMLDivElement> & {
currentPath: string
}

const InteriorPage = async ({children, currentPath, ...props}: Props) => {
const menu = await getMenu(MenuAvailable.Main, isDraftMode());
const activeTrail: string[] = useActiveTrail(menu, currentPath);

// Peel off the menu items from the parent.
const topMenuItem = activeTrail.length > 0 ? menu.find(item => item.id === activeTrail[0]) : undefined;
const subTree = topMenuItem ? topMenuItem.children : [];

return (
<div className="centered flex gap-20" {...props}>
<section className="flex-grow">

{(subTree.length > 1 || subTree[0]?.children) &&
<aside className="hidden lg:block w-1/4 shrink-0">
<a href="#page-content" className="skiplink">Skip secondary navigation</a>
<SideNav menuItems={subTree} activeTrail={activeTrail}/>
</aside>
}

<section className="flex-grow" id="page-content">
{children}
</section>
<SideNav menuItems={menu} currentPath={currentPath}/>
</div>
)
}
export default InteriorPage;

export default InteriorPage;
31 changes: 8 additions & 23 deletions src/components/menu/side-nav.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import useActiveTrail from "@lib/hooks/useActiveTrail";
import Link from "@components/elements/link";
import {clsx} from "clsx";
import {MenuItem as MenuItemType} from "@lib/gql/__generated__/drupal.d";

const SideNav = ({menuItems, currentPath}: { menuItems: MenuItemType[], currentPath?: string }) => {
const activeTrail: string[] = useActiveTrail(menuItems, currentPath);

// Peel off the menu items from the parent.
const topMenuItem = activeTrail.length > 0 ? menuItems.find(item => item.id === activeTrail[0]) : undefined;
if (!topMenuItem) return null;

const subTree = topMenuItem.children || undefined;

if (!subTree || (subTree.length === 1 && !subTree[0].children)) {
return null;
}

const SideNav = ({menuItems, activeTrail}: { menuItems: MenuItemType[], activeTrail: string[] }) => {
return (
<aside className="hidden lg:block w-1/4 shrink-0 order-first">
<nav aria-label="Secondary Navigation">
<ul className="list-unstyled">
{subTree.map(item =>
<MenuItem key={`sidenav--${item.id}`} {...item} activeTrail={activeTrail} level={0}/>
)}
</ul>
</nav>
</aside>
<nav aria-label="Secondary Navigation">
<ul className="list-unstyled">
{menuItems.map(item =>
<MenuItem key={`sidenav--${item.id}`} {...item} activeTrail={activeTrail} level={0}/>
)}
</ul>
</nav>
)
}

Expand Down
10 changes: 8 additions & 2 deletions src/lib/gql/fetcher.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use server";

import {getSdk} from "@lib/gql/__generated__/queries";
import {
ConfigPagesQuery,
Expand Down Expand Up @@ -34,6 +32,8 @@ export const getEntityFromPath = cache(async <T extends NodeUnion | TermUnion, >
redirect?: RouteRedirect
error?: string
}> => {
"use server";

const headers = await buildHeaders({draftMode})
let entity: T | undefined;
let query: RouteQuery;
Expand All @@ -51,6 +51,8 @@ export const getEntityFromPath = cache(async <T extends NodeUnion | TermUnion, >
})

export const getConfigPage = async <T extends ConfigPagesUnion, >(configPageType: ConfigPagesUnion['__typename']): Promise<T | undefined> => {
"use server";

let query: ConfigPagesQuery;
try {
query = await getConfigPagesData();
Expand Down Expand Up @@ -79,6 +81,8 @@ const getConfigPagesData = cache(async (): Promise<ConfigPagesQuery> => {
})

export const getMenu = cache(async (name?: MenuAvailable, draftMode?: boolean): Promise<MenuItem[]> => {
"use server";

const headers = await buildHeaders({draftMode});
const menu = await graphqlClient({headers, next: {tags: ['menus', `menu:${name || "main"}`]}}).Menu({name});
const menuItems = (menu.menu?.items || []) as MenuItem[];
Expand All @@ -92,6 +96,8 @@ export const getMenu = cache(async (name?: MenuAvailable, draftMode?: boolean):
})

export const getAllNodePaths = cache(async () => {
"use server";

const nodeQuery = await graphqlClient({next: {tags: ['paths']}}).AllNodes();
const nodePaths: string[] = [];
nodeQuery.nodeStanfordCourses.nodes.map(node => nodePaths.push(node.path));
Expand Down
8 changes: 3 additions & 5 deletions src/lib/hooks/useActiveTrail.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@

import {useCallback, useMemo} from "react";
import {MenuItem} from "@lib/gql/__generated__/drupal.d";

const useActiveTrail = (menuItems: MenuItem[], currentPath?: string) => {

const getActiveTrail = useCallback((menuItems: MenuItem[], trail: string[] = []): string[] => {
const getActiveTrail = (menuItems: MenuItem[], trail: string[] = []): string[] => {
let childTrail, currentTrail;
for (let i = 0; i < menuItems.length; i++) {
currentTrail = [...trail];
Expand All @@ -25,9 +23,9 @@ const useActiveTrail = (menuItems: MenuItem[], currentPath?: string) => {

}
return [];
}, [currentPath]);
};

return useMemo(() => getActiveTrail(menuItems), [getActiveTrail, menuItems]);
return getActiveTrail(menuItems);
}

export default useActiveTrail;
Loading

0 comments on commit c158cdd

Please sign in to comment.