diff --git a/.sprofile b/.2022rkhondakprofile similarity index 100% rename from .sprofile rename to .2022rkhondakprofile diff --git a/.tprofile b/.eharris1profile similarity index 100% rename from .tprofile rename to .eharris1profile diff --git a/CLI/student.py b/CLI/student.py index d215337..2d494a2 100644 --- a/CLI/student.py +++ b/CLI/student.py @@ -13,15 +13,15 @@ import datetime # git clone student directory ==> /classes/assignments # get teacher info from api -def getStudent(ion_user): +def getStudent(ion_user, password): """ Get's student information from the api :param ion_user: a student :return: student information or error """ URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/" - r = requests.get(url=URL, auth=('raffukhondaker', 'hackgroup1')) - if r.status_code == 200: + r = requests.get(url=URL, auth=(ion_user, password)) + if (r.status_code == 200): data = r.json() return data elif r.status_code == 404: @@ -36,60 +36,61 @@ def getStudent(ion_user): # makes a GET request to given url, returns dict -def getDB(url): +def getDB(user, pwd, url): """ Sends a GET request to the URL :param url: URL for request """ - r = requests.get(url=url, auth=('raffukhondaker', 'hackgroup1')) + r = requests.get(url=url, auth=(user, pwd)) print("GET:" + str(r.status_code)) return r.json() # makes a PATCH (updates instance) request to given url, returns dict -def patchDB(data, url): +def patchDB(user, pwd, data, url): """ Sends a PATCH request to the URL :param data: :param url: URL for request """ - r = requests.patch(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + r = requests.patch(url=url, data=data, auth=(user, pwd)) print("PATCH:" + str(r.status_code)) return r.json() # makes a POST (makes new instance) request to given url, returns dict -def postDB(data, url): +def postDB(user, pwd, data, url): """ Sends a POST request to the URL :param data: :param url: URL for request """ - r = requests.post(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + r = requests.post(url=url, data=data, auth=(user, pwd)) print("POST:" + str(r.status_code)) return r.json() # makes a PUT (overwrites instance) request to given url, returns dict -def putDB(data, url): +def putDB(user, pwd, data, url): """ Sends a PUT request to the URL :param data: :param url: URL for request - """ - r = requests.put(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + """ + r = requests.put(url=url, data=data, auth=(user, pwd)) print("PUT:" + str(r.status_code)) return r.json() # makes a DELETE (delete instance) request to given url, returns dict -def delDB(url): +def delDB(user, pwd, url): """ Sends a DELETE request to the URL :param url: URL for request """ - r = requests.delete(url=url, auth=('raffukhondaker', 'hackgroup1')) + r = requests.delete(url=url, auth=(user, pwd)) print("DELETE:" + str(r.status_code)) + return None def command(command): @@ -112,7 +113,7 @@ def command(command): # public methods: deleteClass, makeClass, update class Student: - def __init__(self, data): + def __init__(self, data, password): # teacher info already stored in API # intitialze fields after GET request """ @@ -125,6 +126,7 @@ class Student: self.grade = data['grade'] self.completed = data['completed'] self.user = data['user'] + self.password = password # classes in id form (Example: 4,5) # storing actual classes cid = data['classes'].split(",") @@ -139,7 +141,7 @@ class Student: classes = [] for c in cid: url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/" - classes.append(getDB(url)) + classes.append(getDB(self.username, self.password,url)) self.classes = classes self.sclass = str(data['classes']) @@ -157,7 +159,7 @@ class Student: nclasses = [] for c in nid: url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/" - nclasses.append(getDB(url)) + nclasses.append(getDB(self.username, self.password,url)) self.new = nclasses self.snew = str(data['added_to']) @@ -184,7 +186,7 @@ class Student: data = { 'repo': self.repo } - print(patchDB(data, self.url)) + print(patchDB(self.username, self.password,data, self.url)) print("Synced to " + self.username) def getClasses(self): @@ -206,7 +208,7 @@ class Student: print(c['name']) alist = c['assignments'] for a in alist: - ass = getDB("http://127.0.0.1:8000/api/assignments/" + a) + ass = getDB(self.username, self.password,"http://127.0.0.1:8000/api/assignments/" + a) now = datetime.datetime.now() try: due = ass['due_date'].replace("T", " ").replace("Z", "") @@ -231,7 +233,7 @@ class Student: command("git checkout master") for c in self.classes: print("UPDATING CLASS: " + str(c['name'])) - data = getDB("http://127.0.0.1:8000/api/classes/" + str(c['name'])) + data = getDB(self.username, self.password,"http://127.0.0.1:8000/api/classes/" + str(c['name'])) # command("git checkout master") command("git checkout " + data['name']) command("git add .") @@ -272,8 +274,8 @@ class Student: :param cid: the id number of the class :return: data from the class, None if an error occures """ - data = getDB('http://127.0.0.1:8000/api/classes/' + str(cid)) - if not (cid in self.snew) or (self.username in data['confirmed']): + data = getDB(self.username, self.password,'http://127.0.0.1:8000/api/classes/' + str(cid)) + if ((cid in self.snew) == False or (self.username in data['confirmed'])): print("Already enrolled in this class.") return None if (cid in self.sclass) or not (self.username in data['unconfirmed']): @@ -283,7 +285,7 @@ class Student: # add class teacher as collaborator to student repo print(os.getcwd()) pwd = input("Enter Github password: ") - tgit = getDB("http://127.0.0.1:8000/api/teachers/" + data['teacher'] + "/")['git'] + tgit = getDB(self.username, self.password,"http://127.0.0.1:8000/api/teachers/" + data['teacher'] + "/")['git'] url = "curl -i -u " + self.git + ":" + pwd + " -X PUT -d '' " + "'https://api.github.com/repos/" + self.git + "/" + self.username + "/collaborators/" + tgit + "'" print(url) os.system(url) @@ -336,7 +338,7 @@ class Student: # recreate sclass field, using ids for c in self.new: snew = snew + str(c['name']) + "," - new.append(getDB("http://127.0.0.1:8000/api/classes/" + str(cid))) + new.append(getDB(self.username, self.password,"http://127.0.0.1:8000/api/classes/" + str(cid))) self.snew = snew self.new = new break @@ -348,7 +350,7 @@ class Student: 'classes': self.sclass } print(self.url) - print(patchDB(data, self.url)) + print(patchDB(self.username, self.password,data, self.url)) return data def viewClass(self, courses): @@ -413,8 +415,8 @@ class Student: os.chdir(cdir) -# data = getStudent("2022rkhondak") -# s = Student(data) +#data = getStudent("2022rkhondak", "PWD") +#s = Student(data, "PWD") # s.viewClass("APLit_eharris1") # #s.addClass("APLit_eharris1") # # #s.update() diff --git a/CLI/teacher.py b/CLI/teacher.py index 0f1eaa7..3281083 100644 --- a/CLI/teacher.py +++ b/CLI/teacher.py @@ -26,14 +26,16 @@ from datetime import datetime # git clone student directory ==> /classes/assignments # get teacher info from api -def getTeacher(ion_user): +def getTeacher(ion_user, password): """ Gets information about a teacher from the api :param ion_user: a teacher + :param password: a string :return: teacher information or error """ URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/" - r = requests.get(url=URL, auth=('raffukhondaker', 'hackgroup1')) + r = requests.get(url=URL, auth=(ion_user,password)) + print(r.json()) if r.status_code == 200: data = r.json() return data @@ -48,58 +50,67 @@ def getTeacher(ion_user): print(r.status_code) #makes a GET request to given url, returns dict -def getDB(url): +def getDB(user, pwd, url): """ Sends a GET request to the URL + :param user: a string + :param password: a string :param url: URL for request """ - r = requests.get(url=url, auth=('raffukhondaker', 'hackgroup1')) + r = requests.get(url=url, auth=(user, pwd)) print("GET:" + str(r.status_code)) return(r.json()) #makes a PATCH (updates instance) request to given url, returns dict -def patchDB(data, url): +def patchDB(user, pwd, data, url): """ Sends a PATCH request to the URL :param data: + :param user: a string + :param password: a string :param url: URL for request """ - r = requests.patch(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + r = requests.patch(url=url, data=data, auth=(user, pwd)) print("PATCH:" + str(r.status_code)) return r.json() #makes a POST (makes new instance) request to given url, returns dict -def postDB(data, url): +def postDB(user, pwd, data, url): """ Sends a POST request to the URL :param data: + :param user: a string + :param password: a string :param url: URL for request """ - r = requests.post(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + r = requests.post(url=url, data=data, auth=(user, pwd)) print("POST:" + str(r.status_code)) return r.json() #makes a PUT (overwrites instance) request to given url, returns dict -def putDB(data, url): +def putDB(user, pwd, data, url): """ Sends a PUT request to the URL - :param data: + :param user: a string + :param password: a string :param url: URL for request """ - r = requests.put(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) + r = requests.put(url=url, data=data, auth=(user, pwd)) print("PUT:" + str(r.status_code)) return r.json() #makes a DELETE (delete instance) request to given url, returns dict -def delDB(url): +def delDB(user, pwd, url): """ Sends a DELETE request to the URL + :param user: a string + :param password: a string :param url: URL for request """ - r = requests.delete(url=url, auth=('raffukhondaker', 'hackgroup1')) + r = requests.delete(url=url, auth=(user, pwd)) print("DELETE:" + str(r.status_code)) return None @@ -123,7 +134,7 @@ def command(command): # public methods: deleteClass, makeClass, update class Teacher: - def __init__(self, data): + def __init__(self, data, password): # teacher info already stored in API # intitialze fields after GET request """ @@ -134,6 +145,7 @@ class Teacher: self.username = data['ion_user'] self.url = "http://127.0.0.1:8000/api/teachers/" + self.username + "/" self.id = data['user'] + self.password = password # classes in id form (Example: 4,5) # array @@ -218,15 +230,22 @@ class Teacher: return if self.checkClass(path): cpath = self.username + "/" + cname + subject = cname.split("_")[0] + period = int(input("Enter period: ")) + while(not (type(period) is int and period >= 0)): + print("Incorrect format") + period = int(input("Enter period: ")) data = { "name": cname, "repo": "", "path": cpath, + "subject": subject, + "period":period, "teacher": self.username, "owner": self.id } # make class instance in db - postDB(data, 'http://127.0.0.1:8000/api/classes/') + postDB(self.username, self.password, data, 'http://127.0.0.1:8000/api/classes/') time.sleep(1) self.classes.append(cname) # add to instance @@ -235,7 +254,7 @@ class Teacher: 'classes': self.classes } print(self.classes) - print(patchDB(data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/")) + print(patchDB(self.username, self.password, data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/")) # make a new class from scratch # subject: string, assignments: list @@ -248,7 +267,7 @@ class Teacher: # check if class exists path = self.username + "/" + cname isclass = False - acourses = getDB("http://127.0.0.1:8000/api/classes/")['results'] + acourses = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/")['results'] for c in acourses: if c['name'] == cname: isclass = True @@ -300,7 +319,7 @@ class Teacher: # 'classes':self.classes, # } # print(patchDB(data, self.url)) - delDB("http://127.0.0.1:8000/api/classes/" + cname + "/") + delDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname + "/") break # remove locally @@ -318,7 +337,7 @@ class Teacher: :return: True if student exists, False otherwise """ r = requests.get(url="http://127.0.0.1:8000/api/students/" + student + "/", - auth=('raffukhondaker', 'hackgroup1')) + auth=(self.username, self.password)) if r.status_code != 200: return False return True @@ -333,7 +352,7 @@ class Teacher: if not self.isStudent(sname): print(sname + " does not exist.") return False - course = getDB("http://127.0.0.1:8000/api/classes/" + cname) + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname) if sname in str(course['unconfirmed']): print(sname + " already requested.") return True @@ -341,7 +360,7 @@ class Teacher: print(sname + " already enrolled.") return False - student = getDB("http://127.0.0.1:8000/api/students/" + sname) + student = getDB(self.username, self.password, "http://127.0.0.1:8000/api/students/" + sname) try: if student['added_to'] == "": student['added_to'] = course['name'] @@ -354,8 +373,8 @@ class Teacher: data = { 'added_to': student['added_to'], } - student = patchDB(data, "http://localhost:8000/api/students/" + student['ion_user'] + "/") - student = getDB("http://localhost:8000/api/students/" + sname + "/") + student = patchDB(self.username, self.password, data, "http://localhost:8000/api/students/" + student['ion_user'] + "/") + student = getDB(self.username, self.password, "http://localhost:8000/api/students/" + sname + "/") if not course['unconfirmed']: course['unconfirmed'] = student['ion_user'] else: @@ -364,7 +383,7 @@ class Teacher: "unconfirmed": course['unconfirmed'] } print(cinfo) - patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/") + patchDB(self.username, self.password, cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/") return True # Student should have confirmed on their endd, but class had not been updated yet @@ -380,8 +399,8 @@ class Teacher: print(sname + " does not exist.") return False - student = getDB("http://127.0.0.1:8000/api/students/" + sname) - course = getDB("http://127.0.0.1:8000/api/classes/" + cname) + student = getDB(self.username, self.password, "http://127.0.0.1:8000/api/students/" + sname) + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + cname) if (os.path.exists(self.username + "/Students/" + cname + "/" + student['ion_user']) or ( student['ion_user'] in course['confirmed']) == True): @@ -435,7 +454,7 @@ class Teacher: "confirmed": course["confirmed"], "unconfirmed": course['unconfirmed'] } - print(putDB(course, "http://localhost:8000/api/classes/" + course['name'] + "/")) + print(putDB(self.username, self.password, course, "http://localhost:8000/api/classes/" + course['name'] + "/")) return True # goes through list of studennts, tries to add, then request, return unconfirmed students @@ -494,7 +513,7 @@ class Teacher: print("Due-date format is incorrect") return False - course = getDB("http://127.0.0.1:8000/api/classes/" + course) + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course) if aname in str(course['assignments']): print("Assignment name already taken.") return False @@ -525,22 +544,23 @@ class Teacher: print(st + " already has assignment") # check if assignment already exists - r = requests.get(url='http://127.0.0.1:8000/api/assignments/' + aname, auth=('raffukhondaker', 'hackgroup1')) + r = requests.get(url='http://127.0.0.1:8000/api/assignments/' + aname, auth=(self.username, self.password)) if r.status_code != 200: ass = { 'name': oname, 'path': path, 'classes': course['name'], 'teacher': self.username, - 'due_date': due + 'due_date': due, + 'owner':self.id } - postDB(ass, 'http://127.0.0.1:8000/api/assignments/') + postDB(self.username, self.password, ass, 'http://127.0.0.1:8000/api/assignments/') course['assignments'].append(oname) cinfo = { "assignments": course['assignments'], } - print(patchDB(cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/")) + print(patchDB(self.username, self.password, cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/")) return True else: print("Assignment already addedd") @@ -561,12 +581,12 @@ class Teacher: d = { 'due_date': due, } - print(patchDB(d, 'http://localhost:8000/api/assignments/' + oname + "/")) + print(patchDB(self.username, self.password, d, 'http://localhost:8000/api/assignments/' + oname + "/")) print("Due-date changed " + due) except: print("Due-date is the same") input() - course = getDB("http://127.0.0.1:8000/api/classes/" + course) + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course) slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name']) cdir = os.getcwd() for st in slist: @@ -597,7 +617,7 @@ class Teacher: os.chdir(cdir) def getCommits(self, student, course, commits): - course = getDB("http://127.0.0.1:8000/api/classes/" + course) + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course) try: if not (student in course['confirmed']): print("Student not in class") @@ -645,7 +665,7 @@ class Teacher: :param course: the course :param commits: commits the CLI has made for the assignment """ - course = getDB("http://127.0.0.1:8000/api/classes/" + course + "/") + course = getDB(self.username, self.password, "http://127.0.0.1:8000/api/classes/" + course + "/") ar = self.getCommits(student, course['name'], commits) commit = ar[len(ar) - 1][0] start = "" @@ -670,7 +690,7 @@ class Teacher: def afterSubmit(self, course, assignment, student): - assignment = getDB("http://127.0.0.1:8000/api/assignments/" + assignment) + assignment = getDB(self.username, self.password, "http://127.0.0.1:8000/api/assignments/" + assignment) # assignment = { # 'name': assignment, # 'due_date': "2020-04-11 16:58:33.383124", @@ -705,8 +725,9 @@ class Teacher: print("heheheh") -# data = getTeacher("eharris1") -# t = Teacher(data) +# data = getTeacher("eharris1","PWD") +# print(data) +# t = Teacher(data, "PWD") # t.makeClass("APLit_eharris1") # t.updateAssignment("eharris1/APLit_eharris1/BookReport", "APLit_eharris1", '2020-08-11 16:58:33.383124') # ar = ['2022rkhondak','2022inafi','2023rumareti'] diff --git a/Website/api/models.py b/Website/api/models.py index c4b92ae..37364a1 100644 --- a/Website/api/models.py +++ b/Website/api/models.py @@ -3,50 +3,51 @@ from django.contrib.auth.models import User import secrets + class Student(models.Model): user = models.OneToOneField(User, blank=True, on_delete=models.CASCADE) ion_user = models.CharField(max_length=100, primary_key=True) grade = models.IntegerField(default=0, blank=True) - git = models.CharField(default="", max_length=100, blank=True) - repo = models.URLField(default="", blank=True) - classes = models.CharField(max_length=100, default="", blank=True) - added_to = models.CharField(max_length=100, default="", blank=True) - completed = models.TextField(default="", blank=True) + git=models.CharField(default="", max_length=100, blank=True) + repo=models.URLField(default="", blank=True) + classes=models.CharField(max_length=100, default="", blank=True) + added_to=models.CharField(max_length=100, default="", blank=True) + completed=models.TextField(default="", blank=True) def save(self, *args, **kwargs): super(Student, self).save(*args, **kwargs) def __str__(self): - return f"{self.user.username}'s Profile" + return f"{self.user.first_name} {self.user.last_name} ({self.user.username})" class Assignment(models.Model): owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE) - - name = models.CharField(max_length=100, primary_key=True) - due_date = models.DateTimeField() + name=models.CharField(max_length=100, primary_key=True) + due_date=models.DateTimeField() # files = models.ManyToManyField(DefFiles) - files = models.CharField(max_length=100, default="", blank=True) - path = models.CharField(max_length=100) - classes = models.CharField(max_length=100) - teacher = models.CharField(max_length=100) - + files=models.CharField(max_length=100, default="", blank=True) + path=models.CharField(max_length=100, default="", blank=True) + classes=models.CharField(max_length=100, default="", blank=True) + teacher=models.CharField(max_length=100, default="", blank=True) def __str__(self): - return '%s' % (self.name) + return f'{self.name}' class Class(models.Model): owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', on_delete=models.CASCADE) - teacher = models.CharField(max_length=100) + teacher = models.CharField(max_length=100, blank=True) + subject = models.CharField(max_length=50, blank=True) + period = models.PositiveIntegerField(null=True, blank=True, default=0) name = models.CharField(primary_key=True, max_length=100) id = models.CharField(max_length=8, blank=True, null=True) - description = models.CharField(default="Class Description", max_length=500) - repo = models.URLField(default="", blank=True) - path = models.CharField(max_length=100, default="") - assignments = models.ManyToManyField(Assignment, blank=True) - default_file = models.CharField(max_length=100, default="", blank=True) - confirmed = models.ManyToManyField(Student, blank=True, related_name='confirmed') - unconfirmed = models.ManyToManyField(Student, blank=True, related_name='unconfirmed') + description = models.CharField(default="Class Description", max_length=500, blank=True) + repo=models.URLField(default="", blank=True) + path=models.CharField(max_length=100, default="", blank=True) + assignments=models.ManyToManyField(Assignment, blank=True) + default_file=models.CharField(max_length=100, default="", blank=True) + confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed') + unconfirmed=models.ManyToManyField(Student, blank=True, related_name='unconfirmed') # assignments = models.ManyToManyField(Assignment, default="") # default_file = models.ManyToManyField(DefFiles) @@ -60,22 +61,20 @@ class Class(models.Model): return super(Class, self).save(*args, **kwargs) def __str__(self): - return self.name - + return f"{self.name}" class Teacher(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) - classes = models.ManyToManyField(Class, blank=True, related_name='classes') - git = models.CharField(max_length=100, default="", blank=True) - ion_user = models.CharField(primary_key=True, max_length=100) + classes=models.ManyToManyField(Class, blank=True, related_name='classes') + git=models.CharField(max_length=100, default="", blank=True) + ion_user=models.CharField(primary_key=True, max_length=100) def __str__(self): - return f"{self.user.username}'s Profile" + return f"{self.user.first_name} {self.user.last_name} ({self.user.username})" def save(self, *args, **kwargs): super(Teacher, self).save(*args, **kwargs) - # class Student(models.Model): # user = models.OneToOneField(User, on_delete=models.CASCADE) # ion_user=models.CharField(primary_key=True, max_length=100) @@ -88,8 +87,8 @@ class Teacher(models.Model): class DefFiles(models.Model): - name = models.CharField(max_length=100) - path = models.CharField(max_length=100) - assignment = models.CharField(max_length=100, default="") - classes = models.CharField(max_length=100) - teacher = models.CharField(max_length=100) + name=models.CharField(max_length=100) + path=models.CharField(max_length=100) + assignment=models.CharField(max_length=100, default="") + classes=models.CharField(max_length=100) + teacher=models.CharField(max_length=100) diff --git a/Website/api/serializers.py b/Website/api/serializers.py index 40521ac..7d7b2aa 100644 --- a/Website/api/serializers.py +++ b/Website/api/serializers.py @@ -34,7 +34,7 @@ class ClassSerializer(serializers.ModelSerializer): class Meta: model = Class # fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner'] - fields = ['name', 'repo','path','assignments',"teacher","default_file", 'confirmed', 'unconfirmed','owner'] + fields = ['name', 'repo','path','subject','period','assignments',"teacher","default_file", 'confirmed', 'unconfirmed','owner'] class StudentSerializer(serializers.ModelSerializer): # Class = ClassSerializer(many=True, read_only=True,allow_null=True) diff --git a/Website/skoolos/forms.py b/Website/skoolos/forms.py index 6374f97..2f498c0 100644 --- a/Website/skoolos/forms.py +++ b/Website/skoolos/forms.py @@ -1,6 +1,6 @@ from django import forms from django.contrib.auth.models import User -from api.models import Student, Teacher +from api.models import Student, Teacher, Class, Assignment import re class UserUpdateForm(forms.ModelForm): @@ -26,3 +26,47 @@ class TeacherUpdateForm(forms.ModelForm): class Meta: model = Teacher fields = ['git'] + +class ClassCreationForm (forms.ModelForm): + subject = forms.CharField(max_length=50) + period = forms.IntegerField(min_value=0, max_value=9) + description = forms.CharField(widget=forms.Textarea) + unconfirmed = forms.ModelMultipleChoiceField(queryset=Student.objects.all(), label="Invite students") + + + def clean_period(self): + pd = self.cleaned_data['period'] + if pd < 1 or pd > 9: + raise forms.ValidationError("Invalid period") + return pd; + + def __init__(self, *args, **kwargs): + super(ClassCreationForm, self).__init__(*args, **kwargs) + self.fields['period'].widget.attrs['min'] = 0 + # Only in case we build the form from an instance + # (otherwise, 'unconfirmed' list should be empty) + if kwargs.get('instance'): + # We get the 'initial' keyword argument or initialize it + # as a dict if it didn't exist. + initial = kwargs.setdefault('initial', {}) + # The widget for a ModelMultipleChoiceField expects + # a list of primary key for the selected data. + initial['unconfirmed'] = [t.pk for t in kwargs['instance'].unconfirmed.all()] + + # Overriding save allows us to process the value of 'unconfirmed' field + def save(self, username=""): + cleaned_data = self.cleaned_data + print(self) + + # Get the unsave Class instance + instance = forms.ModelForm.save(self) + instance.unconfirmed.clear() + instance.unconfirmed.add(*cleaned_data['unconfirmed']) + instance.name = cleaned_data['subject'] + str(cleaned_data['period']) + "_" + username + print("Class name: " + instance.name) + + return instance + + class Meta: + model = Class + fields = ['subject', 'period', 'description', 'unconfirmed'] diff --git a/Website/skoolos/templates/skoolos/base.html b/Website/skoolos/templates/skoolos/base.html index 2ec152d..fa2f42c 100644 --- a/Website/skoolos/templates/skoolos/base.html +++ b/Website/skoolos/templates/skoolos/base.html @@ -34,6 +34,12 @@ + {% empty %} + {% if isTeacher %} +

Looks like you haven't made any assignments yet, hit the button in the top right to get started

+ {% else %} +

Looks like there aren't any assignments at the moment, you got lucky this time!

+ {% endif %} {% endfor %} @@ -20,6 +26,8 @@ diff --git a/Website/skoolos/templates/skoolos/createClass.html b/Website/skoolos/templates/skoolos/createClass.html new file mode 100644 index 0000000..4acb8f9 --- /dev/null +++ b/Website/skoolos/templates/skoolos/createClass.html @@ -0,0 +1,26 @@ +{% extends "skoolos/base.html" %} +{% load crispy_forms_tags %} +{% block content %} + Classes + +
+ {% csrf_token %} +
+ Create a new class + {{ classForm|crispy }} + + Use ctrl to select multiple students +
+
+ +
+
+ + +{% endblock content %} diff --git a/Website/skoolos/templates/skoolos/home.html b/Website/skoolos/templates/skoolos/home.html index 6822cb6..45dfedc 100644 --- a/Website/skoolos/templates/skoolos/home.html +++ b/Website/skoolos/templates/skoolos/home.html @@ -10,6 +10,12 @@ + {% empty %} + {% if isTeacher %} +

Looks like you haven't created any classes yet, hit the button in the top right to get started.

+ {% else %} +

