-
Notifications
You must be signed in to change notification settings - Fork 50
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
Convert pathogens to app router [#1066] #1124
Conversation
Note: this will leave the site in a broken state; doing this to ensure better Git tracking of file renames.
Note: this is a copy, not a move, as `<ExpandableTiles>` is also used in the `splash` and `Groups` components in addition to the `ListResources` component that is consumed by the `/pathogens` page.
Note: this is a copy, not a move, as `<ErrorBoundary>` is used elsewhere in the site, in addition to the `ListResources` component that is consumed by the `/pathogens` page.
Note: this is a copy, not a move, as `<ListResources>` is used elsewhere in the site, in addition to the `/pathogens` page.
Note: despite the placement of the component outside the <ListResources> component, it is only used within that component. I considered relocating it to `static-site/components/list-resources/spinner.tsx` but elected to maintain it outside of the <ListResources> component to better support future re-use, which seems not unlikely.
bfd05fb
to
2c2d562
Compare
2c2d562
to
042d526
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested out (in dev mode) and the page & styles look fine, although I couldn't test the modal due to the context error Jover noted. I didn't notice any poor on-hover box positioning, but you may have already fixed that bug?
I didn't really review the code as (from skimming) the majoriy of changes seem to be whitespace / splitting across new lines / changing comment styles etc. If there are sections of code which you'd like me to take a look at let me know and I'd be happy to; perhaps css modules?
import { useState, useEffect } from 'react'; | ||
import { Group, Resource, ResourceListingInfo } from './types'; | ||
import { InternalError } from '../ErrorBoundary'; | ||
|
||
|
||
/** | ||
* Uses the provided callback to fetch resources and parse those | ||
* resources into the `pathVersions` and `pathPrefix` values. The | ||
* callback is expected (and encouraged!) to throw() on any errors. | ||
* | ||
* Continues on to parse the `pathVersions`/`pathPrefix` data | ||
* structures into an array of groups, each representing a "pathogen" | ||
* and detailing the available resources for each, and the available | ||
* versions (snapshots) for each of those resources. In the case of | ||
* un-versioned resources, versions will be a zero-length array (i.e., | ||
* `[]`) | ||
* | ||
* The current implementation defines `versioned: boolean` for the | ||
* entire API response, however in the future we may shift this to the | ||
* API response and it may vary across the resources returned. | ||
*/ | ||
export function useDataFetch( | ||
"use client"; | ||
|
||
import { useState, useEffect } from "react"; | ||
|
||
import { InternalError } from "../error-boundary"; | ||
|
||
import { Group, Resource, ResourceListingInfo } from "./types"; | ||
|
||
// Uses the provided callback to fetch resources and parse those | ||
// resources into the `pathVersions` and `pathPrefix` values. The | ||
// callback is expected (and encouraged!) to throw() on any errors. | ||
// | ||
// Continues on to parse the `pathVersions`/`pathPrefix` data | ||
// structures into an array of groups, each representing a "pathogen" | ||
// and detailing the available resources for each, and the available | ||
// versions (snapshots) for each of those resources. In the case of | ||
// un-versioned resources, versions will be a zero-length array (i.e., | ||
// `[]`) | ||
// | ||
// The current implementation defines `versioned: boolean` for the | ||
// entire API response, however in the future we may shift this to the | ||
// API response and it may vary across the resources returned. | ||
export default function useDataFetch( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this reformatting done by hand or an automated tool? It seems... unnecessary [1]. Looking at this highlighted block as an example, there are only 2 changes - addition of "use client"
and export default
vs export
- but we've changed all 22 lines.
There are examples throughout this PR. The downside is that tracking changes through git blame
(and the GitHub interface into that) becomes much much harder [2]. I'm not sure what the upside is - consistency?
[1] also unnecessary to spend time switching it back I guess
[2] Although a preceeding commit (365f622) added this file without any history (i.e. a duplication of an existing file, not a rename), so git blame
isn't going to be useful in any case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the intention is consistency. Some of the reformatting is by hand; some of it is semi-automated via prettier and similar tooling.
I'm treating all of the new App Router files (so, things under /static-site/app
and /static-site/components
) as effectively completely new files, and trying to have them all be consistent with each other in terms of layout and style, as well as consistent with "standard" Next.js layout and approach.
The last big chunk of work I did, I did not include the "starting" version of the file, and there were complaints about breaking the history. This time, when I had things where I had to make a copy (because the existing version of the file needs to keep working to support as-yet un-ported Page Router-based pages), I included an initial commit that contains the "starting" version of the file, without any changes, as that felt like the best way to indicate what had happened.
It is very unclear to me what approach would satisfy everybody — I somewhat suspect there isn't one. If people have concrete suggestions on better ways to do things, I'm happy to hear them; feedback that amounts to "I don't like this" without a suggestion of what would be better is not helpful to me.
Overall, enough of the specifics and the finer details of implementation have changed and been cleaned up as part of this port, that it seems highly unlikely to me that anybody would ever end up walking the history back into the Pages Router version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't care to weigh in here on how to do this conversion more broadly, but I do want to point out that here (and generally) the change of comment style from
-/**
- * Uses the provided callback to fetch resources and parse those
+// Uses the provided callback to fetch resources and parse those
turns what was a JSDoc comment into a non-JSDoc comment.
Now, we're not currently doing anything with those JSDoc comments beyond reading them with our own eyes (although maybe some your IDEs are automatically?), but the convention in this code base has been to write JSDoc comments for modules, functions, classes, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't care to weigh in here on how to do this conversion more broadly, but I do want to point out that here (and generally) the change of comment style from
-/** - * Uses the provided callback to fetch resources and parse those +// Uses the provided callback to fetch resources and parse thoseturns what was a JSDoc comment into a non-JSDoc comment.
They didn't read as JSDoc comments to me, because they don't have any actual JSDoc-style annotations, like @constructor or @param; they just looked like C++-style block comments in front of some (not all) of the functions. (I do see JSDoc comments with annotations in other parts of the repo, but I've kinda being viewing the static-site/
directory and its contents as a distinct thing from the rest of the codebase.
Now, we're not currently doing anything with those JSDoc comments beyond reading them with our own eyes (although maybe some your IDEs are automatically?), but the convention in this code base has been to write JSDoc comments for modules, functions, classes, etc.
I guess my question there is, is there still a use for JSDoc-style commentary in a Typescript codebase? I think of JSDoc as an attempt to layer type hints onto plain old JS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@victorlin do you think we should be adding
@param x ...
to function docs if the param is itself typed with a description in the underlying type?
Not Victor, but noting: none of the @param
annotations I added are to document the parameter types; they all add explanatory commentary about what the parameter is for, or means. In some cases, this involves describing the type (sometimes, you have to call a boolean a boolean), but that's not the main thrust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none of the @param annotations I added are to document the parameter types
Yeah, I get that, I'm talking about the duplication of the description between the one found within the type definition and the one found in the JSDoc of the calling function. This is not blocking, just a question. We should, however, change the comment style back to JSDoc within the type defs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none of the @param annotations I added are to document the parameter types
Yeah, I get that, I'm talking about the duplication of the description between the one found within the type definition and the one found in the JSDoc of the calling function.
Ah, yeah. I will note that -- broadly and generally speaking -- the various bits of Typescript-specific stuff that have been added (custom types, interfaces, etc.) are not documented at all, beyond the inherent documentation of how things are named.
This is not blocking, just a question. We should, however, change the comment style back to JSDoc within the type defs.
yep, that's been done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… the
function ListResources(props: ListResourcesProps)
doesn't give us any of these niceties because it doesn't destructureprops
in the signature.
I'm struggling to understand. Isn't everything tucked away in props
because the individual properties are not relevant in the component directly? Even if there was a reference to something like props.defaultGroupLinks
, the info-on-hover would be available:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@victorlin do you think we should be adding
@param x ...
to function docs if the param is itself typed with a description in the underlying type?
We can avoid @param
lines entirely for TypeScript functions in favor of JSDoc descriptions on the original property definitions, even if it's inline within the function signature (example in Auspice). Right now there is some duplication and inconsistency:
nextstrain.org/static-site/components/list-resources/index.tsx
Lines 131 to 136 in 279f3b4
* @param versioned - boolean for whether the resources are versioned | |
* @param elWidth - width of the element | |
* @param quickLinks - list of `QuickLink` objects for the resources | |
* @param defaultGroupLinks - boolean for if the group name is a url | |
* @param groupDisplayNames - apping from group name -> display name | |
* @param tileData - the tiles for the resources |
nextstrain.org/static-site/components/list-resources/index.tsx
Lines 45 to 62 in 279f3b4
interface ListResourcesProps { | |
versioned: boolean; | |
quickLinks: QuickLink[]; | |
/** | |
* Should the group name itself be a url? (which we let the server | |
* redirect) | |
*/ | |
defaultGroupLinks: boolean; | |
/** Mapping from group name -> display name */ | |
groupDisplayNames: Record<string, string>; | |
tileData: FilterTile[]; | |
/** this is currently unused */ | |
resourceType: string; | |
} |
I would address with something like e3563b0
042d526
to
da860b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left small nits and comments, but overall the ported /pathogens page works for me.
static-site/components/list-resources/group-and-resource-links.module.css
Show resolved
Hide resolved
static-site/components/list-resources/group-and-resource-links.module.css
Outdated
Show resolved
Hide resolved
da860b4
to
e2a9855
Compare
* add `use client` because of use of `useState` * rename `Tile` type to `GenericTileBase`; rename `AnyTile` to `Tile` * converted styled components to CSS module * swap various prop-driven styled components bits to dynamic inline styles
* move `div.errorContainer` into global CSS file because it is used in multiple places
* segregate types and functions * update formatting
* adjust leading/trailing whitespace
e2a9855
to
d6f0962
Compare
d6f0962
to
4cfe238
Compare
4cfe238
to
feb55a3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skimmed over force-push changes and did another review in the test-app.
Overall changes look good, I only flagged minor text formatting and styling issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally (dev mode) and things work well, but didn't inspect the styles as in depth as Jover did.
* move styling from styled components to CSS module * refactor <ResourceModal> to `useContext` and `useCallback` to build `dismissModal()` function, rather than passing it in — this was necessary because all props of React Client Components need to be serializable (i.e., not functions), and <ResourceModal> needs to "use client" because it depends on `useState` and `useEffect` * refactor the `_draw` function out into a distinct file (`modal_draw.js`) to reflect the lack of typing in that code (I briefly explored converting that file to Typescript and concluded the juice was not worth the squeeze) * note that this also means we don't need to add @types/d3 to devDependencies
* export component as a function * convert to Typescript; light reformatting
* Refactor <Name>, <ResourceLinkWrapper>, and <ResourceLink> into <IndividualResourceLink>, and migrate into distinct file; in the future, <GroupLink> will also be refactored into that file, which is reflected in the `group-and-resource-links` file name * Refactor <IconContainer> into distinct file, rework to avoid need to pass non-serializable prop * Refactor <IndividualResource> and associated components from Styled to CSS Module * Refactor <IndividualResource> component to be passed `gapWidth` prop, which supports cleaner separation of concerns with where that constant is defined and used * Refactor <TooltipWrapper> into a distinct file, because it doesn't need to be a React Client component
* Refactored styles from structured component to CSS Module * Refactored <GroupLink> and <IndividualQuickLink> components out into `group-and-resource-links.tsx` * Refactored <ResourceGroup> and contained components
* convert `export const`` to `export default function` * add "use client" * refactor and update code
* convert to React Client Component * refactor code lightly
* convert from styled comp to css module * convert const fat-arrows to functions * update imports, etc.
This moves the resource listing callback into a distinct file; this is because Next.js Pages are limited in the types of methods that can be exported from them. The resource listing code was moved into a distinct method, which is imported by the `<ListResources>` component, so that this page file can remain a React Server Component, which allows for the Metadata API to be used to generate content in the page `<head>` during SSR, prior to hydration.
feb55a3
to
3a75a9a
Compare
Description of proposed changes
Preview
Converts /pathogens and components used on that page to App Router style.
Converted components:
Note that all of these were done in two stages: first a move or copy of the old Pages Router style code to the new App Router location — which sometimes, inevitably, leaves the code in a broken state — and then a subsequent commit to convert to the App Router style/code layout.
Please see individual commits for extra details around some porting decisions.
Related issue(s)
Closes #1066
Checklist