diff --git a/goathacks/__init__.py b/goathacks/__init__.py index d6967a9..455a979 100644 --- a/goathacks/__init__.py +++ b/goathacks/__init__.py @@ -4,6 +4,7 @@ from flask_migrate import Migrate from flask_login import LoginManager from flask_assets import Bundle, Environment from flask_cors import CORS +from flask_mail import Mail db = SQLAlchemy() @@ -11,6 +12,7 @@ migrate = Migrate() login = LoginManager() environment = Environment() cors = CORS() +mail = Mail() def create_app(): app = Flask(__name__) @@ -22,6 +24,7 @@ def create_app(): login.init_app(app) environment.init_app(app) cors.init_app(app) + mail.init_app(app) scss = Bundle('css/style.scss', filters='scss', output='css/style.css') @@ -38,3 +41,5 @@ def create_app(): app.register_blueprint(admin.bp) return app + + diff --git a/goathacks/admin/__init__.py b/goathacks/admin/__init__.py index 89f035f..58dafea 100644 --- a/goathacks/admin/__init__.py +++ b/goathacks/admin/__init__.py @@ -1,11 +1,12 @@ -from flask import Blueprint, jsonify, redirect, render_template, 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 from goathacks.models import User bp = Blueprint("admin", __name__, url_prefix="/admin") -from goathacks import db +from goathacks import db,mail @bp.route("/") @login_required @@ -53,6 +54,45 @@ def home(): female_count=female_count, nb_count=nb_count, check_in_count=check_in_count, schools=schools) +@bp.route("/mail") +@login_required +def mail(): + if not current_user.is_admin: + return redirect(url_for("dashboard.home")) + + total_count = len(db.session.execute(db.select(User)).scalars().all()) + + return render_template("mail.html", NUM_HACKERS=total_count) + +@bp.route("/send", methods=["POST"]) +@login_required +def send(): + if not current_user.is_admin: + return {"status": "error"} + + json = request.json + + users = User.query.all() + + to = [] + if json["recipients"] == "org": + to = ["hack@wpi.edu"] + elif json['recipients'] == 'admin': + to = ["acm-sysadmin@wpi.edu"] + elif json['recipients'] == "all": + to = [x['email'] for x in users] + + with mail.connect() as conn: + for e in to: + msg = Message(json['subject']) + msg.add_recipient(e) + msg.html = json['html'] + msg.body = json['text'] + + conn.send(msg) + + return {"status": "success"} + @bp.route("/check_in/") @login_required def check_in(id): @@ -79,6 +119,11 @@ def drop(id): if user.checked_in: return {"status": "error", "msg": "Hacker is already checked in"} + msg = Message("Application Dropped") + msg.add_recipient(user.email) + msg.sender = ("GoatHacks Team", "hack@wpi.edu") + msg.body = render_template("emails/dropped.txt", user=user) + db.session.delete(user) db.session.commit() @@ -122,6 +167,11 @@ def promote_waitlist(id): user.waitlisted = False db.session.commit() + msg = Message("Waitlist Promotion") + msg.add_recipient(user.email) + msg.sender = ("GoatHacks Team", "hack@wpi.edu") + msg.body = render_template("emails/waitlist_promotion.txt", user=user) + return {"status": "success"} @bp.route("/hackers.csv") diff --git a/goathacks/registration/__init__.py b/goathacks/registration/__init__.py index 3ddd699..3a9833d 100644 --- a/goathacks/registration/__init__.py +++ b/goathacks/registration/__init__.py @@ -1,5 +1,5 @@ from datetime import datetime -from flask import Blueprint, flash, redirect, render_template, request, url_for +from flask import Blueprint, config, current_app, flash, redirect, render_template, request, url_for import flask_login from flask_login import current_user from goathacks.registration.forms import LoginForm, RegisterForm @@ -14,8 +14,10 @@ bp = Blueprint('registration', __name__, url_prefix="/registration") def register(): if current_user.is_authenticated: flash("You are already registered and logged in!") + print("got register") form = RegisterForm(request.form) + print(vars(form.gender)) if request.method == 'POST': print("Got form") email = request.form.get('email') @@ -23,22 +25,32 @@ def register(): last_name = request.form.get('last_name') password = request.form.get('password') password_c = request.form.get('password_confirm') + school = request.form.get('school') + phone = request.form.get('phone_number') + gender = request.form.get('gender') if password == password_c: # Passwords match! + + # Count of all non-waitlisted hackers + num_not_waitlisted = len(User.query.filter_by(waitlisted=False).all()) + waitlisted = False + print(num_not_waitlisted) + print(current_app.config['MAX_BEFORE_WAITLIST']) + if num_not_waitlisted >= current_app.config['MAX_BEFORE_WAITLIST']: + waitlisted = True user = User( email=email, password=generate_password_hash(password), first_name=first_name, last_name=last_name, last_login=datetime.now(), + waitlisted=waitlisted, + school=school, + phone=phone, + gender=gender ) - - # Count of all non-waitlisted hackers - # num_not_waitlisted = len(db.session.execute(db.select(User).filter(waitlisted=False)).scalars().all()) - # print(num_not_waitlisted) - db.session.add(user) db.session.commit() flask_login.login_user(user) @@ -48,3 +60,7 @@ def register(): flash("Passwords do not match") return render_template("register.html", form=form) + +@bp.route("/login", methods=["GET", "POST"]) +def login(): + return "OK" diff --git a/goathacks/registration/forms.py b/goathacks/registration/forms.py index 08f7fd1..3fe74c5 100644 --- a/goathacks/registration/forms.py +++ b/goathacks/registration/forms.py @@ -1,5 +1,5 @@ from flask_wtf import FlaskForm -from wtforms import BooleanField, PasswordField, StringField, SubmitField +from wtforms import BooleanField, PasswordField, SelectField, StringField, SubmitField, widgets from wtforms.validators import DataRequired class RegisterForm(FlaskForm): @@ -10,6 +10,11 @@ class RegisterForm(FlaskForm): password = PasswordField("Password", validators=[DataRequired()]) password_confirm = PasswordField("Confirm Password", validators=[DataRequired()]) + school = StringField("School/University", validators=[DataRequired()]) + phone_number = StringField("Phone number", validators=[DataRequired()]) + gender = SelectField("Gender", choices=[("F", "Female"), ("M", "Male"), + ("NB", "Non-binary/Other")], + widget=widgets.Select()) agree_coc = BooleanField("I confirm that I have read and agree to the Code of Conduct", validators=[DataRequired()]) submit = SubmitField("Register") diff --git a/goathacks/static/css/style.css b/goathacks/static/css/style.css index 7383868..68108c1 100644 --- a/goathacks/static/css/style.css +++ b/goathacks/static/css/style.css @@ -150,8 +150,20 @@ 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; +} diff --git a/goathacks/static/css/style.scss b/goathacks/static/css/style.scss index 1b8da94..92088ee 100644 --- a/goathacks/static/css/style.scss +++ b/goathacks/static/css/style.scss @@ -1,6 +1,6 @@ $color-bg: #003049; $color-fg: #eee; -$color-section-bg: #F5665B; +$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"); } @@ -148,9 +148,19 @@ form { 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; + } } diff --git a/goathacks/static/img/favicon.png b/goathacks/static/img/favicon.png new file mode 100644 index 0000000..39a081f Binary files /dev/null and b/goathacks/static/img/favicon.png differ diff --git a/goathacks/templates/dashboard.html b/goathacks/templates/dashboard.html index 546fbf7..859f3f0 100644 --- a/goathacks/templates/dashboard.html +++ b/goathacks/templates/dashboard.html @@ -1,46 +1,10 @@ {% include 'header.html' %} - - \ No newline at end of file + diff --git a/goathacks/templates/register.html b/goathacks/templates/register.html index 25949ad..e3e45f1 100644 --- a/goathacks/templates/register.html +++ b/goathacks/templates/register.html @@ -29,6 +29,18 @@
{{form.last_name}}
{{form.last_name.label}}
+
+

Miscellaneous Information

+
+ {{form.phone_number}}
{{form.phone_number.label}} +
+
+ {{form.school}}
{{form.school.label}} +
+
+ {{form.gender.label}}{{form.gender}} +
+
diff --git a/requirements.txt b/requirements.txt index 1ccc43f..a1a0a95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ click==8.1.3 Flask==2.2.2 Flask-Assets Flask-CORS +Flask-Mail Flask-Login==0.6.2 Flask-Migrate==4.0.0 Flask-SQLAlchemy==3.0.2