Skip to content

Commit

Permalink
add proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
ajatprabha committed Oct 23, 2018
1 parent 81f5fec commit 2fe5945
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 8 deletions.
6 changes: 3 additions & 3 deletions ui/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 ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"vue": "^2.5.2",
"vue-analytics": "^5.16.0",
"vue-router": "^3.0.1",
"vuetify": "^1.2.4",
"vuetify": "^1.3.1",
"vuex": "^3.0.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/MentorList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
...mapActions('mentorList', ['fetchMentorList'])
},
mounted () {
this.fetchMentorList()
if (!this.mentorList.length) this.fetchMentorList()
}
}
</script>
Expand Down
15 changes: 12 additions & 3 deletions ui/src/components/Project.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<div>
<v-icon class="mx-2" v-if="mentor" @click="dialog = true">fa-trash</v-icon>
<v-icon class="mx-2" v-if="mentor" @click="editDialog = true">fa-pencil</v-icon>
<v-btn v-if="showProposalDialogButton" @click="proposalDialog = true">Add Proposal</v-btn>
<a :href="project.github_link" target="_blank" class="dashline">
<v-icon class="mx-2">fa-github</v-icon>
</a>
Expand All @@ -23,6 +24,9 @@
<v-dialog v-if="mentor" v-model="editDialog" max-width="900">
<ProjectCreateUpdate :mode="'update'" :updateId="project.id" :key="project.id" @close_dialog="editDialog = false"/>
</v-dialog>
<v-dialog v-if="showProposalDialogButton" v-model="proposalDialog" max-width="900">
<ProposalCreateUpdate :mode="'apply'" :projectId="project.id" @close_dialog="proposalDialog = false"/>
</v-dialog>
</div>
</v-layout>
<div>{{project.short_description}}</div>
Expand Down Expand Up @@ -55,21 +59,27 @@
<script>
import {mapGetters, mapActions} from 'vuex'
import ProjectCreateUpdate from './ProjectCreateUpdate'
import ProposalCreateUpdate from './ProposalCreateUpdate'
export default {
name: 'Project',
components: {ProjectCreateUpdate},
components: {ProjectCreateUpdate, ProposalCreateUpdate},
props: ['project', 'mentor', 'mode'],
data () {
return {
dialog: false,
editDialog: false
editDialog: false,
proposalDialog: false
}
},
computed: {
...mapGetters('mentorList', ['mentorList']),
...mapGetters('auth', ['isLoggedIn']),
chips () {
return this.project.technologies
},
showProposalDialogButton () {
return !this.mentor && this.isLoggedIn
}
},
methods: {
Expand Down Expand Up @@ -98,4 +108,3 @@
text-decoration: none;
}
</style>

139 changes: 139 additions & 0 deletions ui/src/components/ProposalCreateUpdate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<template>
<v-layout column>
<v-card flat>
<v-container
fluid>
<v-layout row wrap>
<v-card-title primary-title>
<span class="display-1 primary--text">{{this.mode|capitalize}} Proposal</span>
</v-card-title>
<v-spacer></v-spacer>
<v-icon @click="$emit('close_dialog')">fa-times-circle</v-icon>
</v-layout>
<v-form>
<v-layout row wrap>
<v-flex xs12>
<v-text-field prepend-icon="person" name="proposal_drive_link" label="Drive Link"
:rules="[rules.required, rules.url]"
v-model="proposal.drive_link"/>
</v-flex>
</v-layout>
</v-form>
<v-card-actions>
<v-flex xs4></v-flex>
<v-flex xs4>
<v-btn primary round large block color="primary" @click="performCreateUpdate">
{{mode === 'apply' ? 'Apply':'Update'}}
</v-btn>
</v-flex>
<v-flex xs4></v-flex>
</v-card-actions>
</v-container>
</v-card>
</v-layout>
</template>

<script>
import {mapGetters, mapActions} from 'vuex'
import _ from 'lodash'
export default {
name: 'ProposalCreateUpdate',
props: ['mode', 'updateId', 'projectId'],
data: () => ({
proposal: {
id: '',
project: '',
student: '',
drive_link: '',
file: null,
is_accepted: false
},
rules: {
required: value => !!value || 'Required.',
url: value => /(http(s)?:\/\/.)(www\.)?[-a-zA-Z0-9@:%._~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_.~#?&//=]*)/g
.test(value) || 'Invalid URL (include https://)'
}
}),
computed: {
...mapGetters('studentProfile', ['studentProfile']),
...mapGetters('proposalList', ['studentProposalList'])
},
mounted () {
if (this.mode === 'update') {
this.setProposal()
}
if (this.studentProfile.id === '') this.fetchStudentProfile()
},
methods: {
...mapActions('studentProfile', ['fetchStudentProfile']),
...mapActions('proposalList', ['addProposal', 'updateProposal']),
performCreateUpdate () {
if (this.mode === 'apply') this.performApply()
else this.performUpdate()
},
setFile (file) {
this.proposal.file = file
},
performApply () {
this.$httpClient.post('/api/project/student-proposal/', {
project: this.projectId,
student: this.studentProfile.id,
drive_link: this.proposal.drive_link
}).then(response => {
this.addProposal(_.cloneDeep(response.data))
this.$emit('close_dialog')
this.proposal = {
id: '',
project: '',
student: '',
drive_link: ''
}
this.$store.dispatch('messages/showMessage', {
message: 'Proposal applied successfully! Go to dashboard to view.',
color: 'success'
}, {root: true})
}).catch(err => {
if (err.response.status === 400 && err.response.data.non_field_errors[0] === 'The fields project, student must make a unique set.') {
this.$store.dispatch('messages/showMessage', {
message: 'You can\'t apply twice for a project. Go to your dashboard to edit a proposal.',
color: 'error'
}, {root: true})
}
})
},
performUpdate () {
this.$httpClient.patch(`/api/project/student-proposal/${this.updateId}/`, {
drive_link: this.proposal.drive_link
}).then(response => {
this.updateProposal(_.cloneDeep(response.data))
this.proposal = response.data
this.$emit('close_dialog')
}).catch(() => {
this.$store.dispatch('messages/showMessage', {
message: 'Something went wrong!',
color: 'error'
}, {root: true})
})
},
setProposal () {
if (this.updateId) {
const proposal = this.studentProposalList.find(proposal => proposal.id === this.updateId)
if (proposal) this.proposal = proposal
else {
this.$httpClient.get(`/api/project/student-proposal/${this.updateId}/`).then(response => {
this.project = response.data
})
}
}
}
},
filters: {
capitalize: value => value.charAt(0).toUpperCase() + value.slice(1)
}
}
</script>

<style scoped>
</style>
60 changes: 60 additions & 0 deletions ui/src/store/modules/proposalList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {httpClient} from '../../plugins/httpClient'

const state = {
proposalList: [{
id: '',
project: '',
student: '',
drive_link: '',
file: null,
is_accepted: false
}]
}

const getters = {
proposalList: (state, getters) => state.proposalList[0] ? state.proposalList : [],
studentProposalList: (state, getters, rootState, rootGetters) => state.proposalList
.filter(proposal => proposal.student === rootGetters['studentProfile/studentProfile'].id)
}

const mutations = {
'SET_PROPOSAL_LIST' (state, proposalList) {
state.proposalList = proposalList
},
'REMOVE_PROPOSAL' (state, proposalId) {
state.proposalList = state.proposalList.filter(proposal => proposal.id !== proposalId)
},
'ADD_PROPOSAL' (state, proposal) {
state.proposalList.push(proposal)
},
'UPDATE_PROPOSAL' (state, updatedProposal) {
state.proposalList = [
...state.proposalList.filter(proposal => proposal.id !== updatedProposal.id),
updatedProposal
].sort((a, b) => a.id - b.id)
}
}

const actions = {
fetchProposalList ({commit}, state) {
httpClient.get('/api/project/student-proposal/').then(response => {
commit('SET_PROPOSAL_LIST', response.data)
}).catch(err => console.log(err))
},
removeProposalById ({commit}, proposalId) {
commit('REMOVE_PROPOSAL', proposalId)
},
addProposal ({commit}, proposal) {
commit('ADD_PROPOSAL', proposal)
},
updateProposal ({commit}, proposal) {
commit('UPDATE_PROPOSAL', proposal)
}
}

export {
state,
getters,
mutations,
actions
}

0 comments on commit 2fe5945

Please sign in to comment.