Compare commits

...

4 Commits

Author SHA1 Message Date
Ed 58812c787f Update default propic for Riverside 2023-08-06 12:47:32 +02:00
Ed 294d30a464 Translated ita -> eng and tidied for public release 2023-08-06 12:47:07 +02:00
Ed fc864fce57 Updated json schema for latest pretix version 2023-08-06 12:46:09 +02:00
Ed cb89641d05 Added flag for unknown countries 2023-08-06 12:45:40 +02:00
17 changed files with 112 additions and 126 deletions

19
api.py
View File

@ -1,5 +1,5 @@
from sanic import response from sanic import response
from sanic import Blueprint, exceptions from sanic import Blueprint
from ext import * from ext import *
from config import * from config import *
import sqlite3 import sqlite3
@ -59,8 +59,8 @@ async def api_leaderboard(request):
async def send_feedback(request): async def send_feedback(request):
try: try:
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
r = await client.post("https://api.telegram.org/bot5648800229:AAGr5EJdyo4obXB7pftIcQGjYLAlQdpu1Iw/sendMessage", r = await client.post(f"https://api.telegram.org/bot{TG_BOT_API}/sendMessage",
json = {'chat_id': -946677603, 'text': str(request.json)} json = {'chat_id': TG_CHAT_ID, 'text': str(request.json)}
) )
except: except:
return response.json({'ok': False, 'error': 'There has been an issue sending your feedback.'}) return response.json({'ok': False, 'error': 'There has been an issue sending your feedback.'})
@ -85,19 +85,6 @@ async def show_events(request):
return r return r
@bp.route("/achievements.json")
async def show_achievements(request):
if request.token:
user = await request.app.ctx.om.get_order(code=request.token[:5])
if not user or user.app_token != request.token[5:]:
return response.json({'ok': False, 'error': 'The token you have provided is not valid.'}, status=401)
with sqlite3.connect('data/boop.db') as db:
db.row_factory = sqlite3.Row
events = db.execute('SELECT * FROM achievement ORDER BY points DESC')
return response.json([{'won_at': '2023-05-05T21:00Z' if request.token and random.random() < 0.2 else None, **dict(x), 'about': 'This is instructions on how to win the field.'} for x in events])
@bp.get("/logout") @bp.get("/logout")
async def logout(request): async def logout(request):
if not request.token: if not request.token:

View File

@ -1,8 +1,6 @@
from sanic.response import html, redirect, text from sanic.response import html
from sanic import Blueprint, exceptions from sanic import Blueprint, exceptions
from random import choice
from ext import * from ext import *
from config import headers
import json import json
bp = Blueprint("carpooling", url_prefix="/manage/carpooling") bp = Blueprint("carpooling", url_prefix="/manage/carpooling")

View File

@ -1,11 +1,41 @@
headers = {'Host': 'your-pretix-hostname', 'Authorization': 'Token XXXXXXXXXXXXXXXXXXXXXXXX'} ORGANIZER = 'furizon'
base_url = "https://your-pretix-hostname/api/v1/organizers/organizer-name/events/your-event/" EVENT_NAME = 'river-side-2023'
API_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxx'
HOSTNAME = 'your-pretix-hostname'
headers = {'Host': HOSTNAME, 'Authorization': f'Token {API_TOKEN}'}
base_url = f"https://{HOSTNAME}/api/v1/organizers/{ORGANIZER}/events/{EVENT_NAME}/"
PROPIC_DEADLINE = 1683575684 PROPIC_DEADLINE = 1683575684
FILL_CACHE = True FILL_CACHE = True
DEV_MODE = True DEV_MODE = True
ITEM_IDS = {
'ticket': [90,],
'membership_card': [91,],
'sponsorship': [], # first one = normal, second = super
'early_arrival': [],
'late_departure': [],
'room': 98
}
# Create a bunch of "room" items which will get added to the order once somebody gets a room.
ROOM_MAP = {
1: 16,
2: 17,
3: 18,
4: 19,
5: 20
}
# This is used for feedback sending inside of the app. Feedbacks will be sent to the specified chat using the bot api id.
TG_BOT_API = '123456789:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
TG_CHAT_ID = -1234567
# These order codes have additional functions.
ADMINS = ['XXXXX', 'YYYYY']
SMTP_HOST = 'your-smtp-host.com' SMTP_HOST = 'your-smtp-host.com'
SMTP_USER = 'username' SMTP_USER = 'username'
SMTP_PASSWORD = 'password' SMTP_PASSWORD = 'password'

