mirror of https://github.com/JohnHammond/CTFd.git
Updated CTFd UI to use Bootstrap; makes viewing and adding challenges
much more visually appealingselenium-screenshot-testing
parent
ac6e5b8c4f
commit
b501561551
|
@ -196,7 +196,7 @@ def delete_page(pageroute):
|
|||
def admin_chals():
|
||||
if request.method == 'POST':
|
||||
chals = Challenges.query.add_columns('id', 'name', 'value', 'description', 'category').order_by(Challenges.value).all()
|
||||
|
||||
|
||||
json_data = {'game':[]}
|
||||
for x in chals:
|
||||
json_data['game'].append({'id':x[1], 'name':x[2], 'value':x[3], 'description':x[4], 'category':x[5]})
|
||||
|
@ -228,7 +228,7 @@ def admin_keys(chalid):
|
|||
flag_dict = {'flag':flag, 'type':int(val)}
|
||||
flags.append(flag_dict)
|
||||
json_data = json.dumps(flags)
|
||||
|
||||
|
||||
chal.flags = json_data
|
||||
|
||||
db.session.commit()
|
||||
|
@ -293,7 +293,7 @@ def admin_files(chalid):
|
|||
|
||||
if len(filename) <= 0:
|
||||
continue
|
||||
|
||||
|
||||
md5hash = hashlib.md5(os.urandom(64)).hexdigest()
|
||||
|
||||
if not os.path.exists(os.path.join(os.path.normpath(app.static_folder), 'uploads', md5hash)):
|
||||
|
@ -433,7 +433,7 @@ def admin_graph(graph_type):
|
|||
return jsonify(json_data)
|
||||
elif graph_type == "solves":
|
||||
solves = Solves.query.add_columns(db.func.count(Solves.chalid)).group_by(Solves.chalid).all()
|
||||
json_data = {}
|
||||
json_data = {}
|
||||
for chal, count in solves:
|
||||
json_data[chal.chal.name] = count
|
||||
return jsonify(json_data)
|
||||
|
@ -489,7 +489,7 @@ def delete_solve(teamid, chalid):
|
|||
@admins_only
|
||||
def admin_stats():
|
||||
db.session.commit()
|
||||
|
||||
|
||||
teams_registered = db.session.query(db.func.count(Teams.id)).first()[0]
|
||||
wrong_count = db.session.query(db.func.count(WrongKeys.id)).first()[0]
|
||||
solve_count = db.session.query(db.func.count(Solves.id)).first()[0]
|
||||
|
|
|
@ -73,7 +73,7 @@ table{
|
|||
}
|
||||
|
||||
#keys-pie-graph{
|
||||
width: 400px;
|
||||
width: 600px;
|
||||
max-height: 330px;
|
||||
float: left;
|
||||
}
|
||||
|
@ -86,16 +86,14 @@ table{
|
|||
|
||||
.chal-button{
|
||||
width: 150px;
|
||||
color: white;
|
||||
border: None;
|
||||
}
|
||||
|
||||
.chal-button > p{
|
||||
font-family: monospace;
|
||||
.chal-button > p {
|
||||
margin-bottom: 0px;
|
||||
height: 20px;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.chal-button > span{
|
||||
|
|
|
@ -21,7 +21,7 @@ String.prototype.hashCode = function() {
|
|||
return hash;
|
||||
};
|
||||
|
||||
function loadchal(id) {
|
||||
function loadchal(id, update) {
|
||||
// $('#chal *').show()
|
||||
// $('#chal > h1').hide()
|
||||
obj = $.grep(challenges['game'], function (e) {
|
||||
|
@ -37,8 +37,8 @@ function loadchal(id) {
|
|||
//$('#update-challenge .chal-delete').attr({
|
||||
// 'href': '/admin/chal/close/' + (id + 1)
|
||||
//})
|
||||
$('#update-challenge').foundation('reveal', 'open');
|
||||
|
||||
if (typeof update === 'undefined')
|
||||
$('#update-challenge').modal();
|
||||
}
|
||||
|
||||
function submitkey(chal, key) {
|
||||
|
@ -57,12 +57,13 @@ function loadkeys(chal){
|
|||
keys = keys['keys'];
|
||||
$('#current-keys').empty();
|
||||
for(x=0; x<keys.length; x++){
|
||||
var elem = $('<div>');
|
||||
elem.append($("<input class='current-key' type='text'>").val(keys[x].key));
|
||||
elem.append('<input type="radio" name="key_type['+x+']" value="0">Static');
|
||||
elem.append('<input type="radio" name="key_type['+x+']" value="1">Regex');
|
||||
elem.append('<a href="#" onclick="$(this).parent().remove()" class="remove-key">Remove</a>');
|
||||
|
||||
var elem = $('<div class="col-md-4">');
|
||||
|
||||
elem.append($("<div class='form-group'>").append($("<input class='current-key form-control' type='text'>").val(keys[x].key)));
|
||||
elem.append('<div class="radio-inline"><input type="radio" name="key_type['+x+']" value="0">Static</div>');
|
||||
elem.append('<div class="radio-inline"><input type="radio" name="key_type['+x+']" value="1">Regex</div>');
|
||||
elem.append('<a href="#" onclick="$(this).parent().remove()" class="btn btn-danger key-remove-button">Remove</a>');
|
||||
|
||||
$('#current-keys').append(elem);
|
||||
$('#current-keys input[name="key_type['+x+']"][value="'+keys[x].type+'"]').prop('checked',true);
|
||||
}
|
||||
|
@ -80,7 +81,8 @@ function updatekeys(){
|
|||
vals.push($(this).val());
|
||||
})
|
||||
$.post('/admin/keys/'+chal, {'keys':keys, 'vals':vals, 'nonce': $('#nonce').val()})
|
||||
loadchal(chal)
|
||||
loadchal(chal, true)
|
||||
$('#update-keys').modal('hide');
|
||||
}
|
||||
|
||||
function loadtags(chal){
|
||||
|
@ -91,7 +93,7 @@ function loadtags(chal){
|
|||
tags = $.parseJSON(JSON.stringify(data))
|
||||
tags = tags['tags']
|
||||
for (var i = 0; i < tags.length; i++) {
|
||||
tag = "<span class='secondary label chal-tag'><span>"+tags[i].tag+"</span><a name='"+tags[i].id+"'' class='delete-tag'>×</a></span>"
|
||||
tag = "<span class='label label-primary chal-tag'><span>"+tags[i].tag+"</span><a name='"+tags[i].id+"'' class='delete-tag'>×</a></span>"
|
||||
$('#current-tags').append(tag)
|
||||
};
|
||||
$('.delete-tag').click(function(e){
|
||||
|
@ -120,7 +122,7 @@ function updatetags(){
|
|||
}
|
||||
|
||||
function loadfiles(chal){
|
||||
$('#update-files > form').attr('action', '/admin/files/'+chal)
|
||||
$('#update-files form').attr('action', '/admin/files/'+chal)
|
||||
$.get('/admin/files/' + chal, function(data){
|
||||
$('#files-chal').val(chal)
|
||||
files = $.parseJSON(JSON.stringify(data));
|
||||
|
@ -129,7 +131,7 @@ function loadfiles(chal){
|
|||
for(x=0; x<files.length; x++){
|
||||
filename = files[x].file.split('/')
|
||||
filename = filename[filename.length - 1]
|
||||
$('#current-files').append('<div data-alert class="alert-box info radius">'+'<a href=/'+files[x].file+'>'+filename+'</a><a href="#" onclick="deletefile('+chal+','+files[x].id+', $(this))" value="'+files[x].id+'" style="float:right;">Delete</a></div>')
|
||||
$('#current-files').append('<div class="row" style="margin:5px 0px;">'+'<a style="position:relative;top:10px;" href=/'+files[x].file+'>'+filename+'</a><a href="#" class="btn btn-danger" onclick="deletefile('+chal+','+files[x].id+', $(this))" value="'+files[x].id+'" style="float:right;">Delete</a></div>')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -137,7 +139,7 @@ function loadfiles(chal){
|
|||
function deletefile(chal, file, elem){
|
||||
$.post('/admin/files/' + chal,{
|
||||
'nonce': $('#nonce').val(),
|
||||
'method': 'delete',
|
||||
'method': 'delete',
|
||||
'file': file
|
||||
}, function (data){
|
||||
if (data == "1") {
|
||||
|
@ -159,13 +161,13 @@ function loadchals(){
|
|||
for (var i = challenges['game'].length - 1; i >= 0; i--) {
|
||||
if ($.inArray(challenges['game'][i].category, categories) == -1) {
|
||||
categories.push(challenges['game'][i].category)
|
||||
$('#challenges').append($('<tr id="' + challenges['game'][i].category.replace(/ /g,"-").hashCode() + '"><td class="large-2"><h3>' + challenges['game'][i].category + '</h3></td></tr>'))
|
||||
$('#challenges').append($('<tr id="' + challenges['game'][i].category.replace(/ /g,"-").hashCode() + '"><td class="col-md-1"><h3>' + challenges['game'][i].category + '</h3></td></tr>'))
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i <= challenges['game'].length - 1; i++) {
|
||||
var chal = challenges['game'][i]
|
||||
var chal_button = $('<button class="chal-button" value="{0}"><p>{1}</p><span>{2}</span></button>'.format(chal.id, chal.name, chal.value))
|
||||
var chal_button = $('<button class="chal-button col-md-2 theme-background" value="{0}"><p>{1}</p><span>{2}</span></button>'.format(chal.id, chal.name, chal.value))
|
||||
$('#' + challenges['game'][i].category.replace(/ /g,"-").hashCode()).append(chal_button);
|
||||
};
|
||||
|
||||
|
@ -179,7 +181,7 @@ function loadchals(){
|
|||
$('.create-challenge').click(function (e) {
|
||||
$('#new-chal-category').val($($(this).siblings()[0]).text().trim())
|
||||
$('#new-chal-title').text($($(this).siblings()[0]).text().trim())
|
||||
$('#new-challenge').foundation('reveal', 'open');
|
||||
$('#new-challenge').modal();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -190,25 +192,28 @@ $('#submit-key').click(function (e) {
|
|||
});
|
||||
|
||||
$('#submit-keys').click(function (e) {
|
||||
e.preventDefault();
|
||||
updatekeys()
|
||||
});
|
||||
|
||||
$('#submit-tags').click(function (e) {
|
||||
e.preventDefault();
|
||||
updatetags()
|
||||
});
|
||||
|
||||
$('#delete-chal > form').submit(function(e){
|
||||
$('#delete-chal form').submit(function(e){
|
||||
e.preventDefault();
|
||||
$.post('/admin/chal/delete', $(this).serialize(), function(data){
|
||||
console.log(data)
|
||||
if (data){
|
||||
loadchals();
|
||||
$('#delete-chal').foundation('reveal', 'close');
|
||||
}
|
||||
else {
|
||||
alert('There was an error');
|
||||
}
|
||||
})
|
||||
$("#delete-chal").modal("hide");
|
||||
$("#update-challenge").modal("hide");
|
||||
});
|
||||
|
||||
$(".tag-insert").keyup(function (e) {
|
||||
|
@ -216,7 +221,7 @@ $(".tag-insert").keyup(function (e) {
|
|||
tag = $('.tag-insert').val()
|
||||
tag = tag.replace(/'/g, '');
|
||||
if (tag.length > 0){
|
||||
tag = "<span class='secondary label chal-tag'><span>"+tag+"</span><a onclick='$(this).parent().remove()'>×</a></span>"
|
||||
tag = "<span class='label label-primary chal-tag'><span>"+tag+"</span><a class='delete-tag' onclick='$(this).parent().remove()'>×</a></span>"
|
||||
$('#chal-tags').append(tag)
|
||||
}
|
||||
$('.tag-insert').val("")
|
||||
|
@ -226,34 +231,33 @@ $(".tag-insert").keyup(function (e) {
|
|||
|
||||
|
||||
// Markdown Preview
|
||||
$('#desc-edit').on('toggled', function (event, tab) {
|
||||
if (tab[0].id == 'desc-preview'){
|
||||
$(tab[0]).html(marked($('#desc-editor').val(), {'gfm':true, 'breaks':true}))
|
||||
$('#desc-edit').on('shown.bs.tab', function (event) {
|
||||
if (event.target.hash == '#desc-preview'){
|
||||
$(event.target.hash).html(marked($('#desc-editor').val(), {'gfm':true, 'breaks':true}))
|
||||
}
|
||||
});
|
||||
$('#new-desc-edit').on('toggled', function (event, tab) {
|
||||
if (tab[0].id == 'new-desc-preview'){
|
||||
$(tab[0]).html(marked($('#new-desc-editor').val(), {'gfm':true, 'breaks':true}))
|
||||
$('#new-desc-edit').on('shown.bs.tab', function (event) {
|
||||
if (event.target.hash == '#new-desc-preview'){
|
||||
$(event.target.hash).html(marked($('#new-desc-editor').val(), {'gfm':true, 'breaks':true}))
|
||||
}
|
||||
});
|
||||
|
||||
// Open New Challenge modal when New Challenge button is clicked
|
||||
$('.create-challenge').click(function (e) {
|
||||
$('#create-challenge').foundation('reveal', 'open');
|
||||
$('#create-challenge').modal();
|
||||
});
|
||||
|
||||
|
||||
$('#create-key').click(function(e){
|
||||
var amt = $('#current-keys input[type=text]').length
|
||||
// $('#current-keys').append("<input class='current-key' type='text' placeholder='Blank Key'>");
|
||||
// $('#current-keys').append('<input type="radio" name="key_type[{0}]" value="0">Static'.format(amt));
|
||||
// $('#current-keys').append('<input type="radio" name="key_type[{0}]" value="1">Regex'.format(amt));
|
||||
|
||||
var elem = $('<div>');
|
||||
elem.append("<input class='current-key' type='text' placeholder='Blank Key'>");
|
||||
elem.append('<input type="radio" name="key_type[{0}]" value="0" checked="checked">Static'.format(amt));
|
||||
elem.append('<input type="radio" name="key_type[{0}]" value="1">Regex'.format(amt));
|
||||
elem.append('<a href="#" onclick="$(this).parent().remove()" class="remove-key">Remove</a>');
|
||||
|
||||
var elem = $('<div class="col-md-4">');
|
||||
|
||||
elem.append($("<div class='form-group'>").append($("<input class='current-key form-control' type='text'>")));
|
||||
elem.append('<div class="radio-inline"><input type="radio" name="key_type['+amt+']" value="0">Static</div>');
|
||||
elem.append('<div class="radio-inline"><input type="radio" name="key_type['+amt+']" value="1">Regex</div>');
|
||||
elem.append('<a href="#" onclick="$(this).parent().remove()" class="btn btn-danger key-remove-button">Remove</a>');
|
||||
|
||||
$('#current-keys').append(elem);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
(function($, window) {
|
||||
'use strict';
|
||||
|
||||
var MultiModal = function(element) {
|
||||
this.$element = $(element);
|
||||
this.modalCount = 0;
|
||||
};
|
||||
|
||||
MultiModal.BASE_ZINDEX = 1040;
|
||||
|
||||
MultiModal.prototype.show = function(target) {
|
||||
var that = this;
|
||||
var $target = $(target);
|
||||
var modalIndex = that.modalCount++;
|
||||
|
||||
$target.css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20) + 10);
|
||||
|
||||
window.setTimeout(function() {
|
||||
if(modalIndex > 0)
|
||||
$('.modal-backdrop').not(':first').addClass('hidden');
|
||||
|
||||
that.adjustBackdrop();
|
||||
});
|
||||
};
|
||||
|
||||
MultiModal.prototype.hidden = function(target) {
|
||||
this.modalCount--;
|
||||
|
||||
if(this.modalCount) {
|
||||
this.adjustBackdrop();
|
||||
$('body').addClass('modal-open');
|
||||
}
|
||||
};
|
||||
|
||||
MultiModal.prototype.adjustBackdrop = function() {
|
||||
var modalIndex = this.modalCount - 1;
|
||||
$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20));
|
||||
};
|
||||
|
||||
function Plugin(method, target) {
|
||||
return this.each(function() {
|
||||
var $this = $(this);
|
||||
var data = $this.data('multi-modal-plugin');
|
||||
|
||||
if(!data)
|
||||
$this.data('multi-modal-plugin', (data = new MultiModal(this)));
|
||||
|
||||
if(method)
|
||||
data[method](target);
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.multiModal = Plugin;
|
||||
$.fn.multiModal.Constructor = MultiModal;
|
||||
|
||||
$(document).on('show.bs.modal', function(e) {
|
||||
$(document).multiModal('show', e.target);
|
||||
});
|
||||
|
||||
$(document).on('hidden.bs.modal', function(e) {
|
||||
$(document).multiModal('hidden', e.target);
|
||||
});
|
||||
}(jQuery, window));
|
|
@ -0,0 +1,132 @@
|
|||
.submit-row {
|
||||
padding-left: 15px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-block;
|
||||
margin: 1em 0em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
position: relative;
|
||||
display: block;
|
||||
float: right;
|
||||
padding: 0.8em;
|
||||
width: 60%;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: #f0f0f0;
|
||||
color: #aaa;
|
||||
font-weight: 400;
|
||||
font-family: "Avenir Next", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
-webkit-appearance: none; /* for box shadows to show on iOS */
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
padding: 0 1em;
|
||||
width: 40%;
|
||||
color: #6a7989;
|
||||
font-weight: bold;
|
||||
font-size: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.label-content {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 1.6em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.graphic {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: #ddd;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
border: 2px solid transparent;
|
||||
-webkit-transition: background-color 0.3s, border-color 0.3s;
|
||||
transition: background-color 0.3s, border-color 0.3s;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
padding: 0 1.25em;
|
||||
-webkit-transform: translate3d(0, 3em, 0);
|
||||
transform: translate3d(0, 3em, 0);
|
||||
-webkit-transition: -webkit-transform 0.3s;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.label-content {
|
||||
color: #8B8C8B;
|
||||
padding: 0.25em 0;
|
||||
-webkit-transition: -webkit-transform 0.3s;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.label-content::after {
|
||||
content: attr(data-content);
|
||||
position: absolute;
|
||||
font-weight: 800;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: #a3d39c;
|
||||
padding: 0.25em 0;
|
||||
letter-spacing: 1px;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .input-field {
|
||||
background-color: transparent;
|
||||
border-color: #a3d39c;
|
||||
}
|
||||
|
||||
.input--hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#submit {
|
||||
position: relative;
|
||||
right: -15px;
|
||||
}
|
||||
|
||||
.done-row {
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
|
||||
html, body, .container {
|
||||
height: 100% !important;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-weight: 500;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 15px !important;
|
||||
}
|
||||
|
||||
a {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.no-margin-right {
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
|
||||
.no-margin-left {
|
||||
margin-left: -3px !important;
|
||||
}
|
||||
|
||||
.navbar > .container {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.navbar .navbar-brand {
|
||||
font-size: 24px;
|
||||
letter-spacing: -0.04rem;
|
||||
line-height: 15px;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.navbar li > a {
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.08s ease-in 0s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navbar li > a:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.align-text-to-button {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.padded-container {
|
||||
margin-top: 50px;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-top: 35px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
#login-container {
|
||||
padding-left: 70px;
|
||||
padding-right: 70px;
|
||||
}
|
||||
|
||||
#chal > form{
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.reveal-modal{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chal-desc{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#challenges button{
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.row > h1{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#challenges{
|
||||
line-height: 66px;
|
||||
}
|
||||
|
||||
#score-graph{
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
#keys-pie-graph{
|
||||
width: 50%;
|
||||
max-height: 330px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#categories-pie-graph{
|
||||
width: 50%;
|
||||
float: left;
|
||||
max-height: 330px;
|
||||
}
|
||||
|
||||
.logo{
|
||||
margin: 0 auto;
|
||||
width: 500px;
|
||||
padding: 50px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 40.063em){
|
||||
.top-bar .dropdown{
|
||||
display: block;
|
||||
padding: 0 15px 5px;
|
||||
width: 200% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
letter-spacing: 1px;
|
||||
text-decoration: none;
|
||||
background: none;
|
||||
-moz-user-select: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
font-size:14px;
|
||||
line-height:20px;
|
||||
font-weight:700;
|
||||
text-transform:uppercase;
|
||||
border: 3px solid;
|
||||
padding:8px 20px;
|
||||
}
|
||||
|
||||
.btn-outlined {
|
||||
border-radius: 0;
|
||||
-webkit-transition: all 0.3s;
|
||||
-moz-transition: all 0.3s;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.file-wrapper {
|
||||
background-color: #5B7290;
|
||||
}
|
||||
|
||||
.file-wrapper:hover {
|
||||
background-color: #747474;
|
||||
}
|
||||
|
||||
.theme-background {
|
||||
background-color: #545454 !important;
|
||||
|
||||
}
|
||||
|
||||
.solved-challenge {
|
||||
background-color: #8EDC9D !important;
|
||||
}
|
||||
|
||||
.panel-theme {
|
||||
border-color: #545454;
|
||||
}
|
||||
|
||||
.panel-theme > .panel-heading {
|
||||
border-color: #545454;
|
||||
background-color: #545454;
|
||||
opacity: 1;
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-outlined.btn-theme {
|
||||
background: none;
|
||||
color: #545454;
|
||||
border-color: #545454;
|
||||
}
|
||||
|
||||
.btn-outlined.btn-theme:hover,
|
||||
.btn-outlined.btn-theme:active {
|
||||
color: #FFF;
|
||||
background: #545454;
|
||||
border-color: #545454;
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
background: none repeat scroll 0% 0% #545454;
|
||||
border: medium none;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.jumbotron {
|
||||
background-color: #545454;
|
||||
color: #FFF;
|
||||
padding: 0px 0px 25px;
|
||||
}
|
||||
|
||||
.jumbotron.home {
|
||||
text-align: center;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.home h1 {
|
||||
font-size: 48px !important;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
#chal > form{
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.reveal-modal{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chal-desc{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*Not sure why foundation needs these two...*/
|
||||
.top-bar input{
|
||||
height: auto;
|
||||
padding-top: 0.35rem;
|
||||
padding-bottom: 0.35rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.top-bar .button{
|
||||
padding-top: 0.45rem;
|
||||
padding-bottom: 0.35rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.dropdown{
|
||||
background-color: #333 !important;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.dropdown button{
|
||||
padding-top: 0.45rem;
|
||||
padding-bottom: 0.35rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
#challenges button{
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.row > h1{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#challenges{
|
||||
line-height: 66px;
|
||||
}
|
||||
|
||||
#score-graph{
|
||||
max-height: 400px;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.dropdown{
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.dropdown input{
|
||||
margin: 5px auto;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.dropdown button{
|
||||
margin: 10px auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#keys-pie-graph{
|
||||
width: 50%;
|
||||
max-height: 330px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#categories-pie-graph{
|
||||
width: 50%;
|
||||
float: left;
|
||||
max-height: 330px;
|
||||
}
|
||||
|
||||
.logo{
|
||||
margin: 0 auto;
|
||||
width: 500px;
|
||||
padding: 50px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chal-button{
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.chal-button > p{
|
||||
font-family: monospace;
|
||||
margin-bottom: 0px;
|
||||
height: 20px;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.chal-button > span{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 40.063em){
|
||||
.top-bar .dropdown{
|
||||
display: block;
|
||||
padding: 0 15px 5px;
|
||||
width: 200% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar input{
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.scroll-wrap{
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
//http://stackoverflow.com/a/2648463 - wizardry!
|
||||
String.prototype.format = String.prototype.f = function() {
|
||||
var s = this,
|
||||
|
@ -30,58 +31,43 @@ var challenges;
|
|||
function loadchal(id) {
|
||||
obj = $.grep(challenges['game'], function (e) {
|
||||
return e.id == id;
|
||||
})[0]
|
||||
window.location.hash = obj.name
|
||||
$('#chal-window .chal-name').text(obj.name)
|
||||
$('#chal-window .chal-desc').html(marked(obj.description, {'gfm':true, 'breaks':true}))
|
||||
})[0];
|
||||
|
||||
updateChalWindow(obj);
|
||||
}
|
||||
|
||||
function loadchalbyname(chalname) {
|
||||
obj = $.grep(challenges['game'], function (e) {
|
||||
return e.name == chalname;
|
||||
})[0];
|
||||
|
||||
updateChalWindow(obj);
|
||||
}
|
||||
|
||||
function updateChalWindow(obj) {
|
||||
window.location.hash = obj.name
|
||||
$('#chal-window').find('.chal-name').text(obj.name)
|
||||
$('#chal-window').find('.chal-desc').html(marked(obj.description, {'gfm':true, 'breaks':true}))
|
||||
$('#chal-window').find('.chal-files').empty();
|
||||
for (var i = 0; i < obj.files.length; i++) {
|
||||
filename = obj.files[i].split('/')
|
||||
filename = filename[filename.length - 1]
|
||||
$('#chal-window .chal-desc').append("<a href='"+obj.files[i]+"'>"+filename+"</a><br/>")
|
||||
$('#chal-window').find('.chal-files').append("<div class='col-md-3 file-button-wrapper'><a class='file-button' href='"+obj.files[i]+"'><label class='challenge-wrapper file-wrapper hide-text'>"+filename+"</label></a></div>")
|
||||
};
|
||||
|
||||
$('#chal-window .chal-value').text(obj.value)
|
||||
$('#chal-window .chal-category').text(obj.category)
|
||||
$('#chal-window #chal-id').val(obj.id)
|
||||
$('#chal-window .chal-solves').text(obj.solves + " solves")
|
||||
$('#chal-window').find('.chal-value').text(obj.value)
|
||||
$('#chal-window').find('.chal-category').text(obj.category)
|
||||
$('#chal-window').find('#chal-id').val(obj.id)
|
||||
var solves = obj.solves == 1 ? " Solve" : " Solves";
|
||||
$('#chal-window').find('.chal-solves').text(obj.solves + solves)
|
||||
$('#answer').val("")
|
||||
|
||||
$('pre code').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
$('#chal-window').foundation('reveal', 'open');
|
||||
}
|
||||
|
||||
function loadchalbyname(chalname) {
|
||||
obj = $.grep(challenges['game'], function (e) {
|
||||
return e.name == chalname;
|
||||
})[0]
|
||||
window.location.hash = obj.name
|
||||
$('#chal-window .chal-name').text(obj.name)
|
||||
$('#chal-window .chal-desc').html(marked(obj.description, {'gfm':true, 'breaks':true}))
|
||||
|
||||
for (var i = 0; i < obj.files.length; i++) {
|
||||
filename = obj.files[i].split('/')
|
||||
filename = filename[filename.length - 1]
|
||||
$('#chal-window .chal-desc').append("<a href='"+obj.files[i]+"'>"+filename+"</a><br/>")
|
||||
};
|
||||
|
||||
$('#chal-window .chal-value').text(obj.value)
|
||||
$('#chal-window .chal-category').text(obj.category)
|
||||
$('#chal-window #chal-id').val(obj.id)
|
||||
$('#chal-window .chal-solves').text(obj.solves + " solves")
|
||||
$('#answer').val("")
|
||||
|
||||
$('pre code').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
|
||||
$('#chal-window').foundation('reveal', 'open');
|
||||
}
|
||||
|
||||
|
||||
$("#answer").keyup(function(event){
|
||||
$("#answer-input").keyup(function(event){
|
||||
if(event.keyCode == 13){
|
||||
$("#submit-key").click();
|
||||
}
|
||||
|
@ -89,8 +75,10 @@ $("#answer").keyup(function(event){
|
|||
|
||||
|
||||
function submitkey(chal, key, nonce) {
|
||||
$('#submit-key').addClass("disabled-button");
|
||||
$('#submit-key').prop('disabled', true);
|
||||
$.post("/chal/" + chal, {
|
||||
key: key,
|
||||
key: key,
|
||||
nonce: nonce
|
||||
}, function (data) {
|
||||
if (data == -1){
|
||||
|
@ -98,37 +86,37 @@ function submitkey(chal, key, nonce) {
|
|||
return
|
||||
}
|
||||
else if (data == 0){ // Incorrect key
|
||||
$('#submit-key').text('Incorrect, sorry')
|
||||
$('#submit-key').css('background-color', 'red')
|
||||
$('#submit-key').prop('disabled', true)
|
||||
$("#incorrect-key").slideDown();
|
||||
$("#answer-input").addClass("wrong");
|
||||
$("#answer-input").removeClass("correct");
|
||||
setTimeout(function() {
|
||||
$("#answer-input").removeClass("wrong");
|
||||
}, 3000);
|
||||
}
|
||||
else if (data == 1){ // Challenge Solved
|
||||
$('#submit-key').text('Correct!')
|
||||
$('#submit-key').css('background-color', 'green')
|
||||
$('#submit-key').prop('disabled', true)
|
||||
$('#chal-window .chal-solves').text( (parseInt($('#chal-window .chal-solves').text().split(" ")[0]) + 1 + " solves") )
|
||||
$("#correct-key").slideDown();
|
||||
$('.chal-solves').text((parseInt($('.chal-solves').text().split(" ")[0]) + 1 + " Solves") )
|
||||
$("#answer-input").val("");
|
||||
$("#answer-input").removeClass("wrong");
|
||||
$("#answer-input").addClass("correct");
|
||||
}
|
||||
else if (data == 2){ // Challenge already solved
|
||||
$('#submit-key').text('You already solved this')
|
||||
$('#submit-key').prop('disabled', true)
|
||||
$("#already-solved").slideDown();
|
||||
$("#answer-input").addClass("correct");
|
||||
}
|
||||
else if (data == 3){ // Keys per minute too high
|
||||
$('#submit-key').text("You're submitting keys too fast. Slow down.")
|
||||
$('#submit-key').css('background-color', '#e18728')
|
||||
$('#submit-key').prop('disabled', true)
|
||||
$("#too-fast").slideDown();
|
||||
$("#answer-input").addClass("wrong");
|
||||
setTimeout(function() {
|
||||
$("#answer-input").removeClass("wrong");
|
||||
}, 3000);
|
||||
}
|
||||
else if (data == 4){ // too many incorrect solves
|
||||
$('#submit-key').text('Too many attempts.')
|
||||
$('#submit-key').css('background-color', 'red')
|
||||
$('#submit-key').prop('disabled', true)
|
||||
}
|
||||
marktoomanyattempts()
|
||||
marksolves()
|
||||
updatesolves()
|
||||
setTimeout(function(){
|
||||
$('#submit-key').text('Submit')
|
||||
$('#submit-key').prop('disabled', false)
|
||||
$('#submit-key').css('background-color', '#007095')
|
||||
$('.alert').slideUp();
|
||||
$('#submit-key').removeClass("disabled-button");
|
||||
$('#submit-key').prop('disabled', false);
|
||||
}, 3000);
|
||||
})
|
||||
}
|
||||
|
@ -137,26 +125,13 @@ function marksolves() {
|
|||
$.get('/solves', function (data) {
|
||||
solves = $.parseJSON(JSON.stringify(data));
|
||||
for (var i = solves['solves'].length - 1; i >= 0; i--) {
|
||||
id = solves['solves'][i].chalid
|
||||
$('#challenges button[value="' + id + '"]').addClass('secondary')
|
||||
$('#challenges button[value="' + id + '"]').css('opacity', '0.3')
|
||||
};
|
||||
if (window.location.hash.length > 0){
|
||||
loadchalbyname(window.location.hash.substring(1))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function marktoomanyattempts() {
|
||||
$.get('/maxattempts', function (data) {
|
||||
maxattempts = $.parseJSON(JSON.stringify(data));
|
||||
for (var i = maxattempts['maxattempts'].length - 1; i >= 0; i--) {
|
||||
id = maxattempts['maxattempts'][i].chalid
|
||||
$('#challenges button[value="' + id + '"]').addClass('secondary')
|
||||
$('#challenges button[value="' + id + '"]').css('background-color', '#FF9999')
|
||||
id = solves['solves'][i].chalid;
|
||||
$('button[value="' + id + '"]').removeClass('theme-background');
|
||||
$('button[value="' + id + '"]').addClass('solved-challenge');
|
||||
};
|
||||
if (window.location.hash.length > 0){
|
||||
loadchalbyname(window.location.hash.substring(1))
|
||||
$("#chal-window").modal("show");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -166,7 +141,7 @@ function updatesolves(){
|
|||
solves = $.parseJSON(JSON.stringify(data));
|
||||
chals = Object.keys(solves);
|
||||
|
||||
for (var i = 0; i < chals.length; i++) {
|
||||
for (var i = 0; i < chals.length; i++) {
|
||||
obj = $.grep(challenges['game'], function (e) {
|
||||
return e.name == chals[i];
|
||||
})[0]
|
||||
|
@ -196,39 +171,64 @@ function loadchals() {
|
|||
categories = [];
|
||||
challenges = $.parseJSON(JSON.stringify(data));
|
||||
|
||||
$('#challenges-board').html("");
|
||||
|
||||
for (var i = challenges['game'].length - 1; i >= 0; i--) {
|
||||
challenges['game'][i].solves = 0
|
||||
if ($.inArray(challenges['game'][i].category, categories) == -1) {
|
||||
categories.push(challenges['game'][i].category)
|
||||
$('#challenges').append($('<tr id="' + challenges['game'][i].category.replace(/ /g,"-").hashCode() + '"><td class="large-2"><h4>' + challenges['game'][i].category + '</h4></td></tr>'))
|
||||
var category = challenges['game'][i].category;
|
||||
categories.push(category);
|
||||
|
||||
var categoryid = category.replace(/ /g,"-").hashCode();
|
||||
var categoryrow = $('<div id="{0}-row" class="row"><div class="category-header col-md-2"></div><div class="category-challenges col-md-9"><div class="row"></div></div></div>'.format(categoryid));
|
||||
categoryrow.find(".category-header").append($("<h2>"+ category +"</h2>"));
|
||||
|
||||
$('#challenges-board').append(categoryrow);
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i <= challenges['game'].length - 1; i++) {
|
||||
var chal = challenges['game'][i]
|
||||
var chal_button = $('<button class="chal-button" value="{0}"><p>{1}</p><span>{2}</span></button>'.format(chal.id, chal.name, chal.value))
|
||||
$('#' + challenges['game'][i].category.replace(/ /g,"-").hashCode()).append(chal_button);
|
||||
};
|
||||
updatesolves()
|
||||
marktoomanyattempts()
|
||||
marksolves()
|
||||
chalinfo = challenges['game'][i];
|
||||
challenge = chalinfo.category.replace(/ /g,"-").hashCode();
|
||||
var chalid = chalinfo.name.replace(/ /g,"-").hashCode();
|
||||
var catid = chalinfo.category.replace(/ /g,"-").hashCode();
|
||||
var chalwrap = $("<div id='{0}' class='challenge-wrapper col-md-2'></div>".format(chalid));
|
||||
var chalbutton = $("<button class='challenge-button trigger theme-background hide-text' value='{0}' data-toggle='modal' data-target='#chal-window'></div>".format(chalinfo.id));
|
||||
var chalheader = $("<h5>{0}</h5>".format(chalinfo.name));
|
||||
var chalscore = $("<span>{0}</span>".format(chalinfo.value));
|
||||
chalbutton.append(chalheader);
|
||||
chalbutton.append(chalscore);
|
||||
chalwrap.append(chalbutton);
|
||||
|
||||
$('#challenges button').click(function (e) {
|
||||
$("#"+ catid +"-row").find(".category-challenges > .row").append(chalwrap);
|
||||
};
|
||||
|
||||
updatesolves();
|
||||
marksolves();
|
||||
|
||||
$('.challenge-button').click(function (e) {
|
||||
loadchal(this.value);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$('#submit-key').click(function (e) {
|
||||
submitkey($('#chal-id').val(), $('#answer').val(), $('#nonce').val())
|
||||
submitkey($('#chal-id').val(), $('#answer-input').val(), $('#nonce').val())
|
||||
});
|
||||
|
||||
$('.chal-solves').click(function (e) {
|
||||
getsolves($('#chal-id').val())
|
||||
});
|
||||
|
||||
$('#chal-window').on('hide.bs.modal', function (event) {
|
||||
$("#answer-input").removeClass("wrong");
|
||||
$("#answer-input").removeClass("correct");
|
||||
$("#incorrect-key").slideUp();
|
||||
$("#correct-key").slideUp();
|
||||
$("#already-solved").slideUp();
|
||||
$("#too-fast").slideUp();
|
||||
});
|
||||
|
||||
// $.distint(array)
|
||||
// Unique elements in array
|
||||
$.extend({
|
||||
|
@ -240,6 +240,7 @@ $.extend({
|
|||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
function colorhash (x) {
|
||||
color = ""
|
||||
for (var i = 20; i <= 60; i+=20){
|
||||
|
@ -250,35 +251,17 @@ function colorhash (x) {
|
|||
return "#" + color.substring(0, 6)
|
||||
}
|
||||
|
||||
$(document).on('close', '[data-reveal]', function () {
|
||||
window.location.hash = ""
|
||||
});
|
||||
|
||||
// function solves_graph() {
|
||||
// $.get('/graphs/solves', function(data){
|
||||
// solves = $.parseJSON(JSON.stringify(data));
|
||||
// chals = []
|
||||
// counts = []
|
||||
// colors = []
|
||||
// i = 1
|
||||
// $.each(solves, function(key, value){
|
||||
// chals.push(key)
|
||||
// counts.push(value)
|
||||
// colors.push(colorhash(i++))
|
||||
// });
|
||||
|
||||
// });
|
||||
// }
|
||||
|
||||
function update(){
|
||||
$('#challenges').empty()
|
||||
loadchals()
|
||||
solves_graph()
|
||||
}
|
||||
|
||||
$(function() {
|
||||
loadchals()
|
||||
// solves_graph()
|
||||
loadchals();
|
||||
});
|
||||
|
||||
$('.nav-tabs a').click(function (e) {
|
||||
e.preventDefault()
|
||||
$(this).tab('show')
|
||||
})
|
||||
|
||||
setInterval(update, 300000);
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
(function() {
|
||||
// trim polyfill : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
|
||||
if (!String.prototype.trim) {
|
||||
(function() {
|
||||
// Make sure we trim BOM and NBSP
|
||||
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
|
||||
String.prototype.trim = function() {
|
||||
return this.replace(rtrim, '');
|
||||
};
|
||||
})();
|
||||
}
|
||||
[].slice.call( document.querySelectorAll( 'input.input-field' ) ).forEach( function( inputEl ) {
|
||||
// in case the input is already filled..
|
||||
if( inputEl.value.trim() !== '' ) {
|
||||
classie.add( inputEl.parentNode, 'input--filled' );
|
||||
classie.add( inputEl.nextElementSibling, 'input--hide' );
|
||||
$label = $(inputEl).siblings(".input-label");
|
||||
$label.removeClass("input--hide");
|
||||
$label.css({
|
||||
"transform": "translate3d(0, 0, 0)"
|
||||
});
|
||||
}
|
||||
} );
|
||||
})();
|
||||
|
||||
$(".input-field").bind({
|
||||
focus: function() {
|
||||
$(this).parent().addClass('input--filled' );
|
||||
$label = $(this).siblings(".input-label");
|
||||
//$label.addClass('input--hide' );
|
||||
$label.css({
|
||||
"transform": "translate3d(0, 10%, 0)"
|
||||
});
|
||||
},
|
||||
blur: function() {
|
||||
if ($(this).val() === '') {
|
||||
$(this).parent().removeClass('input--filled' );
|
||||
$label = $(this).siblings(".input-label");
|
||||
$label.removeClass('input--hide' );
|
||||
$label.css({
|
||||
"transform": "translate3d(0, 150%, 0)"
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -79,7 +79,7 @@ function scoregraph () {
|
|||
team_scores.unshift(teams[i])
|
||||
// team_scores.push( team_scores[team_scores.length-1] )
|
||||
|
||||
|
||||
|
||||
xs_data[teams[i]] = "x"+i
|
||||
column_data.push(times)
|
||||
column_data.push(team_scores)
|
||||
|
@ -99,11 +99,11 @@ function scoregraph () {
|
|||
x : {
|
||||
tick: {
|
||||
count: 10,
|
||||
format: function (x) {
|
||||
format: function (x) {
|
||||
return moment(x*1000).local().format('LLL');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
y:{
|
||||
label: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
function teamid (){
|
||||
loc = window.location.pathname
|
||||
return parseInt(loc.substring(loc.lastIndexOf('/')+1, loc.length));
|
||||
return loc.substring(loc.lastIndexOf('/')+1, loc.length);
|
||||
}
|
||||
|
||||
function colorhash (x) {
|
||||
|
@ -29,8 +29,6 @@ function scoregraph () {
|
|||
solves = $.parseJSON(JSON.stringify(data));
|
||||
solves = solves['solves']
|
||||
|
||||
console.log(solves)
|
||||
|
||||
if (solves.length == 0)
|
||||
return
|
||||
|
||||
|
@ -46,8 +44,6 @@ function scoregraph () {
|
|||
scores.unshift('data1')
|
||||
// scores.push( scores[scores.length-1] )
|
||||
|
||||
console.log(scores)
|
||||
|
||||
var chart = c3.generate({
|
||||
bindto: "#score-graph",
|
||||
data: {
|
||||
|
@ -70,11 +66,11 @@ function scoregraph () {
|
|||
axis : {
|
||||
x : {
|
||||
tick: {
|
||||
format: function (x) {
|
||||
format: function (x) {
|
||||
return moment(x).local().format('M/D h:mm:ss');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
y:{
|
||||
label: {
|
||||
|
|
|
@ -2,56 +2,57 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title></title>
|
||||
<title>Admin Panel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="/static/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="/static/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/css/normalize.min.css" />
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/css/foundation.min.css" />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/css/main-style.css">
|
||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" />
|
||||
<link href='//fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
|
||||
<link href='//fonts.googleapis.com/css?family=Raleway:500' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/railscasts.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/admin/css/style.css">
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="top-bar" data-topbar>
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="/">CTF</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="body-container">
|
||||
<div class="navbar navbar-inverse home">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button class="navbar-toggle" data-target=".navbar-collapse" data-toggle="collapse" type="button">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="/" class="navbar-brand">CTF</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav navbar-nav-right">
|
||||
<li><a href="/admin/graphs">Graphs</a></li>
|
||||
<li><a href="/admin/pages">Pages</a></li>
|
||||
<li><a href="/admin/teams">Teams</a></li>
|
||||
<li><a href="/admin/scoreboard">Scoreboard</a></li>
|
||||
<li><a href="/admin/chals">Challenges</a></li>
|
||||
<li><a href="/admin/statistics">Statistics</a></li>
|
||||
<li><a href="/admin/config">Config</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Left Nav Section -->
|
||||
<ul class="left">
|
||||
<li><a href="/admin/graphs">Graphs</a></li>
|
||||
<li><a href="/admin/pages">Pages</a></li>
|
||||
<li><a href="/admin/teams">Teams</a></li>
|
||||
<li><a href="/admin/scoreboard">Scoreboard</a></li>
|
||||
<li><a href="/admin/chals">Challenges</a></li>
|
||||
<li><a href="/admin/statistics">Statistics</a></li>
|
||||
<li><a href="/admin/config">Config</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</nav>
|
||||
|
||||
{% block content %} {% endblock %}
|
||||
<div class="container">
|
||||
{% block content %} {% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/jquery.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/modernizr.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation/foundation.topbar.min.js"></script>
|
||||
<script>
|
||||
$(document).foundation();
|
||||
</script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
|
||||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||
{% block scripts %} {% endblock %}
|
||||
</body>
|
||||
|
||||
|
|
|
@ -1,141 +1,283 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<style>
|
||||
.btn-primary { background-color: #337ab7; }
|
||||
.btn-danger { background-color: #d9534f; }
|
||||
.col-md-4 { margin-bottom: 15px; }
|
||||
.key-remove-button { margin-top: 10px; }
|
||||
.delete-tag { color: white; margin-left: 3px; cursor: pointer; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="email-user" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" value="{{ nonce }}" id="nonce">
|
||||
|
||||
<div id="create-challenge" class="reveal-modal" data-reveal>
|
||||
<h3>New Challenge</h3>
|
||||
<form method="POST" action="/admin/chal/new" enctype="multipart/form-data">
|
||||
<input type='text' name='name' placeholder='Name'><br/>
|
||||
<input type='text' name='category' placeholder='Category'><br/>
|
||||
|
||||
<ul id="new-desc-edit" class="tabs" data-tab>
|
||||
<li class="tab-title active"><a href="#new-desc-write" style="padding: 0 2rem;">Write</a></li>
|
||||
<li class="tab-title"><a href="#new-desc-preview" style="padding: 0 2rem;">Preview</a></li>
|
||||
</ul>
|
||||
<div class="tabs-content">
|
||||
<div class="content active" id="new-desc-write">
|
||||
<textarea id="new-desc-editor" class="new-chal-desc" name='desc' placeholder='Description' rows="10"></textarea><br>
|
||||
<div id="create-challenge" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>New Challenge</h3>
|
||||
</div>
|
||||
<div class="content" id="new-desc-preview">
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="/admin/chal/new" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" name="name" placeholder="Enter challenge name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category">Category</label>
|
||||
<input type="text" class="form-control" name="category" placeholder="Enter challenge category">
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist" id="new-desc-edit">
|
||||
<li role="presentation" class="active"><a href="#new-desc-write" aria-controls="home" role="tab" data-toggle="tab">Write</a></li>
|
||||
<li role="presentation"><a href="#new-desc-preview" aria-controls="home" role="tab" data-toggle="tab">Preview</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="new-desc-write">
|
||||
<div class="form-group">
|
||||
<label for="message-text" class="control-label">Message:</label>
|
||||
<textarea id="new-desc-editor" class="form-control" name="desc" rows="10"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="new-desc-preview">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="value">Value</label>
|
||||
<input type="number" class="form-control" name="value" placeholder="Enter value">
|
||||
</div>
|
||||
<div class="form-group" style="height:75px">
|
||||
<div class="col-md-9" style="padding-left:0px">
|
||||
<label for="key">Key</label>
|
||||
<input type="text" class="form-control" name="key" placeholder="Enter key">
|
||||
</div>
|
||||
<div class="col-md-3" style="margin-top:30px;padding-right:0px">
|
||||
<div class="radio-inline">
|
||||
<input type="radio" name="key_type[0]" value="0" checked>
|
||||
Static
|
||||
</div>
|
||||
<div class="radio-inline">
|
||||
<input type="radio" name="key_type[0]" value="1">
|
||||
Regex
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="exampleInputFile">Upload challenge files</label>
|
||||
<input type="file" name="files[]" multiple="multiple">
|
||||
</div>
|
||||
|
||||
<div style="text-align:center">
|
||||
<button class="btn btn-theme btn-outlined create-challenge" type="submit">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type='number' name='value' placeholder='Value'><br/>
|
||||
<input type='text' name='key' placeholder='Key'><br/>
|
||||
<input type="radio" name="key_type[0]" value="0" checked="checked">Static
|
||||
<input type="radio" name="key_type[0]" value="1">Regex
|
||||
<br/>
|
||||
<input type="file" name="files[]" multiple="multiple">
|
||||
|
||||
<button type='submit'>Create</button>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="delete-chal" class="reveal-modal" data-reveal>
|
||||
<h2 class="text-center">Delete Challenge</h2>
|
||||
<form method="POST" action="/admin/chal/delete">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<input type="hidden" name="id" class="chal-id">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete this challenge?</p>
|
||||
<p>Solves, wrong keys, files, tags will all be deleted.</p>
|
||||
<button type="button" class="button alert radius" onclick="$('#delete-chal').foundation('reveal', 'close');">No</button>
|
||||
<button type="submit" id="delete-user" class="button success radius">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
|
||||
<div id="update-keys" class="reveal-modal" data-reveal>
|
||||
<form method="POST" action="/admin/keys">
|
||||
<h3>Keys</h3>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="keys-chal" name='chal' type='hidden'>
|
||||
<div id="current-keys"></div>
|
||||
<a href="#" id="create-key" class="secondary button">New Key</a>
|
||||
<a href="#" id="submit-keys" class="button">Update</a>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="update-files" class="reveal-modal" data-reveal>
|
||||
<form method="POST" action="/admin/files" enctype="multipart/form-data">
|
||||
<h3>Files</h3>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="files-chal" name='chal' type='hidden'>
|
||||
|
||||
<div id="current-files"></div>
|
||||
<input type="hidden" name="method" value="upload">
|
||||
<input type="file" name="files[]" multiple="multiple">
|
||||
<button type='submit'>Upload</button>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="update-tags" class="reveal-modal" data-reveal>
|
||||
<h3>Tags</h3>
|
||||
<input type="text" class="tag-insert" maxlength="80" placeholder="Type tag and press Enter">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="tags-chal" name='chal' type='hidden'>
|
||||
|
||||
<div id="current-tags">
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<div id="chal-tags">
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<a href="#" id="submit-tags" class="button">Update</a>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
|
||||
<div id="update-challenge" class="reveal-modal" data-reveal>
|
||||
<form method="POST" action="/admin/chal/update">
|
||||
<h3 class="chal-title text-center"></h3>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
Name: <input class="chal-name" type='text' name='name' placeholder='Name'><br>
|
||||
Category: <input class="chal-category" type="text" name="category" placeholder="Category"><br>
|
||||
Description:
|
||||
|
||||
<ul id="desc-edit" class="tabs" data-tab>
|
||||
<li class="tab-title active"><a href="#desc-write" style="padding: 0 2rem;">Write</a></li>
|
||||
<li class="tab-title"><a href="#desc-preview" style="padding: 0 2rem;">Preview</a></li>
|
||||
</ul>
|
||||
<div class="tabs-content">
|
||||
<div class="content active" id="desc-write">
|
||||
<textarea id="desc-editor" class="chal-desc" name='desc' placeholder='Description' rows="10"></textarea><br>
|
||||
<div id="update-challenge" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="chal-title text-center"></h3>
|
||||
</div>
|
||||
<div class="content" id="desc-preview">
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="/admin/chal/update">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control chal-name" name="name" placeholder="Enter challenge name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category">Category</label>
|
||||
<input type="text" class="form-control chal-category" name="category" placeholder="Enter challenge category">
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist" id="desc-edit">
|
||||
<li role="presentation" class="active"><a href="#desc-write" aria-controls="home" role="tab" data-toggle="tab">Write</a></li>
|
||||
<li role="presentation"><a href="#desc-preview" aria-controls="home" role="tab" data-toggle="tab">Preview</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="desc-write">
|
||||
<div class="form-group">
|
||||
<label for="message-text" class="control-label">Message:</label>
|
||||
<textarea id="desc-editor" class="form-control chal-desc" name="desc" rows="10"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="desc-preview">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="value">Value</label>
|
||||
<input type="number" class="form-control chal-value" name="value" placeholder="Enter value">
|
||||
</div>
|
||||
<input class="chal-id" type='hidden' name='id' placeholder='ID'>
|
||||
|
||||
<div class="form-group">
|
||||
<a href="#" data-toggle="modal" data-target="#update-tags" class="btn btn-primary">Tags</a>
|
||||
<a href="#" data-toggle="modal" data-target="#update-files" class="btn btn-primary">Files</a>
|
||||
<a href="#" data-toggle="modal" data-target="#update-keys" class="btn btn-primary">Keys</a>
|
||||
<a href="#" data-toggle="modal" data-target="#delete-chal" class="btn btn-danger">Delete</a>
|
||||
</div>
|
||||
<div style="text-align:center">
|
||||
<button class="btn btn-theme btn-outlined create-challenge" type="submit">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Value: <input class="chal-value" type='number' name='value' placeholder='Value'><br>
|
||||
<input class="chal-id" type='hidden' name='id' placeholder='ID'>
|
||||
|
||||
<a href="#" data-reveal-id="update-tags" class="secondary button">Tags</a>
|
||||
<a href="#" data-reveal-id="update-files" class="secondary button">Files</a>
|
||||
<a href="#" data-reveal-id="update-keys" class="secondary button">Keys</a>
|
||||
<a href="#" data-reveal-id="delete-chal" class="secondary alert button">Delete</a>
|
||||
<button type='submit'>Update</button>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div id="delete-chal" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Delete Challenge</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="/admin/chal/delete">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<input type="hidden" name="id" class="chal-id">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete this challenge?</p>
|
||||
<p>Solves, wrong keys, files, tags will all be deleted.</p>
|
||||
<a onclick="$('#delete-chal').modal('hide')" class="btn btn-primary">No</a>
|
||||
<button class="btn btn-danger" id="delete-user" type="submit">Delete</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-keys" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Keys</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="/admin/keys" style="text-align:center">
|
||||
<a href="#" id="create-key" class="btn btn-primary" style="margin-bottom:15px;">New Key</a>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="keys-chal" name='chal' type='hidden'>
|
||||
<div id="current-keys" class="row"></div>
|
||||
<div class="row">
|
||||
<button id="submit-keys" class="btn btn-theme btn-outlined">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-files" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Files</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="/admin/files/" enctype="multipart/form-data">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="files-chal" name='chal' type='hidden'>
|
||||
<input name='method' type='hidden' value='upload'>
|
||||
|
||||
<div id="current-files"></div>
|
||||
<input type="hidden" name="method" value="upload">
|
||||
<input type="file" name="files[]" multiple="multiple">
|
||||
<div class="row" style="text-align:center;margin-top:20px">
|
||||
<button class="btn btn-theme btn-outlined" type="submit">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-tags" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Tags</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="tag-insert">Value</label>
|
||||
<input max-length="80" type="text" class="form-control tag-insert" name="tag-insert" placeholder="Type tag and press Enter">
|
||||
</div>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="tags-chal" name='chal' type='hidden'>
|
||||
|
||||
<div id="current-tags">
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<div id="chal-tags">
|
||||
</div>
|
||||
<div class="row" style="text-align:center;margin-top:20px">
|
||||
<button class="btn btn-theme btn-outlined" id="submit-tags">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="email-user" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Tags</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="text" class="tag-insert" maxlength="80" placeholder="Type tag and press Enter">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input id="tags-chal" name='chal' type='hidden'>
|
||||
|
||||
<div id="current-tags">
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<div id="chal-tags">
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<a href="#" id="submit-tags" class="button">Update</a>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:center">
|
||||
<h1 class="text-center">Challenges</h1>
|
||||
|
||||
<button class="btn btn-theme btn-outlined create-challenge">New Challenge</button>
|
||||
<div>
|
||||
<table id='challenges'>
|
||||
</table>
|
||||
<button style="width:100%;" class="radius create-challenge">New Challenge</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/static/admin/js/multi-modal.js"></script>
|
||||
<script src="/static/admin/js/chalboard.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,58 +2,67 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<h1>Config</h1>
|
||||
<form method="POST">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
<form method="POST">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
|
||||
<div class="row">
|
||||
<label for="start">CTF Name:</label>
|
||||
<input id='ctf_name' name='ctf_name' type='text' placeholder="CTF Name" {% if ctf_name is defined and ctf_name != None %}value="{{ ctf_name }}"{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ctf_name">CTF Name:</label>
|
||||
<input class="form-control" id='ctf_name' name='ctf_name' type='text' placeholder="CTF Name" {% if ctf_name is defined and ctf_name != None %}value="{{ ctf_name }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="max_tries">Maximum Attempts Per Challenge (0 to disable):</label>
|
||||
<input id='max_tries' name='max_tries' type='text' placeholder="0" {% if max_tries is defined and max_tries != None %}value="{{ max_tries }}"{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="max_tries">Maximum Attempts Per Challenge (0 to disable):</label>
|
||||
<input class="form-control" id='max_tries' name='max_tries' type='text' placeholder="0" {% if max_tries is defined and max_tries != None %}value="{{ max_tries }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="start">Mailgun API Key:</label>
|
||||
<input id='mg_api_key' name='mg_api_key' type='text' placeholder="Mailgun API Key" {% if mg_api_key is defined and mg_api_key != None %}value="{{ mg_api_key }}"{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="start">Mailgun API Key:</label>
|
||||
<input class="form-control" id='mg_api_key' name='mg_api_key' type='text' placeholder="Mailgun API Key" {% if mg_api_key is defined and mg_api_key != None %}value="{{ mg_api_key }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="start">Start Date:</label>
|
||||
<input id='start' name='start' type='text' placeholder="Start Date (UTC timestamp)" {% if start is defined and start != None %}value="{{ start }}"{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="start">Start Date:</label>
|
||||
<input class="form-control" id='start' name='start' type='text' placeholder="Start Date (UTC timestamp)" {% if start is defined and start != None %}value="{{ start }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="end">End Date:</label>
|
||||
<input id='end' name='end' type='text' placeholder="End Date (UTC timestamp)" {% if end is defined and end != None %}value="{{ end }}"{% endif %}>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="end">End Date:</label>
|
||||
<input class="form-control" id='end' name='end' type='text' placeholder="End Date (UTC timestamp)" {% if end is defined and end != None %}value="{{ end }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<input id="view_after_ctf" name="view_after_ctf" type="checkbox" {% if view_after_ctf %}checked{% endif %}>
|
||||
<label for="end">Allow challenges to be viewed after CTF end</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="view_after_ctf" name="view_after_ctf" type="checkbox" {% if view_after_ctf %}checked{% endif %}>
|
||||
Allow challenges to be viewed after CTF end
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<input id="view_challenges_unregistered" name="view_challenges_unregistered" type="checkbox" {% if view_challenges_unregistered %}checked{% endif %}>
|
||||
<label for="view_challenges_unregistered">Unregistered users can view challenges</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="view_challenges_unregistered" name="view_challenges_unregistered" type="checkbox" {% if view_challenges_unregistered %}checked{% endif %}>
|
||||
Unregistered users can view challenges
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<input id="prevent_registration" name="prevent_registration" type="checkbox" {% if prevent_registration %}checked{% endif %}>
|
||||
<label for="prevent_registration">Prevent public registration</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="prevent_registration" name="prevent_registration" type="checkbox" {% if prevent_registration %}checked{% endif %}>
|
||||
Prevent public registration
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<input id="prevent_name_change" name="prevent_name_change" type="checkbox" {% if prevent_name_change %}checked{% endif %}>
|
||||
<label for="prevent_name_change">Prevent team name changes</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="prevent_name_change" name="prevent_name_change" type="checkbox" {% if prevent_name_change %}checked{% endif %}>
|
||||
Prevent team name changes
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button class="radius" type='submit'>Update</button>
|
||||
</form>
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-primary btn-theme btn-outlined pull-right">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/theme/elegant.min.css">
|
||||
<style>
|
||||
.row-fluid { margin: 25px; padding-bottom: 25px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.css">
|
||||
<div class="row">
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
|
@ -13,25 +20,36 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<form id="page-edit" method="POST">
|
||||
<br>
|
||||
<strong>Route: </strong><input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input class="radius" id="route" type="text" name="route" value="{% if page is defined %}{{ page.route }}{% endif %}" placeholder="Route">
|
||||
<strong>HTML: </strong><textarea id="admin-pages-editor" name="html">{% if page is defined %}{{ page.html }}{% endif %}</textarea><br>
|
||||
<button class="radius" type='submit'>Create</button>
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<strong>Route: </strong><input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input class="radius" id="route" type="text" name="route" value="{% if page is defined %}{{ page.route }}{% endif %}" placeholder="Route">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<textarea id="admin-pages-editor" name="html">{% if page is defined %}{{ page.html }}{% endif %}</textarea><br>
|
||||
<button class="btn btn-theme btn-outlined create-challenge pull-right">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.2.0/mode/xml/xml.min.js"></script>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("admin-pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "text/html"
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'elegant'
|
||||
});
|
||||
|
||||
$('#page-edit').submit(function (e){
|
||||
$(this).attr('action', '/admin/pages/'+$('#route').val());
|
||||
});
|
||||
|
|
|
@ -2,14 +2,25 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div id="solves-graph"></div>
|
||||
<div id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<div class="col-md-6 col-md-offset-1">
|
||||
<div id="solves-graph"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div id="keys-pie-graph"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div id="categories-pie-graph"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<style>
|
||||
.row {
|
||||
text-align: center;
|
||||
}
|
||||
#solves-graph{
|
||||
margin-left: -50px;
|
||||
}
|
||||
|
@ -97,7 +108,7 @@
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function keys_percentage_graph(){
|
||||
// Solves and Fails pie chart
|
||||
$.get('/admin/fails/all', function(data){
|
||||
|
@ -124,7 +135,7 @@
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function category_breakdown_graph(){
|
||||
$.get('/admin/graphs/categories', function(data){
|
||||
res = $.parseJSON(JSON.stringify(data));
|
||||
|
@ -163,6 +174,6 @@
|
|||
});
|
||||
|
||||
setInterval(update, 300000);
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,29 +1,84 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
<style>
|
||||
.input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
#submit {
|
||||
position: relative;
|
||||
right: -30px;
|
||||
}
|
||||
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h1>Login</h1>
|
||||
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
<div class="large-8 large-centered columns">
|
||||
<div data-alert class="alert-box alert radius centered text-center">
|
||||
<span>{{ error }}</span>
|
||||
<a href="#" class="close">×</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% for error in errors %}
|
||||
<div class="submit-row">
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="name" id="name-input" />
|
||||
<label class="input-label" for="name-input">
|
||||
<span class="label-content" data-content="Team Name">Team Name</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="password-input" />
|
||||
<label class="input-label" for="password-input">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="done-row row">
|
||||
<div class="col-md-6">
|
||||
<a class="pull-left align-text-to-button" href="/reset_password">Forgot your password?</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined pull-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<input class="radius" type='text' name='name' placeholder='Name'><br/>
|
||||
<input class="radius" type='password' name='password' placeholder='Password'><br/>
|
||||
<p><a href="/reset_password">Forgot your password?</a></p>
|
||||
<button class="radius" type='submit'>Login</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,30 +1,46 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.css">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.11.0/theme/elegant.min.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<div id="confirm" class="reveal-modal" data-reveal>
|
||||
<h2 class="text-center">Delete Page</h2>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="route">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete <strong id="confirm-route-name"></strong>?</p>
|
||||
<button type="button" class="button alert radius" onclick="$('#confirm').foundation('reveal', 'close');">No</button>
|
||||
<button type="button" id="delete-route" class="button success radius">Yes</button>
|
||||
<div id="confirm" class="modal fade" tabindex="-1" data-width="760">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center">Delete Page</h2>
|
||||
</div>
|
||||
<div class="modal-body" style="height:110px">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="route">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete <strong id="confirm-route-name"></strong>?</p>
|
||||
<button type="button" data-dismiss="modal" class="btn btn-theme btn-outlined">No</button>
|
||||
<button type="button" id="delete-route" class="btn btn-theme btn-outlined">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-6 columns">
|
||||
<div class="col-md-9">
|
||||
<h3>CSS editor <a onclick="save_css()"><i class="fa fa-floppy-o"></i></a></h3>
|
||||
<div style="height: 500px;" id="admin-css-editor" name="css">{{ css }}</div>
|
||||
<textarea id="pages-editor" name="html">{{ css }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="small-6 columns">
|
||||
<div class="col-md-3">
|
||||
<h3>HTML Pages <a href="/admin/pages?mode=create"><i class="fa fa-plus"></i></a></h3>
|
||||
<table id="pages">
|
||||
<table id="pages" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Route</b></td>
|
||||
|
@ -45,10 +61,17 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-github.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-css.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.2.0/mode/xml/xml.min.js"></script>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'elegant'
|
||||
});
|
||||
|
||||
$('#delete-route').click(function(e){
|
||||
e.preventDefault();
|
||||
var route = $('#confirm input[name="route"]').val()
|
||||
|
@ -65,7 +88,7 @@ function load_confirm_modal(route){
|
|||
modal.find('input[name=route]').val(route)
|
||||
modal.find('#confirm-route-name').text(route)
|
||||
$('#confirm form').attr('action', '/admin/page/'+route+'/delete');
|
||||
$('#confirm').foundation('reveal', 'open');
|
||||
$('#confirm').modal();
|
||||
}
|
||||
|
||||
function save_css(){
|
||||
|
@ -82,9 +105,5 @@ $('.fa-times').click(function(){
|
|||
load_confirm_modal(name)
|
||||
});
|
||||
|
||||
var editor = ace.edit("admin-css-editor");
|
||||
editor.setTheme("ace/theme/github");
|
||||
editor.getSession().setMode("ace/mode/css");
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<table id="scoreboard">
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b></td>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="row" style="text-align:center">
|
||||
<h1>Statistics</h1>
|
||||
|
||||
<h3><b>{{ team_count }}</b> teams registered</h3>
|
||||
|
|
|
@ -1,79 +1,103 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
<style>
|
||||
td { text-align:center; }
|
||||
.checkbox { margin: 0px !important; }
|
||||
input[type="checkbox"] { margin: 0px !important; position: relative; top: 5px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<div id="confirm" class="reveal-modal" data-reveal>
|
||||
<h2 class="text-center">Delete User</h2>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="id">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete <strong id="confirm-team-name"></strong>?</p>
|
||||
<button type="button" class="button alert radius" onclick="$('#confirm').foundation('reveal', 'close');">No</button>
|
||||
<button type="button" id="delete-user" class="button success radius">Yes</button>
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center">Delete User</h2>
|
||||
</div>
|
||||
<div class="modal-body" style="height:110px">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="route">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p>Are you sure you want to delete <strong id="confirm-team-name"></strong>?</p>
|
||||
<button type="button" data-dismiss="modal" class="btn btn-theme btn-outlined">No</button>
|
||||
<button type="button" id="delete-user" class="btn btn-theme btn-outlined">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="email-user" class="reveal-modal" data-reveal>
|
||||
<h2 class="text-center">Email User</h2>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="id">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<textarea name="msg" placeholder="Enter your message here" rows="15"></textarea>
|
||||
<div id="email-user-errors"></div>
|
||||
<button type="button" id="send-user-email">Send Message</button>
|
||||
</form>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
<div id="email-user" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center">Email User</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="id">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<textarea name="msg" placeholder="Enter your message here" rows="15"></textarea>
|
||||
<div id="email-user-errors"></div>
|
||||
<button type="button" id="send-user-email">Send Message</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="user" class="reveal-modal" data-reveal>
|
||||
<h2 class="text-center">Edit User</h2>
|
||||
<form method="POST" action="/admin/teams/">
|
||||
<div class="row">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<input type="hidden" name="id">
|
||||
<div class="large-12 columns">
|
||||
<label>Team Name
|
||||
<input type="text" name="name" placeholder="Enter new team name" />
|
||||
</label>
|
||||
<div id="user" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center">Edit User</h2>
|
||||
</div>
|
||||
<div class="large-12 columns">
|
||||
<label>Email
|
||||
<input type="text" name="email" placeholder="Enter new email" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="large-12 columns">
|
||||
<label>Password
|
||||
<input type="password" name="password" placeholder="Enter new password" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="large-12 columns">
|
||||
<label>Website
|
||||
<input type="text" name="website" placeholder="Enter Website" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="large-6 columns">
|
||||
<label>Affiliation
|
||||
<input type="text" name="affiliation" placeholder="Enter Affiliation" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="large-6 columns">
|
||||
<label>Country
|
||||
<input type="text" name="country" placeholder="Enter Country" />
|
||||
</label>
|
||||
</div>
|
||||
<div id="results">
|
||||
<div class="modal-body" style="padding:20px; height:525px;">
|
||||
<form method="POST" action="/admin/teams/">
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<input type="hidden" name="id">
|
||||
<div class="form-group">
|
||||
<label for="name">Team Name</label>
|
||||
<input type="text" class="form-control" name="name" id="name" placeholder="Enter new team name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" name="email" id="email" placeholder="Enter new email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" name="password" id="password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="website">Website</label>
|
||||
<input type="text" class="form-control" name="website" id="website" placeholder="Enter website">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="affiliation">Affiliation</label>
|
||||
<input type="text" class="form-control" name="affiliation" id="affiliation" placeholder="Enter affiliation">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="affiliation">Country</label>
|
||||
<input type="text" class="form-control" name="country" id="country" placeholder="Enter country">
|
||||
</div>
|
||||
<div id="results">
|
||||
|
||||
</div>
|
||||
<button id="update-user" type="submit" class="btn btn-theme btn-outlined pull-right">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
<button id="update-user" class="radius" type="submit">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
</div>
|
||||
<table id="teamsboard">
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px" class="text-center"><b>ID</b>
|
||||
|
@ -126,7 +150,7 @@
|
|||
<div class="text-center">Page
|
||||
<br>
|
||||
{% for page in range(1, pages + 1) %}
|
||||
<a href="/admin/teams/{{ page }}">{{ page }}</a>
|
||||
<a href="/admin/teams/{{ page }}">{{ page }}</a>
|
||||
{% endfor %}
|
||||
<a href="">
|
||||
</div>
|
||||
|
@ -138,16 +162,15 @@
|
|||
<script>
|
||||
function load_update_modal(id, name, email, website, affiliation, country){
|
||||
var modal_form = $('#user form');
|
||||
|
||||
|
||||
modal_form.find('input[name=name]').val(name)
|
||||
modal_form.find('input[name=id]').val(id)
|
||||
modal_form.find('input[name=email]').val(email)
|
||||
modal_form.find('input[name=website]').val(website)
|
||||
modal_form.find('input[name=affiliation]').val(affiliation)
|
||||
modal_form.find('input[name=country]').val(country)
|
||||
console.log(modal_form);
|
||||
$('#user form').attr('action', '/admin/team/'+id)
|
||||
$('#user').foundation('reveal', 'open');
|
||||
$('#user').modal("show");
|
||||
}
|
||||
|
||||
$('#update-user').click(function(e){
|
||||
|
@ -170,7 +193,7 @@ $('#update-user').click(function(e){
|
|||
|
||||
row.find('.team-affiliation').text( $.grep(user_data, function(e){ return e.name == 'affiliation'; })[0]['value'] );
|
||||
row.find('.team-country').text( $.grep(user_data, function(e){ return e.name == 'country'; })[0]['value'] );
|
||||
$('#user').foundation('reveal', 'close');
|
||||
$('#user').modal();
|
||||
}
|
||||
else{
|
||||
$('#results').append($('p').text( data['data'][i] ))
|
||||
|
@ -195,7 +218,7 @@ $('#send-user-email').click(function(e){
|
|||
var email_data = $('#email-user form').serializeArray();
|
||||
$.post($('#email-user form').attr('action'), $('#email-user form').serialize(), function(data){
|
||||
if (data == "1"){
|
||||
$('#email-user').foundation('reveal', 'close');
|
||||
$('#email-user').modal();
|
||||
}
|
||||
else{
|
||||
$('#email-user-errors').append("<b>Failed to send email</b>");
|
||||
|
@ -232,7 +255,7 @@ function load_confirm_modal(id, name){
|
|||
modal.find('input[name=id]').val(id)
|
||||
modal.find('#confirm-team-name').text(name)
|
||||
$('#confirm form').attr('action', '/admin/team/'+id+'/delete');
|
||||
$('#confirm').foundation('reveal', 'open');
|
||||
$('#confirm').modal();
|
||||
}
|
||||
|
||||
$('.fa-times').click(function(){
|
||||
|
@ -248,7 +271,7 @@ function load_email_modal(id){
|
|||
modal.find('input[name=id]').val(id)
|
||||
$('#email-user-errors').empty()
|
||||
$('#email-user form').attr('action', '/admin/team/'+id+'/mail');
|
||||
$('#email-user').foundation('reveal', 'open');
|
||||
$('#email-user').modal();
|
||||
}
|
||||
|
||||
$('.fa-envelope').click(function(){
|
||||
|
|
|
@ -6,72 +6,67 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="/static/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="/static/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/css/normalize.min.css" />
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/css/foundation.min.css" />
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/css/main-style.css">
|
||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" />
|
||||
<link href='//fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
|
||||
<link href='//fonts.googleapis.com/css?family=Raleway:500' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/railscasts.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/user.css">
|
||||
{% block stylesheets %}{% endblock %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="top-bar" data-topbar>
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="/">{{ ctf_name() }}</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
|
||||
</ul>
|
||||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
{% if username is defined %}
|
||||
<li class="has-dropdown">
|
||||
<a href="/team/{{ id }}">{{ username }} {% if admin %} (ADMIN) {% endif %}</a>
|
||||
<ul class="dropdown">
|
||||
{% if admin %}
|
||||
<li><a href="/admin">Admin</a></li>
|
||||
{% endif %}
|
||||
<li><a href="/team/{{ id }}">Team</a></li>
|
||||
<li><a href="/profile">Account</a></li>
|
||||
<li><a href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{%else %}
|
||||
<li class="has-form">
|
||||
{% if can_register() %}
|
||||
<li><a href="/register">Register</a></li>
|
||||
{% endif %}
|
||||
<li><a href="/login">Login</a></li>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Left Nav Section -->
|
||||
<ul class="left">
|
||||
{% for page in pages() %}
|
||||
<li><a href="/{{ page.route }}">{{ page.route|title }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="/teams">Teams</a></li>
|
||||
<li><a href="/scoreboard">Scoreboard</a></li>
|
||||
<li><a href="/challenges">Challenges</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</nav>
|
||||
<div class="body-container">
|
||||
<div class="navbar navbar-inverse home">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button class="navbar-toggle" data-target=".navbar-collapse" data-toggle="collapse" type="button">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="/" class="navbar-brand">{{ ctf_name() }}</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav">
|
||||
{% for page in pages() %}
|
||||
<li><a href="/{{ page.route }}">{{ page.route|title }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="/teams">Teams</a></li>
|
||||
<li><a href="/scoreboard">Scoreboard</a></li>
|
||||
<li><a href="/challenges">Challenges</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if username is defined %}
|
||||
{% if admin %}
|
||||
<li><a href="/admin">Admin</a></li>
|
||||
{% endif %}
|
||||
<li><a href="/team/{{ id }}">Team</a></li>
|
||||
<li><a href="/profile">Profile</a></li>
|
||||
<li><a href="/logout">Logout</a></li>
|
||||
{% else %}
|
||||
{% if can_register() %}
|
||||
<li><a href="/register">Register</a></li>
|
||||
<li><a style="padding-left:0px;padding-right:0px;">|</a></li>
|
||||
{% endif %}
|
||||
<li><a href="/login">Login</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/jquery.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/modernizr.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation/foundation.topbar.min.js"></script>
|
||||
<script>
|
||||
$(document).foundation();
|
||||
</script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/jquery.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/modernizr.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,53 +1,164 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.0/isotope.pkgd.min.js">
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
<style>
|
||||
.hide-text { text-overflow: ellipsis; overflow: hidden; }
|
||||
.dialog-inner {padding-bottom: 30px;}
|
||||
.alert {display: none}
|
||||
.category-header {text-align: center}
|
||||
.challenge-wrapper {padding: 5px;}
|
||||
.challenge-button {width: 100%}
|
||||
.submit-row {padding-top: 0px; padding-right: 0px; padding-left: 0px;}
|
||||
.disabled-button {background-color: #EEEEEE}
|
||||
|
||||
.file-button {text-decoration: none; color: #fff;}
|
||||
.file-button:hover {text-decoration: none; color: #fff;}
|
||||
.file-wrapper {padding: 20px; transition: all 0.5s ease; cursor: pointer; color: #fff; width: 100%; text-overflow: ellipsis; overflow: hidden;}
|
||||
.file-button {cursor: pointer;}
|
||||
.file-button-wrapper {padding: 0px 10px;}
|
||||
|
||||
.close-text {color: #ccc;position: relative;top: -25px;right: -15px;cursor: pointer;}
|
||||
.chal-desc {padding-left: 30px; padding-right: 30px;}
|
||||
.key-submit {padding-top: 14px; padding-right: 10px;}
|
||||
.notification-row {padding-left: 10px;padding-right: 10px;}
|
||||
.input {padding-right: 5px;}
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .input-field {
|
||||
border-color: rgb(238, 238, 238);
|
||||
}
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .correct {
|
||||
border-color: rgb(223, 240, 216);
|
||||
}
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .wrong {
|
||||
border-color: rgb(255, 190, 190);
|
||||
}
|
||||
a, button {
|
||||
color: #74716D;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a:hover, a:focus {
|
||||
color: #c94e50;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 1em 2em;
|
||||
outline: none;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background: #c94e50;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 1000px;
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
padding: 2.5em 0 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
button.trigger {
|
||||
background: #c94e50;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
|
||||
<div id="chal-solves-window" class="reveal-modal" data-reveal>
|
||||
<h3>Solved By</h3>
|
||||
<div class="scroll-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Name</b>
|
||||
</td>
|
||||
<td><b>Date</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="chal-solves-names">
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Challenges</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div id='challenges-board' class="row">
|
||||
</div>
|
||||
<a class="close-reveal-modal" data-reveal-id="chal-window">×</a>
|
||||
</div>
|
||||
|
||||
<div id="chal-window" class="reveal-modal" data-reveal>
|
||||
<div class="row">
|
||||
<h3 class='chal-name'></h3>
|
||||
<h4 class="chal-value"></h4>
|
||||
<p><i><a data-reveal-id="chal-solves-window" class="chal-solves"></a></i></p>
|
||||
<p class="chal-desc"></p>
|
||||
{% if ctftime %}
|
||||
<input id="answer" type="text" placeholder="Key">
|
||||
<input type="hidden" id="nonce" name="nonce" value={{ nonce }}>
|
||||
<button id="submit-key">Submit</button>
|
||||
{% endif %}
|
||||
<input id="chal-id" type="hidden">
|
||||
</div>
|
||||
<a class="close-reveal-modal">×</a>
|
||||
</div>
|
||||
<div class="modal fade" id="chal-window" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content content">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#challenge" aria-controls="challenge" role="tab">Challenge</a></li>
|
||||
<li role="presentation"><a href="#solves" aria-controls="solves" class="chal-solves" role="tab"></a></li>
|
||||
</ul>
|
||||
<div class="modal-body">
|
||||
<div role="tabpanel">
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="challenge">
|
||||
<h3 class='chal-name'></h3>
|
||||
<h4 class="chal-value"></h4>
|
||||
<p class="chal-desc"></p>
|
||||
<div class="chal-files file-row row">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1 class="text-center">Challenges</h1>
|
||||
<br>
|
||||
|
||||
<div class="large-12 columns">
|
||||
<table id='challenges'>
|
||||
</table>
|
||||
<div class="row submit-row">
|
||||
<div class="col-md-9" style="padding-right:0px;padding-left:10px;">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="answer" id="answer-input" placeholder="Key" />
|
||||
</span>
|
||||
<input type="hidden" id="nonce" name="nonce" value={{ nonce }}>
|
||||
<input id="chal-id" type="hidden">
|
||||
</div>
|
||||
<div class="col-md-3 key-submit">
|
||||
<button type="submit" id="submit-key" tabindex="5" class="btn btn-md btn-theme btn-outlined pull-right" style="height:46.375px">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row notification-row">
|
||||
<div id="incorrect-key" class="alert alert-danger alert-dismissable" role="alert">
|
||||
<strong>Incorrect</strong>
|
||||
</div>
|
||||
<div id="correct-key" class="alert alert-success alert-dismissable" role="alert">
|
||||
<strong>Correct</strong>
|
||||
</div>
|
||||
<div id="already-solved" class="alert alert-info alert-dismissable" role="alert">
|
||||
<strong>You already solved this</strong>
|
||||
</div>
|
||||
<div id="too-fast" class="alert alert-warning alert-dismissable" role="alert">
|
||||
<strong>You're submitting keys too fast. Slow down.</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="solves">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Name</b>
|
||||
</td>
|
||||
<td><b>Date</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="chal-solves-names">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="solves-graph" style="width: 90%; height: 400px; margin: 0 auto"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
@ -55,4 +166,13 @@
|
|||
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
|
||||
<script src="/static/js/chalboard.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
<script>
|
||||
$('[data-dialog-close]').click(function() {
|
||||
$('.nav-tabs > li:nth-child(1)').addClass("active");
|
||||
$('.nav-tabs > li:nth-child(2)').removeClass("active");
|
||||
openDialog.toggle();
|
||||
window.location.hash = ""
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,30 +1,73 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
<style>
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h1>Login</h1>
|
||||
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
<div class="large-8 large-centered columns">
|
||||
<div data-alert class="alert-box alert radius centered text-center">
|
||||
<span>{{ error }}</span>
|
||||
<a href="#" class="close">×</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% for error in errors %}
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="name" id="name-input" />
|
||||
<label class="input-label" for="name-input">
|
||||
<span class="label-content" data-content="Team Name">Team Name</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="password-input" />
|
||||
<label class="input-label" for="password-input">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="done-row row">
|
||||
<div class="col-md-6" style="padding-left:0px">
|
||||
<a class="pull-left align-text-to-button" href="/reset_password">Forgot your password?</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined pull-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<input class="radius" type='text' name='name' placeholder='Name'><br/>
|
||||
<input class="radius" type='password' name='password' placeholder='Password'><br/>
|
||||
<p><a href="/reset_password">Forgot your password?</a></p>
|
||||
<input type="hidden" name="nonce" value="{{nonce}}">
|
||||
<button class="radius" type='submit'>Login</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,46 +1,133 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
<style>
|
||||
hr {
|
||||
margin-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.row {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
|
||||
<div class="row">
|
||||
<br/>
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
<form method="POST">
|
||||
<span>Team Name</span>
|
||||
<input class="radius" type="text" name="name" placeholder="Team Name" value="{{name}}" {% if prevent_name_change %}disabled{% endif %}>
|
||||
|
||||
<span>Email Address</span>
|
||||
<input class="radius" type="text" name="email" placeholder="Email Address" value="{{email}}">
|
||||
<br/>
|
||||
<hr/>
|
||||
<br/>
|
||||
<span>Old Password</span>
|
||||
<input class="radius" type="password" name="confirm" placeholder="Old Password">
|
||||
|
||||
<span>Password</span>
|
||||
<input class="radius" type="password" name="password" placeholder="Password">
|
||||
<br/>
|
||||
<hr/>
|
||||
<br/>
|
||||
<span>Website</span>
|
||||
<input class="radius" type="text" name="website" placeholder="Website" value="{% if website %}{{website}}{% endif %}">
|
||||
<span>Affiliation</span>
|
||||
<input class="radius" type="text" name="affiliation" placeholder="Affiliation" value="{% if affiliation %}{{affiliation}}{% endif %}">
|
||||
<span>Country</span>
|
||||
<input class="radius" type="text" name="country" placeholder="Country" value="{% if country %}{{country}}{% endif %}">
|
||||
<input type="hidden" name="nonce" value="{{nonce}}">
|
||||
<button class="radius">Update</button>
|
||||
</form>
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Profile</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% if success %}
|
||||
<div class="alert alert-success alert-dismissable submit-row" role="alert">
|
||||
<strong>Success!</strong>
|
||||
Your profile has been updated
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% else %}
|
||||
{% for error in errors %}
|
||||
<div class="submit-row">
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="name" id="name-input" value="{{name}}"/>
|
||||
<label class="input-label" for="name-input">
|
||||
<span class="label-content" data-content="Team Name">Team Name</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="email" id="email-input" value="{{email}}"/>
|
||||
<label class="input-label" for="email-input">
|
||||
<span class="label-content" data-content="Email">Email</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="confirm" id="confirm-input" />
|
||||
<label class="input-label" for="confirm-input">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="password-input" />
|
||||
<label class="input-label" for="password-input">
|
||||
<span class="label-content" data-content="New Password">New Password</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="affiliation" id="affiliation-input" value="{% if affiliation %}{{affiliation}}{% endif %}" />
|
||||
<label class="input-label" for="affiliation-input">
|
||||
<span class="label-content" data-content="Affiliation">Affiliation</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="website" id="website-input" value="{% if website %}{{website}}{% endif %}" />
|
||||
<label class="input-label" for="website-input">
|
||||
<span class="label-content" data-content="Website">Website</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="country" id="country-input" value="{% if country %}{{country}}{% endif %}" />
|
||||
<label class="input-label" for="country-input">
|
||||
<span class="label-content" data-content="Country">Country</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="submit-row">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-primary btn-theme btn-outlined pull-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
|
||||
<script src="/static/js/team.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,34 +1,73 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h1>Register</h1>
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
{% endblock %}
|
||||
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
<div class="large-8 large-centered columns">
|
||||
<div data-alert class="alert-box alert radius centered text-center">
|
||||
<span>{{ error }}</span>
|
||||
<a href="#" class="close">×</a>
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Register</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% for error in errors %}
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="name" id="input-10" />
|
||||
<label class="input-label" for="input-10">
|
||||
<span class="label-content" data-content="Team Name">Team Name</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="email" id="input-10" />
|
||||
<label class="input-label" for="input-10">
|
||||
<span class="label-content" data-content="Email">Email</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="input-10" />
|
||||
<label class="input-label" for="input-10">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="done-row row">
|
||||
<div class="col-md-6 col-md-offset-6" style="margin-top:10px">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined pull-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<input type='text' class="radius" name='name' placeholder='Team Name' {% if name %}value="{{ name }}"{% endif %}><br/>
|
||||
<input type='text' class="radius" name='email' placeholder='Email' {% if email %}value="{{ email }}"{% endif %}><br/>
|
||||
<input type='password' class="radius" name='password' placeholder='Password' {% if password %}value="{{ password }}"{% endif %}><br/>
|
||||
<button class="radius" type='submit'>Register</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
<script>
|
||||
if (window.location.hash == "#frame"){
|
||||
$('.top-bar').hide()
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,34 +1,60 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h1>Reset Password</h1>
|
||||
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
<div class="large-8 large-centered columns">
|
||||
<div data-alert class="alert-box alert radius centered text-center">
|
||||
<span>{{ error }}</span>
|
||||
<a href="#" class="close">×</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Reset Password</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% for error in errors %}
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
{% if mode %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="password-input" />
|
||||
<label class="input-label" for="password-input">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="email" id="input-10" />
|
||||
<label class="input-label" for="input-10">
|
||||
<span class="label-content" data-content="Email">Email</span>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="done-row row">
|
||||
<div class="col-md-6 col-md-offset-6" style="margin-top:10px">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined pull-right">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if mode %}
|
||||
<form method="POST">
|
||||
<input class="radius" type='password' name='password' placeholder='Password'><br/>
|
||||
<button class="radius" type='submit'>Reset Password</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form method="POST">
|
||||
<input class="radius" type='text' name='email' placeholder='Email'><br/>
|
||||
<button class="radius" type='submit'>Reset Password</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
|
||||
<div class="row">
|
||||
<h1>Scoreboard</h1>
|
||||
<br>
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Scoreboard</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div id="score-graph"></div>
|
||||
<br>
|
||||
|
||||
<table id="scoreboard">
|
||||
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b>
|
||||
|
|
|
@ -1,56 +1,102 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.css">
|
||||
<div class="row">
|
||||
<h1>Setup</h1>
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.css">
|
||||
<link rel="stylesheet" href="/static/css/input.css">
|
||||
<link rel="stylesheet" href="/static/css/codemirror-monokai.css">
|
||||
<style>
|
||||
.submit-row {
|
||||
padding-right: 15px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
<div class="row">
|
||||
{% for error in errors %}
|
||||
<div class="large-8 large-centered columns">
|
||||
<div data-alert class="alert-box alert radius centered text-center">
|
||||
<span>{{ error }}</span>
|
||||
<a href="#" class="close">×</a>
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Setup</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
<h2 class="text-center">CTF Settings</h2>
|
||||
{% for error in errors %}
|
||||
<div class="submit-row">
|
||||
<div class="alert alert-danger alert-dismissable" role="alert">
|
||||
<span class="sr-only">Error:</span>
|
||||
{{ error }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<form method="post" accept-charset="utf-8" autocomplete="off" role="form" class="form-horizontal">
|
||||
<input type="hidden" name="nonce" value="{{nonce}}"> {# This nonce is implemented specially in the route itself #}
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="ctf_name" id="ctf_name-input" />
|
||||
<label class="input-label" for="ctf_name-input">
|
||||
<span class="label-content" data-content="CTF Name">CTF Name</span>
|
||||
</label>
|
||||
</span>
|
||||
<span class="input">
|
||||
<input class="input-field" type="text" name="name" id="username-input" />
|
||||
<label class="input-label" for="username-input">
|
||||
<span class="label-content" data-content="Username">Username</span>
|
||||
</label>
|
||||
</span>
|
||||
<span class="input">
|
||||
<input class="input-field" type="email" name="email" id="email-input" />
|
||||
<label class="input-label" for="email-input">
|
||||
<span class="label-content" data-content="Email">Email</span>
|
||||
</label>
|
||||
</span>
|
||||
<span class="input">
|
||||
<input class="input-field" type="password" name="password" id="password-input" />
|
||||
<label class="input-label" for="password-input">
|
||||
<span class="label-content" data-content="Password">Password</span>
|
||||
</label>
|
||||
</span>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<strong>CTF Name</strong>
|
||||
<input class="radius" type='text' name='ctf_name' placeholder='CTF Name'><br/>
|
||||
|
||||
<strong>Username</strong>
|
||||
<input class="radius" type='text' name='name' placeholder='Name'><br/>
|
||||
|
||||
<strong>Email</strong>
|
||||
<input class="radius" type='text' name='email' placeholder='Email'><br/>
|
||||
|
||||
<strong>Password</strong>
|
||||
<input class="radius" type='password' name='password' placeholder='Password'><br/>
|
||||
<strong>Index Page</strong>
|
||||
<div class="container" style="margin-bottom:50px;">
|
||||
<h2 class="text-center">Index Page</h2>
|
||||
<textarea id="pages-editor" name="html">
|
||||
<div class="row">
|
||||
<img class="logo" src="/static/img/logo.png">
|
||||
<h3 class="text-center">Welcome to a cool CTF framework written by <a href="https://github.com/ColdHeat">Kevin Chung</a> of <a href="https://github.com/isislab">@isislab</a></h3>
|
||||
<img class="logo" src="/static/img/logo.png" />
|
||||
<h3 class="text-center">
|
||||
Welcome to a cool CTF framework written by <a href="https://github.com/ColdHeat">Kevin Chung</a> of <a href="https://github.com/isislab">@isislab</a>
|
||||
</h3>
|
||||
|
||||
<h4 class="text-center"><a href="/login">Click here</a> to login and setup your CTF</h4>
|
||||
<h4 class="text-center">
|
||||
<a href="/admin">Click here</a> to login and setup your CTF
|
||||
</h4>
|
||||
</div>
|
||||
</textarea><br>
|
||||
<input type="hidden" name="nonce" value="{{nonce}}"> {# This nonce is implemented specially in the route itself #}
|
||||
<button class="radius" type='submit'>Login</button>
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="container main-container" style="margin-bottom:100px;">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
<div class="submit-row text-center">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.min.js"></script>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "text/html"
|
||||
});
|
||||
</script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/classie/1.0.1/classie.min.js"></script>
|
||||
<script src="/static/js/input.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.8.0/codemirror.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.2.0/mode/xml/xml.min.js"></script>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'monokai'
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,28 +1,35 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css">
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css">
|
||||
{% endblock %}
|
||||
|
||||
<div class="row">
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
<h2 id="team-place" class="text-center">
|
||||
{%if place %}
|
||||
{{ place }} <small>place</small>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<h2 id="team-score" class="text-center">
|
||||
{%if score %}
|
||||
{{ score }} <small>points</small>
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="team-info">
|
||||
<h2 id="team-place" class="text-center">
|
||||
{%if place %}
|
||||
{{ place }} <small>place</small>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<h2 id="team-score" class="text-center">
|
||||
{%if score %}
|
||||
{{ score }} <small>points</small>
|
||||
{% endif %}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<div id="score-graph"></div>
|
||||
|
||||
<table>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Challenge</b></td>
|
||||
|
@ -37,9 +44,8 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="score-graph"></div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.0/c3.min.css">
|
||||
{% endblock %}
|
||||
|
||||
<div class="row">
|
||||
<h1>Teams</h1>
|
||||
<br>
|
||||
<table id="teamsboard">
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Teams</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>ID</b></td>
|
||||
<td><b>Team</b></td>
|
||||
<td><b>Website</b></td>
|
||||
<td><b>Affiliation</b></td>
|
||||
|
@ -19,9 +23,8 @@
|
|||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td class="team-id">{{ team.id }}</td>
|
||||
<td><a href="/team/{{ team.id }}">{{ team.name | truncate(32) }}</a></td>
|
||||
<td>{% if team.website and team.website.startswith('http') %}<a href="{{ team.website }}">{{ team.website }}</a>{% endif %}</td>
|
||||
<td><a href="/team/{{ team.id }}">{{ team.name }}</a></td>
|
||||
<td>{% if team.website and team.website.startswith('http://') %}<a href="{{ team.website }}">{{ team.website }}</a>{% endif %}</td>
|
||||
<td><span>{% if team.affiliation %}{{ team.affiliation }}{% endif %}</span></td>
|
||||
<td><span>{% if team.country %}{{ team.country }}{% endif %}</span></td>
|
||||
</tr>
|
||||
|
@ -32,7 +35,7 @@
|
|||
<div class="text-center">Page
|
||||
<br>
|
||||
{% for page in range(1, team_pages + 1) %}
|
||||
<a href="/teams/{{ page }}">{{ page }}</a>
|
||||
<a href="/teams/{{ page }}">{{ page }}</a>
|
||||
{% endfor %}
|
||||
<a href="">
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue