7 files changed
+109
-33
No files matched your search
@@ -1,20 +1,22 @@
|
|||||||
# XP-System
|
# XP-System
|
||||||
|
|
||||||
School Project
|
This school project is for my teacher to have students log in and check out their XP and assignments.
|
||||||
This school project is for my teacher to have students
|
|
||||||
log in and check out their XP and assignments.
|
|
||||||
This website application is not available online, this is just a locally run website at our school.
|
This website application is not available online, this is just a locally run website at our school.
|
||||||
To create a teacher, it must be done by a site admin. You'll need to create the site admin in the
|
To create a teacher, it must be done by a site admin.
|
||||||
database in a collection called `users` and set insert a document formatted as shown:
|
|
||||||
`
|
You'll need to create the site admin in the database in a collection called users,
|
||||||
{
|
and insert a document via MongoDB Compass. Format the document as shown:
|
||||||
"_id": your generated id,
|
`{
|
||||||
"role": "Admin",
|
"role": "Admin",
|
||||||
"name": your name,
|
"name": your name,
|
||||||
"email": your email,
|
"email": your email,
|
||||||
"password": your encrypted password
|
"password": your encrypted password
|
||||||
}
|
}`
|
||||||
`
|
|
||||||
|
Replace `your name` with the name you specify, `your email` with the email you would like to use to login,
|
||||||
|
and replace `your encrypted password` with your [Encrypted Password](#Encrypting Your Password)
|
||||||
|
|
||||||
|
The ID for your admin document should be auto generated by MongoDB Compass when you `insert` the document.
|
||||||
|
|
||||||
### Requirements :
|
### Requirements :
|
||||||
1. [Node.js](https://nodejs.org/en/)
|
1. [Node.js](https://nodejs.org/en/)
|
||||||
@@ -28,7 +30,15 @@ database in a collection called `users` and set insert a document formatted as s
|
|||||||
1. Run `npm start` to boot up server.
|
1. Run `npm start` to boot up server.
|
||||||
1. Go to http://localhost:8080. Or Whatever you set it to in the `.env` file.
|
1. Go to http://localhost:8080. Or Whatever you set it to in the `.env` file.
|
||||||
|
|
||||||
|
### Setting up MongoDB
|
||||||
|
1. Install mongodb and follow the setup steps.
|
||||||
|
1. [Step by step instructions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows)
|
||||||
|
|
||||||
### Accessing the Database
|
### Accessing the Database
|
||||||
1. Locally this will use any db you set the DB_URI to in the `.env` file.
|
1. Locally this will use any db you set the DB_URI to in the `.env` file.
|
||||||
1. You can use MongoDB compass app to view the db and edit any information stored.
|
1. You can use MongoDB compass app to view the db and edit any information stored.
|
||||||
2. Or connect it to an external db by changing the DB_URI in the `.env` to your db key.
|
2. Or connect it to an external db by changing the DB_URI in the `.env` to your db key.
|
||||||
|
|
||||||
|
### Encrypting Your Password
|
||||||
|
1. To encrypt your password while creating the admin account. Go into the `config` folder,
|
||||||
|
1. follow the instructions in encrypt.js and run encrypt.js via node `node encrypt.js`
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
const bcrypt = require('bcryptjs');
|
||||||
|
|
||||||
|
// Set `password` as the password you will use
|
||||||
|
// Then Run this script and copy the output as it is your encrypted password
|
||||||
|
let password = "APPLEZ57";
|
||||||
|
|
||||||
|
// Encrypts password and returns encrypted password
|
||||||
|
bcrypt.genSalt(10, (err, salt) => {
|
||||||
|
bcrypt.hash(password, salt, (err, hash) => {
|
||||||
|
if (err) throw err;
|
||||||
|
console.log(hash);
|
||||||
|
});
|
||||||
|
});
|
||||||
+3
-3
@@ -224,7 +224,7 @@ router.post('/addXP', (req, res, next) => {
|
|||||||
// Edit
|
// Edit
|
||||||
router.post('/edit', upload.single('image'), (req, res, next) => {
|
router.post('/edit', upload.single('image'), (req, res, next) => {
|
||||||
// Passes image path to defaultImage Model
|
// Passes image path to defaultImage Model
|
||||||
imagePath = __dirname + '/uploads/default-image';
|
let imagePath = __dirname + '/uploads/default-image';
|
||||||
module.exports = {
|
module.exports = {
|
||||||
defaultPath: imagePath
|
defaultPath: imagePath
|
||||||
}
|
}
|
||||||
@@ -426,7 +426,7 @@ router.post('/edit', upload.single('image'), (req, res, next) => {
|
|||||||
// Register Teacher
|
// Register Teacher
|
||||||
router.post('/registerTeacher', upload.single('image'), (req, res, next) => {
|
router.post('/registerTeacher', upload.single('image'), (req, res, next) => {
|
||||||
// Passes image path to defaultImage Model
|
// Passes image path to defaultImage Model
|
||||||
imagePath = __dirname + '/uploads/default-image';
|
let imagePath = __dirname + '/uploads/default-image';
|
||||||
module.exports = {
|
module.exports = {
|
||||||
defaultPath: imagePath
|
defaultPath: imagePath
|
||||||
}
|
}
|
||||||
@@ -565,7 +565,7 @@ router.post('/registerTeacher', upload.single('image'), (req, res, next) => {
|
|||||||
// Register
|
// Register
|
||||||
router.post('/register', upload.single('image'), (req, res, next) => {
|
router.post('/register', upload.single('image'), (req, res, next) => {
|
||||||
// Passes image path to defaultImage Model
|
// Passes image path to defaultImage Model
|
||||||
imagePath = __dirname + '/uploads/default-image';
|
let imagePath = __dirname + '/uploads/default-image';
|
||||||
module.exports = {
|
module.exports = {
|
||||||
defaultPath: imagePath
|
defaultPath: imagePath
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
<!-- Shows user specific Dashboard -->
|
<!-- Shows user specific Dashboard -->
|
||||||
<% if (user.role == "Admin") { %>
|
<% if (user.role == "Admin") { %>
|
||||||
<% include admin %>
|
<% include admin %>
|
||||||
|
|||||||
+5
-1
@@ -17,6 +17,9 @@
|
|||||||
const queryString = window.location.search;
|
const queryString = window.location.search;
|
||||||
const urlParams = new URLSearchParams(queryString);
|
const urlParams = new URLSearchParams(queryString);
|
||||||
const id = urlParams.get('id');
|
const id = urlParams.get('id');
|
||||||
|
<% if(quests.length == 0) { %>
|
||||||
|
document.getElementById('div-container').innerHTML = "<h2>Uh oh, theres no quests :(</h2>";
|
||||||
|
<% } else if(quests.length > 0) { %>
|
||||||
<% quests.forEach(function (quest) { %>
|
<% quests.forEach(function (quest) { %>
|
||||||
if('<%= quest._id %>' == id) {
|
if('<%= quest._id %>' == id) {
|
||||||
document.getElementById('div-container').innerHTML += '<div id="quest">';
|
document.getElementById('div-container').innerHTML += '<div id="quest">';
|
||||||
@@ -24,9 +27,10 @@
|
|||||||
document.getElementById('quest').innerHTML += '<h2 class="title">Campaign: <%= quest.campaign %></h2>'
|
document.getElementById('quest').innerHTML += '<h2 class="title">Campaign: <%= quest.campaign %></h2>'
|
||||||
document.getElementById('quest').innerHTML += '<p class="info">XP: <%= quest.xp %></p>';
|
document.getElementById('quest').innerHTML += '<p class="info">XP: <%= quest.xp %></p>';
|
||||||
document.getElementById('quest').innerHTML += '<p class="info">Expires: <%= quest.expiry %></p>';
|
document.getElementById('quest').innerHTML += '<p class="info">Expires: <%= quest.expiry %></p>';
|
||||||
document.getElementById('quest').innerHTML += '<h3 class="info">Instructions: <%= quest.instruction %></h3>';
|
document.getElementById('quest').innerHTML += `<h3 class="info">Instructions: <%= quest.instruction %></h3>`;
|
||||||
}
|
}
|
||||||
<% }) %>
|
<% }) %>
|
||||||
|
<% } %>
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
+26
-18
@@ -1,4 +1,4 @@
|
|||||||
<!-- Simple Syling for layout -->
|
<!-- Simple Styling for layout -->
|
||||||
<style>
|
<style>
|
||||||
.quests-container {
|
.quests-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -201,19 +201,25 @@
|
|||||||
let percent;
|
let percent;
|
||||||
let indexes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12]
|
let indexes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12]
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
calculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
let xp = <%= user.xp %>;
|
let xp = <%= user.xp %>;
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
calculate()
|
||||||
|
}
|
||||||
|
|
||||||
// Passing user _id to edit page script
|
// Passing user _id to edit page script
|
||||||
function passData() {
|
function passData() {
|
||||||
let url = '/users/edit?name=' + encodeURIComponent('<%= user._id %>');
|
let url = '/users/edit?name=' + encodeURIComponent('<%= user._id %>');
|
||||||
|
|
||||||
document.location.href = url;
|
document.location.href = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redirects to quest page to see quest
|
||||||
|
function redirect(id) {
|
||||||
|
let url = '/users/quests?id=' + encodeURIComponent(id);
|
||||||
|
document.location.href = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a list of Quest Objects
|
||||||
let allQuests = [];
|
let allQuests = [];
|
||||||
let questObj;
|
let questObj;
|
||||||
<% quests.forEach(function (quest) { %>
|
<% quests.forEach(function (quest) { %>
|
||||||
@@ -222,23 +228,25 @@
|
|||||||
title: "<%= quest.title %>",
|
title: "<%= quest.title %>",
|
||||||
expiry: "<%= quest.expiry %>",
|
expiry: "<%= quest.expiry %>",
|
||||||
xp: <%= quest.xp %>,
|
xp: <%= quest.xp %>,
|
||||||
instruction: "<%= quest.instruction %>",
|
instruction: `<%= quest.instruction %>`,
|
||||||
referenceClass: "<%= quest.referenceClass %>",
|
referenceClass: "<%= quest.referenceClass %>",
|
||||||
campaign: "<%= quest.campaign %>",
|
campaign: "<%= quest.campaign %>",
|
||||||
};
|
};
|
||||||
allQuests.push(questObj);
|
allQuests.push(questObj);
|
||||||
<% }) %>
|
<% }) %>
|
||||||
|
|
||||||
|
// Shows quests only related to selected class
|
||||||
function showQuest() {
|
function showQuest() {
|
||||||
document.getElementById('class-quests').innerHTML = "";
|
document.getElementById('class-quests').innerHTML = "";
|
||||||
let className = document.getElementById('classes').value;
|
let className = document.getElementById('classes').value;
|
||||||
for(let i = 0; i < allQuests.length; i++) {
|
for(let i = 0; i < allQuests.length; i++) {
|
||||||
if (allQuests[i]["referenceClass"] == className) {
|
if (allQuests[i]["referenceClass"] == className) {
|
||||||
document.getElementById('class-quests').innerHTML += `<li><button class='list-button btn btn-outline-success mt-2' onclick="redirect(${allQuests[i]["_id"]})">${allQuests[i]["title"]}</button></li>`;
|
document.getElementById('class-quests').innerHTML += `<li><button class="list-button btn btn-outline-success mt-2" onclick="redirect('${allQuests[i]["_id"]}')">${allQuests[i]["title"]}</button></li>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global Ranks + RankXP
|
||||||
let ranks = [
|
let ranks = [
|
||||||
{"Digital Noob": 0}, // index 0
|
{"Digital Noob": 0}, // index 0
|
||||||
{"Digital Novice": 48}, // index 1
|
{"Digital Novice": 48}, // index 1
|
||||||
@@ -290,7 +298,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if(xp == 800 || xp > 800) {
|
||||||
|
console.log('You are a coding master!');
|
||||||
// Display data for max level
|
// Display data for max level
|
||||||
document.getElementById('percent').innerHTML = '800|800';
|
document.getElementById('percent').innerHTML = '800|800';
|
||||||
currRank = "Master Digital Crafter";
|
currRank = "Master Digital Crafter";
|
||||||
@@ -306,17 +315,19 @@
|
|||||||
document.getElementById('XP-Till').innerHTML = remain + 'XP till your next Rank: ' + rankUp;
|
document.getElementById('XP-Till').innerHTML = remain + 'XP till your next Rank: ' + rankUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re calculate recaculates all the data from oldXP + addxp to newxp
|
// reCalculate function recaculates all the data with oldXP + addxp to newxp
|
||||||
function reCalculate(addXP) {
|
function reCalculate(addXP) {
|
||||||
let newXP = xp + parseInt(addXP);
|
let newXP = xp + parseInt(addXP);
|
||||||
console.log(newXP);
|
|
||||||
// Get current rank
|
// Get current rank
|
||||||
if (newXP < 800) {
|
if (newXP < 800) {
|
||||||
for(var i = 0; i < ranks.length; i++) {
|
for(var i = 0; i < ranks.length; i++) {
|
||||||
for (let rank in ranks[i]) {
|
for (let rank in ranks[i]) {
|
||||||
let nextIndex = indexes[i];
|
let nextIndex = indexes[i];
|
||||||
|
// Gets rank after current rank
|
||||||
for (let nextRank in ranks[nextIndex]) {
|
for (let nextRank in ranks[nextIndex]) {
|
||||||
|
// Verifies current XP is > currentRank xp level && current XP < nextRank xp level
|
||||||
if (newXP >= ranks[i][rank] && newXP < ranks[nextIndex][nextRank]) {
|
if (newXP >= ranks[i][rank] && newXP < ranks[nextIndex][nextRank]) {
|
||||||
|
// Sets new temporary variables
|
||||||
let newCurrRank = rank;
|
let newCurrRank = rank;
|
||||||
let newCurrRankXP = ranks[i][rank]
|
let newCurrRankXP = ranks[i][rank]
|
||||||
// Calculate xp till next Rank
|
// Calculate xp till next Rank
|
||||||
@@ -324,6 +335,7 @@
|
|||||||
i++;
|
i++;
|
||||||
let newNextRank = ranks[i];
|
let newNextRank = ranks[i];
|
||||||
for (let r in newNextRank) {
|
for (let r in newNextRank) {
|
||||||
|
// Initialize new temporary variables
|
||||||
let newRankUp = r;
|
let newRankUp = r;
|
||||||
let newPercent;
|
let newPercent;
|
||||||
let diff = addXP;
|
let diff = addXP;
|
||||||
@@ -337,6 +349,7 @@
|
|||||||
let diffPercent=(diff/total)*100;
|
let diffPercent=(diff/total)*100;
|
||||||
newRemain = remain - diff;
|
newRemain = remain - diff;
|
||||||
newTotal = total;
|
newTotal = total;
|
||||||
|
// Update Progress Bar
|
||||||
let elem = document.getElementById("myBar");
|
let elem = document.getElementById("myBar");
|
||||||
newPercent = percent + diffPercent;
|
newPercent = percent + diffPercent;
|
||||||
elem.style.height = newPercent + "%";
|
elem.style.height = newPercent + "%";
|
||||||
@@ -356,7 +369,7 @@
|
|||||||
let elem = document.getElementById("myBar");
|
let elem = document.getElementById("myBar");
|
||||||
newPercent = Math.round((newProgress/newTotal)*100);
|
newPercent = Math.round((newProgress/newTotal)*100);
|
||||||
elem.style.height = newPercent + "%";
|
elem.style.height = newPercent + "%";
|
||||||
// Adds 1 to progress till progress == total
|
// Sets progress to new Progress
|
||||||
let progressDiff = total-progress;
|
let progressDiff = total-progress;
|
||||||
document.getElementById('percent').innerHTML = newProgress + "|" + newTotal;
|
document.getElementById('percent').innerHTML = newProgress + "|" + newTotal;
|
||||||
// Update Display with new Data
|
// Update Display with new Data
|
||||||
@@ -381,6 +394,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.log('You are a coding master!')
|
||||||
// Display data for max level
|
// Display data for max level
|
||||||
document.getElementById('percent').innerHTML = '800|800';
|
document.getElementById('percent').innerHTML = '800|800';
|
||||||
currRank = "Master Digital Crafter";
|
currRank = "Master Digital Crafter";
|
||||||
@@ -396,10 +410,4 @@
|
|||||||
document.getElementById('XP-Till').innerHTML = remain + 'XP till your next Rank: ' + rankUp;
|
document.getElementById('XP-Till').innerHTML = remain + 'XP till your next Rank: ' + rankUp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function redirect(id) {
|
|
||||||
let url = '/users/quests?id=' + encodeURIComponent(id);
|
|
||||||
|
|
||||||
document.location.href = url;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
@@ -380,6 +380,33 @@
|
|||||||
</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">
|
<div class="members-container">
|
||||||
<!-- List of all site students (not teachers) -->
|
<!-- List of all site students (not teachers) -->
|
||||||
<h2>Studen Members</h2>
|
<h2>Studen Members</h2>
|
||||||
@@ -462,11 +489,13 @@
|
|||||||
<!-- List of Courses -->
|
<!-- List of Courses -->
|
||||||
<div class='course-content'>
|
<div class='course-content'>
|
||||||
<h2>All Courses</h2>
|
<h2>All Courses</h2>
|
||||||
|
<ul>
|
||||||
<% courses.forEach(function (course) { %>
|
<% courses.forEach(function (course) { %>
|
||||||
<div class='course'>
|
<div class='course'>
|
||||||
<p><%= course.name %>: Grade <%= course.grade %></p>
|
<li><button class="btn btn-outline-success mt-2" onclick="showDetails('<%= course._id %>')"><%= course.name %>: <%= course.grade %></button></li>
|
||||||
</div>
|
</div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -474,6 +503,17 @@
|
|||||||
<script>
|
<script>
|
||||||
let socket = io.connect('http://localhost:5000');
|
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
|
// Creates unique ID
|
||||||
function makeid(length) {
|
function makeid(length) {
|
||||||
var result = '';
|
var result = '';
|
||||||
|
|||||||
Reference in new issue
Block a user