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-1198] All Experiments Table #254

Merged
merged 2 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions src/assets/scss/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ table tr.is-edited + .detail {
}
}

.table td.fixed-width-wrapped {
word-break: break-word;
width: 25%;
}

.table.is-striped tbody tr:not(.is-edited):nth-child(2n).is-new {
background-color: $success-light;
Expand Down
4 changes: 2 additions & 2 deletions src/breeding-insight/dao/TrialDAO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import { Result, Err, Success, ResultGenerator } from "@/breeding-insight/model/

export class TrialDAO {

static async getAll(programId: string, paginationQuery: PaginationQuery, full : boolean): Promise<Result<Error, BiResponse>> {
static async getAll(programId: string, paginationQuery: PaginationQuery, full : boolean, metadata: boolean): Promise<Result<Error, BiResponse>> {
try {
// TODO: update pageSize setting when we can do backend brapi sorting
const { data } = await api.call({
url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/brapi/v2/trials`,
method: 'get',
params: { full, pageSize: 1000000 }
params: { full, pageSize: 1000000, metadata: true }
}) as Response;

return ResultGenerator.success(new BiResponse(data));
Expand Down
10 changes: 7 additions & 3 deletions src/breeding-insight/service/TrialService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {Result, Err, Success, ResultGenerator } from "@/breeding-insight/model/R

export class TrialService {

static async getAll(programId: string, paginationQuery?: PaginationQuery, full?: boolean): Promise<Result<Error, [Trial[], Metadata]>> {
static async getAll(programId: string, paginationQuery?: PaginationQuery, full?: boolean, metadata?:boolean): Promise<Result<Error, [Trial[], Metadata]>> {

if (paginationQuery === undefined){
paginationQuery = new PaginationQuery(0, 0, true);
Expand All @@ -34,10 +34,14 @@ export class TrialService {
full = false;
}

if (metadata === undefined) {
metadata = true;
}

try {
if(!programId) throw new Error('missing or invalid program id');

let response = await TrialDAO.getAll(programId, paginationQuery, full) as Result<Error, BiResponse>;
let response = await TrialDAO.getAll(programId, paginationQuery, full, metadata) as Result<Error, BiResponse>;
if(response.isErr()) throw response.value;

const frontendModel = (res: BiResponse): [Trial[], Metadata] => {
Expand All @@ -46,7 +50,7 @@ export class TrialService {

data = PaginationController.mockSortRecords(data);
trials = data.map((trial: any) => {
return new Trial(trial.trialDbId, trial.trialName, trial.active);
return trial as Trial;
});

let newPagination;
Expand Down
163 changes: 163 additions & 0 deletions src/components/experiments/ExperimentsObservationsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<!--
- 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.
-->

<template>
<section id="experimentsObservationsTableLabel">

<div class="is-clearfix"></div>

<ExpandableTable
v-bind:records.sync="experiments"
v-bind:loading="this.experimentsLoading"
v-bind:pagination="experimentsPagination"
v-on:show-error-notification="$emit('show-error-notification', $event)"
v-on:paginate="paginationController.updatePage($event)"
v-on:paginate-toggle-all="paginationController.toggleShowAll()"
v-on:paginate-page-size="paginationController.updatePageSize($event)"
>
<b-table-column label="Title" cell-class="fixed-width-wrapped" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
{{ props.row.data.trialName }}
</b-table-column>
<b-table-column label="Status" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
{{ getStatus(props.row.data.active) }}
</b-table-column>
<b-table-column label="Date Created" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
{{ }}
</b-table-column>
<b-table-column label="Created By" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
{{ }}
</b-table-column>
<b-table-column label="Datasets" cell-class="fixed-width-wrapped" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
<template v-for="dataset in props.row.data.additionalInfo.datasets">
<span v-bind:key="dataset" class="tag is-info is-normal mr-1">{{ dataset }}</span>
</template>
</b-table-column>
<b-table-column field="data.listDbId" sortable v-slot="props" :th-attrs="(column) => ({scope:'col'})">
<a href="#" v-on:click="activateExtensionSelect(props.row.data.listDbId)">
Download
</a>
</b-table-column>

<template v-slot:emptyMessage>
<p class="has-text-weight-bold">
No experiments and observations are currently defined for this program.
</p>
</template>
</ExpandableTable>
</section>
</template>

<script lang="ts">
import {Component, Prop, Vue, Watch} from 'vue-property-decorator'
import {validationMixin} from 'vuelidate';
import { mapGetters } from 'vuex'
import {Program} from "@/breeding-insight/model/Program";
import {TrialService} from "@/breeding-insight/service/TrialService";
import EmptyTableMessage from "@/components/tables/EmtpyTableMessage.vue";
import TableColumn from "@/components/tables/TableColumn.vue";
import {Metadata, Pagination} from "@/breeding-insight/model/BiResponse";
import {PaginationController} from "@/breeding-insight/model/view_models/PaginationController";
import {PaginationQuery} from "@/breeding-insight/model/PaginationQuery";
import {Trial} from '@/breeding-insight/model/Trial'
import {Result, Err, Success, ResultGenerator } from "@/breeding-insight/model/Result";
import ExpandableTable from '@/components/tables/expandableTable/ExpandableTable.vue';
import {FileType} from "@/breeding-insight/model/FileType";
import SelectModal from "@/components/modals/SelectModal.vue";

@Component({
mixins: [validationMixin],
components: { ExpandableTable, EmptyTableMessage, TableColumn, SelectModal},
computed: {
...mapGetters([
'activeProgram'
])
}
})
export default class ExperimentsObservationsTable extends Vue {

private activeProgram?: Program;
private experiments: Trial[] = [];
private experimentsPagination?: Pagination = new Pagination();
private programName: string = "Program Name";

private experimentsLoading = true;

private paginationController: PaginationController = new PaginationController();

private experimentDownloadTitle = 'Download Experiment';
private experimentDownloadSubtitle = 'File Format';
private modalActive: boolean = false;
//private fileExtension: string;
//private selectedExperimentDbId: string;
private fileOptions = Object.values(FileType);

mounted() {
this.getExperiments();
}

@Watch('paginationController', { deep: true})
async getExperiments() {
let paginationQuery: PaginationQuery = PaginationController.getPaginationSelections(
this.paginationController.currentPage,
this.paginationController.pageSize,
this.paginationController.showAll);

this.paginationController.setCurrentCall(paginationQuery);

try {
const response: Result<Error, [Trial[], Metadata]> = await TrialService.getAll(this.activeProgram!.id!, paginationQuery);
if(response.isErr()) throw response.value;
let [experiments, metadata] = response.value;

if (this.paginationController.matchesCurrentRequest(metadata.pagination)) {
this.experiments = experiments;
this.experimentsPagination = metadata.pagination;
}
} catch (err) {
// Display error that experiments cannot be loaded
this.$emit('show-error-notification', 'Error while trying to load experiments');
} finally {
this.experimentsLoading=false;
}
}

activateExtensionSelect(experimentDbId: string){
this.modalActive = true;
this.selectedExperimentDbId = experimentDbId;
}

cancelDownload(){
this.modalActive = false;
this.selectedExperimentDbId = "";
this.fileExtension = "";
}

setFileExtension(value){
this.fileExtension = value;
}

getStatus(active){
if (active) {
return "active";
} else {
return "archived";
}
}

}

</script>
4 changes: 2 additions & 2 deletions src/components/layouts/UserSideBarLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@
</li>
<li>
<router-link
v-bind:to="{name: 'trials-studies', params: {programId: activeProgram.id}}"
v-bind:to="{name: 'experiments-observations', params: {programId: activeProgram.id}}"
>
Trials and Studies <span class="ml-2 tag is-warning">Beta</span>
Experiments & Observations
</router-link>
</li>
</ul>
Expand Down
32 changes: 6 additions & 26 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import ProgramConfiguration from "@/views/program/ProgramConfiguration.vue";
import JobManagement from '@/views/program/JobManagement.vue';
import GermplasmPedigreesView from "@/components/germplasm/GermplasmPedigreesView.vue";
import ImportExperiment from "@/views/import/ImportExperiment.vue";
import ExperimentsAndObservations from "@/views/experiments-and-observations/ExperimentsAndObservations.vue";

Vue.use(VueRouter);

Expand Down Expand Up @@ -171,35 +172,14 @@ const routes = [
component: StudiesList
},
{
path: '/programs/:programId/trials-studies',
name: 'trials-studies',
path: '/programs/:programId/experiments-observations',
name: 'experiments-observations',
meta: {
title: 'Trials and Studies',
title: 'Experiments & Observations',
layout: layouts.userSideBar
},
component: TrialsAndStudies,
redirect: {name: 'trials-list'},
beforeEnter: processProgramNavigation,
children: [
{
path: 'studies',
name: 'studies-list',
meta: {
title: 'Studies',
layout: layouts.userSideBar
},
component: StudiesList
},
{
path: 'trials',
name: 'trials-list',
meta: {
title: 'Trials',
layout: layouts.userSideBar
},
component: Trials
}
]
component: ExperimentsAndObservations,
beforeEnter: processProgramNavigation
},
{
path: '/programs/:programId/program-management',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<!--
- 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.
-->

<template>
<div class="experiments-observations">
<h1 class="title">
Experiments & Observations
</h1>
<button
v-if="$ability.can('create', 'Import')"
class="button is-primary is-pulled-right has-text-weight-bold"
v-on:click="$router.push({name: 'experiment-import', params: {programId: activeProgram.id}})"
>
<span class="icon is-small">
<PlusCircleIcon
size="1.5x"
aria-hidden="true"
/>
</span>
<span>
Import Experiments & Observations
</span>
</button>
<ExperimentsObservationsTable
v-on:show-success-notification="$emit('show-success-notification', $event)"
v-on:show-error-notification="$emit('show-error-notification', $event)"
>
</ExperimentsObservationsTable>
</div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import ExperimentsObservationsTable from '@/components/experiments/ExperimentsObservationsTable.vue';
import {PlusCircleIcon} from 'vue-feather-icons'
import {mapGetters} from "vuex";
import {Program} from "@/breeding-insight/model/Program";
import TrialsAndStudiesBase from "@/components/trials/TrialsAndStudiesBase.vue";

@Component({
components: {
ExperimentsObservationsTable, PlusCircleIcon
},
computed: {
...mapGetters([
'activeProgram'
])
}
})
export default class ExperimentsAndObservations extends TrialsAndStudiesBase {

private activeProgram?: Program;

}
</script>