Compare commits
No commits in common. "58812c787f38257d8fca238b51ed4fd12d237361" and "d53ee2eaf097e14a4fec1aebd3037948296dff39" have entirely different histories.
58812c787f
...
d53ee2eaf0
19
api.py
19
api.py
|
@ -1,5 +1,5 @@
|
|||
from sanic import response
|
||||
from sanic import Blueprint
|
||||
from sanic import Blueprint, exceptions
|
||||
from ext import *
|
||||
from config import *
|
||||
import sqlite3
|
||||
|
@ -59,8 +59,8 @@ async def api_leaderboard(request):
|
|||
async def send_feedback(request):
|
||||
try:
|
||||
async with httpx.AsyncClient() as client:
|
||||
r = await client.post(f"https://api.telegram.org/bot{TG_BOT_API}/sendMessage",
|
||||
json = {'chat_id': TG_CHAT_ID, 'text': str(request.json)}
|
||||
r = await client.post("https://api.telegram.org/bot5648800229:AAGr5EJdyo4obXB7pftIcQGjYLAlQdpu1Iw/sendMessage",
|
||||
json = {'chat_id': -946677603, 'text': str(request.json)}
|
||||
)
|
||||
except:
|
||||
return response.json({'ok': False, 'error': 'There has been an issue sending your feedback.'})
|
||||
|
@ -85,6 +85,19 @@ async def show_events(request):
|
|||
|
||||
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")
|
||||
async def logout(request):
|
||||
if not request.token:
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from sanic.response import html
|
||||
from sanic.response import html, redirect, text
|
||||
from sanic import Blueprint, exceptions
|
||||
from random import choice
|
||||
from ext import *
|
||||
from config import headers
|
||||
import json
|
||||
|
||||
bp = Blueprint("carpooling", url_prefix="/manage/carpooling")
|
||||
|
|
|
@ -1,41 +1,11 @@
|
|||
ORGANIZER = 'furizon'
|
||||
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}/"
|
||||
headers = {'Host': 'your-pretix-hostname', 'Authorization': 'Token XXXXXXXXXXXXXXXXXXXXXXXX'}
|
||||
base_url = "https://your-pretix-hostname/api/v1/organizers/organizer-name/events/your-event/"
|
||||
|
||||
PROPIC_DEADLINE = 1683575684
|
||||
FILL_CACHE = 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_USER = 'username'
|
||||
SMTP_PASSWORD = 'password'
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from sanic.response import text
|
||||
from sanic import Blueprint, exceptions
|
||||
from ext import *
|
||||
from config import headers, ADMINS, ORGANIZER, EVENT_NAME
|
||||
from config import headers
|
||||
|
||||
bp = Blueprint("export", url_prefix="/manage/export")
|
||||
|
||||
@bp.route("/export.csv")
|
||||
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 order.code not in ADMINS: raise exceptions.Forbidden("Birichino :)")
|
||||
if order.code not in ['HWUC9','9YKGJ']: raise exceptions.Forbidden("Birichino :)")
|
||||
|
||||
page = 0
|
||||
orders = {}
|
||||
|
@ -18,7 +18,7 @@ async def export_csv(request, order: Order):
|
|||
while 1:
|
||||
page += 1
|
||||
|
||||
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/{ORGANIZER}/events/{EVENT_NAME}/orders/?page={page}', headers=headers)
|
||||
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/furizon/events/beyond/orders/?page={page}', headers=headers)
|
||||
if r.status_code == 404: break
|
||||
|
||||
for r in r.json()['results']:
|
||||
|
@ -64,7 +64,7 @@ async def export_hotel_csv(request, order: Order):
|
|||
while 1:
|
||||
page += 1
|
||||
|
||||
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/{ORGANIZER}/events/{EVENT_NAME}/orders/?page={page}', headers=headers)
|
||||
r = httpx.get(f'https://reg.furizon.net/api/v1/organizers/furizon/events/beyond/orders/?page={page}', headers=headers)
|
||||
if r.status_code == 404: break
|
||||
|
||||
for r in r.json()['results']:
|
||||
|
|
11
ext.py
11
ext.py
|
@ -29,21 +29,17 @@ class Order:
|
|||
self.has_late = False
|
||||
self.first_name = None
|
||||
self.last_name = None
|
||||
self.country = 'xx'
|
||||
self.country = None
|
||||
self.address = None
|
||||
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']:
|
||||
if p['item'] in ITEM_IDS['ticket']:
|
||||
self.position_id = p['id']
|
||||
self.position_positionid = p['positionid']
|
||||
self.answers = p['answers']
|
||||
self.barcode = p['secret']
|
||||
self.address = f"{p['street']} - {p['zipcode']} {p['city']} - {p['country']}"
|
||||
self.checked_in = bool(p['checkins'])
|
||||
|
||||
if p['item'] in ITEM_IDS['membership_card']:
|
||||
|
@ -52,6 +48,9 @@ class Order:
|
|||
if p['item'] in ITEM_IDS['sponsorship']:
|
||||
self.sponsorship = 'normal' if p['variation'] == ITEMS_IDS['sponsorship'][0] else 'super'
|
||||
|
||||
if p['country']:
|
||||
self.country = p['country']
|
||||
|
||||
if p['attendee_name']:
|
||||
self.first_name = p['attendee_name_parts']['given_name']
|
||||
self.last_name = p['attendee_name_parts']['family_name']
|
||||
|
|
15
karaoke.py
15
karaoke.py
|
@ -1,8 +1,15 @@
|
|||
from sanic.response import html, redirect, text
|
||||
from sanic import Blueprint, exceptions, response
|
||||
from random import choice
|
||||
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 config import ADMINS
|
||||
import json
|
||||
|
||||
bp = Blueprint("karaoke", url_prefix="/manage/karaoke")
|
||||
|
@ -10,7 +17,7 @@ bp = Blueprint("karaoke", url_prefix="/manage/karaoke")
|
|||
@bp.get("/admin")
|
||||
async def show_songs(request, order: Order):
|
||||
|
||||
if order.code not in ADMINS:
|
||||
if order.code not in ['9YKGJ', 'CMPQG']:
|
||||
raise exceptions.Forbidden("Birichino")
|
||||
|
||||
orders = [x for x in request.app.ctx.om.cache.values() if x.karaoke_songs]
|
||||
|
@ -28,7 +35,7 @@ async def show_songs(request, order: Order):
|
|||
@bp.post("/approve")
|
||||
async def approve_songs(request, order: Order):
|
||||
|
||||
if order.code not in ADMINS:
|
||||
if order.code not in ['9YKGJ', 'CMPQG']:
|
||||
raise exceptions.Forbidden("Birichino")
|
||||
|
||||
for song in request.form:
|
||||
|
@ -44,7 +51,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 order.code not in ADMINS:
|
||||
if order.code not in ['9YKGJ', 'CMPQG']:
|
||||
raise exceptions.Forbidden("Birichino")
|
||||
|
||||
songname = unquote(songname)
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
from sanic.response import html, redirect
|
||||
from sanic.response import html, redirect, text
|
||||
from sanic import Blueprint, exceptions
|
||||
from random import choice
|
||||
from ext import *
|
||||
from config import PROPIC_DEADLINE
|
||||
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
|
||||
|
|
|
@ -1,44 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
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 xmlns="http://www.w3.org/2000/svg" id="flag-icons-xx" viewBox="0 0 640 480">
|
||||
<path fill="#fff" fill-rule="evenodd" stroke="#adb5bd" stroke-width="1.1" d="M.5.5h638.9v478.9H.5z"/>
|
||||
<path fill="none" stroke="#adb5bd" stroke-width="1.1" d="m.5.5 639 479M639.5.5l-639 479"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 286 B |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 19 KiB |
5
stats.py
5
stats.py
|
@ -1,6 +1,9 @@
|
|||
from sanic.response import html
|
||||
from sanic import Blueprint
|
||||
from sanic import Blueprint, exceptions
|
||||
from ext import *
|
||||
from config import headers
|
||||
from time import time
|
||||
import asyncio
|
||||
|
||||
bp = Blueprint("stats", url_prefix="/manage")
|
||||
|
||||
|
|
|
@ -88,6 +88,9 @@
|
|||
<a href="/manage/nosecount">Nose Count</a>
|
||||
{% if order %}
|
||||
<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>
|
||||
{% endif %}
|
||||
<br clear="both" />
|
||||
|
@ -106,7 +109,7 @@
|
|||
});
|
||||
</script>
|
||||
<footer>
|
||||
Made in 🇮🇹 by <img src="/res/icons/silhouette.svg" class="icon" /> · <a href="/manage/privacy">Privacy</a>
|
||||
Made in 🇮🇹 by <img src="/res/icons/silhouette.svg" class="icon" title="ACCBCAC" /> · <a href="/manage/privacy">Privacy</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% block main %}
|
||||
<main class="container">
|
||||
<h1>Search order</h1>
|
||||
<h1>Cerca ordine</h1>
|
||||
<input id="search" type="text" onchange="updateSearch();" onclick="this.value = '';" />
|
||||
<form method="get" id="actionform" style="font-family:monospace;" action="order">
|
||||
<select id="badgelist" name="order" id="order" multiple>
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
{% block main %}
|
||||
<main class="container">
|
||||
<h1><kbd>{{order.code}}</kbd> {{order.name}} ({{order.first_name}} {{order.last_name}})</h1>
|
||||
<p><strong>Comment:</strong> {{order.comment or '--'}}<br />
|
||||
<strong>Order notes:</strong> {{order.notes or '--'}}<br />
|
||||
<strong>Status: <span style="color: {{'#900' if order.status == 'unpaid' else '#090'}}">{{order.status}}</span></strong><br />
|
||||
<p><strong>Commento:</strong> {{order.comment or '--'}}<br />
|
||||
<strong>Note ordine:</strong> {{order.notes or '--'}}<br />
|
||||
<strong>Stato ordine: <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>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://{config.HOSTNAME}/control/event/{config.ORGANIZER}/{config.EVENT_NAME}/orders/{{order.code}}/">Open on pretix</a><br /></p>
|
||||
<strong>Compagni di stanza:</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>
|
||||
<form method="post" id="actionform" action="checkin">
|
||||
<input type="hidden" value="{{order.code}}" name="code" />
|
||||
<label for="actual_room">Real Room Number</label>
|
||||
<label for="actual_room">Numero Stanza Reale</label>
|
||||
<input type="text" value="{{room_owner.actual_room or ''}}" name="actual_room" required />
|
||||
<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 />
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
{% extends "base.html" %}
|
||||
{% block main %}
|
||||
<main class="container">
|
||||
<h1>✅ Checkin done!</h1>
|
||||
<p><strong>Remember to stick the REG number to the badge! Number: {{order.badge_id}}</strong></p>
|
||||
<h1>✅ Checkin effettuato!</h1>
|
||||
<p><strong>Ricorda di apporre il numero sul badge! Numero: {{order.badge_id}}</strong></p>
|
||||
|
||||
<h2>Other members of the same room ({{room_owner.actual_room}})</h2>
|
||||
<h2>Altri membri della stessa stanza ({{room_owner.actual_room}})</h2>
|
||||
<table>
|
||||
{% for o in roommates %}
|
||||
<tr>
|
||||
<td><a href="order?order={{o.code}}">{{o.code}}</a></td>
|
||||
<td>{{o.name}}</td>
|
||||
<td><a href="order?order={{o.code}}">{{'Checkin' if not o.checked_in else '✅'}}</a></td>
|
||||
<td><a href="order?order={{o.code}}">{{'Effettua Checkin' if not o.checked_in else '✅'}}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<h3><a href="start">Checkin somebody else ➡️</a></h3>
|
||||
<h3><a href="start">Effettua un altro checkin ➡️</a></h3>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<main class="container">
|
||||
<h1>Karaoke Admin</h1>
|
||||
|
||||
<h2>Songs to sing</h2>
|
||||
<h2>Canzoni da cantare</h2>
|
||||
<table>
|
||||
{% 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 %}>
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
{% 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 %}
|
|
@ -24,7 +24,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>When{{' (convention)' if order.has_early or order.has_late else ''}}?</th>
|
||||
<td>13 October → 15 October 2023</td></td>
|
||||
<td>30 May → 3 June 2023</td></td>
|
||||
</tr>
|
||||
{% if order.has_early or order.has_late %}
|
||||
<tr>
|
||||
|
@ -53,7 +53,7 @@
|
|||
{% if order.status == 'paid' and order.room_confirmed %}
|
||||
<br />
|
||||
<img src="/res/icons/pdf.svg" class="icon" />
|
||||
<a href="/manage/download_ticket?name=RIVERSIDE-{{order.code}}.pdf" target="_blank">Download ticket PDF</a>
|
||||
<a href="/manage/download_ticket?name=BEYOND-{{order.code}}.pdf" target="_blank">Download ticket PDF</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
Loading…
Reference in New Issue