Compare commits

..

No commits in common. "master" and "2024" have entirely different histories.
master ... 2024

43 changed files with 1297 additions and 3388 deletions

3
.gitignore vendored
View file

@ -1,6 +1,7 @@
resumes*/
resumes*.zip
config_hackWPI.py
config.py
admin/*.json
admin/*.csv
@ -12,8 +13,6 @@ goathacks/config.py
sqldmp
.vscode/
.DS_Store
### Bower ###
bower_components

View file

@ -32,14 +32,8 @@ daemon:
@echo "--- STARTING UWSGI DAEMON ---"
@echo ""
@echo ""
source .venv/bin/activate && flask --debug run
source .venv/bin/activate && flask run
@echo ""
@echo ""
@echo "--- STARTING UWSGI DAEMON ---"
post_upgrade: upgrade_env run_migrations
# Make sure a tmp directory exists
@mkdir -p acmsite/tmp
# Create upload directory
@mkdir -p acmsite/uploads

View file

@ -1,30 +0,0 @@
import os
from dotenv import load_dotenv, dotenv_values
basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))
class Config():
TESTING = dotenv_values().get("TESTING") or False
DEBUG = dotenv_values().get("DEBUG") or False
SQLALCHEMY_DATABASE_URI = dotenv_values().get("SQLALCHEMY_DATABASE_URI") or "postgresql://localhost/goathacks"
MAX_BEFORE_WAITLIST = int(dotenv_values().get("MAX_BEFORE_WAITLIST") or 1)
MCE_API_KEY = dotenv_values().get("MCE_API_KEY")
SECRET_KEY = dotenv_values().get("SECRET_KEY") or "bad-key-change-me"
UPLOAD_FOLDER = dotenv_values().get("UPLOAD_FOLDER") or "./uploads/"
DISCORD_LINK = dotenv_values().get("DISCORD_LINK") or None
# Mail server settings
MAIL_SERVER = dotenv_values().get("MAIL_SERVER") or "localhost"
MAIL_PORT = dotenv_values().get("MAIL_PORT") or 25
MAIL_USE_TLS = dotenv_values().get("MAIL_USE_TLS") or False
MAIL_USE_SSL = dotenv_values().get("MAIL_USE_SSL") or False
MAIL_USERNAME = dotenv_values().get("MAIL_USERNAME") or "dummy"
MAIL_PASSWORD = dotenv_values().get("MAIL_PASSWORD") or "dummy"
MAIL_DEFAULT_SENDER = dotenv_values().get("MAIL_DEFAULT_SENDER") or "GoatHacks Team <hack@wpi.edu>"
MAIL_SUPPRESS_SEND = dotenv_values().get("MAIL_SUPPRESS_SEND") or TESTING

View file

@ -5,13 +5,8 @@ from flask_login import LoginManager
from flask_assets import Bundle, Environment
from flask_cors import CORS
from flask_mail import Mail, email_dispatched
from flask_bootstrap import Bootstrap5
from flask_font_awesome import FontAwesome
from flask_qrcode import QRcode
from config import Config
db = SQLAlchemy()
migrate = Migrate()
@ -19,14 +14,12 @@ login = LoginManager()
environment = Environment()
cors = CORS()
mail = Mail()
bootstrap = Bootstrap5()
font_awesome = FontAwesome()
qrcode = QRcode()
def create_app(config_class=Config):
def create_app():
app = Flask(__name__)
app.config.from_object(config_class)
app.config.from_pyfile("config.py")
db.init_app(app)
migrate.init_app(app, db)
@ -34,9 +27,7 @@ def create_app(config_class=Config):
environment.init_app(app)
cors.init_app(app)
mail.init_app(app)
bootstrap.init_app(app)
qrcode.init_app(app)
font_awesome.init_app(app)
scss = Bundle('css/style.scss', filters='scss',
output='css/style.css')
@ -84,10 +75,6 @@ def create_app(config_class=Config):
def index():
return render_template("home/index.html")
@app.route("/index2.html")
def index2():
return render_template("home/index2.html")
# homepage assets
@app.route("/assets/<path:path>")
def assets(path):

View file

@ -1,4 +1,4 @@
from flask import Blueprint, current_app, jsonify, redirect, render_template, request, url_for
from flask import Blueprint, jsonify, redirect, render_template, request, url_for
from flask_login import current_user, login_required
from flask_mail import Message
@ -9,9 +9,9 @@ bp = Blueprint("admin", __name__, url_prefix="/admin")
from goathacks import db, mail as app_mail
from goathacks.admin import events
# Helper function for admin.home and admin.admin_list to render list of users.
# This function was abstracted to promote code reuse.
def render_user_list(admin_list):
@bp.route("/")
@login_required
def home():
if not current_user.is_admin:
return redirect(url_for("dashboard.home"))
male_count = 0
@ -21,10 +21,7 @@ def render_user_list(admin_list):
waitlist_count = 0
total_count = 0
shirt_count = {'XS': 0, 'S': 0, 'M': 0, 'L': 0, 'XL': 0}
if(admin_list):
hackers = db.session.execute(db.select(User).where(User.is_admin)).scalars().all()
else:
hackers = db.session.execute(db.select(User).where(User.is_admin == False)).scalars().all()
hackers = db.session.execute(db.select(User)).scalars().all()
schools = {}
for h in hackers:
@ -58,17 +55,6 @@ def render_user_list(admin_list):
female_count=female_count, nb_count=nb_count,
check_in_count=check_in_count, schools=schools)
@bp.route("/")
@login_required
def home():
return render_user_list(False) # list users (not admins)
@bp.route("/admin_list")
@login_required
def admin_list():
return render_user_list(True) # list users (admins)
@bp.route("/mail")
@login_required
def mail():
@ -76,20 +62,8 @@ def mail():
return redirect(url_for("dashboard.home"))
total_count = len(db.session.execute(db.select(User)).scalars().all())
api_key = current_app.config["MCE_API_KEY"]
return render_template("mail.html", NUM_HACKERS=total_count,
MCE_API_KEY=api_key)
@bp.route("/users")
@login_required
def users():
if not current_user.is_admin:
return redirect(url_for("dashboard.home"))
users = User.query.all()
return render_template("users.html", users=users)
return render_template("mail.html", NUM_HACKERS=total_count)
@bp.route("/send", methods=["POST"])
@login_required

View file

@ -1,11 +1,11 @@
import flask
from flask import Response, render_template, redirect, request, url_for, flash, current_app
from flask import Response, render_template, redirect, request, url_for, flash
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, datetime
import io, qrcode
import qrcode.image.pure
@bp.route("/events")
@ -16,86 +16,7 @@ def list_events():
events = Event.query.all()
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"))
return render_template("events/list.html", events=events)
@bp.route("/events/events.json")
@login_required

View file

@ -1,14 +1,12 @@
from flask_wtf import FlaskForm
from wtforms import StringField, DateField, TimeField, SubmitField, TextAreaField
from wtforms import StringField, DateTimeField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
class EventForm(FlaskForm):
name = StringField("Name", validators=[DataRequired()])
description = TextAreaField("Description")
location = StringField("Location", 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()])
start_time = DateTimeField("Start Time", validators=[DataRequired()])
end_time = DateTimeField("End Time", validators=[DataRequired()])
category = StringField("Category")
submit = SubmitField("Submit")

View file

@ -23,10 +23,8 @@ gr = AppGroup("user")
@click.option("--school", prompt=True)
@click.option("--phone", prompt=True)
@click.option("--gender", prompt=True)
@click.option("--country", prompt=True)
@click.option("--age", prompt=True)
def create_user(email, first_name, last_name, password, school, phone, gender,
admin,age, country):
admin):
"""
Creates a user
"""
@ -50,9 +48,7 @@ def create_user(email, first_name, last_name, password, school, phone, gender,
school=school,
phone=phone,
gender=gender,
is_admin=admin,
country=country,
age=age
is_admin=admin
)
db.session.add(user)
db.session.commit()

View file

@ -0,0 +1,18 @@
SQLALCHEMY_DATABASE_URI="postgresql://localhost/goathacks"
MAX_BEFORE_WAITLIST=1
SECRET_KEY="bad-key-change-me"
UPLOAD_FOLDER="./uploads/"
DISCORD_LINK=None
# Mail settings
MAIL_SERVER="localhost"
MAIL_PORT=25
MAIL_USE_TLS=False
MAIL_USE_SSL=False
MAIL_USERNAME="dummy"
MAIL_PASSWORD="dummy"
MAIL_DEFAULT_SENDER="GoatHacks Team <hack@wpi.edu>"

View file

@ -1,4 +1,4 @@
from flask import Blueprint, current_app, flash, jsonify, redirect, render_template, request, url_for
from flask import Blueprint, current_app, flash, jsonify, render_template, request
from flask_login import current_user, login_required
from werkzeug.utils import secure_filename
@ -19,8 +19,6 @@ def home():
current_user.accomodations = request.form.get('accomodations')
db.session.commit()
flash("Updated successfully")
else:
form = forms.ShirtAndAccomForm(obj=current_user)
return render_template("dashboard.html", form=form, resform=resform)
@bp.route("/resume", methods=["POST"])
@ -47,17 +45,9 @@ def resume():
filename = current_user.first_name.lower() + '_' + current_user.last_name.lower() + '_' + str(
current_user.id) + '.' + resume.filename.split('.')[-1].lower()
filename = secure_filename(filename)
if not os.path.exists(current_app.config['UPLOAD_FOLDER']):
try:
os.makedirs(current_app.config['UPLOAD_FOLDER'])
except Exception:
flash("Error saving resume. Contact acm-sysadmin@wpi.edu")
return redirect(url_for("dashboard.home"))
resume.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
flash("Resume uploaded!")
return redirect(url_for("dashboard.home"))
flash("Something went wrong. If this keeps happening, contact hack@wpi.edu for assistance")
return redirect(url_for("dashboard.home"))
return 'Resume uploaded! <a href="/dashboard">Return to dashboard</a>'
return "Something went wrong. If this keeps happening, contact hack@wpi.edu for assistance"
def allowed_file(filename):

View file

@ -1,19 +1,16 @@
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired, FileAllowed
from wtforms import SelectField, TextAreaField, SubmitField
from wtforms import RadioField, TextAreaField
from wtforms.validators import DataRequired
class ShirtAndAccomForm(FlaskForm):
shirt_size = SelectField("Shirt size", choices=["XS", "S", "M", "L", "XL",
shirt_size = RadioField("Shirt size", choices=["XS", "S", "M", "L", "XL",
"None"],
validators=[DataRequired()])
accomodations = TextAreaField("Special needs and/or Accomodations")
submit = SubmitField("Save")
class ResumeForm(FlaskForm):
resume = FileField("Resume", validators=[FileRequired(),
FileAllowed(['pdf', 'docx', 'doc',
'txt', 'rtf'],
"Documents only!")])
submit = SubmitField("Submit")

View file

@ -20,13 +20,7 @@ class User(db.Model, UserMixin):
school = Column(String, nullable=True)
phone = Column(String, nullable=True)
gender = Column(String, nullable=True)
newsletter = Column(Boolean, nullable=False, default=False)
country = Column(String, nullable=False)
age = Column(Integer, nullable=False)
dietary_restrictions = Column(String, nullable=True)
def __str__(self):
return f"{self.first_name} {self.last_name} ({self.email})"
def create_json_output(lis):
hackers = []
@ -54,7 +48,7 @@ def user_loader(user_id):
@login.unauthorized_handler
def unauth():
flash("Please login first")
return redirect(url_for("registration.login"))
return redirect(url_for("registration.register"))
class PwResetRequest(db.Model):
@ -79,21 +73,18 @@ class Event(db.Model):
events = []
for e in lis:
events.append(e.create_json())
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
})
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()

View file

@ -1,7 +1,7 @@
from datetime import datetime, timedelta
from flask import Blueprint, abort, config, current_app, flash, redirect, render_template, request, url_for
import flask_login
from flask_login import current_user, login_required
from flask_login import current_user
from goathacks.registration.forms import LoginForm, PwResetForm, RegisterForm, ResetForm
from werkzeug.security import check_password_hash, generate_password_hash
from flask_mail import Message
@ -30,10 +30,7 @@ def register():
school = request.form.get('school')
phone = request.form.get('phone_number')
gender = request.form.get('gender')
country = request.form.get('country')
age = request.form.get('age')
dietary_restrictions = request.form.get('dietary_restrictions')
newsletter = request.form.get('newsletter')
if password == password_c:
# Passwords match!
@ -54,11 +51,7 @@ def register():
waitlisted=waitlisted,
school=school,
phone=phone,
gender=gender,
country=country,
age=age,
dietary_restrictions=dietary_restrictions,
newsletter=newsletter
gender=gender
)
db.session.add(user)
db.session.commit()
@ -104,13 +97,6 @@ def login():
return render_template("login.html", form=form)
@bp.route("/logout")
@login_required
def logout():
flask_login.logout_user()
flash("See you later!")
return redirect(url_for("registration.login"))
@bp.route("/reset", methods=["GET", "POST"])
def reset():
form = ResetForm(request.form)

View file

@ -1,249 +0,0 @@
United States of America,US,USA,840,ISO 3166-2:US,Americas,Northern America,"",019,021,""
Afghanistan,AF,AFG,004,ISO 3166-2:AF,Asia,Southern Asia,"",142,034,""
Åland Islands,AX,ALA,248,ISO 3166-2:AX,Europe,Northern Europe,"",150,154,""
Albania,AL,ALB,008,ISO 3166-2:AL,Europe,Southern Europe,"",150,039,""
Algeria,DZ,DZA,012,ISO 3166-2:DZ,Africa,Northern Africa,"",002,015,""
American Samoa,AS,ASM,016,ISO 3166-2:AS,Oceania,Polynesia,"",009,061,""
Andorra,AD,AND,020,ISO 3166-2:AD,Europe,Southern Europe,"",150,039,""
Angola,AO,AGO,024,ISO 3166-2:AO,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Anguilla,AI,AIA,660,ISO 3166-2:AI,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Antarctica,AQ,ATA,010,ISO 3166-2:AQ,"","","","","",""
Antigua and Barbuda,AG,ATG,028,ISO 3166-2:AG,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Argentina,AR,ARG,032,ISO 3166-2:AR,Americas,Latin America and the Caribbean,South America,019,419,005
Armenia,AM,ARM,051,ISO 3166-2:AM,Asia,Western Asia,"",142,145,""
Aruba,AW,ABW,533,ISO 3166-2:AW,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Australia,AU,AUS,036,ISO 3166-2:AU,Oceania,Australia and New Zealand,"",009,053,""
Austria,AT,AUT,040,ISO 3166-2:AT,Europe,Western Europe,"",150,155,""
Azerbaijan,AZ,AZE,031,ISO 3166-2:AZ,Asia,Western Asia,"",142,145,""
Bahamas,BS,BHS,044,ISO 3166-2:BS,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Bahrain,BH,BHR,048,ISO 3166-2:BH,Asia,Western Asia,"",142,145,""
Bangladesh,BD,BGD,050,ISO 3166-2:BD,Asia,Southern Asia,"",142,034,""
Barbados,BB,BRB,052,ISO 3166-2:BB,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Belarus,BY,BLR,112,ISO 3166-2:BY,Europe,Eastern Europe,"",150,151,""
Belgium,BE,BEL,056,ISO 3166-2:BE,Europe,Western Europe,"",150,155,""
Belize,BZ,BLZ,084,ISO 3166-2:BZ,Americas,Latin America and the Caribbean,Central America,019,419,013
Benin,BJ,BEN,204,ISO 3166-2:BJ,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Bermuda,BM,BMU,060,ISO 3166-2:BM,Americas,Northern America,"",019,021,""
Bhutan,BT,BTN,064,ISO 3166-2:BT,Asia,Southern Asia,"",142,034,""
"Bolivia, Plurinational State of",BO,BOL,068,ISO 3166-2:BO,Americas,Latin America and the Caribbean,South America,019,419,005
"Bonaire, Sint Eustatius and Saba",BQ,BES,535,ISO 3166-2:BQ,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Bosnia and Herzegovina,BA,BIH,070,ISO 3166-2:BA,Europe,Southern Europe,"",150,039,""
Botswana,BW,BWA,072,ISO 3166-2:BW,Africa,Sub-Saharan Africa,Southern Africa,002,202,018
Bouvet Island,BV,BVT,074,ISO 3166-2:BV,Americas,Latin America and the Caribbean,South America,019,419,005
Brazil,BR,BRA,076,ISO 3166-2:BR,Americas,Latin America and the Caribbean,South America,019,419,005
British Indian Ocean Territory,IO,IOT,086,ISO 3166-2:IO,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Brunei Darussalam,BN,BRN,096,ISO 3166-2:BN,Asia,South-eastern Asia,"",142,035,""
Bulgaria,BG,BGR,100,ISO 3166-2:BG,Europe,Eastern Europe,"",150,151,""
Burkina Faso,BF,BFA,854,ISO 3166-2:BF,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Burundi,BI,BDI,108,ISO 3166-2:BI,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Cabo Verde,CV,CPV,132,ISO 3166-2:CV,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Cambodia,KH,KHM,116,ISO 3166-2:KH,Asia,South-eastern Asia,"",142,035,""
Cameroon,CM,CMR,120,ISO 3166-2:CM,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Canada,CA,CAN,124,ISO 3166-2:CA,Americas,Northern America,"",019,021,""
Cayman Islands,KY,CYM,136,ISO 3166-2:KY,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Central African Republic,CF,CAF,140,ISO 3166-2:CF,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Chad,TD,TCD,148,ISO 3166-2:TD,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Chile,CL,CHL,152,ISO 3166-2:CL,Americas,Latin America and the Caribbean,South America,019,419,005
China,CN,CHN,156,ISO 3166-2:CN,Asia,Eastern Asia,"",142,030,""
Christmas Island,CX,CXR,162,ISO 3166-2:CX,Oceania,Australia and New Zealand,"",009,053,""
Cocos (Keeling) Islands,CC,CCK,166,ISO 3166-2:CC,Oceania,Australia and New Zealand,"",009,053,""
Colombia,CO,COL,170,ISO 3166-2:CO,Americas,Latin America and the Caribbean,South America,019,419,005
Comoros,KM,COM,174,ISO 3166-2:KM,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Congo,CG,COG,178,ISO 3166-2:CG,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
"Congo, Democratic Republic of the",CD,COD,180,ISO 3166-2:CD,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Cook Islands,CK,COK,184,ISO 3166-2:CK,Oceania,Polynesia,"",009,061,""
Costa Rica,CR,CRI,188,ISO 3166-2:CR,Americas,Latin America and the Caribbean,Central America,019,419,013
Côte d'Ivoire,CI,CIV,384,ISO 3166-2:CI,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Croatia,HR,HRV,191,ISO 3166-2:HR,Europe,Southern Europe,"",150,039,""
Cuba,CU,CUB,192,ISO 3166-2:CU,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Curaçao,CW,CUW,531,ISO 3166-2:CW,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Cyprus,CY,CYP,196,ISO 3166-2:CY,Asia,Western Asia,"",142,145,""
Czechia,CZ,CZE,203,ISO 3166-2:CZ,Europe,Eastern Europe,"",150,151,""
Denmark,DK,DNK,208,ISO 3166-2:DK,Europe,Northern Europe,"",150,154,""
Djibouti,DJ,DJI,262,ISO 3166-2:DJ,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Dominica,DM,DMA,212,ISO 3166-2:DM,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Dominican Republic,DO,DOM,214,ISO 3166-2:DO,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Ecuador,EC,ECU,218,ISO 3166-2:EC,Americas,Latin America and the Caribbean,South America,019,419,005
Egypt,EG,EGY,818,ISO 3166-2:EG,Africa,Northern Africa,"",002,015,""
El Salvador,SV,SLV,222,ISO 3166-2:SV,Americas,Latin America and the Caribbean,Central America,019,419,013
Equatorial Guinea,GQ,GNQ,226,ISO 3166-2:GQ,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Eritrea,ER,ERI,232,ISO 3166-2:ER,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Estonia,EE,EST,233,ISO 3166-2:EE,Europe,Northern Europe,"",150,154,""
Eswatini,SZ,SWZ,748,ISO 3166-2:SZ,Africa,Sub-Saharan Africa,Southern Africa,002,202,018
Ethiopia,ET,ETH,231,ISO 3166-2:ET,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Falkland Islands (Malvinas),FK,FLK,238,ISO 3166-2:FK,Americas,Latin America and the Caribbean,South America,019,419,005
Faroe Islands,FO,FRO,234,ISO 3166-2:FO,Europe,Northern Europe,"",150,154,""
Fiji,FJ,FJI,242,ISO 3166-2:FJ,Oceania,Melanesia,"",009,054,""
Finland,FI,FIN,246,ISO 3166-2:FI,Europe,Northern Europe,"",150,154,""
France,FR,FRA,250,ISO 3166-2:FR,Europe,Western Europe,"",150,155,""
French Guiana,GF,GUF,254,ISO 3166-2:GF,Americas,Latin America and the Caribbean,South America,019,419,005
French Polynesia,PF,PYF,258,ISO 3166-2:PF,Oceania,Polynesia,"",009,061,""
French Southern Territories,TF,ATF,260,ISO 3166-2:TF,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Gabon,GA,GAB,266,ISO 3166-2:GA,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Gambia,GM,GMB,270,ISO 3166-2:GM,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Georgia,GE,GEO,268,ISO 3166-2:GE,Asia,Western Asia,"",142,145,""
Germany,DE,DEU,276,ISO 3166-2:DE,Europe,Western Europe,"",150,155,""
Ghana,GH,GHA,288,ISO 3166-2:GH,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Gibraltar,GI,GIB,292,ISO 3166-2:GI,Europe,Southern Europe,"",150,039,""
Greece,GR,GRC,300,ISO 3166-2:GR,Europe,Southern Europe,"",150,039,""
Greenland,GL,GRL,304,ISO 3166-2:GL,Americas,Northern America,"",019,021,""
Grenada,GD,GRD,308,ISO 3166-2:GD,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Guadeloupe,GP,GLP,312,ISO 3166-2:GP,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Guam,GU,GUM,316,ISO 3166-2:GU,Oceania,Micronesia,"",009,057,""
Guatemala,GT,GTM,320,ISO 3166-2:GT,Americas,Latin America and the Caribbean,Central America,019,419,013
Guernsey,GG,GGY,831,ISO 3166-2:GG,Europe,Northern Europe,"",150,154,""
Guinea,GN,GIN,324,ISO 3166-2:GN,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Guinea-Bissau,GW,GNB,624,ISO 3166-2:GW,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Guyana,GY,GUY,328,ISO 3166-2:GY,Americas,Latin America and the Caribbean,South America,019,419,005
Haiti,HT,HTI,332,ISO 3166-2:HT,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Heard Island and McDonald Islands,HM,HMD,334,ISO 3166-2:HM,Oceania,Australia and New Zealand,"",009,053,""
Holy See,VA,VAT,336,ISO 3166-2:VA,Europe,Southern Europe,"",150,039,""
Honduras,HN,HND,340,ISO 3166-2:HN,Americas,Latin America and the Caribbean,Central America,019,419,013
Hong Kong,HK,HKG,344,ISO 3166-2:HK,Asia,Eastern Asia,"",142,030,""
Hungary,HU,HUN,348,ISO 3166-2:HU,Europe,Eastern Europe,"",150,151,""
Iceland,IS,ISL,352,ISO 3166-2:IS,Europe,Northern Europe,"",150,154,""
India,IN,IND,356,ISO 3166-2:IN,Asia,Southern Asia,"",142,034,""
Indonesia,ID,IDN,360,ISO 3166-2:ID,Asia,South-eastern Asia,"",142,035,""
"Iran, Islamic Republic of",IR,IRN,364,ISO 3166-2:IR,Asia,Southern Asia,"",142,034,""
Iraq,IQ,IRQ,368,ISO 3166-2:IQ,Asia,Western Asia,"",142,145,""
Ireland,IE,IRL,372,ISO 3166-2:IE,Europe,Northern Europe,"",150,154,""
Isle of Man,IM,IMN,833,ISO 3166-2:IM,Europe,Northern Europe,"",150,154,""
Israel,IL,ISR,376,ISO 3166-2:IL,Asia,Western Asia,"",142,145,""
Italy,IT,ITA,380,ISO 3166-2:IT,Europe,Southern Europe,"",150,039,""
Jamaica,JM,JAM,388,ISO 3166-2:JM,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Japan,JP,JPN,392,ISO 3166-2:JP,Asia,Eastern Asia,"",142,030,""
Jersey,JE,JEY,832,ISO 3166-2:JE,Europe,Northern Europe,"",150,154,""
Jordan,JO,JOR,400,ISO 3166-2:JO,Asia,Western Asia,"",142,145,""
Kazakhstan,KZ,KAZ,398,ISO 3166-2:KZ,Asia,Central Asia,"",142,143,""
Kenya,KE,KEN,404,ISO 3166-2:KE,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Kiribati,KI,KIR,296,ISO 3166-2:KI,Oceania,Micronesia,"",009,057,""
"Korea, Democratic People's Republic of",KP,PRK,408,ISO 3166-2:KP,Asia,Eastern Asia,"",142,030,""
"Korea, Republic of",KR,KOR,410,ISO 3166-2:KR,Asia,Eastern Asia,"",142,030,""
Kuwait,KW,KWT,414,ISO 3166-2:KW,Asia,Western Asia,"",142,145,""
Kyrgyzstan,KG,KGZ,417,ISO 3166-2:KG,Asia,Central Asia,"",142,143,""
Lao People's Democratic Republic,LA,LAO,418,ISO 3166-2:LA,Asia,South-eastern Asia,"",142,035,""
Latvia,LV,LVA,428,ISO 3166-2:LV,Europe,Northern Europe,"",150,154,""
Lebanon,LB,LBN,422,ISO 3166-2:LB,Asia,Western Asia,"",142,145,""
Lesotho,LS,LSO,426,ISO 3166-2:LS,Africa,Sub-Saharan Africa,Southern Africa,002,202,018
Liberia,LR,LBR,430,ISO 3166-2:LR,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Libya,LY,LBY,434,ISO 3166-2:LY,Africa,Northern Africa,"",002,015,""
Liechtenstein,LI,LIE,438,ISO 3166-2:LI,Europe,Western Europe,"",150,155,""
Lithuania,LT,LTU,440,ISO 3166-2:LT,Europe,Northern Europe,"",150,154,""
Luxembourg,LU,LUX,442,ISO 3166-2:LU,Europe,Western Europe,"",150,155,""
Macao,MO,MAC,446,ISO 3166-2:MO,Asia,Eastern Asia,"",142,030,""
Madagascar,MG,MDG,450,ISO 3166-2:MG,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Malawi,MW,MWI,454,ISO 3166-2:MW,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Malaysia,MY,MYS,458,ISO 3166-2:MY,Asia,South-eastern Asia,"",142,035,""
Maldives,MV,MDV,462,ISO 3166-2:MV,Asia,Southern Asia,"",142,034,""
Mali,ML,MLI,466,ISO 3166-2:ML,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Malta,MT,MLT,470,ISO 3166-2:MT,Europe,Southern Europe,"",150,039,""
Marshall Islands,MH,MHL,584,ISO 3166-2:MH,Oceania,Micronesia,"",009,057,""
Martinique,MQ,MTQ,474,ISO 3166-2:MQ,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Mauritania,MR,MRT,478,ISO 3166-2:MR,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Mauritius,MU,MUS,480,ISO 3166-2:MU,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Mayotte,YT,MYT,175,ISO 3166-2:YT,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Mexico,MX,MEX,484,ISO 3166-2:MX,Americas,Latin America and the Caribbean,Central America,019,419,013
"Micronesia, Federated States of",FM,FSM,583,ISO 3166-2:FM,Oceania,Micronesia,"",009,057,""
"Moldova, Republic of",MD,MDA,498,ISO 3166-2:MD,Europe,Eastern Europe,"",150,151,""
Monaco,MC,MCO,492,ISO 3166-2:MC,Europe,Western Europe,"",150,155,""
Mongolia,MN,MNG,496,ISO 3166-2:MN,Asia,Eastern Asia,"",142,030,""
Montenegro,ME,MNE,499,ISO 3166-2:ME,Europe,Southern Europe,"",150,039,""
Montserrat,MS,MSR,500,ISO 3166-2:MS,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Morocco,MA,MAR,504,ISO 3166-2:MA,Africa,Northern Africa,"",002,015,""
Mozambique,MZ,MOZ,508,ISO 3166-2:MZ,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Myanmar,MM,MMR,104,ISO 3166-2:MM,Asia,South-eastern Asia,"",142,035,""
Namibia,NA,NAM,516,ISO 3166-2:NA,Africa,Sub-Saharan Africa,Southern Africa,002,202,018
Nauru,NR,NRU,520,ISO 3166-2:NR,Oceania,Micronesia,"",009,057,""
Nepal,NP,NPL,524,ISO 3166-2:NP,Asia,Southern Asia,"",142,034,""
"Netherlands, Kingdom of the",NL,NLD,528,ISO 3166-2:NL,Europe,Western Europe,"",150,155,""
New Caledonia,NC,NCL,540,ISO 3166-2:NC,Oceania,Melanesia,"",009,054,""
New Zealand,NZ,NZL,554,ISO 3166-2:NZ,Oceania,Australia and New Zealand,"",009,053,""
Nicaragua,NI,NIC,558,ISO 3166-2:NI,Americas,Latin America and the Caribbean,Central America,019,419,013
Niger,NE,NER,562,ISO 3166-2:NE,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Nigeria,NG,NGA,566,ISO 3166-2:NG,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Niue,NU,NIU,570,ISO 3166-2:NU,Oceania,Polynesia,"",009,061,""
Norfolk Island,NF,NFK,574,ISO 3166-2:NF,Oceania,Australia and New Zealand,"",009,053,""
North Macedonia,MK,MKD,807,ISO 3166-2:MK,Europe,Southern Europe,"",150,039,""
Northern Mariana Islands,MP,MNP,580,ISO 3166-2:MP,Oceania,Micronesia,"",009,057,""
Norway,NO,NOR,578,ISO 3166-2:NO,Europe,Northern Europe,"",150,154,""
Oman,OM,OMN,512,ISO 3166-2:OM,Asia,Western Asia,"",142,145,""
Pakistan,PK,PAK,586,ISO 3166-2:PK,Asia,Southern Asia,"",142,034,""
Palau,PW,PLW,585,ISO 3166-2:PW,Oceania,Micronesia,"",009,057,""
"Palestine, State of",PS,PSE,275,ISO 3166-2:PS,Asia,Western Asia,"",142,145,""
Panama,PA,PAN,591,ISO 3166-2:PA,Americas,Latin America and the Caribbean,Central America,019,419,013
Papua New Guinea,PG,PNG,598,ISO 3166-2:PG,Oceania,Melanesia,"",009,054,""
Paraguay,PY,PRY,600,ISO 3166-2:PY,Americas,Latin America and the Caribbean,South America,019,419,005
Peru,PE,PER,604,ISO 3166-2:PE,Americas,Latin America and the Caribbean,South America,019,419,005
Philippines,PH,PHL,608,ISO 3166-2:PH,Asia,South-eastern Asia,"",142,035,""
Pitcairn,PN,PCN,612,ISO 3166-2:PN,Oceania,Polynesia,"",009,061,""
Poland,PL,POL,616,ISO 3166-2:PL,Europe,Eastern Europe,"",150,151,""
Portugal,PT,PRT,620,ISO 3166-2:PT,Europe,Southern Europe,"",150,039,""
Puerto Rico,PR,PRI,630,ISO 3166-2:PR,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Qatar,QA,QAT,634,ISO 3166-2:QA,Asia,Western Asia,"",142,145,""
Réunion,RE,REU,638,ISO 3166-2:RE,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Romania,RO,ROU,642,ISO 3166-2:RO,Europe,Eastern Europe,"",150,151,""
Russian Federation,RU,RUS,643,ISO 3166-2:RU,Europe,Eastern Europe,"",150,151,""
Rwanda,RW,RWA,646,ISO 3166-2:RW,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Saint Barthélemy,BL,BLM,652,ISO 3166-2:BL,Americas,Latin America and the Caribbean,Caribbean,019,419,029
"Saint Helena, Ascension and Tristan da Cunha",SH,SHN,654,ISO 3166-2:SH,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Saint Kitts and Nevis,KN,KNA,659,ISO 3166-2:KN,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Saint Lucia,LC,LCA,662,ISO 3166-2:LC,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Saint Martin (French part),MF,MAF,663,ISO 3166-2:MF,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Saint Pierre and Miquelon,PM,SPM,666,ISO 3166-2:PM,Americas,Northern America,"",019,021,""
Saint Vincent and the Grenadines,VC,VCT,670,ISO 3166-2:VC,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Samoa,WS,WSM,882,ISO 3166-2:WS,Oceania,Polynesia,"",009,061,""
San Marino,SM,SMR,674,ISO 3166-2:SM,Europe,Southern Europe,"",150,039,""
Sao Tome and Principe,ST,STP,678,ISO 3166-2:ST,Africa,Sub-Saharan Africa,Middle Africa,002,202,017
Saudi Arabia,SA,SAU,682,ISO 3166-2:SA,Asia,Western Asia,"",142,145,""
Senegal,SN,SEN,686,ISO 3166-2:SN,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Serbia,RS,SRB,688,ISO 3166-2:RS,Europe,Southern Europe,"",150,039,""
Seychelles,SC,SYC,690,ISO 3166-2:SC,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Sierra Leone,SL,SLE,694,ISO 3166-2:SL,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Singapore,SG,SGP,702,ISO 3166-2:SG,Asia,South-eastern Asia,"",142,035,""
Sint Maarten (Dutch part),SX,SXM,534,ISO 3166-2:SX,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Slovakia,SK,SVK,703,ISO 3166-2:SK,Europe,Eastern Europe,"",150,151,""
Slovenia,SI,SVN,705,ISO 3166-2:SI,Europe,Southern Europe,"",150,039,""
Solomon Islands,SB,SLB,090,ISO 3166-2:SB,Oceania,Melanesia,"",009,054,""
Somalia,SO,SOM,706,ISO 3166-2:SO,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
South Africa,ZA,ZAF,710,ISO 3166-2:ZA,Africa,Sub-Saharan Africa,Southern Africa,002,202,018
South Georgia and the South Sandwich Islands,GS,SGS,239,ISO 3166-2:GS,Americas,Latin America and the Caribbean,South America,019,419,005
South Sudan,SS,SSD,728,ISO 3166-2:SS,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Spain,ES,ESP,724,ISO 3166-2:ES,Europe,Southern Europe,"",150,039,""
Sri Lanka,LK,LKA,144,ISO 3166-2:LK,Asia,Southern Asia,"",142,034,""
Sudan,SD,SDN,729,ISO 3166-2:SD,Africa,Northern Africa,"",002,015,""
Suriname,SR,SUR,740,ISO 3166-2:SR,Americas,Latin America and the Caribbean,South America,019,419,005
Svalbard and Jan Mayen,SJ,SJM,744,ISO 3166-2:SJ,Europe,Northern Europe,"",150,154,""
Sweden,SE,SWE,752,ISO 3166-2:SE,Europe,Northern Europe,"",150,154,""
Switzerland,CH,CHE,756,ISO 3166-2:CH,Europe,Western Europe,"",150,155,""
Syrian Arab Republic,SY,SYR,760,ISO 3166-2:SY,Asia,Western Asia,"",142,145,""
"Taiwan, Province of China",TW,TWN,158,ISO 3166-2:TW,,,,,,
Tajikistan,TJ,TJK,762,ISO 3166-2:TJ,Asia,Central Asia,"",142,143,""
"Tanzania, United Republic of",TZ,TZA,834,ISO 3166-2:TZ,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Thailand,TH,THA,764,ISO 3166-2:TH,Asia,South-eastern Asia,"",142,035,""
Timor-Leste,TL,TLS,626,ISO 3166-2:TL,Asia,South-eastern Asia,"",142,035,""
Togo,TG,TGO,768,ISO 3166-2:TG,Africa,Sub-Saharan Africa,Western Africa,002,202,011
Tokelau,TK,TKL,772,ISO 3166-2:TK,Oceania,Polynesia,"",009,061,""
Tonga,TO,TON,776,ISO 3166-2:TO,Oceania,Polynesia,"",009,061,""
Trinidad and Tobago,TT,TTO,780,ISO 3166-2:TT,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Tunisia,TN,TUN,788,ISO 3166-2:TN,Africa,Northern Africa,"",002,015,""
Türkiye,TR,TUR,792,ISO 3166-2:TR,Asia,Western Asia,"",142,145,""
Turkmenistan,TM,TKM,795,ISO 3166-2:TM,Asia,Central Asia,"",142,143,""
Turks and Caicos Islands,TC,TCA,796,ISO 3166-2:TC,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Tuvalu,TV,TUV,798,ISO 3166-2:TV,Oceania,Polynesia,"",009,061,""
Uganda,UG,UGA,800,ISO 3166-2:UG,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Ukraine,UA,UKR,804,ISO 3166-2:UA,Europe,Eastern Europe,"",150,151,""
United Arab Emirates,AE,ARE,784,ISO 3166-2:AE,Asia,Western Asia,"",142,145,""
United Kingdom of Great Britain and Northern Ireland,GB,GBR,826,ISO 3166-2:GB,Europe,Northern Europe,"",150,154,""
United States Minor Outlying Islands,UM,UMI,581,ISO 3166-2:UM,Oceania,Micronesia,"",009,057,""
Uruguay,UY,URY,858,ISO 3166-2:UY,Americas,Latin America and the Caribbean,South America,019,419,005
Uzbekistan,UZ,UZB,860,ISO 3166-2:UZ,Asia,Central Asia,"",142,143,""
Vanuatu,VU,VUT,548,ISO 3166-2:VU,Oceania,Melanesia,"",009,054,""
"Venezuela, Bolivarian Republic of",VE,VEN,862,ISO 3166-2:VE,Americas,Latin America and the Caribbean,South America,019,419,005
Viet Nam,VN,VNM,704,ISO 3166-2:VN,Asia,South-eastern Asia,"",142,035,""
Virgin Islands (British),VG,VGB,092,ISO 3166-2:VG,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Virgin Islands (U.S.),VI,VIR,850,ISO 3166-2:VI,Americas,Latin America and the Caribbean,Caribbean,019,419,029
Wallis and Futuna,WF,WLF,876,ISO 3166-2:WF,Oceania,Polynesia,"",009,061,""
Western Sahara,EH,ESH,732,ISO 3166-2:EH,Africa,Northern Africa,"",002,015,""
Yemen,YE,YEM,887,ISO 3166-2:YE,Asia,Western Asia,"",142,145,""
Zambia,ZM,ZMB,894,ISO 3166-2:ZM,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
Zimbabwe,ZW,ZWE,716,ISO 3166-2:ZW,Africa,Sub-Saharan Africa,Eastern Africa,002,202,014
1 United States of America US USA 840 ISO 3166-2:US Americas Northern America 019 021
2 Afghanistan AF AFG 004 ISO 3166-2:AF Asia Southern Asia 142 034
3 Åland Islands AX ALA 248 ISO 3166-2:AX Europe Northern Europe 150 154
4 Albania AL ALB 008 ISO 3166-2:AL Europe Southern Europe 150 039
5 Algeria DZ DZA 012 ISO 3166-2:DZ Africa Northern Africa 002 015
6 American Samoa AS ASM 016 ISO 3166-2:AS Oceania Polynesia 009 061
7 Andorra AD AND 020 ISO 3166-2:AD Europe Southern Europe 150 039
8 Angola AO AGO 024 ISO 3166-2:AO Africa Sub-Saharan Africa Middle Africa 002 202 017
9 Anguilla AI AIA 660 ISO 3166-2:AI Americas Latin America and the Caribbean Caribbean 019 419 029
10 Antarctica AQ ATA 010 ISO 3166-2:AQ
11 Antigua and Barbuda AG ATG 028 ISO 3166-2:AG Americas Latin America and the Caribbean Caribbean 019 419 029
12 Argentina AR ARG 032 ISO 3166-2:AR Americas Latin America and the Caribbean South America 019 419 005
13 Armenia AM ARM 051 ISO 3166-2:AM Asia Western Asia 142 145
14 Aruba AW ABW 533 ISO 3166-2:AW Americas Latin America and the Caribbean Caribbean 019 419 029
15 Australia AU AUS 036 ISO 3166-2:AU Oceania Australia and New Zealand 009 053
16 Austria AT AUT 040 ISO 3166-2:AT Europe Western Europe 150 155
17 Azerbaijan AZ AZE 031 ISO 3166-2:AZ Asia Western Asia 142 145
18 Bahamas BS BHS 044 ISO 3166-2:BS Americas Latin America and the Caribbean Caribbean 019 419 029
19 Bahrain BH BHR 048 ISO 3166-2:BH Asia Western Asia 142 145
20 Bangladesh BD BGD 050 ISO 3166-2:BD Asia Southern Asia 142 034
21 Barbados BB BRB 052 ISO 3166-2:BB Americas Latin America and the Caribbean Caribbean 019 419 029
22 Belarus BY BLR 112 ISO 3166-2:BY Europe Eastern Europe 150 151
23 Belgium BE BEL 056 ISO 3166-2:BE Europe Western Europe 150 155
24 Belize BZ BLZ 084 ISO 3166-2:BZ Americas Latin America and the Caribbean Central America 019 419 013
25 Benin BJ BEN 204 ISO 3166-2:BJ Africa Sub-Saharan Africa Western Africa 002 202 011
26 Bermuda BM BMU 060 ISO 3166-2:BM Americas Northern America 019 021
27 Bhutan BT BTN 064 ISO 3166-2:BT Asia Southern Asia 142 034
28 Bolivia, Plurinational State of BO BOL 068 ISO 3166-2:BO Americas Latin America and the Caribbean South America 019 419 005
29 Bonaire, Sint Eustatius and Saba BQ BES 535 ISO 3166-2:BQ Americas Latin America and the Caribbean Caribbean 019 419 029
30 Bosnia and Herzegovina BA BIH 070 ISO 3166-2:BA Europe Southern Europe 150 039
31 Botswana BW BWA 072 ISO 3166-2:BW Africa Sub-Saharan Africa Southern Africa 002 202 018
32 Bouvet Island BV BVT 074 ISO 3166-2:BV Americas Latin America and the Caribbean South America 019 419 005
33 Brazil BR BRA 076 ISO 3166-2:BR Americas Latin America and the Caribbean South America 019 419 005
34 British Indian Ocean Territory IO IOT 086 ISO 3166-2:IO Africa Sub-Saharan Africa Eastern Africa 002 202 014
35 Brunei Darussalam BN BRN 096 ISO 3166-2:BN Asia South-eastern Asia 142 035
36 Bulgaria BG BGR 100 ISO 3166-2:BG Europe Eastern Europe 150 151
37 Burkina Faso BF BFA 854 ISO 3166-2:BF Africa Sub-Saharan Africa Western Africa 002 202 011
38 Burundi BI BDI 108 ISO 3166-2:BI Africa Sub-Saharan Africa Eastern Africa 002 202 014
39 Cabo Verde CV CPV 132 ISO 3166-2:CV Africa Sub-Saharan Africa Western Africa 002 202 011
40 Cambodia KH KHM 116 ISO 3166-2:KH Asia South-eastern Asia 142 035
41 Cameroon CM CMR 120 ISO 3166-2:CM Africa Sub-Saharan Africa Middle Africa 002 202 017
42 Canada CA CAN 124 ISO 3166-2:CA Americas Northern America 019 021
43 Cayman Islands KY CYM 136 ISO 3166-2:KY Americas Latin America and the Caribbean Caribbean 019 419 029
44 Central African Republic CF CAF 140 ISO 3166-2:CF Africa Sub-Saharan Africa Middle Africa 002 202 017
45 Chad TD TCD 148 ISO 3166-2:TD Africa Sub-Saharan Africa Middle Africa 002 202 017
46 Chile CL CHL 152 ISO 3166-2:CL Americas Latin America and the Caribbean South America 019 419 005
47 China CN CHN 156 ISO 3166-2:CN Asia Eastern Asia 142 030
48 Christmas Island CX CXR 162 ISO 3166-2:CX Oceania Australia and New Zealand 009 053
49 Cocos (Keeling) Islands CC CCK 166 ISO 3166-2:CC Oceania Australia and New Zealand 009 053
50 Colombia CO COL 170 ISO 3166-2:CO Americas Latin America and the Caribbean South America 019 419 005
51 Comoros KM COM 174 ISO 3166-2:KM Africa Sub-Saharan Africa Eastern Africa 002 202 014
52 Congo CG COG 178 ISO 3166-2:CG Africa Sub-Saharan Africa Middle Africa 002 202 017
53 Congo, Democratic Republic of the CD COD 180 ISO 3166-2:CD Africa Sub-Saharan Africa Middle Africa 002 202 017
54 Cook Islands CK COK 184 ISO 3166-2:CK Oceania Polynesia 009 061
55 Costa Rica CR CRI 188 ISO 3166-2:CR Americas Latin America and the Caribbean Central America 019 419 013
56 Côte d'Ivoire CI CIV 384 ISO 3166-2:CI Africa Sub-Saharan Africa Western Africa 002 202 011
57 Croatia HR HRV 191 ISO 3166-2:HR Europe Southern Europe 150 039
58 Cuba CU CUB 192 ISO 3166-2:CU Americas Latin America and the Caribbean Caribbean 019 419 029
59 Curaçao CW CUW 531 ISO 3166-2:CW Americas Latin America and the Caribbean Caribbean 019 419 029
60 Cyprus CY CYP 196 ISO 3166-2:CY Asia Western Asia 142 145
61 Czechia CZ CZE 203 ISO 3166-2:CZ Europe Eastern Europe 150 151
62 Denmark DK DNK 208 ISO 3166-2:DK Europe Northern Europe 150 154
63 Djibouti DJ DJI 262 ISO 3166-2:DJ Africa Sub-Saharan Africa Eastern Africa 002 202 014
64 Dominica DM DMA 212 ISO 3166-2:DM Americas Latin America and the Caribbean Caribbean 019 419 029
65 Dominican Republic DO DOM 214 ISO 3166-2:DO Americas Latin America and the Caribbean Caribbean 019 419 029
66 Ecuador EC ECU 218 ISO 3166-2:EC Americas Latin America and the Caribbean South America 019 419 005
67 Egypt EG EGY 818 ISO 3166-2:EG Africa Northern Africa 002 015
68 El Salvador SV SLV 222 ISO 3166-2:SV Americas Latin America and the Caribbean Central America 019 419 013
69 Equatorial Guinea GQ GNQ 226 ISO 3166-2:GQ Africa Sub-Saharan Africa Middle Africa 002 202 017
70 Eritrea ER ERI 232 ISO 3166-2:ER Africa Sub-Saharan Africa Eastern Africa 002 202 014
71 Estonia EE EST 233 ISO 3166-2:EE Europe Northern Europe 150 154
72 Eswatini SZ SWZ 748 ISO 3166-2:SZ Africa Sub-Saharan Africa Southern Africa 002 202 018
73 Ethiopia ET ETH 231 ISO 3166-2:ET Africa Sub-Saharan Africa Eastern Africa 002 202 014
74 Falkland Islands (Malvinas) FK FLK 238 ISO 3166-2:FK Americas Latin America and the Caribbean South America 019 419 005
75 Faroe Islands FO FRO 234 ISO 3166-2:FO Europe Northern Europe 150 154
76 Fiji FJ FJI 242 ISO 3166-2:FJ Oceania Melanesia 009 054
77 Finland FI FIN 246 ISO 3166-2:FI Europe Northern Europe 150 154
78 France FR FRA 250 ISO 3166-2:FR Europe Western Europe 150 155
79 French Guiana GF GUF 254 ISO 3166-2:GF Americas Latin America and the Caribbean South America 019 419 005
80 French Polynesia PF PYF 258 ISO 3166-2:PF Oceania Polynesia 009 061
81 French Southern Territories TF ATF 260 ISO 3166-2:TF Africa Sub-Saharan Africa Eastern Africa 002 202 014
82 Gabon GA GAB 266 ISO 3166-2:GA Africa Sub-Saharan Africa Middle Africa 002 202 017
83 Gambia GM GMB 270 ISO 3166-2:GM Africa Sub-Saharan Africa Western Africa 002 202 011
84 Georgia GE GEO 268 ISO 3166-2:GE Asia Western Asia 142 145
85 Germany DE DEU 276 ISO 3166-2:DE Europe Western Europe 150 155
86 Ghana GH GHA 288 ISO 3166-2:GH Africa Sub-Saharan Africa Western Africa 002 202 011
87 Gibraltar GI GIB 292 ISO 3166-2:GI Europe Southern Europe 150 039
88 Greece GR GRC 300 ISO 3166-2:GR Europe Southern Europe 150 039
89 Greenland GL GRL 304 ISO 3166-2:GL Americas Northern America 019 021
90 Grenada GD GRD 308 ISO 3166-2:GD Americas Latin America and the Caribbean Caribbean 019 419 029
91 Guadeloupe GP GLP 312 ISO 3166-2:GP Americas Latin America and the Caribbean Caribbean 019 419 029
92 Guam GU GUM 316 ISO 3166-2:GU Oceania Micronesia 009 057
93 Guatemala GT GTM 320 ISO 3166-2:GT Americas Latin America and the Caribbean Central America 019 419 013
94 Guernsey GG GGY 831 ISO 3166-2:GG Europe Northern Europe 150 154
95 Guinea GN GIN 324 ISO 3166-2:GN Africa Sub-Saharan Africa Western Africa 002 202 011
96 Guinea-Bissau GW GNB 624 ISO 3166-2:GW Africa Sub-Saharan Africa Western Africa 002 202 011
97 Guyana GY GUY 328 ISO 3166-2:GY Americas Latin America and the Caribbean South America 019 419 005
98 Haiti HT HTI 332 ISO 3166-2:HT Americas Latin America and the Caribbean Caribbean 019 419 029
99 Heard Island and McDonald Islands HM HMD 334 ISO 3166-2:HM Oceania Australia and New Zealand 009 053
100 Holy See VA VAT 336 ISO 3166-2:VA Europe Southern Europe 150 039
101 Honduras HN HND 340 ISO 3166-2:HN Americas Latin America and the Caribbean Central America 019 419 013
102 Hong Kong HK HKG 344 ISO 3166-2:HK Asia Eastern Asia 142 030
103 Hungary HU HUN 348 ISO 3166-2:HU Europe Eastern Europe 150 151
104 Iceland IS ISL 352 ISO 3166-2:IS Europe Northern Europe 150 154
105 India IN IND 356 ISO 3166-2:IN Asia Southern Asia 142 034
106 Indonesia ID IDN 360 ISO 3166-2:ID Asia South-eastern Asia 142 035
107 Iran, Islamic Republic of IR IRN 364 ISO 3166-2:IR Asia Southern Asia 142 034
108 Iraq IQ IRQ 368 ISO 3166-2:IQ Asia Western Asia 142 145
109 Ireland IE IRL 372 ISO 3166-2:IE Europe Northern Europe 150 154
110 Isle of Man IM IMN 833 ISO 3166-2:IM Europe Northern Europe 150 154
111 Israel IL ISR 376 ISO 3166-2:IL Asia Western Asia 142 145
112 Italy IT ITA 380 ISO 3166-2:IT Europe Southern Europe 150 039
113 Jamaica JM JAM 388 ISO 3166-2:JM Americas Latin America and the Caribbean Caribbean 019 419 029
114 Japan JP JPN 392 ISO 3166-2:JP Asia Eastern Asia 142 030
115 Jersey JE JEY 832 ISO 3166-2:JE Europe Northern Europe 150 154
116 Jordan JO JOR 400 ISO 3166-2:JO Asia Western Asia 142 145
117 Kazakhstan KZ KAZ 398 ISO 3166-2:KZ Asia Central Asia 142 143
118 Kenya KE KEN 404 ISO 3166-2:KE Africa Sub-Saharan Africa Eastern Africa 002 202 014
119 Kiribati KI KIR 296 ISO 3166-2:KI Oceania Micronesia 009 057
120 Korea, Democratic People's Republic of KP PRK 408 ISO 3166-2:KP Asia Eastern Asia 142 030
121 Korea, Republic of KR KOR 410 ISO 3166-2:KR Asia Eastern Asia 142 030
122 Kuwait KW KWT 414 ISO 3166-2:KW Asia Western Asia 142 145
123 Kyrgyzstan KG KGZ 417 ISO 3166-2:KG Asia Central Asia 142 143
124 Lao People's Democratic Republic LA LAO 418 ISO 3166-2:LA Asia South-eastern Asia 142 035
125 Latvia LV LVA 428 ISO 3166-2:LV Europe Northern Europe 150 154
126 Lebanon LB LBN 422 ISO 3166-2:LB Asia Western Asia 142 145
127 Lesotho LS LSO 426 ISO 3166-2:LS Africa Sub-Saharan Africa Southern Africa 002 202 018
128 Liberia LR LBR 430 ISO 3166-2:LR Africa Sub-Saharan Africa Western Africa 002 202 011
129 Libya LY LBY 434 ISO 3166-2:LY Africa Northern Africa 002 015
130 Liechtenstein LI LIE 438 ISO 3166-2:LI Europe Western Europe 150 155
131 Lithuania LT LTU 440 ISO 3166-2:LT Europe Northern Europe 150 154
132 Luxembourg LU LUX 442 ISO 3166-2:LU Europe Western Europe 150 155
133 Macao MO MAC 446 ISO 3166-2:MO Asia Eastern Asia 142 030
134 Madagascar MG MDG 450 ISO 3166-2:MG Africa Sub-Saharan Africa Eastern Africa 002 202 014
135 Malawi MW MWI 454 ISO 3166-2:MW Africa Sub-Saharan Africa Eastern Africa 002 202 014
136 Malaysia MY MYS 458 ISO 3166-2:MY Asia South-eastern Asia 142 035
137 Maldives MV MDV 462 ISO 3166-2:MV Asia Southern Asia 142 034
138 Mali ML MLI 466 ISO 3166-2:ML Africa Sub-Saharan Africa Western Africa 002 202 011
139 Malta MT MLT 470 ISO 3166-2:MT Europe Southern Europe 150 039
140 Marshall Islands MH MHL 584 ISO 3166-2:MH Oceania Micronesia 009 057
141 Martinique MQ MTQ 474 ISO 3166-2:MQ Americas Latin America and the Caribbean Caribbean 019 419 029
142 Mauritania MR MRT 478 ISO 3166-2:MR Africa Sub-Saharan Africa Western Africa 002 202 011
143 Mauritius MU MUS 480 ISO 3166-2:MU Africa Sub-Saharan Africa Eastern Africa 002 202 014
144 Mayotte YT MYT 175 ISO 3166-2:YT Africa Sub-Saharan Africa Eastern Africa 002 202 014
145 Mexico MX MEX 484 ISO 3166-2:MX Americas Latin America and the Caribbean Central America 019 419 013
146 Micronesia, Federated States of FM FSM 583 ISO 3166-2:FM Oceania Micronesia 009 057
147 Moldova, Republic of MD MDA 498 ISO 3166-2:MD Europe Eastern Europe 150 151
148 Monaco MC MCO 492 ISO 3166-2:MC Europe Western Europe 150 155
149 Mongolia MN MNG 496 ISO 3166-2:MN Asia Eastern Asia 142 030
150 Montenegro ME MNE 499 ISO 3166-2:ME Europe Southern Europe 150 039
151 Montserrat MS MSR 500 ISO 3166-2:MS Americas Latin America and the Caribbean Caribbean 019 419 029
152 Morocco MA MAR 504 ISO 3166-2:MA Africa Northern Africa 002 015
153 Mozambique MZ MOZ 508 ISO 3166-2:MZ Africa Sub-Saharan Africa Eastern Africa 002 202 014
154 Myanmar MM MMR 104 ISO 3166-2:MM Asia South-eastern Asia 142 035
155 Namibia NA NAM 516 ISO 3166-2:NA Africa Sub-Saharan Africa Southern Africa 002 202 018
156 Nauru NR NRU 520 ISO 3166-2:NR Oceania Micronesia 009 057
157 Nepal NP NPL 524 ISO 3166-2:NP Asia Southern Asia 142 034
158 Netherlands, Kingdom of the NL NLD 528 ISO 3166-2:NL Europe Western Europe 150 155
159 New Caledonia NC NCL 540 ISO 3166-2:NC Oceania Melanesia 009 054
160 New Zealand NZ NZL 554 ISO 3166-2:NZ Oceania Australia and New Zealand 009 053
161 Nicaragua NI NIC 558 ISO 3166-2:NI Americas Latin America and the Caribbean Central America 019 419 013
162 Niger NE NER 562 ISO 3166-2:NE Africa Sub-Saharan Africa Western Africa 002 202 011
163 Nigeria NG NGA 566 ISO 3166-2:NG Africa Sub-Saharan Africa Western Africa 002 202 011
164 Niue NU NIU 570 ISO 3166-2:NU Oceania Polynesia 009 061
165 Norfolk Island NF NFK 574 ISO 3166-2:NF Oceania Australia and New Zealand 009 053
166 North Macedonia MK MKD 807 ISO 3166-2:MK Europe Southern Europe 150 039
167 Northern Mariana Islands MP MNP 580 ISO 3166-2:MP Oceania Micronesia 009 057
168 Norway NO NOR 578 ISO 3166-2:NO Europe Northern Europe 150 154
169 Oman OM OMN 512 ISO 3166-2:OM Asia Western Asia 142 145
170 Pakistan PK PAK 586 ISO 3166-2:PK Asia Southern Asia 142 034
171 Palau PW PLW 585 ISO 3166-2:PW Oceania Micronesia 009 057
172 Palestine, State of PS PSE 275 ISO 3166-2:PS Asia Western Asia 142 145
173 Panama PA PAN 591 ISO 3166-2:PA Americas Latin America and the Caribbean Central America 019 419 013
174 Papua New Guinea PG PNG 598 ISO 3166-2:PG Oceania Melanesia 009 054
175 Paraguay PY PRY 600 ISO 3166-2:PY Americas Latin America and the Caribbean South America 019 419 005
176 Peru PE PER 604 ISO 3166-2:PE Americas Latin America and the Caribbean South America 019 419 005
177 Philippines PH PHL 608 ISO 3166-2:PH Asia South-eastern Asia 142 035
178 Pitcairn PN PCN 612 ISO 3166-2:PN Oceania Polynesia 009 061
179 Poland PL POL 616 ISO 3166-2:PL Europe Eastern Europe 150 151
180 Portugal PT PRT 620 ISO 3166-2:PT Europe Southern Europe 150 039
181 Puerto Rico PR PRI 630 ISO 3166-2:PR Americas Latin America and the Caribbean Caribbean 019 419 029
182 Qatar QA QAT 634 ISO 3166-2:QA Asia Western Asia 142 145
183 Réunion RE REU 638 ISO 3166-2:RE Africa Sub-Saharan Africa Eastern Africa 002 202 014
184 Romania RO ROU 642 ISO 3166-2:RO Europe Eastern Europe 150 151
185 Russian Federation RU RUS 643 ISO 3166-2:RU Europe Eastern Europe 150 151
186 Rwanda RW RWA 646 ISO 3166-2:RW Africa Sub-Saharan Africa Eastern Africa 002 202 014
187 Saint Barthélemy BL BLM 652 ISO 3166-2:BL Americas Latin America and the Caribbean Caribbean 019 419 029
188 Saint Helena, Ascension and Tristan da Cunha SH SHN 654 ISO 3166-2:SH Africa Sub-Saharan Africa Western Africa 002 202 011
189 Saint Kitts and Nevis KN KNA 659 ISO 3166-2:KN Americas Latin America and the Caribbean Caribbean 019 419 029
190 Saint Lucia LC LCA 662 ISO 3166-2:LC Americas Latin America and the Caribbean Caribbean 019 419 029
191 Saint Martin (French part) MF MAF 663 ISO 3166-2:MF Americas Latin America and the Caribbean Caribbean 019 419 029
192 Saint Pierre and Miquelon PM SPM 666 ISO 3166-2:PM Americas Northern America 019 021
193 Saint Vincent and the Grenadines VC VCT 670 ISO 3166-2:VC Americas Latin America and the Caribbean Caribbean 019 419 029
194 Samoa WS WSM 882 ISO 3166-2:WS Oceania Polynesia 009 061
195 San Marino SM SMR 674 ISO 3166-2:SM Europe Southern Europe 150 039
196 Sao Tome and Principe ST STP 678 ISO 3166-2:ST Africa Sub-Saharan Africa Middle Africa 002 202 017
197 Saudi Arabia SA SAU 682 ISO 3166-2:SA Asia Western Asia 142 145
198 Senegal SN SEN 686 ISO 3166-2:SN Africa Sub-Saharan Africa Western Africa 002 202 011
199 Serbia RS SRB 688 ISO 3166-2:RS Europe Southern Europe 150 039
200 Seychelles SC SYC 690 ISO 3166-2:SC Africa Sub-Saharan Africa Eastern Africa 002 202 014
201 Sierra Leone SL SLE 694 ISO 3166-2:SL Africa Sub-Saharan Africa Western Africa 002 202 011
202 Singapore SG SGP 702 ISO 3166-2:SG Asia South-eastern Asia 142 035
203 Sint Maarten (Dutch part) SX SXM 534 ISO 3166-2:SX Americas Latin America and the Caribbean Caribbean 019 419 029
204 Slovakia SK SVK 703 ISO 3166-2:SK Europe Eastern Europe 150 151
205 Slovenia SI SVN 705 ISO 3166-2:SI Europe Southern Europe 150 039
206 Solomon Islands SB SLB 090 ISO 3166-2:SB Oceania Melanesia 009 054
207 Somalia SO SOM 706 ISO 3166-2:SO Africa Sub-Saharan Africa Eastern Africa 002 202 014
208 South Africa ZA ZAF 710 ISO 3166-2:ZA Africa Sub-Saharan Africa Southern Africa 002 202 018
209 South Georgia and the South Sandwich Islands GS SGS 239 ISO 3166-2:GS Americas Latin America and the Caribbean South America 019 419 005
210 South Sudan SS SSD 728 ISO 3166-2:SS Africa Sub-Saharan Africa Eastern Africa 002 202 014
211 Spain ES ESP 724 ISO 3166-2:ES Europe Southern Europe 150 039
212 Sri Lanka LK LKA 144 ISO 3166-2:LK Asia Southern Asia 142 034
213 Sudan SD SDN 729 ISO 3166-2:SD Africa Northern Africa 002 015
214 Suriname SR SUR 740 ISO 3166-2:SR Americas Latin America and the Caribbean South America 019 419 005
215 Svalbard and Jan Mayen SJ SJM 744 ISO 3166-2:SJ Europe Northern Europe 150 154
216 Sweden SE SWE 752 ISO 3166-2:SE Europe Northern Europe 150 154
217 Switzerland CH CHE 756 ISO 3166-2:CH Europe Western Europe 150 155
218 Syrian Arab Republic SY SYR 760 ISO 3166-2:SY Asia Western Asia 142 145
219 Taiwan, Province of China TW TWN 158 ISO 3166-2:TW
220 Tajikistan TJ TJK 762 ISO 3166-2:TJ Asia Central Asia 142 143
221 Tanzania, United Republic of TZ TZA 834 ISO 3166-2:TZ Africa Sub-Saharan Africa Eastern Africa 002 202 014
222 Thailand TH THA 764 ISO 3166-2:TH Asia South-eastern Asia 142 035
223 Timor-Leste TL TLS 626 ISO 3166-2:TL Asia South-eastern Asia 142 035
224 Togo TG TGO 768 ISO 3166-2:TG Africa Sub-Saharan Africa Western Africa 002 202 011
225 Tokelau TK TKL 772 ISO 3166-2:TK Oceania Polynesia 009 061
226 Tonga TO TON 776 ISO 3166-2:TO Oceania Polynesia 009 061
227 Trinidad and Tobago TT TTO 780 ISO 3166-2:TT Americas Latin America and the Caribbean Caribbean 019 419 029
228 Tunisia TN TUN 788 ISO 3166-2:TN Africa Northern Africa 002 015
229 Türkiye TR TUR 792 ISO 3166-2:TR Asia Western Asia 142 145
230 Turkmenistan TM TKM 795 ISO 3166-2:TM Asia Central Asia 142 143
231 Turks and Caicos Islands TC TCA 796 ISO 3166-2:TC Americas Latin America and the Caribbean Caribbean 019 419 029
232 Tuvalu TV TUV 798 ISO 3166-2:TV Oceania Polynesia 009 061
233 Uganda UG UGA 800 ISO 3166-2:UG Africa Sub-Saharan Africa Eastern Africa 002 202 014
234 Ukraine UA UKR 804 ISO 3166-2:UA Europe Eastern Europe 150 151
235 United Arab Emirates AE ARE 784 ISO 3166-2:AE Asia Western Asia 142 145
236 United Kingdom of Great Britain and Northern Ireland GB GBR 826 ISO 3166-2:GB Europe Northern Europe 150 154
237 United States Minor Outlying Islands UM UMI 581 ISO 3166-2:UM Oceania Micronesia 009 057
238 Uruguay UY URY 858 ISO 3166-2:UY Americas Latin America and the Caribbean South America 019 419 005
239 Uzbekistan UZ UZB 860 ISO 3166-2:UZ Asia Central Asia 142 143
240 Vanuatu VU VUT 548 ISO 3166-2:VU Oceania Melanesia 009 054
241 Venezuela, Bolivarian Republic of VE VEN 862 ISO 3166-2:VE Americas Latin America and the Caribbean South America 019 419 005
242 Viet Nam VN VNM 704 ISO 3166-2:VN Asia South-eastern Asia 142 035
243 Virgin Islands (British) VG VGB 092 ISO 3166-2:VG Americas Latin America and the Caribbean Caribbean 019 419 029
244 Virgin Islands (U.S.) VI VIR 850 ISO 3166-2:VI Americas Latin America and the Caribbean Caribbean 019 419 029
245 Wallis and Futuna WF WLF 876 ISO 3166-2:WF Oceania Polynesia 009 061
246 Western Sahara EH ESH 732 ISO 3166-2:EH Africa Northern Africa 002 015
247 Yemen YE YEM 887 ISO 3166-2:YE Asia Western Asia 142 145
248 Zambia ZM ZMB 894 ISO 3166-2:ZM Africa Sub-Saharan Africa Eastern Africa 002 202 014
249 Zimbabwe ZW ZWE 716 ISO 3166-2:ZW Africa Sub-Saharan Africa Eastern Africa 002 202 014

View file

@ -1,13 +1,8 @@
from flask_wtf import FlaskForm
from wtforms import BooleanField, IntegerField, PasswordField, SelectField, StringField, SubmitField, widgets
from wtforms import BooleanField, PasswordField, SelectField, StringField, SubmitField, widgets
from wtforms.validators import DataRequired
import os
class RegisterForm(FlaskForm):
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
schools_list = open(os.path.join(__location__, 'schools.txt')).read().split("\n")
countries_list = open(os.path.join(__location__, 'countries.csv')).read().split("\n")
email = StringField("Email", validators=[DataRequired()])
first_name = StringField("Preferred First Name",
validators=[DataRequired()])
@ -15,18 +10,12 @@ class RegisterForm(FlaskForm):
password = PasswordField("Password", validators=[DataRequired()])
password_confirm = PasswordField("Confirm Password",
validators=[DataRequired()])
school = SelectField("School", choices=[(school, school) for school in schools_list], widget=widgets.Select())
school = StringField("School/University", validators=[DataRequired()])
phone_number = StringField("Phone number", validators=[DataRequired()])
age = IntegerField("Age", validators=[DataRequired()])
dietary_restrictions = StringField("Dietary Restrictions (Optional)")
gender = SelectField("Gender", choices=[("F", "Female"), ("M", "Male"),
("NB", "Non-binary/Other")],
widget=widgets.Select())
country = SelectField("Country", choices=[(country.split(",")[0], country.split(",")[0]) for country in countries_list], widget=widgets.Select())
newsletter = BooleanField("Subscribe to the MLH newsletter?")
agree_coc = BooleanField("I confirm that I have read and agree to the Code of Conduct", validators=[DataRequired()])
logistics = BooleanField("I authorize you to share my application/registration 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.", validators=[DataRequired()])
submit = SubmitField("Register")
class LoginForm(FlaskForm):

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,185 @@
.navbar-dark, .modal-header, .table-header {
background-color: #974355;
color: #FFFFFF;
@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");
}
.modal-header, .table-header {
color: #FFFFFF;
}
.container {
min-height: 100vh;
position: relative;
html {
height: 100%;
}
body {
min-height: 100vh;
background-color: #000000;
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;
}
form input[type="radio"] {
padding-right: 5px;
}
form input[type="checkbox"]:checked {
visibility: visible;
left: unset;
position: unset;
}
form label {
font-size: 1.1rem;
padding-right: 10px;
padding-left: 25px !important;
}
form select {
display: unset;
background: #974355;
max-width: 11rem;
}
.flashes {
list-style-type: none;
display: flex;
justify-content: center;
}
.message {
width: 80%;
justify-content: center;
border: 1px solid #eee;
background-color: #26a69a;
padding: 0.2rem;
font-size: large;
color: #eee;
}

View file

@ -1,21 +1,184 @@
$color-nav-bg: #974355;
$color-bg: #000000;
$color-bg: #003049;
$color-fg: #eee;
$color-section-bg: #974355;
$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"); }
.navbar-dark, .modal-header, .table-header {
background-color: $color-nav-bg;
color: #FFFFFF;
}
.modal-header, .table-header {
color: #FFFFFF;
}
.container {
min-height: 100vh;
position: relative;
html {
height: 100%;
}
body {
min-height: 100vh;
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;
}
input[type="radio"] {
padding-right: 5px;
}
input[type="checkbox"]:checked {
visibility: visible;
left: unset;
position: unset;
}
label {
font-size: 1.1rem;
padding-right: 10px;
padding-left: 25px !important;
}
select {
display: unset;
background: $color-section-bg;
max-width: 11rem;
}
}
// Flashed messages
.flashes {
list-style-type: none;
display: flex;
justify-content: center;
}
.message {
width: 80%;
justify-content: center;
border: 1px solid $color-fg;
background-color: $color-accent;
padding: 0.2rem;
font-size: large;
color: $color-fg;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,39 +0,0 @@
{% extends 'layout.html' %}
{% block navbar %}
<nav class="navbar navbar-dark mb-4 navbar-expand-lg">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="true"
aria-label="Toggle
navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-header">
<a class="navbar-brand" href="{{ url_for('admin.home') }}">
<img src="{{url_for('static', filename='img/logo.png')}}"
alt="Logo" width="35" height="35" class="d-inline-block
align-text-middle mx-2">GoatHacks Admin</a>
</div>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav me-auto mb-2 mb-lg-0">
{{ render_nav_item('admin.home', 'User List')}}
{{ render_nav_item('admin.admin_list', 'Admin List')}}
{{ render_nav_item('admin.list_events', 'Event List')}}
{{ render_nav_item('admin.mail', 'Bulk Mail Tool')}}
</ul>
<ul class="nav navbar-nav">
{% if current_user.is_authenticated %}
{{ render_nav_item('dashboard.home', '<- Back To Site') }}
{{ render_nav_item('registration.logout', 'Logout') }}
{% else %}
{{ render_nav_item('registration.register', 'Registration') }}
{{ render_nav_item('registration.login', 'Login') }}
{% endif %}
</ul>
</div>
</div>
</nav>
{% endblock %}

View file

@ -1,29 +1,213 @@
{% extends 'admin-layout.html' %}
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hack @ WPI</title>
<link rel="icon" href="../static/favicon.png" type="image/png">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://opensource.keycdn.com/fontawesome/4.7.0/font-awesome.min.css" integrity="sha384-dNpIIXE8U05kAbPhy3G1cz+yZmTzA6CY8Vg/u2L9xRnHjJiAK76m2BIEaSEV+/aU" crossorigin="anonymous">
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]--><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
{% block head %}
{{super()}}
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.4.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="{{url_for('static', filename='js/admin.js')}}"></script>
{% endblock %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
</head>
{% block app_content %}
<div class="card text-center">
<div class="card-body">
<h1 class="h3 mb-3 fw-normal">Registered Users</h1>
<table id="hackers" class="table table-striped">
<style>
.table-striped > tbody > tr:nth-of-type(odd) {
background-color: rgba(255, 255, 255, 0.15);
}
.table-hover > tbody > tr:hover {
background-color: rgba(255, 255, 255, 0.25);
}
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
content: " \25B4\25BE"
}
canvas {
max-width: 500px;
max-height: 500px;
}
</style>
<div class="contact-section" style="height: auto; background-repeat: repeat; background-size: contain;">
<div class="container-fluid" style="margin-left: 3%; margin-right: 3%;">
<div class="row" style="margin-top: 10%;">
<h5>JSON object of users from MLH (Including dropped applications):</h5>
<p><a href="{{ mlh_url }}"><b>Do NOT share this URL.</b></a></p>
<h5>Get registered hackers only:</h5>
<p><a href="{{url_for('admin.hackers')}}">JSON</a> <a
href="{{url_for('admin.hackers_csv')}}">CSV</a></p>
</div>
<div class="row">
<div class="col-md-4">
<h2 style="">Gender:</h2>
<canvas id="genderCanvas" width="400" height="400"></canvas>
<script>
let genderCtx = document.getElementById('genderCanvas')
let genderChart = new Chart(genderCtx, {
type: 'doughnut',
data: {
labels: ['Female', 'Male', 'Non-Binary/Other'],
datasets: [
{
data: [{{ female_count }}, {{ male_count }}, {{ nb_count }}]
}
]
},
options: {
title: {
display: false
},
legend: {
display: false
},
labels: {
display: false
}
}
})
</script>
</div>
<div class="col-md-4">
<h2 style="">Schools:</h2>
<canvas id="schoolCanvas" width="400" height="400"></canvas>
<script>
let schoolNames = []
let schoolNums = []
{% for school in schools %}
schoolNames.push('{{ school }}')
schoolNums.push({{ schools[school] }})
{% endfor %}
let schoolCtx = document.getElementById('schoolCanvas')
let schoolChart = new Chart(schoolCtx, {
type: 'doughnut',
data: {
labels: schoolNames,
datasets: [
{
data: schoolNums
}
]
},
options: {
title: {
display: false
},
legend: {
display: false
},
labels: {
display: false
}
}
})
</script>
</div>
<div class="col-md-4">
<h2 style="">Majors:</h2>
<canvas id="majorCanvas" width="400" height="400"></canvas>
<script>
let majorNames = []
let majorNums = []
{% for major in majors %}
majorNames.push('{{ major }}')
majorNums.push({{ majors[major] }})
{% endfor %}
let majorCtx = document.getElementById('majorCanvas')
let majorChart = new Chart(majorCtx, {
type: 'doughnut',
data: {
labels: majorNames,
datasets: [
{
data: majorNums
}
]
},
options: {
title: {
display: false
},
legend: {
display: false
},
labels: {
display: false
}
}
})
</script>
</div>
</div>
<div class="row" style="">
<h2 style="">Counts:</h2>
<table id="counts" class="table table-striped table-hover table-condensed sortable">
<thead>
<tr>
<th>Total</th>
<th>Attendees</th>
<th>Waitlist</th>
<th>Checked In</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ total_count }}</td>
<td>{{ (total_count - waitlist_count) }}</td>
<td>{{ waitlist_count }}</td>
<td>{{ check_in_count }}</td>
</tr>
</tbody>
</table>
<h2 style="margin-top: 2%;">Shirts:</h2>
<table id="shirts" class="table table-striped table-hover table-condensed sortable">
<thead>
<tr>
<th>XXS</th>
<th>XS</th>
<th>S</th>
<th>M</th>
<th>L</th>
<th>XL</th>
<th>XXL</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ shirt_count['XXS'] }}</td>
<td>{{ shirt_count['XS'] }}</td>
<td>{{ shirt_count['S'] }}</td>
<td>{{ shirt_count['M'] }}</td>
<td>{{ shirt_count['L'] }}</td>
<td>{{ shirt_count['XL'] }}</td>
<td>{{ shirt_count['XXL'] }}</td>
</tr>
</tbody>
</table>
<h2 style="margin-top: 2%;">Hackers:</h2>
<table id="hackers" class="table table-striped table-hover table-condensed sortable">
<thead>
<tr>
<th>Options</th>
<th>Checked In?</th>
<th>Waitlisted?</th>
<th>Admin</th>
<th>User ID</th>
<th>Registration Time</th>
<th>MLH ID</th>
<th>Time Registered</th>
<th>Email</th>
<th>Name</th>
<th>Phone</th>
@ -36,59 +220,61 @@
{% for hacker in hackers %}
<tr id="{{ hacker.id }}-row">
<td>
<div class="dropdown">
<a href="#" class="btn btn-primary dropdown-toggle"
data-bs-toggle="dropdown"><span
<div class="btn-group">
<a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown"><span
class="caret"></span></a>
<ul class="dropdown-menu">
{% if not hacker.checked_in %}
<li><a class="dropdown-item check_in" id="{{
hacker.id}}-check_in"
href="#">Check
In</a></li>
<li><a class="check_in" id="{{ hacker.id }}-check_in" href="#">Check In</a>
</li>
{% endif %}
{% if hacker.waitlisted and not
hacker.checked_in %}
<li><a class="dropdown-item
promote_from_waitlist" id="{{
hacker.id}}-promote_from_waitlist"
href="#">Promote From
Waitlist</a></li>
{% if hacker.waitlisted and not hacker.checked_in %}
<li><a class="promote_from_waitlist"
id="{{ hacker['id'] }}-promote_from_waitlist"
href="#">Promote From Waitlist</a></li>
{% endif %}
<li><hr class="dropdown-divider"></li>
<li class="divider"></li>
{% if not hacker.checked_in %}
<li><a class="dropdown-item drop"
id="{{hacker.id}}-drop"
href="#">Drop Registration</a></li>
<li><a class="drop" id="{{ hacker['id'] }}-drop" href="#">Drop Application</a>
</li>
{% endif %}
{% if hacker.is_admin %}
<li><a class="dropdown-item demote_admin"
id="{{hacker.id}}-demote_admin"
href="#">Demote Admin</a></li>
<li><a class="demote_admin" id="{{ hacker['id'] }}-demote_admin" href="#">Demote
Admin</a>
</li>
{% else %}
<li><a class="dropdown-item promote_admin"
id="{{hacker.id}}-promote_admin"
href="#">Promote Admin</a></li>
<li><a class="promote_admin" id="{{ hacker['id'] }}-promote_admin" href="#">Promote
Admin</a>
</li>
{% endif %}
</ul>
</div>
</td>
<td id="{{hacker.id}}-checked_in">{{ hacker.checked_in }}</td>
<td id="{{hacker.id}}-waitlisted">{{ hacker.waitlisted }}</td>
<td id="{{ hacker['id'] }}-checked_in">{{ hacker['checked_in'] }}</td>
<td id="{{ hacker['id'] }}-waitlisted">{{ hacker['waitlisted'] }}</td>
<td>{{ hacker.is_admin }}</td>
<td>{{ hacker.id }}</td>
<td>{{ hacker.last_login }}</td>
<td>{{ hacker.email }}</td>
<td>{{ hacker.first_name + ' ' + hacker.last_name }}</td>
<td>{{ hacker.phone }}</td>
<td>{{ hacker.shirt_size }}</td>
<td>{{ hacker.accomodations }}</td>
<td>{{ hacker.school }}</td>
<td>{{ hacker['id'] }}</td>
<td>{{ hacker['last_login'] }}</td>
<td>{{ hacker['email'] }}</td>
<td>{{ hacker['first_name'] + ' ' + hacker['last_name'] }}</td>
<td>{{ hacker['phone'] }}</td>
<td>{{ hacker['shirt_size'] }}</td>
<td>{{ hacker['accomodations'] }}</td>
<td>{{ hacker['school'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
</div>
<script>
$(document).ready(() => {
setTimeout('let myTh = document.getElementsByTagName("th")[14]; sorttable.innerSortFunction.apply(myTh, []); sorttable.innerSortFunction.apply(myTh, []);', 50)
})
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="../static/js/jquery.easing.min.js"></script>
</body>
</html>

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">{{ m }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}
This content block is still being worked on!
{% endblock %}
</div>
{% include 'footer.html' %}

View file

@ -1,44 +0,0 @@
{% from 'bootstrap5/nav.html' import render_nav_item %}
{% from 'bootstrap5/utils.html' import render_messages %}
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
{% if title %}
<title>{{ title }} - GoatHacks</title>
{% else %}
<title>GoatHacks</title>
{% endif %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% block styles %}
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
{% endblock %}
{% endblock %}
</head>
<body>
<!-- Your page content -->
{% block navbar %}{% endblock %}
<!-- Your page content -->
<div class="container">
<div id="outerAlerts">
{{ render_messages(container=False, dismissible=True, dismiss_animate=True) }}
</div>
{% block app_content %}{% endblock %}
</div>
{% block scripts %}
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
{% endblock %}
</body>
</html>

View file

@ -1,56 +1,104 @@
{% extends 'layout.html' %}
{% from 'bootstrap5/form.html' import render_field %}
{% extends 'base.html' %}
{% block app_content %}
<div class="card text-center">
<div class="card-body">
<h1 class="h2 mb-3 fw-normal">Hi {{current_user.first_name}}!</h1>
{% block content %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<script>
function drop(id) {
if(window.confirm("Are you sure you wish to drop your application? This cannot be undone. (patiently wait after clicking the button)")) {
window.location.href = "/admin/drop/" + id;
}
}
function resumeChange() {
let val = document.getElementById('resume').value;
val = val.split(/\\|\//gi).slice(-1)[0]
document.getElementById('filename').setAttribute('value', val);
}
</script>
<div class="contact-section" style="height: 100%;">
<div class="container">
<div class="row center justify-content-center" style="margin-top: 10%;">
<h1>Hi {{ current_user.first_name }}!</h1>
{% if current_user.waitlisted %}
<h4 class="h3 mb-3 fw-normal">You're currently waitlisted. If space
opens up, we'll let you know!</h4>
<h2>You are waitlisted, if space opens up we will let you know</h2>
{% else %}
<h4>You are fully registered! We look forward to seeing you!</h4>
{% endif %}
<p class="card-text">Let us know if you have any questions by sending
them to <a href="mailto:hack@wpi.edu">hack@wpi.edu</a></p>
{% if not current_user.waitlisted and config['DISCORD_LINK'] %}
<p>Make sure to join our Discord to get the latest updates!</p>
<button type="button" class="btn btn-primary mb-3"><a href="{{ config['DISCORD_LINK']
}}" class="link-light">Discord</a></button>
{% endif %}
<h2>You are fully registered! We look forward to seeing you!</h2>
Let us know if you have any questions by sending them to <a href="mailto:hack@wpi.edu">hack@wpi.edu</a>
<br>
<br>
Forgot to upload your resume while registering? No worries, submit it below.
</div>
<div class="row center justify-content-center">
{% if config['DISCORD_LINK'] is defined %}
<h5>Make sure to join the Discord and enter your shirt size below!</h5>
<a href="{{ config['DISCORD_LINK'] }}" style="margin: 5px;"
class="btn btn-lg btn-primary btn-invert">Discord</a>
{% else %}
<h5>Our discord is still under construction! We'll send out an email when it's ready.</h5>
{% endif %}
</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="post">
{{ form.csrf_token() }}
<p><b>Optional Info</b></p>
<div class="form-floating mb-3 required">
{{ form.shirt_size(class="form-control", selected=current_user.shirt_size) }}
{{ form.shirt_size.label() }}
{{ form.csrf_token }}
<br>
<p><b>Optional Info:</b></p>
<div>
<p>Shirt Size (Currently selected: {{current_user.shirt_size}})</p>
{% for subfield in form.shirt_size %}
{{subfield}}{{subfield.label}}
{% endfor %}
<p>Special Needs/Accommodations:</p>
<input type="text" name="accomodations"
id="special_needs" value="{{ current_user.accomodations }}">
</div>
<div class="form-floating mb-3 required">
{{ form.accomodations(class="form-control") }}
{{ form.accomodations.label() }}
</div>
{{ render_field(form.submit) }}
<br><br>
<input name="save" class="btn btn-lg btn-primary btn-invert" type="submit" value="Save"/>
<br><br><br>
</form>
</div>
<hr/>
<div class="row center justify-content-center">
<form method="post" action="{{url_for('dashboard.resume')}}"
enctype="multipart/form-data">
{{ resform.csrf_token() }}
<p><b>If you'd like, add your resume to send to
sponsors...</b></p>
<div class="form mb-3 required">
{{ resform.resume(class="form-control") }}
</div>
{{ render_field(resform.submit) }}
</form>
</div>
<form method="post" action="{{url_for('dashboard.resume')}}" enctype="multipart/form-data">
{{ resform.csrf_token }}
<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>
<input name="submit" class="btn btn-lg btn-primary btn-invert" type="submit" value="Submit"/>
</form>
{% endif %}
<br>
</div>
{% if current_user.is_admin %}
<br>
<div class="row justify-content-center">
<a href="/admin"><p class="btn">Admin Dashboard</p></a>
</div>
{% endif %}
<br>
</div>
<br>
<br>
<center><a onclick="drop('{{current_user.id}}')" id="drop-link"><p class="btn">Drop Application if you can't make it :(</p></a></center>
</div>
<script>
let errColor = '#E74C3C'
$(document).ready(() => {
$('#drop-link').click((e) => {
e.preventDefault()
let id = {{ id }}
drop(id)
})
})
</script>
{% endblock %}

View file

@ -1,9 +1,8 @@
{% extends 'admin-layout.html' %}
{% extends 'base.html' %}
{% block app_content %}
<div class="card text-center">
{% block content %}
<div style="height: 100%;">
<div style="height: 100%; color: white;">
<h2>Events</h2>
Get a JSON readout of events <a href="{{ url_for('admin.events_json')
}}">here</a>
@ -19,7 +18,7 @@
<th>Category</th>
<th>Checked in</th>
<th>QR Code</th>
<th><a href="#editModal" data-bs-toggle="modal" data-id="0">New</a></th>
<th><a href="{{url_for('admin.new_event')}}">New</a></th>
</tr>
</thead>
<tbody>
@ -34,166 +33,11 @@
<td>{{ event.get_checkins()|length }}</td>
<td><a href='{{ url_for("admin.qrcode_event", id=event.id)
}}'>QR Code</a></td>
<td><a href="#editModal" data-bs-toggle="modal" data-id="{{ event.id}}" >Edit</a></td>
<td><a href="{{url_for('admin.edit_event', 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 %}

View file

@ -1,7 +1,6 @@
{% extends 'admin-layout.html' %}
{% extends 'base.html' %}
{% block app_content %}
<div class="card text-center">
{% block content %}
<div style="height: 100%;">
<div id="registration-banner" class="parallax-container valign-wrapper">
<div class="section">
@ -10,39 +9,30 @@
</div>
</div>
<div class="container">
<div class="section" style="background-color: #974355; padding: 20px;">
<form method="post">
{{ form.csrf_token }}
<div class="form-floating mb-3 required">
{{ form.name(class="form-control") }}
{{ form.name.label }}
<div>
{{ form.name}}<br/> {{ form.name.label }}
</div>
<div class="form-floating mb-3">
{{ form.description(class="form-control") }}
{{form.description.label}}
<div>
{{ form.description}}<br/>{{form.description.label}}
</div>
<div class="form-floating mb-3 required">
{{ form.location(class="form-control")}}
{{form.location.label}}
<div>
{{ form.location}}<br/>{{form.location.label}}
</div>
<div class="row">
<div class="col">
<div class="form mb-3 required">
{{form.start_time(class="form-control")}}
{{form.start_time.label}}
<div>
{{form.start_time}}<br/>{{form.start_time.label}}
</div>
<div>
{{form.end_time}}<br/>{{form.end_time.label}}
</div>
<div class="col">
<div class="form mb-3 required">
{{form.end_time(class="form-control")}}
{{form.end_time.label}}
</div>
</div>
</div>
<div class="form-floating mb-3 required">
{{form.category(class="form-control")}}
{{form.category.label}}
<div>
{{form.category}}<br/>{{form.category.label}}
</div>
<div>
{{form.submit}}
</div>
</form>
</div>
</div>

View file

@ -2,6 +2,5 @@
<title>QR Code for {{ event.name }}</title>
</head>
<body>
<img src="{{ qrcode(url_for('events.workshop_checkin', id=event.id,
_external=True)) }}">
<img src="{{ qrcode(url_for('events.workshop_checkin', id=event.id)) }}">
</body>

View file

@ -0,0 +1,16 @@
<!-- A hack to make sure the footer bar shows-->
<div style="height: 100px"></div>
<nav class="navbar navbar-inverse footer-nav" style= "margin-top: 30px">
<div class="container-fluid">
<div class="navbar-header">
</div>
<ul class="nav justify-content-end">
<li class="nav-item">
<a class="nav-link" href="mailto:hack@wpi.edu?subject=[Hackathon]">Contact Us</a>
</li>
</ul>
</div>
</nav>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<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/materialize.min.css" rel="stylesheet">
{% assets 'scss' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
</head>
<style>
nav {
background-color: #F5665B;
border-color: #E7E4C6;
color: white;
}
</style>
<body>
<nav class="navbar navbar-inverse sticky-top navbar-expand">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">Goathacks</a>
</div>
<ul class="nav justify-content-end">
<!-- <li class="nav-item">
{% if registration_open or registration_open is not defined %}
<a class="nav-link active" href="/register">Register</a>
{% else %}
<a class="nav-link active disabled" href="#">Registration is closed</a>
{% endif %}
</li>
<li class="nav-item">
<a class="nav-link" href="../static/assets/Hack@WPI-SponsorshipInformation-2020.pdf">Sponsorship Packet</a>
</li> -->
<li class="nav-item">
<a class="nav-link" href="https://hack.wpi.edu/conduct/conduct.pdf">Code of Conduct</a>
</li>
</ul>
</div>
</nav>

@ -1 +1 @@
Subproject commit db2a7a865f9b3865fa2180b1b53b1c2d2640be81
Subproject commit e0fb69c0be54c6cce7391ccb86a9bf14b80f432b

195
goathacks/templates/index.html Executable file
View file

@ -0,0 +1,195 @@
{% include 'header.html' %}
<div>
<style>
hr {
margin-top: 2rem;
margin-bottom: 2rem;
width: 70%;
border-width: 10px;
border-color: #F5665B;
}
h2 {
text-align: center;
}
h3 {
text-align: center;
}
h4 {
text-align: center;
}
h5 {
text-align: center;
}
h6 {
text-align: center;
margin-right: 100px;
margin-left: 100px;
}
div.main-logo {
margin-top: 16px;
}
.sponsors {
text-align: center;
display: block;
padding: 20px;
}
.sponsors > div {
margin-bottom: 40px;
}
.sponsors > div:last-child {
margin-bottom: 0;
}
.sponsors img {
display: inline-block;
margin-right: 40px;
/* Hack to fix overflow of bose logo*/
max-width: calc(100% - 10px);
}
.title-sponsors img{
max-height: 90px;
}
.silver-sponsors img {
max-height: 25px;
}
a {
color: black;
}
.x{
background-color: #E7E4C6;
margin-right: 100px;
margin-left: 100px;
color: black;
border-radius: 50px 50px 50px 50px;
padding-bottom: 10px;
padding-top:10px;
}
.snow-banner {
background-color: red;
width: 100%;
padding: 10px;
text-align: center;
}
</style>
<div class="snow-banner">
<b>Attention!</b> Due to the road conditions, we have delayed the schedule by an hour. We will still have live presentations, but submissions have been extended until 9am, and judging will take place at 10am.
</div>
<!--Logo + Date+ Hosted By -->
<div class="container">
<div class="row center main-logo">
<img src="../static/img/hackwpilogo.png" alt="logo" style='height: 100%; width: 100%; object-fit: contain'/>
</div>
</div>
<!--"Hackathon for all students" -->
<hr/>
<h2> A HACKATHON FOR ALL COLLEGE STUDENTS </h2>
<hr/>
<!--Location -->
<h3> WPI Campus Center </h3>
<h4>100 Institute Road</h4>
<h4> Worcester, MA 01609</h4>
<hr/>
<!-- Sponsors for 2020 -->
<h2> OUR SPONSORS FOR 2020 </h2>
<div class="container">
<div class="row center sponsors">
<div class="title-sponsors">
<img class="logo" src="../static/img/logos/bose.png"></div>
<div class="platinum-sponsors">
<h1>WPI Computer Science Department</h1>
</div>
<div class="gold-sponsors">
<img class="logo" src="../static/img/logos/iboss.png" style = "height: 150px">
<img class="logo" src="../static/img/logos/kronos.png" style = "height: 75px">
<img class="logo" src="../static/img/logos/paytronix.png" style = "height: 30px">
<img class="logo" src="../static/img/logos/abbvie.png" style = "height: 60px">
</div>
<div class="silver-sponsors">
<img class="logo" src="../static/img/logos/carbonblack.png" >
</div>
<div class="bronze-sponsors">
<img class="logo" src="../static/img/logos/wakefly.png" style = "height: 70px">
<img class="logo" src="../static/img/logos/amazon.png" style = "height: 70px">
<img class="logo" src="../static/img/logos/everquote.png" style = "height: 35px">
<img class="logo" src="../static/img/logos/synopses.png" style = "height: 20px">
<img class="logo" src="../static/img/logos/boozallenhamilton.png" style = "height: 35px">
</div>
</div>
</div>
<!--FAQs -->
<hr/>
<div class = "x">
<h2> FAQs </h2>
<div class = "FAQ">
<h4>Who can attend?</h4>
<h6> Our event is open to any college student! You dont need any experience to participate. However, due to legal issues, anyone under 18 must have a legal guardian present and cannot win prizes </h6>
</div>
<div class = "FAQ">
<h4>What is the max team size?</h4>
<h6>The maximum is 5 people per team. Minimum is 1 :P</h6>
</div>
<div class = "FAQ">
<h4>What are the awards for?</h4>
<h6>The categories this year are: </h6>
<h6>Best Overall Project
<h6>Best Game </h6>
<h6>Best Software </h6>
<h6>Best Hardware </h6>
<h6>Company Favorite </h6>
<h6>Best Use of the Bose API/SDK </h6>
<h6>Best Meme </h6>
<h6>Best Rookie </h6>
</div>
<div class = "FAQ">
<h4>What should I bring?</h4>
<h6>Bring devices, chargers, sleeping bags, toiletries, basically anything you need to be comfortable. We will provide showers at certain time slots during the weekend. Food will also be provided.</h6>
</div>
<div class = "FAQ">
<h4>What if I don't have a team?</h4>
<h6>You dont need a team to register! We will have a team formation session right after the opening ceremony for those who would like to work with a team. If you prefer to stay solo, thats also great. </h6>
</div>
<div class = "FAQ">
<h4>How should I prepare beforehand?</h4>
<h6>Make sure you have travel plans in place, especially in case of random snowfalls. Unfortunately, we do not provide travel reimbursements.
Its also nice to have an idea in mind beforehand. However, we ask that you do not bring any pre-made materials to keep the competition fair. </h6>
</div>
<div class = "FAQ">
<h4>What is the schedule?</h4>
<h6><a href = 'https://docs.google.com/spreadsheets/d/1FSh2UfZwoMwXlgrKnKjnQg2okEcLDVCP30khnPdM1H0/edit?usp=sharing' style= "color: blue">Here it is!</a> Keep in mind that this is tentative. </h6>
</div>
</div>
</div>
{% include 'footer.html' %}

