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-2373 Add Delete Option to Germplasm Lists View #420

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
46 changes: 29 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/assets/scss/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ tr:nth-child(odd) td.db-filled {
margin-right: 10px;
}

.sub-entity-dataset-modal, .experiment-observations-download-button, .experiment-observation-add-collaborator-button, .experiment-observation-remove-collaborator-button {
.sub-entity-dataset-modal, .experiment-observations-download-button, .experiment-observation-add-collaborator-button, .experiment-observation-remove-collaborator-button, .germplasm-list-deletion-button {
.modal {
.modal-card {
width: $medium-modal-content-width;
Expand Down
2 changes: 1 addition & 1 deletion src/breeding-insight/dao/GermplasmDAO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 5 additions & 4 deletions src/breeding-insight/service/GermplasmService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -34,7 +35,7 @@ export class GermplasmService {
{ listDbId, listName, ...brapiFilters }: GermplasmFilter):
Promise<BiResponse> {
//Form the query params including sorting, pagination, and filtering
let params: any = { ...brapiFilters };
let params: any = {listDbId: listDbId, ...brapiFilters };

if (sort.field) {
params['sortField'] = sort.field;
Expand Down Expand Up @@ -67,8 +68,8 @@ export class GermplasmService {
}

//Get the list germplasm
const {data} = await api.call({
url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/germplasm/lists/${listId}/records`,
const {data}: any = await api.call({
url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/brapi/v2/germplasm`,
method: 'get',
params: params
}) as Response;
Expand Down
93 changes: 93 additions & 0 deletions src/breeding-insight/service/ListService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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 {BiResponse} from "@/breeding-insight/model/BiResponse";
import {SortOrder} from "@/breeding-insight/model/Sort";
import * as api from "@/util/api";
import {ListType} from "@/util/ListType";

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}/brapi/v2/lists/${listDbId}`,
method: 'delete',
params: { hardDelete: true }
mlm483 marked this conversation as resolved.
Show resolved Hide resolved
}) 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 since http clients can be configured to
// automatically throw an error if the response has no content
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<T>(listType: ListType,
programId: string,
sort: { field: T, order: SortOrder },
pagination: {pageSize: number, page: number},
filters?: any): Promise<BiResponse> {
if (!programId) throw 'Program ID required';

// Set list type, sort, and pagination
let params: any = { listType };

if(filters) {
params = { listType, ...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}/brapi/v2/lists`,
method: 'get',
params: params
});

return new BiResponse(data);

} catch (error) {
throw error;
}
}
}
89 changes: 89 additions & 0 deletions src/components/germplasm/GermplasmListDeletionlModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<!--
- 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>
<ConfirmationModal
v-bind:unique-id="listDbId"
v-bind:modal-title="modalTitle"
v-bind:confirmedAction="deleteList"
v-bind:active="active"
modal-class="germplasm-list-deletion-button"
v-on:deactivate="cancelDelete"
>
<template #form>
<p>Are you sure you want to delete the germplasm list? Note that deleting a germplasm list will not delete the associated germplasm records.</p>
</template>
<slot />
</ConfirmationModal>
</template>

<script lang="ts">
import {Component, Vue, Prop} from "vue-property-decorator";
import {validationMixin} from "vuelidate";
import {mapGetters} from "vuex";
import {Program} from "@/breeding-insight/model/Program";
import {AlertTriangleIcon} from 'vue-feather-icons';
import {Trial} from "@/breeding-insight/model/Trial";
import ConfirmationModal from "@/components/modals/ConfirmationModal.vue";
import {ExperimentService} from "@/breeding-insight/service/ExperimentService";
import { Collaborator } from '@/breeding-insight/model/Collaborator';
import { ListService } from '@/breeding-insight/service/ListService';

@Component({
mixins: [validationMixin],
components: {ConfirmationModal, AlertTriangleIcon},
computed: {
...mapGetters([
'activeProgram'
])
}
})
export default class GermplasmListDeletionlModal extends Vue {

@Prop()
active!: boolean;
@Prop()
listDbId!: string;
@Prop()
modalTitle?: string;

private activeProgram?: Program;

async deleteList(): Promise<void> {
if (this.activeProgram) {
try {
// Call the service method and await its completion
await ListService.deleteList(this.activeProgram.id, this.listDbId)

// If the above call doesn't throw an error, we assume it was successful
// Emit the event after the promise is resolved
this.$emit('list-deleted');

} catch (error) {
// Handle any errors that might occur during the async operation
console.error('Error deleting the list:', error);
// Optionally emit an error event or handle the error in some way
this.$emit('show-error-notification', `Error while trying to delete the list`);
}
}
}

cancelDelete(){
this.$emit('deactivate');
}
}
</script>
2 changes: 1 addition & 1 deletion src/components/germplasm/GermplasmTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
3 changes: 2 additions & 1 deletion src/config/AppAbility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {Ability, AbilityClass} from '@casl/ability';

type Actions = 'manage' | 'create' | 'read' | 'update' | 'delete' | 'archive' | 'access' | 'submit';
type Subjects = 'ProgramUser' | 'Location' | 'User' | 'AdminSection' | 'Trait' | 'Import' | 'ProgramConfiguration' | 'Submission'
| 'Experiment' | 'Germplasm' | 'Ontology' | 'SampleManagement' | 'ProgramAdministration' | 'JobManagement' | 'Collaborator' | 'BrAPI' ;
| 'Experiment' | 'Germplasm' | 'Ontology' | 'SampleManagement' | 'ProgramAdministration' | 'JobManagement' | 'Collaborator' | 'BrAPI'
| 'List';

export type AppAbility = Ability<[Actions, Subjects]>;
export const AppAbility = Ability as AbilityClass<AppAbility>;
2 changes: 2 additions & 0 deletions src/config/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const rolePermissions: Record<string, DefinePermissions> = {
can('access', 'BrAPI');
can('access', 'JobManagement');
can('manage', 'Collaborator');
can('delete', 'List');

},
systemadministrator(user, { can }) {
Expand All @@ -79,6 +80,7 @@ const rolePermissions: Record<string, DefinePermissions> = {
can('access', 'BrAPI');
can('access', 'JobManagement');
can('manage', 'Collaborator');
can('delete', 'List');

}
};
Expand Down
2 changes: 1 addition & 1 deletion src/store/filtering/getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<FilterState, RootState> = {
// germplasm
Expand Down
Loading
Loading