mirror of https://github.com/JohnHammond/CTFd.git
Design improvements (#276)
* Fixes #269 * Adding tooltips to some admin content * Switching from spaces to tabs in HTML files * A variety of aesthetic improvementsselenium-screenshot-testing
parent
285b320ea5
commit
4fedc8f69e
|
@ -494,3 +494,7 @@ table{
|
|||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gray-text{
|
||||
color: lightgray;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
|
@ -1,11 +1,15 @@
|
|||
<div class="col-md-6 col-md-offset-3">
|
||||
<form method="POST" action="{{ script_root }}/admin/chal/new" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<label for="name">Name
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="The name of your challenge"></i>
|
||||
</label>
|
||||
<input type="text" class="form-control" name="name" placeholder="Enter challenge name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category">Category</label>
|
||||
<label for="category">Category
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="The category of your challenge"></i>
|
||||
</label>
|
||||
<input type="text" class="form-control" name="category" placeholder="Enter challenge category">
|
||||
</div>
|
||||
|
||||
|
@ -16,22 +20,28 @@
|
|||
<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>
|
||||
<label for="message-text" class="control-label">Message:
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="Use this to give a brief introduction to your challenge. The description supports HTML and Markdown."></i>
|
||||
</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" style="height:234px">
|
||||
<div role="tabpanel" class="tab-pane content" id="new-desc-preview" style="height:234px; overflow-y: scroll;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="value">Value</label>
|
||||
<label for="value">Value
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="This is how many points are rewarded for solving this challenge."></i>
|
||||
</label>
|
||||
<input type="number" class="form-control" name="value" placeholder="Enter value" required>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="col-md-8">
|
||||
<label for="key">Key</label>
|
||||
<label for="key">Key
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="This is the flag/solution for the challenge."></i>
|
||||
</label>
|
||||
<input type="text" class="form-control" name="key" placeholder="Enter key">
|
||||
</div>
|
||||
<div class="form-vertical">
|
||||
|
@ -74,7 +84,9 @@
|
|||
</label>
|
||||
</div>
|
||||
<div id="solve-attempts-input" style="display: none;">
|
||||
<label for="max_attempts">Maximum Attempts</label>
|
||||
<label for="max_attempts">Maximum Attempts
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="How many attempts should a user have for this challenge? For unlimited attempts, use the value 0"></i>
|
||||
</label>
|
||||
<input class="form-control" id='max_attempts' name='max_attempts' type='number' placeholder="0">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,7 +94,9 @@
|
|||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="col-md-9">
|
||||
<label>Upload challenge files</label>
|
||||
<label>Upload Challenge Files
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="Challenges files are provided to users for download alongside your challenge description"></i>
|
||||
</label>
|
||||
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
|
||||
<input type="file" name="files[]" multiple="multiple">
|
||||
</div>
|
||||
|
|
|
@ -16,4 +16,8 @@ $("#solve-attempts-checkbox").change(function() {
|
|||
$('#solve-attempts-input').hide();
|
||||
$('#max_attempts').val('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
|
|
@ -10,11 +10,15 @@
|
|||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<label for="name">Name
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="The name of your challenge"></i>
|
||||
</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>
|
||||
<label for="category">Category
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="The category of your challenge"></i>
|
||||
</label>
|
||||
<input type="text" class="form-control chal-category" name="category" placeholder="Enter challenge category">
|
||||
</div>
|
||||
|
||||
|
@ -25,16 +29,20 @@
|
|||
<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>
|
||||
<label for="message-text" class="control-label">Message:
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="Use this to give a brief introduction to your challenge. The description supports HTML and Markdown."></i>
|
||||
</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" style="height:214px">
|
||||
<div role="tabpanel" class="tab-pane content" id="desc-preview" style="height:214px; overflow-y: scroll;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="value">Value</label>
|
||||
<label for="value">Value
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="This is how many points teams will receive once they solve this challenge."></i>
|
||||
</label>
|
||||
<input type="number" class="form-control chal-value" name="value" placeholder="Enter value" required>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -388,3 +388,6 @@ function openchal(id){
|
|||
loadfiles(id);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
|
|
@ -18,6 +18,10 @@ a {
|
|||
outline: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.body-container {
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
|
|
|
@ -2,82 +2,83 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Admin Panel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment-timezone-with-data.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
<title>Admin Panel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment-timezone-with-data.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<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="{{ request.script_root }}/" class="navbar-brand">CTFd</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav navbar-nav-right">
|
||||
<li><a href="{{ request.script_root }}/admin/graphs">Graphs</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">Pages <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ request.script_root }}/admin/pages">All Pages</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/pages?mode=create">New Page</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{{ request.script_root }}/admin/teams">Teams</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/scoreboard">Scoreboard</a></li>
|
||||
{% if can_create_container() %}
|
||||
<li><a href="{{ request.script_root }}/admin/containers">Containers</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/admin/chals">Challenges</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/statistics">Statistics</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/config">Config</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Plugins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plugin in get_configurable_plugins() %}
|
||||
<li><a href="{{ request.script_root }}/admin/plugins/{{ plugin }}">{{ plugin }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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="{{ request.script_root }}/" class="navbar-brand">CTFd</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav navbar-nav-right">
|
||||
<li><a href="{{ request.script_root }}/admin/graphs">Graphs</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">Pages <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ request.script_root }}/admin/pages">All Pages</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/pages?mode=create">New Page</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{{ request.script_root }}/admin/teams">Teams</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/scoreboard">Scoreboard</a></li>
|
||||
{% if can_create_container() %}
|
||||
<li><a href="{{ request.script_root }}/admin/containers">Containers</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/admin/chals">Challenges</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/statistics">Statistics</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/config">Config</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Plugins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plugin in get_configurable_plugins() %}
|
||||
<li><a href="{{ request.script_root }}/admin/plugins/{{ plugin }}">{{ plugin }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<div class="navbar navbar-bottom footer">
|
||||
<p class="text-muted text-center"><a style="text-decoration:none;" href="https://ctfd.io"><sub>Powered by CTFd</sub></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/bootstrap.min.js"></script>
|
||||
{% block scripts %} {% endblock %}
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<div class="navbar navbar-bottom footer">
|
||||
<p class="text-muted text-center"><a style="text-decoration:none;" href="https://ctfd.io"><sub>Powered by CTFd</sub></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/bootstrap.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/main.js"></script>
|
||||
{% block scripts %} {% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -11,46 +11,46 @@
|
|||
{% 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>
|
||||
<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">
|
||||
<input type="hidden" value="{{ nonce }}" id="nonce">
|
||||
|
||||
<div id="create-challenge" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3>New Challenge</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="create-challenge" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3>New Challenge</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-modals-entry-div">
|
||||
</div>
|
||||
<div id="update-modals-entry-div">
|
||||
</div>
|
||||
|
||||
<div style="text-align:center">
|
||||
<br>
|
||||
<h1 class="text-center">Challenges</h1>
|
||||
<a class="btn btn-theme btn-outlined create-challenge" href="{{ request.script_root }}/admin/chal/new" role="button">New Challenge</a>
|
||||
<div>
|
||||
<table id='challenges'>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align:center">
|
||||
<br>
|
||||
<h1 class="text-center">Challenges</h1>
|
||||
<a class="btn btn-theme btn-outlined create-challenge" href="{{ request.script_root }}/admin/chal/new" role="button">New Challenge</a>
|
||||
<div>
|
||||
<table id='challenges'>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/chalboard.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/multi-modal.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/chalboard.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/multi-modal.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -12,61 +12,61 @@
|
|||
|
||||
{% block content %}
|
||||
<div id="create-challenge" class="container main-container">
|
||||
<h1 class="text-center">Create Challenge</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="create-chals-select-div">
|
||||
<label for="create-chals-select" class="control-label">Choose Challenge Type</label>
|
||||
<select class="form-control" id="create-chals-select">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div id="create-chal-entry-div">
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-center">Create Challenge</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="create-chals-select-div">
|
||||
<label for="create-chals-select" class="control-label">Choose Challenge Type</label>
|
||||
<select class="form-control" id="create-chals-select">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div id="create-chal-entry-div">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/codemirror.min.js"></script>
|
||||
<script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/codemirror.min.js"></script>
|
||||
<script>
|
||||
|
||||
function load_chal_template(chal_type_name){
|
||||
$.get(script_root + '/static/admin/js/templates/challenges/'+ chal_type_name +'/' + chal_type_name + '-challenge-create.hbs', function(template_data){
|
||||
var template = Handlebars.compile(template_data);
|
||||
$("#create-chal-entry-div").html(template({'nonce':nonce, 'script_root':script_root}));
|
||||
$.getScript(script_root + '/static/admin/js/templates/challenges/'+chal_type_name+'/'+chal_type_name+'-challenge-create.js', function(){
|
||||
console.log('loaded');
|
||||
});
|
||||
});
|
||||
}
|
||||
function load_chal_template(chal_type_name){
|
||||
$.get(script_root + '/static/admin/js/templates/challenges/'+ chal_type_name +'/' + chal_type_name + '-challenge-create.hbs', function(template_data){
|
||||
var template = Handlebars.compile(template_data);
|
||||
$("#create-chal-entry-div").html(template({'nonce':nonce, 'script_root':script_root}));
|
||||
$.getScript(script_root + '/static/admin/js/templates/challenges/'+chal_type_name+'/'+chal_type_name+'-challenge-create.js', function(){
|
||||
console.log('loaded');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
nonce = "{{ nonce }}";
|
||||
$.get(script_root + '/admin/chal_types', function(data){
|
||||
console.log(data);
|
||||
$("#create-chals-select").empty();
|
||||
var chal_type_amt = Object.keys(data).length;
|
||||
if (chal_type_amt > 1){
|
||||
var option = "<option> -- </option>";
|
||||
$("#create-chals-select").append(option);
|
||||
for (var key in data){
|
||||
var option = "<option value='{0}'>{1}</option>".format(key, data[key]);
|
||||
$("#create-chals-select").append(option);
|
||||
}
|
||||
} else if (chal_type_amt == 1) {
|
||||
var key = Object.keys(data)[0];
|
||||
$("#create-chals-select").parent().parent().parent().empty();
|
||||
load_chal_template(data[key]);
|
||||
}
|
||||
});
|
||||
$('#create-chals-select').change(function(){
|
||||
var chal_type_name = $(this).find("option:selected").text();
|
||||
load_chal_template(chal_type_name);
|
||||
});
|
||||
</script>
|
||||
nonce = "{{ nonce }}";
|
||||
$.get(script_root + '/admin/chal_types', function(data){
|
||||
console.log(data);
|
||||
$("#create-chals-select").empty();
|
||||
var chal_type_amt = Object.keys(data).length;
|
||||
if (chal_type_amt > 1){
|
||||
var option = "<option> -- </option>";
|
||||
$("#create-chals-select").append(option);
|
||||
for (var key in data){
|
||||
var option = "<option value='{0}'>{1}</option>".format(key, data[key]);
|
||||
$("#create-chals-select").append(option);
|
||||
}
|
||||
} else if (chal_type_amt == 1) {
|
||||
var key = Object.keys(data)[0];
|
||||
$("#create-chals-select").parent().parent().parent().empty();
|
||||
load_chal_template(data[key]);
|
||||
}
|
||||
});
|
||||
$('#create-chals-select').change(function(){
|
||||
var chal_type_name = $(this).find("option:selected").text();
|
||||
load_chal_template(chal_type_name);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,109 +2,109 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="modal fade" id="create-container-modal" tabindex="-1" role="dialog" aria-labelledby="container-modal-label">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="container-modal-label">Create Container</h4>
|
||||
</div>
|
||||
<form method="POST" action="{{ request.script_root }}/admin/containers/new" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" name="name" placeholder="Enter container name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="buildfile-editor" class="control-label">Build File</label>
|
||||
<textarea id="buildfile-editor" class="form-control" name="buildfile" rows="10" placeholder="Enter container build file"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="container-files">Associated Files
|
||||
<i class="fa fa-question-circle" title="These files are uploaded alongside your buildfile"></i>
|
||||
</label>
|
||||
<input type="file" name="files[]" id="container-files" multiple>
|
||||
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
|
||||
</div>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="container-modal-label">Create Container</h4>
|
||||
</div>
|
||||
<form method="POST" action="{{ request.script_root }}/admin/containers/new" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" name="name" placeholder="Enter container name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="buildfile-editor" class="control-label">Build File</label>
|
||||
<textarea id="buildfile-editor" class="form-control" name="buildfile" rows="10" placeholder="Enter container build file"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="container-files">Associated Files
|
||||
<i class="fa fa-question-circle gray-text" data-toggle="tooltip" data-placement="right" title="These files are uploaded alongside your buildfile"></i>
|
||||
</label>
|
||||
<input type="file" name="files[]" id="container-files" multiple>
|
||||
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
|
||||
</div>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center"><span id="confirm-container-title"></span> Container</h2>
|
||||
</div>
|
||||
<div class="modal-body" style="height:110px">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<form method="POST">
|
||||
<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 <span id="confirm-container-method"></span> <strong id="confirm-container-name"></strong>?</p>
|
||||
<button type="button" data-dismiss="modal" class="btn btn-theme btn-outlined">No</button>
|
||||
<button type="button" id="confirm-container" class="btn btn-theme btn-outlined">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="text-center"><span id="confirm-container-title"></span> Container</h2>
|
||||
</div>
|
||||
<div class="modal-body" style="height:110px">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<form method="POST">
|
||||
<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 <span id="confirm-container-method"></span> <strong id="confirm-container-name"></strong>?</p>
|
||||
<button type="button" data-dismiss="modal" class="btn btn-theme btn-outlined">No</button>
|
||||
<button type="button" id="confirm-container" class="btn btn-theme btn-outlined">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<br>
|
||||
<div style="text-align:center">
|
||||
<h1>Containers</h1>
|
||||
<button class="btn btn-theme btn-outlined create-challenge" data-toggle="modal" data-target="#create-container-modal">
|
||||
New Container
|
||||
</button>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div style="text-align:center">
|
||||
<h1>Containers</h1>
|
||||
<button class="btn btn-theme btn-outlined create-challenge" data-toggle="modal" data-target="#create-container-modal">
|
||||
New Container
|
||||
</button>
|
||||
</div>
|
||||
<br>
|
||||
{% if containers %}
|
||||
<table id="teamsboard">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><strong>Status</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Name</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Ports</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Settings</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for c in containers %}
|
||||
<tr>
|
||||
<td class="text-center">{{ c.status }}</td>
|
||||
<td class="text-center container_item" id="{{ c.id }}">{{ c.name }}</td>
|
||||
<td class="text-center">{{ c.ports }}</td>
|
||||
<td class="text-center">
|
||||
<span>
|
||||
{% if c.status != 'running' %}
|
||||
<i class="fa fa-play"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-stop"></i>
|
||||
{% endif %}
|
||||
<i class="fa fa-times"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="teamsboard">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><strong>Status</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Name</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Ports</strong>
|
||||
</td>
|
||||
<td class="text-center"><strong>Settings</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for c in containers %}
|
||||
<tr>
|
||||
<td class="text-center">{{ c.status }}</td>
|
||||
<td class="text-center container_item" id="{{ c.id }}">{{ c.name }}</td>
|
||||
<td class="text-center">{{ c.ports }}</td>
|
||||
<td class="text-center">
|
||||
<span>
|
||||
{% if c.status != 'running' %}
|
||||
<i class="fa fa-play"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-stop"></i>
|
||||
{% endif %}
|
||||
<i class="fa fa-times"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -113,46 +113,50 @@
|
|||
<script>
|
||||
|
||||
function load_confirm_modal(title, url, container_name){
|
||||
var modal = $('#confirm')
|
||||
modal.find('#confirm-container-name').text(container_name)
|
||||
modal.find('#confirm-container-title').text(title)
|
||||
modal.find('#confirm-container-method').text(title.toLowerCase())
|
||||
$('#confirm form').attr('action', url);
|
||||
$('#confirm').modal('show');
|
||||
var modal = $('#confirm')
|
||||
modal.find('#confirm-container-name').text(container_name)
|
||||
modal.find('#confirm-container-title').text(title)
|
||||
modal.find('#confirm-container-method').text(title.toLowerCase())
|
||||
$('#confirm form').attr('action', url);
|
||||
$('#confirm').modal('show');
|
||||
}
|
||||
|
||||
$('#confirm-container').click(function(e){
|
||||
e.preventDefault();
|
||||
var id = $('#confirm input[name="id"]').val()
|
||||
var user_data = $('#confirm form').serializeArray()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
e.preventDefault();
|
||||
var id = $('#confirm input[name="id"]').val()
|
||||
var user_data = $('#confirm form').serializeArray()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
$('.fa-times').click(function(){
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Delete', '/admin/containers/'+container+'/delete', container_name)
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Delete', '/admin/containers/'+container+'/delete', container_name)
|
||||
});
|
||||
|
||||
$('.fa-play').click(function(){
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Start', '/admin/containers/'+container+'/start', container_name)
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Start', '/admin/containers/'+container+'/start', container_name)
|
||||
});
|
||||
|
||||
$('.fa-stop').click(function(){
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Stop', '/admin/containers/'+container+'/stop', container_name)
|
||||
var elem = $(this).parent().parent().parent().find('.container_item');
|
||||
var container = elem.attr('id');
|
||||
var container_name = elem.text().trim();
|
||||
load_confirm_modal('Stop', '/admin/containers/'+container+'/stop', container_name)
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -10,102 +10,102 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<br>
|
||||
<h1>Correct Key Submissions</h1>
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Delete Key</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="">
|
||||
<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 successful key submission for team: <strong id="confirm-team-name"></strong> in challenge: <strong id="confirm-chal-name"></strong>?</p>
|
||||
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="teamsboard" class=" table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Team</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Challenge</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Date</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Key Submitted</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Delete</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr>
|
||||
<td class="text-center team" id="{{ solve.teamid }}"><a href="{{ request.script_root }}/admin/team/{{ solve.teamid }}">{{ solve.team_name }}</a>
|
||||
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal_name }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center flag" id="{{ solve.id }}">{{ solve.flag }}</td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/admin/correct_keys/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/admin/correct_keys/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{ page }}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != pages %}<a href="{{ request.script_root }}/admin/correct_keys/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
<a href="{{ request.script_root }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
<br>
|
||||
<h1>Correct Key Submissions</h1>
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3>Delete Key</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="">
|
||||
<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 successful key submission for team: <strong id="confirm-team-name"></strong> in challenge: <strong id="confirm-chal-name"></strong>?</p>
|
||||
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="teamsboard" class=" table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Team</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Challenge</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Date</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Key Submitted</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Delete</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr>
|
||||
<td class="text-center team" id="{{ solve.teamid }}"><a href="{{ request.script_root }}/admin/team/{{ solve.teamid }}">{{ solve.team_name }}</a>
|
||||
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal_name }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center flag" id="{{ solve.id }}">{{ solve.flag }}</td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/admin/correct_keys/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/admin/correct_keys/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{ page }}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != pages %}<a href="{{ request.script_root }}/admin/correct_keys/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
<a href="{{ request.script_root }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script>
|
||||
$('#delete-solve').click(function(e){
|
||||
e.preventDefault();
|
||||
var solve = $('#confirm input[name="solve"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script>
|
||||
$('#delete-solve').click(function(e){
|
||||
e.preventDefault();
|
||||
var solve = $('#confirm input[name="solve"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function load_confirm_modal(key_id, team_name, chal_name){
|
||||
var modal = $('#confirm')
|
||||
modal.find('#confirm-team-name').text(team_name)
|
||||
modal.find('#confirm-chal-name').text(chal_name)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/solves/'+key_id+'/delete');
|
||||
$('#confirm').modal('show');
|
||||
}
|
||||
function load_confirm_modal(key_id, team_name, chal_name){
|
||||
var modal = $('#confirm')
|
||||
modal.find('#confirm-team-name').text(team_name)
|
||||
modal.find('#confirm-chal-name').text(chal_name)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/solves/'+key_id+'/delete');
|
||||
$('#confirm').modal('show');
|
||||
}
|
||||
|
||||
$('.fa-times').click(function(){
|
||||
var elem = $(this).parent().parent();
|
||||
var chal = elem.find('.chal').attr('id');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team = elem.find('.team').attr('id');
|
||||
var team_name = elem.find('.team').text().trim();
|
||||
var key_id = elem.find('.flag').attr('id');
|
||||
load_confirm_modal(key_id, team_name, chal_name)
|
||||
});
|
||||
</script>
|
||||
$('.fa-times').click(function(){
|
||||
var elem = $(this).parent().parent();
|
||||
var chal = elem.find('.chal').attr('id');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team = elem.find('.team').attr('id');
|
||||
var team_name = elem.find('.team').text().trim();
|
||||
var key_id = elem.find('.flag').attr('id');
|
||||
load_confirm_modal(key_id, team_name, chal_name)
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/vendor/codemirror.min.css">
|
||||
<style>
|
||||
.row-fluid { margin: 25px; padding-bottom: 25px; }
|
||||
.media-item-wrapper { height: 120px; margin: 5px;
|
||||
float: left; border: 1px solid #eee; text-align: center; text-overflow: ellipsis; overflow: hidden;}
|
||||
.media-item-wrapper > a > i {line-height: 90px;}
|
||||
.media-item-title{ font-size: 10px; }
|
||||
#media-item{display: none;}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/vendor/codemirror.min.css">
|
||||
<style>
|
||||
.row-fluid { margin: 25px; padding-bottom: 25px; }
|
||||
.media-item-wrapper { height: 120px; margin: 5px;
|
||||
float: left; border: 1px solid #eee; text-align: center; text-overflow: ellipsis; overflow: hidden;}
|
||||
.media-item-wrapper > a > i {line-height: 90px;}
|
||||
.media-item-title{ font-size: 10px; }
|
||||
#media-item{display: none;}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="media-modal" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 class="text-center">Media Library</h3>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 class="text-center">Media Library</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-1" id="media-library-list">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<h4 class="text-center">Media Details</h4>
|
||||
<div id="media-item">
|
||||
<div class="row text-center" id="media-icon">
|
||||
</div>
|
||||
<br>
|
||||
<div class="row text-center" id="media-filename">
|
||||
</div>
|
||||
<br>
|
||||
<div class="row form-group">
|
||||
Link: <input class="form-control" type="text" id="media-link">
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-1" id="media-library-list">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<h4 class="text-center">Media Details</h4>
|
||||
<div id="media-item">
|
||||
<div class="row text-center" id="media-icon">
|
||||
</div>
|
||||
<br>
|
||||
<div class="row text-center" id="media-filename">
|
||||
</div>
|
||||
<br>
|
||||
<div class="row form-group">
|
||||
Link: <input class="form-control" type="text" id="media-link">
|
||||
</div>
|
||||
|
||||
<div class="row form-group text-center">
|
||||
<button class="btn btn-success" id="media-insert">Insert</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group text-center">
|
||||
<button class="btn btn-success" id="media-insert">Insert</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
<form id="media-library-upload">
|
||||
<div class="form-group">
|
||||
<label for="media-files">Upload Files
|
||||
</label>
|
||||
<input type="file" name="files[]" id="media-files" multiple>
|
||||
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
|
||||
</div>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
</form>
|
||||
<div class="pull-right">
|
||||
<button type="submit" class="btn btn-primary" onclick="uploadfiles();">Upload</button>
|
||||
</div>
|
||||
<form id="media-library-upload">
|
||||
<div class="form-group">
|
||||
<label for="media-files">Upload Files
|
||||
</label>
|
||||
<input type="file" name="files[]" id="media-files" multiple>
|
||||
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
|
||||
</div>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
</form>
|
||||
<div class="pull-right">
|
||||
<button type="submit" class="btn btn-primary" onclick="uploadfiles();">Upload</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<form id="page-edit" method="POST">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<h3>Route: </h3>
|
||||
<p class="help-block">This is the URL route that your page will be at (e.g. /page)</p>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input class="form-control radius" id="route" type="text" name="route" value="{% if page is defined %}{{ page.route }}{% endif %}" placeholder="Route">
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<form id="page-edit" method="POST">
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
<h3>Route: </h3>
|
||||
<p class="help-block">This is the URL route that your page will be at (e.g. /page)</p>
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<input class="form-control radius" id="route" type="text" name="route" value="{% if page is defined %}{{ page.route }}{% endif %}" placeholder="Route">
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row-fluid">
|
||||
<div class="col-md-12">
|
||||
|
||||
<h3>Content: </h3>
|
||||
<p class="help-block">This is the HTML content of your page</p>
|
||||
<h3>Content: </h3>
|
||||
<p class="help-block">This is the HTML content of your page</p>
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist" id="content-edit">
|
||||
<li role="presentation" class="active"><a href="#content-write" aria-controls="home" role="tab" data-toggle="tab">Write</a></li>
|
||||
<li role="presentation"><a href="#content-preview" aria-controls="home" role="tab" data-toggle="tab">Preview</a></li>
|
||||
</ul>
|
||||
<ul class="nav nav-tabs" role="tablist" id="content-edit">
|
||||
<li role="presentation" class="active"><a href="#content-write" aria-controls="home" role="tab" data-toggle="tab">Write</a></li>
|
||||
<li role="presentation"><a href="#content-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="content-write" style="height:400px">
|
||||
<div class="form-group">
|
||||
<br>
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="...">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-default" id="media-button"><i class="fa fa-camera-retro" aria-hidden="true"></i> Media Library</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="content-write" style="height:400px">
|
||||
<div class="form-group">
|
||||
<br>
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="...">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-default" id="media-button"><i class="fa fa-camera-retro" aria-hidden="true"></i> Media Library</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<textarea id="admin-pages-editor" name="html">{% if page is defined %}{{ page.html }}{% endif %}</textarea><br>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="content-preview" style="height:400px">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-theme btn-outlined create-challenge pull-right">
|
||||
{% if page is defined %}
|
||||
Update
|
||||
{% else %}
|
||||
Create
|
||||
{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<textarea id="admin-pages-editor" name="html">{% if page is defined %}{{ page.html }}{% endif %}</textarea><br>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="content-preview" style="height:400px">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-theme btn-outlined create-challenge pull-right">
|
||||
{% if page is defined %}
|
||||
Update
|
||||
{% else %}
|
||||
Create
|
||||
{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -132,158 +132,158 @@
|
|||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/codemirror.min.js"></script>
|
||||
<script>
|
||||
function uploadfiles(){
|
||||
var form = $('#media-library-upload')[0];
|
||||
var formData = new FormData(form);
|
||||
console.log(formData);
|
||||
$.ajax({
|
||||
url: script_root + '/admin/media',
|
||||
data: formData,
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
refreshfiles(data);
|
||||
form.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
function uploadfiles(){
|
||||
var form = $('#media-library-upload')[0];
|
||||
var formData = new FormData(form);
|
||||
console.log(formData);
|
||||
$.ajax({
|
||||
url: script_root + '/admin/media',
|
||||
data: formData,
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data){
|
||||
refreshfiles(data);
|
||||
form.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refreshfiles(data){
|
||||
var data = data.results;
|
||||
var list = $('#media-library-list');
|
||||
var mapping = {
|
||||
// Image Files
|
||||
'png': 'fa-file-image-o',
|
||||
'jpg': 'fa-file-image-o',
|
||||
'jpeg': 'fa-file-image-o',
|
||||
'gif': 'fa-file-image-o',
|
||||
'bmp': 'fa-file-image-o',
|
||||
'svg': 'fa-file-image-o',
|
||||
function refreshfiles(data){
|
||||
var data = data.results;
|
||||
var list = $('#media-library-list');
|
||||
var mapping = {
|
||||
// Image Files
|
||||
'png': 'fa-file-image-o',
|
||||
'jpg': 'fa-file-image-o',
|
||||
'jpeg': 'fa-file-image-o',
|
||||
'gif': 'fa-file-image-o',
|
||||
'bmp': 'fa-file-image-o',
|
||||
'svg': 'fa-file-image-o',
|
||||
|
||||
// Text Files
|
||||
'txt': 'fa-file-text-o',
|
||||
// Text Files
|
||||
'txt': 'fa-file-text-o',
|
||||
|
||||
// Video Files
|
||||
'mov': 'fa-file-video-o',
|
||||
'mp4': 'fa-file-video-o',
|
||||
'wmv': 'fa-file-video-o',
|
||||
'flv': 'fa-file-video-o',
|
||||
'mkv': 'fa-file-video-o',
|
||||
'avi': 'fa-file-video-o',
|
||||
// Video Files
|
||||
'mov': 'fa-file-video-o',
|
||||
'mp4': 'fa-file-video-o',
|
||||
'wmv': 'fa-file-video-o',
|
||||
'flv': 'fa-file-video-o',
|
||||
'mkv': 'fa-file-video-o',
|
||||
'avi': 'fa-file-video-o',
|
||||
|
||||
// PDF Files
|
||||
'pdf': 'fa-file-pdf-o',
|
||||
// PDF Files
|
||||
'pdf': 'fa-file-pdf-o',
|
||||
|
||||
// Audio Files
|
||||
'mp3': 'fa-file-sound-o',
|
||||
'wav': 'fa-file-sound-o',
|
||||
'aac': 'fa-file-sound-o',
|
||||
// Audio Files
|
||||
'mp3': 'fa-file-sound-o',
|
||||
'wav': 'fa-file-sound-o',
|
||||
'aac': 'fa-file-sound-o',
|
||||
|
||||
// Archive Files
|
||||
'zip': 'fa-file-archive-o',
|
||||
'gz': 'fa-file-archive-o',
|
||||
'tar': 'fa-file-archive-o',
|
||||
'7z': 'fa-file-archive-o',
|
||||
'rar': 'fa-file-archive-o',
|
||||
// Archive Files
|
||||
'zip': 'fa-file-archive-o',
|
||||
'gz': 'fa-file-archive-o',
|
||||
'tar': 'fa-file-archive-o',
|
||||
'7z': 'fa-file-archive-o',
|
||||
'rar': 'fa-file-archive-o',
|
||||
|
||||
// Code Files
|
||||
'py': 'fa-file-code-o',
|
||||
'c': 'fa-file-code-o',
|
||||
'cpp': 'fa-file-code-o',
|
||||
'html': 'fa-file-code-o',
|
||||
'js': 'fa-file-code-o',
|
||||
'rb': 'fa-file-code-o',
|
||||
'go': 'fa-file-code-o',
|
||||
}
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var f = data[i];
|
||||
var ext = f.location.split('.').pop();
|
||||
var fname = f.location.split('/')[1];
|
||||
// Code Files
|
||||
'py': 'fa-file-code-o',
|
||||
'c': 'fa-file-code-o',
|
||||
'cpp': 'fa-file-code-o',
|
||||
'html': 'fa-file-code-o',
|
||||
'js': 'fa-file-code-o',
|
||||
'rb': 'fa-file-code-o',
|
||||
'go': 'fa-file-code-o',
|
||||
}
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var f = data[i];
|
||||
var ext = f.location.split('.').pop();
|
||||
var fname = f.location.split('/')[1];
|
||||
|
||||
var wrapper = $('<div>').attr('class', 'media-item-wrapper col-md-2')
|
||||
var wrapper = $('<div>').attr('class', 'media-item-wrapper col-md-2')
|
||||
|
||||
var link = $('<a>');
|
||||
link.attr('href', '#');
|
||||
var link = $('<a>');
|
||||
link.attr('href', '##');
|
||||
|
||||
if (mapping[ext] == undefined)
|
||||
link.append('<i class="fa fa-file-o fa-4x" aria-hidden="true"></i>'.format(mapping[ext]));
|
||||
else
|
||||
link.append('<i class="fa {0} fa-4x" aria-hidden="true"></i>'.format(mapping[ext]));
|
||||
if (mapping[ext] == undefined)
|
||||
link.append('<i class="fa fa-file-o fa-4x" aria-hidden="true"></i>'.format(mapping[ext]));
|
||||
else
|
||||
link.append('<i class="fa {0} fa-4x" aria-hidden="true"></i>'.format(mapping[ext]));
|
||||
|
||||
link.click(function(e){
|
||||
var media_div = $(this).parent();
|
||||
var icon = $(this).find('.fa')[0];
|
||||
var f_loc = media_div.attr('data-location');
|
||||
var fname = media_div.attr('data-filename');
|
||||
$('#media-link').val(f_loc);
|
||||
$('#media-filename').text(fname);
|
||||
link.click(function(e){
|
||||
var media_div = $(this).parent();
|
||||
var icon = $(this).find('.fa')[0];
|
||||
var f_loc = media_div.attr('data-location');
|
||||
var fname = media_div.attr('data-filename');
|
||||
$('#media-link').val(f_loc);
|
||||
$('#media-filename').text(fname);
|
||||
|
||||
$('#media-icon').empty()
|
||||
if ($(icon).hasClass('fa-file-image-o')){
|
||||
$('#media-icon').append($('<img>').attr('src', f_loc).attr('width', '100%'));
|
||||
} else {
|
||||
// icon is empty so we need to pull outerHTML
|
||||
$('#media-icon').append(icon.outerHTML);
|
||||
}
|
||||
$('#media-item').show();
|
||||
});
|
||||
wrapper.append(link);
|
||||
wrapper.attr('data-location', script_root + '/files/' + f.location);
|
||||
wrapper.attr('data-id', f.id);
|
||||
wrapper.attr('data-filename', fname);
|
||||
list.append(wrapper);
|
||||
$('#media-icon').empty()
|
||||
if ($(icon).hasClass('fa-file-image-o')){
|
||||
$('#media-icon').append($('<img>').attr('src', f_loc).attr('width', '100%'));
|
||||
} else {
|
||||
// icon is empty so we need to pull outerHTML
|
||||
$('#media-icon').append(icon.outerHTML);
|
||||
}
|
||||
$('#media-item').show();
|
||||
});
|
||||
wrapper.append(link);
|
||||
wrapper.attr('data-location', script_root + '/files/' + f.location);
|
||||
wrapper.attr('data-id', f.id);
|
||||
wrapper.attr('data-filename', fname);
|
||||
list.append(wrapper);
|
||||
|
||||
wrapper.append($('<span>').attr('class', 'media-item-title').text(fname));
|
||||
}
|
||||
}
|
||||
wrapper.append($('<span>').attr('class', 'media-item-title').text(fname));
|
||||
}
|
||||
}
|
||||
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("admin-pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'elegant'
|
||||
});
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("admin-pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'elegant'
|
||||
});
|
||||
|
||||
function insert_at_cursor(editor, text) {
|
||||
var doc = editor.getDoc();
|
||||
var cursor = doc.getCursor();
|
||||
doc.replaceRange(text, cursor);
|
||||
}
|
||||
function insert_at_cursor(editor, text) {
|
||||
var doc = editor.getDoc();
|
||||
var cursor = doc.getCursor();
|
||||
doc.replaceRange(text, cursor);
|
||||
}
|
||||
|
||||
$('#media-insert').click(function(e){
|
||||
var tag = $('#media-icon').children()[0].nodeName.toLowerCase();
|
||||
console.log(tag);
|
||||
var link = $('#media-link').val();
|
||||
var fname = $('#media-filename').text();
|
||||
if (tag == 'img'){
|
||||
var entry = '![{0}]({1})'.format(fname, link);
|
||||
} else if (tag == 'i'){
|
||||
var entry = '[{0}]({1})'.format(fname, link);
|
||||
}
|
||||
$('#media-insert').click(function(e){
|
||||
var tag = $('#media-icon').children()[0].nodeName.toLowerCase();
|
||||
console.log(tag);
|
||||
var link = $('#media-link').val();
|
||||
var fname = $('#media-filename').text();
|
||||
if (tag == 'img'){
|
||||
var entry = '![{0}]({1})'.format(fname, link);
|
||||
} else if (tag == 'i'){
|
||||
var entry = '[{0}]({1})'.format(fname, link);
|
||||
}
|
||||
|
||||
insert_at_cursor(editor, entry);
|
||||
});
|
||||
insert_at_cursor(editor, entry);
|
||||
});
|
||||
|
||||
$('#page-edit').submit(function (e){
|
||||
$(this).attr('action', '{{ request.script_root }}/admin/pages/'+$('#route').val());
|
||||
});
|
||||
$('#page-edit').submit(function (e){
|
||||
$(this).attr('action', '{{ request.script_root }}/admin/pages/'+$('#route').val());
|
||||
});
|
||||
|
||||
// Markdown Preview
|
||||
$('#content-edit').on('shown.bs.tab', function (event) {
|
||||
if (event.target.hash == '#content-preview'){
|
||||
$(event.target.hash).html(marked(editor.getValue(), {'gfm':true, 'breaks':true}));
|
||||
}
|
||||
});
|
||||
// Markdown Preview
|
||||
$('#content-edit').on('shown.bs.tab', function (event) {
|
||||
if (event.target.hash == '#content-preview'){
|
||||
$(event.target.hash).html(marked(editor.getValue(), {'gfm':true, 'breaks':true}));
|
||||
}
|
||||
});
|
||||
|
||||
$('#media-button').click(function(){
|
||||
$.get(script_root + '/admin/media', function(data){
|
||||
$('#media-library-list').empty();
|
||||
refreshfiles(data);
|
||||
$('#media-modal').modal();
|
||||
});
|
||||
})
|
||||
$('#media-button').click(function(){
|
||||
$.get(script_root + '/admin/media', function(data){
|
||||
$('#media-library-list').empty();
|
||||
refreshfiles(data);
|
||||
$('#media-modal').modal();
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div id="solves-graph"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div id="keys-pie-graph"></div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="solves-graph"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div id="keys-pie-graph"></div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<style>
|
||||
#solves-graph{
|
||||
display: block;
|
||||
height: 500px;
|
||||
}
|
||||
#keys-pie-graph{
|
||||
height: 400px;
|
||||
display: block;
|
||||
}
|
||||
#categories-pie-graph{
|
||||
height: 400px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/plotly.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
// $.distint(array)
|
||||
// Unique elements in array
|
||||
$.extend({
|
||||
distinct : function(anArray) {
|
||||
var result = [];
|
||||
$.each(anArray, function(i,v){
|
||||
if ($.inArray(v, result) == -1) result.push(v);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
});
|
||||
<style>
|
||||
#solves-graph{
|
||||
display: block;
|
||||
height: 500px;
|
||||
}
|
||||
#keys-pie-graph{
|
||||
height: 400px;
|
||||
display: block;
|
||||
}
|
||||
#categories-pie-graph{
|
||||
height: 400px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/plotly.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
// $.distint(array)
|
||||
// Unique elements in array
|
||||
$.extend({
|
||||
distinct : function(anArray) {
|
||||
var result = [];
|
||||
$.each(anArray, function(i,v){
|
||||
if ($.inArray(v, result) == -1) result.push(v);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
// Praise Resig: http://ejohn.org/blog/fast-javascript-maxmin/
|
||||
Array.max = function( array ){
|
||||
return Math.max.apply( Math, array );
|
||||
};
|
||||
// Praise Resig: http://ejohn.org/blog/fast-javascript-maxmin/
|
||||
Array.max = function( array ){
|
||||
return Math.max.apply( Math, array );
|
||||
};
|
||||
|
||||
function colorhash (x) {
|
||||
color = ""
|
||||
for (var i = 20; i <= 60; i+=20){
|
||||
x += i
|
||||
x *= i
|
||||
color += x.toString(16)
|
||||
};
|
||||
return "#" + color.substring(0, 6)
|
||||
}
|
||||
function colorhash (x) {
|
||||
color = ""
|
||||
for (var i = 20; i <= 60; i+=20){
|
||||
x += i
|
||||
x *= i
|
||||
color += x.toString(16)
|
||||
};
|
||||
return "#" + color.substring(0, 6)
|
||||
}
|
||||
|
||||
function solves_graph() {
|
||||
$.get('{{ request.script_root }}/admin/graphs/solves', function (data) {
|
||||
var solves = $.parseJSON(JSON.stringify(data));
|
||||
var chals = [];
|
||||
var counts = [];
|
||||
var colors = [];
|
||||
var annotations = [];
|
||||
var i = 1;
|
||||
solves_order = Object.keys(solves).sort(function (a, b) {
|
||||
return solves[b] - solves[a]
|
||||
});
|
||||
$.each(solves_order, function (key, value) {
|
||||
chals.push(value);
|
||||
counts.push(solves[value]);
|
||||
var result = {
|
||||
x: value,
|
||||
y: solves[value],
|
||||
text: solves[value],
|
||||
xanchor: 'center',
|
||||
yanchor: 'bottom',
|
||||
showarrow: false
|
||||
};
|
||||
annotations.push(result);
|
||||
colors.push(colorhash(i++));
|
||||
});
|
||||
function solves_graph() {
|
||||
$.get('{{ request.script_root }}/admin/graphs/solves', function (data) {
|
||||
var solves = $.parseJSON(JSON.stringify(data));
|
||||
var chals = [];
|
||||
var counts = [];
|
||||
var colors = [];
|
||||
var annotations = [];
|
||||
var i = 1;
|
||||
solves_order = Object.keys(solves).sort(function (a, b) {
|
||||
return solves[b] - solves[a]
|
||||
});
|
||||
$.each(solves_order, function (key, value) {
|
||||
chals.push(value);
|
||||
counts.push(solves[value]);
|
||||
var result = {
|
||||
x: value,
|
||||
y: solves[value],
|
||||
text: solves[value],
|
||||
xanchor: 'center',
|
||||
yanchor: 'bottom',
|
||||
showarrow: false
|
||||
};
|
||||
annotations.push(result);
|
||||
colors.push(colorhash(i++));
|
||||
});
|
||||
|
||||
var data = [{
|
||||
type: 'bar',
|
||||
x: chals,
|
||||
y: counts,
|
||||
text: counts,
|
||||
orientation: 'v'
|
||||
}];
|
||||
var data = [{
|
||||
type: 'bar',
|
||||
x: chals,
|
||||
y: counts,
|
||||
text: counts,
|
||||
orientation: 'v'
|
||||
}];
|
||||
|
||||
var layout = {
|
||||
title: 'Score Counts',
|
||||
annotations: annotations
|
||||
};
|
||||
var layout = {
|
||||
title: 'Score Counts',
|
||||
annotations: annotations
|
||||
};
|
||||
|
||||
Plotly.newPlot('solves-graph', data, layout);
|
||||
});
|
||||
}
|
||||
Plotly.newPlot('solves-graph', data, layout);
|
||||
});
|
||||
}
|
||||
|
||||
function keys_percentage_graph(){
|
||||
// Solves and Fails pie chart
|
||||
$.get('{{ request.script_root }}/admin/fails/all', function(data){
|
||||
var res = $.parseJSON(JSON.stringify(data));
|
||||
var solves = res['solves'];
|
||||
var fails = res['fails'];
|
||||
function keys_percentage_graph(){
|
||||
// Solves and Fails pie chart
|
||||
$.get('{{ request.script_root }}/admin/fails/all', function(data){
|
||||
var res = $.parseJSON(JSON.stringify(data));
|
||||
var solves = res['solves'];
|
||||
var fails = res['fails'];
|
||||
|
||||
var data = [{
|
||||
values: [solves, fails],
|
||||
labels: ['Solves', 'Fails'],
|
||||
marker: {
|
||||
colors: [
|
||||
"rgb(0, 209, 64)",
|
||||
"rgb(207, 38, 0)"
|
||||
]
|
||||
},
|
||||
hole: .4,
|
||||
type: 'pie'
|
||||
}];
|
||||
var data = [{
|
||||
values: [solves, fails],
|
||||
labels: ['Solves', 'Fails'],
|
||||
marker: {
|
||||
colors: [
|
||||
"rgb(0, 209, 64)",
|
||||
"rgb(207, 38, 0)"
|
||||
]
|
||||
},
|
||||
hole: .4,
|
||||
type: 'pie'
|
||||
}];
|
||||
|
||||
var layout = {
|
||||
title: 'Key Percentages'
|
||||
};
|
||||
var layout = {
|
||||
title: 'Key Percentages'
|
||||
};
|
||||
|
||||
Plotly.newPlot('keys-pie-graph', data, layout);
|
||||
});
|
||||
}
|
||||
Plotly.newPlot('keys-pie-graph', data, layout);
|
||||
});
|
||||
}
|
||||
|
||||
function category_breakdown_graph(){
|
||||
$.get('{{ request.script_root }}/admin/graphs/categories', function(data){
|
||||
res = $.parseJSON(JSON.stringify(data));
|
||||
res = res['categories']
|
||||
function category_breakdown_graph(){
|
||||
$.get('{{ request.script_root }}/admin/graphs/categories', function(data){
|
||||
res = $.parseJSON(JSON.stringify(data));
|
||||
res = res['categories']
|
||||
|
||||
categories = [];
|
||||
count = [];
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
categories.push(res[i].category)
|
||||
count.push(res[i].count)
|
||||
};
|
||||
categories = [];
|
||||
count = [];
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
categories.push(res[i].category)
|
||||
count.push(res[i].count)
|
||||
};
|
||||
|
||||
var data = [{
|
||||
values: count,
|
||||
labels: categories,
|
||||
hole: .4,
|
||||
type: 'pie'
|
||||
}];
|
||||
var data = [{
|
||||
values: count,
|
||||
labels: categories,
|
||||
hole: .4,
|
||||
type: 'pie'
|
||||
}];
|
||||
|
||||
var layout = {
|
||||
title: 'Category Breakdown'
|
||||
};
|
||||
var layout = {
|
||||
title: 'Category Breakdown'
|
||||
};
|
||||
|
||||
Plotly.newPlot('categories-pie-graph', data, layout);
|
||||
});
|
||||
}
|
||||
Plotly.newPlot('categories-pie-graph', data, layout);
|
||||
});
|
||||
}
|
||||
|
||||
function update(){
|
||||
solves_graph();
|
||||
keys_percentage_graph();
|
||||
category_breakdown_graph();
|
||||
}
|
||||
function update(){
|
||||
solves_graph();
|
||||
keys_percentage_graph();
|
||||
category_breakdown_graph();
|
||||
}
|
||||
|
||||
$(function() {
|
||||
update();
|
||||
window.onresize = function () {
|
||||
console.log('resizing')
|
||||
Plotly.Plots.resize(document.getElementById('keys-pie-graph'));
|
||||
Plotly.Plots.resize(document.getElementById('categories-pie-graph'));
|
||||
Plotly.Plots.resize(document.getElementById('solves-graph'));
|
||||
};
|
||||
});
|
||||
$(function() {
|
||||
update();
|
||||
window.onresize = function () {
|
||||
console.log('resizing')
|
||||
Plotly.Plots.resize(document.getElementById('keys-pie-graph'));
|
||||
Plotly.Plots.resize(document.getElementById('categories-pie-graph'));
|
||||
Plotly.Plots.resize(document.getElementById('solves-graph'));
|
||||
};
|
||||
});
|
||||
|
||||
setInterval(update, 300000);
|
||||
setInterval(update, 300000);
|
||||
|
||||
</script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,78 +2,78 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Admin Panel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment-timezone-with-data.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
<title>Admin Panel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/original/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/admin/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/style.css">
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment-timezone-with-data.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
{% block stylesheets %} {% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<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="{{ request.script_root }}/" class="navbar-brand">CTFd</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav navbar-nav-right">
|
||||
<li><a href="{{ request.script_root }}/admin/graphs">Graphs</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">Pages <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ request.script_root }}/admin/pages">All Pages</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/pages?mode=create">New Page</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{{ request.script_root }}/admin/teams">Teams</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/scoreboard">Scoreboard</a></li>
|
||||
{% if can_create_container() %}
|
||||
<li><a href="{{ request.script_root }}/admin/containers">Containers</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/admin/chals">Challenges</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/statistics">Statistics</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/config">Config</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Plugins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plugin in get_configurable_plugins() %}
|
||||
<li><a href="{{ request.script_root }}/admin/plugins/{{ plugin }}">{{ plugin }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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="{{ request.script_root }}/" class="navbar-brand">CTFd</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" aria-expanded="false" style="height: 0px">
|
||||
<ul class="nav navbar-nav navbar-nav-right">
|
||||
<li><a href="{{ request.script_root }}/admin/graphs">Graphs</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||
aria-expanded="false">Pages <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ request.script_root }}/admin/pages">All Pages</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/pages?mode=create">New Page</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{{ request.script_root }}/admin/teams">Teams</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/scoreboard">Scoreboard</a></li>
|
||||
{% if can_create_container() %}
|
||||
<li><a href="{{ request.script_root }}/admin/containers">Containers</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/admin/chals">Challenges</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/statistics">Statistics</a></li>
|
||||
<li><a href="{{ request.script_root }}/admin/config">Config</a></li>
|
||||
<li>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Plugins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plugin in get_configurable_plugins() %}
|
||||
<li><a href="{{ request.script_root }}/admin/plugins/{{ plugin }}">{{ plugin }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
<div class="container">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/bootstrap.min.js"></script>
|
||||
{% block scripts %} {% endblock %}
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/bootstrap.min.js"></script>
|
||||
{% block scripts %} {% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/vendor/codemirror.min.css">
|
||||
<style>
|
||||
.CodeMirror {
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/admin/css/vendor/codemirror.min.css">
|
||||
<style>
|
||||
.CodeMirror {
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3>Pages</h3>
|
||||
<table id="pages" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Route</b></td>
|
||||
<td class="text-center" style="width: 150px;"><b>Settings</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for route in routes %}
|
||||
<tr name="{{ route.route }}">
|
||||
<td class="route-name"><a
|
||||
href="{{ request.script_root }}/admin/pages/{{ route.route }}">{{ route.route }}</a></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="col-md-6">
|
||||
<h3>Pages</h3>
|
||||
<table id="pages" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Route</b></td>
|
||||
<td class="text-center" style="width: 150px;"><b>Settings</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for route in routes %}
|
||||
<tr name="{{ route.route }}">
|
||||
<td class="route-name"><a
|
||||
href="{{ request.script_root }}/admin/pages/{{ route.route }}">{{ route.route }}</a></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ request.script_root }}/admin/pages?mode=create">
|
||||
<button type="button" id="submit" class="btn btn-md btn-primary btn-theme btn-outlined">
|
||||
Add Page
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<a href="{{ request.script_root }}/admin/pages?mode=create">
|
||||
<button type="button" id="submit" class="btn btn-md btn-primary btn-theme btn-outlined">
|
||||
Add Page
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3>CSS editor</h3>
|
||||
<form method="POST">
|
||||
<textarea id="pages-editor" name="css" style="padding-left:20px;">{{ css }}</textarea>
|
||||
<button onclick="save_css()" type="button" id="submit" class="btn btn-md btn-primary btn-theme btn-outlined">
|
||||
Update CSS
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>CSS editor</h3>
|
||||
<form method="POST">
|
||||
<textarea id="pages-editor" name="css" style="padding-left:20px; visibility: hidden;">{{ css }}</textarea>
|
||||
<button onclick="save_css()" type="button" id="submit" class="btn btn-md btn-primary btn-theme btn-outlined">
|
||||
Update CSS
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -81,44 +81,44 @@
|
|||
<script src="{{ request.script_root }}/static/admin/js/vendor/codemirror.min.js"></script>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("pages-editor"), {
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "xml",
|
||||
htmlMode: true,
|
||||
theme: 'elegant'
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
mode: "css",
|
||||
htmlMode: false,
|
||||
theme: 'elegant'
|
||||
});
|
||||
|
||||
$('#delete-route').click(function(e){
|
||||
e.preventDefault();
|
||||
var route = $('#confirm input[name="route"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
e.preventDefault();
|
||||
var route = $('#confirm input[name="route"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function load_confirm_modal(route){
|
||||
var modal = $('#confirm')
|
||||
modal.find('input[name=route]').val(route)
|
||||
modal.find('#confirm-route-name').text(route)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/page/'+route+'/delete');
|
||||
$('#confirm').modal();
|
||||
var modal = $('#confirm')
|
||||
modal.find('input[name=route]').val(route)
|
||||
modal.find('#confirm-route-name').text(route)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/page/'+route+'/delete');
|
||||
$('#confirm').modal();
|
||||
}
|
||||
|
||||
function save_css(){
|
||||
var css = editor.getValue();
|
||||
var nonce = $('#nonce').val();
|
||||
$.post(script_root + '/admin/css', {'css':css, 'nonce':nonce}, function(){
|
||||
console.log('saved');
|
||||
});
|
||||
var css = editor.getValue();
|
||||
var nonce = $('#nonce').val();
|
||||
$.post(script_root + '/admin/css', {'css':css, 'nonce':nonce}, function(){
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
$('.fa-times').click(function(){
|
||||
var elem = $(this).parent().parent();
|
||||
var name = elem.find('.route-name').text().trim();
|
||||
load_confirm_modal(name)
|
||||
var elem = $(this).parent().parent();
|
||||
var name = elem.find('.route-name').text().trim();
|
||||
load_confirm_modal(name)
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -2,40 +2,40 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<h1>Scoreboard</h1>
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b></td>
|
||||
<td><b>Team</b></td>
|
||||
<td><b>Score</b></td>
|
||||
<td><b>Status</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td><a href="{{ request.script_root }}/admin/team/{{ team.teamid }}">{{ team.name }}</a></td>
|
||||
<td>{{ team.score }}</td>
|
||||
<td>
|
||||
{% if not team.banned %}
|
||||
<form method="POST" style="margin:0;" action="{{ request.script_root }}/admin/team/{{ team.teamid }}/ban">
|
||||
<a onclick="$(this).parent().submit()">Ban</a>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce">
|
||||
</form>
|
||||
{%else %}
|
||||
<form method="POST" style="margin:0;" action="{{ request.script_root }}/admin/team/{{ team.teamid }}/unban">
|
||||
<a onclick="$(this).parent().submit()">Unban</a>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce">
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h1>Scoreboard</h1>
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b></td>
|
||||
<td><b>Team</b></td>
|
||||
<td><b>Score</b></td>
|
||||
<td><b>Status</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td><a href="{{ request.script_root }}/admin/team/{{ team.teamid }}">{{ team.name }}</a></td>
|
||||
<td>{{ team.score }}</td>
|
||||
<td>
|
||||
{% if not team.banned %}
|
||||
<form method="POST" style="margin:0;" action="{{ request.script_root }}/admin/team/{{ team.teamid }}/ban">
|
||||
<a onclick="$(this).parent().submit()">Hide</a>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce">
|
||||
</form>
|
||||
{%else %}
|
||||
<form method="POST" style="margin:0;" action="{{ request.script_root }}/admin/team/{{ team.teamid }}/unban">
|
||||
<a onclick="$(this).parent().submit()">Unhide</a>
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce">
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row" style="text-align:center">
|
||||
<br>
|
||||
<h1>Statistics</h1>
|
||||
<br>
|
||||
<h1>Statistics</h1>
|
||||
|
||||
<h3><b>{{ team_count }}</b> teams registered</h3>
|
||||
<h3><b>{{ wrong_count }}</b> <a href="{{ request.script_root }}/admin/wrong_keys/1">wrong keys</a> submitted</h3>
|
||||
<h3><b>{{ solve_count }}</b> <a href="{{ request.script_root }}/admin/correct_keys/1">right keys</a> submitted</h3>
|
||||
<h3><b>{{ challenge_count }}</b> challenges</h3>
|
||||
{% if most_solved %}
|
||||
<h3>Most solved: <b>{{ most_solved }}</b> with {{ solve_data[most_solved] }}</b> solves</h3>
|
||||
{% endif %}
|
||||
{% if least_solved %}
|
||||
<h3>Least solved: <b>{{ least_solved }}</b> with {{ solve_data[least_solved] }}</b> solves</h3>
|
||||
{% endif %}
|
||||
<h3><b>{{ team_count }}</b> teams registered</h3>
|
||||
<h3><b>{{ wrong_count }}</b> <a href="{{ request.script_root }}/admin/wrong_keys/1">wrong keys</a> submitted</h3>
|
||||
<h3><b>{{ solve_count }}</b> <a href="{{ request.script_root }}/admin/correct_keys/1">right keys</a> submitted</h3>
|
||||
<h3><b>{{ challenge_count }}</b> challenges</h3>
|
||||
{% if most_solved %}
|
||||
<h3>Most solved: <b>{{ most_solved }}</b> with {{ solve_data[most_solved] }}</b> solves</h3>
|
||||
{% endif %}
|
||||
{% if least_solved %}
|
||||
<h3>Least solved: <b>{{ least_solved }}</b> with {{ solve_data[least_solved] }}</b> solves</h3>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -2,355 +2,355 @@
|
|||
|
||||
{% block stylesheets %}
|
||||
<style>
|
||||
.btn-primary {
|
||||
background-color: #337ab7;
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: #337ab7;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
.btn-danger {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="modal fade" id="create-award-modal" tabindex="-1" role="dialog" aria-labelledby="create-award-label">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="create-award-label">Create Award</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="award-create-form" method="POST" action="{{ request.script_root }}/admin/awards/add">
|
||||
<div class="form-group">
|
||||
<label for="award-name-input">Name</label>
|
||||
<input type="text" class="form-control" id="award-name-input" name="name" placeholder="Enter award name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-value-input">Value</label>
|
||||
<input type="number" class="form-control" id="award-value-input" name="value" placeholder="Enter award value">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-category-input">Category</label>
|
||||
<input type="text" class="form-control" id="award-category-input" name="category" placeholder="Enter award category">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-description-input" class="control-label">Description</label>
|
||||
<textarea id="award-description-input" class="form-control" name="description" rows="10" placeholder="Description of what the award is for"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-icon-input">Award Icon</label>
|
||||
<input type="file" id="award-icon-input" name="icon">
|
||||
</div>
|
||||
<input type="hidden" value="{{ team.id }}" name="teamid" id="teamid">
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
<div class="modal-footer">
|
||||
<button type="submit" id="award-create-button" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="create-award-label">Create Award</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="award-create-form" method="POST" action="{{ request.script_root }}/admin/awards/add">
|
||||
<div class="form-group">
|
||||
<label for="award-name-input">Name</label>
|
||||
<input type="text" class="form-control" id="award-name-input" name="name" placeholder="Enter award name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-value-input">Value</label>
|
||||
<input type="number" class="form-control" id="award-value-input" name="value" placeholder="Enter award value">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-category-input">Category</label>
|
||||
<input type="text" class="form-control" id="award-category-input" name="category" placeholder="Enter award category">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-description-input" class="control-label">Description</label>
|
||||
<textarea id="award-description-input" class="form-control" name="description" rows="10" placeholder="Description of what the award is for"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="award-icon-input">Award Icon</label>
|
||||
<input type="file" id="award-icon-input" name="icon">
|
||||
</div>
|
||||
<input type="hidden" value="{{ team.id }}" name="teamid" id="teamid">
|
||||
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
|
||||
<div class="modal-footer">
|
||||
<button type="submit" id="award-create-button" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row container-fluid">
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3 id="confirm-title">Delete Key</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="{{ request.script_root }}/admin/chal/delete">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p id="confirm-description"></p>
|
||||
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<h3 id="confirm-title">Delete Key</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="{{ request.script_root }}/admin/chal/delete">
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
<div class="small-6 small-centered text-center columns">
|
||||
<p id="confirm-description"></p>
|
||||
<a onclick="$('#confirm').modal('hide')" class="btn btn-primary">No</a>
|
||||
<button class="btn btn-danger" id="delete-solve" type="button">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
<h2 id="team-email" class="text-center">{{ team.email }}</h2>
|
||||
<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>
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
<h2 id="team-email" class="text-center">{{ team.email }}</h2>
|
||||
<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 id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<div id="score-graph"></div>
|
||||
<div id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<div id="score-graph"></div>
|
||||
|
||||
<table class="table table-striped">
|
||||
<h3>IP Addresses</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>IP Address</b></td>
|
||||
<td class="text-center"><b>Last Seen</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for addr in addrs %}
|
||||
<tr>
|
||||
<td class="text-center">{{ addr[0]|long2ip }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ addr[1]|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-striped">
|
||||
<h3>IP Addresses</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>IP Address</b></td>
|
||||
<td class="text-center"><b>Last Seen</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for addr in addrs %}
|
||||
<tr>
|
||||
<td class="text-center">{{ addr[0]|long2ip }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ addr[1]|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<table class="table table-striped">
|
||||
<h3>Awards</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Name</b></td>
|
||||
<td class="text-center"><b>Description</b></td>
|
||||
<td class="text-center"><b>Date</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Icon</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="awards-body">
|
||||
{% for award in awards %}
|
||||
<tr class="award-row">
|
||||
<td class="text-center chal" id="{{ award.id }}">{{ award.name }}</td>
|
||||
<td class="text-center">{{ award.description }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ award.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center">{{ award.value }}</td>
|
||||
<td class="text-center">{{ award.category }}</td>
|
||||
<td class="text-center">{{ award.icon }}</td>
|
||||
<table class="table table-striped">
|
||||
<h3>Awards</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Name</b></td>
|
||||
<td class="text-center"><b>Description</b></td>
|
||||
<td class="text-center"><b>Date</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Icon</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="awards-body">
|
||||
{% for award in awards %}
|
||||
<tr class="award-row">
|
||||
<td class="text-center chal" id="{{ award.id }}">{{ award.name }}</td>
|
||||
<td class="text-center">{{ award.description }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ award.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center">{{ award.value }}</td>
|
||||
<td class="text-center">{{ award.category }}</td>
|
||||
<td class="text-center">{{ award.icon }}</td>
|
||||
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="row container-fluid">
|
||||
<button type="button" data-toggle="modal" data-target="#create-award-modal" class="btn btn-primary pull-right">Create Award</button>
|
||||
</div>
|
||||
<div class="row container-fluid">
|
||||
<button type="button" data-toggle="modal" data-target="#create-award-modal" class="btn btn-primary pull-right">Create Award</button>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped">
|
||||
<h3>Solves</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Submitted</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Time</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr class="chal-solve">
|
||||
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal.name }}</td>
|
||||
<td class="text-center flag" id="{{ solve.id }}">{{ solve.flag }}</td>
|
||||
<td class="text-center">{{ solve.chal.category }}</td>
|
||||
<td class="text-center">{{ solve.chal.value }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-striped">
|
||||
<h3>Solves</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Submitted</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Time</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr class="chal-solve">
|
||||
<td class="text-center chal" id="{{ solve.chalid }}">{{ solve.chal.name }}</td>
|
||||
<td class="text-center flag" id="{{ solve.id }}">{{ solve.flag }}</td>
|
||||
<td class="text-center">{{ solve.chal.category }}</td>
|
||||
<td class="text-center">{{ solve.chal.value }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="table table-striped">
|
||||
<h3>Missing</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Mark Solved</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for chal in missing %}
|
||||
<tr class="chal-solve">
|
||||
<td class="text-center chal" id="{{ chal.id }}">{{ chal.name }}</td>
|
||||
<td class="text-center">{{ chal.category }}</td>
|
||||
<td class="text-center">{{ chal.value }}</td>
|
||||
<td class="text-center"><i class="fa fa-check"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-striped">
|
||||
<h3>Missing</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Category</b></td>
|
||||
<td class="text-center"><b>Value</b></td>
|
||||
<td class="text-center"><b>Mark Solved</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for chal in missing %}
|
||||
<tr class="chal-solve">
|
||||
<td class="text-center chal" id="{{ chal.id }}">{{ chal.name }}</td>
|
||||
<td class="text-center">{{ chal.category }}</td>
|
||||
<td class="text-center">{{ chal.value }}</td>
|
||||
<td class="text-center"><i class="fa fa-check"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<table class="table table-striped">
|
||||
<h3>Wrong Keys</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Submitted</b></td>
|
||||
<td class="text-center"><b>Time</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for wrong_key in wrong_keys %}
|
||||
<tr class="chal-wrong">
|
||||
<td class="text-center chal" id="{{ wrong_key.chalid }}">{{ wrong_key.chal.name }}</td>
|
||||
<td class="text-center flag" id="{{ wrong_key.id }}">{{ wrong_key.flag }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ wrong_key.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-striped">
|
||||
<h3>Wrong Keys</h3>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><b>Challenge</b></td>
|
||||
<td class="text-center"><b>Submitted</b></td>
|
||||
<td class="text-center"><b>Time</b></td>
|
||||
<td class="text-center"><b>Delete</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for wrong_key in wrong_keys %}
|
||||
<tr class="chal-wrong">
|
||||
<td class="text-center chal" id="{{ wrong_key.chalid }}">{{ wrong_key.chal.name }}</td>
|
||||
<td class="text-center flag" id="{{ wrong_key.id }}">{{ wrong_key.flag }}</td>
|
||||
<td class="text-center solve-time"><script>document.write( moment({{ wrong_key.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
<td class="text-center"><i class="fa fa-times"></i></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/team.js"></script>
|
||||
<script>
|
||||
$('#delete-solve').click(function (e) {
|
||||
e.preventDefault();
|
||||
var solve = $('#confirm input[name="solve"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function (data) {
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1") {
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/admin/js/team.js"></script>
|
||||
<script>
|
||||
$('#delete-solve').click(function (e) {
|
||||
e.preventDefault();
|
||||
var solve = $('#confirm input[name="solve"]').val()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function (data) {
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1") {
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function load_confirm_modal(msg) {
|
||||
var title = msg.title;
|
||||
var description = msg.description;
|
||||
var action = msg.action;
|
||||
$('#confirm-title').text(title);
|
||||
$('#confirm-description').html(description);
|
||||
$('#confirm form').attr('action', action);
|
||||
$('#confirm').modal('show');
|
||||
}
|
||||
function load_confirm_modal(msg) {
|
||||
var title = msg.title;
|
||||
var description = msg.description;
|
||||
var action = msg.action;
|
||||
$('#confirm-title').text(title);
|
||||
$('#confirm-description').html(description);
|
||||
$('#confirm form').attr('action', action);
|
||||
$('#confirm').modal('show');
|
||||
}
|
||||
|
||||
$('.fa-times').click(function () {
|
||||
var elem = $(this).parent().parent();
|
||||
var type = elem.attr('class');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team_name = $("#team-id").text();
|
||||
var key_id = elem.find('.flag').attr('id');
|
||||
$('.fa-times').click(function () {
|
||||
var elem = $(this).parent().parent();
|
||||
var type = elem.attr('class');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team_name = $("#team-id").text();
|
||||
var key_id = elem.find('.flag').attr('id');
|
||||
|
||||
if (type == 'chal-solve'){
|
||||
var title = 'Delete Solve';
|
||||
var description = "<span>Are you sure you want to delete " +
|
||||
"<strong>correct</strong> " +
|
||||
"key submission for team: " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"in challenge: " +
|
||||
"<strong id='confirm-chal-name'></strong>?</span>"
|
||||
if (type == 'chal-solve'){
|
||||
var title = 'Delete Solve';
|
||||
var description = "<span>Are you sure you want to delete " +
|
||||
"<strong>correct</strong> " +
|
||||
"key submission for team: " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"in challenge: " +
|
||||
"<strong id='confirm-chal-name'></strong>?</span>"
|
||||
|
||||
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
|
||||
var action = '{{ request.script_root }}/admin/solves/' + key_id + '/delete';
|
||||
} else if (type == 'chal-wrong') {
|
||||
var title = 'Delete Wrong Key';
|
||||
var description = "<span>Are you sure you want to delete " +
|
||||
"<strong>incorrect</strong> " +
|
||||
"key submission for team: " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"in challenge: " +
|
||||
"<strong id='confirm-chal-name'></strong>?</span>"
|
||||
var action = '{{ request.script_root }}/admin/solves/' + key_id + '/delete';
|
||||
} else if (type == 'chal-wrong') {
|
||||
var title = 'Delete Wrong Key';
|
||||
var description = "<span>Are you sure you want to delete " +
|
||||
"<strong>incorrect</strong> " +
|
||||
"key submission for team: " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"in challenge: " +
|
||||
"<strong id='confirm-chal-name'></strong>?</span>"
|
||||
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
|
||||
var action = '{{ request.script_root }}/admin/wrong_keys/' + key_id + '/delete';
|
||||
} else if (type == 'award-row') {
|
||||
var title = 'Delete Award';
|
||||
var award_id = elem.find('.chal').attr('id');
|
||||
var description = "<span>Are you sure you want to delete the " +
|
||||
"<strong>{0}</strong> award?</span>".format(chal_name);
|
||||
var action = '{{ request.script_root }}/admin/awards/{0}/delete'.format(award_id);
|
||||
}
|
||||
var action = '{{ request.script_root }}/admin/wrong_keys/' + key_id + '/delete';
|
||||
} else if (type == 'award-row') {
|
||||
var title = 'Delete Award';
|
||||
var award_id = elem.find('.chal').attr('id');
|
||||
var description = "<span>Are you sure you want to delete the " +
|
||||
"<strong>{0}</strong> award?</span>".format(chal_name);
|
||||
var action = '{{ request.script_root }}/admin/awards/{0}/delete'.format(award_id);
|
||||
}
|
||||
|
||||
var msg = {
|
||||
title : title,
|
||||
description : description,
|
||||
action : action,
|
||||
}
|
||||
var msg = {
|
||||
title : title,
|
||||
description : description,
|
||||
action : action,
|
||||
}
|
||||
|
||||
load_confirm_modal(msg)
|
||||
});
|
||||
load_confirm_modal(msg)
|
||||
});
|
||||
|
||||
$('.fa-check').click(function () {
|
||||
var elem = $(this).parent().parent();
|
||||
var type = elem.attr('class');
|
||||
var chal = elem.find('.chal').attr('id');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team = window.location.pathname.split('/').pop();
|
||||
var team_name = $("#team-id").text();
|
||||
$('.fa-check').click(function () {
|
||||
var elem = $(this).parent().parent();
|
||||
var type = elem.attr('class');
|
||||
var chal = elem.find('.chal').attr('id');
|
||||
var chal_name = elem.find('.chal').text().trim();
|
||||
var team = window.location.pathname.split('/').pop();
|
||||
var team_name = $("#team-id").text();
|
||||
|
||||
var title = 'Mark '+chal_name+' Solved';
|
||||
var description = "<span>Are you sure you want to mark " +
|
||||
"<strong id='confirm-chal-name'></strong> " +
|
||||
"as solved for team " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"?</span>";
|
||||
var title = 'Mark '+chal_name+' Solved';
|
||||
var description = "<span>Are you sure you want to mark " +
|
||||
"<strong id='confirm-chal-name'></strong> " +
|
||||
"as solved for team " +
|
||||
"<strong id='confirm-team-name'></strong> " +
|
||||
"?</span>";
|
||||
|
||||
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
var description = $($.parseHTML(description));
|
||||
description.find('#confirm-team-name').text(team_name);
|
||||
description.find('#confirm-chal-name').text(chal_name);
|
||||
description = description.html()
|
||||
|
||||
var action = '{{request.script_root }}/admin/solves/' + team + '/' + chal + '/solve';
|
||||
var action = '{{request.script_root }}/admin/solves/' + team + '/' + chal + '/solve';
|
||||
|
||||
var msg = {
|
||||
title : title,
|
||||
description : description,
|
||||
action : action,
|
||||
};
|
||||
var msg = {
|
||||
title : title,
|
||||
description : description,
|
||||
action : action,
|
||||
};
|
||||
|
||||
load_confirm_modal(msg);
|
||||
});
|
||||
load_confirm_modal(msg);
|
||||
});
|
||||
|
||||
$('#award-create-form').submit(function(e){
|
||||
$.post($(this).attr('action'), $(this).serialize(), function(res){
|
||||
if (res == '1'){
|
||||
var award = $('#award-create-form').serializeObject();
|
||||
var award_text = '<td class="text-center">{0}</td>'.format(award.name) +
|
||||
'<td class="text-center">{0}</td>'.format(award.description) +
|
||||
'<td class="text-center solve-time">{0}</td>'.format(moment().local().format('MMMM Do, h:mm:ss A')) +
|
||||
'<td class="text-center">{0}</td>'.format(award.value) +
|
||||
'<td class="text-center">{0}</td>'.format(award.category) +
|
||||
'<td class="text-center">{0}</td>'.format('None') +
|
||||
'<td class="text-center"><i class="fa fa-times"></i></td>'
|
||||
$('#awards-body').append(award_text);
|
||||
$('#create-award-modal').modal('hide');
|
||||
}
|
||||
})
|
||||
e.preventDefault();
|
||||
});
|
||||
$('#award-create-form').submit(function(e){
|
||||
$.post($(this).attr('action'), $(this).serialize(), function(res){
|
||||
if (res == '1'){
|
||||
var award = $('#award-create-form').serializeObject();
|
||||
var award_text = '<td class="text-center">{0}</td>'.format(award.name) +
|
||||
'<td class="text-center">{0}</td>'.format(award.description) +
|
||||
'<td class="text-center solve-time">{0}</td>'.format(moment().local().format('MMMM Do, h:mm:ss A')) +
|
||||
'<td class="text-center">{0}</td>'.format(award.value) +
|
||||
'<td class="text-center">{0}</td>'.format(award.category) +
|
||||
'<td class="text-center">{0}</td>'.format('None') +
|
||||
'<td class="text-center"><i class="fa fa-times"></i></td>'
|
||||
$('#awards-body').append(award_text);
|
||||
$('#create-award-modal').modal('hide');
|
||||
}
|
||||
})
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
</script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -10,299 +10,302 @@ input[type="checkbox"] { margin: 0px !important; position: relative; top: 5px; }
|
|||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<br>
|
||||
<h1>Teams</h1>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<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 class="form-control" name="msg" placeholder="Enter your message here" rows="15"></textarea>
|
||||
<br>
|
||||
<div id="email-user-errors"></div>
|
||||
<button type="button" id="send-user-email" class="btn btn-theme btn-outlined">Send Message</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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="modal-body" style="padding:20px; height:525px;">
|
||||
<form method="POST" action="{{ request.script_root }}/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" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" name="email" id="email" placeholder="Enter new email" required>
|
||||
</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">
|
||||
<br>
|
||||
<h1>Teams</h1>
|
||||
<div id="confirm" class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div id="email-user" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<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 class="form-control" name="msg" placeholder="Enter your message here" rows="15"></textarea>
|
||||
<br>
|
||||
<div id="email-user-errors"></div>
|
||||
<button type="button" id="send-user-email" class="btn btn-theme btn-outlined">Send Message</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="user" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h2 class="text-center">Edit User</h2>
|
||||
</div>
|
||||
<div class="modal-body" style="padding:20px; height:525px;">
|
||||
<form method="POST" action="{{ request.script_root }}/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" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" name="email" id="email" placeholder="Enter new email" required>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px" class="text-center"><b>ID</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Team</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Email</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Website</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Affiliation</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Country</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Admin</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Verified</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Settings</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr name="{{ team.id }}">
|
||||
<td class="team-id" value="{{ team.id }}">{{ team.id }}</td>
|
||||
<td class="team-name" value="{{ team.name }}"><a href="{{ request.script_root }}/admin/team/{{ team.id }}">{{ team.name | truncate(32) }}</a>
|
||||
</td>
|
||||
<td class="team-email">{{ team.email | truncate(32) }}</td>
|
||||
<td class="team-website">{% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %}<a href="{{ team.website }}">{{ team.website | truncate(32) }}</a>{% endif %}
|
||||
</td>
|
||||
<td class="team-affiliation" value="{{ team.affiliation if team.affiliation is not none }}"><span>{% if team.affiliation %}{{ team.affiliation | truncate(20) }}{% endif %}</span>
|
||||
</td>
|
||||
<td class="team-country" value="{{ team.country if team.country is not none }}"><span>{% if team.country %}{{ team.country }}{% endif %}</span>
|
||||
</td>
|
||||
<td class="team-admin">
|
||||
<div class="center-block checkbox text-center">
|
||||
<input type="checkbox" {% if team.admin %}checked{% endif %}>
|
||||
</div>
|
||||
</td>
|
||||
<td class="team-verified">
|
||||
<div class="center-block checkbox text-center">
|
||||
<input type="checkbox" {% if team.verified %}checked{% endif %}>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center"><span>
|
||||
<i class="fa fa-pencil-square-o"></i>
|
||||
{% if can_send_mail() %}<i class="fa fa-envelope"></i>{% endif %}
|
||||
<i class="fa fa-times"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/admin/teams/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/admin/teams/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{ page }}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != pages %}<a href="{{ request.script_root }}/admin/teams/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<button id="update-user" type="submit" class="btn btn-theme btn-outlined pull-right">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px" class="text-center"><b>ID</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Team</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Email</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Website</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Affiliation</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Country</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Admin</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Verified</b>
|
||||
</td>
|
||||
<td class="text-center"><b>Settings</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr name="{{ team.id }}">
|
||||
<td class="team-id" value="{{ team.id }}">{{ team.id }}</td>
|
||||
<td class="team-name" value="{{ team.name }}"><a href="{{ request.script_root }}/admin/team/{{ team.id }}">{{ team.name | truncate(32) }}</a>
|
||||
</td>
|
||||
<td class="team-email">{{ team.email | truncate(32) }}</td>
|
||||
<td class="team-website">{% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %}<a href="{{ team.website }}">{{ team.website | truncate(32) }}</a>{% endif %}
|
||||
</td>
|
||||
<td class="team-affiliation" value="{{ team.affiliation if team.affiliation is not none }}"><span>{% if team.affiliation %}{{ team.affiliation | truncate(20) }}{% endif %}</span>
|
||||
</td>
|
||||
<td class="team-country" value="{{ team.country if team.country is not none }}"><span>{% if team.country %}{{ team.country }}{% endif %}</span>
|
||||
</td>
|
||||
<td class="team-admin">
|
||||
<div class="center-block checkbox text-center">
|
||||
<input type="checkbox" {% if team.admin %}checked{% endif %}>
|
||||
</div>
|
||||
</td>
|
||||
<td class="team-verified">
|
||||
<div class="center-block checkbox text-center">
|
||||
<input type="checkbox" {% if team.verified %}checked{% endif %}>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center"><span>
|
||||
<i class="fa fa-pencil-square-o" data-toggle="tooltip" data-placement="top" title="Modify {{ team.name }}"></i>
|
||||
{% if can_send_mail() %}<i class="fa fa-envelope"></i>{% endif %}
|
||||
<i class="fa fa-times" data-toggle="tooltip" data-placement="top" title="Delete {{ team.name }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/admin/teams/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/admin/teams/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{ page }}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != pages %}<a href="{{ request.script_root }}/admin/teams/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
function load_update_modal(id, name, email, website, affiliation, country){
|
||||
var modal_form = $('#user form');
|
||||
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)
|
||||
$('#user form').attr('action', '{{ request.script_root }}/admin/team/'+id)
|
||||
$('#user').modal("show");
|
||||
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)
|
||||
$('#user form').attr('action', '{{ request.script_root }}/admin/team/'+id)
|
||||
$('#user').modal("show");
|
||||
}
|
||||
|
||||
$('#update-user').click(function(e){
|
||||
e.preventDefault();
|
||||
var id = $('#user input[name="id"]').val()
|
||||
var user_data = $('#user form').serializeArray()
|
||||
$.post($('#user form').attr('action'), $('#user form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
for (var i = 0; i < data['data'].length; i++) {
|
||||
if (data['data'][i] == 'success'){
|
||||
var row = $('tr[name='+id+']')
|
||||
console.log($.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'])
|
||||
console.log(row.find('.team-name > a'))
|
||||
row.find('.team-name > a').text( $.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'] );
|
||||
var new_email = $.grep(user_data, function(e){ return e.name == 'email'; })[0]['value'];
|
||||
if (new_email){
|
||||
row.find('.team-email').text( new_email );
|
||||
}
|
||||
row.find('.team-website > a').empty()
|
||||
var website = $.grep(user_data, function(e){ return e.name == 'website'; })[0]['value']
|
||||
row.find('.team-website').append($('<a>').attr('href', website).text(website));
|
||||
e.preventDefault();
|
||||
var id = $('#user input[name="id"]').val()
|
||||
var user_data = $('#user form').serializeArray()
|
||||
$.post($('#user form').attr('action'), $('#user form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
for (var i = 0; i < data['data'].length; i++) {
|
||||
if (data['data'][i] == 'success'){
|
||||
var row = $('tr[name='+id+']')
|
||||
console.log($.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'])
|
||||
console.log(row.find('.team-name > a'))
|
||||
row.find('.team-name > a').text( $.grep(user_data, function(e){ return e.name == 'name'; })[0]['value'] );
|
||||
var new_email = $.grep(user_data, function(e){ return e.name == 'email'; })[0]['value'];
|
||||
if (new_email){
|
||||
row.find('.team-email').text( new_email );
|
||||
}
|
||||
row.find('.team-website > a').empty()
|
||||
var website = $.grep(user_data, function(e){ return e.name == 'website'; })[0]['value']
|
||||
row.find('.team-website').append($('<a>').attr('href', website).text(website));
|
||||
|
||||
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').modal('hide');
|
||||
}
|
||||
else{
|
||||
$('#results').append($('p').text( data['data'][i] ))
|
||||
}
|
||||
};
|
||||
})
|
||||
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').modal('hide');
|
||||
}
|
||||
else{
|
||||
$('#results').append($('p').text( data['data'][i] ))
|
||||
}
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
$('.team-admin input').on('change', function(){
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var admin = $(this).prop('checked');
|
||||
var nonce = $('#nonce').val();
|
||||
console.log(admin);
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var admin = $(this).prop('checked');
|
||||
var nonce = $('#nonce').val();
|
||||
console.log(admin);
|
||||
|
||||
$.post('{{ request.script_root }}/admin/team/'+id, {'admin':admin, 'nonce':nonce});
|
||||
$.post('{{ request.script_root }}/admin/team/'+id, {'admin':admin, 'nonce':nonce});
|
||||
});
|
||||
|
||||
$('.team-verified input').on('change', function () {
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var verified = $(this).prop('checked');
|
||||
var nonce = $('#nonce').val();
|
||||
console.log(verified);
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var verified = $(this).prop('checked');
|
||||
var nonce = $('#nonce').val();
|
||||
console.log(verified);
|
||||
|
||||
$.post('{{ request.script_root }}/admin/team/' + id, {'verified': verified, 'nonce': nonce});
|
||||
$.post('{{ request.script_root }}/admin/team/' + id, {'verified': verified, 'nonce': nonce});
|
||||
})
|
||||
|
||||
$('#send-user-email').click(function(e){
|
||||
e.preventDefault();
|
||||
var id = $('#email-user input[name="id"]').val();
|
||||
var email_data = $('#email-user form').serializeArray();
|
||||
$.post($('#email-user form').attr('action'), $('#email-user form').serialize(), function(data){
|
||||
if (data == "1"){
|
||||
$('#email-user').modal('hide');
|
||||
}
|
||||
else{
|
||||
$('#email-user-errors').append("<b>Failed to send email</b>");
|
||||
}
|
||||
});
|
||||
e.preventDefault();
|
||||
var id = $('#email-user input[name="id"]').val();
|
||||
var email_data = $('#email-user form').serializeArray();
|
||||
$.post($('#email-user form').attr('action'), $('#email-user form').serialize(), function(data){
|
||||
if (data == "1"){
|
||||
$('#email-user').modal('hide');
|
||||
}
|
||||
else{
|
||||
$('#email-user-errors').append("<b>Failed to send email</b>");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#delete-user').click(function(e){
|
||||
e.preventDefault();
|
||||
var id = $('#confirm input[name="id"]').val()
|
||||
var user_data = $('#confirm form').serializeArray()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
e.preventDefault();
|
||||
var id = $('#confirm input[name="id"]').val()
|
||||
var user_data = $('#confirm form').serializeArray()
|
||||
$.post($('#confirm form').attr('action'), $('#confirm form').serialize(), function(data){
|
||||
var data = $.parseJSON(JSON.stringify(data))
|
||||
if (data == "1"){
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$('.fa-pencil-square-o').click(function(){
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').attr('value') || '';
|
||||
var name = elem.find('.team-name').attr('value') || '';
|
||||
var email = elem.find('.team-email').attr('value') || '';
|
||||
var website = elem.find('.team-website > a').attr('href') || '';
|
||||
var affiliation = elem.find('.team-affiliation').attr('value') || '';
|
||||
var country = elem.find('.team-country').attr('value') || '';
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').attr('value') || '';
|
||||
var name = elem.find('.team-name').attr('value') || '';
|
||||
var email = elem.find('.team-email').attr('value') || '';
|
||||
var website = elem.find('.team-website > a').attr('href') || '';
|
||||
var affiliation = elem.find('.team-affiliation').attr('value') || '';
|
||||
var country = elem.find('.team-country').attr('value') || '';
|
||||
|
||||
load_update_modal(id, name, email, website, affiliation, country);
|
||||
load_update_modal(id, name, email, website, affiliation, country);
|
||||
});
|
||||
|
||||
function load_confirm_modal(id, name){
|
||||
var modal = $('#confirm')
|
||||
modal.find('input[name=id]').val(id)
|
||||
modal.find('#confirm-team-name').text(name)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/team/'+id+'/delete');
|
||||
$('#confirm').modal();
|
||||
var modal = $('#confirm')
|
||||
modal.find('input[name=id]').val(id)
|
||||
modal.find('#confirm-team-name').text(name)
|
||||
$('#confirm form').attr('action', '{{ request.script_root }}/admin/team/'+id+'/delete');
|
||||
$('#confirm').modal();
|
||||
}
|
||||
|
||||
$('.fa-times').click(function(){
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var name = elem.find('.team-name').text().trim();
|
||||
load_confirm_modal(id, name)
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
var name = elem.find('.team-name').text().trim();
|
||||
load_confirm_modal(id, name)
|
||||
});
|
||||
|
||||
function load_email_modal(id){
|
||||
var modal = $('#email-user')
|
||||
modal.find('textarea').val("")
|
||||
modal.find('input[name=id]').val(id)
|
||||
$('#email-user-errors').empty()
|
||||
$('#email-user form').attr('action', '{{ request.script_root }}/admin/team/'+id+'/mail');
|
||||
$('#email-user').modal();
|
||||
var modal = $('#email-user')
|
||||
modal.find('textarea').val("")
|
||||
modal.find('input[name=id]').val(id)
|
||||
$('#email-user-errors').empty()
|
||||
$('#email-user form').attr('action', '{{ request.script_root }}/admin/team/'+id+'/mail');
|
||||
$('#email-user').modal();
|
||||
}
|
||||
|
||||
$('.fa-envelope').click(function(){
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
load_email_modal(id);
|
||||
var elem = $(this).parent().parent().parent();
|
||||
var id = elem.find('.team-id').text().trim();
|
||||
load_email_modal(id);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ ctf_name() }}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/{{ ctf_theme() }}/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/{{ ctf_theme() }}/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link href='{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/user.css">
|
||||
{% block stylesheets %}{% endblock %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/original/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
<title>{{ ctf_name() }}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="{{ request.script_root }}/static/{{ ctf_theme() }}/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="{{ request.script_root }}/static/{{ ctf_theme() }}/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/font-awesome/css/font-awesome.min.css" />
|
||||
<link href='{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/lato.css' rel='stylesheet' type='text/css'>
|
||||
<link href='{{ request.script_root }}/static/{{ ctf_theme() }}/css/vendor/raleway.css' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="{{ request.script_root }}/static/{{ ctf_theme() }}/css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="{{ request.script_root }}/static/user.css">
|
||||
{% block stylesheets %}{% endblock %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/moment.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/original/js/vendor/handlebars.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var script_root = "{{ request.script_root }}";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<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="{{ request.script_root }}/" 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="{{ request.script_root }}/{{ page.route }}">{{ page.route|title }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="{{ request.script_root }}/teams">Teams</a></li>
|
||||
{% if not hide_scores() %}
|
||||
<li><a href="{{ request.script_root }}/scoreboard">Scoreboard</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/challenges">Challenges</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if username is defined %}
|
||||
{% if admin %}
|
||||
<li><a href="{{ request.script_root }}/admin">Admin</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/team/{{ id }}">Team</a></li>
|
||||
<li><a href="{{ request.script_root }}/profile">Profile</a></li>
|
||||
<li><a href="{{ request.script_root }}/logout">Logout</a></li>
|
||||
{% else %}
|
||||
{% if can_register() %}
|
||||
<li><a href="{{ request.script_root }}/register">Register</a></li>
|
||||
<li><a style="padding-left:0px;padding-right:0px;">|</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/login">Login</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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="{{ request.script_root }}/" 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="{{ request.script_root }}/{{ page.route }}">{{ page.route|title }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="{{ request.script_root }}/teams">Teams</a></li>
|
||||
{% if not hide_scores() %}
|
||||
<li><a href="{{ request.script_root }}/scoreboard">Scoreboard</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/challenges">Challenges</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if username is defined %}
|
||||
{% if admin %}
|
||||
<li><a href="{{ request.script_root }}/admin">Admin</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/team/{{ id }}">Team</a></li>
|
||||
<li><a href="{{ request.script_root }}/profile">Profile</a></li>
|
||||
<li><a href="{{ request.script_root }}/logout">Logout</a></li>
|
||||
{% else %}
|
||||
{% if can_register() %}
|
||||
<li><a href="{{ request.script_root }}/register">Register</a></li>
|
||||
<li><a style="padding-left:0px;padding-right:0px;">|</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ request.script_root }}/login">Login</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
<div class="navbar navbar-bottom footer">
|
||||
<p class="text-muted text-center"><a style="text-decoration:none;" href="https://ctfd.io"><sub>Powered by CTFd</sub></p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/bootstrap.min.js"></script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
<div class="navbar navbar-bottom footer">
|
||||
<p class="text-muted text-center"><a style="text-decoration:none;" href="https://ctfd.io"><sub>Powered by CTFd</sub></p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/jquery.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/marked.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/bootstrap.min.js"></script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2,80 +2,80 @@
|
|||
|
||||
{% block stylesheets %}
|
||||
<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%; height:100px;}
|
||||
.submit-row {padding-top: 0px; padding-right: 0px; padding-left: 0px;}
|
||||
.disabled-button {background-color: #EEEEEE}
|
||||
.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%; height:100px;}
|
||||
.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: 10px; 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;}
|
||||
.file-button {text-decoration: none; color: #fff;}
|
||||
.file-button:hover {text-decoration: none; color: #fff;}
|
||||
.file-wrapper {padding: 10px; 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);
|
||||
}
|
||||
.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);
|
||||
}
|
||||
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .too-fast {
|
||||
border-color: rgb(252, 248, 227);
|
||||
}
|
||||
a, button {
|
||||
color: #74716D;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
.input-field:focus + .input-field,
|
||||
.input--filled .too-fast {
|
||||
border-color: rgb(252, 248, 227);
|
||||
}
|
||||
a, button {
|
||||
color: #74716D;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a:hover, a:focus {
|
||||
color: #c94e50;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
.content {
|
||||
max-width: 1000px;
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
padding: 2.5em 0 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
.button-wrap {
|
||||
padding: 2.5em 0 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
button.trigger {
|
||||
background: #c94e50;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
button.trigger {
|
||||
background: #c94e50;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -83,37 +83,37 @@
|
|||
|
||||
{% if errors %}
|
||||
<div class="container main-container">
|
||||
<div id='errors' class="row">
|
||||
<div id='errors' class="row">
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Challenges</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1>Challenges</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<div id='challenges-board' class="row">
|
||||
</div>
|
||||
<div id='challenges-board' class="row">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="nonce" type="hidden" name="nonce" value="{{ nonce }}">
|
||||
|
||||
<div class="modal fade" id="hint-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3>Hint</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="hint-modal-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3>Hint</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="hint-modal-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="chal-window" tabindex="-1" role="dialog">
|
||||
|
@ -122,8 +122,8 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/multi-modal.js"></script>
|
||||
{% if not errors %}<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/chalboard.js"></script>{% endif %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/multi-modal.js"></script>
|
||||
{% if not errors %}<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/chalboard.js"></script>{% endif %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<style>
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
<style>
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Confirm</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 %}
|
||||
<h3 class="text-center">
|
||||
We've sent a confirmation email to {{ team.email }}
|
||||
</h3>
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Confirm</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 %}
|
||||
<h3 class="text-center">
|
||||
We've sent a confirmation email to {{ team.email }}
|
||||
</h3>
|
||||
|
||||
<h3 class="text-center">
|
||||
Please click the link in that email to confirm your account and access the rest of the CTF.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="text-center">
|
||||
Please click the link in that email to confirm your account and access the rest of the CTF.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<h1 class="text-center">403</h1>
|
||||
<h2 class="text-center">An authorization error has occured</h2>
|
||||
<h2 class="text-center">Please try again</h2>
|
||||
<h1 class="text-center">403</h1>
|
||||
<h2 class="text-center">An authorization error has occured</h2>
|
||||
<h2 class="text-center">Please try again</h2>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<h1 class="text-center">404</h1>
|
||||
<h2 class="text-center">Whoops, looks like we can't find that.</h2>
|
||||
<h2 class="text-center">Sorry about that</h2>
|
||||
<h1 class="text-center">404</h1>
|
||||
<h2 class="text-center">Whoops, looks like we can't find that.</h2>
|
||||
<h2 class="text-center">Sorry about that</h2>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<h1 class="text-center">500</h1>
|
||||
<h2 class="text-center">An Internal Server Error has occured</h2>
|
||||
<h1 class="text-center">500</h1>
|
||||
<h2 class="text-center">An Internal Server Error has occured</h2>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<h1 class="text-center">502</h1>
|
||||
<h2 class="text-center">That action isn't allowed</h2>
|
||||
<h1 class="text-center">502</h1>
|
||||
<h2 class="text-center">That action isn't allowed</h2>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<style>
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
<style>
|
||||
#login-container {
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
.done-row {
|
||||
padding-top: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
<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">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="{{ request.script_root }}/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>
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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">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="{{ request.script_root }}/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>
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container main-container">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
{{ content | safe }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,140 +1,140 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<style>
|
||||
hr {
|
||||
margin-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.row {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
hr {
|
||||
margin-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.row {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Profile</h1>
|
||||
</div>
|
||||
<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 %}
|
||||
{% if confirm_email %}
|
||||
<div class="alert alert-info alert-dismissable submit-row" role="alert">
|
||||
Your email address isn't confirmed!
|
||||
Please check your email to confirm your email address.
|
||||
<br>
|
||||
<br>
|
||||
To have the confirmation email resent please <a href="{{ request.script_root }}/confirm">click
|
||||
here.</a>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% 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">Current 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 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 %}
|
||||
{% if confirm_email %}
|
||||
<div class="alert alert-info alert-dismissable submit-row" role="alert">
|
||||
Your email address isn't confirmed!
|
||||
Please check your email to confirm your email address.
|
||||
<br>
|
||||
<br>
|
||||
To have the confirmation email resent please <a href="{{ request.script_root }}/confirm">click
|
||||
here.</a>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
{% 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">Current 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="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,60 +5,60 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Register</h1>
|
||||
</div>
|
||||
<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>
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<input type="hidden" name="nonce" value="{{ nonce }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -5,55 +5,55 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Reset Password</h1>
|
||||
</div>
|
||||
<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-info 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">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
{% 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>
|
||||
<div class="row">
|
||||
<div id="login-container" class="col-md-6 col-md-offset-3">
|
||||
{% for error in errors %}
|
||||
<div class="alert alert-info 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">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
{% 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>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,55 +2,55 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Scoreboard</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1>Scoreboard</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
{% if errors %}
|
||||
<div class="container main-container">
|
||||
<div id='errors' class="row">
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if errors %}
|
||||
<div class="container main-container">
|
||||
<div id='errors' class="row">
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
{% if score_frozen %}
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<h1>Scoreboard has been frozen.</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if score_frozen %}
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<h1>Scoreboard has been frozen.</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="score-graph"></div>
|
||||
<br>
|
||||
<div id="score-graph"></div>
|
||||
<br>
|
||||
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b>
|
||||
</td>
|
||||
<td><b>Team</b>
|
||||
</td>
|
||||
<td><b>Score</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr><td>{{ loop.index }}</td><td><a href="{{ request.script_root }}/team/{{ team.teamid }}">{{ team.name }}</a></td><td>{{ team.score }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
<table id="scoreboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="10px"><b>Place</b>
|
||||
</td>
|
||||
<td><b>Team</b>
|
||||
</td>
|
||||
<td><b>Score</b>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr><td>{{ loop.index }}</td><td><a href="{{ request.script_root }}/team/{{ team.teamid }}">{{ team.name }}</a></td><td>{{ team.score }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/scoreboard.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/scoreboard.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,58 +5,58 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Setup</h1>
|
||||
</div>
|
||||
<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 %}
|
||||
<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">Admin 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">Admin 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">Admin Password</span>
|
||||
</label>
|
||||
</span>
|
||||
<br/>
|
||||
<div class="submit-row text-center">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<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 %}
|
||||
<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">Admin 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">Admin 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">Admin Password</span>
|
||||
</label>
|
||||
</span>
|
||||
<br/>
|
||||
<div class="submit-row text-center">
|
||||
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/style.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,99 +5,99 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1 id="team-id">{{ team.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
{% if errors %}
|
||||
<div id='errors' class="row">
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% if errors %}
|
||||
<div id='errors' class="row">
|
||||
{% for error in errors %}
|
||||
<h1>{{ error }}</h1>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
{% if score_frozen %}
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<h1>Scoreboard has been frozen.</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if score_frozen %}
|
||||
<div class="container main-container">
|
||||
<div class="row">
|
||||
<h1>Scoreboard has been frozen.</h1>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<br>
|
||||
|
||||
<div id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<br>
|
||||
<div id="score-graph"></div>
|
||||
<div id="keys-pie-graph"></div>
|
||||
<div id="categories-pie-graph"></div>
|
||||
<br>
|
||||
<div id="score-graph"></div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
{% if awards %}
|
||||
<div class="row">
|
||||
<h3>Awards</h3>
|
||||
{% for award in awards %}
|
||||
{% set count= awards|length - loop.index %}
|
||||
{% set rem = awards|length % 4 %}
|
||||
{% if count < rem %}
|
||||
<div class="col-xs-{{ (12//rem)|string }} col-md-{{ (12//rem)|string }}">
|
||||
{% else %}
|
||||
<div class="col-xs-3 col-md-3">
|
||||
{% endif %}
|
||||
<p class="text-center"><strong>{{ award.name }}</strong></p>
|
||||
{% if award.category %}<p class="text-center">{{ award.category }}</p>{% endif %}
|
||||
<p class="text-center">{{ award.description }}</p>
|
||||
<p class="text-center">{{ award.value }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if awards %}
|
||||
<div class="row">
|
||||
<h3>Awards</h3>
|
||||
{% for award in awards %}
|
||||
{% set count= awards|length - loop.index %}
|
||||
{% set rem = awards|length % 4 %}
|
||||
{% if count < rem %}
|
||||
<div class="col-xs-{{ (12//rem)|string }} col-md-{{ (12//rem)|string }}">
|
||||
{% else %}
|
||||
<div class="col-xs-3 col-md-3">
|
||||
{% endif %}
|
||||
<p class="text-center"><strong>{{ award.name }}</strong></p>
|
||||
{% if award.category %}<p class="text-center">{{ award.category }}</p>{% endif %}
|
||||
<p class="text-center">{{ award.description }}</p>
|
||||
<p class="text-center">{{ award.value }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<br>
|
||||
{% endif %}
|
||||
<br>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<h3>Solves</h3>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Challenge</b></td>
|
||||
<td class="hidden-xs"><b>Category</b></td>
|
||||
<td><b>Value</b></td>
|
||||
<td><b>Time</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr>
|
||||
<td><a href="{{ request.script_root }}/challenges#{{ solve.chal.name }}">{{ solve.chal.name }}</a></td>
|
||||
<td class="hidden-xs">{{ solve.chal.category }}</td><td>{{ solve.chal.value }}</td>
|
||||
<td class="solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<h3>Solves</h3>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Challenge</b></td>
|
||||
<td class="hidden-xs"><b>Category</b></td>
|
||||
<td><b>Value</b></td>
|
||||
<td><b>Time</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for solve in solves %}
|
||||
<tr>
|
||||
<td><a href="{{ request.script_root }}/challenges#{{ solve.chal.name }}">{{ solve.chal.name }}</a></td>
|
||||
<td class="hidden-xs">{{ solve.chal.category }}</td><td>{{ solve.chal.value }}</td>
|
||||
<td class="solve-time"><script>document.write( moment({{ solve.date|unix_time_millis }}).local().format('MMMM Do, h:mm:ss A'))</script></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/team.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/vendor/plotly.min.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/utils.js"></script>
|
||||
<script src="{{ request.script_root }}/static/{{ ctf_theme() }}/js/team.js"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,52 +5,52 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="jumbotron home">
|
||||
<div class="container">
|
||||
<h1>Teams</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1>Teams</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-container">
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Team</b></td>
|
||||
<td><b>Website</b></td>
|
||||
<td><b>Affiliation</b></td>
|
||||
<td class="hidden-xs"><b>Country</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if hide_scores() %}
|
||||
<span>{{ team.name }}</span>
|
||||
{% else %}
|
||||
<a href="{{ request.script_root }}/team/{{ team.id }}">{{ team.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %}<a href="{{ team.website }}">{{ team.website }}</a>{% endif %}</td>
|
||||
<td><span>{% if team.affiliation %}{{ team.affiliation }}{% endif %}</span></td>
|
||||
<td class="hidden-xs"><span>{% if team.country %}{{ team.country }}{% endif %}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if team_pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/teams/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, team_pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/teams/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{page}}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != team_pages %}<a href="{{ request.script_root }}/teams/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
<a href="{{ request.script_root }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
<table id="teamsboard" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>Team</b></td>
|
||||
<td><b>Website</b></td>
|
||||
<td><b>Affiliation</b></td>
|
||||
<td class="hidden-xs"><b>Country</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if hide_scores() %}
|
||||
<span>{{ team.name }}</span>
|
||||
{% else %}
|
||||
<a href="{{ request.script_root }}/team/{{ team.id }}">{{ team.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if team.website and (team.website.startswith('http://') or team.website.startswith('https://')) %}<a href="{{ team.website }}">{{ team.website }}</a>{% endif %}</td>
|
||||
<td><span>{% if team.affiliation %}{{ team.affiliation }}{% endif %}</span></td>
|
||||
<td class="hidden-xs"><span>{% if team.country %}{{ team.country }}{% endif %}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if team_pages > 1 %}
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if curr_page != 1 %}<a href="{{ request.script_root }}/teams/{{ curr_page-1 }}"><<<</a>{% endif %}
|
||||
{% for page in range(1, team_pages + 1) %}
|
||||
{% if curr_page != page %}
|
||||
<a href="{{ request.script_root }}/teams/{{ page }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<b>{{page}}</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if curr_page != team_pages %}<a href="{{ request.script_root }}/teams/{{ curr_page+1 }}">>>></a>{% endif %}
|
||||
<a href="{{ request.script_root }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
Loading…
Reference in New Issue