View file

@ -1,56 +0,0 @@
{% extends 'bootstrap-base.html' %}
{% block html_attribs %} lang="en"{% endblock %}
{% block title %}{% if title %}{{ title }} - GoatHacks{% else %}GoatHacks{%
endif %}{% endblock %}
{% block head %}
{{super()}}
{{ font_awesome.load_css() }}
{% endblock %}
{% block styles %}
{{super()}}
{% assets 'scss' %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-dark mb-4 navbar-expand-lg">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="true"
aria-label="Toggle
navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-header">
<a class="navbar-brand" href="{{ url_for('registration.register') }}">
<img src="{{url_for('static', filename='img/logo.png')}}"
alt="Logo" width="35" height="35" class="d-inline-block
align-text-middle mx-2">GoatHacks</a>
</div>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav me-auto mb-2 mb-lg-0">
{{ render_nav_item('registration.register', 'Home')}}
</ul>
<ul class="nav navbar-nav">
{% if current_user.is_authenticated %}
{{ render_nav_item('dashboard.home', 'Dashboard') }}
{% if current_user.is_admin %}
{{ render_nav_item('admin.home', 'Admin Dash') }}
{% endif %}
{{ render_nav_item('registration.logout', 'Logout') }}
{% else %}
{{ render_nav_item('registration.register', 'Registration') }}
{{ render_nav_item('registration.login', 'Login') }}
{% endif %}
</ul>
</div>
</div>
</nav>
{% endblock %}

View file

@ -1,34 +1,34 @@
{% extends 'layout.html' %}
{% from 'bootstrap5/form.html' import render_field %}
{% extends 'base.html' %}
{% block app_content %}
<div class="card text-center">
<div class="card-body">
<img class="mb-4" src="{{ url_for('static', filename='img/banner.png')
}}" alt="GoatHacks 2024 Banner">
<h1 class="h3 mb-3 fw-normal">Welcome back to GoatHacks!</h1>
<p class="card-text">If you've already registered, please use this page
to access your participant dashboard. Otherwise, please use the <a
href="{{
url_for('registration.register')
}}"
>
registration</a> page to register!</p>
<div class="text-center">
<form action="" method="post" class="form" role="form">
{{ form.csrf_token() }}
<div class="form-floating mb-3 required">
{{ form.email(class="form-control") }}
{{ form.email.label() }}
{% 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">Login</h3>
</div>
<div class="form-floating mb-3 required">
{{ form.password(class="form-control") }}
{{ form.password.label() }}
</div>
{{ render_field(form.submit) }}
</div>
<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.submit}}
</div>
</form>
</div>
<span><p><em>Don't have an account? <a
href="{{url_for('registration.register')}}">Register
here</a>.</em></p></span>
<span><p><em>Forgot your password? Head over <a
href="{{url_for('registration.reset')}}">here</a>
to reset it.</em></p></span>
</div>
</div>
{% endblock %}

View file

@ -1,20 +1,23 @@
{% extends 'admin-layout.html' %}
{% block head %}
{{super()}}
<!DOCTYPE html>
<html lang="en">
<head>
<title>🍪CookieMailer</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<meta name="theme-color" content="">
<link rel="stylesheet" type="text/css" href="/static/css/mail.css" />
<script src="https://cdn.tiny.cloud/1/{{MCE_API_KEY}}/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script></head>
{% endblock %}
{% block app_content %}
<div class="card">
<div class="card-body">
<h1 class="h3 mb-3 fw-normal">🍪CookieMailer</h1>
<body>
<div id="loader"></div>
<div class="container">
<div class="row">
<div id="root" class="col">
<h2>🍪CookieMailer</h2>
<label for="recipients">To: </label>
<br/>
<select class="form-control" id="recipients" name="recipients">
<select id="recipients" name="recipients">
<option value="admin">Test Email (SysAdmin)</option>
<option value="org">Test Email (Organizers)</option>
<!-- <option value="wpi">WPI Only</option> -->
@ -23,8 +26,7 @@
<br/>
<label for="subject">Subject: </label>
<br/>
<input class="form-control" id="subject" name="subject" width="100%"
type="text" value="GoatHacks -- " />
<input id="subject" name="subject" width="100%" type="text" value="Hack@WPI" />
<br/>
<br/>
<textarea id="content" name="content">
@ -38,7 +40,7 @@
</textarea>
<br/>
<br/>
<input class="btn btn-primary" type="button" onClick="send()" value="Send"/>
<input type="button" onClick="send()" value="Send"/>
</div>
</div>
</div>
@ -75,7 +77,6 @@
];
if((rec != "all" && window.confirm("Send test email?")) || (rec == "all" && window.confirm("Send email to {{NUM_HACKERS}} recipients?"))) {
console.log(`Sending email to ${rec}`)
fetch('/admin/send', {method: 'POST', body: JSON.stringify(body), headers: headers}).then(async (res) => {
window.alert(await res.text());
}).catch((err) => {
@ -95,7 +96,6 @@
// })
}
</script>
</div>
</div>
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,27 @@
{% 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">Reset Password</h3>
</div>
</div>
</div>
<div class="container">
<div class="section" style="background-color: #974355; padding: 20px;">
<form method="post">
{{ form.csrf_token }}
<div>
{{form.password}}<br/>{{form.password.label}}
</div>
<div>
{{form.password_confirm}}<br/>{{form.password_confirm.label}}
</div>
<div>
{{form.submit}}
</div>
</form>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,24 @@
{% 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">Reset Password</h3>
</div>
</div>
</div>
<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.submit}}
</div>
</form>
</div>
</div>
{% endblock %}

View file

@ -1,112 +1,58 @@
{% extends 'layout.html' %}
{% from 'bootstrap5/form.html' import render_field %}
{% extends 'base.html' %}
{% block app_content %}
<div class="card text-center">
<div class="card-body">
<img class="mb-4" src="{{ url_for('static', filename='img/banner.png')
}}" alt="GoatHacks Banner">
<h1 class="h3 mb-3 fw-normal">Welcome to GoatHacks!</h1>
<p class="card-text">Please use this page to register for this year's
Hackathon. Accounts from prior years are not carried over!</p>
<div class="text-center">
<form action="" method="post" class="form" role="form">
{{ form.csrf_token() }}
<div class="form-floating mb-3 required">
{{ form.email(class="form-control") }}
{{ form.email.label() }}
</div>
<div class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.password(class="form-control") }}
{{ form.password.label() }}
</div>
</div>
<div class="col">
<div class="form-floating mb-3 required">
{{ form.password_confirm(class="form-control") }}
{{ form.password_confirm.label() }}
{% 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>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.first_name(class="form-control") }}
{{ form.first_name.label() }}
<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 class="col">
<div class="form-floating mb-3 required">
{{ form.last_name(class="form-control") }}
{{ form.last_name.label() }}
<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 class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.school(class="form-control") }}
{{ form.school.label() }}
<hr/>
<h3>Miscellaneous Information</h3>
<div>
{{form.phone_number}}<br/>{{form.phone_number.label}}
</div>
<div>
{{form.school}}<br/>{{form.school.label}}
</div>
<div class="col">
<div class="form-floating mb-3 required">
{{ form.country(class="form-control") }}
{{ form.country.label() }}
<div>
{{form.gender.label}}{{form.gender}}
</div>
<hr/>
<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>
<div class="row">
<div class="col">
<div class="form-floating mb-3 required">
{{ form.phone_number(class="form-control") }}
{{ form.phone_number.label() }}
</div>
</div>
<div class="col">
<div class="form-floating mb-3 required">
{{ form.age(class="form-control") }}
{{ form.age.label() }}
</div>
</div>
</div>
<div class="form-floating mb-3 required">
{{ form.gender(class="form-control") }}
{{ form.gender.label() }}
</div>
<div class="form-floating mb-3">
{{ form.dietary_restrictions(class="form-control") }}
{{ form.dietary_restrictions.label() }}
</div>
<div class="form-check mb-3 required">
{{ form.agree_coc }}
I confirm that I have read and agree to the <a href="https://static.mlh.io/docs/mlh-code-of-conduct.pdf" target="_blank">MLH Code of Conduct</a>
</div>
<div class="form-check mb-3 required">
{{ form.logistics }}
I authorize you to share my application/registration 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 <a
href="https://github.com/MLH/mlh-policies/blob/main/contest-terms.md">MLH
Contest Terms
and
Conditions</a>
and the <a
href="https://github.com/MLH/mlh-policies/blob/main/privacy-policy.md">MLH
Privacy
Policy</a>.
</div>
<div class="form-check mb-3">
{{ form.newsletter }}
Subscribe to the MLH newsletter?
</div>
{{ render_field(form.submit) }}
</form>
</div>
<span><p><em>You may also want to <a
href="{{url_for('registration.login')}}">
log in</a>.</em></p></span>
</div>
</div>
{% 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,16 @@
{% include 'header.html' %}
<link href="../static/css/materialize.min.css" rel="stylesheet">
<div style="margin: 16px">
<p>
I agree to hold harmless the organizers of HACK@WPI and WPIs Chapter of the Association of Computing Machinery (ACM) from any and all claims, lawsuits, demands, causes of action, liability, loss, damage and/or injury of any kind whatsoever (including without limitation all claims for monetary loss, property damager, equitable relief, personal injury and/or wrongful death), whether brought by an individual or other entity. The indemnification applies to and includes, without limitation, the payment of all penalties, fines, judgments, awards, decrees, attorneys fees, and related costs or expenses, and any reimbursements to ACM for all legal fees, expenses, and costs incurred by it.
</p>
<p>
I also acknowledge the organizers of HACK@WPI will be recording the event using video, photographs, audio recordings, and other media and give them permission to use said media in marketing/promotional materials.
</p>
</div>
<!-- This is stupid but it works -->
<div style="position: absolute; bottom: 0; width: 100%;">
{% include 'footer.html' %}
</div>

View file

@ -1,38 +0,0 @@
"""empty message
Revision ID: f5b70c6e73eb
Revises: 858e0d45876f
Create Date: 2024-10-31 13:04:48.500263
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f5b70c6e73eb'
down_revision = '858e0d45876f'
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('newsletter', sa.Boolean(), nullable=False))
batch_op.add_column(sa.Column('country', sa.String(), nullable=False))
batch_op.add_column(sa.Column('age', sa.Integer(), nullable=False))
batch_op.add_column(sa.Column('dietary_restrictions', 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('dietary_restrictions')
batch_op.drop_column('age')
batch_op.drop_column('country')
batch_op.drop_column('newsletter')
# ### end Alembic commands ###

View file

@ -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
greenlet==2.0.1
itsdangerous==2.1.2
Jinja2==3.1.2
Mako==1.2.4
@ -19,11 +19,8 @@ psycopg2==2.9.5
pynvim==0.4.3
python-dotenv==0.21.0
SQLAlchemy==1.4.44
uWSGI
uWSGI==2.0.21
Werkzeug==2.2.2
WTForms==3.0.1
ulid
bootstrap-flask
Font-Awesome-Flask
tabulate
markupsafe