Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Cara Salter
a0402feab0 about: Update events coordinator ID for automatic photo 2024-08-31 12:57:28 -04:00
Cara Salter
596847ca0a admin: Add events coordinator to officer form options 2024-08-31 12:53:09 -04:00
Cara Salter
228ff85e6a
finish event checkins 2024-08-28 16:51:15 -04:00
Cara Salter
302fe4289a Init event checkin structure 2024-08-28 16:16:45 -04:00
9 changed files with 162 additions and 7 deletions

View file

@ -8,7 +8,7 @@ from io import BytesIO
from PIL import Image
import base64
from acmsite.models import Link, Officer, User, Event
from acmsite.models import EventCheckin, Link, Officer, User, Event
from acmsite import models
from .forms import EventForm, LinkForm, OfficerForm
@ -155,6 +155,28 @@ def update_create_event(id):
return redirect(url_for("admin.events"))
@bp.route("/event/<string:id>/checkins")
@login_required
def event_checkins(id):
if not current_user.is_admin:
flash("Unauthorized")
return redirect(url_for("dashboard.home"))
event = db.session.execute(db.select(Event).where(Event.id == id)).scalar_one_or_none()
if event is None:
flash("Invalid event")
return redirect(url_for("admin.events"))
checkins = db.session.execute(db.select(EventCheckin).where(EventCheckin.event ==
id).join(User)).scalars()
processed_checkins = []
for c in checkins:
user = db.session.execute(db.select(User).where(User.id == c.user)).scalar_one_or_none()
processed_checkins.append({"name": f"{user.first_name} {user.last_name}", "email": user.email})
return render_template("admin/checkins.html", checkins=processed_checkins,e=event)
@bp.route("/links")
@login_required
def links():

View file

@ -17,7 +17,8 @@ class LinkForm(FlaskForm):
class OfficerForm(FlaskForm):
position = SelectField("Position", choices=["President", "Vice President",
"Treasurer", "Secretary", "PR Chair", "Hackathon Manager 1",
"Treasurer", "Secretary", "PR Chair",
"Event Coordinator", "Hackathon Manager 1",
"Hackathon Manager 2", "System Administrator"],
validators=[DataRequired()])
term_start = DateField("Term Start", validators=[DataRequired()])

View file

@ -1,9 +1,47 @@
from flask import Blueprint, render_template
from datetime import datetime
from flask import Blueprint, current_app, flash, redirect, render_template, url_for
from flask_login import login_required, current_user
from ulid import ulid
from acmsite.models import Event, EventCheckin
from acmsite import db
bp = Blueprint('dashboard', __name__, url_prefix='/dashboard')
@bp.route("/")
@login_required
def home():
return render_template('dashboard.html')
now = datetime.now()
events = db.session.execute(db.select(Event).where(Event.start_time < now,
Event.end_time >
now)).scalars()
return render_template('dashboard.html', events=events)
@bp.route("/checkin/<string:event_id>")
@login_required
def checkin(event_id):
# actually first check if the event even exists
event = db.get_or_404(Event, event_id)
# first check if this user has already checked in
checkins = db.session.execute(db.select(EventCheckin).where(EventCheckin.user ==
current_user.id,
EventCheckin.event
==event_id)).scalar_one_or_none()
current_app.logger.debug(checkins)
if checkins is None:
# There's not a checkin already, let's create one!
check = EventCheckin(
id = ulid(),
user = current_user.id,
event = event_id)
db.session.add(check)
db.session.commit()
flash(f"Checked in to {event.name} successfully")
return redirect(url_for("dashboard.home"))
else:
flash(f"You've already checked in to {event.name}")
return redirect(url_for("dashboard.home"))

View file

@ -80,6 +80,12 @@ class Event(db.Model):
"end_time": self.end_time.isoformat(),
}
class EventCheckin(db.Model):
__tablename__ = "acm_checkins"
id = Column(String, primary_key=True)
user = Column(String, ForeignKey("acm_users.id"), nullable=False)
event = Column(String, ForeignKey("acm_events.id"), nullable=False)
class Link(db.Model):
__tablename__ = "acm_links"
id = Column(String, primary_key=True)

View file

@ -74,12 +74,12 @@ very friendly. You can find a list of our upcoming events and meetings <a href="
</div>
<div class="col">
<div class="card" id="events-coordinator">
<img class="card-img-top" id="Events Coordinator-img" src="{{ url_for('static',
<img class="card-img-top" id="Event Coordinator-img" src="{{ url_for('static',
filename='img/officers/placeholder.png')
}}" alt="Events Coordinator">
}}" alt="Event Coordinator">
<div class="card-body">
<h5 class="card-title">Events Coordinator</h5>
<p class="card-text" id="Events Coordinator-name">Unavailable</p>
<p class="card-text" id="Event Coordinator-name">Unavailable</p>
</div>
</div>
</div>

View file

@ -0,0 +1,35 @@
{% extends "admin/admin-layout.html" %}
{% import "bootstrap5/form.html" as wtf %}
{% block app_content %}
<h1>Checkins for `{{ e.name }}`</h1>
{% for c in checkins %}
{{ c.__dict__ }}
{% endfor %}
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{% for c in checkins %}
<tr>
<td>{{ c.name }}</td>
<td>{{ c.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h3>Copy-pastable list for CampusGroups</h3>
{% for c in checkins %}
{{ c.email }},
{% endfor %}
{% endblock %}

View file

@ -40,6 +40,11 @@
<li class="dropdown-item">
<a href="#deleteModal"
data-bs-toggle="modal" data-id="{{ e.id }}">Delete Event</a>
</li>
<li class="dropdown-item">
<a href="{{ url_for('admin.event_checkins',
id=e.id) }}">Event Checkins</a>
</li>
</ul>
</div>
</td>

View file

@ -4,6 +4,19 @@
<h1>Welcome back, {{ current_user.first_name }}!</h1>
{% if events %}
<p>The following events are available for check-in:</p>
{% for e in events %}
<h5>{{ e.name }} <a class="btn btn-primary" href="{{ url_for('dashboard.checkin', event_id=e.id)
}}">Check in</a></h5>
{% endfor %}
{% else %}
<p>There are no events available for check-in.</p>
{% endif %}
<hr/>
<p>For a list of upcoming events, take a look at our <a href="{{
url_for('main.events')
}}">events

View file

@ -0,0 +1,35 @@
"""add event checkins
Revision ID: 53a76e988b5a
Revises: 300f24071c14
Create Date: 2024-08-25 15:18:22.451548
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '53a76e988b5a'
down_revision = '300f24071c14'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('acm_checkins',
sa.Column('id', sa.String(), nullable=False),
sa.Column('user', sa.String(), nullable=False),
sa.Column('event', sa.String(), nullable=False),
sa.ForeignKeyConstraint(['event'], ['acm_events.id'], ),
sa.ForeignKeyConstraint(['user'], ['acm_users.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('acm_checkins')
# ### end Alembic commands ###