Skip to content
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

BI-1717 (View experiment: Details, Summary Stats, Actions) #316

Merged
merged 11 commits into from
Jun 5, 2023
40 changes: 40 additions & 0 deletions src/breeding-insight/dao/ExperimentDAO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Response} from "@/breeding-insight/model/BiResponse";
import * as api from "@/util/api";
import {Result, ResultGenerator} from "@/breeding-insight/model/Result";
import {Trial} from "@/breeding-insight/model/Trial.ts";

export class ExperimentDAO {

static async getSingleExperiment(programId: string, experimentId: string, stats: boolean): Promise<Result<Error, Trial>> {
const config: any = {};
config.url = `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/brapi/v2/trials/${experimentId}`;
config.method = 'get';
config.programId = programId;
config.experimentId = experimentId;
config.params = {stats: stats};
try {
const res = await api.call(config) as Response;
let { result } = res.data;
return ResultGenerator.success(result);
} catch (error) {
return ResultGenerator.err(error);
}
}
}
17 changes: 16 additions & 1 deletion src/breeding-insight/model/Trial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,24 @@
import { ExternalReferences } from '@/breeding-insight/brapi/model/externalReferences';

export class Trial {
trialDbId?: string;

id?: string;
trialName?: string;
trialDescription?: string;
active?: boolean;
externalReferences?: ExternalReferences;
commonCropName?: string;
// contacts?: Array<Contact>;
//datasetAuthorships?: Array<TrialNewRequestDatasetAuthorships>;
Comment on lines +29 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the commented out fields if not needed

Copy link
Member

@timparsons timparsons May 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmeidlin I think they are commented out because the Contact and TrialNewRequestDatasetAuthorships types aren't in the code base, but these fields are a part of the BrAPI Trial model. Are you ok with leaving them in there with this in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, np.

documentationURL?: string;
endDate?: string;
programDbId?: string;
programName?: string;
startDate?: string;
trialPUI?: string;
additionalInfo?: any;


constructor(id?: string,
trialName?: string,
Expand All @@ -46,4 +60,5 @@ export class Trial {
return (this.id === trial.id) &&
(this.trialName === trial.trialName)
}
}

}
30 changes: 30 additions & 0 deletions src/breeding-insight/service/ExperimentService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {ExperimentDAO} from "@/breeding-insight/dao/ExperimentDAO";
import {Trial} from "@/breeding-insight/model/Trial.ts";
import {Result, ResultGenerator} from "@/breeding-insight/model/Result";

export class ExperimentService {

static async getSingleExperiment(programId: string, experimentId: string, stats: boolean): Promise<Result<Error, Trial>> {
if (!programId) {
return ResultGenerator.err(new Error('Missing or invalid program id'));
}
return await ExperimentDAO.getSingleExperiment(programId, experimentId, stats);
}
}
25 changes: 25 additions & 0 deletions src/breeding-insight/utils/BrAPIUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {ExternalReferences} from "@/breeding-insight/brapi/model/externalReferences";

export class BrAPIUtils {
static getBreedingInsightId(references: ExternalReferences, referenceSourcePath: string = ""): string | undefined {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of typing the source as string with an empty string as default, would you mind making an ExternalReferenceSource enum and specify the arg as non-null?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method was copied from GermplasmUtils. I think there are places in the code that don't specify a referenceSourcePath parameter (because it's intended to just be breedinginsight.org) hence why there is a default of an empty string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. I'm fine leaving it as is, then.

let val = references.find(ref => ref.referenceSource === process.env.VUE_APP_BI_REFERENCE_SOURCE + referenceSourcePath);
return val ? val.referenceID : "";
}
}
7 changes: 0 additions & 7 deletions src/breeding-insight/utils/GermplasmUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

import moment from "moment";
import {Germplasm} from "@/breeding-insight/brapi/model/germplasm";
import {ExternalReferences} from "@/breeding-insight/brapi/model/externalReferences";
import {GermplasmService} from "@/breeding-insight/service/GermplasmService";
import {MOMENT_BRAPI_DATE_FORMAT} from "@/breeding-insight/utils/BrAPIDateTime";

// The moment.js interpretable format for Date values sent and received via the BI API.
Expand All @@ -43,11 +41,6 @@ export class GermplasmUtils {
return "";
}

