...
 
Commits (10)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-12-29 12:54
from __future__ import unicode_literals
from django.db import migrations, models
import markdownx.models
class Migration(migrations.Migration):
dependencies = [
('articles', '0003_article_markdown_text'),
]
operations = [
migrations.AlterField(
model_name='article',
name='markdown_text',
field=markdownx.models.MarkdownxField(blank=True, null=True, verbose_name=b"Texte de l'article, en MarkDown"),
),
migrations.AlterField(
model_name='article',
name='texte',
field=models.TextField(blank=True, help_text=b"Ce texte peut-\xc3\xaatre formatt\xc3\xa9 librement en HTML.\n\xc3\x80 n'utiliser que si vous souhaitez avoir un contr\xc3\xb4le plus fin sur la mise en forme ;\nauquel cas, videz le champ \xc2\xab texte de l'article en markdown \xc2\xbb", max_length=10000, verbose_name=b"Texte de l'article, en HTML"),
),
]
#profile-group > h2:first-child,
#profile-0 h3:first-child {
display: none;
}
......@@ -569,7 +569,7 @@ h3 .plus {
}
.infocontact {
text-align: center;
text-align: left;
margin:100px 5% -20px 5%;
}
......@@ -583,6 +583,16 @@ h3 .plus {
padding:0;
}
.infocontact {
min-width: 30rem;
margin-left: 1rem;
}
.infocontact > p,
.infocontact > div {
margin-bottom: 1rem;
}
#savie img.portrait {
display: block;
margin-left: auto;
......
......@@ -14,7 +14,7 @@ class SubscriptionForm(forms.Form):
class RSSForm(SubscriptionForm):
pass
class EmailForm(SubscriptionForm):
class EmailForm(forms.Form):
email = forms.EmailField(widget=forms.TextInput(
attrs={'type': 'email', 'required': 'yes',
'placeholder': 'votre addresse mail'}))
......@@ -18,8 +18,6 @@ class EmailSubscriptionProcess(TestCase):
def test_double_optin_ok(self):
# require subscription
response = self.client.post('/abonnements/email/',{
'texts': 'ok',
'events': 'ok',
'email': 'f@example.com'
}, follow=True)
self.assertEqual(len(response.redirect_chain), 1)
......@@ -33,12 +31,10 @@ class EmailSubscriptionProcess(TestCase):
# get registered !
sub = EmailSubscription.objects.get(email='f@example.com')
self.assertEqual(sub.targets, 'texts+events')
self.assertEqual(sub.targets, 'texts')
def test_confirm_link_idempotence(self):
self.client.post('/abonnements/email/',{
'texts': 'ok',
'events': 'ok',
'email': 'f@example.com'
})
link = self.re_link.search(mail.outbox[0].body).group(0)
......@@ -49,12 +45,9 @@ class EmailSubscriptionProcess(TestCase):
def test_confirm_different_inscription_updates(self):
self.client.post('/abonnements/email/',{
'texts': 'ok',
'events': 'ok',
'email': 'f@example.com'
})
self.client.post('/abonnements/email/',{
'texts': 'ok',
'email': 'f@example.com'
})
......@@ -69,7 +62,7 @@ class EmailSubscriptionProcess(TestCase):
def test_unsubscription_ok(self):
sub = EmailSubscription.objects.create(email='sausage@example.com',
targets='paperbacks+texts')
targets='texts')
url = '/abonnements/email/desinscription/{}/'.format(
UnsubscriptionSigner.sign(1))
......
......@@ -31,7 +31,7 @@ def email_sub_process(request):
token = SubscriptionSigner.sign({
'type': 'email-subscription',
'addr': to_addr,
'subscriptions': form.enabled_options(),
'subscriptions': ['texts'],
})
validation_url = request.build_absolute_uri(
reverse('email-sub-validate', kwargs={'token': token}))
......
......@@ -31,10 +31,18 @@
</p>
{% endif %}
{% if object.profile.site_perso %}
{% if object.profile.website_url %}
<p>
<img src="{% static "icones/32x32/emblems/emblem-web.png" %}" alt="Contact mail:" />
<a href="{{object.profile.site_perso}}">{{object.profile.site_perso}}</a>
<a href="{{object.profile.website_url}}">
{% firstof object.profile.website_text object.profile.website_url %}
</a>
</p>
{% endif %}
{% if object.profile.newsletter_url %}
<p>
<img src="{% static "icones/32x32/emblems/emblem-mail.png" %}" alt="" />
<a href="{{object.profile.newsletter_url}}">{{object.profile.newsletter_text}}</a>
</p>
{% endif %}
<div class="abo-links central">
......@@ -46,10 +54,10 @@
<a class="email" title="Recevoir les nouveautés par email" href="#">
<img src="{% static "icones/32x32/emblems/emblem-mail.png" %}"
alt="Suivre l'auteur par mail" />
<span class="a-style">S'abonner…</span>
<span class="a-style">Suivre les nouveautés</span>
</a>
{% abo_forms pre_checked="paperbacks+events+texts"%}
</div>
</div>
</div>
......
......@@ -60,17 +60,30 @@
<li>
<a class="rss" title="S'abonner par flux RSS" href="#">
<img src="{% static "icones/128x128/emblems/RSS.png" %}"
alt="S'abonner par flux RSS" />
<span class="a-style">S'abonner par RSS</span>
alt="" />
<span class="a-style">Suivre par RSS</span>
</a>
</li>
<li>
<a class="email" title="Recevoir les nouveautés par email" href="#">
<img src="{% static "icones/32x32/emblems/emblem-mail.png" %}"
alt="Suivre l'auteur par mail" />
<span class="a-style">S'abonner par mail</span>
alt="" />
<span class="a-style">Suivre par email</span>
</a>
</li>
{% all_newsletters as newsletters %}
{% for newsletter in newsletters %}
<li>
<a class="email" title="S'ouvre dans une nouvelle fenêtre"
href="{{ newsletter.newsletter_url }}" target="_blank">
<img src="{% static "icones/32x32/emblems/emblem-mail.png" %}"
alt="" />
<span class="a-style">
{% firstof newsletter.newsletter_text newsletter.newsletter_url %}
</span>
</a>
</li>
{% endfor %}
</ul>
{% abo_forms pre_checked="paperbacks+events+texts"%}
......
{% load static %}
<div class="abo email" style="display: none;">
<p>Recevoir les nouveautés par email</p>
<p>Recevoir un email à chaque nouvelle parution d'un texte en ligne</p>
<form action="{% url "email-sub-process" %}" method="post">
<table>
{% for field in email_form %}
......
# -*- coding: utf-8 -*-
from texte.models import *
from django.contrib import admin
import django.contrib.auth.models
import django.contrib.auth.admin
from django.contrib.auth.models import User
from django.contrib.admin.widgets import AdminFileWidget
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from texte.models import (
AuteurExterne,
CategorieReferenceExterne,
Commentaire,
Genre,
Illustration,
Lien,
Licence,
Modele,
ProfilAuteur,
ReferenceExterne,
Section,
Texte,
)
from texte.templatetags import lvtags
# Widget that displays a miniature on ImageFields
# http://www.psychicorigami.com/2009/06/20/django-simple-admin-imagefield-thumbnail/
class AdminImageWidget(AdminFileWidget):
thumb_size = "700x400"
id="illustration"
id = "illustration"
def render(self, name, value, attrs=None):
output = []
if value and getattr(value, "url", None):
image_url = value.url
thumb_url = lvtags.thumbnail(image_url, self.thumb_size)
file_name=str(value)
file_name = str(value)
output.append(u'<input type="hidden" id="full_%s_width" value="%i"/><img id="%s" src="%s" alt="%s" /><br />' % \
(self.id, value.width, self.id, thumb_url, file_name))
output.append(super(AdminFileWidget, self).render(name, value, attrs))
return mark_safe(u''.join(output))
class AdminImageSquareWidget(AdminImageWidget):
thumb_size = "100x100"
id="square"
id = "square"
## Admin parameters
# Non utilisé pour l'instant
class ProfilAuteur_Inline(admin.StackedInline):
model=ProfilAuteur
model = ProfilAuteur
max_num = 1
extra = 1
can_delete = False
fieldsets = [
('Profil', {'fields': [
'photo',
'anniv',
'influences',
'hobies',
]}),
('Contact par mail', {'fields': [
'aut_email',
'aut_formulaire',
]}),
('site perso', {'fields': [
'website_url',
'website_text',
]}),
("newsletter de l'auteur", {'fields': [
'newsletter_url',
'newsletter_text',
]}),
('ailleurs sur le web', {'fields': [
'url_don',
]}),
]
class Media:
css = {
"all": ['style/custom_admin/profilauteur_inline.css']
}
class ProfilAuteurAdmin(django.contrib.auth.admin.UserAdmin):
inlines = (ProfilAuteur_Inline,)
inlines = [ProfilAuteur_Inline]
def get_fieldsets(self, *args, **kwargs):
# Collapse « dates importantes » and « permissions »
ret = super(ProfilAuteurAdmin, self).get_fieldsets(*args, **kwargs)
rw_ret = [
[fieldset[0], fieldset[1]]
for fieldset in ret
]
rw_ret[2][1]['classes'] = ('collapse',)
rw_ret[3][1]['classes'] = ('collapse',)
return rw_ret
class ReferenceExterne_Inline(admin.StackedInline):
model= ReferenceExterne
model = ReferenceExterne
num = 1
extra = 1
class TexteAdmin(admin.ModelAdmin):
class Media:
js = ("js/prototype.js","js/foreignImage.js")
list_display = ('titre','pub_date', 'auteur', 'nombre_com','bouton_compiler')
js = ("js/prototype.js", "js/foreignImage.js")
list_display = (
'titre',
'pub_date',
'auteur',
'nombre_com',
'bouton_compiler',
)
# FIXME: Come back to custom form
fieldsets = (
(None, {'fields': ('titre', 'pub_date')}),
('Contenu',{'fields':('fichier_source','resume')}),
('Métadonnées',{'fields':('illustration','licence','genre','tags')})
)
list_filter = ['auteur','pub_date','genre','est_publie','est_compile']
search_fields = ['titre','resume']
(None, {'fields': (
'titre',
'pub_date',
)}),
('Contenu', {'fields': (
'fichier_source',
'resume',
)}),
('Métadonnées', {'fields': (
'illustration',
'licence',
'genre',
'tags',
)}),
)
list_filter = ['auteur', 'pub_date', 'genre', 'est_publie', 'est_compile']
search_fields = ['titre', 'resume']
date_hierarchy = 'pub_date'
inlines = [ReferenceExterne_Inline]
# Ces deux méthodes sont redéfinies afin de permettre le choix de l'auteur automatique.
# Ces deux méthodes sont redéfinies afin de permettre le choix de l'auteur
# automatique.
def save_model(self, request, obj, form, change):
# Si l'objet est nouveau, on définit son auteur
......@@ -73,49 +145,49 @@ class TexteAdmin(admin.ModelAdmin):
obj.auteur = request.user
obj.save()
# J'ai commenté ce code, pas l'impression que ça soit utile
# (copier-coller d'un snippet ?)
# def save_formset(self, request, form, formset, change):
# def set_user(instance):
# instance.user = request.user
# instance.save()
# return formset.save()
class CommentaireAdmin(admin.ModelAdmin):
list_display = ('auteur','pub_date')
list_filter = ['auteur','pub_date']
search_fields = ['auteur','texte']
list_display = ('auteur', 'pub_date')
list_filter = ['auteur', 'pub_date']
search_fields = ['auteur', 'texte']
date_hierarchy = 'pub_date'
class IllustrationAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('fichier', 'square', 'square_size',
'square_x_pos', 'square_y_pos', 'auteur')
}),)
fieldsets = [
(None, {'fields': (
'fichier',
'square',
'square_size',
'square_x_pos',
'square_y_pos',
'auteur',
)}),
]
class Media:
css = {"all": ("style/admin-crop.css",)}
js = ("js/prototype.js","js/crop.js")
js = ("js/prototype.js", "js/crop.js")
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name in ('fichier', 'square'):
if db_field.name == 'fichier':
kwargs['widget'] = AdminImageWidget
else: # square
else: # square
kwargs['widget'] = AdminImageSquareWidget
try:
del kwargs['request']
except KeyError:
pass
return db_field.formfield(**kwargs)
return super(IllustrationAdmin,self).formfield_for_dbfield(db_field, **kwargs)
return super(IllustrationAdmin, self).formfield_for_dbfield(
db_field, **kwargs
)
admin.site.register(Genre)
admin.site.register(AuteurExterne)
admin.site.register(Texte,TexteAdmin)
admin.site.register(Texte, TexteAdmin)
admin.site.register(Commentaire, CommentaireAdmin)
admin.site.register(Section)
admin.site.register(Lien)
......@@ -124,5 +196,5 @@ admin.site.register(Modele)
admin.site.register(CategorieReferenceExterne)
admin.site.register(ReferenceExterne)
admin.site.register(Illustration, IllustrationAdmin)
admin.site.unregister(django.contrib.auth.models.User)
admin.site.register(django.contrib.auth.models.User, ProfilAuteurAdmin)
admin.site.unregister(User)
admin.site.register(User, ProfilAuteurAdmin)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-12-29 16:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('texte', '0004_auto_20180125_0952'),
]
operations = [
migrations.AddField(
model_name='profilauteur',
name='newsletter_text',
field=models.CharField(blank=True, default=b'', help_text=b"Adresse externe (ex: mailchimp). Laisser vide si pas de lettre d'info", max_length=100, verbose_name=b"Texte du lien d'abonnement \xc3\xa0 la lettre d'info de l'auteur"),
),
migrations.AddField(
model_name='profilauteur',
name='newsletter_url',
field=models.URLField(blank=True, default=b'', help_text=b"Laisser vide si pas de lettre d'info", verbose_name=b"URL d'abonnement \xc3\xa0 la lettre d'infos de l'auteur"),
),
migrations.AlterField(
model_name='profilauteur',
name='url_don',
field=models.URLField(blank=True, help_text=b'Permet de proposer au visiteur de vous faire un don (par exemple via paypal)', null=True, verbose_name=b'URL de don'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-12-29 16:56
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('texte', '0005_auto_20181229_1641'),
]
operations = [
migrations.RenameField(
model_name='profilauteur',
old_name='site_perso',
new_name='website_url',
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-12-29 16:58
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('texte', '0006_auto_20181229_1656'),
]
operations = [
migrations.AlterField(
model_name='profilauteur',
name='website_url',
field=models.URLField(blank=True, default=b'', help_text=b'\xe2\x80\xa6ou r\xc3\xa9seau social. Laisser vide si pas de site perso', null=True, verbose_name=b'URL du Site Perso '),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-12-29 17:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('texte', '0007_auto_20181229_1658'),
]
operations = [
migrations.AddField(
model_name='profilauteur',
name='website_text',
field=models.CharField(blank=True, default=b'', help_text=b"Si vide, l'URL sera utilis\xc3\xa9 en tant que texte", max_length=100, verbose_name=b'Texte du lien vers le site web'),
),
]
......@@ -59,13 +59,32 @@ class ProfilAuteur(models.Model):
aut_formulaire = models.BooleanField('Formulaire de contact',
default=True,
help_text="Si cette option est activée, les visiteurs pourront vous envoyer des mails à travers un formulaire en ligne, ils ne verront pas votre véritable adresse")
site_perso = models.URLField("Site Perso",blank=True,null=True)
website_url = models.URLField(
"URL du Site Perso ",
help_text="…ou réseau social. Laisser vide si pas de site perso",
blank=True, null=True, default='',
)
website_text = models.CharField(
"Texte du lien vers le site web",
help_text="Si vide, l'URL sera utilisé en tant que texte",
blank=True, null=False, default='', max_length=100,
)
newsletter_url = models.URLField(
"URL d'abonnement à la lettre d'infos de l'auteur",
help_text="Laisser vide si pas de lettre d'info",
blank=True, null=False, default='',
)
newsletter_text = models.CharField(
"Texte du lien d'abonnement à la lettre d'info de l'auteur",
help_text="Adresse externe (ex: mailchimp). Laisser vide si pas de lettre d'info",
blank=True, null=False, default='', max_length=100)
complement = models.TextField("Description",
max_length=800,
blank=True,
null=True,
help_text="Un petit texte de quelques lignes qui sera affiché à côté de vos textes")
url_don = models.URLField('Url de don',
url_don = models.URLField('URL de don',
blank=True,null=True,
help_text="Permet de proposer au visiteur de vous faire un don (par exemple via paypal)")
......
......@@ -386,4 +386,10 @@ def plaintext(html):
def absolutize(path):
""" Adds domain and protocol to url
"""
return urlparse.urljoin(settings.SITE_URL,path)
return urlparse.urljoin(settings.SITE_URL, path)
@register.simple_tag
def all_newsletters():
profiles_qs = texte.models.ProfilAuteur.objects.exclude(newsletter_url='')
return profiles_qs.values('newsletter_url', 'newsletter_text')