Skip to content

Commit 17e8d24

Browse files
committed
events-profiles-added keynote speakers
1 parent b5a5fbb commit 17e8d24

File tree

10 files changed

+171
-25
lines changed

10 files changed

+171
-25
lines changed

db/events.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Attendee(db.Base):
3535
name = sa.Column(sa.String(50), nullable=False)
3636
email = sa.Column(sa.String(256), unique=True, nullable=False)
3737
phone = sa.Column(sa.String(10))
38+
profile_pk = sa.Column(sa.Integer)
3839

3940
category = sa.Column(sa.String(100), nullable=False)
4041
identityCard = sa.Column(sa.String(256))
@@ -43,6 +44,20 @@ class Attendee(db.Base):
4344
fee = sa.Column(sa.Integer)
4445
status = sa.Column(p_attendees_stage, server_default='pending')
4546
ticket = sa.Column(sa.String(500))
46-
47+
4748
receiptPath = sa.Column(sa.String(256))
48-
paymentReceiptFile = sa.Column(sa.LargeBinary, nullable=True)
49+
paymentReceiptFile = sa.Column(sa.LargeBinary)
50+
51+
52+
class Profile(db.Base):
53+
__tablename__ = 'profiles'
54+
__table_args__ = {
55+
'schema' : 'conf25',
56+
'comment' : 'Speaker Details',
57+
}
58+
59+
pk = sa.Column(sa.Integer, autoincrement=True, primary_key=True)
60+
61+
name = sa.Column(sa.String(256))
62+
introduction = sa.Column(sa.Text())
63+
photoBlob = sa.Column(sa.LargeBinary)

db/programs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class Proposal(db.Base):
1818
email = sa.Column(sa.String(256))
1919
country = sa.Column(sa.String(256))
2020
category = sa.Column(sa.String(256), nullable=False)
21+
profile_pk = sa.Column(sa.Integer)
2122

2223
# Session Details
2324
session = sa.Column(sa.String(50))
@@ -55,4 +56,6 @@ class Rate(db.Base):
5556

5657
proposal_pk = sa.Column(sa.Integer, sa.ForeignKey(Proposal.pk, ondelete='CASCADE'))
5758
value = sa.Column(sa.Integer, nullable=True, comment='average value of all the rates')
58-
score = sa.Column(sa.JSON, comment='JSON data of all the ratings for a proposal')
59+
score = sa.Column(sa.JSON, comment='JSON data of all the ratings for a proposal')
60+
61+

run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import srv.rates
1313
import srv.dash
1414
import srv.mbox
15+
import srv.profiles
16+
import srv.programs
1517

1618
import jinja2
1719

srv/programs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import srv.programs.speakers

srv/programs/speakers.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import io
2+
3+
import db.events
4+
import flask
5+
import sqlalchemy as sa
6+
7+
import db
8+
import db.programs
9+
import srv.auth
10+
11+
from srv import app
12+
13+
FILE_MAGIC_NUMBERS = {
14+
b'%PDF-' : 'application/pdf',
15+
b'\xFF\xD8\xFF' : 'image/jpeg',
16+
b'\x89PNG\r\n\x1a\n' : 'image/png',
17+
}
18+
19+
@app.route('/programs/speakers')
20+
def programs_speaker_list_page():
21+
isAdmin = srv.auth.isValid(flask.request)
22+
if isAdmin is False:
23+
return srv.auth.respondInValid()
24+
25+
query = sa.select(
26+
db.events.Profile.pk,
27+
db.events.Profile.name,
28+
db.events.Profile.introduction,
29+
db.events.Profile.photoBlob,
30+
db.programs.Proposal.title,
31+
db.programs.Proposal.abstract,
32+
).where(
33+
db.programs.Proposal.session == 'keynote'
34+
).outerjoin(
35+
db.programs.Proposal,
36+
db.programs.Proposal.name == db.events.Profile.name,
37+
).order_by(
38+
db.events.Profile.pk
39+
)
40+
41+
with db.engine.connect() as connection:
42+
cursor = connection.execute(query)
43+
44+
return flask.render_template(
45+
'/speakers/speakers.djhtml',
46+
pageTitle = 'Speakers',
47+
pageDesc = 'List of all submitted speakers',
48+
baseURL = '/speakers',
49+
isAdmin = isAdmin,
50+
cursor = cursor
51+
)
52+
53+
54+
@app.route('/programs/speakers/<int:pk>')
55+
def programs_speakers_file_download(pk):
56+
query = sa.select(
57+
db.events.Profile.photoBlob,
58+
).where(
59+
db.events.Profile.pk == pk,
60+
)
61+
62+
with db.engine.connect() as connection:
63+
blob = connection.execute(query).scalar()
64+
65+
if blob is None:
66+
return 'File Not Found', 404
67+
68+
for magic, mime_type in FILE_MAGIC_NUMBERS.items():
69+
if blob.startswith(magic): break
70+
mime_type = 'application/octet-stream'
71+
72+
download_name = '{slug}.{ext}'.format(
73+
slug = pk,
74+
ext = mime_type.split('/')[1]
75+
)
76+
return flask.send_file(
77+
io.BytesIO(blob),
78+
#as_attachment = True,
79+
download_name = download_name,
80+
mimetype = mime_type,
81+
),200
82+

srv/proposals/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
import srv.proposals.crud
22
import srv.proposals.pages
3-
import srv.proposals.speakers

srv/proposals/crud.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def proposal_list_api():
4848
db.programs.Proposal.pk,
4949
db.programs.Proposal.title,
5050
db.programs.Proposal.name,
51+
db.programs.Proposal.session,
5152
db.programs.Proposal.createdOn,
5253
sa.func.coalesce(sa.func.round(sa.func.avg(db.programs.Rate.value), 0)).label('avg(rating)'), # noqa:E501
5354
).outerjoin(

srv/proposals/speakers.py

Lines changed: 0 additions & 21 deletions
This file was deleted.
249 KB
Loading
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{% extends 'base.djhtml' %}
2+
{% set pageTitle = 'Speakers' %}
3+
4+
5+
{% block head %}
6+
<style>
7+
.speaker-profile { display: flex; flex-wrap: wrap; gap: 20px; }
8+
.speaker-photo img { width: 300px; height: 300px; object-fit: cover; border: 1px solid #ddd; }
9+
.speaker-details { flex: 1; min-width: 300px; }
10+
.speaker-name { margin:0px; font-size: 24px; font-weight: bold; color: #007bff; }
11+
.speaker-title { font-size: 16px; color: #666; }
12+
.talk-title { font-size: 20px; font-style: italic; margin: 10px 0; }
13+
.abstract, .bio { font-size: 16px; line-height: 1.5; color: #333; }
14+
.resources a { color: #007bff; text-decoration: none; }
15+
.resources a:hover { text-decoration: underline; }
16+
.cta-button { display: inline-block; padding: 10px 20px; background: #007bff; color: #fff; text-decoration: none; border-radius: 4px; }
17+
.cta-button:hover { background: #0056b3; }
18+
@media (max-width: 768px) { .speaker-profile { flex-direction: column; align-items: center; } }
19+
</style>
20+
{% endblock %}
21+
22+
23+
{% block main %}
24+
<div class="content-container">
25+
<a href="/pages/schedule" class="cta-button" style="width: 200px;">Check the Schedule</a>
26+
27+
<h2 style="font-size: 28px; color: #333; margin-bottom: 20px;">Keynote Speakers</h2>
28+
29+
<section class="keynote-section" style="margin-bottom: 40px;">
30+
{% for row in cursor %}
31+
32+
<div class="speaker-profile" style="margin-bottom: 20px;">
33+
<div class="speaker-photo">
34+
35+
<img src="/programs/speakers/{{row.pk}}" alt="{{row.name}}">
36+
37+
</div>
38+
39+
<div class="speaker-details">
40+
<h3 class="speaker-name">{{row.name}}</h3>
41+
<!-- <p class="speaker-title">Vice President, Postgres Evangelist, EnterpriseDB<br>Co-founder, PostgreSQL Global Development Group</p> -->
42+
43+
<p class="bio">
44+
{{row.introduction}}
45+
</p>
46+
47+
<div class="talk-details">
48+
<p class="talk-title"><em>{{row.title}}</em></p>
49+
<p class="abstract">{{row.abstract}}</p>
50+
51+
<p class="resources"></p>
52+
</div>
53+
</div>
54+
</div>
55+
{% endfor %}
56+
57+
</section>
58+
</div>
59+
{% endblock %}
60+
61+
62+
{% block tail %}
63+
64+
{% endblock %}

0 commit comments

Comments
 (0)