From 28d86bae1b27df3b427639658d62757eefc303f1 Mon Sep 17 00:00:00 2001 From: dmeidlin <14339308+dmeidlin@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:38:56 -0500 Subject: [PATCH 1/7] add delete option to germplasm list management --- src/breeding-insight/dao/GermplasmDAO.ts | 2 +- .../{GermplasmFilter.ts => ListFilter.ts} | 11 +- .../service/GermplasmService.ts | 5 +- src/breeding-insight/service/ListService.ts | 157 +++++++++++ .../germplasm/GermplasmListDeletionlModal.vue | 89 +++++++ src/components/germplasm/GermplasmTable.vue | 2 +- src/store/filtering/getters.ts | 2 +- src/store/filtering/index.ts | 2 +- src/store/filtering/mutations.ts | 2 +- src/store/filtering/types.ts | 2 +- src/util/ListType.ts | 2 +- src/views/germplasm/GermplasmByList.vue | 252 +++++++++++++----- src/views/germplasm/GermplasmLists.vue | 30 +-- 13 files changed, 470 insertions(+), 88 deletions(-) rename src/breeding-insight/model/{GermplasmFilter.ts => ListFilter.ts} (86%) create mode 100644 src/breeding-insight/service/ListService.ts create mode 100644 src/components/germplasm/GermplasmListDeletionlModal.vue diff --git a/src/breeding-insight/dao/GermplasmDAO.ts b/src/breeding-insight/dao/GermplasmDAO.ts index af5eeb1f2..33072750b 100644 --- a/src/breeding-insight/dao/GermplasmDAO.ts +++ b/src/breeding-insight/dao/GermplasmDAO.ts @@ -30,7 +30,7 @@ export class GermplasmDAO { config.url = `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/brapi/v2/lists`; config.method = 'get'; config.programId = programId; - config.params = {listType: ListType.Germplasm}; + config.params = {listType: ListType.GERMPLASM}; if (paginationQuery.page) config.params.page = paginationQuery.page - 1; if (paginationQuery.pageSize) config.params.pageSize = paginationQuery.pageSize; diff --git a/src/breeding-insight/model/GermplasmFilter.ts b/src/breeding-insight/model/ListFilter.ts similarity index 86% rename from src/breeding-insight/model/GermplasmFilter.ts rename to src/breeding-insight/model/ListFilter.ts index 0a0644472..e5bd51ffb 100644 --- a/src/breeding-insight/model/GermplasmFilter.ts +++ b/src/breeding-insight/model/ListFilter.ts @@ -18,14 +18,17 @@ import {GermplasmSortField} from "@/breeding-insight/model/Sort"; import {BaseFilter} from "@/breeding-insight/model/BaseFilter"; -export enum GermplasmBIField { +export enum ListBIField { ListDbId = "listDbId", ListName = "listName", } -export class GermplasmFilter extends BaseFilter { - [GermplasmBIField.ListDbId]: string; - [GermplasmBIField.ListName]: string; +export class ListFilter extends BaseFilter { + [ListBIField.ListDbId]: string; + [ListBIField.ListName]: string; +} + +export class GermplasmFilter extends ListFilter { [GermplasmSortField.AccessionNumber]: string; [GermplasmSortField.DefaultDisplayName]: string; [GermplasmSortField.BreedingMethod]: string; diff --git a/src/breeding-insight/service/GermplasmService.ts b/src/breeding-insight/service/GermplasmService.ts index 7049e37f2..4f943b413 100644 --- a/src/breeding-insight/service/GermplasmService.ts +++ b/src/breeding-insight/service/GermplasmService.ts @@ -24,7 +24,8 @@ import {Germplasm} from "@/breeding-insight/brapi/model/germplasm"; import {Result, ResultGenerator} from "@/breeding-insight/model/Result"; import {SortOrder} from "@/breeding-insight/model/Sort"; import * as api from "@/util/api"; -import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter"; +import {GermplasmFilter} from "@/breeding-insight/model/ListFilter"; + export class GermplasmService { @@ -67,7 +68,7 @@ export class GermplasmService { } //Get the list germplasm - const {data} = await api.call({ + const {data}: any = await api.call({ url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/germplasm/lists/${listId}/records`, method: 'get', params: params diff --git a/src/breeding-insight/service/ListService.ts b/src/breeding-insight/service/ListService.ts new file mode 100644 index 000000000..bf3b38a7c --- /dev/null +++ b/src/breeding-insight/service/ListService.ts @@ -0,0 +1,157 @@ +/* + * 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 {GermplasmList} from "@/breeding-insight/model/GermplasmList"; +import {BiResponse, Metadata} from "@/breeding-insight/model/BiResponse"; +import {PaginationQuery} from "@/breeding-insight/model/PaginationQuery"; +import {PaginationUtilities} from "@/breeding-insight/model/view_models/PaginationUtilities"; +import {GermplasmDAO} from "@/breeding-insight/dao/GermplasmDAO"; +import {Germplasm} from "@/breeding-insight/brapi/model/germplasm"; +import {Result, ResultGenerator} from "@/breeding-insight/model/Result"; +import {GermplasmListSortField, SortOrder} from "@/breeding-insight/model/Sort"; +import * as api from "@/util/api"; +import {ListType} from "@/util/ListType"; +import {ListFilter} from "@/breeding-insight/model/ListFilter"; + +export class ListService { + static async deleteList(programId: string | undefined, listDbId: string) { + if (programId == undefined) { + throw new Error("Not valid program"); + } + try { + const response = await api.call({ + url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/deltalists/${listDbId}`, + method: 'delete', + params: { hardDelete: true } + }) as Response; + + // If we get here, it means the call was successful (likely 200 OK) + return new BiResponse({ success: true }); + + } catch (error) { + // Check if the error is actually a 204 No Content response + if (error.response && error.response.status === 204) { + // This is actually a successful deletion + return new BiResponse({ success: true }); + } + + // For other errors, log and rethrow + console.error('Error in deleteList:', error); + throw error; + } + } + + static async getLists(listType: ListType, + programId: string, + sort: { field: T, order: SortOrder }, + pagination: {pageSize: number, page: number}, + filters?: any): Promise { + if (!programId) throw 'Program ID required'; + + // Set list type, sort, and pagination + let params: any = { listType }; + if(filters) { + params = filters; + } + + if (sort.field) { + params['sortField'] = sort.field; + } + if (sort.order) { + params['sortOrder'] = sort.order; + } + if (pagination.page || pagination.page == 0) { //have to account for 0-index pagination since 0 falsy + params['page'] = pagination.page; + } + if (pagination.pageSize) { + params['pageSize'] = pagination.pageSize; + } + + // Make the GET call + try { + const { data }: any = await api.call({ + url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/deltalists`, + method: 'get', + params: params + }); + + return new BiResponse(data); + + } catch (error) { + throw error; + } + } + + static async getAllInList( + listType: ListType, + programId: string, + sort: { field: T, order: SortOrder }, + pagination: { pageSize: number, page: number }, + { listDbId, listName, ...brapiFilters }: U): Promise { + // Form the query params including list type, sorting, pagination, and filtering + let params: any = { listType, ...brapiFilters }; + + if (sort.field) { + params['sortField'] = sort.field; + } + if (sort.order) { + params['sortOrder'] = sort.order; + } + if (pagination.page || pagination.page == 0) { //have to account for 0-index pagination since 0 falsy + params['page'] = pagination.page; + } + if (pagination.pageSize) { + params['pageSize'] = pagination.pageSize; + } + + try { + let listId: String = ''; + + if(listName && !listDbId) { + //Get the list db id + const paginationQuery = new PaginationQuery(0, 20, true); + //const {result: {data: lists}} = await GermplasmDAO.getAllLists(programId, paginationQuery); + const {result: {data: lists}} = await ListService.getLists( + ListType.GERMPLASM, + programId, + { field: GermplasmListSortField.Name, order: SortOrder.Descending }, + new PaginationQuery(0, 200, true)); + const matchingLists = lists.filter((list: any) => list.listName === listName); + if (matchingLists.length === 0) throw Error("List name is not valid for this program"); + if (matchingLists.length > 1) throw Error("List name must be unique"); + listId = matchingLists[0].listDbId; + } else if(listDbId) { + listId = listDbId; + } else { + throw Error("Missing list id and name"); + } + + //Get the list germplasm + const { data }: any = await api.call({ + url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/deltalists/${listId}`, + method: 'get', + params: params + }) as Response; + + return new BiResponse(data); + + } catch(error) { + throw error; + } + } + +} diff --git a/src/components/germplasm/GermplasmListDeletionlModal.vue b/src/components/germplasm/GermplasmListDeletionlModal.vue new file mode 100644 index 000000000..4d1da73c7 --- /dev/null +++ b/src/components/germplasm/GermplasmListDeletionlModal.vue @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file diff --git a/src/components/germplasm/GermplasmTable.vue b/src/components/germplasm/GermplasmTable.vue index 974efb163..2691c40ba 100644 --- a/src/components/germplasm/GermplasmTable.vue +++ b/src/components/germplasm/GermplasmTable.vue @@ -94,7 +94,7 @@ import { } from "@/breeding-insight/model/Sort"; import {UPDATE_GERMPLASM_SORT} from "@/store/sorting/mutation-types"; import { PaginationQuery } from '@/breeding-insight/model/PaginationQuery'; -import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter"; +import {GermplasmFilter} from "@/breeding-insight/model/ListFilter"; @Component({ mixins: [validationMixin], diff --git a/src/store/filtering/getters.ts b/src/store/filtering/getters.ts index b8d8a81a9..cfb45523a 100644 --- a/src/store/filtering/getters.ts +++ b/src/store/filtering/getters.ts @@ -18,7 +18,7 @@ import {GetterTree} from 'vuex'; import {RootState} from "@/store/types"; import {FilterState} from "@/store/filtering/types"; -import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter"; +import {GermplasmFilter} from "@/breeding-insight/model/ListFilter"; export const getters: GetterTree = { // germplasm diff --git a/src/store/filtering/index.ts b/src/store/filtering/index.ts index 12cb5078b..c0b5b6dff 100644 --- a/src/store/filtering/index.ts +++ b/src/store/filtering/index.ts @@ -20,7 +20,7 @@ import {getters} from '@/store/filtering/getters'; import {mutations} from '@/store/filtering/mutations'; import {RootState} from '@/store/types'; import {FilterState} from "@/store/filtering/types"; -import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter"; +import {GermplasmFilter} from "@/breeding-insight/model/ListFilter"; export let state: FilterState; state = { diff --git a/src/store/filtering/mutations.ts b/src/store/filtering/mutations.ts index 8a6212a69..5976d9bc1 100644 --- a/src/store/filtering/mutations.ts +++ b/src/store/filtering/mutations.ts @@ -17,7 +17,7 @@ import {MutationTree} from 'vuex'; import {FilterState} from "@/store/filtering/types"; -import {GermplasmFilter} from "@/breeding-insight/model/GermplasmFilter"; +import {GermplasmFilter} from "@/breeding-insight/model/ListFilter"; import {UPDATE_GERMPLASM_FILTER} from "@/store/filtering/mutation-types"; export const mutations: MutationTree = { diff --git a/src/store/filtering/types.ts b/src/store/filtering/types.ts index 3d1c7b83f..6d9dd0daa 100644 --- a/src/store/filtering/types.ts +++ b/src/store/filtering/types.ts @@ -1,4 +1,4 @@ -import { GermplasmFilter } from "@/breeding-insight/model/GermplasmFilter"; +import { GermplasmFilter } from "@/breeding-insight/model/ListFilter"; export interface FilterState { // germplasm table diff --git a/src/util/ListType.ts b/src/util/ListType.ts index 09a2b11c6..23df7121f 100644 --- a/src/util/ListType.ts +++ b/src/util/ListType.ts @@ -16,5 +16,5 @@ */ export enum ListType { - Germplasm = "germplasm", + GERMPLASM = "germplasm", } diff --git a/src/views/germplasm/GermplasmByList.vue b/src/views/germplasm/GermplasmByList.vue index 821a852f0..69985c08c 100644 --- a/src/views/germplasm/GermplasmByList.vue +++ b/src/views/germplasm/GermplasmByList.vue @@ -18,45 +18,100 @@