mega: Oh wow lots of things

- Static files
- Dashboard
- User registration
- Initial work on fixing templates
This commit is contained in:
Cara Salter 2022-12-06 10:10:58 -05:00
parent ff62e1d28d
commit 26468e82ea
No known key found for this signature in database
GPG key ID: 90C66610C82B29CA
22 changed files with 7201 additions and 74 deletions

View file

@ -32,7 +32,7 @@ daemon:
@echo "--- STARTING UWSGI DAEMON ---"
@echo ""
@echo ""
source .venv/bin/activate && uwsgi --py-autoreload=5 --socket 0.0.0.0:8000 --protocol=http --wsgi-file goathacks.py --enable-threads --master
source .venv/bin/activate && flask run
@echo ""
@echo ""
@echo "--- STARTING UWSGI DAEMON ---"

View file

@ -2,11 +2,13 @@ from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_assets import Bundle, Environment
db = SQLAlchemy()
migrate = Migrate()
login = LoginManager()
environment = Environment()
def create_app():
app = Flask(__name__)
@ -16,11 +18,18 @@ def create_app():
db.init_app(app)
migrate.init_app(app, db)
login.init_app(app)
environment.init_app(app)
scss = Bundle('css/style.scss', filters='scss',
output='css/style.css')
environment.register('scss', scss)
from .models import User
from . import registration
from . import dashboard
app.register_blueprint(registration.bp)
app.register_blueprint(dashboard.bp)
return app

View file

@ -0,0 +1,10 @@
from flask import Blueprint, render_template
from flask_login import login_required
bp = Blueprint("dashboard", __name__, url_prefix="/dashboard")
@bp.route("/")
@login_required
def home():
return render_template("dashboard.html")

View file

@ -14,6 +14,8 @@ class User(db.Model, UserMixin):
active = Column(Boolean, nullable=False, default=True)
is_admin = Column(Boolean, nullable=False, default=False)
waitlisted = Column(Boolean, nullable=False, default=False)
shirt_size = Column(String, nullable=True)
accomodations = Column(String, nullable=True)
@login.user_loader

View file

@ -1,5 +1,5 @@
from datetime import datetime
from flask import Blueprint, flash, render_template, request
from flask import Blueprint, flash, redirect, render_template, request, url_for
import flask_login
from flask_login import current_user
from goathacks.registration.forms import LoginForm, RegisterForm
@ -10,13 +10,14 @@ from goathacks.models import User
bp = Blueprint('registration', __name__, url_prefix="/registration")
@bp.route("/")
@bp.route("/", methods=["GET", "POST"])
def register():
if current_user.is_authenticated:
flash("You are already registered and logged in!")
print("got register")
form = RegisterForm(request.form)
if request.method == 'POST' and form.validate():
if request.method == 'POST':
print("Got form")
email = request.form.get('email')
first_name = request.form.get('first_name')
last_name = request.form.get('last_name')
@ -34,11 +35,15 @@ def register():
last_login=datetime.now(),
)
# Count of all non-waitlisted hackers
# num_not_waitlisted = len(db.session.execute(db.select(User).filter(waitlisted=False)).scalars().all())
# print(num_not_waitlisted)
db.session.add(user)
db.session.commit()
flask_login.login_user(user)
return "OK"
return redirect(url_for("dashboard.home"))
else:
flash("Passwords do not match")

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,147 @@
@font-face {
font-family: "Krungthep";
src: url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.eot");
src: url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.eot?#iefix") format("embedded-opentype"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.woff2") format("woff2"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.woff") format("woff"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.ttf") format("truetype"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.svg#Krungthep") format("svg");
}
html {
height: 100%;
}
body {
background-color: #003049;
font-family: 'Montserrat', sans-serif;
font-size: 1.1rem;
color: #eee;
position: relative;
min-height: 100%;
}
p {
line-height: 2rem;
}
#logo-container {
display: flex;
justify-content: center;
flex-direction: row;
padding-top: 5px;
padding-bottom: 5px;
height: 100%;
width: 100%;
}
#goat {
height: 100%;
}
.button-collapse {
color: #26a69a;
}
.parallax-container {
min-height: 380px;
line-height: 0;
height: auto;
color: rgba(255, 255, 255, 0.9);
}
.parallax-container .section {
width: 100%;
}
label {
color: white !important;
}
@media only screen and (max-width: 992px) {
.parallax-container .section {
top: 40%;
}
#index-banner .section {
top: 10%;
}
}
@media only screen and (max-width: 600px) {
.parallax-container .section {
height: auto;
overflow: auto;
}
.container {
height: auto;
}
#index-banner .section {
top: 0;
}
}
#tagline {
font-weight: 600;
}
#event-info {
font-weight: 400;
}
#registration-banner {
min-height: 100px;
max-height: 150px;
}
#registration-banner .section {
top: auto;
}
.icon-block {
padding: 0 15px;
}
.icon-block .material-icons {
font-size: inherit;
}
.parallax img {
display: inherit;
max-width: 200%;
}
#mlh-trust-badge {
display: block;
max-width: 100px;
min-width: 60px;
position: fixed;
right: 50px;
top: 0;
width: 10%;
z-index: 10000;
}
nav {
line-height: normal !important;
font-family: "Jost", sans-serif;
font-weight: 700;
}
/*
.navbar-brand {
} */
.footer-nav {
position: absolute;
bottom: 0;
width: 100%;
}
label {
padding-bottom: 0.5rem;
}
form input {
border-radius: 5px;
}
form input[type="submit"] {
background: #26a69a;
border-radius: 10px;
border-color: #26a69a;
}

View file

@ -0,0 +1,148 @@
$color-bg: #003049;
$color-fg: #eee;
$color-section-bg: #F5665B;
$color-accent: #26a69a;
@font-face {font-family: "Krungthep"; src: url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.eot"); src: url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.eot?#iefix") format("embedded-opentype"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.woff2") format("woff2"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.woff") format("woff"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.ttf") format("truetype"), url("//db.onlinewebfonts.com/t/736cf5b08b01082a3645e14038868e20.svg#Krungthep") format("svg"); }
html {
height: 100%;
}
body {
background-color: $color-bg;
font-family: 'Montserrat', sans-serif;
font-size: 1.1rem;
color: $color-fg;
position: relative;
min-height: 100%;
}
p {
line-height: 2rem;
}
#logo-container {
display: flex;
justify-content: center;
flex-direction: row;
padding-top: 5px;
padding-bottom: 5px;
height: 100%;
width: 100%;
}
#goat {
height: 100%;
}
.button-collapse {
color: $color-accent;
}
.parallax-container {
min-height: 380px;
line-height: 0;
height: auto;
color: rgba(255,255,255,.9);
}
.parallax-container .section {
width: 100%;
}
label {
color: white !important;
}
@media only screen and (max-width : 992px) {
.parallax-container .section {
top: 40%;
}
#index-banner .section {
top: 10%;
}
}
@media only screen and (max-width : 600px) {
.parallax-container .section {
height: auto;
overflow: auto;
}
.container {
height: auto;
}
#index-banner .section {
top: 0;
}
}
#tagline {
font-weight: 600;
}
#event-info {
font-weight: 400;
}
#registration-banner {
min-height: 100px;
max-height: 150px;
}
#registration-banner .section{
top: auto;
}
.icon-block {
padding: 0 15px;
}
.icon-block .material-icons {
font-size: inherit;
}
.parallax img {
display: inherit;
max-width: 200%;
}
#mlh-trust-badge {
display: block;
max-width: 100px;
min-width: 60px;
position: fixed;
right: 50px;
top: 0;
width: 10%;
z-index: 10000;
}
nav {
line-height: normal !important;
font-family: "Jost", sans-serif;
font-weight: 700;
}
/*
.navbar-brand {
} */
.footer-nav {
position: absolute;
bottom: 0;
width: 100%;
}
// Forms
label {
padding-bottom: 0.5rem;
}
form {
input {
border-radius: 5px;
}
input[type="submit"] {
background: $color-accent;
border-radius: 10px;
border-color: $color-accent;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View file

@ -0,0 +1,192 @@
'use strict'
let pn = new PubNub({
publishKey: '',
subscribeKey: '',
ssl: true
})
pn.subscribe({
channels: ['hackWPI-admin']
})
pn.addListener({
message: (msg) => {
msg = msg.message
console.log(msg)
const id = msg.id
if (msg.action === 'check_in') {
document.getElementById(id + '-check_in').outerHTML = ''
document.getElementById(id + '-checked_in').innerHTML = 'True'
} else if (msg.action === 'drop') {
document.getElementById(id + '-row').outerHTML = ''
} else if (msg.action === 'promote_from_waitlist') {
document.getElementById(id + '-promote_from_waitlist').outerHTML = ''
document.getElementById(id + '-waitlisted').innerHTML = 'False'
} else if (msg.action === 'new_user' || msg.action === 'refresh' || msg.action.split(':')[0] === 'change_admin') {
window.location.reload(true)
}
}
})
let successColor = '#18BC9C'
let errColor = '#E74C3C'
$(document).ready(() => {
let timeout = setTimeout("window.location.reload(true);", 300000)
const resetTimeout = () => {
clearTimeout(timeout)
timeout = setTimeout("window.location.reload(true);", 300000)
}
$('a.check_in').click((e) => {
e.preventDefault()
let id = e.target.id.split('-')[0]
console.log('check in ' + id)
checkIn(id)
})
$('a.drop').click((e) => {
e.preventDefault()
let id = e.target.id.split('-')[0]
console.log('drop ' + id)
drop(id)
})
$('a.demote_admin').click((e) => {
e.preventDefault()
let id = e.target.id.split('-')[0]
console.log('demote admin ' + id)
changeAdmin(id, 'demote')
})
$('a.promote_admin').click((e) => {
e.preventDefault()
let id = e.target.id.split('-')[0]
console.log('promote admin ' + id)
changeAdmin(id, 'promote')
})
$('a.promote_from_waitlist').click((e) => {
e.preventDefault()
let id = e.target.id.split('-')[0]
console.log('promote waitlist ' + id)
promoteFromWaitlist(id)
})
})
const promoteFromWaitlist = (id) => {
swal({
title: 'Promote hacker ' + id + ' off the waitlist?',
text: 'Are you sure you wish to promote this hacker off the waitlist?',
type: 'info',
showCancelButton: true,
closeOnConfirm: false,
confirmButtonText: 'Yes, promote!',
confirmButtonColor: successColor
}, () => {
$.get('/promote_from_waitlist?mlh_id=' + id, (data) => {
let title = ''
let msg = ''
let type = ''
if (data.status === 'success') {
title = 'Promoted!'
msg = 'The hacker was successfully promoted off the waitlist!'
type = 'success'
} else {
title = 'Error!'
msg = JSON.stringify(data)
type = 'error'
}
swal(title, msg, type)
})
})
}
const changeAdmin = (id, action) => {
swal({
title: 'Modify:' + action + ' admin prviliges on hacker ' + id + ' ?',
text: 'Are you sure you wish to modify:' + action + ' this hacker\'s administrative privileges?',
type: 'warning',
showCancelButton: true,
closeOnConfirm: false,
confirmButtonText: 'Yes, ' + action + '!',
confirmButtonColor: errColor
}, () => {
$.get('/change_admin?mlh_id=' + id + '&action=' + action, (data) => {
let title = ''
let msg = ''
let type = ''
if (data.status === 'success') {
title = 'Modified!'
msg = 'The hacker\'s administrative privileges have been modified:' + action + '!'
type = 'success'
} else {
title = 'Error!'
msg = JSON.stringify(data)
type = 'error'
}
swal({title: title, msg: msg, type: type}, () => window.location.reload(true))
})
})
}
const drop = (id) => {
swal({
title: 'Drop hacker ' + id + ' ?',
text: 'Are you sure you wish to drop this hacker\'s application?',
type: 'warning',
showCancelButton: true,
closeOnConfirm: false,
confirmButtonText: 'Yes, drop!',
confirmButtonColor: errColor
}, () => {
$.get('/drop?mlh_id=' + id, (data) => {
let title = ''
let msg = ''
let type = ''
if (data.status === 'success') {
title = 'Dropped!'
msg = 'The hacker\'s application was successfully dropped!'
type = 'success'
} else {
title = 'Error!'
msg = JSON.stringify(data)
type = 'error'
}
swal(title, msg, type)
})
})
}
const checkIn = (id) => {
swal({
title: 'Check in hacker ' + id + ' ?',
text: 'Are you sure you wish to check in this hacker?',
type: 'info',
showCancelButton: true,
closeOnConfirm: false,
confirmButtonText: 'Yes, check in!',
confirmButtonColor: successColor
}, () => {
$.get('/check_in?mlh_id=' + id, (data) => {
let title = ''
let msg = ''
let type = ''
if (data.status === 'success') {
title = 'Checked in!'
msg = 'The hacker was checked in!'
type = 'success'
// Update table in admin.html (This is a hack, and a terrible one, but at least there's feedback on the change.
document.getElementById(id + '-checked_in').innerHTML = "True"
} else {
title = 'Error!'
msg = JSON.stringify(data)
type = 'error'
}
if (data.status === 'success' && data.action === 'check_in' && data.minor === true) {
msg += '\nATTENTION:\nHacker is a minor, please ensure they have the minor consent form!'
}
swal(title, msg, type)
})
})
}

View file

@ -0,0 +1,3 @@
$(document).ready(function(){
$('.parallax').parallax();
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
(function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],function($){return factory($)})}else if(typeof module==="object"&&typeof module.exports==="object"){exports=factory(require("jquery"))}else{factory(jQuery)}})(function($){$.easing.jswing=$.easing.swing;var pow=Math.pow,sqrt=Math.sqrt,sin=Math.sin,cos=Math.cos,PI=Math.PI,c1=1.70158,c2=c1*1.525,c3=c1+1,c4=2*PI/3,c5=2*PI/4.5;function bounceOut(x){var n1=7.5625,d1=2.75;if(x<1/d1){return n1*x*x}else if(x<2/d1){return n1*(x-=1.5/d1)*x+.75}else if(x<2.5/d1){return n1*(x-=2.25/d1)*x+.9375}else{return n1*(x-=2.625/d1)*x+.984375}}$.extend($.easing,{def:"easeOutQuad",swing:function(x){return $.easing[$.easing.def](x)},easeInQuad:function(x){return x*x},easeOutQuad:function(x){return 1-(1-x)*(1-x)},easeInOutQuad:function(x){return x<.5?2*x*x:1-pow(-2*x+2,2)/2},easeInCubic:function(x){return x*x*x},easeOutCubic:function(x){return 1-pow(1-x,3)},easeInOutCubic:function(x){return x<.5?4*x*x*x:1-pow(-2*x+2,3)/2},easeInQuart:function(x){return x*x*x*x},easeOutQuart:function(x){return 1-pow(1-x,4)},easeInOutQuart:function(x){return x<.5?8*x*x*x*x:1-pow(-2*x+2,4)/2},easeInQuint:function(x){return x*x*x*x*x},easeOutQuint:function(x){return 1-pow(1-x,5)},easeInOutQuint:function(x){return x<.5?16*x*x*x*x*x:1-pow(-2*x+2,5)/2},easeInSine:function(x){return 1-cos(x*PI/2)},easeOutSine:function(x){return sin(x*PI/2)},easeInOutSine:function(x){return-(cos(PI*x)-1)/2},easeInExpo:function(x){return x===0?0:pow(2,10*x-10)},easeOutExpo:function(x){return x===1?1:1-pow(2,-10*x)},easeInOutExpo:function(x){return x===0?0:x===1?1:x<.5?pow(2,20*x-10)/2:(2-pow(2,-20*x+10))/2},easeInCirc:function(x){return 1-sqrt(1-pow(x,2))},easeOutCirc:function(x){return sqrt(1-pow(x-1,2))},easeInOutCirc:function(x){return x<.5?(1-sqrt(1-pow(2*x,2)))/2:(sqrt(1-pow(-2*x+2,2))+1)/2},easeInElastic:function(x){return x===0?0:x===1?1:-pow(2,10*x-10)*sin((x*10-10.75)*c4)},easeOutElastic:function(x){return x===0?0:x===1?1:pow(2,-10*x)*sin((x*10-.75)*c4)+1},easeInOutElastic:function(x){return x===0?0:x===1?1:x<.5?-(pow(2,20*x-10)*sin((20*x-11.125)*c5))/2:pow(2,-20*x+10)*sin((20*x-11.125)*c5)/2+1},easeInBack:function(x){return c3*x*x*x-c1*x*x},easeOutBack:function(x){return 1+c3*pow(x-1,3)+c1*pow(x-1,2)},easeInOutBack:function(x){return x<.5?pow(2*x,2)*((c2+1)*2*x-c2)/2:(pow(2*x-2,2)*((c2+1)*(x*2-2)+c2)+2)/2},easeInBounce:function(x){return 1-bounceOut(1-x)},easeOutBounce:bounceOut,easeInOutBounce:function(x){return x<.5?(1-bounceOut(1-2*x))/2:(1+bounceOut(2*x-1))/2}})});

