mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-16 00:13:12 +00:00
Add comment to tikets + send_notif mails
This commit is contained in:
parent
c8c89fab1d
commit
38b119bb8e
15 changed files with 524 additions and 76 deletions
|
@ -25,13 +25,15 @@ Ticket preferences model
|
||||||
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Ticket
|
from .models import Ticket, CommentTicket
|
||||||
|
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
class TicketAdmin(VersionAdmin):
|
class TicketAdmin(VersionAdmin):
|
||||||
"""Gestion des ticket"""
|
pass
|
||||||
|
|
||||||
|
class CommentTicketAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
admin.site.register(Ticket, TicketAdmin)
|
admin.site.register(Ticket, TicketAdmin)
|
||||||
|
admin.site.register(CommentTicket, CommentTicketAdmin)
|
||||||
|
|
|
@ -31,7 +31,7 @@ from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
from re2o.mixins import FormRevMixin
|
from re2o.mixins import FormRevMixin
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from .models import Ticket
|
from .models import Ticket, CommentTicket
|
||||||
|
|
||||||
|
|
||||||
class NewTicketForm(FormRevMixin, ModelForm):
|
class NewTicketForm(FormRevMixin, ModelForm):
|
||||||
|
@ -48,7 +48,7 @@ class NewTicketForm(FormRevMixin, ModelForm):
|
||||||
self.fields.pop('email')
|
self.fields.pop('email')
|
||||||
self.instance.user = request.user
|
self.instance.user = request.user
|
||||||
self.fields['description'].help_text = render_to_string('tickets/help_text.html')
|
self.fields['description'].help_text = render_to_string('tickets/help_text.html')
|
||||||
self.instance.request = request
|
self.instance.language = getattr(request, "LANGUAGE_CODE", "en")
|
||||||
|
|
||||||
|
|
||||||
class EditTicketForm(FormRevMixin, ModelForm):
|
class EditTicketForm(FormRevMixin, ModelForm):
|
||||||
|
@ -62,3 +62,16 @@ class EditTicketForm(FormRevMixin, ModelForm):
|
||||||
super(EditTicketForm, self).__init__(*args, **kwargs)
|
super(EditTicketForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['email'].required = False
|
self.fields['email'].required = False
|
||||||
|
|
||||||
|
|
||||||
|
class CommentTicketForm(FormRevMixin, ModelForm):
|
||||||
|
"""Edit and create comment to a ticket"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CommentTicket
|
||||||
|
fields = ["comment"]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
|
||||||
|
super(CommentTicketForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
self.fields["comment"].label = _("comment")
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 2.5\n"
|
"Project-Id-Version: 2.5\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2020-04-22 22:06+0200\n"
|
"POT-Creation-Date: 2020-04-23 03:10+0200\n"
|
||||||
"PO-Revision-Date: 2019-11-16 00:35+0100\n"
|
"PO-Revision-Date: 2019-11-16 00:35+0100\n"
|
||||||
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
|
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@ -30,44 +30,68 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: tickets/models.py:54
|
#: tickets/forms.py:76
|
||||||
|
msgid "comment"
|
||||||
|
msgstr "commentaire"
|
||||||
|
|
||||||
|
#: tickets/models.py:57
|
||||||
msgid "Title of the ticket."
|
msgid "Title of the ticket."
|
||||||
msgstr "Titre du ticket."
|
msgstr "Titre du ticket."
|
||||||
|
|
||||||
#: tickets/models.py:63
|
#: tickets/models.py:66
|
||||||
msgid "An email address to get back to you."
|
msgid "An email address to get back to you."
|
||||||
msgstr "Une adresse mail pour vous recontacter."
|
msgstr "Une adresse mail pour vous recontacter."
|
||||||
|
|
||||||
#: tickets/models.py:69
|
#: tickets/models.py:70
|
||||||
|
msgid "Language of the ticket."
|
||||||
|
msgstr "Langue des tickets"
|
||||||
|
|
||||||
|
#: tickets/models.py:74 tickets/models.py:170
|
||||||
msgid "Can view a ticket object"
|
msgid "Can view a ticket object"
|
||||||
msgstr "Peut voir un objet ticket"
|
msgstr "Peut voir un objet ticket"
|
||||||
|
|
||||||
#: tickets/models.py:70
|
#: tickets/models.py:75 tickets/models.py:171
|
||||||
msgid "ticket"
|
msgid "ticket"
|
||||||
msgstr "ticket"
|
msgstr "ticket"
|
||||||
|
|
||||||
#: tickets/models.py:71
|
#: tickets/models.py:76 tickets/models.py:172
|
||||||
msgid "tickets"
|
msgid "tickets"
|
||||||
msgstr "tickets"
|
msgstr "tickets"
|
||||||
|
|
||||||
#: tickets/models.py:75
|
#: tickets/models.py:80
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Ticket from %(name)s. Date: %(date)s."
|
msgid "Ticket from %(name)s. Date: %(date)s."
|
||||||
msgstr "Ticket de %(name)s. Date : %(date)s."
|
msgstr "Ticket de %(name)s. Date : %(date)s."
|
||||||
|
|
||||||
#: tickets/models.py:77
|
#: tickets/models.py:82
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Anonymous ticket. Date: %s."
|
msgid "Anonymous ticket. Date: %s."
|
||||||
msgstr "Ticket anonyme. Date : %s."
|
msgstr "Ticket anonyme. Date : %s."
|
||||||
|
|
||||||
#: tickets/models.py:111
|
#: tickets/models.py:90 tickets/templates/tickets/aff_ticket.html:52
|
||||||
|
msgid "Anonymous user"
|
||||||
|
msgstr "Utilisateur anonyme"
|
||||||
|
|
||||||
|
#: tickets/models.py:128
|
||||||
msgid "You don't have the right to view other tickets than yours."
|
msgid "You don't have the right to view other tickets than yours."
|
||||||
msgstr "Vous n'avez pas le droit de voir d'autres tickets que les vôtres."
|
msgstr "Vous n'avez pas le droit de voir d'autres tickets que les vôtres."
|
||||||
|
|
||||||
#: tickets/models.py:123
|
#: tickets/models.py:140 tickets/models.py:214
|
||||||
msgid "You don't have the right to view the list of tickets."
|
msgid "You don't have the right to view the list of tickets."
|
||||||
msgstr "Vous n'avez pas le droit de voir la liste des tickets."
|
msgstr "Vous n'avez pas le droit de voir la liste des tickets."
|
||||||
|
|
||||||
|
#: tickets/models.py:187
|
||||||
|
msgid "You don't have the right to view other tickets comments than yours."
|
||||||
|
msgstr "Vous n'avez pas le droit de voir d'autres tickets que les vôtres."
|
||||||
|
|
||||||
|
#: tickets/models.py:202
|
||||||
|
msgid "You don't have the right to edit other tickets comments than yours."
|
||||||
|
msgstr "Vous n'avez pas le droit d'éditer d'autres tickets que les vôtres."
|
||||||
|
|
||||||
|
#: tickets/models.py:232
|
||||||
|
msgid "Update of your ticket"
|
||||||
|
msgstr "Mise à jour de votre ticket"
|
||||||
|
|
||||||
#: tickets/preferences/forms.py:44
|
#: tickets/preferences/forms.py:44
|
||||||
msgid "Publish address"
|
msgid "Publish address"
|
||||||
msgstr "Adresse mail de publication"
|
msgstr "Adresse mail de publication"
|
||||||
|
@ -87,7 +111,7 @@ msgstr "Options des tickets"
|
||||||
msgid "Can view tickets options"
|
msgid "Can view tickets options"
|
||||||
msgstr "Peut voir les options des tickets"
|
msgstr "Peut voir les options des tickets"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:31
|
#: tickets/templates/tickets/aff_ticket.html:32
|
||||||
#: tickets/templates/tickets/contact.html:4
|
#: tickets/templates/tickets/contact.html:4
|
||||||
#: tickets/templates/tickets/index.html:29
|
#: tickets/templates/tickets/index.html:29
|
||||||
#: tickets/templates/tickets/preferences.html:6
|
#: tickets/templates/tickets/preferences.html:6
|
||||||
|
@ -95,57 +119,79 @@ msgstr "Peut voir les options des tickets"
|
||||||
msgid "Tickets"
|
msgid "Tickets"
|
||||||
msgstr "Tickets"
|
msgstr "Tickets"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:35
|
#: tickets/templates/tickets/aff_ticket.html:36
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Ticket #%(id)s"
|
msgid "Ticket #%(id)s"
|
||||||
msgstr "Ticket #%(id)s"
|
msgstr "Ticket #%(id)s"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:37
|
#: tickets/templates/tickets/aff_ticket.html:38
|
||||||
#: tickets/templates/tickets/aff_tickets.html:58
|
#: tickets/templates/tickets/aff_tickets.html:58
|
||||||
msgid "Solved"
|
msgid "Solved"
|
||||||
msgstr "Résolu"
|
msgstr "Résolu"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:39
|
#: tickets/templates/tickets/aff_ticket.html:40
|
||||||
msgid "Not solved"
|
msgid "Not solved"
|
||||||
msgstr "Non résolu"
|
msgstr "Non résolu"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:45
|
#: tickets/templates/tickets/aff_ticket.html:46
|
||||||
msgid "Opened by"
|
msgid "Opened by"
|
||||||
msgstr "Ouvert par"
|
msgstr "Ouvert par"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:51
|
#: tickets/templates/tickets/aff_ticket.html:56
|
||||||
msgid "Anonymous user"
|
|
||||||
msgstr "Utilisateur anonyme"
|
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:55
|
|
||||||
msgid "Response address: "
|
msgid "Response address: "
|
||||||
msgstr "Adresse de réponse : "
|
msgstr "Adresse de réponse : "
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:55
|
#: tickets/templates/tickets/aff_ticket.html:56
|
||||||
msgid "Response to your ticket"
|
msgid "Response to your ticket"
|
||||||
msgstr "Réponse à votre ticket"
|
msgstr "Réponse à votre ticket"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:60
|
|
||||||
msgid "Title:"
|
|
||||||
msgstr "Titre :"
|
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:61
|
#: tickets/templates/tickets/aff_ticket.html:61
|
||||||
msgid "Description:"
|
msgid "Add a comment "
|
||||||
msgstr "Description :"
|
msgstr "Ajouter un commentaire"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:65
|
#: tickets/templates/tickets/aff_ticket.html:64
|
||||||
msgid "Edit this ticket"
|
#: tickets/templates/tickets/preferences.html:14 tickets/views.py:153
|
||||||
msgstr "Modifier le ticket."
|
msgid "Edit"
|
||||||
|
msgstr "Modifier"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:67
|
#: tickets/templates/tickets/aff_ticket.html:66
|
||||||
msgid "Mark as solved"
|
msgid "Mark as solved"
|
||||||
msgstr "Marquer comme résolu"
|
msgstr "Marquer comme résolu"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:69
|
#: tickets/templates/tickets/aff_ticket.html:68
|
||||||
msgid "Mark as unsolved"
|
msgid "Mark as unsolved"
|
||||||
msgstr "Marquer comme non résolu"
|
msgstr "Marquer comme non résolu"
|
||||||
|
|
||||||
#: tickets/templates/tickets/aff_ticket.html:78
|
#: tickets/templates/tickets/aff_ticket.html:76
|
||||||
|
msgid "Title:"
|
||||||
|
msgstr "Titre :"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:77
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:84
|
||||||
|
msgid "Description:"
|
||||||
|
msgstr "Description :"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:83
|
||||||
|
msgid "Comment "
|
||||||
|
msgstr "Commentaire"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:83
|
||||||
|
msgid " added by "
|
||||||
|
msgstr " ajouté par "
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:83
|
||||||
|
msgid " on "
|
||||||
|
msgstr " le "
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:87
|
||||||
|
msgid "Edit this comment "
|
||||||
|
msgstr "Modifier le commentaire"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:90
|
||||||
|
msgid "Delete this comment "
|
||||||
|
msgstr "Supprimer ce commentaire"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/aff_ticket.html:99
|
||||||
msgid "All tickets"
|
msgid "All tickets"
|
||||||
msgstr "Tous les tickets"
|
msgstr "Tous les tickets"
|
||||||
|
|
||||||
|
@ -200,6 +246,21 @@ msgstr ""
|
||||||
msgid "Open a ticket"
|
msgid "Open a ticket"
|
||||||
msgstr "Ouvrir un ticket"
|
msgstr "Ouvrir un ticket"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/delete.html:29
|
||||||
|
msgid "Deletion of tickets"
|
||||||
|
msgstr "Suppression de tickets"
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/delete.html:35
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"Warning: are you sure you want to delete this %(objet_name)s object "
|
||||||
|
"( %(objet)s )?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tickets/templates/tickets/delete.html:36
|
||||||
|
msgid "Confirm"
|
||||||
|
msgstr "Confirmer"
|
||||||
|
|
||||||
#: tickets/templates/tickets/edit.html:34
|
#: tickets/templates/tickets/edit.html:34
|
||||||
msgid "Ticket opening"
|
msgid "Ticket opening"
|
||||||
msgstr "Ouverture de ticket"
|
msgstr "Ouverture de ticket"
|
||||||
|
@ -242,10 +303,6 @@ msgstr "Liste des tickets"
|
||||||
msgid "Manage the tickets"
|
msgid "Manage the tickets"
|
||||||
msgstr "Gérer les tickets"
|
msgstr "Gérer les tickets"
|
||||||
|
|
||||||
#: tickets/templates/tickets/preferences.html:14
|
|
||||||
msgid "Edit"
|
|
||||||
msgstr "Modifier"
|
|
||||||
|
|
||||||
#: tickets/templates/tickets/preferences.html:21
|
#: tickets/templates/tickets/preferences.html:21
|
||||||
msgid "Publication email address"
|
msgid "Publication email address"
|
||||||
msgstr "Adresse mail de publication"
|
msgstr "Adresse mail de publication"
|
||||||
|
@ -258,18 +315,38 @@ msgstr "Pas d'adresse mail, les tickets ne seront pas publiés."
|
||||||
msgid "No tickets"
|
msgid "No tickets"
|
||||||
msgstr "Pas de tickets"
|
msgstr "Pas de tickets"
|
||||||
|
|
||||||
#: tickets/views.py:56
|
#: tickets/views.py:62
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your ticket has been succesfully opened. We will take care of it as soon as "
|
"Your ticket has been succesfully opened. We will take care of it as soon as "
|
||||||
"possible."
|
"possible."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Votre ticket a bien été ouvert. Nous nous en occuperons dès que possible."
|
"Votre ticket a bien été ouvert. Nous nous en occuperons dès que possible."
|
||||||
|
|
||||||
#: tickets/views.py:102
|
#: tickets/views.py:109
|
||||||
msgid "Ticket has been updated successfully"
|
msgid "Ticket has been updated successfully"
|
||||||
msgstr "Le ticket a été mis à jour"
|
msgstr "Le ticket a été mis à jour"
|
||||||
|
|
||||||
#: tickets/views.py:123 tickets/views.py:148
|
#: tickets/views.py:130
|
||||||
|
msgid "This comment was added."
|
||||||
|
msgstr "Le commentaire a été ajouté"
|
||||||
|
|
||||||
|
#: tickets/views.py:135
|
||||||
|
msgid "Add a comment"
|
||||||
|
msgstr "Ajouter un commentaire"
|
||||||
|
|
||||||
|
#: tickets/views.py:148
|
||||||
|
msgid "This comment was edited."
|
||||||
|
msgstr "Le commentaire a été édité"
|
||||||
|
|
||||||
|
#: tickets/views.py:164
|
||||||
|
msgid "The comment was deleted."
|
||||||
|
msgstr "Le commentaire a été supprimé"
|
||||||
|
|
||||||
|
#: tickets/views.py:169
|
||||||
|
msgid "Ticket Comment"
|
||||||
|
msgstr "Commentaire de ticket"
|
||||||
|
|
||||||
|
#: tickets/views.py:183 tickets/views.py:208
|
||||||
msgid "Never"
|
msgid "Never"
|
||||||
msgstr "Jamais"
|
msgstr "Jamais"
|
||||||
|
|
||||||
|
@ -298,9 +375,6 @@ msgstr "Jamais"
|
||||||
#~ "Vous n'êtes pas authentifié. Veuillez vous connecter ou fournir une "
|
#~ "Vous n'êtes pas authentifié. Veuillez vous connecter ou fournir une "
|
||||||
#~ "adresse mail pour que nous puissions vous recontacter."
|
#~ "adresse mail pour que nous puissions vous recontacter."
|
||||||
|
|
||||||
#~ msgid "Open the ticket"
|
|
||||||
#~ msgstr "Ouvrir le ticket"
|
|
||||||
|
|
||||||
#~ msgid "Email language"
|
#~ msgid "Email language"
|
||||||
#~ msgstr "Langue du mail"
|
#~ msgstr "Langue du mail"
|
||||||
|
|
||||||
|
|
40
tickets/migrations/0005_auto_20200422_2309.py
Normal file
40
tickets/migrations/0005_auto_20200422_2309.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.28 on 2020-04-22 21:09
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import re2o.mixins
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0004_auto_20200422_2127'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CommentTicket',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('date', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('comment', models.TextField(max_length=4095)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ticket',
|
||||||
|
'verbose_name_plural': 'tickets',
|
||||||
|
'permissions': (('view_commentticket', 'Can view a ticket object'),),
|
||||||
|
},
|
||||||
|
bases=(re2o.mixins.AclMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='ticket',
|
||||||
|
options={'permissions': (('view_ticket', 'Can view a ticket object'),), 'verbose_name': 'ticket', 'verbose_name_plural': 'tickets'},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='commentticket',
|
||||||
|
name='parent_ticket',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tickets.Ticket'),
|
||||||
|
),
|
||||||
|
]
|
31
tickets/migrations/0006_auto_20200423_0202.py
Normal file
31
tickets/migrations/0006_auto_20200423_0202.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.28 on 2020-04-23 00:02
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('tickets', '0005_auto_20200422_2309'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='commentticket',
|
||||||
|
name='created_at',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='commentticket',
|
||||||
|
name='created_by',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_comment', to=settings.AUTH_USER_MODEL),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
20
tickets/migrations/0007_ticket_language.py
Normal file
20
tickets/migrations/0007_ticket_language.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.28 on 2020-04-23 01:05
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0006_auto_20200423_0202'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ticket',
|
||||||
|
name='language',
|
||||||
|
field=models.CharField(default='en', help_text='Language of the ticket.', max_length=16),
|
||||||
|
),
|
||||||
|
]
|
|
@ -29,6 +29,9 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
from reversion.models import Version
|
||||||
|
|
||||||
from re2o.mixins import AclMixin
|
from re2o.mixins import AclMixin
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
@ -63,10 +66,12 @@ class Ticket(AclMixin, models.Model):
|
||||||
help_text=_("An email address to get back to you."), max_length=100, null=True
|
help_text=_("An email address to get back to you."), max_length=100, null=True
|
||||||
)
|
)
|
||||||
solved = models.BooleanField(default=False)
|
solved = models.BooleanField(default=False)
|
||||||
request = None
|
language = models.CharField(
|
||||||
|
max_length=16, help_text=_("Language of the ticket."), default="en"
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_tickets", _("Can view a ticket object")),)
|
permissions = (("view_ticket", _("Can view a ticket object")),)
|
||||||
verbose_name = _("ticket")
|
verbose_name = _("ticket")
|
||||||
verbose_name_plural = _("tickets")
|
verbose_name_plural = _("tickets")
|
||||||
|
|
||||||
|
@ -76,13 +81,25 @@ class Ticket(AclMixin, models.Model):
|
||||||
else:
|
else:
|
||||||
return _("Anonymous ticket. Date: %s.") % (self.date)
|
return _("Anonymous ticket. Date: %s.") % (self.date)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def opened_by(self):
|
||||||
|
"""Return full name of this ticket opener"""
|
||||||
|
if self.user:
|
||||||
|
return self.user.get_full_name()
|
||||||
|
else:
|
||||||
|
return _("Anonymous user")
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def get_mail(self):
|
||||||
|
"""Return the mail of the owner of this ticket"""
|
||||||
|
return self.email or self.user.get_mail
|
||||||
|
|
||||||
def publish_mail(self):
|
def publish_mail(self):
|
||||||
site_url = GeneralOption.get_cached_value("main_site_url")
|
site_url = GeneralOption.get_cached_value("main_site_url")
|
||||||
to_addr = TicketOption.get_cached_value("publish_address")
|
to_addr = TicketOption.get_cached_value("publish_address")
|
||||||
context = {"ticket": self, "site_url": site_url}
|
context = {"ticket": self, "site_url": site_url}
|
||||||
|
|
||||||
language = getattr(self.request, "LANGUAGE_CODE", "en")
|
if self.language == "fr":
|
||||||
if language == "fr":
|
|
||||||
obj = "Nouveau ticket ouvert"
|
obj = "Nouveau ticket ouvert"
|
||||||
template = loader.get_template("tickets/publication_mail_fr")
|
template = loader.get_template("tickets/publication_mail_fr")
|
||||||
else:
|
else:
|
||||||
|
@ -94,7 +111,7 @@ class Ticket(AclMixin, models.Model):
|
||||||
template.render(context),
|
template.render(context),
|
||||||
GeneralOption.get_cached_value("email_from"),
|
GeneralOption.get_cached_value("email_from"),
|
||||||
[to_addr],
|
[to_addr],
|
||||||
reply_to=[self.email],
|
reply_to=[self.get_mail],
|
||||||
)
|
)
|
||||||
mail_to_send.send(fail_silently=False)
|
mail_to_send.send(fail_silently=False)
|
||||||
|
|
||||||
|
@ -103,13 +120,13 @@ class Ticket(AclMixin, models.Model):
|
||||||
""" Check that the user has the right to view the ticket
|
""" Check that the user has the right to view the ticket
|
||||||
or that it is the author"""
|
or that it is the author"""
|
||||||
if (
|
if (
|
||||||
not user_request.has_perm("tickets.view_tickets")
|
not user_request.has_perm("tickets.view_ticket")
|
||||||
and self.user != user_request
|
and self.user != user_request
|
||||||
):
|
):
|
||||||
return (
|
return (
|
||||||
False,
|
False,
|
||||||
_("You don't have the right to view other tickets than yours."),
|
_("You don't have the right to view other tickets than yours."),
|
||||||
("tickets.view_tickets",),
|
("tickets.view_ticket",),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return True, None, None
|
return True, None, None
|
||||||
|
@ -117,13 +134,13 @@ class Ticket(AclMixin, models.Model):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_view_all(user_request, *_args, **_kwargs):
|
def can_view_all(user_request, *_args, **_kwargs):
|
||||||
""" Check that the user has access to the list of all tickets"""
|
""" Check that the user has access to the list of all tickets"""
|
||||||
can = user_request.has_perm("tickets.view_tickets")
|
can = user_request.has_perm("tickets.view_ticket")
|
||||||
return (
|
return (
|
||||||
can,
|
can,
|
||||||
_("You don't have the right to view the list of tickets.")
|
_("You don't have the right to view the list of tickets.")
|
||||||
if not can
|
if not can
|
||||||
else None,
|
else None,
|
||||||
("tickets.view_tickets",),
|
("tickets.view_ticket",),
|
||||||
)
|
)
|
||||||
|
|
||||||
def can_create(user_request, *_args, **_kwargs):
|
def can_create(user_request, *_args, **_kwargs):
|
||||||
|
@ -131,6 +148,97 @@ class Ticket(AclMixin, models.Model):
|
||||||
return True, None, None
|
return True, None, None
|
||||||
|
|
||||||
|
|
||||||
|
class CommentTicket(AclMixin, models.Model):
|
||||||
|
"""A comment of a ticket"""
|
||||||
|
date = models.DateTimeField(auto_now_add=True)
|
||||||
|
comment = models.TextField(
|
||||||
|
max_length=4095,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
)
|
||||||
|
parent_ticket = models.ForeignKey(
|
||||||
|
"Ticket", on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
created_by = models.ForeignKey(
|
||||||
|
"users.User",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="ticket_comment",
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (("view_commentticket", _("Can view a ticket object")),)
|
||||||
|
verbose_name = _("ticket")
|
||||||
|
verbose_name_plural = _("tickets")
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def comment_id(self):
|
||||||
|
return CommentTicket.objects.filter(parent_ticket=self.parent_ticket, pk__lt=self.pk).count() + 1
|
||||||
|
|
||||||
|
def can_view(self, user_request, *_args, **_kwargs):
|
||||||
|
""" Check that the user has the right to view the ticket comment
|
||||||
|
or that it is the author"""
|
||||||
|
if (
|
||||||
|
not user_request.has_perm("tickets.view_commentticket")
|
||||||
|
and self.parent_ticket.user != user_request
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
_("You don't have the right to view other tickets comments than yours."),
|
||||||
|
("tickets.view_commentticket",),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return True, None, None
|
||||||
|
|
||||||
|
def can_edit(self, user_request, *_args, **_kwargs):
|
||||||
|
""" Check that the user has the right to edit the ticket comment
|
||||||
|
or that it is the author"""
|
||||||
|
if (
|
||||||
|
not user_request.has_perm("tickets.edit_commentticket")
|
||||||
|
and (self.parent_ticket.user != user_request or self.parent_ticket.user != self.created_by)
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
_("You don't have the right to edit other tickets comments than yours."),
|
||||||
|
("tickets.edit_commentticket",),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return True, None, None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def can_view_all(user_request, *_args, **_kwargs):
|
||||||
|
""" Check that the user has access to the list of all tickets comments"""
|
||||||
|
can = user_request.has_perm("tickets.view_commentticket")
|
||||||
|
return (
|
||||||
|
can,
|
||||||
|
_("You don't have the right to view the list of tickets.")
|
||||||
|
if not can
|
||||||
|
else None,
|
||||||
|
("tickets.view_commentticket",),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Comment " + str(self.comment_id) + " on " + str(self.parent_ticket)
|
||||||
|
|
||||||
|
def publish_mail(self):
|
||||||
|
site_url = GeneralOption.get_cached_value("main_site_url")
|
||||||
|
to_addr = TicketOption.get_cached_value("publish_address")
|
||||||
|
context = {"comment": self, "site_url": site_url}
|
||||||
|
|
||||||
|
if self.parent_ticket.language == "fr":
|
||||||
|
template = loader.get_template("tickets/update_mail_fr")
|
||||||
|
else:
|
||||||
|
template = loader.get_template("tickets/update_mail_en")
|
||||||
|
obj = _("Update of your ticket")
|
||||||
|
mail_to_send = EmailMessage(
|
||||||
|
obj,
|
||||||
|
template.render(context),
|
||||||
|
GeneralOption.get_cached_value("email_from"),
|
||||||
|
[to_addr, self.parent_ticket.get_mail],
|
||||||
|
)
|
||||||
|
mail_to_send.send(fail_silently=False)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Ticket)
|
@receiver(post_save, sender=Ticket)
|
||||||
def ticket_post_save(**kwargs):
|
def ticket_post_save(**kwargs):
|
||||||
""" Send the mail to publish the new ticket """
|
""" Send the mail to publish the new ticket """
|
||||||
|
@ -138,3 +246,12 @@ def ticket_post_save(**kwargs):
|
||||||
if TicketOption.get_cached_value("publish_address"):
|
if TicketOption.get_cached_value("publish_address"):
|
||||||
ticket = kwargs["instance"]
|
ticket = kwargs["instance"]
|
||||||
ticket.publish_mail()
|
ticket.publish_mail()
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=CommentTicket)
|
||||||
|
def comment_post_save(**kwargs):
|
||||||
|
""" Send the mail to publish the new comment """
|
||||||
|
if kwargs["created"]:
|
||||||
|
if TicketOption.get_cached_value("publish_address"):
|
||||||
|
comment = kwargs["instance"]
|
||||||
|
comment.publish_mail()
|
||||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% load bootstrap3 %}
|
{% load bootstrap3 %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
|
{% load logs_extra %}
|
||||||
{% load acl %}
|
{% load acl %}
|
||||||
|
|
||||||
{% block title %}{% trans "Tickets" %}{% endblock %}
|
{% block title %}{% trans "Tickets" %}{% endblock %}
|
||||||
|
@ -54,28 +55,48 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% if not ticket.user %}
|
{% if not ticket.user %}
|
||||||
{% trans "Response address: " %}<A HREF="mailto:{{ticket.email}}?subject={% trans "Response to your ticket"%}">{{ticket.email}}</A>
|
{% trans "Response address: " %}<A HREF="mailto:{{ticket.email}}?subject={% trans "Response to your ticket"%}">{{ticket.email}}</A>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
{% can_view ticket %}
|
||||||
|
<a class="btn btn-info btn-sm" role="button" href="{% url 'tickets:add-comment' ticket.id %}"><i class="fa fa-plus"></i> {% trans "Add a comment " %}</a>
|
||||||
|
{% acl_end %}
|
||||||
|
{% can_edit ticket %}
|
||||||
|
<a class="btn btn-info btn-sm" role="button" href="{% url 'tickets:edit-ticket' ticket.id %}"><i class="fa fa-edit"></i> {% trans "Edit" %}</a>
|
||||||
|
{% if not ticket.solved %}
|
||||||
|
<a class="btn btn-success btn-sm" role="button" href="{% url 'tickets:change-ticket-status' ticket.id %}"><i class="fa fa-check"></i> {% trans "Mark as solved" %}</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="btn btn-warning btn-sm" role="button" href="{% url 'tickets:change-ticket-status' ticket.id %}"><i class="fa fa-close"></i> {% trans "Mark as unsolved" %}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% acl_end %}
|
||||||
|
{% history_button ticket text=True %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
<p><b>{% trans "Title:" %}</b> {{ticket.title}}</p>
|
<p><b>{% trans "Title:" %}</b> {{ticket.title}}</p>
|
||||||
<p><b>{% trans "Description:" %}</b> {{ ticket.description | linebreaks }}</p>
|
<b>{% trans "Description:" %}</b> {{ ticket.description | linebreaks }}
|
||||||
|
|
||||||
<div class="text-right">
|
</div>
|
||||||
{% can_edit ticket %}
|
|
||||||
<a type="button" href="{% url 'tickets:edit-ticket' ticket.id %}" class="btn btn-info"><p>{% trans "Edit this ticket" %}</p></a>
|
{% for comment in comments %}
|
||||||
{% if not ticket.solved %}
|
<div class="panel-footer">
|
||||||
<a type="button" href="{% url 'tickets:change-ticket-status' ticket.id %}" class="btn btn-success"><p>{% trans "Mark as solved" %}</p></a>
|
<p><span class="badge">{% trans "Comment " %}<b>#{{comment.comment_id}}</b></span> {% trans " added by " %}{{ comment.created_by.get_full_name }}{% trans " on " %} {{comment.created_at}}</p>
|
||||||
{% else %}
|
<b>{% trans "Description:" %}</b> {{ comment.comment | linebreaks }}
|
||||||
<a type="button" href="{% url 'tickets:change-ticket-status' ticket.id %}" class="btn btn-warning"><p>{% trans "Mark as unsolved" %}</p></a>
|
<div class="text-right">
|
||||||
{% endif %}
|
{% can_edit comment %}
|
||||||
|
<a class="btn btn-info btn-sm" role="button" href="{% url 'tickets:edit-comment' comment.id %}"><i class="fa fa-edit"></i> {% trans "Edit this comment " %}</a>
|
||||||
{% acl_end %}
|
{% acl_end %}
|
||||||
|
{% can_delete comment %}
|
||||||
|
<a class="btn btn-danger btn-sm" role="button" href="{% url 'tickets:del-comment' comment.id %}"><i class="fa fa-close"></i> {% trans "Delete this comment " %}</a>
|
||||||
|
{% acl_end %}
|
||||||
|
{% history_button comment text=True %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<a type="button" href="{% url 'tickets:aff-tickets' %}" class="btn btn-primary"><p>{% trans "All tickets" %}</p></a>
|
<a class="btn btn-primary" role="button" href="{% url 'tickets:aff-tickets' %}"><i class="fa fa-reorder"></i> {% trans "All tickets" %}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
43
tickets/templates/tickets/delete.html
Normal file
43
tickets/templates/tickets/delete.html
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{% 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 Lara 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 "Deletion of tickets" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<h4>{% blocktrans %}Warning: are you sure you want to delete this {{ objet_name }} object ( {{ objet }} )?{% endblocktrans %}</h4>
|
||||||
|
{% trans "Confirm" as tr_confirm %}
|
||||||
|
{% bootstrap_button tr_confirm button_type="submit" icon="trash" button_class='btn-danger' %}
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{% if ticket.user %} {{ ticket.user.get_full_name }} opened a ticket.
|
{% if ticket.user %} {{ ticket.user.get_full_name }} opened a ticket.
|
||||||
Profile: {{site_url}}{% url 'users:profil' ticket.user.id%}
|
Profile: {{site_url}}{% url 'users:profil' ticket.user.id%}
|
||||||
Answer to the address: {{ticket.user.get_mail}}.
|
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
An anonymous user (not authenticated) opened a ticket
|
An anonymous user (not authenticated) opened a ticket
|
||||||
Answer to the address:{{ticket.email}}.
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Answer to the address: {{{ticket.get_mail}}.
|
||||||
|
|
||||||
Title: {{ ticket.title | safe }}
|
Title: {{ ticket.title | safe }}
|
||||||
|
|
||||||
Description: {{ ticket.description | safe }}
|
Description: {{ ticket.description | safe }}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{% if ticket.user %} {{ ticket.user.get_full_name }} a ouvert un ticket.
|
{% if ticket.user %} {{ ticket.user.get_full_name }} a ouvert un ticket.
|
||||||
Profil : {{site_url}}{% url 'users:profil' ticket.user.id%}
|
Profil : {{site_url}}{% url 'users:profil' ticket.user.id%}
|
||||||
Répondre à l'adresse : {{ticket.user.get_mail}}.
|
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
Un utilisateur anonyme (non connecté) a ouvert un ticket.
|
Un utilisateur anonyme (non connecté) a ouvert un ticket.
|
||||||
Répondre à l'adresse : {{ticket.email}}.
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Répondre à l'adresse : {{ticket.get_mail}}.
|
||||||
|
|
||||||
|
|
||||||
Titre : {{ ticket.title | safe }}
|
Titre : {{ ticket.title | safe }}
|
||||||
|
|
||||||
|
|
12
tickets/templates/tickets/update_mail_en
Normal file
12
tickets/templates/tickets/update_mail_en
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Hello,
|
||||||
|
|
||||||
|
The ticket {{ comment.parent_ticket.title | safe }} n°{{ comment.parent_ticket.id }}, opened by {{ comment.parent_ticket.opened_by }}, has been updated by {{ comment.created_by.get_full_name | safe }}.
|
||||||
|
{% if comment.parent_ticket.user %}
|
||||||
|
The complete re2o profil can be found here : {{site_url}}{% url 'users:profil' comment.parent_ticket.user.id%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
Description : {{ comment.comment | safe }}
|
||||||
|
|
||||||
|
Best regards,
|
||||||
|
|
||||||
|
The member of the association
|
12
tickets/templates/tickets/update_mail_fr
Normal file
12
tickets/templates/tickets/update_mail_fr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Bonjour,
|
||||||
|
|
||||||
|
Le ticket {{ comment.parent_ticket.title | safe }} n°{{ comment.parent_ticket.id }}, ouvert par {{ comment.parent_ticket.opened_by }}, a reçu une mise à jour par {{ comment.created_by.get_full_name | safe }}.
|
||||||
|
{% if comment.parent_ticket.user %}
|
||||||
|
Le profil re2o est accessible à l'adresse suivante : {{site_url}}{% url 'users:profil' comment.parent_ticket.user.id%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
Description : {{ comment.comment | safe }}
|
||||||
|
|
||||||
|
Cordialement,
|
||||||
|
|
||||||
|
Les membres actifs de l'association
|
|
@ -39,4 +39,7 @@ urlpatterns = [
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(r"^new_ticket/$", views.new_ticket, name="new-ticket"),
|
url(r"^new_ticket/$", views.new_ticket, name="new-ticket"),
|
||||||
|
url(r"^add_comment/(?P<ticketid>[0-9]+)$", views.add_comment, name="add-comment"),
|
||||||
|
url(r"^edit_comment/(?P<commentticketid>[0-9]+)$", views.edit_comment, name="edit-comment"),
|
||||||
|
url(r"^del_comment/(?P<commentticketid>[0-9]+)$", views.del_comment, name="del-comment"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -36,13 +36,19 @@ from re2o.views import form
|
||||||
|
|
||||||
from re2o.base import re2o_paginator
|
from re2o.base import re2o_paginator
|
||||||
|
|
||||||
from re2o.acl import can_view, can_view_all, can_edit, can_create
|
from re2o.acl import (
|
||||||
|
can_view,
|
||||||
|
can_view_all,
|
||||||
|
can_edit,
|
||||||
|
can_create,
|
||||||
|
can_delete
|
||||||
|
)
|
||||||
|
|
||||||
from preferences.models import GeneralOption
|
from preferences.models import GeneralOption
|
||||||
|
|
||||||
from .models import Ticket
|
from .models import Ticket, CommentTicket
|
||||||
|
|
||||||
from .forms import NewTicketForm, EditTicketForm
|
from .forms import NewTicketForm, EditTicketForm, CommentTicketForm
|
||||||
|
|
||||||
|
|
||||||
def new_ticket(request):
|
def new_ticket(request):
|
||||||
|
@ -71,10 +77,11 @@ def new_ticket(request):
|
||||||
@can_view(Ticket)
|
@can_view(Ticket)
|
||||||
def aff_ticket(request, ticket, ticketid):
|
def aff_ticket(request, ticket, ticketid):
|
||||||
"""View to display only one ticket"""
|
"""View to display only one ticket"""
|
||||||
|
comments = CommentTicket.objects.filter(parent_ticket=ticket)
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"tickets/aff_ticket.html",
|
"tickets/aff_ticket.html",
|
||||||
{"ticket": ticket},
|
{"ticket": ticket, "comments": comments},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,6 +117,59 @@ def edit_ticket(request, ticket, ticketid):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_view(Ticket)
|
||||||
|
def add_comment(request, ticket, ticketid):
|
||||||
|
""" Add a comment to a ticket"""
|
||||||
|
commentticket = CommentTicketForm(request.POST or None)
|
||||||
|
if commentticket.is_valid():
|
||||||
|
commentticket = commentticket.save(commit=False)
|
||||||
|
commentticket.parent_ticket = ticket
|
||||||
|
commentticket.created_by = request.user
|
||||||
|
commentticket.save()
|
||||||
|
messages.success(request, _("This comment was added."))
|
||||||
|
return redirect(
|
||||||
|
reverse("tickets:aff-ticket", kwargs={"ticketid": str(ticketid)})
|
||||||
|
)
|
||||||
|
return form(
|
||||||
|
{"ticketform": commentticket, "action_name": _("Add a comment")}, "tickets/edit.html", request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_edit(CommentTicket)
|
||||||
|
def edit_comment(request, commentticket_instance, **_kwargs):
|
||||||
|
""" Edit a comment of a ticket"""
|
||||||
|
commentticket = CommentTicketForm(request.POST or None, instance=commentticket_instance)
|
||||||
|
if commentticket.is_valid():
|
||||||
|
ticketid = commentticket_instance.parent_ticket.id
|
||||||
|
if commentticket.changed_data:
|
||||||
|
commentticket.save()
|
||||||
|
messages.success(request, _("This comment was edited."))
|
||||||
|
return redirect(
|
||||||
|
reverse("tickets:aff-ticket", kwargs={"ticketid": str(ticketid)})
|
||||||
|
)
|
||||||
|
return form(
|
||||||
|
{"ticketform": commentticket, "action_name": _("Edit")}, "tickets/edit.html", request,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_delete(CommentTicket)
|
||||||
|
def del_comment(request, commentticket, **_kwargs):
|
||||||
|
"""Delete a comment of a ticket"""
|
||||||
|
if request.method == "POST":
|
||||||
|
ticketid = commentticket.parent_ticket.id
|
||||||
|
commentticket.delete()
|
||||||
|
messages.success(request, _("The comment was deleted."))
|
||||||
|
return redirect(
|
||||||
|
reverse("tickets:aff-ticket", kwargs={"ticketid": str(ticketid)})
|
||||||
|
)
|
||||||
|
return form(
|
||||||
|
{"objet": commentticket, "objet_name": _("Ticket Comment")}, "tickets/delete.html", request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(Ticket)
|
@can_view_all(Ticket)
|
||||||
def aff_tickets(request):
|
def aff_tickets(request):
|
||||||
|
|
Loading…
Reference in a new issue