<template> <div> <base-toaster :open="toasterIsOpen" @close="hideDialog" > <div class="flex justify-between items-center"> <font-awesome-icon class="ml-3" icon="fa-solid fa-thumbs-up " size="lg" /> <h4>Request submitted successfully!</h4> <button class="btn btn-outline" @click="hideDialog" > <font-awesome-icon icon="fa-regular fa-circle-xmark" size="2x" /> </button> </div> </base-toaster> <div> <form class="form-horizontal" autocomplete="off" @submit.prevent="proteinExperimentalHandler" > <div v-if="isLoading"> <base-spinner /> </div> <div class="form-group"> <div class="flex flex-col px-8 space-y-4"> <div v-if="mode === 'Add'" class="w-full" :class="{ invalid: !experimentalEvidance.isValid }" > <h1 class=" text-left font-bold mb-2 text-xl sm:text-2xl font-montserrat " > Add Experimental Evidence </h1> <!-- <div v-for="options in proteinExpEvidenceData" :key="options.id"> <input :id="options.id" v-model="experimentalEvidance.value" type="checkbox" class="h-6 w-6" :name="options" :value="options.type" @blur="clearValidity('experimentalEvidance')" /> <label class="mx-3" :for="options.id">{{ options.type }}</label> </div> --> <select id="expTyp" v-model.trim="experimentalEvidance.value" class="form-control" @blur="clearValidity('experimentalEvidance')" > <option v-for="options in proteinExpEvidenceData" :key="options.id" :value="options.type" > {{ options.type==='frap' ? 'FRAP' :formatValue(options.type) }} </option> </select> <p v-if="!experimentalEvidance.isValid" class="text-red-500 mt-2" > {{ experimentalEvidanceMsg }} </p> </div> <div v-if="mode === 'Remove'" class="w-full" :class="{ invalid: !deleteExperimentalEvidance.isValid }" > <div v-if="!data"> <h1 class=" text-left font-bold mb-2 text-xl sm:text-2xl font-montserrat " > This protein do not have any Experimental Evidance data to remove. </h1> </div> <div v-else> <h1 class=" text-left font-bold mb-2 text-xl sm:text-2xl font-montserrat " > Remove Experimental Evidence. </h1> <div v-for="(item, index) in data" :key="index" class="flex space-x-4" > <input :id="index" v-model.trim="deleteExperimentalEvidance.value" type="radio" :value="item" @blur="clearValidity('deleteExperimentalEvidance')" > <div class="flex items-center"> <label :for="index"> {{ item === 'frap' ? 'FRAP' : formatValue(item) }} </label> </div> </div> </div> <p v-if="!deleteExperimentalEvidance.isValid" class="text-red-500 mt-2" > {{ experimentalEvidanceMsg }} </p> </div> <div class="w-full" :class="{ invalid: !comment.isValid }" > <textarea v-if="(!data && mode === 'Add') || data" v-model.trim="comment.value" class=" form-control block px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none " rows="5" :placeholder=" role === 'Maintainer' ? 'Reason (Optional)' : 'Reason' " @blur="clearValidity('comment')" /> <p v-if="!comment.isValid" class="text-red-500" > Reason must not be empty or less than 50 characters. </p> <p v-if="serverError" class="text-danger font-bold" > {{ errMessage }} </p> </div> <div class="space-x-4 w-2/3"> <button v-if="(!data && mode === 'Add') || data" class=" text-white bg-blue-600 hover:bg-blue-700 focus:ring-2 focus:ring-blue-300 rounded-lg inline-flex items-center px-5 py-2.5 text-center font-bold " type="submit" > {{ mode === "Add" ? "Add" : "Remove" }} </button> <button class=" bg-white hover:bg-gray-200 focus:ring-2 focus:ring-gray-300 rounded-lg border border-gray-300 px-5 py-2.5 hover:text-gray-900 font-bold " type="button" @click="close" > Cancel </button> </div> </div> </div> </form> </div> </div> </template> <script> let host = require('../js/const').apiHost; import BaseSpinner from '../UI/BaseSpinner.vue'; import BaseToaster from '../UI/BaseToaster.vue'; import _ from 'lodash' export default { components: { BaseSpinner, BaseToaster }, props: ['data', 'uniprotId', 'canonicalId', 'mode'], data() { return { isLoading: false, toasterIsOpen: false, formIsValid: true, experimentalEvidance: { value: 'Select', isValid: true, }, deleteExperimentalEvidance: { value: '', isValid: true, }, comment: { value: '', isValid: true, }, proteinExpEvidenceData: [ { id: '1', type: 'Select', displayData:'Select' }, { id: '2', type: 'in_vitro', displayData:'In Vitro' }, { id: '3', type: 'in_vivo', displayData:'In Vivo' }, { id: '4', type: 'in_cellulo', displayData:'In Cellulo' }, { id: '5', type: 'mass_spectrometry', displayData:'Mass Spectrometry' }, { id: '6', type: 'colocalization', displayData:'Colocalization' }, { id: '7', type: 'frap', displayData:'FRAP' }, { id: '8', type: 'others', displayData:'Others' }, ], experimentalEvidanceMsg: '', serverError: false, errMessage: '', }; }, computed: { jwt: function () { return this.$store.getters['User/jwt']; }, role: function () { return this.$store.getters['User/userRole']; }, }, methods: { formatValue(input){ let val = _.startCase(input); return val; }, showDialog() { this.toasterIsOpen = true; }, hideDialog() { this.toasterIsOpen = false; }, close() { this.$emit('closeProteinExpEvidence'); }, clearValidity(input) { this[input].isValid = true; }, validateForm() { this.formIsValid = true; if (this.mode === 'Add') { if ( this.experimentalEvidance.value === '' || this.experimentalEvidance.value === 'Select' ) { this.experimentalEvidanceMsg = 'Please select an Experimental evidence value!'; this.experimentalEvidance.isValid = false; this.formIsValid = false; } let findExpData; if (this.data) { for (let presentExp of this.data) { if (this.experimentalEvidance.value === presentExp) { findExpData = presentExp; } } } if (findExpData) { this.experimentalEvidanceMsg = `Selected experimental evidence ${findExpData.toUpperCase()} is already in this protein. Please select another value to add.`; this.experimentalEvidance.isValid = false; this.formIsValid = false; } } else { if (this.deleteExperimentalEvidance.value === '') { this.experimentalEvidanceMsg = 'Please select an Experimental evidence value to remove!'; this.deleteExperimentalEvidance.isValid = false; this.formIsValid = false; } } if ( (this.comment.value === '' || this.comment.value.length < 50) && this.role !== 'Maintainer' ) { this.comment.isValid = false; this.formIsValid = false; } }, async proteinExperimentalHandler() { this.validateForm(); if (!this.formIsValid) { return; } if (this.isDev) { host = require('../js/const').devApiHost; } let url = `${host}/api/update-items`; let data; let entityId = `${this.canonicalId}==${this.uniprotId}`; if (this.mode === 'Add') { if (this.role === 'Maintainer') { data = { Entity: 'condensate_protein', EntityId: entityId, ChangeOperation: 'add', Attribute: 'exp_evidence', SubmissionComments: 'Maintainer do not need to provide a reason for such change at the moment!', Value: this.experimentalEvidance.value, Status: 'accepted', }; } else { data = { Entity: 'condensate_protein', EntityId: entityId, ChangeOperation: 'add', Attribute: 'exp_evidence', SubmissionComments: this.comment.value, Value: this.experimentalEvidance.value, Status: 'requested', }; } } else { if (this.role === 'Maintainer') { data = { Entity: 'condensate_protein', EntityId: entityId, ChangeOperation: 'remove', Attribute: 'exp_evidence', SubmissionComments: 'Maintainer do not need to provide a reason for such change at the moment!', Value: this.deleteExperimentalEvidance.value, Status: 'accepted', }; } else { data = { Entity: 'condensate_protein', EntityId: entityId, ChangeOperation: 'remove', Attribute: 'exp_evidence', SubmissionComments: this.comment.value, Value: this.deleteExperimentalEvidance.value, Status: 'requested', }; } } this.isLoading = true; try { await this.axios.post( url, { data: data }, { headers: { Authorization: `Bearer ${this.jwt}`, }, } ); this.isLoading = false; this.toasterIsOpen = true; this.experimentalEvidance.value = 'Select'; this.deleteExperimentalEvidance.value = ''; this.comment.value = ''; this.serverError = false; this.errMessage = ''; this.$emit('update-key'); setTimeout(() => { this.toasterIsOpen = false; }, 2000); } catch (e) { console.error(e); this.isLoading = false; this.serverError = true; this.errMessage = e.message || 'Something went wrong, please try again later!'; } }, }, }; </script> <style scoped> .invalid h1, .invalid label { color: red; } .invalid input, .invalid textarea, .invalid select { border: 1px solid red; } </style>