Ajout du champ préstage, améliorations UX
This commit is contained in:
parent
7f69e44094
commit
0c70d1b76b
11 changed files with 110 additions and 116 deletions
|
@ -56,6 +56,8 @@ class StageForm(forms.ModelForm):
|
|||
|
||||
# Date de modification
|
||||
self.instance.date_maj = timezone.now()
|
||||
|
||||
self.instance.update_stats(False)
|
||||
|
||||
stage = super(StageForm, self).save(commit=commit)
|
||||
return stage
|
||||
|
@ -64,12 +66,13 @@ class StageForm(forms.ModelForm):
|
|||
class AvisStageForm(HTMLTrimmerForm):
|
||||
class Meta:
|
||||
model = AvisStage
|
||||
fields = ['chapo', 'avis_sujet', 'avis_ambiance', 'avis_admin', 'les_plus', 'les_moins']
|
||||
fields = ['chapo', 'avis_sujet', 'avis_ambiance', 'avis_admin', 'avis_prestage', 'les_plus', 'les_moins']
|
||||
help_texts = {
|
||||
"chapo": u"\"Trop long, pas lu\" : une accroche résumant ce que vous avez pensé de ce séjour",
|
||||
"avis_ambiance": u"Avez-vous passé un bon moment à ce travail ? Étiez-vous assez guidé⋅e ? Aviez-vous un bon contact avec vos encadrant⋅e⋅s ? Y avait-il une bonne ambiance dans l'équipe ?",
|
||||
"avis_sujet": u"Quelle était votre mission ? Qu'en avez-vous retiré ? Le travail correspondait-il à vos attentes ? Était-ce à votre niveau, trop dur, trop facile ?",
|
||||
"avis_admin": u"Avez-vous commencé votre travail à la date prévue ? Était-ce compliqué d'obtenir les documents nécessaires (visa, contrats, etc) ? L'administration de l'établissement vous a-t-elle aidé⋅e ? Étiez-vous rémunéré⋅e ?",
|
||||
"avis_prestage": u"Comment avez-vous trouvé où aller pour cette expérience ? À quel moment avez-vous commencé à chercher ? Avez-vous eu des entretiens pour obtenir votre place ? Avez-vous eu d'autres pistes, pourquoi avez-vous choisi cette option ?",
|
||||
"les_plus": u"Les principaux points positifs de cette expérience",
|
||||
"les_moins": u"Ce qui aurait pu être mieux",
|
||||
}
|
||||
|
|
31
avisstage/migrations/0002_auto_20171002_2243.py
Normal file
31
avisstage/migrations/0002_auto_20171002_2243.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.2 on 2017-10-02 20:43
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import tinymce.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('avisstage', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='avisstage',
|
||||
name='avis_prestage',
|
||||
field=tinymce.models.HTMLField(blank=True, default='', verbose_name='Avant le stage'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='stage',
|
||||
name='len_avis_lieux',
|
||||
field=models.IntegerField(default=0, verbose_name='Longueur des avis de lieu'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='stage',
|
||||
name='len_avis_stage',
|
||||
field=models.IntegerField(default=0, verbose_name='Longueur des avis de stage'),
|
||||
),
|
||||
]
|
|
@ -10,6 +10,7 @@ from django.template.defaultfilters import slugify
|
|||
from django.forms.widgets import DateInput
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.html import strip_tags
|
||||
|
||||
from taggit_autosuggest.managers import TaggableManager
|
||||
from tinymce.models import HTMLField as RichTextField
|
||||
|
@ -162,6 +163,8 @@ class Stage(models.Model):
|
|||
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)
|
||||
len_avis_stage = models.IntegerField(u"Longueur des avis de stage", default=0)
|
||||
len_avis_lieux = models.IntegerField(u"Longueur des avis de lieu", default=0)
|
||||
|
||||
# Caractéristiques du stage
|
||||
sujet = models.CharField(u"Sujet", max_length=500)
|
||||
|
@ -221,6 +224,26 @@ class Stage(models.Model):
|
|||
def __unicode__(self):
|
||||
return u"%s (par %s)" % (self.sujet, self.auteur.user.username)
|
||||
|
||||
def update_stats(self, save=True):
|
||||
def get_len(obj):
|
||||
length = 0
|
||||
avis = obj.avis_all
|
||||
for k, av in avis:
|
||||
length += len(av.split())
|
||||
length += len(obj.chapo.split())
|
||||
length += len(obj.les_plus.split())
|
||||
length += len(obj.les_moins.split())
|
||||
return length
|
||||
|
||||
if self.avis_stage:
|
||||
self.len_avis_stage = get_len(self.avis_stage)
|
||||
self.len_avis_lieux = 0
|
||||
for avis in self.avislieu_set.all():
|
||||
self.len_avis_lieux += get_len(avis)
|
||||
|
||||
if save:
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Stage"
|
||||
|
||||
|
@ -235,6 +258,7 @@ class AvisStage(models.Model):
|
|||
avis_ambiance = RichTextField(u"L'ambiance de travail", blank=True)
|
||||
avis_sujet = RichTextField(u"La mission", blank=True)
|
||||
avis_admin = RichTextField(u"Formalités et administration", blank=True)
|
||||
avis_prestage = RichTextField(u"Avant le stage", blank=True, default="")
|
||||
|
||||
les_plus = models.TextField(u"Les plus de cette expérience", blank=True)
|
||||
les_moins = models.TextField(u"Les moins de cette expérience", blank=True)
|
||||
|
@ -245,7 +269,7 @@ class AvisStage(models.Model):
|
|||
# Liste des champs d'avis, couplés à leur nom (pour l'affichage)
|
||||
@property
|
||||
def avis_all(self):
|
||||
fields = ['avis_sujet', 'avis_ambiance', 'avis_admin']
|
||||
fields = ['avis_sujet', 'avis_ambiance', 'avis_admin', 'avis_prestage']
|
||||
return [(AvisStage._meta.get_field(field).verbose_name,
|
||||
getattr(self, field, '')) for field in fields]
|
||||
|
||||
|
|
|
@ -158,6 +158,11 @@ article.stage {
|
|||
}
|
||||
}
|
||||
}
|
||||
.avis-vides {
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Sommaire sur le côté
|
||||
|
|
|
@ -542,25 +542,31 @@ article.stage section .plusmoins .moins:before {
|
|||
vertical-align: top;
|
||||
color: #c70660;
|
||||
}
|
||||
/* line 165, ../../sass/_stage_detail.scss */
|
||||
/* line 161, ../../sass/_stage_detail.scss */
|
||||
article.stage section .avis-vides {
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
text-align: center;
|
||||
}
|
||||
/* line 170, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper {
|
||||
display: table;
|
||||
margin-left: -15px;
|
||||
width: 100%;
|
||||
}
|
||||
/* line 170, ../../sass/_stage_detail.scss */
|
||||
/* line 175, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc-wrapper, article.stage .section-wrapper > section {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
}
|
||||
/* line 174, ../../sass/_stage_detail.scss */
|
||||
/* line 179, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc-wrapper {
|
||||
max-width: 230px;
|
||||
width: 25%;
|
||||
padding: 5px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
/* line 180, ../../sass/_stage_detail.scss */
|
||||
/* line 185, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc {
|
||||
font-family: "Dosis", sans-serif;
|
||||
position: -webkit-sticky;
|
||||
|
@ -571,12 +577,12 @@ article.stage .section-wrapper .toc {
|
|||
padding: 5px;
|
||||
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
/* line 190, ../../sass/_stage_detail.scss */
|
||||
/* line 195, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
/* line 195, ../../sass/_stage_detail.scss */
|
||||
/* line 200, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc a {
|
||||
display: block;
|
||||
color: inherit;
|
||||
|
@ -585,45 +591,45 @@ article.stage .section-wrapper .toc a {
|
|||
padding: 5px;
|
||||
line-height: 1;
|
||||
}
|
||||
/* line 203, ../../sass/_stage_detail.scss */
|
||||
/* line 208, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc a:hover {
|
||||
color: #8fcc33;
|
||||
}
|
||||
/* line 207, ../../sass/_stage_detail.scss */
|
||||
/* line 212, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc .toc-h1 a {
|
||||
font-weight: 900;
|
||||
}
|
||||
/* line 210, ../../sass/_stage_detail.scss */
|
||||
/* line 215, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc .toc-h2 {
|
||||
margin-top: 10px;
|
||||
font-weight: 400;
|
||||
}
|
||||
/* line 214, ../../sass/_stage_detail.scss */
|
||||
/* line 219, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc .toc-h3 a {
|
||||
font-weight: 300;
|
||||
}
|
||||
/* line 217, ../../sass/_stage_detail.scss */
|
||||
/* line 222, ../../sass/_stage_detail.scss */
|
||||
article.stage .section-wrapper .toc .toc-active a {
|
||||
color: #0f4c82;
|
||||
}
|
||||
|
||||
/* line 224, ../../sass/_stage_detail.scss */
|
||||
/* line 229, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr {
|
||||
display: table;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
/* line 229, ../../sass/_stage_detail.scss */
|
||||
/* line 234, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr > * {
|
||||
display: table-cell;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
/* line 234, ../../sass/_stage_detail.scss */
|
||||
/* line 239, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr h1, .misc-hdr h3 {
|
||||
width: 100%;
|
||||
padding-right: 5px;
|
||||
}
|
||||
/* line 238, ../../sass/_stage_detail.scss */
|
||||
/* line 243, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr .dates {
|
||||
width: 50px;
|
||||
background-color: #950548;
|
||||
|
@ -634,28 +640,28 @@ article.stage .section-wrapper .toc .toc-active a {
|
|||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
}
|
||||
/* line 248, ../../sass/_stage_detail.scss */
|
||||
/* line 253, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr .dates span {
|
||||
display: block;
|
||||
}
|
||||
/* line 251, ../../sass/_stage_detail.scss */
|
||||
/* line 256, ../../sass/_stage_detail.scss */
|
||||
.misc-hdr .dates .year {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
/* line 259, ../../sass/_stage_detail.scss */
|
||||
/* line 264, ../../sass/_stage_detail.scss */
|
||||
.edit-box {
|
||||
background: #eee;
|
||||
margin: 10px;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
/* line 265, ../../sass/_stage_detail.scss */
|
||||
/* line 270, ../../sass/_stage_detail.scss */
|
||||
.edit-box.public {
|
||||
background: #cae3f9;
|
||||
border: 1px solid #125b9b;
|
||||
}
|
||||
/* line 270, ../../sass/_stage_detail.scss */
|
||||
/* line 275, ../../sass/_stage_detail.scss */
|
||||
.edit-box.prive {
|
||||
background: #fdcfe4;
|
||||
border: 1px solid #ad0654;
|
||||
|
|
|
@ -34,4 +34,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if longueur < 15 %}
|
||||
<p class="avis-vides">Pas grand-chose par ici. Peut-être aurez-vous plus d'informations en <a href="{% url "avisstage:profil" auteur %}">contactant directement l'auteur⋅e</a> ?</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
|
|
@ -109,10 +109,10 @@
|
|||
</div>
|
||||
|
||||
<section class="avis">
|
||||
{% include "avisstage/detail/avis.html" with avis=object.avis_stage titre="Avis sur le travail" %}
|
||||
{% include "avisstage/detail/avis.html" with avis=object.avis_stage titre="Avis sur le travail" auteur=object.auteur.user.username longueur=object.len_avis_stage %}
|
||||
|
||||
{% for avis in object.avislieu_set.all %}
|
||||
{% include "avisstage/detail/avis.html" with avis=avis titre=avis.lieu %}
|
||||
{% include "avisstage/detail/avis.html" with avis=avis titre=avis.lieu auteur=object.auteur.user.username longueur=object.len_avis_lieux %}
|
||||
{% endfor %}
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Chercher un stage - ExperiENS{% endblock %}
|
||||
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript" src="{% static "js/leaflet.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "js/leaflet.markercluster.js" %}"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/leaflet.css" %}" />
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/MarkerCluster.css" %}" />
|
||||
<link rel="stylesheet" type="text/css" href="{% static "css/MarkerCluster.Default.css" %}" />
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var STATIC_ROOT = "{{ STATIC_URL|escapejs }}";
|
||||
var API_LIEU = "{% url 'avisstage:api_dispatch_list' resource_name="lieu" api_name="v1" %}";
|
||||
var map = L.map("stages-map").panTo([30, 15]).setZoom(2);
|
||||
var layer = new L.TileLayer("https://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", {attribution: 'Map tiles by <a href="http://korona.geog.uni-heidelberg.de/">GIScience Heidelberg</a>'});
|
||||
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');
|
||||
|
||||
$.getJSON(API_LIEU + "?format=json&has_stage&limit=10000", onLoadLieux);
|
||||
|
||||
var marqueurs = L.markerClusterGroup();
|
||||
var marqueurs_db = {};
|
||||
|
||||
function onLoadLieux(data){
|
||||
console.log(data);
|
||||
var lieux = data.objects;
|
||||
$.each(lieux, function(i, item) {
|
||||
var marqueur = L.marker(item.coord, {icon: greenIcon});
|
||||
var txt = item.num_stages > 1 ? item.num_stages+" stages ici": "1 stage ici";
|
||||
txt = "<h3>"+item.nom+"</h3>"+
|
||||
"<p>"+txt+"</p>";
|
||||
marqueur.bindPopup(txt + "<p>Chargement...</p>");
|
||||
marqueurs.addLayer(marqueur);
|
||||
marqueur.on("popupopen", loadDetailLieu);
|
||||
marqueur._lieu_data = item;
|
||||
marqueur._popup_header = txt;
|
||||
marqueur._lieu_data_loading = false;
|
||||
marqueurs_db[item.id] = marqueur;
|
||||
});
|
||||
map.addLayer(marqueurs);
|
||||
}
|
||||
|
||||
function loadDetailLieu(){
|
||||
if(this._lieu_data_loading) return;
|
||||
var id = this._lieu_data.id;
|
||||
$.getJSON(API_LIEU + id + "/?format=json", detailLieu);
|
||||
}
|
||||
|
||||
function detailLieu(data){
|
||||
var marqueur = marqueurs_db[data.id];
|
||||
marqueur._lieu_data = data;
|
||||
var html = $("<div>").html(marqueur._popup_header);
|
||||
var stageliste = $("<ul>");
|
||||
$.each(data.stages, function(i, item) {
|
||||
var stage = $("<li>")
|
||||
.append($("<a>", {href: item.url}).text(item.sujet))
|
||||
.append($("<span>").text(" par "+item.auteur));
|
||||
stageliste.append(stage);
|
||||
});
|
||||
html.append(stageliste);
|
||||
marqueur.setPopupContent(html[0]);
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<h1>Recherche</h1>
|
||||
<div class="entrer">Ici, bientôt, un vrai formulaire de recherche</div>
|
||||
<p><a href="{% url "avisstage:stage_majs" %}">Dernières mises à jour</a></p>
|
||||
<article>
|
||||
<h2>Carte des expériences</h2>
|
||||
<div id="stages-map"></div>
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -9,6 +9,6 @@
|
|||
<h1>Chercher un stage</h1>
|
||||
{% include "avisstage/recherche/formulaire.html" with form=form %}
|
||||
<h2>Ou alors</h2>
|
||||
<p><a href="{% url 'avisstage:recherche_resultats' %}?vue=carte">Afficher la carte de tous les stages</a></p>
|
||||
<p><a href="{% url 'avisstage:recherche_resultats' %}?vue=liste&tri=-date_maj">Afficher les dernières mises à jour</a></p>
|
||||
<p><a href="{% url 'avisstage:recherche_resultats' %}?vue=carte">Afficher la carte de tous les stages, triés par dernière mise à jour</a></p>
|
||||
{# <p><a href="{% url 'avisstage:recherche_resultats' %}?vue=liste&tri=-date_maj">Afficher les dernières mises à jour</a></p> #}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load staticfiles avisstage_tags %}
|
||||
|
||||
{% block title %}Chercher un stage - ExperiENS{% endblock %}
|
||||
|
||||
|
@ -54,6 +54,8 @@
|
|||
<li class="thematique">{{ thematique.name }}</li>
|
||||
{% endfor %}
|
||||
<li class="year">{{ stage.date_debut|date:"Y" }}</li>
|
||||
<li class="avis-len avis-{{ stage.len_avis_stage|avis_len }}">Avis stage {{ stage.len_avis_stage|avis_len }}</li>
|
||||
<li class="avis-len avis-{{ stage.len_avis_lieux|avis_len }}">Avis lieux {{ stage.len_avis_lieux|avis_len }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a href="{% url "avisstage:stage" stage.id %}" class="hoverlink"> </a>
|
||||
|
|
|
@ -24,3 +24,12 @@ def typonazisme(value):
|
|||
value = re.sub(r'(\w)\s*([,.])', u'\\1\\2', value)
|
||||
value = re.sub(r'([?!:,.])(\w)', u'\\1 \\2', value)
|
||||
return value
|
||||
|
||||
@register.filter
|
||||
def avis_len(value):
|
||||
if value < 5:
|
||||
return "vide"
|
||||
elif value < 50:
|
||||
return "court"
|
||||
else:
|
||||
return "fourni"
|
||||
|
|
Loading…
Reference in a new issue