Skip to content

Conversation

MatthewBemis
Copy link
Member

@MatthewBemis MatthewBemis commented May 16, 2025

Jira Ticket: https://broadworkbench.atlassian.net/browse/TSPS-156

Adds views and custom branding within Terra UI to interact with the Imputation Service.

NOTE: These changes have almost all been reviewed in individual PRs, with the exception of the last 3 commits which were just small fixes for lint rules and configs.

Summary of changes:

What

  • UI for Imputation Service, allowing users to run imputation jobs, view the status of their jobs, and download the outputs
  • New custom branding for Scientific Services, with a couple of extensions to hide certain components in the sidebar and footer. This is triggered by going to services.terra.bio (subdomain not yet provisioned)
screencapture-localhost-3000-2025-08-15-14_58_05 screencapture-localhost-3000-2025-08-15-14_58_18 screencapture-localhost-3000-2025-08-15-14_58_28 screencapture-localhost-3000-2025-08-15-14_58_38

Why

Testing strategy

Copilot

This comment was marked as outdated.

@DataBiosphere DataBiosphere deleted a comment from Copilot AI Jun 10, 2025
@DataBiosphere DataBiosphere deleted a comment from Copilot AI Jun 10, 2025
@DataBiosphere DataBiosphere deleted a comment from Copilot AI Jun 10, 2025
@MatthewBemis MatthewBemis changed the title [TSPS-156] Imputation UI feature branch [WIP - do not merge] [TSPS-156] Imputation UI feature branch [WIP] Jun 12, 2025
Copy link

@MatthewBemis MatthewBemis changed the title [TSPS-156] Imputation UI feature branch [WIP] [TSPS-156] Imputation UI feature branch Aug 15, 2025
@MatthewBemis MatthewBemis changed the title [TSPS-156] Imputation UI feature branch [TSPS-156] Imputation Service UI [feature branch] Aug 15, 2025
@MatthewBemis MatthewBemis marked this pull request as ready for review August 15, 2025 20:07
Copy link
Contributor

@mmorgantaylor mmorgantaylor left a comment

Choose a reason for hiding this comment

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

this is great - just have a few questions that came up as I clicked around

</div>
<ButtonPrimary
style={{ marginTop: '1.5rem' }}
href='https://allofus-anvil-imputation.terra.bio/'
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect we ultimately want this to link to documentation, but it's not public yet. What do you think about linking to pypi https://pypi.org/project/terralab-cli/ instead of the marketing page until the documentation is public?

Copy link
Member Author

Choose a reason for hiding this comment

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

great idea, done in c73dfa7


<h2 style={{ marginTop: '2rem' }}>User Documentation</h2>
<div style={{ marginTop: '1rem' }}>
<a href='services/pipelines' style={{ color: '#46A3E9', textDecoration: 'underline', fontWeight: 'bold' }}>
Copy link
Contributor

Choose a reason for hiding this comment

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

this is currently a dead page (same link in row 58)

Copy link
Member Author

Choose a reason for hiding this comment

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

good catch, just updated these to be real paths. eventually we'll link out to documentation here once that's public