View File

@ -1,14 +1,14 @@
from sanic.response import text from sanic.response import text
from sanic import Blueprint, exceptions from sanic import Blueprint, exceptions
from ext import * from ext import *
from config import headers from config import headers, ADMINS, ORGANIZER, EVENT_NAME
bp = Blueprint("export", url_prefix="/manage/export") bp = Blueprint("export", url_prefix="/manage/export")
@bp.route("/export.csv") @bp.route("/export.csv")
async def export_csv(request, order: Order): async def export_csv(request, order: Order):
if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!")
if order.code not in ['HWUC9','9YKGJ']: raise exceptions.Forbidden("Birichino :)") if order.code not in ADMINS: raise exceptions.Forbidden("Birichino :)")
page = 0 page = 0
orders = {} orders = {}
@ -18,7 +18,7 @@ async def export_csv(request, order: Order):
while 1: while 1:
page += 1 page += 1
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/furizon/events/beyond/orders/?page={page}', headers=headers) r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/{ORGANIZER}/events/{EVENT_NAME}/orders/?page={page}', headers=headers)
if r.status_code == 404: break if r.status_code == 404: break
for r in r.json()['results']: for r in r.json()['results']:
@ -64,7 +64,7 @@ async def export_hotel_csv(request, order: Order):
while 1: while 1:
page += 1 page += 1
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/furizon/events/beyond/orders/?page={page}', headers=headers) r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/{ORGANIZER}/events/{EVENT_NAME}/orders/?page={page}', headers=headers)
if r.status_code == 404: break if r.status_code == 404: break
for r in r.json()['results']: for r in r.json()['results']:

11
ext.py
View File

@ -29,17 +29,21 @@ class Order:
self.has_late = False self.has_late = False
self.first_name = None self.first_name = None
self.last_name = None self.last_name = None
self.country = None self.country = 'xx'
self.address = None self.address = None
self.checked_in = False self.checked_in = False
idata = data['invoice_address']
if idata:
self.address = f"{idata['street']} - {idata['zipcode']} {idata['city']} - {idata['country']}"
self.country = idata['country']
for p in self.data['positions']: for p in self.data['positions']:
if p['item'] in ITEM_IDS['ticket']: if p['item'] in ITEM_IDS['ticket']:
self.position_id = p['id'] self.position_id = p['id']
self.position_positionid = p['positionid'] self.position_positionid = p['positionid']
self.answers = p['answers'] self.answers = p['answers']
self.barcode = p['secret'] self.barcode = p['secret']
self.address = f"{p['street']} - {p['zipcode']} {p['city']} - {p['country']}"
self.checked_in = bool(p['checkins']) self.checked_in = bool(p['checkins'])
if p['item'] in ITEM_IDS['membership_card']: if p['item'] in ITEM_IDS['membership_card']:
@ -48,9 +52,6 @@ class Order:
if p['item'] in ITEM_IDS['sponsorship']: if p['item'] in ITEM_IDS['sponsorship']:
self.sponsorship = 'normal' if p['variation'] == ITEMS_IDS['sponsorship'][0] else 'super' self.sponsorship = 'normal' if p['variation'] == ITEMS_IDS['sponsorship'][0] else 'super'
if p['country']:
self.country = p['country']
if p['attendee_name']: if p['attendee_name']:
self.first_name = p['attendee_name_parts']['given_name'] self.first_name = p['attendee_name_parts']['given_name']
self.last_name = p['attendee_name_parts']['family_name'] self.last_name = p['attendee_name_parts']['family_name']

