Browse Source

Updated translations. Add edit me option.

master
Joshua Rubingh 10 months ago
parent
commit
8e1948a56f
  1. 54
      components/user/profile/list/item.vue
  2. 10
      config/routes.js
  3. 15
      locales/en.js
  4. 15
      locales/nl.js
  5. 19
      pages/index.vue
  6. 195
      pages/profile/edit.vue
  7. 8
      pages/researchStudies/_studyId/contributors/_contributorId/edit.vue
  8. 18
      pages/researchStudies/_studyId/contributors/index.vue
  9. 6
      pages/researchStudies/_studyId/contributors/invite.vue
  10. 111
      pages/researchStudies/_studyId/contributors/join.vue
  11. 8
      pages/researchStudies/_studyId/index.vue
  12. 12
      pages/researchStudies/_studyId/settings.vue
  13. 8
      pages/researchStudies/create.vue
  14. 12
      pages/researchStudies/index.vue
  15. 38
      store/researchers.js
  16. 11
      store/studies.js
  17. 57
      store/universities.js

54
components/user/profile/list/item.vue

@ -1,15 +1,20 @@ @@ -1,15 +1,20 @@
<template>
<v-list-item class="px-2">
<v-list-item-avatar>
<v-img :src="getUser.avatar || `https://randomuser.me/api/portraits/men/${getUser.id}.jpg`"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title class="text-h6">
{{getUser.display_name}}
</v-list-item-title>
<v-list-item-subtitle>{{getUser.email_address}}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item class="px-2" @click="editProfile">
<v-list-item-avatar>
<v-img
:src="
getUser.avatar ||
`https://randomuser.me/api/portraits/men/${getUser.id}.jpg`
"
></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title class="text-h6">
{{ getUser.display_name }}
</v-list-item-title>
<v-list-item-subtitle>{{ getUser.email_address }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
<script>
@ -20,18 +25,25 @@ export default { @@ -20,18 +25,25 @@ export default {
default: () => ({
avatar: '',
display_name: '',
email_address: ''
})
}
email_address: '',
}),
},
},
computed: {
getUser() {
return this.user || {
avatar: '',
display_name: '',
email_address: ''
}
}
}
return (
this.user || {
avatar: '',
display_name: '',
email_address: '',
}
)
},
},
methods: {
editProfile() {
this.$router.push(this.localePath(`/profile/edit`))
},
},
}
</script>

10
config/routes.js

@ -28,6 +28,11 @@ export default { @@ -28,6 +28,11 @@ export default {
path: '/en/profile/',
component: 'pages/profile/overview',
},
{
name: 'profile.edit',
path: '/en/profile/',
component: 'pages/profile/edit',
},
{
name: 'researchStudies',
path: '/en/researchStudies/',
@ -53,6 +58,11 @@ export default { @@ -53,6 +58,11 @@ export default {
path: '/en/researchStudies/:studyId/contributors/invite/',
component: 'pages/studies/study/contributors/contributor/invite',
},
{
name: 'researchStudies.study.contributors.join',
path: '/en/researchStudies/:studyId/contributors/join/',
component: 'pages/studies/study/contributors/contributor/join',
},
{
name: 'researchStudies.study.contributors.edit',
path: '/en/researchStudies/:studyId/contributors/:contributorId/edit/',

15
locales/en.js

@ -7,6 +7,21 @@ export default { @@ -7,6 +7,21 @@ export default {
'page.studies.create.privacyStatement.text': 'On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammeled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.',
'page.studies.study.contributors.contributor.invite.title': 'Invite contributor',
'page.studies.study.contributors.contributor.edit.title': 'Edit contributor',
'page.researchStudies.index.title': 'Studies overview',
'page.researchStudies.studyId.index.title': 'Study detail: {study_name}',
'page.researchStudies.studyId.contributors.contributorId.edit.title': 'Edit contributor',
'page.researchStudies.studyId.contributors.index.title': 'Study contributors overview',
'page.researchStudies.studyId.contributors.index.invite': 'Invite a researcher to this study',
'page.researchStudies.studyId.settings.title': 'Study settings',
'page.researchStudies.create.title': 'Create a new study',
'page.profile.edit.title': 'Edit me',
'page.profile.edit.header': 'Edit me',
'form.label.firstName': 'First name',
'form.label.lastName': 'Last name',
'form.label.faculty': 'Faculty',
'form.label.mobilePhone': 'Mobile phone',
'form.label.idNumber': 'P Number',
'form.label.profileAvatar': 'Avatar',
'form.label.studyName': 'Study name',
'form.label.studyShortDescription': 'Study short description',
'form.label.projectCode': 'Project code',

15
locales/nl.js

@ -7,6 +7,21 @@ export default { @@ -7,6 +7,21 @@ export default {
'page.studies.create.privacyStatement.text': 'On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammeled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.',
'page.studies.study.contributors.contributor.invite.title': 'Invite contributor',
'page.studies.study.contributors.contributor.edit.title': 'Edit contributor',
'page.researchStudies.index.title': 'Studies overview',
'page.researchStudies.studyId.index.title': 'Study detail: {study_name}',
'page.researchStudies.studyId.contributors.contributorId.edit.title': 'Edit contributor',
'page.researchStudies.studyId.contributors.index.title': 'Study contributors overview',
'page.researchStudies.studyId.contributors.index.invite': 'Invite a researcher to this study',
'page.researchStudies.studyId.settings.title': 'Study settings',
'page.researchStudies.create.title': 'Create a new study',
'page.profile.edit.title': 'Edit me',
'page.profile.edit.header': 'Edit me',
'form.label.firstName': 'First name',
'form.label.lastName': 'Last name',
'form.label.faculty': 'Faculty',
'form.label.mobilePhone': 'Mobile phone',
'form.label.idNumber': 'P Number',
'form.label.profileAvatar': 'Avatar',
'form.label.studyName': 'Study name',
'form.label.studyShortDescription': 'Study short description',
'form.label.projectCode': 'Project code',

19
pages/index.vue

@ -1,12 +1,6 @@ @@ -1,12 +1,6 @@
<template>
<v-card
class="mx-auto"
max-width="375"
>
<v-img
:src="`https://picsum.photos/seed/${seed}/400/200`"
height="200px"
/>
<v-card class="mx-auto" max-width="375">
<v-img :src="`https://picsum.photos/seed/${seed}/400/200`" height="200px" />
<v-card-title>
{{ $t('page.landing.title') }}
@ -30,7 +24,14 @@ export default { @@ -30,7 +24,14 @@ export default {
auth: 'guest',
data() {
return {
seed: + new Date(),
seed: +new Date(),
}
},
head() {
// https://kazupon.github.io/vue-i18n/api/#vue-injected-methods
const $t = this.$t.bind(this)
return {
title: $t('page.landing.title'),
}
},
}

195
pages/profile/edit.vue

@ -0,0 +1,195 @@ @@ -0,0 +1,195 @@
<template>
<v-container>
<ui-rug-card-form :form="form">
<ui-rug-card-title>
{{ $t('page.profile.edit.header') }}
</ui-rug-card-title>
<v-card-text class="d-flex flex-row mb-6">
<v-col cols="6">
<v-text-field
id="formData.first_name"
v-model="formData.first_name"
:error-messages="form.getError('formData.first_name')"
:label="$t('form.label.firstName')"
@blur="form.onBlur"
></v-text-field>
<v-text-field
id="formData.last_name"
v-model="formData.last_name"
:error-messages="form.getError('formData.last_name')"
:label="$t('form.label.lastName')"
@blur="form.onBlur"
></v-text-field>
<v-select
id="formData.faculty"
v-model="formData.faculty"
:error-messages="form.getError('formData.faculty')"
:items="faculties"
item-text="name"
item-value="id"
:label="$t('form.label.faculty')"
></v-select>
<v-text-field
id="formData.mobilephone"
v-model="formData.mobilephone"
:error-messages="form.getError('formData.mobilephone')"
:label="$t('form.label.mobilePhone')"
@blur="form.onBlur"
></v-text-field>
<v-text-field
id="formData.idnumber"
v-model="formData.idnumber"
:error-messages="form.getError('formData.idnumber')"
:label="$t('form.label.idNumber')"
@blur="form.onBlur"
></v-text-field>
</v-col>
<v-col cols="6">
<v-text-field
id="formData.avatar"
v-model="formData.avatar"
type="hidden"
:error-messages="form.getError('formData.avatar')"
:label="$t('form.label.profileAvatar')"
></v-text-field>
<client-only>
<image-uploader
:preview="true"
:className="['fileinput', { 'fileinput--loaded': hasImage }]"
capture="false"
:debug="0"
: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-card-text>
</ui-rug-card-form>
</v-container>
</template>
<script>
import { mapActions } from 'vuex'
import Form from '@/lib/form'
export default {
async asyncData({ store }) {
await store.dispatch('researchers/getMe')
const me = store.getters['researchers/getMe']
await store.dispatch('universities/getFaculties', {
universityId: me.university.id,
})
return {
faculties: store.getters['universities/getFaculties'],
}
},
data() {
const profile = this.$store.getters['researchers/getMe']
return {
hasImage: profile.avatar !== '',
formData: {
first_name: profile.first_name,
last_name: profile.last_name,
mobilephone: profile.mobilephone,
idnumber: profile.idnumber,
faculty: profile.faculty.id,
avatar: profile.avatar,
},
form: new Form({
vm: this,
action: this['researchers/updateMe'],
schema: {
type: 'object',
properties: {
first_name: {
type: 'string',
maxLength: 200,
},
last_name: {
type: 'string',
maxLength: 200,
},
mobilephone: {
type: 'string',
maxLength: 16,
},
faculty: {
type: 'integer',
},
idnumber: {
type: 'string',
maxLength: 50,
},
avatar: {
type: 'string',
},
},
required: [
'first_name',
'last_name',
'faculty',
'mobilephone',
'idnumber',
],
},
onResponse(response) {
console.log(response)
/*
this.vm.$router.push(
this.vm.localePath(`/researchStudies/${response.data.id}/`)
)
*/
},
}),
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.profile.edit.title'),
}
},
methods: {
...mapActions(['researchers/updateMe']),
setImage(output) {
this.hasImage = true
this.formData.avatar = output.dataUrl
},
},
}
</script>
<style>
#fileInput {
display: none;
}
</style>

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

@ -73,6 +73,14 @@ export default { @@ -73,6 +73,14 @@ export default {
}),
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t(
'page.researchStudies.studyId.contributors.contributorId.edit.title'
),
}
},
methods: {
...mapActions(['studies/updateContributorRole']),
},

18
pages/researchStudies/_studyId/contributors/index.vue

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
<template>
<div>
<contributors-list :contributors="study.contributors" :owner="study.owner" :study-id="studyId" />
<contributors-list
:contributors="study.contributors"
:owner="study.owner"
:study-id="studyId"
/>
<contributors-invite-button :study-id="studyId" />
</div>
</template>
@ -8,12 +12,18 @@ @@ -8,12 +12,18 @@
<script>
export default {
async asyncData({ store, route }) {
const studyId = route.params.studyId;
await store.dispatch('studies/getStudy', { studyId });
const studyId = route.params.studyId
await store.dispatch('studies/getStudy', { studyId })
return {
study: store.getters['studies/getActiveStudy'],
studyId,
};
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.studyId.contributors.index.title'),
}
},
}
</script>

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

@ -104,6 +104,12 @@ export default { @@ -104,6 +104,12 @@ export default {
}),
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.studyId.contributors.index.invite'),
}
},
methods: {
...mapActions(['studies/inviteContributor']),
},

111
pages/researchStudies/_studyId/contributors/join.vue

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
<template>
<v-container>
<v-row no-gutters>
<v-col cols="12">
<ui-rug-card-title>
{{ $t('page.studies.study.contributors.contributor.join.title') }}
{{ studyData.name }}
</ui-rug-card-title>
<v-card-text class="flex-row mb-6">
{{ studyData }}
<v-btn elevation="2" @click="check_invitation"></v-btn>
</v-card-text>
</v-col>
</v-row>
</v-container>
</template>
<script>
/*
import { mapActions } from 'vuex'
import Form from '@/lib/form'
*/
export default {
async asyncData({ store, route }) {
// const data = {
const studyId = route.params.studyId
const jwtToken = route.query.key
await store.dispatch('studies/getStudy', { studyId })
return {
studyId,
jwtToken,
studyData: store.getters['studies/getActiveStudy'],
// store.getters['studies/getJoinInvitationMessage'],
}
},
data() {
return {
/*
message: {
Bla: 'test',
},
*/
/*
formData: {
first_name: undefined,
last_name: undefined,
email: undefined,
role: null,
studyId: this.$route.params.studyId,
},
form: new Form({
form: 'formData',
vm: this,
action: this['studies/inviteContributor'],
schema: {
type: 'object',
properties: {
first_name: {
type: 'string',
minLength: 2,
maxLength: 100,
},
last_name: {
type: 'string',
minLength: 2,
maxLength: 100,
},
email: {
type: 'string',
format: 'email',
},
role: {
type: 'string',
},
},
required: ['first_name', 'last_name', 'email', 'role'],
},
onResponse() {
const studyId = this.vm.$route.params.studyId
this.vm.$router.push(
this.vm.localePath(`/researchStudies/${studyId}/contributors`)
)
},
}),
*/
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.studyId.contributors.join.title'),
}
},
methods: {
// ...mapActions(['studies/inviteContributor']),
check_invitation() {
// console.log(this)
this.$store.dispatch('studies/joinContributor', {
studyId: this.studyId,
key: this.jwtToken,
})
},
},
}
</script>

8
pages/researchStudies/_studyId/index.vue

@ -70,5 +70,13 @@ export default { @@ -70,5 +70,13 @@ export default {
studyId,
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.studyId.index.title', {
study_name: this.study.name,
}),
}
},
}
</script>

