Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI improvement: Upload success/error messages #72

Merged
merged 12 commits into from
Jun 11, 2020
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ The developers of SyllabiShare do not pretend to be perfect and recognize that f
- Language & Framework: **Python, Django**
- Webapp Hosting: **Heroku**,
- Files Storage: **AWS S3** Bucket (Northern Virginia)
- User Auethnication: **Google OAuth**
- User Authenication: **Google OAuth**

These service providers will eventually cost money, which is why we humbly ask for your financial support.
Please support us by clicking `Donate link` at the bottom of the screen if you are able to.
Expand Down
Binary file added project/static/sarahmeng.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions project/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,18 @@ footer {
margin-bottom: 2%;
border: 1px solid black;
}

.success, .warning {
display: inline-block;
color: white;
}

.success {
border-color: #43a546;
background-color: #43a546;
}

.warning {
border-color: #d33840;
background-color: #d33840;
}
19 changes: 14 additions & 5 deletions syllabiShare/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.conf import settings
from django.contrib.auth.models import User
from django.core.mail import send_mass_mail
from django.contrib import messages


def about(request):
Expand Down Expand Up @@ -167,12 +168,14 @@ def suggest(request):
return render(request, 'suggest.html', {'suggestion':Suggestion.objects.all()})


# TODO: guard against refreshing if it resends a POST request
def upload(request):
(template, context) = authenticate(request.user)
if template:
return render(request, template, context)
success = False
message = 'Misuse of uploads will be met by a ban!'
# success = False
# message = 'Misuse of uploads will be met by a ban!'
# above message is now hardcoded into upload.html and stays there permanently
if request.method == 'POST':
prof = request.POST['prof'].strip().split()
goodProf = len(prof) == 2 and all(char.isalpha() or char == '-' or char == '\'' for char in prof[0]) and all(char.isalpha() or char == '-' or char == '\'' for char in prof[1])
Expand All @@ -191,10 +194,16 @@ def upload(request):
entry.syllabus = request.FILES['file']
entry.syllabus.name = '_'.join([prof[0].lower(), prof[1].lower(), entry.dept.lower(), entry.number, entry.semester, entry.year]) + '.pdf'
entry.save()
success = True
# success = True
messages.success(request, 'Syllabus successfully added. Thank you!')
# if we want to keep users on this page, then maybe we could add
# a courtesy link directly to the department page that has the
# newly-uploaded syllabus
else:
message = 'Professor name not valid! Try "FirstName LastName" Format'
return render(request, 'upload.html', {'success': success, 'message': message})
# message = 'Professor name not valid! Try "FirstName LastName" Format'
messages.error(request, 'Please enter the professor\'s name as "FirstName LastName"')
# return render(request, 'upload.html', {'success': success, 'message': message})
return render(request, 'upload.html')