View File

@ -1,15 +1,8 @@
from sanic.response import html, redirect, text from sanic.response import html, redirect, text
from sanic import Blueprint, exceptions, response from sanic import Blueprint, exceptions, response
from random import choice
from ext import * from ext import *
from config import headers, PROPIC_DEADLINE
from PIL import Image
from os.path import isfile
from os import unlink
from io import BytesIO
from hashlib import sha224
from time import time
from urllib.parse import unquote from urllib.parse import unquote
from config import ADMINS
import json import json
bp = Blueprint("karaoke", url_prefix="/manage/karaoke") bp = Blueprint("karaoke", url_prefix="/manage/karaoke")
@ -17,7 +10,7 @@ bp = Blueprint("karaoke", url_prefix="/manage/karaoke")
@bp.get("/admin") @bp.get("/admin")
async def show_songs(request, order: Order): async def show_songs(request, order: Order):
if order.code not in ['9YKGJ', 'CMPQG']: if order.code not in ADMINS:
raise exceptions.Forbidden("Birichino") raise exceptions.Forbidden("Birichino")
orders = [x for x in request.app.ctx.om.cache.values() if x.karaoke_songs] orders = [x for x in request.app.ctx.om.cache.values() if x.karaoke_songs]
@ -35,7 +28,7 @@ async def show_songs(request, order: Order):
@bp.post("/approve") @bp.post("/approve")
async def approve_songs(request, order: Order): async def approve_songs(request, order: Order):
if order.code not in ['9YKGJ', 'CMPQG']: if order.code not in ADMINS:
raise exceptions.Forbidden("Birichino") raise exceptions.Forbidden("Birichino")
for song in request.form: for song in request.form:
@ -51,7 +44,7 @@ async def sing_song(request, order: Order, songname):
if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!")
if order.code not in ['9YKGJ', 'CMPQG']: if order.code not in ADMINS:
raise exceptions.Forbidden("Birichino") raise exceptions.Forbidden("Birichino")
songname = unquote(songname) songname = unquote(songname)

View File

@ -1,11 +1,8 @@
from sanic.response import html, redirect, text from sanic.response import html, redirect
from sanic import Blueprint, exceptions from sanic import Blueprint, exceptions
from random import choice
from ext import * from ext import *
from config import headers, PROPIC_DEADLINE from config import PROPIC_DEADLINE
from PIL import Image from PIL import Image
from os.path import isfile
from os import unlink
from io import BytesIO from io import BytesIO
from hashlib import sha224 from hashlib import sha224
from time import time from time import time

View File

