Created
January 12, 2018 23:32
-
-
Save dib258/467417e362e5cf6cdecfb839fb53de9e to your computer and use it in GitHub Desktop.
Vuejs component to show map + CRUD of institute / student
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="card my-3"> | |
<div class="card-header d-flex"> | |
<div class="pt-2"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing" | |
> | |
<a v-show="show" :href="'institute/'+institute.id">{{ institute.name }}</a> | |
<span v-show="!show">{{ institute.name }}</span> | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="institute.name" | |
v-on:keyup="edited = true" | |
placeholder="Institute name" | |
> | |
</div> | |
<div class="ml-auto"> | |
<button | |
v-on:click="isEditing = true" | |
v-if="!isEditing" | |
class="btn btn-primary" | |
> | |
<i class="fa fa-pencil" aria-hidden="true"></i> | |
</button> | |
<button | |
v-on:click="updateInstitute()" | |
v-if="isEditing" | |
class="btn btn-success" | |
> | |
<i class="fa fa-check" aria-hidden="true"></i> | |
</button> | |
<button | |
v-show="show" | |
v-on:click="deleteInstitute()" | |
class="btn btn-danger ml-1" | |
> | |
<i class="fa fa-times" aria-hidden="true"></i> | |
</button> | |
<button v-on:click="createStudent()" class="btn btn-default ml-1"> | |
Add <i class="fa fa-user" aria-hidden="true"></i> | |
</button> | |
<button | |
v-on:click="$emit('uploadfile', { element : institute.id })" | |
class="btn btn-default" | |
data-toggle="modal" | |
data-target="#uploadModal" | |
> | |
Import | |
<i class="fa fa-file-excel-o" aria-hidden="true"></i> | |
</button> | |
</div> | |
</div> | |
<div class="card-body"> | |
<div class="row mb-2" v-if="isEditing"> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="institute.address_number" | |
v-on:keyup="edited = true" | |
placeholder="Number" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="institute.address_street" | |
v-on:keyup="edited = true" | |
placeholder="Street name" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="institute.address_postal" | |
v-on:keyup="edited = true" | |
placeholder="Postal code" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="institute.address_city" | |
v-on:keyup="edited = true" | |
placeholder="City" | |
> | |
</div> | |
</div> | |
<div v-if="notYetCreatedUser.length"> | |
<student | |
v-for="(student, index) in notYetCreatedUser" | |
v-bind:key="index + '-notcreated'" | |
v-bind:student="student" | |
v-on:studentdeleted="deleteStudent" | |
v-on:studentcreated="confirmStudentCreated" | |
></student> | |
</div> | |
<div v-if="notValidUser.length"> | |
<h5 class="card-title">Invalid address user</h5> | |
<h6 class="card-subtitle mb-2 text-muted">You need to change the address for this student to be valid</h6> | |
<student | |
v-for="(student, index) in notValidUser" | |
v-bind:key="index + '-invalid'" | |
v-bind:student="student" | |
v-on:studentdeleted="deleteStudent" | |
v-on:studentcreated="confirmStudentCreated" | |
v-on:studentupdate="updateStudent" | |
></student> | |
</div> | |
<h5 class="card-title">Valid address user</h5> | |
<student | |
v-for="(student, index) in validUser" | |
v-bind:key="index + '-valid'" | |
v-bind:student="student" | |
v-on:studentdeleted="deleteStudent" | |
v-on:studentcreated="confirmStudentCreated" | |
v-on:studentupdate="updateStudent" | |
v-if="validUser.length" | |
></student> | |
<div v-else> | |
No valid student yet | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
// import Student from 'student'; | |
export default { | |
props : ['institute', 'students', 'show'], | |
data () { | |
return { | |
// students : [], | |
isOneStudentInCreation : false, | |
isEditing : false | |
}; | |
}, | |
computed : { | |
notYetCreatedUser() { | |
return this.students.filter(function (student) { | |
return student.id == -1 | |
}); | |
}, | |
notValidUser() { | |
return this.students.filter(function (student) { | |
return !student.is_valid && student.id != -1; | |
}); | |
}, | |
validUser() { | |
return this.students.filter(function (student) { | |
return student.is_valid && student.id != -1; | |
}) | |
} | |
}, | |
methods : { | |
updateInstitute() { | |
if (this.isEditing && this.edited) { | |
axios | |
.put('/institute/'+this.institute.id, { | |
name : this.institute.name, | |
address_number : this.institute.address_number, | |
address_street : this.institute.address_street, | |
address_postal : this.institute.address_postal, | |
address_city : this.institute.address_city, | |
}) | |
.then(function (response) { | |
this.isEditing = false; | |
this.edited = false; | |
console.log('[Institute.vue] updateInstitute.then :', response.data); | |
this.institute.latitude = response.data.latitude; | |
this.institute.longitude = response.data.longitude; | |
this.$emit('instituteupdate', { | |
institute : this.institute, | |
students : this.students | |
}); | |
}.bind(this)) | |
.catch(error => console.log('[Institute.vue] updateInstitute.catch : ', error)); | |
} else { | |
this.isEditing = false; | |
} | |
}, | |
deleteInstitute() { | |
if (confirm('Are you sure you want to delete the Institute ?\nAll the students inside will be deleted too !')) { | |
axios | |
.delete('/institute/'+this.institute.id) | |
.then(function (response) { | |
console.log('[Institute.vue] deleteInstitute.then : ', response.data.message); | |
this.$emit('institutedelete', { | |
element: this.institute | |
}); | |
}.bind(this)) | |
.catch(error => console.log('[Student.vue] deleteInstitute.catch : ', error)); | |
} | |
}, | |
// Student | |
createStudent() { | |
if (!this.isOneStudentInCreation) { | |
this.isOneStudentInCreation = true; | |
this.students.push({ | |
id: -1, | |
firstname: '', | |
lastname: '', | |
address_city: '', | |
address_number: '', | |
address_postal: '', | |
address_street: '', | |
is_valid: 1, | |
latitude: 0, | |
longitude: 0, | |
transport_mode: '', | |
institute_id: this.institute.id | |
}); | |
} else { | |
// scroll to the current student in creation | |
// or shake the current student in creation | |
} | |
}, | |
confirmStudentCreated(element) { | |
var studentNew = element.element | |
console.log('[Institute.vue] confirmStudentCreated : ', studentNew, this.students); | |
var student = this.students.filter(function (element) { | |
if (element.id == -1 || element.id == studentNew.id) { | |
return element; | |
} | |
}.bind(studentNew)); | |
console.log('[Institute.vue] confirmStudentCreated : found student', student); | |
if (student.length > 0) { | |
var id = this.students.indexOf(student[0]); | |
// Remove the current new student | |
this.students.splice(id, 1); | |
// this.students[id] = studentNew; | |
this.isOneStudentInCreation = false; | |
// Emit to the parent to let him add the new student | |
this.$emit('studentcreate', { | |
institute : this.institute, | |
student : studentNew | |
}) | |
} else { | |
console.log('[Institute.vue] confirmStudentCreated.else : error student new not found'); | |
} | |
}, | |
updateStudent(element) { | |
var studentNew = element.element; | |
console.log('[Institute.vue] updateStudent : ', studentNew); | |
var student = this.students.filter(function (element) { | |
if (element.id == studentNew.id) { | |
return element; | |
} | |
}); | |
console.log('[Institute.vue] updateStudent : found student', student); | |
// if (student.length > 0) { | |
var id = this.students.indexOf(student[0]); | |
this.students.splice(id, 1); | |
// this.students[id] = studentNew; | |
console.log('[Institute.vue] updateStudent.if : found student'); | |
this.$emit('studentupdate', { | |
institute : this.institute, | |
student : studentNew | |
}) | |
// Redo the sort between good and invalid user (or it'll be automatic after the correct update of the new student data) | |
// } else { | |
// console.log('[Institute.vue] updateStudent.else : error student not found'); | |
// } | |
}, | |
deleteStudent(element) { | |
var student = element.element; | |
var id = this.students.indexOf(student); | |
if (id > -1) { | |
this.$emit('studentdelete', { | |
institute : this.institute, | |
student : student | |
}) | |
this.students.splice(id, 1); | |
} else { | |
console.log('[Institute.vue] deleteStudent.else : error finding student to delete'); | |
} | |
} | |
}, | |
created() { | |
console.log('[Institute.vue] created : ',this.institute); | |
// Retrieve only the id and let the Student component grab it's informations | |
// More request but otherwise how to have parent / child same information | |
// Since I create an empty user in the institute array | |
// Then the update of the data happen in the child (Student component) | |
// ??? | |
// axios | |
// .get('/institute/'+this.institute.id+'/student') | |
// .then((response) => { | |
// this.students = response.data; | |
// }); | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@extends('layouts.app') | |
@section('content') | |
<div class="container"> | |
<school | |
v-bind:institutes="{{ json_encode($institutes) }}" | |
v-bind:schoolid="{{ $schoolId }}" | |
v-bind:show="true" | |
v-bind:publicpath="{{ json_encode(asset('')) }}" | |
></school> | |
</div> | |
@endsection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<div id="mapdiv" class="my-3"></div> | |
<StudentMap | |
v-for="(tuple, index) in database" | |
v-bind:key="index" | |
v-bind:map="map" | |
v-bind:tuple="tuple" | |
v-bind:publicpath="publicpath" | |
></StudentMap> | |
<!-- v-bind:institute="tuple.institute" --> | |
<!-- v-bind:students="tuple.students" --> | |
</div> | |
</template> | |
<script> | |
import StudentMap from './StudentMap.vue'; | |
export default { | |
props : ['database', 'publicpath'], | |
data() { | |
return { | |
map : null, | |
}; | |
}, | |
watch : { | |
database () { | |
this.$forceUpdate(); | |
console.log('[MapBox.vue] watch.database : Detected a change in the database'); | |
} | |
}, | |
created() { | |
/* Minimum Zoom 0 , Maximum Zoom 20 */ | |
/* Creation of the OpenStreetMap */ | |
var oMapCenter = | |
{ | |
center: [50.820008, 4.368169], | |
zoom: 11 | |
} | |
var oTileSettings = | |
{ | |
maxZoom: 18, | |
minZoom: 12, | |
id: 'mapbox.streets', | |
accessToken: document.head.querySelector('meta[name="mapbox-token"]').content | |
} | |
// Why the observer database.length is empty, but contains the 3 tuples ? | |
// this.database.forEach(function (tuple) { | |
// }.bind(this)); | |
this.$nextTick(function () { | |
this.map = L.map('mapdiv', oMapCenter); | |
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', oTileSettings).addTo(this.map); | |
L.control.scale().addTo(this.map); | |
}.bind(this)); | |
}, | |
components : { | |
StudentMap | |
} | |
} | |
</script> | |
<style lang="scss"> | |
#mapdiv { | |
height: 600px; | |
} | |
.leaflet-bottom.leaflet-right { | |
/* Make the Attributions disappear from left bottom border */ | |
bottom: -20px !important; | |
} | |
.leaflet-left { | |
.leaflet-control { | |
.leaflet-control-scale-line { | |
&:first-child { | |
background-color: rgba(255, 255, 255, 0); | |
} | |
&:last-child { | |
display: none; | |
} | |
} | |
} | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<mapbox | |
v-bind:database="database" | |
v-bind:publicpath="publicpath" | |
></mapbox> | |
<div v-show="!show"> | |
<a :href="publicpath" v-show="!show" class="btn btn-default"> | |
<i class="fa fa-chevron-left" aria-hidden="true"></i> Back | |
</a> | |
</div> | |
<div v-show="show" class="text-right"> | |
<button v-on:click="createInstitute()" class="btn btn-default my-3">Add Institution</button> | |
</div> | |
<div class="card" v-show="isOneInstituteInCreation"> | |
<div class="card-header d-flex"> | |
<div class="pt-2">Create a new Institute</div> | |
<div class="ml-auto"> | |
<button v-on:click="storeInstitute()" class="btn btn-success"><i class="fa fa-check"></i></button> | |
<button v-on:click="isOneInstituteInCreation = false; edited = false;" class="btn btn-danger"><i class="fa fa-times"></i></button> | |
</div> | |
</div> | |
<div class="card-body"> | |
<div class="row"> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-model="newInstitute.name" | |
v-on:keyup="edited = true" | |
placeholder="Name" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-model="newInstitute.address_number" | |
v-on:keyup="edited = true" | |
placeholder="Number" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-model="newInstitute.address_street" | |
v-on:keyup="edited = true" | |
placeholder="Street name" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-model="newInstitute.address_postal" | |
v-on:keyup="edited = true" | |
placeholder="Postal code" | |
> | |
</div> | |
<div class="col"> | |
<input | |
class="form-control" | |
v-model="newInstitute.address_city" | |
v-on:keyup="edited = true" | |
placeholder="City" | |
> | |
</div> | |
</div> | |
</div> | |
</div> | |
<institute | |
v-for="(element, index) in database" | |
v-bind:key="index" | |
v-bind:institute="element.institute" | |
v-bind:students="element.students" | |
v-bind:show="show" | |
v-on:uploadfile="showModal" | |
v-on:institutedelete="deleteInstitute" | |
v-on:instituteupdate="updateInstitute" | |
v-on:studentcreate="addStudent" | |
v-on:studentupdate="updateStudent" | |
v-on:studentdelete="deleteStudent" | |
></institute> | |
<div class="modal" v-show="isModalShowed" :class="{ in: isModalShowed }" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="uploadModal" aria-hidden="true"> | |
<form id="uploadForm" :action="'http://goodmap.test/institute/'+uploadInstituteId+'/uploadExcel'" method="post" enctype="multipart/form-data"> | |
<div class="modal-dialog" role="document"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h5 class="modal-title">Upload excel file</h5> | |
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |
<span aria-hidden="true">×</span> | |
</button> | |
</div> | |
<div class="modal-body"> | |
<input type="hidden" name="_token" :value="csrf"> | |
<input class="form-control" type="file" name="excel"> | |
<!-- <label class="btn btn-default"> | |
<span class="btn btn-primary">Browse file</span> <input type="file" name="excel" hidden> | |
</label> --> | |
</div> | |
<div class="modal-footer text-right"> | |
<button type="submit" class="btn btn-primary">Upload file</button> | |
</div> | |
</div> | |
</div> | |
</form> | |
</div> | |
</div> | |
</template> | |
<script> | |
export default { | |
props : ['institutes', 'schoolid', 'show', 'publicpath'], | |
data() { | |
return { | |
isOneInstituteInCreation : false, | |
edited : false, | |
newInstitute : { | |
id: -1, | |
name: '', | |
address_city: '', | |
address_number: '', | |
address_postal: '', | |
address_street: '', | |
latitude: 0, | |
longitude: 0, | |
school_id: this.schoolId | |
}, | |
uploadInstituteId : 0, | |
isModalShowed : false, | |
csrf : document.head.querySelector('meta[name="csrf-token"]').content, | |
database: [] | |
}; | |
}, | |
methods : { | |
showModal(element) { | |
console.log('[School.vue] showModal : called !', element.element); | |
// this.isModalShowed = true; | |
this.uploadInstituteId = element.element; | |
}, | |
createInstitute() { | |
if (!this.isOneInstituteInCreation) { | |
this.isOneInstituteInCreation = true; | |
this.newInstitute = { | |
id: -1, | |
name: '', | |
address_city: '', | |
address_number: '', | |
address_postal: '', | |
address_street: '', | |
latitude: 0, | |
longitude: 0, | |
school_id: this.schoolid | |
}; | |
} else { | |
// scroll to the current student in creation | |
// or shake the current student in creation | |
} | |
}, | |
storeInstitute() { | |
if (this.isOneInstituteInCreation && this.edited) { | |
axios | |
.post('/institute', { | |
name : this.newInstitute.name, | |
address_number : this.newInstitute.address_number, | |
address_street : this.newInstitute.address_street, | |
address_postal : this.newInstitute.address_postal, | |
address_city : this.newInstitute.address_city, | |
school_id : this.schoolid | |
}) | |
.then(function (response) { | |
// this.institutes.push(response.data.institute); | |
this.database.push({ | |
institute : response.data.institute, | |
students : [] | |
}); | |
console.log('[School.vue] storeInstitute.if.then : '+response.data.id); | |
this.isOneInstituteInCreation = false; | |
this.edited = false; | |
}.bind(this)) | |
.catch(error => console.log('[School.vue] storeInstitute.if.catch : '+error)); | |
} else { | |
this.isOneInstituteInCreation = false; | |
this.edited = false; | |
} | |
}, | |
updateInstitute(element) { | |
var institute = element.institute; | |
var students = element.students | |
for (var i = 0; i < this.database.length; i++) { | |
if (this.database[i].institute.id == institute.id) { | |
this.database.splice(i, 1); | |
this.database.push({ | |
institute : institute, | |
students : students | |
}); | |
// this.database[i].institute = institute; | |
this.$forceUpdate(); | |
console.log('[School.vue] updateInstitute.if : ', this.database); | |
} | |
} | |
}, | |
deleteInstitute(element) { | |
var institute = element.element; | |
console.log('[School.vue] deleteInstitute : print institute'); | |
console.log(institute); | |
for (var i = 0; i < this.database.length; i++) { | |
if (this.database[i].institute.id == institute.id) { | |
// this.database.splice(i, 1); | |
console.log('[School.vue] deleteInstitute.if.beforeDelete : ', this.database); | |
Vue.delete(this.database, i); | |
// this.$forceUpdate(); | |
console.log('[School.vue] deleteInstitute.if.afterDelete : ', this.database); | |
} | |
} | |
// var id = this.institutes.indexOf(institute); | |
// console.log('[School.vue] deleteInstitute.id : '+id); | |
// if (id > -1) { | |
// this.institutes.splice(id, 1); | |
// this.$forceUpdate() | |
// console.log('[School.vue] deleteInstitute.if : ', this.institutes); | |
// } else { | |
// console.log('[School.vue] deleteInstitute.else : error finding institute to delete'); | |
// } | |
}, | |
addStudent(element) { | |
for (var i = 0; i < this.database.length; i++) { | |
if (this.database[i].institute.id == element.institute.id) { | |
this.database[i].students.push(element.student); | |
this.$forceUpdate(); | |
console.log('[School.vue] addStudent.if : ', this.database[i].students); | |
} | |
} | |
}, | |
updateStudent(element) { | |
console.log('[School.vue] updateStudent : ', element.institute, element.student); | |
for (var i = 0; i < this.database.length; i++) { | |
if (this.database[i].institute.id == element.institute.id) { | |
// for (var j = 0; j < this.database[i].students.length; j++) { | |
// if (this.database[i].students[j].id == element.student.id) { | |
// this.database[i].students[j] = element.student; | |
// this.database[i].students.splice(j, 1); | |
this.database[i].students.push(element.student); | |
this.$forceUpdate(); | |
console.log('[School.vue] updateStudent.if : found ', this.database[i].students); | |
// } | |
// } | |
} | |
} | |
}, | |
deleteStudent(element) { | |
for (var i = 0; i < this.database.length; i++) { | |
if (this.database[i].institute.id == element.institute.id) { | |
for (var j = 0; j < this.database[i].students.length; j++) { | |
if (this.database[i].students[j].id == element.student.id) { | |
this.database[i].students.splice(j, 1); | |
this.$forceUpdate() | |
console.log('[School.vue] deleteStudent.if : ', this.database[i].students); | |
} | |
} | |
} | |
} | |
} | |
}, | |
mounted() { | |
this.$nextTick(function () { | |
console.log('[School.vue] created : ', this.institutes.length); | |
// For each institute we make an ajax request to retrieve is students | |
for(var i = 0; i < this.institutes.length; i++) { | |
console.log('[School.vue] created : ', this.institutes[i]); | |
axios | |
.get('/institute/'+this.institutes[i].id+'/student') | |
.then(function (response) { | |
for (var j = 0; j < this.institutes.length; j++) { | |
if (this.institutes[j].id == response.data.instituteid) { | |
console.log('[School.vue] created.then : ', this.institutes[j]); | |
this.database.push({ | |
institute : this.institutes[j], | |
students : response.data.students | |
}); | |
} | |
} | |
}.bind(this)); | |
} | |
}.bind(this)); | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="row my-2 border p-2 student"> | |
<div class="col-1"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing" | |
> | |
{{ student.firstname }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.firstname" | |
v-on:keyup="edited = true" | |
placeholder="Firstname" | |
> | |
</div> | |
<div class="col-1"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing" | |
> | |
{{ student.lastname }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.lastname" | |
v-on:keyup="edited = true" | |
placeholder="Lastname" | |
> | |
</div> | |
<div class="col-1"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing"> | |
{{ student.address_number }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.address_number" | |
v-on:keyup="edited = true" | |
placeholder="Number" | |
> | |
</div> | |
<div class="col-2"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing"> | |
{{ student.address_street }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.address_street" | |
v-on:keyup="edited = true" | |
placeholder="Street name" | |
> | |
</div> | |
<div class="col-2"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing"> | |
{{ student.address_postal }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.address_postal" | |
v-on:keyup="edited = true" | |
placeholder="Postal code" | |
> | |
</div> | |
<div class="col-2"> | |
<span | |
class="text mt-2" | |
v-show="!isEditing"> | |
{{ student.address_city }} | |
</span> | |
<input | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.address_city" | |
v-on:keyup="edited = true" | |
placeholder="City" | |
> | |
</div> | |
<div class="col-2"> | |
<span | |
class="text mt-2 badge" | |
:class="colorForTransportation(student.transport_mode)" | |
v-show="!isEditing"> | |
{{ student.transport_mode }} | |
</span> | |
<select | |
class="form-control" | |
v-show="isEditing" | |
v-model="student.transport_mode" | |
v-on:change="edited = true" | |
> | |
<option disabled value="">Transport</option> | |
<option | |
v-for="(transport, index) in transportation_mode" | |
v-bind:key="index" | |
v-bind:value="transport.value" | |
> | |
{{ transport.text }} | |
</option> | |
</select> | |
</div> | |
<div class="col-1 d-flex"> | |
<button v-show="!isEditing" v-on:click="isEditing = true" class="btn btn-primary"><i class="fa fa-pencil" aria-hidden="true"></i></button> | |
<button v-show="isEditing" v-on:click="updateStudent()" class="btn btn-success"><i class="fa fa-check" aria-hidden="true"></i></button> | |
<button v-on:click="deleteStudent()" class="btn btn-danger ml-1"><i class="fa fa-times" aria-hidden="true"></i></button> | |
</div> | |
</div> | |
</template> | |
<script> | |
export default { | |
props : ['student'], | |
data () { | |
return { | |
isNew : false, | |
isEditing : false, | |
edited : false, | |
transportation_mode : [ | |
{ text: 'Pied', value: 'pied', color : 'vert'}, | |
{ text: 'Velo', value: 'velo', color : 'bleu'}, | |
{ text: 'Moto', value: 'moto', color : 'rouge'}, | |
{ text: 'Voiture', value: 'voiture', color : 'rouge'}, | |
{ text: 'Covoiturage', value: 'covoiturage', color : 'violet'}, | |
{ text: 'Bus', value: 'bus', color : 'orange'}, | |
{ text: 'Tram', value: 'tram', color : 'orange'}, | |
{ text: 'Train', value: 'train', color : 'orange'}, | |
] | |
}; | |
}, | |
methods : { | |
colorForTransportation(value) { | |
var elm = this.transportation_mode.filter(function (transport) { | |
if ( transport.value == value) return transport; | |
}); | |
if (elm.length > 0) { | |
return elm[0].color; | |
} | |
}, | |
updateStudent() { | |
if (this.isEditing && this.edited) { | |
if (this.isNew) { | |
console.log('[Student.vue] updateStudent.if : is new'); | |
axios | |
.post('/student', { | |
firstname : this.student.firstname, | |
lastname : this.student.lastname, | |
address_number : this.student.address_number, | |
address_street : this.student.address_street, | |
address_postal : this.student.address_postal, | |
address_city : this.student.address_city, | |
transport_mode : this.student.transport_mode, | |
institute_id : this.student.institute_id | |
}) | |
.then(function (response) { | |
this.student.id = response.data.id; | |
this.student.is_valid = response.data.is_valid; | |
this.student.latitude = response.data.latitude; | |
this.student.longitude = response.data.longitude; | |
console.log('[Student.vue] updateStudent.if.then : '+response.data.id); | |
this.isEditing = false; | |
this.isNew = false; | |
this.edited = false; | |
this.$emit('studentcreated', { | |
element : this.student | |
}); | |
}.bind(this)) | |
.catch(error => console.log('[Student.vue] updateStudent.if.catch : '+error)); | |
} else { | |
console.log('[Student.vue] updateStudent.else : is not new'); | |
axios | |
.put('/student/'+this.student.id, { | |
firstname : this.student.firstname, | |
lastname : this.student.lastname, | |
address_number : this.student.address_number, | |
address_street : this.student.address_street, | |
address_postal : this.student.address_postal, | |
address_city : this.student.address_city, | |
transport_mode : this.student.transport_mode | |
}) | |
.then(function (response) { | |
this.isEditing = false; | |
this.edited = false; | |
// Retrieve is address is valid | |
console.log('[Student.vue] updateStudent.else.then : '+response.data.is_valid); | |
this.student.is_valid = response.data.is_valid; | |
this.student.latitude = response.data.latitude; | |
this.student.longitude = response.data.longitude; | |
this.$emit('studentupdate', { | |
element : this.student | |
}); | |
}.bind(this)) | |
.catch(error => console.log('[Student.vue] updateStudent.else.catch : '+error)); | |
} | |
} else { | |
// If nothing has been changed we do not sent modifications | |
this.isEditing = false; | |
} | |
}, | |
deleteStudent() { | |
if (!this.isNew) { | |
if (confirm('Are you sure you want to delete this student ?')) { | |
axios | |
.delete('/student/'+this.student.id) | |
.then(function (response) { | |
console.log('[Student.vue] deleteStudent.then : '+response.data.message); | |
this.$emit('studentdeleted', { | |
element: this.student | |
}); | |
}.bind(this)) | |
.catch(error => console.log('[Student.vue] deleteStudent.catch : ' +error)); | |
} | |
} else { | |
this.$emit('studentdeleted', { | |
element: this.student | |
}); | |
} | |
} | |
}, | |
created() { | |
if (this.student.id == -1) { | |
this.isNew = true; | |
this.isEditing = true; | |
} | |
} | |
} | |
</script> | |
<style lang="scss"> | |
.student { | |
span { | |
display : inline-block; | |
} | |
.badge { | |
padding: 9px; | |
border-radius: 82px; | |
color: #FFFFFF; | |
} | |
.orange { | |
background-color : #F08707; | |
} | |
.bleu { | |
background-color : #1895D3; | |
} | |
.violet { | |
background-color : #B383AF; | |
} | |
.rouge { | |
background-color : #ff5b5b; | |
} | |
.jaune { | |
background-color : #f9c851; | |
} | |
.vert { | |
background-color : #10c469; | |
} | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div></div> | |
</template> | |
<script> | |
export default { | |
props: ['map', 'tuple', 'publicpath'], | |
data() { | |
return { | |
oSmallCircleParams : { | |
color: 'blue', // Stroke | |
weight: '5', // Stroke | |
opacity: '0,3', // Stroke | |
stroke: false, // stroke | |
film: true, | |
fillColor: 'blue', | |
fillOpacity: 0.3, | |
radius: 500 | |
// clickabe: true [ If you want to click ] | |
// className : 'NameOfClass' [ If you want to give it a class ] | |
}, | |
oBigCircleParams : { | |
color: 'green', // Stroke | |
weight: '5', // Stroke | |
opacity: '0,2', // Stroke | |
stroke: false, // stroke | |
film: true, | |
fillColor: 'green', | |
fillOpacity: 0.2, | |
radius: 2000 | |
// clickabe: true [ If you want to click ] | |
// className : 'NameOfClass' [ If you want to give it a class ] | |
}, | |
instituteIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/school.svg', | |
iconSize: [50, 50], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
veloIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/velo.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
motoIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/moto.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
voitureIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/voiture.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
piedIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/pied.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
covoiturageIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/covoiturage.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
tramIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/tram.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
trainIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/train.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
busIcon : L.icon( | |
{ | |
iconUrl: this.publicpath+'icons/bus.svg', | |
iconSize: [15, 15], // Icon Dimension | |
iconAnchor: (0, 0), // Position Icon | |
popupAnchor: [-3, -76] // Popup Anchor Position from Icon | |
} | |
), | |
arrayIcon : null, | |
layerGroup : null, | |
}; | |
}, | |
methods : { | |
addSchoolAndRadius(institute) { | |
console.log('[MapBox.vue] addSchoolAndRadius : begin'); | |
/* Creation of Circles */ | |
// Radius are in Meters | |
var school = [institute.latitude, institute.longitude]; | |
var oSmallCircle = L.circle((school), this.oSmallCircleParams).addTo(this.layerGroup); | |
var oBigCircle = L.circle((school), this.oBigCircleParams).addTo(this.layerGroup); | |
/* Creation of Popups in already created circle */ | |
var sBigCirclePopup = "Distance parcourable à vélo (rayon de 4km autour de l'école)"; | |
oBigCircle.bindPopup(sBigCirclePopup); | |
/* Creation of Marker with Institutes Image */ | |
L.marker( (school), {icon: this.instituteIcon} ).addTo(this.layerGroup); | |
}, | |
addStudents(students) { | |
console.log('[MapBox.vue] addStudents : begin'); | |
students.forEach(function (student) { | |
if (student.is_valid && student.id != -1) { | |
var user = [student.latitude, student.longitude]; | |
console.log('[MapBox.vue] addStudents.forEach : ', student.transport_mode); | |
console.log('[MapBox.vue] addStudents.forEach.arrayIcon : ', this.arrayIcon); | |
// TODO : Deterimene student.transport and apply | |
L.marker( (user), {icon: this.arrayIcon[student.transport_mode]} ).addTo(this.layerGroup); | |
} | |
}.bind(this)); | |
}, | |
eraseCurrentMapLayers() { | |
// this.map.clearLayers(); | |
this.layerGroup.clearLayers(); | |
// this.layerGroup.eachLayer(function (layer) { | |
// console.log('[StudentMap.vue] eraseCurrentMapLayers : ', layer); | |
// this.layerGroup.removeLayer(); | |
// }.bind(this)); | |
} | |
}, | |
watch : { | |
tuple(newTuple) { | |
console.log('[StudentMap.vue] : watch.tuple : newTuple'); | |
this.addSchoolAndRadius(newTuple.institute); | |
this.addStudents(newTuple.students); | |
} | |
// institute : function (newInstitute) { | |
// console.log('[StudentMap.vue] : watch.institute : newInstitute'); | |
// this.addSchoolAndRadius(newInstitute); | |
// this.addStudents(this.students); | |
// }, | |
// students : function (newStudents) { | |
// console.log('[StudentMap.vue] : watch.students : newStudents'); | |
// this.eraseCurrentMapLayers(); | |
// this.addSchoolAndRadius(this.institute); | |
// this.addStudents(newStudents); | |
// } | |
}, | |
created() { | |
this.arrayIcon = { | |
"pied" : this.piedIcon, | |
"velo" : this.veloIcon, | |
"moto" : this.motoIcon, | |
"voiture" : this.voitureIcon, | |
"covoiturage" : this.covoiturageIcon, | |
"bus" : this.busIcon, | |
"tram" : this.tramIcon, | |
"train" : this.trainIcon, | |
} | |
this.layerGroup = L.layerGroup().addTo(this.map); | |
// console.log('[MapBox.vue] created : database size', this.database.length); | |
// console.log('[MapBox.vue] created : database content', this.database); | |
this.addSchoolAndRadius(this.tuple.institute); | |
this.addStudents(this.tuple.students); | |
} | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment