edited button disabling
This commit is contained in:
parent
0a47adb419
commit
ecb080e358
7 changed files with 141 additions and 176 deletions
|
@ -3,5 +3,6 @@ import logger
|
||||||
import models
|
import models
|
||||||
import problem
|
import problem
|
||||||
import user
|
import user
|
||||||
|
import stats
|
||||||
import team
|
import team
|
||||||
import utils
|
import utils
|
||||||
|
|
|
@ -108,11 +108,11 @@ def problem_submit():
|
||||||
db.session.add(problem)
|
db.session.add(problem)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
logger.log("submissions.log", logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.name, flag))
|
logger.log(__name__, logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.name, flag))
|
||||||
return { "success": 1, "message": "Correct!" }
|
return { "success": 1, "message": "Correct!" }
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.log("submissions.log", logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.name))
|
logger.log(__name__, logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.name))
|
||||||
raise WebException("Incorrect.")
|
raise WebException("Incorrect.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
22
server/api/stats.py
Normal file
22
server/api/stats.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
from flask import Blueprint, request, session
|
||||||
|
from flask import current_app as app
|
||||||
|
|
||||||
|
from decorators import api_wrapper
|
||||||
|
|
||||||
|
import team
|
||||||
|
|
||||||
|
blueprint = Blueprint("stats", __name__)
|
||||||
|
|
||||||
|
@blueprint.route("/scoreboard")
|
||||||
|
@api_wrapper
|
||||||
|
def all_teams_stats():
|
||||||
|
teams = team.get_team().all()
|
||||||
|
result = [ ]
|
||||||
|
for _team in teams:
|
||||||
|
result.append({
|
||||||
|
"teamname": _team.teamname,
|
||||||
|
"tid": _team.tid,
|
||||||
|
"school": _team.school,
|
||||||
|
"points": _team.points()
|
||||||
|
})
|
||||||
|
return { "success": 1, "scoreboard": result }
|
|
@ -23,50 +23,50 @@ blueprint = Blueprint("user", __name__)
|
||||||
@blueprint.route("/forgot/<token>", methods=["GET", "POST"])
|
@blueprint.route("/forgot/<token>", methods=["GET", "POST"])
|
||||||
@api_wrapper
|
@api_wrapper
|
||||||
def user_forgot_password(token=None):
|
def user_forgot_password(token=None):
|
||||||
params = utils.flat_multi(request.form)
|
params = utils.flat_multi(request.form)
|
||||||
if token is not None:
|
if token is not None:
|
||||||
user = get_user(reset_token=token).first()
|
user = get_user(reset_token=token).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
raise WebException("Invalid reset token.")
|
raise WebException("Invalid reset token.")
|
||||||
|
|
||||||
# We are viewing the actual reset form
|
# We are viewing the actual reset form
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
return { "success": 1, "message": ""}
|
return { "success": 1, "message": ""}
|
||||||
|
|
||||||
# Submission of actual reset form
|
# Submission of actual reset form
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
password = params.get("password")
|
password = params.get("password")
|
||||||
confirm_password = params.get("confirm_password")
|
confirm_password = params.get("confirm_password")
|
||||||
if password != confirm_password:
|
if password != confirm_password:
|
||||||
raise WebException("Passwords do not match.")
|
raise WebException("Passwords do not match.")
|
||||||
else:
|
else:
|
||||||
user.password = utils.hash_password(password)
|
user.password = utils.hash_password(password)
|
||||||
user.reset_token = None
|
user.reset_token = None
|
||||||
current_session = db.session.object_session(user)
|
current_session = db.session.object_session(user)
|
||||||
current_session.add(user)
|
current_session.add(user)
|
||||||
current_session.commit()
|
current_session.commit()
|
||||||
return { "success": 1, "message": "Success!" }
|
return { "success": 1, "message": "Success!" }
|
||||||
else:
|
else:
|
||||||
email = params.get("email")
|
email = params.get("email").lower()
|
||||||
|
|
||||||
user = get_user(email=email).first()
|
user = get_user(email=email).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
raise WebException("User with that email does not exist.")
|
raise WebException("User with that email does not exist.")
|
||||||
|
|
||||||
token = utils.generate_string(length=64)
|
token = utils.generate_string(length=64)
|
||||||
user.reset_token = token
|
user.reset_token = token
|
||||||
current_session = db.session.object_session(user)
|
current_session = db.session.object_session(user)
|
||||||
current_session.add(user)
|
current_session.add(user)
|
||||||
current_session.commit()
|
current_session.commit()
|
||||||
|
|
||||||
reset_link = "%s/forgot/%s" % ("127.0.0.1:8000", token)
|
reset_link = "%s/forgot/%s" % ("127.0.0.1:8000", token)
|
||||||
subject = "EasyCTF password reset"
|
subject = "EasyCTF password reset"
|
||||||
body = """%s,\n\nA request to reset your EasyCT password has been made. If you did not request this password reset, you may safely ignore this email and delete it.\n\nYou may reset your password by clicking this link or pasting it to your browser.\n\n%s\n\nThis link can only be used once, and will lead you to a page where you can reset your password.\n\nGood luck!\n\n- The EasyCTF Team""" % (user.username, reset_link)
|
body = """%s,\n\nA request to reset your EasyCTF password has been made. If you did not request this password reset, you may safely ignore this email and delete it.\n\nYou may reset your password by clicking this link or pasting it to your browser.\n\n%s\n\nThis link can only be used once, and will lead you to a page where you can reset your password.\n\nGood luck!\n\n- The EasyCTF Team""" % (user.username, reset_link)
|
||||||
response = utils.send_email(email, subject, body).json()
|
response = utils.send_email(email, subject, body).json()
|
||||||
if "Queued" in response["message"]:
|
if "Queued" in response["message"]:
|
||||||
return { "success": 1, "message": "Email sent to %s" % email }
|
return { "success": 1, "message": "Email sent to %s" % email }
|
||||||
else:
|
else:
|
||||||
raise WebException(response["message"])
|
raise WebException(response["message"])
|
||||||
|
|
||||||
@blueprint.route("/register", methods=["POST"])
|
@blueprint.route("/register", methods=["POST"])
|
||||||
@api_wrapper
|
@api_wrapper
|
||||||
|
@ -89,7 +89,7 @@ def user_register():
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
logger.log("registrations", logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8")))
|
logger.log(__name__, logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8")))
|
||||||
login_user(username, password)
|
login_user(username, password)
|
||||||
|
|
||||||
return { "success": 1, "message": "Success!" }
|
return { "success": 1, "message": "Success!" }
|
||||||
|
@ -200,22 +200,22 @@ UserSchema = Schema({
|
||||||
}, extra=True)
|
}, extra=True)
|
||||||
|
|
||||||
def get_user(username=None, username_lower=None, email=None, uid=None, reset_token=None):
|
def get_user(username=None, username_lower=None, email=None, uid=None, reset_token=None):
|
||||||
match = {}
|
match = {}
|
||||||
if username != None:
|
if username != None:
|
||||||
match.update({ "username": username })
|
match.update({ "username": username })
|
||||||
elif username_lower != None:
|
elif username_lower != None:
|
||||||
match.update({ "username_lower": username_lower })
|
match.update({ "username_lower": username_lower })
|
||||||
elif uid != None:
|
elif uid != None:
|
||||||
match.update({ "uid": uid })
|
match.update({ "uid": uid })
|
||||||
elif email != None:
|
elif email != None:
|
||||||
match.update({ "email": email })
|
match.update({ "email": email })
|
||||||
elif is_logged_in():
|
elif is_logged_in():
|
||||||
match.update({ "username": session["username"] })
|
match.update({ "username": session["username"] })
|
||||||
elif reset_token != None:
|
elif reset_token != None:
|
||||||
match.update({ "reset_token": reset_token })
|
match.update({ "reset_token": reset_token })
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
result = Users.query.filter_by(**match)
|
result = Users.query.filter_by(**match)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def login_user(username, password):
|
def login_user(username, password):
|
||||||
user = get_user(username_lower=username.lower()).first()
|
user = get_user(username_lower=username.lower()).first()
|
||||||
|
@ -237,8 +237,8 @@ def login_user(username, password):
|
||||||
session["sid"] = token.sid
|
session["sid"] = token.sid
|
||||||
session["username"] = token.username
|
session["username"] = token.username
|
||||||
session["admin"] = user.admin == True
|
session["admin"] = user.admin == True
|
||||||
if user.tid is not None and user.tid >= 0:
|
if user.tid is not None and user.tid >= 0:
|
||||||
session["tid"] = user.tid
|
session["tid"] = user.tid
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ app.secret_key = config.SECRET_KEY
|
||||||
|
|
||||||
app.register_blueprint(api.admin.blueprint, url_prefix="/api/admin")
|
app.register_blueprint(api.admin.blueprint, url_prefix="/api/admin")
|
||||||
app.register_blueprint(api.problem.blueprint, url_prefix="/api/problem")
|
app.register_blueprint(api.problem.blueprint, url_prefix="/api/problem")
|
||||||
|
app.register_blueprint(api.stats.blueprint, url_prefix="/api/stats")
|
||||||
app.register_blueprint(api.team.blueprint, url_prefix="/api/team")
|
app.register_blueprint(api.team.blueprint, url_prefix="/api/team")
|
||||||
app.register_blueprint(api.user.blueprint, url_prefix="/api/user")
|
app.register_blueprint(api.user.blueprint, url_prefix="/api/user")
|
||||||
api.logger.initialize_logs()
|
api.logger.initialize_logs()
|
||||||
|
|
|
@ -42,7 +42,7 @@ app.config(function($routeProvider, $locationProvider) {
|
||||||
})
|
})
|
||||||
.when("/scoreboard", {
|
.when("/scoreboard", {
|
||||||
templateUrl: "pages/scoreboard.html",
|
templateUrl: "pages/scoreboard.html",
|
||||||
controller: "mainController"
|
controller: "scoreboardController"
|
||||||
})
|
})
|
||||||
.when("/settings", {
|
.when("/settings", {
|
||||||
templateUrl: "pages/settings.html",
|
templateUrl: "pages/settings.html",
|
||||||
|
@ -128,6 +128,23 @@ app.controller("teamController", ["$controller", "$scope", "$http", "$routeParam
|
||||||
} else {
|
} else {
|
||||||
$controller("loginController", { $scope: $scope });
|
$controller("loginController", { $scope: $scope });
|
||||||
}
|
}
|
||||||
|
$.get("/api/team/info", data, function(result) {
|
||||||
|
if (result["success"] == 1) {
|
||||||
|
$scope.team = result["team"];
|
||||||
|
}
|
||||||
|
$scope.$apply();
|
||||||
|
$(".timeago").timeago();
|
||||||
|
});
|
||||||
|
}]);
|
||||||
|
|
||||||
|
app.controller("scoreboardController", ["$controller", "$scope", "$http", function($controller, $scope, $http) {
|
||||||
|
$controller("mainController", { $scope: $scope });
|
||||||
|
api_call("GET", "/api/stats/scoreboard", { }, function(result) {
|
||||||
|
if (result["success"] == 1) {
|
||||||
|
$scope.scoreboard = result["scoreboard"];
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
app.controller("resetController", ["$controller", "$scope", "$http", "$routeParams", function($controller, $scope, $http, $routeParams) {
|
app.controller("resetController", ["$controller", "$scope", "$http", "$routeParams", function($controller, $scope, $http, $routeParams) {
|
||||||
|
@ -214,20 +231,19 @@ $.fn.serializeObject = function() {
|
||||||
var register_form = function() {
|
var register_form = function() {
|
||||||
var input = "#register_form input";
|
var input = "#register_form input";
|
||||||
var data = $("#register_form").serializeObject();
|
var data = $("#register_form").serializeObject();
|
||||||
var button = $("#register_form").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/user/register", data, function(result) {
|
api_call("POST", "/api/user/register", data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
location.href = "/profile";
|
location.href = "/profile";
|
||||||
} else {
|
} else {
|
||||||
display_message("register_msg", "danger", result["message"], function() {
|
display_message("register_msg", "danger", result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("register_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("register_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -235,20 +251,19 @@ var register_form = function() {
|
||||||
// password reset
|
// password reset
|
||||||
var request_reset_form = function() {
|
var request_reset_form = function() {
|
||||||
var data = $("#request_reset_form").serializeObject();
|
var data = $("#request_reset_form").serializeObject();
|
||||||
var button = $("#request_reset_form").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/user/forgot", data, function(result) {
|
api_call("POST", "/api/user/forgot", data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
display_message("reset_msg", "success", result["message"]);
|
display_message("reset_msg", "success", result["message"]);
|
||||||
} else {
|
} else {
|
||||||
display_message("reset_msg", "danger", result["message"], function() {
|
display_message("reset_msg", "danger", result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -258,8 +273,7 @@ var reset_form = function() {
|
||||||
data["csrf_token"] = $.cookie("csrf_token");
|
data["csrf_token"] = $.cookie("csrf_token");
|
||||||
var url = window.location.href;
|
var url = window.location.href;
|
||||||
var token = url.substr(url.lastIndexOf("/")+1);
|
var token = url.substr(url.lastIndexOf("/")+1);
|
||||||
var button = $("#reset_form").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/user/forgot/" + token, data, function(result) {
|
api_call("POST", "/api/user/forgot/" + token, data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
display_message("reset_msg", "success", result["message"], function() {
|
display_message("reset_msg", "success", result["message"], function() {
|
||||||
|
@ -267,13 +281,13 @@ var reset_form = function() {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
display_message("reset_msg", "danger", result["message"], function() {
|
display_message("reset_msg", "danger", result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -283,20 +297,19 @@ var reset_form = function() {
|
||||||
var login_form = function() {
|
var login_form = function() {
|
||||||
var input = "#login_form input";
|
var input = "#login_form input";
|
||||||
var data = $("#login_form").serializeObject();
|
var data = $("#login_form").serializeObject();
|
||||||
var button = $("#login_form").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/user/login", data, function(result) {
|
api_call("POST", "/api/user/login", data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
location.href = "/profile";
|
location.href = "/profile";
|
||||||
} else {
|
} else {
|
||||||
display_message("login_msg", "danger", result["message"], function() {
|
display_message("login_msg", "danger", result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("login_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("login_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -306,20 +319,19 @@ var login_form = function() {
|
||||||
var create_team = function() {
|
var create_team = function() {
|
||||||
var input = "#create_team input";
|
var input = "#create_team input";
|
||||||
var data = $("#create_team").serializeObject();
|
var data = $("#create_team").serializeObject();
|
||||||
var button = $("#create_team").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/team/create", data, function(result) {
|
api_call("POST", "/api/team/create", data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
location.reload(true);
|
location.reload(true);
|
||||||
} else {
|
} else {
|
||||||
display_message("create_team_msg", "danger", result["message"], function() {
|
display_message("create_team_msg", "danger", result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -327,18 +339,17 @@ var create_team = function() {
|
||||||
var add_member = function() {
|
var add_member = function() {
|
||||||
var input = "#add_member input";
|
var input = "#add_member input";
|
||||||
var data = $("#add_member").serializeObject();
|
var data = $("#add_member").serializeObject();
|
||||||
var button = $("#add_member").find(":submit");
|
$(input).attr("disabled", "disabled");
|
||||||
button.prop("disabled", true);
|
|
||||||
api_call("POST", "/api/team/invite", data, function(result) {
|
api_call("POST", "/api/team/invite", data, function(result) {
|
||||||
if (result["success"] == 1) {
|
if (result["success"] == 1) {
|
||||||
location.reload(true);
|
location.reload(true);
|
||||||
} else {
|
} else {
|
||||||
button.removeAtr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
}
|
}
|
||||||
}).fail(function(jqXHR, status, error) {
|
}).fail(function(jqXHR, status, error) {
|
||||||
var result = JSON.parse(jqXHR["responseText"]);
|
var result = JSON.parse(jqXHR["responseText"]);
|
||||||
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
|
||||||
button.removeAttr("disabled");
|
$(input).removeAttr("disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,92 +1,22 @@
|
||||||
<script type="text/javascript">
|
<div class="page-header">
|
||||||
var chart = c3.generate({
|
<h1>Scoreboard</h1>
|
||||||
data: {
|
|
||||||
x: 'x',
|
|
||||||
columns: [
|
|
||||||
['x', '2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-06'],
|
|
||||||
['Team Thomas', 30, 250, 380, 500, 620, 740],
|
|
||||||
]
|
|
||||||
},
|
|
||||||
axis: {
|
|
||||||
x: {
|
|
||||||
type: 'timeseries',
|
|
||||||
tick: {
|
|
||||||
format: '%Y-%m-%d'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setTimeout(function() {
|
|
||||||
chart.load({
|
|
||||||
columns: [
|
|
||||||
['Team Charles', 100, 210, 320, 430, 540, 650]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
setTimeout(function() {
|
|
||||||
chart.load({
|
|
||||||
columns: [
|
|
||||||
['Team Zach', 10, 120, 230, 340, 450, 560]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, 2000);
|
|
||||||
setTimeout(function() {
|
|
||||||
chart.load({
|
|
||||||
columns: [
|
|
||||||
['Team Michael', 0, 80, 190, 300, 410, 520]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, 3000);
|
|
||||||
setTimeout(function() {
|
|
||||||
chart.load({
|
|
||||||
columns: [
|
|
||||||
['Team James', 0, 100, 250, 300, 450, 600]
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, 4000);
|
|
||||||
</script>
|
|
||||||
<div class="fade_in text-center">
|
|
||||||
<h1 class="heading1">Scoreboard</h1>
|
|
||||||
<br>
|
|
||||||
<div id="chart"></div>
|
|
||||||
<br>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th>Team Name</th>
|
|
||||||
<th>School</th>
|
|
||||||
<th>Points</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>1</td>
|
|
||||||
<td>Team Thomas</td>
|
|
||||||
<td>T. High School</td>
|
|
||||||
<td>740</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2</td>
|
|
||||||
<td>Team Charles</td>
|
|
||||||
<td>C. High School</td>
|
|
||||||
<td>650</td>
|
|
||||||
</tr><tr>
|
|
||||||
<td>3</td>
|
|
||||||
<td>Team Zach</td>
|
|
||||||
<td>Z. High School</td>
|
|
||||||
<td>560</td>
|
|
||||||
</tr><tr>
|
|
||||||
<td>4</td>
|
|
||||||
<td>Team Michael</td>
|
|
||||||
<td>M. High School</td>
|
|
||||||
<td>520</td>
|
|
||||||
</tr><tr>
|
|
||||||
<td>5</td>
|
|
||||||
<td>Team James</td>
|
|
||||||
<td>J. High School</td>
|
|
||||||
<td>600</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Rank</th>
|
||||||
|
<th>Team Name</th>
|
||||||
|
<th>School</th>
|
||||||
|
<th>Points</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="team in scoreboard">
|
||||||
|
<td></td>
|
||||||
|
<td><a ng-href="/team/{{ team['teamname'] }}">{{ team['teamname'] }}</a></td>
|
||||||
|
<td>{{ team['school'] }}</td>
|
||||||
|
<td>{{ team['points'] }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
Loading…
Reference in a new issue