@ -1,4 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-xx" viewBox="0 0 640 480"> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<path fill="#fff" fill-rule="evenodd" stroke="#adb5bd" stroke-width="1.1" d="M.5.5h638.9v478.9H.5z"/> <svg
<path fill="none" stroke="#adb5bd" stroke-width="1.1" d="m.5.5 639 479M639.5.5l-639 479"/> id="flag-icons-us"
viewBox="0 0 640 480"
version="1.1"
sodipodi:docname="??.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs4" />
<sodipodi:namedview
id="namedview4"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.8295363"
inkscape:cx="391.356"
inkscape:cy="277.93928"
inkscape:window-width="2560"
inkscape:window-height="1035"
inkscape:window-x="0"
inkscape:window-y="21"
inkscape:window-maximized="1"
inkscape:current-layer="flag-icons-us" />
<rect
style="fill:#003399;fill-rule:evenodd;stroke-width:2.59276;stroke-linecap:square;stroke-linejoin:round;paint-order:markers stroke fill"
id="rect4"
width="640"
height="480"
x="0"
y="0" />
<path
style="font-size:377.089px;line-height:1.25;font-family:OfficinaSanITCBoo;-inkscape-font-specification:OfficinaSanITCBoo;text-align:center;word-spacing:0px;text-anchor:middle;fill:#ffffff;stroke-width:1.964"
d="m 122.59391,314.85217 q 6.41051,0 12.06684,2.63962 5.65634,2.26253 9.80432,6.7876 4.52507,4.14798 6.7876,10.1814 2.63962,5.65634 2.63962,12.44394 0,13.19812 -9.42722,22.24825 -9.05014,9.42723 -22.24825,9.42723 -13.19812,0 -22.625341,-9.42723 -9.427225,-9.42722 -9.427225,-22.62534 0,-13.19811 9.427225,-22.24825 9.427221,-9.42722 23.002431,-9.42722 z m 18.85445,-48.26739 q 0,5.27924 -1.50836,6.7876 -1.13127,1.13127 -6.03342,1.13127 h -26.77332 q -5.27925,0 -6.7876,-1.13127 -1.13127,-1.50836 -1.13127,-6.7876 v -47.13613 q 0,-4.14798 1.50836,-5.65633 1.50835,-1.50836 7.16469,-3.01671 49.02157,-10.5585 49.02157,-39.21726 0,-13.19811 -9.42723,-19.98572 -9.05014,-7.16469 -26.01914,-7.16469 -9.80431,0 -18.85445,2.26254 -8.673046,2.26253 -22.625339,8.29596 -3.3938,1.50835 -4.525067,1.88544 -1.131267,0.37709 -1.885445,0.37709 -2.639623,0 -3.77089,-3.77089 l -9.804314,-25.64205 q -0.754178,-2.26254 -0.754178,-4.14798 0,-3.3938 6.787602,-7.16469 6.787602,-4.14798 17.346093,-7.16469 10.558492,-3.3938 22.625338,-5.65634 12.06685,-2.26253 23.00243,-2.26253 16.969,0 30.54421,5.27925 13.95229,4.90215 23.7566,14.32938 9.80432,9.05013 15.08356,22.24825 5.27925,12.82102 5.27925,28.65876 0,35.82345 -29.03585,54.6779 -6.03343,4.14798 -13.57521,7.16469 -7.16469,3.01672 -19.60862,7.1647 z m 169.69004,48.26739 q 6.41051,0 12.06685,2.63962 5.65633,2.26253 9.80431,6.7876 4.52507,4.14798 6.78761,10.1814 2.63962,5.65634 2.63962,12.44394 0,13.19812 -9.42723,22.24825 -9.05013,9.42723 -22.24825,9.42723 -13.19811,0 -22.62534,-9.42723 -9.42722,-9.42722 -9.42722,-22.62534 0,-13.19811 9.42722,-22.24825 9.42723,-9.42722 23.00243,-9.42722 z m 18.85445,-48.26739 q 0,5.27924 -1.50835,6.7876 -1.13127,1.13127 -6.03343,1.13127 h -26.77332 q -5.27924,0 -6.7876,-1.13127 -1.13127,-1.50836 -1.13127,-6.7876 v -47.13613 q 0,-4.14798 1.50836,-5.65633 1.50836,-1.50836 7.16469,-3.01671 49.02157,-10.5585 49.02157,-39.21726 0,-13.19811 -9.42722,-19.98572 -9.05014,-7.16469 -26.01915,-7.16469 -9.80431,0 -18.85444,2.26254 -8.67305,2.26253 -22.62534,8.29596 -3.3938,1.50835 -4.52507,1.88544 -1.13127,0.37709 -1.88545,0.37709 -2.63962,0 -3.77089,-3.77089 l -9.80431,-25.64205 q -0.75418,-2.26254 -0.75418,-4.14798 0,-3.3938 6.7876,-7.16469 6.78761,-4.14798 17.3461,-7.16469 10.55849,-3.3938 22.62534,-5.65634 12.06684,-2.26253 23.00242,-2.26253 16.96901,0 30.54421,5.27925 13.9523,4.90215 23.75661,14.32938 9.80431,9.05013 15.08356,22.24825 5.27924,12.82102 5.27924,28.65876 0,35.82345 -29.03585,54.6779 -6.03342,4.14798 -13.5752,7.16469 -7.16469,3.01672 -19.60863,7.1647 z m 169.69005,48.26739 q 6.41051,0 12.06684,2.63962 5.65634,2.26253 9.80432,6.7876 4.52507,4.14798 6.7876,10.1814 2.63962,5.65634 2.63962,12.44394 0,13.19812 -9.42722,22.24825 -9.05014,9.42723 -22.24825,9.42723 -13.19812,0 -22.62534,-9.42723 -9.42723,-9.42722 -9.42723,-22.62534 0,-13.19811 9.42723,-22.24825 9.42722,-9.42722 23.00243,-9.42722 z m 18.85445,-48.26739 q 0,5.27924 -1.50836,6.7876 -1.13127,1.13127 -6.03342,1.13127 h -26.77332 q -5.27925,0 -6.7876,-1.13127 -1.13127,-1.50836 -1.13127,-6.7876 v -47.13613 q 0,-4.14798 1.50836,-5.65633 1.50835,-1.50836 7.16469,-3.01671 49.02156,-10.5585 49.02156,-39.21726 0,-13.19811 -9.42722,-19.98572 -9.05014,-7.16469 -26.01914,-7.16469 -9.80431,0 -18.85445,2.26254 -8.67305,2.26253 -22.62534,8.29596 -3.3938,1.50835 -4.52507,1.88544 -1.13126,0.37709 -1.88544,0.37709 -2.63963,0 -3.77089,-3.77089 l -9.80432,-25.64205 q -0.75417,-2.26254 -0.75417,-4.14798 0,-3.3938 6.7876,-7.16469 6.7876,-4.14798 17.34609,-7.16469 10.55849,-3.3938 22.62534,-5.65634 12.06685,-2.26253 23.00243,-2.26253 16.969,0 30.54421,5.27925 13.95229,4.90215 23.7566,14.32938 9.80432,9.05013 15.08356,22.24825 5.27925,12.82102 5.27925,28.65876 0,35.82345 -29.03585,54.6779 -6.03343,4.14798 -13.57521,7.16469 -7.16469,3.01672 -19.60862,7.1647 z"
id="text4"
aria-label="???" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 286 B

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,9 +1,6 @@
from sanic.response import html from sanic.response import html
from sanic import Blueprint, exceptions from sanic import Blueprint
from ext import * from ext import *
from config import headers
from time import time
import asyncio
bp = Blueprint("stats", url_prefix="/manage") bp = Blueprint("stats", url_prefix="/manage")

