Skip to content

feat(website): resistance mutation sets as collections#1181

Open
fhennig wants to merge 17 commits into
mainfrom
resistance-collections
Open

feat(website): resistance mutation sets as collections#1181
fhennig wants to merge 17 commits into
mainfrom
resistance-collections

Conversation

@fhennig
Copy link
Copy Markdown
Contributor

@fhennig fhennig commented Apr 28, 2026

Summary

  • Resistance mutation sets are now sourced from backend collections (IDs 1/2/3) rather than hard-coded arrays in TypeScript
  • Collections are fetched server-side in Wasap.astro (SSR) and passed as a prop to WasapPage, so no client-side fetch or loading state is needed for resistance data
  • The config is resolved server-side in Wasap.astro, picking prod vs staging collection IDs — staging overrides live in wastewaterOrganismStagingConfigs
  • resistanceData.ts contains the plain async fetch logic; useResistanceMutationSets hook deleted
  • Prod collections visible at: https://genspectrum.org/api/collections - I already created them so we don't break prod!

Screenshot

n/a

PR Checklist

  • All necessary documentation has been adapted.
  • The implemented feature is covered by an appropriate test.

fhennig and others added 2 commits April 28, 2026 15:58
Creates three COVID collections (3CLpro, RdRp, Spike mAb) from the
resistance mutation sets defined in resistanceMutations.ts, each with
one filterObject variant per individual mutation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dashboards Ready Ready Preview, Comment Apr 30, 2026 11:29am

Request Review

@fhennig fhennig changed the title feat(backend): add script to seed resistance mutation collections resistance mutation sets as collections Apr 29, 2026
@fhennig fhennig self-assigned this Apr 29, 2026
fhennig and others added 2 commits April 29, 2026 09:13
…cript

When SESSION_TOKEN is set, the script hits the website proxy at /api/collections
(which injects the user ID from the session) and passes the auth cookie.
Automatically uses the __Secure- cookie prefix for HTTPS targets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of hard-coding mutation lists in the codebase, fetch them at
runtime from the backend collections API (one collection per set:
3CLpro, RdRp, Spike). The seed script now uses mature protein names
(offset-adjusted) as variant names, so the name calculation is no
longer needed in client code. Offset and matureName are removed from
the frontend entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
useResistanceMutationSets now returns ResistanceData directly
(mutationAnnotations + displayMutationsBySet), removing the intermediate
ResistanceMutationSet type and resistanceMutations.ts entirely.
The selector/filter chain now takes plain string[] for set names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The example data seeder on feat/example-data-seeder handles this now.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…errides

Add wastewaterOrganismStagingConfigs with staging resistance collection IDs
(1/2/3 for 3CLpro/RdRp/Spike). Wasap.astro now selects prod vs staging config
and passes it directly to WasapPage, removing the env dependency from React.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tance collections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
IDs confirmed at https://genspectrum.org/api/collections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…2, 3)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@fhennig fhennig changed the title resistance mutation sets as collections feat(website): resistance mutation sets as collections Apr 29, 2026
Moves resistance collection fetching from a React Query hook to the Astro
SSR layer, so data is available before the page reaches the browser.
WasapPage now receives resistanceData as a prop instead of fetching it
client-side. Removes useResistanceMutationSets hook; logic lives in
resistanceData.ts as a plain async function.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@fhennig fhennig force-pushed the resistance-collections branch from 5ca6a5d to 2b50741 Compare April 29, 2026 12:25
@fhennig fhennig marked this pull request as ready for review April 29, 2026 12:25
@fhennig
Copy link
Copy Markdown
Contributor Author

fhennig commented Apr 29, 2026

Hey Fabian, the resistance stuff is fetched in the astro frontmatter, I think that's better because it's a simple Docker internal call. But I had it before with a React hook, the change is all in this commit: 2b50741 - Both approaches have pros and cons I'd say, we can also revert this commit if the hook approach is better.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Moves W-ASAP resistance mutation sets from hard-coded TypeScript arrays to backend collections, fetching them server-side in Wasap.astro and passing the resolved config + resistance data into the React page to avoid client-side loading.

Changes:

  • Replace resistanceMutationSets with resistanceMutationCollections (collection IDs + metadata) across config/types/tests.
  • Add server-side resistance collection fetching/building (resistanceData.ts) and plumb it through Wasap.astroWasapPage.
  • Remove the old hard-coded resistance mutations module and update the resistance filter UI to use set names derived from fetched data.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
