Skip to content

Commit

Permalink
feat(website): add option to search by clade/subtype on sequencing ef…
Browse files Browse the repository at this point in the history
…forts page (#423)
  • Loading branch information
anna-parker authored Dec 18, 2024
1 parent c490b9f commit 424c784
Show file tree
Hide file tree
Showing 21 changed files with 161 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useMemo, useState } from 'react';
import { ApplyFilterButton } from './ApplyFilterButton.tsx';
import { BaselineSelector, type DateRangeFilterConfig, type LocationFilterConfig } from './BaselineSelector.tsx';
import { SelectorHeadline } from './SelectorHeadline.tsx';
import { toVariantFilter, type VariantFilterConfig } from './VariantFilterConfig.ts';
import { VariantSelector } from './VariantSelector.tsx';
import type { OrganismsConfig } from '../../config.ts';
import type { LapisLocation } from '../../views/helpers.ts';
import { type OrganismViewKey, Routing } from '../../views/routing.ts';
Expand All @@ -12,15 +14,18 @@ import type { sequencingEffortsViewKey } from '../../views/viewKeys.ts';
export function SequencingEffortsPageStateSelector({
locationFilterConfig,
dateRangeFilterConfig,
variantFilterConfig,
organismViewKey,
organismsConfig,
}: {
locationFilterConfig: LocationFilterConfig;
dateRangeFilterConfig: DateRangeFilterConfig;
variantFilterConfig: VariantFilterConfig;
organismViewKey: OrganismViewKey & `${string}.${typeof sequencingEffortsViewKey}`;
organismsConfig: OrganismsConfig;
}) {
const [location, setLocation] = useState<LapisLocation>(locationFilterConfig.initialLocation);
const [variantFilterConfigState, setVariantFilterConfigState] = useState<VariantFilterConfig>(variantFilterConfig);
const [dateRange, setDateRange] = useState<DateRangeOption>(dateRangeFilterConfig.initialDateRange);
const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey);

Expand All @@ -30,8 +35,9 @@ export function SequencingEffortsPageStateSelector({
location,
dateRange,
},
variantFilter: toVariantFilter(variantFilterConfigState),
}),
[location, dateRange],
[location, dateRange, variantFilterConfigState],
);

