automate study guides

This commit is contained in:
lauren 2021-01-16 00:54:37 -05:00
parent 28dd5563a5
commit 3557f36069
18 changed files with 206 additions and 37 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ venv
.venv
db.sqlite3
media
key.json

View File

@ -10,3 +10,4 @@ django = "*"
social-auth-app-django = "*"
pillow = "~=6.0"
whitenoise = "*"
django-googledrive-storage = "*"

View File

@ -1,8 +1,9 @@
from django.contrib import admin
from .models import Subject, Course, Guide, Tag
from .models import Subject, Course, Guide, Tag, Request
# Register your models here.
admin.site.register(Subject)
admin.site.register(Course)
admin.site.register(Guide)
admin.site.register(Tag)
admin.site.register(Request)

View File

@ -0,0 +1,9 @@
from django import forms
from .models import Request, Course, Tag
class StudyGuideRequestForm(forms.Form):
name = forms.CharField(max_length=100)
course = forms.ModelChoiceField(queryset=Course.objects.all())
tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
guide = forms.FileField()

View File

@ -0,0 +1,28 @@
# Generated by Django 3.0.6 on 2021-01-16 03:49
from django.db import migrations, models
import gdstorage.storage
class Migration(migrations.Migration):
dependencies = [
('courses', '0008_auto_20201104_1557'),
]
operations = [
migrations.AlterModelOptions(
name='tag',
options={'ordering': ['url']},
),
migrations.CreateModel(
name='Request',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=100, unique=True)),
('guide', models.FileField(storage=gdstorage.storage.GoogleDriveStorage(), upload_to='guides')),
('course', models.ManyToManyField(related_name='proposed_course', to='courses.Course')),
('tags', models.ManyToManyField(related_name='proposed_tags', to='courses.Tag')),
],
),
]

View File

@ -1,6 +1,9 @@
from django.db import models
from django.core.validators import RegexValidator, FileExtensionValidator
from gdstorage.storage import GoogleDriveStorage
gd_storage = GoogleDriveStorage()
class Subject(models.Model):
id = models.AutoField(primary_key=True)
@ -46,3 +49,13 @@ class Tag(models.Model):
def __str__(self):
return self.name
class Request(models.Model):
id = models.AutoField(primary_key=True)
course = models.ManyToManyField("Course", related_name="proposed_course")
tags = models.ManyToManyField("Tag", related_name="proposed_tags")
name = models.CharField(max_length=100, unique=True)
guide = models.FileField(upload_to='guides', storage=gd_storage)
def __str__(self):
return self.name

View File

@ -8,5 +8,8 @@ urlpatterns = [
path("subject/<str:subject_url>/", views.subject_view, name="subject_view"),
path("tag/<str:tag>/", views.tag_view, name="tag"),
path("course/<str:subject_url>/<str:course_url>/", views.course_view, name="course_view"),
path("search/", views.search_view, name="search")
path("search/", views.search_view, name="search"),
path("add/", views.add_view, name="add"),
path("approve-index/", views.approve_index_view, name="approve_index_view"),
path("approve/<int:request_id>/", views.approve_view, name="approve_view"),
]

View File

@ -6,8 +6,13 @@ from django import http
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from gdstorage.storage import GoogleDriveStorage
from django.core.exceptions import PermissionDenied
from .models import Subject, Course, Guide, Tag
from .models import Subject, Course, Guide, Tag, Request
from .forms import StudyGuideRequestForm
gd_storage = GoogleDriveStorage()
@login_required
def subject_view(request, subject_url):
@ -41,6 +46,54 @@ def search_view(request):
"tag_results": Tag.objects.filter(reduce(operator.or_, (Q(name__icontains=x) for x in q_list))),
"sq": q
}
return render(request, 'search_results.html', context=context)
return render(request, "search_results.html", context=context)
return redirect(request.META["HTTP_REFERER"])
@login_required
def add_view(request):
if request.method == "POST":
form = StudyGuideRequestForm(request.POST, request.FILES)
if form.is_valid():
r = Request(name=form.cleaned_data["name"])
r.save()
r.course.add(form.cleaned_data["course"])
for t in form.cleaned_data["tags"]:
r.tags.add(t)
r.guide = form.cleaned_data["guide"]
r.save()
return redirect(reverse("home:index"))
return render(request, "add.html", context={"form": form})
else:
form = StudyGuideRequestForm()
return render(request, "add.html", context={"form": form})
@login_required
def approve_index_view(request):
if request.user.is_superuser or request.user.is_staff:
return render(request, "approve_index.html", context={"guide_requests": Request.objects.all()})
raise PermissionDenied
@login_required
def approve_view(request, request_id):
if request.user.is_superuser or request.user.is_staff:
guide_request = Request.objects.get(id=request_id)
if request.method == "POST":
if request.POST.get("approve"):
guide = Guide(name=guide_request.name)
guide.save()
for t in guide_request.tags.all():
guide.tags.add(t)
guide.course = guide_request.course.all()[0]
guide.url = guide_request.guide.url
guide.save()
guide_request.delete()
return redirect(reverse("courses:approve_index_view"))
else:
ctx = {
"guide_request": guide_request,
"course": guide_request.course.all()[0],
"tags": guide_request.tags.all()
}
return render(request, "approve.html", context=ctx)
raise PermissionDenied

View File

