Browse Source

A hole lot of updates

master
Joshua Rubingh 2 months ago
parent
commit
2a8353c800
  1. 49
      components/contributor/list/item.vue
  2. 60
      components/contributors/deleteButton.vue
  3. 87
      components/contributors/editForm.vue
  4. 16
      components/contributors/list.vue
  5. 135
      components/researchStudies/list.vue
  6. 15
      locales/en.js
  7. 15
      locales/nl.js
  8. 1
      nuxt.config.js
  9. 1
      package.json
  10. 54
      pages/researchStudies/_studyId/contributors/_contributorId/edit.vue
  11. 2
      pages/researchStudies/_studyId/contributors/invite.vue
  12. 43
      pages/researchStudies/_studyId/index.vue
  13. 110
      pages/researchStudies/create.vue
  14. 3
      plugins/axios.js
  15. 4
      plugins/vue-image-upload.js
  16. 32
      store/studies.js
  17. 15
      yarn.lock

49
components/contributor/list/item.vue

@ -1,17 +1,48 @@
<template>
<v-list-item class="px-2" link :to="localePath(`/researchStudies/${studyId}/contributors/${contributor.id}/edit`)">
<v-list-item
class="px-2"
link
:to="
localePath(
`/researchStudies/${studyId}/contributors/${contributor.id}/edit`
)
"
>
<v-list-item-avatar>
<v-img :src="contributor.researcher.avatar ||`https://randomuser.me/api/portraits/men/${contributor.researcher.id+6}.jpg`"></v-img>
<v-img
:src="
contributor.researcher.avatar ||
`https://randomuser.me/api/portraits/men/${
contributor.researcher.id + 6
}.jpg`
"
></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title class="text-h6">
{{contributor.researcher.display_name}}
{{ contributor.researcher.display_name }}
</v-list-item-title>
<v-list-item-subtitle>{{contributor.researcher.email_address}}</v-list-item-subtitle>
<v-list-item-subtitle>{{ $t('study.faculty') }}: {{contributor.researcher.faculty.name}}</v-list-item-subtitle>
<v-list-item-subtitle>{{
contributor.researcher.email_address
}}</v-list-item-subtitle>
<v-list-item-subtitle
>{{ $t('study.faculty') }}:
<span v-if="contributor.researcher.faculty">
{{ contributor.researcher.faculty.name }}
</span>
<span v-else>
{{ $t('contributors.table.no_faculty') }}
</span>
</v-list-item-subtitle>
<v-list-item-subtitle>
{{ $t('contributor.role') }}: {{contributor.role}}<span v-if="contributor.isOwner">, {{ $t('contributor.role.owner') }}</span>
</v-list-item-subtitle>
{{ $t('contributor.role') }}: {{ contributor.role
}}<span v-if="contributor.isOwner"
>, {{ $t('contributor.role.owner') }}</span
>
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
@ -35,8 +66,8 @@ export default {
faculty: '',
},
role: '',
})
}
}),
},
},
}
</script>

60
components/contributors/deleteButton.vue

@ -1,39 +1,25 @@
<template>
<v-row justify="center">
<v-dialog
v-model="dialog"
persistent
max-width="290"
>
<v-dialog v-model="dialog" persistent max-width="290">
<template #activator="{ on, attrs }">
<v-icon
v-if="!contributor.isOwner"
small
v-bind="attrs"
v-on="on"
>
<v-icon v-if="!contributor.isOwner" small v-bind="attrs" v-on="on">
mdi-delete
</v-icon>
</template>
<ui-rug-card-form
:form="form"
>
<v-card-title>{{ $t('contributors.inviteButton.modal.title') }}</v-card-title>
<v-card-text>{{ $t('contributors.inviteButton.modal.text') }}</v-card-text>
<ui-rug-card-form :form="form">
<v-card-title>{{
$t('contributors.inviteButton.modal.title')
}}</v-card-title>
<v-card-text>{{
$t('contributors.inviteButton.modal.text')
}}</v-card-text>
<span slot="actions">
<v-spacer></v-spacer>
<v-btn
text
@click="dialog = false"
>
<v-btn text @click="dialog = false">
{{ $t('contributors.inviteButton.modal.negative') }}
</v-btn>
<v-btn
text
type="submit"
>
<v-btn text type="submit">
{{ $t('contributors.inviteButton.modal.positive') }}
</v-btn>
</span>
@ -43,8 +29,8 @@
</template>
<script>
import { mapActions } from 'vuex';
import Form from '@/lib/form';
import { mapActions } from 'vuex'
import Form from '@/lib/form'
export default {
props: {
@ -54,28 +40,30 @@ export default {
},
contributor: {
type: Object,
default() { return {} }
}
default() {
return {}
},
},
},
data () {
data() {
return {
dialog: false,
formData: {
studyId: this.studyId,
contributorId: this.contributor.researcher.id
contributorId: this.contributor.id,
},
form: new Form({
vm: this,
action: this['studies/deleteContributorFromStudy'],
onResponse() {
this.dialog = false;
this.$nuxt.refresh();
}
}),
this.vm.dialog = false
this.vm.$nuxt.refresh()
},
}),
}
},
methods: {
...mapActions(['studies/deleteContributorFromStudy']),
}
},
}
</script>