static getBreedingInsightId(references: ExternalReferences, referenceSourcePath: string = ""): string | undefined {
let val = references.find(ref => ref.referenceSource === process.env.VUE_APP_BI_REFERENCE_SOURCE + referenceSourcePath);
return val ? val.referenceID : "";
}

static formatSynonyms(synonyms: any[]): string {
if (!synonyms) return "";
return synonyms.map(synonym => synonym.synonym).join("; ");
Expand Down
3 changes: 3 additions & 0 deletions src/components/DownloadButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<a
href="javascript:void(0)"
v-on:click="openDownloadModal"
v-bind:class="anchorClass"
>
<slot />
</a>
Expand All @@ -76,6 +77,8 @@ export default class DownloadButton extends Vue {
modalClass?: string;
@Prop()
download!: () => boolean;
@Prop()
anchorClass?: string;

private modalActive: boolean = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
v-bind:unique-id="trialDbId"
v-bind:modal-title="modalTitle"
v-bind:download="downloadList"
v-bind:anchor-class="anchorClass"
modal-class="experiment-observations-download-button"
v-on:deactivate="resetExportOptions"
>
Expand Down Expand Up @@ -165,6 +166,8 @@ export default class ExperimentObservationsDownloadButton extends Vue {
trialDbId!: string;
@Prop()
modalTitle?: string;
@Prop()
anchorClass?: string;

private activeProgram?: Program;
private fileOptions: ExperimentExportOptions = new ExperimentExportOptions();
Expand Down
10 changes: 8 additions & 2 deletions src/components/experiments/ExperimentsObservationsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
v-on:search="initSearch"
>
<b-table-column label="Title" field="name" cell-class="fixed-width-wrapped" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})" searchable>
{{ props.row.data.trialName }}
<router-link v-bind:to="{name: 'experiment-details', params: {programId: activeProgram.id, experimentId: BrAPIUtils.getBreedingInsightId(props.row.data.externalReferences,'/trials')}}">
{{ props.row.data.trialName }}
</router-link>

</b-table-column>
<b-table-column label="Status" field="active" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})" >
{{ getStatus(props.row.data.active) }}
Expand All @@ -57,6 +60,7 @@
>
Download
</ExperimentObservationsDownloadButton>

</b-table-column>