def view404(request, exception=None):
Expand Down
116 changes: 85 additions & 31 deletions templates/about.html
Original file line number Diff line number Diff line change
@@ -1,80 +1,134 @@
{% load static %}
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Syllabi Share </title>
<link rel="shortcut icon" href="{% static 'favicon.ico' %}">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
<meta charset="utf-8" />
<title>Syllabi Share</title>
<link rel="shortcut icon" href="{% static 'favicon.ico' %}" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="background-image: url({% static 'back.png' %}); background-size: cover;" class="d-flex flex-column align-items-center vh-100">
<body style="background-image: url({%static 'back.png'%}); background-size: cover;" class="d-flex flex-column align-items-center vh-100">
<nav class="navbar navbar-expand-md bg-dark navbar-dark w-100">
<a class="navbar-brand" href="/">SyllabiShare</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto d-flex align-items-md-center">
{% if user.is_authenticated %}
<li class="nav-item">
{# mt-3, mt-md-0: provide a top margin when we're collapsed but not when expanded #}
<form action="/search/" method="POST" class="form-inline mt-2 mt-md-0 ml-md-2 mr-md-5">
{% csrf_token %} {# d-inline-block & w-auto force the form to be inline at all sizes, since we only have two elements #}
<input class="form-control form-control-sm mr-2 d-inline-block w-auto" id="search" type="search" name="search" placeholder="Search" />
<input class="btn btn-sm btn-outline-success" id="button" type="submit" value="Search" />
</form>
</li>
<li class="nav-item">
<a class="nav-link" href="/upload">upload</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/suggest">feedback</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about">about</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbardrop" data-toggle="dropdown">
{{user.username}}
</a>
<div class="dropdown-menu dropdown-menu-right" style="min-width: 0;">
<a class="dropdown-item" href="/settings">Settings</a>
<a class="dropdown-item" href="{% url 'logout' %}">Logout</a>
</div>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="/login/google-oauth2/">Login!</a>
</li>
{% endif %}
</ul>
</div>
</nav>
<div class="container my-3 flex-fill">
<h1 class="mb-3 text-center">About SyllabiShare</h1>
<h2>What is SyllabiShare for?</h2>
<p>
SyllabiShare was developed as an open-source project to empower students to crowdsource a public repository of course syllabi that are essential to make informed course selections and to understand course policies.
To find out information about a course, you would usually go to a friend or RateMyProfessor, but if you didn't know anyone who took the class before and there are no online reviews for the class you would need to email the professor for a syllabus and hope they respond... yeah right good luck with that.
With this tool users will be able to upload, search, and download syllabi for students at their university to use.
It is ludicrous that students can pay tens of thousands of dollars to their university and not have access to such materials already.
Fortunately, some schools have a Syllabus repository like this already, but not nearly enough schools do it.
All of these are reasons why we made this tool and made it open-source for students of any university to adopt and improve.
If you can get your university to sponsor your fork of the app please do let us know and we'll redirect to yours.
Please feel free to add to the codebase or join the team if you feel inclined to help the effort.
SyllabiShare was developed as an open-source project to empower students to crowdsource a public repository of course syllabi that are essential to make informed course selections and to understand course policies. To find out
information about a course, you would usually go to a friend or RateMyProfessor, but if you didn't know anyone who took the class before and there are no online reviews for the class you would need to email the professor for a
syllabus and hope they respond... yeah right good luck with that. With this tool users will be able to upload, search, and download syllabi for students at their university to use. It is ludicrous that students can pay tens of
thousands of dollars to their university and not have access to such materials already. Fortunately, some schools have a Syllabus repository like this already, but not nearly enough schools do it. All of these are reasons why we
made this tool and made it open-source for students of any university to adopt and improve. If you can get your university to sponsor your fork of the app please do let us know and we'll redirect to yours. Please feel free to add to
the codebase or join the team if you feel inclined to help the effort.
</p>
<h2>The Team</h2>
<div class="row row-cols-md-2 row-cols-lg-3">
<div class="col my-2 text-center profile">
<img src="{% static 'vernon.jpg' %}" class="rounded-circle mb-2">
<h3><a class="text-body" href='https://www.linkedin.com/in/SyllabiShare'>Vernon Andrade</a></h3>
<img src="{% static 'vernon.jpg' %}" class="rounded-circle mb-2" />
<h3><a class="text-body" href="https://www.linkedin.com/in/SyllabiShare">Vernon Andrade</a></h3>
<h4>UVA CS '21</h4>
<h4>Lead Developer / Admin</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'winston.jpg' %}" class="rounded-circle mb-2">
<h3><a class="text-body" href='https://www.linkedin.com/in/winston-liu'>Winston Liu</a></h3>
<img src="{% static 'winston.jpg' %}" class="rounded-circle mb-2" />
<h3><a class="text-body" href="https://www.linkedin.com/in/winston-liu">Winston Liu</a></h3>
<h4>UVA CS '20</h4>
<h4>Developer</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'unknown.png' %}" class="rounded-circle mb-2">
<h3><a class="text-body" href=''>Madison Flynn</a></h3>
<img src="{% static 'unknown.png' %}" class="rounded-circle mb-2" />
<h3><a class="text-body" href="">Madison Flynn</a></h3>
<h4>UVA CS '21</h4>
<h4>Developer</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'hamster.jpg' %}" class="rounded-circle mb-2">
<img src="{% static 'hamster.jpg' %}" class="rounded-circle mb-2" />
<h3>Robbie B</h3>
<h4>UVA CS '26</h4>
<h4>Hamster Intern</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'hamster.jpg' %}" class="rounded-circle mb-2" style="transform: scaleX(-1);">
<img src="{% static 'hamster.jpg' %}" class="rounded-circle mb-2" style="transform: scaleX(-1);" />
<h3>Peter B</h3>
<h4>CNU '23</h4>
<h4>Hamster Documenter</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'unknown.png' %}" class="rounded-circle mb-2">
<h3><a class="text-body" href=''>You!</a></h3>
<img src="{% static 'sarahmeng.jpg' %}" class="rounded-circle mb-2" />
<h3><a class="text-body" href="https://www.linkedin.com/in/sarahmeng">Sarah Meng</a></h3>
<h4>UVA CS '20</h4>
<h4>Developer</h4>
</div>
<div class="col my-2 text-center profile">
<img src="{% static 'unknown.png' %}" class="rounded-circle mb-2" />
<h3><a class="text-body" href="">You!</a></h3>
<h4>UVA '2?</h4>
<h4>Bug Creator</h4>
</div>
</div>
<h2>Testimonials</h2>
<p>"I think it would benefit our students and potential students if more faculty members participated in this. I know that many student and friend groups keep copies of all syllabi and share them amongst themselves. I think posting them publicly on a site like this helps level the playing field for students who do not belong to those groups. It also seems like this would make my life easier, having students get my syllabi without dealing with all the personal requests through email. I'm glad you are working on this." ~ Prof. Raymond Pettit, UVA Computer Science</p>
<p>
"I think it would benefit our students and potential students if more faculty members participated in this. I know that many student and friend groups keep copies of all syllabi and share them amongst themselves. I think posting
them publicly on a site like this helps level the playing field for students who do not belong to those groups. It also seems like this would make my life easier, having students get my syllabi without dealing with all the personal
requests through email. I'm glad you are working on this." ~ Prof. Raymond Pettit, UVA Computer Science
</p>
<h2>Privacy Policy</h2>
<p>By logging in to this website you are agreeing to the <a href="/privacy" style="color: purple"> privacy policy </a> and certify that you will only use the material for educational purposes</p>
<p>By logging in to this website you are agreeing to the <a href="/privacy" style="color: purple;"> privacy policy </a> and certify that you will only use the material for educational purposes</p>
<h2>Technical Details</h2>
<p>This app was written in Python using the Django Framework and is hosted on Heroku, with files being served through an Amazon Web Services S3 Bucket in Northern Virginia. I will once again ask for your financial support and ask that you click the Donate link at the bottom of the screen if you are in the financial position to. We understand if you can't thought, we're all college students here. The code is on Github <a style="color: purple" href="https://github.com/SyllabiShare/syllabi-share">here</a> or in the bottom right corner of your screen.</p>
<p>
This app was written in Python using the Django Framework and is hosted on Heroku, with files being served through an Amazon Web Services S3 Bucket in Northern Virginia. I will once again ask for your financial support and ask that
you click the Donate link at the bottom of the screen if you are in the financial position to. We understand if you can't thought, we're all college students here. The code is on Github
<a style="color: purple;" href="https://github.com/SyllabiShare/syllabi-share">here</a> or in the bottom right corner of your screen.
</p>
<h2>Suggestions</h2>
<p>If you have suggestions for how to make this app better or any feedback, please click <a href="/suggest">here</a>.</p>
<a href="/"><img class="left" src="{% static 'left.png' %}"></a>
<a href="/"><img class="left" src="{% static 'left.png' %}" /></a>
</div>
<a href="https://github.com/SyllabiShare/syllabi-share"><img class="github" src="{% static 'github.png' %}"></a>
<a href="https://github.com/SyllabiShare/syllabi-share"><img class="github" src="{% static 'github.png' %}" /></a>
</body>
</html>
51 changes: 35 additions & 16 deletions templates/upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
{% load static %}
{% block content %}