View File

@ -88,9 +88,6 @@
<a href="/manage/nosecount">Nose Count</a> <a href="/manage/nosecount">Nose Count</a>
{% if order %} {% if order %}
<a href="/manage/carpooling">Carpooling</a> <a href="/manage/carpooling">Carpooling</a>
{% if not order.room_confirmed %}
<a href="/manage/roommate_search">Roommate Search</a>
{% endif %}
<a style="float:right;" href="/manage/logout">Logout</a> <a style="float:right;" href="/manage/logout">Logout</a>
{% endif %} {% endif %}
<br clear="both" /> <br clear="both" />
@ -109,7 +106,7 @@
}); });
</script> </script>
<footer> <footer>
Made in 🇮🇹 by <img src="/res/icons/silhouette.svg" class="icon" title="ACCBCAC" /> · <a href="/manage/privacy">Privacy</a> Made in 🇮🇹 by <img src="/res/icons/silhouette.svg" class="icon" /> · <a href="/manage/privacy">Privacy</a>
</footer> </footer>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block main %} {% block main %}
<main class="container"> <main class="container">
<h1>Cerca ordine</h1> <h1>Search order</h1>
<input id="search" type="text" onchange="updateSearch();" onclick="this.value = '';" /> <input id="search" type="text" onchange="updateSearch();" onclick="this.value = '';" />
<form method="get" id="actionform" style="font-family:monospace;" action="order"> <form method="get" id="actionform" style="font-family:monospace;" action="order">
<select id="badgelist" name="order" id="order" multiple> <select id="badgelist" name="order" id="order" multiple>

