629 lines
19 KiB
Plaintext
629 lines
19 KiB
Plaintext
<!-- Simple Styling for layout -->
|
|
<style>
|
|
.members {
|
|
width: 230px;
|
|
display: inline-block;
|
|
}
|
|
.head {
|
|
position: absolute;
|
|
width: 345px;
|
|
height: 600px;
|
|
top: 25px;
|
|
left: 25px;
|
|
border: solid #5b94f0 2px;
|
|
border-style: solid;
|
|
border-radius: 10px;
|
|
background-color: rgba(112, 196, 255, .3);
|
|
}
|
|
.head-content {
|
|
position: absolute;
|
|
left: 15px;
|
|
}
|
|
.teacher-container {
|
|
position: absolute;
|
|
width: 300px;
|
|
}
|
|
.members-container {
|
|
position: absolute;
|
|
left: 400px;
|
|
}
|
|
.quests-container {
|
|
position: absolute;
|
|
left: 800px;
|
|
background: rgba(0, 0, 0, .2);
|
|
border-radius: 24px;
|
|
border-style: solid;
|
|
border-color: rgba(0, 0, 0, .2);
|
|
}
|
|
.quest-content {
|
|
margin-left: 15px;
|
|
margin-top: 10px;
|
|
margin-right: 15px;
|
|
}
|
|
.course-container {
|
|
position: absolute;
|
|
left: 1000px;
|
|
background: rgba(0, 0, 0, .2);
|
|
border-radius: 24px;
|
|
border-style: solid;
|
|
border-color: rgba(0, 0, 0, .2);
|
|
}
|
|
.course-content {
|
|
margin-left: 15px;
|
|
margin-top: 10px;
|
|
margin-right: 15px;
|
|
max-width: 200px;
|
|
}
|
|
.quest {
|
|
color: #e05f3a;
|
|
}
|
|
#pro-pic {
|
|
position: absolute;
|
|
top: 0px;
|
|
left: 0px;
|
|
width: 100px;
|
|
display: block;
|
|
border-radius: 50px;
|
|
border: 1px solid black;
|
|
margin:5px;
|
|
}
|
|
#user-pro-pic {
|
|
position: absolute;
|
|
top: 0px;
|
|
left: 150px;
|
|
width: 50px;
|
|
height: 50px;
|
|
display: block;
|
|
border-radius: 50px;
|
|
border: 1px solid black;
|
|
margin:5px;
|
|
}
|
|
.buttons-container {
|
|
position: absolute;
|
|
top: 380px;
|
|
right: 180px;
|
|
}
|
|
.button-content {
|
|
width: 127px;
|
|
margin-left: 25px;
|
|
margin-top: 10px;
|
|
}
|
|
#edit-btn {
|
|
width: 127px;
|
|
margin-left: 25px;
|
|
margin-top: 10px;
|
|
}
|
|
#bug-btn {
|
|
width: 127px;
|
|
margin-left: 25px;
|
|
margin-top: 10px;
|
|
}
|
|
#logout-btn {
|
|
width: 127px;
|
|
margin-left: 25px;
|
|
margin-top: 10px;
|
|
}
|
|
#welcome {
|
|
position: absolute;
|
|
left: 115px;
|
|
top: 60px;
|
|
}
|
|
h2 {
|
|
font: 350 35px/1.5 Helvetica, Verdana, sans-serif;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
ul {
|
|
list-style-type: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
li {
|
|
font: 200 20px/1.5 Helvetica, Verdana, sans-serif;
|
|
border-bottom: 1px solid #ccc;
|
|
}
|
|
li:last-child {
|
|
border: none;
|
|
}
|
|
li a {
|
|
text-decoration: none;
|
|
color: #000;
|
|
display: block;
|
|
width: 200px;
|
|
-webkit-transition: font-size 0.3s ease, background-color 0.3s ease;
|
|
-moz-transition: font-size 0.3s ease, background-color 0.3s ease;
|
|
-o-transition: font-size 0.3s ease, background-color 0.3s ease;
|
|
-ms-transition: font-size 0.3s ease, background-color 0.3s ease;
|
|
transition: font-size 0.3s ease, background-color 0.3s ease;
|
|
}
|
|
li a:hover {
|
|
font-size: 30px;
|
|
background: #f6f6f6;
|
|
}
|
|
</style>
|
|
|
|
<!-- Welcome Message & Profile Picture -->
|
|
<div class='head'>
|
|
<div class='head-content'>
|
|
<h1 class="mt-4">Teacher Dashboard</h1>
|
|
<div class="teacher-container">
|
|
<p id='welcome' class="lead mb-3">Welcome <%= user.name %></p>
|
|
<img id='pro-pic' src='data:image/<%=user.image.contentType%>;base64,
|
|
<%=user.image.data.toString('base64')%>'>
|
|
</div>
|
|
<br>
|
|
|
|
<div class="buttons-container">
|
|
<!-- Action Buttons -->
|
|
<a href="/users/logout" class="button-content btn btn-outline-info btn-sm">Logout</a>
|
|
<button onClick='passData()' class='button-content btn btn-outline-info btn-sm'>Edit</button>
|
|
<a href="https://github.com/Braeden57/XP-System/issues" target="_blank" class='button-content btn btn-outline-info btn-sm'>Report Bug</a>
|
|
<button class="button-content btn btn-outline-info btn-sm" data-toggle="modal" data-target="#createQuest">New Quest</button>
|
|
<button class="button-content btn btn-outline-info btn-sm" data-toggle="modal" data-target="#createClass">New Class</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
|
|
<!-- Sets Variables for calculating users data -->
|
|
<script>
|
|
let xp;
|
|
let currRank;
|
|
let ranks = [
|
|
{"Digital Noob": 0}, // index 0
|
|
{"Digital Novice": 48}, // index 1
|
|
{"Digital Novice II": 100}, // index 2
|
|
{"Digital Amature": 148}, // index 3
|
|
{"Digital Amature II": 200}, // index 4
|
|
{"Digital Apprentice": 248}, // index 5
|
|
{"Digital Apprentice II": 300}, // index 6
|
|
{"Digital Journeyman": 396}, // index 7
|
|
{"Digital Journeyman II": 476}, // index 8
|
|
{"Digital Journeyman III": 532}, // index 9
|
|
{"Digital Crafter": 580}, // index 10
|
|
{"Expert Digital Crafter": 648}, // index 11
|
|
{"Master Digital Crafter": 800} // index 12
|
|
]
|
|
let indexes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12]
|
|
|
|
// Students should't be on this page sooooo...
|
|
console.log("Students Shouldnt be here");
|
|
</script>
|
|
|
|
<!-- Alert container -->
|
|
<div id='div-container'></div>
|
|
|
|
<!-- Add XP Modal -->
|
|
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="exampleModalLabel">Add XP</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form action="/users/addXP" method="POST">
|
|
<div>
|
|
<input id='_id_add' type='text' name='_id_add' value='' style='display: none'></input>
|
|
<input id="current_xp" type="text" name="current_xp" value="" style="display: none"></input>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="amount">Amount</label>
|
|
<input
|
|
id="amount"
|
|
name="amount"
|
|
type="number"
|
|
min="1"
|
|
value=""
|
|
class="form-control"
|
|
>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">
|
|
Add XP
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Quest Modal -->
|
|
<div class="modal fade" id="createQuest" tabindex="-1" role="dialog" aria-labelledby="createQuestLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="createQuestLabel">Create Quest</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form action="/users/createQuest" method="POST">
|
|
<div>
|
|
<label for="title">Title</label>
|
|
<input
|
|
id="title"
|
|
name="title"
|
|
type="text"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="amount">Amount</label>
|
|
<input
|
|
id="amount"
|
|
name="amount"
|
|
type="number"
|
|
min="1"
|
|
max="50"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<div>
|
|
<label for="expiry">Expiry</label>
|
|
<input
|
|
id="expiry"
|
|
name="expiry"
|
|
type="date"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<div>
|
|
<label for="instructions">Instructions</label>
|
|
<textarea
|
|
id="instructions"
|
|
name="instructions"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
></textarea>
|
|
</div>
|
|
<div>
|
|
<label for="course">Course/Class</label>
|
|
<select class="form-control" required name="course" id="course">
|
|
<option value="">--Please Choose a Class--</option>
|
|
<% courses.forEach(function(course) { %>
|
|
<option value="<%= course.name %>"><%= course.name %></option>
|
|
<% }) %>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="campaign">Campaign</label>
|
|
<input
|
|
id="campaign"
|
|
name="campaign"
|
|
type="text"
|
|
value=""
|
|
placeholder="New Campaign"
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">
|
|
Create Quest
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Class Modal -->
|
|
<div class="modal fade" id="createClass" tabindex="-1" role="dialog" aria-labelledby="createClassLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="createClassLabel">Create Class</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form action="/users/createClass" method="POST">
|
|
<div>
|
|
<label for="name">Class Name</label>
|
|
<input
|
|
id="name"
|
|
name="name"
|
|
type="text"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<div>
|
|
<label for="description">Class Description</label>
|
|
<textarea
|
|
id="description"
|
|
name="description"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
></textarea>
|
|
</div>
|
|
<div>
|
|
<label for="grade">Grade</label>
|
|
<input
|
|
id="grade"
|
|
name="grade"
|
|
type="number"
|
|
min="8"
|
|
max="12"
|
|
value=""
|
|
class="form-control"
|
|
required
|
|
>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">
|
|
Create Class
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Class Details Modal -->
|
|
<div class="modal fade" id="classDetails" tabindex="-1" role="dialog" aria-labelledby="classDetailsLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="classDetailsLabel">Class Details</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<label>Name:</label>
|
|
<h2 id="classDetailName"></h2>
|
|
<br>
|
|
<label>Grade:</label>
|
|
<h3 id="classDetailGrade"></h3>
|
|
<br>
|
|
<label>Description:</label>
|
|
<p id="classDetailDesc"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="members-container">
|
|
<!-- List of all site students (not teachers) -->
|
|
<h2>Studen Members</h2>
|
|
<div class='members'>
|
|
<ul>
|
|
<!-- Loops through all members -->
|
|
<% members.forEach(function (member) { %>
|
|
<!-- Identifies students -->
|
|
<% if (member.role == "Student") { %>
|
|
<!-- Creates User Button link -->
|
|
<li><button class='btn btn-link mt-2' onclick='openProfile("<%= member.id %>")'><%= member.name %></button></li>
|
|
|
|
<!-- Creates hidden Div with user specific Data -->
|
|
<div style='display: none; position: relative;' data-role='page' id='<%= member._id %>'>
|
|
<img id='user-pro-pic' src='data:image/<%=member.image.contentType%>;base64,<%=member.image.data.toString('base64')%>'>
|
|
<p id='memberName' class='lead mb-3'><%= member.name %></p>
|
|
<p class='lead mb-3'><%= member.email %></p>
|
|
<br>
|
|
<div>
|
|
<p id='userRank-<%= member.id %>'></p>
|
|
<p>XP: <%= member.xp %></p>
|
|
|
|
<!-- Button trigger modal -->
|
|
<button onClick='passName("<%= member.name %>", <%= member.xp %>, "<%= member._id %>")' type="button" class="btn btn-outline-info btn-sm">
|
|
Add XP
|
|
</button>
|
|
|
|
<p><%= member.role %></p>
|
|
</div>
|
|
<br>
|
|
|
|
<!-- Calculates user specific Rank -->
|
|
<script>
|
|
xp = <%= member.xp %>;
|
|
// Get current rank
|
|
if (xp == 0) {
|
|
currRank = 'Digital Noob';
|
|
} else {
|
|
if (xp < 800 && xp > 0) {
|
|
for(var i = 0; i < ranks.length; i++) {
|
|
for (let rank in ranks[i]) {
|
|
let nextIndex = indexes[i];
|
|
for (let nextRank in ranks[nextIndex]) {
|
|
if (xp >= ranks[i][rank] && xp < ranks[nextIndex][nextRank]) {
|
|
currRank = rank;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (xp == 800) {
|
|
currRank = "Master Digital Crafter";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Display Rank
|
|
document.getElementById('userRank-<%= member.id %>').innerHTML = currRank;
|
|
</script>
|
|
</div>
|
|
<% } %>
|
|
<% }) %>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="quests-container">
|
|
<!-- List of Quests -->
|
|
<div class='quest-content'>
|
|
<h2>All Quests</h2>
|
|
<ul>
|
|
<% quests.forEach(function (quest) { %>
|
|
<li><button class='list-button btn btn-outline-success mt-2' onclick="redirect('<%= quest._id %>')"><%= quest.title %></button></li>
|
|
<% }) %>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="course-container">
|
|
<!-- List of Courses -->
|
|
<div class='course-content'>
|
|
<h2>All Courses</h2>
|
|
<ul>
|
|
<% courses.forEach(function (course) { %>
|
|
<div class='course'>
|
|
<li><button class="btn btn-outline-success mt-2" onclick="showDetails('<%= course._id %>')"><%= course.name %>: <%= course.grade %></button></li>
|
|
</div>
|
|
<% }) %>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/socket.io/socket.io.js"></script>
|
|
<script>
|
|
let socket = io.connect('http://localhost:5000');
|
|
|
|
function showDetails(id) {
|
|
<% courses.forEach(function(course) { %>
|
|
if('<%=course._id%>' == id) {
|
|
document.getElementById('classDetailName').innerHTML = '<%= course.name %>';
|
|
document.getElementById('classDetailGrade').innerHTML = '<%= course.grade %>';
|
|
document.getElementById('classDetailDesc').innerHTML = '<%= course.description %>';
|
|
$("#classDetails").modal();
|
|
}
|
|
<% }) %>
|
|
}
|
|
|
|
// Creates unique ID
|
|
function makeid(length) {
|
|
var result = '';
|
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
var charactersLength = characters.length;
|
|
for ( var i = 0; i < length; i++ ) {
|
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function passData() {
|
|
let url = '/users/edit?name=' + encodeURIComponent('<%= user._id %>');
|
|
|
|
document.location.href = url;
|
|
}
|
|
|
|
// Create Div
|
|
function createDiv(type, message) {
|
|
let id = makeid(8);
|
|
|
|
if (type == 'error') {
|
|
document.getElementById('div-container').innerHTML += '<div id="new-div-'+id+'" style="display: none;" class="alert alert-warning alert-dismissible fade show" role="alert">';
|
|
}
|
|
if (type == 'message') {
|
|
document.getElementById('div-container').innerHTML += '<div id="new-div-'+id+'" style="display: none;" class="alert alert-info alert-dismissible fade show" role="alert">';
|
|
}
|
|
document.getElementById('new-div-'+id).innerHTML += '<div id="message'+id+'">'+message+'</div>';
|
|
document.getElementById('new-div-'+id).innerHTML += '<button id="close-btn-'+id+'" class="close" data-dismiss="alert" aria-label="Close"></button>';
|
|
document.getElementById('close-btn-'+id).innerHTML += '<span aria-hidden="true">×</span>';
|
|
document.getElementById('new-div-'+id).style.display = "block";
|
|
}
|
|
|
|
// Pass name to Modal
|
|
function passName(name, xp, member_id) {
|
|
if (xp < 800) {
|
|
document.getElementById("exampleModalLabel").innerHTML = "Give " + name + " XP";
|
|
document.getElementById("_id_add").value = member_id;
|
|
document.getElementById("current_xp").value = xp;
|
|
$("#exampleModal").modal()
|
|
}
|
|
if (xp >= 800) {
|
|
// Construct and show Max XP Alert
|
|
message = name + ' has reached max XP!';
|
|
createDiv('message', message);
|
|
}
|
|
}
|
|
|
|
let getParameterByName = function() {
|
|
let queries = location.search.substring(1).split('&'),
|
|
processed = {};
|
|
for (let query of queries) {
|
|
let [name, value] = query.split('=');
|
|
processed[decodeURIComponent(name)] = value? decodeURIComponent(value) : '';
|
|
}
|
|
|
|
return function(name) {
|
|
if (typeof processed[name] !== 'undefined')
|
|
return processed[name];
|
|
else
|
|
return null;
|
|
};
|
|
}();
|
|
|
|
function updateXP(addXP, id) {
|
|
let data = {
|
|
userID: id,
|
|
addXP: addXP
|
|
}
|
|
socket.emit('add:xp', data);
|
|
}
|
|
|
|
// Catching url Parameters
|
|
window.onload = function () {
|
|
const queryString = window.location.search;
|
|
const urlParams = new URLSearchParams(queryString);
|
|
const successRate = urlParams.get('successRate')
|
|
if(successRate == 'addXP > 50') {
|
|
createDiv('error', "Can't add more than 50 XP")
|
|
}
|
|
if(successRate == 'addXP <= 0') {
|
|
createDiv('error', "XP Must be Greater than 0");
|
|
}
|
|
if(parseInt(successRate) > 0) {
|
|
createDiv('message', "Gave " + successRate + "XP to a Student");
|
|
updateXP(successRate, getParameterByName('id'));
|
|
}
|
|
if(successRate == 'createdQuest') {
|
|
createDiv('message', "Successfully Created Quest");
|
|
}
|
|
if(successRate == 'createdClass') {
|
|
createDiv('message', "Successfully created Course");
|
|
}
|
|
}
|
|
|
|
// Script for show/hide user profile data
|
|
function openProfile(id) {
|
|
let state = document.getElementById(id).style.display;
|
|
if (state == "block") {
|
|
document.getElementById(id).style.display = 'none';
|
|
} else {
|
|
document.getElementById(id).style.display = 'block';
|
|
}
|
|
}
|
|
|
|
// Script for redirecting to selected Quest
|
|
function redirect(id) {
|
|
let url = '/users/quests?id=' + encodeURIComponent(id);
|
|
|
|
document.location.href = url;
|
|
}
|
|
</script>
|