Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
191 commits
Select commit Hold shift + click to select a range
2fc1db6
format results page
azrosen92 Nov 18, 2014
2b3a33a
fixed search function
denisefrancisco Nov 21, 2014
fd3644c
fixed search all the way
azrosen92 Nov 27, 2014
ce6fab0
fix search on search results page
azrosen92 Nov 28, 2014
3397a03
clean up search results page header
azrosen92 Nov 28, 2014
60123e3
change time field on create page to datetime type
azrosen92 Nov 29, 2014
2a5a1f4
fix search to be not case sensitive
azrosen92 Nov 29, 2014
1a0a72d
add wsgi and runserver to gitignore
Nov 29, 2014
0c0e9a9
untrack wsgi and runserver
azrosen92 Nov 29, 2014
f0a1ffc
stuff
Nov 29, 2014
0185b01
fix merge conflicts
Nov 29, 2014
e7602e7
add favicon
azrosen92 Nov 29, 2014
8e94008
change names in footer, remove i'm feeling lucky button
azrosen92 Nov 29, 2014
95a803a
updated from old repo
Nov 30, 2014
08dae14
change study buddy to succor, add names
azrosen92 Dec 2, 2014
5e23f69
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Dec 2, 2014
2a9a862
we have user accounts
azrosen92 Dec 3, 2014
c1ab11c
stuff for denise
azrosen92 Dec 5, 2014
7ea29c9
changes with date and time picker
denisefrancisco Dec 5, 2014
fbeed8a
change to date and time picker
denisefrancisco Dec 5, 2014
7b7ce08
123
denisefrancisco Dec 5, 2014
f4d185b
adding group route
azrosen92 Dec 5, 2014
0f263d5
123
denisefrancisco Dec 5, 2014
e5c21aa
implementation of date time picker
denisefrancisco Dec 5, 2014
43440d6
individual group page
azrosen92 Dec 5, 2014
b3f5045
fix merge conflict
azrosen92 Dec 5, 2014
4ffc0f7
added drop down back
azrosen92 Dec 5, 2014
9f0599a
fixed interface of date time picker
denisefrancisco Dec 5, 2014
96d8537
hello
denisefrancisco Dec 5, 2014
6575d35
remove names from pages besides index
azrosen92 Dec 5, 2014
cfffb6a
datetime works
Dec 5, 2014
458ef34
merged
Dec 5, 2014
6577f23
styles
azrosen92 Dec 5, 2014
d6a15fc
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Dec 5, 2014
3c4cca8
use wtforms for create form
azrosen92 Dec 5, 2014
160c7f5
remove lesscss
azrosen92 Dec 5, 2014
3ad1981
small fix
azrosen92 Dec 5, 2014
1dc421f
disable user accounts for now
azrosen92 Dec 5, 2014
4c0e6f3
change design
azrosen92 Dec 6, 2014
bc840df
changes to group page
azrosen92 Dec 6, 2014
8c23fbf
small style adjustment to group page
azrosen92 Dec 7, 2014
a92c891
store department names in lowercase to assist with search
azrosen92 Dec 7, 2014
339f4f2
small UX change - search button changes to search all when input is e…
azrosen92 Dec 7, 2014
e0e5dd1
validate .edu email
azrosen92 Dec 7, 2014
1364dbb
add google analytics
azrosen92 Dec 7, 2014
4066585
add thumbnail
azrosen92 Dec 7, 2014
f073347
fix thumbnail
azrosen92 Dec 7, 2014
b76674c
add feedback email
azrosen92 Dec 7, 2014
085f312
fix background color for legacy browsers
azrosen92 Dec 7, 2014
57f4ee0
change location field to where so no autofill
azrosen92 Dec 7, 2014
1888e8b
validate for 3 digit course number, including those below 100
azrosen92 Dec 8, 2014
2c82f6c
change search results to have upcoming and old results separately
azrosen92 Dec 8, 2014
fd17bee
clean up
azrosen92 Dec 8, 2014
7e305e4
clean up some css and center elements on home page
azrosen92 Dec 8, 2014
66a5a0c
add 404 page
azrosen92 Dec 8, 2014
4262346
click pointer now
Dec 8, 2014
b2d802f
fix hover effect on search results page:
azrosen92 Dec 9, 2014
067a60f
About page changed
aditya-gupta3 Dec 9, 2014
af7d1c5
begin working on login
azrosen92 Dec 9, 2014
faae6ef
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Dec 9, 2014
7b94da4
small fix to about page
azrosen92 Dec 9, 2014
c56185a
style about page
azrosen92 Dec 9, 2014
370c0e2
fixing about page
azrosen92 Dec 9, 2014
90a0bb0
start on user profile page
azrosen92 Dec 9, 2014
f7474b3
working on profile page
azrosen92 Dec 10, 2014
5598dec
SEO
denisefrancisco Dec 11, 2014
bf67d17
SEO
denisefrancisco Dec 11, 2014
80e9800
some clean up
azrosen92 Dec 16, 2014
b5ba81f
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Dec 16, 2014
6c83418
fix margin on home page
azrosen92 Dec 16, 2014
957b273
initial about page
azrosen92 Dec 16, 2014
9ed7935
update path to people bios
azrosen92 Dec 16, 2014
76667a4
made an all nighter button
Dec 17, 2014
0ebc5c0
live validation
Dec 18, 2014
d7ad521
working on flip animation for about page
azrosen92 Dec 21, 2014
90c8453
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Dec 21, 2014
d0eaedf
account verification via email
azrosen92 Jan 2, 2015
0259a3f
password recovery/reset
azrosen92 Jan 2, 2015
37aa2fd
can edit class list on user profile sort of
azrosen92 Jan 4, 2015
b94d2f2
recover password
azrosen92 Jan 4, 2015
8160c04
finished class adding and removing
azrosen92 Jan 5, 2015
189d350
figuring out what's going on
azrosen92 Jan 5, 2015
3c01d01
fix javascript thing on nav bar
azrosen92 Jan 5, 2015
84ce924
add styles to user dropdown menu
azrosen92 Jan 7, 2015
82cf70e
small style changes to user page
azrosen92 Jan 7, 2015
2f6fb31
new favicon
azrosen92 Jan 7, 2015
0e3fd64
touch up user profile page
azrosen92 Jan 7, 2015
124b798
touch up user edit page
azrosen92 Jan 7, 2015
c269cec
fix capitalization bugs
azrosen92 Jan 7, 2015
ad56b19
fix merge conflict
azrosen92 Jan 7, 2015
77455b2
small css changes
azrosen92 Jan 7, 2015
ca22ba5
fix login and register cards
azrosen92 Jan 8, 2015
a9ba3ae
implement search by school or location if user is not logged in
azrosen92 Jan 8, 2015
02fa900
small changes for mobile optimization
azrosen92 Jan 10, 2015
fac2f81
finish about page
azrosen92 Jan 23, 2015
7861584
add denise picture
azrosen92 Jan 24, 2015
14345a0
add field to user schema for hora
azrosen92 Jan 24, 2015
bf7fa90
get rid of location based search for now
azrosen92 Jan 24, 2015
5f7d6a7
Remove geolocation functionality from group create
azrosen92 Jan 26, 2015
0f2218f
Slangs
aditya-gupta3 Jan 26, 2015
f430ad6
move configurations into external file
azrosen92 Jan 28, 2015
a9aac88
move database configurations into config file
azrosen92 Jan 28, 2015
31cbf3f
add local config file
azrosen92 Jan 28, 2015
57780b4
remove local config file, need to untrack it
azrosen92 Jan 28, 2015
76019bb
update gitignore to not track local config
azrosen92 Jan 28, 2015
7bf9373
Merge branch 'master' of github.com:succor-app/study_buddy
azrosen92 Jan 28, 2015
751b247
fix dev gitignore file
Jan 28, 2015
e30de17
Merge branch 'master' of https://github.com/succor-app/study_buddy
Jan 28, 2015
87c653e
switch order of config files
azrosen92 Jan 28, 2015
73eaf4c
move some other stuff into init_db file, to resolve dependency issues
azrosen92 Jan 28, 2015
810d870
remove geolocation functionality
azrosen92 Jan 28, 2015
ce2d493
add school field to create form for users not logged in
azrosen92 Jan 28, 2015
e50a6c6
remove location field from mongo query in search
azrosen92 Jan 28, 2015
6d71d25
stuff
Jan 28, 2015
c5aead6
Merge branch 'master' of https://github.com/succor-app/study_buddy
Jan 28, 2015
ab03dec
accessing db based on local config
azrosen92 Jan 28, 2015
1981f25
remove location index from db
azrosen92 Jan 28, 2015
0cc5742
add some print statements to email sender
azrosen92 Jan 28, 2015
6069d87
fix merge conflicts
Jan 28, 2015
5fb81b1
move local config out of environment variable
azrosen92 Jan 28, 2015
f1e43fb
Merge branch 'master' of https://github.com/succor-app/study_buddy
Jan 28, 2015
8cef07c
logs for home route
azrosen92 Jan 31, 2015
aa31f22
fix bug maybe
azrosen92 Jan 31, 2015
2cfa4ac
blah
azrosen92 Jan 31, 2015
cf4e9b3
fixing things
azrosen92 Jan 31, 2015
4a10c7d
change validation of create form to allow no contact info for non-log…
azrosen92 Feb 1, 2015
648e444
add full name field to user model
azrosen92 Feb 1, 2015
d864f65
allow user to add him/herself to group project if logged in
azrosen92 Feb 1, 2015
f3ab667
fix login link in top bar
azrosen92 Feb 1, 2015
2fd204d
fix bug on user profile page
azrosen92 Feb 1, 2015
02919b2
show user email if no name present on list of group participants
azrosen92 Feb 1, 2015
0d478ed
make group info card wider to fit list of participants
azrosen92 Feb 1, 2015
a8d8bae
change list of participants to list of reference to participants
azrosen92 Feb 1, 2015
cfbc243
set secret key
azrosen92 Feb 1, 2015
a949a93
add log statements to register
azrosen92 Feb 1, 2015
5a2e664
fix csrf token issue hopefully
azrosen92 Feb 1, 2015
bb90885
remove unused csrf token function
azrosen92 Feb 1, 2015
ab908a9
fix create page bug
azrosen92 Feb 2, 2015
4b29d64
add csrf token to join group button
azrosen92 Feb 2, 2015
bf455a8
add csrf error page
azrosen92 Feb 2, 2015
2c29f5f
add csrf error template
azrosen92 Feb 2, 2015
04d9463
roll out custom csrf protection
azrosen92 Feb 2, 2015
079eb6d
add logging for csrf bug
azrosen92 Feb 2, 2015
39a32a5
add more loggin
azrosen92 Feb 2, 2015
a9d8766
move secret key to local config file
azrosen92 Feb 2, 2015
17b3f73
set up amazon ses email sending
azrosen92 Feb 3, 2015
9498578
plug password reset into amazon ses emailing
azrosen92 Feb 3, 2015
bf6d7a1
remove link to github
azrosen92 Feb 3, 2015
441f4c8
finish integrating smart search, and some clean up
azrosen92 Feb 4, 2015
717067b
fix update script
azrosen92 Feb 4, 2015
3f1ec1c
include all updaters
azrosen92 Feb 4, 2015
cf81bf1
small fixes to search
azrosen92 Feb 4, 2015
99af39f
user prompt in edit page
azrosen92 Feb 4, 2015
d4b28ff
fix bug that was not letting user remove class from classes list if i…
azrosen92 Feb 4, 2015
5c5b745
remove those silly curved corners from the card ui
azrosen92 Feb 4, 2015
c5c9a18
remove csrf_error page, not needed anymore
azrosen92 Feb 5, 2015
f085620
start to implement logging
azrosen92 Feb 5, 2015
d596a1e
add heart svg to _svg file
azrosen92 Feb 5, 2015
46994e0
remove leftover print statements from debugging
azrosen92 Feb 5, 2015
47ba157
removed all nighter from main branch
Feb 7, 2015
6e22c6c
removed html tags from input
Feb 9, 2015
09d64d7
remove some unneeded documentation
azrosen92 Feb 9, 2015
72b5435
ignore log files
azrosen92 Feb 9, 2015
77387ea
remove old favicon, ignore DS_Store files, add logo to home page
azrosen92 Feb 9, 2015
bdc5e71
fix merge conflict
azrosen92 Feb 9, 2015
e621375
fix styling of password reset form
azrosen92 Feb 9, 2015
a497bc6
fix small bug with user edit input stripping
azrosen92 Feb 9, 2015
a3a3d23
allow user to resend verification link if it expires
azrosen92 Feb 10, 2015
1ef80f0
removed all nighter
Feb 10, 2015
963b24f
Merge branch 'master' of https://github.com/succor-app/study_buddy
Feb 10, 2015
0829b22
added a way for user to resend verification email
azrosen92 Feb 10, 2015
ae5bd63
Merge branch 'master' of https://github.com/succor-app/study_buddy
azrosen92 Feb 10, 2015
4a9784a
remove all-nighters button on index page
azrosen92 Feb 10, 2015
30800d4
put logo on about page
azrosen92 Feb 10, 2015
9a80a12
fix merge conflicts
azrosen92 Feb 10, 2015
2a95980
send user to public use rpage after editing user page
azrosen92 Feb 10, 2015
1412c01
redirect user to page they were trying to go to after logging in
azrosen92 Feb 10, 2015
869e5d3
Merge branch 'master' of https://github.com/succor-app/study_buddy
azrosen92 Feb 10, 2015
8e8a0e3
fix login bug
azrosen92 Feb 11, 2015
32cfc47
really fix login bug and merge conflicts
azrosen92 Feb 11, 2015
f5c45e4
make user verification emails look pretty
azrosen92 Feb 11, 2015
6e7256f
make password recovery email pretty
azrosen92 Feb 11, 2015
7179cee
UI Touch ups on password reset with token page
azrosen92 Feb 11, 2015
90da769
ignore secret key files
azrosen92 Feb 11, 2015
e98faed
UX change on user profile page
azrosen92 Feb 13, 2015
3a0915e
vassar update script
azrosen92 Feb 15, 2015
a9bac44
add logging to create form
azrosen92 Feb 15, 2015
7846762
fix merge conflicts
azrosen92 Feb 15, 2015
1d6d678
fix bugs
azrosen92 Feb 15, 2015
6a8fb6a
change logs to go to stdout
azrosen92 Feb 15, 2015
d3e0657
log to stderr
azrosen92 Feb 15, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
14 changes: 12 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.DS_Store