@ -40,6 +40,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'gdstorage',
'social_django',
'studyguides.apps.courses',
'studyguides.apps.auth',
@ -164,9 +165,7 @@ STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'studyguides/static'),
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'studyguides/media')
MEDIA_URL = "/media/"
GOOGLE_DRIVE_STORAGE_JSON_KEY_FILE = os.path.join(BASE_DIR, 'studyguides/settings/key.json')
USE_X_FORWARDED_HOST = True

View File

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action='' method='post' enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action='' method='post'>
{% csrf_token %}
Name: {{ guide_request.name }}<br><br>
Course: {{ course }}<br><br>
Tags:
<ul>
{% for t in tags %}
<li>
{{ t }}
</li>
{% endfor %}
</ul>
Guide: <a href="{{ guide_request.guide.url }}">{{ guide_request.guide }}</a><br>
<br>
<input type="submit" name="approve" value="Approve">
<input type="submit" name="reject" value="Reject">
</form>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
Click on a guide below to view and approve or reject it.
<ul>
{% for r in guide_requests %}
<li>
<a href="{% url 'courses:approve_view' r.id %}" >{{ r }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -30,35 +30,14 @@
<main>
{% block disclaimer %}{% endblock %}
{% if user.is_authenticated %}
<form action="/search" method="get" autocomplete="off">
<input type="text" name="q" value="{% if sq %}{{ sq }}{% endif %}" placeholder="Search" aria-label="Search">
<button type="submit" class="search-button" aria-label="Search">
<i class="fas fa-search"></i>
</button>
</form>
<br>
{% endif %}
{% block search %}{% endblock %}
<div class="my-2">
{% block path %}{% endblock %}
</div>
{% block content %}{% endblock %}
</main>
{% if user.is_authenticated %}
<div class="size-5 my-2 josefin-sans text-center">
{% if user.is_teacher %}
<a style="padding:20px;" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSddHARB7zIgCBN-swWkejx6f4wJNslxh5AnkS65BzJ2pt7uLQ/viewform?usp=sf_link">Report a Study Guide</a>
{% elif user.is_superuser or user.is_staff %}
<a style="padding:20px;" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSddHARB7zIgCBN-swWkejx6f4wJNslxh5AnkS65BzJ2pt7uLQ/viewform?usp=sf_link">Report a Study Guide</a>
<a style="padding:20px;" href="/admin">Access Admin Console</a>
{% endif %}
<a style="padding:20px;" target="_blank" href="https://docs.google.com/forms/d/1p7DvGQfJM8nG88fC7eQ4lWcdEOKjNixUtFoJ8zpq_Co/viewform?edit_requested=true">Add Study Guide</a>
</div>
<br>
<div class="size-5 my-2 josefin-sans text-center">
<a href="{% url 'auth:logout' %}">Logout</a>
</div>
{% endif %}
{% block links %}{% endblock %}
</body>
</html>

View File

@ -1,4 +1,4 @@
{% extends "base.html" %} {% load static %}
{% extends "head_foot.html" %} {% load static %}
{% block path %}
<span class="bold size-2 hoverable">
<a href="/">

View File

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% load static %}
{% block search %}
{% if user.is_authenticated %}
<form action="/search" method="get" autocomplete="off">
<input type="text" name="q" value="{% if sq %}{{ sq }}{% endif %}" placeholder="Search" aria-label="Search">
<button type="submit" class="search-button" aria-label="Search">
<i class="fas fa-search"></i>
</button>
</form>
<br>
{% endif %}
{% endblock %}
{% block links %}
{% if user.is_authenticated %}
<div class="size-5 my-2 josefin-sans text-center">
{% if user.is_teacher %}
<a style="padding:20px;" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSddHARB7zIgCBN-swWkejx6f4wJNslxh5AnkS65BzJ2pt7uLQ/viewform?usp=sf_link">Report a Study Guide</a>
{% elif user.is_superuser or user.is_staff %}
<a style="padding:20px;" target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSddHARB7zIgCBN-swWkejx6f4wJNslxh5AnkS65BzJ2pt7uLQ/viewform?usp=sf_link">Report a Study Guide</a>
<a style="padding:20px;" href="/admin">Access Admin Console</a>
<a style="padding:20px;" href="{% url 'courses:approve_index_view' %}">Approve Study Guides</a>
{% endif %}
<a style="padding:20px;" href="{% url 'courses:add' %}">Add Study Guide</a>
</div>
<br>
<div class="size-5 my-2 josefin-sans text-center">
<a href="{% url 'auth:logout' %}">Logout</a>
</div>
{% endif %}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "base.html" %} {% load static %}
{% extends "head_foot.html" %} {% load static %}
{% block disclaimer %}
<p>
DISCLAIMER: Please note these materials are student-made study guides over the past years. Some information may be outdated or not 100% reflective of the content your teacher is teaching. It is also possible the information is not 100% accurate. Therefore, make sure to not solely rely on these study guides. If you see an inconsistency in a study guide that confuses you, ask your teacher to clarify. SGA maintains this site but is not liable for the credibility of the information found. To contact SGA, please email SGA.tjhsst@gmail.com.

View File

@ -1,4 +1,4 @@
{% extends "base.html" %} {% load static %}
{% extends "head_foot.html" %} {% load static %}
{% block path %}
<span class="bold size-2 hoverable">
<a href="{% url 'home:index' %}">

View File

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "head_foot.html" %}
{% load static %}