Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,67 @@ import { UcscTrack } from "../../../../../../../../../../../../utils/ucsc-tracks
import { COLUMN_TYPE } from "../../SampleSheetClassificationStep/types";
import { Strandedness } from "../../StrandednessStep/types";

export interface ConfiguredValue {
// Base configured values shared across all scopes
export interface BaseConfiguredValue {
readRunsPaired: EnaSequencingReads[] | null;
readRunsSingle: EnaSequencingReads[] | null;
tracks: UcscTrack[] | null;
}

// ASSEMBLY scope: workflows that operate on a specific genome assembly
export interface AssemblyConfiguredValue extends BaseConfiguredValue {
_scope: "ASSEMBLY";
designFormula: string | null;
geneModelUrl: string | null;
numberOfHits?: number;
primaryContrasts: PrimaryContrasts | null;
readRunsPaired: EnaSequencingReads[] | null;
readRunsSingle: EnaSequencingReads[] | null;
referenceAssembly: string;
sampleSheet: Record<string, string>[] | null;
sampleSheetClassification: Record<string, COLUMN_TYPE | null> | null;
sequence?: string;
strandedness: Strandedness | undefined;
tracks: UcscTrack[] | null;
}

// ORGANISM scope: workflows that operate at organism level (may not require specific assembly)
// Organism scope workflows may have collection_spec (defined in workflow YAML) and variables.
// fastaCollection can be either:
// - User-selected assembly accessions (string[]) for user-defined FASTA collections
// - Auto-configured via collection_spec in workflow YAML (handled by Galaxy API)
export interface OrganismConfiguredValue extends BaseConfiguredValue {
_scope: "ORGANISM";
fastaCollection: string[] | null;
}

// SEQUENCE scope: workflows that operate on user-provided sequences
export interface SequenceConfiguredValue extends BaseConfiguredValue {
_scope: "SEQUENCE";
numberOfHits?: number;
sequence?: string;
}

// Type guards for ConfiguredValue discrimination
export function isAssemblyConfiguredValue(
value: ConfiguredValue
): value is AssemblyConfiguredValue {
return value._scope === "ASSEMBLY";
}

export function isOrganismConfiguredValue(
value: ConfiguredValue
): value is OrganismConfiguredValue {
return value._scope === "ORGANISM";
}

export function isSequenceConfiguredValue(
value: ConfiguredValue
): value is SequenceConfiguredValue {
return value._scope === "SEQUENCE";
}

// Union type for all configured values
export type ConfiguredValue =
| AssemblyConfiguredValue
| OrganismConfiguredValue
| SequenceConfiguredValue;

export interface Status {
disabled: boolean;
error: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,115 @@ import { CUSTOM_WORKFLOW } from "../../../../../../../../../../../../views/Analy
import { DIFFERENTIAL_EXPRESSION_ANALYSIS } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/differentialExpressionAnalysis/constants";
import { LEXICMAP } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/lexicmap/constants";
import { LOGAN_SEARCH } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/loganSearch/constants";
import { Props, UseLaunchGalaxy } from "./types";
import { Workflow } from "../../../../../../../../../../../../apis/catalog/brc-analytics-catalog/common/entities";
import {
ConfiguredValue,
isAssemblyConfiguredValue,
isSequenceConfiguredValue,
Props,
UseLaunchGalaxy,
} from "./types";
import { getConfiguredValues, launchGalaxy } from "./utils";

/**
* Gets the appropriate landing URL based on workflow type.
* @param workflow - Workflow to launch.
* @param configuredValue - Configured values for the workflow.
* @param origin - Origin URL for the Galaxy instance.
* @param run - Async runner function from useAsync hook.
* @returns Promise resolving to the Galaxy workflow landing URL.
*/
async function getLandingUrlForWorkflow(
workflow: Workflow,
configuredValue: ConfiguredValue,
origin: string,
run: (promise: Promise<string>) => Promise<string>
Comment thread
d-callan marked this conversation as resolved.
Outdated
): Promise<string> {
if (workflow.trsId === CUSTOM_WORKFLOW.trsId) {
if (!isAssemblyConfiguredValue(configuredValue)) {
throw new Error("Invalid configured value for CUSTOM workflow");
}
return run(
getDataLandingUrl(
configuredValue.referenceAssembly,
configuredValue.geneModelUrl,
configuredValue.readRunsSingle,
configuredValue.readRunsPaired,
null,
configuredValue.tracks,
origin
)
);
}

if (
workflow.trsId === LOGAN_SEARCH.trsId ||
workflow.trsId === LEXICMAP.trsId
) {
if (!workflow.workflowId) {
throw new Error("Missing workflow ID for LMLS workflow");
}
if (
!isSequenceConfiguredValue(configuredValue) ||
!configuredValue.numberOfHits ||
!configuredValue.sequence
) {
throw new Error("Missing required values for LMLS workflow");
}
return run(
getLMLSLandingUrl(
workflow.workflowId,
configuredValue.numberOfHits,
configuredValue.sequence,
origin
)
);
}

if (workflow.trsId === DIFFERENTIAL_EXPRESSION_ANALYSIS.trsId) {
if (
!workflow.workflowId ||
!isAssemblyConfiguredValue(configuredValue) ||
!configuredValue.geneModelUrl ||
!configuredValue.sampleSheet ||
!configuredValue.sampleSheetClassification ||
!configuredValue.designFormula
) {
throw new Error("Missing required values for DE workflow");
}
return run(
getDeSeq2LandingUrl(
workflow.workflowId,
configuredValue.referenceAssembly,
configuredValue.geneModelUrl,
configuredValue.sampleSheet,
configuredValue.sampleSheetClassification,
configuredValue.designFormula,
configuredValue.primaryContrasts,
configuredValue.strandedness,
origin
)
);
}

return run(
getWorkflowLandingUrl(
workflow.trsId,
isAssemblyConfiguredValue(configuredValue)
? configuredValue.referenceAssembly
: "",
isAssemblyConfiguredValue(configuredValue)
? configuredValue.geneModelUrl
: null,
configuredValue.readRunsSingle,
configuredValue.readRunsPaired,
null,
workflow.parameters,
origin
)
);
}

export const useLaunchGalaxy = ({
configuredInput,
workflow,
Expand All @@ -27,79 +133,17 @@ export const useLaunchGalaxy = ({
if (!configuredValue) return;
const origin = config.browserURL || window.location.origin;

let landingUrl = "";

if (workflow.trsId === CUSTOM_WORKFLOW.trsId) {
landingUrl = await run(
getDataLandingUrl(
configuredValue.referenceAssembly,
configuredValue.geneModelUrl,
configuredValue.readRunsSingle,
configuredValue.readRunsPaired,
null, // fastaCollection - not yet supported in UI
configuredValue.tracks,
origin
)
);
} else if (
workflow.trsId === LOGAN_SEARCH.trsId ||
workflow.trsId === LEXICMAP.trsId
) {
// LMLS workflows use stored workflow IDs with sequence and numberOfHits parameters
if (!workflow.workflowId) {
throw new Error("Missing workflow ID for LMLS workflow");
}
landingUrl = await run(
getLMLSLandingUrl(
workflow.workflowId,
configuredValue.numberOfHits!,
configuredValue.sequence!,
origin
)
);
} else if (workflow.trsId === DIFFERENTIAL_EXPRESSION_ANALYSIS.trsId) {
if (
!workflow.workflowId ||
!configuredValue.geneModelUrl ||
!configuredValue.sampleSheet ||
!configuredValue.sampleSheetClassification ||
!configuredValue.designFormula
) {
throw new Error("Missing required values for DE workflow");
}
landingUrl = await run(
getDeSeq2LandingUrl(
workflow.workflowId,
configuredValue.referenceAssembly,
configuredValue.geneModelUrl,
configuredValue.sampleSheet,
configuredValue.sampleSheetClassification,
configuredValue.designFormula,
configuredValue.primaryContrasts,
configuredValue.strandedness,
origin
)
);
} else {
landingUrl = await run(
getWorkflowLandingUrl(
workflow.trsId,
configuredValue.referenceAssembly,
configuredValue.geneModelUrl,
configuredValue.readRunsSingle,
configuredValue.readRunsPaired,
null, // fastaCollection - not yet supported in UI
workflow.parameters,
origin
)
);
}
const landingUrl = await getLandingUrlForWorkflow(
workflow,
configuredValue,
origin,
run
);

if (!landingUrl) {
throw new Error("Failed to retrieve Galaxy workflow launch URL.");
}

// Launch the Galaxy workflow.
launchGalaxy(landingUrl);
}, [config, configuredValue, run, workflow]);

Expand Down
Loading
Loading