Merge
This commit is contained in:
commit
c7ffbc947c
@ -6,10 +6,10 @@
|
||||
|
||||
meteor-base@1.0.4 # Packages every Meteor app needs to have
|
||||
mobile-experience@1.0.4 # Packages for a great mobile UX
|
||||
mongo@1.1.12_1 # The database Meteor supports right now
|
||||
mongo@1.1.13 # The database Meteor supports right now
|
||||
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
|
||||
reactive-var@1.0.10 # Reactive variable for tracker
|
||||
jquery # Helpful client-side library
|
||||
jquery@1.11.9 # Helpful client-side library
|
||||
tracker@1.1.0 # Meteor's client-side reactive programming library
|
||||
|
||||
standard-minifier-js@1.2.0_1 # JS minifier run for production mode
|
||||
@ -33,7 +33,6 @@ shell-server@0.2.1
|
||||
http@1.2.9_1
|
||||
underscore@1.0.9
|
||||
ahref:dragula
|
||||
harrison:papa-parse
|
||||
pfafman:filesaver
|
||||
natestrauser:select2
|
||||
juliancwirko:s-alert
|
||||
@ -42,5 +41,5 @@ aldeed:collection2
|
||||
dburles:collection-helpers
|
||||
yogiben:admin-edit
|
||||
mfactory:admin-lte
|
||||
standard-minifier-css
|
||||
mrt:jquery-ui
|
||||
standard-minifier-css@1.2.0_1
|
||||
|
||||
@ -1 +1 @@
|
||||
METEOR@1.4.1.2
|
||||
METEOR@1.4.1.3
|
||||
|
||||
@ -45,7 +45,6 @@ fastclick@1.0.12
|
||||
fortawesome:fontawesome@4.5.0
|
||||
geojson-utils@1.0.9
|
||||
google@1.1.14
|
||||
harrison:papa-parse@1.1.1
|
||||
hot-code-push@1.0.4
|
||||
html-tools@1.0.11
|
||||
htmljs@1.0.11
|
||||
@ -82,11 +81,11 @@ mobile-status-bar@1.0.12
|
||||
modules@0.7.6_1
|
||||
modules-runtime@0.7.6_1
|
||||
momentjs:moment@2.15.1
|
||||
mongo@1.1.12_1
|
||||
mongo@1.1.13
|
||||
mongo-id@1.0.5
|
||||
mrt:jquery-ui@1.9.2
|
||||
natestrauser:select2@4.0.3
|
||||
npm-mongo@1.5.49
|
||||
npm-mongo@2.2.11_1
|
||||
oauth@1.1.11
|
||||
oauth2@1.1.10
|
||||
observe-sequence@1.0.12
|
||||
|
||||
@ -4,13 +4,13 @@ All your work in one place. Finish before your time runs out.
|
||||
Hourglass is a planner tool specialized for schools.
|
||||
## Usage
|
||||
How to use hourglass as an end product.
|
||||
If you find any bugs or have an idea to make this better, you can press the yield icon in the bottom right of the screen.
|
||||
If you find any bugs or have an idea to make this better, you can press the question mark icon in the bottom right of the screen.
|
||||
### Main Page
|
||||
After logging in with a Google account, you are automatically redirected to this page. Here, you can view work from subscribed classes. Preferences are found in the right sidebar, while the left sidebar contains classes and class management. The left sidebar also has options to allow you to switch between displaying a calendar and displaying a list of classes. Hovering over classes in the left sidebar will highlight works from that class. Clicking on a class will filter works to only be of that class. You can filter more than one class at a time. Clicking on a work, both in calendar and class mode, will open a menu showing more details. Cards are colored according to the type of work they are.
|
||||
After logging in with a Google account and setting up your profile, you can redirect to this page. Here, you can view work from subscribed classes. Preferences are found in the right sidebar, while the left sidebar contains classes and class management. The left sidebar also has options to allow you to switch between displaying a calendar and displaying a list of classes. Hovering over classes in the left sidebar will highlight works from that class. Clicking on a class will filter works to only be of that class. You can filter more than one class at a time or filter by the type of work. Clicking on a work, both in calendar and class mode, will open a menu showing more details. Cards are colored according to the type of work they are.
|
||||
##### Calendar Mode
|
||||
Calendar mode organizes work by due date rather than by class. Pressing on a date will open the left sidebar, allowing you to choose a class to create a piece of work under.
|
||||
Calendar mode organizes work by due date rather than by class. Pressing on a date will open the left sidebar, allowing you to choose a class in which you want to create the work.
|
||||
##### Class Mode
|
||||
Class mode allows you to organize work by the class it belongs to.
|
||||
Class mode allows you to organize work by the class it belongs to. You can drag classes to reorder them.
|
||||
##### Work
|
||||
Every piece of work has a confirmed:reported ratio. This is the ratio of the number of people who confirm the presence of the work to the number of people who believe that this is a false report. The creator of a work can edit fields after creation by clicking on details needed to be changed. Lastly, by marking a work as done, it is hidden from view. To disable this, go to preferences.
|
||||
##### Filters
|
||||
@ -21,3 +21,19 @@ On this page, it is possible to edit profile details as well as create, join, an
|
||||
After filling out class details, class creators must wait for the class to be approved by administrators. Public classes can be viewed and joined by all, while private classes are hidden from others and require a code to join.
|
||||
#### Joining a class
|
||||
One can join a public class by searching for and then clicking on the class they want to join. Joining a private class requires that the class administrator gives you a code, which you then provide in the "Join Private Class" button.
|
||||
#### Managing classes
|
||||
On this tab, you can see all of your current classes. If you are an admin of the class, clicking on it will allow you to manage details about the class. Otherwise, you can leave the class by clicking the x.
|
||||
### User Pages
|
||||
You can go to <-url->/user/<-email-> to vist a user's profile.
|
||||
|
||||
##Changelog
|
||||
|
||||
### 0.1.2
|
||||
- First beta version
|
||||
- Fixed resolution / display issues
|
||||
- Bug fixes
|
||||
|
||||
### 0.1.1
|
||||
- Added dynamic resizing, zooming and scaling support for CSS.
|
||||
- Fixed reactive updating on work.
|
||||
- Added personal work.
|
||||
|
||||
56
hourglass/client/admin/admin.css
Normal file
56
hourglass/client/admin/admin.css
Normal file
@ -0,0 +1,56 @@
|
||||
.adminUserIcon {
|
||||
width: 2.7vw;
|
||||
margin: 1%;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.adminUserInfo {
|
||||
margin-top: 1vh;
|
||||
padding: 0.5% 1.5% 0.5% 1.5%;
|
||||
|
||||
background-color: #fff;
|
||||
-webkit-filter: drop-shadow(0px -1px 2px #666);
|
||||
filter: drop-shadow(0px -1px 2px #666);
|
||||
|
||||
position: fixed;
|
||||
display: none;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.adminUserInfo p {
|
||||
margin: 5% 0 5% 0;
|
||||
}
|
||||
|
||||
.infoTitle {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.infoTab {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
border-bottom: 2vh solid #fff;
|
||||
border-left: 1.5vh solid transparent;
|
||||
border-right: 1.5vh solid transparent;
|
||||
|
||||
position: absolute;
|
||||
right: 1vh;
|
||||
top: -1.9vh;
|
||||
}
|
||||
|
||||
.approveStatus {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.approveStatus .fa {
|
||||
font-size: 5vh
|
||||
}
|
||||
|
||||
.approveStatus .fa-toggle-on {
|
||||
color: #288cd3;
|
||||
}
|
||||
17
hourglass/client/admin/admin.html
Normal file
17
hourglass/client/admin/admin.html
Normal file
@ -0,0 +1,17 @@
|
||||
<template name="adminUserDisplay">
|
||||
{{#each info}}
|
||||
<img class="adminUserIcon" src="{{icon}}">
|
||||
<div class="adminUserInfo">
|
||||
<div class="infoTab"></div>
|
||||
<p><span class="infoTitle">ID: </span><span>{{id}}</span></p>
|
||||
<p><span class="infoTitle">Email: </span><span>{{email}}</span></p>
|
||||
<p><span class="infoTitle">Name: </span><span>{{name}}</span></p>
|
||||
</div>
|
||||
{{/each}}
|
||||
</template>
|
||||
|
||||
<template name="statusButton">
|
||||
<div class="approveStatus">
|
||||
<i class="fa fa-toggle-{{status}}" aria-hidden="true"></i>
|
||||
</div>
|
||||
</template>
|
||||
66
hourglass/client/admin/admin.js
Normal file
66
hourglass/client/admin/admin.js
Normal file
@ -0,0 +1,66 @@
|
||||
var inInfo = false;
|
||||
var openUserDisplay = null;
|
||||
|
||||
Template.adminUserDisplay.helpers({
|
||||
info() {
|
||||
var ids = (this.value instanceof Array) ? this.value : [this.value];
|
||||
var userInfo = [];
|
||||
for(var i = 0; i < ids.length; i++) {
|
||||
var user = Meteor.users.findOne({_id: ids[i]});
|
||||
userInfo.push({
|
||||
name: user.profile.name,
|
||||
email: user.services.google.email,
|
||||
id: user._id,
|
||||
icon: user.services.google.picture
|
||||
})
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
});
|
||||
|
||||
Template.statusButton.helpers({
|
||||
status() {
|
||||
console.log(this.value);
|
||||
return (this.value) ? "on" : "off";
|
||||
}
|
||||
});
|
||||
|
||||
Template.adminUserDisplay.events({
|
||||
'click .adminUserIcon' (event) {
|
||||
var icoCoords = $(event.target)[0].getBoundingClientRect();
|
||||
var x = window.innerWidth - icoCoords.right;
|
||||
var y = icoCoords.bottom;
|
||||
openUserDisplay = $(event.target).next();
|
||||
$(".adminUserInfo").fadeOut(200);
|
||||
openUserDisplay
|
||||
.css({'right': x, 'top': y})
|
||||
.fadeIn(200);
|
||||
},
|
||||
'mouseenter .adminUserInfo' () {
|
||||
inInfo = true;
|
||||
},
|
||||
'mouseleave .adminUserInfo' (event) {
|
||||
if(inInfo) openUserDisplay.fadeOut(200);
|
||||
inInfo = false;
|
||||
openUserDisplay = null;
|
||||
}
|
||||
});
|
||||
|
||||
Template.AdminLTE.events({
|
||||
'click' (event) {
|
||||
if(!event.target.className.includes("adminUserInfo") &&
|
||||
!event.target.className.includes("adminUserIcon") &&
|
||||
openUserDisplay !== null) {
|
||||
openUserDisplay.fadeOut(200);
|
||||
openUserDisplay = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.statusButton.events({
|
||||
'click .approveStatus' () {
|
||||
console.log(this.doc._id);
|
||||
Meteor.call("approveClass", this.doc._id);
|
||||
}
|
||||
})
|
||||
|
||||
@ -639,9 +639,9 @@ Template.main.events({
|
||||
});
|
||||
},
|
||||
'click #exportDiv' (event) {
|
||||
var events = [];
|
||||
var events = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//hacksw/handcal//NONSGML v1.0//EN";
|
||||
var userClasses = Session.get("calendarClasses");
|
||||
|
||||
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++) {
|
||||
@ -655,24 +655,27 @@ Template.main.events({
|
||||
if (workclass === undefined) workclass = {
|
||||
name: "Personal"
|
||||
};
|
||||
events.push([
|
||||
workclass.name + ": " + work.name,
|
||||
work.realDate.toLocaleDateString(),
|
||||
work.description,
|
||||
"True"
|
||||
]);
|
||||
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";
|
||||
}
|
||||
events += "\nEND:VCALENDAR";
|
||||
}
|
||||
|
||||
var JSONevents = JSON.stringify(events);
|
||||
var CSVevents = Papa.unparse({
|
||||
fields: ["Subject", "Start Date", "Description", "All Day Event"],
|
||||
data: JSONevents
|
||||
var eventBlob = new Blob([events], {
|
||||
type: "data:text/ics;charset=utf-8"
|
||||
});
|
||||
var eventBlob = new Blob([CSVevents], {
|
||||
type: "data:text/csv;charset=utf-8"
|
||||
});
|
||||
saveAs(eventBlob, "hourglass.csv");
|
||||
saveAs(eventBlob, "hourglass.ics");
|
||||
},
|
||||
// HANDLING INPUT CHANGING
|
||||
'focus .clickModify' (event) {
|
||||
|
||||
@ -177,7 +177,7 @@
|
||||
{{#if noclass}}
|
||||
<h3>No results found...</h3>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{else}}
|
||||
{{#each autocompleteClasses}}
|
||||
{{> classDisplay}}
|
||||
{{/each}}
|
||||
|
||||
@ -25,17 +25,17 @@ Session.set("noclass", null); // If user doesn't have classes.
|
||||
Session.set("notfound", null); // If no results for autocomplete.
|
||||
|
||||
Template.profile.helpers({
|
||||
/* themeName() {
|
||||
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);
|
||||
/* themeName() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Custom";
|
||||
},*/
|
||||
return "Custom";
|
||||
},*/
|
||||
classSettings() { // Returns autocomplete array for classes.
|
||||
return {
|
||||
position: "bottom",
|
||||
@ -50,7 +50,15 @@ Template.profile.helpers({
|
||||
},
|
||||
selector: (match) => {
|
||||
regex = new RegExp(match, 'i');
|
||||
return {$or: [{'name': regex}, {'teacher': regex}, {'hour': regex}]};
|
||||
return {
|
||||
$or: [{
|
||||
'name': regex
|
||||
}, {
|
||||
'teacher': regex
|
||||
}, {
|
||||
'hour': regex
|
||||
}]
|
||||
};
|
||||
}
|
||||
}]
|
||||
};
|
||||
@ -143,9 +151,9 @@ Template.profile.helpers({
|
||||
},
|
||||
profClassTabColor(status) { // Change this [Supposed to show the current mode that's selected via color]
|
||||
if (Session.equals("profClassTab", status)) {
|
||||
return Meteor.user().profile.preferences.theme.modeHighlight;
|
||||
return Meteor.user().profile.preferences.theme.modeHighlight;
|
||||
} else {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
},
|
||||
profClassTab(tab) { // Tells current class
|
||||
@ -182,22 +190,22 @@ Template.profile.helpers({
|
||||
Template.profile.events({
|
||||
'click' (event) { // Whenever a click happens'
|
||||
var e = event.target.className;
|
||||
if(modifyingInput !== null && event.target !== document.getElementById(modifyingInput)) {
|
||||
if (modifyingInput !== null && event.target !== document.getElementById(modifyingInput)) {
|
||||
if (!(e.includes("optionHolder") || e.includes("optionText"))) {
|
||||
if(document.getElementById(modifyingInput).className.includes("dropdown")) {
|
||||
if (document.getElementById(modifyingInput).className.includes("dropdown")) {
|
||||
$(".optionHolder")
|
||||
.fadeOut(250, "linear");
|
||||
.fadeOut(250, "linear");
|
||||
|
||||
$(".selectedOption").removeClass("selectedOption");
|
||||
} else {
|
||||
if(modifyingInput === "description") {
|
||||
if (modifyingInput === "description") {
|
||||
Session.set("restrictText", {});
|
||||
$("#"+modifyingInput).css('cursor','pointer');
|
||||
$("#" + modifyingInput).css('cursor', 'pointer');
|
||||
var newSetting = Session.get("user");
|
||||
newSetting[modifyingInput] = document.getElementById(modifyingInput).value;
|
||||
serverData = newSetting;
|
||||
sendData("editProfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
modifyingInput = null;
|
||||
}
|
||||
@ -225,7 +233,10 @@ Template.profile.events({
|
||||
'click #mainpage' () {
|
||||
if (!Meteor.userId() || _.contains([null, undefined, ""], Meteor.user().profile.school)) {
|
||||
sAlert.closeAll();
|
||||
sAlert.error('Please fill in your profile!', {effect: 'stackslide', position: 'top'});
|
||||
sAlert.error('Please fill in your profile!', {
|
||||
effect: 'stackslide',
|
||||
position: 'top'
|
||||
});
|
||||
} else {
|
||||
window.location = '/';
|
||||
}
|
||||
@ -237,12 +248,12 @@ Template.profile.events({
|
||||
var div = document.getElementById("profClasses");
|
||||
div.style.height = "50%";
|
||||
setTimeout(function() {
|
||||
Session.set("profClassTab", "addClass");
|
||||
Session.set("profClassTab", "addClass");
|
||||
div.style.height = "70%";
|
||||
openDivFade(functionHolder);
|
||||
}, 400);
|
||||
},
|
||||
'click .manageClass' () {
|
||||
},
|
||||
'click .manageClass' () {
|
||||
if (Session.equals("profClassTab", "manClass")) return;
|
||||
var functionHolder = document.getElementById("profClassInfoHolder");
|
||||
closeDivFade(functionHolder);
|
||||
@ -254,16 +265,16 @@ Template.profile.events({
|
||||
openDivFade(functionHolder);
|
||||
}, 400);
|
||||
},
|
||||
'click .createClass' () {
|
||||
'click .createClass' () {
|
||||
if (Session.equals("profClassTab", "creClass")) return;
|
||||
var functionHolder = document.getElementById("profClassInfoHolder");
|
||||
closeDivFade(functionHolder);
|
||||
var div = document.getElementById("profClasses");
|
||||
div.style.height = "50%";
|
||||
setTimeout(function() {
|
||||
Session.set("profClassTab", "creClass");
|
||||
div.style.height = "70%";
|
||||
openDivFade(functionHolder);
|
||||
Session.set("profClassTab", "creClass");
|
||||
div.style.height = "70%";
|
||||
openDivFade(functionHolder);
|
||||
}, 400);
|
||||
},
|
||||
'click .classBox' (event) { // When you click on a box that holds class
|
||||
@ -293,7 +304,7 @@ Template.profile.events({
|
||||
} else {
|
||||
var attribute = event.target.getAttribute("classid");
|
||||
}
|
||||
if(attribute === Meteor.userId()) return;
|
||||
if (attribute === Meteor.userId()) return;
|
||||
Session.set("selectedClass", null);
|
||||
var usertype = ["moderators", "banned"];
|
||||
var array = classes.findOne({
|
||||
@ -461,21 +472,21 @@ Template.profile.events({
|
||||
// INPUT HANDLING
|
||||
'focus .clickModify' (event) {
|
||||
$(".optionHolder")
|
||||
.fadeOut(250, "linear");
|
||||
.fadeOut(250, "linear");
|
||||
|
||||
if(modifyingInput !== null) {
|
||||
if(!$("#"+modifyingInput)[0].className.includes("dropdown")) closeInput(modifyingInput);
|
||||
}
|
||||
if (modifyingInput !== null) {
|
||||
if (!$("#" + modifyingInput)[0].className.includes("dropdown")) closeInput(modifyingInput);
|
||||
}
|
||||
modifyingInput = event.target.id;
|
||||
if(!$("#"+modifyingInput)[0].className.includes("dropdown")) {
|
||||
if (!$("#" + modifyingInput)[0].className.includes("dropdown")) {
|
||||
event.target.select();
|
||||
event.target.style.cursor = "text";
|
||||
event.target.style.cursor = "text";
|
||||
}
|
||||
},
|
||||
'keydown .dropdown' (event) {
|
||||
event.preventDefault();
|
||||
var first = $("#"+modifyingInput).next().children("p:first-child");
|
||||
var last = $("#"+modifyingInput).next().children("p:last-child");
|
||||
var first = $("#" + modifyingInput).next().children("p:first-child");
|
||||
var last = $("#" + modifyingInput).next().children("p:last-child");
|
||||
var next = $(".selectedOption").next();
|
||||
var prev = $(".selectedOption").prev();
|
||||
var lastSel = $(".selectedOption");
|
||||
@ -487,7 +498,7 @@ Template.profile.events({
|
||||
} else {
|
||||
if (prev.length === 0) {
|
||||
last.addClass("selectedOption");
|
||||
lastSel.removeClass("selectedOption");
|
||||
lastSel.removeClass("selectedOption");
|
||||
} else {
|
||||
prev.addClass("selectedOption");
|
||||
lastSel.removeClass("selectedOption");
|
||||
@ -506,7 +517,7 @@ Template.profile.events({
|
||||
next.addClass("selectedOption");
|
||||
lastSel.removeClass("selectedOption");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (event.keyCode === 13) {
|
||||
lastSel[0].click();
|
||||
}
|
||||
@ -515,27 +526,29 @@ Template.profile.events({
|
||||
$(".selectedOption").removeClass("selectedOption");
|
||||
|
||||
$("#" + modifyingInput).next()
|
||||
.css('opacity',0)
|
||||
.slideDown(300)
|
||||
.animate(
|
||||
{ opacity: 1 },
|
||||
{ queue: false, duration: 100 }
|
||||
);
|
||||
.css('opacity', 0)
|
||||
.slideDown(300)
|
||||
.animate({
|
||||
opacity: 1
|
||||
}, {
|
||||
queue: false,
|
||||
duration: 100
|
||||
});
|
||||
},
|
||||
'click .optionText' (event) { // Click each preferences setting.
|
||||
var option = event.target.childNodes[0].nodeValue;
|
||||
var userSettings = ["description","school","grade"];
|
||||
var userSettings = ["description", "school", "grade"];
|
||||
var newSetting = Session.get("user");
|
||||
|
||||
if(modifyingInput === "privacy" || modifyingInput === "category") {
|
||||
|
||||
if (modifyingInput === "privacy" || modifyingInput === "category") {
|
||||
document.getElementById(modifyingInput).value = option;
|
||||
$("#" + modifyingInput).next()
|
||||
.fadeOut(250, "linear");
|
||||
.fadeOut(250, "linear");
|
||||
$(".selectedOption").removeClass("selectedOption");
|
||||
return;
|
||||
}
|
||||
|
||||
if(_.contains(userSettings, modifyingInput)) {
|
||||
if (_.contains(userSettings, modifyingInput)) {
|
||||
newSetting[modifyingInput] = (modifyingInput === "grade") ? parseInt(option) : option;
|
||||
} else {
|
||||
newSetting.preferences[modifyingInput] = (function() {
|
||||
@ -547,10 +560,10 @@ Template.profile.events({
|
||||
}
|
||||
Session.set("user", newSetting);
|
||||
serverData = Session.get("user");
|
||||
sendData("editProfile");
|
||||
sendData("editProfile");
|
||||
|
||||
$("#" + modifyingInput).next()
|
||||
.fadeOut(250, "linear");
|
||||
.fadeOut(250, "linear");
|
||||
|
||||
$(".selectedOption").removeClass("selectedOption");
|
||||
},
|
||||
@ -585,11 +598,13 @@ Template.profile.events({
|
||||
name: item.childNodes[1].childNodes[0].nodeValue,
|
||||
teacher: item.childNodes[3].childNodes[0].nodeValue,
|
||||
hour: item.childNodes[5].childNodes[0].nodeValue,
|
||||
subscribers: Math.floor(item.childNodes[7].childNodes[0].nodeValue.replace(",","").length / 17),
|
||||
subscribers: Math.floor(item.childNodes[7].childNodes[0].nodeValue.replace(",", "").length / 17),
|
||||
_id: item.getAttribute("classid")
|
||||
});
|
||||
}
|
||||
Session.set("autocompleteDivs", divs.sort(function(a,b){return b.subscribers-a.subscribers}));
|
||||
Session.set("autocompleteDivs", divs.sort(function(a, b) {
|
||||
return b.subscribers - a.subscribers
|
||||
}));
|
||||
} catch (err) {}
|
||||
}
|
||||
});
|
||||
@ -712,8 +727,8 @@ function checkUser(email, classid) { // Checks if user email exists.
|
||||
return true;
|
||||
} else {
|
||||
if (classes.findOne({
|
||||
_id: classid
|
||||
}).subscribers)
|
||||
_id: classid
|
||||
}).subscribers)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,11 +48,3 @@ schools.attachSchema(schools.schema);
|
||||
classes.attachSchema(classes.schema);
|
||||
work.attachSchema(work.schema);
|
||||
requests.attachSchema(requests.schema);
|
||||
|
||||
classes.helpers({
|
||||
fullUserInfo() {
|
||||
var user = Meteor.users.findOne({_id: this.admin});
|
||||
console.log(user);
|
||||
return this.admin + " | " + user.services.google.email + " | " + user.profile.name;
|
||||
}
|
||||
})
|
||||
|
||||
@ -131,16 +131,16 @@ AdminConfig = {
|
||||
{ label: 'Name', name: 'name' },
|
||||
{ label: 'Hour', name: 'hour' },
|
||||
{ label: 'Teacher', name: 'teacher' },
|
||||
{ label: 'Admin', name: 'admin' },
|
||||
{ label: 'Status', name: 'status' },
|
||||
{ label: 'Admin', name: 'admin', template: 'adminUserDisplay' },
|
||||
{ label: 'Status', name: 'status', template: 'statusButton'},
|
||||
{ label: 'Code', name: 'code' },
|
||||
{ label: 'Privacy', name: 'privacy' },
|
||||
{ label: 'Category', name: 'category' },
|
||||
{ label: 'Moderators', name: 'moderators' },
|
||||
{ label: 'Banned', name: 'banned' },
|
||||
{ label: 'Subscribers', name: 'subscribers' }
|
||||
{ label: 'Moderators', name: 'moderators', template: 'adminUserDisplay' },
|
||||
{ label: 'Banned', name: 'banned', template: 'adminUserDisplay' },
|
||||
{ label: 'Subscribers', name: 'subscribers', template: 'adminUserDisplay'}
|
||||
],
|
||||
color: 'blue'
|
||||
color: 'purple'
|
||||
},
|
||||
work: {
|
||||
tableColumns: [
|
||||
@ -149,11 +149,11 @@ AdminConfig = {
|
||||
{ label: 'Name', name: 'name' },
|
||||
{ label: 'Due Date', name: 'dueDate' },
|
||||
{ label: 'Description', name: 'description' },
|
||||
{ label: 'Creator', name: 'creator' },
|
||||
{ label: 'Creator', name: 'creator', template: 'adminUserDisplay' },
|
||||
{ label: 'Comments', name: 'comments' },
|
||||
{ label: 'Confirmations', name: 'confirmations' },
|
||||
{ label: 'Reports', name: 'reports' },
|
||||
{ label: 'Done', name: 'done' },
|
||||
{ label: 'Confirmations', name: 'confirmations', template: 'adminUserDisplay' },
|
||||
{ label: 'Reports', name: 'reports', template: 'adminUserDisplay' },
|
||||
{ label: 'Done', name: 'done', template: 'adminUserDisplay' },
|
||||
{ label: 'Type', name: 'type' }
|
||||
],
|
||||
color: 'yellow'
|
||||
@ -161,7 +161,7 @@ AdminConfig = {
|
||||
requests: {
|
||||
tableColumns: [
|
||||
{ label: 'ID', name: '_id' },
|
||||
{ label: 'User', name: 'requestor' },
|
||||
{ label: 'User', name: 'requestor', template: 'adminUserDisplay' },
|
||||
{ label: 'Request', name: 'request' },
|
||||
{ label: 'Time', name: 'timeRequested' }
|
||||
],
|
||||
|
||||
@ -175,26 +175,52 @@ Meteor.methods({
|
||||
schools.findOne({
|
||||
name: input.school
|
||||
})) {
|
||||
input.status = Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin']);
|
||||
input.admin = Meteor.userId();
|
||||
Meteor.call('genCode', function(error, result) {
|
||||
input.code = result;
|
||||
});
|
||||
if (input.category != "class" && input.category != "club") {
|
||||
input.category = "other";
|
||||
}
|
||||
input.subscribers = [];
|
||||
input.moderators = [];
|
||||
input.banned = [];
|
||||
if (classes.find({
|
||||
status: true,
|
||||
privacy: false,
|
||||
teacher: input.teacher,
|
||||
hour: input.hour
|
||||
}).fetch().length < 1 ||
|
||||
input.teacher === "" ||
|
||||
input.hour === "") {
|
||||
input.status = Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin']);
|
||||
input.admin = Meteor.userId();
|
||||
Meteor.call('genCode', function(error, result) {
|
||||
input.code = result;
|
||||
});
|
||||
if (input.category != "class" && input.category != "club") {
|
||||
input.category = "other";
|
||||
}
|
||||
input.subscribers = [];
|
||||
input.moderators = [];
|
||||
input.banned = [];
|
||||
|
||||
classes.insert(input, function(err, result) {
|
||||
Meteor.call('joinClass', [result, input.code]);
|
||||
});
|
||||
classes.insert(input, function(err, result) {
|
||||
Meteor.call('joinClass', [result, input.code]);
|
||||
});
|
||||
} else {
|
||||
throw new Meteor.Error("overlap", "This teacher is already teaching a class elsewhere!");
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Meteor.Error("unauthorized", "You are not authorized to complete this action.");
|
||||
}
|
||||
},
|
||||
'approveClass': function(classId) {
|
||||
if (Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin'])) {
|
||||
var currentclass = classes.findOne({
|
||||
_id: classId
|
||||
});
|
||||
|
||||
classes.update({
|
||||
_id: classId
|
||||
}, {
|
||||
$set: {
|
||||
status: !currentclass.status
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
// For class admins to get code
|
||||
'getCode': function(classId) {
|
||||
var foundclass = classes.findOne({
|
||||
@ -501,7 +527,7 @@ Meteor.methods({
|
||||
"hideReport": true
|
||||
};
|
||||
|
||||
if (_.contains(superadmins, currentuser.services.google.email)) {
|
||||
if (_.contains(superadmins, currentuser.services.google.email)) {
|
||||
Roles.addUsersToRoles(userId, 'superadmin');
|
||||
Roles.addUsersToRoles(userId, 'admin');
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user