87
components/contributors/editForm.vue

@ -1,70 +1,53 @@
<template>
<v-card>
<v-card-title>
<span class="text-h5">{{ $t('contributors.editForm.title') }}</span>
</v-card-title>
<v-card>
<v-card-title>
<span class="text-h5">{{ $t('contributors.editForm.title') }}</span>
</v-card-title>
<contributor-list-item :contributor="contributor" />
<contributor-list-item :contributor="contributor" />
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-select
v-model="formData.roles"
:items="roles"
item-text="name"
item-value="id"
multiple
chips
:label="$t('form.studyField')"
></v-select>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-select
v-model="formData.roles"
:items="roles"
item-text="name"
item-value="id"
multiple
chips
:label="$t('form.contributorRole')"
></v-select>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="close"
>
{{ $t('contributors.editForm.cancel') }}
</v-btn>
<v-btn
color="blue darken-1"
text
@click="save"
>
{{ $t('contributors.editForm.save') }}
</v-btn>
</v-card-actions>
</v-card>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close">
{{ $t('contributors.editForm.cancel') }}
</v-btn>
<v-btn color="blue darken-1" text @click="save">
{{ $t('contributors.editForm.save') }}
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import Form from '@/lib/form';
import Form from '@/lib/form'
export default {
props: {
},
props: {},
data() {
return {
formData: {},
contributor: {},
roles: [],
form: Form({
})
form: Form({}),
}
},
}
</script>

16
components/contributors/list.vue

