-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow curating mutation summary #433
Changes from 4 commits
663fa4c
b49f4a4
fdd4c15
80bd1ff
eaeed75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ import { | |
getFirebaseGenePath, | ||
getFirebaseVusPath, | ||
getMutationName, | ||
hasMultipleMutations, | ||
isMutationEffectCuratable, | ||
isSectionRemovableWithoutReview, | ||
} from 'app/shared/util/firebase/firebase-utils'; | ||
|
@@ -35,7 +36,7 @@ import { IRootStore } from 'app/stores'; | |
import { get, onValue, ref } from 'firebase/database'; | ||
import _ from 'lodash'; | ||
import { observer } from 'mobx-react'; | ||
import React, { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; | ||
import { Button } from 'reactstrap'; | ||
import BadgeGroup from '../BadgeGroup'; | ||
import { DeleteSectionButton } from '../button/DeleteSectionButton'; | ||
|
@@ -49,6 +50,7 @@ import { NestLevelColor, NestLevelMapping, NestLevelType } from './NestLevel'; | |
import { RemovableCollapsible } from './RemovableCollapsible'; | ||
import { Unsubscribe } from 'firebase/database'; | ||
import { getLocationIdentifier } from 'app/components/geneHistoryTooltip/gene-history-tooltip-utils'; | ||
import { SimpleConfirmModal } from 'app/shared/modal/SimpleConfirmModal'; | ||
|
||
export interface IMutationCollapsibleProps extends StoreProps { | ||
mutationPath: string; | ||
|
@@ -77,15 +79,21 @@ const MutationCollapsible = ({ | |
annotatedAltsCache, | ||
genomicIndicators, | ||
showLastModified, | ||
handleFirebaseUpdate, | ||
}: IMutationCollapsibleProps) => { | ||
const firebaseMutationsPath = `${getFirebaseGenePath(isGermline, hugoSymbol)}/mutations`; | ||
|
||
const [mutationUuid, setMutationUuid] = useState<string>(''); | ||
const [mutationName, setMutationName] = useState<string>(''); | ||
const [mutationNameReview, setMutationNameReview] = useState<Review | null>(null); | ||
const [mutationSummary, setMutationSummary] = useState<string>(''); | ||
const [mutationAlterations, setMutationAlterations] = useState<Alteration[] | null>(null); | ||
const [isRemovableWithoutReview, setIsRemovableWithoutReview] = useState(false); | ||
const [relatedAnnotationResult, setRelatedAnnotationResult] = useState<AlterationAnnotationStatus[]>([]); | ||
const [oncogenicity, setOncogenicity] = useState<string>(''); | ||
const [showSimpleConfirmModal, setShowSimpleConfirmModal] = useState<boolean>(false); | ||
const [simpleConfirmModalBody, setSimpleConfirmModalBody] = useState<string | undefined>(undefined); | ||
const [mutationSummaryRef, setMutationSummaryRef] = useState<HTMLElement | null>(null); | ||
|
||
useEffect(() => { | ||
const arr = annotatedAltsCache?.get(hugoSymbol ?? '', [{ name: mutationName, alterations: mutationAlterations }]) ?? []; | ||
|
@@ -157,6 +165,11 @@ const MutationCollapsible = ({ | |
setMutationName(snapshot.val()); | ||
}), | ||
); | ||
callbacks.push( | ||
onValue(ref(firebaseDb, `${mutationPath}/summary`), snapshot => { | ||
setMutationSummary(snapshot.val()); | ||
}), | ||
); | ||
callbacks.push( | ||
onValue(ref(firebaseDb, `${mutationPath}/alterations`), snapshot => { | ||
setMutationAlterations(snapshot.val()); | ||
|
@@ -169,6 +182,11 @@ const MutationCollapsible = ({ | |
setIsRemovableWithoutReview(isSectionRemovableWithoutReview(review)); | ||
}), | ||
); | ||
callbacks.push( | ||
onValue(ref(firebaseDb, `${mutationPath}/mutation_effect/oncogenic`), snapshot => { | ||
setOncogenicity(snapshot.val()); | ||
}), | ||
); | ||
|
||
onValue( | ||
ref(firebaseDb, `${mutationPath}/name_uuid`), | ||
|
@@ -197,6 +215,34 @@ const MutationCollapsible = ({ | |
[mutationPath, mutationName, parsedHistoryList], | ||
); | ||
|
||
async function simpleConfirmModalOnConfirm() { | ||
await handleFirebaseUpdate?.(mutationPath, { summary: '' }); | ||
if (mutationSummaryRef) { | ||
mutationSummaryRef.click(); | ||
} | ||
setShowSimpleConfirmModal(false); | ||
setSimpleConfirmModalBody(undefined); | ||
} | ||
|
||
function oncogenicityRadioOnClick( | ||
event: React.MouseEvent<HTMLInputElement> | React.MouseEvent<HTMLLabelElement> | React.MouseEvent<HTMLDivElement>, | ||
) { | ||
if (mutationSummary && event.target) { | ||
let newOncogenicityVal; | ||
if (event.target instanceof HTMLInputElement) { | ||
newOncogenicityVal = event.target.value; | ||
} else if (event.target instanceof HTMLDivElement || event.target instanceof HTMLLabelElement) { | ||
newOncogenicityVal = event.target.innerText; | ||
} | ||
if (newOncogenicityVal === RADIO_OPTION_NONE) { | ||
event.preventDefault(); | ||
setMutationSummaryRef(event.target as HTMLElement); | ||
setShowSimpleConfirmModal(true); | ||
setSimpleConfirmModalBody(`Mutation summary will be removed after removing oncogenicity.`); | ||
} | ||
} | ||
} | ||
|
||
async function handleDeleteMutation(toVus = false) { | ||
if (!firebaseDb) { | ||
return; | ||
|
@@ -308,6 +354,25 @@ const MutationCollapsible = ({ | |
} | ||
isPendingDelete={isMutationPendingDelete} | ||
> | ||
<RealtimeTextAreaInput | ||
firebasePath={`${mutationPath}/summary`} | ||
inputClass={styles.summaryTextarea} | ||
label="Mutation Summary (Optional)" | ||
labelIcon={ | ||
<GeneHistoryTooltip | ||
historyData={parsedHistoryList} | ||
location={`${getMutationName(mutationName, mutationAlterations)}, ${READABLE_FIELD.SUMMARY}`} | ||
locationIdentifier={getLocationIdentifier({ | ||
mutationUuid, | ||
fields: [READABLE_FIELD.SUMMARY], | ||
})} | ||
/> | ||
} | ||
name="summary" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we change to |
||
parseRefs | ||
disabled={oncogenicity === ''} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Edge case: What happens when oncogenicity is cleared after entering mutation summary already. Should the mutation summary get cleared back to empty string. |
||
disabledMessage={'Not curatable: mutation summary is only curatable when oncogenicity is specified.'} | ||
/> | ||
<Collapsible | ||
idPrefix={`${mutationName}-mutation-effect`} | ||
title="Mutation Effect" | ||
|
@@ -369,6 +434,10 @@ const MutationCollapsible = ({ | |
} | ||
</> | ||
} | ||
/** Radio a bit tricky. Have to use onMouseDown event to cancel the default event. | ||
* The onclick event does not like to be overwritten **/ | ||
onMouseDown={oncogenicityRadioOnClick} | ||
labelOnClick={oncogenicityRadioOnClick} | ||
isRadio | ||
options={[...ONCOGENICITY_OPTIONS, RADIO_OPTION_NONE].map(label => ({ | ||
label, | ||
|
@@ -598,6 +667,12 @@ const MutationCollapsible = ({ | |
}} | ||
/> | ||
) : undefined} | ||
<SimpleConfirmModal | ||
show={showSimpleConfirmModal} | ||
body={simpleConfirmModalBody} | ||
onConfirm={simpleConfirmModalOnConfirm} | ||
onCancel={() => setShowSimpleConfirmModal(false)} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
@@ -623,6 +698,7 @@ const mapStoreToProps = ({ | |
firebaseDb: firebaseAppStore.firebaseDb, | ||
annotatedAltsCache: curationPageStore.annotatedAltsCache, | ||
genomicIndicators: firebaseGenomicIndicatorsStore.data, | ||
handleFirebaseUpdate: firebaseGeneService.updateObject, | ||
}); | ||
|
||
type StoreProps = Partial<ReturnType<typeof mapStoreToProps>>; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -400,8 +400,12 @@ const addDuplicateMutationInfo = (duplicates: DuplicateMutationInfo[], mutationN | |
} | ||
}; | ||
|
||
export const hasMultipleMutations = (mutationName: string) => { | ||
return mutationName.includes(','); | ||
}; | ||
export const isMutationEffectCuratable = (mutationName: string) => { | ||
if (mutationName.includes(',')) { | ||
const multipleMuts = hasMultipleMutations(mutationName); | ||
if (multipleMuts) { | ||
Comment on lines
+403
to
+408
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably not in the scope of this PR, but we should update so that |
||
return false; | ||
} | ||
const excludedMutations = ['Oncogenic Mutations']; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.