Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event Modals & Split date/time fields #33

Merged
merged 4 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 82 additions & 3 deletions goathacks/admin/events.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import flask
from flask import Response, render_template, redirect, request, url_for, flash
from flask import Response, render_template, redirect, request, url_for, flash, current_app
from flask_login import current_user, login_required
from goathacks.admin import bp, forms
from goathacks import db
from goathacks.models import Event

import io, qrcode
import io, qrcode, datetime
import qrcode.image.pure

@bp.route("/events")
Expand All @@ -16,7 +16,86 @@ def list_events():

events = Event.query.all()

return render_template("events/list.html", events=events)
form = forms.EventForm()

return render_template("events/list.html", events=events, form=form)

@bp.route("/event/<int:id>/delete")
@login_required
def delete_event(id):
if not current_user.is_admin:
return {"status": "error", "message": "Unauthorized"}

event = Event.query.filter_by(id=id).first()

if event is None:
return {"status": "error", "message": "Invalid event ID"}

db.session.delete(event)
db.session.commit()

return {"status": "success"}

@bp.route("/event/<int:id>")
@login_required
def event(id):
if not current_user.is_admin:
return {"status": "error", "message": "Unauthorized"}

event = Event.query.filter_by(id=id).first()

if event is None:
return {"status": "error", "message": "Invalid event ID"}

return event.create_json()

@bp.route("/event/<int:id>", methods=["POST"])
@login_required
def update_create_event(id):
if not current_user.is_admin:
flash("Unauthorized")
return redirect(url_for("dashboard.home"))

name = request.form.get('name')
description = request.form.get('description')
location = request.form.get('location')
start_day = request.form.get('start_day')
start_time = request.form.get('start_time')
end_day = request.form.get('end_day')
end_time = request.form.get('end_time')
start = datetime.datetime.combine(datetime.date.fromisoformat(start_day),
datetime.time.fromisoformat(start_time))
end = datetime.datetime.combine(datetime.date.fromisoformat(end_day),
datetime.time.fromisoformat(end_time))
category = request.form.get("category")

if id == 0:
# new event
e = Event(
name=name,
description=description,
location=location,
start_time=start,
category=category,
end_time=end)
db.session.add(e)
db.session.commit()
current_app.logger.info(f"{current_user} is creating a new event: {e.name}")
else:
e = Event.query.filter_by(id=id).first()
if e is None:
return {"status": "error", "message": "Invalid event ID"}
e.name = name
e.description = description
e.location = location
e.start_time = start
e.end_time = end
e.category=category
db.session.commit()
current_app.logger.info(f"{current_user} is updating an existing event: {e.name}")


return redirect(url_for("admin.list_events"))

@bp.route("/events/events.json")
@login_required
Expand Down
8 changes: 5 additions & 3 deletions goathacks/admin/forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from flask_wtf import FlaskForm
from wtforms import StringField, DateTimeField, SubmitField, TextAreaField
from wtforms import StringField, DateField, TimeField, SubmitField, TextAreaField
from wtforms.validators import DataRequired

class EventForm(FlaskForm):
name = StringField("Name", validators=[DataRequired()])
description = TextAreaField("Description")
location = StringField("Location", validators=[DataRequired()])
start_time = DateTimeField("Start Time", validators=[DataRequired()])
end_time = DateTimeField("End Time", validators=[DataRequired()])
start_day = DateField("Start Day", validators=[DataRequired()])
start_time = TimeField("Start Time", validators=[DataRequired()])
end_day = DateField("End Day", validators=[DataRequired()])
end_time = TimeField("End Time", validators=[DataRequired()])
category = StringField("Category")
submit = SubmitField("Submit")
25 changes: 15 additions & 10 deletions goathacks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class User(db.Model, UserMixin):
phone = Column(String, nullable=True)
gender = Column(String, nullable=True)

def __str__(self):
return f"{self.first_name} {self.last_name} ({self.email})"
def create_json_output(lis):
hackers = []

Expand Down Expand Up @@ -48,7 +50,7 @@ def user_loader(user_id):
@login.unauthorized_handler
def unauth():
flash("Please login first")
return redirect(url_for("registration.register"))
return redirect(url_for("registration.login"))


class PwResetRequest(db.Model):
Expand All @@ -73,17 +75,20 @@ def create_json_output(lis):
events = []

for e in lis:
events.append({
'id': e.id,
'name': e.name,
'description': e.description,
'location': e.location,
'start': e.start_time,
'end': e.end_time,
'category': e.category
})
events.append(e.create_json())

return events

def create_json(self):
return {
"id": self.id,
"name": self.name,
"description": self.description,
"location": self.location,
"start_time": self.start_time.isoformat(),
"end_time": self.end_time.isoformat(),
"category": self.category
}

def get_checkins(self):
checkins = EventCheckins.query.filter_by(event_id=self.id).all()
Expand Down
2 changes: 2 additions & 0 deletions goathacks/static/js/jquery-3.6.3.min.js

Large diffs are not rendered by default.