<template v-slot:emptyMessage>
Expand All @@ -80,6 +84,7 @@ import {PaginationQuery} from "@/breeding-insight/model/PaginationQuery";
import {Trial} from '@/breeding-insight/model/Trial'
import ExpandableTable from '@/components/tables/expandableTable/ExpandableTable.vue';
import {CallStack} from "@/breeding-insight/utils/CallStack";
import {BrAPIUtils} from "@/breeding-insight/utils/BrAPIUtils";
import {
ExperimentSort,
Sort,
Expand All @@ -106,7 +111,7 @@ import ExperimentObservationsDownloadButton from "@/components/experiments/Exper
updateSort: UPDATE_EXPERIMENT_SORT
})
},
data: () => ({Sort})
data: () => ({Sort, BrAPIUtils})
})
export default class ExperimentsObservationsTable extends Vue {

Expand Down Expand Up @@ -170,6 +175,7 @@ export default class ExperimentsObservationsTable extends Vue {
// Account for brapi 0 indexing of paging
this.paginationController.currentPage = this.paginationController.currentPage.valueOf() + 1;
this.experiments = response.result.data;
console.log( this.experiments);
this.experimentsLoading = false;

} catch (err) {
Expand Down
9 changes: 4 additions & 5 deletions src/components/germplasm/GermplasmTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</b-table-column>
<b-table-column field="accessionNumber" label="GID" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})" searchable>
<GermplasmLink
v-bind:germplasmUUID="GermplasmUtils.getBreedingInsightId(props.row.data.externalReferences)"
v-bind:germplasmUUID="BrAPIUtils.getBreedingInsightId(props.row.data.externalReferences)"
v-bind:germplasmGID="props.row.data.accessionNumber"
>
</GermplasmLink>
Expand Down Expand Up @@ -53,7 +53,7 @@
{{ props.row.data.additionalInfo.createdBy.userName }}
</b-table-column>
<b-table-column v-slot="props" :th-attrs="(column) => ({scope:'col'})">
<router-link v-bind:to="{name: 'germplasm-details', params: {programId: activeProgram.id, germplasmId: GermplasmUtils.getBreedingInsightId(props.row.data.externalReferences)}}">
<router-link v-bind:to="{name: 'germplasm-details', params: {programId: activeProgram.id, germplasmId: BrAPIUtils.getBreedingInsightId(props.row.data.externalReferences)}}">
Show Details
</router-link>
</b-table-column>
Expand All @@ -77,22 +77,21 @@ import {StringFormatters} from "@/breeding-insight/utils/StringFormatters";
import {TraitStringFormatters} from "@/breeding-insight/utils/TraitStringFormatters";
import ReportTable from "@/components/report/ReportTable.vue";
import {Program} from "@/breeding-insight/model/Program";
import {BrAPIService, BrAPIType} from "@/breeding-insight/service/BrAPIService";
import {Germplasm} from "@/breeding-insight/brapi/model/germplasm";
import {BiResponse} from "@/breeding-insight/model/BiResponse";
import ExpandableTable from "@/components/tables/expandableTable/ExpandableTable.vue";
import {PaginationController} from "@/breeding-insight/model/view_models/PaginationController";
import {Pedigree} from "@/breeding-insight/model/import/germplasm/Pedigree";
import GermplasmLink from '@/components/germplasm/GermplasmLink.vue'
import {GermplasmUtils} from '@/breeding-insight/utils/GermplasmUtils';
import {BrAPIUtils} from "@/breeding-insight/utils/BrAPIUtils";
import {CallStack} from "@/breeding-insight/utils/CallStack";
import {
GermplasmSort,
GermplasmSortField,
Sort
} from "@/breeding-insight/model/Sort";
import {UPDATE_GERMPLASM_SORT} from "@/store/sorting/mutation-types";
import {GermplasmService} from "@/breeding-insight/service/GermplasmService";
import { PaginationQuery } from '@/breeding-insight/model/PaginationQuery';
import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter";

Expand All @@ -113,7 +112,7 @@ import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter";
updateSort: UPDATE_GERMPLASM_SORT
})
},
data: () => ({Trait, StringFormatters, TraitStringFormatters, Pedigree, GermplasmUtils, Sort})
data: () => ({Trait, StringFormatters, TraitStringFormatters, Pedigree, GermplasmUtils, BrAPIUtils, Sort})
})
export default class GermplasmTable extends Vue {

Expand Down
1 change: 0 additions & 1 deletion src/components/trait/TraitDetailPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@

abbreviationsSynonymsString(synonymsMaxLength: number) : string | undefined {
let abbSyn = "";

if (this.data && this.data.synonyms && this.data.synonyms.length > 0) {
// Up to synonymsMaxLength synonyms will be shown before , ... cutoff
const synonyms = this.data.synonyms.slice(0, Math.min(this.data.synonyms.length, synonymsMaxLength)).join(", ");
Expand Down
15 changes: 12 additions & 3 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ import NotAuthorized from '@/views/NotAuthorized.vue'
import BrapiAuthorize from '@/views/BrAPI/BrapiAuthorize.vue'
import BrAPIInfo from '@/views/BrAPI/BrAPIInfo.vue'
import ProgramManagement from '@/views/program/ProgramManagement.vue'
import TrialsAndStudies from "@/views/trials-and-studies/TrialsAndStudies.vue";
import Trials from "@/views/trials-and-studies/Trials.vue";
import ExperimentDetails from "@/views/experiments-and-observations/ExperimentDetails";
import StudiesList from "@/views/trials-and-studies/StudiesList.vue";
import ObservationsList from '@/views/observations/ObservationsList.vue';
import AdminProgramManagement from '@/views/admin/AdminProgramManagement.vue'
Expand Down Expand Up @@ -357,7 +356,17 @@ const routes = [
},
component: GermplasmGenotypeView
}
]
]
},
{
path: '/programs/:programId/experiment/:experimentId',
name: 'experiment-details',
meta: {
title: 'Experiment Detail',
layout: layouts.userSideBar
},
component: ExperimentDetails,
beforeEnter: processProgramNavigation
},
{
path: '/programs/:programId/import',
Expand Down
Loading