From 904777203eee1e67e86d190d6186506a8b6138d9 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 4 Dec 2024 11:03:10 +0100 Subject: [PATCH] feat: mtb gene centric search (#951) * feat: initial refacotring of mtb geneAlteration/variant form * feat: adjust rendering query criteria summary * feat: cleanup query geneAlterations building --- .../utility/form-tab/DFormTabGroups.vue | 10 +- .../components/core/MMutationTabGroup.vue | 268 +++++++++++++----- .../query-criteria/MQueryCriteriaSummary.vue | 216 +++++--------- .../components/core/search/MSearchCNVForm.vue | 182 ++++-------- .../components/core/search/MSearchForm.vue | 118 ++------ .../core/search/MSearchFusionForm.vue | 171 ++++------- .../components/core/search/MSearchSNVForm.vue | 101 ++----- .../mtb/src/runtime/domains/form/constants.ts | 6 - .../mtb/src/runtime/domains/form/index.ts | 2 - .../mtb/src/runtime/domains/form/types.ts | 23 -- packages/mtb/src/runtime/domains/index.ts | 1 - .../src/runtime/domains/query/constants.ts | 11 + .../mtb/src/runtime/domains/query/index.ts | 1 + .../mtb/src/runtime/domains/query/types.ts | 57 ++-- .../src/runtime/pages/query/[id]/index.vue | 6 - packages/portal/nuxt.config.ts | 4 +- 16 files changed, 490 insertions(+), 687 deletions(-) delete mode 100644 packages/mtb/src/runtime/domains/form/constants.ts delete mode 100644 packages/mtb/src/runtime/domains/form/index.ts delete mode 100644 packages/mtb/src/runtime/domains/form/types.ts create mode 100644 packages/mtb/src/runtime/domains/query/constants.ts diff --git a/packages/core/src/components/utility/form-tab/DFormTabGroups.vue b/packages/core/src/components/utility/form-tab/DFormTabGroups.vue index 24e7021f..231a7bd1 100644 --- a/packages/core/src/components/utility/form-tab/DFormTabGroups.vue +++ b/packages/core/src/components/utility/form-tab/DFormTabGroups.vue @@ -87,12 +87,18 @@ export default defineComponent({ currentIndex.value = nextIndex < 0 ? 0 : nextIndex; - items.value.splice(index, 1); + if (items.value.length > 0) { + items.value.splice(index, 1); + } } else { currentIndex.value = index; } }; + const toggleCurrent = () => { + toggle(currentIndex.value); + }; + const handleUpdated = (data: Record) => { if (currentIndex.value === -1) { items.value.push({ ...data }); @@ -110,6 +116,7 @@ export default defineComponent({ items, add, toggle, + toggleCurrent, }; }, }); @@ -124,6 +131,7 @@ export default defineComponent({
-import { VCFormSelect } from '@vuecs/form-controls'; +import { + type CodeSystemConcept, + DCodeSystem, + DCollectionTransform, + DTags, toCoding, + transformConceptToFormSelectOption, +} from '@dnpm-dip/core'; +import { VCFormSelect, VCFormSelectSearch } from '@vuecs/form-controls'; import type { FormSelectOption } from '@vuecs/form-controls'; import { - type PropType, type Ref, computed, watch, + type PropType, type Ref, computed, reactive, toRef, watch, } from 'vue'; import { - defineComponent, markRaw, ref, toRef, + defineComponent, markRaw, ref, } from 'vue'; -import { FormMutationType, type MutationDefinition } from '../../domains'; +import { + type QueryGeneAlterationCriteria, + type QueryGeneAlterationVariantCriteria, + QueryMutationType, +} from '../../domains'; import MSearchCNVForm from './search/MSearchCNVForm.vue'; import MSearchFusionForm from './search/MSearchFusionForm.vue'; import MSearchSNVForm from './search/MSearchSNVForm.vue'; export default defineComponent({ - components: { VCFormSelect }, - emit: ['updated'], + components: { + DCollectionTransform, DTags, VCFormSelectSearch, DCodeSystem, VCFormSelect, + }, + emit: ['updated', 'toggle'], props: { entity: { - type: Object as PropType, + type: Object as PropType, }, }, setup(props, { emit }) { - const entityRef = toRef(props, 'entity'); + const entity = toRef(props, 'entity'); + const form = reactive>>({ + gene: '', + supporting: false, + negated: false, + }); + + const mutationType = ref(null); + const mutationData = ref(null); - const options : FormSelectOption[] = [ - { id: FormMutationType.CNV, value: 'CNV' }, - { id: FormMutationType.SNV, value: 'SNV' }, - { id: FormMutationType.DNA_FUSION, value: 'DNA Fusion' }, - { id: FormMutationType.RNA_FUSION, value: 'RNA Fusion' }, + const mutationOptions : FormSelectOption[] = [ + { id: QueryMutationType.CNV, value: 'CNV' }, + { id: QueryMutationType.SNV, value: 'SNV' }, + { id: QueryMutationType.FUSION, value: 'Fusion' }, ]; const comp = ref(null) as Ref>; - const changeComp = (type: FormMutationType) => { + const changeMutationType = (type: `${QueryMutationType}` | null) => { switch (type) { - case FormMutationType.CNV: { + case QueryMutationType.CNV: { comp.value = markRaw(MSearchCNVForm); + + mutationData.value = { + type: QueryMutationType.CNV, + }; + mutationType.value = QueryMutationType.CNV; break; } - case FormMutationType.SNV: { + case QueryMutationType.SNV: { comp.value = markRaw(MSearchSNVForm); + + mutationData.value = { + type: QueryMutationType.SNV, + }; + mutationType.value = QueryMutationType.SNV; break; } - case FormMutationType.RNA_FUSION: - case FormMutationType.DNA_FUSION: { + case QueryMutationType.FUSION: { comp.value = markRaw(MSearchFusionForm); + + mutationData.value = { + type: QueryMutationType.FUSION, + }; + mutationType.value = QueryMutationType.FUSION; break; } default: { comp.value = null; + mutationData.value = null; + mutationType.value = null; break; } } }; - const changeCompByEvent = (event: Event) => { - if (!event.target) return; + const changeMutationTypeByEvent = (event: Event) => { + if (!event.target) { + return; + } - changeComp((event.target as Record).value); + changeMutationType((event.target as Record).value || null); }; - const compData = ref(null); - const compType = ref(null); - + const isEditing = computed(() => !!props.entity && Object.keys(props.entity).length > 0); const init = () => { - if (props.entity) { - changeComp(props.entity.type); - - compType.value = props.entity.type; - compData.value = props.entity.data; + if (!props.entity) { return; } - compType.value = null; - compData.value = null; + if ( + props.entity.variant && + props.entity.variant.type + ) { + changeMutationType(props.entity.variant.type); + } else { + changeMutationType(null); + } + + if (props.entity.gene) { + form.gene = props.entity.gene.code; + } else { + form.gene = ''; + } + + if (typeof props.entity.supporting !== 'undefined') { + form.supporting = props.entity.supporting; + } else { + form.supporting = false; + } + + if (typeof props.entity.negated !== 'undefined') { + form.negated = props.entity.negated; + } else { + form.negated = false; + } }; init(); - watch(entityRef, () => { + watch(entity, () => { init(); }, { deep: true }); - const isEditing = computed(() => !!props.entity && - !!props.entity.type && - !!props.entity.data); - - const handleUpdated = (data: Record) => { - compData.value = data; + const submit = () => { + if (form.gene) { + emit('updated', { + gene: form.gene ? toCoding(form.gene) : undefined, + supporting: form.supporting, + negated: form.negated, + ...(mutationData.value ? { variant: mutationData.value } : {}), + } satisfies QueryGeneAlterationCriteria); + } else { + emit('toggle'); + } + }; - emit('updated', { - type: compType.value, - data: compData.value, - }); + const handleVariantChanged = (data: QueryGeneAlterationVariantCriteria | null) => { + mutationData.value = data; }; + const transformConcepts = ( + concept: CodeSystemConcept, + ) => transformConceptToFormSelectOption(concept); + return { - changeCompByEvent, + form, + + changeMutationTypeByEvent, comp, - compData, - compType, - options, + mutationType, + mutationOptions, - handleUpdated, + handleVariantChanged, isEditing, + transformConcepts, + + submit, }; }, });