A Better interface

This commit is contained in:
Evarin 2017-04-20 01:53:29 +02:00
parent a2109cbb9d
commit df038f0226
10 changed files with 349 additions and 267 deletions

View file

@ -9,7 +9,7 @@ from django.template.defaultfilters import slugify
from django.contrib.gis.db import models as geomodels from django.contrib.gis.db import models as geomodels
from django.forms.widgets import DateInput from django.forms.widgets import DateInput
from django.urls import reverse from django.urls import reverse
from django.utils import timezone
from taggit_autosuggest.managers import TaggableManager from taggit_autosuggest.managers import TaggableManager
from tinymce.models import HTMLField as RichTextField from tinymce.models import HTMLField as RichTextField
@ -130,6 +130,8 @@ class Stage(models.Model):
# Misc # Misc
auteur = models.ForeignKey(Normalien, related_name="stages") auteur = models.ForeignKey(Normalien, related_name="stages")
public = models.BooleanField(u"Visible publiquement", default=False) public = models.BooleanField(u"Visible publiquement", default=False)
date_creation = models.DateTimeField(u"Créé le", default=timezone.now)
date_maj = models.DateTimeField(u"Mis à jour le", default=timezone.now)
# Caractéristiques du stage # Caractéristiques du stage
sujet = models.CharField(u"Sujet", max_length=500) sujet = models.CharField(u"Sujet", max_length=500)

View file