View File

@ -2,15 +2,15 @@
{% block main %} {% block main %}
<main class="container"> <main class="container">
<h1><kbd>{{order.code}}</kbd> {{order.name}} ({{order.first_name}} {{order.last_name}})</h1> <h1><kbd>{{order.code}}</kbd> {{order.name}} ({{order.first_name}} {{order.last_name}})</h1>
<p><strong>Commento:</strong> {{order.comment or '--'}}<br /> <p><strong>Comment:</strong> {{order.comment or '--'}}<br />
<strong>Note ordine:</strong> {{order.notes or '--'}}<br /> <strong>Order notes:</strong> {{order.notes or '--'}}<br />
<strong>Stato ordine: <span style="color: {{'#900' if order.status == 'unpaid' else '#090'}}">{{order.status}}</span></strong><br /> <strong>Status: <span style="color: {{'#900' if order.status == 'unpaid' else '#090'}}">{{order.status}}</span></strong><br />
<strong>Sponsor: <span style="color: {{'#fa0' if order.sponsorship == 'super' else ('#e8e' if order.sponsorship else 'initial')}}">{{order.sponsorship}}</span></strong><br /> <strong>Sponsor: <span style="color: {{'#fa0' if order.sponsorship == 'super' else ('#e8e' if order.sponsorship else 'initial')}}">{{order.sponsorship}}</span></strong><br />
<strong>Compagni di stanza:</strong> {% for code in room_owner.room_members %}<kbd><a href="order?order={{code}}">{{code}}</a></kbd> {% endfor %}<br /> <strong>Roommates:</strong> {% for code in room_owner.room_members %}<kbd><a href="order?order={{code}}">{{code}}</a></kbd> {% endfor %}<br />
<a target="_blank" href="https://reg.furizon.net/control/event/furizon/beyond/orders/{{order.code}}/">Apri su pretix</a><br /></p> <a target="_blank" href="https://{config.HOSTNAME}/control/event/{config.ORGANIZER}/{config.EVENT_NAME}/orders/{{order.code}}/">Open on pretix</a><br /></p>
<form method="post" id="actionform" action="checkin"> <form method="post" id="actionform" action="checkin">
<input type="hidden" value="{{order.code}}" name="code" /> <input type="hidden" value="{{order.code}}" name="code" />
<label for="actual_room">Numero Stanza Reale</label> <label for="actual_room">Real Room Number</label>
<input type="text" value="{{room_owner.actual_room or ''}}" name="actual_room" required /> <input type="text" value="{{room_owner.actual_room or ''}}" name="actual_room" required />
<label for="nfc_id">NFC Badge</label> <label for="nfc_id">NFC Badge</label>
<input type="text" value="{{order.nfc_id or ''}}" name="nfc_id" pattern="[A-F0-9]{14}" title="NFC Tag id must be 14 chars" required /> <input type="text" value="{{order.nfc_id or ''}}" name="nfc_id" pattern="[A-F0-9]{14}" title="NFC Tag id must be 14 chars" required />

View File

