Merge remote-tracking branch 'origin/master'

This commit is contained in:
Rushil Umaretiya 2020-06-16 22:02:03 -04:00
commit 2a99716650
35 changed files with 139889 additions and 549 deletions

1
.2023rumaretiprofile Normal file
View File

@ -0,0 +1 @@
{"username": "2022rkhondak", "grade": 9, "is_student": true, "password": "hackgroup1"}

1
.rushilwizprofile Normal file
View File

@ -0,0 +1 @@
{"username": "rushilwiz", "grade": 69, "is_student": true, "password": "a"}

1
.sstern1profile Normal file
View File

@ -0,0 +1 @@
{"username": "eharris1", "is_student": false, "password": "hackgroup1"}

View File

@ -9,77 +9,128 @@ import time
import pyperclip
import datetime
#git clone student directory ==> <student-id>/classes/assignments
#get teacher info from api
def getStudent(ion_user):
# git clone student directory ==> <student-id>/classes/assignments
# get teacher info from api
def getStudent(ion_user, password):
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):
elif (r.status_code == 404):
return None
print("Make new account!")
elif(r.status_code == 403):
elif (r.status_code == 403):
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
#makes a GET request to given url, returns dict
def getDB(user, pwd, url):
"""
Sends a GET request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(user, pwd))
print("GET:" + str(r.status_code))
return(r.json())
def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
#makes a PATCH (updates instance) request to given url, returns dict
def patchDB(user, pwd, data, url):
"""
Sends a PATCH request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
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(user, pwd, data, url):
"""
Sends a POST request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(user, pwd))
print("POST:" + str(r.status_code))
return(r.json())
return r.json()
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
#makes a PUT (overwrites instance) request to given url, returns dict
def putDB(user, pwd, data, url):
"""
Sends a PUT request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(user, pwd))
print("PUT:" + str(r.status_code))
return(r.json())
return r.json()
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PATH:" + str(r.status_code))
return(r.json())
def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1'))
#makes a DELETE (delete instance) request to given url, returns dict
def delDB(user, pwd, url):
"""
Sends a DELETE request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(user, pwd))
print("DELETE:" + str(r.status_code))
return None
def command(command):
ar = []
command = command.split(" ")
for c in command:
ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
process = subprocess.Popen(ar, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0]
print(output.decode('utf-8'))
return output.decode('utf-8')
####################################################################################################################################
#public methods: deleteClass, makeClass, update
# 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
self.git=data['git']
self.username=data['ion_user']
self.url= "http://127.0.0.1:8000/api/students/" + self.username + "/"
self.git = data['git']
self.username = data['ion_user']
self.url = "http://127.0.0.1:8000/api/students/" + self.username + "/"
self.grade = data['grade']
self.completed = data['completed']
self.user = data['user']
#classes in id form (Example: 4,5)
#storing actual classes
cid=data['classes'].split(",")
self.password = password
self.completed = data['completed']
# classes in id form (Example: 4,5)
# storing actual classes
cid = data['classes'].split(",")
try:
cid.remove('')
except:
@ -88,16 +139,16 @@ class Student:
cid.remove("")
except:
pass
classes=[]
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'])
self.sclass = str(data['classes'])
#storing added_to classes
nid=data['added_to'].split(",")
# storing added_to classes
nid = data['added_to'].split(",")
try:
nid.remove('')
except:
@ -106,21 +157,21 @@ class Student:
nid.remove("")
except:
pass
nclasses=[]
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'])
self.snew = str(data['added_to'])
self.repo = data['repo']
if(os.path.isdir(self.username) == False):
if(self.repo == ""):
user= self.git
pwd= input("Enter Github password: ")
#curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url= "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
if (os.path.isdir(self.username) == False):
if (self.repo == ""):
user = self.git
pwd = input("Enter Github password: ")
# curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url = "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
print(url)
os.system(url)
cdir = os.getcwd()
@ -133,10 +184,10 @@ class Student:
command('git push -u origin master')
os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={
'repo':self.repo
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):
@ -151,29 +202,29 @@ 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", "")
due = datetime.datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
diff = now - due
zero = datetime.timedelta(0,0)
#check due ddate is in span range is now past date (- timdelta)
if(diff < span and diff > zero):
print(a + " due in:" + str(now-due))
zero = datetime.timedelta(0, 0)
# check due ddate is in span range is now past date (- timdelta)
if (diff < span and diff > zero):
print(a + " due in:" + str(now - due))
except Exception as e:
print(e)
pass
#update API and Github, all assignments / classes
# update API and Github, all assignments / classes
def update(self):
cdir = os.getcwd()
os.chdir(self.username)
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 .")
@ -188,9 +239,9 @@ class Student:
command("git checkout master")
print(os.getcwd())
#updates 1 class, does not switch to master
# updates 1 class, does not switch to master
def updateClass(self, course):
if((course in self.sclass) == False):
if ((course in self.sclass) == False):
print("Class not found")
return
cdir = os.getcwd()
@ -201,45 +252,46 @@ class Student:
command("git pull origin " + course)
command("git push -u origin " + course)
#class name format: <course-name>_<ion_user>
# class name format: <course-name>_<ion_user>
#add classes from 'new' field
# add classes from 'new' field
def addClass(self, cid):
data = getDB('http://127.0.0.1:8000/api/classes/'+ str(cid))
if((cid in self.snew) == False 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 (self.username in data['unconfirmed']) == False):
if ((cid in self.sclass) or (self.username in data['unconfirmed']) == False):
print("Not added by teacher yet.")
return None
#add class teacher as cocllaborator to student repo
# add class teacher as cocllaborator to student repo
print(os.getcwd())
pwd= input("Enter Github password: ")
tgit = getDB("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 + "'"
pwd = input("Enter Github password: ")
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)
cdir = os.getcwd()
path1 = self.username + "/" + self.username
path2 = self.username
if(os.path.isdir(path1)):
os.chdir(path1)
else:
os.chdir(self.username)
command("git clone " + self.repo)
os.chdir(self.username)
# path1 = self.username + "/" + self.username
# path2 = self.username
# if(os.path.isdir(path1)):
# os.chdir(path1)
# else:
# os.chdir(self.username)
# command("git clone " + self.repo)
# os.chdir(self.username)
#push to git, start at master
os.chdir(self.username)
# push to git, start at master
#os.chdir(self.username)
command("git checkout master")
command("git branch " + data['name'])
command("git commit -m initial")
command("git push origin " + data['name'])
command("git checkout master")
#git clone --single-branch --branch <branchname> <remote-repo>
# git clone --single-branch --branch <branchname> <remote-repo>
os.chdir(cdir)
# data['unconfirmed'] = data['unconfirmed'].replace("," + self.username, "")
@ -250,78 +302,78 @@ class Student:
# print(data['confirmed'])
# print(putDB(data, 'http://127.0.0.1:8000/api/classes/'+ str(cid) + "/"))
#add teacher as collaborator
#curl -i -u "USER:PASSWORDD" -X PUT -d '' 'https://api.github.com/repos/USER/REPO/collaborators/COLLABORATOR'
# add teacher as collaborator
# curl -i -u "USER:PASSWORDD" -X PUT -d '' 'https://api.github.com/repos/USER/REPO/collaborators/COLLABORATOR'
user = self.git
self.classes.append(data)
if(len(self.sclass)==0):
if (len(self.sclass) == 0):
self.sclass = data['name']
else:
self.sclass = self.sclass + "," + str(data['name'])
#upddate self.new
snew=""
# upddate self.new
snew = ""
new = []
for i in range(len(self.new)):
if(self.new[i]['name'] == data['name']):
if (self.new[i]['name'] == data['name']):
del self.new[i]
#recreate sclass field, using ids
# 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)))
self.snew=snew
self.new=new
new.append(getDB(self.username, self.password,"http://127.0.0.1:8000/api/classes/" + str(cid)))
self.snew = snew
self.new = new
break
#update teacher instance in db, classes field
data={
'user':self.user,
'added_to':self.snew,
'classes':self.sclass
# update teacher instance in db, classes field
data = {
'user': self.user,
'added_to': self.snew,
'classes': self.sclass
}
print(self.url)
print(patchDB(data, self.url))
print(patchDB(self.username, self.password,data, self.url))
return data
def submit(self, path):
#2022rkhondak/English11_eharris1/Essay1
#check if valid assignment
# 2022rkhondak/English11_eharris1/Essay1
# check if valid assignment
parts = path.split("/")
if(len(parts) != 3):
if (len(parts) != 3):
print("Assignment path too short")
return
isclass = False
for c in self.classes:
if(c['name'] == parts[1]):
isclass==True
if (c['name'] == parts[1]):
isclass == True
break
if(parts[0] != self.username and isclass and os.path.isdir(path) == False):
if (parts[0] != self.username and isclass and os.path.isdir(path) == False):
print("Not valid assignment")
return
if((parts[1] + "/" + parts[2]) in self.completed):
if ((parts[1] + "/" + parts[2]) in self.completed):
print(parts[2] + " already submited. ")
# return
resp = input("Are you sure you want to submit? You cannot do this again.(y/N) ")
if(resp == 'y'):
if (resp == 'y'):
os.chdir(self.username + "/" + parts[1])
command("git add .")
command("git commit -m submit")
command("git tag " + parts[1] + "-final")
command("git push -u origin " + self.username + " --tags")
self.completed = self.completed + "," + parts[1] + "/" + parts[2]
data={
'user':self.user,
'git':self.git,
'ion_user':self.username,
'student_id':self.student_id,
'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'grade':self.grade,
'completed':self.completed
data = {
'user': self.user,
'git': self.git,
'ion_user': self.username,
'student_id': self.student_id,
'added_to': self.snew,
'url': self.url,
'classes': self.sclass,
'grade': self.grade,
'completed': self.completed
}
#print(putDB(data, "http://127.0.0.1:8000/api/students/" + self.username + "/"))
# print(putDB(data, "http://127.0.0.1:8000/api/students/" + self.username + "/"))
def viewClass(self, courses):
self.update()
@ -331,7 +383,8 @@ class Student:
if c['name'] == courses:
command("git checkout " + courses)
print(os.listdir())
break
os.chdir(cdir)
return
os.chdir(cdir)
print("Class not found")
return
@ -348,14 +401,15 @@ class Student:
command("git add .")
command("git commit -m update")
command('git checkout ' + course)
time.sleep(5)
ass = os.listdir()
oname = ''
inclass = False
for a in ass:
if a == assignment:
if a in assignment:
inclass = True
oname = a + "_" + course
break
if(inclass == False):
if (inclass == False):
print(assignment + " not an assignment of " + course)
command('git checkout master')
os.chdir(cdir)
@ -367,10 +421,16 @@ class Student:
command("git tag " + assignment + "-final")
command("git push -u origin " + course + " --tags")
command('git checkout master')
self.completed = assignment + "," + self.completed
data = {
'completed': self.completed
}
patchDB(self.username, self.password, data, self.url)
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()
@ -379,6 +439,7 @@ class Student:
def main():
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()

View File

@ -9,6 +9,8 @@ import time
import pyperclip
from distutils.dir_util import copy_tree
from datetime import datetime
# from django.conf import settings
# import django
@ -21,187 +23,284 @@ from datetime import datetime
# django.setup()
# from ..Website.api.models import *
#git clone student directory ==> <student-id>/classes/assignments
# git clone student directory ==> <student-id>/classes/assignments
#get teacher info from api
def getTeacher(ion_user):
# get teacher info from api
def getTeacher(ion_user, password):
"""
Gets information about a teacher from the api
:param ion_user: a teacher
:param password: the teacher's password
:return: teacher information or error
"""
URL = "http://127.0.0.1:8000/api/teachers/" + ion_user + "/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
if(r.status_code == 200):
r = requests.get(url=URL, auth=(ion_user,password))
print(r.json())
if r.status_code == 200:
data = r.json()
return data
elif(r.status_code == 404):
elif r.status_code == 404:
return None
print("Make new account!")
elif(r.status_code == 403):
elif r.status_code == 403:
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
#makes a GET request to given url, returns dict
def getDB(user, pwd, url):
"""
Sends a GET request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(user, pwd))
print("GET:" + str(r.status_code))
return(r.json())
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
#makes a PATCH (updates instance) request to given url, returns dict
def patchDB(user, pwd, data, url):
"""
Sends a PATCH request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.patch(url=url, data=data, auth=(user, pwd))
print("PATCH:" + str(r.status_code))
return(r.json())
return r.json()
def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
#makes a POST (makes new instance) request to given url, returns dict
def postDB(user, pwd, data, url):
"""
Sends a POST request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(user, pwd))
print("POST:" + str(r.status_code))
return(r.json())
return r.json()
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
#makes a PUT (overwrites instance) request to given url, returns dict
def putDB(user, pwd, data, url):
"""
Sends a PUT request to url
:param user: username
:param pwd: password
:param url: URL for request
:param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(user, pwd))
print("PUT:" + str(r.status_code))
return(r.json())
return r.json()
def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1'))
#makes a DELETE (delete instance) request to given url, returns dict
def delDB(user, pwd, url):
"""
Sends a DELETE request to url
:param user: username
:param pwd: password
:param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(user, pwd))
print("DELETE:" + str(r.status_code))
return None
def command(command):
"""
Runs a shell command
:param command: shell command
"""
ar = []
command = command.split(" ")
for c in command:
ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
process = subprocess.Popen(ar, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[1]
print(output.decode('utf-8'))
####################################################################################################################################
#public methods: deleteClass, makeClass, update
# 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
self.git=data['git']
self.username=data['ion_user']
self.url= "http://127.0.0.1:8000/api/teachers/" + self.username + "/"
"""
Initializes a Teacher with the data from the api
:param data: api data
"""
self.git = data['git']
self.username = data['ion_user']
self.url = "http://127.0.0.1:8000/api/teachers/" + self.username + "/"
self.id = data['user']
#classes in id form (Example: 4,5)
self.password = password
# classes in id form (Example: 4,5)
#array
self.classes=data['classes']
if(os.path.isdir(self.username + "/Students")):
# array
self.classes = data['classes']
if os.path.isdir(self.username + "/Students"):
print("Synced to " + self.username)
existing_classes = os.listdir(self.username)
for c in self.classes:
if not c in str(existing_classes):
os.mkdir(self.username + "/" + c)
print("Updated: " + c)
command("touch " + self.username + "/" + c + "/README.md")
os.makedirs(self.username + "/Students/" + c)
else:
os.makedirs(self.username + "/Students")
#2020-05-11 12:25:00
# 2020-05-11 12:25:00
# class name format: <course-name>_<ion_user>
#class name format: <course-name>_<ion_user>
#turn existing directory into class, Pre-condition: directory exists
#relative path to class: 2022rkhondak/Math4
def checkClass(self,path):
# turn existing directory into class, Pre-condition: directory exists
# relative path to class: 2022rkhondak/Math4
def checkClass(self, path):
"""
Checks if a directory is valid for creating a class
:param path: path to the new class directory
"""
cname = path.split("/")
cname = cname[len(cname)-1]
if(os.path.isfile(path)):
cname = cname[len(cname) - 1]
if os.path.isfile(path):
print(path + " must be in a Class directory.")
return False
if(("_" + self.username) in cname) == False:
print("Incorrect class name: Must be in the format: " + self.username+ "/<course-name>_<ion_user>, not " + path)
if not (("_" + self.username) in cname):
print(
"Incorrect class name: Must be in the format: " + self.username + "/<course-name>_<ion_user>, not " + path)
return False
dirs = os.listdir(path)
#checks if there is a file (not within Assignments) in class, need at least 1
# checks if there is a file (not within Assignments) in class, need at least 1
deffile = False
#checks if there is a file in an Assignment, need at least 1 (default True in case no assignments)
# checks if there is a file in an Assignment, need at least 1 (default True in case no assignments)
as_file = True
as_bad = ""
for d in dirs:
if(os.path.isfile(d)):
deffile=True
if os.path.isfile(d):
deffile = True
else:
#checks if there is a file in an Assignment, need at least 1
# checks if there is a file in an Assignment, need at least 1
as_file = False
asdir = os.listdir(path + "/" + d)
for a in asdir:
if(os.path.isfile(path + "/" + d + "/" +a)):
as_file=True
if(as_file==False):
if os.path.isfile(path + "/" + d + "/" + a):
as_file = True
if not as_file:
as_bad = d
break
if(as_file==False):
if not as_file:
print("Assignment '" + as_bad + "' does not have a default file!")
return False
if(deffile==False):
if not deffile:
print("Need a default file in the " + path + " Directory!")
return False
return True
def checkInDB(self, path):
"""
Checks if "path" is in the database
:param path: path to directory
"""
n = path.split("/")
n = n[len(n)-1]
n = n[len(n) - 1]
for c in self.classes:
if(n == c['name']):
if n == c['name']:
return True
return False
#make class from existing directory, add to git and api
# make class from existing directory, add to git and api
def addClass(self, path):
"""
Creates a class from an existing directory, adding it to the proper git repository and the api
:param path:
"""
cname = path.split("/")
cname = cname[len(cname)-1]
cname = cname[len(cname) - 1]
for c in self.classes:
if c == cname:
print(cname + " already exists.")
return
if (self.checkClass(path)):
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
"owner": self.id
}
#make class instance in db
postDB(data, 'http://127.0.0.1:8000/api/classes/')
# make class instance in db
postDB(self.username, self.password, data, 'http://127.0.0.1:8000/api/classes/')
time.sleep(1)
self.classes.append(cname)
#add to instance
#upate self.classes
# add to instance
# update self.classes
data = {
'classes':self.classes
'classes': self.classes
}
print(self.username)
print(patchDB(data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/"))
print(self.classes)
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
#class name must be: <subject>_<ion_user>
# make a new class from scratch
# subject: string, assignments: list
# class name must be: <subject>_<ion_user>
def makeClass(self, cname):
#check if class exists
"""
Makes a class with its own new directory
:param cname: name of class
"""
# 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
isclass = True
break
if(os.path.exists(path) or isclass):
if os.path.exists(path) or isclass:
print("Class already exists: " + cname)
if(isclass):
if isclass:
print("Class already exists in Database")
return
else:
if((("_" + self.username) in cname) == False):
print("class name must be: "+ cname + "_" + self.username)
if not (("_" + self.username) in cname):
print("class name must be: " + cname + "_" + self.username)
return
cdir = os.getcwd()
os.mkdir(path)
f=open(path + "/README.md", "w")
f = open(path + "/README.md", "w")
f.close()
#push to remote repo
os.makedirs(self.username + "/Students/" + cname)
# push to remote repo
# os.chdir(path)
# for a in assignments:
@ -213,114 +312,136 @@ class Teacher:
self.addClass(path)
def deleteClass(self, path):
if(os.path.exists(path) == False):
"""
Deletes an existing class
:param path: class directory path
"""
if not os.path.exists(path):
print(path + " does not exist locally.")
resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ")
if(resp != 'y'):
if resp != 'y':
return
cname = path.split("/")
cname = cname[len(cname)-1]
cname = cname[len(cname) - 1]
repo = ''
print("DELETE: " + self.classes[i]['name'])
for i in range(len(self.classes)):
c = self.classes[i]
if(c == cname):
if c == cname:
del self.classes[i]
# data={
# '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
# remove locally
try:
shutil.rmtree(path)
except:
pass
#remove from student directories
# remove from student directories
def isStudent(self, student):
r = requests.get(url = "http://127.0.0.1:8000/api/students/" + student + "/", auth=('raffukhondaker','hackgroup1'))
if(r.status_code != 200):
"""
Checks if the student exists
:param student: a student
:return: True if student exists, False otherwise
"""
r = requests.get(url="http://127.0.0.1:8000/api/students/" + student + "/",
auth=(self.username, self.password))
if r.status_code != 200:
return False
return True
def reqStudent(self, sname, cname):
if(self.isStudent(sname) == False):
"""
Request student informatiion from the api
:param sname: student's name
:param cname: class name
:return: True if successful
"""
if not self.isStudent(sname):
print(sname + " does not exist.")
return False
course = getDB("http://127.0.0.1:8000/api/classes/" + cname)
if(sname in str(course['unconfirmed'])):
print (sname + " already requested.")
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
if(sname in str(course['confirmed'])):
print (sname + " alredy enrolled.")
if sname in str(course['confirmed']):
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']
if student['added_to'] == "":
student['added_to'] = course['name']
else:
student['added_to']=student['added_to']+ "," + course['name']
student['added_to'] = student['added_to'] + "," + course['name']
except:
print(sname + " does not exist.")
return False
print(student['added_to'])
data={
'added_to':student['added_to'],
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)+ "/")
if(course['unconfirmed']==[]):
course['unconfirmed']=student['ion_user']
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:
course['unconfirmed']=course['unconfirmed'].append(student['ion_user'])
course['unconfirmed'] = course['unconfirmed'].append(student['ion_user'])
cinfo = {
"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
#git clone confirmed student repo, copy files into repo and push branch
# Student should have confirmed on their endd, but class had not been updated yet
# git clone confirmed student repo, copy files into repo and push branch
def addStudent(self, sname, cname):
if(self.isStudent(sname) == False):
"""
Adds a student to a class
:param sname: student name
:param cname: class name
:return:
"""
if not self.isStudent(sname):
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):
if (os.path.exists(self.username + "/Students/" + cname + "/" + student['ion_user']) or (
student['ion_user'] in course['confirmed']) == True):
print(student['ion_user'] + " already added to class")
return True
if((cname in student['added_to']) == True or (cname in student['classes']) == False):
print(student['ion_user']+ " has not confirmed class yet")
if (cname in student['added_to']) or not (cname in student['classes']):
print(student['ion_user'] + " has not confirmed class yet")
return False
if((student['ion_user'] in course['unconfirmed']) == False):
if not (student['ion_user'] in course['unconfirmed']):
print(course['unconfirmed'])
print(student['ion_user']+" has not been requested to join yet.")
print(student['ion_user'] + " has not been requested to join yet.")
return False
#git clone and make student/class directories
# git clone and make student/class directories
cdir = os.getcwd()
cpath = self.username + "/" + cname
path = self.username + "/Students/" + cname
spath = self.username + "/Students/" + cname + "/" + student['ion_user']
if(os.path.isdir(path) == False):
if not os.path.isdir(path):
os.makedirs(path)
if(os.path.isdir(spath) == False):
if not os.path.isdir(spath):
os.chdir(path)
command("git clone " + student['repo'])
os.chdir(cdir)
#push to git
# push to git
os.chdir(spath)
command('git checkout ' + cname)
command('git pull origin ' + cname)
@ -332,15 +453,15 @@ class Teacher:
command('git push -u origin ' + cname)
os.chdir(cdir)
if(course['confirmed']==[]):
course['confirmed']=student['ion_user']
if not course['confirmed']:
course['confirmed'] = student['ion_user']
else:
course['confirmed'].append(student['ion_user'])
#only 1 pereson on confirmeed
if(len(course['unconfirmed']) == 1):
course['unconfirmed']=[]
#mutiple
# only 1 pereson on confirmeed
if len(course['unconfirmed']) == 1:
course['unconfirmed'] = []
# mutiple
else:
course['unconfirmed'].remove(student['ion_user'])
@ -348,32 +469,45 @@ 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
# goes through list of studennts, tries to add, then request, return unconfirmed students
def reqAddStudentList(self, array, cname):
"""
Runs addStudent() on all students in array
:param array: an array of students
:param cname: class name
:return: students that have not confirmed the request
"""
unconf = []
for i in range(len(array)):
a = array[i]
if(self.addStudent(a, cname) == False):
if not self.addStudent(a, cname):
self.reqStudent(a, cname)
unconf.append(a)
return unconf
#add local path to student directory, make new instance in api
# add local path to student directory, make new instance in api
def addAssignment(self, path, course, due):
"""
Creates an assignment for "course" that is due on "due"
:param path: directory of assignment
:param course: course name
:param due: due date
:return: False if unsuccessful
"""
parts = path.split("/")
aname = parts[len(parts)-1]
aname = parts[len(parts) - 1]
oname = aname + "_" + course
if(os.path.isdir(path) == 0 or len(parts) < 3) or aname in str(self.classes):
if (os.path.isdir(path) == 0 or len(parts) < 3) or aname in str(self.classes):
print("Not valid path.")
return False
if((parts[1] in str(self.classes)) == False):
if not (parts[1] in str(self.classes)):
print("Not in valid class directory")
return False
#parts of assignment name (Essay1, APLit)
# parts of assignment name (Essay1, APLit)
# if((course in aname) == False):
# print("Assignment named incorrectly; could be "+ aname + "_" + course)
# return False
@ -394,15 +528,15 @@ class Teacher:
print("Due-date format is incorrect")
return False
course = getDB("http://127.0.0.1:8000/api/classes/" + course)
if(aname in str(course['assignments'])):
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
print(course['assignments'])
print(aname)
#################### FINISH VERIFYING
if(os.path.exists(os.getcwd() + "/" + self.username + "/Students/" + course['name']) == False):
if not os.path.exists(os.getcwd() + "/" + self.username + "/Students/" + course['name']):
print("No students in this class yet")
return True
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
@ -410,7 +544,7 @@ class Teacher:
for st in slist:
if st in str(course['confirmed']):
spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st)
if(os.path.exists(spath + "/" + aname) == False):
if not os.path.exists(spath + "/" + aname):
os.mkdir(spath + "/" + aname)
print(st)
print(copy_tree(path, spath + "/" + aname))
@ -424,49 +558,50 @@ class Teacher:
else:
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'))
if(r.status_code != 200):
# check if assignment already exists
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
'path': path,
'classes': course['name'],
'teacher': self.username,
'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")
return True
#try to avoid
#copy modified assignments to student directories
# try to avoid
# copy modified assignments to student directories
def updateAssignment(self, path, course, due):
parts = path.split("/")
aname = parts[len(parts)-1]
oname=aname + "_" + course
if(os.path.isdir(path) == False):
aname = parts[len(parts) - 1]
oname = aname + "_" + course
if not os.path.isdir(path):
print(path + " is not an assignment.")
return
try:
if(due != None or due == ""):
if due != None or due == "":
datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
d = {
'due_date':due,
'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:
@ -475,16 +610,16 @@ class Teacher:
print(st)
print(copy_tree(path, spath + "/" + aname))
os.chdir(spath)
#command('git checkout ' + course['name'])
# command('git checkout ' + course['name'])
command('git add .')
command('git commit -m Hello')
command('git pull origin ' + course['name'])
command('git push -u origin ' + course['name'])
os.chdir(cdir)
#pull student's work, no modifications
# pull student's work, no modifications
def getStudents(self, course):
if((course in self.sclass) == False):
if not (course in str(self.classes)):
print(course + " not a class.")
return
path = self.username + "/Students/" + course
@ -497,9 +632,9 @@ 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((student in course['confirmed']) == False):
if not (student in course['confirmed']):
print("Student not in class")
return
except:
@ -508,19 +643,20 @@ class Teacher:
cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course['name'] + "/" + student)
process = subprocess.Popen(['git', 'log', '-' + str(commits), course['name']], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
process = subprocess.Popen(['git', 'log', '-' + str(commits), course['name']], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0].decode('utf-8').split('\n\n')
months = ['Jan', 'Feb', 'Mar', "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
fout = []
for i in range(len(output)):
if("Date" in output[i]):
if "Date" in output[i]:
c = output[i].split("\n")
for k in range(len(c)):
temp = []
if('commit' in c[k]):
if 'commit' in c[k]:
c[k] = c[k].replace('commit', '').strip()
elif('Date:' in c[k]):
elif 'Date:' in c[k]:
c[k] = c[k].replace('Date:', '').strip()
date = c[2].split(" ")
times = date[3].split(":")
@ -529,25 +665,32 @@ class Teacher:
if date[1] == months[m]:
mon = m
d1 = datetime(int(date[4]), mon, int(date[2]), int(times[0]), int(times[1]))
#datetime1 = datetime.strptime('07/11/2019 02:45PM', '%m/%d/%Y %I:%M%p')
fout.append([c[0],d1])
#output[i] = [c[0], d1]
#print(output[i])
# datetime1 = datetime.strptime('07/11/2019 02:45PM', '%m/%d/%Y %I:%M%p')
fout.append([c[0], d1])
# output[i] = [c[0], d1]
# print(output[i])
print(fout)
os.chdir(cdir)
return fout
def getChanges(self, student, course, commits):
course = getDB("http://127.0.0.1:8000/api/classes/" + course + "/")
"""
Checks for new submissions by a student
:param student: the student
:param course: the course
:param commits: commits the CLI has made for the assignment
"""
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]
commit = ar[len(ar) - 1][0]
start = ""
print("END:" + commit)
print("START: " + start)
cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course['name'] + "/" + student)
process = subprocess.Popen(['git', 'diff', commit, '--name-status'], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
process = subprocess.Popen(['git', 'diff', commit, '--name-status'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0].decode('utf-8')
print(output)
os.chdir(cdir)
@ -558,29 +701,30 @@ class Teacher:
'due_date': 2020-06-11 16:58:33.383124
}
'''
#check if assignment changed after due date
# check if assignment changed after due date
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",
# 'classes':course
# }
log = self.getCommits(student, course, 30)
assignment['due_date'] = datetime.strptime(assignment['due_date'], '%Y-%m-%d %H:%M:%S.%f')
assignment['due_date'] = datetime.strptime(assignment['due_date'], '%Y-%m-%dT%H:%M:%S.%fZ')
late = False
cdir = os.getcwd()
os.chdir(self.username + "/Students/" + course + "/" + student)
for l in log:
process = subprocess.Popen(['git', 'show', l[0]], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
process = subprocess.Popen(['git', 'show', l[0]], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = process.poll()
output = process.communicate()[0].decode('utf-8')
if(assignment['name'] in output):
if assignment['name'] in output:
print(l[1])
print(assignment['due_date'])
print("--------------")
if(l[1] > assignment['due_date']):
if l[1] > assignment['due_date']:
print("LATE")
os.chdir(cdir)
return True
@ -589,17 +733,22 @@ class Teacher:
return False
def comment(self):
"""
The ultimate form of laughter
:return: pure joy
"""
print("heheheh")
# data = getTeacher("eharris1")
# t = Teacher(data)
#t.makeClass("APLit_eharris1")
# 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']
#extra = t.reqAddStudentList(ar, "APLit_eharris1")
#print(extra)
#t.addStudent('2022rkhondak', 'APLit_eharris1')
# ar = ['2022rkhondak','2022inafi','2023rumareti']
# extra = t.reqAddStudentList(ar, "APLit_eharris1")
# print(extra)
# t.addStudent('2022rkhondak', 'APLit_eharris1')
# t.getChanges('2022rkhondak','APLit_eharris1', 10)
'''
@ -614,4 +763,3 @@ TO-DO
- check differences between commits
- check if student changes file after submissionn deadline
'''

View File

@ -8,6 +8,7 @@ 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)
log = models.TextField(default="", blank=True)
git=models.CharField(default="", max_length=100, blank=True)
log = models.TextField(default="", blank=True)
repo=models.URLField(default="", blank=True)
@ -19,31 +20,32 @@ class Student(models.Model):
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()
# 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)
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)
description = models.CharField(default="Class Description", max_length=500, blank=True)
repo=models.URLField(default="", blank=True)
path=models.CharField(max_length=100, default="")
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')
@ -61,7 +63,7 @@ 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)
@ -70,7 +72,7 @@ class Teacher(models.Model):
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)

View File

@ -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)

View File

@ -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,33 @@ 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()]
class Meta:
model = Class
fields = ['subject', 'period', 'description', 'unconfirmed']

View File

@ -92,3 +92,13 @@ a.article-title:hover {
.account-heading {
font-size: 2.5rem;
}
.class-card {
text-decoration: none;
color: gray;
}
.class-card:hover {
text-decoration: none;
color: black;
}

View File

@ -34,6 +34,11 @@
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if user.is_authenticated %}
{% if isTeacher %}
<a class="nav-item nav-link" href="{% url 'create-class' %}">Create Class</a>
{% else %}
{% endif %}
<a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
{% endif %}

View File

@ -11,6 +11,12 @@
<small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small>
</div>
</article>
{% empty %}
{% if isTeacher %}
<p class="mr-2">Looks like you haven't made any assignments yet, hit the button in the top right to get started</p>
{% else %}
<p class="mr-2">Looks like there aren't any assignments at the moment, you got lucky this time!</p>
{% endif %}
{% endfor %}
</div>
@ -20,6 +26,8 @@
<ul>
{% for teacher in teachers %}
<li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li>
{% empty %}
<li>No Teachers, weird...</li>
{% endfor %}
</ul>
</div>

View File

@ -0,0 +1,26 @@
{% extends "skoolos/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<legend class="border-bottom mb-4">Classes</legend>
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% empty %}
<li>Not teaching any classes</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Create a new class </legend>
{{ classForm|crispy }}
<!-- mmmm crispy yummm -->
<small class="text-secondary">Use ctrl to select multiple students</small>
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-outline-info">Create</button>
</div>
</form>
</div>
</div>
{% endblock content %}

View File

@ -3,13 +3,25 @@
<div class="content-section">
{% for class in classes %}
<div class="card-columns">
<a class="card" href="/class/{{ class.id }}" style="text-decoration: none;">
<a class="card class-card" href="/class/{{ class.id }}" style="">
<div class="card-body">
<h5 class="card-title">{{ class.name }}</h5>
<h5 class="card-title">{{ class.subject }}</h5>
{% if class.period != 0 %}
<small>Period: {{ class.period }}<br></small>
{% endif %}
{% if class.name %}
<small style="font-size:.75em"><i>{{ class.name }}</i></small>
{% endif %}
<p class="card-text">{{ class.description }}</p>
</div>
</a>
</div>
{% empty %}
{% if isTeacher %}
<p>Looks like you haven't created any classes yet, hit the button in the top right to get started.</p>
{% else %}
<p>Looks like you're not enrolled in any classes at the moment! Ask your teacher if you think this is wrong.</p>
{% endif %}
{% endfor %}
</div>
{% endblock content %}

View File

@ -5,6 +5,7 @@
<div class="media">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">Student</p>
<large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary">
{{ user.email }}
@ -16,6 +17,8 @@
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% empty %}
<li>No classes</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">

View File

@ -5,6 +5,7 @@
<div class="media">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">Teacher</p>
<large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary">
{{ user.email }}
@ -16,6 +17,8 @@
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% empty %}
<li>Not teaching any classes</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">

View File

@ -7,4 +7,5 @@ urlpatterns = [
path('', views.home, name='home'),
path('profile/', views.profile, name='profile'),
path("class/<str:id>", views.classDetail, name="class"),
path("create-class/", views.createClass, name="create-class"),
]

View File

@ -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,55 @@ 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)
newClass = classForm.save(commit=False)
newClass.owner = request.user
newClass.teacher = request.user.username
newClass.name = cleaned_data['subject'].replace(' ', '')[:8].lower() + str(cleaned_data['period']) + "_" + teacher.user.username.lower()
newClass.save()
classObj = classForm.save_m2m()
messages.success(request, cleaned_data['subject'].capitalize() + " has been created!")
print (newClass)
teacher.classes.add(newClass)
for student in newClass.unconfirmed.all():
if student.added_to == "":
student.added_to = newClass.name
else:
student.added_to = student.added_to + "," + newClass.name
student.save()
return redirect('home')
else:
classForm = ClassCreationForm()
context = {
'teacher': teacher,
'classes': teacher.classes.all(),
'classForm': classForm
}
return render(request, "skoolos/createClass.html", context)

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,8 @@
"""
A simple background service to log events in a directory,
check for git commands in bash/zsh history,
and check for non-whitelisted files in the watched directory.
"""
import time
import sys
import os

3
bgservice/bgservice.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
python3 bgservice.py

2
bgservice/run.py Normal file
View File

@ -0,0 +1,2 @@
import bgservice as bg
bg.watch_dir()

View File

@ -1,2 +1,71 @@
Command Line Interface
=====================
1. Making a user:
-------
python skoolos.py
You will be redirected to a login page for the SkoolOS website. If you have already created an account on the website, enter login informatiton. If not, select
the registration button bellow and create an account. Once you create an account via Ion OAuth and SkoolOS, login. The window should close, prompting:
Enter SkoolOS Username:
Enter SkoolOS Password:
Enter the valid SkoolOS username and password. Congratialations, you have successfully logged in.
1. CLI as a teacher:
============
Start the CLI and select your username. For instance, teacher 'eharris1'
python skoolos.py
? Select User: (Use arrow keys)
1) 2022rkhondak
2) eharris1
3) Make new user
You will then be given the choice to select an existing class, Make a new class, or exit the CLI:
? Select class: (Use arrow keys)
Art12_eharris1
English12_eharris1
History12_eharris1
Make New Class
Exit SkoolOS
1. Making a new class:
-------
Select 'Make a New Class'. You will then be prompted to enter a class name. The format for every class must be <subject>_<teacher_username> (Example: Art12_eharris1).
Enter Period (must be a positive integer). You will then be prompted to add students. If you have a list of students, enter the relative path of a text file with the student usernames.
The file must be a .txt file and have one student username per line. If you add an individual student, simply enter their ion username.
one username per line.
? Select class: (Use arrow keys)
Art12_eharris1
English12_eharris1
History12_eharris1
Make New Class
Exit SkoolOS
? Add Students): (Use arrow keys)
1) Add individual student
2) Add list of students through path
3) Exit
? Add Students): 2) Add list of students through path
File must be .txt and have 1 student username per line
Relative Path: students.txt

View File

@ -1,7 +1,3 @@
.. SkoolOS documentation master file, created by
sphinx-quickstart on Tue Jun 16 11:22:02 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to SkoolOS's documentation!
===================================

View File

@ -1,2 +1,16 @@
Installation
============
Git clone repository:
-------
https://gitlab.tjhsst.edu/understudyathon-2020/group-1/schoolos.git
Install repository and create env
-------
cd SkoolOS
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt

View File

View File

View File

View File

View File

@ -1,5 +1,6 @@
appdirs==1.4.3
cachecontrol==0.12.6
chromedriver==2.24.1
click==7.1.2
colorama==0.4.3
contextlib2==0.6.0
@ -52,20 +53,20 @@ yapf==0.30.0
# lazy-object-proxy==1.4.3 # Installed as dependency for astroid
# markupsafe==1.1.1 # Installed as dependency for jinja2
# mccabe==0.6.1 # Installed as dependency for pylint
# msgpack==0.6.2 # Installed as dependency for pynvim, cachecontrol
# oauthlib==3.1.0 # Installed as dependency for requests-oauthlib, django-oauth-toolkit
# msgpack==0.6.2 # Installed as dependency for cachecontrol, pynvim
# oauthlib==3.1.0 # Installed as dependency for django-oauth-toolkit, requests-oauthlib
# packaging==20.1 # Installed as dependency for sphinx
# pillow==7.1.2 # Installed as dependency for wpgtk
# prompt-toolkit==1.0.14 # Installed as dependency for pyinquirer
# psycopg2-binary==2.8.5 # Installed as dependency for django-request-token
# pygments==2.6.1 # Installed as dependency for sphinx, pyinquirer
# pygments==2.6.1 # Installed as dependency for pyinquirer, sphinx
# pyjwt==1.7.1 # Installed as dependency for django-request-token
# pyparsing==2.4.6 # Installed as dependency for packaging
# pytz==2020.1 # Installed as dependency for django, babel
# pytz==2020.1 # Installed as dependency for babel, django
# pywal==3.3.0 # Installed as dependency for wpgtk
# regex==2020.5.14 # Installed as dependency for pyinquirer
# requests==2.23.0 # Installed as dependency for cachecontrol, requests-oauth, django-oauth-toolkit, sphinx, requests-oauthlib
# six==1.15.0 # Installed as dependency for astroid, prompt-toolkit, html5lib, retrying, packaging
# requests==2.23.0 # Installed as dependency for cachecontrol, requests-oauthlib, django-oauth-toolkit, sphinx, requests-oauth
# six==1.15.0 # Installed as dependency for prompt-toolkit, astroid, retrying, html5lib, packaging
# snowballstemmer==2.0.0 # Installed as dependency for sphinx
# sphinxcontrib-applehelp==1.0.2 # Installed as dependency for sphinx
# sphinxcontrib-devhelp==1.0.2 # Installed as dependency for sphinx
@ -73,9 +74,9 @@ yapf==0.30.0
# sphinxcontrib-jsmath==1.0.1 # Installed as dependency for sphinx
# sphinxcontrib-qthelp==1.0.3 # Installed as dependency for sphinx
# sphinxcontrib-serializinghtml==1.1.4 # Installed as dependency for sphinx
# sqlparse==0.3.1 # Installed as dependency for django, django-request-token
# sqlparse==0.3.1 # Installed as dependency for django-request-token, django
# toml==0.10.0 # Installed as dependency for pylint, pep517
# urllib3==1.25.9 # Installed as dependency for selenium, requests
# urllib3==1.25.9 # Installed as dependency for requests, selenium
# wcwidth==0.2.3 # Installed as dependency for prompt-toolkit
# webencodings==0.5.1 # Installed as dependency for html5lib
# wrapt==1.12.1 # Installed as dependency for astroid

View File

@ -1,3 +1,6 @@
"""
The main program file for SkoolOS
"""
import sys
from urllib.parse import urlparse
import requests
@ -94,8 +97,8 @@ def main():
def studentCLI(user, password):
"""
The CLI for students to access
:param user: student username
:param password: student password
@param user: student username
@param password: student password
"""
from CLI import student
data = getUser(user, password, 'student')
@ -113,7 +116,7 @@ def studentCLI(user, password):
def chooseClassStudent(student):
"""
Chooses a class for a student to view and work on
:param student: a student
@param student: a student
:return: a course prompt
"""
carray = student.sclass.split(",")
@ -139,8 +142,8 @@ def classOptionsStudent(student, course):
"""
Allows students to choose what they want to do related to a class
The student can save, exit, or go back
:param student: a student
:param course: a course
@param student: a student
@param course: a course
:return: True if exiting, False if going back
"""
student.viewClass(course)
@ -200,8 +203,8 @@ def classOptionsStudent(student, course):
def teacherCLI(user, password):
"""
The CLI for teachers to access
:param user: teachers username
:param password: teachers password
@param user: teachers username
@param password: teachers password
"""
from CLI import teacher
data = getUser(user, password, 'teacher')
@ -448,7 +451,6 @@ def viewStudentsTeacher(teacher, course):
s = f.split("_")[0]
alist.append(s)
print("Has submitted: " + str(alist))
#Y/N
#put log stuff
@ -458,9 +460,9 @@ def viewStudentsTeacher(teacher, course):
def getUser(ion_user, password, utype):
"""
Returns user information
:param ion_user: user
:param password: user's password
:param utype: type of user (student or teacher
@param ion_user: user
@param password: user's password
@param utype: type of user (student or teacher
:return: api user information
"""
if 'student' in utype:
@ -488,10 +490,10 @@ def getUser(ion_user, password, utype):
def patchDB(USER, PWD, url, data):
"""
Sends a PATCH request to url
:param USER: username
:param PWD: password
:param url: URL for request
:param data: data to request
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.patch(url=url, data=data, auth=(USER, PWD))
@ -502,9 +504,9 @@ def patchDB(USER, PWD, url, data):
def getDB(USER, PWD, url):
"""
Sends a GET request to url
:param USER: username
:param PWD: password
:param url: URL for request
@param USER: username
@param PWD: password
@param url: URL for request
:return: json request response
"""
r = requests.get(url=url, auth=(USER, PWD))
@ -515,10 +517,10 @@ def getDB(USER, PWD, url):
def postDB(USER, PWD, url, data):
"""
Sends a POST request to url
:param USER: username
:param PWD: password
:param url: URL for request
:param data: data to request
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.post(url=url, data=data, auth=(USER, PWD))
@ -529,10 +531,10 @@ def postDB(USER, PWD, url, data):
def putDB(USER, PWD, url, data):
"""
Sends a PUT request to url
:param USER: username
:param PWD: password
:param url: URL for request
:param data: data to request
@param USER: username
@param PWD: password
@param url: URL for request
@param data: data to request
:return: json request response
"""
r = requests.put(url=url, data=data, auth=(USER, PWD))
@ -543,9 +545,9 @@ def putDB(USER, PWD, url, data):
def delDB(USER, PWD, url):
"""
Sends a DELETE request to url
:param USER: username
:param PWD: password
:param url: URL for request
@param USER: username
@param PWD: password
@param url: URL for request
:return: json request response
"""
r = requests.delete(url=url, auth=(USER, PWD))

105
snew.py
View File

@ -1,105 +0,0 @@
import sys
from urllib.parse import urlparse
import requests
from requests_oauthlib import OAuth2Session
from selenium import webdriver
import os.path
import time
import http.server
import socketserver
from threading import Thread
from werkzeug.urls import url_decode
import pprint
from PyInquirer import prompt, print_json
import json
import os
import argparse
import webbrowser
import subprocess
from django.conf import settings
import django
from Website.config.settings import DATABASES, INSTALLED_APPS
INSTALLED_APPS.remove('users.apps.UsersConfig')
INSTALLED_APPS.remove('api')
INSTALLED_APPS.remove('skoolos.apps.SkoolosConfig')
INSTALLED_APPS.append('Website.api')
settings.configure(DATABASES=DATABASES, INSTALLED_APPS=INSTALLED_APPS)
django.setup()
from Website.api.models import *
def command(command):
ar = []
command = command.split(" ")
for c in command:
ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
output = process.communicate()[0]
print(output.decode('utf-8'))
return output.decode('utf-8')
class Students:
def __init__(self, username):
self.student = Student.objects.get(ion_user = username)
#ion id: student.user
if(os.path.isdir(self.student.user) == False):
if(self.student.repo == ""):
user= self.student.git
pwd= input("Enter Github password: ")
#curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url= "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
print(url)
os.system(url)
cdir = os.getcwd()
command('git clone https://github.com/' + self.git + '/' + self.username + '.git')
os.chdir(self.username)
command('git checkout master')
command('touch README.md')
command('git add README.md')
command('git commit -m "Hello"')
command('git push -u origin master')
os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={
'user':self.user,
'git':self.git,
'ion_user':self.username,
'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'grade':self.grade,
'completed':self.completed,
'repo':self.repo
}
print(putDB(data, self.url))
print("Synced to " + self.username)
# c = {
# 'name':'Math5'
# }
# c = Class.objects.get(name='Math5')
# data = requests.get(url = "http://localhost:8000/api/classes/Math5", auth=('raffukhondaker','hackgroup1')).json()
# r = requests.post(url = "http://localhost:8000/api/classes/", data={'name':'English11', 'teacher':'eharris1', 'owner':2}, auth=('raffukhondaker','hackgroup1'))
# print("POST:" + str(r.json()))
# # print(r.json())
# # print(c.name)
# # c = {
# # 'classes':c
# # }
# # print(c)
# r = requests.patch(url = "http://localhost:8000/api/teachers/eharris1/", data={'classes':['English11']}, auth=('raffukhondaker','hackgroup1'))
# print(r.json())
import bgservice.bgservice as bg
bg.watch_dir('2022rkhondak', 'eharris1')
time.sleep(60)
bg.stop_watching()

View File

View File

View File

@ -1 +1,2 @@
2022rkhondak
2023rmama