diff --git a/hourglass/.meteor/packages b/hourglass/.meteor/packages
index a5eacd0..70b9a54 100644
--- a/hourglass/.meteor/packages
+++ b/hourglass/.meteor/packages
@@ -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
diff --git a/hourglass/.meteor/release b/hourglass/.meteor/release
index 2631a23..3a5f4f2 100644
--- a/hourglass/.meteor/release
+++ b/hourglass/.meteor/release
@@ -1 +1 @@
-METEOR@1.4.1.2
+METEOR@1.4.1.3
diff --git a/hourglass/.meteor/versions b/hourglass/.meteor/versions
index af83fc5..d3a88b5 100644
--- a/hourglass/.meteor/versions
+++ b/hourglass/.meteor/versions
@@ -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
diff --git a/hourglass/README.md b/hourglass/README.md
index ec61448..6449550 100644
--- a/hourglass/README.md
+++ b/hourglass/README.md
@@ -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.
diff --git a/hourglass/client/admin/admin.css b/hourglass/client/admin/admin.css
new file mode 100644
index 0000000..395809f
--- /dev/null
+++ b/hourglass/client/admin/admin.css
@@ -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;
+}
\ No newline at end of file
diff --git a/hourglass/client/admin/admin.html b/hourglass/client/admin/admin.html
new file mode 100644
index 0000000..9df4827
--- /dev/null
+++ b/hourglass/client/admin/admin.html
@@ -0,0 +1,17 @@
+
+ {{#each info}}
+
+
+
+
ID: {{id}}
+
Email: {{email}}
+
Name: {{name}}
+
+ {{/each}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hourglass/client/admin/admin.js b/hourglass/client/admin/admin.js
new file mode 100644
index 0000000..b2f827c
--- /dev/null
+++ b/hourglass/client/admin/admin.js
@@ -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);
+ }
+})
+
diff --git a/hourglass/client/main/main.js b/hourglass/client/main/main.js
index 90485f0..a518483 100644
--- a/hourglass/client/main/main.js
+++ b/hourglass/client/main/main.js
@@ -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) {
diff --git a/hourglass/client/profile/profile.html b/hourglass/client/profile/profile.html
index aea3558..d197e5a 100644
--- a/hourglass/client/profile/profile.html
+++ b/hourglass/client/profile/profile.html
@@ -177,7 +177,7 @@
{{#if noclass}}
No results found...
{{/if}}
- {{else}}
+ {{else}}
{{#each autocompleteClasses}}
{{> classDisplay}}
{{/each}}
diff --git a/hourglass/client/profile/profile.js b/hourglass/client/profile/profile.js
index 36cc6e9..dd41558 100644
--- a/hourglass/client/profile/profile.js
+++ b/hourglass/client/profile/profile.js
@@ -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;
}
}
diff --git a/hourglass/collections/main.js b/hourglass/collections/main.js
index 211d46d..abb9b71 100644
--- a/hourglass/collections/main.js
+++ b/hourglass/collections/main.js
@@ -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;
- }
-})
diff --git a/hourglass/lib/constants.js b/hourglass/lib/constants.js
index a1ca16e..b0fb4b0 100644
--- a/hourglass/lib/constants.js
+++ b/hourglass/lib/constants.js
@@ -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' }
],
diff --git a/hourglass/server/main.js b/hourglass/server/main.js
index e0f8e86..5909dc3 100644
--- a/hourglass/server/main.js
+++ b/hourglass/server/main.js
@@ -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');
}