scripts/

# The local config file should be specific to the machine running the app.
local_config.py
*.pyc
# The settings.cfg file should be specific to the machine running the app.
settings.cfg

app.wsgi
runserver.py

*.log
application.log
3 changes: 2 additions & 1 deletion departmentArray.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def combineShortAndLong(depts_list):
for dept in depts_list:
short_name = dept[0]
long_name = dept[1]
combined_list.append(short_name + "-" + long_name)
combined_list.append(short_name.lower() + "-" + long_name.lower())
print combined_list
return combined_list

##
Expand Down
2 changes: 1 addition & 1 deletion runserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@

from study_buddy import app
print "Starting server..."
app.run(debug=True)
app.run(debug=True)
100 changes: 44 additions & 56 deletions study_buddy/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,72 +1,60 @@
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore
from flask.ext.social import Social, SQLAlchemyConnectionDatastore, \
login_failed
from mongokit import *
from models import *
from flask import Flask, render_template, request, session, abort

app = Flask(__name__)
# from flask.ext.wtf.csrf import CsrfProtect
from flask.ext.assets import Environment, Bundle
from flask.ext.mail import Mail, Message

# TODO: move all configs into external file.
app.config['SOCIAL_FACEBOOK'] = {
'consumer_key': '804807199563793',
'consumer_secret': 'e7d68bbbd3b828743dc3d6fff7cc9406'
}
from itsdangerous import URLSafeTimedSerializer
from inflection import titleize

app.config['SOCIAL_GOOGLE'] = {
'consumer_key': '967982158206-146hbl8954b0oa45e71ii9efuuaj4fj0.apps.googleusercontent.com',
'consumer_secret': 'JFYgnNsq8FR6qfjSC-uDHFEl'
}
import os, binascii, logging, sys

app.config['SECURITY_POST_LOGIN'] = '/profile'
logging.basicConfig(level=logging.DEBUG,
streamHandler=sys.stderr,
format='[%(levelname)s] <%(asctime)s> %(message)s')

##
# STAGE FOR DELETE
#################################################
app.config.update(
SECRET_KEY='Tieng3us3Xie5meiyae6iKKHVUIUDF',
GOOGLE_LOGIN_CLIENT_ID='1002179078501-mdq5hvm940d0hbuhqltr0o1qhsr7sduc.apps.googleusercontent.com',
GOOGLE_LOGIN_CLIENT_SECRET='O1kpQ8Is9s2pD3eOpxRfh-7x',
GOOGLE_LOGIN_REDIRECT_URI='http://127.0.0.1:5000/oauth2callback',
)
#################################################
app = Flask(__name__)

db = SQLAlchemy(app)
app.config.from_object('study_buddy.base_config')
app.config.from_object('study_buddy.local_config')

connection = Connection()
connection.register([StudySession])
mongo_db = connection.succor
APP_ROOT = os.path.dirname(os.path.abspath(__file__))

print "Running app..."
def output_time(result):
format = "%a, %-d at %-I:%M %p"
return result.strftime(format)

from . import views, models
def generate_csrf_token():
if '_csrf_token' not in session:
session['_csrf_token'] = binascii.hexlify(os.urandom(24))
return session['_csrf_token']

# security_ds = SQLAlchemyUserDatastore(db, models.User, models.Role)
# social_ds = SQLAlchemyConnectionDatastore(db, models.Connection)
# assets = Environment(app)
# scss = Bundle('', filters='pyscss', output='all.css')
# assets.register('scss_all', scss)

# app.security = Security(app, security_ds)
# app.social = Social(app, social_ds)
# csrf = CsrfProtect()
# csrf.init_app(app)

# class SocialLoginError(Exception):
# def __init__(self, provider):
# self.provider = provider
ts = URLSafeTimedSerializer(app.config["SECRET_KEY"])

mail = Mail(app)

print "Running app..."
app.jinja_env.globals.update(output_time=output_time)
app.jinja_env.globals.update(titleize=titleize)
app.jinja_env.globals['csrf_token'] = generate_csrf_token

# @app.before_first_request
# def before_first_request():
# try:
# models.db.create_all()
# except Exception, e:
# app.logger.error(str(e))
from study_buddy import views, models

# @login_failed.connect_via(app)
# def on_login_failed(sender, provider, oauth_response):
# app.logger.debug('Social Login Failed via %s; '
# '&oauth_response=%s' % (provider.name, oauth_response))
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404

# # Save the oauth response in the session so we can make the connection
# # later after the user possibly registers
# session['failed_login_connection'] = \
# get_connection_values_from_oauth_response(provider, oauth_response)
@app.before_request
def csrf_protect():
if request.method == "POST":
token = session.pop('_csrf_token', None)
if not token or token != request.form.get('_csrf_token'):
abort(403)

# raise SocialLoginError(provider)
1 change: 1 addition & 0 deletions study_buddy/backup/department_names.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{department_name:"Computer Science",school:"Wesleyan University",names:"[comp, compsci, computer]"}
4 changes: 4 additions & 0 deletions study_buddy/backup/slangscommand
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#mongoimport --db succor --collection slangs --type json --file backup/department_names.json --jsonArray
#Copy paste this command after running mongod on the terminal and adding to the
# file department_names located in backup folder. MAKE SURE TO COPY THE FORMAT or else
# it won't import
10 changes: 10 additions & 0 deletions study_buddy/base_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SECURITY_POST_LOGIN = '/profile'

MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USE_SSL = False
ADMINS = ['succorapp@gmail.com']

DB_HOST = 'localhost'
DB_PORT = 27017
132 changes: 99 additions & 33 deletions study_buddy/forms.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,101 @@
from flask import current_app
from flask.ext.wtf import Form
from wtforms import TextField, PasswordField, ValidationError
from wtforms.validators import Required, Email, Length, Regexp, EqualTo

class UniqueUser(object):
def __init__(self, message="User exists"):
self.message = message

def __call__(self, form, field):
if current_app.security.datastore.find_user(email=field.data):
raise ValidationError(self.message)


validators = {
'email': [
Required(),
Email(),
UniqueUser(message='Email address is associated with '
'an existing account')
],
'password': [
Required(),
Length(min=6, max=50),
EqualTo('confirm', message='Passwords must match'),
Regexp(r'[A-Za-z0-9@#$%^&+=]',
message='Password contains invalid characters')
]
}


class RegisterForm(Form):
email = TextField('Email', validators['email'])
password = PasswordField('Password', validators['password'], )
from wtforms import TextField, PasswordField, ValidationError, BooleanField, IntegerField, DateTimeField, HiddenField, validators
from init_db import mongo_db
from werkzeug.security import check_password_hash
import re

class EmailForm(Form):
email = TextField('Email', validators = [validators.Email(), validators.Required()])

def validate_email(self, field):
if self.get_user() is None:
raise validators.ValidationError('There is no account with this email')

def get_user(self):
return mongo_db.users.User.find_one({'email' : self.email.data})


class PasswordForm(Form):
password = PasswordField('New Password', validators = [validators.Required()])

class GroupForm(Form):
email = TextField('Contact')
department = TextField('Department', [
validators.Required()
])
course_no = IntegerField('Course Number', [
validators.Required(),
])
datetime = DateTimeField('Date and time', format="%Y/%m/%d %H:%M")
where = TextField('Where', [
validators.Required()
])
assignment = TextField('Assignment', [
validators.Required()
])

school = TextField('School')
details = TextField('Details')
geo_location = HiddenField()
#all_nighter=BooleanField('All nighter')

def validate_course_no(self, field):
if not self.course_no.data < 1000 or len(str(self.course_no.data)) != 3:
raise validators.ValidationError('Please enter a 3 digit course number')

def validate_email(self, field):
if self.email.data and '.edu' not in self.email.data:
raise validators.ValidationError('Please use a .edu email')

class EditUserForm(Form):
first_name = TextField('First Name', [
#validators.Regexp(r'^[A-Za-z0-9.]+$', message= u'That\'s not a valid first name'),
validators.Required()
])
last_name = TextField('Last Name', [
validators.Required()
])
course = TextField('Class')


class LoginForm(Form):
email = TextField('Email', [
validators.Required()
])

password = PasswordField('Password')

remember = BooleanField('Remember me')

def validate_password(self, field):
user = self.get_user()

if user is None:
raise validators.ValidationError('Email does not exist')

if not check_password_hash(user.password, self.password.data):
raise validators.ValidationError('Invalid password')

def get_user(self):
return mongo_db.users.User.find_one({'email' : self.email.data})


class RegistrationForm(Form):
email = TextField('Email', [
validators.Required(),
validators.length(min=6, max=50),
validators.Email()
])

def validate_email(self, field):
if '.edu' not in self.email.data:
raise validators.ValidationError('Please use a .edu email')

if mongo_db.users.User.find({'email' : self.email.data}).count() > 0:
raise validators.ValidationError('Account with that email already exists')

password = PasswordField('Password', [
validators.Required(),
validators.EqualTo('confirm', message='Passwords must match')
])
confirm = PasswordField('Confirm Password')
Loading