6478
goathacks/static/js/materialize.js vendored Normal file

File diff suppressed because one or more lines are too long

10
goathacks/static/js/materialize.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,20 @@
{% include 'header.html' %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flashed-content">
{% for m in messages %}
<li class="message">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}
This content block is still being worked on!
{% endblock %}
</div>
{% include 'footer.html' %}

View file

@ -53,7 +53,7 @@
<div class="contact-section" style="height: 100%;">
<div class="container">
<div class="row center justify-content-center" style="margin-top: 10%;">
<h1>Hi {{ name }}!</h1>
<h1>Hi {{ current_user.first_name }}!</h1>
{% if waitlisted %}
<h2>You are waitlisted, if space opens up we will let you know...</h2>
{% else %}
@ -64,9 +64,10 @@
Forgot to upload your resume while registering? No worries, submit it below.
</div>
<div class="row center justify-content-center">
<h5>Make sure to join the Slack and enter your shirt size below!</h5>
<h5>Make sure to join the Discord and enter your shirt size below!</h5>
<p>(Please note that due to COVID-19 constraints, we can't guarantee that all participants will receive Hack@WPI t-shirts this year but we are trying to find a way!)</p>
<a href="https://join.slack.com/t/wpi-rqw4180/shared_invite/zt-1089kvjx1-3b6v152r6a_fX7NS8EGL9g" style="margin: 5px;" class="btn btn-lg btn-primary btn-invert">Slack</a>
<a href="https://discord.gg/G3pseHPRNv" style="margin: 5px;"
class="btn btn-lg btn-primary btn-invert">Discord</a>
</div>
<div class="row center justify-content-center" style="background-color: #974355; padding: 20; margin-left: 20; margin-right: 20; border-radius: 5px;">
<form method="get" action="/shirtpost">

View file

@ -4,7 +4,9 @@
<head>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link href="../static/css/style.css" rel="stylesheet">
{% assets 'scss' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
</head>
<style>

View file

@ -1,69 +1,44 @@
{% include 'header.html' %}
<link href="../static/css/materialize.min.css" rel="stylesheet">
<style>
a{
color: skyblue;
}
</style>
<script>
function resumeChange() {
let val = document.getElementById('resume').value;
val = val.split(/\\|\//gi).slice(-1)[0]
document.getElementById('filename').setAttribute('value', val);
}
</script>
{% extends 'base.html' %}
{% block content %}
<div style="height: 100%;">
<div id="registration-banner" class="parallax-container valign-wrapper">
<div class="section">
<h3 class="header center text-darken-2">Registration</h3>
<h3 class="header-center text-darken-2">Registration</h3>
</div>
<div class="parallax"><img src="{{url_for('static', filename='img/background1.jpg')}}"
alt="background"></div>
</div>
<div class="parallax"><img src="../static/img/background1.jpg" alt="background"></div>
</div>
<div class="container">
<div class="container">
<Center><h2>Hi {{ name }}, just a few more steps!</h2></Center>
<div class="section" style="background-color: #974355; padding: 20px;">
<form method="post" action="/register" enctype="multipart/form-data">
<form method="post">
{{ form.csrf_token }}
<div>
<p><b>If you'd like, add your resume to send to sponsors... </b></p>
<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input id="resume" name="resume" type="file" oninput="resumeChange()"/>
{{ form.email}}<br/> {{ form.email.label }}
</div>
<div class="file-path-wrapper white-text">
<input disabled id="filename" class="file-path validate white-text" type="text">
<div>
{{ form.password}}<br/>{{form.password.label}}
</div>
<div>
{{ form.password_confirm}}<br/>{{form.password_confirm.label}}
</div>
<div>
{{form.first_name}}<br/>{{form.first_name.label}}
</div>
<div>
{{form.last_name}}<br/>{{form.last_name.label}}
</div>
<div>
<label for="agree_coc">I confirm that I have read and agree to the
Code of Conduct</label>
<input type="checkbox" id="agree_coc" name="agree_coc">
</div>
<div>
{{form.submit}}
</div>
<p><i>No worries if you don't have one on hand, you can come back and upload it later via the Hack@WPI dashboard!</i></p>
<p>Please take a moment to review the following policies and check all the boxes below so we can finalize your registration:</p>
<p>
<center><a href="/tos">Hack@WPI's Terms and Conditions</a></center>
</p>
<p>
<center><a href="https://github.com/MLH/mlh-policies/blob/master/data-sharing.md">MLH's Data Sharing Notice</a></center>
</p>
<p>
<center><a href="https://mlh.io/privacy">MLH's Privacy Policy</a></center>
</p>
<p>
<center><a href="https://github.com/MLH/mlh-policies/blob/master/prize-terms-and-conditions/contest-terms.md">MLH's
Contest Terms and Conditions</a></center>
</p>
<p>
<center><a href="https://static.mlh.io/docs/mlh-code-of-conduct.pdf">MLH's Code of Conduct</a></center>
</p>
<br>
<input type="checkbox" name="tos" id="checkboxid" required><label for="checkboxid"><b style="color:white;">*I have read and agree to the Hack@WPI Terms and Conditions</b></label>
<input type="checkbox" name="mlh1" id="checkboxid1" required><label for="checkboxid1"><b style="color:white;">*I have read and agree to the MLH Code of Conduct</b></label>
<input type="checkbox" name="mlh2" id="checkboxid2" required><label for="checkboxid2"><b style="color:white;">*I authorize you to share my application/registration information with Major League Hacking for event administration, ranking, and MLH administration in-line with the MLH Privacy Policy. I further agree to the terms of both the MLH Contest Terms and Conditions and the MLH Privacy Policy.</b></label>
<input type="checkbox" name="mlh3" id="checkboxid3" required><label for="checkboxid3"><b style="color:white;">*I authorize MLH to send me pre- and post-event information emails, which contain free credit and opportunities from their partners.</b></label>
<input type="checkbox" name="mlh3" id="checkboxid4" required><label for="checkboxid4"><b style="color:white;">*I understand that in-person participation is limited to WPI students that are part of the testing protocol only.</b></label>
<br><br>
<center><input name="submit" class="btn btn-lg btn-primary btn-invert" type="submit" value="Submit"/></center>
</form>
</div>
</div>
</div>
{% include 'footer.html' %}
{% endblock %}

View file

@ -0,0 +1,69 @@
{% include 'header.html' %}
<link href="../static/css/materialize.min.css" rel="stylesheet">
<style>
a{
color: skyblue;
}
</style>
<script>
function resumeChange() {
let val = document.getElementById('resume').value;
val = val.split(/\\|\//gi).slice(-1)[0]
document.getElementById('filename').setAttribute('value', val);
}
</script>
<div style="height: 100%;">
<div id="registration-banner" class="parallax-container valign-wrapper">
<div class="section">
<h3 class="header center text-darken-2">Registration</h3>
</div>
<div class="parallax"><img src="../static/img/background1.jpg" alt="background"></div>
</div>
<div class="container">
<div class="container">
<Center><h2>Hi {{ name }}, just a few more steps!</h2></Center>
<div class="section" style="background-color: #974355; padding: 20px;">
<form method="post" action="/register" enctype="multipart/form-data">
<div>
<p><b>If you'd like, add your resume to send to sponsors... </b></p>
<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input id="resume" name="resume" type="file" oninput="resumeChange()"/>
</div>
<div class="file-path-wrapper white-text">
<input disabled id="filename" class="file-path validate white-text" type="text">
</div>
</div>
</div>
<p><i>No worries if you don't have one on hand, you can come back and upload it later via the Hack@WPI dashboard!</i></p>
<p>Please take a moment to review the following policies and check all the boxes below so we can finalize your registration:</p>
<p>
<center><a href="/tos">Hack@WPI's Terms and Conditions</a></center>
</p>
<p>
<center><a href="https://github.com/MLH/mlh-policies/blob/master/data-sharing.md">MLH's Data Sharing Notice</a></center>
</p>
<p>
<center><a href="https://mlh.io/privacy">MLH's Privacy Policy</a></center>
</p>
<p>
<center><a href="https://github.com/MLH/mlh-policies/blob/master/prize-terms-and-conditions/contest-terms.md">MLH's
Contest Terms and Conditions</a></center>
</p>
<p>
<center><a href="https://static.mlh.io/docs/mlh-code-of-conduct.pdf">MLH's Code of Conduct</a></center>
</p>
<br>
<input type="checkbox" name="tos" id="checkboxid" required><label for="checkboxid"><b style="color:white;">*I have read and agree to the Hack@WPI Terms and Conditions</b></label>
<input type="checkbox" name="mlh1" id="checkboxid1" required><label for="checkboxid1"><b style="color:white;">*I have read and agree to the MLH Code of Conduct</b></label>
<input type="checkbox" name="mlh2" id="checkboxid2" required><label for="checkboxid2"><b style="color:white;">*I authorize you to share my application/registration information with Major League Hacking for event administration, ranking, and MLH administration in-line with the MLH Privacy Policy. I further agree to the terms of both the MLH Contest Terms and Conditions and the MLH Privacy Policy.</b></label>
<input type="checkbox" name="mlh3" id="checkboxid3" required><label for="checkboxid3"><b style="color:white;">*I authorize MLH to send me pre- and post-event information emails, which contain free credit and opportunities from their partners.</b></label>
<input type="checkbox" name="mlh3" id="checkboxid4" required><label for="checkboxid4"><b style="color:white;">*I understand that in-person participation is limited to WPI students that are part of the testing protocol only.</b></label>
<br><br>
<center><input name="submit" class="btn btn-lg btn-primary btn-invert" type="submit" value="Submit"/></center>
</form>
</div>
</div>
</div>
{% include 'footer.html' %}

View file

@ -0,0 +1,34 @@
"""empty message
Revision ID: 55d77cdbbb49
Revises: d210860eb46a
Create Date: 2022-12-06 10:09:50.254449
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '55d77cdbbb49'
down_revision = 'd210860eb46a'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('shirt_size', sa.String(), nullable=True))
batch_op.add_column(sa.Column('accomodations', sa.String(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.drop_column('accomodations')
batch_op.drop_column('shirt_size')
# ### end Alembic commands ###

View file

@ -1,6 +1,7 @@
alembic==1.8.1
click==8.1.3
Flask==2.2.2
Flask-Assets
Flask-Login==0.6.2
Flask-Migrate==4.0.0
Flask-SQLAlchemy==3.0.2