Skip to content

Commit

Permalink
Merge pull request #1322 from nextstrain/feat/web-about
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov authored Nov 27, 2023
2 parents e35362b + bcfbafe commit 1d046f6
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 221 deletions.
7 changes: 0 additions & 7 deletions packages_rs/nextclade-web/src/components/About/About.tsx

This file was deleted.

38 changes: 4 additions & 34 deletions packages_rs/nextclade-web/src/components/About/AboutContent.mdx
Original file line number Diff line number Diff line change
@@ -1,43 +1,13 @@
import { CladeSchema } from 'src/components/Main/CladeSchema.tsx'

## What is Nextclade?

Nextclade is a tool that performs genetic sequence alignment, clade assignment, mutation calling, phylogenetic placement, and quality checks for SARS-CoV-2, Influenza (Flu), Mpox (Monkeypox), Respiratory Syncytial Virus (RSV) and other pathogens.

Nextclade identifies differences between your sequences and a reference sequence, uses these differences to assign your sequences to clades, reports potential sequence quality issues in your data, and shows how the sequences are related to each other by placing them into an existing phylogenetic tree (we call it "phylogenetic placement"). You can use the tool to analyze sequences before you upload them to a database, or if you want to assign Nextstrain clades to a set of sequences.

To analyze your data, drag a fasta file onto the upload box or paste sequences into the text box. These sequences will then be analyzed in your browser - data never leave your computer. Since your computer is doing the work rather than a server, it is advisable to analyze at most a few hundred sequences at a time.

The Nextclade app and algorithms are opensource. The code is available on [GitHub](https://github.com/nextstrain/nextclade). The user manual is available at [docs.nextstrain.org/projects/nextclade](https://docs.nextstrain.org/projects/nextclade).


### What are the SARS-CoV-2 clades?

Nextclade was originally developed during COVID-19 pandemic, primarily focused on SARS-CoV-2. This section describes clades with application to SARS-CoV-2, but Nextclade can analyse other pathogens too.

<CladeSchema />

Since its emergence in late 2019, SARS-CoV-2 has diversified into several different co-circulating variants. To facilitate discussion of these variants, we have grouped them into __clades__ which are defined by specific signature mutations.

We currently define more than 30 clades (see [this blog post](https://nextstrain.org/blog/2021-01-06-updated-SARS-CoV-2-clade-naming) for details):

- 19A and 19B emerged in Wuhan and have dominated the early outbreak
- 20A emerged from 19A out of dominated the European outbreak in March and has since spread globally
- 20B and 20C are large genetically distinct subclades 20A emerged in early 2020
- 20D to 20J have emerged over the summer of 2020 and include three "Variants of Concern" (VoC).
- 21A to 21F include the VoC __delta__ and several Variants of Interest (VoI).
- 21K onwards are different clades within the diverse VoC __omicron__.

Within Nextstrain, we define each clade by its combination of signature mutations. You can find the exact clade definition in [github.com/nextstrain/ncov/defaults/clades.tsv](https://github.com/nextstrain/ncov/blob/master/defaults/clades.tsv). When available, we will include [WHO labels for VoCs and VoIs](https://www.who.int/en/activities/tracking-SARS-CoV-2-variants/).

Learn more about how Nextclade assigns clades in the [documentation](https://docs.nextstrain.org/projects/nextclade/en/stable/user/algorithm/).

### Other pathogens
To analyze your data, drag a [FASTA](https://en.wikipedia.org/wiki/FASTA_format) file onto the upload box. These sequences will then be analyzed locally, in your browser. Your data never leaves your computer. Since your computer is doing the work rather than a server, it is advisable to analyze at most a few hundred sequences at a time.

Besides SARS-CoV-2, we provide Nextclade datasets to analyze the following other pathogens:
The Nextclade app and algorithms are open-source. The code is available on [GitHub](https://github.com/nextstrain/nextclade).

* Seasonal Influenza viruses (HA and NA for A/H3N2, A/H1N1pdm, B/Vic, and B/Yam)
* Mpox virus (the overall clade structure, as well as fine-grained lineages within the recent sustained human-to-human transmission)
* Respiratory Syncytial Virus (RSV) (subtypes A and B)
For large-scale analysis you can use a command line version - [Nextclade CLI](https://docs.nextstrain.org/projects/nextclade/en/stable/user/nextclade-cli.html).

You can also put together your own dataset to analyse other pathogens.
Read [user documentation](https://docs.nextstrain.org/projects/nextclade) for more details.
59 changes: 59 additions & 0 deletions packages_rs/nextclade-web/src/components/About/AboutPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react'
import { TeamCredits } from 'src/components/About/TeamCredits'
import styled from 'styled-components'
import { Layout } from 'src/components/Layout/Layout'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'

import AboutContent from './AboutContent.mdx'

export function AboutPage() {
const { t } = useTranslationSafe()

return (
<Layout>
<Container>
<ContentWrapper>
<Main>
<H3>{t('About')}</H3>

<AboutContent />

<TeamCredits />
</Main>
</ContentWrapper>
</Container>
</Layout>
)
}

const Container = styled.div`
margin: 0 auto;
padding: 0.8rem 0;
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
overflow: auto;
`

const ContentWrapper = styled.div`
display: flex;
flex-direction: column;
max-width: ${(props) => props.theme.containerMaxWidths.lg};
margin: 0 auto;
`

const H3 = styled.h3`
display: flex;
flex: 0;
margin: auto;
margin-top: 10px;
margin-bottom: 3px;
`

const Main = styled.main`
display: flex;
flex: 1;
flex-direction: column;
overflow: auto;
`
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
/* eslint-disable sonarjs/no-duplicate-string */
import { shuffle } from 'lodash'
import React, { useMemo } from 'react'

import React, { ReactNode, useMemo } from 'react'
import { Col, Row } from 'reactstrap'
import { Maintainer } from 'src/components/Team/TeamCreditsMaintainer'
import { PROJECT_NAME } from 'src/constants'

import styled from 'styled-components'
import { FaGithub, FaTwitter } from 'react-icons/fa'
import { GiEarthAfricaEurope } from 'react-icons/gi'

import { PROJECT_NAME } from 'src/constants'
import { getContributors } from 'src/io/getContributors'
import { LinkExternal } from 'src/components/Link/LinkExternal'
import type { MaintainerInfo } from 'src/components/Team/TeamCreditsMaintainer'
import { TeamCreditsContributor } from 'src/components/Team/TeamCreditsContributor'
import { TeamCreditsContributor } from 'src/components/About/TeamCreditsContributor'
import NextstrainLogo from 'src/assets/img/nextstrain_logo.svg'
import { FlexCol, FlexContributors, TeamCreditsH1 } from './TeamCreditsStyles'

const maintainers: MaintainerInfo[] = [
{
Expand All @@ -26,7 +21,7 @@ const maintainers: MaintainerInfo[] = [
{
title: 'GitHub',
url: 'https://github.com/ivan-aksamentov',
alt: 'Link to Github page, with grey Github Octocat logo',
alt: 'Link to GitHub page, with grey GitHub Octocat logo',
icon: <FaGithub size={25} color="#24292E" />,
},
],
Expand All @@ -52,7 +47,7 @@ const maintainers: MaintainerInfo[] = [
{
title: 'GitHub',
url: 'https://github.com/rneher',
alt: 'Link to Github page, with grey Github Octocat logo',
alt: 'Link to GitHub page, with grey GitHub Octocat logo',
icon: <FaGithub size={25} color="#24292E" />,
},
],
Expand All @@ -72,7 +67,7 @@ const maintainers: MaintainerInfo[] = [
{
title: 'GitHub',
url: 'https://github.com/corneliusroemer',
alt: 'Link to Github page, with grey Github Octocat logo',
alt: 'Link to GitHub page, with grey GitHub Octocat logo',
icon: <FaGithub size={25} color="#24292E" />,
},
],
Expand Down Expand Up @@ -125,3 +120,134 @@ export function TeamCredits() {
</Row>
)
}

export interface MaintainerInfoLink {
title: string
url: string
alt: string
icon: ReactNode
}

export interface MaintainerInfo {
name: string
portraitUrl: string
title: string
affiliations: string[]
links: MaintainerInfoLink[]
}

export interface MaintainerProps {
maintainer: MaintainerInfo
}

export function Maintainer({ maintainer }: MaintainerProps) {
const { name, portraitUrl, title, affiliations, links } = maintainer
const alt = useMemo(() => `Portrait of '${PROJECT_NAME}' maintainer, ${name}`, [name])
const affiliationComponents = useMemo(
() => affiliations.map((affiliation) => <AffiliationText key={affiliation}>{affiliation}</AffiliationText>),
[affiliations],
)
return (
<Flex>
<Portrait src={portraitUrl} alt={alt} />
<NameText>{name}</NameText>
<AffiliationText>{title}</AffiliationText>
{affiliationComponents}
<Ul>
{links.map(({ title, url, alt, icon }) => (
<Li key={title}>
<LinkExternal title={title} href={url} alt={alt}>
{icon}
</LinkExternal>
</Li>
))}
</Ul>
</Flex>
)
}

export const FlexCol = styled(Col)`
display: flex;
flex-wrap: wrap;
text-align: center;
`

export const Flex = styled.section`
display: flex;
flex-direction: column;
flex: 1 0 300px;
margin: 10px auto;
@media (min-width: 768px) {
&:first-child {
padding-left: 50px;
}
&:last-child {
padding-right: 50px;
}
}
@media (min-width: 992px) {
&:first-child {
padding-left: 70px;
}
&:last-child {
padding-right: 70px;
}
}
@media (min-width: 1201px) {
&:first-child {
padding-left: 120px;
}
&:last-child {
padding-right: 120px;
}
}
`

export const TeamCreditsH1 = styled.h1`
font-size: 1.33rem;
margin: 15px auto;
`

export const Ul = styled.ul`
list-style: none;
padding: 0;
margin-top: 0.5rem;
`

export const Li = styled.li`
display: inline-block;
margin-left: 5px;
margin-right: 5px;
`

export const NameText = styled.h2`
font-size: 1.1rem;
`

export const AffiliationText = styled.small`
font-size: 0.8rem;
`

export const Portrait = styled.img`
margin: 0 auto;
width: 100px;
border-radius: 100px;
`

export const FlexContributors = styled.section`
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-evenly;
width: 100%;
max-width: 1500px;
margin: 10px auto;
`
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Link } from 'src/components/Link/Link'
import { FaDocker, FaGithub, FaXTwitter, FaDiscourse } from 'react-icons/fa6'
import { LinkSmart } from 'src/components/Link/LinkSmart'
import { ResultsStatus } from 'src/components/Results/ResultsStatus'
import { PROJECT_NAME } from 'src/constants'
import { canDownloadAtom, hasRanAtom, hasTreeAtom } from 'src/state/results.state'
import styled, { useTheme } from 'styled-components'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'
Expand Down Expand Up @@ -171,6 +172,11 @@ export function NavigationBar() {
content: t('Settings'),
title: t('Configure Nextclade'),
},
{
url: '/about',
title: t('About {{what}}', { what: PROJECT_NAME }),
content: t('About'),
},
{
title: t('Cite Nextclade in your work'),
content: <CitationButton />,
Expand Down
26 changes: 0 additions & 26 deletions packages_rs/nextclade-web/src/components/Main/MainSectionInfo.tsx

This file was deleted.

21 changes: 18 additions & 3 deletions packages_rs/nextclade-web/src/components/Main/Title.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react'
import { LinkSmart } from 'src/components/Link/LinkSmart'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'

import styled from 'styled-components'

Expand Down Expand Up @@ -48,8 +50,9 @@ const LetterSpan = styled.span<{ pos: number }>`
`

export function Title() {
const { t } = useTranslationSafe()
return (
<span>
<span className="d-inline-flex">
<TitleH1>
{'Nextclade'.split('').map((letter, i) => (
// eslint-disable-next-line react/no-array-index-key
Expand All @@ -58,14 +61,26 @@ export function Title() {
</LetterSpan>
))}
</TitleH1>
{PACKAGE_VERSION && <VersionNumberBadge color="secondary">{`v${PACKAGE_VERSION}`}</VersionNumberBadge>}

<div className="d-flex h-auto flex-row">
<span className="flex-1 d-flex h-auto flex-column mb-2 mt-2">
<span className="mb-auto">{<AboutLink href="/about">{t('What is this?')}</AboutLink>}</span>
<span className="mt-auto">
{PACKAGE_VERSION && <VersionNumberBadge color="secondary">{`v${PACKAGE_VERSION}`}</VersionNumberBadge>}
</span>
</span>
</div>
</span>
)
}

const AboutLink = styled(LinkSmart)`
margin-bottom: auto;
`

export const Subtitle = styled.h2`
text-align: center;
font-size: 2rem;
font-size: 1.5rem;
font-weight: 300;
@media (max-width: 991.98px) {
Expand Down
Loading

1 comment on commit 1d046f6

@vercel
Copy link

@vercel vercel bot commented on 1d046f6 Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nextclade – ./

nextclade-nextstrain.vercel.app
nextclade.vercel.app
nextclade-git-master-nextstrain.vercel.app

Please sign in to comment.