From fb437dd09612c6e518b0b23b0f62e54b408a0fc6 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 6 Jul 2019 08:25:24 +0000 Subject: [PATCH 01/42] Commit initial start app tickets --- tickets/__init__.py | 0 tickets/admin.py | 3 +++ tickets/apps.py | 5 +++++ tickets/migrations/__init__.py | 0 tickets/models.py | 3 +++ tickets/tests.py | 3 +++ tickets/views.py | 3 +++ 7 files changed, 17 insertions(+) create mode 100644 tickets/__init__.py create mode 100644 tickets/admin.py create mode 100644 tickets/apps.py create mode 100644 tickets/migrations/__init__.py create mode 100644 tickets/models.py create mode 100644 tickets/tests.py create mode 100644 tickets/views.py diff --git a/tickets/__init__.py b/tickets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tickets/admin.py b/tickets/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/tickets/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/tickets/apps.py b/tickets/apps.py new file mode 100644 index 00000000..3ea742ac --- /dev/null +++ b/tickets/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TicketsConfig(AppConfig): + name = 'tickets' diff --git a/tickets/migrations/__init__.py b/tickets/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tickets/models.py b/tickets/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/tickets/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/tickets/tests.py b/tickets/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/tickets/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/tickets/views.py b/tickets/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/tickets/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From f054c0a2af15d8aed66e5860fbfb1e360c1597ec Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 7 Jul 2019 17:09:56 +0000 Subject: [PATCH 02/42] Premiere vue d'affichage des tickets --- re2o/settings.py | 1 + re2o/urls.py | 1 + tickets/forms.py | 27 ++++++++++ tickets/models.py | 34 ++++++++++++- tickets/templates/tickets/aff_tickets.html | 59 ++++++++++++++++++++++ tickets/urls.py | 10 ++++ tickets/views.py | 25 ++++++++- 7 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tickets/forms.py create mode 100644 tickets/templates/tickets/aff_tickets.html create mode 100644 tickets/urls.py diff --git a/re2o/settings.py b/re2o/settings.py index f2557b44..ce7d3257 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -77,6 +77,7 @@ LOCAL_APPS = ( 're2o', 'preferences', 'logs', + 'tickets', ) INSTALLED_APPS = ( DJANGO_CONTRIB_APPS + diff --git a/re2o/urls.py b/re2o/urls.py index 37497572..c9e00667 100644 --- a/re2o/urls.py +++ b/re2o/urls.py @@ -70,6 +70,7 @@ urlpatterns = [ include('cotisations.urls', namespace='cotisations') ), url(r'^machines/', include('machines.urls', namespace='machines')), + url(r'^tickets/', include('tickets.urls', namespace='tickets')), url(r'^topologie/', include('topologie.urls', namespace='topologie')), url(r'^logs/', include('logs.urls', namespace='logs')), url( diff --git a/tickets/forms.py b/tickets/forms.py new file mode 100644 index 00000000..d1ebc323 --- /dev/null +++ b/tickets/forms.py @@ -0,0 +1,27 @@ +from django import forms +from django.forms import ModelForm, Form + +from .models import( + Ticket +) + +class EditTicketForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): + """Formulaire d'edition d'un Ticket""" + + class Meta: + model = Ticket + exclude = ['user','assigned_staff','date'] + + def __init__(self,*args, **kwargs): + prefix = kwargs.pop('prefix',self.Meta.model.__name__) + super(EditMachineForm, self).__init__(*args, prefix=prefix, **kwargs) + self.fields['title'].label = _("Titre du ticket") + self.fields['decription'].label = _("Description du ticket") + self.field['solved'].label = _("Problème réglé ?") + + + +class NewTicketForm(EditTicketForm): + """ Creation d'une machine""" + class Meta(EditeTicketForm): + fields = '__all__' diff --git a/tickets/models.py b/tickets/models.py index 71a83623..e1a0f81e 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -1,3 +1,35 @@ from django.db import models +from django.utils.translation import ugettext_lazy as _ -# Create your models here. +import users.models + +class Ticket(models.Model): + """Class définissant un ticket""" + + user = models.ForeignKey( + 'users.User', + on_delete=models.CASCADE, + related_name="tickets") + title = models.CharField( + max_length=255, + help_text=_("Nom du ticket"), + blank=False, + null=False,) + description = models.CharField( + max_length=3000, + help_text=_("Description du ticket"), + blank=False, + null=False) + date = models.DateTimeField(auto_now_add=True) + assigned_staff = models.ForeignKey( + 'users.User', + on_delete=models.PROTECT, + related_name="tickets_assigned", + blank=False, + null=True) + #categories = models.OneToManyFiled('Category') + solved = models.BooleanField(default=False) + + class Meta: + verbose_name = _("Ticket") + verbose_name_plural = _("Tickets") diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html new file mode 100644 index 00000000..ebd658b1 --- /dev/null +++ b/tickets/templates/tickets/aff_tickets.html @@ -0,0 +1,59 @@ +{% extends 'users/sidebar.html' %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block title %}{% trans "Tickets" %}{% endblock %} + +{% block content %} +
+ + + + + + + + + + {% for ticket in tickets_list %} + + + + + + {% if ticket.solved %} + + {% else %} + + {% endif %} + + {% endfor %} + + +
UserTitreDateRésolu
Lien {{ ticket.user }}{{ ticket.title }}{{ ticket.date }}
+
+{% endblock %} diff --git a/tickets/urls.py b/tickets/urls.py new file mode 100644 index 00000000..f7af41ce --- /dev/null +++ b/tickets/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', views.aff_tickets, name='index des tickets'), + url(r'^new_ticket/(?P[0-9]+)$', + views.new_ticket, + name='new-ticket'), +] diff --git a/tickets/views.py b/tickets/views.py index 91ea44a2..51c3e104 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,3 +1,26 @@ from django.shortcuts import render -# Create your views here. +from .models import( + Ticket +) + +def new_ticket(request,user): + """ Vue de création d'un ticket """ + ticket = NewTicketForm(request.POST or None, user=request.user) + if ticket.is_valid(): + new_ticket_obj = machine.save(commit=False) + nex_ticket_obj.user = user + new_machine_obj.save() + + return form( + { + 'ticketform':ticket, + }, + 'ticket/ticket.html', + request + ) +def aff_tickets(request): + """ Vue d'affichage de tout les tickets """ + tickets = Ticket.objects.all() + return render(request,'tickets/aff_tickets.html', + {'tickets_list':tickets}) From c11cc35ffc59cb06bcd96713ca0bcf420e0d1a38 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Mon, 8 Jul 2019 09:59:35 +0000 Subject: [PATCH 03/42] Just a bit of front --- templates/base.html | 1 + tickets/urls.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index e58950ab..fa3b4706 100644 --- a/templates/base.html +++ b/templates/base.html @@ -100,6 +100,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% can_view_app cotisations %}
  • {% trans "Manage the subscriptions" %}
  • {% acl_end %} +
  • {% trans "Tickets" %}
  • {% acl_end %} diff --git a/tickets/urls.py b/tickets/urls.py index f7af41ce..34913bf6 100644 --- a/tickets/urls.py +++ b/tickets/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import url from . import views urlpatterns = [ - url(r'^$', views.aff_tickets, name='index des tickets'), + url(r'^$', views.aff_tickets, name='aff-tickets'), url(r'^new_ticket/(?P[0-9]+)$', views.new_ticket, name='new-ticket'), From 1381433501830620b5ccf2defe0ab03c3ba177e5 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Mon, 8 Jul 2019 10:21:51 +0000 Subject: [PATCH 04/42] Affichage d'un ticket individuel --- tickets/templates/tickets/aff_ticket.html | 35 ++++++++++++++++++++++ tickets/templates/tickets/aff_tickets.html | 8 +++-- tickets/urls.py | 5 ++-- tickets/views.py | 6 ++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tickets/templates/tickets/aff_ticket.html diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html new file mode 100644 index 00000000..4436182a --- /dev/null +++ b/tickets/templates/tickets/aff_ticket.html @@ -0,0 +1,35 @@ +{% extends 'users/sidebar.html' %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block title %}{% trans "Tickets" %}{% endblock %} + +{% block content %} + +{{ ticket.title }} + +{% endblock %} diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index ebd658b1..04487425 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., - + @@ -41,7 +41,11 @@ with this program; if not, write to the Free Software Foundation, Inc., {% for ticket in tickets_list %} - + diff --git a/tickets/urls.py b/tickets/urls.py index 34913bf6..3e1e2c48 100644 --- a/tickets/urls.py +++ b/tickets/urls.py @@ -4,7 +4,6 @@ from . import views urlpatterns = [ url(r'^$', views.aff_tickets, name='aff-tickets'), - url(r'^new_ticket/(?P[0-9]+)$', - views.new_ticket, - name='new-ticket'), + url(r'^ticket/(?P[0-9]+)$', views.aff_ticket, name='aff-ticket'), + url(r'^new_ticket/(?P[0-9]+)$',views.new_ticket,name='new-ticket'), ] diff --git a/tickets/views.py b/tickets/views.py index 51c3e104..70e3857e 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -19,6 +19,12 @@ def new_ticket(request,user): 'ticket/ticket.html', request ) + +def aff_ticket(request,ticketid): + """Vue d'affichage d'un ticket""" + ticket = Ticket.objects.filter(id=ticketid).get() + return render(request,'tickets/aff_ticket.html',{'ticket':ticket}) + def aff_tickets(request): """ Vue d'affichage de tout les tickets """ tickets = Ticket.objects.all() From c4259658eb3c490c55563bd4f73da984dd7bd92b Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 10 Jul 2019 08:28:16 +0000 Subject: [PATCH 05/42] Formulaire de creation de ticket --- tickets/admin.py | 3 +- tickets/forms.py | 31 ++++++++------ tickets/models.py | 4 +- tickets/templates/tickets/form_ticket.html | 48 ++++++++++++++++++++++ tickets/urls.py | 2 +- tickets/views.py | 41 +++++++++++------- users/templates/users/profil.html | 5 +++ 7 files changed, 103 insertions(+), 31 deletions(-) create mode 100644 tickets/templates/tickets/form_ticket.html diff --git a/tickets/admin.py b/tickets/admin.py index 8c38f3f3..76763b9c 100644 --- a/tickets/admin.py +++ b/tickets/admin.py @@ -1,3 +1,4 @@ from django.contrib import admin - +from .models import Ticket +admin.site.register(Ticket) # Register your models here. diff --git a/tickets/forms.py b/tickets/forms.py index d1ebc323..f2a6891f 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -1,27 +1,34 @@ from django import forms from django.forms import ModelForm, Form +from re2o.field_permissions import FieldPermissionFormMixin +from re2o.mixins import FormRevMixin +from django.utils.translation import ugettext_lazy as _ from .models import( Ticket ) -class EditTicketForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): +class EditTicketForm(FormRevMixin, ModelForm): """Formulaire d'edition d'un Ticket""" + + #def __init__(self,*args, **kwargs): + #prefix = kwargs.pop('prefix',self.Meta.model.__name__) + #super(EditTicketForm, self).__init__(*args, prefix=prefix, **kwargs) + #self.fields['title'].label = _("Titre du ticket") + #self.fields['decription'].label = _("Description du ticket") + #self.fields['solved'].label = _("Problème réglé ?") class Meta: model = Ticket exclude = ['user','assigned_staff','date'] - - def __init__(self,*args, **kwargs): - prefix = kwargs.pop('prefix',self.Meta.model.__name__) - super(EditMachineForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['title'].label = _("Titre du ticket") - self.fields['decription'].label = _("Description du ticket") - self.field['solved'].label = _("Problème réglé ?") - -class NewTicketForm(EditTicketForm): +class NewTicketForm(ModelForm): """ Creation d'une machine""" - class Meta(EditeTicketForm): - fields = '__all__' + class Meta: + model = Ticket + fields = ['title', 'description'] + + #def __init(self,*args, **kwargs): + #prefix = kwargs.pop('prefix', self.Meta.model.__name__) + #super(NewTicketForm, self).__init__(*args, prefix=prefix, **kwargs) diff --git a/tickets/models.py b/tickets/models.py index e1a0f81e..abdab335 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -15,7 +15,7 @@ class Ticket(models.Model): help_text=_("Nom du ticket"), blank=False, null=False,) - description = models.CharField( + description = models.TextField( max_length=3000, help_text=_("Description du ticket"), blank=False, @@ -25,7 +25,7 @@ class Ticket(models.Model): 'users.User', on_delete=models.PROTECT, related_name="tickets_assigned", - blank=False, + blank=True, null=True) #categories = models.OneToManyFiled('Category') solved = models.BooleanField(default=False) diff --git a/tickets/templates/tickets/form_ticket.html b/tickets/templates/tickets/form_ticket.html new file mode 100644 index 00000000..79e9c68f --- /dev/null +++ b/tickets/templates/tickets/form_ticket.html @@ -0,0 +1,48 @@ +{% extends 'machines/sidebar.html' %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle +Copyright © 2017 Maël Kervella + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} +{% load massive_bootstrap_form %} +{% load i18n %} + +{% block title %}{% trans "Ticket" %}{% endblock %} + +{% block content %} +

    Ouverture d'un Ticket

    + +{% for message in messages %} +
    + + {{ message | safe }} +
    +{% endfor %} + +
    + {% csrf_token %} + {% bootstrap_form ticketform %} + {% bootstrap_button "Ouvrir le Ticket" button_type="submit" icon='ok' button_class='btn-success' %} + +{% endblock %} diff --git a/tickets/urls.py b/tickets/urls.py index 3e1e2c48..d270aa4c 100644 --- a/tickets/urls.py +++ b/tickets/urls.py @@ -5,5 +5,5 @@ from . import views urlpatterns = [ url(r'^$', views.aff_tickets, name='aff-tickets'), url(r'^ticket/(?P[0-9]+)$', views.aff_ticket, name='aff-ticket'), - url(r'^new_ticket/(?P[0-9]+)$',views.new_ticket,name='new-ticket'), + url(r'^new_ticket/$',views.new_ticket,name='new-ticket'), ] diff --git a/tickets/views.py b/tickets/views.py index 70e3857e..af2ccc83 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,24 +1,35 @@ -from django.shortcuts import render +from django.contrib import messages +from django.shortcuts import render, redirect +from django.urls import reverse +from django.forms import modelformset_factory +from re2o.views import form from .models import( Ticket ) -def new_ticket(request,user): - """ Vue de création d'un ticket """ - ticket = NewTicketForm(request.POST or None, user=request.user) - if ticket.is_valid(): - new_ticket_obj = machine.save(commit=False) - nex_ticket_obj.user = user - new_machine_obj.save() +from .forms import ( + NewTicketForm +) - return form( - { - 'ticketform':ticket, - }, - 'ticket/ticket.html', - request - ) +def new_ticket(request): + """ Vue de création d'un ticket """ + ticketform = NewTicketForm(request.POST or None)#, user=request.user) + + if request.method == 'POST': + ticketform = NewTicketForm(request.POST) + + if ticketform.is_valid(): + ticket = ticketform.save(commit=False) + ticket.user = request.user + ticket.save() + messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') + return redirect(reverse('users:profil',kwargs={'userid':str(request.user.id)})) + else: + messages.error(request, 'Formulaire invalide') + else: + ticketform = NewTicketForm + return form({'ticketform':ticketform,},'tickets/form_ticket.html',request) def aff_ticket(request,ticketid): """Vue d'affichage d'un ticket""" diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 52a214a6..5b57f6a8 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -119,6 +119,11 @@ with this program; if not, write to the Free Software Foundation, Inc., + + + {% trans " Open a Ticket" %} + +
    Date: Wed, 10 Jul 2019 09:16:37 +0000 Subject: [PATCH 06/42] Affichage des tickets sur le profil --- tickets/templates/tickets/aff_tickets.html | 1 - users/templates/users/profil.html | 25 ++++++++++++++++++---- users/views.py | 8 +++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 04487425..54573ace 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -1,4 +1,3 @@ -{% extends 'users/sidebar.html' %} {% comment %} Re2o est un logiciel d'administration développé initiallement au rezometz. Il se veut agnostique au réseau considéré, de manière à être installable en diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 5b57f6a8..dee64ccc 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -120,10 +120,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    - - {% trans " Open a Ticket" %} - -
    +
    +
    +

    + {% trans " Tickets" %} +

    +
    +
    + +
    + {% if tickets_list %} + {% include 'tickets/aff_tickets.html' with tickets_list=tickets_list %} + {% else %} +

    {% trans "No tickets" %}

    + {% endif %} +
    +
    +
    {% endblock %} diff --git a/users/views.py b/users/views.py index ad8543b5..ca95e584 100644 --- a/users/views.py +++ b/users/views.py @@ -53,6 +53,10 @@ from reversion import revisions as reversion from cotisations.models import Facture, Paiement from machines.models import Machine + +# A IMPORTER SOUS CONDITION QUE TICKET SOIT INSTALLED +from tickets.models import Ticket + from preferences.models import OptionalUser, GeneralOption, AssoOption from re2o.views import form from re2o.utils import ( @@ -974,6 +978,8 @@ def profil(request, users, **_kwargs): request.GET.get('order'), SortTable.MACHINES_INDEX ) + tickets = Ticket.objects.filter(user=users).all() + nb_tickets = tickets.count() pagination_large_number = GeneralOption.get_cached_value( 'pagination_large_number' ) @@ -1016,6 +1022,8 @@ def profil(request, users, **_kwargs): 'users': users, 'machines_list': machines, 'nb_machines': nb_machines, + 'tickets_list': tickets, + 'nb_tickets': nb_tickets, 'facture_list': factures, 'ban_list': bans, 'white_list': whitelists, From 790b43ccc36498d360ce60570ed7c3cd066791f6 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 10 Jul 2019 12:24:06 +0000 Subject: [PATCH 07/42] Affichage propre d'un ticket simple --- re2o/settings.py | 1 + tickets/templates/tickets/aff_ticket.html | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/re2o/settings.py b/re2o/settings.py index ce7d3257..96fa9308 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -62,6 +62,7 @@ DJANGO_CONTRIB_APPS = ( 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.humanize', ) EXTERNAL_CONTRIB_APPS = ( 'bootstrap3', diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index 4436182a..242aa4f4 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -25,11 +25,28 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load i18n %} +{% load humanize %} {% block title %}{% trans "Tickets" %}{% endblock %} {% block content %} -{{ ticket.title }} +

    Ticket #{{ticket.id}}

    + +
    +
    + {% trans "Opened by" %} + + {{ ticket.user.get_full_name }} + + {{ ticket.date | naturalday}}. +
    +
    + +

    {% trans "Title:" %} {{ticket.title}}

    +

    {% trans "Description" %} {{ ticket.description }}

    + +
    +
    {% endblock %} From a561f094582a1792391645c99dfac03b4233af58 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 10 Jul 2019 14:39:55 +0000 Subject: [PATCH 08/42] Meilleur affichage de tout les tickets --- tickets/templates/tickets/aff_tickets.html | 2 +- tickets/templates/tickets/index.html | 34 ++++++++++++++++++++++ tickets/views.py | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tickets/templates/tickets/index.html diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 54573ace..5c10a4a4 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    id User Titre Date
    Lien + + + + {{ ticket.user }} {{ ticket.title }} {{ ticket.date }}
    - + diff --git a/tickets/templates/tickets/index.html b/tickets/templates/tickets/index.html new file mode 100644 index 00000000..4429c4fd --- /dev/null +++ b/tickets/templates/tickets/index.html @@ -0,0 +1,34 @@ +{% extends 'users/sidebar.html' %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block title%}{% trans "Tickets" %}{% endblock %} + +{% block content %} +

    {% trans "Tickets" %}

    + {% include 'tickets/aff_tickets.html' with tickets_list=tickets_list %} +{% endblock %} diff --git a/tickets/views.py b/tickets/views.py index af2ccc83..98a9518d 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -39,5 +39,5 @@ def aff_ticket(request,ticketid): def aff_tickets(request): """ Vue d'affichage de tout les tickets """ tickets = Ticket.objects.all() - return render(request,'tickets/aff_tickets.html', + return render(request,'tickets/index.html', {'tickets_list':tickets}) From 609904c279e9f98cd61d502864697a3657b6d52f Mon Sep 17 00:00:00 2001 From: Grizzly Date: Thu, 11 Jul 2019 08:00:49 +0000 Subject: [PATCH 09/42] Ordonancement des tickets par date --- tickets/views.py | 2 +- users/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tickets/views.py b/tickets/views.py index 98a9518d..c6eccdd7 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -38,6 +38,6 @@ def aff_ticket(request,ticketid): def aff_tickets(request): """ Vue d'affichage de tout les tickets """ - tickets = Ticket.objects.all() + tickets = Ticket.objects.all().order_by('date') return render(request,'tickets/index.html', {'tickets_list':tickets}) diff --git a/users/views.py b/users/views.py index ca95e584..4bed47f4 100644 --- a/users/views.py +++ b/users/views.py @@ -978,7 +978,7 @@ def profil(request, users, **_kwargs): request.GET.get('order'), SortTable.MACHINES_INDEX ) - tickets = Ticket.objects.filter(user=users).all() + tickets = Ticket.objects.filter(user=users).all().order_by('date') nb_tickets = tickets.count() pagination_large_number = GeneralOption.get_cached_value( 'pagination_large_number' From 13afc5aaebf32a5160bf6a9aea21c9b38908de8d Mon Sep 17 00:00:00 2001 From: Grizzly Date: Thu, 11 Jul 2019 08:27:58 +0000 Subject: [PATCH 10/42] Dummy bouton, order des date, et affichage dans l'admin --- tickets/models.py | 3 +++ tickets/templates/tickets/aff_ticket.html | 10 ++++++++++ tickets/views.py | 2 +- users/views.py | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tickets/models.py b/tickets/models.py index abdab335..ba0b183e 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -33,3 +33,6 @@ class Ticket(models.Model): class Meta: verbose_name = _("Ticket") verbose_name_plural = _("Tickets") + + def __str__(self): + return "Ticket de {} date: {}".format(self.user.surname,self.date) diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index 242aa4f4..42ef897b 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -46,6 +46,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,

    {% trans "Title:" %} {{ticket.title}}

    {% trans "Description" %} {{ ticket.description }}

    + diff --git a/tickets/views.py b/tickets/views.py index c6eccdd7..270bf0df 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -38,6 +38,6 @@ def aff_ticket(request,ticketid): def aff_tickets(request): """ Vue d'affichage de tout les tickets """ - tickets = Ticket.objects.all().order_by('date') + tickets = Ticket.objects.all().order_by('-date') return render(request,'tickets/index.html', {'tickets_list':tickets}) diff --git a/users/views.py b/users/views.py index 4bed47f4..a039bad6 100644 --- a/users/views.py +++ b/users/views.py @@ -978,7 +978,7 @@ def profil(request, users, **_kwargs): request.GET.get('order'), SortTable.MACHINES_INDEX ) - tickets = Ticket.objects.filter(user=users).all().order_by('date') + tickets = Ticket.objects.filter(user=users).all().order_by('-date') nb_tickets = tickets.count() pagination_large_number = GeneralOption.get_cached_value( 'pagination_large_number' From 2650065787ea4631a3a16c1462e60d1fb2e64ff9 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Fri, 12 Jul 2019 11:41:17 +0000 Subject: [PATCH 11/42] Ouverture de ticket pour les utilisaterus non authentifies --- tickets/forms.py | 5 ++++- tickets/models.py | 8 +++++++- tickets/templates/tickets/form_ticket.html | 21 +++++++++++++++++++-- tickets/views.py | 21 +++++++++++++++------ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/tickets/forms.py b/tickets/forms.py index f2a6891f..d914d022 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -25,9 +25,12 @@ class EditTicketForm(FormRevMixin, ModelForm): class NewTicketForm(ModelForm): """ Creation d'une machine""" + + email = forms.EmailField(required=False) + class Meta: model = Ticket - fields = ['title', 'description'] + fields = ['title', 'description', 'email'] #def __init(self,*args, **kwargs): #prefix = kwargs.pop('prefix', self.Meta.model.__name__) diff --git a/tickets/models.py b/tickets/models.py index ba0b183e..01a4d77b 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -9,7 +9,9 @@ class Ticket(models.Model): user = models.ForeignKey( 'users.User', on_delete=models.CASCADE, - related_name="tickets") + related_name="tickets", + blank=True, + null=True) title = models.CharField( max_length=255, help_text=_("Nom du ticket"), @@ -21,6 +23,10 @@ class Ticket(models.Model): blank=False, null=False) date = models.DateTimeField(auto_now_add=True) + email = models.EmailField( + help_text = _("Une adresse mail pour vous recontacter"), + max_length=100, + null=True) assigned_staff = models.ForeignKey( 'users.User', on_delete=models.PROTECT, diff --git a/tickets/templates/tickets/form_ticket.html b/tickets/templates/tickets/form_ticket.html index 79e9c68f..d80a993e 100644 --- a/tickets/templates/tickets/form_ticket.html +++ b/tickets/templates/tickets/form_ticket.html @@ -40,9 +40,26 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endfor %} -
    + {% csrf_token %} - {% bootstrap_form ticketform %} + {% if not user.is_authenticated %} +

    {% trans "Vous n'êtes pas authentifié. Veuillez fournir une adresse mail afin que nous puissions vous recontacter." %}

    + {% bootstrap_field ticketform.email %} + {% endif %} + {% bootstrap_field ticketform.title %} +
    +

    {% trans "Description de votre problème. Veuillez fournir le plus d'informations possible afin de faciliter la recherche de solution. Voici quelques informations dont nous pourions avoir besoin:" %}

    +
      +
    • +

      {% trans "Le type de votre problème (adhesion, connexion, paiement ou autre)." %}

      +
    • +
    • +

      {% trans "Les conditions dans lesquelles vous rencontrez le problème (Wifi/filaire, sur tout les apareils ou sur un seul. Est-ce une nouvelle machine ?" %}

      +
    • +
    • +

      {% trans "Les endroits dans lequels le problème survient (chez vous, dans une partie commune, dans un batiment en particulier)." %}

      +
    + {% bootstrap_field ticketform.description %} {% bootstrap_button "Ouvrir le Ticket" button_type="submit" icon='ok' button_class='btn-success' %} {% endblock %} diff --git a/tickets/views.py b/tickets/views.py index 270bf0df..cb138590 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -20,13 +20,22 @@ def new_ticket(request): ticketform = NewTicketForm(request.POST) if ticketform.is_valid(): + email = ticketform.cleaned_data.get('email') ticket = ticketform.save(commit=False) - ticket.user = request.user - ticket.save() - messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') - return redirect(reverse('users:profil',kwargs={'userid':str(request.user.id)})) - else: - messages.error(request, 'Formulaire invalide') + #raise ValueError("email: {} type: {}".format(email,type(email))) + if request.user.is_authenticated: + ticket.user = request.user + ticket.save() + messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') + return redirect(reverse('users:profil',kwargs={'userid':str(request.user.id)})) + if not request.user.is_authenticated and email != "": + ticket.save() + messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') + return redirect(reverse('index')) + else: + messages.error(request,"Vous n'êtes pas authentifié, veuillez vous authentifier ou fournir une adresse mail pour que nous puissions vous recontacter") + return form({'ticketform':ticketform,},'tickets/form_ticket.html',request) + else: ticketform = NewTicketForm return form({'ticketform':ticketform,},'tickets/form_ticket.html',request) From 22c311c1eca17936f92797520e07e40281da9431 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Fri, 12 Jul 2019 12:00:56 +0000 Subject: [PATCH 12/42] affichage des tickets sans user et adresse de reponse --- tickets/templates/tickets/aff_ticket.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index 42ef897b..4683f1fc 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -35,11 +35,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    - {% trans "Opened by" %} - - {{ ticket.user.get_full_name }} - + {% trans "Opened by" %} + {% if ticket.user %} + + {{ ticket.user.get_full_name }} + + {% else %} + {% trans "Anonymous User" %} + {% endif %} {{ ticket.date | naturalday}}. + {% if not ticket.user %} + {% trans "Response address: " %}{{ticket.email}} + {% endif %}
    From 7099d6d57af4367f81c35187bff2debad9d9b158 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Fri, 12 Jul 2019 13:57:50 +0000 Subject: [PATCH 13/42] Ouverture des tickets disponible sur la page d'accueil --- templates/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/base.html b/templates/base.html index fa3b4706..10590167 100644 --- a/templates/base.html +++ b/templates/base.html @@ -131,6 +131,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if not request.user.is_authenticated %} From 575e570d16b28806e82d18599280e5565d83cb96 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Thu, 25 Jul 2019 14:44:40 +0000 Subject: [PATCH 14/42] Cannonisation de l'affichage des apps optionnels sur le profil et imports conditionnels dans les urls --- re2o/settings.py | 1 - re2o/urls.py | 7 ++++++- templates/base.html | 5 +++++ tickets/templates/tickets/profil.html | 23 +++++++++++++++++++++++ tickets/views.py | 6 ++++++ users/templates/users/profil.html | 26 +++++--------------------- users/views.py | 15 ++++++++------- 7 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 tickets/templates/tickets/profil.html diff --git a/re2o/settings.py b/re2o/settings.py index 96fa9308..14907570 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -78,7 +78,6 @@ LOCAL_APPS = ( 're2o', 'preferences', 'logs', - 'tickets', ) INSTALLED_APPS = ( DJANGO_CONTRIB_APPS + diff --git a/re2o/urls.py b/re2o/urls.py index c9e00667..5db9abe8 100644 --- a/re2o/urls.py +++ b/re2o/urls.py @@ -49,6 +49,8 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ from django.views.generic import RedirectView +from .settings_local import OPTIONNAL_APPS + from .views import index, about_page, contact_page # Admin site configuration @@ -70,7 +72,6 @@ urlpatterns = [ include('cotisations.urls', namespace='cotisations') ), url(r'^machines/', include('machines.urls', namespace='machines')), - url(r'^tickets/', include('tickets.urls', namespace='tickets')), url(r'^topologie/', include('topologie.urls', namespace='topologie')), url(r'^logs/', include('logs.urls', namespace='logs')), url( @@ -84,6 +85,10 @@ urlpatterns = [ url(r'^admin/login/$', RedirectView.as_view(pattern_name='login')), url(r'^admin/', include(admin.site.urls)), ] + + +urlpatterns += [url(r'^{}/'.format(app), include('{}.urls'.format(app), namespace=app)) for app in OPTIONNAL_APPS] + # Add debug_toolbar URLs if activated if 'debug_toolbar' in settings.INSTALLED_APPS: import debug_toolbar diff --git a/templates/base.html b/templates/base.html index 10590167..6d39f8c8 100644 --- a/templates/base.html +++ b/templates/base.html @@ -100,7 +100,10 @@ with this program; if not, write to the Free Software Foundation, Inc., {% can_view_app cotisations %}
  • {% trans "Manage the subscriptions" %}
  • {% acl_end %} + + {% comment %}
  • {% trans "Tickets" %}
  • + {% endcomment %} {% acl_end %} @@ -131,7 +134,9 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if not request.user.is_authenticated %} diff --git a/tickets/templates/tickets/profil.html b/tickets/templates/tickets/profil.html new file mode 100644 index 00000000..06b727a4 --- /dev/null +++ b/tickets/templates/tickets/profil.html @@ -0,0 +1,23 @@ +{% load i18n %} + +
    +
    +

    + {% trans " Tickets" %} +

    +
    +
    + +
    + {% if tickets_list %} + {% include 'tickets/aff_tickets.html' with tickets_list=tickets_list %} + {% else %} +

    {% trans "No tickets" %}

    + {% endif %} +
    +
    +
    diff --git a/tickets/views.py b/tickets/views.py index cb138590..9c6b42e6 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,5 +1,6 @@ from django.contrib import messages from django.shortcuts import render, redirect +from django.template.loader import render_to_string from django.urls import reverse from django.forms import modelformset_factory from re2o.views import form @@ -50,3 +51,8 @@ def aff_tickets(request): tickets = Ticket.objects.all().order_by('-date') return render(request,'tickets/index.html', {'tickets_list':tickets}) +def profil(request,user): + """ Vue cannonique d'affichage des tickets dans l'accordeon du profil""" + tickets = Ticket.objects.filter(user=user).all().order_by('-date') + context = {'tickets_list':tickets} + return render_to_string('tickets/profil.html', context=context, request=request, using=None) diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index dee64ccc..a7079232 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -528,27 +528,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    -
    -
    -

    - {% trans " Tickets" %} -

    -
    -
    - -
    - {% if tickets_list %} - {% include 'tickets/aff_tickets.html' with tickets_list=tickets_list %} - {% else %} -

    {% trans "No tickets" %}

    - {% endif %} -
    -
    -
    + + {% for template in optionnal_templates_list %} + {{ template }} + {% endfor %} + {% endblock %} diff --git a/users/views.py b/users/views.py index a039bad6..426645e5 100644 --- a/users/views.py +++ b/users/views.py @@ -47,6 +47,7 @@ from django.http import HttpResponse from django.http import HttpResponseRedirect from django.views.decorators.csrf import csrf_exempt from django.utils.translation import ugettext as _ +from django.template import loader from rest_framework.renderers import JSONRenderer from reversion import revisions as reversion @@ -54,10 +55,9 @@ from reversion import revisions as reversion from cotisations.models import Facture, Paiement from machines.models import Machine -# A IMPORTER SOUS CONDITION QUE TICKET SOIT INSTALLED -from tickets.models import Ticket - from preferences.models import OptionalUser, GeneralOption, AssoOption +from importlib import import_module +from re2o.settings_local import OPTIONNAL_APPS from re2o.views import form from re2o.utils import ( all_has_access, @@ -978,8 +978,10 @@ def profil(request, users, **_kwargs): request.GET.get('order'), SortTable.MACHINES_INDEX ) - tickets = Ticket.objects.filter(user=users).all().order_by('-date') - nb_tickets = tickets.count() + + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_templates_list = [app.views.profil(request,users) for app in optionnal_apps] + pagination_large_number = GeneralOption.get_cached_value( 'pagination_large_number' ) @@ -1022,8 +1024,7 @@ def profil(request, users, **_kwargs): 'users': users, 'machines_list': machines, 'nb_machines': nb_machines, - 'tickets_list': tickets, - 'nb_tickets': nb_tickets, + 'optionnal_templates_list': optionnal_templates_list, 'facture_list': factures, 'ban_list': bans, 'white_list': whitelists, From 8e403443b522dbc760de24fd3f1c8ccfffa61528 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Mon, 5 Aug 2019 14:38:53 +0000 Subject: [PATCH 15/42] =?UTF-8?q?Affichage=20des=20pr=C3=A9f=C3=A9rences?= =?UTF-8?q?=20des=20tickets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../preferences/display_preferences.html | 4 ++++ preferences/views.py | 7 ++++++ tickets/models.py | 22 +++++++++++++++++++ tickets/templates/tickets/preferences.html | 12 ++++++++++ tickets/views.py | 13 ++++++++++- 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tickets/templates/tickets/preferences.html diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index a7d15679..3e71c817 100644 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -503,5 +503,9 @@ with this program; if not, write to the Free Software Foundation, Inc., +{% for template in optionnal_templates_list %} + {{ template }} +{% endfor %} + {% endblock %} diff --git a/preferences/views.py b/preferences/views.py index ecb3826e..680fcac0 100644 --- a/preferences/views.py +++ b/preferences/views.py @@ -40,6 +40,8 @@ from django.utils.translation import ugettext as _ from reversion import revisions as reversion +from importlib import import_module +from re2o.settings_local import OPTIONNAL_APPS from re2o.views import form from re2o.acl import can_create, can_edit, can_delete_set, can_view_all, can_delete @@ -94,6 +96,10 @@ def display_options(request): radiusoptions, _ = RadiusOption.objects.get_or_create() cotisationsoptions, _created = CotisationsOption.objects.get_or_create() document_template_list = DocumentTemplate.objects.order_by('name') + + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_templates_list = [app.views.preferences(request) for app in optionnal_apps] + return form({ 'useroptions': useroptions, 'machineoptions': machineoptions, @@ -109,6 +115,7 @@ def display_options(request): 'switchmanagementcred_list': switchmanagementcred_list, 'radiusoptions' : radiusoptions, 'cotisationsoptions': cotisationsoptions, + 'optionnal_templates_list': optionnal_templates_list, 'document_template_list': document_template_list, }, 'preferences/display_preferences.html', request) diff --git a/tickets/models.py b/tickets/models.py index 01a4d77b..df1cd8ac 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -1,5 +1,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from django.core.mail import send_mail +from django.template import Context, loader import users.models @@ -42,3 +44,23 @@ class Ticket(models.Model): def __str__(self): return "Ticket de {} date: {}".format(self.user.surname,self.date) + + def publish_mail(self): + template = loader.get_template('ticket/mail_publish_ticket') + context = Context({'ticket':self}) + send_mail( + 'Nouvelle ouverture de ticket', + '', + 'ticket_app_re2o@crans.org', + '', + html_message=template.render(context)) + +class Preferences(models.Model): + """ Class cannonique définissants les préférences des tickets """ + + publish_address = models.EmailField( + help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), + max_length = 1000, + null = True) + class Meta: + verbose_name = _("Préférences des tickets") diff --git a/tickets/templates/tickets/preferences.html b/tickets/templates/tickets/preferences.html new file mode 100644 index 00000000..c27c0a99 --- /dev/null +++ b/tickets/templates/tickets/preferences.html @@ -0,0 +1,12 @@ +{% load i18n %} + +
    + +
    + preferences des tickets +
    +
    diff --git a/tickets/views.py b/tickets/views.py index 9c6b42e6..ef268f9f 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -6,13 +6,15 @@ from django.forms import modelformset_factory from re2o.views import form from .models import( - Ticket + Ticket, + Preferences, ) from .forms import ( NewTicketForm ) + def new_ticket(request): """ Vue de création d'un ticket """ ticketform = NewTicketForm(request.POST or None)#, user=request.user) @@ -51,8 +53,17 @@ def aff_tickets(request): tickets = Ticket.objects.all().order_by('-date') return render(request,'tickets/index.html', {'tickets_list':tickets}) + + +# views cannoniques des apps optionnels def profil(request,user): """ Vue cannonique d'affichage des tickets dans l'accordeon du profil""" tickets = Ticket.objects.filter(user=user).all().order_by('-date') context = {'tickets_list':tickets} return render_to_string('tickets/profil.html', context=context, request=request, using=None) + +def preferences(request): + """ Vue cannonique d'affichage des tickets dans l'affichage du profil""" + preferences = Preferences.objects.first() + context = {'preferences':preferences} + return render_to_string('tickets/preferences.html', context=context, request=request, using=None) From 1d60f62555d8ac5e27d90844d9cf7adf7b316682 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 6 Aug 2019 05:10:37 +0000 Subject: [PATCH 16/42] =?UTF-8?q?Edition=20des=20pr=C3=A9f=C3=A9rences=20d?= =?UTF-8?q?es=20tickets=20sur=20la=20page=20des=20pr=C3=A9f=C3=A9rences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tickets/forms.py | 21 +++----- .../templates/tickets/form_preferences.html | 48 +++++++++++++++++++ tickets/templates/tickets/preferences.html | 25 +++++++++- tickets/urls.py | 1 + tickets/views.py | 22 ++++++++- 5 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 tickets/templates/tickets/form_preferences.html diff --git a/tickets/forms.py b/tickets/forms.py index d914d022..1b4fa4ce 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -5,19 +5,12 @@ from re2o.mixins import FormRevMixin from django.utils.translation import ugettext_lazy as _ from .models import( - Ticket + Ticket, + Preferences, ) class EditTicketForm(FormRevMixin, ModelForm): """Formulaire d'edition d'un Ticket""" - - #def __init__(self,*args, **kwargs): - #prefix = kwargs.pop('prefix',self.Meta.model.__name__) - #super(EditTicketForm, self).__init__(*args, prefix=prefix, **kwargs) - #self.fields['title'].label = _("Titre du ticket") - #self.fields['decription'].label = _("Description du ticket") - #self.fields['solved'].label = _("Problème réglé ?") - class Meta: model = Ticket exclude = ['user','assigned_staff','date'] @@ -25,13 +18,13 @@ class EditTicketForm(FormRevMixin, ModelForm): class NewTicketForm(ModelForm): """ Creation d'une machine""" - email = forms.EmailField(required=False) - class Meta: model = Ticket fields = ['title', 'description', 'email'] - #def __init(self,*args, **kwargs): - #prefix = kwargs.pop('prefix', self.Meta.model.__name__) - #super(NewTicketForm, self).__init__(*args, prefix=prefix, **kwargs) +class EditPreferencesForm(ModelForm): + """ Edition des préférences des tickets """ + class Meta: + model = Preferences + fields = '__all__' diff --git a/tickets/templates/tickets/form_preferences.html b/tickets/templates/tickets/form_preferences.html new file mode 100644 index 00000000..83339484 --- /dev/null +++ b/tickets/templates/tickets/form_preferences.html @@ -0,0 +1,48 @@ +{% extends 'machines/sidebar.html' %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle +Copyright © 2017 Maël Kervella + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} +{% load massive_bootstrap_form %} +{% load i18n %} + +{% block title %}{% trans "Ticket" %}{% endblock %} + +{% block content %} +

    Edition des préférences des Tickets

    + +{% for message in messages %} +
    + + {{ message | safe }} +
    +{% endfor %} + +
    + {% csrf_token %} + {% bootstrap_field preferencesform.publish_address %} + {% bootstrap_button "Editer" button_type="submit" icon='ok' button_class='btn-success' %} + +{% endblock %} diff --git a/tickets/templates/tickets/preferences.html b/tickets/templates/tickets/preferences.html index c27c0a99..8f9fe490 100644 --- a/tickets/templates/tickets/preferences.html +++ b/tickets/templates/tickets/preferences.html @@ -6,7 +6,28 @@ {% trans "Tickets" %} -
    - preferences des tickets + +
    id User Titre Date
    + + + + {% if preferences.publish_address %} + + {% else %} + + {% endif %} + +

    Email de publication

    {{ preferences.publish_address }}

    {% trans "Pas d'adresse, les tickets ne sont pas annoncés" %}

    +
    + diff --git a/tickets/urls.py b/tickets/urls.py index d270aa4c..98556a7a 100644 --- a/tickets/urls.py +++ b/tickets/urls.py @@ -5,5 +5,6 @@ from . import views urlpatterns = [ url(r'^$', views.aff_tickets, name='aff-tickets'), url(r'^ticket/(?P[0-9]+)$', views.aff_ticket, name='aff-ticket'), + url(r'^ticket/edit-preferences-tickets$', views.edit_preferences, name='edit-preferences-tickets'), url(r'^new_ticket/$',views.new_ticket,name='new-ticket'), ] diff --git a/tickets/views.py b/tickets/views.py index ef268f9f..13b6ad23 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -11,13 +11,14 @@ from .models import( ) from .forms import ( - NewTicketForm + NewTicketForm, + EditPreferencesForm, ) def new_ticket(request): """ Vue de création d'un ticket """ - ticketform = NewTicketForm(request.POST or None)#, user=request.user) + ticketform = NewTicketForm(request.POST or None) if request.method == 'POST': ticketform = NewTicketForm(request.POST) @@ -54,6 +55,23 @@ def aff_tickets(request): return render(request,'tickets/index.html', {'tickets_list':tickets}) +def edit_preferences(request): + """ Vue d'édition des préférences des tickets """ + + preferences_instance, created = Preferences.objects.get_or_create(id=1) + preferencesform = EditPreferencesForm( + request.POST or None, + instance = preferences_instance,) + + if preferencesform.is_valid(): + if preferencesform.changed_data: + preferencesform.save() + messages.success(request,'Préférences des Tickets mises à jour') + return redirect(reverse('preferences:display-options',)) + else: + messages.error(request,'Formulaire Invalide') + return form({'preferencesform':preferencesform,},'tickets/form_preferences.html',request) + return form({'preferencesform':preferencesform,},'tickets/form_preferences.html',request) # views cannoniques des apps optionnels def profil(request,user): From 209f118de2be448b3dbe1e105379f833731df95a Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 6 Aug 2019 07:41:27 +0000 Subject: [PATCH 17/42] =?UTF-8?q?R=C3=A9solution=20et=20r=C3=A9ouverture?= =?UTF-8?q?=20des=20tickets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tickets/forms.py | 7 +++++++ tickets/templates/tickets/aff_ticket.html | 18 ++++++++++-------- tickets/views.py | 7 ++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tickets/forms.py b/tickets/forms.py index 1b4fa4ce..4bb59458 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -28,3 +28,10 @@ class EditPreferencesForm(ModelForm): class Meta: model = Preferences fields = '__all__' + +class ChangeStatusTicketForm(ModelForm): + """ Passe un Ticket en résolu """ + class Meta: + model = Ticket + fields = [] + diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index 4683f1fc..f56a6b6c 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -54,14 +54,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,

    {% trans "Description" %} {{ ticket.description }}

    -{% if not ticket.solved %} - - {% trans "Mark as Solved" %} -{% else %} - - {% trans "Mark as Not Solved" %} -{% endif %} - +
    + {% csrf_token %} + {% bootstrap_form changestatusform %} + + {% if not ticket.solved %} + {% bootstrap_button "Résoudre" button_type="submit" button_class='btn-info' %} + {% else %} + {% bootstrap_button "Ouvrir" button_type="submit" button_class='btn-warning' %} + {% endif %} +
    diff --git a/tickets/views.py b/tickets/views.py index 13b6ad23..0e89218d 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -12,6 +12,7 @@ from .models import( from .forms import ( NewTicketForm, + ChangeStatusTicketForm, EditPreferencesForm, ) @@ -47,7 +48,11 @@ def new_ticket(request): def aff_ticket(request,ticketid): """Vue d'affichage d'un ticket""" ticket = Ticket.objects.filter(id=ticketid).get() - return render(request,'tickets/aff_ticket.html',{'ticket':ticket}) + changestatusform = ChangeStatusTicketForm(request.POST) + if request.method == 'POST': + ticket.solved = not ticket.solved + ticket.save() + return render(request,'tickets/aff_ticket.html',{'ticket':ticket,'changestatusform':changestatusform}) def aff_tickets(request): """ Vue d'affichage de tout les tickets """ From 034dec924d73d13dd4e27edbbe0a09c16a1c44c7 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 6 Aug 2019 16:06:53 +0000 Subject: [PATCH 18/42] frontend kikoo --- tickets/templates/tickets/aff_ticket.html | 17 ++++++++++++++--- tickets/templates/tickets/aff_tickets.html | 20 +++++++++++++++++++- tickets/views.py | 11 +++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index f56a6b6c..7bf5b04d 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -31,7 +31,13 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block content %} -

    Ticket #{{ticket.id}}

    +

    Ticket #{{ticket.id}} +{% if ticket.solved %} +{% trans "Solved" %} +{% else %} +{% trans "Not Solved" %} +{% endif %} +

    @@ -59,13 +65,18 @@ with this program; if not, write to the Free Software Foundation, Inc., {% bootstrap_form changestatusform %} {% if not ticket.solved %} - {% bootstrap_button "Résoudre" button_type="submit" button_class='btn-info' %} + {% bootstrap_button "Mark as Solved" button_type="submit" button_class='btn-info' %} {% else %} - {% bootstrap_button "Ouvrir" button_type="submit" button_class='btn-warning' %} + {% bootstrap_button "Mark as not Solved" button_type="submit" button_class='btn-warning' %} {% endif %}
    + + + {% endblock %} diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 5c10a4a4..1d447234 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -28,8 +28,26 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block title %}{% trans "Tickets" %}{% endblock %} {% block content %} + + +
    +
    +
    +
    + {{ nbr_tickets }} {% trans "Tickets" %} +
    +
    + {{ nbr_tickets_unsolved }}{% trans "Not Solved Tickets" %} +
    +
    + {% trans "Last Ticket:" %} {{ last_ticket_date }} +
    +
    +
    +
    +
    - +
    diff --git a/tickets/views.py b/tickets/views.py index 0e89218d..7a86ecf4 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -57,8 +57,15 @@ def aff_ticket(request,ticketid): def aff_tickets(request): """ Vue d'affichage de tout les tickets """ tickets = Ticket.objects.all().order_by('-date') - return render(request,'tickets/index.html', - {'tickets_list':tickets}) + last_ticket_date = tickets.first().date + nbr_tickets = tickets.count() + nbr_tickets_unsolved = Ticket.objects.filter(solved=False).count() + context = {'tickets_list':tickets, + 'last_ticket_date':last_ticket_date, + 'nbr_tickets':nbr_tickets, + 'nbr_tickets_unsolved':nbr_tickets_unsolved} + + return render(request,'tickets/index.html',context=context) def edit_preferences(request): """ Vue d'édition des préférences des tickets """ From 49184d32d63a59b663233effcf205257fe2ec59d Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 6 Aug 2019 19:27:03 +0000 Subject: [PATCH 19/42] pagination --- tickets/templates/tickets/aff_tickets.html | 11 +++++++++-- tickets/views.py | 23 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 1d447234..401d1c3c 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {{ nbr_tickets }} {% trans "Tickets" %}
    - {{ nbr_tickets_unsolved }}{% trans "Not Solved Tickets" %} + {{ nbr_tickets_unsolved }}{% trans "Not Solved Tickets" %}
    {% trans "Last Ticket:" %} {{ last_ticket_date }} @@ -46,8 +46,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    + +
    -
    + +
    @@ -76,5 +79,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
    + + {% if tickets_list.paginator %} + {% include 'pagination.html' with list=tickets_list go_to_id="tickets" %} + {% endif %}
    {% endblock %} diff --git a/tickets/views.py b/tickets/views.py index 7a86ecf4..e5dd14a5 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -5,6 +5,11 @@ from django.urls import reverse from django.forms import modelformset_factory from re2o.views import form +from re2o.base import ( + re2o_paginator, +) + +from preferences.models import GeneralOption from .models import( Ticket, Preferences, @@ -56,10 +61,20 @@ def aff_ticket(request,ticketid): def aff_tickets(request): """ Vue d'affichage de tout les tickets """ - tickets = Ticket.objects.all().order_by('-date') - last_ticket_date = tickets.first().date - nbr_tickets = tickets.count() - nbr_tickets_unsolved = Ticket.objects.filter(solved=False).count() + tickets_list = Ticket.objects.all().order_by('-date') + last_ticket_date = tickets_list.first().date + nbr_tickets = tickets_list.count() + nbr_tickets_unsolved = tickets_list.filter(solved=False).count() + + pagination_number = (GeneralOption + .get_cached_value('pagination_number')) + + tickets = re2o_paginator( + request, + tickets_list, + pagination_number, + ) + context = {'tickets_list':tickets, 'last_ticket_date':last_ticket_date, 'nbr_tickets':nbr_tickets, From 02a4305cbd9fa8cee4f97cc3ad2400b9e3e68f7d Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 08:12:49 +0000 Subject: [PATCH 20/42] regle l'affichage sur le profil --- tickets/views.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tickets/views.py b/tickets/views.py index e5dd14a5..b4111204 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -103,8 +103,24 @@ def edit_preferences(request): # views cannoniques des apps optionnels def profil(request,user): """ Vue cannonique d'affichage des tickets dans l'accordeon du profil""" - tickets = Ticket.objects.filter(user=user).all().order_by('-date') - context = {'tickets_list':tickets} + tickets_list = Ticket.objects.filter(user=user).all().order_by('-date') + last_ticket_date = tickets_list.first().date + nbr_tickets = tickets_list.count() + nbr_tickets_unsolved = tickets_list.filter(solved=False).count() + + pagination_number = (GeneralOption + .get_cached_value('pagination_large_number')) + + tickets = re2o_paginator( + request, + tickets_list, + pagination_number, + ) + + context = {'tickets_list':tickets, + 'last_ticket_date':last_ticket_date, + 'nbr_tickets':nbr_tickets, + 'nbr_tickets_unsolved':nbr_tickets_unsolved} return render_to_string('tickets/profil.html', context=context, request=request, using=None) def preferences(request): From 84ab2b0cbdd4d7e7af8a53b9d14abd34ffa63900 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 08:21:24 +0000 Subject: [PATCH 21/42] Titre moche --- tickets/templates/tickets/aff_tickets.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 401d1c3c..56dda782 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load i18n %} -{% block title %}{% trans "Tickets" %}{% endblock %} - {% block content %} From f112cf3305b091fe2a30c54ff57838e33cee9b7f Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 08:53:52 +0000 Subject: [PATCH 22/42] liens des profils dans la liste des tickets --- tickets/templates/tickets/aff_tickets.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index 56dda782..ed9e1f88 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -64,7 +64,11 @@ with this program; if not, write to the Free Software Foundation, Inc., - {{ ticket.user }} + {% if ticket.user %} + {{ ticket.user.id }} + {% else %} + Anonyme + {% endif %} {{ ticket.title }} {{ ticket.date }} {% if ticket.solved %} From 9fa82776cfd22e3aa6ceba92d1d2fa8f006bf618 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 09:45:13 +0000 Subject: [PATCH 23/42] =?UTF-8?q?Envoit=20de=20mail=20=C3=A0=20l'ouverture?= =?UTF-8?q?=20des=20tickets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tickets/models.py | 23 ++++++++++++++++------ tickets/templates/tickets/publication_mail | 12 +++++++++++ tickets/views.py | 4 ++-- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 tickets/templates/tickets/publication_mail diff --git a/tickets/models.py b/tickets/models.py index df1cd8ac..6af24c4c 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -2,6 +2,8 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from django.core.mail import send_mail from django.template import Context, loader +from django.db.models.signals import post_save +from django.dispatch import receiver import users.models @@ -46,21 +48,30 @@ class Ticket(models.Model): return "Ticket de {} date: {}".format(self.user.surname,self.date) def publish_mail(self): - template = loader.get_template('ticket/mail_publish_ticket') + to_addr = Preferences.objects.first().publish_address + template = loader.get_template('tickets/publication_mail') context = Context({'ticket':self}) send_mail( 'Nouvelle ouverture de ticket', - '', - 'ticket_app_re2o@crans.org', - '', - html_message=template.render(context)) + template.render(context), + 'grisel-davy@crans.org', + [to_addr], + fail_silently = False) class Preferences(models.Model): """ Class cannonique définissants les préférences des tickets """ - + publish_address = models.EmailField( help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), max_length = 1000, null = True) class Meta: verbose_name = _("Préférences des tickets") + + +@receiver(post_save, sender=Ticket) +def ticket_post_save(**kwargs): + """Envoit du mail de publication du ticket""" + if Preferences.objects.first().publish_address: + ticket = kwargs['instance'] + ticket.publish_mail() diff --git a/tickets/templates/tickets/publication_mail b/tickets/templates/tickets/publication_mail new file mode 100644 index 00000000..f68c729d --- /dev/null +++ b/tickets/templates/tickets/publication_mail @@ -0,0 +1,12 @@ +{% if ticket.user %} +{{ ticket.user.get_full_name }} à ouvert un ticket. +Répondre à l'adresse: {{ticket.user.get_mail}}. + +{% else %} +Un utilisateur anonyme (non connecté) à ouvert un ticket. +Répondre à l'adresse: {{ticket.email}}. +{% endif %} + +Titre: {{ticket.title}} + +Description: {{ticket.description}} diff --git a/tickets/views.py b/tickets/views.py index b4111204..f75b1766 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -36,11 +36,11 @@ def new_ticket(request): if request.user.is_authenticated: ticket.user = request.user ticket.save() - messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') + messages.success(request,'Votre ticket a été ouvert. Nous vous répondrons le plus rapidement possible.') return redirect(reverse('users:profil',kwargs={'userid':str(request.user.id)})) if not request.user.is_authenticated and email != "": ticket.save() - messages.success(request,'Votre ticket à été ouvert. Nous vous répondront le plus rapidement possible.') + messages.success(request,'Votre ticket a été ouvert. Nous vous répondront le plus rapidement possible.') return redirect(reverse('index')) else: messages.error(request,"Vous n'êtes pas authentifié, veuillez vous authentifier ou fournir une adresse mail pour que nous puissions vous recontacter") From 6440ac48e86ee8aaf5d74e9cb8cf58b1e047e2d0 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 17:25:21 +0000 Subject: [PATCH 24/42] =?UTF-8?q?Inclusion=20des=20apps=20optionnels=20dan?= =?UTF-8?q?s=20le=20navbar=20(je=20sais=20pas=20trop=20pourquoi=20=C3=A7a?= =?UTF-8?q?=20marche=20=C3=A7a=20risque=20de=20casser)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- re2o/context_processors.py | 10 +++++++++- re2o/settings.py | 1 + templates/base.html | 6 +++--- tickets/views.py | 5 +++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/re2o/context_processors.py b/re2o/context_processors.py index 6beac564..739f4ab8 100644 --- a/re2o/context_processors.py +++ b/re2o/context_processors.py @@ -29,7 +29,8 @@ from django.contrib import messages from django.http import HttpRequest from preferences.models import GeneralOption, OptionalMachine from django.utils.translation import get_language - +from importlib import import_module +from re2o.settings_local import OPTIONNAL_APPS def context_user(request): """Fonction de context lorsqu'un user est logué (ou non), @@ -57,6 +58,13 @@ def context_user(request): 'ipv6_enabled': OptionalMachine.get_cached_value('ipv6'), } +def context_optionnal_apps(request): + """Fonction de context pour générer la navbar en fonction des + apps optionnels""" + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_templates_navbar_list = [app.views.navbar(request) for app in optionnal_apps] + return {'optionnal_templates_navbar_list':optionnal_templates_navbar_list} + def date_now(request): """Add the current date in the context for quick informations and diff --git a/re2o/settings.py b/re2o/settings.py index 14907570..ee219cfa 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -132,6 +132,7 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.request', 're2o.context_processors.context_user', + 're2o.context_processors.context_optionnal_apps', 're2o.context_processors.date_now', ], }, diff --git a/templates/base.html b/templates/base.html index 6d39f8c8..67799c28 100644 --- a/templates/base.html +++ b/templates/base.html @@ -101,9 +101,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
  • {% trans "Manage the subscriptions" %}
  • {% acl_end %} - {% comment %} -
  • {% trans "Tickets" %}
  • - {% endcomment %} + {% for template in optionnal_templates_navbar_list%} + {{ template }} + {% endfor %} {% acl_end %} diff --git a/tickets/views.py b/tickets/views.py index f75b1766..e4ffda89 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,6 +1,7 @@ from django.contrib import messages from django.shortcuts import render, redirect from django.template.loader import render_to_string +from django.views.decorators.cache import cache_page from django.urls import reverse from django.forms import modelformset_factory from re2o.views import form @@ -128,3 +129,7 @@ def preferences(request): preferences = Preferences.objects.first() context = {'preferences':preferences} return render_to_string('tickets/preferences.html', context=context, request=request, using=None) + +def navbar(request): + """Vue cannonique d'affichage des tickets dans la navbar""" + return render_to_string('tickets/navbar.html') From 295f7fa5fa65afb1b9454e0e0d9c83f1b2a98cf5 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sat, 10 Aug 2019 22:41:33 +0000 Subject: [PATCH 25/42] Pas d'envoit de mail pour les updates --- tickets/models.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tickets/models.py b/tickets/models.py index 6af24c4c..85857a1f 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -72,6 +72,7 @@ class Preferences(models.Model): @receiver(post_save, sender=Ticket) def ticket_post_save(**kwargs): """Envoit du mail de publication du ticket""" - if Preferences.objects.first().publish_address: - ticket = kwargs['instance'] - ticket.publish_mail() + if kwargs['created']: + if Preferences.objects.first().publish_address: + ticket = kwargs['instance'] + ticket.publish_mail() From 81d2bf233abdcbe3c548f5625920801b43b3d195 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 09:03:47 +0000 Subject: [PATCH 26/42] =?UTF-8?q?Envoit=20du=20mail=20avec=20l'adresse=20s?= =?UTF-8?q?p=C3=A9cifi=C3=A9e=20dans=20les=20preferences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tickets/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tickets/models.py b/tickets/models.py index 85857a1f..ff609437 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -5,6 +5,8 @@ from django.template import Context, loader from django.db.models.signals import post_save from django.dispatch import receiver +from preferences.models import GeneralOption + import users.models class Ticket(models.Model): @@ -54,7 +56,7 @@ class Ticket(models.Model): send_mail( 'Nouvelle ouverture de ticket', template.render(context), - 'grisel-davy@crans.org', + GeneralOption.get_cached_value('email_from'), [to_addr], fail_silently = False) From 18a97caa567debf754112a69646090d15bb80ecb Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 09:50:37 +0000 Subject: [PATCH 27/42] Changement de noms et commit du template --- re2o/context_processors.py | 2 +- tickets/templates/tickets/navbar.html | 2 ++ tickets/views.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 tickets/templates/tickets/navbar.html diff --git a/re2o/context_processors.py b/re2o/context_processors.py index 739f4ab8..ad7194cf 100644 --- a/re2o/context_processors.py +++ b/re2o/context_processors.py @@ -62,7 +62,7 @@ def context_optionnal_apps(request): """Fonction de context pour générer la navbar en fonction des apps optionnels""" optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] - optionnal_templates_navbar_list = [app.views.navbar(request) for app in optionnal_apps] + optionnal_templates_navbar_list = [app.views.navbar_user(request) for app in optionnal_apps] return {'optionnal_templates_navbar_list':optionnal_templates_navbar_list} diff --git a/tickets/templates/tickets/navbar.html b/tickets/templates/tickets/navbar.html new file mode 100644 index 00000000..3c4318f7 --- /dev/null +++ b/tickets/templates/tickets/navbar.html @@ -0,0 +1,2 @@ +{% load i18n %} +
  • {% trans "Tickets" %}
  • diff --git a/tickets/views.py b/tickets/views.py index e4ffda89..be7cc270 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -130,6 +130,6 @@ def preferences(request): context = {'preferences':preferences} return render_to_string('tickets/preferences.html', context=context, request=request, using=None) -def navbar(request): +def navbar_user(request): """Vue cannonique d'affichage des tickets dans la navbar""" return render_to_string('tickets/navbar.html') From 0596df673f26e460637aa0a986737d6e952453fa Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 13:06:56 +0000 Subject: [PATCH 28/42] Correction d'une erreure si aucun ticket et creation des acls --- tickets/models.py | 24 +++++++++++++++++++++++- tickets/views.py | 26 ++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/tickets/models.py b/tickets/models.py index ff609437..9cdb334b 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -5,11 +5,13 @@ from django.template import Context, loader from django.db.models.signals import post_save from django.dispatch import receiver +from re2o.mixins import AclMixin + from preferences.models import GeneralOption import users.models -class Ticket(models.Model): +class Ticket(AclMixin, models.Model): """Class définissant un ticket""" user = models.ForeignKey( @@ -59,6 +61,26 @@ class Ticket(models.Model): GeneralOption.get_cached_value('email_from'), [to_addr], fail_silently = False) + + def can_view(self, user_request, *_args, **_kwargs): + """Verifie que la personne à le droit pour voir le ticket + ou qu'elle est l'auteur du ticket""" + if (not user_request.has_perm('tickets.view_ticket') and self.user != user_request): + return False, _("You don't have the right to view other Tickets than yours.") + else: + return True, None + + @staticmethod + def can_view_all(user_request, *_args, **_kwargs): + """Vérifie si l'user a acccés à la liste de tous les tickets""" + return( + user_request.has_perm('tickets.view_tickets'), + _("You don't have the right to view the list of tickets.") + ) + + def can_create(user_request,*_args, **_kwargs): + """Autorise tout les utilisateurs à créer des tickets""" + return True,None class Preferences(models.Model): """ Class cannonique définissants les préférences des tickets """ diff --git a/tickets/views.py b/tickets/views.py index be7cc270..a556efe3 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,4 +1,5 @@ from django.contrib import messages +from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect from django.template.loader import render_to_string from django.views.decorators.cache import cache_page @@ -10,6 +11,13 @@ from re2o.base import ( re2o_paginator, ) +from re2o.acl import( + can_view, + can_view_all, + can_edit, + can_create, +) + from preferences.models import GeneralOption from .models import( Ticket, @@ -51,6 +59,8 @@ def new_ticket(request): ticketform = NewTicketForm return form({'ticketform':ticketform,},'tickets/form_ticket.html',request) +@login_required +@can_view(Ticket) def aff_ticket(request,ticketid): """Vue d'affichage d'un ticket""" ticket = Ticket.objects.filter(id=ticketid).get() @@ -59,13 +69,18 @@ def aff_ticket(request,ticketid): ticket.solved = not ticket.solved ticket.save() return render(request,'tickets/aff_ticket.html',{'ticket':ticket,'changestatusform':changestatusform}) - + +@login_required +@can_view_all(Ticket) def aff_tickets(request): """ Vue d'affichage de tout les tickets """ tickets_list = Ticket.objects.all().order_by('-date') - last_ticket_date = tickets_list.first().date nbr_tickets = tickets_list.count() nbr_tickets_unsolved = tickets_list.filter(solved=False).count() + if nbr_tickets: + last_ticket_date = tickets_list.first().date + else: + last_ticket_date = "Jamais" pagination_number = (GeneralOption .get_cached_value('pagination_number')) @@ -105,10 +120,13 @@ def edit_preferences(request): def profil(request,user): """ Vue cannonique d'affichage des tickets dans l'accordeon du profil""" tickets_list = Ticket.objects.filter(user=user).all().order_by('-date') - last_ticket_date = tickets_list.first().date nbr_tickets = tickets_list.count() nbr_tickets_unsolved = tickets_list.filter(solved=False).count() - + if nbr_tickets: + last_ticket_date = tickets_list.first().date + else: + last_ticket_date = "Jamais" + pagination_number = (GeneralOption .get_cached_value('pagination_large_number')) From a42624d0d9db8094add7728fc65053b703f31d0d Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 14:01:44 +0000 Subject: [PATCH 29/42] Acl pour le visualisation des tickets --- tickets/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tickets/views.py b/tickets/views.py index a556efe3..52b4f68f 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -61,9 +61,8 @@ def new_ticket(request): @login_required @can_view(Ticket) -def aff_ticket(request,ticketid): +def aff_ticket(request, ticket, ticketid): """Vue d'affichage d'un ticket""" - ticket = Ticket.objects.filter(id=ticketid).get() changestatusform = ChangeStatusTicketForm(request.POST) if request.method == 'POST': ticket.solved = not ticket.solved @@ -98,6 +97,7 @@ def aff_tickets(request): return render(request,'tickets/index.html',context=context) + def edit_preferences(request): """ Vue d'édition des préférences des tickets """ From a0dcda697542a136358bef52a202f79a7cb3d1b9 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 16:03:45 +0000 Subject: [PATCH 30/42] Vues cannoniques navbar et adresses de contact --- re2o/context_processors.py | 6 ++++-- re2o/templates/re2o/contact.html | 4 ++++ re2o/views.py | 8 +++++++- templates/base.html | 5 ++++- tickets/templates/tickets/contact.html | 13 +++++++++++++ tickets/templates/tickets/navbar_logout.html | 6 ++++++ tickets/views.py | 12 +++++++++++- 7 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tickets/templates/tickets/contact.html create mode 100644 tickets/templates/tickets/navbar_logout.html diff --git a/re2o/context_processors.py b/re2o/context_processors.py index ad7194cf..860a5a58 100644 --- a/re2o/context_processors.py +++ b/re2o/context_processors.py @@ -62,8 +62,10 @@ def context_optionnal_apps(request): """Fonction de context pour générer la navbar en fonction des apps optionnels""" optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] - optionnal_templates_navbar_list = [app.views.navbar_user(request) for app in optionnal_apps] - return {'optionnal_templates_navbar_list':optionnal_templates_navbar_list} + optionnal_templates_navbar_user_list = [app.views.navbar_user(request) for app in optionnal_apps] + optionnal_templates_navbar_logout_list = [app.views.navbar_logout(request) for app in optionnal_apps] + return {'optionnal_templates_navbar_user_list':optionnal_templates_navbar_user_list, + 'optionnal_templates_navbar_logout_list':optionnal_templates_navbar_logout_list} def date_now(request): diff --git a/re2o/templates/re2o/contact.html b/re2o/templates/re2o/contact.html index b20fe875..05b34655 100644 --- a/re2o/templates/re2o/contact.html +++ b/re2o/templates/re2o/contact.html @@ -31,6 +31,10 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block content %}

    {% blocktrans %}Contact the organisation {{asso_name}}{% endblocktrans %}


    + +{% for template in optionnal_templates_contact_list %} + {{template}} +{% endfor %} {% for contact in contacts %} diff --git a/re2o/views.py b/re2o/views.py index aa85e997..c4c8b72e 100644 --- a/re2o/views.py +++ b/re2o/views.py @@ -43,6 +43,8 @@ from preferences.models import ( ) from .contributors import CONTRIBUTORS +from importlib import import_module +from re2o.settings_local import OPTIONNAL_APPS def form(ctx, template, request): @@ -113,12 +115,16 @@ def contact_page(request): """ address = MailContact.objects.all() + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_templates_contact_list = [app.views.contact(request) for app in optionnal_apps] + return render( request, "re2o/contact.html", { 'contacts': address, - 'asso_name': AssoOption.objects.first().name + 'asso_name': AssoOption.objects.first().name, + 'optionnal_templates_contact_list':optionnal_templates_contact_list, } ) diff --git a/templates/base.html b/templates/base.html index 67799c28..de6f308c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -101,7 +101,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
  • {% trans "Manage the subscriptions" %}
  • {% acl_end %} - {% for template in optionnal_templates_navbar_list%} + {% for template in optionnal_templates_navbar_user_list%} {{ template }} {% endfor %} @@ -140,6 +140,9 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if not request.user.is_authenticated %} + {% for template in optionnal_templates_navbar_logout_list %} + {{ template }} + {% endfor %} {% if var_sa %}
  • diff --git a/tickets/templates/tickets/contact.html b/tickets/templates/tickets/contact.html new file mode 100644 index 00000000..0a348f01 --- /dev/null +++ b/tickets/templates/tickets/contact.html @@ -0,0 +1,13 @@ +{% load i18n %} + + diff --git a/tickets/templates/tickets/navbar_logout.html b/tickets/templates/tickets/navbar_logout.html new file mode 100644 index 00000000..8a7114f3 --- /dev/null +++ b/tickets/templates/tickets/navbar_logout.html @@ -0,0 +1,6 @@ +{% load i18n %} +
  • + + {% trans "Ouvrir un ticket" %} + +
  • diff --git a/tickets/views.py b/tickets/views.py index 52b4f68f..26dce0cd 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -148,6 +148,16 @@ def preferences(request): context = {'preferences':preferences} return render_to_string('tickets/preferences.html', context=context, request=request, using=None) +def contact(request): + """Vue cannonique d'affichage d'une adresse dans la page contact. + Utilisée ici pour proposer l'ouverture d'un ticket""" + return render_to_string('tickets/contact.html') + def navbar_user(request): """Vue cannonique d'affichage des tickets dans la navbar""" - return render_to_string('tickets/navbar.html') + return render_to_string('tickets/navbar.html') + +def navbar_logout(request): + """Vue cannonique d'affichage du lien de creation de ticket + lorsque l'utilisateur est déconnecté dans la navbar""" + return render_to_string('tickets/navbar_logout.html') From 3a5fad0287b5bc605e8984c6c4a7301f3df42c58 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Sun, 11 Aug 2019 19:51:31 +0000 Subject: [PATCH 31/42] =?UTF-8?q?Separation=20des=20lists=20d'apps=20optio?= =?UTF-8?q?nnelles=20pour=20eviter=20les=20erreurs=20d'import=20d'urls=20n?= =?UTF-8?q?on=20pr=C3=A9sents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- preferences/views.py | 4 ++-- re2o/context_processors.py | 4 ++-- re2o/settings_local.example.py | 5 ++++- re2o/urls.py | 4 ++-- re2o/views.py | 4 ++-- users/views.py | 4 ++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/preferences/views.py b/preferences/views.py index 680fcac0..471207e0 100644 --- a/preferences/views.py +++ b/preferences/views.py @@ -41,7 +41,7 @@ from django.utils.translation import ugettext as _ from reversion import revisions as reversion from importlib import import_module -from re2o.settings_local import OPTIONNAL_APPS +from re2o.settings_local import OPTIONNAL_APPS_RE2O from re2o.views import form from re2o.acl import can_create, can_edit, can_delete_set, can_view_all, can_delete @@ -97,7 +97,7 @@ def display_options(request): cotisationsoptions, _created = CotisationsOption.objects.get_or_create() document_template_list = DocumentTemplate.objects.order_by('name') - optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O] optionnal_templates_list = [app.views.preferences(request) for app in optionnal_apps] return form({ diff --git a/re2o/context_processors.py b/re2o/context_processors.py index 860a5a58..67a700be 100644 --- a/re2o/context_processors.py +++ b/re2o/context_processors.py @@ -30,7 +30,7 @@ from django.http import HttpRequest from preferences.models import GeneralOption, OptionalMachine from django.utils.translation import get_language from importlib import import_module -from re2o.settings_local import OPTIONNAL_APPS +from re2o.settings_local import OPTIONNAL_APPS_RE2O def context_user(request): """Fonction de context lorsqu'un user est logué (ou non), @@ -61,7 +61,7 @@ def context_user(request): def context_optionnal_apps(request): """Fonction de context pour générer la navbar en fonction des apps optionnels""" - optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O] optionnal_templates_navbar_user_list = [app.views.navbar_user(request) for app in optionnal_apps] optionnal_templates_navbar_logout_list = [app.views.navbar_logout(request) for app in optionnal_apps] return {'optionnal_templates_navbar_user_list':optionnal_templates_navbar_user_list, diff --git a/re2o/settings_local.example.py b/re2o/settings_local.example.py index 662c1447..bb0fd21e 100644 --- a/re2o/settings_local.example.py +++ b/re2o/settings_local.example.py @@ -108,5 +108,8 @@ GID_RANGES = { 'posix': [501, 600], } +# Some optionnal Re2o Apps +OPTIONNAL_APPS_RE2O = () + # Some Django apps you want to add in you local project -OPTIONNAL_APPS = () +OPTIONNAL_APPS = OPTIONNAL_APPS_RE2O + () diff --git a/re2o/urls.py b/re2o/urls.py index 5db9abe8..8af7335a 100644 --- a/re2o/urls.py +++ b/re2o/urls.py @@ -49,7 +49,7 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ from django.views.generic import RedirectView -from .settings_local import OPTIONNAL_APPS +from .settings_local import OPTIONNAL_APPS_RE2O from .views import index, about_page, contact_page @@ -87,7 +87,7 @@ urlpatterns = [ ] -urlpatterns += [url(r'^{}/'.format(app), include('{}.urls'.format(app), namespace=app)) for app in OPTIONNAL_APPS] +urlpatterns += [url(r'^{}/'.format(app), include('{}.urls'.format(app), namespace=app)) for app in OPTIONNAL_APPS_RE2O] # Add debug_toolbar URLs if activated if 'debug_toolbar' in settings.INSTALLED_APPS: diff --git a/re2o/views.py b/re2o/views.py index c4c8b72e..17622fd5 100644 --- a/re2o/views.py +++ b/re2o/views.py @@ -44,7 +44,7 @@ from preferences.models import ( from .contributors import CONTRIBUTORS from importlib import import_module -from re2o.settings_local import OPTIONNAL_APPS +from re2o.settings_local import OPTIONNAL_APPS_RE2O def form(ctx, template, request): @@ -115,7 +115,7 @@ def contact_page(request): """ address = MailContact.objects.all() - optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O] optionnal_templates_contact_list = [app.views.contact(request) for app in optionnal_apps] return render( diff --git a/users/views.py b/users/views.py index 426645e5..045446b1 100644 --- a/users/views.py +++ b/users/views.py @@ -57,7 +57,7 @@ from machines.models import Machine from preferences.models import OptionalUser, GeneralOption, AssoOption from importlib import import_module -from re2o.settings_local import OPTIONNAL_APPS +from re2o.settings_local import OPTIONNAL_APPS_RE2O from re2o.views import form from re2o.utils import ( all_has_access, @@ -979,7 +979,7 @@ def profil(request, users, **_kwargs): SortTable.MACHINES_INDEX ) - optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS] + optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O] optionnal_templates_list = [app.views.profil(request,users) for app in optionnal_apps] pagination_large_number = GeneralOption.get_cached_value( From cb3fdff202f601c26be58637e2bcfcaba0b9e007 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Tue, 13 Aug 2019 13:05:12 +0000 Subject: [PATCH 32/42] =?UTF-8?q?r=C3=A9partition=20des=20preferences=20et?= =?UTF-8?q?=20squash=20des=20migrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tickets/forms.py | 5 +- ...0008_remove_preferences_publish_tickets.py | 48 +++++++++++++++++++ tickets/models.py | 5 +- tickets/preferences/forms.py | 11 +++++ tickets/preferences/models.py | 12 +++++ tickets/views.py | 8 ++++ 6 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 tickets/migrations/0001_squashed_0008_remove_preferences_publish_tickets.py create mode 100644 tickets/preferences/forms.py create mode 100644 tickets/preferences/models.py diff --git a/tickets/forms.py b/tickets/forms.py index 4bb59458..5e565cc7 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -6,7 +6,6 @@ from django.utils.translation import ugettext_lazy as _ from .models import( Ticket, - Preferences, ) class EditTicketForm(FormRevMixin, ModelForm): @@ -22,12 +21,12 @@ class NewTicketForm(ModelForm): class Meta: model = Ticket fields = ['title', 'description', 'email'] - +""" class EditPreferencesForm(ModelForm): - """ Edition des préférences des tickets """ class Meta: model = Preferences fields = '__all__' +""" class ChangeStatusTicketForm(ModelForm): """ Passe un Ticket en résolu """ diff --git a/tickets/migrations/0001_squashed_0008_remove_preferences_publish_tickets.py b/tickets/migrations/0001_squashed_0008_remove_preferences_publish_tickets.py new file mode 100644 index 00000000..2b42726e --- /dev/null +++ b/tickets/migrations/0001_squashed_0008_remove_preferences_publish_tickets.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2019-08-13 12:55 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + replaces = [('tickets', '0001_initial'), ('tickets', '0002_auto_20190710_0952'), ('tickets', '0003_ticket_email'), ('tickets', '0004_auto_20190712_1205'), ('tickets', '0005_auto_20190712_1209'), ('tickets', '0006_preferences'), ('tickets', '0007_preferences_publish_tickets'), ('tickets', '0008_remove_preferences_publish_tickets')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(help_text='Nom du ticket', max_length=255)), + ('description', models.TextField(help_text='Description du ticket', max_length=3000)), + ('date', models.DateTimeField(auto_now_add=True)), + ('solved', models.BooleanField(default=False)), + ('assigned_staff', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets_assigned', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to=settings.AUTH_USER_MODEL)), + ('email', models.EmailField(help_text='Une adresse mail pour vous recontacter', max_length=100, null=True)), + ], + options={ + 'verbose_name_plural': 'Tickets', + 'verbose_name': 'Ticket', + }, + ), + migrations.CreateModel( + name='Preferences', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('publish_address', models.EmailField(help_text='Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)', max_length=1000, null=True)), + ], + options={ + 'verbose_name': 'Préférences des tickets', + }, + ), + ] diff --git a/tickets/models.py b/tickets/models.py index 9cdb334b..ed446064 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -81,9 +81,8 @@ class Ticket(AclMixin, models.Model): def can_create(user_request,*_args, **_kwargs): """Autorise tout les utilisateurs à créer des tickets""" return True,None - +""" class Preferences(models.Model): - """ Class cannonique définissants les préférences des tickets """ publish_address = models.EmailField( help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), @@ -91,7 +90,7 @@ class Preferences(models.Model): null = True) class Meta: verbose_name = _("Préférences des tickets") - +""" @receiver(post_save, sender=Ticket) def ticket_post_save(**kwargs): diff --git a/tickets/preferences/forms.py b/tickets/preferences/forms.py new file mode 100644 index 00000000..9aa7319e --- /dev/null +++ b/tickets/preferences/forms.py @@ -0,0 +1,11 @@ +from django import forms +from django.forms import ModelForm, Form +from django.utils.translation import ugettext_lazy as _ + +from .models import Preferences + +class EditPreferencesForm(ModelForm): + """ Edition des préférences des tickets """ + class Meta: + model = Preferences + fields = '__all__' diff --git a/tickets/preferences/models.py b/tickets/preferences/models.py new file mode 100644 index 00000000..62a98a09 --- /dev/null +++ b/tickets/preferences/models.py @@ -0,0 +1,12 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +class Preferences(models.Model): + """ Class cannonique définissants les préférences des tickets """ + + publish_address = models.EmailField( + help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), + max_length = 1000, + null = True) + class Meta: + verbose_name = _("Préférences des tickets") diff --git a/tickets/views.py b/tickets/views.py index 26dce0cd..b09ef3e4 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -19,18 +19,26 @@ from re2o.acl import( ) from preferences.models import GeneralOption + from .models import( Ticket, +) + +from .preferences.models import( Preferences, ) from .forms import ( NewTicketForm, ChangeStatusTicketForm, +) + +from .preferences.forms import ( EditPreferencesForm, ) + def new_ticket(request): """ Vue de création d'un ticket """ ticketform = NewTicketForm(request.POST or None) From 19f4fdbf97876e0b2514dc3124dccd33335c2ee8 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 14 Aug 2019 15:09:46 +0000 Subject: [PATCH 33/42] Ajout d'un lien vers le profil dans le mail --- tickets/models.py | 10 ++++++++-- tickets/templates/tickets/publication_mail | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tickets/models.py b/tickets/models.py index ed446064..5ec2e544 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -11,6 +11,8 @@ from preferences.models import GeneralOption import users.models +from .preferences.models import Preferences + class Ticket(AclMixin, models.Model): """Class définissant un ticket""" @@ -49,12 +51,16 @@ class Ticket(AclMixin, models.Model): verbose_name_plural = _("Tickets") def __str__(self): - return "Ticket de {} date: {}".format(self.user.surname,self.date) + if self.user: + return "Ticket de {}. Date: {}".format(self.user.surname,self.date) + else: + return "Ticket anonyme. Date: {}".format(self.date) def publish_mail(self): + site_url = GeneralOption.objects.first().main_site_url to_addr = Preferences.objects.first().publish_address template = loader.get_template('tickets/publication_mail') - context = Context({'ticket':self}) + context = Context({'ticket':self,'site_url':site_url}) send_mail( 'Nouvelle ouverture de ticket', template.render(context), diff --git a/tickets/templates/tickets/publication_mail b/tickets/templates/tickets/publication_mail index f68c729d..1f3752be 100644 --- a/tickets/templates/tickets/publication_mail +++ b/tickets/templates/tickets/publication_mail @@ -1,5 +1,5 @@ -{% if ticket.user %} -{{ ticket.user.get_full_name }} à ouvert un ticket. +{% if ticket.user %} {{ ticket.user.get_full_name }} à ouvert un ticket. +Profile: {{site_url}}{% url 'users:profil' ticket.user.id%} Répondre à l'adresse: {{ticket.user.get_mail}}. {% else %} From d59783fd6bfd4c2afd07c3411dc7abbea0590629 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 14 Aug 2019 17:07:31 +0000 Subject: [PATCH 34/42] Affichage du nom et pas de l'id --- tickets/templates/tickets/aff_tickets.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tickets/templates/tickets/aff_tickets.html b/tickets/templates/tickets/aff_tickets.html index ed9e1f88..6bb062fb 100644 --- a/tickets/templates/tickets/aff_tickets.html +++ b/tickets/templates/tickets/aff_tickets.html @@ -65,7 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if ticket.user %} - {{ ticket.user.id }} + {{ ticket.user.get_short_name }} {% else %} Anonyme {% endif %} From 0f203f43e46b5178f15bb4ebeb2df133916e9ae2 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 14 Aug 2019 17:39:19 +0000 Subject: [PATCH 35/42] La doc en anglais et le commentaires en moins --- tickets/forms.py | 16 ++-------- tickets/models.py | 41 +++++++----------------- tickets/preferences/forms.py | 2 +- tickets/preferences/models.py | 6 ++-- tickets/views.py | 60 +++++++++++++++++++++++++---------- 5 files changed, 61 insertions(+), 64 deletions(-) diff --git a/tickets/forms.py b/tickets/forms.py index 5e565cc7..bbeea0c4 100644 --- a/tickets/forms.py +++ b/tickets/forms.py @@ -8,28 +8,16 @@ from .models import( Ticket, ) -class EditTicketForm(FormRevMixin, ModelForm): - """Formulaire d'edition d'un Ticket""" - class Meta: - model = Ticket - exclude = ['user','assigned_staff','date'] - class NewTicketForm(ModelForm): - """ Creation d'une machine""" + """ Creation of a ticket""" email = forms.EmailField(required=False) class Meta: model = Ticket fields = ['title', 'description', 'email'] -""" -class EditPreferencesForm(ModelForm): - class Meta: - model = Preferences - fields = '__all__' -""" class ChangeStatusTicketForm(ModelForm): - """ Passe un Ticket en résolu """ + """ Change ticket status""" class Meta: model = Ticket fields = [] diff --git a/tickets/models.py b/tickets/models.py index 5ec2e544..9c21fb74 100644 --- a/tickets/models.py +++ b/tickets/models.py @@ -14,7 +14,7 @@ import users.models from .preferences.models import Preferences class Ticket(AclMixin, models.Model): - """Class définissant un ticket""" + """Model of a ticket""" user = models.ForeignKey( 'users.User', @@ -24,26 +24,19 @@ class Ticket(AclMixin, models.Model): null=True) title = models.CharField( max_length=255, - help_text=_("Nom du ticket"), + help_text=_("Title of the ticket"), blank=False, null=False,) description = models.TextField( max_length=3000, - help_text=_("Description du ticket"), + help_text=_("Description of the ticket"), blank=False, null=False) date = models.DateTimeField(auto_now_add=True) email = models.EmailField( - help_text = _("Une adresse mail pour vous recontacter"), + help_text = _("An email address to get back to you"), max_length=100, null=True) - assigned_staff = models.ForeignKey( - 'users.User', - on_delete=models.PROTECT, - related_name="tickets_assigned", - blank=True, - null=True) - #categories = models.OneToManyFiled('Category') solved = models.BooleanField(default=False) class Meta: @@ -52,9 +45,9 @@ class Ticket(AclMixin, models.Model): def __str__(self): if self.user: - return "Ticket de {}. Date: {}".format(self.user.surname,self.date) + return "Ticket from {}. Date: {}".format(self.user.surname,self.date) else: - return "Ticket anonyme. Date: {}".format(self.date) + return "Anonymous Ticket. Date: {}".format(self.date) def publish_mail(self): site_url = GeneralOption.objects.first().main_site_url @@ -69,38 +62,28 @@ class Ticket(AclMixin, models.Model): fail_silently = False) def can_view(self, user_request, *_args, **_kwargs): - """Verifie que la personne à le droit pour voir le ticket - ou qu'elle est l'auteur du ticket""" + """ Check that the user has the right to view the ticket + or that it is the author""" if (not user_request.has_perm('tickets.view_ticket') and self.user != user_request): - return False, _("You don't have the right to view other Tickets than yours.") + return False, _("You don't have the right to view other tickets than yours.") else: return True, None @staticmethod def can_view_all(user_request, *_args, **_kwargs): - """Vérifie si l'user a acccés à la liste de tous les tickets""" + """ Check that the user has access to the list of all tickets""" return( user_request.has_perm('tickets.view_tickets'), _("You don't have the right to view the list of tickets.") ) def can_create(user_request,*_args, **_kwargs): - """Autorise tout les utilisateurs à créer des tickets""" + """ Authorise all users to open tickets """ return True,None -""" -class Preferences(models.Model): - - publish_address = models.EmailField( - help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), - max_length = 1000, - null = True) - class Meta: - verbose_name = _("Préférences des tickets") -""" @receiver(post_save, sender=Ticket) def ticket_post_save(**kwargs): - """Envoit du mail de publication du ticket""" + """ Send the mail to publish the new ticket """ if kwargs['created']: if Preferences.objects.first().publish_address: ticket = kwargs['instance'] diff --git a/tickets/preferences/forms.py b/tickets/preferences/forms.py index 9aa7319e..5bdc65d2 100644 --- a/tickets/preferences/forms.py +++ b/tickets/preferences/forms.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from .models import Preferences class EditPreferencesForm(ModelForm): - """ Edition des préférences des tickets """ + """ Edit the ticket's settings""" class Meta: model = Preferences fields = '__all__' diff --git a/tickets/preferences/models.py b/tickets/preferences/models.py index 62a98a09..684c192e 100644 --- a/tickets/preferences/models.py +++ b/tickets/preferences/models.py @@ -2,11 +2,11 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ class Preferences(models.Model): - """ Class cannonique définissants les préférences des tickets """ + """ Definition of the ticket's settings""" publish_address = models.EmailField( - help_text = _("Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)"), + help_text = _("Email address to publish the new tickets (leave empty for no publications)"), max_length = 1000, null = True) class Meta: - verbose_name = _("Préférences des tickets") + verbose_name = _("Ticket's settings") diff --git a/tickets/views.py b/tickets/views.py index b09ef3e4..26b5cad5 100644 --- a/tickets/views.py +++ b/tickets/views.py @@ -1,8 +1,36 @@ +# -*- mode: python; coding: utf-8 -*- +# Re2o est un logiciel d'administration développé initiallement au rezometz. Il +# se veut agnostique au réseau considéré, de manière à être installable en +# quelques clics. +# +# Copyright © 2017 Gabriel Détraz +# Copyright © 2017 Goulven Kermarec +# Copyright © 2017 Augustin Lemesle +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# App de gestion des users pour re2o +# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin +# Gplv2 + from django.contrib import messages from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect from django.template.loader import render_to_string from django.views.decorators.cache import cache_page +from django.utils.translation import ugettext as _ from django.urls import reverse from django.forms import modelformset_factory from re2o.views import form @@ -40,7 +68,7 @@ from .preferences.forms import ( def new_ticket(request): - """ Vue de création d'un ticket """ + """ Ticket creation view""" ticketform = NewTicketForm(request.POST or None) if request.method == 'POST': @@ -49,18 +77,17 @@ def new_ticket(request): if ticketform.is_valid(): email = ticketform.cleaned_data.get('email') ticket = ticketform.save(commit=False) - #raise ValueError("email: {} type: {}".format(email,type(email))) if request.user.is_authenticated: ticket.user = request.user ticket.save() - messages.success(request,'Votre ticket a été ouvert. Nous vous répondrons le plus rapidement possible.') + messages.success(request,_('Your ticket has been succesfully open. We will take care of it as soon as possible.')) return redirect(reverse('users:profil',kwargs={'userid':str(request.user.id)})) if not request.user.is_authenticated and email != "": ticket.save() - messages.success(request,'Votre ticket a été ouvert. Nous vous répondront le plus rapidement possible.') + messages.success(request,_('Your ticket has been succesfully open. We will take care of it as soon as possible.')) return redirect(reverse('index')) else: - messages.error(request,"Vous n'êtes pas authentifié, veuillez vous authentifier ou fournir une adresse mail pour que nous puissions vous recontacter") + messages.error(request,_("You are not authenticated. Please login or provide an email address so we can get back to you.")) return form({'ticketform':ticketform,},'tickets/form_ticket.html',request) else: @@ -70,7 +97,7 @@ def new_ticket(request): @login_required @can_view(Ticket) def aff_ticket(request, ticket, ticketid): - """Vue d'affichage d'un ticket""" + """View to display only one ticket""" changestatusform = ChangeStatusTicketForm(request.POST) if request.method == 'POST': ticket.solved = not ticket.solved @@ -80,14 +107,14 @@ def aff_ticket(request, ticket, ticketid): @login_required @can_view_all(Ticket) def aff_tickets(request): - """ Vue d'affichage de tout les tickets """ + """ View to display all the tickets """ tickets_list = Ticket.objects.all().order_by('-date') nbr_tickets = tickets_list.count() nbr_tickets_unsolved = tickets_list.filter(solved=False).count() if nbr_tickets: last_ticket_date = tickets_list.first().date else: - last_ticket_date = "Jamais" + last_ticket_date = _("Never") pagination_number = (GeneralOption .get_cached_value('pagination_number')) @@ -107,7 +134,7 @@ def aff_tickets(request): def edit_preferences(request): - """ Vue d'édition des préférences des tickets """ + """ View to edit the settings of the tickets """ preferences_instance, created = Preferences.objects.get_or_create(id=1) preferencesform = EditPreferencesForm( @@ -126,14 +153,14 @@ def edit_preferences(request): # views cannoniques des apps optionnels def profil(request,user): - """ Vue cannonique d'affichage des tickets dans l'accordeon du profil""" + """ View to display the ticket's module on the profil""" tickets_list = Ticket.objects.filter(user=user).all().order_by('-date') nbr_tickets = tickets_list.count() nbr_tickets_unsolved = tickets_list.filter(solved=False).count() if nbr_tickets: last_ticket_date = tickets_list.first().date else: - last_ticket_date = "Jamais" + last_ticket_date = _("Never") pagination_number = (GeneralOption .get_cached_value('pagination_large_number')) @@ -151,21 +178,20 @@ def profil(request,user): return render_to_string('tickets/profil.html', context=context, request=request, using=None) def preferences(request): - """ Vue cannonique d'affichage des tickets dans l'affichage du profil""" + """ View to display the settings of the tickets in the preferences page""" preferences = Preferences.objects.first() context = {'preferences':preferences} return render_to_string('tickets/preferences.html', context=context, request=request, using=None) def contact(request): - """Vue cannonique d'affichage d'une adresse dans la page contact. - Utilisée ici pour proposer l'ouverture d'un ticket""" + """View to display a contact address on the contact page + used here to display a link to open a ticket""" return render_to_string('tickets/contact.html') def navbar_user(request): - """Vue cannonique d'affichage des tickets dans la navbar""" + """View to display the ticket link in thet user's dropdown in the navbar""" return render_to_string('tickets/navbar.html') def navbar_logout(request): - """Vue cannonique d'affichage du lien de creation de ticket - lorsque l'utilisateur est déconnecté dans la navbar""" + """View to display the ticket link to log out users""" return render_to_string('tickets/navbar_logout.html') From 5e3fb3044196764a5332023b9145a4c172ef1314 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Wed, 14 Aug 2019 17:48:58 +0000 Subject: [PATCH 36/42] traduction --- tickets/templates/tickets/aff_ticket.html | 2 +- tickets/templates/tickets/contact.html | 2 +- tickets/templates/tickets/form_preferences.html | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tickets/templates/tickets/aff_ticket.html b/tickets/templates/tickets/aff_ticket.html index 7bf5b04d..ede878b3 100644 --- a/tickets/templates/tickets/aff_ticket.html +++ b/tickets/templates/tickets/aff_ticket.html @@ -51,7 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endif %} {{ ticket.date | naturalday}}. {% if not ticket.user %} - {% trans "Response address: " %}{{ticket.email}} + {% trans "Response address: " %}{{ticket.email}} {% endif %}
    diff --git a/tickets/templates/tickets/contact.html b/tickets/templates/tickets/contact.html index 0a348f01..475af26d 100644 --- a/tickets/templates/tickets/contact.html +++ b/tickets/templates/tickets/contact.html @@ -5,7 +5,7 @@
    - {% blocktrans %} Si vous rencontrez des problème concernant les services proposés par l'association {{ asso_name }}, il vous est possible d'ouvir un ticket qui sera traité par les membres actifs de l'association. Si vous souhaitez nous contacter pour une question autres qu'un problème technique, choisissez l'une des adresses mail ci-dessous. {% endblocktrans %} + {% blocktrans %}If you are experiencing issues with the services offered by {{asso_name}}, you can open a ticket that will be taken care of. If you want to contact us on any other topic, please choose one address below.{% endblocktrans %}
    diff --git a/tickets/templates/tickets/form_preferences.html b/tickets/templates/tickets/form_preferences.html index 83339484..03a6a333 100644 --- a/tickets/templates/tickets/form_preferences.html +++ b/tickets/templates/tickets/form_preferences.html @@ -25,13 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load bootstrap3 %} -{% load massive_bootstrap_form %} {% load i18n %} {% block title %}{% trans "Ticket" %}{% endblock %} {% block content %} -

    Edition des préférences des Tickets

    +

    {% trans "Tickets settings modification" %}

    {% for message in messages %}
    From 8e2e36c882c00e405d334e5e5c619f8ed93c9ad1 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Fri, 16 Aug 2019 13:43:32 +0000 Subject: [PATCH 37/42] =?UTF-8?q?migrations=20compress=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...uashed_0007_preferences_publish_tickets.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tickets/migrations/0001_squashed_0007_preferences_publish_tickets.py diff --git a/tickets/migrations/0001_squashed_0007_preferences_publish_tickets.py b/tickets/migrations/0001_squashed_0007_preferences_publish_tickets.py new file mode 100644 index 00000000..b2293a4a --- /dev/null +++ b/tickets/migrations/0001_squashed_0007_preferences_publish_tickets.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2019-08-16 13:41 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + replaces = [('tickets', '0001_initial'), ('tickets', '0002_auto_20190710_0952'), ('tickets', '0003_ticket_email'), ('tickets', '0004_auto_20190712_1205'), ('tickets', '0005_auto_20190712_1209'), ('tickets', '0006_preferences'), ('tickets', '0007_preferences_publish_tickets')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(help_text='Nom du ticket', max_length=255)), + ('description', models.TextField(help_text='Description du ticket', max_length=3000)), + ('date', models.DateTimeField(auto_now_add=True)), + ('solved', models.BooleanField(default=False)), + ('assigned_staff', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets_assigned', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to=settings.AUTH_USER_MODEL)), + ('email', models.EmailField(help_text='Une adresse mail pour vous recontacter', max_length=100, null=True)), + ], + options={ + 'verbose_name': 'Ticket', + 'verbose_name_plural': 'Tickets', + }, + ), + migrations.CreateModel( + name='Preferences', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('publish_address', models.EmailField(help_text='Adresse mail pour annoncer les nouveau tickets (laisser vide pour ne rien annoncer)', max_length=1000, null=True)), + ('publish_tickets', models.BooleanField(default=True, help_text='Publier ou pas les tickets')), + ], + options={ + 'verbose_name': 'Préférences des tickets', + }, + ), + ] From b0fb188e24b7e11bb018b1b8803c6b898c2486e0 Mon Sep 17 00:00:00 2001 From: Grizzly Date: Fri, 16 Aug 2019 14:13:20 +0000 Subject: [PATCH 38/42] =?UTF-8?q?menu=20deroulant=20et=20migrations=20supp?= =?UTF-8?q?rim=C3=A9e=20oubli=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/base.html | 2 +- ...0008_remove_preferences_publish_tickets.py | 48 ------------------- 2 files changed, 1 insertion(+), 49 deletions(-) delete mode 100644 tickets/migrations/0001_squashed_0008_remove_preferences_publish_tickets.py diff --git a/templates/base.html b/templates/base.html index de6f308c..7a2074f2 100644 --- a/templates/base.html +++ b/templates/base.html @@ -130,7 +130,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,