many fixes
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
{% if user.is_superuser %}{% load bootstrap3 %}
|
|
||||||
<li class="dropdown app-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Administration<b class="caret"></b></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a href="{% url 'sujets:create' %}">{% bootstrap_icon "plus" %} Nouveau sujet</a></li>
|
|
||||||
<li><a href="{% url 'admin:app_list' app_label='sujets' %}">{% bootstrap_icon "wrench" %} Gérer les sujets</a></li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
@@ -2,4 +2,10 @@
|
|||||||
<li class="dropdown app-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Sujets<b class="caret"></b></a>
|
<li class="dropdown app-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Sujets<b class="caret"></b></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="{% url 'sujets:liste' %}">{% bootstrap_icon "list" %} Liste complète</a></li>
|
<li><a href="{% url 'sujets:liste' %}">{% bootstrap_icon "list" %} Liste complète</a></li>
|
||||||
|
{% if user.is_superuser %}{% load bootstrap3 %}
|
||||||
|
<li class="dropdown-header">Administration</li>
|
||||||
|
<li><a href="{% url 'sujets:create' %}">{% bootstrap_icon "plus" %} Nouveau sujet</a></li>
|
||||||
|
<li><a href="{% url 'admin:app_list' app_label='sujets' %}">
|
||||||
|
{% bootstrap_icon "wrench" %} Gérer les sujets</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -10,36 +10,36 @@ from sujets.models import Sujet
|
|||||||
webpage = website.webpage(
|
webpage = website.webpage(
|
||||||
ajax=False,
|
ajax=False,
|
||||||
permissions=['sujets.view_sujets'],
|
permissions=['sujets.view_sujets'],
|
||||||
app_menu=["suivi/menu_sujets.html", "suivi/menu_administration.html"]
|
app_menu=["suivi/menu_sujets.html"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class IndexView(generic.TemplateView):
|
class IndexView(generic.TemplateView):
|
||||||
template_name = "suivi/index.html"
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Suivi des bénéficiaires"
|
title = "Suivi des bénéficiaires"
|
||||||
header = "Suivi"
|
header = "Suivi"
|
||||||
header_small = "Tableau de bord"
|
header_small = "Tableau de bord"
|
||||||
|
#TemplateView
|
||||||
|
template_name = "suivi/index.html"
|
||||||
|
|
||||||
def get_panels(self):
|
|
||||||
return ["suivi/panel_sujets.html", "suivi/panel_admin.html"]
|
|
||||||
|
|
||||||
from notes.mixins import NoteFormMixin
|
from notes.mixins import NoteFormMixin
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class SuiviSujetView(NoteFormMixin, generic.DetailView):
|
class SuiviSujetView(NoteFormMixin, generic.DetailView):
|
||||||
model = Sujet
|
|
||||||
template_name = "suivi/details.html"
|
|
||||||
context_object_name = "sujet"
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Sujet - {{sujet}}"
|
title = "Sujet - {{sujet}}"
|
||||||
header = "{{sujet}}"
|
header = "{{sujet}}"
|
||||||
header_small = "suivi"
|
header_small = "suivi"
|
||||||
|
#DetailView
|
||||||
|
model = Sujet
|
||||||
|
template_name = "suivi/details.html"
|
||||||
|
context_object_name = "sujet"
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.app_menu.insert(0, "sujets/menu_sujet.html")
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['notes'] = self.object.notes.by_date(reverse=True)
|
context['notes'] = self.object.notes.by_date(reverse=True)
|
||||||
|
|||||||
@@ -1,44 +1,11 @@
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
# Create your models here.
|
### Item choices
|
||||||
|
|
||||||
class Personne(models.Model):
|
|
||||||
""" Modèle de base d'une personne
|
|
||||||
- genre
|
|
||||||
- nom
|
|
||||||
- prénom
|
|
||||||
"""
|
|
||||||
|
|
||||||
HOMME = 'M'
|
|
||||||
FEMME = 'Mme'
|
|
||||||
GENRE_CHOICES = (
|
|
||||||
(HOMME, 'Homme'),
|
|
||||||
(FEMME, 'Femme'),
|
|
||||||
)
|
|
||||||
genre = models.CharField(max_length=3,
|
|
||||||
choices=GENRE_CHOICES,
|
|
||||||
default=HOMME)
|
|
||||||
nom = models.CharField(max_length=32, blank=True)
|
|
||||||
prenom = models.CharField(max_length=32, blank=True)
|
|
||||||
surnom = models.CharField(max_length=64, blank=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
string = '%s ' % self.genre
|
|
||||||
if self.nom: string += '%s ' % self.nom
|
|
||||||
if self.surnom: string += '"%s" ' % self.surnom
|
|
||||||
if self.prenom: string += '%s' % self.prenom
|
|
||||||
return string
|
|
||||||
|
|
||||||
def clean(self):
|
|
||||||
if not any([self.nom, self.prenom, self.surnom]):
|
|
||||||
raise ValidationError(_("Vous devez remplir au moins un nom, prénom ou surnom"))
|
|
||||||
return super().clean()
|
|
||||||
|
|
||||||
# Item: Parcours institutionnel
|
# Item: Parcours institutionnel
|
||||||
PARCOURS_INSTITUTIONNEL = "Institutionnel"
|
PARCOURS_INSTITUTIONNEL = "Institutionnel"
|
||||||
@@ -81,15 +48,49 @@ RESSOURCES_CHOICES = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
from django.db import models
|
|
||||||
|
### Models
|
||||||
|
# - Personne
|
||||||
|
# - Sujet
|
||||||
|
|
||||||
|
class Personne(models.Model):
|
||||||
|
""" Modèle de base d'une personne
|
||||||
|
- genre
|
||||||
|
- nom
|
||||||
|
- prénom
|
||||||
|
"""
|
||||||
|
|
||||||
|
HOMME = 'M'
|
||||||
|
FEMME = 'Mme'
|
||||||
|
GENRE_CHOICES = (
|
||||||
|
(HOMME, 'Homme'),
|
||||||
|
(FEMME, 'Femme'),
|
||||||
|
)
|
||||||
|
genre = models.CharField(max_length=3,
|
||||||
|
choices=GENRE_CHOICES,
|
||||||
|
default=HOMME)
|
||||||
|
nom = models.CharField(max_length=32, blank=True)
|
||||||
|
prenom = models.CharField(max_length=32, blank=True)
|
||||||
|
surnom = models.CharField(max_length=64, blank=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
string = '%s ' % self.genre
|
||||||
|
if self.nom: string += '%s ' % self.nom
|
||||||
|
if self.surnom: string += '"%s" ' % self.surnom
|
||||||
|
if self.prenom: string += '%s' % self.prenom
|
||||||
|
return string
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if not any([self.nom, self.prenom, self.surnom]):
|
||||||
|
raise ValidationError(_("Vous devez remplir au moins un nom, prénom ou surnom"))
|
||||||
|
return super().clean()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Sujet(Personne):
|
class Sujet(Personne):
|
||||||
""" Personne faisant l'objet d'un suivi par la maraude
|
""" Personne faisant l'objet d'un suivi par la maraude
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# referent = models.ForeignKey("utilisateurs.Professionnel", related_name="suivis")
|
# referent = models.ForeignKey("utilisateurs.Professionnel", related_name="suivis")
|
||||||
|
|
||||||
premiere_rencontre = models.DateField(default=timezone.now)
|
premiere_rencontre = models.DateField(default=timezone.now)
|
||||||
age = models.SmallIntegerField(blank=True, null=True)
|
age = models.SmallIntegerField(blank=True, null=True)
|
||||||
|
|
||||||
@@ -113,7 +114,6 @@ class Sujet(Personne):
|
|||||||
default=RESSOURCES_NR)
|
default=RESSOURCES_NR)
|
||||||
connu_siao = models.NullBooleanField("Connu du SIAO ?")
|
connu_siao = models.NullBooleanField("Connu du SIAO ?")
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "Sujet"
|
verbose_name = "Sujet"
|
||||||
ordering = ('surnom', 'nom', 'prenom')
|
ordering = ('surnom', 'nom', 'prenom')
|
||||||
|
|||||||
@@ -1,85 +1,77 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from website import decorators as website
|
|
||||||
|
|
||||||
from .models import Sujet
|
from .models import Sujet
|
||||||
|
from .forms import SujetCreateForm
|
||||||
|
|
||||||
from django.forms import ModelForm
|
### Webpage config
|
||||||
|
from website import decorators as website
|
||||||
|
|
||||||
webpage = website.webpage(
|
webpage = website.webpage(
|
||||||
ajax=True,
|
ajax=True,
|
||||||
permissions=['sujets.view_sujets'],
|
permissions=['sujets.view_sujets'],
|
||||||
app_name="suivi",
|
app_name="suivi",
|
||||||
app_menu=["suivi/menu_sujets.html", "suivi/menu_administration.html"]
|
app_menu=["sujets/menu_sujet.html"]
|
||||||
)
|
)
|
||||||
# Create your views here.
|
### Views
|
||||||
|
|
||||||
# TODO: deal with setting an active_app name other than module name
|
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class SujetDetailsView(generic.DetailView):
|
class SujetDetailsView(generic.DetailView):
|
||||||
template_name = "sujets/sujet_details.html"
|
|
||||||
model = Sujet
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Sujet - {{ sujet }}"
|
title = "Sujet - {{ sujet }}"
|
||||||
header = "{{ sujet }}"
|
header = "{{ sujet }}"
|
||||||
header_small = "suivi"
|
header_small = "suivi"
|
||||||
|
#DetailView
|
||||||
|
template_name = "sujets/sujet_details.html"
|
||||||
|
model = Sujet
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class SujetListView(generic.ListView):
|
class SujetListView(generic.ListView):
|
||||||
model = Sujet
|
|
||||||
template_name = "sujets/sujet_liste.html"
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Sujet - Liste des sujets"
|
title = "Sujet - Liste des sujets"
|
||||||
header = "Liste des sujets"
|
header = "Liste des sujets"
|
||||||
|
#ListView
|
||||||
|
model = Sujet
|
||||||
|
template_name = "sujets/sujet_liste.html"
|
||||||
|
paginate_by = 10
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.app_menu = ["suivi/menu_sujets.html"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class SujetUpdateView(generic.edit.UpdateView):
|
class SujetUpdateView(generic.edit.UpdateView):
|
||||||
template_name = "sujets/sujet_update.html"
|
|
||||||
model = Sujet
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Mise à jour - {{sujet}}"
|
title = "Mise à jour - {{sujet}}"
|
||||||
header = "{{sujet}}"
|
header = "{{sujet}}"
|
||||||
header_small = "mise à jour"
|
header_small = "mise à jour"
|
||||||
|
#UpdateView
|
||||||
def __init__(self, *args, **kwargs):
|
template_name = "sujets/sujet_update.html"
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
print('SujetUpdateView init:', self.__class__.__bases__)
|
|
||||||
|
|
||||||
class SujetCreateForm(ModelForm):
|
|
||||||
class Meta:
|
|
||||||
model = Sujet
|
model = Sujet
|
||||||
fields = ['nom', 'surnom', 'prenom', 'genre', 'premiere_rencontre']
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@webpage
|
@webpage
|
||||||
class SujetCreateView(generic.edit.CreateView):
|
class SujetCreateView(generic.edit.CreateView):
|
||||||
template_name = "sujets/sujet_create.html"
|
|
||||||
form_class = SujetCreateForm
|
|
||||||
|
|
||||||
class PageInfo:
|
class PageInfo:
|
||||||
title = "Nouveau sujet"
|
title = "Nouveau sujet"
|
||||||
header = "Nouveau sujet"
|
header = "Nouveau sujet"
|
||||||
|
# Special permissions
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.permissions += ['sujets.add_sujet']
|
self.permissions += ['sujets.add_sujet']
|
||||||
|
#CreateView
|
||||||
|
template_name = "sujets/sujet_create.html"
|
||||||
|
form_class = SujetCreateForm
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
if 'next' in self.request.POST:
|
if 'next' in self.request.POST:
|
||||||
self.success_url = self.request.POST["next"]
|
self.success_url = self.request.POST["next"]
|
||||||
return super().post(self, request, *args, **kwargs)
|
return super().post(self, request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
try:
|
try: context['next'] = self.request.GET['next']
|
||||||
context['next'] = self.request.GET['next']
|
except:context['next'] = None
|
||||||
except:
|
|
||||||
context['next'] = None
|
|
||||||
return context
|
return context
|
||||||
|
|||||||
@@ -6,19 +6,7 @@ from django.contrib.auth.decorators import login_required, permission_required
|
|||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin
|
from django.views.generic.base import ContextMixin, TemplateResponseMixin
|
||||||
|
|
||||||
## Utils ##
|
|
||||||
APP_ICONS = {
|
|
||||||
'maraudes': 'road',
|
|
||||||
'suivi': 'eye-open',
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_apps_config(app_names):
|
|
||||||
_apps = []
|
|
||||||
for name in app_names:
|
|
||||||
app_config = apps.get_app_config(name)
|
|
||||||
app_config.menu_icon = APP_ICONS[name]
|
|
||||||
_apps.append(app_config)
|
|
||||||
return _apps
|
|
||||||
|
|
||||||
## Mixins ##
|
## Mixins ##
|
||||||
|
|
||||||
@@ -63,12 +51,12 @@ class WebsiteTemplateMixin(TemplateResponseMixin):
|
|||||||
class Configuration:
|
class Configuration:
|
||||||
stylesheets = ['base.css']
|
stylesheets = ['base.css']
|
||||||
navbar_apps = ['maraudes', 'suivi']
|
navbar_apps = ['maraudes', 'suivi']
|
||||||
apps = get_apps_config(navbar_apps)
|
|
||||||
page_blocks = ['header', 'header_small', 'title']
|
page_blocks = ['header', 'header_small', 'title']
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
self.user = None
|
||||||
self._page_blocks = []
|
self._page_blocks = []
|
||||||
if not hasattr(self, "PageInfo"):
|
if not hasattr(self, "PageInfo"):
|
||||||
raise ImproperlyConfigured("You must define a PageInfo on ", self)
|
raise ImproperlyConfigured("You must define a PageInfo on ", self)
|
||||||
@@ -86,10 +74,38 @@ class WebsiteTemplateMixin(TemplateResponseMixin):
|
|||||||
self.content_template = self.template_name
|
self.content_template = self.template_name
|
||||||
return self.content_template
|
return self.content_template
|
||||||
|
|
||||||
|
def get_apps_config(self):
|
||||||
|
""" Load additionnal config data on each app registered in navbar"""
|
||||||
|
## Utils ##
|
||||||
|
APP_ICONS = {
|
||||||
|
'maraudes': 'road',
|
||||||
|
'suivi': 'eye-open',
|
||||||
|
}
|
||||||
|
app_names = self.Configuration.navbar_apps
|
||||||
|
self._apps = []
|
||||||
|
for name in app_names:
|
||||||
|
app_config = apps.get_app_config(name)
|
||||||
|
app_config.menu_icon = APP_ICONS[name]
|
||||||
|
#Known Issue: there is actually no 'suivi.view_suivi' permission yet !
|
||||||
|
app_config.disabled = not self.request.user.has_perm('%s.view_%s' % (name, name))
|
||||||
|
print(self.request.user, app_config, '-> has perm:', not app_config.disabled)
|
||||||
|
self._apps.append(app_config)
|
||||||
|
return self._apps
|
||||||
|
|
||||||
|
@property
|
||||||
|
def apps(self):
|
||||||
|
if not hasattr(self, '_apps'):
|
||||||
|
self._apps = self.get_apps_config()
|
||||||
|
return self._apps
|
||||||
|
|
||||||
def get_active_app(self):
|
def get_active_app(self):
|
||||||
if not self.app_name:
|
if not self.app_name:
|
||||||
self.app_name = self.__class__.__module__.split(".")[0]
|
self.app_name = self.__class__.__module__.split(".")[0]
|
||||||
return apps.get_app_config(self.app_name)
|
active_app = apps.get_app_config(self.app_name)
|
||||||
|
if not active_app in self.apps: #TODO: how do we deal with this ?
|
||||||
|
print("%s must be registered in Configuration.navbar_apps" % active_app)
|
||||||
|
return None
|
||||||
|
return active_app
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_app(self):
|
def active_app(self):
|
||||||
@@ -122,7 +138,7 @@ class WebsiteTemplateMixin(TemplateResponseMixin):
|
|||||||
self._update_context_with_rendered_blocks(context)
|
self._update_context_with_rendered_blocks(context)
|
||||||
#Website processor
|
#Website processor
|
||||||
context['stylesheets'] = self.Configuration.stylesheets
|
context['stylesheets'] = self.Configuration.stylesheets
|
||||||
context['apps'] = self.Configuration.apps
|
context['apps'] = self.apps
|
||||||
context['active_app'] = self.active_app
|
context['active_app'] = self.active_app
|
||||||
# User processor
|
# User processor
|
||||||
context = user_processor(self.request, context)
|
context = user_processor(self.request, context)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">{% for app in apps %}
|
<ul class="nav navbar-nav">{% for app in apps %}
|
||||||
<li {% if app == active_app %} class="active" {%endif%}>
|
<li class="{% if app == active_app %}active{%endif%} {% if app.disabled %}disabled{% endif%}">
|
||||||
<a href="/{{app.label}}/">{% bootstrap_icon app.menu_icon %} · <strong>{{ app.name|title }}</strong></a>
|
<a href="/{{app.label}}/">{% bootstrap_icon app.menu_icon %} · <strong>{{ app.name|title }}</strong></a>
|
||||||
</li>
|
</li>
|
||||||
{% if app == active_app %}{% for t in app_menu %}{% include t %}{% endfor %}{% endif %}
|
{% if app == active_app %}{% for t in app_menu %}{% include t %}{% endfor %}{% endif %}
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a id="UserMenu" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
<a id="UserMenu" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||||
<strong style="color:#fff;">{% bootstrap_icon "user" %} {{user}} </strong>· {{ user_group }}<span class="caret"></span></a>
|
<strong style="color:#fff;">{% bootstrap_icon "user" %} · {{user}} </strong>· {{ user_group }}<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="UserMenu">
|
<ul class="dropdown-menu" aria-labelledby="UserMenu">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% if user.is_superuser %}<li><a href="/admin/">Administration {% bootstrap_icon "new-window" %} </a></li>{% endif %}
|
{% if user.is_superuser %}<li><a href="{% url 'admin:index' %}">{% bootstrap_icon "wrench" %} Administration</a></li>{% endif %}
|
||||||
<li><a href="{% url 'logout' %}">Déconnecter {% bootstrap_icon "log-out" %}</a></li>
|
<li><a href="{% url 'logout' %}">{% bootstrap_icon "log-out" %} Déconnecter</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li>
|
<li>
|
||||||
<form class="navbar-form navbar-left" method="post" action="">{% csrf_token %}
|
<form class="navbar-form navbar-left" method="post" action="">{% csrf_token %}
|
||||||
|
|||||||
Reference in New Issue
Block a user