return (
Expand All @@ -45,6 +51,13 @@ export function SequencingEffortsPageStateSelector({
dateRangeFilterConfig={dateRangeFilterConfig}
/>
</div>
<div>
<VariantSelector
onVariantFilterChange={setVariantFilterConfigState}
variantFilterConfig={variantFilterConfigState}
hideMutationFilter={true}
/>
</div>
<ApplyFilterButton pageStateHandler={view.pageStateHandler} newPageState={newPageState} />
</div>
);
Expand Down
30 changes: 17 additions & 13 deletions website/src/components/pageStateSelectors/VariantSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { GsMutationFilter } from '../genspectrum/GsMutationFilter.tsx';
export function VariantSelector({
onVariantFilterChange,
variantFilterConfig,
hideMutationFilter,
}: {
variantFilterConfig: VariantFilterConfig;
onVariantFilterChange: (variantFilter: VariantFilterConfig) => void;
hideMutationFilter?: boolean | undefined;
}) {
return (
<div className='flex flex-col gap-2'>
Expand All @@ -29,19 +31,21 @@ export function VariantSelector({
key={lineageFilterConfig.lapisField}
/>
))}
<GsMutationFilter
initialValue={getMutationFilter(variantFilterConfig.mutationFilterConfig)}
onMutationChange={(mutation) => {
if (mutation === undefined) {
return;
}
const newVariantFilterConfig = {
...variantFilterConfig,
mutationFilterConfig: mutation,
};
onVariantFilterChange(newVariantFilterConfig);
}}
/>
{!hideMutationFilter && (
<GsMutationFilter
initialValue={getMutationFilter(variantFilterConfig.mutationFilterConfig)}
onMutationChange={(mutation) => {
if (mutation === undefined) {
return;
}
const newVariantFilterConfig = {
...variantFilterConfig,
mutationFilterConfig: mutation,
};
onVariantFilterChange(newVariantFilterConfig);
}}
/>
)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useMemo, useState } from 'react';
import { z } from 'zod';

import type { OrganismsConfig } from '../../../config.ts';
import { type CovidAnalyzeSingleVariantData } from '../../../views/covid.ts';
import { type CovidVariantData } from '../../../views/covid.ts';
import { Routing } from '../../../views/routing.ts';
import { withQueryProvider } from '../../subscriptions/backendApi/withQueryProvider.tsx';

Expand Down Expand Up @@ -104,7 +104,7 @@ function CollectionVariantList({ collection, organismsConfig }: CollectionVarian
const currentPageState = routing
.getOrganismView('covid.singleVariantView')
.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href));
let newPageState: CovidAnalyzeSingleVariantData;
let newPageState: CovidVariantData;
const query = querySchema.parse(JSON.parse(variant.query));
if (query.variantQuery !== undefined) {
newPageState = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import { CompareSideBySideSelectorFallback } from '../../pageStateSelectors/Fall
type OrganismViewCompareVariant = OrganismWithViewKey<typeof compareSideBySideViewKey>;
interface Props {
organism: OrganismViewCompareVariant;
hideMutationFilter?: boolean;
}
const { organism } = Astro.props;
const { organism, hideMutationFilter } = Astro.props;
const organismViewKey = `${organism}.${compareSideBySideViewKey}` satisfies OrganismViewKey;
const view = ServerSide.routing.getOrganismView(organismViewKey);
Expand Down Expand Up @@ -97,8 +98,12 @@ const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url);
lapisDateField={view.organismConstants.mainDateField}
granularity={timeGranularity}
/>
<GsMutations lapisFilter={numeratorFilter} sequenceType='nucleotide' />
<GsMutations lapisFilter={numeratorFilter} sequenceType='amino acid' />
{!hideMutationFilter && (
<>
<GsMutations lapisFilter={numeratorFilter} sequenceType='nucleotide' />
<GsMutations lapisFilter={numeratorFilter} sequenceType='amino acid' />
</>
)}
<GsAggregate
title='Sub-lineages'
fields={getLineageFilterFields(view.organismConstants.lineageFilters)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getDashboardsConfig } from '../../../config';
import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro';
import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange';
import { ComponentHeight } from '../../../views/OrganismConstants';
import { getLineageFilterConfigs, getLineageFilterFields } from '../../../views/View';
import { getLocationDisplayConfig } from '../../../views/locationHelpers';
import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing';
import { ServerSide } from '../../../views/serverSideRouting';
Expand All @@ -22,10 +23,10 @@ interface Props {
const { organism } = Astro.props;
const organismViewKey: OrganismViewKey = `${organism}.${sequencingEffortsViewKey}` satisfies OrganismViewKey;
const view = ServerSide.routing.getOrganismView(organismViewKey);
const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url);
const datasetLapisFilter = view.pageStateHandler.toLapisFilter(pageState);
const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url);
const variantLapisFilter = view.pageStateHandler.toLapisFilter(pageState);
const timeGranularity = chooseGranularityBasedOnDateRange(
pageState.datasetFilter.dateRange,
new Date(view.organismConstants.earliestDate),
Expand All @@ -35,6 +36,10 @@ const {
locationField,
mapName,
} = getLocationDisplayConfig(view.organismConstants.locationFields, pageState.datasetFilter.location);
const lineageFilterConfigs = getLineageFilterConfigs(
view.organismConstants.lineageFilters,
pageState.variantFilter.lineages,
);
---

<SingleVariantOrganismPageLayout view={view}>
Expand All @@ -54,6 +59,7 @@ const {
organismViewKey={organismViewKey}
organismsConfig={getDashboardsConfig().dashboards.organisms}
client:only='react'
variantFilterConfig={{ mutationFilterConfig: pageState.variantFilter.mutations, lineageFilterConfigs }}
>
<SequencingEffortsSelectorFallback slot='fallback' />
</SequencingEffortsPageStateSelector>
Expand All @@ -63,7 +69,7 @@ const {
lapisFilters={[
{
displayName: '',
lapisFilter: datasetLapisFilter,
lapisFilter: variantLapisFilter,
},
]}
lapisDateField={view.organismConstants.mainDateField}
Expand All @@ -75,7 +81,7 @@ const {
title={locationLabel}
height={ComponentHeight.large}
lapisLocationField={locationField}
lapisFilter={datasetLapisFilter}
lapisFilter={variantLapisFilter}
mapName={mapName}
/>
)
Expand All @@ -84,11 +90,16 @@ const {
title='Hosts'
height={ComponentHeight.large}
fields={[view.organismConstants.hostField]}
lapisFilter={datasetLapisFilter}
lapisFilter={variantLapisFilter}
/>
<GsAggregate
title='Sub-lineages'
fields={getLineageFilterFields(view.organismConstants.lineageFilters)}
lapisFilter={variantLapisFilter}
/>
{
view.organismConstants.additionalSequencingEffortsFields.map(({ label, fields, height }) => (
<GsAggregate title={label} height={height} fields={fields} lapisFilter={datasetLapisFilter} />
<GsAggregate title={label} height={height} fields={fields} lapisFilter={variantLapisFilter} />
))
}
</ComponentsGrid>
Expand Down
18 changes: 11 additions & 7 deletions website/src/views/BaseView.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { OrganismConstants, SequencingEffortsConstants, SingleVariantConstants } from './OrganismConstants.ts';
import type { CompareToBaselineData, CompareVariantsData, Dataset, DatasetAndVariantData, View } from './View.ts';
import type { OrganismConstants, ExtendedConstants } from './OrganismConstants.ts';
import type { CompareToBaselineData, CompareVariantsData, DatasetAndVariantData, View } from './View.ts';
import {
compareToBaselineViewConstants,
compareVariantsViewConstants,
Expand Down Expand Up @@ -40,7 +40,7 @@ export abstract class BaseView<
}
}

export class GenericSingleVariantView<Constants extends SingleVariantConstants> extends BaseView<
export class GenericSingleVariantView<Constants extends ExtendedConstants> extends BaseView<
DatasetAndVariantData,
Constants,
SingleVariantPageStateHandler
Expand All @@ -67,8 +67,8 @@ export class GenericSingleVariantView<Constants extends SingleVariantConstants>
}
}

export class GenericSequencingEffortsView<Constants extends SequencingEffortsConstants> extends BaseView<
Dataset,
export class GenericSequencingEffortsView<Constants extends ExtendedConstants> extends BaseView<
DatasetAndVariantData,
Constants,
SequencingEffortsStateHandler
> {
Expand All @@ -82,6 +82,10 @@ export class GenericSequencingEffortsView<Constants extends SequencingEffortsCon
location: {},
dateRange: constants.defaultDateRange,
},
variantFilter: {
mutations: {},
lineages: {},
},
},
organismConfig[constants.organism].pathFragment,
),
Expand All @@ -90,7 +94,7 @@ export class GenericSequencingEffortsView<Constants extends SequencingEffortsCon
}
}