export const navPaths = [
{
name: 'pipelines-about',
path: '/pipelines/imputation',
Copy link
Contributor

Choose a reason for hiding this comment

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

it's a little confusing that '/pipelines' is not a page. could that redirect to '/pipelines/imputation' for now?

Copy link
Member Author

Choose a reason for hiding this comment

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

good call! added this route in c73dfa7

// If a pipeline doesn't have any tips, this widget won't be rendered at all.
// This supports ReactNodes in case you want to include links or other non-string elements in the tips.
array_imputation: [
{ id: 'vcf-valid', content: 'Ensure that your file is a valid vcf file' },
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{ id: 'vcf-valid', content: 'Ensure that your file is a valid vcf file' },
{ id: 'vcf-valid', content: 'Ensure that your file is a valid VCF file containing array data (fewer than 10 million sites)' },

{ id: 'vcf-valid', content: 'Ensure that your file is a valid vcf file' },
{ id: 'grch38', content: 'VCFs must be generated from GRCh38/hg38' },
{ id: 'quota-check', content: 'Ensure your multi-sample file contains no more than your remaining quota.' },
{ id: 'format-guidelines', content: 'More guidelines for data formatting' },
Copy link
Contributor

Choose a reason for hiding this comment

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

is this supposed to link to documentation?

Copy link
Member Author

Choose a reason for hiding this comment

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

eventually! for context, these are all just placeholder tips from Lou's mocks. there's a ticket in the backlog to make these tips more useful https://broadworkbench.atlassian.net/browse/TSPS-525

Mind if I fold your suggested changes here into that ticket?

Copy link
Contributor

Choose a reason for hiding this comment

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

sure, it makes sense to add to that ticket, thanks!

array_imputation: [
{ id: 'vcf-valid', content: 'Ensure that your file is a valid vcf file' },
{ id: 'grch38', content: 'VCFs must be generated from GRCh38/hg38' },
{ id: 'quota-check', content: 'Ensure your multi-sample file contains no more than your remaining quota.' },
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{ id: 'quota-check', content: 'Ensure your multi-sample file contains no more than your remaining quota.' },
{ id: 'quota-check', content: 'Ensure your multi-sample file contains no more samples than your remaining quota.' },

// Add tips for new pipelines here, and they'll automatically be displayed.
// If a pipeline doesn't have any tips, this widget won't be rendered at all.
// This supports ReactNodes in case you want to include links or other non-string elements in the tips.
array_imputation: [
Copy link
Contributor

@mmorgantaylor mmorgantaylor Aug 18, 2025

Choose a reason for hiding this comment

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

can we add a tip that's like
{ id: 'all-chr', content: 'Your VCF should include data for all autosomes (chr1-chr22). Sex chromosomes are not processed.' },

<div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem' }}>
<h3>Job History</h3>
<div style={{ marginBottom: '0.25rem' }}>
All files associated with jobs will be automatically deleted after 2 weeks from completion.
Copy link
Contributor

Choose a reason for hiding this comment

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

can we also (here or elsewhere) note that this includes error information? i.e. jobs older than 2 weeks won't display an error message. feel free to put this in a new ticket.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@mmorgantaylor mmorgantaylor left a comment

Choose a reason for hiding this comment

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

thank you!! so exciting!

Copy link

@Copilot 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

This PR implements a comprehensive UI for the Imputation Service within Terra, adding views and custom branding for Scientific Services. The imputation service allows users to run imputation jobs, monitor their status, and download outputs through a new Scientific Services interface.

Key changes include:

  • Complete UI implementation for the Imputation Service with job submission, history, and output management
  • New Scientific Services branding with custom styling, logos, and compact navigation
  • Feature preview gate system for controlled access to the imputation UI

Reviewed Changes

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

Show a summary per file
File Description
src/registration/Register.tsx Conditionally hides Terra-specific registration sections for Scientific Services branding
src/pages/scientificServices/ Complete imputation service UI with job submission, history, modals, and components
src/libs/brands.tsx New Scientific Services brand configuration with custom styling and compact TopBar
src/components/TopBar.tsx Support for compact navigation mode that hides non-essential menu items
src/components/FooterWrapper.js Hide Terra-specific footer links for Scientific Services branding
src/libs/ajax/teaspoons/ Complete API client implementation for Teaspoons service
config/ Teaspoons service URL configuration for dev and prod environments

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

selectedUserInputs: Record<string, any>,
description: string,
pipelineInputs: PipelineInput[],
setUploadProgress: (percentage: Record<string, any>) => void = () => {}
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

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

The parameter name 'percentage' is misleading since the type is Record<string, any> which represents upload progress for multiple files, not a single percentage value. Consider renaming to 'uploadProgress' or 'progressMap' to better reflect its purpose.

Suggested change
setUploadProgress: (percentage: Record<string, any>) => void = () => {}
setUploadProgress: (uploadProgress: Record<string, any>) => void = () => {}

Copilot uses AI. Check for mistakes.

setPageNumber(v);
}}
itemsPerPage={itemsPerPage}
setItemsPerPage={(v) => {
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

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

Using @ts-ignore suppresses TypeScript errors without addressing the underlying issue. This should be replaced with proper type definitions or explicit type assertions to maintain type safety.

Suggested change
setItemsPerPage={(v) => {
<Paginator
filteredDataLength={pipelineRunsResponse?.totalResults ?? 0 as number}
unfilteredDataLength={pipelineRunsResponse?.totalResults ?? 0 as number}
pageNumber={pageNumber as number}
setPageNumber={(v: number) => {
setPageNumber(v);
}}
itemsPerPage={itemsPerPage as number}
setItemsPerPage={(v: number) => {

Copilot uses AI. Check for mistakes.

const { inputs } = await Teaspoons(signal).getPipelineDetails(pipelineName, pipelineVersion);
setPipelineInputs(inputs);
setIsLoading(false);
});
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

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

Using map() with async functions creates promises that are not awaited, potentially causing race conditions. The pipeline details are fetched for all pipelines simultaneously but only the last one sets the state. Use Promise.all() or process pipelines sequentially to ensure proper state management.

Suggested change
});
const pipelineDetails = await Promise.all(
response.results.map(async (pipeline) => {
const pipelineName = pipeline.pipelineName;
const pipelineVersion = pipeline.pipelineVersion;
const { inputs } = await Teaspoons(signal).getPipelineDetails(pipelineName, pipelineVersion);
return { pipelineName, pipelineVersion, inputs };
})
);
// If you want to set inputs for all pipelines, you could store them in an object or array.
// For now, set inputs for the first pipeline (or handle as needed).
if (pipelineDetails.length > 0) {
setPipelineInputs(pipelineDetails[0].inputs);
}
setIsLoading(false);

Copilot uses AI. Check for mistakes.

}

export const PipelineStringInput: React.FC<PipelineStringInputProps> = ({ input, value, onChange }) => {
const { label, placeholder, helpText } = INPUT_DESCRIPTIONS[input.name];
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

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

Destructuring INPUT_DESCRIPTIONS[input.name] will throw an error if the input name doesn't exist in the mapping. Add a fallback or optional chaining: INPUT_DESCRIPTIONS[input.name] || {} to prevent runtime errors.

Suggested change
const { label, placeholder, helpText } = INPUT_DESCRIPTIONS[input.name];
const { label, placeholder, helpText } = INPUT_DESCRIPTIONS[input.name] || {};

Copilot uses AI. Check for mistakes.

@MatthewBemis MatthewBemis force-pushed the tsps_imputation_ui_feature_branch branch from d4396ad to 220bfb2 Compare August 19, 2025 15:32
Copy link

@MatthewBemis MatthewBemis added this pull request to the merge queue Aug 19, 2025
Merged via the queue into dev with commit 105dcd2 Aug 19, 2025
11 checks passed
@MatthewBemis MatthewBemis deleted the tsps_imputation_ui_feature_branch branch August 19, 2025 16:34
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.

5 participants