diff --git a/preferences/admin.py b/preferences/admin.py index 296dc57c..5ca90095 100644 --- a/preferences/admin.py +++ b/preferences/admin.py @@ -34,6 +34,7 @@ from .models import ( OptionalTopologie, GeneralOption, Service, + MailContact, AssoOption, MailMessageOption, HomeOption @@ -65,6 +66,11 @@ class ServiceAdmin(VersionAdmin): pass +class MailContactAdmin(VersionAdmin): + """Admin class for contact email adresses""" + pass + + class AssoOptionAdmin(VersionAdmin): """Class admin options de l'asso""" pass @@ -86,5 +92,6 @@ admin.site.register(OptionalTopologie, OptionalTopologieAdmin) admin.site.register(GeneralOption, GeneralOptionAdmin) admin.site.register(HomeOption, HomeOptionAdmin) admin.site.register(Service, ServiceAdmin) +admin.site.register(MailContact, MailContactAdmin) admin.site.register(AssoOption, AssoOptionAdmin) admin.site.register(MailMessageOption, MailMessageOptionAdmin) diff --git a/preferences/forms.py b/preferences/forms.py index 477d4d57..99910f9c 100644 --- a/preferences/forms.py +++ b/preferences/forms.py @@ -27,6 +27,8 @@ from __future__ import unicode_literals from django.forms import ModelForm, Form from django import forms + +from re2o.mixins import FormRevMixin from .models import ( OptionalUser, OptionalMachine, @@ -35,7 +37,8 @@ from .models import ( AssoOption, MailMessageOption, HomeOption, - Service + Service, + MailContact ) @@ -227,3 +230,30 @@ class DelServiceForm(Form): self.fields['services'].queryset = instances else: self.fields['services'].queryset = Service.objects.all() + +class MailContactForm(FormRevMixin, ModelForm): + """Edit and add contact email adress""" + class Meta: + model = MailContact + fields = '__all__' + + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(MailContactForm, self).__init__(*args, prefix=prefix, **kwargs) + + +class DelMailContactForm(Form): + """Delete contact email adress""" + mailcontacts = forms.ModelMultipleChoiceField( + queryset=MailContact.objects.none(), + label="Enregistrements adresses actuels", + widget=forms.CheckboxSelectMultiple + ) + + def __init__(self, *args, **kwargs): + instances = kwargs.pop('instances', None) + super(DelMailContactForm, self).__init__(*args, **kwargs) + if instances: + self.fields['mailcontacts'].queryset = instances + else: + self.fields['mailcontacts'].queryset = MailContact.objects.all() diff --git a/preferences/locale/fr/LC_MESSAGES/django.mo b/preferences/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 00000000..21ed01a4 Binary files /dev/null and b/preferences/locale/fr/LC_MESSAGES/django.mo differ diff --git a/preferences/locale/fr/LC_MESSAGES/django.po b/preferences/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 00000000..8a4ce095 --- /dev/null +++ b/preferences/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,70 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-26 21:49+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: models.py:256 +msgid "Contact email adress" +msgstr "Adresse email de contact" + +#: models.py:263 +msgid "Description of the associated email adress." +msgstr "Description de l'adresse mail associée." + +#: models.py:273 +msgid "Can see contact email" +msgstr "Peut voir un mail de contact" + +#: templates/preferences/aff_mailcontact.html:30 +msgid "Adress" +msgstr "Adresse" + +#: templates/preferences/aff_mailcontact.html:31 +msgid "Remark" +msgstr "Commentaire" + +#: templates/preferences/display_preferences.html:205 +msgid "Contact email adresses list" +msgstr "Liste des adresses email de contact" + +#: templates/preferences/display_preferences.html:207 +msgid "Add an adress" +msgstr "Ajouter une adresse" + +#: templates/preferences/display_preferences.html:209 +msgid "Delete one or multiple adresses" +msgstr "Supprimer une ou plusieurs adresses" + +#: views.py:210 +msgid "The adress was created." +msgstr "L'adresse a été créée." + +#: views.py:230 +msgid "Email adress updated." +msgstr "L'adresse email a été mise à jour." + +#: views.py:233 +msgid "Edit" +msgstr "Éditer" + +#: views.py:251 +msgid "The email adress was deleted." +msgstr "L'adresse email a été supprimée." + +#: views.py:254 +msgid "Delete" +msgstr "Supprimer" diff --git a/preferences/migrations/0047_mailcontact.py b/preferences/migrations/0047_mailcontact.py new file mode 100644 index 00000000..c7b7eda5 --- /dev/null +++ b/preferences/migrations/0047_mailcontact.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2018-06-30 15:27 +from __future__ import unicode_literals + +from django.db import migrations, models +import re2o.mixins + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0046_optionaluser_mail_extension'), + ] + + operations = [ + migrations.CreateModel( + name='MailContact', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('address', models.EmailField(default='contact@example.org', help_text="Contact email adress", max_length=254)), + ('commentary', models.CharField(blank=True, help_text="Description of the associated email adress.", max_length=256, null=True)), + ], + options={ + 'permissions': (('view_mailcontact', "Can see contact email"),), + }, + bases=(re2o.mixins.AclMixin, models.Model), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index c2d6aa74..9226bd4a 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -31,6 +31,7 @@ from django.db.models.signals import post_save from django.dispatch import receiver from django.core.cache import cache from django.forms import ValidationError +from django.utils.translation import ugettext_lazy as _ import machines.models from re2o.mixins import AclMixin @@ -267,6 +268,34 @@ class Service(AclMixin, models.Model): def __str__(self): return str(self.name) +class MailContact(AclMixin, models.Model): + """Contact email adress with a commentary.""" + + address = models.EmailField( + default = "contact@example.org", + help_text = _("Contact email adress") + ) + + commentary = models.CharField( + blank = True, + null = True, + help_text = _( + "Description of the associated email adress."), + max_length = 256 + ) + + @cached_property + def get_name(self): + return self.address.split("@")[0] + + class Meta: + permissions = ( + ("view_mailcontact", _("Can see contact email")), + ) + + def __str__(self): + return(self.address) + class AssoOption(AclMixin, PreferencesModel): """Options générales de l'asso : siret, addresse, nom, etc""" diff --git a/preferences/templates/preferences/aff_mailcontact.html b/preferences/templates/preferences/aff_mailcontact.html new file mode 100644 index 00000000..a87e03bb --- /dev/null +++ b/preferences/templates/preferences/aff_mailcontact.html @@ -0,0 +1,47 @@ +{% 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 i18n %} +{% load acl %} +{% load logs_extra %} + + + + + + + + + {% for mailcontact in mailcontact_list %} + + + + + + {% endfor %} +
{% trans "Adress" %}{% trans "Remark" %}
{{ mailcontact.address }}{{ mailcontact.commentary }} + {% can_edit mailcontact %} + {% include 'buttons/edit.html' with href='preferences:edit-mailcontact' id=mailcontact.id %} + {% acl_end %} + {% history_button mailcontact %} +
diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html index a3f2dbc3..2e34db5a 100644 --- a/preferences/templates/preferences/display_preferences.html +++ b/preferences/templates/preferences/display_preferences.html @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load acl %} {% load design %} +{% load i18n %} {% block title %}Création et modification des préférences{% endblock %} @@ -212,7 +213,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Ajouter un service {% acl_end %} - + Supprimer un ou plusieurs service {% include "preferences/aff_service.html" with service_list=service_list %} @@ -220,6 +221,15 @@ with this program; if not, write to the Free Software Foundation, Inc., Editer + +

{% trans "Contact email adresses list" %}

+ {% can_create preferences.MailContact%} + {% trans "Add an adress" %} + {% acl_end %} + {% trans "Delete one or multiple adresses" %} + {% include "preferences/aff_mailcontact.html" with mailcontact_list=mailcontact_list %} +

+ diff --git a/preferences/urls.py b/preferences/urls.py index ec35cc41..a89fcdf3 100644 --- a/preferences/urls.py +++ b/preferences/urls.py @@ -72,6 +72,13 @@ urlpatterns = [ views.edit_service, name='edit-service' ), - url(r'^del_services/$', views.del_services, name='del-services'), + url(r'^del_service/$', views.del_service, name='del-service'), + url(r'^add_mailcontact/$', views.add_mailcontact, name='add-mailcontact'), + url( + r'^edit_mailcontact/(?P[0-9]+)$', + views.edit_mailcontact, + name='edit-mailcontact' + ), + url(r'^del_mailcontact/$', views.del_mailcontact, name='del-mailcontact'), url(r'^$', views.display_options, name='display-options'), ] diff --git a/preferences/views.py b/preferences/views.py index b8ca39d2..3c0c4879 100644 --- a/preferences/views.py +++ b/preferences/views.py @@ -36,15 +36,19 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.db.models import ProtectedError from django.db import transaction +from django.utils.translation import ugettext as _ from reversion import revisions as reversion from re2o.views import form from re2o.acl import can_create, can_edit, can_delete_set, can_view_all -from .forms import ServiceForm, DelServiceForm +from .forms import ( + ServiceForm, DelServiceForm, MailContactForm, DelMailContactForm +) from .models import ( Service, + MailContact, OptionalUser, OptionalMachine, AssoOption, @@ -71,6 +75,7 @@ def display_options(request): homeoptions, _created = HomeOption.objects.get_or_create() mailmessageoptions, _created = MailMessageOption.objects.get_or_create() service_list = Service.objects.all() + mailcontact_list = MailContact.objects.all() return form({ 'useroptions': useroptions, 'machineoptions': machineoptions, @@ -79,7 +84,8 @@ def display_options(request): 'assooptions': assooptions, 'homeoptions': homeoptions, 'mailmessageoptions': mailmessageoptions, - 'service_list': service_list + 'service_list': service_list, + 'mailcontact_list': mailcontact_list }, 'preferences/display_preferences.html', request) @@ -169,7 +175,7 @@ def edit_service(request, service_instance, **_kwargs): @login_required @can_delete_set(Service) -def del_services(request, instances): +def del_service(request, instances): """Suppression d'un service de la page d'accueil""" services = DelServiceForm(request.POST or None, instances=instances) if services.is_valid(): @@ -179,7 +185,7 @@ def del_services(request, instances): with transaction.atomic(), reversion.create_revision(): services_del.delete() reversion.set_user(request.user) - messages.success(request, "Le service a été supprimée") + messages.success(request, "Le service a été supprimé") except ProtectedError: messages.error(request, "Erreur le service\ suivant %s ne peut être supprimé" % services_del) @@ -189,3 +195,63 @@ def del_services(request, instances): 'preferences/preferences.html', request ) + + +@login_required +@can_create(MailContact) +def add_mailcontact(request): + """Add a contact email adress.""" + mailcontact = MailContactForm( + request.POST or None, + request.FILES or None + ) + if mailcontact.is_valid(): + mailcontact.save() + messages.success(request, _("The adress was created.")) + return redirect(reverse('preferences:display-options')) + return form( + {'preferenceform': mailcontact, 'action_name': 'Ajouter'}, + 'preferences/preferences.html', + request + ) + + +@login_required +@can_edit(MailContact) +def edit_mailcontact(request, mailcontact_instance, **_kwargs): + """Edit contact email adress.""" + mailcontact = MailContactForm( + request.POST or None, + request.FILES or None, + instance=mailcontact_instance + ) + if mailcontact.is_valid(): + mailcontact.save() + messages.success(request, _("Email adress updated.")) + return redirect(reverse('preferences:display-options')) + return form( + {'preferenceform': mailcontact, 'action_name': _('Edit')}, + 'preferences/preferences.html', + request + ) + + +@login_required +@can_delete_set(MailContact) +def del_mailcontact(request, instances): + """Delete an email adress""" + mailcontacts = DelMailContactForm( + request.POST or None, + instances=instances + ) + if mailcontacts.is_valid(): + mailcontacts_dels = mailcontacts.cleaned_data['mailcontacts'] + for mailcontacts_del in mailcontacts_dels: + mailcontacts_del.delete() + messages.success(request, _("The email adress was deleted.")) + return redirect(reverse('preferences:display-options')) + return form( + {'preferenceform': mailcontacts, 'action_name': _('Delete')}, + 'preferences/preferences.html', + request + ) diff --git a/re2o/templates/re2o/contact.html b/re2o/templates/re2o/contact.html new file mode 100644 index 00000000..f2de696d --- /dev/null +++ b/re2o/templates/re2o/contact.html @@ -0,0 +1,52 @@ +{% extends "re2o/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 "Contact" %}{% endblock %} + +{% block content %} +

{% blocktrans %}Contacter l'association {{asso_name}}{% endblocktrans %}

+
+ +{% for contact in contacts %} + +
+

{{ contact.get_name }}

+
+
+
{{ contact.commentary}}
+ +
+
+
+ +{% endfor %} + + + +{% endblock %} + diff --git a/re2o/templatetags/acl.py b/re2o/templatetags/acl.py index fe13c5ac..9a439f88 100644 --- a/re2o/templatetags/acl.py +++ b/re2o/templatetags/acl.py @@ -79,7 +79,6 @@ from django.contrib.contenttypes.models import ContentType register = template.Library() - def get_model(model_name): """Retrieve the model object from its name""" splitted = model_name.split('.') diff --git a/re2o/urls.py b/re2o/urls.py index 87a5b346..d1e11d52 100644 --- a/re2o/urls.py +++ b/re2o/urls.py @@ -47,7 +47,7 @@ from django.conf.urls import include, url from django.contrib import admin from django.contrib.auth import views as auth_views -from .views import index, about_page +from .views import index, about_page, contact_page handler500 = 're2o.views.handler500' handler404 = 're2o.views.handler404' @@ -55,6 +55,7 @@ handler404 = 're2o.views.handler404' urlpatterns = [ url(r'^$', index, name='index'), url(r'^about/$', about_page, name='about'), + url(r'^contact/$', contact_page, name='contact'), url('^logout/', auth_views.logout, {'next_page': '/'}), url('^', include('django.contrib.auth.urls')), url(r'^i18n/', include('django.conf.urls.i18n')), diff --git a/re2o/views.py b/re2o/views.py index 9a9dec78..fb00b98e 100644 --- a/re2o/views.py +++ b/re2o/views.py @@ -36,6 +36,8 @@ from django.views.decorators.cache import cache_page from preferences.models import ( Service, + MailContact, + GeneralOption, AssoOption, HomeOption ) @@ -106,6 +108,21 @@ def about_page(request): } ) +def contact_page(request): + """The view for the contact page + Send all the objects MailContact + """ + address = MailContact.objects.all() + + return render( + request, + "re2o/contact.html", + { + 'contacts': address, + 'asso_name': AssoOption.objects.first().name + } + ) + def handler500(request): """The handler view for a 500 error""" diff --git a/templates/base.html b/templates/base.html index d6b03798..8a21a612 100644 --- a/templates/base.html +++ b/templates/base.html @@ -124,8 +124,12 @@ with this program; if not, write to the Free Software Foundation, Inc., {% acl_end %} -
  • - {% trans "About" %} +
  • {% if not request.user.is_authenticated %} {% if var_sa %}
    Url du compte twitter