Tracking PR for registration rewrite #5
22 changed files with 7201 additions and 74 deletions
2
Makefile
2
Makefile
|
@ -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 ---"
|
||||
|
|
|
@ -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
|
||||
|
|
10
goathacks/dashboard/__init__.py
Normal file
10
goathacks/dashboard/__init__.py
Normal 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")
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
16
goathacks/static/css/materialize.min.css
vendored
Normal file
16
goathacks/static/css/materialize.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
147
goathacks/static/css/style.css
Normal file
147
goathacks/static/css/style.css
Normal 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;
|
||||
}
|
148
goathacks/static/css/style.scss
Normal file
148
goathacks/static/css/style.scss
Normal 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;
|
||||
}
|
||||
}
|
BIN
goathacks/static/img/hackwpilogo.png
Normal file
BIN
goathacks/static/img/hackwpilogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
192
goathacks/static/js/admin.js
Normal file
192
goathacks/static/js/admin.js
Normal 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)
|
||||
})
|
||||
})
|
||||
}
|
3
goathacks/static/js/init.js
Normal file
3
goathacks/static/js/init.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
$(document).ready(function(){
|
||||
$('.parallax').parallax();
|
||||
});
|
4
goathacks/static/js/jquery-2.2.4.min.js
vendored
Normal file
4
goathacks/static/js/jquery-2.2.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
goathacks/static/js/jquery.easing.min.js
vendored
Normal file
1
goathacks/static/js/jquery.easing.min.js
vendored
Normal 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
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
10
goathacks/static/js/materialize.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
20
goathacks/templates/base.html
Normal file
20
goathacks/templates/base.html
Normal 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' %}
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
<div style="height: 100%;">
|
||||
{% 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="../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 class="parallax"><img src="{{url_for('static', filename='img/background1.jpg')}}"
|
||||
alt="background"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'footer.html' %}
|
||||
<div class="container">
|
||||
<div class="section" style="background-color: #974355; padding: 20px;">
|
||||
<form method="post">
|
||||
{{ form.csrf_token }}
|
||||
<div>
|
||||
{{ form.email}}<br/> {{ form.email.label }}
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
69
goathacks/templates/register_step2.html
Normal file
69
goathacks/templates/register_step2.html
Normal 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' %}
|
34
migrations/versions/55d77cdbbb49_.py
Normal file
34
migrations/versions/55d77cdbbb49_.py
Normal 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 ###
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue