From 9755974491a79a74307c81dd52d2730a3d93e996 Mon Sep 17 00:00:00 2001 From: Raffu Khondaker <2022rkhondak@tjhsst.edu> Date: Wed, 10 Jun 2020 02:25:52 -0400 Subject: [PATCH] f --- CLI/oauth/index.html | 2 +- CLI/s-git.py | 323 +++++++--- CLI/t-git-old.py | 573 ++++++++---------- CLI/t-git.py | 366 ----------- .../api/migrations/0003_auto_20200609_2206.py | 40 ++ .../api/migrations/0004_student_added_to.py | 18 + .../api/migrations/0005_student_completed.py | 18 + Website/api/models.py | 10 +- Website/api/serializers.py | 6 +- 9 files changed, 569 insertions(+), 787 deletions(-) delete mode 100644 CLI/t-git.py create mode 100644 Website/api/migrations/0003_auto_20200609_2206.py create mode 100644 Website/api/migrations/0004_student_added_to.py create mode 100644 Website/api/migrations/0005_student_completed.py diff --git a/CLI/oauth/index.html b/CLI/oauth/index.html index 7afe9a9..e84ea5f 100644 --- a/CLI/oauth/index.html +++ b/CLI/oauth/index.html @@ -14,7 +14,7 @@
- + Sign in with Ion diff --git a/CLI/s-git.py b/CLI/s-git.py index 1203091..0cf4486 100644 --- a/CLI/s-git.py +++ b/CLI/s-git.py @@ -1,101 +1,256 @@ import subprocess import os import requests +import webbrowser import pprint import json +import shutil +import time +import pyperclip #git clone student directory ==> /classes/assignments -def initStudent(ion_user): - #check if git has already been initialized - if(os.path.exists(str(ion_user) +"/" + ".git")): - print("Already synced to: " + str(ion_user)) - return - #get student repo from API - URL = "http://127.0.0.1:8000/students/" + ion_user + "/" - r = requests.get(url = URL, auth=('student','_$YFE#34.9_37jr')) - if(r.status_code == 200): - data = r.json() - repo = data['repo'] - classes = data['classes'] - print(data) - #git clone repo - process = subprocess.Popen(['git', 'clone', repo], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.wait() +#get teacher info from api +def getStudent(ion_user): + URL = "http://127.0.0.1:8000/students/" + ion_user + "/" + r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) + if(r.status_code == 200): + data = r.json() + return data + elif(r.status_code == 404): + return None + print("Make new account!") + elif(r.status_code == 403): + return None + print("Invalid username/password") + else: + return None + print(r.status_code) - # make classes directory - for c in classes: - cpath = str(ion_user) + "/" + c['name'] - if(os.path.exists(cpath)): - print(cpath + " already exists...") - else: - os.mkdir(str(ion_user) + "/" + c['name']) - - #make assignments directory - for a in c['assignments']: - path = str(ion_user) + "/" + c['name'] + "/" + a['name'] - print(path) - if(os.path.exists("/" +path)): - print(path + " already exists...") - else: - os.mkdir(str(ion_user) + "/" + c['name'] + "/" + a['name']) +def getDB(url): + r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) + print("GET:" + str(r.status_code)) + return(r.json()) + +def postDB(data, url): + r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) + print("POST:" + str(r.status_code)) + return(r.json()) + +def putDB(data, url): + r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) + print("PUT:" + str(r.status_code)) + return(r.json()) + +def delDB(url): + r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) + 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() + output = process.communicate()[1] + print(output.decode('utf-8')) + +#################################################################################################################################### + +#public methods: deleteClass, makeClass, update +class Student: + def __init__(self, data): + # teacher info already stored in API + # intitialze fields after GET request + self.first_name=data['first_name'] + self.last_name=data['last_name'] + self.git=data['git'] + self.username=data['ion_user'] + self.url= "http://127.0.0.1:8000/students/" + self.username + "/" + self.email = data['email'] + self.grade = data['grade'] + self.student_id=data['student_id'] + self.completed = data['completed'] + #classes in id form (Example: 4,5) + + #storing actual classes + cid=data['classes'].split(",") + try: + cid.remove('') + except: + pass + try: + cid.remove("") + except: + pass + classes=[] + for c in cid: + url = "http://127.0.0.1:8000/classes/" + str(c) + "/" + classes.append(getDB(url)) - #push to remote repo - os.chdir(ion_user) - process = subprocess.Popen(['git', 'init'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.wait() - process = subprocess.Popen(['git', 'add', '.'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.wait() - process = subprocess.Popen(['git', 'commit', '-m', "First Commit"], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.wait() - process = subprocess.Popen(['git', 'push', '-u', 'origin','master'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.wait() + self.classes = classes + self.sclass=str(data['classes']) + + #storing added_to classes + nid=data['added_to'].split(",") + try: + nid.remove('') + except: + pass + try: + nid.remove("") + except: + pass + nclasses=[] + for c in nid: + url = "http://127.0.0.1:8000/classes/" + str(c) + "/" + nclasses.append(getDB(url)) + + self.new = nclasses + self.snew=str(data['added_to']) + if(os.path.isdir(self.username)): + print("Synced to " + self.username) + else: + os.mkdir(self.username) - elif(r.status_code == 404): - print("Make new account!") - elif(r.status_code == 403): - print("Invalid username/password") - else: - print(r.status_code) + + #update API and Github, all assignments / classes + def update(self): + #lists all classes + ignore=['.DS_Store'] + classes = os.listdir(self.username) + for i in ignore: + try: + classes.remove(i) + except: + pass + + for i in range(len(classes)): + c = classes[i] + path = self.username + "/" + c + #lists all assignments and default files + #push to git + isclass = False + for d in os.listdir(path): + if(d == '.git'): + isclass=True + break + if(isclass): + loc = os.getcwd() + os.chdir(path) + command('git fetch origin') + command('git checkout ' + self.username) + command('git add .') + command('git commit -m ' + self.username + '-update') + command('git push -u origin ' + self.username) + command('git merge master') + os.chdir(loc) + print("Updated: " + c) + else: + print(d + " is not a class") + + #class name format: _ + #add classes from 'new' field + def addClass(self, cid): + if((cid in self.snew) == False): + if((cid in self.sclass) == True): + print("Already enrolled in this class.") + else: + print("Not added by teacher yet.") + return None + data = getDB('http://127.0.0.1:8000/classes/'+cid) -#Teachers + #clone class repo and make student branch (branch name: username) + os.chdir(self.username) + command("git clone " + data['repo']) + os.chdir(data['name']) + command("git checkout " + self.username) + command("git push -u origin " + self.username) -#make student repo by student id -def addStudent(stid, teacher): - os.mkdir(stid) - os.chdir(os.getcwd() + "/" + stid) - process = subprocess.Popen(['git', 'init'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.communicate() - process = subprocess.Popen(['git', 'add', '.'], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.communicate() - process = subprocess.Popen(['git', 'commit', '-m', "First Commit"], stdout=subprocess.PIPE,stderr=subprocess.PIPE) - process.communicate() + self.classes.append(data) + if(len(self.sclass)==0): + self.sclass = data['id'] + else: + self.sclass = self.sclass + "," + str(data['id']) -def addStudents(filename): - print(filename) + #upddate self.new + s="" + nar = '' + for i in range(len(self.new)): + if(self.new[i]['id'] == int(data['id'])): + print("DELETE: " + self.new[i]['name']) + del self.new[i] + #recreate sclass field, using ids + for c in self.new: + s = s + str(c['id']) + "," + nar.append(c) + self.snew=s + self.new=nar + break + + #update teacher instance in db, classes field + data={ + 'first_name':self.first_name, + 'last_name':self.last_name, + 'git':self.git, + 'ion_user':self.username, + 'student_id':self.student_id, + 'added_to':self.snew, + 'url':self.url, + 'classes':self.sclass, + 'email':self.email, + 'grade':self.grade, + 'completed':self.completed + } + print(self.url) + print(putDB(data, self.url)) + return data + + def submit(self, path): + #2022rkhondak/English11_eharris1/Essay1 + #check if valid assignment + parts = path.split("/") + if(len(parts) != 3): + print("Assignment path too short") + return + isclass = False + for c in self.classes: + if(c['name'] == parts[1]): + isclass==True + break + 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): + 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'): + 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={ + 'first_name':self.first_name, + 'last_name':self.last_name, + 'git':self.git, + 'ion_user':self.username, + 'student_id':self.student_id, + 'added_to':self.snew, + 'url':self.url, + 'classes':self.sclass, + 'email':self.email, + 'grade':self.grade, + 'completed':self.completed + } + #print(putDB(data, "http://127.0.0.1:8000/students/" + self.username + "/")) -def addAsignment(name): - print(name) - -def updateAssignment(name): - print(name) - -def comment(filename, text): - print(text) - -#initStudent("2022rkhondak") -ion_user = "2022rkhondak" -headers = {'Content-type': 'application/json'} -data = {'first_name': 'Jeff', - 'git': 'https://github.com/', - 'grade': 10, - 'ion_user': '2022jlol1', - 'last_name': 'lol.', - 'student_id': 11111 - } -data = json.dumps(data) -URL = "http://127.0.0.1:8000/students/" + ion_user + "/" -r = requests.put(url = URL, data= data, headers=headers ,auth=('raffukhondaker','hackgroup1')) -pprint.pprint(r.json()) \ No newline at end of file +data = getStudent("2022rkhondak") +s = Student(data) +s.update() \ No newline at end of file diff --git a/CLI/t-git-old.py b/CLI/t-git-old.py index d2a3316..6e11a47 100644 --- a/CLI/t-git-old.py +++ b/CLI/t-git-old.py @@ -4,46 +4,12 @@ import requests import webbrowser import pprint import json +import shutil +import time +import pyperclip #git clone student directory ==> /classes/assignments -''' -{ - "url": "http://127.0.0.1:8000/teachers/eharris1/", - "first_name": "Errin", - "last_name": "Harris", - "classes": [ - { - "url": "http://127.0.0.1:8000/classes/1/", - "name": "Math5", - "assignments": [ - { - "name": "Week1_HW", - "due_date": "2020-06-07T07:46:30.537197Z", - "url": "http://127.0.0.1:8000/assignments/1/", - "files": [ - { - "name": "instructions.txt" - } - ] - }, - { - "name": "Week2_HW", - "due_date": "2020-06-07T07:46:30.548596Z", - "url": "http://127.0.0.1:8000/assignments/2/", - "files": [ - { - "name": "instructions.txt" - } - ] - } - ], - "repo": "" - } - ], - "git": "therealraffi", - "ion_user": "eharris1" - }, -''' + #get teacher info from api def getTeacher(ion_user): URL = "http://127.0.0.1:8000/teachers/" + ion_user + "/" @@ -63,8 +29,37 @@ def getTeacher(ion_user): def getDB(url): r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) - return r.json() + print("GET:" + str(r.status_code)) + return(r.json()) +def postDB(data, url): + r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) + print("POST:" + str(r.status_code)) + return(r.json()) + +def putDB(data, url): + r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) + print("PUT:" + str(r.status_code)) + return(r.json()) + +def delDB(url): + r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) + 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() + output = process.communicate()[1] + #print(output.decode('utf-8')) + +#################################################################################################################################### + +#public methods: deleteClass, makeClass, update class Teacher: def __init__(self, data): # teacher info already stored in API @@ -74,260 +69,78 @@ class Teacher: self.git=data['git'] self.username=data['ion_user'] self.url= "http://127.0.0.1:8000/teachers/" + self.username + "/" + self.email = data['email'] + #classes in id form (Example: 4,5) - classes=data['classes'].split(",") - cdict = [] - for cid in classes: - adict=[] - c = getDB("http://127.0.0.1:8000/classes/" + cid + "/") - name=c['name'] - repo=c['repo'] - path=c['path'] - teacher=c['teacher'] - id=c['id'] - assignments=c['assignments'].split(",") - dfs = c['default_file'].split(' ') - dfdict=[] - for fid in dfs: - f = getDB("http://127.0.0.1:8000/files/" + fid + "/") - fname=f['name'] - fpath=f['path'] - dfdict.append({ - 'name':fname, - 'path':fpath, - 'classes':classes, - 'assignment':"none", - 'id':fid, - }) - for aid in assignments: - fdict=[] - a = getDB("http://127.0.0.1:8000/assignments/" + aid + "/") - aname= a['name'] - due_date = a['due_date'] - apath=a['path'] - classes=a['classes'] - files = a['files'].split(' ') - for fid in files: - f = getDB("http://127.0.0.1:8000/files/" + fid + "/") - fname=f['name'] - fpath=f['path'] - fdict.append({ - 'name':fname, - 'path':fpath, - 'classes':classes, - 'assignment':aname, - 'id':fid, - }) - adict.append({ - 'name':aname, - 'due_date':due_date, - 'path':apath, - 'classes':classes, - 'teacher':teacher, - 'files':fdict, - }) - cdict.append({ - 'name':name, - 'path':path, - 'teacher':teacher, - 'assignments':adict, - 'default_file':adict, - }) - - self.classes = cdict + cid=data['classes'].split(",") + try: + cid.remove('') + except: + pass + try: + cid.remove("") + except: + pass + classes=[] + for c in cid: + url = "http://127.0.0.1:8000/classes/" + str(c) + "/" + classes.append(getDB(url)) + + self.classes = classes + self.sclass=str(data['classes']) + if(os.path.isdir(self.username)): + print("Synced to " + self.username) + else: + os.mkdir(self.username) - def command(self,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')) - - def initTeacher(self): - if(os.path.exists(self.username )): - print("Already synced to: " + str(self.username)) - return - os.mkdir(self.username) - classes = self.classes - # make classes directory - for c in classes: - cname= c['name'] - cpath = self.username + "/" + cname - - input("Make new Git Repo with name: " + cname + " (Press any key to continue)\n") - webbrowser.open('https://github.com/new') - input("Repo created? (Press any key to continue)\n") - - url='https://github.com/' + self.git + "/" + cname - print(url) - while(requests.get(url).status_code != 200): - print(requests.get(url)) - r = input("Repo not created yet. (Press any key to continue after repo created, or 'N' to exit)\n") - if(r=="N" or r=="No"): - return - cdir = os.getcwd() - os.chdir(self.username) - self.command('git clone ' + url) - os.chdir(cdir) - - #make class directory - #make default files for each class - for filename in c['default_file']: - f=open(cpath+"/"+filename['name'], "w") - f.close() - - #make assignments directory - for a in c['assignments']: - path = cpath + "/" + a['name'] - if(os.path.exists(path)): - print(path + " already exists...") - else: - os.mkdir(path) - f=open(path + "/instructions.txt", "w") - f.close() - - #push to remote repo - os.chdir(cpath) - print(cpath) - self.command('git add .') - self.command('git commit -m Hello_Class') - self.command('git push -u origin master') - def checkGit(self, ass): - for a in ass: - if a =='.git': - return True - return False - - def compareDB(self, fdict, url): - URL = url - r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) - data = r.json()['results'] - allfiles = data - # far = [] - # for f in allfiles: - # far.append(f['path']) - - for f in fdict: - URL = url - in_db = False - pid=None - for dbf in allfiles: - if(dbf['path'] == f['path']): - in_db=True - break - if(in_db==False): - r = requests.post(url = URL, data=f , auth=('raffukhondaker','hackgroup1')) - print("POST: (" + URL + "): " + f['path']) - f['url']=r.json()['url'] - print(r.status_code) - else: - URL = URL + str(dbf['id']) + "/" - r = requests.put(url = URL, data=f , auth=('raffukhondaker','hackgroup1')) - print(r.status_code) - print("UPDATED: (" + URL + "): " + f['path']) - f['url']=r.json()['url'] - f['id']=dbf['id'] - print(f) - - return fdict - #update API and Github, all assignments / classes def update(self): #lists all classes + ignore=['.git','.DS_Store'] classes = os.listdir(self.username) - + for i in ignore: + try: + classes.remove(i) + except: + pass + #list of classes that have been deleted (not with deleteClass) + extra = [] + for c in self.classes: + extra.append(c) + for i in range(len(extra)): + e = extra[i]['path'] + extra[i] = e + print("Extra: "+str(extra)) + print("Local:" + str(classes)) #checks all class directories first for c in classes: path = self.username + "/" + c if(self.checkClass(path) == False): return - cdict = [] - for c in classes: + extra.remove(path) + print("Current classes: " + path) + + for e in extra: + self.deleteClass(e) + + for i in range(len(classes)): + c = classes[i] path = self.username + "/" + c #lists all assignments and default files - ass = os.listdir(path) #if no .git, directory not synced to git or API - if (self.checkGit(ass)==False): + if (self.checkInDB(path)==False): self.addClass(path) else: #push to git loc = os.getcwd() os.chdir(path) - self.command('git add .') - self.command('git commit -m "Update"') - self.command('git push -u origin master') + command('git fetch origin') + command('git pull origin master') + command('git add .') + command('git commit -m "Update"') + command('git push -u origin master') os.chdir(loc) - ass.remove('.git') - - loc = os.getcwd() - os.chdir(path) - repo = self.command('git config --get remote.origin.url') - os.chdir(loc) - - #assignments - adict = [] - #default files for classes - fdict=[] - #default files for assignments - afdict=[] - for a in ass: - aname=a - path = self.username + "/" + c + "/" + a - #need to add option - due_date= '2020-06-07T07:46:30.537197Z', - #check for default file - if(os.path.isfile(path)): - fdict.append({ - 'name':a, - 'path':path - }) - elif(os.path.isdir(path)): - for af in os.listdir(path): - path = path+ "/" + af - if(os.path.isfile(path)): - afdict.append({ - 'name':af, - 'path':path - }) - path = self.username + "/" + c + "/" + a - adict.append({ - 'name':aname, - 'due_date': due_date[0], - 'path':path, - 'files':afdict - }) - - fdict=self.compareDB(fdict, "http://127.0.0.1:8000/files/") - afdict=self.compareDB(afdict,"http://127.0.0.1:8000/files/") - - adict=self.compareDB(adict, 'http://127.0.0.1:8000/assignments/') - - path = self.username + "/" + c - cdict.append({ - 'name':c, - 'repo': repo, - 'path':path, - 'assignments':adict, - 'default_file':fdict, - }) - cdict=self.compareDB(cdict,'http://127.0.0.1:8000/classes/') - - mdict= { - 'first_name':self.first_name, - 'last_name':self.last_name, - 'git':self.git, - 'ion_user':self.username, - 'classes':cdict, - } - - data = json.dumps(mdict) - # r = requests.put(url = 'http://127.0.0.1:8000/teachers/eharris1/', data=data, headers={'Content-type': 'application/json'} , auth=('raffukhondaker','hackgroup1')) - # print(print(r.json())) - #class name format: _ @@ -336,8 +149,11 @@ class Teacher: def checkClass(self,path): cname = path.split("/") 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: _") + print("Incorrect class name: Must be in the format: " + self.username+ "/_, not " + path) return False dirs = os.listdir(path) #checks if there is a file (not within Assignments) in class, need at least 1 @@ -349,98 +165,199 @@ class Teacher: for d in dirs: if(os.path.isfile(d)): deffile=True - if(os.path.isdir(d)) and d != '.git': + else: #checks if there is a file in an Assignment, need at least 1 as_file = False - asdir = os.listdir(d) + asdir = os.listdir(path + "/" + d) for a in asdir: - if(os.path.isfile(a)): + if(os.path.isfile(path + "/" + d + "/" +a)): as_file=True if(as_file==False): - as_bad = a + as_bad = d break if(as_file==False): print("Assignment '" + as_bad + "' does not have a default file!") return False - if(deffile): + if(deffile==False): print("Need a default file in the " + path + " Directory!") return False return True + + def checkInDB(self, path): + n = path.split("/") + n = n[len(n)-1] + for c in self.classes: + if(n == c['name']): + return True + return False #adds class to git, not API + #Assuming valid class name def addClasstoGit(self, path): cname = path.split("/") cname = cname[len(cname)-1] #push to remote repo - if(self.checkClass(path)): + url='https://github.com/' + self.git + "/" + cname + if(requests.get(url).status_code != 200): input("Make new Git Repo with name: " + cname + " (Press any key to continue)\n") + try: + pyperclip.copy(cname) + print(cname + " copied to clipboard.") + except: + pass + time.sleep(2) webbrowser.open('https://github.com/new') input("Repo created? (Press any key to continue)\n") - url='https://github.com/' + self.git + "/" + cname print(url) while(requests.get(url).status_code != 200): - print(requests.get(url)) r = input("Repo not created yet. (Press any key to continue after repo created, or 'N' to exit)\n") if(r=="N" or r=="No"): return None cdir = os.getcwd() os.chdir(path) - self.command('git init') - self.command('git add .') - self.command('git commit -m Hello_Class') - self.command('git remote add origin ' + url + '.git') - self.command('git push -u origin master') - os.chdir(cdir) + command('git init') + command('git add .') + command('git commit -m Hello_Class') + command('git remote add origin ' + url + '.git') + command('git push -u origin master') + else: + cdir = os.getcwd() + os.chdir(path) + print("Repo already exists. Cloning instead.") + command('git clone') + command('git fetch origin') + command('git pull') + command('git add .') + command('git commit -m Hello_Class') + command('git push -u origin master') + os.chdir(cdir) + print(cdir) + data={ + 'name':cname, + 'repo':url, + 'path':path, + 'teacher':self.username, + } + return data + + #make class from existing directory, add to git and api + def addClass(self, path): + if (self.checkClass(path)): + data = self.addClasstoGit(path) + #make class instance in db + data = postDB(data, 'http://127.0.0.1:8000/classes/') + #add to instance + #upate self.classes + self.classes.append(data) + if(len(self.sclass)==0): + self.sclass = data['id'] + else: + self.sclass = self.sclass + "," + str(data['id']) + + #update teacher instance in db, classes field + data={ + 'first_name':self.first_name, + 'last_name':self.last_name, + 'git':self.git, + 'ion_user':self.username, + 'url':self.url, + 'classes':self.sclass, + 'email':self.email + } + putDB(data, self.url) + + return data #make a new class from scratch - def makeClass(self, subject): - cname = subject + "_" + self.username - os.chdir(self.username) + #subject: string, assignments: list + #class name must be: _ + def makeClass(self, cname, assignments): #check if class exists - if(os.path.exists(cname)): - print("Already synced to: " + str(self.username)) + path = self.username + "/" + cname + if(os.path.exists(path)): + print("Class already exists: " + cname) return else: - os.mkdir(cname) - f=open(cname + "/README.md", "w") + if((("_" + self.username) in cname) == False): + print("class name must be: "+ cname + "_" + self.username) + return + cdir = os.getcwd() + os.mkdir(path) + f=open(path + "/README.md", "w") f.close() #push to remote repo - os.chdir(cname) - command(self, 'git init') - command(self, 'git add .') - command(self, 'git commit -m "Hello Class!"') - #git remote add origin git@github.com:alexpchin/.git - command(self, 'git remote add origin git@github.com:'+ self.git + "/" + cname + ".git") - command(self, 'git push -u origin master') + os.chdir(path) + for a in assignments: + os.mkdir(a) + f=open(a + "/instructions.txt", "w") + f.close() + os.chdir(cdir) - cinfo=[ - { - "name":cname, - "assignments":[], - "repo": "https://github.com:" + self.git + "/" + cname + ".git", - "default_file": [ - { - "name":"README.md" - } - ] - } - ] + data = self.addClass(path) + return data + + def deleteClass(self, path): + if(os.path.exists(path) == False): + print(path + " does not exist locally.") + resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ") + if(resp != 'y'): + return - #update rest API - self.classes.append(cinfo) - update(self) - data = { - "url": self.url, - "first_name": self.first_name, - "last_name": self.first_name, - "classes": self.classes, - "git": self.git, - "ion_user": self.username - }, - r = requests.put(url = self.url, data= data, headers={'Content-type': 'application/json'} ,auth=('raffukhondaker','hackgroup1')) + cname = path.split("/") + cname = cname[len(cname)-1] + cid = None + repo = '' + for c in self.classes: + if cname == c['name']: + cid = str(c['id']) + repo = c['repo'] + + #remove from api + for i in range(len(self.classes)): + if(self.classes[i]['id'] == int(cid)): + print("DELETE: " + self.classes[i]['name']) + del self.classes[i] + s="" + #recreate sclass field, using ids + for c in self.classes: + s = s + str(c['id']) + "," + print(s) + s = s[:-1] + print(s) + data={ + 'first_name':self.first_name, + 'last_name':self.last_name, + 'git':self.git, + 'ion_user':self.username, + 'url':self.url, + 'classes':s, + 'email':self.email + } + print(putDB(data, self.url)) + delDB("http://127.0.0.1:8000/classes/" + cid + "/") + break + + #remove locally + try: + shutil.rmtree(path) + except: + pass + + #remove from git + input("Delete repository: " + cname + ". Scroll to the bottom of the page and press 'Delete this repository' (Press any key to continue) ") + print(repo) + time.sleep(2) + webbrowser.open(repo + "/settings") + input("Repo deleted? (Press any key to continue) ") + + print(repo) + while(requests.get(repo).status_code == 200): + r = input("Repo still no deleted yet. (Press any key to continue after repo deleted, or 'N' to exit)\n") + if(r=="N" or r=="No" or r=='n'): + return None #make student repo by student id def addStudent(self,stid): @@ -449,9 +366,7 @@ class Teacher: def comment(self): print("heheheh") -# data = getData("eharris1") -data={'url': 'http://127.0.0.1:8000/teachers/eharris1/', 'first_name': 'Errin', 'last_name': 'Harris', 'git': 'therealraffi', 'ion_user': 'eharris1', 'classes': [{'url': 'http://127.0.0.1:8000/classes/1/', 'name': 'Math5_eharris1', 'repo': 'http://127.0.0.1:8000/assignments/3/', 'assignments': [{'name': 'Week1_HW', 'due_date': '2020-06-07T07:46:30.537197Z', 'url': 'http://127.0.0.1:8000/assignments/1/', 'files': [{'name': 'instructions.txt'}]}, {'name': 'Week2_HW', 'due_date': '2020-06-07T07:46:30.548596Z', 'url': 'http://127.0.0.1:8000/assignments/2/', 'files': [{'name': 'instructions.txt'}]}], 'default_file': [{'name': 'instructions.txt'}]}]} +data = getTeacher("eharris1") t = Teacher(data) +t.makeClass('English11_eharris1', ["Essay1"]) t.update() - - diff --git a/CLI/t-git.py b/CLI/t-git.py deleted file mode 100644 index 9c2f4e9..0000000 --- a/CLI/t-git.py +++ /dev/null @@ -1,366 +0,0 @@ -import subprocess -import os -import requests -import webbrowser -import pprint -import json -import shutil -import time -import pyperclip - -#git clone student directory ==> /classes/assignments - -#get teacher info from api -def getTeacher(ion_user): - URL = "http://127.0.0.1:8000/teachers/" + ion_user + "/" - r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) - if(r.status_code == 200): - data = r.json() - return data - elif(r.status_code == 404): - return None - print("Make new account!") - 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')) - print("GET:" + str(r.status_code)) - return(r.json()) - -def postDB(data, url): - r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("POST:" + str(r.status_code)) - return(r.json()) - -def putDB(data, url): - r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("PUT:" + str(r.status_code)) - return(r.json()) - -def delDB(url): - r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) - 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() - output = process.communicate()[1] - #print(output.decode('utf-8')) - -#public methods: deleteClass, makeClass, update -class Teacher: - def __init__(self, data): - # teacher info already stored in API - # intitialze fields after GET request - self.first_name=data['first_name'] - self.last_name=data['last_name'] - self.git=data['git'] - self.username=data['ion_user'] - self.url= "http://127.0.0.1:8000/teachers/" + self.username + "/" - #classes in id form (Example: 4,5) - - cid=data['classes'].split(",") - try: - cid.remove('') - except: - pass - try: - cid.remove("") - except: - pass - classes=[] - for c in cid: - url = "http://127.0.0.1:8000/classes/" + str(c) + "/" - classes.append(getDB(url)) - - self.classes = classes - self.sclass=str(data['classes']) - if(os.path.isdir(self.username)): - print("Synced to " + self.username) - else: - os.mkdir(self.username) - - #update API and Github, all assignments / classes - def update(self): - #lists all classes - ignore=['.git','.DS_Store'] - classes = os.listdir(self.username) - for i in ignore: - try: - classes.remove(i) - except: - pass - #list of classes that have been deleted (not with deleteClass) - extra = [] - for c in self.classes: - extra.append(c) - for i in range(len(extra)): - e = extra[i]['path'] - extra[i] = e - print("Extra: "+str(extra)) - print("Local:" + str(classes)) - #checks all class directories first - for c in classes: - path = self.username + "/" + c - if(self.checkClass(path) == False): - return - extra.remove(path) - print("Current classes: " + path) - - for e in extra: - self.deleteClass(e) - - for i in range(len(classes)): - c = classes[i] - path = self.username + "/" + c - #lists all assignments and default files - #if no .git, directory not synced to git or API - if (self.checkInDB(path)==False): - self.addClass(path) - else: - #push to git - loc = os.getcwd() - os.chdir(path) - command('git fetch origin') - command('git pull origin master') - command('git add .') - command('git commit -m "Update"') - command('git push -u origin master') - os.chdir(loc) - - #class name format: _ - - #turn existing directory into class, Pre-condition: directory exists - #relative path to class: 2022rkhondak/Math4 - def checkClass(self,path): - cname = path.split("/") - 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+ "/_, not " + path) - return False - dirs = os.listdir(path) - #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) - as_file = True - as_bad = "" - - for d in dirs: - if(os.path.isfile(d)): - deffile=True - else: - #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): - as_bad = d - break - if(as_file==False): - print("Assignment '" + as_bad + "' does not have a default file!") - return False - - if(deffile==False): - print("Need a default file in the " + path + " Directory!") - return False - return True - - def checkInDB(self, path): - n = path.split("/") - n = n[len(n)-1] - for c in self.classes: - if(n == c['name']): - return True - return False - - #adds class to git, not API - #Assuming valid class name - def addClasstoGit(self, path): - cname = path.split("/") - cname = cname[len(cname)-1] - #push to remote repo - url='https://github.com/' + self.git + "/" + cname - if(requests.get(url).status_code != 200): - input("Make new Git Repo with name: " + cname + " (Press any key to continue)\n") - try: - pyperclip.copy(cname) - print(cname + " copied to clipboard.") - except: - pass - time.sleep(2) - webbrowser.open('https://github.com/new') - input("Repo created? (Press any key to continue)\n") - - print(url) - while(requests.get(url).status_code != 200): - r = input("Repo not created yet. (Press any key to continue after repo created, or 'N' to exit)\n") - if(r=="N" or r=="No"): - return None - cdir = os.getcwd() - os.chdir(path) - command('git init') - command('git add .') - command('git commit -m Hello_Class') - command('git remote add origin ' + url + '.git') - command('git push -u origin master') - else: - cdir = os.getcwd() - os.chdir(path) - print("Repo already exists. Cloning instead.") - command('git clone') - command('git fetch origin') - command('git pull') - command('git add .') - command('git commit -m Hello_Class') - command('git push -u origin master') - os.chdir(cdir) - print(cdir) - data={ - 'name':cname, - 'repo':url, - 'path':path, - 'teacher':self.username - } - return data - - #make class from existing directory, add to git and api - def addClass(self, path): - if (self.checkClass(path)): - data = self.addClasstoGit(path) - #make class instance in db - data = postDB(data, 'http://127.0.0.1:8000/classes/') - #add to instance - #upate self.classes - self.classes.append(data) - if(len(self.sclass)==0): - self.sclass = data['id'] - else: - self.sclass = self.sclass + "," + str(data['id']) - - #update teacher instance in db, classes field - data={ - 'first_name':self.first_name, - 'last_name':self.last_name, - 'git':self.git, - 'ion_user':self.username, - 'url':self.url, - 'classes':self.sclass - } - putDB(data, self.url) - - return data - - - #make a new class from scratch - #subject: string, assignments: list - #class name must be: _ - def makeClass(self, cname, assignments): - #check if class exists - path = self.username + "/" + cname - if(os.path.exists(path)): - print("Class already exists: " + cname) - return - else: - if((("_" + self.username) in cname) == False): - print("class name must be: "+ cname + "_" + self.username) - return - cdir = os.getcwd() - os.mkdir(path) - f=open(path + "/README.md", "w") - f.close() - #push to remote repo - os.chdir(path) - for a in assignments: - os.mkdir(a) - f=open(a + "/instructions.txt", "w") - f.close() - os.chdir(cdir) - - data = self.addClass(path) - return data - - def deleteClass(self, path): - if(os.path.exists(path) == False): - print(path + " does not exist locally.") - resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ") - if(resp != 'y'): - return - - cname = path.split("/") - cname = cname[len(cname)-1] - cid = None - repo = '' - for c in self.classes: - if cname == c['name']: - cid = str(c['id']) - repo = c['repo'] - - #remove from api - for i in range(len(self.classes)): - if(self.classes[i]['id'] == int(cid)): - print("DELETE: " + self.classes[i]['name']) - del self.classes[i] - s="" - #recreate sclass field, using ids - for c in self.classes: - s = s + str(c['id']) + "," - print(s) - s = s[:-1] - print(s) - data={ - 'first_name':self.first_name, - 'last_name':self.last_name, - 'git':self.git, - 'ion_user':self.username, - 'url':self.url, - 'classes':s - } - print(putDB(data, self.url)) - delDB("http://127.0.0.1:8000/classes/" + cid + "/") - break - - #remove locally - try: - shutil.rmtree(path) - except: - pass - - #remove from git - input("Delete repository: " + cname + ". Scroll to the bottom of the page and press 'Delete this repository' (Press any key to continue) ") - print(repo) - time.sleep(2) - webbrowser.open(repo + "/settings") - input("Repo deleted? (Press any key to continue) ") - - print(repo) - while(requests.get(repo).status_code == 200): - r = input("Repo still no deleted yet. (Press any key to continue after repo deleted, or 'N' to exit)\n") - if(r=="N" or r=="No" or r=='n'): - return None - -#make student repo by student id - def addStudent(self,stid): - print(stid) - - def comment(self): - print("heheheh") - -data = getTeacher("eharris1") -t = Teacher(data) -t.makeClass('English11_eharris1', ["Essay1"]) -t.update() diff --git a/Website/api/migrations/0003_auto_20200609_2206.py b/Website/api/migrations/0003_auto_20200609_2206.py new file mode 100644 index 0000000..d33709f --- /dev/null +++ b/Website/api/migrations/0003_auto_20200609_2206.py @@ -0,0 +1,40 @@ +# Generated by Django 3.0.7 on 2020-06-09 22:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0002_auto_20200609_0358'), + ] + + operations = [ + migrations.RemoveField( + model_name='student', + name='repo', + ), + migrations.RemoveField( + model_name='student', + name='webmail', + ), + migrations.AddField( + model_name='student', + name='email', + field=models.CharField(blank=True, default='', max_length=100), + ), + migrations.AddField( + model_name='teacher', + name='email', + field=models.CharField(blank=True, default='', max_length=100), + ), + migrations.RemoveField( + model_name='student', + name='classes', + ), + migrations.AddField( + model_name='student', + name='classes', + field=models.CharField(blank=True, default='', max_length=100), + ), + ] diff --git a/Website/api/migrations/0004_student_added_to.py b/Website/api/migrations/0004_student_added_to.py new file mode 100644 index 0000000..71ed04f --- /dev/null +++ b/Website/api/migrations/0004_student_added_to.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.7 on 2020-06-09 22:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0003_auto_20200609_2206'), + ] + + operations = [ + migrations.AddField( + model_name='student', + name='added_to', + field=models.CharField(blank=True, default='', max_length=100), + ), + ] diff --git a/Website/api/migrations/0005_student_completed.py b/Website/api/migrations/0005_student_completed.py new file mode 100644 index 0000000..28d0f9b --- /dev/null +++ b/Website/api/migrations/0005_student_completed.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.7 on 2020-06-10 01:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_student_added_to'), + ] + + operations = [ + migrations.AddField( + model_name='student', + name='completed', + field=models.TextField(blank=True, default=''), + ), + ] diff --git a/Website/api/models.py b/Website/api/models.py index a8770e4..71cad70 100644 --- a/Website/api/models.py +++ b/Website/api/models.py @@ -39,6 +39,7 @@ class Teacher(models.Model): classes=models.CharField(max_length=100, default="", blank=True) ion_user=models.CharField(primary_key=True, max_length=100) git=models.CharField(max_length=100) + email=models.CharField(max_length=100, default="", blank=True) class Student(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -46,12 +47,13 @@ class Student(models.Model): last_name = models.CharField(max_length=100) student_id = models.IntegerField() ion_user=models.CharField(primary_key=True, max_length=100) - webmail = models.EmailField(blank=True) + email=models.CharField(max_length=100, default="", blank=True) grade = models.IntegerField() git=models.CharField(max_length=100) - classes = models.ManyToManyField(Classes, default="") - repo = models.URLField(default="") - + 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): return super(Student, self).save(*args, **kwargs) diff --git a/Website/api/serializers.py b/Website/api/serializers.py index ca13238..f88fe97 100644 --- a/Website/api/serializers.py +++ b/Website/api/serializers.py @@ -23,15 +23,15 @@ class ClassesSerializer(serializers.HyperlinkedModelSerializer): fields = ['url', 'name', 'repo','path', "teacher",'assignments',"default_file",'id'] class StudentSerializer(serializers.HyperlinkedModelSerializer): - classes = ClassesSerializer(many=True, read_only=True,allow_null=True) + # classes = ClassesSerializer(many=True, read_only=True,allow_null=True) class Meta: model = Student - fields = ['url', 'first_name', 'last_name', 'grade','webmail','student_id', 'git','repo','ion_user','classes'] + fields = ['url', 'first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed'] class TeacherSerializer(serializers.ModelSerializer): # classes = ClassesSerializer(many=True, read_only=True,allow_null=True) class Meta: model = Teacher - fields = ['url', 'first_name', 'last_name','git','ion_user','classes'] + fields = ['url', 'first_name', 'last_name','git','ion_user', 'email','classes']