Commit 078881bc authored by Martin Féaux's avatar Martin Féaux
Browse files

Merge branch 'trace' into 'master'

Trace

See merge request mFeaux/site-vikazimute!30
parents 11ab77bb ba1b6dd8
......@@ -6,7 +6,8 @@ framework:
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
cookie_secure: auto
cookie_samesite: lax
......
......@@ -14,12 +14,12 @@ function initIcon(modify, span, icon) {
function customeDropzone(uploadLink, defaultMessage, removeMessage, uploadErrorMessage,
modify, xmlIcon, spanXml, kmlIcon, spanKml, imageIcon, spanImage) {
return new Dropzone(".dropzone", {
timeout: 9000000,
url: uploadLink,
maxFiles: 4,
dictDefaultMessage: defaultMessage,
dictRemoveFile: removeMessage,
maxFilesize: 50, // in Mb
acceptedFile: "text/xml, application/vnd.google-earth.kml+xml, image/*",
addRemoveLinks: true,
uploadErrorMessage: uploadErrorMessage,
modify: modify,
......@@ -172,20 +172,23 @@ function previewMap(data, divMap, divLeaflet, map, overlay, img) {
});
try{
let lines = data.kml.split('\n');
lines.splice(0, 1);
let kml = lines.join('\n');
let parser = new DOMParser();
let kmlDoc = parser.parseFromString(data.kml, "text/xml");
let kmlDoc = parser.parseFromString(kml, "text/xml");
divMap.appendChild(divLeaflet);
let corner = calculateCorner(kmlDoc);
divLeaflet.style.width = "400px";
divLeaflet.style.height = "400px";
divLeaflet.style.width = Math.floor(window.innerHeight * 0.7)+"px";
divLeaflet.style.height = Math.floor(window.innerHeight * 0.7)+"px";
overlay.reposition(L.latLng(corner[0]), L.latLng(corner[1]), L.latLng(corner[2]));
overlay.reposition(L.latLng(corner[0]), L.latLng(corner[1]), L.latLng(corner[3]));
map.fitBounds([corner[0], corner[2]]);
}catch(e){
console.log(e);
let error = document.createElement("p");
error.setAttribute("class", "alert alert-danger");
......
class ColorPicker{
constructor(){
this.colors = [];
this.basic_color = [{red: 10, green: 40, blue: 250}, {red: 250, green: 10, blue: 10},
{red: 10, green: 250, blue: 70}, {red: 30, green: 30, blue: 30}, {red: 230, green: 160, blue: 30}];
}
addColor(){
let color;
if(this.basic_color.length > 0){
color = this.basic_color[0];
this.basic_color.splice(0, 1);
}else{
let red = Math.floor(Math.random() * (230 - 0)) + 0;
let green = Math.floor(Math.random() * (230 - 0)) + 0;
let blue = Math.floor(Math.random() * (230 - 0)) + 0;
color = {red: red, green: green, blue: blue};
}
this.colors.push(color);
return color;
}
removeColor(color){
if(typeof color == "string"){
color = this.StringToColor(color);
}
let colors = this.colors;
this.basic_color.push(color);
colors.forEach(function(color2, index){
if(color2.red == color.red && color2.green == color.green && color2.blue == color.blue)
return colors.splice(index, 1);
});
}
ColorToString(color){
return '#' + this.NbToString(color.red) + this.NbToString(color.green) + this.NbToString(color.blue);
}
NbToString(number){
number = Math.floor(number);
let str = number.toString(16);
if(str.length == 1)
return "0" + str;
if(str.length > 2)
return "fa";
return str;
}
StringToColor(string){
let color = {};
let str = string.substring(4, string.length - 1).split(",");
color.red = parseInt(str[0]);
color.green = parseInt(str[1]);
color.blue = parseInt(str[2]);
return color;
}
}
\ No newline at end of file
function addTrack(event, map, track){
let color = colorPicker.addColor();
let gpx = new L.GPX(track, {async: true,
polyline_options: {color: color}});
gpx.addTo(map);
event.target.style.backgroundColor = colorPicker.ColorToString(color);
let handler = function(e){
e.target.removeEventListener("click", handler);
removeTrack(e, map, gpx, track);
};
event.target.addEventListener("click", handler);
}
function removeTrack(event, map, gpx, track){
let color = event.target.style.backgroundColor;
colorPicker.removeColor(color);
gpx.clearLayers();
event.target.style.backgroundColor = "white";
let handler = function(e){
e.target.removeEventListener("click", handler);
addTrack(e, map, track);
};
event.target.addEventListener("click", handler);
}
function addTable(event, name, checkpoints){
table.push([name, checkpoints]);
showTable();
let handler = function(e){
e.target.removeEventListener("click", handler);
removeTable(e, name, checkpoints);
};
event.target.addEventListener("click", handler);
}
function removeTable(event, name, checkpoints){
table.forEach(function(orienteer, index){
if(orienteer[0] == name){
table.splice(index, 1);
}
});
showTable();
let handler = function(e){
e.target.removeEventListener("click", handler);
addTable(e, name, checkpoints);
};
event.target.addEventListener("click", handler);
}
function renderTable(){
if(table.length == 0){
let text = document.createElement("p");
text.innerHTML = "Sélectionner un courreur";
return text;
}
let elTable = document.createElement("table");
elTable.setAttribute("class", "table");
let head = document.createElement("thead");
let row = document.createElement("tr");
let name = document.createElement("th");
name.setAttribute("scope", "col");
name.innerHTML = "Balises";
row.appendChild(name);
head.appendChild(row);
let body = document.createElement("tbody");
let rows = [];
table[0][1].forEach(function(checkpoint, index){
let row = document.createElement("tr");
let name = document.createElement("th");
name.setAttribute("scope", "col");
if(index == 0){
name.innerHTML = "Départ";
}else if(index == table[0][1].length - 1){
name.innerHTML = "Arrivée";
}else{
name.innerHTML = index;
}
row.appendChild(name);
body.appendChild(row);
rows.push(row);
});
table.forEach(function(orienteer){
let name = document.createElement("th");
name.setAttribute("scope", "col");
name.innerHTML = orienteer[0];
row.appendChild(name);
orienteer[1].forEach(function(checkpoint, index){
let elCheckpoint = document.createElement("th");
elCheckpoint.setAttribute("scope", "col");
if(checkpoint.punchTime == 0){
elCheckpoint.innerHTML = "---";
}else{
let lastTime = 0;
let lastIndex = index;
while(lastTime == 0 && lastIndex > 0){
lastIndex--;
lastTime = orienteer[1][lastIndex].punchTime;
}
let time = checkpoint.punchTime - lastTime;
let min = Math.floor(time / 1000 / 60);
let sec = Math.floor((time / 1000) % 60);
sec = sec.toString();
sec = (sec.length == 1 ? "0" + sec : sec);
elCheckpoint.innerHTML = min + (sec != "00" ? ":" + sec : "");
}
rows[index].appendChild(elCheckpoint);
});
});
elTable.appendChild(head);
elTable.appendChild(body);
return elTable;
}
\ No newline at end of file
This diff is collapsed.
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use App\Entity\Course;
use App\Entity\Track;
class CourseController extends AbstractController
{
/**
* @Route("/course", name="course")
*/
public function index()
{
$courses = $this->getDoctrine()->getRepository(Course::class)->findAll();
return $this->render('course/index.html.twig', [
'courses' => $courses,
]);
}
/**
* @Route("/course/{id}/track", name="show_track")
*/
public function track($id)
{
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
return $this->render('course/track.html.twig', [
'name' => $course->getName(),
'route_map' => $this->generateUrl('course_map', ['id' => $id]),
'route_track' => $this->generateUrl('course_track', ['id' => $id]),
]);
}
/**
* @Route("/course/{id}/graph", name="show_graph")
*/
public function finx($id)
{
$courses = $this->getDoctrine()->getRepository(Course::class)->findAll();
return $this->render('course/index.html.twig', [
'courses' => $courses,
]);
}
/**
* @Route("/course/course_info/{id}", name="course_map")
* json data are not well send with render method, have to use xhr to access this function
*/
function course_map($id){
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
return new JsonResponse(['kml' => $course->getKml(),
'image' => $course->getImage()]);
}
/**
* @Route("/course/checkpoint/{id}", name="checkpoint")
*/
function checkpoint($id){
$orienteer = $this->getDoctrine()->getRepository(Track::class)->find($id);
return new JsonResponse(['controlPoints' => $orienteer->getControlPoints()]);
}
/**
* @Route("/course/course_track/{id}", name="course_track")
* json data are not well send with render method, have to use xhr to access this function
*/
function course_track($id){
$orienteers = $this->getDoctrine()->getRepository(Track::class)->findByCourse($id);
$tracks = array();
foreach ($orienteers as $orienteer) {
array_push($tracks, [$orienteer->getName(), $orienteer->getTotalTime(),
$orienteer->getTrace(), $orienteer->getControlPoints()]);
}
return new JsonResponse(['tracks' => $tracks]);
}
}
......@@ -62,10 +62,45 @@ class PlannerController extends AbstractController
/**
* @Route("/planner/clear/{id}", name="clear_course")
* TODO when added track
*/
public function clear($id){
//TODO when track added
$user = $this->security->getUser();
$entityManager = $this->getDoctrine()->getManager();
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
if(\in_array($course, $user->getCourses()->toArray()) || \in_array('ROLE_ADMIN', $user->getRoles())){
$tracks = $course->getOrienteer()->toArray();
foreach ($tracks as $track) {
$entityManager->remove($track);
}
$entityManager->flush();
return $this->redirectToRoute('your_courses');
}else{
throw new AccessDeniedException();
}
}
/**
* @Route("/planner/missing_checkpoint/{id}", name="missing_checkpoint")
*/
public function missing_checkpoint($id){
$user = $this->security->getUser();
$entityManager = $this->getDoctrine()->getManager();
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
if(\in_array($course, $user->getCourses()->toArray()) || \in_array('ROLE_ADMIN', $user->getRoles())){
$checkpoints = $course->getMissingCheckpoints();
return $this->render('planner/missing_checkpoint.html.twig', [
'courses' => $checkpoints,
]);
}else{
throw new AccessDeniedException();
}
}
/**
......@@ -86,6 +121,28 @@ class PlannerController extends AbstractController
}
}
/**
* @Route("/planner/delete_checkpoint/{id}", name="delete_checkpoint")
*/
public function delete_checkpoint($id){
$user = $this->security->getUser();
$entityManager = $this->getDoctrine()->getManager();
$checkpoint = $this->getDoctrine()->getRepository(MissingCheckpoint::class)->find($id);
$course = $checkpoint->getCourse();
if(\in_array($course, $user->getCourses()->toArray()) || \in_array('ROLE_ADMIN', $user->getRoles())){
$course->remove($entityManager);
$entityManager->remove($checkpoint);
$entityManager->flush();
return $this->redirectToRoute('your_courses');
}else{
throw new AccessDeniedException();
}
}
/**
* @Route("/planner/preview/{id}", name="preview_course")
*/
......
......@@ -24,11 +24,15 @@ class ProfileController extends AbstractController
}
/**
* @Route("/profile", name="profile")
* @Route("/profile/{id}", name="profile", defaults={"id": -1}, requirements={"id"="\d+"})
*/
public function index()
public function index(int $id)
{
$user = $this->security->getUser();
if($id != -1 && \in_array('ROLE_ADMIN', $user->getRoles())){
$user = $this->getDoctrine()->getRepository(User::class)->find($id);
}
return $this->render('profile/index.html.twig', [
'user' => $user,
......@@ -43,6 +47,11 @@ class ProfileController extends AbstractController
$planner = $this->security->getUser();
$form = $this->createForm(PlannerType::class, $planner, ['password' => true]);
if($request->request->get('password') == ""){
$_POST['password'] = $planner->getPassword();
$request = new Request($_POST);//if user don't change password generate weird bug
}
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
......
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200514122810 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE track (id INT AUTO_INCREMENT NOT NULL, course_id INT NOT NULL, name VARCHAR(255) NOT NULL, total_time INT NOT NULL, control_points LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', trace LONGTEXT NOT NULL, INDEX IDX_D6E3F8A6591CC992 (course_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE track ADD CONSTRAINT FK_D6E3F8A6591CC992 FOREIGN KEY (course_id) REFERENCES course (id)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('DROP TABLE track');
}
}
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200515143120 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE missing_checkpoint (id INT AUTO_INCREMENT NOT NULL, course_id INT NOT NULL, control_point_id INT NOT NULL, INDEX IDX_D3F3931591CC992 (course_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE missing_checkpoint ADD CONSTRAINT FK_D3F3931591CC992 FOREIGN KEY (course_id) REFERENCES course (id)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('DROP TABLE missing_checkpoint');
}
}
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200520091021 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE course ADD CONSTRAINT FK_169E6FB961220EA6 FOREIGN KEY (creator_id) REFERENCES user (id)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE course DROP FOREIGN KEY FK_169E6FB961220EA6');
}
}
......@@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200418184354 extends AbstractMigration
final class Version20200522171530 extends AbstractMigration
{
public function getDescription() : string
{
......@@ -22,9 +22,13 @@ final class Version20200418184354 extends AbstractMigration
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE course (id INT AUTO_INCREMENT NOT NULL, creator_id INT NOT NULL, xml TEXT NOT NULL, image VARCHAR(255) NOT NULL, kml VARCHAR(2000) NOT NULL, update_at DATETIME NOT NULL, name VARCHAR(255) NOT NULL, INDEX IDX_169E6FB961220EA6 (creator_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE track (id INT AUTO_INCREMENT NOT NULL, course_id INT NOT NULL, name VARCHAR(255) NOT NULL, total_time INT NOT NULL, control_points LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', trace LONGTEXT NOT NULL, INDEX IDX_D6E3F8A6591CC992 (course_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE course (id INT AUTO_INCREMENT NOT NULL, creator_id INT NOT NULL, xml TEXT NOT NULL, image VARCHAR(255) NOT NULL, kml VARCHAR(2000) NOT NULL, update_at DATETIME NOT NULL, name VARCHAR(255) NOT NULL, latitude VARCHAR(255) NOT NULL, longitude VARCHAR(255) NOT NULL, length INT NOT NULL, INDEX IDX_169E6FB961220EA6 (creator_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE missing_checkpoint (id INT AUTO_INCREMENT NOT NULL, course_id INT NOT NULL, control_point_id INT NOT NULL, INDEX IDX_D3F3931591CC992 (course_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(100) NOT NULL, phone VARCHAR(15) DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D649F85E0677 (username), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE track ADD CONSTRAINT FK_D6E3F8A6591CC992 FOREIGN KEY (course_id) REFERENCES course (id)');
$this->addSql('ALTER TABLE course ADD CONSTRAINT FK_169E6FB961220EA6 FOREIGN KEY (creator_id) REFERENCES user (id)');
$this->addSql('ALTER TABLE missing_checkpoint ADD CONSTRAINT FK_D3F3931591CC992 FOREIGN KEY (course_id) REFERENCES course (id)');
}
public function down(Schema $schema) : void
......@@ -32,8 +36,12 @@ final class Version20200418184354 extends AbstractMigration
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');