Looks like you're not enrolled in any classes at the moment! Ask your teacher if you think this is wrong.

+ {% endif %} {% endfor %} {% endblock content %} diff --git a/Website/skoolos/templates/skoolos/profile_student.html b/Website/skoolos/templates/skoolos/profile_student.html index 3da2f41..947dab7 100644 --- a/Website/skoolos/templates/skoolos/profile_student.html +++ b/Website/skoolos/templates/skoolos/profile_student.html @@ -5,6 +5,7 @@
+

Student

{{ user.first_name }} {{ user.last_name }}

{{ user.email }} @@ -16,6 +17,8 @@

    {% for class in classes %}
  • {{ class.name }}
  • + {% empty %} +
  • No classes
  • {% endfor %}
diff --git a/Website/skoolos/templates/skoolos/profile_teacher.html b/Website/skoolos/templates/skoolos/profile_teacher.html index 3da2f41..7c62793 100644 --- a/Website/skoolos/templates/skoolos/profile_teacher.html +++ b/Website/skoolos/templates/skoolos/profile_teacher.html @@ -5,6 +5,7 @@
+

Teacher

{{ user.first_name }} {{ user.last_name }}

{{ user.email }} @@ -16,6 +17,8 @@

    {% for class in classes %}
  • {{ class.name }}
  • + {% empty %} +
  • Not teaching any classes
  • {% endfor %}
diff --git a/Website/skoolos/urls.py b/Website/skoolos/urls.py index a028497..8fa2724 100644 --- a/Website/skoolos/urls.py +++ b/Website/skoolos/urls.py @@ -7,4 +7,6 @@ urlpatterns = [ path('', views.home, name='home'), path('profile/', views.profile, name='profile'), path("class/", views.classDetail, name="class"), + path("create-class/", views.createClass, name="create-class"), + path("create-assignment/", views.createAssignment, name="create-assignment"), ] diff --git a/Website/skoolos/views.py b/Website/skoolos/views.py index 3f67c84..ff00036 100644 --- a/Website/skoolos/views.py +++ b/Website/skoolos/views.py @@ -5,7 +5,12 @@ from django.contrib import messages from django.contrib.auth.models import User -from .forms import UserUpdateForm, StudentUpdateForm, TeacherUpdateForm +from .forms import ( + UserUpdateForm, + StudentUpdateForm, + TeacherUpdateForm, + ClassCreationForm, +) from api.models import Student, Teacher, Class, Assignment @@ -14,14 +19,14 @@ from api.models import Student, Teacher, Class, Assignment @login_required() def home (request): try: - student = Student.objects.get(user=request.user) - return render(request, "skoolos/home.html", {'classes': student.confirmed.all()}) + student = request.user.student + return render(request, "skoolos/home.html", {'classes': student.confirmed.all(), 'isTeacher': False}) except Student.DoesNotExist: pass try: - teacher = Teacher.objects.get(user=request.user) - return render(request, "skoolos/home.html", {'classes': teacher.classes.all()}) + teacher = request.user.teacher + return render(request, "skoolos/home.html", {'classes': teacher.classes.all(), 'isTeacher': True}) except Teacher.DoesNotExist: pass @@ -36,38 +41,37 @@ def classDetail (request, id): classObj = Class.objects.get(id=id) try: - student = Student.objects.get(user=request.user) + student = request.user.student except Student.DoesNotExist: pass else: if classObj.confirmed.filter(user=student.user).count() != 1: return redirect('/') else: - return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()}) + return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': False}) try: - teacher = Teacher.objects.get(user=request.user) - return render(request, "skoolos/home.html", {'classes': teacher.classes.all()}) + teacher = request.user.teacher except Teacher.DoesNotExist: pass else: - if classObj.confirmed.filter(user=student.user).count() != 1: + if teacher.classes.filter(id=classObj.id).count() != 1: return redirect('/') else: - return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()}) + return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all(), 'isTeacher': True}) return redirect('/') @login_required() def profile (request): try: - student = Student.objects.get(user=request.user) + student = request.user.student return student_profile(request) except Student.DoesNotExist: pass try: - teacher = Teacher.objects.get(user=request.user) + teacher = request.user.teacher return teacher_profile(request) except Teacher.DoesNotExist: pass @@ -91,7 +95,8 @@ def student_profile (request): context = { 'userForm': userForm, 'profileForm': profileForm, - 'classes': request.user.student.confirmed.all() + 'classes': request.user.student.confirmed.all(), + 'isTeacher': False, } return render(request, 'skoolos/profile_student.html', context) @@ -113,7 +118,46 @@ def teacher_profile (request): context = { 'userForm': userForm, 'profileForm': profileForm, - 'classes': request.user.teacher.classes.all() + 'classes': request.user.teacher.classes.all(), + 'isTeacher': True, } return render(request, 'skoolos/profile_teacher.html', context) + +@login_required() +def createClass (request): + try: + teacher = request.user.teacher + except Teacher.DoesNotExist: + pass + else: + return createClassHelper(request) + + return redirect('/') + +def createClassHelper(request): + teacher = request.user.teacher + + if request.method == "POST": + classForm = ClassCreationForm(request.POST) + if classForm.is_valid(): + cleaned_data = classForm.clean() + print(cleaned_data) + classForm.save(username=teacher.user.username) + messages.success(request, cleaned_data['subject'].capitalize() + " has been created!") + return redirect('home') + else: + classForm = ClassCreationForm() + + context = { + 'teacher': teacher, + 'classes': teacher.classes.all(), + 'classForm': classForm + + } + + return render(request, "skoolos/createClass.html", context) + +@login_required() +def createAssignment (request): + pass diff --git a/eharris1/APLit_eharris1/BookReport/rubric.txt b/eharris1/APLit_eharris1/BookReport/rubric.txt deleted file mode 100644 index a65722f..0000000 --- a/eharris1/APLit_eharris1/BookReport/rubric.txt +++ /dev/null @@ -1,7 +0,0 @@ -kskskksks -kskskksks -kskskksks -kskskksks -kskskksks -kskskksks -kskskksks \ No newline at end of file diff --git a/eharris1/APLit_eharris1/BookReport/sample.txt b/eharris1/APLit_eharris1/BookReport/sample.txt deleted file mode 100644 index e69de29..0000000 diff --git a/eharris1/APLit_eharris1/Essay1_APLit_eharris1/instruct.txt b/eharris1/APLit_eharris1/Essay1_APLit_eharris1/instruct.txt deleted file mode 100644 index e69de29..0000000 diff --git a/eharris1/APLit_eharris1/Essay2/instruct.txt b/eharris1/APLit_eharris1/Essay2/instruct.txt deleted file mode 100644 index e69de29..0000000 diff --git a/eharris1/Art12_eharris1/Painting1/rubric.txt b/eharris1/Art12_eharris1/Painting1/rubric.txt deleted file mode 100644 index e69de29..0000000 diff --git a/eharris1/English11_eharris1/README.md b/eharris1/English11_eharris1/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/eharris1/APLit_eharris1/README.md b/eharris1/English12_eharris1/README.md similarity index 100% rename from eharris1/APLit_eharris1/README.md rename to eharris1/English12_eharris1/README.md diff --git a/skoolos.py b/skoolos.py index 6f2ba9f..cc8fe8c 100644 --- a/skoolos.py +++ b/skoolos.py @@ -40,7 +40,9 @@ def main(): print("╚═════╝░╚═╝░░╚═╝░╚════╝░░╚════╝░╚══════╝  ░╚════╝░╚═════╝░") print("") - if not (os.path.exists(".sprofile") or os.path.exists(".tprofile")): + profiles = os.listdir() + + if not ("profile" in str(profiles)): try: URL = "http://127.0.0.1:8000/api/" r = requests.get(url=URL) @@ -65,6 +67,7 @@ def main(): info.append(d) users.append(str(count) + ") " + d['username']) count = count + 1 + users.append(str(count) + ") Make new user") user = [ { 'type': 'list', @@ -74,6 +77,9 @@ def main(): }, ] u = int(prompt(user)['user'].split(")")[0]) - 1 + if(u+1 == count): + authenticate() + return data = info[u] PWD = data['password'] USER = data['username'] @@ -83,8 +89,7 @@ def main(): else: teacherCLI(USER, PWD) - -################################################ STUDENT METHODS +#################################################################################################### STUDENT METHODS def studentCLI(user, password): """ @@ -94,11 +99,13 @@ def studentCLI(user, password): """ from CLI import student data = getUser(user, password, 'student') - student = student.Student(data) + student = student.Student(data, password) student.update() EXIT = False while not EXIT: course = chooseClassStudent(student) + if(course == "Exit SkoolOS"): + return EXIT = classOptionsStudent(student, course) @@ -162,7 +169,7 @@ def classOptionsStudent(student, course): return True -################################################ TEACHER METHODS +#################################################################################################### TEACHER METHODS def teacherCLI(user, password): from CLI import teacher data = getUser(user, password, 'teacher') @@ -174,26 +181,25 @@ def teacherCLI(user, password): # 3. Get progress logs on a student # 2. make an assignment for a class # 3. view student submissions for an assignment - while (not EXIT): - # Options: '1) Request Student', "2) Add assignment", "3) View student information", "4) Exit" + while(not EXIT): + #Options: '1) Request Student', "2) Add assignment", "3) View student information", "4) Exit" course = chooseGeneralTeacher(teacher) if course == "Exit SkoolOS": EXIT = True elif course == "Make New Class": EXIT = makeClassTeacher(teacher) - # selected a class + #selected a class else: option = classOptionsTeacher(teacher, course) - if (option == '1'): + if(option == '1'): EXIT = addStudentsTeacher(teacher, course) - elif (option == '2'): + elif(option == '2'): EXIT = addAssignmentTeacher(teacher, course) - elif (option == '3'): + elif(option == '3'): EXIT = viewStudentsTeacher(teacher, course) else: EXIT = True - def chooseGeneralTeacher(teacher): carray = [] for c in teacher.classes: @@ -201,57 +207,56 @@ def chooseGeneralTeacher(teacher): carray.append("Make New Class") carray.append("Exit SkoolOS") courses = [ - { - 'type': 'list', - 'name': 'course', - 'choices': carray, - 'message': 'Select class: ', - }, + { + 'type': 'list', + 'name': 'course', + 'choices':carray, + 'message': 'Select class: ', + }, ] course = prompt(courses)['course'] return course - def makeClassTeacher(teacher): questions = [ + { + 'type': 'input', + 'name': 'cname', + 'message': 'Class Name (Must be: _): ', + }, + ] + cname = prompt(questions)['cname'] + print(cname) + while(not ("_" + teacher.username) in cname): + print("Incorrect naming format") + questions = [ { 'type': 'input', 'name': 'cname', 'message': 'Class Name (Must be: _): ', }, - ] - cname = prompt(questions)['cname'] - print(cname) - while (not ("_" + teacher.username) in cname): - print("Incorrect naming format") - questions = [ - { - 'type': 'input', - 'name': 'cname', - 'message': 'Class Name (Must be: _): ', - }, ] cname = prompt(questions)['cname'] teacher.makeClass(cname) soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"] questions = [ - { - 'type': 'list', - 'choices': soption, - 'name': 'students', - 'message': 'Add Students): ', - }, + { + 'type': 'list', + 'choices':soption, + 'name': 'students', + 'message': 'Add Students): ', + }, ] choice = prompt(questions)['students'].split(")")[0] - if ("1" == choice): + if("1" == choice): s = input("Student name: ") teacher.addStudent(s, cname) - if ("2" == choice): + if("2" == choice): print("File must be .txt and have 1 student username per line") path = input("Relative Path: ") - while (not os.path.exists(path)): - if (path == 'N'): + while(not os.path.exists(path)): + if(path == 'N'): return True print(path + " is not a valid path") path = input("Enter file path ('N' to exit): ") @@ -260,7 +265,6 @@ def makeClassTeacher(teacher): teacher.reqAddStudentList(students, cname) return False - def classOptionsTeacher(teacher, course): print("Class: " + course) unconf = getDB(teacher.username, teacher.password, "http://localhost:8000/api/classes/" + course)['unconfirmed'] @@ -268,50 +272,49 @@ def classOptionsTeacher(teacher, course): teacher.addStudent(s, course) options = ['1) Request Student', "2) Add assignment", "3) View student information", "4) Exit"] questions = [ - { - 'type': 'list', - 'name': 'course', - 'choices': options, - 'message': 'Select option: ', - }, + { + 'type': 'list', + 'name': 'course', + 'choices':options, + 'message': 'Select option: ', + }, ] option = prompt(questions)['course'].split(")")[0] return option - def addStudentsTeacher(teacher, course): soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"] questions = [ - { - 'type': 'list', - 'choices': soption, - 'name': 'students', - 'message': 'Add list of students (input path): ', - }, + { + 'type': 'list', + 'choices':soption, + 'name': 'students', + 'message': 'Add list of students (input path): ', + }, ] schoice = prompt(questions)['students'].split(")")[0] - if (schoice == '1'): + if(schoice == '1'): questions = [ - { - 'type': 'input', - 'name': 'student', - 'message': 'Student Name: ', - }, + { + 'type': 'input', + 'name': 'student', + 'message': 'Student Name: ', + }, ] s = prompt(questions)['student'] teacher.reqStudent(s, course) return False - if (schoice == '2'): + if(schoice == '2'): questions = [ - { - 'type': 'input', - 'name': 'path', - 'message': 'Path: ', - }, + { + 'type': 'input', + 'name': 'path', + 'message': 'Path: ', + }, ] path = prompt(questions)['path'] - while (not os.path.exists(path)): - if (path == 'N'): + while(not os.path.exists(path)): + if(path == 'N'): sys.exit(0) print(path + " is not a valid path") path = input("Enter file path ('N' to exit): ") @@ -322,7 +325,6 @@ def addStudentsTeacher(teacher, course): else: return True - def addAssignmentTeacher(teacher, course): nlist = os.listdir(teacher.username + "/" + course) alist = getDB(teacher.username, teacher.password, "http://localhost:8000/api/classes/" + course)['assignments'] @@ -332,36 +334,36 @@ def addAssignmentTeacher(teacher, course): for n in nlist: b = True print(teacher.username + "/" + course + "/" + n) - for a in alist: - if (n in a or n == a): - # print("Assignments: " + n) + for a in alist: + if(n in a or n == a): + #print("Assignments: " + n) b = False - if (not os.path.isdir(teacher.username + "/" + course + "/" + n)): + if(not os.path.isdir(teacher.username + "/" + course + "/" + n)): b = False - if (b): + if(b): tlist.append(n) + nlist = tlist - if (len(nlist) == 0): + if(len(nlist) == 0): print("No new assignments found") - print( - "To make an assignment: make a subdirectory in the " + course + " folder. Add a file within the new folder") + print("To make an assignment: make a subdirectory in the " + course + " folder. Add a file within the new folder") return False questions = [ - { - 'type': 'list', - 'choices': nlist, - 'name': 'assignment', - 'message': 'Select new assignment: ', - }, + { + 'type': 'list', + 'choices':nlist, + 'name': 'assignment', + 'message': 'Select new assignment: ', + }, ] ass = prompt(questions)['assignment'] apath = teacher.username + "/" + course + "/" + ass due = input("Enter due date (Example: 2020-08-11 16:58): ") - due = due + ":33.383124" + due = due + ":33.383124" due = due.strip() f = False - while (not f): + while(not f): try: datetime.datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f') f = True @@ -369,11 +371,10 @@ def addAssignmentTeacher(teacher, course): print("Due-date format is incorrect.") print(due) due = input("Enter due date (Example: 2020-08-11 16:58): ") - due = due + ":33.383124" + due = due + ":33.383124" teacher.addAssignment(apath, course, due) return False - def viewStudentsTeacher(teacher, course): data = getDB(teacher.username, teacher.password, "http://127.0.0.1:8000/api/classes/" + course) students = data["confirmed"] @@ -385,7 +386,7 @@ def viewStudentsTeacher(teacher, course): for s in unconf: print(s) student = input("View student (Enter student's ion username): ") - while ((not student in str(data['confirmed'])) or (not student in str(data['unconfirmed']))): + while((not student in str(data['confirmed'])) or (not student in str(data['unconfirmed']))): print("Student not affiliated with class") student = input("View student ('N' to exit): ") if student == 'N': @@ -393,7 +394,8 @@ def viewStudentsTeacher(teacher, course): print(getDB(teacher.username, teacher.password, "http://127.0.0.1:8000/api/students/" + student + "/")) -###################################################################### + +############################################################################################################################################ def getUser(ion_user, password, utype): @@ -408,6 +410,7 @@ def getUser(ion_user, password, utype): URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/" else: URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/" + print(URL) r = requests.get(url=URL, auth=(ion_user, password)) print(r.json()) if r.status_code == 200: @@ -424,49 +427,32 @@ def getUser(ion_user, password, utype): print(r.status_code) return None - -def patchDB(data, url): - r = requests.patch(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) +def patchDB(USER, PWD, url, data): + r = requests.patch(url = url, data=data, auth=(USER,PWD)) print("PATH:" + str(r.status_code)) return r.json() -def getDB(url): - """ - Sends a GET request to the URL - :param url: URL for request - """ - r = requests.get(url=url, auth=('raffukhondaker', 'hackgroup1')) +def getDB(USER, PWD, url): + r = requests.get(url = url, auth=(USER,PWD)) print("GET:" + str(r.status_code)) return r.json() -def postDB(data, url): - """ - Sends a POST request to the URL - :param url: URL for request - """ - r = requests.post(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) +def postDB(USER, PWD, url, data): + r = requests.post(url = url, data=data, auth=(USER,PWD)) print("POST:" + str(r.status_code)) return r.json() -def putDB(data, url): - """ - Sends a PUT request to the URL - :param url: URL for request - """ - r = requests.put(url=url, data=data, auth=('raffukhondaker', 'hackgroup1')) +def putDB(USER, PWD, url, data): + r = requests.put(url = url, data=data, auth=(USER,PWD)) print("PUT:" + str(r.status_code)) return r.json() -def delDB(url): - """ - Sends a DEL request to the URL - :param url: URL for request - """ - r = requests.delete(url=url, auth=('raffukhondaker', 'hackgroup1')) +def delDB(USER, PWD, url): + r = requests.delete(url = url, auth=(USER,PWD)) print("DELETE:" + str(r.status_code)) return None @@ -514,10 +500,7 @@ def authenticate(): # Linux: chromdriver-linux # Macos: chromdriver-mac # Windows: chromdriver.exe - if 'CLI' in os.getcwd(): - path = os.path.join(os.getcwd(), '../', 'chromedriver-mac') - else: - path = os.path.join(os.getcwd(), 'chromedriver-mac') + path = os.path.join(os.getcwd(),'chromedriver','chromedriver-mac') browser = webdriver.Chrome(path) @@ -577,7 +560,8 @@ def authenticate(): 'is_student': is_student, 'password': pwd, } - profileFile = open(".sprofile", "w") + fname = "." + username + "profile" + profileFile = open(fname, "w") profileFile.write(json.dumps(profile)) profileFile.close() @@ -591,7 +575,8 @@ def authenticate(): 'is_student': is_student, 'password': pwd, } - profileFile = open(".tprofile", "w") + fname = "." + username + "profile" + profileFile = open(fname, "w") profileFile.write(json.dumps(profile)) profileFile.close()