159 changes: 157 additions & 2 deletions goathacks/templates/events/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h2>Events</h2>
<th>Category</th>
<th>Checked in</th>
<th>QR Code</th>
<th><a href="{{url_for('admin.new_event')}}">New</a></th>
<th><a href="#editModal" data-bs-toggle="modal" data-id="0">New</a></th>
</tr>
</thead>
<tbody>
Expand All @@ -34,11 +34,166 @@ <h2>Events</h2>
<td>{{ event.get_checkins()|length }}</td>
<td><a href='{{ url_for("admin.qrcode_event", id=event.id)
}}'>QR Code</a></td>
<td><a href="{{url_for('admin.edit_event', id=event.id)}}">Edit</a></td>
<td><a href="#editModal" data-bs-toggle="modal" data-id="{{ event.id}}" >Edit</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

<div class="modal" id="editModal" tabindex="-1" aria-labelledby="editModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="editModalLabel">Event</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form class="form" id="edit-form" action="/admin/events/0" role="form" method="post">
<div class="modal-body">
{{ form.csrf_token }}
<div class="form-floating mb-3 required">
{{ form.name(class="form-control") }}
{{ form.name.label() }}
</div>
<div class="form-floating mb-3">
{{ form.description(class="form-control") }}
{{ form.description.label() }}
</div>
<div class="form-floating mb-3 required">
{{ form.location(class="form-control") }}
{{ form.location.label() }}
</div>
<div class="form-floating mb-3">
{{ form.category(class="form-control") }}
{{ form.category.label() }}
</div>
<div class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.start_day(class="form-control") }}
{{ form.start_day.label() }}
</div>
</div>
<div class="col">
<div class="form-floating mb-3 required">
{{ form.start_time(class="form-control") }}
{{ form.start_time.label() }}
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.end_day(class="form-control") }}
{{ form.end_day.label() }}
</div>
</div>
<div class="col">
<div class="form-floating mb-3 required">
{{ form.end_time(class="form-control") }}
{{ form.end_time.label() }}
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-id="0" id="delete">Delete</button>
<button type="submit" class="btn btn-primary" id="edit-save">Save changes</button>
</div>
</form>
</div>
</div>
</div>

<script src="{{ url_for('static', filename='js/jquery-3.6.3.min.js') }}" charset="utf-8"></script>

<script charset="utf-8">
const editButton = document.getElementById("edit-save")

$('#delete').on("click", (event) => {
if (window.confirm("Delete this event?")) {
console.log("Got OK")
deleteButton = document.getElementById("delete")
id = deleteButton.dataset.id
$.get(`/admin/event/${id}/delete`, (data) => {
if (data.status == "error") {
window.alert(`Error: ${data.message}`)
} else {
window.alert("Success")
}
location.reload()
})
}
})

$('#editModal').on('show.bs.modal', function(event) {
var modal = $(this)
modal.find('#name').val('')
modal.find('#location').val('')
modal.find('#description').val('')
modal.find('#start_day').val('')
modal.find('#start_time').val('')
modal.find('#end_day').val('')
modal.find('#end_time').val('')

var button = $(event.relatedTarget)
var name,description,loc,start_time,start_day,end_time,end_day
id = button.data('id')

saveButton = document.getElementById("edit-save")
saveButton.dataset.id = id

deleteButton = document.getElementById("delete")
deleteButton.dataset.id = id

editForm = document.getElementById("edit-form")
editForm.action = "/admin/event/" + id

if (id) {
$.get(`/admin/event/${id}`, (data) => {

if (data.status == "error") {
// This is a new event, do nothing!
} else {
name = data.name,
description = data.description,
loc = data.location,
category = data.category

start = new Date(data.start_time)

var day = ("0" + start.getDate()).slice(-2);
var month = ("0" + (start.getMonth() + 1)).slice(-2);

start_day = start.getFullYear()+"-"+(month)+"-"+(day);
start_time = `${start.getHours()}:${padTwoDigits(start.getMinutes())}`
end = new Date(data.end_time)

var day = ("0" + end.getDate()).slice(-2);
var month = ("0" + (end.getMonth() + 1)).slice(-2);

end_day = end.getFullYear()+"-"+(month)+"-"+(day);
end_time = `${end.getHours()}:${padTwoDigits(end.getMinutes())}`
}

modal.find('#name').val(name)
modal.find('#location').val(loc)
modal.find('#description').val(description)
modal.find('#start_day').val(start_day)
modal.find('#start_time').val(start_time)
modal.find('#end_day').val(end_day)
modal.find('#end_time').val(end_time)
modal.find('#category').val(category)


});
}
})

function padTwoDigits(num) {
return num.toString().padStart(2, '0')
}
</script>
{% endblock %}
2 changes: 1 addition & 1 deletion goathacks/templates/home
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Flask-Login==0.6.2
Flask-Migrate==4.0.0
Flask-SQLAlchemy==3.0.2
Flask-WTF==1.0.1
greenlet==2.0.1
greenlet
itsdangerous==2.1.2
Jinja2==3.1.2
Mako==1.2.4
Expand All @@ -19,7 +19,7 @@ psycopg2==2.9.5
pynvim==0.4.3
python-dotenv==0.21.0
SQLAlchemy==1.4.44
uWSGI==2.0.21
uWSGI
Werkzeug==2.2.2
WTForms==3.0.1
ulid
Expand Down