From 667ddf84305ba209c9180de0d639c7031fd7384e Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Tue, 17 Mar 2026 10:33:45 -0400 Subject: [PATCH 1/5] Initial implementation --- package-lock.json | 4 ++-- src/views/import/ImportExperiment.vue | 32 +++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 494aa6eb..1c892c89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bi-web", - "version": "v1.0.0+789", + "version": "v1.3.0+907", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bi-web", - "version": "v1.0.0+789", + "version": "v1.3.0+907", "hasInstallScript": true, "dependencies": { "@casl/ability": "~4.0.0", diff --git a/src/views/import/ImportExperiment.vue b/src/views/import/ImportExperiment.vue index da6739f3..3c1e63af 100644 --- a/src/views/import/ImportExperiment.vue +++ b/src/views/import/ImportExperiment.vue @@ -308,12 +308,19 @@ import {ImportObjectState} from "@/breeding-insight/model/import/ImportObjectSta import { GeoCoordinates } from '@/breeding-insight/model/GeoCoordinates'; import {ExperimentUserInput} from "@/breeding-insight/model/ExperimentUserInput"; import {StringFormatters} from "../../breeding-insight/utils/StringFormatters"; +import {TraitService} from "@/breeding-insight/service/TraitService"; +import {mapGetters} from "vuex"; +import {Program} from "@/breeding-insight/model/Program"; +import {Trait} from "@/breeding-insight/model/Trait"; @Component({ computed: { StringFormatters() { return StringFormatters - } + }, + ...mapGetters([ + 'activeProgram' + ]), }, components: { ImportInfoTemplateMessageBox, ConfirmImportMessageBox, ImportTemplate, AlertTriangleIcon, BasicInputField, ExpandableTable @@ -327,6 +334,15 @@ import {StringFormatters} from "../../breeding-insight/utils/StringFormatters"; }) export default class ImportExperiment extends ProgramsBase { + async mounted() { + // Hopefully no more than 100 ontology terms + let traitResponse = await TraitService.getTraits(this.activeProgram.id, {}, {pageSize: 100, page: 1}); + + this.traits = traitResponse.value.result.data.map( + (trait: any) => trait.observationVariableName + ); + } + private experimentImportTemplateName = 'ExperimentsTemplateMap'; private confirmImportState: DataFormEventBusHandler = new DataFormEventBusHandler(); private phenotypeColumns?: Array = []; @@ -334,6 +350,10 @@ export default class ImportExperiment extends ProgramsBase { private experimentUserInput: ExperimentUserInput = new ExperimentUserInput(); private repeatObservationsCount = 10; + + private activeProgram!: Program; + private traits : String[] = []; + get showProceedDialog() { return this.experimentUserInput.overwrite; } @@ -415,7 +435,15 @@ export default class ImportExperiment extends ProgramsBase { } previewDataLoaded(dynamicColumns: String[]) { - this.phenotypeColumns = dynamicColumns; + + for (const dynCol of dynamicColumns) { + if (this.traits.includes(dynCol)) { + this.phenotypeColumns.push(dynCol); + } else { + console.log(`Dynamic column [${dynCol}] not found in the list of available traits for program [${this.activeProgram.name}]`) + } + } + this.createObservationIndexMap(); } From 4eafe82b828cd8e0e8d32f6bc818779d7413a2d8 Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Tue, 17 Mar 2026 12:07:09 -0400 Subject: [PATCH 2/5] Fix bug where if import tab not reloaded previews would break --- src/views/import/ImportExperiment.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/import/ImportExperiment.vue b/src/views/import/ImportExperiment.vue index 3c1e63af..ec437912 100644 --- a/src/views/import/ImportExperiment.vue +++ b/src/views/import/ImportExperiment.vue @@ -436,6 +436,10 @@ export default class ImportExperiment extends ProgramsBase { previewDataLoaded(dynamicColumns: String[]) { + // To ensure correct phenotype mapping when multiple appends/create experiments on a single page load, + // reset the phenotypeColumns every time a new preview is loaded. + this.phenotypeColumns = []; + for (const dynCol of dynamicColumns) { if (this.traits.includes(dynCol)) { this.phenotypeColumns.push(dynCol); From aec232cb7ff7ede4577b27185365a27a75a5a40f Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Wed, 18 Mar 2026 10:06:55 -0400 Subject: [PATCH 3/5] Utilize new obsVarCount stat, remove filter on OUID OUIDs will now be filtered by function which filters on dynCols that exist in the associated trait list for a program. --- src/views/import/ImportExperiment.vue | 6 ++++-- src/views/import/ImportTemplate.vue | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/views/import/ImportExperiment.vue b/src/views/import/ImportExperiment.vue index ec437912..7316437a 100644 --- a/src/views/import/ImportExperiment.vue +++ b/src/views/import/ImportExperiment.vue @@ -83,7 +83,7 @@ Import Summary

-
Observation Variables: {{ dynamicColumns.filter( obsVar => !obsVar.startsWith("TS:") ).length }} +
Observation Variables: {{ statistics.Observation_Variables.newObjectCount }}
New Observations: {{ statistics.Observations.newObjectCount }}
Existing Observations: {{ statistics.Existing_Observations.newObjectCount }} @@ -444,11 +444,13 @@ export default class ImportExperiment extends ProgramsBase { if (this.traits.includes(dynCol)) { this.phenotypeColumns.push(dynCol); } else { - console.log(`Dynamic column [${dynCol}] not found in the list of available traits for program [${this.activeProgram.name}]`) + console.log(`Dynamic column [${dynCol}] not found in the list of available traits for program [${this.activeProgram.name}]`); } } this.createObservationIndexMap(); + + return this.phenotypeColumns.length; } // Map phenotypeColumn indices to brapi observation indices for use in highlighting diff --git a/src/views/import/ImportTemplate.vue b/src/views/import/ImportTemplate.vue index 0ef2a29e..aaafb529 100644 --- a/src/views/import/ImportTemplate.vue +++ b/src/views/import/ImportTemplate.vue @@ -633,7 +633,7 @@ export default class ImportTemplate extends ProgramsBase { this.previewData = previewResponse.preview.rows as any[]; this.newObjectCounts = previewResponse.preview.statistics; this.$emit('statistics-loaded', this.newObjectCounts); - this.dynamicColumns = previewResponse.preview.dynamicColumnNames.filter(name => !name.includes('ObsUnitID')); + this.dynamicColumns = previewResponse.preview.dynamicColumnNames; this.$emit('preview-data-loaded', this.dynamicColumns); this.importService.send(ImportEvent.IMPORT_SUCCESS); // TODO: Temp pagination From 1d650a913d3f1162d7a830e04a66038a86de9348 Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Wed, 18 Mar 2026 11:20:50 -0400 Subject: [PATCH 4/5] Restore package-lock.json to develop --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c892c89..494aa6eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bi-web", - "version": "v1.3.0+907", + "version": "v1.0.0+789", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bi-web", - "version": "v1.3.0+907", + "version": "v1.0.0+789", "hasInstallScript": true, "dependencies": { "@casl/ability": "~4.0.0", From 351a134fabbb280a2ef3aea91e826ed13742dc51 Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Fri, 20 Mar 2026 12:34:29 -0400 Subject: [PATCH 5/5] Use vue-js logging, remove erroneous return --- src/views/import/ImportExperiment.vue | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/views/import/ImportExperiment.vue b/src/views/import/ImportExperiment.vue index 7316437a..f55959f7 100644 --- a/src/views/import/ImportExperiment.vue +++ b/src/views/import/ImportExperiment.vue @@ -338,6 +338,10 @@ export default class ImportExperiment extends ProgramsBase { // Hopefully no more than 100 ontology terms let traitResponse = await TraitService.getTraits(this.activeProgram.id, {}, {pageSize: 100, page: 1}); + if (traitResponse.value.metadata.pagination.totalCount > 100) { + this.$log.error("More than 100 traits detected while loading experiment import preview"); + } + this.traits = traitResponse.value.result.data.map( (trait: any) => trait.observationVariableName ); @@ -444,13 +448,11 @@ export default class ImportExperiment extends ProgramsBase { if (this.traits.includes(dynCol)) { this.phenotypeColumns.push(dynCol); } else { - console.log(`Dynamic column [${dynCol}] not found in the list of available traits for program [${this.activeProgram.name}]`); + this.$log.info(`Dynamic column [${dynCol}] not found in the list of available traits for program [${this.activeProgram.name}]`); } } this.createObservationIndexMap(); - - return this.phenotypeColumns.length; } // Map phenotypeColumn indices to brapi observation indices for use in highlighting