Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c6f9cc8
Use 1-indexing for exon numbers in convert coordinates (#341)
jarbesfeld Oct 7, 2024
f794ca4
chore: use consistent labeling for coordinate system (#342)
korikuzma Oct 7, 2024
5863da8
build!: update dependencies (#352)
korikuzma Sep 18, 2025
dc6e75d
fix: resolve `get_strand` when valid input is passed (#355)
korikuzma Sep 24, 2025
4920910
feat: add assay inferred or observed to summary (#356)
korikuzma Sep 24, 2025
1e0b78e
chore(ci): add elb health check (#357)
korikuzma Sep 24, 2025
538e82b
feat: add back strand switch (#354)
korikuzma Sep 29, 2025
fe19bf3
feat!: enforce residue mode for coordinates (#358)
korikuzma Sep 29, 2025
d036b5f
refactor: fix styling for genomic start/end position (#361)
korikuzma Sep 30, 2025
868184b
feat: add dropdown for chromosome (#360)
korikuzma Sep 30, 2025
b01d5ce
feat: add mane annotations to transcripts (#362)
korikuzma Sep 30, 2025
488803b
feat: add option for gene when inputting exon coordinates (#363)
korikuzma Sep 30, 2025
d7419b3
refactor(dry): create shared component for gene transcript selector (…
korikuzma Sep 30, 2025
dd882f0
fix: handle cases where no mane transcripts are found or no protein s…
korikuzma Sep 30, 2025
797ce49
refactor: use dynamodb as db for get_uniprot_refs (#371)
korikuzma Oct 24, 2025
87909be
feat: add additional regulatory element fields (feature ID + loc) (#…
korikuzma Nov 6, 2025
dd36328
feat: provide pre-populated options for assay metadata (#370)
korikuzma Nov 6, 2025
04f8709
revert:"chore(ci): add elb health check (#357)"
korikuzma Nov 13, 2025
377c53d
merge: 'main' into 'staging'
korikuzma Nov 20, 2025
7af2959
chore: update seqrepo version to 2024-12-20 (#374)
korikuzma Nov 21, 2025
bc0abc7
refactor: clean up ui code (#373)
korikuzma Nov 21, 2025
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
6 changes: 6 additions & 0 deletions .ebextensions/autoscaling.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Resources:
AWSEBAutoScalingGroup:
Type: "AWS::AutoScaling::AutoScalingGroup"
Properties:
HealthCheckType: ELB
HealthCheckGracePeriod: 300
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ dynamodb_local_latest/*

# Build files
Pipfile.lock
uv.lock

# client-side things
curation/client/node_modules
Expand Down
69 changes: 68 additions & 1 deletion client/src/components/Pages/Assay/Assay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import {
Box,
FormControl,
FormControlLabel,
InputLabel,
MenuItem,
Radio,
RadioGroup,
Select,
TextField,
Typography,
} from "@material-ui/core";
Expand All @@ -20,6 +23,25 @@ interface Props {
index: number;
}

const ASSAY_OPTIONS = [
{
name: "fluorescence in-situ hybridization assay",
identifier: "obi:OBI_0003094",
},
{ name: "sequencing assay", identifier: "obi:OBI_0600047" },
{ name: "DNA sequencing assay", identifier: "obi:OBI_0000626" },
{ name: "RNA-seq assay", identifier: "obi:OBI_0001271" },
{
name: "comparative genomic hybridization by array assay",
identifier: "obi:OBI_0001393",
},
{
name: "RT-PCR",
identifier: "obi:OBI_0000552",
},
{ name: "custom", identifier: "" },
];

export const Assay: React.FC<Props> = () => {
const { colorTheme } = useColorTheme();
const useStyles = makeStyles(() => ({
Expand Down Expand Up @@ -69,6 +91,17 @@ export const Assay: React.FC<Props> = () => {
const [assayName, setAssayName] = useState(
fusion?.assay?.assayName !== undefined ? fusion?.assay?.assayName : ""
);
const [selectedAssayOption, setSelectedAssayOption] = useState(() => {
return (
ASSAY_OPTIONS.find((a) => a.name === assayName) || {
name: "",
identifier: "",
}
);
});
const isCustom = selectedAssayOption
? selectedAssayOption?.name === "custom"
: false;

const [assayId, setAssayId] = useState(
fusion?.assay?.assayId !== undefined ? fusion?.assay?.assayId : ""
Expand All @@ -89,6 +122,7 @@ export const Assay: React.FC<Props> = () => {
};

const propertySetterMap = {
assaySelectedOption: [setSelectedAssayOption, "assaySelectedOption"],
assayName: [setAssayName, "assayName"],
assayId: [setAssayId, "assayId"],
methodUri: [setMethodUri, "methodUri"],
Expand Down Expand Up @@ -116,6 +150,19 @@ export const Assay: React.FC<Props> = () => {
const setterFunction: CallableFunction = propertySetterMap[propertyName][0];
const jsonName: string = propertySetterMap[propertyName][1];
const assay: FusionAssay = JSON.parse(JSON.stringify(fusion.assay));
if (propertyName === "assaySelectedOption") {
value = ASSAY_OPTIONS.find((a) => a.name === value);
setterFunction(value);
const newAssayName = value.name === "custom" ? "" : value?.name;
const newAssayId = value.identifier;

setAssayId(newAssayId);
setAssayName(newAssayName);
assay["assayId"] = newAssayId;
assay["assayName"] = newAssayName;
setFusion({ ...fusion, assay: assay });
return;
}
if (value !== assay[jsonName]) {
setterFunction(value);
assay[jsonName] = value;
Expand Down Expand Up @@ -168,6 +215,24 @@ export const Assay: React.FC<Props> = () => {
<Typography variant="h5" className={classes.prompt}>
Provide assay metadata:
</Typography>
<InputLabel id="select-assay-option">Select assay</InputLabel>
<Select
label="Select assay"
labelId="assay-option-select-label"
value={selectedAssayOption?.name}
onChange={(event) =>
handleValueChange("assaySelectedOption", event.target.value)
}
style={{ width: 550 }}
>
{ASSAY_OPTIONS.map((assayOption) => (
<MenuItem key={assayOption.name} value={assayOption.name}>
{assayOption.name}{" "}
{assayOption.identifier ? `(${assayOption.identifier})` : null}
</MenuItem>
))}
</Select>

<HelpTooltip
placement="left"
title={
Expand All @@ -181,7 +246,8 @@ export const Assay: React.FC<Props> = () => {
<TextField
label="Assay name"
margin="dense"
value={assayName}
value={assayName || ""}
disabled={!isCustom}
onChange={(event) =>
handleValueChange("assayName", event.target.value)
}
Expand All @@ -201,6 +267,7 @@ export const Assay: React.FC<Props> = () => {
label="Assay ID"
margin="dense"
value={assayId}
disabled={!isCustom}
onChange={(event) =>
handleValueChange("assayId", event.target.value)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const DomainForm: React.FC = () => {
return [<MenuItem key={-1} value="" disabled></MenuItem>].concat(
Object.keys(domainOptions).map((geneId: string, index: number) => (
<MenuItem key={index} value={geneId}>
{`${globalGenes[geneId].label}(${geneId})`}
{`${globalGenes[geneId].name}(${geneId})`}
</MenuItem>
))
);
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Pages/Domains/Main/Domains.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const Domain: React.FC<Props> = () => {
avatar={<Avatar>{domain.status === "preserved" ? "P" : "L"}</Avatar>}
label={
<React.Fragment>
{domainLabelString} <b>{`(${domain.associatedGene.label})`}</b>
{domainLabelString} <b>{`(${domain.associatedGene.name})`}</b>
</React.Fragment>
}
onDelete={() => handleRemove(domain)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const StructureDiagram: React.FC = () => {

const regEls = [];
suggestion.regulatoryElements.forEach((el) => {
regEls.push(el.gene.label);
regEls.push(el.gene.name);
});

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const GeneElementInput: React.FC<GeneElementInputProps> = ({
icon,
}) => {
const [errors, setErrors] = useState<string[]>([]);
const [gene, setGene] = useState<string>(element.gene?.label || "");
const [gene, setGene] = useState<string>(element.gene?.name || "");
const [geneText, setGeneText] = useState<string>("");
const validated = gene !== "" && geneText == "";
const [expanded, setExpanded] = useState<boolean>(!validated);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,47 +57,90 @@ const RegulatoryElementInput: React.FC<RegulatoryElementInputProps> = ({
const [elementClass, setElementClass] = useState<RegulatoryClass | "default">(
regElement?.regulatoryClass || "default"
);
const [featureId, setFeatureId] = useState<string>(
regElement?.featureId || ""
);
const [gene, setGene] = useState<string>(
regElement?.associatedGene?.label || ""
regElement?.associatedGene?.name || ""
);
const [geneText, setGeneText] = useState<string>("");

const validated = gene !== "" && geneText == "" && elementClass !== "default";
const [chromosome, setChromosome] = useState<string>(
regElement?.featureLocation?.name || ""
);
const [genomicStart, setGenomicStart] = useState<string>(() => {
const start = regElement?.featureLocation?.start;

if (typeof start === "number") {
return String(start + 1);
}

return "";
});
const [genomicEnd, setGenomicEnd] = useState<string>(() => {
const end = regElement?.featureLocation?.end;

if (typeof end == "number") {
return String(end);
}
return "";
});

const validated =
(gene !== "" && geneText == "" && elementClass !== "default") ||
(chromosome !== "" && genomicStart !== "" && genomicEnd !== "");
const [expanded, setExpanded] = useState<boolean>(!validated);

const [errors, setErrors] = useState<string[]>([]);

useEffect(() => {
if (validated) handleAdd();
}, [gene, geneText, elementClass]);
}, [
gene,
geneText,
elementClass,
featureId,
chromosome,
genomicStart,
genomicEnd,
]);

const handleAdd = () => {
if (elementClass === "default") return;
getRegulatoryElement(elementClass, gene).then((reResponse) => {
getRegulatoryElement(
elementClass,
gene,
featureId,
chromosome,
genomicStart,
genomicEnd
).then((reResponse) => {
if (reResponse.warnings && reResponse.warnings.length > 0) {
setErrors(reResponse.warnings);
return;
}
getRegElementNomenclature(reResponse.regulatoryElement).then(
(nomenclatureResponse) => {
if (
nomenclatureResponse.warnings &&
nomenclatureResponse.warnings.length > 0
) {
setErrors(nomenclatureResponse.warnings);
return;
if (reResponse.regulatoryElement) {
getRegElementNomenclature(reResponse.regulatoryElement).then(
(nomenclatureResponse) => {
if (
nomenclatureResponse.warnings &&
nomenclatureResponse.warnings.length > 0
) {
setErrors(nomenclatureResponse.warnings);
return;
}
setErrors([]);
const newRegElement: ClientRegulatoryElement = {
...reResponse.regulatoryElement,
elementId: element.elementId,
displayClass: regulatoryClassItems[elementClass][1],
nomenclature: nomenclatureResponse.nomenclature || "",
};
setRegElement(newRegElement);
setFusion({ ...fusion, ...{ regulatoryElement: newRegElement } });
}
setErrors([]);
const newRegElement: ClientRegulatoryElement = {
...reResponse.regulatoryElement,
elementId: element.elementId,
displayClass: regulatoryClassItems[elementClass][1],
nomenclature: nomenclatureResponse.nomenclature || "",
};
setRegElement(newRegElement);
setFusion({ ...fusion, ...{ regulatoryElement: newRegElement } });
}
);
);
}
});
};

Expand All @@ -107,8 +150,12 @@ const RegulatoryElementInput: React.FC<RegulatoryElementInputProps> = ({
setRegElement(undefined);
setFusion(cloneFusion);
setElementClass("default");
setFeatureId("");
setGene("");
setGeneText("");
setChromosome("");
setGenomicStart("");
setGenomicEnd("");
setErrors([]);
};

Expand All @@ -118,10 +165,18 @@ const RegulatoryElementInput: React.FC<RegulatoryElementInputProps> = ({
regulatoryClassItems={regulatoryClassItems}
elementClass={elementClass}
setElementClass={setElementClass}
featureId={featureId}
setFeatureId={setFeatureId}
gene={gene}
setGene={setGene}
geneText={geneText}
setGeneText={setGeneText}
chromosome={chromosome}
setChromosome={setChromosome}
genomicStart={genomicStart}
setGenomicStart={setGenomicStart}
genomicEnd={genomicEnd}
setGenomicEnd={setGenomicEnd}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useState, useEffect, KeyboardEvent } from "react";
import { TextField, Box, Typography } from "@material-ui/core";
import { TextField, Typography } from "@material-ui/core";
import { StructuralElementInputProps } from "../StructuralElementInputProps";
import {
getTemplatedSequenceElement,
getTemplatedSequenceNomenclature,
} from "../../../../../services/main";
import { ClientTemplatedSequenceElement } from "../../../../../services/ResponseModels";
import StructuralElementInputAccordion from "../StructuralElementInputAccordion";
import StrandSwitch from "../../../../main/shared/StrandSwitch/StrandSwitch";
import HelpTooltip from "../../../../main/shared/HelpTooltip/HelpTooltip";
import ChromosomeField from "../../../../main/shared/ChromosomeField/ChromosomeField";

interface TemplatedSequenceElementInputProps
extends StructuralElementInputProps {
Expand Down Expand Up @@ -106,38 +106,19 @@ const TemplatedSequenceElementInput: React.FC<
const inputElements = (
<>
<div className="top-inputs">
<HelpTooltip
placement="bottom"
title={
<>
<Typography>The chromosome on which the segment lies.</Typography>
<Typography>
RefSeq identifiers (e.g.{" "}
<Typography variant="overline">NC_000001.11</Typography>) are
preferred.
</Typography>
</>
<ChromosomeField
fieldValue={chromosome}
onChange={(event, _child) =>
setChromosome(event.target.value as string)
}
>
<TextField
margin="dense"
style={{ height: 38, width: 125 }}
label="Chromosome"
value={chromosome}
onChange={(event) => setChromosome(event.target.value)}
onKeyDown={handleEnterKey}
/>
</HelpTooltip>
<Box mt="18px">
<StrandSwitch setStrand={setStrand} selectedStrand={strand} />
</Box>
/>
</div>
<div className="bottom-inputs">
<HelpTooltip
placement="bottom"
title={
<Typography>
The starting genomic position of the segment. Inter-residue.
The starting genomic position (residue) of the segment.
</Typography>
}
>
Expand All @@ -154,7 +135,7 @@ const TemplatedSequenceElementInput: React.FC<
placement="bottom"
title={
<Typography>
The ending genomic position of the segment. Inter-residue.
The ending genomic position (residue) of the segment.
</Typography>
}
>
Expand Down
Loading