Skip to content

Commit

Permalink
Merge pull request #34 from BBMRI-ERIC/feat/add_attachments
Browse files Browse the repository at this point in the history
Feat/add attachments
  • Loading branch information
svituz committed Sep 26, 2023
2 parents 0024972 + 18436d7 commit 668328b
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 74 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ module.exports = {
"semi": [
"error",
"never"
],
"key-spacing": [
"error", {
"beforeColon": false
}
]
}
}
2 changes: 1 addition & 1 deletion oidc_mock/config/clients.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"AllowAccessTokensViaBrowser": true,
"RedirectUris": ["http://localhost:8080/logged-in"],
"AllowedScopes": ["openid", "profile", "email", "permissions"],
"IdentityTokenLifetime": 3600,
"IdentityTokenLifetime": 36000,
"AccessTokenLifetime": 3600,
"ClientClaimsPrefix": ""
}
Expand Down
4 changes: 4 additions & 0 deletions src/assets/scss/bbmri.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ $default-text-color: white;

.btn-primary {
color: white;
}

.cursor-pointer {
cursor: pointer;
}
31 changes: 25 additions & 6 deletions src/components/NegotiationForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
v-for="section in accessCriteria.sections"
:key="section.name"
:title="section.label"
class="form-step border rounded px-2 py-3 mb-2"
class="form-step border rounded-2 px-2 py-3 mb-2"
>
<div
v-for="criteria in section.accessCriteria"
Expand All @@ -56,6 +56,14 @@
class="form-control"
:required="criteria.required"
/>
<input
v-else-if="criteria.type === 'file'"
accept=".pdf"
class="form-control"
:required="criteria.required"
:type="criteria.type"
@change="handleFileUpload($event, section.name, criteria.name)"
>
<input
v-else
v-model="negotiationCriteria[section.name][criteria.name]"
Expand All @@ -69,16 +77,21 @@
<div
v-for="section in accessCriteria.sections"
:key="section.name"
class="border input-group p-3 mb-3"
class="border rounded-2 input-group p-3 mb-2 mb-3"
>
<span class="mb-4 fs-4 fw-bold text-secondary">{{ section.label }}</span>
<span class="mb-3 fs-4 fw-bold text-secondary">{{ section.label.toUpperCase() }}</span>
<div
v-for="criteria in section.accessCriteria"
:key="criteria.name"
class="input-group mb-3"
class="input-group mb-2"
>
<label class="me-2 fw-bold">{{ criteria.label }}:</label>
<span>{{ negotiationCriteria[section.name][criteria.name] }}</span>
<span v-if="isAttachment(negotiationCriteria[section.name][criteria.name])">
{{ negotiationCriteria[section.name][criteria.name].name }}
</span>
<span v-else>
{{ negotiationCriteria[section.name][criteria.name] }}
</span>
</div>
</div>
</tab-content>
Expand Down Expand Up @@ -170,7 +183,7 @@ export default {
await this.createNegotiation({
data: {
requests: [this.requestId],
payload: this.negotiationCriteria
payload: this.negotiationCriteria,
}
}).then((negotiationId) => {
if (negotiationId) {
Expand All @@ -180,6 +193,12 @@ export default {
}
})
},
isAttachment(value) {
return value instanceof File || value instanceof Object
},
handleFileUpload(event, section, criteria) {
this.negotiationCriteria[section][criteria] = event.target.files[0]
},
showNotification(variant, header, body) {
this.notificationVariant = variant
this.notificationHeader = header
Expand Down
2 changes: 1 addition & 1 deletion src/config/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ const MESSAGE_STATUS = {
}


export { dateFormat, ROLES, MESSAGE_STATUS }
export { MESSAGE_STATUS, ROLES, dateFormat }
3 changes: 2 additions & 1 deletion src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import router from "./router"
import store from "./store"
import { sync } from "vuex-router-sync"
import { library } from "@fortawesome/fontawesome-svg-core"
import { faPencil, faSpinner, faTrash } from "@fortawesome/free-solid-svg-icons"
import { faDownload, faPencil, faSpinner, faTrash } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"
import "bootstrap/dist/css/bootstrap.css"
import "bootstrap-vue-next/dist/bootstrap-vue-next.css"
Expand All @@ -13,6 +13,7 @@ import "bootstrap"
library.add(faSpinner)
library.add(faPencil)
library.add(faTrash)
library.add(faDownload)

const app = createApp(App)

Expand Down
78 changes: 59 additions & 19 deletions src/store/actions.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import axios from "axios"
import { ROLES } from "@/config/consts"
import axios from "axios"

let BASE_API_PATH = "/api/v3"
const ACCESS_CRITERIA_PATH = `${BASE_API_PATH}/access-criteria/`
const REQUESTS_PATH = `${BASE_API_PATH}/requests`
const NEGOTIATION_PATH = `${BASE_API_PATH}/negotiations`
const USER_PATH = `${BASE_API_PATH}/users/roles`
const ATTACHMENTS_PATH = `${BASE_API_PATH}/attachments`

function getBearerHeaders(token) {
return {
Expand Down Expand Up @@ -34,7 +35,7 @@ export default {
})
},
retrieveAccessCriteriaByResourceId({ state, commit }, { resourceId }) {
return axios.get(`${ACCESS_CRITERIA_PATH}`, {headers : getBearerHeaders(state.oidc.access_token), params : {resourceId : resourceId}})
return axios.get(`${ACCESS_CRITERIA_PATH}`, {headers: getBearerHeaders(state.oidc.access_token), params: {resourceId: resourceId}})
.then((response) => {
return response.data
})
Expand All @@ -44,17 +45,41 @@ export default {
})

},
createNegotiation({ state }, { data }) {
return axios.post(NEGOTIATION_PATH, data, {headers : getBearerHeaders(state.oidc.access_token)})
async createNegotiation({ state, commit }, { data }) {
data.attachments = []
for (const [sectionName, criteriaList] of Object.entries(data.payload)) {
for (const [criteriaName, criteriaValue] of Object.entries(criteriaList)) {
if (criteriaValue instanceof File) {
const formData = new FormData()
formData.append("file", criteriaValue)
const uploadFileHeaders = { headers: getBearerHeaders(state.oidc.access_token) }

uploadFileHeaders["Content-type"] = "multipart/form-data"

const attachmentsIds = await axios.post("/api/v3/attachments", formData, uploadFileHeaders)
.then((response) => {
return response.data
})
.catch(() => {
commit("setNotification", "There was an error saving the attachment")
return null
})
data.payload[sectionName][criteriaName] = attachmentsIds
data.attachments.push(attachmentsIds)
}
}
}
return axios.post(NEGOTIATION_PATH, data, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data.id
})
.catch(() => {
return null
commit("setNotification", "There was an error saving the Negotiation")
})

},
retrieveNegotiationsByRole({ state, commit }, { userRole }) {
return axios.get(`${NEGOTIATION_PATH}`, {headers : getBearerHeaders(state.oidc.access_token), params : {userRole : userRole}})
return axios.get(`${NEGOTIATION_PATH}`, {headers: getBearerHeaders(state.oidc.access_token), params: {userRole: userRole}})
.then((response) => {
return response.data
})
Expand All @@ -64,7 +89,7 @@ export default {
})
},
updateNegotiationStatus({ state, commit }, { negotiationId , event }) {
return axios.put(`${NEGOTIATION_PATH}/${negotiationId}/lifecycle/${event}`, {}, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.put(`${NEGOTIATION_PATH}/${negotiationId}/lifecycle/${event}`, {}, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
commit("setNotification", `Negotiation updated correctly with data ${response.data.id}`)
return response.data
Expand All @@ -75,7 +100,7 @@ export default {
})
},
retrievePossibleEvents({ state, commit }, { negotiationId }) {
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}/lifecycle`, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}/lifecycle`, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
Expand All @@ -84,7 +109,7 @@ export default {
})
},
retrievePossibleEventsForResource({ state, commit }, { negotiationId, resourceId }) {
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}/resources/${resourceId}/lifecycle`, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}/resources/${resourceId}/lifecycle`, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
Expand All @@ -93,7 +118,7 @@ export default {
})
},
updateResourceStatus({ state, commit }, { negotiationId , resourceId, event }) {
return axios.put(`${NEGOTIATION_PATH}/${negotiationId}/resources/${resourceId}/lifecycle/${event}`, {}, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.put(`${NEGOTIATION_PATH}/${negotiationId}/resources/${resourceId}/lifecycle/${event}`, {}, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
commit("setNotification", `Negotiation updated correctly with data ${response.data.id}`)
return response.data
Expand All @@ -103,8 +128,8 @@ export default {
return null
})
},
retrieveNegotiationById({ state, commit }, { negotiationId }) {
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}`, {headers : getBearerHeaders(state.oidc.access_token)})
async retrieveNegotiationById({ state, commit }, { negotiationId }) {
return axios.get(`${NEGOTIATION_PATH}/${negotiationId}`, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
Expand All @@ -114,8 +139,8 @@ export default {
},
retrievePostsByNegotiationId({ state, commit }, { negotiationId, type, resourceId }) {
let url = `${NEGOTIATION_PATH}/${negotiationId}/posts`
let params = resourceId ? {type: type, resource: resourceId} : {type : type}
return axios.get(url, {headers : getBearerHeaders(state.oidc.access_token), params: params})
let params = resourceId ? {type: type, resource: resourceId} : {type: type}
return axios.get(url, {headers: getBearerHeaders(state.oidc.access_token), params: params})
.then((response) => {
return response.data
})
Expand All @@ -124,7 +149,7 @@ export default {
})
},
addMessageToNegotiation({ state, commit }, { data }) {
return axios.post(`${NEGOTIATION_PATH}/${data.negotiationId}/posts`, data, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.post(`${NEGOTIATION_PATH}/${data.negotiationId}/posts`, data, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
Expand All @@ -133,7 +158,7 @@ export default {
})
},
markMessageAsRead({ state }, { data }) {
return axios.put(`${NEGOTIATION_PATH}/${data.negotiationId}/posts/${data.postId}`, data, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.put(`${NEGOTIATION_PATH}/${data.negotiationId}/posts/${data.postId}`, data, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data.id
})
Expand All @@ -144,7 +169,7 @@ export default {
getUnreadMessagesByRole({ state }, { data }) {
//the role shoud be complementary in relation of the one from the user
let complementaryRole = data.Rolename == ROLES.RESEARCHER ? ROLES.REPRESENTATIVE : ROLES.RESEARCHER
return axios.get(`${NEGOTIATION_PATH}/${data.negotiationId}/${complementaryRole}/posts`, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.get(`${NEGOTIATION_PATH}/${data.negotiationId}/${complementaryRole}/posts`, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
Expand All @@ -153,13 +178,28 @@ export default {
})
},
retrieveUserRoles({ state, commit }) {
return axios.get(USER_PATH, {headers : getBearerHeaders(state.oidc.access_token)})
return axios.get(USER_PATH, {headers: getBearerHeaders(state.oidc.access_token)})
.then((response) => {
return response.data
})
.catch(() => {
commit("setNotification", "Error sending message")
})

},
downloadAttachment({ state }, { id, name }) {
axios.get(`${ATTACHMENTS_PATH}/${id}`, { headers: getBearerHeaders(state.oidc.access_token), responseType: "blob" })
.then((response) => {
const href = window.URL.createObjectURL(response.data)

const anchorElement = document.createElement("a")
anchorElement.href = href
anchorElement.download = name

document.body.appendChild(anchorElement)
anchorElement.click()

document.body.removeChild(anchorElement)
window.URL.revokeObjectURL(href)
})
}
}
Loading

0 comments on commit 668328b

Please sign in to comment.