@ -1,19 +1,19 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block main %} {% block main %}
<main class="container"> <main class="container">
<h1>✅ Checkin effettuato!</h1> <h1>✅ Checkin done!</h1>
<p><strong>Ricorda di apporre il numero sul badge! Numero: {{order.badge_id}}</strong></p> <p><strong>Remember to stick the REG number to the badge! Number: {{order.badge_id}}</strong></p>
<h2>Altri membri della stessa stanza ({{room_owner.actual_room}})</h2> <h2>Other members of the same room ({{room_owner.actual_room}})</h2>
<table> <table>
{% for o in roommates %} {% for o in roommates %}
<tr> <tr>
<td><a href="order?order={{o.code}}">{{o.code}}</a></td> <td><a href="order?order={{o.code}}">{{o.code}}</a></td>
<td>{{o.name}}</td> <td>{{o.name}}</td>
<td><a href="order?order={{o.code}}">{{'Effettua Checkin' if not o.checked_in else '✅'}}</a></td> <td><a href="order?order={{o.code}}">{{'Checkin' if not o.checked_in else '✅'}}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<h3><a href="start">Effettua un altro checkin ➡️</a></h3> <h3><a href="start">Checkin somebody else ➡️</a></h3>
</main> </main>
{% endblock %} {% endblock %}

View File

@ -4,7 +4,7 @@
<main class="container"> <main class="container">
<h1>Karaoke Admin</h1> <h1>Karaoke Admin</h1>
<h2>Canzoni da cantare</h2> <h2>Songs to sing</h2>
<table> <table>
{% for s in songs if s.approved is not none and (not s.singed) %} {% for s in songs if s.approved is not none and (not s.singed) %}
<tr {% if s.approved == false %}style="text-decoration: line-through"{% endif %}> <tr {% if s.approved == false %}style="text-decoration: line-through"{% endif %}>

View File

@ -1,54 +0,0 @@
{% extends "base.html" %}
{% block title %}Furizon 2023 Stats{% endblock %}
{% block main %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<main class="container">
<header>
<picture>
<source srcset="/res/furizon.png" media="(prefers-color-scheme:dark)">
<img src="/res/furizon-light.png" style="height:4rem;text-align:center;">
</picture>
</header>
<h2>Countries</h2>
<div style="margin: 0 auto;">
<canvas id="countries"></canvas>
</div>
<script>
const ctx = document.getElementById('countries');
new Chart(ctx, {
type: 'bar',
data: {
labels: {{stats['countries'].keys()|list|safe}},
datasets: [{
label: '# of Attendees',
data: {{stats['countries'].values()|list|safe}},
borderWidth: 0
}]
},
options: {
scales: {
y: {beginAtZero: true}
}
}
});
</script>
<h2>Sponsors</h2>
<div style="max-width:20em;margin: 0 auto;">
<canvas id="sponsors"></canvas>
</div>
<script>
const ctx2 = document.getElementById('sponsors');
new Chart(ctx2, {
type: 'pie',
data: {
labels: {{stats['sponsors'].keys()|list|safe}},
datasets: [{
label: '# of Attendees',
data: {{stats['sponsors'].values()|list|safe}},
borderWidth: 0
}]
}
});
</script>
</main>
{% endblock %}

View File

@ -24,7 +24,7 @@
</tr> </tr>
<tr> <tr>
<th>When{{' (convention)' if order.has_early or order.has_late else ''}}?</th> <th>When{{' (convention)' if order.has_early or order.has_late else ''}}?</th>
<td>30 May → 3 June 2023</td></td> <td>13 October → 15 October 2023</td></td>
</tr> </tr>
{% if order.has_early or order.has_late %} {% if order.has_early or order.has_late %}
<tr> <tr>
@ -53,7 +53,7 @@
{% if order.status == 'paid' and order.room_confirmed %} {% if order.status == 'paid' and order.room_confirmed %}
<br /> <br />
<img src="/res/icons/pdf.svg" class="icon" /> <img src="/res/icons/pdf.svg" class="icon" />
<a href="/manage/download_ticket?name=BEYOND-{{order.code}}.pdf" target="_blank">Download ticket PDF</a> <a href="/manage/download_ticket?name=RIVERSIDE-{{order.code}}.pdf" target="_blank">Download ticket PDF</a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>