Skip to content
Merged
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
52 changes: 52 additions & 0 deletions static-site/app/ncov/[[...ncov]]/error-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client";

import React from "react";
import { useParams } from "next/navigation";

import ErrorMessage from "../../../components/error-message";

/**
* A React Client component that detects if the requested URL
* contains path elements past `/ncov`, and, if so, returns a
* component that displays an error message banner. If additional
* path elements are not detected, returns null.
*
* N.b., the way this component is used, we only render it when we've
* already determined that there _is_ a need to display an error
* message. In other words, it is fully expected that the `else`
* branch of the conditional will never actually execute.
*/
export default function ErrorBanner(): React.ReactElement | null {
const params = useParams();

if (params && params["ncov"]) {
// n.b., I don't think `params["ncov"]` is ever going to be
// anything other than a list, but let's make the type checker
// happy…
const path =
typeof params["ncov"] === "string"
? params["ncov"]
: params["ncov"].join("/");

const resourceType = path.startsWith("narratives")
? "narrative"
: "dataset";

const title = `The ${resourceType} "nextstrain.org/ncov/${path}" doesn't exist.`;
const contents = (
<p>
{`Here is the SARS-CoV-2 page, where we have listed featured datasets,
narratives, and resources related to SARS-CoV-2. Note that some SARS-CoV-2
datasets may not be listed here. For a more comprehensive list of
Nextstrain-maintained (including SARS-CoV-2) datasets,
check out `}
<a href="/pathogens">nextstrain.org/pathogens</a>.
</p>
);

return <ErrorMessage title={title} contents={contents} />;
} else {
// this will never happen
return null;
}
}
20 changes: 20 additions & 0 deletions static-site/app/ncov/[[...ncov]]/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

import SarsCov2PageContent from "../../sars-cov-2/[[...sars-cov-2]]/content";

import ErrorBanner from "./error-banner";
import { metadata } from "./page";

/**
* A React Server component that renders the usual `/ncov` page
* content, with an error banner up-top explaining that the requested
* dataset doesn't actually exist.
*/
export default function FourOhFour(): React.ReactElement {
return (
<>
<ErrorBanner />
<SarsCov2PageContent metadata={metadata} />
</>
);
}
28 changes: 28 additions & 0 deletions static-site/app/ncov/[[...ncov]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { Metadata } from "next";

import SarsCov2PageContent from "../../sars-cov-2/[[...sars-cov-2]]/content";
import ValidateNcovUrl from "./validateNcovUrl";

const title = "Nextstrain SARS-CoV-2 resources";

/** page metadata */
export const metadata: Metadata = {
/** page title */
title,
};

/**
* A React Server Component for `/ncov`
*
* See note in `static-site/app/staging/[[...staging]]/page.tsx`
* to understand how this works
*/
export default function SarsCov2Page(): React.ReactElement {
return (
<>
<ValidateNcovUrl />
<SarsCov2PageContent metadata={metadata} />
</>
);
}
23 changes: 23 additions & 0 deletions static-site/app/ncov/[[...ncov]]/validateNcovUrl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import { notFound, useParams }from "next/navigation";

/**
* A React Client Component to detect when an invalid `/ncov/` URL
* is requested, which calls the `notFound()` method to redirect to
* the `not-found.tsx` component
*
* Note that any actually valid `/ncov/<something>` URL will be
* redirected at the Express router level, before the Next.js router
* is engaged, so if we are trying to render a `/ncov/<something>`
* URL, it _is_ an error
*/
export default function ValidateSarsUrl(): null {
const params = useParams();

if (params && params["ncov"]) {
notFound();
}
else { return null; }

}
26 changes: 26 additions & 0 deletions static-site/app/sars-cov-2/[[...sars-cov-2]]/content.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.listContainer {
font-size: 18px;
font-weight: 300;
line-height: var(--niceLineHeight);
margin: 0px auto;
max-width: 640px;
}
/* svg sub-elements represent icons (eg. external link) */
.listContainer svg {
color: var(--brandColor);
font-size: 14px;
margin-left: 10px;
}
.listContainer ul {
margin: 20px 0 0;
}
.listContainer li {
padding-bottom: 10px;
}

.subtext {
font-size: var(--niceFontSize);
font-style: italic;
font-weight: 300;
line-height: var(--niceLineHeight);
}
Loading