1067 lines
41 KiB
JavaScript
Raw Normal View History

2016-09-04 20:10:58 -04:00
/* jshint esversion: 6 */
2016-08-12 12:28:55 -04:00
import {
Template
} from 'meteor/templating';
2016-08-09 01:33:14 -04:00
import './main.html';
var load = true;
2016-09-02 00:15:29 -04:00
var calWorkOpen = null;
var calWorkDate = null;
var defaultWork = {
name: "Name | Click here to edit...",
dueDate: "Click here to edit...",
description: "Click here to edit...",
type: "Click here to edit..."
2016-09-14 06:37:32 -04:00
};
2016-08-20 23:37:04 -04:00
// Reactive variables.
2016-10-03 23:13:05 -04:00
Session.set("user", {}); // Stores user preferences.
Session.set("calendarEvents", []); // Stores calendar classes.
Session.set("myClasses", []); // Stores user classes.
2016-10-03 23:13:05 -04:00
Session.set("requests", false); // Status of requests.
Session.set("sidebarMode", ""); // Status of sidebars.
2016-09-04 20:13:31 -04:00
Session.set("newWork", null); // If user creating new work.
2016-10-23 22:11:27 -04:00
Session.set("currentWork",null); // Current stored work.
2016-09-04 20:13:31 -04:00
Session.set("classDisp", []); // Stores current filter for classes.
2016-09-15 08:30:24 -04:00
Session.set("typeFilter", []); // Stores type filters for classes.
2016-10-03 23:13:05 -04:00
Session.set("typeFilterHover", null); // Stores current hovered type filter.
2016-09-15 10:25:10 -04:00
Session.set("classDispHover", null); // Stores current hovered class filter.
2016-10-16 02:15:47 -04:00
Session.set("restrictText", {}); // Stores text for comment character restriction.
2016-11-08 20:19:22 -05:00
Session.set("confirmText", ""); // Stores text for confirmations.
2016-08-09 01:33:14 -04:00
// On render actions
2016-09-16 16:48:39 -04:00
2016-09-09 02:17:32 -04:00
Template.login.rendered = function() {
Accounts._loginButtonsSession.set('dropdownVisible', true);
};
2016-11-02 19:18:36 -04:00
Template.main.created = function() {
Session.set("mode", Session.get("user").preferences.mode);
2016-11-07 21:22:51 -05:00
Session.set("classInfo", null);
2017-02-09 10:26:22 -05:00
/*if (Notification.permission !== "granted") {
Notification.requestPermission().then(function(result) {
});
}*/
2016-11-02 19:18:36 -04:00
}
2016-09-09 02:17:32 -04:00
Template.main.rendered = function() {
Accounts._loginButtonsSession.set('dropdownVisible', true);
2016-09-16 18:08:56 -04:00
setTimeout(startDragula, 300);
2016-10-23 22:11:27 -04:00
$("#menuContainer").toggle();
2017-02-03 03:43:21 -05:00
$("#doneUsers").slimScroll({
height: '34vh',
touchScrollStep: 90
});
2016-11-02 19:18:36 -04:00
document.getElementsByTagName("body")[0].style.color = Session.get("user").preferences.theme.textColor;
2016-09-09 02:17:32 -04:00
};
Template.classesMode.rendered = function() {
$(".workHolder").slimScroll({
width: '100%',
height: '',
touchScrollStep: 90
});
2017-02-09 10:34:59 -05:00
$(".mainClass .slimScrollBar").css("display", "none");
2017-03-01 12:14:46 -05:00
};
// Global Helpers
Template.registerHelper('adminPage', () => {
return window.location.pathname.includes("/");
});
2016-09-12 11:12:06 -04:00
Template.registerHelper('screen', (multiplier, fraction) => {
2016-10-03 23:13:05 -04:00
if (typeof multiplier !== "string") return screen.width.toString() + "px";
if (typeof fraction !== "string") return (screen.width * parseFloat(multiplier)).toString() + "px";
return ((screen.width) * parseFloat(multiplier) / parseFloat(fraction)).toString() + "px";
2016-09-12 11:12:06 -04:00
});
2016-08-29 21:02:02 -04:00
Template.registerHelper('divColor', (div) => { // Reactive color changing based on preferences. Colors stored in themeColors.
if(Session.get("user") === null) return;
2017-01-15 23:59:10 -05:00
return (Object.keys(Session.get("user")).length === 0) ? themeColors["lux"][div] : Session.get("user").preferences.theme[div];
2016-08-22 23:44:48 -04:00
});
2016-08-28 23:25:43 -04:00
Template.registerHelper('overlayDim', (part) => { // Gets size of the overlay container.
var dim = [window.innerWidth * 0.25, window.innerHeight * 0.2];
2016-08-12 12:28:55 -04:00
var width = "width:" + dim[0].toString() + "px;";
var height = "height:" + dim[1].toString() + "px;";
var margin = "margin-left:" + (-dim[0] / 2).toString() + "px;";
2016-09-29 23:39:34 -04:00
var bg = "background-color:" + Session.get("user").preferences.theme.header + ";";
2016-08-12 12:28:55 -04:00
return width + height + margin + bg;
});
2016-08-30 18:49:33 -04:00
Template.registerHelper('myClasses', () => { // Gets all classes and respective works.
2016-10-03 23:13:05 -04:00
if (Session.get("user").classes.length === 0) { // Null checking.
2016-08-18 23:59:38 -04:00
return [];
2016-08-14 07:52:27 -04:00
} else {
var array = myClasses();
Session.set("myClasses", array);
calendarEvents(array);
$("#fullcalendar").fullCalendar("removeEvents");
$("#fullcalendar").fullCalendar("addEventSource", Session.get("calendarEvents"))
2016-08-18 23:59:38 -04:00
return array;
}
2016-08-14 07:52:27 -04:00
});
2016-08-30 18:49:33 -04:00
Template.registerHelper('pref', (val) => { // Obtains all user preferences.
2017-04-08 00:07:00 -04:00
try {
var preferences = Session.get("user").preferences;
return options[val].filter(function(entry) {
return (val === 'theme') ? _.isEqual(preferences[val], themeColors[entry.val]) : preferences[val] === entry.val;
})[0].alias;
} catch(err) {}
2016-08-28 14:36:26 -04:00
});
2016-10-16 02:15:47 -04:00
Template.registerHelper('restrict', (input) => { // Returns characters left for comment length.
var restrict = Session.get("restrictText");
$(".resText").removeClass("noneLeft");
if(Object.keys(restrict).length === 0) return "";
if(restrict[restrict.selected][0] === "0") $(".resText").addClass("noneLeft");
return (restrict.selected === input) ? Session.get("restrictText")[input] : "";
2016-09-07 21:26:26 -04:00
});
2016-09-05 14:51:40 -04:00
2016-10-16 02:15:47 -04:00
Template.registerHelper('selectOptions', (val) => {
2016-10-16 19:55:19 -04:00
if(val === "grade") {
var grade = [];
for(var i = 0; i < 5; i++) {
2016-10-28 23:59:02 -04:00
var year = (new Date()).getFullYear() + i;
2016-10-16 19:55:19 -04:00
grade.push( { "val": year, "alias": year.toString() } );
}
grade.push( { "val": 0, "alias": "Faculty" } );
2016-10-16 19:55:19 -04:00
return grade;
} else if(val === "school") {
var school = [];
var schoolList = schools.find().fetch();
for(var i = 0; i < schoolList.length; i++) {
school.push( { "val": schoolList[i].name, "alias": schoolList[i].name } );
}
return school;
} else {
return options[val];
}
2016-10-16 02:15:47 -04:00
});
2016-10-16 02:15:47 -04:00
Template.registerHelper('work', (value) => {// Returns the specified work value.
var thisWork = Session.get("currentWork");
if (Session.equals("currentWork", null)) return;
if (Session.get("newWork") && (thisWork[value] === true || thisWork[value] === undefined)) {
2016-10-19 01:24:14 -04:00
return defaultWork[value];
2016-10-16 02:15:47 -04:00
} else {
return formReadable(thisWork,value);
}
2016-10-16 19:55:19 -04:00
});
2016-11-08 20:19:22 -05:00
Template.registerHelper('confirmText', () => {
return Session.get("confirmText");
})
// Main template helpers and events
2016-08-09 01:33:14 -04:00
Template.main.helpers({
2016-10-16 02:15:47 -04:00
/*themeName() {
2016-10-19 21:20:49 -04:00
var vals = _.values(themeColors);
var curtheme = Session.get("user").preferences.theme;
for (var i = 0; i < vals.length; i++) {
if (_.isEqual(vals[i], curtheme)) {
var name = _.keys(themeColors)[i];
return name.charAt(0).toUpperCase() + name.slice(1);
2016-10-28 23:59:02 -04:00
}
2016-10-19 21:20:49 -04:00
}
return "Custom";
},*/
2016-08-30 18:49:33 -04:00
schoolName() { // Finds the name of the user's school.
2016-10-03 23:13:05 -04:00
if (Session.get("user").school === undefined || Session.get("user").school === null) return;
return " - " + Session.get("user").school;
2016-08-12 12:28:55 -04:00
},
2016-09-07 15:33:13 -04:00
avatar() { // Returns avatar.
2016-09-17 21:35:12 -04:00
return Meteor.user().services.google.picture;
2016-09-07 15:33:13 -04:00
},
username() { // Returns user name.
return Session.get("user").name;
},
bgSrc() { // Returns background.
return "MDBackgrounds/" + "MD"+Session.get("user").preferences.theme.background;
2016-08-12 12:28:55 -04:00
},
2016-10-23 22:11:27 -04:00
iconStatus(icon) {
var sidebar = Session.get("sidebarMode");
return (sidebar === icon) ? Session.get("user").preferences.theme.iconHighlight + ";background-color:rgba(0,0,0,0.2)" : "";
},
sidebarStatus(sidebar) {
return sidebar === Session.get("sidebarMode");
2016-08-12 12:28:55 -04:00
},
2016-09-11 23:22:50 -04:00
requestStatus() {
if (Session.get("requests")) return "0px";
return openValues.requests;
},
2016-11-03 23:12:57 -04:00
currMode(mode) { // Status of display mode.
return Session.equals("mode", mode);
},
currSettingMode(mode) {
return Session.equals("settingMode", mode) && Session.equals("sidebarMode", "option");
2016-08-12 12:28:55 -04:00
},
2016-08-30 18:49:33 -04:00
calendarOptions() { // Settings for the calendar, including work displaying.
2016-08-12 12:28:55 -04:00
return {
2016-08-18 23:59:38 -04:00
id: "fullcalendar",
2016-08-15 20:55:21 -04:00
height: window.innerHeight * 0.8,
2016-08-12 12:28:55 -04:00
buttonText: {
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day'
},
2016-09-02 00:15:29 -04:00
eventLimit: 3,
events: Session.get("calendarEvents"),
2016-08-30 18:49:33 -04:00
eventDrop: function(event, delta, revertFunc) { // When user drops from click-dragging.
2016-09-04 20:13:31 -04:00
var current = work.findOne({
_id: event.id
});
var date = event.start.format().split("-");
2016-09-04 20:13:31 -04:00
current.dueDate = new Date(date[0], parseInt(date[1]) - 1, date[2], 11, 59, 59);
2016-10-28 23:59:02 -04:00
if(Date.parse(new Date()) > Date.parse(current.dueDate)) {
2016-10-23 22:11:27 -04:00
revertFunc();
return;
2016-10-28 23:59:02 -04:00
}
2016-08-29 21:02:02 -04:00
serverData = current;
sendData("editWork");
2016-08-18 23:59:38 -04:00
},
2016-08-30 18:49:33 -04:00
eventClick: function(event, jsEvent, view) { // On-click for work.
2016-09-04 20:13:31 -04:00
Session.set("newWork", false);
2016-10-16 02:15:47 -04:00
Session.set("currentWork", work.findOne({_id: event.id}));
$(".overlay").fadeIn(150);
2017-02-09 09:01:18 -05:00
$("#comment").slimScroll({
width: '100%',
height: '20vh',
touchScrollStep: 90
});
},
2016-10-03 23:13:05 -04:00
eventMouseover: function(event, jsEvent, view) {
2016-09-11 18:47:50 -04:00
this.style.boxShadow = "inset 0 0 0 99999px rgba(255,255,255,0.2)";
},
2016-10-03 23:13:05 -04:00
eventMouseout: function(event, jsEvent, view) {
this.style.boxShadow = "";
},
2016-08-30 18:49:33 -04:00
dayClick: function(date, jsEvent, view) { // On-click for each day.
if (jsEvent.target.className.includes("fc-past")) return;
var realDate = date.format();
realDate = new Date(realDate[0], parseInt(realDate[1]) - 1, realDate[2], 11, 59, 59);
2016-09-01 00:23:22 -04:00
Session.set("newWork", true);
Session.set("currentWork", {dueDate: realDate});
if(!Session.equals("sidebarMode", "create")) toggleToSidebar("create");
2016-08-19 22:04:32 -04:00
}
2016-08-12 12:28:55 -04:00
};
},
calCenter() { // Centers the calendar
2016-08-12 12:28:55 -04:00
var width = window.innerWidth * 0.85;
2016-08-23 00:11:57 -04:00
return "width:" + width.toString() + "px;margin-left:" + (0.5 * window.innerWidth - 0.5 * width).toString() + "px;";
},
2016-08-30 18:49:33 -04:00
highlight() { // Calendar highlight/scale option.
var hoverHighlight = Session.get("classDispHover");
2016-09-15 10:25:10 -04:00
var typeHighlight = Session.get("typeFilterHover");
2016-10-03 23:13:05 -04:00
if (Session.equals("mode", "classes")) {
$(".workCard").toggleClass("scaled", false);
2016-09-11 18:47:50 -04:00
try {
2016-10-03 23:13:05 -04:00
$(".workCard[classid=\'" + hoverHighlight + "\']").toggleClass("scaled", true);
$(".workCard[type=\'" + typeHighlight + "\']").toggleClass("scaled", true);
} catch (err) {}
2016-09-11 18:47:50 -04:00
} else {
2016-10-03 23:13:05 -04:00
$(".workevent").toggleClass("scaled", false);
2016-09-10 02:26:11 -04:00
try {
2016-10-03 23:13:05 -04:00
$("." + hoverHighlight).toggleClass("scaled", true);
$("." + typeHighlight).toggleClass("scaled", true);
} catch (err) {}
}
return;
},
2016-08-30 18:49:33 -04:00
newWork() { // If user is creating a new work.
2016-08-18 23:59:38 -04:00
return Session.get("newWork");
},
2016-08-30 18:49:33 -04:00
inRole() { // Checks correct permissions.
2016-10-16 02:15:47 -04:00
if(Session.equals("currentWork",null)) return;
2017-02-26 19:27:50 -05:00
try {
var thisWork = work.findOne({
_id: Session.get("currentWork")._id
2016-09-04 20:13:31 -04:00
});
2017-02-26 19:27:50 -05:00
if (Session.get("newWork")) {
return true;
} else {
if (thisWork === undefined) return;
var currClass = classes.findOne({
_id: thisWork["class"]
});
if (Meteor.userId() === thisWork.creator ||
Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin']) ||
currClass.moderators.indexOf(Meteor.userId()) !== -1 ||
currClass.banned.indexOf(Meteor.userId()) !== -1
) return true;
}
} catch(err) {}
2016-09-02 00:15:29 -04:00
},
2016-09-07 15:33:13 -04:00
admin() {
return Roles.userIsInRole(Meteor.userId(), ['admin', 'superadmin']);
2016-09-04 20:13:31 -04:00
}
2016-08-09 01:33:14 -04:00
});
Template.main.events({
2016-08-30 18:49:33 -04:00
'click' (event) { // Closes respective divs when clicking outside of them. Order matters.
2016-08-12 12:28:55 -04:00
var e = event.target.className;
2016-10-12 01:45:36 -04:00
if(modifyingInput !== null && event.target !== document.getElementById(modifyingInput)) {
if (!(e.includes("optionHolder") || e.includes("optionText"))) {
2016-10-12 01:45:36 -04:00
if(document.getElementById(modifyingInput).className.includes("dropdown")) {
toggleOptionMenu(false, modifyingInput);
2016-10-28 23:59:02 -04:00
} else {
2016-10-12 01:45:36 -04:00
closeInput(modifyingInput);
}
modifyingInput = null;
}
}
2016-08-28 18:41:35 -04:00
2016-10-23 22:11:27 -04:00
if (!e.includes("fa-cog") && // Sidebar closing.
2016-11-03 23:12:57 -04:00
!e.includes("fa-bars") &&
!e.includes("fa-question") &&
!document.getElementById("menuContainer").contains(event.target) &&
!document.getElementById("menuBar").contains(event.target)) {
if(!(e.includes("fc-day") && !e.includes("fc-past")) &&
!Session.equals("sidebarMode", "option")) {
toggleToSidebar(false);
}
2016-08-12 12:28:55 -04:00
}
2016-09-04 20:13:31 -04:00
if (e === "overlay") { // Overlay closing.
$(".overlay").fadeOut(150);
2016-09-04 20:13:31 -04:00
if (!Session.get("newWork")) {
document.getElementById("workComment").value = "";
2017-02-09 10:26:22 -05:00
var res = Session.get("restrictText");
res[Object.keys(res)[0]] = "";
Session.set("restrictText", res);
}
2016-08-12 23:10:27 -04:00
}
2016-11-08 20:19:22 -05:00
if (!document.getElementById("userDropdown").contains(event.target)) $("#userDropdown").fadeOut(250);
2016-08-12 23:10:27 -04:00
},
2016-08-30 18:49:33 -04:00
// MAIN MENU BUTTONS
2016-10-23 22:11:27 -04:00
'click .fa-bars' (event) { // Click menu button.
toggleToSidebar("menu");
2016-08-30 18:49:33 -04:00
},
2016-10-23 22:11:27 -04:00
'click .fa-cog' (event) { // Click settings button.
toggleToSidebar("option");
},
2016-11-01 23:07:09 -04:00
'click .fa-question' (event) { // Click requests button.
toggleToSidebar("requests");
2016-10-23 22:11:27 -04:00
},
2016-08-30 18:49:33 -04:00
'click .creWork' (event) { // Cick add work button.
2016-09-04 20:10:58 -04:00
var attr;
2016-09-04 20:13:31 -04:00
if (event.target.className !== "creWork") {
2016-09-04 20:10:58 -04:00
attr = event.target.parentNode.getAttribute("classid");
} else {
2016-09-04 20:10:58 -04:00
attr = event.target.getAttribute("classid");
}
2016-08-12 23:10:27 -04:00
Session.set("newWork", true);
2016-10-19 01:24:14 -04:00
Session.set("currentWork",{class: attr, dueDate: (new Date((new Date()).valueOf() + 1000*3600*24))});
$(".overlay").fadeIn(150);
2017-02-09 09:01:18 -05:00
$("#comment").slimScroll({
width: '100%',
height: '20vh',
touchScrollStep: 90
});
2017-02-09 10:32:27 -05:00
$("#workComments .slimScrollBar").css("display", "none");
2016-11-08 20:19:22 -05:00
},
'click .fa-check-circle-o' () { // Confirmation Button
sendData(confirm);
$("#confirmOverlay").fadeOut(250);
if(confirm === "changeAdmin") {
$("#changeAdminWrapper").fadeOut(250);
} else if(confirm === "deleteClass") {
Session.set("classInfo", null);
}
serverData = null;
confirm = null;
},
'click .fa-times-circle-o' () { // Deny Button
$("#confirmOverlay").fadeOut(250);
serverData = null;
confirm = null;
2016-09-04 20:10:58 -04:00
},
2016-09-07 15:33:13 -04:00
'click #dropdown' (event) {
2016-10-03 23:13:05 -04:00
if (document.getElementById("userDropdown").style.display === "block") return;
2016-11-08 20:19:22 -05:00
$("#userDropdown").fadeIn(250);
2016-09-07 15:33:13 -04:00
},
2016-08-30 18:49:33 -04:00
'click .workCard' (event) { // Display work information on work card click.
2016-10-09 22:57:04 -04:00
var workid = event.target.getAttribute("workid");
2016-09-04 20:13:31 -04:00
var thisWork = work.findOne({
_id: workid
});
2016-10-09 22:57:04 -04:00
Session.set("newWork", false);
Session.set("currentWork", thisWork);
2016-10-23 22:11:27 -04:00
if (!Session.get("newWork")) {
2016-09-04 20:13:31 -04:00
var currClass = classes.findOne({
_id: thisWork["class"]
2016-09-04 20:13:31 -04:00
});
if (!(Meteor.userId() === thisWork.creator || // If user has permission.
2016-10-19 21:20:49 -04:00
Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin']) ||
currClass.moderators.indexOf(Meteor.userId()) !== -1 ||
currClass.banned.indexOf(Meteor.userId()) !== -1)) {
2016-10-09 22:57:04 -04:00
var inputs = $('#editWork .clickModify').css("cursor", "default");
2016-09-04 20:10:58 -04:00
}
2016-08-30 18:49:33 -04:00
}
$(".overlay").fadeIn(150);
2017-02-09 09:01:18 -05:00
$("#comment").slimScroll({
width: '100%',
height: '20vh',
touchScrollStep: 90
});
2017-02-09 10:32:27 -05:00
$("#workComments .slimScrollBar").css("display", "none");
2016-08-12 23:10:27 -04:00
},
2016-09-08 16:51:22 -04:00
'click #requestSubmit' () {
var area = document.getElementById("requestArea");
2016-10-03 23:13:05 -04:00
if (area.value === "") return;
2016-09-08 16:51:22 -04:00
var array = {};
array.content = area.value;
array.info = {
2016-09-09 08:20:51 -04:00
"users": Meteor.users.find().fetch(),
2016-09-08 16:51:22 -04:00
"userInfo": Meteor.user(),
"userClasses": Session.get("myClasses")
2016-09-08 16:51:22 -04:00
};
2016-10-03 23:13:05 -04:00
Meteor.call("createRequest", array, function(err, result) {
area.value = "";
Session.set("restrictText", {});
$("#requestSubmit span:first-child").fadeOut(200, function() {
$("#requestSubmit span:nth-child(2)").fadeIn(200);
})
2016-10-03 23:13:05 -04:00
setTimeout(function() {
$("#requestSubmit span:nth-child(2)").fadeOut(200, function() {
$("#requestSubmit span:first-child").fadeIn(200);
})
}, 1250);
2016-09-11 18:47:50 -04:00
});
2016-09-08 16:51:22 -04:00
},
'click #exportDiv' (event) {
2016-10-23 17:50:05 -04:00
var events = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//hacksw/handcal//NONSGML v1.0//EN";
var userClasses = Session.get("myClasses");
2016-10-23 17:50:05 -04:00
var timestamp = new Date().toJSON().replace(/-|:|\./gi, "");
for (var i = 0; i < userClasses.length; i++) {
var works = userClasses[i].thisClassWork;
for (var j = 0; j < works.length; j++) {
var work = works[j];
var workclass = classes.findOne({
_id: work.class
});
if (work.description == defaultWork.description) work.description = "";
if (work.dueDate == defaultWork.dueDate) continue;
if (work.name == defaultWork.name) work.name = "";
if (workclass === undefined) workclass = {
name: "Personal"
};
2016-10-23 17:50:05 -04:00
if (work.description === undefined) {
work.description = "";
} else {
work.description = " - " + work.description;
}
var duedate = work.realDate.toJSON().slice(0,10).replace(/-/gi,"");
events += "\nBEGIN:VEVENT" +
"\nUID:" + timestamp + work._id + "@hourglass.tk" +
"\nDTSTAMP:" + timestamp +
"\nDTSTART:" + duedate +
"\nDTEND:" + duedate +
"\nSUMMARY:" + work.name + work.description +
"\nCATEGORIES:" + workclass.name +
"\nEND:VEVENT";
}
2016-10-23 17:50:05 -04:00
events += "\nEND:VCALENDAR";
}
2016-10-23 17:50:05 -04:00
var eventBlob = new Blob([events], {
type: "data:text/ics;charset=utf-8"
});
2016-10-23 17:50:05 -04:00
saveAs(eventBlob, "hourglass.ics");
2016-10-12 01:45:36 -04:00
},
// HANDLING INPUT CHANGING
2016-10-12 01:45:36 -04:00
'focus .clickModify' (event) {
2017-02-09 10:26:22 -05:00
toggleOptionMenu(false, modifyingInput);
if(modifyingInput !== null) {
if(!$("#"+modifyingInput)[0].className.includes("dropdown")) closeInput(modifyingInput);
2016-10-28 23:59:02 -04:00
}
modifyingInput = event.target.id;
if(!$("#"+modifyingInput)[0].className.includes("dropdown")) {
event.target.select();
2016-10-28 23:59:02 -04:00
event.target.style.cursor = "text";
2017-02-03 03:43:21 -05:00
event.target.style.backgroundColor = "rgba(0,0,0,0.1)";
}
2016-08-12 23:10:27 -04:00
},
2017-02-09 10:26:22 -05:00
'keydown #wName' (event) {
if(event.keyCode === 13) {
closeInput(modifyingInput);
event.target.blur();
}
},
'focus #workComment' () {
toggleOptionMenu(false, modifyingInput);
modifyingInput = null;
},
2016-10-09 22:57:04 -04:00
'keydown .dropdown' (event) {
var first = $("#"+modifyingInput).next().children("p:first-child");
2016-10-28 23:59:02 -04:00
var last = $("#"+modifyingInput).next().children("p:last-child");
var next = $(".selectedOption").next();
var prev = $(".selectedOption").prev();
var lastSel = $(".selectedOption");
if (event.keyCode === 38) {
2016-10-18 16:27:42 -04:00
event.preventDefault();
if (lastSel === undefined) {
last.addClass("selectedOption");
} else {
if (prev.length === 0) {
last.addClass("selectedOption");
2016-10-28 23:59:02 -04:00
lastSel.removeClass("selectedOption");
} else {
prev.addClass("selectedOption");
lastSel.removeClass("selectedOption");
}
}
} else if (event.keyCode === 40) {
2016-10-18 16:27:42 -04:00
event.preventDefault();
if (lastSel === undefined) {
first.addClass("selectedOption");
last.removeClass("selectedOption");
} else {
if (next.length === 0) {
first.addClass("selectedOption");
lastSel.removeClass("selectedOption");
} else {
next.addClass("selectedOption");
lastSel.removeClass("selectedOption");
}
2016-10-28 23:59:02 -04:00
}
} else if (event.keyCode === 13) {
lastSel[0].click();
$("#"+modifyingInput)[0].focus();
}
2016-10-09 22:57:04 -04:00
},
'click .dropdown, focus .dropdown' (event) {
if(clickDisabled) return;
clickDisabled = true;
if(event.target.id === optionOpen[0] && optionOpen[1]) {
toggleOptionMenu(false, event.target.id);
} else {
toggleOptionMenu(true, event.target.id);
}
setTimeout(function(){clickDisabled = false;},130); // Prevents spamming and handles extra click events.
2016-10-09 22:57:04 -04:00
},
'click .optionText' (event) { // Click each preferences setting.
var option = event.target.childNodes[0].nodeValue;
if(modifyingInput[0] === 'w') {
var newSetting = Session.get("currentWork");
newSetting[modifyingInput.charAt(1).toLowerCase() + modifyingInput.slice(2)] = option.toLowerCase();
2016-10-09 22:57:04 -04:00
Session.set("currentWork", newSetting);
2016-10-16 02:15:47 -04:00
serverData = Session.get("currentWork");
2016-10-19 01:24:14 -04:00
toggleOptionMenu(false, modifyingInput);
2016-10-19 01:24:14 -04:00
if(Session.get("newWork")) return;
if(checkMissing()) return;
2016-10-28 23:59:02 -04:00
sendData("editWork");
2016-11-08 20:19:22 -05:00
} else if(modifyingInput.slice(0,3) === "cre") {
document.getElementById(modifyingInput).value = option;
2016-08-22 23:44:48 -04:00
} else {
2016-10-09 22:57:04 -04:00
var newSetting = Session.get("user");
newSetting.preferences[modifyingInput] = (function() {
var value = options[modifyingInput].filter(function(entry) {
return option === entry.alias;
})[0].val;
return (modifyingInput === 'theme') ? themeColors[value] : value;
})();
Session.set("user", newSetting);
serverData = Session.get("user");
2016-10-28 23:47:26 -04:00
sendData("editProfile");
2016-08-22 23:44:48 -04:00
}
2016-10-09 22:57:04 -04:00
toggleOptionMenu(false, modifyingInput);
$(".selectedOption").removeClass("selectedOption");
},
2016-09-05 14:51:40 -04:00
'input .restrict' (event) {
var restrict = event.target.maxLength;
var chars = restrict - event.target.value.length;
2016-10-16 02:15:47 -04:00
var newSetting = Session.get("restrictText");
newSetting[event.target.id] = (chars === restrict) ? "" : (chars.toString() + ((chars === 1) ? " character " : " characters ") + "left");
newSetting.selected = event.target.id;
Session.set("restrictText", newSetting);
2016-09-05 14:51:40 -04:00
},
2016-10-12 01:45:36 -04:00
'focus #wDueDate' () { // Open date picker.
$('#wDueDate').datepicker({
2016-08-30 18:49:33 -04:00
format: 'DD, MM d, yyyy',
2016-10-12 01:45:36 -04:00
clickInput: true,
2016-08-30 18:49:33 -04:00
startDate: 'd',
todayHighlight: true,
todayBtn: true,
autoclose: true
2016-08-30 18:49:33 -04:00
});
},
// WORK OVERLAY BUTTONS
'click #commentSubmit' (event) { // Click to submit a comment.
2016-10-16 02:15:47 -04:00
workId = Session.get("currentWork")._id;
var input = document.getElementById('workComment');
comment = input.value;
input.value = "";
2016-08-22 16:52:04 -04:00
if (comment !== "") {
document.getElementById('workComment').value = "";
2016-10-16 02:15:47 -04:00
serverData = [comment, workId];
sendData("addComment");
2016-08-22 16:52:04 -04:00
}
},
2016-08-30 18:49:33 -04:00
'click #workSubmit' () { // Click submit work to create a work.
2016-10-12 01:45:36 -04:00
serverData = Session.get("currentWork");
if(checkMissing()) return;
sendData("createWork");
$(".overlay").fadeOut(150);
},
'click #workDelete' () {
2016-10-16 02:15:47 -04:00
serverData = Session.get("currentWork")._id;
sendData("deleteWork");
$(".overlay").fadeOut(150);
},
2016-08-30 18:49:33 -04:00
'click #markDone' () { // Click done button.
serverData = [Session.get("currentWork")._id, "done"];
2016-08-30 18:49:33 -04:00
sendData("toggleWork");
},
2016-08-30 18:49:33 -04:00
'click #markConfirm' () { // Click confirm button.
serverData = [Session.get("currentWork")._id, "confirmations"];
2016-08-30 18:49:33 -04:00
sendData("toggleWork");
},
'click #markReport' () { // Click report button.
serverData = [Session.get("currentWork")._id, "reports"];
2016-08-30 18:49:33 -04:00
sendData("toggleWork");
}
2016-08-09 01:33:14 -04:00
});
2016-10-16 02:15:47 -04:00
// Other Functions
2017-01-15 23:59:10 -05:00
toggleOptionMenu = function(toggle, menu) {
if(toggle) {
$(".selectedOption").removeClass("selectedOption");
$("#" + menu).next()
.css('opacity', 0)
.slideDown(300)
.animate(
{ opacity: 1 },
{ queue: false, duration: 100 }
);
optionOpen = [menu, toggle];
2016-10-23 22:11:27 -04:00
} else {
$("#" + menu).next().slideUp(100, function() {
$(this).css("opacity", 0);
});
optionOpen = [null, toggle];
2016-10-23 22:11:27 -04:00
}
}
sendData = function(funcName) { // Call Meteor function, and do actions after function is completed depending on function.
2016-10-19 01:24:14 -04:00
if(funcName === "editWork" || funcName === "createWork") {
for(var key in serverData) {
if(serverData[key] === true) serverData[key] = "";
}
}
Meteor.call(funcName, serverData, function(error, result) {
serverData = null;
currWork = Session.get("currentWork");
2016-11-08 20:19:22 -05:00
if(currWork !== null && currWork._id !== undefined) {
Session.set("currentWork", work.findOne({
_id: currWork._id
}));
2016-10-21 03:03:11 -04:00
} else {
Session.set("currentWork",null);
}
2016-10-28 23:47:26 -04:00
if (error !== undefined) {
sAlert.error(error.error[1] || error.message, {
effect: 'stackslide',
position: 'top'
});
2016-10-28 23:59:02 -04:00
} else {
/*sAlert.success("Success!", {
2016-10-28 23:59:02 -04:00
effect: 'stackslide',
position: 'bottom-right',
timeout: 2500
});*/
2016-11-08 20:19:22 -05:00
if(funcName === "createClass") {
var inputs = document.getElementsByClassName("creInput");
for(var i = 0; i < inputs.length; i++) {
inputs[i].value = "";
}
toggleToMode("manageClass");
}
2016-10-28 23:47:26 -04:00
}
calendarEvents(myClasses());
$("#fullcalendar").fullCalendar("removeEvents");
$("#fullcalendar").fullCalendar("addEventSource", Session.get("calendarEvents"));
2016-11-03 23:12:57 -04:00
document.getElementsByTagName("body")[0].style.color = Session.get("user").preferences.theme.textColor;
});
2016-08-12 12:28:55 -04:00
}
2016-08-12 23:10:27 -04:00
2016-10-09 22:57:04 -04:00
function closeInput() { // Close a changeable input and change it back to span.
2016-10-28 23:47:26 -04:00
var data = getHomeworkFormData();
2016-10-09 22:57:04 -04:00
Session.set("currentWork", data);
2016-10-16 02:15:47 -04:00
Session.set("restrictText", {});
$("#"+modifyingInput).css('cursor','pointer');
2017-02-03 03:43:21 -05:00
$("#"+modifyingInput).css('background-color', 'rgba(0,0,0,0)');
2016-10-12 01:45:36 -04:00
if(!Session.get("newWork")) {
serverData = Session.get("currentWork");
if(checkMissing()) return;
sendData("editWork");
2016-10-28 23:59:02 -04:00
}
2016-08-12 23:10:27 -04:00
}
2016-08-30 18:49:33 -04:00
function getHomeworkFormData() { // Get all data relating to work creation.
2016-10-12 01:45:36 -04:00
var inputs = ["wName", "wDueDate", "wDescription", "wType"]; // All work fields.
var optional = ["wDescription"]; // Optional work fields.
2016-10-09 22:57:04 -04:00
var data = Session.get("currentWork");
for(var i = 0; i < inputs.length; i++) {
var title = inputs[i].charAt(1).toLowerCase() + inputs[i].slice(2);
var thisData = (function() {
if(title === "type") {
return $("#"+inputs[i]+" span")[0].childNodes[0].nodeValue.toLowerCase();
} else if (title === "dueDate") {
var val = $("#"+inputs[i])[0].value;
2016-10-19 00:15:30 -04:00
return toDate(val);
} else {
return $("#"+inputs[i])[0].value;
}
})();
// True signifies missing field to prevent missing if value is'Missing field.'
2016-10-19 01:24:14 -04:00
data[title] = data[title] = (thisData.toString().includes(defaultWork[title].slice(0,-3)) && !_.contains(optional, title)) ? true : thisData;
2016-10-09 22:57:04 -04:00
}
2016-10-12 01:45:36 -04:00
return data;
2016-08-22 23:44:48 -04:00
}
function checkMissing() {
2016-10-28 23:59:02 -04:00
var required = ["name","dueDate","type"];
var no = false;
2016-10-19 01:24:14 -04:00
if(serverData === null || Object.keys(serverData).length < 4) {
for(var i = 0; i < required.length; i++) {
var id = "w" + required[i].charAt(0).toUpperCase() + required[i].slice(1);
$("#"+id).addClass("formInvalid");
$("#"+id)[0].value = "";
$("#"+id)[0].placeholder = "Missing field";
}
return true;
}
for(var key in serverData) {
2016-10-19 01:24:14 -04:00
if(!_.contains(required, key)) continue;
var id = "w" + key.charAt(0).toUpperCase() + key.slice(1);
2016-10-19 01:24:14 -04:00
if(serverData[key] === true || serverData[key] === "" || serverData[key] === undefined) {
no = true;
$("#"+id).addClass("formInvalid");
$("#"+id)[0].value = "";
$("#"+id)[0].placeholder = "Missing field";
} else {
$("#"+id)[0].placeholder = "";
$("#"+id).removeClass("formInvalid");
}
}
return no;
}
2016-09-04 20:13:31 -04:00
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
2017-04-08 00:07:00 -04:00
getReadableDate = function(date) { // Get readable date from Date constructor.
2016-09-04 20:13:31 -04:00
return days[date.getDay()] + ", " + months[date.getMonth()] + " " + date.getDate() + ", " + date.getFullYear();
2016-08-13 20:22:54 -04:00
}
2017-04-08 00:07:00 -04:00
toDate = function(date) { // Turns formatted date back to Date constructor.
2016-09-04 20:13:31 -04:00
date = date.substring(date.search(",") + 2, date.length);
month = months.indexOf(date.substring(0, date.search(" ")));
day = date.substring(date.search(" ") + 1, date.search(","));
year = date.substring(date.search(",") + 2, date.length);
return new Date(year, month, day, 11, 59, 59);
}
function formReadable(input, val) { // Makes work information readable by users.
2017-02-26 19:27:50 -05:00
try {
switch (val) {
case "typeColor":
return input.typeColor = workColors[input.type];
case "name":
return input.name;
2017-04-08 00:07:00 -04:00
case "class":
var id = input["class"];
return (id === Meteor.userId()) ? "Personal" : classes.findOne({_id: id}).name;
2017-02-26 19:27:50 -05:00
case "dueDate":
return getReadableDate(input.dueDate);
case "description":
return input.description;
case "type":
return input.type[0].toUpperCase() + input.type.slice(1);
case "comments":
var comments = input.comments;
var resort = [];
if (Session.get("newWork")) return []; // Don't display comments if user is creating work.
for (var k = 0; k < comments.length; k++) {
var re = comments.length - k - 1;
resort[re] = {
"comment": comments[k].comment,
"date": null,
"user": null,
"avatar": null,
"email": null
};
var user = Meteor.users.findOne({
_id: comments[k].user
});
resort[re].user = user.profile.name;
resort[re].date = moment(comments[k].date).fromNow();
resort[re].avatar = user.services.google.picture;
resort[re].email = user.services.google.email;
}
return resort;
case "done":
if (Session.get("newWork")) return [];
for (var i = 0; i < input.done.length; i++) { // Display users who marked as done.
var user = Meteor.users.findOne({
_id: input.done[i]
});
input.done[i] = {
"user": user.profile.name,
"avatar": user.services.google.picture,
"email": user.services.google.email
};
}
return input.done;
case "doneCol":
if (Session.get("newWork")) return "";
if (!_.contains(input.done, Meteor.userId())) return "";
return "#27A127";
case "doneText":
if (Session.get("newWork")) return "";
if (!_.contains(input.done, Meteor.userId())) return "Mark done";
return "Done!";
case "doneIcon":
if (Session.get("newWork")) return "";
if (!_.contains(input.done, Meteor.userId())) return "fa-square-o";
return "fa-check-square-o";
case "userConfirm":
2017-04-08 00:07:00 -04:00
if (!_.contains(input.confirmations, Meteor.userId())) return (Session.get("mobileMode")) ? "rgb(101,101,101)" : "";
2017-02-26 19:27:50 -05:00
return "#27A127";
case "confirmations":
return input.confirmations.length;
case "userReport":
2017-04-08 00:07:00 -04:00
if (!_.contains(input.reports, Meteor.userId())) return (Session.get("mobileMode")) ? "rgb(101,101,101)" : "";
2017-02-26 19:27:50 -05:00
return "#FF1A1A";
case "reports":
return input.reports.length;
case "email":
return Meteor.users.findOne({
_id: input.creator
}).services.google.email;
case "avatar":
return Meteor.users.findOne({
_id: input.creator
}).services.google.picture;
case "creator":
return Meteor.users.findOne({
_id: input.creator
}).profile.name;
2016-10-19 21:20:49 -04:00
}
2017-02-26 19:27:50 -05:00
} catch(err){}
2016-08-14 07:52:27 -04:00
}
2016-10-16 02:15:47 -04:00
2017-01-17 00:18:26 -05:00
checkComplete = function(required, inputs) {
var values = {};
var no = [];
for (var i = 0; i < inputs.length; i++) {
var val = inputs[i].value;
var where = inputs[i].getAttribute("form");
if (val === "" && _.contains(required, where)) {
no.push(where);
}
values[where] = val;
}
if (no.length > 0) { // Check missing fields.
return [false,no.reduce(function(a, b) {
return (b === no[no.length - 1]) ? a + ((no.length === 2) ? " and " : ", and ") + b : a + ", " + b;
}), values];
} else {
return [true,"", values];
}
}
startDragula = function() {
2016-10-16 02:15:47 -04:00
dragula([document.querySelector('#classesMode'), document.querySelector('#nonexistant')], {
moves: function(el, container, handle) {
// return handle.classList.contains("classInfo") || handle.classList.contains("mainClassName");
return _.intersection(["classInfo", "mainClassName", "mainClassHour", "mainClassTeacher"], handle.classList).length > 0;
}
})
2016-10-19 21:20:49 -04:00
.on('out', function(el) {
var els = document.getElementsByClassName("classWrapper");
var final = [];
for (var i = 0; i < els.length; i++) {
var classid = els[i].getElementsByClassName("creWork")[0].getAttribute("classid");
final.push(classid);
}
2016-10-22 16:55:22 -04:00
Meteor.call("reorderClasses", final);
2016-10-19 21:20:49 -04:00
});
2016-11-18 20:51:04 -05:00
};
2017-02-22 23:09:31 -05:00
myClasses = function() {
var array = [];
var courses = Session.get("user").classes;
var classDisp = Session.get("classDisp"); // Get sidebar class filter.
var sideFilter = Session.get("typeFilter"); // Get sidebar type filter.
var hide = Session.get("user").preferences.timeHide;
for (var i = 0; i < courses.length; i++) { // For each user class.
if (courses[i] === Meteor.userId()) {
found = {
_id: courses[i],
name: "Personal",
subscribers: 1,
mine: false,
box: " owned"
};
} else {
found = classes.findOne({
_id: courses[i]
});
2017-04-08 00:07:00 -04:00
if(found === undefined) return;
found.subscribers = found.subscribers.length;
found.teachershort = found.teacher.split(" ").slice(1).reduce(function(a,b) { return a+ " " + b;});
found.mine = true;
if (found.admin === Meteor.userId()) { // If user owns this class.
found.box = " owned";
found.mine = false;
}
}
found.selected = ((classDisp.indexOf(courses[i]) !== -1)) ? Session.get("user").preferences.theme.modeHighlight : "rgba(0,0,0,0)"; // Filter selected.
array.push(found);
var thisWork = work.find({
class: courses[i]
}).fetch();
if (classDisp.length !== 0 && classDisp.indexOf(found._id) === -1) { // Filter classes based on filter.
array[i].thisClassWork = [];
continue;
}
for (var j = 0; j < thisWork.length; j++) { // For each work in class.
if (hide !== 0) { // Time to hide isn't never.
var due = (moment(thisWork[j].dueDate))._d;
var offset = (moment().subtract(hide, 'days'))._d;
if (offset > due) { // If due is before hide days before today
thisWork[j] = "no";
}
}
if (thisWork[j] !== "no" && Session.get("user").preferences.done) { // If done filter is true
if (thisWork[j].done.indexOf(Meteor.userId()) !== -1) { // If user marked this work done.
thisWork[j] = "no";
}
}
if (thisWork[j] !== "no" && sideFilter.length !== 0 && !_.contains(sideFilter, thisWork[j].type)) {
thisWork[j] = "no";
}
if (thisWork[j] !== "no" && Session.get("user").preferences.hideReport && (thisWork[j].confirmations.length / thisWork[j].reports.length) <= 0.9) {
thisWork[j] = "no";
}
}
while (thisWork.indexOf("no") !== -1) thisWork.splice(thisWork.indexOf("no"), 1); // Splice all filtered works.
for (j = 0; j < thisWork.length; j++) {
thisWork[j].classid = courses[i];
thisWork[j].realDate = thisWork[j].dueDate;
thisWork[j].dueDate = moment(thisWork[j].dueDate).calendar(null, {
sameDay: '[Today]',
nextDay: '[Tomorrow]',
nextWeek: 'dddd',
lastDay: '[Yesterday]',
lastWeek: '[Last] dddd',
sameElse: 'MMMM Do'
});
if (thisWork[j].dueDate === "Today") { // Font weight based on date proximity.
thisWork[j].cardDate = "600";
} else if (thisWork[j].dueDate === "Tomorrow") {
thisWork[j].cardDate = "400";
}
thisWork[j].typeColor = workColors[thisWork[j].type];
thisWork[j].confirmationLength = thisWork[j].confirmations.length; // Counts the number of confirmations and reports for a particular work.
thisWork[j].reportLength = thisWork[j].reports.length;
thisWork[j].creator = Meteor.users.findOne({
_id: thisWork[j].creator
}).profile.name;
var conf = thisWork[j].confirmations.length;
var repo = thisWork[j].reports.length;
var ratio = conf / repo;
var normalColor = Session.get("user").preferences.theme.text;
if (Math.abs(conf - repo)) {
if ((conf + repo) <= 1) {
thisWork[j].doneRatio = normalColor;
} else {
thisWork[j].doneRatio = "#F9F906";
}
} else if (ratio >= 2) {
thisWork[j].doneRatio = "#33DD33";
} else if (ratio <= 0.9) {
thisWork[j].doneRatio = "#FF1A1A";
}
}
array[i].thisClassWork = thisWork.sort(function(a, b) {
return Date.parse(a.realDate) - Date.parse(b.realDate);
});
}
return array;
}
function calendarEvents(array) {
var events = [];
var userClasses = array;
2017-04-08 00:07:00 -04:00
if(userClasses === undefined) return;
for (var i = 0; i < userClasses.length; i++) {
var works = userClasses[i].thisClassWork;
for (var j = 0; j < works.length; j++) {
var work = works[j];
var currClass = classes.findOne({
_id: work.class
});
var inRole = false;
if (work.class === Meteor.userId() ||
Meteor.userId() === work.creator ||
Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin']) ||
currClass.moderators.indexOf(Meteor.userId()) !== -1 ||
currClass.banned.indexOf(Meteor.userId()) !== -1
) inRole = true;
events.push({
id: work._id,
start: work.realDate.toISOString().slice(0, 10),
title: work.name,
backgroundColor: workColors[work.type],
borderColor: "#444",
startEditable: inRole,
className: work.type + " workevent " + work.class
});
}
}
Session.set("calendarEvents", events);
}
2017-02-09 10:26:22 -05:00
function notifyMe() {
}