diff --git a/src/api/locale/de/LC_MESSAGES/django.po b/src/api/locale/de/LC_MESSAGES/django.po index 73f7bdac20b1c17c33b2aa8787d0af9422c4c0c7..27bdfd43b901790187d5ba1ceec8085e98b41654 100644 --- a/src/api/locale/de/LC_MESSAGES/django.po +++ b/src/api/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-10 08:21+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/src/api/locale/en/LC_MESSAGES/django.po b/src/api/locale/en/LC_MESSAGES/django.po index ed3dbd1c3f568cb336fb887ebc297113f4fd79b5..80983e5cc566c9c5a8199ba352bcd2e62af0c353 100644 --- a/src/api/locale/en/LC_MESSAGES/django.po +++ b/src/api/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-10 08:21+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po index abe2df9d02dbf0befb6e4502031ca6ee780d399c..993dc437c762ef9ae369fa46579a8fdf13a1f04a 100644 --- a/src/backoffice/locale/de/LC_MESSAGES/django.po +++ b/src/backoffice/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-17 23:03+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -603,18 +603,14 @@ msgstr "Der Raum konnte nicht gelöscht werden da noch Veranstaltungen vorhanden msgid "lists" msgstr "Listen" -msgid "nav_assemblies_all" -msgstr "alle" +#, fuzzy +#| msgid "nav_assemblies" +msgid "nav_assemblies_" +msgstr "Assembly-Team" msgid "nav_assemblies_accepted" msgstr "akzeptiert" -msgid "nav_assemblies_pending" -msgstr "wartend" - -msgid "nav_assemblies_rejected" -msgstr "abgelehnt" - # use translation from core msgid "Assembly__slug" msgstr "" @@ -628,3 +624,12 @@ msgstr "Dieser Kurzname wird bereits verwendet." msgid "userprofile_updated" msgstr "Benutzerprofil aktualisiert" + +#~ msgid "nav_assemblies_all" +#~ msgstr "alle" + +#~ msgid "nav_assemblies_pending" +#~ msgstr "wartend" + +#~ msgid "nav_assemblies_rejected" +#~ msgstr "abgelehnt" diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po index f1ee9d843c6bb32721b937118e0547551edb6591..2c63c41443df318a8b1e45525bc144cb65c1d925 100644 --- a/src/backoffice/locale/en/LC_MESSAGES/django.po +++ b/src/backoffice/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-17 23:03+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -604,18 +604,14 @@ msgstr "Could not remove the room as it has at least one event assigned to it. P msgid "lists" msgstr "lists" -msgid "nav_assemblies_all" -msgstr "all" +#, fuzzy +#| msgid "nav_assemblies" +msgid "nav_assemblies_" +msgstr "assemblies team" msgid "nav_assemblies_accepted" msgstr "accepted" -msgid "nav_assemblies_pending" -msgstr "pending" - -msgid "nav_assemblies_rejected" -msgstr "rejected" - # use translation from core msgid "Assembly__slug" msgstr "" @@ -628,3 +624,12 @@ msgstr "This slug is already in use on another page." msgid "userprofile_updated" msgstr "user profile updated" + +#~ msgid "nav_assemblies_all" +#~ msgstr "all" + +#~ msgid "nav_assemblies_pending" +#~ msgstr "pending" + +#~ msgid "nav_assemblies_rejected" +#~ msgstr "rejected" diff --git a/src/backoffice/templates/backoffice/assembly_editlinks.html b/src/backoffice/templates/backoffice/assembly_editlinks.html index ee445d6bd7c23b16463d8baf58d4b3b21c940e4b..debb0553780072833fb7b90253584f6ae26a411e 100644 --- a/src/backoffice/templates/backoffice/assembly_editlinks.html +++ b/src/backoffice/templates/backoffice/assembly_editlinks.html @@ -48,7 +48,7 @@ <ul> {% for link in links %} <li> - {{ link.name }} + {{ link.name }} (Slug: {{ link.slug }}) <form action="{% url 'backoffice:assembly-editlinks' pk=assembly.id %}" method="POST">{% csrf_token %} <input type="hidden" name="delete" value="{{ link.pk }}"> <button type="submit" class="btn btn-sm btn-secondary">{% trans 'delete' %}</button> diff --git a/src/core/locale/de/LC_MESSAGES/django.po b/src/core/locale/de/LC_MESSAGES/django.po index 240ae6580ac01f9fbabb20746156e7d580db8833..48531000d4bdf7fa9f3635fa97526ef597d1749d 100644 --- a/src/core/locale/de/LC_MESSAGES/django.po +++ b/src/core/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-17 23:03+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/src/core/locale/en/LC_MESSAGES/django.po b/src/core/locale/en/LC_MESSAGES/django.po index 2937a6cfc20bf2271083815c5a0c3c034100db08..59e4434d80f5422bcbe4cef579b897709f32b33b 100644 --- a/src/core/locale/en/LC_MESSAGES/django.po +++ b/src/core/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-17 23:03+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/src/core/management/commands/rerender_markdown.py b/src/core/management/commands/rerender_markdown.py new file mode 100644 index 0000000000000000000000000000000000000000..3f22ef77c34e86363105d582fb037b6c9bae8e6f --- /dev/null +++ b/src/core/management/commands/rerender_markdown.py @@ -0,0 +1,34 @@ +from django.core.management.base import BaseCommand + +from core.models import Event, Room, Assembly, PlatformUser, StaticPage +from core.utils import render_markdown + + +class Command(BaseCommand): + def handle(self, *args, **options): + for event in Event.objects.all(): + event.description_html = render_markdown(event.description) + event.save(update_fields=['description_html']) + + for room in Room.objects.all(): + room.description_html = render_markdown(room.description) if room.description is not None else None + room.save(update_fields=['description_html']) + + for assembly in Assembly.objects.all(): + assembly.description_html = render_markdown(assembly.description) if assembly.description is not None else None + assembly.save(update_fields=['description_html']) + + for user in PlatformUser.objects.all(): + user.description_html = render_markdown(user.description) if user.description is not None else None + user.save(update_fields=['description_html']) + + for page in StaticPage.objects.all(): + if page.public_revision > 0: + public_page = page.revisions.filter(revision=page.public_revision).first() + if public_page is None: + page.rendered_body = '' + else: + page.rendered_body = render_markdown(public_page.body) + else: + page.rendered_body = '' + page.save(update_fields=['rendered_body']) diff --git a/src/core/migrations/0041_description_html_fields1.py b/src/core/migrations/0041_description_html_fields1.py new file mode 100644 index 0000000000000000000000000000000000000000..181b789aafed23c535d01d3eee26c59674a5b96f --- /dev/null +++ b/src/core/migrations/0041_description_html_fields1.py @@ -0,0 +1,34 @@ +# Generated by Django 3.1.4 on 2020-12-23 12:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0040_room_reserve_capacity'), + ] + + operations = [ + migrations.AddField( + model_name='assembly', + name='description_html', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='event', + name='description_html', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + migrations.AddField( + model_name='platformuser', + name='description_html', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='room', + name='description_html', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/src/core/migrations/0042_description_html_fields2.py b/src/core/migrations/0042_description_html_fields2.py new file mode 100644 index 0000000000000000000000000000000000000000..581423e0170d98765d43e6328dba9b423142579e --- /dev/null +++ b/src/core/migrations/0042_description_html_fields2.py @@ -0,0 +1,50 @@ +# Generated by Django 3.1.4 on 2020-12-23 13:00 + +from django.db import migrations +from core.utils import render_markdown + + +def do(apps, schema_editor): + Event = apps.get_model('core', 'Event') + Room = apps.get_model('core', 'Room') + Assembly = apps.get_model('core', 'Assembly') + PlatformUser = apps.get_model('core', 'PlatformUser') + StaticPage = apps.get_model('core', 'StaticPage') + + for event in Event.objects.all(): + event.description_html = render_markdown(event.description) + event.save(update_fields=['description_html']) + + for room in Room.objects.all(): + room.description_html = render_markdown(room.description) if room.description is not None else None + room.save(update_fields=['description_html']) + + for assembly in Assembly.objects.all(): + assembly.description_html = render_markdown(assembly.description) if assembly.description is not None else None + assembly.save(update_fields=['description_html']) + + for user in PlatformUser.objects.all(): + user.description_html = render_markdown(user.description) if user.description is not None else None + user.save(update_fields=['description_html']) + + for page in StaticPage.objects.all(): + if page.public_revision > 0: + public_page = page.revisions.filter(revision=page.public_revision).first() + if public_page is None: + page.rendered_body = '' + else: + page.rendered_body = render_markdown(public_page.body) + else: + page.rendered_body = '' + page.save(update_fields=['rendered_body']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0041_description_html_fields1'), + ] + + operations = [ + migrations.RunPython(do, migrations.RunPython.noop, elidable=True) + ] diff --git a/src/core/models/assemblies.py b/src/core/models/assemblies.py index a3264330fefe8625750f97174aa0ba796962b193..9637928f10197af33d6ab110bee782372dc218c4 100644 --- a/src/core/models/assemblies.py +++ b/src/core/models/assemblies.py @@ -155,6 +155,7 @@ class Assembly(TaggedItemMixin, models.Model): blank=True, null=True, help_text=_('Assembly__description__help'), verbose_name=_('Assembly__description')) + description_html = models.TextField(blank=True, null=True) registration_details = models.TextField( blank=True, null=True, help_text=_('Assembly__registration_details__help'), @@ -251,27 +252,6 @@ class Assembly(TaggedItemMixin, models.Model): def conference_slug(self): return self.conference.slug - @cached_property - def description_html(self): - if self.description is None: - return None - return render_markdown(self.description) - - # # we safely replace double linebreaks into html paragraphs - # description_parts = re.split(r'\r?\n\r?\n', obj.description or '') - # obj.description_html = mark_safe('<p>') - # for partidx, part in enumerate(description_parts): - # if partidx > 0: - # obj.description_html += mark_safe('</p>\n<p>') - # if part.startswith('# ') and '\n' not in part: - # obj.description_html += format_html('<h3>{0}</h3>', part[2:]) - # else: - # escaped = html_escape(part) - # escaped = re.sub(r'\*([\w\d() ]+)\*', lambda x: format_html('<b>{}</b>', x.group(1)), escaped) - # escaped = re.sub(r'__([\w\d() ]+)__', lambda x: format_html('<i>{}</i>', x.group(1)), escaped) - # obj.description_html += mark_safe(escaped) - # obj.description_html += mark_safe('</p>') - @cached_property def description_html_short(self): if not self.description: @@ -348,6 +328,15 @@ class Assembly(TaggedItemMixin, models.Model): return self.members.filter(member=user, role__in=AssemblyMember.MANAGEMENT_ROLES).exists() + def save(self, *args, update_fields=None, **kwargs): + if update_fields is None or 'description' in update_fields: + if self.description is None: + self.description_html = None + else: + self.description_html = render_markdown(self.description) + + return super().save(*args, update_fields=update_fields, **kwargs) + class AssemblyLinkManager(models.Manager): def accessible_by_user(self, user: PlatformUser, conference: Conference): diff --git a/src/core/models/events.py b/src/core/models/events.py index 585bb31d10226f86a0c7fb539d79a4506d8f3bd4..611a095d0d4659fc2b5d994433d5c87e3ee9fc0b 100644 --- a/src/core/models/events.py +++ b/src/core/models/events.py @@ -4,7 +4,6 @@ from uuid import uuid4 from django.conf import settings from django.core.exceptions import ValidationError from django.db import models -from django.utils.functional import cached_property from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ @@ -116,6 +115,7 @@ class Event(TaggedItemMixin, models.Model): blank=True, help_text=_('Event__description__help'), verbose_name=_('Event__description')) + description_html = models.TextField(blank=True) banner_image_height = models.PositiveIntegerField(blank=True, null=True) banner_image_width = models.PositiveIntegerField(blank=True, null=True) banner_image = models.ImageField( @@ -168,10 +168,6 @@ class Event(TaggedItemMixin, models.Model): Ersteller/Eigentümer des Events, dies ist insb. für Self-Organized-Sessions relevant. """ - @cached_property - def description_html(self): - return render_markdown(self.description) - @property def public_speakers(self): """Returns a list of all public speakers of this event.""" @@ -231,7 +227,7 @@ class Event(TaggedItemMixin, models.Model): if errors: raise ValidationError(errors) - def save(self, *args, **kwargs): + def save(self, *args, update_fields=None, **kwargs): if self.schedule_start is not None and self.schedule_duration is not None: self.schedule_end = self.schedule_start + self.schedule_duration else: @@ -242,7 +238,10 @@ class Event(TaggedItemMixin, models.Model): while Assembly.objects.filter(conference=self.conference, slug=self.slug).exclude(pk=self.pk).exists(): self.slug = gen_slug[:45] + '_' + ''.join([random.SystemRandom().choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(4)]) - return super().save(*args, **kwargs) + if update_fields is None or 'description' in update_fields: + self.description_html = render_markdown(self.description) + + return super().save(*args, update_fields=update_fields, **kwargs) @property def conference_slug(self): diff --git a/src/core/models/rooms.py b/src/core/models/rooms.py index 1786968953afdb7b946384c0d45a77398591a2c1..9d6a7fbee27a1d2d363861e87dd3fc9cee8d33cf 100644 --- a/src/core/models/rooms.py +++ b/src/core/models/rooms.py @@ -3,7 +3,6 @@ from uuid import uuid4 from django.core.exceptions import ValidationError from django.core.validators import URLValidator from django.db import models -from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ from ..fields import ConferenceReference @@ -117,6 +116,7 @@ class Room(models.Model): help_text=_('Room__description__help'), verbose_name=_('Room__description')) """Description of the room/project.""" + description_html = models.TextField(blank=True, null=True) room_type = models.CharField(max_length=20, choices=RoomType.choices, help_text=_('Room__type__help'), verbose_name=_('Room__type')) """Style of the room.""" @@ -159,10 +159,6 @@ class Room(models.Model): def conference_slug(self): return self.conference.slug - @cached_property - def description_html(self): - return render_markdown(self.description) - @property def assembly_slug(self): return self.assembly.slug if self.assembly is not None else None @@ -171,6 +167,15 @@ class Room(models.Model): def has_backend(self): return self.room_type in self.BACKEND_ROOMTYPES + def save(self, *args, update_fields=None, **kwargs): + if update_fields is None or 'description' in update_fields: + if self.description is None: + self.description_html = None + else: + self.description_html = render_markdown(self.description) + + return super().save(*args, update_fields=update_fields, **kwargs) + class RoomLink(models.Model): class LinkType(models.TextChoices): diff --git a/src/core/models/users.py b/src/core/models/users.py index 1f4b001481f36c98fe3dedb40a7d68730c08b332..39b31aa9fc9efc607f0294cb49ea118795c714eb 100644 --- a/src/core/models/users.py +++ b/src/core/models/users.py @@ -57,6 +57,7 @@ class PlatformUser(AbstractUser): blank=True, null=True, help_text=_('PlatformUser__description__help'), verbose_name=_('PlatformUser__description')) + description_html = models.TextField(blank=True, null=True) status = models.CharField( max_length=50, blank=True, null=True, @@ -144,10 +145,6 @@ class PlatformUser(AbstractUser): return AnonUser() - @cached_property - def description_html(self): - return render_markdown(self.description) - def is_conference_staff(self, conference): return conference.users.filter(user=self, is_staff=True).exists() @@ -165,6 +162,15 @@ class PlatformUser(AbstractUser): except ObjectDoesNotExist: return None + def save(self, *args, update_fields=None, **kwargs): + if update_fields is None or 'description' in update_fields: + if self.description is None: + self.description_html = None + else: + self.description_html = render_markdown(self.description) + + return super().save(*args, update_fields=update_fields, **kwargs) + def has_conference_staffpermission(self, conference, *perms, need_all=False): """ Returns True if this user is a staff member of the given conference and has, diff --git a/src/core/tests/__init__.py b/src/core/tests/__init__.py index 94ef1205a4db88b070cc556e147c8074bdcfc998..17e18123c9d048c0329304b2f2fddf9c2b55cc0d 100644 --- a/src/core/tests/__init__.py +++ b/src/core/tests/__init__.py @@ -3,5 +3,6 @@ from .search import * # noqa: F401, F403 from .users import * # noqa: F401, F403 from .tags import * # noqa: F401, F403 from .tickets import * # noqa: F401, F403 +from .markdown import * # noqa: F401, F403 __all__ = '*' diff --git a/src/core/tests/markdown.py b/src/core/tests/markdown.py new file mode 100644 index 0000000000000000000000000000000000000000..5e1d4a836d5e1bd3578ca37c74e665c9d9960b3d --- /dev/null +++ b/src/core/tests/markdown.py @@ -0,0 +1,36 @@ +from django.test import TestCase + +from ..utils import render_markdown + + +class MarkdownTest(TestCase): + def test_url_class(self): + tests = [ + ('https://localhost/', False), + ('https://localhost/foo', False), + ('https://localhost/foo/', False), + ('https://localhost/foo.bar', False), + ('https://some.test/', False), + ('https://some.test/foo', False), + ('https://some.test/foo.bar', False), + ('/foo/bar', True), + ('foo/bar', True), + ('asdf', True), + ('https://rc3.world/', True), + ('https://rc3.world/foo', True), + ('https://rc3.world/foo.bar', True), + ] + for test_url, should_be_local in tests: + with self.subTest(test_url): + class_ = 'internal' if should_be_local else 'external' + self.assertEqual(render_markdown(f'[.]({test_url})'), f'<p><a class="{class_}" href="{test_url}">.</a></p>') + self.assertEqual(render_markdown(f'[.][1]\n\n[1]: {test_url}'), f'<p><a class="{class_}" href="{test_url}">.</a></p>') + + forbidden = [ + 'data:text/html;charset=utf-8;base64,PGh0bWw+PGhlYWQ+PHRpdGxlPnRlc3Q8L3RpdGxlPjwvaGVhZD48Ym9keT48aDE+VGVzdDwvaDE+PC9ib2R5PjwvaHRtbD4=', + 'javascript:alert(1)', + ] + for test_url in forbidden: + with self.subTest(test_url): + self.assertEqual(render_markdown(f'[.]({test_url})'), '<p><a class="external">.</a></p>') + self.assertEqual(render_markdown(f'[.][1]\n\n[1]: {test_url}'), '<p><a class="external">.</a></p>') diff --git a/src/core/utils.py b/src/core/utils.py index 315e7bdfcf3c2114bceb3cdf3001eeab28781190..d2621b93f12947bda69b20a8063571e87bef5a0c 100644 --- a/src/core/utils.py +++ b/src/core/utils.py @@ -1,7 +1,11 @@ +import bleach from django.utils.html import strip_tags from django.utils.safestring import mark_safe import markdown +from markdown.extensions import Extension as MarkdownExtension +from markdown.inlinepatterns import LinkInlineProcessor, LINK_RE, ReferenceInlineProcessor, REFERENCE_RE import random +from urllib.parse import urlparse MARKDOWN_EXTENSIONS = [ @@ -13,8 +17,49 @@ MARKDOWN_EXTENSIONS = [ TOKEN_CHARSET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +def _mark_link_tag(el): + url = urlparse(el.get('href')) + is_local_domain = url.netloc == 'rc3.world' + class_ = 'external' if (url.scheme or url.netloc) and not is_local_domain else 'internal' + el.set('class', class_) + + +class CustomLinkInlineProcessor(LinkInlineProcessor): + def handleMatch(self, m, data): + el, start, idx = super().handleMatch(m, data) + if el is None: + return el, start, idx + + _mark_link_tag(el) + + return el, start, idx + + +class CustomReferenceInlineProcessor(ReferenceInlineProcessor): + def makeTag(self, href, title, text): + el = super().makeTag(href, title, text) + _mark_link_tag(el) + return el + + +class ConferenceLinkExtension(MarkdownExtension): + def extendMarkdown(self, md: markdown.Markdown): + md.inlinePatterns.register(CustomLinkInlineProcessor(LINK_RE, md), 'link', 160) + md.inlinePatterns.register(CustomReferenceInlineProcessor(REFERENCE_RE, md), 'reference', 170) + + def render_markdown(markup: str): - rendered_markup = markdown.markdown(strip_tags(markup), extensions=MARKDOWN_EXTENSIONS) + rendered_markup = markdown.markdown(strip_tags(markup), extensions=[ConferenceLinkExtension()] + MARKDOWN_EXTENSIONS) + + cleaner = bleach.Cleaner( + tags=['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'dl', 'table', 'th', 'td', 'tr', 'hr', 'p', 'pre'] + bleach.sanitizer.ALLOWED_TAGS, + attributes={ + '*': ['class'], + **bleach.sanitizer.ALLOWED_ATTRIBUTES, + }, + protocols=['http', 'https', 'mailto', 'ftp', 'ftps'] + ) + return mark_safe(cleaner.clean(rendered_markup)) return mark_safe(rendered_markup) diff --git a/src/plainui/jinja2/plainui/assembly.html b/src/plainui/jinja2/plainui/assembly.html index 4b0e54be882192a7080c05db238532b5a7726bb6..87d4043af98ecf7590844bc2c752e3fd7c6ab6bf 100644 --- a/src/plainui/jinja2/plainui/assembly.html +++ b/src/plainui/jinja2/plainui/assembly.html @@ -24,7 +24,7 @@ {{- markdownMacro.markdown(markdown=assembly.description_html | safe) -}} <hr> {% endif %} - <a class="col-auto" href="{{ url('plainui:assemblies_all', conf_slug=conf.slug) }}">all assmeblies</a> + <a class="col-auto" href="{{ url('plainui:assemblies_all', conf_slug=conf.slug) }}">all assemblies</a> <a href="{{ url('plainui:assemblies', conf_slug=conf.slug) }}"> assemblies start seite </a> @@ -46,7 +46,7 @@ <hr class="my-5 border-tertiary"> - <h2>{{ _("assmebly events") }}</h2> + <h2>{{ _("assembly events") }}</h2> <div class="border border-tertiary p-6"> {{ list_events.tiles(events, is_favorite_events, is_scheduled_events ) }} </div> diff --git a/src/plainui/jinja2/plainui/component_gallery.html b/src/plainui/jinja2/plainui/component_gallery.html index 85c87ff0c60cb211e432685717c9dd60721f373e..1b9c9fb150a7a9209fc043731ade2c322e912fb1 100644 --- a/src/plainui/jinja2/plainui/component_gallery.html +++ b/src/plainui/jinja2/plainui/component_gallery.html @@ -26,9 +26,9 @@ {% set event2 = {"id": "2", "name": "event example 2", "slug": "event_slug2", "banner_image": {"url": image_url}, "schedule_start": time1, "schedule_end": time2, "schedule_duration": duration, "description": "Lorem Ipsum ...", "language": "de" } %} {% set events = [ event1, event2 ] %} -{% set assmebly1 = {"id": "1", "name": "assembly example 1", "slug": "assembly_slug1", "is_official": false,"banner_image": {"url": image_url}, "description": "Lorem Ipsum ..." } %} +{% set assembly1 = {"id": "1", "name": "assembly example 1", "slug": "assembly_slug1", "is_official": false,"banner_image": {"url": image_url}, "description": "Lorem Ipsum ..." } %} {% set assembly2 = {"id": "2", "name": "assembly example 2 - official", "slug": "assembly_slug2", "is_official": true, "banner_image": {"url": image_url}, "description": "Lorem Ipsum ..." } %} -{% set assemblies = [ assmebly1, assembly2 ] %} +{% set assemblies = [ assembly1, assembly2 ] %} {% block content %} @@ -46,7 +46,7 @@ <dt class="h2 pb-3 mb-3 border-bottom">title</dt> <dd class="mb-10"> - {{ titleMacro.title(title="Fantastic Headline", fav_id="12345", fav_type="assmebly", fav_is=true, sch_id="12345", sch_is=true, share_url="url", stream_url="url", report_url="url") }} + {{ titleMacro.title(title="Fantastic Headline", fav_id="12345", fav_type="assembly", fav_is=true, sch_id="12345", sch_is=true, share_url="url", stream_url="url", report_url="url") }} </dd> <dt class="h2 pb-3 mb-3 border-bottom">Markdown</dt> diff --git a/src/plainui/jinja2/plainui/fahrplan.html b/src/plainui/jinja2/plainui/fahrplan.html index 53ca262ca155e1a4d8ed3d5a82458cee38cd5df2..7bcc38d6ed711652eaa0a7a739a3bb31743eebdd 100644 --- a/src/plainui/jinja2/plainui/fahrplan.html +++ b/src/plainui/jinja2/plainui/fahrplan.html @@ -34,7 +34,7 @@ <button type="submit" name="set" value="fday" class="m-2 btn btn-primary {{ 'active' if show_day_filters }}">{{ _("by day") }}</button> <button type="submit" name="set" value="ftrack" class="m-2 btn btn-primary {{ 'active' if show_track_filters }}">{{ _("by track") }}</button> <button type="submit" name="set" value="curated" class="m-2 btn btn-primary {{ 'active' if curated }}">{{ _("curated only") }}</button> - {# Assembly events are displayed on assmbly page. filter here by assmebly will mean display serveral hundred assmeblies. leave for the future + {# Assembly events are displayed on assmbly page. filter here by assembly will mean display serveral hundred assemblies. leave for the future <button type="submit" name="set" value="fassembly" class="m-2 btn btn-primary {{ 'active' if show_assembly_filters }}">Assembly</button> #} </div> diff --git a/src/plainui/locale/de/LC_MESSAGES/django.po b/src/plainui/locale/de/LC_MESSAGES/django.po index e885b2f94d406f5a767bb350377cc3e206d88923..6db239aa764d496379c83b6f11b5c8ffc144e230 100644 --- a/src/plainui/locale/de/LC_MESSAGES/django.po +++ b/src/plainui/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-06 15:26+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -21,57 +21,120 @@ msgstr "" msgid "Unknown User!" msgstr "" -msgid "Assemblies" +msgid "Please enter the recipient name" +msgstr "" + +msgid "Please enter a subject" +msgstr "" + +msgid "Please enter a title" +msgstr "" + +msgid "Placeholder text" +msgstr "" + +msgid "blocked" +msgstr "" + +msgid "Please enter a name" +msgstr "" + +msgid "Must end with the conference!" +msgstr "" + +msgid "Room is not free!" msgstr "" -msgid "introduction" +msgid "Can't begin before the conference begins!" msgstr "" -msgid "assemblies list" +msgid "Legal (Copyright, Nazi shit, ..)" msgstr "" -msgid "assemblies overview" +msgid "General Report (-> Security Team)" msgstr "" -msgid "assemblies events" +msgid "Awareness Team" +msgstr "" + +msgid "Technical Problem" +msgstr "" + +msgid "Assemblies" +msgstr "" + +msgid "Introduction" +msgstr "" + +msgid "upcoming events" +msgstr "" + +msgid "recommended events" msgstr "" msgid "all assemblies" msgstr "" +msgid "assembly events" +msgstr "" + +msgid "running and upcoming events" +msgstr "" + msgid "all assemblies events" msgstr "" +msgid "New Selforganized Session" +msgstr "" + +msgid "Edit" +msgstr "" + msgid "Your Browser is broken. Get a better one here!" msgstr "Dein Browser ist defekt. Hier bekommst du einen Besseren!" -msgid "world" +msgid "Contact Us" +msgstr "Kontakt" + +msgid "Privacy Policy" msgstr "" -msgid "Low Contrast" +msgid "About RC3" msgstr "" -msgid "low" +msgid "Disclaimer" msgstr "" -msgid "High Contrast" +msgid "Bulletin Board" msgstr "" -msgid "high" +msgid "search" msgstr "" -msgid "logout" +msgid "My Board Entries" msgstr "" -msgid "login" +msgid "New Entry" msgstr "" -msgid "Contact Us" -msgstr "Kontakt" +msgid "Update" +msgstr "" + +msgid "My Bulletin Board" +msgstr "" + +msgid "Public Bulletin Board" +msgstr "" msgid "Curated Events" msgstr "" +msgid "curated events" +msgstr "" + +msgid "No entries available." +msgstr "Keine Einträge vorhanden." + msgid "Event starts in" msgstr "Event startet in" @@ -96,8 +159,30 @@ msgstr "Language" msgid "Room" msgstr "Room" -msgid "No entries available." -msgstr "Keine Einträge vorhanden." +msgid "remove from favorites" +msgstr "" + +msgid "add to favorites" +msgstr "" + +#, fuzzy +#| msgid "personal schedule" +msgid "remove from schedule" +msgstr "Persönlicher Fahrplan" + +#, fuzzy +#| msgid "personal schedule" +msgid "add to schedule" +msgstr "Persönlicher Fahrplan" + +msgid "share this " +msgstr "" + +msgid "open stream" +msgstr "" + +msgid "report this url" +msgstr "" msgid "Live Stream" msgstr "" @@ -108,34 +193,60 @@ msgstr "External Ressources" msgid "Tags" msgstr "Tags" +msgid "by" +msgstr "" + +msgid "Delete" +msgstr "" + +msgid "Report Content" +msgstr "" + msgid "Conferences" msgstr "Konferenzen" -msgid "Curated" +msgid "Hey" +msgstr "Hey" + +msgid "You are leaving the »RC3-area«. For external sites, streams and applications the actual owners are completely and solely responsible regarding data protection, copyright, youth protection, etc.!" +msgstr "Du verlässt gerade das »RC3-Gelände«. Für externe Seiten, Streams und Angebote sind vollinhaltlich die jeweiligen Betreiber in bezug auf Datenschutz, Copyright und Jugendschutz etc. verantwortlich." + +msgid "External Link" msgstr "" -msgid "List" +msgid "download" msgstr "" -msgid "Calendar" +msgid "Xcal" msgstr "" -msgid "curated events" +msgid "Xml" msgstr "" -msgid "congress platform" +msgid "Json" msgstr "" -msgid "community" +msgid "QR-Code" msgstr "" -msgid "Skip intro" -msgstr "Intro überspringen" +msgid "view as list" +msgstr "" -msgid "welcome to the rc3 " +msgid "view as calendar" msgstr "" -msgid "ticket" +msgid "by day" +msgstr "" + +#, fuzzy +#| msgid "Track" +msgid "by track" +msgstr "Track" + +msgid "curated only" +msgstr "" + +msgid "world" msgstr "" msgid "platform" @@ -144,6 +255,58 @@ msgstr "" msgid "info" msgstr "" +msgid "Profile" +msgstr "Profil" + +msgid "My Plan" +msgstr "" + +msgid "logout" +msgstr "" + +msgid "login" +msgstr "" + +msgid "board" +msgstr "" + +#, fuzzy +#| msgid "External Ressources" +msgid "Messages" +msgstr "External Ressources" + +#, fuzzy +#| msgid "External Ressources" +msgid "Mess ages" +msgstr "External Ressources" + +msgid "Fahrplan" +msgstr "" + +msgid "Fahr plan" +msgstr "" + +msgid "Low Contrast" +msgstr "" + +msgid "High Contrast" +msgstr "" + +msgid "de" +msgstr "" + +msgid "en" +msgstr "" + +msgid "Skip intro" +msgstr "Intro überspringen" + +msgid "welcome to the rc3" +msgstr "" + +msgid "ticket" +msgstr "" + msgid "enter username" msgstr "" @@ -165,12 +328,18 @@ msgstr "" msgid "new Ticket" msgstr "" +msgid "Change Password" +msgstr "" + msgid "Your password has been set. You may go ahead and log in now." msgstr "" msgid "back" msgstr "" +msgid "Login" +msgstr "" + msgid "new password" msgstr "" @@ -189,9 +358,6 @@ msgstr "" msgid "You will receive an e-mail with a reset link." msgstr "" -msgid "Login" -msgstr "" - #, fuzzy #| msgid "External Ressources" msgid "Personal Messages" @@ -206,9 +372,6 @@ msgstr "" msgid "New PM" msgstr "" -msgid "Delete" -msgstr "" - msgid "Personal Messages - Send" msgstr "" @@ -221,9 +384,6 @@ msgstr "" msgid "Personal Message" msgstr "" -msgid "Profile" -msgstr "Profil" - msgid "Avatar image" msgstr "" @@ -253,7 +413,25 @@ msgstr "" msgid "custom preferences" msgstr "Konferenzen" -msgid "description" +msgid "Badge-Token" +msgstr "" + +msgid "Submit" +msgstr "" + +msgid "My Favorites" +msgstr "" + +msgid "My Fahrplan" +msgstr "" + +msgid "Please go to the following page and choose a new password:" +msgstr "" + +msgid "Thanks for using our site!" +msgstr "" + +msgid "report content" msgstr "" msgid "Search Results" @@ -262,43 +440,81 @@ msgstr "Suchergebnisse" msgid "No results, sorry!" msgstr "Nichts gefunden, sorry!" -msgid "2D World" +msgid "Cancel" msgstr "" -#, python-format -msgid "You're receiving this email because you requested a password reset for your user account at %(site_name)s." +msgid "Upcoming" msgstr "" -msgid "Please go to the following page and choose a new password:" +msgid "Send PN" msgstr "" -msgid "Your username, in case you’ve forgotten:" +msgid "badges" msgstr "" -msgid "Thanks for using our site!" +msgid "2D World" msgstr "" -#, python-format -msgid "The %(site_name)s team" +msgid "Please activate your Ticket to access this conference!" msgstr "" -#, python-format -msgid "Password reset on %(site_name)s" +msgid "Not allowed to edit this Self Organized Session" +msgstr "" + +msgid "Updated Self Organized Session" +msgstr "" + +msgid "Created Self Organized Session" +msgstr "" + +#, fuzzy +#| msgid "Profile" +msgid "Updated Profile" +msgstr "Profil" + +msgid "Message sent." msgstr "" -msgid "Profile updated successfully" +msgid "Message deleted." msgstr "" msgid "Unknown Username or Password" msgstr "Unbekannter Benutzername oder Passwort falsch" -msgid "Fahrplan" +msgid "Password changed successfully." msgstr "" -msgid "My Plan" +msgid "Bulletin Board Entry updated." +msgstr "" + +msgid "Bulletin Board Entry created." +msgstr "" + +msgid "Bulletin Board Entry deleted." +msgstr "" + +msgid "Report sent" +msgstr "" + +msgid "Assemblies List" +msgstr "" + +msgid "Explore Assemblies" msgstr "" -msgid "bulletin board" +msgid "What are Assemblies?" +msgstr "" + +msgid "Assembly Events" +msgstr "" + +msgid "Explore Assembly Events" +msgstr "" + +msgid "Bulletin Board Entry" +msgstr "" + +msgid "Create" msgstr "" msgid "Explore Events" @@ -311,7 +527,22 @@ msgstr "" msgid "Day %(n)s" msgstr "" -msgid "welcome to rc3" +msgid "Welcome to rC3" +msgstr "" + +msgid "What's Official?" +msgstr "" + +msgid "Explore Curated Events" +msgstr "" + +msgid "Congress Platform" +msgstr "" + +msgid "Community" +msgstr "" + +msgid "Explore Community Events" msgstr "" #, python-format @@ -339,22 +570,44 @@ msgstr "" msgid "My Dashboard" msgstr "" -msgid "my favorite events" +#, python-format +msgid "%(conf)s - Public Fahrplan" msgstr "" -msgid "Report Content" +#, python-format +msgid "%(conf)s Fahrplan" msgstr "" #, python-format -msgid "Tag %(name)s" +msgid "Conference %(conf)s - Redeem Token" msgstr "" -msgid "Upcoming events" +msgid "Redeem Token" msgstr "" -msgid "Hey" -msgstr "Hey" +#, python-format +msgid "You're receiving this email because you requested a password reset for your user account at %(site_name)s." +msgstr "" -msgid "You are leaving the »RC3-area«. For external sites, streams and applications the actual owners are completely and solely responsible regarding data protection, copyright, youth protection, etc.!" -msgstr "Du verlässt gerade das »RC3-Gelände«. Für externe Seiten, Streams und Angebote sind vollinhaltlich die jeweiligen Betreiber in bezug auf Datenschutz, Copyright und Jugendschutz etc. verantwortlich." +#, python-format +msgid "Your username, in case you’ve forgotten: %(username)s" +msgstr "" + +#, python-format +msgid "The %(site_name)s team" +msgstr "" + +msgid "Selforganized Session" +msgstr "" +#, python-format +msgid "Tag %(name)s" +msgstr "" + +msgid "Upcoming events" +msgstr "" + +#, fuzzy, python-format +#| msgid "%(conf)s - Personal Schedule" +msgid "%(conf)s - User %(name)s" +msgstr "%(conf)s - Persönlicher Fahrplan" diff --git a/src/plainui/locale/en/LC_MESSAGES/django.po b/src/plainui/locale/en/LC_MESSAGES/django.po index 13e4917a71dd896b0911f06a848df2bf9c8ee2f9..49e790d108ba72564e1eab054fe01952bc499158 100644 --- a/src/plainui/locale/en/LC_MESSAGES/django.po +++ b/src/plainui/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-12-06 15:26+0000\n" +"POT-Creation-Date: 2020-12-23 11:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -21,57 +21,120 @@ msgstr "" msgid "Unknown User!" msgstr "" -msgid "Assemblies" +msgid "Please enter the recipient name" +msgstr "" + +msgid "Please enter a subject" +msgstr "" + +msgid "Please enter a title" +msgstr "" + +msgid "Placeholder text" +msgstr "" + +msgid "blocked" +msgstr "" + +msgid "Please enter a name" +msgstr "" + +msgid "Must end with the conference!" +msgstr "" + +msgid "Room is not free!" msgstr "" -msgid "introduction" +msgid "Can't begin before the conference begins!" msgstr "" -msgid "assemblies list" +msgid "Legal (Copyright, Nazi shit, ..)" msgstr "" -msgid "assemblies overview" +msgid "General Report (-> Security Team)" msgstr "" -msgid "assemblies events" +msgid "Awareness Team" +msgstr "" + +msgid "Technical Problem" +msgstr "" + +msgid "Assemblies" +msgstr "" + +msgid "Introduction" +msgstr "" + +msgid "upcoming events" +msgstr "" + +msgid "recommended events" msgstr "" msgid "all assemblies" msgstr "" +msgid "assembly events" +msgstr "" + +msgid "running and upcoming events" +msgstr "" + msgid "all assemblies events" msgstr "" +msgid "New Selforganized Session" +msgstr "" + +msgid "Edit" +msgstr "" + msgid "Your Browser is broken. Get a better one here!" msgstr "" -msgid "world" +msgid "Contact Us" msgstr "" -msgid "Low Contrast" +msgid "Privacy Policy" msgstr "" -msgid "low" +msgid "About RC3" msgstr "" -msgid "High Contrast" +msgid "Disclaimer" msgstr "" -msgid "high" +msgid "Bulletin Board" msgstr "" -msgid "logout" +msgid "search" msgstr "" -msgid "login" +msgid "My Board Entries" msgstr "" -msgid "Contact Us" +msgid "New Entry" +msgstr "" + +msgid "Update" +msgstr "" + +msgid "My Bulletin Board" +msgstr "" + +msgid "Public Bulletin Board" msgstr "" msgid "Curated Events" msgstr "" +msgid "curated events" +msgstr "" + +msgid "No entries available." +msgstr "" + msgid "Event starts in" msgstr "" @@ -96,7 +159,25 @@ msgstr "" msgid "Room" msgstr "" -msgid "No entries available." +msgid "remove from favorites" +msgstr "" + +msgid "add to favorites" +msgstr "" + +msgid "remove from schedule" +msgstr "" + +msgid "add to schedule" +msgstr "" + +msgid "share this " +msgstr "" + +msgid "open stream" +msgstr "" + +msgid "report this url" msgstr "" msgid "Live Stream" @@ -108,34 +189,58 @@ msgstr "" msgid "Tags" msgstr "" +msgid "by" +msgstr "" + +msgid "Delete" +msgstr "" + +msgid "Report Content" +msgstr "" + msgid "Conferences" msgstr "" -msgid "Curated" +msgid "Hey" msgstr "" -msgid "List" +msgid "You are leaving the »RC3-area«. For external sites, streams and applications the actual owners are completely and solely responsible regarding data protection, copyright, youth protection, etc.!" msgstr "" -msgid "Calendar" +msgid "External Link" msgstr "" -msgid "curated events" +msgid "download" msgstr "" -msgid "congress platform" +msgid "Xcal" msgstr "" -msgid "community" +msgid "Xml" msgstr "" -msgid "Skip intro" +msgid "Json" msgstr "" -msgid "welcome to the rc3 " +msgid "QR-Code" msgstr "" -msgid "ticket" +msgid "view as list" +msgstr "" + +msgid "view as calendar" +msgstr "" + +msgid "by day" +msgstr "" + +msgid "by track" +msgstr "" + +msgid "curated only" +msgstr "" + +msgid "world" msgstr "" msgid "platform" @@ -144,6 +249,54 @@ msgstr "" msgid "info" msgstr "" +msgid "Profile" +msgstr "" + +msgid "My Plan" +msgstr "" + +msgid "logout" +msgstr "" + +msgid "login" +msgstr "" + +msgid "board" +msgstr "" + +msgid "Messages" +msgstr "" + +msgid "Mess ages" +msgstr "" + +msgid "Fahrplan" +msgstr "" + +msgid "Fahr plan" +msgstr "" + +msgid "Low Contrast" +msgstr "" + +msgid "High Contrast" +msgstr "" + +msgid "de" +msgstr "" + +msgid "en" +msgstr "" + +msgid "Skip intro" +msgstr "" + +msgid "welcome to the rc3" +msgstr "" + +msgid "ticket" +msgstr "" + msgid "enter username" msgstr "" @@ -165,12 +318,18 @@ msgstr "" msgid "new Ticket" msgstr "" +msgid "Change Password" +msgstr "" + msgid "Your password has been set. You may go ahead and log in now." msgstr "" msgid "back" msgstr "" +msgid "Login" +msgstr "" + msgid "new password" msgstr "" @@ -189,9 +348,6 @@ msgstr "" msgid "You will receive an e-mail with a reset link." msgstr "" -msgid "Login" -msgstr "" - msgid "Personal Messages" msgstr "" @@ -204,9 +360,6 @@ msgstr "" msgid "New PM" msgstr "" -msgid "Delete" -msgstr "" - msgid "Personal Messages - Send" msgstr "" @@ -219,9 +372,6 @@ msgstr "" msgid "Personal Message" msgstr "" -msgid "Profile" -msgstr "" - msgid "Avatar image" msgstr "" @@ -249,7 +399,25 @@ msgstr "" msgid "custom preferences" msgstr "" -msgid "description" +msgid "Badge-Token" +msgstr "" + +msgid "Submit" +msgstr "" + +msgid "My Favorites" +msgstr "" + +msgid "My Fahrplan" +msgstr "" + +msgid "Please go to the following page and choose a new password:" +msgstr "" + +msgid "Thanks for using our site!" +msgstr "" + +msgid "report content" msgstr "" msgid "Search Results" @@ -258,43 +426,79 @@ msgstr "" msgid "No results, sorry!" msgstr "" +msgid "Cancel" +msgstr "" + +msgid "Upcoming" +msgstr "" + +msgid "Send PN" +msgstr "" + +msgid "badges" +msgstr "" + msgid "2D World" msgstr "" -#, python-format -msgid "You're receiving this email because you requested a password reset for your user account at %(site_name)s." +msgid "Please activate your Ticket to access this conference!" msgstr "" -msgid "Please go to the following page and choose a new password:" +msgid "Not allowed to edit this Self Organized Session" msgstr "" -msgid "Your username, in case you’ve forgotten:" +msgid "Updated Self Organized Session" msgstr "" -msgid "Thanks for using our site!" +msgid "Created Self Organized Session" msgstr "" -#, python-format -msgid "The %(site_name)s team" +msgid "Updated Profile" msgstr "" -#, python-format -msgid "Password reset on %(site_name)s" +msgid "Message sent." msgstr "" -msgid "Profile updated successfully" +msgid "Message deleted." msgstr "" msgid "Unknown Username or Password" msgstr "" -msgid "Fahrplan" +msgid "Password changed successfully." msgstr "" -msgid "My Plan" +msgid "Bulletin Board Entry updated." +msgstr "" + +msgid "Bulletin Board Entry created." +msgstr "" + +msgid "Bulletin Board Entry deleted." +msgstr "" + +msgid "Report sent" +msgstr "" + +msgid "Assemblies List" +msgstr "" + +msgid "Explore Assemblies" msgstr "" -msgid "bulletin board" +msgid "What are Assemblies?" +msgstr "" + +msgid "Assembly Events" +msgstr "" + +msgid "Explore Assembly Events" +msgstr "" + +msgid "Bulletin Board Entry" +msgstr "" + +msgid "Create" msgstr "" msgid "Explore Events" @@ -307,7 +511,22 @@ msgstr "" msgid "Day %(n)s" msgstr "" -msgid "welcome to rc3" +msgid "Welcome to rC3" +msgstr "" + +msgid "What's Official?" +msgstr "" + +msgid "Explore Curated Events" +msgstr "" + +msgid "Congress Platform" +msgstr "" + +msgid "Community" +msgstr "" + +msgid "Explore Community Events" msgstr "" #, python-format @@ -335,10 +554,34 @@ msgstr "" msgid "My Dashboard" msgstr "" -msgid "my favorite events" +#, python-format +msgid "%(conf)s - Public Fahrplan" msgstr "" -msgid "Report Content" +#, python-format +msgid "%(conf)s Fahrplan" +msgstr "" + +#, python-format +msgid "Conference %(conf)s - Redeem Token" +msgstr "" + +msgid "Redeem Token" +msgstr "" + +#, python-format +msgid "You're receiving this email because you requested a password reset for your user account at %(site_name)s." +msgstr "" + +#, python-format +msgid "Your username, in case you’ve forgotten: %(username)s" +msgstr "" + +#, python-format +msgid "The %(site_name)s team" +msgstr "" + +msgid "Selforganized Session" msgstr "" #, python-format @@ -347,3 +590,7 @@ msgstr "" msgid "Upcoming events" msgstr "" + +#, python-format +msgid "%(conf)s - User %(name)s" +msgstr "" diff --git a/src/plainui/views.py b/src/plainui/views.py index dc77d1a9d53e88df69b01ac5f145a2964c59921a..fcbb1150e204f0be60a4a1217696b092ff361e26 100644 --- a/src/plainui/views.py +++ b/src/plainui/views.py @@ -250,7 +250,9 @@ class AssemblyView(ConferenceRequiredMixin, TemplateView): context['scope'] = 'assembly' context['can_create_sos'] = assembly.has_user(self.request.user) or assembly == self.conf.self_organized_sessions_assembly context['sos'] = assembly.events.filter(is_public=True, kind=Event.Kind.SELF_ORGANIZED) - context['suggested'] = [s.assembly2 for s in assembly.suggestions.select_related('assembly2').exclude(assembly2=assembly.pk).order_by('-like_ratio')[:5]] + context['suggested'] = [s.assembly2 for s in assembly.suggestions.select_related('assembly2') + .exclude(assembly2=assembly.pk) # noqa: E127 + .order_by('-like_ratio')[:5]] can_manage_sos = context['can_manage_sos'] = assembly.user_can_manage(self.request.user) if can_manage_sos: diff --git a/src/requirements.txt b/src/requirements.txt index e4f5f374c3a7ec3bdda90176d91c22feaa3b6842..c542ed21dd5e1d2bab046692fc0181f711f287b5 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,3 +1,4 @@ +bleach >= 3.2.1 Django >=3.1, <3.2 django_bootstrap4 >= 2.3.1, <2.4 django-cors-middleware >= 1.5.0, <1.6