{% if messages %}
{% for message in messages %}
<div class="text-center">
{% if message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you stick the following into settings.py, we'll get full messages<->Bootstrap compat and then you can then do something like ...other classes... alert-{{ message.tags }} instead of the if/else casing for the level. (or, since it seems like we aren't using alert-* styling b/c of the background color, just {{ message.tags }})

# at the top of the file
from django.contrib.messages import constants as messages

# wherever you want
MESSAGE_TAGS = {
    messages.ERROR: 'danger'
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, thanks, I'll look into that later! Good to know--I felt like the if/else casing was a bit unwieldy

<div class="alert d-inline-block success" role="alert">
{% else %}
<div class="alert d-inline-block warning" role="alert">
{% endif %}
{{ message }}
</div>
</div>
{% endfor %}
{% endif %}

<h3>Upload Syllabus</h3>
<form id="form-id" action="/upload/" method="post" enctype="multipart/form-data">
{% csrf_token %}
Expand All @@ -14,7 +28,7 @@ <h3>Upload Syllabus</h3>
<label for="dept"><b>Department</b></label>
<input class="form-control" id="dept" type="text" name="dept" placeholder="CS" required>
</div>
<div class="form-group col-md-1">
<div class="form-group col-md-2">
<label for="number"><b>Number</b></label>
<input class="form-control" id="number" type="number" name="number" placeholder="4102" required>
</div>
Expand All @@ -30,9 +44,10 @@ <h3>Upload Syllabus</h3>
<option value="fall">Fall</option>
<option value="spring">Spring</option>
<option value="summer">Summer</option>
<option value="january">January</option>
</select>
</div>
<div class="form-group col-md-1">
<div class="form-group col-md-2">
<label for="year"><b>Year</b></label>
<select class="form-control" name="year" id="year" required>
<option value="2019">2019</option>
Expand All @@ -43,20 +58,22 @@ <h3>Upload Syllabus</h3>
<b>Please be aware of any policies your school may have about the sharing of syllabi.<br> By uploading a syllabus, you certify that you have done this and there is no problem with it.</b>
</div>
</div>
<div class="form-group">
<label for="file"><b>Syllabus (PDFs only)</b></label>
<input class="form-control-file" id="file" type="file" name="file" accept="application/pdf" required>

<div class="form-row">
<div class="form-group col-md-4">
<label for="file"><b>Syllabus (PDFs only)</b></label>
<input class="form-control-file" id="file" type="file" name="file" accept="application/pdf" required>
</div>
<div class="form-group col-md">
<div id="message" class="alert d-inline-block warning" style="display: none !important;" role="alert"> </div>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: since there's nothing in here by default, would it even display anything if you removed the display: none?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, removing that would display a nice red block that houses no text by default

</div>
</div>
<input class="btn btn-success" type="submit" value="Submit">
</form>

<div class="text-center">
{% if success %}
<div id="message" class="alert d-inline-block" style="display: inline-block; color: white; border-color: #43a546; background-color: #43a546;" role="alert"> Addition Successful! </div>
{% else %}
<div id="message" class="alert d-inline-block" style="display: inline-block; color: white; border-color: #d33840; background-color: #d33840;" role="alert"> {{message}} </div>
{% endif %}
</div>
<div id="message-warning" class="alert d-inline-block warning" role="alert">Misuse of uploads will be met by a ban!</div>

<div><input class="btn btn-success" type="submit" value="Submit"></div>

</form>

<a href="/"><img class="left" src="{% static 'left.png' %}"></a>

Expand All @@ -65,12 +82,14 @@ <h3>Upload Syllabus</h3>
$("#file").on('change', function(event) {
var file = event.target.files[0];
if(file.size>=5*1024*1024) {
document.getElementById('message').innerHTML = "Upload PDFs of size less than 1MB please";
document.getElementById('message').innerHTML = "Please upload PDFs smaller than 5 MB.";
document.getElementById('message').style.display = "inline-block";
$("#form-id").get(0).reset();
return;
}
if(!file.type.match('application/pdf.*')) {
document.getElementById('message').innerHTML = "Upload PDFs only please!";
document.getElementById('message').innerHTML = "PDFs only, please!";
document.getElementById('message').style.display = "inline-block";
$("#form-id").get(0).reset();
return;
}
Expand Down