website/src/views/pageStateHandlers/WasapPageStateHandler.spec.ts Updates test config to use resistanceMutationCollections.
website/src/types/wastewaterConfig.ts Switches COVID resistance config to collection-based IDs; adds staging config override export.
website/src/types/wastewaterConfig.spec.ts Adjusts config validation test to new property name.
website/src/components/views/wasap/wasapPageConfig.ts Updates WasapPageConfig to use ResistanceMutationCollectionConfig.
website/src/components/views/wasap/useWasapPageData.ts Threads displayMutationsBySet into the query path for resistance mode.
website/src/components/views/wasap/resistanceMutations.ts Deletes hard-coded resistance mutation sets + conversion helper.
website/src/components/views/wasap/resistanceData.ts Adds SSR fetch + transformation from collections to mutation annotations + display mutations.
website/src/components/views/wasap/WasapPage.tsx Accepts SSR-provided config + resistanceData, wiring them into gs-app + filters.
website/src/components/views/wasap/Wasap.astro Resolves prod vs staging config and fetches resistance collections server-side.
website/src/components/pageStateSelectors/wasap/filters/ResistanceMutationsFilter.tsx Switches selector inputs from full sets to set-name list.
website/src/components/pageStateSelectors/wasap/filters/ResistanceMutationsFilter.browser.spec.tsx Updates browser test to pass set names instead of mutation sets.
website/src/components/pageStateSelectors/wasap/WasapPageStateSelector.tsx Wires resistanceSetNames through to the resistance filter.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread website/src/components/views/wasap/useWasapPageData.ts Outdated
Comment thread website/src/components/views/wasap/useWasapPageData.ts
Comment thread website/src/components/views/wasap/Wasap.astro Outdated
Comment thread website/src/types/wastewaterConfig.ts
@fhennig fhennig requested a review from chaoran-chen April 30, 2026 11:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment on lines 73 to 80
<WasapPageStateSelector
config={config}
pageStateHandler={pageStateHandler}
initialBaseFilterState={base}
initialAnalysisFilterState={analysis}
setPageState={setPageState}
resistanceSetNames={Object.keys(displayMutationsBySet)}
/>
Comment on lines +25 to +28
} catch (error) {
getInstanceLogger('WasapPage').error(
`Failed to fetch resistance data for WASAP page (organism: ${wastewaterOrganism}): ${error}`,
);
Comment on lines +185 to +195
function withResistanceCollectionOverrides(config: WasapPageConfig): WasapPageConfig {
if (!config.resistanceAnalysisModeEnabled) return config;
// eslint-disable-next-line @typescript-eslint/naming-convention
const stagingIds: Record<string, number> = { '3CLpro': 1, 'RdRp': 2, 'Spike': 3 };
return {
...config,
resistanceMutationCollections: config.resistanceMutationCollections.map((set) => ({
...set,
collectionId: stagingIds[set.name] ?? set.collectionId,
})),
};
type: 'mutations',
displayMutations:
config.resistanceMutationSets.find((set) => set.name === analysis.resistanceSet)?.mutations ?? [],
displayMutations: displayMutationsBySet[analysis.resistanceSet ?? ''] ?? [],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can analysis.resistanceSet ever be undefined?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's maybe add a simple unit test to test the mapping here?

Comment on lines 14 to +25
type Props = {
wastewaterOrganism: WastewaterOrganismName;
};

const { wastewaterOrganism } = Astro.props;
const { name } = wastewaterOrganismConfigs[wastewaterOrganism];
const config = (isStaging() ? wastewaterOrganismStagingConfigs : wastewaterOrganismConfigs)[wastewaterOrganism];
const backendService = new BackendService(getBackendHost());
let resistanceData: ResistanceData = { mutationAnnotations: [], displayMutationsBySet: {} };

try {
resistanceData = await fetchResistanceData(config, backendService);
} catch (error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI: If fetchResistanceData fails, the page renders with empty resistance data — the resistance mode dropdown will show zero options, but the user can still select the "resistance" tab and see an empty dropdown. Should we show some kind of user-facing warning in this case, or hide the resistance mode tab entirely when the data is unavailable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants