Merge branch 'master' of https://github.com/sagidayan/SE-Hub into QA

This commit is contained in:
etyemyer 2015-06-21 23:25:11 +03:00
commit 09a64f9bdb
19 changed files with 835 additions and 290 deletions

View file

@ -29,6 +29,7 @@ from SE_API.UserRoutes import user_routes
from SE_API.CampusRoutes import campus_routes from SE_API.CampusRoutes import campus_routes
from SE_API.CourseRoutes import course_routes from SE_API.CourseRoutes import course_routes
from SE_API.ProjectRoutes import project_routes from SE_API.ProjectRoutes import project_routes
from SE_API.TaskRoutes import task_routes
@ -49,6 +50,7 @@ app.register_blueprint(user_routes)
app.register_blueprint(campus_routes) app.register_blueprint(campus_routes)
app.register_blueprint(course_routes) app.register_blueprint(course_routes)
app.register_blueprint(project_routes) app.register_blueprint(project_routes)
app.register_blueprint(task_routes)
auto = Autodoc(app) auto = Autodoc(app)

View file

@ -66,7 +66,7 @@ def create_campus(token):
#check if name already exists #check if name already exists
try: try:
query = Campus.all() query = Campus.all()
query.filter("title = ", payload['title']) query.filter("title =", payload['title'])
for c in query.run(limit=1): for c in query.run(limit=1):
return forbidden("Campus with same name already exists") return forbidden("Campus with same name already exists")
except Exception as e: except Exception as e:
@ -86,7 +86,6 @@ def create_campus(token):
@campus_routes.route('/api/campuses/getAll/<string:token>', methods=['GET']) @campus_routes.route('/api/campuses/getAll/<string:token>', methods=['GET'])
@auto.doc() @auto.doc()
def get_campuses(token): def get_campuses(token):
@ -124,7 +123,11 @@ def get_campuses(token):
query = Campus.all() query = Campus.all()
for c in query.run(): for c in query.run():
arr.append(dict(json.loads(c.to_JSON()))) arr.append(dict(json.loads(c.to_JSON())))
print "ARR:"
print arr print arr
for c in arr:
print"c:"
print c
if len(arr) != 0: if len(arr) != 0:
return Response(response=json.dumps(arr), return Response(response=json.dumps(arr),
status=200, status=200,
@ -137,6 +140,63 @@ def get_campuses(token):
return forbidden("Invalid Token") return forbidden("Invalid Token")
@campus_routes.route('/api/campuses/deleteCampus/<string:token>/<string:campusName>', methods=['DELETE'])
@auto.doc()
def deleteCampus(token,campusName):
"""
<span class="card-title">This Call will delete a specific campus</span>
<br>
<b>Route Parameters</b><br>
- seToken: 'seToken'
- title: 'campusName'
<br>
<br>
<b>Payload</b><br>
- NONE <br>
<br>
<br>
<b>Response</b>
<br>
202 - Deleted campus
<br>
204 - No Matching Campus Found
<br>
....<br>
{<br>
...<br>
}req<br>
]<br>
400 - Bad Request
<br>
403 - Invalid token or not a lecturer!<br>
"""
if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token)
query = Campus.all()
query.filter('master_user_id =',user.key().id())
try:
query.filter('title =', campusName)
except Exception as e:
print e
return bad_request("invalid campus title attribute")
for c in query.run():
db.delete(c)
db.save
return accepted("campus deleted")
return bad_request("no such campus found")
@campus_routes.route('/api/campuses/help') @campus_routes.route('/api/campuses/help')
def documentation(): def documentation():

View file

@ -7,6 +7,8 @@ from GithubAPI.GithubAPI import GitHubAPI_Keys
from google.appengine.ext import db from google.appengine.ext import db
import requests import requests
import datetime import datetime
from operator import itemgetter
from flask import Flask, request, render_template, redirect, abort, Response from flask import Flask, request, render_template, redirect, abort, Response
@ -16,6 +18,8 @@ from flask.ext.autodoc import Autodoc
# DB Models # DB Models
from models.Course import Course from models.Course import Course
from models.Campus import Campus
from models.Message import Message
#Validation Utils Libs #Validation Utils Libs
from SE_API.Validation_Utils import * from SE_API.Validation_Utils import *
@ -27,6 +31,10 @@ course_routes = Blueprint("course_routes", __name__)
auto = Autodoc() auto = Autodoc()
#----------------------------------------------------------
# POST
#----------------------------------------------------------
@course_routes.route('/api/courses/create/<string:token>', methods=['POST']) @course_routes.route('/api/courses/create/<string:token>', methods=['POST'])
@auto.doc() @auto.doc()
def create_course(token): def create_course(token):
@ -92,8 +100,6 @@ def create_course(token):
print e print e
return bad_request() return bad_request()
db.put(course) db.put(course)
db.save db.save
return Response(response=course.to_JSON(), return Response(response=course.to_JSON(),
@ -102,6 +108,63 @@ def create_course(token):
@course_routes.route('/api/courses/createMessage/<string:token>', methods=['POST'])
@auto.doc()
def createMessage(token):
"""
<span class="card-title">This call will create a new Message in the DB</span>
<br>
<b>Route Parameters</b><br>
- seToken: 'seToken'
<br>
<br>
<b>Payload</b><br>
- JSON Object, Example: <br>
{<br>
'courseName': 'Advance Math',<br>
'message': 'The lecture today is canceled'<br>
}<br>
<br>
<br>
<b>Response</b>
<br>
201 - Created
<br>
400 - Bad Request
<br>
403 - Invalid token or not a lecturer
"""
if not request.data:
return bad_request("no data")
if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token)
#try to parse payload
try:
payload = json.loads(request.data)
except Exception as e:
return bad_request("here")
try:
msg = Message(courseName=payload['courseName'], message=payload['message'], msgDate=datetime.datetime.now())
except Exception as e:
print e
return bad_request("there")
db.save(msg)
db.save
return created()
#----------------------------------------------------------
# GET
#----------------------------------------------------------
@course_routes.route('/api/courses/getCourseByCampusName/<string:name>', methods=["GET"]) @course_routes.route('/api/courses/getCourseByCampusName/<string:name>', methods=["GET"])
@auto.doc() @auto.doc()
def getCourseByCampusName(name): def getCourseByCampusName(name):
@ -132,7 +195,7 @@ def getCourseByCampusName(name):
""" """
arr = [] arr = []
query = Course.all() query = Course.all()
query.filter("campusName = ", name) query.filter("campusName=", name)
for c in query.run(): for c in query.run():
arr.append(dict(json.loads(c.to_JSON()))) arr.append(dict(json.loads(c.to_JSON())))
@ -146,6 +209,184 @@ def getCourseByCampusName(name):
status=200, status=200,
mimetype="application/json") mimetype="application/json")
@course_routes.route('/api/courses/getMessagesByCourseName/<string:name>', methods=["GET"])
@auto.doc()
def getMessagesByCourseName(name):
"""
<span class="card-title">>This Call will return an array of all courses in a given campus</span>
<br>
<b>Route Parameters</b><br>
- name: 'campus name'
<br>
<br>
<b>Payload</b><br>
- NONE
<br>
<br>
<b>Response</b>
<br>
200 - JSON Example:<br>
<code>
{<br>
'courseName': 'Advance Math',<br>
'campusName': 'JCE',<br>
'startDate': '2015-14-3'<br>
'endDate': '2015-29-6'<br>
'taskFlag': 'False'<br>
}
</code>
<br>
"""
arr = []
query = Message.all()
query.filter("courseName = ", name)
for m in query.run():
msgDic = dict(json.loads(m.to_JSON()))
#add a key 'forSortDate' for sorting dates
msgTime = datetime.datetime(msgDic['date']['year'], msgDic['date']['month'], msgDic['date']['day'], msgDic['date']['hour'], msgDic['date']['minute'])
msgDic['forSortDate'] = msgTime
arr.append(msgDic)
arr = sorted(arr, key=itemgetter('forSortDate'), reverse=False)
for i in arr:
del i['forSortDate']
print arr
if len(arr) != 0:
return Response(response=json.dumps(arr),
status=200,
mimetype="application/json")
else:
return Response(response=[],
status=200,
mimetype="application/json")
#----------------------------------------------------------
# PUT
#----------------------------------------------------------
#----------------------------------------------------------
# DELETE
#----------------------------------------------------------
@course_routes.route('/api/courses/deleteCourse/<string:token>/<string:courseName>', methods=['DELETE'])
@auto.doc()
def deleteCourse(token,courseName):
"""
<span class="card-title">This Call will delete a specific course</span>
<br>
<b>Route Parameters</b><br>
- seToken: 'seToken'
- title: 'courseName'
<br>
<br>
<b>Payload</b><br>
- NONE <br>
<br>
<br>
<b>Response</b>
<br>
202 - Deleted campus
<br>
204 - No Matching Campus Found
<br>
....<br>
{<br>
...<br>
}req<br>
]<br>
400 - Bad Request
<br>
403 - Invalid token or not a lecturer!<br>
"""
if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token)
query = Course.all()
query.filter('master_id =',user.key().id())
try:
query.filter('courseName =', courseName)
except Exception as e:
print e
return bad_request("invalid course title attribute")
for c in query.run():
db.delete(c)
db.save
return accepted("course deleted")
return bad_request("no such course or not owner of course")
@course_routes.route('/api/courses/deleteCoursesByCampus/<string:token>/<string:campusName>', methods=['DELETE'])
@auto.doc()
def deleteCoursesByCampus(token,campusName):
"""
<span class="card-title">This Call will delete a specific campus's courses</span>
<br>
<b>Route Parameters</b><br>
- seToken: 'seToken'
- title: 'campusName'
<br>
<br>
<b>Payload</b><br>
- NONE <br>
<br>
<br>
<b>Response</b>
<br>
202 - Deleted campus
<br>
204 - No Matching Campus Found
<br>
....<br>
{<br>
...<br>
}req<br>
]<br>
400 - Bad Request
<br>
403 - Invalid token or not a lecturer!<br>
"""
if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token)
campus = get_campus_by_campusName(campusName)
if campus is None:
return bad_request("Not a campus!")
#check user is owner of campus
if campus.master_user_id != user.key().id():
return forbidden("lecturer is not owner of campus!")
query = Course.all()
try:
query.filter('campusName =', campusName)
except Exception as e:
print e
return bad_request("invalid course title attribute")
for c in query.run():
db.delete(c)
db.save
return no_content()
@course_routes.route('/api/courses/help') @course_routes.route('/api/courses/help')
def documentation(): def documentation():

View file

@ -41,7 +41,7 @@ def create_project(token):
{<br> {<br>
'projectName': 'Advance Math',<br> 'projectName': 'Advance Math',<br>
'courseName': 'JCE',<br> 'courseName': 'JCE',<br>
'logo_url': 'http://location.domain.com/image.jpg'<br> 'logo_url': 'http://location.domain.com/image.jpg',<br>
'gitRepository': 'http://location.git.com/somthing'<br> 'gitRepository': 'http://location.git.com/somthing'<br>
}<br> }<br>
<br> <br>
@ -57,10 +57,12 @@ def create_project(token):
if not request.data: if not request.data:
return bad_request() return bad_request()
payload = json.loads(request.data) payload = json.loads(request.data)
if not is_lecturer(token): #todo: change to lecturer id #if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!") # return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token) user = get_user_by_token(token)
if user is None:
return bad_request("Wrong user Token")
#todo: check legality #todo: check legality

238
SE_API/TaskRoutes.py Normal file
View file

@ -0,0 +1,238 @@
__author__ = 'Aran'
from flask import Blueprint
import json
from GithubAPI.GithubAPI import GitHubAPI_Keys
from google.appengine.ext import db
import requests
import datetime
from operator import itemgetter
from flask import Flask, request, render_template, redirect, abort, Response
from flask.ext.github import GitHub
from flask.ext.cors import CORS, cross_origin
from flask.ext.autodoc import Autodoc
# DB Models
from models.Task import Task
from models.Course import Course
#Validation Utils Libs
from SE_API.Validation_Utils import *
from SE_API.Respones_Utils import *
task_routes = Blueprint("task_routes", __name__)
auto = Autodoc()
@task_routes.route('/api/tasks/create/<string:token>', methods=['POST'])
@auto.doc()
def create_task(token):
"""
<span class="card-title">This call will create a new Task in the DB</span>
<br>
<b>Route Parameters</b><br>
- seToken: 'seToken'
<br>
<br>
<b>Payload</b><br>
- JSON Object, Example: <br>
{<br>
'title' : self.title,<br>
'courseName' : self.course,<br>
'description' : self.description,<br>
'dueDate' : self.dueDate,<br>
'isClose' : self.membersId,<br>
'isDone' : self.isDone,<br>
'taskGrade' : self.taskGrade<br>
}<br>
<br>
<br>
<b>Response</b>
<br>
201 - Created
<br>
400 - Bad Request
<br>
403 - Invalid token or not a lecturer
"""
if not request.data:
return bad_request()
payload = json.loads(request.data)
if not is_lecturer(token): #todo: change to lecturer id
return forbidden("Invalid token or not a lecturer!")
user = get_user_by_token(token)
#TODO: add seconds and minutes
#check the user(lecturer) is owner of the course
# try:
# arr = []
# query = Course.all()
# query.filter('courseName =',payload['courseName'])
# for t in query.run():
# arr.append(dict(json.loads(t.to_JSON())))
# if len(arr) == 0:
# return bad_request("No such course")
# except Exception as e:
# print e
# return bad_request("Missing courseName")
#todo: check legality
#create Task object
try:
#parse dueDate
try:
date = datetime.date(payload['dueDate']['year'],payload['dueDate']['month'],payload['dueDate']['day'])
except Exception:
return bad_request("invalid dueDate format")
#TODO: add time. now, its only date
task = Task(title=payload['title'], courseName=payload['courseName'], description=payload['description'], dueDate=date)
#parse isClose
try:
task.isClose = payload['isClose']
except Exception:
pass
#parse isDone
try:
task.isDone = payload['isDone']
except Exception:
pass
#parse taskGrade
try:
task.taskGrade = payload['taskGrade']
except Exception:
pass
except Exception as e:
print e
return bad_request()
db.put(task)
db.save
return created()
@task_routes.route('/api/tasks/getClosestTask/<string:courseName>', methods=["GET"])
@auto.doc()
def getClosestTask(courseName):
"""
<span class="card-title">>This Call will return an array of all projects in a given course</span>
<br>
<b>Route Parameters</b><br>
- name: 'course name'
<br>
<br>
<b>Payload</b><br>
- NONE
<br>
<br>
<b>Response</b>
<br>
200 - JSON Example:<br>
<code>
{<br>
'projectName': 'Advance Math',<br>
'courseName': 'JCE',<br>
'grade': 98,<br>
'logo_url': 'http://location.domain.com/image.jpg',<br>
'gitRepository': 'http://location.git.com/somthing',<br>
'membersId': ['bob', 'dylan', 'quentin', 'terentino']<br>
}
</code>
<br>
"""
#get all tasks for a specific course
arr = []
query = Task.all()
query.filter("courseName =", courseName)
index = -1
count = -1
closestDate = datetime.date(3000,1,1)
for t in query.run():
count+=1
if t.dueDate < closestDate:
closestDate = t.dueDate
index = count
arr.append(dict(json.loads(t.to_JSON())))
print arr
if len(arr) != 0:
return Response(response=json.dumps(arr[index]),
status=200,
mimetype="application/json")
else:
return no_content("no Tasks")
@task_routes.route('/api/tasks/getAllTasks/<string:courseName>', methods=["GET"])
@auto.doc()
def getAllTasks(courseName):
"""
<span class="card-title">>This Call will return an array of all projects in a given course</span>
<br>
<b>Route Parameters</b><br>
- name: 'course name'
<br>
<br>
<b>Payload</b><br>
- NONE
<br>
<br>
<b>Response</b>
<br>
200 - JSON Example:<br>
<code>
{<br>
'projectName': 'Advance Math',<br>
'courseName': 'JCE',<br>
'grade': 98,<br>
'logo_url': 'http://location.domain.com/image.jpg',<br>
'gitRepository': 'http://location.git.com/somthing',<br>
'membersId': ['bob', 'dylan', 'quentin', 'terentino']<br>
}
</code>
<br>
"""
arr = []
query = Task.all()
query.filter("courseName = ", courseName)
for t in query.run():
taskDic =dict(json.loads(t.to_JSON()))
#add a key 'forSortDate' for sorting dates
taskTime = datetime.datetime(taskDic['dueDate']['year'], taskDic['dueDate']['month'], taskDic['dueDate']['day'])
taskDic['forSortDate'] = taskTime
arr.append(taskDic)
#sort array by date, and remove added key
arr = sorted(arr, key=itemgetter('forSortDate'), reverse=False)
for i in arr:
del i['forSortDate']
if len(arr) != 0:
return Response(response=json.dumps(arr),
status=200,
mimetype="application/json")
else:
return Response(response=[],
status=200,
mimetype="application/json")
@task_routes.route('/api/tasks/help')
def documentation():
return auto.html()

View file

@ -13,6 +13,14 @@ def get_user_by_token(token):
return u return u
return None return None
def get_campus_by_campusName(campusName):
query = Campus.all()
query.filter("title = ", campusName)
for u in query.run(limit = 1):
return u
return None
def get_campus_by_suffix(suffix): def get_campus_by_suffix(suffix):
query = Campus.all() query = Campus.all()
query.filter("email_ending = ", suffix) query.filter("email_ending = ", suffix)

23
models/Message.py Normal file
View file

@ -0,0 +1,23 @@
import json
__author__ = 'Aran'
from google.appengine.ext import db
class Message(db.Model):
courseName = db.StringProperty(required=True)
message = db.StringProperty(required=True)
msgDate = db.DateTimeProperty(required=True)
def to_JSON(self):
data = {
'courseName' : self.courseName,
'message' : self.message,
'date' : {
'year': self.msgDate.year,
'month': self.msgDate.month,
'day': self.msgDate.day,
'hour': self.msgDate.hour,
'minute': self.msgDate.minute
}
}
return json.dumps(data)

View file

@ -1,24 +1,32 @@
import json import json
import time
__author__ = 'Aran' __author__ = 'Aran'
from google.appengine.ext import db from google.appengine.ext import db
class Task(db.Model): class Task(db.Model):
title = db.StringProperty(required=True) title = db.StringProperty(required=True)
description = db.StringProperty(required=True) courseName = db.StringProperty(required=True)
description = db.StringProperty(required=True,default=" ")
dueDate = db.DateProperty(required=True) dueDate = db.DateProperty(required=True)
isProject = db.BooleanProperty(required=True) #isProject = db.BooleanProperty(required=False)
isClose = db.BooleanProperty(required=True) isClose = db.BooleanProperty(required=True, default=False)
isDone = db.BooleanProperty(required=True) isDone = db.BooleanProperty(required=True, default=False)
taskGrade = db.IntegerProperty(required=True) taskGrade = db.IntegerProperty(required=True, default=0)
def to_JSON(self): def to_JSON(self):
data = {'title' : self.title, data = {'title' : self.title,
'courseName' : self.courseName,
'description' : self.description, 'description' : self.description,
'dueDate' : self.dueDate, 'dueDate' : {
'isProject' : self.isProject, 'year': self.dueDate.year,
'isClose' : self.membersId, 'month': self.dueDate.month,
'day': self.dueDate.day
},
#'isProject' : self.isProject,
'isClose' : self.isClose,
'isDone' : self.isDone, 'isDone' : self.isDone,
'taskGrade' : self.taskGrade, 'taskGrade' : self.taskGrade,
} }
return json.dumps(data) return json.dumps(data)

View file

@ -33,9 +33,9 @@ md-list .md-button {
https://github.com/google/material-design-icons https://github.com/google/material-design-icons
*/ */
/*p { p {
margin-left: 2em; margin-left: 2em;
}*/ }
.menuBtn { .menuBtn {
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGcgaWQ9IkhlYWRlciI+CiAgICA8Zz4KICAgICAgICA8cmVjdCB4PSItNjE4IiB5PSItMjIzMiIgZmlsbD0ibm9uZSIgd2lkdGg9IjE0MDAiIGhlaWdodD0iMzYwMCIvPgogICAgPC9nPgo8L2c+CjxnIGlkPSJMYWJlbCI+CjwvZz4KPGcgaWQ9Ikljb24iPgogICAgPGc+CiAgICAgICAgPHJlY3QgZmlsbD0ibm9uZSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+CiAgICAgICAgPHBhdGggZD0iTTMsMThoMTh2LTJIM1YxOHogTTMsMTNoMTh2LTJIM1YxM3ogTTMsNnYyaDE4VjZIM3oiIHN0eWxlPSJmaWxsOiNmM2YzZjM7Ii8+CiAgICA8L2c+CjwvZz4KPGcgaWQ9IkdyaWQiIGRpc3BsYXk9Im5vbmUiPgogICAgPGcgZGlzcGxheT0iaW5saW5lIj4KICAgIDwvZz4KPC9nPgo8L3N2Zz4=) no-repeat center center; background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGcgaWQ9IkhlYWRlciI+CiAgICA8Zz4KICAgICAgICA8cmVjdCB4PSItNjE4IiB5PSItMjIzMiIgZmlsbD0ibm9uZSIgd2lkdGg9IjE0MDAiIGhlaWdodD0iMzYwMCIvPgogICAgPC9nPgo8L2c+CjxnIGlkPSJMYWJlbCI+CjwvZz4KPGcgaWQ9Ikljb24iPgogICAgPGc+CiAgICAgICAgPHJlY3QgZmlsbD0ibm9uZSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+CiAgICAgICAgPHBhdGggZD0iTTMsMThoMTh2LTJIM1YxOHogTTMsMTNoMTh2LTJIM1YxM3ogTTMsNnYyaDE4VjZIM3oiIHN0eWxlPSJmaWxsOiNmM2YzZjM7Ii8+CiAgICA8L2c+CjwvZz4KPGcgaWQ9IkdyaWQiIGRpc3BsYXk9Im5vbmUiPgogICAgPGcgZGlzcGxheT0iaW5saW5lIj4KICAgIDwvZz4KPC9nPgo8L3N2Zz4=) no-repeat center center;
@ -76,21 +76,28 @@ body.noscroll
margin-top: 1em; margin-top: 1em;
margin-right: 1em; margin-right: 1em;
position: center; position: center;
-webkit-border-radius: 30%; -webkit-border-radius: 30%;
-moz-border-radius: 30%; -moz-border-radius: 30%;
border-radius: 30%; border-radius: 30%;
} }
.avatar img { /*.avatar {
border-radius: 40px; background: rgba(0, 0, 0, 0.2);
position:center; }*/
width: 80px;
height: 80px; .avatar img {
margin: 6px; border-radius: 40px;
-webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75); position:center;
-moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75); width: 80px;
box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75); height: 80px;
} margin: 6px; /*centers the image in the parent element */
-webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
}
/* Added BY devMatan */ /* Added BY devMatan */
@ -104,8 +111,14 @@ body.noscroll
}*/ }*/
.campusAvatar img .campusAvatar img
{ {
/*
margin-top: 1em;
margin-right: 1em;
position: center;
*/
border-radius: 40px; border-radius: 40px;
position:center; position:center;
width: 80px; width: 80px;
@ -144,24 +157,9 @@ body.noscroll
margin-bottom: 10px; margin-bottom: 10px;
} }
.feed .md-avatar img
{ {
overflow-y: scroll; /*TODO*/
height: 350px;
/*width: 100%;*/
}
/*.feedMessages
{
overflow: scroll;
height: 300px;
width: 100%;
}
.feedTasks
{
overflow: scroll;
height: 300px;
width: 100%;
} }
.feedContent .feedContent
@ -169,7 +167,7 @@ body.noscroll
padding-left: 6%; padding-left: 6%;
font-size: 15px; font-size: 15px;
display:table; display:table;
}*/ }
.md-no-sticky .md-no-sticky
{ {
@ -183,6 +181,7 @@ body.noscroll
border-radius: 150px; border-radius: 150px;
-webkit-border-radius: 150px; -webkit-border-radius: 150px;
-moz-border-radius: 150px; -moz-border-radius: 150px;
/*background: url(http://i61.tinypic.com/v86f7.png) no-repeat;*/
box-shadow: 0 0 8px rgba(0, 0, 0, .8); box-shadow: 0 0 8px rgba(0, 0, 0, .8);
-webkit-box-shadow: 0 0 8px rgba(0, 0, 0, .8); -webkit-box-shadow: 0 0 8px rgba(0, 0, 0, .8);
-moz-box-shadow: 0 0 8px rgba(0, 0, 0, .8); -moz-box-shadow: 0 0 8px rgba(0, 0, 0, .8);
@ -257,6 +256,7 @@ body.noscroll
-moz-border-radius: 100px; -moz-border-radius: 100px;
border-radius: 50px; border-radius: 50px;
width: 30%; width: 30%;
/*top: -40px;*/
position: relative; position: relative;
z-index: 50; z-index: 50;
} }
@ -282,17 +282,8 @@ body.noscroll
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
} }
.se-menu li .selected{
.se-menu li:active{
background-color: #B2B2B2;
text-shadow:#e0e0e0 1px 1px 0;
font-weight: bold;
}
.se-menu .selected{
background-color: #E2E2E2; background-color: #E2E2E2;
text-shadow:#e0e0e0 1px 1px 0;
font-weight: bold;
} }
.user-box{ .user-box{
@ -302,6 +293,7 @@ body.noscroll
.user-box img{ .user-box img{
width: 100%; width: 100%;
border: 4px #7f7f7f solid; border: 4px #7f7f7f solid;
-webkit-border-radius: 5px; -webkit-border-radius: 5px;
-moz-border-radius: 5px; -moz-border-radius: 5px;
border-radius: 5px; border-radius: 5px;
@ -350,70 +342,26 @@ body.noscroll
} }
/* Colors*/ /* md-list-item .md-no-style.md-button, md-list-item.md-no-proxy.md-button {
.gray{ font-size: inherit;
background:#f5f5f5; height: inherit;
} text-align: left;
.aliceblue { text-transform: none;
background: aliceblue; width: 100%;
} white-space: normal;
.green {
background: #b9f6ca;
}
.yellow {
background: #ffff8d;
}
.blue {
background: #84ffff;
}
.purple {
background: #b388ff;
}
.red {
background: #ff8a80;
}
/* End Colors */
.whiteframedemoBasicUsage md-whiteframe {
background: #fff;
margin: 20px;
padding: 20px;
} }
.tasksContent md-list-item, md-list-item .md-list-item-inner {
{ display: -webkit-flex;
padding-left: 4px; display: -ms-flexbox;
padding-right: 4px; display: flex;
margin: 5px; -webkit-justify-content: flex-start;
background-color: aliceblue; -ms-flex-pack: start;
overflow: scroll; justify-content: flex-start;
height:250; -webkit-align-items: center;
width:500; -ms-flex-align: center;
} align-items: center;
.messagesContent min-height: 48px;
{ }*/
padding-left: 4px;
padding-right: 4px;
margin: 5px;
background-color: #f5f5f5;
overflow: scroll;
height:250;
width:500;
}
p.tasksFeed
{
padding-left: 4px;
margin: 5px;
width:500;
height: auto;
background-color: aliceblue;
} /*End Effects for MD*/
p.messagesFeed
{
padding-left: 4px;
margin: 5px;
width:500;
height: auto;
background-color: #f5f5f5;
}

View file

@ -2,7 +2,7 @@ var DEBUG = true;
var welcome = angular.module('welcome', ['ngMaterial', 'seHub.services', 'ngRoute' , 'ngCookies']); var welcome = angular.module('welcome', ['ngMaterial', 'seHub.services', 'ngRoute' , 'ngCookies']);
var app = angular.module('SeHub', ['ngMaterial', 'ngRoute', 'seHub.services', 'ngCookies', 'chart.js']); var app = angular.module('SeHub', ['ngMaterial', 'ngRoute', 'seHub.services', 'ngCookies']);
welcome.config(function($mdThemingProvider) { welcome.config(function($mdThemingProvider) {
@ -41,11 +41,8 @@ app.config(['$routeProvider', '$locationProvider',
.when('/Settings', { .when('/Settings', {
templateUrl: 'templates/views/settings.html', templateUrl: 'templates/views/settings.html',
controller: 'settingsController' controller: 'settingsController'
})
.when('/tasks', {
templateUrl: 'templates/views/tasks.html',
controller: 'tasksController'
}); });
} }
]); ]);

View file

@ -1,51 +1,71 @@
angular.module('SeHub') angular.module('SeHub')
.controller('homeController', ['$scope', '$cookies', '$cookieStore', '$window', '$location', '$mdToast', '$mdDialog', 'apiService', '$rootScope', function ($scope, $cookies, $cookieStore, $window, $location, $mdToast, $mdDialog, apiService ,$rootScope) .controller('homeController', ['$scope', '$cookies', '$cookieStore', '$window', '$location', '$mdToast', '$mdDialog', 'apiService', '$rootScope', function ($scope, $cookies, $cookieStore, $window, $location, $mdToast, $mdDialog, apiService ,$rootScope)
{ {
$scope.isStudent = false; var imagePath = $scope.user.avatar_url;
$scope.addMsg = false; $scope.phones = [
$scope.msgToPost = ""; { type: 'Home', number: '(972) 865-82861' },
$scope.oldText = ""; { type: 'Cell', number: '(972) 5251-32309' },
];
var imagePath = $scope.user.avatar_url; $scope.messages = [
$scope.phones = [ {
{ type: 'Home', number: '(972) 865-82861' }, face : imagePath,
{ type: 'Cell', number: '(972) 5251-32309' }, what: 'I need to go to luna-park',
]; who: 'Matan Bar Yosef',
when: '3:08PM',
notes: " Lets do something"
},
{
face : imagePath,
what: 'Lets Lets Lets',
who: 'Matan Bar Yosef',
when: '4:33PM',
notes: " Lets go drink something"
},
{
face : imagePath,
what: 'Let me tell you a secret',
who: 'Sagi Dayan',
when: '4:15PM',
notes: " I am S'ein"
},
{
face : imagePath,
what: 'Listen to this!',
who: 'Aran Zaiger',
when: '6:15PM',
notes: " I am gaylord ultima!!"
},
{
face : imagePath,
what: 'Hi?',
who: 'Etye Meyer',
when: '7:45AM',
notes: " I am mega gaylord ultima"
}
];
if($scope.user.isLecturer) $scope.tasks = [
{ {
$scope.isStudent = false; ExNum: '1',
console.log("Lecturer Mode!"); dueDate: '23/06/15',
} notes: " Build A Game: Scrabble"
else },
{ {
$scope.isStudent = true; ExNum: '3',
console.log("Student Mode!"); dueDate: '30/06/15',
} notes: " Static Array"
},
{
ExNum: '4',
dueDate: '07/07/15',
notes: " Dynamic Array"
},
];
$scope.addMessageClicked = function()
{
$scope.addMsg = true; // Reveal the "POST" Button
}
$scope.postMessageClicked = function(msg) // Posting the message itself
{
if(msg != null)
{
$scope.prevText = "- " + msg;
implementText = document.getElementById("msg").value;
$scope.prevText += "<br></br>";
document.getElementById("bindText").innerHTML += $scope.prevText;
}
document.getElementById("msg").value = '';
$scope.prevText = '';
}
$scope.clearAllClicked = function() // Clear Screen from text
{
document.getElementById("bindText").innerHTML = "";
}
// animation // animation
$scope.isEnterd = top.setIsEnterd; $scope.isEnterd = top.setIsEnterd;
}]); }]);

View file

@ -53,7 +53,7 @@ angular.module('SeHub')
"title": "Tasks", "title": "Tasks",
"icon": "fa fa-clipboard", "icon": "fa fa-clipboard",
"style": "", "style": "",
"route": "/tasks" "route": "/campuses"
}, { }, {
"title": "Settings", "title": "Settings",
"icon": "fa fa-cogs", "icon": "fa fa-cogs",

View file

@ -0,0 +1,23 @@
angular.module('SeHub').controller('newTasksController', ['$scope',
function($scope) {
$scope.componentTypes = [{
"type": "textbox"
}, {
"type": "textarea"
}, {
"type": "checkbox"
}];
$scope.task = [];
$scope.addComponent = function(){
$scope.task.push($scope.newComp);
$scope.newComp = {};
}
}
]);

View file

@ -83,7 +83,7 @@ angular.module('SeHub')
console.log("DONE - 200"); console.log("DONE - 200");
$mdDialog.show($mdDialog.alert().title('E-mail Verification').content('A verification e-mail has been sent to your email address.') $mdDialog.show($mdDialog.alert().title('E-mail Verification').content('A verification e-mail has been sent to your email address.')
.ariaLabel('Email verification alert dialog').ok('Got it!').targetEvent(ev)); // Pop-up alert for e-mail verification .ariaLabel('Email verification alert dialog').ok('Got it!').targetEvent(ev)); // Pop-up alert for e-mail verification
// TODO ADD- delete cookies and redirect only after pressed 'Got it' // TODO ADD delete cookies and redirect only after pressed 'Got it'
$cookieStore.remove("com.sehub.www"); // Removing the cookies $cookieStore.remove("com.sehub.www"); // Removing the cookies
$window.location.href = 'http://se-hub.appspot.com'; // Reference to 'welcome' page $window.location.href = 'http://se-hub.appspot.com'; // Reference to 'welcome' page
}).error(function() }).error(function()
@ -117,6 +117,8 @@ angular.module('SeHub')
var result = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i; var result = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
if (!result.test(email)) // TODO Fix when success to show mdDialog until 'Got it' clicked if (!result.test(email)) // TODO Fix when success to show mdDialog until 'Got it' clicked
{ {
console.log(email + ", Error in email, should alert");
// alert('Please provide a valid e-mail address');
$mdDialog.show($mdDialog.alert().title('Error - E-mail Verification').content('An error has occured in your e-mail address.') $mdDialog.show($mdDialog.alert().title('Error - E-mail Verification').content('An error has occured in your e-mail address.')
.ariaLabel('Email verification error alert dialog').ok('Got it!').targetEvent(email)); .ariaLabel('Email verification error alert dialog').ok('Got it!').targetEvent(email));
} }

View file

@ -35,13 +35,7 @@ angular.module('SeHub')
$scope.profileMode = "Save Profile"; $scope.profileMode = "Save Profile";
$scope.profileModeIcon = "fa fa-floppy-o"; $scope.profileModeIcon = "fa fa-floppy-o";
} else { } else {
apiService.updateUser(token, $scope.user).success(function(data) { dataService.userBrodcast($scope.user);
console.info('User Saved');
dataService.userBrodcast($scope.user);
}).error(function(e) {
console.error('Fail To Save User');
});
$scope.profileMode = "Edit Profile"; $scope.profileMode = "Edit Profile";
$scope.profileModeIcon = "fa fa-pencil"; $scope.profileModeIcon = "fa fa-pencil";
} }
@ -80,14 +74,5 @@ angular.module('SeHub')
}]; }];
$scope.labels = ['Commits', 'Issues Assigned', 'Messages', 'Open Tasks'];
$scope.series = ['Project A', 'Project B'];
$scope.data = [
[54, 3, 15, 3],
[28, 48, 40, 3]
];
} }
]); ]);

View file

@ -22,93 +22,47 @@
</div> </div>
</md-card> </md-card>
</md-content> </md-content>
<div ng-if="user.isLecturer"> <!-- Lecturer Mode --> <md-content layout-padding>
<md-content layout-padding> <md-card>
<div layout="row" layout-margin layout-padding> <div class = "feed" ><!-- layout-align="center center"> -->
<div> <div>
<md-card> <md-subheader class="md-no-sticky" style = "background-color:aliceblue; margin-right:0;">Messages</md-subheader>
<p class = "messagesFeed">Messages</p> <md-list-item class="md-3-line" ng-repeat="item in messages">
</md-card> <div class="md-list-item-text" style="border: 1px solid black;">
</div> <img ng-src="{{user.avatar_url}}" class="roundUserAvatar" alt="{{item.who}}" style="margin:8px"/>
<div> <!-- Instead of "user.avatar.url" suppose to be "postedUserAvatarUrl" -->
<md-card>
<p class = "tasksFeed">Tasks</p>
</md-card>
</div>
</div>
<div layout="row" layout-margin layout-padding>
<div>
<md-card>
<p id = "bindText" class = "messagesContent"></p>
</md-card>
</div>
<div>
<md-card>
<p class = "tasksContent">
For Task 3 Press: <a href="http://localhost:8080/home#/tasks">Task #3</a>
<br></br>
For Task 4 Press: <a href="http://localhost:8080/home#/home">Task #4</a>
<br></br>
For Task 5 Press: <a href="http://localhost:8080/home#/home">Task #5</a>
<br></br>
For Task 6 Press: <a href="http://localhost:8080/home#/home">Task #6</a>
<br></br>
For Task 7 Press: <a href="http://localhost:8080/home#/home">Task #7</a>
<br></br>
For Task 8 Press: <a href="http://localhost:8080/home#/home">Task #8</a>
</p>
</md-card>
</div>
</div>
<div layout-margin layout padding>
<md-button ng-click="addMessageClicked()" ng class="md-raised md-primary">Add Message</md-button>
</div>
<div ng-if="addMsg">
<div layout = "row" layout-margin layout padding layout-align = "left center">
<md-button ng-click="postMessageClicked(msgToAdd)" ng class="md-raised md-primary">Post</md-button>
<md-button ng-click="clearAllClicked()" ng class="md-raised md-primary">Clear All</md-button>
</div>
<div class="port_spacer"></div>
<md-input-container>
<label> Write Your Desired Message Here And Press Post</label>
<input type="text" id="msg" md-maxlength="150" minlength="1" ng-model="msgToAdd" required>
</md-input-container>
</div>
</md-content>
</div>
<div ng-if="isStudent"> <!-- Student Mode -->
<md-content layout-padding>
<div layout="row" layout-margin layout-padding>
<div>
<md-card>
<p class = "messagesFeed">Messages</p>
</md-card>
</div>
<div>
<md-card>
<p class = "tasksFeed">Tasks</p>
</md-card>
</div>
</div>
<div layout="row" layout-margin layout-padding>
<div>
<md-card>
<p id = "bindText" class = "messagesContent"></p>
</md-card>
</div>
<div>
<md-card>
<p class = "tasksContent">
For Task 3 Press: <a href="http://localhost:8080/home#/tasks">Task #3</a>
<br></br>
For Task 4 Press: <a href="http://localhost:8080/home#/home">Task #4</a>
<br></br>
For Task 5 Press: <a href="http://localhost:8080/home#/home">Task #5</a>
</p>
</md-card> <div class="spacer"></div>
</div> <br></br>
<md-divider class = "feedContent">
<h4>{{ item.who }}</h4>
<h5>{{ item.what }}</h5>
<h5><b>{{ item.notes }}</b></h5>
<h6>{{ item.when }}</h6>
</md-divider>
</div>
</md-list-item>
</div> </div>
</md-card>
</md-content>
<div class="port_spacer"></div>
<div>
<md-content>
<md-card style="margin:0">
<!-- <md-list> -->
<md-subheader class="md-no-sticky" style = "background-color:aliceblue; margin-right:0;">Tasks</md-subheader>
<md-list-item class="md-3-line" ng-repeat="item in tasks">
<!-- <img ng-src="{{item.face}}?{{$index}}" class="md-avatar" alt="{{item.who}}" /> -->
<div class="md-list-item-text" style="border: 1px solid black;">
<md-divider class = "feedContent">
<h6><u><em>Ex: {{ item.ExNum }}</em></u></h6>
<h5>Task Title: {{ item.notes }}</h5>
<h6>Due Date: {{ item.dueDate }}</h6>
</md-divider>
</div>
</md-list-item>
</md-card>
</md-content> </md-content>
</div> </div>
<!-- </md-card> -->
</div> </div>

View file

@ -6,10 +6,6 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="templates/css/theme.css"> <link rel="stylesheet" href="templates/css/theme.css">
<!--charts css-->
<link rel="stylesheet" href="templates/js/libs/angular-chart.js-0.7.2/dist/angular-chart.css"/>
<meta name="viewport" content="initial-scale=1, maximum-scale=1" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1" />
</head> </head>
@ -83,14 +79,6 @@
<!-- Angular App --> <!-- Angular App -->
<script src="templates/js/app.js"></script> <script src="templates/js/app.js"></script>
<!--Angular Libs (Third Party)-->
<!--charts-->
<!--docs: http://jtblin.github.io/angular-chart.js/-->
<script src="templates/js/libs/angular-chart.js-0.7.2/dist/chart.js"></script>
<script src="templates/js/libs/angular-chart.js-0.7.2/dist/angular-chart.js"></script>
<!-- Services --> <!-- Services -->
<script src="templates/js/services/apiService.js"></script> <script src="templates/js/services/apiService.js"></script>
<script src="templates/js/services/dataService.js"></script> <script src="templates/js/services/dataService.js"></script>

View file

@ -0,0 +1,48 @@
<div layout-padding>
<div layout="row">
<div flex="20" layout-padding>
<h2>
<i class="fa fa-info-circle"></i> Task Info:
</h2>
</div>
<div layout="column" flex="30" layout-padding>
<div>
<h2>
<i class="fa fa-cubes"></i> Add A component:
</h2>
</div>
<div>
Select Type:
<md-select placeholder="Component Type" ng-model="newComp.type">
<md-option ng-repeat="component in componentTypes" value="{{component.type}}">{{component.type}}</md-option>
</md-select>
</div>
<div>
<md-input-container>
<label>Label</label>
<input ng-model="newComp.label" required>
</md-input-container>
</div>
<div>
<md-switch ng-model="newComp.isMandatory" aria-label="Switch 1">
Mandatory?: {{ newComp.isMandatory}}
</md-switch>
</div>
<div layout="row">
<div flex="70"></div>
<md-button class="md-primary" ng-click="addComponent()">Add Component</md-button>
</div>
</div flex="50" layout-padding>
<!-- <md-card style="background-image: url('http://www.stationeryhq.com/content/images/thumbs/0000324_clipboard_500.png')">
</md-card> -->
<h2>
<i class="fa fa-eye"></i> Task Preview:
</h2>
<p>{{task.toString()}}</p>
</div>
</div>

View file

@ -55,8 +55,6 @@
</div> </div>
</div> </div>
<!-- End Edit Div --> <!-- End Edit Div -->
<canvas id="bar" class="chart chart-bar" data="data"
labels="labels" series="series"></canvas>
</md-card> </md-card>
</div> </div>
<!-- Campuses & Classes Div --> <!-- Campuses & Classes Div -->