@ -189,6 +189,12 @@ article.stage {
text-shadow: -3px 3px 0 rgba(#000, 0.1); text-shadow: -3px 3px 0 rgba(#000, 0.1);
//margin-right: 25px; //margin-right: 25px;
} }
#stage-map {
height: 300px;
width: 100%;
}
section { section {
background: #eee; background: #eee;
padding: 14px; padding: 14px;
@ -302,6 +308,24 @@ article.stage {
} }
} }
.edit-box {
background: #eee;
margin: 10px;
padding: 10px 20px;
text-align: center;
&.public {
background: lighten($vert, 40%);
border: 1px solid $vert * 0.7;
}
&.prive {
background: lighten($rouge, 40%);
border: 1px solid $rouge * 0.7;
}
}
.article-wrapper { .article-wrapper {
display: table; display: table;
.toc-wrapper, article { .toc-wrapper, article {
@ -355,6 +379,21 @@ input[type='text'], input[type='password'], textarea, select {
} }
} }
input[type="submit"] {
background-color: $fond;
color: #fff;
border: 1px solid $fond * 0.7;
border-radius: 5px;
padding: 8px 12px;
display: block;
margin-left: auto;
margin-right: 0;
}
p input[type="submit"] {
display:inline-block;
}
select { select {
-moz-appearance: none; -moz-appearance: none;
@ -522,6 +561,17 @@ div.as-results {
overflow: auto; overflow: auto;
} }
.window-closer {
position: absolute;
top: 0;
right: 0;
padding: 12px;
z-index: 3;
&:after {
content: "×";
}
}
} }
.lieu-ui { .lieu-ui {
@ -537,3 +587,21 @@ div.as-results {
#avis_lieu_vide { #avis_lieu_vide {
display:none; display:none;
} }
a.lieu-change {
color:#fff;
background: $compl;
overflow: hidden;
display: inline-block;
max-width: 250px;
text-overflow: ellipsis;
white-space: nowrap;
padding: 5px;
border-radius: 5px;
margin-right: 7px;
&.ajout:before {
content: "+";
margin-right: 5px;
}
}

View file

@ -247,30 +247,35 @@ article.stage h3 {
color: #000; color: #000;
text-shadow: -3px 3px 0 rgba(0, 0, 0, 0.1); text-shadow: -3px 3px 0 rgba(0, 0, 0, 0.1);
} }
/* line 192, ../../sass/screen.scss */ /* line 193, ../../sass/screen.scss */
article.stage #stage-map {
height: 300px;
width: 100%;
}
/* line 198, ../../sass/screen.scss */
article.stage section { article.stage section {
background: #eee; background: #eee;
padding: 14px; padding: 14px;
max-width: 600px; max-width: 600px;
margin: 30px auto; margin: 30px auto;
} }
/* line 198, ../../sass/screen.scss */ /* line 204, ../../sass/screen.scss */
article.stage section:first-child { article.stage section:first-child {
margin-top: 0; margin-top: 0;
} }
/* line 200, ../../sass/screen.scss */ /* line 206, ../../sass/screen.scss */
article.stage section:first-child h3 { article.stage section:first-child h3 {
margin-top: 0; margin-top: 0;
} }
/* line 205, ../../sass/screen.scss */ /* line 211, ../../sass/screen.scss */
article.stage section.misc { article.stage section.misc {
padding-top: 0; padding-top: 0;
} }
/* line 207, ../../sass/screen.scss */ /* line 213, ../../sass/screen.scss */
article.stage section.misc ul.infos { article.stage section.misc ul.infos {
margin: 0 -3px; margin: 0 -3px;
} }
/* line 210, ../../sass/screen.scss */ /* line 216, ../../sass/screen.scss */
article.stage section.misc ul.infos li { article.stage section.misc ul.infos li {
display: inline-block; display: inline-block;
padding: 5px; padding: 5px;
@ -280,42 +285,42 @@ article.stage section.misc ul.infos li {
font-size: 0.9em; font-size: 0.9em;
border-radius: 4px; border-radius: 4px;
} }
/* line 219, ../../sass/screen.scss */ /* line 225, ../../sass/screen.scss */
article.stage section.misc ul.infos li.thematique { article.stage section.misc ul.infos li.thematique {
background-color: #28BF8A; background-color: #28BF8A;
} }
/* line 222, ../../sass/screen.scss */ /* line 228, ../../sass/screen.scss */
article.stage section.misc ul.infos li.matiere { article.stage section.misc ul.infos li.matiere {
background-color: #E80051; background-color: #E80051;
} }
/* line 229, ../../sass/screen.scss */ /* line 235, ../../sass/screen.scss */
article.stage section .chapo, article.stage section .avis-texte { article.stage section .chapo, article.stage section .avis-texte {
margin-bottom: 15px; margin-bottom: 15px;
background: #fff; background: #fff;
padding: 20px; padding: 20px;
} }
/* line 234, ../../sass/screen.scss */ /* line 240, ../../sass/screen.scss */
article.stage section .chapo { article.stage section .chapo {
font-size: 1.1em; font-size: 1.1em;
font-weight: 500; font-weight: 500;
font-variant: small-caps; font-variant: small-caps;
} }
/* line 239, ../../sass/screen.scss */ /* line 245, ../../sass/screen.scss */
article.stage section .avis-texte { article.stage section .avis-texte {
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
padding-left: 15px; padding-left: 15px;
} }
/* line 244, ../../sass/screen.scss */ /* line 250, ../../sass/screen.scss */
article.stage section .plusmoins { article.stage section .plusmoins {
max-width: 600px; max-width: 600px;
margin: 15px auto; margin: 15px auto;
} }
/* line 248, ../../sass/screen.scss */ /* line 254, ../../sass/screen.scss */
article.stage section .plusmoins > div { article.stage section .plusmoins > div {
display: table; display: table;
width: 100%; width: 100%;
} }
/* line 252, ../../sass/screen.scss */ /* line 258, ../../sass/screen.scss */
article.stage section .plusmoins > div:before { article.stage section .plusmoins > div:before {
content: "&nbsp"; content: "&nbsp";
width: 100px; width: 100px;
@ -324,83 +329,101 @@ article.stage section .plusmoins > div:before {
text-align: right; text-align: right;
padding-right: 12px; padding-right: 12px;
} }
/* line 261, ../../sass/screen.scss */ /* line 267, ../../sass/screen.scss */
article.stage section .plusmoins > div > *, article.stage section .plusmoins > div:before { article.stage section .plusmoins > div > *, article.stage section .plusmoins > div:before {
display: table-cell; display: table-cell;
} }
/* line 265, ../../sass/screen.scss */ /* line 271, ../../sass/screen.scss */
article.stage section .plusmoins > div > div { article.stage section .plusmoins > div > div {
padding: 15px; padding: 15px;
color: #fff; color: #fff;
} }
/* line 268, ../../sass/screen.scss */ /* line 274, ../../sass/screen.scss */
article.stage section .plusmoins > div > div h4 { article.stage section .plusmoins > div > div h4 {
font-weight: normal; font-weight: normal;
margin-left: -5px; margin-left: -5px;
font-size: 0.9em; font-size: 0.9em;
opacity: 0.9; opacity: 0.9;
} }
/* line 274, ../../sass/screen.scss */ /* line 280, ../../sass/screen.scss */
article.stage section .plusmoins > div > div p { article.stage section .plusmoins > div > div p {
font-weight: bold; font-weight: bold;
margin: 2px; margin: 2px;
} }
/* line 282, ../../sass/screen.scss */ /* line 288, ../../sass/screen.scss */
article.stage section .plusmoins .plus > div { article.stage section .plusmoins .plus > div {
background: #23cc56; background: #23cc56;
} }
/* line 285, ../../sass/screen.scss */ /* line 291, ../../sass/screen.scss */
article.stage section .plusmoins .plus:before { article.stage section .plusmoins .plus:before {
content: "Les +"; content: "Les +";
vertical-align: bottom; vertical-align: bottom;
color: #1b9f43; color: #1b9f43;
} }
/* line 292, ../../sass/screen.scss */ /* line 298, ../../sass/screen.scss */
article.stage section .plusmoins .moins > div { article.stage section .plusmoins .moins > div {
background: #af1822; background: #af1822;
} }
/* line 295, ../../sass/screen.scss */ /* line 301, ../../sass/screen.scss */
article.stage section .plusmoins .moins:before { article.stage section .plusmoins .moins:before {
content: "Les -"; content: "Les -";
vertical-align: top; vertical-align: top;
color: #88131b; color: #88131b;
} }
/* line 305, ../../sass/screen.scss */ /* line 311, ../../sass/screen.scss */
.edit-box {
background: #eee;
margin: 10px;
padding: 10px 20px;
text-align: center;
}
/* line 317, ../../sass/screen.scss */
.edit-box.public {
background: #dcfae5;
border: 1px solid #1b9f43;
}
/* line 322, ../../sass/screen.scss */
.edit-box.prive {
background: #f5b4b9;
border: 1px solid #88131b;
}
/* line 329, ../../sass/screen.scss */
.article-wrapper { .article-wrapper {
display: table; display: table;
} }
/* line 307, ../../sass/screen.scss */ /* line 331, ../../sass/screen.scss */
.article-wrapper .toc-wrapper, .article-wrapper article { .article-wrapper .toc-wrapper, .article-wrapper article {
display: table-cell; display: table-cell;
vertical-align: top; vertical-align: top;
} }
/* line 311, ../../sass/screen.scss */ /* line 335, ../../sass/screen.scss */
.article-wrapper .toc-wrapper { .article-wrapper .toc-wrapper {
max-width: 250px; max-width: 250px;
width: 25%; width: 25%;
} }
/* line 315, ../../sass/screen.scss */ /* line 339, ../../sass/screen.scss */
.article-wrapper .toc { .article-wrapper .toc {
position: -webkit-sticky; position: -webkit-sticky;
position: sticky; position: sticky;
top: 0; top: 0;
} }
/* line 319, ../../sass/screen.scss */ /* line 343, ../../sass/screen.scss */
.article-wrapper .toc a { .article-wrapper .toc a {
color: inherit; color: inherit;
font-weight: normal; font-weight: normal;
} }
/* line 326, ../../sass/screen.scss */ /* line 350, ../../sass/screen.scss */
.article-wrapper .toc .toc-h3 a { .article-wrapper .toc .toc-h3 a {
font-weight: 300; font-weight: 300;
} }
/* line 329, ../../sass/screen.scss */ /* line 353, ../../sass/screen.scss */
.article-wrapper .toc .toc-active a { .article-wrapper .toc .toc-active a {
color: #E80051; color: #E80051;
} }
/* line 338, ../../sass/screen.scss */ /* line 362, ../../sass/screen.scss */
input, textarea, select, div.tinymce { input, textarea, select, div.tinymce {
background: #fff; background: #fff;
font-size: 1em; font-size: 1em;
@ -410,19 +433,36 @@ input, textarea, select, div.tinymce {
padding: 5px; padding: 5px;
} }
/* line 347, ../../sass/screen.scss */ /* line 371, ../../sass/screen.scss */
input[type='text'], input[type='password'], textarea, select { input[type='text'], input[type='password'], textarea, select {
border: none; border: none;
border-bottom: 1px solid #E80051; border-bottom: 1px solid #E80051;
width: 100%; width: 100%;
transition: border 1s ease-out, background 1s ease-out; transition: border 1s ease-out, background 1s ease-out;
} }
/* line 353, ../../sass/screen.scss */ /* line 377, ../../sass/screen.scss */
input[type='text']:focus, input[type='password']:focus, textarea:focus, select:focus { input[type='text']:focus, input[type='password']:focus, textarea:focus, select:focus {
background-color: #ffe8f0; background-color: #ffe8f0;
} }
/* line 359, ../../sass/screen.scss */ /* line 382, ../../sass/screen.scss */
input[type="submit"] {
background-color: #E80051;
color: #fff;
border: 1px solid #a20039;
border-radius: 5px;
padding: 8px 12px;
display: block;
margin-left: auto;
margin-right: 0;
}
/* line 393, ../../sass/screen.scss */
p input[type="submit"] {
display: inline-block;
}
/* line 398, ../../sass/screen.scss */
select { select {
-moz-appearance: none; -moz-appearance: none;
appearance: none; appearance: none;
@ -431,7 +471,7 @@ select {
cursor: pointer; cursor: pointer;
} }
/* line 367, ../../sass/screen.scss */ /* line 406, ../../sass/screen.scss */
textarea, div.tinymce { textarea, div.tinymce {
border: none; border: none;
border-left: 1px solid #E80051; border-left: 1px solid #E80051;
@ -440,26 +480,26 @@ textarea, div.tinymce {
transition: border 1s ease-out, background 1s ease-out; transition: border 1s ease-out, background 1s ease-out;
} }
/* line 375, ../../sass/screen.scss */ /* line 414, ../../sass/screen.scss */
div.tinymce.mce-edit-focus { div.tinymce.mce-edit-focus {
background-color: #ffe8f0; background-color: #ffe8f0;
outline: none; outline: none;
} }
/* line 380, ../../sass/screen.scss */ /* line 419, ../../sass/screen.scss */
textarea { textarea {
height: 200px; height: 200px;
resize: vertical; resize: vertical;
} }
/* line 386, ../../sass/screen.scss */ /* line 425, ../../sass/screen.scss */
form .field { form .field {
margin: 5px 0; margin: 5px 0;
display: flex; display: flex;
background: #fff; background: #fff;
padding: 10px; padding: 10px;
} }
/* line 392, ../../sass/screen.scss */ /* line 431, ../../sass/screen.scss */
form .field label, form .field .label { form .field label, form .field .label {
display: inline-block; display: inline-block;
width: 250px; width: 250px;
@ -468,33 +508,33 @@ form .field label, form .field .label {
padding-top: 5px; padding-top: 5px;
flex-shrink: 0; flex-shrink: 0;
} }
/* line 400, ../../sass/screen.scss */ /* line 439, ../../sass/screen.scss */
form .field label { form .field label {
font-family: Podkova, serif; font-family: Podkova, serif;
font-weight: bold; font-weight: bold;
} }
/* line 404, ../../sass/screen.scss */ /* line 443, ../../sass/screen.scss */
form .field .help_text { form .field .help_text {
font-style: italic; font-style: italic;
font-size: 0.9em; font-size: 0.9em;
} }
/* line 408, ../../sass/screen.scss */ /* line 447, ../../sass/screen.scss */
form .field .input { form .field .input {
display: inline-block; display: inline-block;
flex-grow: 1; flex-grow: 1;
margin-right: 10px; margin-right: 10px;
} }
/* line 417, ../../sass/screen.scss */ /* line 456, ../../sass/screen.scss */
ul.as-selections { ul.as-selections {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
} }
/* line 421, ../../sass/screen.scss */ /* line 460, ../../sass/screen.scss */
ul.as-selections li { ul.as-selections li {
display: inline-block; display: inline-block;
} }
/* line 425, ../../sass/screen.scss */ /* line 464, ../../sass/screen.scss */
ul.as-selections .as-selection-item { ul.as-selections .as-selection-item {
padding: 0 5px; padding: 0 5px;
background: #28BF8A; background: #28BF8A;
@ -503,57 +543,57 @@ ul.as-selections .as-selection-item {
border-radius: 2px; border-radius: 2px;
font-weight: 500; font-weight: 500;
} }
/* line 433, ../../sass/screen.scss */ /* line 472, ../../sass/screen.scss */
ul.as-selections .as-selection-item a.as-close { ul.as-selections .as-selection-item a.as-close {
color: #fff; color: #fff;
-webkit-cursor: pointer; -webkit-cursor: pointer;
cursor: pointer; cursor: pointer;
margin-right: 5px; margin-right: 5px;
} }
/* line 440, ../../sass/screen.scss */ /* line 479, ../../sass/screen.scss */
ul.as-selections .as-selection-item.selected { ul.as-selections .as-selection-item.selected {
background: #E80051; background: #E80051;
} }
/* line 445, ../../sass/screen.scss */ /* line 484, ../../sass/screen.scss */
ul.as-selections .as-original { ul.as-selections .as-original {
flex-grow: 1; flex-grow: 1;
min-width: 200px; min-width: 200px;
} }
/* line 449, ../../sass/screen.scss */ /* line 488, ../../sass/screen.scss */
ul.as-selections .as-original input { ul.as-selections .as-original input {
width: 100%; width: 100%;
} }
/* line 455, ../../sass/screen.scss */ /* line 494, ../../sass/screen.scss */
div.as-results { div.as-results {
position: relative; position: relative;
} }
/* line 457, ../../sass/screen.scss */ /* line 496, ../../sass/screen.scss */
div.as-results ul { div.as-results ul {
position: absolute; position: absolute;
width: 100%; width: 100%;
background: #fff; background: #fff;
border: 1px solid #ff82ae; border: 1px solid #ff82ae;
} }
/* line 464, ../../sass/screen.scss */ /* line 503, ../../sass/screen.scss */
div.as-results ul li { div.as-results ul li {
padding: 3px 5px; padding: 3px 5px;
} }
/* line 470, ../../sass/screen.scss */ /* line 509, ../../sass/screen.scss */
div.as-results ul li.as-result-item.active { div.as-results ul li.as-result-item.active {
background: #ebfbf5; background: #ebfbf5;
} }
/* line 475, ../../sass/screen.scss */ /* line 514, ../../sass/screen.scss */
div.as-results ul li.as-message { div.as-results ul li.as-message {
font-style: italic; font-style: italic;
} }
/* line 482, ../../sass/screen.scss */ /* line 521, ../../sass/screen.scss */
#map_addlieu { #map_addlieu {
height: 500px; height: 500px;
} }
/* line 486, ../../sass/screen.scss */ /* line 525, ../../sass/screen.scss */
.window { .window {
display: none; display: none;
position: fixed; position: fixed;
@ -564,11 +604,11 @@ div.as-results ul li.as-message {
left: 0; left: 0;
z-index: 10; z-index: 10;
} }
/* line 496, ../../sass/screen.scss */ /* line 535, ../../sass/screen.scss */
.window.visible { .window.visible {
display: block; display: block;
} }
/* line 500, ../../sass/screen.scss */ /* line 539, ../../sass/screen.scss */
.window .window-bg { .window .window-bg {
background: #000; background: #000;
opacity: 0.7; opacity: 0.7;
@ -579,7 +619,7 @@ div.as-results ul li.as-message {
top: 0; top: 0;
z-index: -1; z-index: -1;
} }
/* line 511, ../../sass/screen.scss */ /* line 550, ../../sass/screen.scss */
.window .window-content { .window .window-content {
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
@ -593,18 +633,49 @@ div.as-results ul li.as-message {
max-height: 100%; max-height: 100%;
overflow: auto; overflow: auto;
} }
/* line 565, ../../sass/screen.scss */
.window .window-closer {
position: absolute;
top: 0;
right: 0;
padding: 12px;
z-index: 3;
}
/* line 571, ../../sass/screen.scss */
.window .window-closer:after {
content: "×";
}
/* line 528, ../../sass/screen.scss */ /* line 578, ../../sass/screen.scss */
.lieu-ui .map { .lieu-ui .map {
height: 400px; height: 400px;
width: 100%; width: 100%;
} }
/* line 532, ../../sass/screen.scss */ /* line 582, ../../sass/screen.scss */
.lieu-ui .hidden { .lieu-ui .hidden {
display: none; display: none;
} }
/* line 537, ../../sass/screen.scss */ /* line 587, ../../sass/screen.scss */
#avis_lieu_vide { #avis_lieu_vide {
display: none; display: none;
} }
/* line 591, ../../sass/screen.scss */
a.lieu-change {
color: #fff;
background: #28BF8A;
overflow: hidden;
display: inline-block;
max-width: 250px;
text-overflow: ellipsis;
white-space: nowrap;
padding: 5px;
border-radius: 5px;
margin-right: 7px;
}
/* line 603, ../../sass/screen.scss */
a.lieu-change.ajout:before {
content: "+";
margin-right: 5px;
}

View file

@ -7,12 +7,16 @@ function SelectLieuWidget(STATIC_ROOT, API_LIEU, target, callback) {
var ui_ready = false; var ui_ready = false;
var lieux_db = {}; var lieux_db = {};
var message_el = $el.find(".lieu-message"); var message_el = $el.find(".lieu-message");
var closer = $el.find(".window-closer");
form_el.detach(); form_el.detach();
form_el.on("submit", nouveauLieu); form_el.on("submit", nouveauLieu);
function initUI(){ function initUI(){
$.each(ui_el.children(), function(i, item){$(item).remove();}); $.each(ui_el.children(), function(i, item){$(item).remove();});
closer.on("click", closeWidget).attr("href", "javascript:void(0);");
$el.find(".window-bg").on("click", closeWidget);
var map_el = $("<div>", {class: "map"}); var map_el = $("<div>", {class: "map"});
input = $("<input>", input = $("<input>",
@ -37,6 +41,12 @@ function SelectLieuWidget(STATIC_ROOT, API_LIEU, target, callback) {
map.panTo(lieu.coord); map.panTo(lieu.coord);
lieuSurCarte(lieu, greenIcon); lieuSurCarte(lieu, greenIcon);
} }
function handleLieuOrigine(data) {
lieux_db[data.id] = data;
setLieuOrigine(data);
askForSuggestions(data.coord);
}
this.showWidget = function(lieu_id) { this.showWidget = function(lieu_id) {
$el.addClass("visible").removeClass("ajout"); $el.addClass("visible").removeClass("ajout");
@ -51,21 +61,20 @@ function SelectLieuWidget(STATIC_ROOT, API_LIEU, target, callback) {
$el.find("h3").text("Modifier le lieu"); $el.find("h3").text("Modifier le lieu");
if(lieux_db[lieu_id] === undefined) { if(lieux_db[lieu_id] === undefined) {
$.getJSON(API_LIEU + lieu_id + "/?format=json", $.getJSON(API_LIEU + lieu_id + "/?format=json",
function(data) { handleLieuOrigine);
lieux_db[data.id] = data;
setLieuOrigine(data);
askForSuggestions(data.coord);
});
ui_el.addClass("hidden"); ui_el.addClass("hidden");
} else { } else {
setLieuOrigine(lieux_db[lieu_id]); handleLieuOrigine(lieux_db[lieu_id]);
} }
} }
} }
this.closeWidget = function() { function closeWidget () {
$el.removeClass("visible"); $el.removeClass("visible");
} }
this.closeWidget = closeWidget;
// Icones // Icones
function makeIcon(couleur){ function makeIcon(couleur){

View file

@ -3,15 +3,53 @@
{% block extra_head %} {% block extra_head %}
<script src="{% static 'js/toc.min.js' %}" type="text/javascript"></script> <script src="{% static 'js/toc.min.js' %}" type="text/javascript"></script>
<script type="text/javascript" src="{% static "js/leaflet.js" %}"></script>
<link rel="stylesheet" type="text/css" href="{% static "css/leaflet.css" %}" />
<script type="text/javascript" src="//maps.stamen.com/js/tile.stamen.js?v1.3.0"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function(){$(".toc").toc({container:'.content'});}); $(function(){$(".toc").toc({container:'.content'});});
var STATIC_ROOT = "{{ STATIC_URL|escapejs }}";
function initStageMap(lieux) {
var map = L.map("stage-map");
var layer = new L.StamenTileLayer("terrain");
map.addLayer(layer);
function makeIcon(couleur){
return L.icon({
iconUrl: STATIC_ROOT + 'images/marker-'+couleur+'.png',
iconSize: [36, 46],
iconAnchor: [18, 45],
popupAnchor: [0, -48]
})
}
var greenIcon = makeIcon('red');
var bds = [];
$.each(lieux, function(i, item) {
bds.push(item.coord);
var marqueur = L.marker(item.coord, {icon: greenIcon});
marqueur.bindPopup(item.popup);
marqueur.addTo(map);
});
map.fitBounds(bds, {maxZoom: 13});
}
</script> </script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h1>{{ object.sujet }}</h1> <h1>{{ object.sujet }}</h1>
{% if object.auteur == user.profil %} {% if object.auteur == user.profil %}
<p><a href="{% url "avisstage:stage_edit" object.id %}">Modifier ce stage</a></p> <div class="edit-box {{ object.public|yesno:"public,prive" }}">
<p><a href="{% url "avisstage:stage_edit" object.id %}" class="edit-stage">Modifier ce stage</a></p>
<form action="{% url "avisstage:stage_publication" object.id %}" method="POST">
{% csrf_token %}
{% if object.public %}
<p>Ce stage est visible publiquement. <input type="submit" value="Masquer ce stage" name="depublier" /></p>
{% else %}
<p>Ce stage n'est qu'un brouillon, vous seul pouvez le voir. <input type="submit" value="Publier ce stage" name="publier" /></p>
{% endif %}
</form>
</div>
{% endif %} {% endif %}
<div class="article-wrapper"> <div class="article-wrapper">
<div class="toc-wrapper"> <div class="toc-wrapper">
@ -21,7 +59,25 @@
<article class="stage"> <article class="stage">
<section class="misc"> <section class="misc">
<h3>À propos du stage</h3> <h3>À propos du stage</h3>
<p>{{ object.auteur.nom }} a fait ce stage du {{ object.date_debut }} au {{ object.date_fin }}, supervisé par {{ object.encadrants }}</p> {% if object.lieux %}
<div id="stage-map"></div>
<script type="text/javascript">
var lieux = [
{% for lieu in object.lieux.all %}
{
coord: {lat: {{ lieu.coord.y|escapejs }}, lon: {{ lieu.coord.x|escapejs }} },
popup: "<h3>{{ lieu.nom|escapejs }}</h3>" +
"<p>{{ lieu.get_type_lieu_display|escapejs }}</p>" +
"<p>{{ lieu.ville|escapejs }}, {{ lieu.get_pays_display|escapejs }}</p>"
}{% if not forloop.last %},{% endif %}
{% endfor %}
];
$(function(){
initStageMap(lieux);
});
</script>
{% endif %}
<p><a href="{% url "avisstage:profil" object.auteur.user.username %}">{{ object.auteur.nom }}</a> a fait ce {{ object.get_type_stage_display|lower }} du {{ object.date_debut }} au {{ object.date_fin }}, supervisé par {{ object.encadrants }}</p>
<ul class="infos"> <ul class="infos">
{% for matiere in object.matieres.all %} {% for matiere in object.matieres.all %}
<li class="matiere">{{ matiere.nom }}</li> <li class="matiere">{{ matiere.nom }}</li>
@ -35,7 +91,7 @@
{% include "avisstage/detail/avis.html" with avis=object.avis_stage titre="Avis sur le stage" %} {% include "avisstage/detail/avis.html" with avis=object.avis_stage titre="Avis sur le stage" %}
{% for avis in object.avislieu_set.all %} {% for avis in object.avislieu_set.all %}
{% include "avisstage/detail/avis.html" with avis=avis titre="Avis sur le lieu" %} {% include "avisstage/detail/avis.html" with avis=avis titre=avis.lieu %}
{% endfor %} {% endfor %}
</article> </article>
</div> </div>

View file

@ -1,16 +1,7 @@
{% load staticfiles %} {% load staticfiles %}
<h1>Ajouter un lieu</h1> <form action="{% url 'avisstage:lieu_ajout' %}" method="post" id="lieu_ajout">
<form action="" method="post"> <h1>Ajouter un lieu</h1>
{% csrf_token %} {% csrf_token %}
{% block extra_head %}
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyDd4innPShfHcW8KDJB833vZHZSsqt-ACw"></script>
<script type="text/javascript" src="{% static "js/leaflet.js" %}"></script>
<script type="text/javascript" src="{% static "js/leaflet-gplaces-autocomplete.js" %}"></script>
<script type="text/javascript" src="http://maps.stamen.com/js/tile.stamen.js?v1.3.0"></script>
<link rel="stylesheet" type="text/css" href="{% static "css/leaflet.css" %}" />
{% endblock %}
<p><input id="addlieu" type="text" placeholder="Chercher un établissement" /></p> <p><input id="addlieu" type="text" placeholder="Chercher un établissement" /></p>
<div id="map_addlieu"></div> <div id="map_addlieu"></div>
<div id="candidats"></div> <div id="candidats"></div>
@ -28,140 +19,4 @@
</div> </div>
{% endfor %} {% endfor %}
<input type="submit" /> <input type="submit" />
<script type="text/javascript">
$(function(){
var STATIC_ROOT = "{{ STATIC_URL }}";
// Affiche la carte
var map = L.map('map_addlieu').setView([48.8422411,2.3430553], 13);
var layer = new L.StamenTileLayer("terrain");
map.addLayer(layer);
// Autocomplete
var input = document.getElementById('addlieu');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.setTypes(["geocode", "establishment"]);
autocomplete.addListener('place_changed', handlePlaceSearch);
// Préparation de la suite
var mainmarker;
var suggestion_actuelle;
var propositions_data = [];
var propositions_markers = [];
var choix_actuel;
// Icones
var iconProps = {
iconSize: [36, 46],
iconAnchor: [18, 45],
popupAnchor: [0, -48]
};
var greenIcon = L.icon($.extend({}, iconProps, {iconUrl: STATIC_ROOT + 'images/marker-green.png'}));
var redIcon = L.icon($.extend({}, iconProps, {iconUrl: STATIC_ROOT + 'images/marker-red.png'}));
var blueIcon = L.icon($.extend({}, iconProps, {iconUrl: STATIC_ROOT + 'images/marker-blue.png'}));
// Callback autocomplete
function handlePlaceSearch() {
var place = autocomplete.getPlace();
if (!place.geometry) {
window.alert("No details available for input: '" + place.name + "'");
return;
}
// Processing du lieu
var data = {};
$.each(place.address_components, function(i, obj) {
for (var j=0; j<obj.types.length; j++) {
switch(obj.types[j]) {
case "locality":
data.ville = obj.long_name;
break;
case "country":
data.pays = obj.short_name;
break;
}
}
});
data.nom = place.name;
data.coord = {lng: place.geometry.location.lng(),
lat: place.geometry.location.lat()};
data.orig_coord = data.coord;
suggestion_actuelle = data;
console.log(place);
var location = data.coord;
map.panTo(location);
if(mainmarker===undefined) {
mainmarker = L.marker(location,
{draggable: true,
icon: redIcon}).addTo(map);
mainmarker.on("dragend", refreshSuggestedPosition);
} else
mainmarker.setLatLng(location);
mainmarker.bindPopup(popupText(data, ""));
// Affichage des suggestions
$.getJSON("/api/v1/lieu/", {"format":"json",
"lat":location.lat,
"lng":location.lng}, showPropositions);
}
// Callback suggestions
function showPropositions(data) {
// TODO gérer les appels concurrents
$.each(propositions_markers, function(i, item) { item.remove(); });
propositions_markers = [];
propositions_data = data.objects;
$.each(data.objects, function(i, item) {
var mark = L.marker([item.coord.lat, item.coord.lng],
{icon: blueIcon});
mark.addTo(map).bindPopup(popupText(item, i));
propositions_markers.push(mark);
});
}
function popupText(data, ilieu) {
var desc = "<div><b>" + data.nom +"</b><br />"+data.ville+", "+data.pays+"<br />";
if(ilieu !== "") {
desc += "<a href=\"javascript:choixLieuStage("+ilieu+")\">Choisir ce lieu</a></div>"
} else {
desc += "<a href=\"javascript:restoreSuggestedPosition()\">Restaurer la position originale</a><br/>"
desc += "<a href=\"javascript:choixLieuStage()\">Créer un nouveau lieu</a></div>"
}
return desc;
}
function refreshSuggestedPosition() {
var coord = mainmarker.getLatLng();
suggestion_actuelle.coord = {lat:coord.lat, lng:coord.lng};
if (choix_actuel == suggestion_actuelle) {
$("#id_coord_0").val(choix_actuel.coord.lat);
$("#id_coord_1").val(choix_actuel.coord.lng);
}
}
window.restoreSuggestedPosition = function() {
mainmarker.setLatLng(suggestion_actuelle.orig_coord);
refreshSuggestedPosition();
}
window.choixLieuStage = function(ilieu) {
var choix;
if(ilieu === undefined)
choix = suggestion_actuelle;
else
choix = propositions_data[ilieu];
$("#id_nom").val(choix.nom);
$("#id_ville").val(choix.ville);
$("#id_pays").val(choix.pays);
$("#id_coord_0").val(choix.coord.lat);
$("#id_coord_1").val(choix.coord.lng);
choix_actuel = choix;
}
});
</script>
</form> </form>

View file

@ -122,6 +122,7 @@
lieu_select.closeWidget(); lieu_select.closeWidget();
} }
// À l'envoi du formulaire // À l'envoi du formulaire
$("#stageform").submit(function() { $("#stageform").submit(function() {
$.each(txtr, function(i, item) { $.each(txtr, function(i, item) {
@ -144,50 +145,55 @@
<form action="" method="post" id="stageform"> <form action="" method="post" id="stageform">
{% csrf_token %} {% csrf_token %}
{# Général #} {# Général #}
<h2>Informations générales</h2> <div class="general">
{{ form.non_field_errors }} <h2>Informations générales</h2>
{% for field in form %} {{ form.non_field_errors }}
{{ field.errors }} {% for field in form %}
<div class="field"> {{ field.errors }}
<label for="{{ field.id_for_label }}">{{ field.label }}</label> <div class="field">
<div class="input">
{{ field }}
{% if field.help_text %}
<p class="help_text">{{ field.help_text }}</p>
{% endif %}
</div>
</div>
{% endfor %}
{# Lieux #}
<div class="field">
<label>Lieu(x) du stage</label>
<div class="input">
<div id="lieux-selector">
{% for fform in avis_lieu_formset %}
<a id="change-{{ fform.prefix }}" class="lieu-change" href="javascript:void(0)">{{ fform.instance.lieu }}</a>
{% endfor %}
<a id="lieu-ajout" class="lieu-change ajout" href="javascript:void(0)">Ajouter un lieu</a>
</div>
</div>
</div>
{# Avis - général #}
<h2>Commentaires sur le stage</h2>
{{ avis_stage_form.non_field_errors }}
{% for field in avis_stage_form %}
{{ field.errors }}
<div class="field">
<div class="label">
<label for="{{ field.id_for_label }}">{{ field.label }}</label> <label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% if field.help_text %} <div class="input">
<p class="help_text">{{ field.help_text }}</p> {{ field }}
{% endif %} {% if field.help_text %}
<p class="help_text">{{ field.help_text }}</p>
{% endif %}
</div>
</div> </div>
{% endfor %}
{# Lieux #}
<div class="field">
<label>Lieu(x) du stage</label>
<div class="input"> <div class="input">
{{ field }} <div id="lieux-selector">
{% for fform in avis_lieu_formset %}
<a id="change-{{ fform.prefix }}" class="lieu-change" href="javascript:void(0)">{{ fform.instance.lieu }}</a>
{% endfor %}
<a id="lieu-ajout" class="lieu-change ajout" href="javascript:void(0)">Ajouter un lieu</a>
</div>
</div> </div>
</div> </div>
{% endfor %} <input type="submit" value="Enregistrer" />
</div>
<div id="avis-general">
{# Avis - général #}
<h2>Commentaires sur le stage</h2>
{{ avis_stage_form.non_field_errors }}
{% for field in avis_stage_form %}
{{ field.errors }}
<div class="field">
<div class="label">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% if field.help_text %}
<p class="help_text">{{ field.help_text }}</p>
{% endif %}
</div>
<div class="input">
{{ field }}
</div>
</div>
{% endfor %}
<input type="submit" value="Enregistrer" />
</div>
{{ avis_lieu_formset.management_form }} {{ avis_lieu_formset.management_form }}
<div id="avis_lieu_container"> <div id="avis_lieu_container">
{% for fform in avis_lieu_formset %} {% for fform in avis_lieu_formset %}
@ -195,6 +201,7 @@
<h2>Commentaire sur le lieu "<span class="lieu-nom">{{ fform.instance.lieu }}</span>"</h2> <h2>Commentaire sur le lieu "<span class="lieu-nom">{{ fform.instance.lieu }}</span>"</h2>
{{ fform.non_field_errors }} {{ fform.non_field_errors }}
{% for field in fform.hidden_fields %} {% for field in fform.hidden_fields %}
{{ field.errors }}
{{ field }} {{ field }}
{% endfor %} {% endfor %}
{% for field in fform.visible_fields %} {% for field in fform.visible_fields %}

View file

@ -9,7 +9,7 @@
<h2>Mes stages</h2> <h2>Mes stages</h2>
<ul class="stagelist"> <ul class="stagelist">
{% for stage in user.profil.stages.all %} {% for stage in user.profil.stages.all %}
<li class="stage-{{ stage.published|yesno:"publie,brouillon" }}"> <li class="stage-{{ stage.public|yesno:"publie,brouillon" }}">
<a href="{% url "avisstage:stage" stage.id %}"> <a href="{% url "avisstage:stage" stage.id %}">
{{ stage.sujet }} {{ stage.sujet }}
</a> </a>

View file

@ -10,7 +10,8 @@ urlpatterns = [
url(r'^perso/$', views.perso, name='perso'), url(r'^perso/$', views.perso, name='perso'),
url(r'^stage/nouveau/$', views.manage_stage, name='stage_ajout'), url(r'^stage/nouveau/$', views.manage_stage, name='stage_ajout'),
url(r'^stage/(?P<pk>\w+)/$', views.StageView.as_view(), name='stage'), url(r'^stage/(?P<pk>\w+)/$', views.StageView.as_view(), name='stage'),
url(r'^stage/(?P<id_stage>\w+)/edit/$', views.manage_stage, name='stage_edit'), url(r'^stage/(?P<pk>\w+)/edit/$', views.manage_stage, name='stage_edit'),
url(r'^stage/(?P<pk>\w+)/publication/$', views.publier_stage, name='stage_publication'),
url(r'^lieu/ajout/$', views.LieuAjout.as_view(), name='lieu_ajout'), url(r'^lieu/ajout/$', views.LieuAjout.as_view(), name='lieu_ajout'),
url(r'^profil/show/(?P<username>\w+)/$', views.ProfilView.as_view(), url(r'^profil/show/(?P<username>\w+)/$', views.ProfilView.as_view(),

View file

@ -1,6 +1,6 @@
# coding: utf-8 # coding: utf-8
from django.shortcuts import render, redirect from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import DetailView from django.views.generic import DetailView
from django.views.generic.edit import UpdateView, CreateView from django.views.generic.edit import UpdateView, CreateView
@ -8,7 +8,7 @@ from django import forms
from django.urls import reverse from django.urls import reverse
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from braces.views import LoginRequiredMixin from braces.views import LoginRequiredMixin
from django.http import JsonResponse from django.http import JsonResponse, HttpResponseForbidden
from avisstage.models import Normalien, Stage, Lieu, AvisLieu, AvisStage from avisstage.models import Normalien, Stage, Lieu, AvisLieu, AvisStage
from avisstage.forms import StageForm, LieuForm, AvisStageForm, AvisLieuForm from avisstage.forms import StageForm, LieuForm, AvisStageForm, AvisLieuForm
@ -47,13 +47,13 @@ class ProfilView(DetailView, LoginRequiredMixin):
# Stages # Stages
@login_required @login_required
def manage_stage(request, id_stage=None): def manage_stage(request, pk=None):
if id_stage is None: if pk is None:
stage = Stage(auteur=request.user.profil) stage = Stage(auteur=request.user.profil)
avis_stage = AvisStage(stage=stage) avis_stage = AvisStage(stage=stage)
c_del = False c_del = False
else: else:
stage = Stage.objects.filter(auteur=request.user.profil).get(pk=id_stage) stage = Stage.objects.filter(auteur=request.user.profil).get(pk=pk)
avis_stage, _ = AvisStage.objects.get_or_create(stage=stage) avis_stage, _ = AvisStage.objects.get_or_create(stage=stage)
c_del = True c_del = True
@ -82,7 +82,7 @@ def manage_stage(request, id_stage=None):
return render(request, "avisstage/formulaires/stage.html", return render(request, "avisstage/formulaires/stage.html",
{'form': form, 'avis_stage_form': avis_stage_form, {'form': form, 'avis_stage_form': avis_stage_form,
'avis_lieu_formset': avis_lieu_formset, 'avis_lieu_formset': avis_lieu_formset,
'creation': id_stage is None}) 'creation': pk is None})
class StageView(DetailView, LoginRequiredMixin): class StageView(DetailView, LoginRequiredMixin):
model = Stage model = Stage
@ -109,7 +109,20 @@ class LieuAjout(CreateView, LoginRequiredMixin):
"errors": form.errors}) "errors": form.errors})
else: else:
super(LieuAjout, self).form_valid(form) super(LieuAjout, self).form_valid(form)
@login_required
def publier_stage(request, pk):
if request.method != "POST":
return HttpResponseForbidden()
stage = get_object_or_404(Stage, pk=pk)
if stage.auteur != request.user.profil:
return HttpResponseForbidden()
if "publier" in request.POST:
stage.public = True
else:
stage.public = False
stage.save()
return redirect(reverse("avisstage:stage", kwargs={"pk": pk}))
def recherche(request): def recherche(request):
return render(request, 'avisstage/recherche.html') return render(request, 'avisstage/recherche.html')