12
pages/researchStudies/_studyId/settings.vue

@ -7,13 +7,19 @@ @@ -7,13 +7,19 @@
<script>
export default {
async asyncData({ store, route }) {
const studyId = route.params.studyId;
await store.dispatch('studies/getStudy', { studyId });
const studyId = route.params.studyId
await store.dispatch('studies/getStudy', { studyId })
return {
study: store.getters['studies/getActiveStudy'],
contributor: {},
studyId,
};
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.studyId.settings.title'),
}
},
}
</script>

8
pages/researchStudies/create.vue

@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
:preview="true"
:className="['fileinput', { 'fileinput--loaded': hasImage }]"
capture="false"
:debug="1"
:debug="0"
:quality="0.9"
doNotResize="['gif','svg']"
:autoRotate="true"
@ -151,6 +151,12 @@ export default { @@ -151,6 +151,12 @@ export default {
}),
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.create.title'),
}
},
methods: {
...mapActions(['studies/createStudy']),
setImage(output) {

12
pages/researchStudies/index.vue

@ -8,12 +8,18 @@ @@ -8,12 +8,18 @@
<script>
export default {
async asyncData({ store }) {
await store.dispatch('studies/getStudies');
await store.dispatch('studies/getStudyFields');
await store.dispatch('studies/getStudies')
await store.dispatch('studies/getStudyFields')
return {
studies: store.getters['studies/getStudies'],
studyFields: store.getters['studies/getStudyFields'],
};
}
},
head() {
const $t = this.$t.bind(this)
return {
title: $t('page.researchStudies.index.title'),
}
},
}
</script>

38
store/researchers.js

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
import { actionCreator } from '@/lib/store';
export const state = () => ({
profile: {},
})
export const actions = {
getMe: actionCreator({
name: 'getMe',
method() {
return this.$axios.get('/api/v1/researchers/me/')
},
}),
updateMe: actionCreator({
name: 'updateMe',
method(data) {
return this.$axios.put('/api/v1/researchers/me/', data)
},
}),
}
export const mutations = {
getMeSuccess(state, { result }) {
state.profile = result;
},
updateMeSuccess(state, { result }) {
}
}
export const getters = {
getMe(state) {
return state.profile;
},
}

11
store/studies.js

@ -67,6 +67,14 @@ export const actions = { @@ -67,6 +67,14 @@ export const actions = {
return this.$axios.post(`/api/v1/studies/${invitee.studyId}/contributors/invite/`, invitee)
},
}),
joinContributor: actionCreator({
name: 'joinContributor',
method(data) {
return this.$axios.get(`/api/v1/studies/${data.studyId}/contributors/join/${data.key}`)
},
}),
}
export const mutations = {
@ -123,5 +131,8 @@ export const getters = { @@ -123,5 +131,8 @@ export const getters = {
getContributorFromActiveStudy: (state) => ({ contributorId }) => {
contributorId = parseInt(contributorId, 10)
return state.activeStudy.contributors.filter(contributor => contributor.id === contributorId)[0];
},
getJoinInvitationMessage(state) {
return state.message
}
}

57
store/universities.js

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
import { actionCreator } from '@/lib/store';
export const state = () => ({
universities: [],
faculties: [],
studyFields: []
})
export const actions = {
getUniversities: actionCreator({
name: 'getUniversities',
method() {
return this.$axios.get('/api/v1/universities/')
},
}),
getFaculties: actionCreator({
name: 'getFaculties',
method({ universityId }) {
return this.$axios.get(`/api/v1/universities/${universityId}/faculties/`)
},
}),
getFacultyStudyFields: actionCreator({
name: 'getFacultyStudyFields',
method(universityId, facultyId) {
return this.$axios.get(`/api/v1/universities/${universityId}/faculties/${facultyId}/study_fields/`)
},
}),
}
export const mutations = {
getUniversitiesSuccess(state, { result }) {
state.universities = result;
},
getFacultiesSuccess(state, { result }) {
state.faculties = result;
},
getFacultyStudyFieldsSuccess(state, { result }) {
state.studyFields = result;
},
}
export const getters = {
getUniversities(state) {
return state.universities;
},
getFaculties(state) {
return state.faculties;
},
getFacultyStudyFields(state) {
return state.studyFields
},
}
Loading…
Cancel
Save