@ -26,7 +26,7 @@
:src="`https://randomuser.me/api/portraits/men/${
item.researcher.id + 6
}.jpg`"
:alt="`${item.researcher.first_name} ${item.researcher.last_name}`"
:alt="`${item.researcher.display_name}`"
/>
</v-avatar>
</template>
@ -40,11 +40,21 @@
</template>
<template #item.faculty="{ item }">
{{ item.researcher.faculty.name }}
<span v-if="item.researcher.faculty">
{{ item.researcher.faculty.name }}
</span>
<span v-else>
{{ $t('contributors.table.no_faculty') }}
</span>
</template>
<template #item.university="{ item }">
{{ item.researcher.faculty.university.name }}
<span v-if="item.researcher.faculty">
{{ item.researcher.faculty.university.name }}
</span>
<span v-else>
{{ $t('contributors.table.no_university') }}
</span>
</template>
<template #item.isOwner="{ item }">

135
components/researchStudies/list.vue

@ -22,93 +22,92 @@
>
<template #item.image="{ item }">
<v-avatar>
<v-img
:src="item.src"
:alt="item.name"
/>
<v-img :src="item.src" :alt="item.name" />
</v-avatar>
</template>
<template #item.field="{ item }">
{{item.field.name}}
{{ item.field.name }}
</template>
<template #item.faculty="{ item }">
{{item.field.faculty.name}}
{{ item.field.faculty.name }}
</template>
<template #item.university="{ item }">
{{item.field.faculty.university.name}}
{{ item.field.faculty.university.name }}
</template>
<template #item.startDate="{ item }">
{{$d(item.startDate, 'short')}}
{{ $d(item.startDate, 'short') }}
</template>
<template #item.isShared="{ item }">
<v-icon v-if="item.isShared" icon-account-group></v-icon>
<v-badge :content="`${item.amountContributors}`" overlap>
<v-icon large>mdi-account-group</v-icon>
</v-badge>
</template>
</v-data-table>
</v-card>
</template>
<script>
export default {
props: {
studies: {
type: Array,
default() {
return []
},
export default {
props: {
studies: {
type: Array,
default() {
return []
},
},
data () {
return {
search: '',
headers: [
{
text: '',
align: 'start',
value: 'image',
},
{
text: this.$t('study.name'),
value: 'name'
},
{
text: this.$t('study.field'),
value: 'field',
},
{
text: this.$t('study.faculty'),
value: 'faculty',
},
{
text: this.$t('study.university'),
value: 'university',
},
{
text: this.$t('study.startDate'),
value: 'startDate'
},
{
text: '',
sortable: false,
value: 'isShared'
}
],
}
},
data() {
return {
search: '',
headers: [
{
text: '',
align: 'start',
value: 'image',
},
{
text: this.$t('study.name'),
value: 'name',
},
{
text: this.$t('study.field'),
value: 'field',
},
{
text: this.$t('study.faculty'),
value: 'faculty',
},
{
text: this.$t('study.university'),
value: 'university',
},
{
text: this.$t('study.startDate'),
value: 'startDate',
},
{
text: '',
sortable: false,
value: 'isShared',
},
],
}
},
methods: {
navigateToRow(row) {
this.$router.push(this.localePath(`/researchStudies/${row.id}`))
},
methods: {
navigateToRow(row) {
this.$router.push(this.localePath(`/researchStudies/${row.id}`))
},
customFilter(_, search, item) {
search = search.toString().toLowerCase();
return (
item.startDate.toString().toLowerCase().includes(search)
|| item.name.toLowerCase().includes(search)
|| item.field.name.toLowerCase().includes(search)
|| item.field.faculty.name.toLowerCase().includes(search)
|| item.field.faculty.university.name.toLowerCase().includes(search)
)
}
customFilter(_, search, item) {
search = search.toString().toLowerCase()
return (
item.startDate.toString().toLowerCase().includes(search) ||
item.name.toLowerCase().includes(search) ||
item.field.name.toLowerCase().includes(search) ||
item.field.faculty.name.toLowerCase().includes(search) ||
item.field.faculty.university.name.toLowerCase().includes(search)
)
},
}
},
}
</script>

15
locales/en.js

@ -8,10 +8,11 @@ export default {
'page.studies.study.contributors.contributor.invite.title': 'Invite contributor',
'page.studies.study.contributors.contributor.edit.title': 'Edit contributor',
'form.label.studyName': 'Study name',
'form.studyShortDescription': 'Study short description',
'form.projectCode': 'Project code',
'form.usesHumanSubjectData': 'Uses human subject data',
'form.studyField': 'Study field',
'form.label.studyShortDescription': 'Study short description',
'form.label.projectCode': 'Project code',
'form.label.usesHumanSubjectData': 'Uses human subject data',
'form.label.studyField': 'Study field',
'form.label.studyAvatar': 'Study avatar',
'form.contributorFirstName': 'Contributor first name',
'form.contributorLastName': 'Contributor last name',
'form.contributorEmail': 'Contributor email',
@ -46,11 +47,13 @@ export default {
'researchStudies.createButton.button': 'Create',
'contributors.title': 'Contributors',
'contributors.inviteButton.button': 'Invite contributor',
'contributors.editoFrom.title': 'Edit contributor',
'contributors.editFrom.title': 'Edit contributor',
'contributors.editForm.cancel': 'Cancel',
'contributors.editForm.save': 'Save',
'contributors.inviteButton.modal.title': 'Remove contributor',
'contributors.inviteButton.modal.text': 'Are you sure you want to remove this contributor?',
'contributors.inviteButton.modal.negative': 'No',
'contributors.inviteButton.modal.positive': 'Yes'
'contributors.inviteButton.modal.positive': 'Yes',
'contributors.table.no_faculty': 'Unknown faculty',
'contributors.table.no_university': 'Unknown university',
}

15
locales/nl.js

@ -8,10 +8,11 @@ export default {
'page.studies.study.contributors.contributor.invite.title': 'Invite contributor',
'page.studies.study.contributors.contributor.edit.title': 'Edit contributor',
'form.label.studyName': 'Study name',
'form.studyShortDescription': 'Study short description',
'form.projectCode': 'Project code',
'form.usesHumanSubjectData': 'Uses human subject data',
'form.studyField': 'Study field',
'form.label.studyShortDescription': 'Study short description',
'form.label.projectCode': 'Project code',
'form.label.usesHumanSubjectData': 'Uses human subject data',
'form.label.studyField': 'Study field',
'form.label.studyAvatar': 'Study avatar',
'form.contributorFirstName': 'Contributor first name',
'form.contributorLastName': 'Contributor last name',
'form.contributorEmail': 'Contributor email',
@ -46,11 +47,13 @@ export default {
'researchStudies.createButton.button': 'Create',
'contributors.title': 'Contributors',
'contributors.inviteButton.button': 'Invite contributor',
'contributors.editoFrom.title': 'Edit contributor',
'contributors.editFrom.title': 'Edit contributor',
'contributors.editForm.cancel': 'Cancel',
'contributors.editForm.save': 'Save',
'contributors.inviteButton.modal.title': 'Remove contributor',
'contributors.inviteButton.modal.text': 'Are you sure you want to remove this contributor?',
'contributors.inviteButton.modal.negative': 'No',
'contributors.inviteButton.modal.positive': 'Yes'
'contributors.inviteButton.modal.positive': 'Yes',
'contributors.table.no_faculty': 'Unknown faculty',
'contributors.table.no_university': 'Unknown university',
}

1
nuxt.config.js

@ -37,6 +37,7 @@ export default {
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
'~/plugins/axios',
{ src: '~/plugins/vue-image-upload.js', mode: 'client' },
],
// Auto import components: https://go.nuxtjs.dev/config-components

1
package.json

@ -25,6 +25,7 @@
"core-js": "^3.15.1",
"nuxt": "^2.15.7",
"vue": "^2.6.14",
"vue-image-upload-resize": "^2.3.0",
"vue-types": "^4.1.0",
"vuetify": "^2.5.5",
"vuex": "^3.6.2"

54
pages/researchStudies/_studyId/contributors/_contributorId/edit.vue

@ -1,12 +1,15 @@
<template>
<v-container>
<v-container>
<ui-rug-card-form :form="form">
<ui-rug-card-title>
{{ $t('page.studies.study.contributors.contributor.edit.title') }}
</ui-rug-card-title>
<v-card-text class="flex-row mb-6">
<contributor-list-item :contributor="contributor" :study-id="studyId" />
<contributor-list-item
:contributor="contributor"
:study-id="formData.studyId"
/>
<v-select
id="formData.role"
@ -15,29 +18,25 @@
:items="roles"
item-text="name"
item-value="id"
:label="$t('form.role')"
:label="$t('form.contributorRole')"
></v-select>
</v-card-text>
</ui-rug-card-form>
</v-container>
</template>
<script>
import { mapActions } from 'vuex';
import Form from '@/lib/form';
import { mapActions } from 'vuex'
import Form from '@/lib/form'
export default {
async asyncData({store, route}) {
const studyId = route.params.studyId;
const contributorId = route.params.contributorId;
await Promise.all([
store.dispatch('studies/getStudy', { studyId }),
store.dispatch('studies/getRoles'),
]);
const contributor = store.getters['studies/getContributorFromActiveStudy']({ contributorId })
export default {
async asyncData({ store, route }) {
await store.dispatch('studies/getRoles')
const contributorId = route.params.contributorId
const contributor = store.getters['studies/getContributorFromActiveStudy']({
contributorId,
})
return {
studyId,
contributor,
roles: store.getters['studies/getRoles'],
formData: {
@ -45,12 +44,15 @@ export default {
contributorId: route.params.contributorId,
role: contributor.role,
},
};
}
},
data () {
data() {
return {
formData: {},
formData: {
role: null,
},
form: new Form({
form: 'formData',
vm: this,
action: this['studies/updateContributorRole'],
schema: {
@ -58,19 +60,21 @@ export default {
properties: {
role: {
type: 'string',
}
},
},
required: ['role', ],
required: ['role'],
},
onResponse() {
const studyId = this.vm.$route.params.studyId;
this.vm.$router.push(this.localePath(`/researchStudies/${studyId}/contributors`))
}
const studyId = this.vm.$route.params.studyId
this.vm.$router.push(
this.vm.localePath(`/researchStudies/${studyId}/contributors`)
)
},
}),
}
},
methods: {
...mapActions(['studies/updateContributorRole']),
}
},
}
</script>

2
pages/researchStudies/_studyId/contributors/invite.vue

@ -98,7 +98,7 @@ export default {
onResponse() {
const studyId = this.vm.$route.params.studyId
this.vm.$router.push(
this.localePath(`/researchStudies/${studyId}/contributors`)
this.vm.localePath(`/researchStudies/${studyId}/contributors`)
)
},
}),

43
pages/researchStudies/_studyId/index.vue

@ -1,12 +1,9 @@
<template>
<v-card>
<ui-rug-card-title>
{{ study.name }} ({{ study.code }})
</ui-rug-card-title>
<ui-rug-card-title> {{ study.name }} ({{ study.code }}) </ui-rug-card-title>
<v-card-text class="d-flex flex-row mb-6">
<apps-list :apps="apps" :study-id="studyId"/>
<apps-list :apps="apps" :study-id="studyId" />
<v-list
v-for="contributor in study.contributors"
@ -16,26 +13,40 @@
</v-list>
<v-card>
<v-card-title>
{{ study.name }} ({{ study.code }})
</v-card-title>
<v-card-title> {{ study.name }} ({{ study.code }}) </v-card-title>
<v-card-subtitle>
{{ study.description }}
</v-card-subtitle>
<v-card-text>
{{ $t('study.access') }}:
<span v-if="study.human_subject" class="warning--text">{{ $t('study.access.restricted') }}</span>
<span v-if="study.human_subject" class="warning--text">{{
$t('study.access.restricted')
}}</span>
<span v-else>{{ $t('study.access.public') }}</span>
<br />
{{ $t('study.field') }}: {{ study.field.name }}
<br />
{{ $t('study.faculty') }}: {{ study.field.faculty.name }}
{{ $t('study.faculty') }}:
<span v-if="study.field.faculty">
{{ study.field.faculty.name }}
</span>
<span v-else class="text--lighten-10">
{{ $t('contributors.table.no_faculty') }}
</span>
<br />
{{ $t('study.university') }}: {{ study.field.faculty.university.name }}
{{ $t('study.university') }}:
<span v-if="study.field.faculty">
{{ study.field.faculty.university.name }}
</span>
<span v-else class="text--lighten-10">
{{ $t('contributors.table.no_university') }}
</span>
<br />
{{ $t('study.createdAt') }}: {{ $d(new Date(study.created_at), 'long') }}
{{ $t('study.createdAt') }}:
{{ $d(new Date(study.created_at), 'long') }}
<br />
{{ $t('study.updatedAt') }}: {{ $d(new Date(study.updated_at), 'long') }}
{{ $t('study.updatedAt') }}:
{{ $d(new Date(study.updated_at), 'long') }}
</v-card-text>
</v-card>
</v-card-text>
@ -46,18 +57,18 @@
<script>
export default {
async asyncData({ store, route }) {
const studyId = route.params.studyId;
const studyId = route.params.studyId
await Promise.all([
store.dispatch('studies/getStudy', { studyId }),
store.dispatch('studies/getStudyFields'),
store.dispatch('apps/getApps'),
]);
])
return {
study: store.getters['studies/getActiveStudy'],
studyFields: store.getters['studies/getStudyFields'],
apps: store.getters['apps/getAppsForStudy'](studyId),
studyId,
};
}
},
}
</script>

110
pages/researchStudies/create.vue

@ -1,41 +1,40 @@
<template>
<ui-rug-card-form :form="form">
<ui-rug-card-title>
{{ $t('page.studies.create.title') }}
</ui-rug-card-title>
<v-card-text class="d-flex flex-row mb-6">
<div class="pa-4">
<v-col cols="6">
<v-text-field
id="formData.name"
v-model="formData.name"
:error-messages="form.getError('formData.name')"
:label="$t('form.studyName')"
:label="$t('form.label.studyName')"
@blur="form.onBlur"
></v-text-field>
<v-text-field
<v-textarea
id="formData.description"
v-model="formData.description"
:error-messages="form.getError('formData.description')"
:label="$t('form.studyShortDescription')"
:label="$t('form.label.studyShortDescription')"
@blur="form.onBlur"
></v-text-field>
></v-textarea>
<v-text-field
id="formData.code"
v-model="formData.code"
:error-messages="form.getError('formData.code')"
:label="$t('form.projectCode')"
:label="$t('form.label.projectCode')"
@blur="form.onBlur"
></v-text-field>
<v-switch
v-model="formData.human_subject"
:label="$t('form.usesHumanSubjectData')"
:label="$t('form.label.usesHumanSubjectData')"
></v-switch>
<v-select
id="formData.field"
v-model="formData.field"
@ -43,39 +42,80 @@
:items="studyFields"
item-text="name"
item-value="id"
:label="$t('form.studyField')"
:label="$t('form.label.studyField')"
></v-select>
</div>
<div class="pa-2">
<v-text-field
id="formData.avatar"
v-model="formData.avatar"
type="hidden"
:error-messages="form.getError('formData.avatar')"
:label="$t('form.label.studyAvatar')"
></v-text-field>
<client-only>
<image-uploader
:preview="true"
:className="['fileinput', { 'fileinput--loaded': hasImage }]"
capture="false"
:debug="1"
:quality="0.9"
doNotResize="['gif','svg']"
:autoRotate="true"
outputFormat="verbose"
@input="setImage"
>
<label slot="upload-label" for="fileInput">
<figure>
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 32 32"
>
<path
class="path1"
d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875s3.973-8.875 8.875-8.875c4.902 0 8.875 3.973 8.875 8.875s-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z"
></path>
</svg>
</figure>
<span class="upload-caption">{{
hasImage ? 'Replace' : 'Click to upload'
}}</span>
</label>
</image-uploader>
</client-only>
</v-col>
<v-col cols="6">
<h2>{{ $t('page.studies.create.privacyStatement.title') }}</h2>
<p>{{ $t('page.studies.create.privacyStatement.text') }}</p>
</div>
</v-col>
</v-card-text>
</ui-rug-card-form>
</template>
<script>
import { mapActions } from 'vuex';
import Form from '@/lib/form';
import { mapActions } from 'vuex'
import Form from '@/lib/form'
export default {
async asyncData({store}) {
await store.dispatch('studies/getStudyFields');
async asyncData({ store }) {
await store.dispatch('studies/getStudyFields')
return {
studyFields: store.getters['studies/getStudyFields'],
};
}
},
data () {
data() {
return {
hasImage: false,
formData: {
name: '',
name: null,
description: '',
code: '',
code: null,
human_subject: false,
field: null,
avatar: '',
},
form: new Form({
vm: this,
@ -89,7 +129,6 @@ export default {
},
description: {
type: 'string',
maxLength: 2048,
},
code: {
type: 'string',
@ -99,19 +138,30 @@ export default {
type: 'boolean',
},
field: {
type: 'integer'
}
type: 'integer',
},
},
required: ['name', 'code', 'field', ],
required: ['name', 'code', 'field'],
},
onResponse(response) {
this.vm.$router.push(this.localePath(`/researchStudies/${response.data.id}/`))
}
this.vm.$router.push(
this.vm.localePath(`/researchStudies/${response.data.id}/`)
)
},
}),
}
},
methods: {
...mapActions(['studies/createStudy']),
}
setImage(output) {
this.hasImage = true
this.formData.avatar = output.dataUrl
},
},
}
</script>
<style>
#fileInput {
display: none;
}
</style>

3
plugins/axios.js

@ -7,6 +7,9 @@ export default function (args) {
$axios.defaults.xsrfCookieName = 'csrftoken';
$axios.defaults.xsrfHeaderName = 'X-CSRFTOKEN';
/* Allow cross-site Access-Control requests: https://stackoverflow.com/a/54470754 */
$axios.defaults.withCredentials = true;
$axios.interceptors.request.use(config => {
const locales = i18n.locales;
const currentLocale = i18n.locale;

4
plugins/vue-image-upload.js

@ -0,0 +1,4 @@
import Vue from 'vue'
import ImageUploader from 'vue-image-upload-resize'
Vue.use(ImageUploader)

32
store/studies.js

@ -44,26 +44,15 @@ export const actions = {
success: false,
},
name: 'deleteContributorFromStudy',
async method({ studyId, contributorId }) {
const result = await this.$axios.get(`/api/v1/studies/${studyId}/`);
const study = result.data;
const contributors = study.contributors.filter(contributor => contributor.researcher.id !== contributorId);
return this.$axios.post(`/api/v1/studies/${studyId}/contributors/`, contributors);
method({ studyId, contributorId }) {
return this.$axios.delete(`/api/v1/studies/${studyId}/contributors/${contributorId}/`);
},
}),
updateContributorRole: actionCreator({
name: 'updateContributor',
async method({ studyId, contributorId, role }) {
const result = await this.$axios.get(`/api/v1/studies/${studyId}/`);
const study = result.data;
const contributors = study.contributors;
contributorId = parseInt(contributorId, 10)
return this.$axios.post(`/api/v1/studies/${studyId}/contributors/`, contributors.map(contributor => {
if (contributor.id === contributorId) {
contributor.role = role;
}
return contributor;
}))
method(role) {
return this.$axios.put(`/api/v1/studies/${role.studyId}/contributors/${role.contributorId}/`, role)
}
}),
getRoles: actionCreator({
@ -85,14 +74,18 @@ export const mutations = {
state.studies = result.map((study) => {
return {
id: study.id,
src: `https://picsum.photos/seed/${study.id}/24/24`,
src: study.avatar,
name: study.name,
field: study.field,
startDate: new Date(study.created_at),
isShared: study.contributors.length > 1
amountContributors: study.contributors.length
}
})
},
createStudySuccess(state, { result }) {
/* TODO: Is there any action needed here? As we should be redirected to the newly created study, which will set the active Study data? */
state.activeStudy = result;
},
getStudyFieldsSuccess(state, { result }) {
state.studyFields = result
},
@ -102,6 +95,9 @@ export const mutations = {
getRolesSuccess(state, { result }) {
state.roles = result;
},
inviteContributorSuccess(state, { result }) {
},
}
export const getters = {

15
yarn.lock

@ -2551,6 +2551,11 @@ bluebird@^3.1.1, bluebird@^3.5.5:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
blueimp-canvas-to-blob@^3.14.0:
version "3.29.0"
resolved "https://registry.yarnpkg.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz#d965f06cb1a67fdae207a2be56683f55ef531466"
integrity sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==
blueimp-md5@^2.10.0:
version "2.18.0"
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.18.0.tgz#1152be1335f0c6b3911ed9e36db54f3e6ac52935"
@ -10462,6 +10467,14 @@ vue-i18n@^8.25.0:
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.26.1.tgz#56419bcb2414a01e0e9046fe1883d0edd421bf41"
integrity sha512-N6GpogueNQqmAye6lkUySlrXAZqBs9DYz8+8LHxm4IV7hEP/KWQL9VUCV8oJ0DS1asUTlvI2qKm2MydRgoPJFQ==
vue-image-upload-resize@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vue-image-upload-resize/-/vue-image-upload-resize-2.3.0.tgz#c2e8e887a81afc641122f21284540e5849475bf7"
integrity sha512-ElzyAVCluiDt8xSZkSK9FbuLY5mr23JlO4cHyyRo86RfEGLWtvXrTq7vYOgDstT8rNBmnTgNCkPKc0rpmyl1yA==
dependencies:
blueimp-canvas-to-blob "^3.14.0"
vue "^2.5.17"
vue-loader@^15.9.7:
version "15.9.8"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.8.tgz#4b0f602afaf66a996be1e534fb9609dc4ab10e61"
@ -10532,7 +10545,7 @@ vue-types@^4.1.0:
dependencies:
is-plain-object "5.0.0"
vue@^2.6.12, vue@^2.6.14:
vue@^2.5.17, vue@^2.6.12, vue@^2.6.14:
version "2.6.14"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==

Loading…
Cancel
Save