export class GenericCompareVariantsView<Constants extends SingleVariantConstants> extends BaseView<
export class GenericCompareVariantsView<Constants extends ExtendedConstants> extends BaseView<
CompareVariantsData,
Constants,
CompareVariantsPageStateHandler
Expand All @@ -114,7 +118,7 @@ export class GenericCompareVariantsView<Constants extends SingleVariantConstants
}
}

export class GenericCompareToBaselineView<Constants extends SingleVariantConstants> extends BaseView<
export class GenericCompareToBaselineView<Constants extends ExtendedConstants> extends BaseView<
CompareToBaselineData,
Constants,
CompareToBaselineStateHandler
Expand Down
5 changes: 1 addition & 4 deletions website/src/views/OrganismConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@ export interface AdditionalSequencingEffortsField {
readonly height: (typeof ComponentHeight)[keyof typeof ComponentHeight];
}

export interface SequencingEffortsConstants extends OrganismConstants {
export interface ExtendedConstants extends OrganismConstants {
readonly locationFields: string[];
readonly mainDateField: string;
readonly dateRangeOptions: DateRangeOption[];
readonly defaultDateRange: DateRangeOption;
readonly additionalFilters: Record<string, string> | undefined;
readonly additionalSequencingEffortsFields: AdditionalSequencingEffortsField[];
}

export interface SingleVariantConstants extends SequencingEffortsConstants {
readonly lineageFilters: LineageFilterConfig[];
}

Expand Down
Loading

0 comments on commit 424c784

Please sign in to comment.