feat: Initial commit
This commit is contained in:
commit
cfa40c6918
24 changed files with 669 additions and 0 deletions
62
.gitignore
vendored
Normal file
62
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# 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
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
#Ipython Notebook
|
||||
.ipynb_checkpoints
|
||||
17
.gitlab-ci.yml
Normal file
17
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
pypi:
|
||||
image:
|
||||
name: pretix/ci-image
|
||||
before_script:
|
||||
- cat $PYPIRC > ~/.pypirc
|
||||
- pip install -U pip uv
|
||||
- uv pip install --system -U wheel setuptools twine build pretix-plugin-build check-manifest
|
||||
script:
|
||||
- python -m build
|
||||
- check-manifest .
|
||||
- twine check dist/*
|
||||
- twine upload dist/*
|
||||
only:
|
||||
- pypi
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
37
.update-locales
Executable file
37
.update-locales
Executable file
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/sh
|
||||
COMPONENTS=pretix/pretix-plugin-congressschedule pretix/pretix-plugin-congressschedule-js
|
||||
DIR=pretix_congressschedule/locale
|
||||
# Renerates .po files used for translating the plugin
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# Lock Weblate
|
||||
for c in $COMPONENTS; do
|
||||
wlc lock $c;
|
||||
done
|
||||
|
||||
# Push changes from Weblate to GitHub
|
||||
for c in $COMPONENTS; do
|
||||
wlc commit $c;
|
||||
done
|
||||
|
||||
# Pull changes from GitHub
|
||||
git pull --rebase
|
||||
|
||||
# Update po files itself
|
||||
make localegen
|
||||
|
||||
# Commit changes
|
||||
git add $DIR/*/*/*.po
|
||||
git add $DIR/*.pot
|
||||
|
||||
git commit -s -m "Update po files
|
||||
[CI skip]"
|
||||
|
||||
# Push changes
|
||||
git push
|
||||
|
||||
# Unlock Weblate
|
||||
for c in $COMPONENTS; do
|
||||
wlc unlock $c;
|
||||
done
|
||||
13
LICENSE
Normal file
13
LICENSE
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Copyright 2025 Vincent 'ViMaSter' Mahnke
|
||||
|
||||
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.
|
||||
3
MANIFEST.in
Normal file
3
MANIFEST.in
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
recursive-include pretix_congressschedule/static *
|
||||
recursive-include pretix_congressschedule/templates *
|
||||
recursive-include pretix_congressschedule/locale *
|
||||
10
Makefile
Normal file
10
Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
all: localecompile
|
||||
LNGS:=`find pretix_congressschedule/locale/ -mindepth 1 -maxdepth 1 -type d -printf "-l %f "`
|
||||
|
||||
localecompile:
|
||||
django-admin compilemessages
|
||||
|
||||
localegen:
|
||||
django-admin makemessages --keep-pot -i build -i dist -i "*egg*" $(LNGS)
|
||||
django-admin makemessages -d djangojs --keep-pot -i build -i dist -i "*egg*" $(LNGS)
|
||||
|
||||
46
README.rst
Normal file
46
README.rst
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
pretix-congressschedule
|
||||
=======================
|
||||
|
||||
This is a plugin for `pretix`_. It generates a `c3voc-schema`_ compatible `schedule.xml` endpoint for events.
|
||||
|
||||
Accessing schedule.xml
|
||||
----------------------
|
||||
|
||||
1. Create an `event-series`_ in pretix; a singular event or non-event shop will not work, as products won't have required start and end times associated with them
|
||||
|
||||
2. Visit `/api/v1/event/{organizationSlug}/{eventSlug}/schedule.xml` and replace `{organizationSlug}` and `{eventSlug}` with the respective slugs
|
||||
|
||||
3. Receive either a 200 status code with an XML document adhering to `schedule.xml.xsd`_ or a 400 error code with additional information inside `<error>`
|
||||
|
||||
|
||||
Development setup
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Make sure that you have a working `pretix development setup`_.
|
||||
|
||||
2. Clone this repository, eg to ``local/pretix-congressschedule``.
|
||||
|
||||
3. Activate the virtual environment you use for pretix development.
|
||||
|
||||
4. Execute ``pip install -e .`` within this directory to register this application with pretix's plugin registry.
|
||||
|
||||
5. Execute ``make`` within this directory to compile translations.
|
||||
|
||||
6. Restart your local pretix 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 2025 Vincent 'ViMaSter' Mahnke
|
||||
|
||||
Released under the terms of the Apache License 2.0
|
||||
|
||||
|
||||
|
||||
.. _pretix: https://github.com/pretix/pretix
|
||||
.. _pretix development setup: https://docs.pretix.eu/en/latest/development/setup.html
|
||||
.. _c3voc-schema: https://c3voc.de/wiki/schedule#schedule_xml
|
||||
.. _schedule.xml.xsd: https://c3voc.de/schedule/schema.xsd
|
||||
.. _event-series: https://docs.pretix.eu/guides/event-series/?h=dates#how-to-create-an-event-series
|
||||
1
pretix_congressschedule/__init__.py
Normal file
1
pretix_congressschedule/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
__version__ = "1.0.0"
|
||||
193
pretix_congressschedule/api.py
Normal file
193
pretix_congressschedule/api.py
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
from django.http import HttpResponse
|
||||
from rest_framework import views
|
||||
from pretix.base.models import Event, SubEvent
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import defaultdict
|
||||
from datetime import timedelta
|
||||
import uuid
|
||||
import re
|
||||
|
||||
from . import __version__
|
||||
|
||||
class CongressScheduleView(views.APIView):
|
||||
def get(self, request, organizer, event, *args, **kwargs):
|
||||
try:
|
||||
ev = Event.objects.get(organizer__slug=organizer, slug=event)
|
||||
except Event.DoesNotExist:
|
||||
return HttpResponse(b'<?xml version="1.0"?><error>Event not found</error>', status=404, content_type='application/xml')
|
||||
|
||||
if not ev.has_subevents:
|
||||
return HttpResponse(
|
||||
b'<?xml version="1.0"?><error>Event is not an event-series: https://docs.pretix.eu/guides/event-series/?h=dates#how-to-create-an-event-series</error>',
|
||||
status=400,
|
||||
content_type='application/xml'
|
||||
)
|
||||
|
||||
subs = SubEvent.objects.filter(event=ev).order_by('date_from')
|
||||
|
||||
root = ET.Element('schedule')
|
||||
|
||||
gen = ET.SubElement(root, 'generator')
|
||||
gen.set('name', 'pretix-congressschedule')
|
||||
gen.set('version', __version__)
|
||||
|
||||
try:
|
||||
feed_url = request.build_absolute_uri()
|
||||
ET.SubElement(root, 'url').text = feed_url
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Version string – keep simple and stable per event
|
||||
ET.SubElement(root, 'version').text = f"{ev.slug}-v1"
|
||||
|
||||
conf = ET.SubElement(root, 'conference')
|
||||
conf_title = ev.name.localize(ev.settings.locale) if hasattr(ev.name, 'localize') else str(ev.name)
|
||||
ET.SubElement(conf, 'title').text = conf_title or str(ev.slug)
|
||||
acronym = f"{organizer}_{event}".lower()
|
||||
ET.SubElement(conf, 'acronym').text = acronym
|
||||
|
||||
# start/end/days based on subevents if available, else fall back to event
|
||||
all_starts = [se.date_from for se in subs if se.date_from]
|
||||
all_ends = [se.date_to for se in subs if se.date_to]
|
||||
|
||||
if all_starts:
|
||||
ET.SubElement(conf, 'start').text = min(all_starts).isoformat()
|
||||
if all_ends:
|
||||
ET.SubElement(conf, 'end').text = max(all_ends).isoformat()
|
||||
|
||||
# days count – unique calendar days from subevents
|
||||
unique_days = sorted({(se.date_from.date() if se.date_from else None) for se in subs} - {None})
|
||||
if unique_days:
|
||||
ET.SubElement(conf, 'days').text = str(len(unique_days))
|
||||
|
||||
# time zone name – try Event.timezone or settings
|
||||
tz_name = getattr(ev, 'timezone', None) or getattr(ev.settings, 'timezone', None)
|
||||
if tz_name:
|
||||
tz_text = tz_name if isinstance(tz_name, str) else str(tz_name)
|
||||
ET.SubElement(conf, 'time_zone_name').text = tz_text
|
||||
|
||||
# Group subevents into days and rooms
|
||||
# days: {date -> {room_name -> [subevents]}}
|
||||
days: dict = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
def get_room_name(se):
|
||||
# Try SubEvent.location if present, else fallback to `Main`
|
||||
loc = getattr(se, 'location', None)
|
||||
if hasattr(loc, 'localize'):
|
||||
try:
|
||||
txt = loc.localize(ev.settings.locale)
|
||||
except Exception:
|
||||
txt = str(loc)
|
||||
else:
|
||||
txt = str(loc) if loc else ''
|
||||
return (txt or 'Main').strip() or 'Main'
|
||||
|
||||
for se in subs:
|
||||
if not se.date_from:
|
||||
# Skip entries without a start
|
||||
continue
|
||||
day_key = se.date_from.date()
|
||||
room = get_room_name(se)
|
||||
days[day_key][room].append(se)
|
||||
|
||||
# Emit <day> elements in chronological order
|
||||
for day_index, (day_date, rooms) in enumerate(sorted(days.items()), start=1):
|
||||
# Compute day start/end from all events this day
|
||||
starts = [se.date_from for r in rooms.values() for se in r if se.date_from]
|
||||
ends = [se.date_to for r in rooms.values() for se in r if se.date_to]
|
||||
day_start = min(starts) if starts else None
|
||||
# If end is missing for any, approximate using +0 duration => start
|
||||
if ends:
|
||||
day_end = max(ends)
|
||||
else:
|
||||
day_end = (day_start + timedelta(minutes=0)) if day_start else None
|
||||
|
||||
day_el = ET.SubElement(root, 'day')
|
||||
if day_date:
|
||||
day_el.set('date', day_date.isoformat())
|
||||
if day_start:
|
||||
day_el.set('start', day_start.isoformat())
|
||||
if day_end:
|
||||
day_el.set('end', day_end.isoformat())
|
||||
day_el.set('index', str(day_index))
|
||||
|
||||
# Emit <room> containers
|
||||
for room_name, events_in_room in sorted(rooms.items(), key=lambda x: x[0].lower()):
|
||||
room_el = ET.SubElement(day_el, 'room')
|
||||
room_el.set('name', room_name)
|
||||
# Optional guid on room – stable UUID5 based on names
|
||||
room_el.set('guid', str(uuid.uuid5(uuid.NAMESPACE_DNS, f"room:{organizer}:{event}:{room_name}")))
|
||||
|
||||
# Emit each <event> in chronological order within the room
|
||||
for se in sorted(events_in_room, key=lambda s: s.date_from or 0):
|
||||
ev_el = ET.SubElement(room_el, 'event')
|
||||
ev_el.set('id', str(se.pk))
|
||||
ev_el.set('guid', str(uuid.uuid5(uuid.NAMESPACE_DNS, f"subevent:{ev.pk}:{se.pk}")))
|
||||
|
||||
# Helper: localize strings
|
||||
def _localize(val):
|
||||
if hasattr(val, 'localize'):
|
||||
try:
|
||||
return val.localize(ev.settings.locale)
|
||||
except Exception:
|
||||
return str(val)
|
||||
return str(val) if val is not None else ''
|
||||
|
||||
# Required children according to schema
|
||||
ET.SubElement(ev_el, 'room').text = room_name
|
||||
title = _localize(se.name)
|
||||
ET.SubElement(ev_el, 'title').text = title
|
||||
ET.SubElement(ev_el, 'subtitle').text = ''
|
||||
ET.SubElement(ev_el, 'type').text = 'subevent'
|
||||
|
||||
# date (full datetime with TZ)
|
||||
if se.date_from:
|
||||
ET.SubElement(ev_el, 'date').text = se.date_from.isoformat()
|
||||
|
||||
# start (HH:MM or HH:MM:SS)
|
||||
if se.date_from:
|
||||
ET.SubElement(ev_el, 'start').text = se.date_from.strftime('%H:%M')
|
||||
|
||||
# duration from date_to - date_from
|
||||
dur_txt = '00:00'
|
||||
if se.date_from and se.date_to and se.date_to >= se.date_from:
|
||||
delta: timedelta = se.date_to - se.date_from
|
||||
total_seconds = int(delta.total_seconds())
|
||||
hours = total_seconds // 3600
|
||||
minutes = (total_seconds % 3600) // 60
|
||||
seconds = total_seconds % 60
|
||||
# prefer HH:MM if no seconds, else HH:MM:SS
|
||||
if seconds == 0:
|
||||
dur_txt = f"{hours:02d}:{minutes:02d}"
|
||||
else:
|
||||
dur_txt = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
||||
ET.SubElement(ev_el, 'duration').text = dur_txt
|
||||
|
||||
ET.SubElement(ev_el, 'abstract').text = ''
|
||||
|
||||
# slug (pattern: "[a-z0-9_]{4,}-[a-z0-9\-_]{4,}")
|
||||
def slugify(text: str) -> str:
|
||||
text = (text or '').lower()
|
||||
text = re.sub(r'\s+', '-', text)
|
||||
text = re.sub(r'[^a-z0-9\-_]', '', text)
|
||||
text = text.strip('-_')
|
||||
return text or 'item'
|
||||
|
||||
base = f"{organizer}_{event}".lower()
|
||||
second = slugify(title)
|
||||
if len(second) < 4:
|
||||
second = f"{second}-{se.pk}"
|
||||
ET.SubElement(ev_el, 'slug').text = f"{base}-{second}"
|
||||
|
||||
# track – use room name as a simple track assignment
|
||||
ET.SubElement(ev_el, 'track').text = slugify(room_name) or 'general'
|
||||
|
||||
# Optional elements: keep minimal but include language if available
|
||||
lang = getattr(ev.settings, 'locale', None)
|
||||
if lang:
|
||||
ET.SubElement(ev_el, 'language').text = str(lang)
|
||||
|
||||
# Leave optional complex children (persons, recording, links, attachments) empty for now
|
||||
|
||||
xml_bytes = ET.tostring(root, encoding='utf-8', xml_declaration=True)
|
||||
return HttpResponse(xml_bytes, content_type='application/xml')
|
||||
43
pretix_congressschedule/apps.py
Normal file
43
pretix_congressschedule/apps.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
from . import __version__
|
||||
|
||||
|
||||
class PassbookApp(AppConfig):
|
||||
name = "pretix_congressschedule"
|
||||
verbose_name = "Congress Schedule"
|
||||
|
||||
class PretixPluginMeta:
|
||||
name = gettext_lazy("Congress Schedule")
|
||||
author = "Vincent Mahnke"
|
||||
description = gettext_lazy("Provides passbook tickets for pretix")
|
||||
category = "API"
|
||||
visible = True
|
||||
featured = True
|
||||
version = __version__
|
||||
compatibility = "pretix>=4.17.0"
|
||||
|
||||
def ready(self):
|
||||
from . import signals # NOQA
|
||||
|
||||
@cached_property
|
||||
def compatibility_errors(self):
|
||||
import shutil
|
||||
|
||||
errs = []
|
||||
if not shutil.which("openssl"):
|
||||
errs.append("The OpenSSL binary is not installed or not in the PATH.")
|
||||
return errs
|
||||
|
||||
@cached_property
|
||||
def compatibility_warnings(self):
|
||||
errs = []
|
||||
try:
|
||||
from PIL import Image # NOQA
|
||||
except ImportError:
|
||||
errs.append(
|
||||
"Pillow is not installed on this system, which is required for converting and scaling images."
|
||||
)
|
||||
return errs
|
||||
19
pretix_congressschedule/locale/de/LC_MESSAGES/django.po
Normal file
19
pretix_congressschedule/locale/de/LC_MESSAGES/django.po
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# pretix-congressschedule
|
||||
# Copyright (C) 2025 Vincent 'ViMaSter' Mahnke
|
||||
# This file is distributed under the same license as the pretix-congressschedule package.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\n"
|
||||
"PO-Revision-Date: 2022-03-21 15:45+0000\n"
|
||||
"Last-Translator: Vincent 'ViMaSter' Mahnke <pretix-congress@vincent.mahn.ke>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix-plugin-congressschedule/de/>\n"
|
||||
"Language: de\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"
|
||||
"X-Generator: Weblate 4.11.2\n"
|
||||
19
pretix_congressschedule/locale/de/LC_MESSAGES/djangojs.po
Normal file
19
pretix_congressschedule/locale/de/LC_MESSAGES/djangojs.po
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# 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 <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\n"
|
||||
"PO-Revision-Date: 2017-05-10 13:48+0200\n"
|
||||
"Last-Translator: Vincent 'ViMaSter' Mahnke <pretix-congress@vincent.mahn.ke>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\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"
|
||||
"X-Generator: Poedit 2.0.1\n"
|
||||
0
pretix_congressschedule/locale/de_Informal/.gitkeep
Normal file
0
pretix_congressschedule/locale/de_Informal/.gitkeep
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# pretix-congressschedule
|
||||
# Copyright (C) 2025 Vincent 'ViMaSter' Mahnke
|
||||
# This file is distributed under the same license as the pretix-congressschedule package.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\n"
|
||||
"PO-Revision-Date: 2022-03-21 15:45+0000\n"
|
||||
"Last-Translator: Vincent 'ViMaSter' Mahnke <pretix-congress@vincent.mahn.ke>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix-plugin-congressschedule/de_Informal/>\n"
|
||||
"Language: de_Informal\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"
|
||||
"X-Generator: Weblate 4.11.2\n"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# 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 <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\n"
|
||||
"PO-Revision-Date: 2017-05-10 13:48+0200\n"
|
||||
"Last-Translator: Vincent 'ViMaSter' Mahnke <pretix-congress@vincent.mahn.ke>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\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"
|
||||
"X-Generator: Poedit 2.0.1\n"
|
||||
26
pretix_congressschedule/locale/django.pot
Normal file
26
pretix_congressschedule/locale/django.pot
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# 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 <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\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"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: pretix_congressschedule/__init__.py:11
|
||||
msgid "Congress Schedule"
|
||||
msgstr ""
|
||||
|
||||
#: pretix_congressschedule/__init__.py:13
|
||||
msgid "Provides passbook tickets for pretix"
|
||||
msgstr ""
|
||||
32
pretix_congressschedule/locale/djangojs.pot
Normal file
32
pretix_congressschedule/locale/djangojs.pot
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# 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 <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-08-16 15:52+0200\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"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: pretix_congressschedule/static/pretix_congressschedule/geosuggest.js:4
|
||||
msgid "Loading suggested geolocations…"
|
||||
msgstr ""
|
||||
|
||||
#: pretix_congressschedule/static/pretix_congressschedule/geosuggest.js:13
|
||||
msgid ""
|
||||
"Click on one of the following suggestions to fill in the coordinates "
|
||||
"automatically:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix_congressschedule/static/pretix_congressschedule/geosuggest.js:35
|
||||
msgid "Error while loading suggested geolocations."
|
||||
msgstr ""
|
||||
0
pretix_congressschedule/signals.py
Normal file
0
pretix_congressschedule/signals.py
Normal file
10
pretix_congressschedule/urls.py
Normal file
10
pretix_congressschedule/urls.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from django.urls import path
|
||||
from .api import CongressScheduleView
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
'api/v1/event/<str:organizer>/<str:event>/schedule.xml',
|
||||
CongressScheduleView.as_view(),
|
||||
name='schedule-xml',
|
||||
),
|
||||
]
|
||||
10
pretixplugin.toml
Normal file
10
pretixplugin.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# This file is used by the pretix team internally to coordinate releases of this plugin
|
||||
[plugin]
|
||||
package = "pretix-congressschedule"
|
||||
modules = [ "pretix_congressschedule" ]
|
||||
marketplace_name = "congressschedule"
|
||||
pypi = true
|
||||
repository_servers = { origin = "github.com", gitlab = "code.rami.io" }
|
||||
tag_targets = [ "origin", "gitlab" ]
|
||||
branch_targets = [ "origin/master", "gitlab/master", "f:gitlab/pypi" ]
|
||||
|
||||
39
pyproject.toml
Normal file
39
pyproject.toml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
[project]
|
||||
name = "pretix-congressschedule"
|
||||
dynamic = ["version"]
|
||||
description = "c3voc schedule-compatible schedule.xml endpoint"
|
||||
readme = "README.rst"
|
||||
requires-python = ">=3.9"
|
||||
license = {file = "LICENSE"}
|
||||
keywords = ["pretix"]
|
||||
authors = [
|
||||
{name = "Vincent Mahnke", email = "pretix-congress@vincent.mahn.ke"},
|
||||
]
|
||||
maintainers = [
|
||||
{name = "Vincent Mahnke", email = "pretix-congress@vincent.mahn.ke"},
|
||||
]
|
||||
|
||||
[project.entry-points."pretix.plugin"]
|
||||
congressschedule = "pretix_congressschedule:PretixPluginMeta"
|
||||
|
||||
[project.entry-points."distutils.commands"]
|
||||
build = "pretix_plugin_build.build:CustomBuild"
|
||||
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools",
|
||||
"pretix-plugin-build"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://git.hamburg.ccc.de/ViMaSter/pretix-congressschedule"
|
||||
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "pretix_congressschedule.__version__"}
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ["pretix*"]
|
||||
namespaces = false
|
||||
2
pytest.ini
Normal file
2
pytest.ini
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[pytest]
|
||||
DJANGO_SETTINGS_MODULE=pretix.testutils.settings
|
||||
46
setup.cfg
Normal file
46
setup.cfg
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
[flake8]
|
||||
ignore = N802,W503,E402
|
||||
max-line-length = 160
|
||||
exclude = migrations,.ropeproject,static,_static,build,setup.py
|
||||
|
||||
[isort]
|
||||
combine_as_imports = true
|
||||
default_section = THIRDPARTY
|
||||
include_trailing_comma = true
|
||||
known_third_party = pretix
|
||||
known_standard_library = typing
|
||||
multi_line_output = 3
|
||||
skip = setup.py
|
||||
use_parentheses = True
|
||||
force_grid_wrap = 0
|
||||
line_length = 88
|
||||
known_first_party = pretix_congressschedule
|
||||
|
||||
[tool:pytest]
|
||||
DJANGO_SETTINGS_MODULE = pretix.testutils.settings
|
||||
|
||||
[coverage:run]
|
||||
source = pretix_adyen
|
||||
omit = */migrations/*,*/urls.py,*/tests/*
|
||||
|
||||
[coverage:report]
|
||||
exclude_lines =
|
||||
pragma: no cover
|
||||
def __str__
|
||||
der __repr__
|
||||
if settings.DEBUG
|
||||
NOQA
|
||||
NotImplementedError
|
||||
|
||||
[check-manifest]
|
||||
ignore =
|
||||
.update-locales
|
||||
.update-locales.sh
|
||||
.gitlab-ci.yml
|
||||
.install-hooks.sh
|
||||
pretixplugin.toml
|
||||
Makefile
|
||||
pytest.ini
|
||||
manage.py
|
||||
tests/*
|
||||
|
||||
3
setup.py
Normal file
3
setup.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup()
|
||||
Loading…
Add table
Add a link
Reference in a new issue