From bdf7281b74a82307f37e140d04211c91abec6c62 Mon Sep 17 00:00:00 2001 From: Franziska Kunsmann Date: Sat, 20 Nov 2021 09:05:08 +0100 Subject: [PATCH] initial commit --- .github/workflows/style.yml | 155 ++++++++++++++++++ .gitignore | 63 +++++++ LICENSE | 13 ++ MANIFEST.in | 3 + Makefile | 8 + README.rst | 32 ++++ pretalx_lower_thirds/apps.py | 17 ++ .../locale/de_DE/LC_MESSAGES/.gitkeep | 0 .../locale/fr_FR/LC_MESSAGES/.gitkeep | 0 pretalx_lower_thirds/signals.py | 1 + .../static/pretalx_lower_thirds/.gitkeep | 0 .../static/pretalx_lower_thirds/frontend.css | 30 ++++ .../static/pretalx_lower_thirds/update.js | 70 ++++++++ .../templates/pretalx_lower_thirds/.gitkeep | 0 .../pretalx_lower_thirds/lower_thirds.html | 25 +++ pretalx_lower_thirds/urls.py | 18 ++ pretalx_lower_thirds/views.py | 71 ++++++++ pylama.ini | 3 + pytest.ini | 2 + setup.cfg | 10 ++ setup.py | 42 +++++ 21 files changed, 563 insertions(+) create mode 100644 .github/workflows/style.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 Makefile create mode 100644 README.rst create mode 100644 pretalx_lower_thirds/apps.py create mode 100644 pretalx_lower_thirds/locale/de_DE/LC_MESSAGES/.gitkeep create mode 100644 pretalx_lower_thirds/locale/fr_FR/LC_MESSAGES/.gitkeep create mode 100644 pretalx_lower_thirds/signals.py create mode 100644 pretalx_lower_thirds/static/pretalx_lower_thirds/.gitkeep create mode 100644 pretalx_lower_thirds/static/pretalx_lower_thirds/frontend.css create mode 100644 pretalx_lower_thirds/static/pretalx_lower_thirds/update.js create mode 100644 pretalx_lower_thirds/templates/pretalx_lower_thirds/.gitkeep create mode 100644 pretalx_lower_thirds/templates/pretalx_lower_thirds/lower_thirds.html create mode 100644 pretalx_lower_thirds/urls.py create mode 100644 pretalx_lower_thirds/views.py create mode 100644 pylama.ini create mode 100644 pytest.ini create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 0000000..04a9cb7 --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,155 @@ +name: Code Style + +on: + push: + branches: [ main ] + paths-ignore: + - 'pretalx_lower_thirds/locale/**' + - 'pretalx_lower_thirds/static/**' + pull_request: + branches: [ main ] + paths-ignore: + - 'pretalx_lower_thirds/locale/**' + - 'pretalx_lower_thirds/static/**' + + +jobs: + isort: + name: isort + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install isort -Ue . + - name: Run isort + run: isort -c . + flake: + name: flake8 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install flake8 -Ue . + - name: Run flake8 + run: flake8 . + working-directory: . + black: + name: black + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install black -Ue . + - name: Run black + run: black --check . + working-directory: . + docformatter: + name: docformatter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install docformatter -Ue . + - name: Run docformatter + run: docformatter --check -r . + working-directory: . + - name: Run docformatter + djhtml: + name: djhtml + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install djhtml -Ue . + - name: Run docformatter + run: find -name "*.html" | xargs djhtml -c + working-directory: . + packaging: + name: packaging + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install pretalx + run: pip3 install pretalx + - name: Install Dependencies + run: pip3 install twine check-manifest -Ue . + - name: Run check-manifest + run: check-manifest . + working-directory: . + - name: Build package + run: python setup.py sdist + working-directory: . + - name: Check package + run: twine check dist/* + working-directory: . + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d95f781 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +.ropeproject/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5d5595a --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2021 kunsi + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..a08af3c --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-include pretalx_lower_thirds/static * +recursive-include pretalx_lower_thirds/templates * +recursive-include pretalx_lower_thirds/locale * diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c730ffe --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +all: localecompile + +localecompile: + django-admin compilemessages + +localegen: + django-admin makemessages -l de_DE -i build -i dist -i "*egg*" + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..29a85c5 --- /dev/null +++ b/README.rst @@ -0,0 +1,32 @@ +Lower Thirds +========================== + +This is a plugin for `pretalx`_. + +Development setup +----------------- + +1. Make sure that you have a working `pretalx development setup`_. + +2. Clone this repository, eg to ``local/pretalx-plugin-lower-thirds``. + +3. Activate the virtual environment you use for pretalx development. + +4. Execute ``python setup.py develop`` within this directory to register this application with pretalx's plugin registry. + +5. Execute ``make`` within this directory to compile translations. + +6. Restart your local pretalx server. You can now use the plugin from this repository for your events by enabling it in + the 'plugins' tab in the settings. + + +License +------- + +Copyright 2021 kunsi + +Released under the terms of the Apache License 2.0 + + +.. _pretalx: https://github.com/pretalx/pretalx +.. _pretalx development setup: https://docs.pretalx.org/en/latest/developer/setup.html diff --git a/pretalx_lower_thirds/apps.py b/pretalx_lower_thirds/apps.py new file mode 100644 index 0000000..87d227c --- /dev/null +++ b/pretalx_lower_thirds/apps.py @@ -0,0 +1,17 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy + + +class PluginApp(AppConfig): + name = "pretalx_lower_thirds" + verbose_name = "Lower Thirds" + + class PretalxPluginMeta: + name = gettext_lazy("Lower Thirds") + author = "kunsi" + description = gettext_lazy("Creates lower thirds from your current schedule. Will show speaker names and talk title using the configured track and event colours.") + visible = True + version = "0.0.0" + + def ready(self): + from . import signals # NOQA diff --git a/pretalx_lower_thirds/locale/de_DE/LC_MESSAGES/.gitkeep b/pretalx_lower_thirds/locale/de_DE/LC_MESSAGES/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pretalx_lower_thirds/locale/fr_FR/LC_MESSAGES/.gitkeep b/pretalx_lower_thirds/locale/fr_FR/LC_MESSAGES/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pretalx_lower_thirds/signals.py b/pretalx_lower_thirds/signals.py new file mode 100644 index 0000000..a025794 --- /dev/null +++ b/pretalx_lower_thirds/signals.py @@ -0,0 +1 @@ +# Register your receivers here diff --git a/pretalx_lower_thirds/static/pretalx_lower_thirds/.gitkeep b/pretalx_lower_thirds/static/pretalx_lower_thirds/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pretalx_lower_thirds/static/pretalx_lower_thirds/frontend.css b/pretalx_lower_thirds/static/pretalx_lower_thirds/frontend.css new file mode 100644 index 0000000..7b49b82 --- /dev/null +++ b/pretalx_lower_thirds/static/pretalx_lower_thirds/frontend.css @@ -0,0 +1,30 @@ +* { + margin: 0; + padding: 0; + line-height: 1.2em; +} + +#box { + width: 1020px; + + position: absolute; + bottom: 80px; + left: 50%; + margin-left: -510px; + + color: white; + font-family: "Muli","Open Sans","OpenSans","Helvetica Neue",Helvetica,Arial,sans-serif; + padding: 15px; + + box-shadow: 5px 5px 10px 0px rgba(50, 50, 50, 0.75); +} + +#title { + font-size: 30px; + font-weight: 500; + margin-bottom: 15px; +} + +#speaker { + font-size: 20px; +} diff --git a/pretalx_lower_thirds/static/pretalx_lower_thirds/update.js b/pretalx_lower_thirds/static/pretalx_lower_thirds/update.js new file mode 100644 index 0000000..05ecff0 --- /dev/null +++ b/pretalx_lower_thirds/static/pretalx_lower_thirds/update.js @@ -0,0 +1,70 @@ +schedule = null; +room_name = null; + +$(function() { + $('#speaker').text('Content will appear soon.'); +}); + +function update_lower_third() { + current_time = new Date(Date.now()).getTime() + + try { + hash = decodeURIComponent(window.location.hash.substring(1)); + room_name = hash; + } catch (e) { + console.error(e); + return + } + + if (!schedule) { + console.warn("There's no schedule yet, exiting ..."); + return + } + + if (schedule['rooms'].length > 1 && !schedule['rooms'].includes(room_name)) { + $('#title').text('Error') + $('#speaker').text('Invalid room_name. Valid names: ' + schedule['rooms'].join(', ')); + + return + } + + current_talk = null; + + for (talk_i in schedule['talks']) { + talk = schedule['talks'][talk_i] + + if (schedule['rooms'].length > 1 && talk['room'] != room_name) { + // not in this room + continue; + } + + talk_start = new Date(talk['start']).getTime(); + talk_end = new Date(talk['end']).getTime(); + + if (talk_start < current_time && talk_end > current_time) { + current_talk = talk; + } + } + + if (current_talk) { + $('#title').text(current_talk['title']); + $('#speaker').text(current_talk['persons'].join(', ')); + $('#box').css('border-bottom', '10px solid ' + current_talk['track']['color']); + } else { + $('#title').text('Currently no talk'); + $('#speaker').text(''); + $('#box').css('border-bottom', 'none'); + } +} +window.setInterval(update_lower_third, 1000); + +function update_schedule() { + $.getJSON('schedule.json', function(data) { + console.info('schedule updated with ' + data['talks'].length + ' talks in ' + data['rooms'].length + ' rooms'); + + schedule = data; + + window.setTimeout(update_schedule, 30000); + }); +} +update_schedule(); diff --git a/pretalx_lower_thirds/templates/pretalx_lower_thirds/.gitkeep b/pretalx_lower_thirds/templates/pretalx_lower_thirds/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pretalx_lower_thirds/templates/pretalx_lower_thirds/lower_thirds.html b/pretalx_lower_thirds/templates/pretalx_lower_thirds/lower_thirds.html new file mode 100644 index 0000000..0efedaa --- /dev/null +++ b/pretalx_lower_thirds/templates/pretalx_lower_thirds/lower_thirds.html @@ -0,0 +1,25 @@ +{% load static %} +{% load compress %} + + + + + {{ request.event.name }} lower thirds + {% compress js %} + + {% endcompress %} + + + + + +
+

Loading ...

+

Content should appear soon. If not, please verify you have Javascript enabled.

+
+ + diff --git a/pretalx_lower_thirds/urls.py b/pretalx_lower_thirds/urls.py new file mode 100644 index 0000000..bb0568c --- /dev/null +++ b/pretalx_lower_thirds/urls.py @@ -0,0 +1,18 @@ +from django.urls import re_path + +from pretalx.event.models.event import SLUG_CHARS + +from . import views + +urlpatterns = [ + re_path( + f"^(?P[{SLUG_CHARS}]+)/p/lower-thirds/$", + views.LowerThirdsView.as_view(), + name="lowerthirds", + ), + re_path( + f"^(?P[{SLUG_CHARS}]+)/p/lower-thirds/schedule.json$", + views.ScheduleView.as_view(), + name="schedule", + ), +] diff --git a/pretalx_lower_thirds/views.py b/pretalx_lower_thirds/views.py new file mode 100644 index 0000000..d83c273 --- /dev/null +++ b/pretalx_lower_thirds/views.py @@ -0,0 +1,71 @@ +import datetime as dt +import json +import pytz +import random + +from django.contrib import messages +from django.db.models import Case, OuterRef, Subquery, When +from django.http import Http404, JsonResponse +from django.shortcuts import redirect +from django.urls import reverse +from django.utils.functional import cached_property +from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ +from django.views.generic.base import TemplateView +from django_context_decorator import context + +from pretalx.agenda.views.schedule import ScheduleMixin +from pretalx.common.mixins.views import EventPermissionRequired +from pretalx.common.signals import register_data_exporters +from pretalx.schedule.exporters import ScheduleData + + +class LowerThirdsView(TemplateView): + template_name = "pretalx_lower_thirds/lower_thirds.html" + + +class ScheduleView(EventPermissionRequired, ScheduleMixin, TemplateView): + permission_required = "agenda.view_schedule" + + def get(self, request, *args, **kwargs): + schedule = ScheduleData( + event=self.request.event, + schedule=self.schedule, + ) + tz = pytz.timezone(schedule.event.timezone) + return JsonResponse( + { + "conference": { + "slug": schedule.event.slug, + "name": str(schedule.event.name), + }, + "rooms": sorted({ + str(room["name"]) + for day in schedule.data + for room in day["rooms"] + }), + "talks": [ + { + "id": talk.submission.id, + "start": talk.start.astimezone(tz).isoformat(), + "end": (talk.start + dt.timedelta(minutes=talk.duration)).astimezone(tz).isoformat(), + "slug": talk.frab_slug, + "title": talk.submission.title, + "persons": sorted({ + person.get_display_name() for person in talk.submission.speakers.all() + }), + "track": { + "color": talk.submission.track.color, + "name": str(talk.submission.track.name), + } if talk.submission.track else None, + "room": str(room["name"]), + } + for day in schedule.data + for room in day["rooms"] + for talk in room["talks"] + ], + }, + json_dumps_params={ + "indent": 4, + }, + ) diff --git a/pylama.ini b/pylama.ini new file mode 100644 index 0000000..316e118 --- /dev/null +++ b/pylama.ini @@ -0,0 +1,3 @@ +[pylama] +ignore = E501, +skip = */settings.py,*/celery_app.py,*.ropeproject/* diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..b4b36ad --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE=pretalx.common.settings.test_settings diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..1805733 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,10 @@ +[isort] +balanced_wrapping = True +combine_as_imports = True +default_section = THIRDPARTY +include_trailing_comma = True +known_third_party = pretalx +line_length = 80 +multi_line_output = 5 +not_skip = __init__.py +skip = migrations,setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..043fd30 --- /dev/null +++ b/setup.py @@ -0,0 +1,42 @@ +import os +from distutils.command.build import build + +from django.core import management +from setuptools import find_packages, setup + +try: + with open( + os.path.join(os.path.dirname(__file__), "README.rst"), encoding="utf-8" + ) as f: + long_description = f.read() +except FileNotFoundError: + long_description = "" + + +class CustomBuild(build): + def run(self): + management.call_command("compilemessages", verbosity=1) + build.run(self) + + +cmdclass = {"build": CustomBuild} + + +setup( + name="pretalx-plugin-lower-thirds", + version="0.0.0", + description="Creates lower thirds from your current schedule. Will show speaker names and talk title using the configured track and event colours.", + long_description=long_description, + url="https://git.franzi.business/kunsi/pretalx-plugin-lower-thirds", + author="kunsi", + author_email="git@kunsmann.eu", + license="Apache Software License", + install_requires=[], + packages=find_packages(exclude=["tests", "tests.*"]), + include_package_data=True, + cmdclass=cmdclass, + entry_points=""" +[pretalx.plugin] +pretalx_lower_thirds=pretalx_lower_thirds:PretalxPluginMeta +""", +)