diff --git a/odevzdavatko/templates/odevzdavatko/detail.html b/odevzdavatko/templates/odevzdavatko/detail.html
index 06f69609..73265563 100644
--- a/odevzdavatko/templates/odevzdavatko/detail.html
+++ b/odevzdavatko/templates/odevzdavatko/detail.html
@@ -1,6 +1,7 @@
{% extends "base.html" %}
{% load static %}
{% load deadliny %}
+{% load mail %}
{% block content %}
@@ -14,7 +15,14 @@
{% if edit %}
Řešitelé:
- {% for r in object.resitele.all %}{{ r }} ({{ r.osoba.email }}){% if forloop.revcounter0 != 0 %}, {% endif %}{% endfor %}
+ {% for r in object.resitele.all %}
+ {{ r }}
+ {# DjangoTemplates neumí spojovat řetězce (https://stackoverflow.com/q/4386168), tak si necháváme vyrobit subject mailu ve view. #}
+ ({% maillink r.osoba.email to=r.osoba.email subject=predmetmailu %}){% if forloop.revcounter0 != 0 %}, {% endif %}
+ {% endfor %}
+
+
+ {% maillink "Poslat mail všem řešitelům" bcc=maily_vsech_resitelu subject=predmetmailu %}
{% else %}
Řešitelé: {{ object.resitele.all | join:", " }}
diff --git a/odevzdavatko/views.py b/odevzdavatko/views.py
index 0100ef24..9ac1ac29 100644
--- a/odevzdavatko/views.py
+++ b/odevzdavatko/views.py
@@ -235,8 +235,12 @@ class DetailReseniView(DetailView):
def get_context_data(self, **kw):
self.check_access()
ctx = super().get_context_data(**kw)
- hodnoceni = self.aktualni_hodnoceni()
- ctx["hodnoceni"] = hodnoceni
+ detaily_hodnoceni = self.aktualni_hodnoceni()
+ ctx["hodnoceni"] = detaily_hodnoceni
+
+ # Subject případného mailu (template neumí použitelně spojovat řetězce: https://stackoverflow.com/q/4386168)
+ ctx["predmetmailu"] = "Oprava řešení M&M "+self.reseni.problem.first().hlavni_problem.nazev
+ ctx["maily_vsech_resitelu"] = [y for x in self.reseni.resitele.all().values_list('osoba__email') for y in x]
return ctx
def get(self, request, *args, **kwargs):
diff --git a/various/templatetags/__init__.py b/various/templatetags/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/various/templatetags/mail.py b/various/templatetags/mail.py
new file mode 100644
index 00000000..ecbb2a39
--- /dev/null
+++ b/various/templatetags/mail.py
@@ -0,0 +1,48 @@
+from django import template
+from django.utils.safestring import mark_safe
+from urllib.request import quote as urlencode
+register = template.Library()
+
+@register.simple_tag
+def mailurl(*, subject=None, body=None, to=[], cc=[], bcc=[]):
+ """Tag na vytváření správně zakódované mailto: adresy
+
+ Ref: RFC 6068, """
+ if isinstance(to, str):
+ to = [to]
+ if isinstance(cc, str):
+ cc = [cc]
+ if isinstance(bcc, str):
+ bcc = [bcc]
+ assert isinstance(to, list)
+ assert isinstance(cc, list)
+ assert isinstance(bcc, list)
+ # FIXME: adresa není správně zakódovaná, rozbije se to na adresách s divnými znaky
+ parts = [
+ f'mailto:{str.join(",", to)}',
+ ]
+ if len(to) + len(cc) + len(bcc) < 1:
+ raise ValueError('Cannot mail to empty set of people')
+
+ if subject:
+ parts.append(f'subject={urlencode(subject)}')
+ if body:
+ parts.append(f'body={urlencode(body)}')
+ if len(cc) > 0:
+ parts.append(f'cc={str.join(",", cc)}')
+ if len(bcc) > 0:
+ parts.append(f'bcc={str.join(",", bcc)}')
+
+ if len(parts) > 1:
+ url = parts[0] + '?' + str.join('&', parts[1:])
+ else:
+ url = parts[0]
+ return url
+
+@register.simple_tag
+def maillink(text, subject=None, body=None, to=[], cc=[], bcc=[], attrs=None):
+ url = mailurl(subject=subject, body=body, to=to, cc=cc, bcc=bcc)
+ if not attrs: attrs = ''
+ mezera = ' '*bool(attrs)
+ full_link = f'{text}'
+ return mark_safe(full_link)
diff --git a/various/tests.py b/various/tests.py
index 7ce503c2..0abf4e26 100644
--- a/various/tests.py
+++ b/various/tests.py
@@ -1,3 +1,60 @@
from django.test import TestCase
+# TODO: Možná vyrobit separátní soubory v tests/… než mít všechny testy v jednom souboru?
+from various.templatetags.mail import maillink, mailurl
-# Create your tests here.
+class MailTagsTest(TestCase):
+ """Testuje template tagy ohledně mailů."""
+ def test_maillink(self):
+ # Tohle nedává smysl dělit do víc funkcí, bylo by v nich víc boilerplatu než užitečného kódu.
+ self.assertEquals(maillink('Hello', to='some@body.test'), r'Hello')
+ self.assertEquals(maillink('Hello', to=['some@body.test']), r'Hello')
+ self.assertEquals(
+ maillink('Hello', to=['alice@test.test', 'bob@jinde.test']),
+ r'Hello',
+ )
+ self.assertEquals(
+ maillink('Hello', to='some@body.test', attrs='class="trida" id="id"'),
+ r'Hello',
+ )
+ # Následující test toho testuje moc zároveň, měly by předcházet dedikované testy… (kašlu na ně :-P)
+ self.assertEquals(
+ maillink('Text odkazu', to='prijemce@wtf.test', subject="Předmět", body="Čau"),
+ r'Text odkazu',
+ )
+ self.assertRaises(ValueError, lambda: maillink('Nemám příjemce'))
+ self.assertRaises(TypeError, lambda: maillink()) # Nemá text, takže to shodí python
+
+ def test_mailurl(self):
+ self.assertEquals(mailurl(to='some@body.test'), r'mailto:some@body.test')
+ self.assertEquals(mailurl(to=['some@body.test']), r'mailto:some@body.test')
+ self.assertEquals(mailurl(to=['alice@test.test', 'bob@jinde.test']), r'mailto:alice@test.test,bob@jinde.test')
+ self.assertEquals(
+ mailurl(to='some@body.test', body='Tělo', subject='Předmět'),
+ r'mailto:some@body.test?subject=P%C5%99edm%C4%9Bt&body=T%C4%9Blo',
+ )
+ self.assertRaises(ValueError, lambda: mailurl())
+
+ def test_render_in_template(self):
+ # Pomocná funkce: vykreslí template do stringu
+ # Ref: https://stackoverflow.com/a/1690879
+ def render_template(template, context=None):
+ from django.template import Template, Context
+ context = context or {}
+ context = Context(context)
+ return Template(template).render(context)
+
+ template = (
+ r'{% load mail %}'
+ # TODO: Vyzkoušet i víc adresátů. (Nepamatuji si z hlavy syntaxi…)
+ r'{% maillink "Text" to="alice@test.test" subject="Oprava řešení" %}'
+ )
+ self.assertEquals(
+ render_template(template),
+ r'Text',
+ )
+
+ mailurltemplate = (
+ r'{% load mail %}'
+ r'{% mailurl to="alice@test.test" subject="Čau Alice" %}'
+ )
+ self.assertEquals(render_template(mailurltemplate), r'mailto:alice@test.test?subject=%C4%8Cau%20Alice')