From 7047697164dd36648d5c4c0193e74ee45c86f21c Mon Sep 17 00:00:00 2001 From: ksjdragon Date: Sat, 22 Oct 2016 18:42:49 -0400 Subject: [PATCH 01/16] Update README.md --- hourglass/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hourglass/README.md b/hourglass/README.md index ec61448..729af96 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -21,3 +21,15 @@ 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. + +#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. From 234df9df94a634bce3bdf4f163dab2bd24e965b4 Mon Sep 17 00:00:00 2001 From: ksjdragon Date: Sat, 22 Oct 2016 18:43:08 -0400 Subject: [PATCH 02/16] Update README.md --- hourglass/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hourglass/README.md b/hourglass/README.md index 729af96..ad478f9 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -24,12 +24,12 @@ One can join a public class by searching for and then clicking on the class they #Changelog -# 0.1.2 +## 0.1.2 - First beta version - Fixed resolution / display issues - Bug fixes -# 0.1.1 +## 0.1.1 - Added dynamic resizing, zooming and scaling support for CSS. - Fixed reactive updating on work. - Added personal work. From 5cf986e7e10400e24754999c56c37d0bdecf9078 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 15:46:32 -0400 Subject: [PATCH 03/16] update meteor to 1.4.1.3 --- hourglass/.meteor/packages | 6 +++--- hourglass/.meteor/release | 2 +- hourglass/.meteor/versions | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hourglass/.meteor/packages b/hourglass/.meteor/packages index f5dc3eb..8912fad 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 @@ -42,4 +42,4 @@ aldeed:collection2 dburles:collection-helpers yogiben:admin-edit mfactory:admin-lte -standard-minifier-css +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 2aae236..6c9e262 100644 --- a/hourglass/.meteor/versions +++ b/hourglass/.meteor/versions @@ -82,10 +82,10 @@ 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 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 From d2dbdb0cd39917409bd473d4b31fb4ab30177075 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 15:49:43 -0400 Subject: [PATCH 04/16] run filter on profile.js --- hourglass/client/profile/profile.js | 125 ++++++++++++++++------------ 1 file changed, 70 insertions(+), 55 deletions(-) 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; } } From 2dc62abe6f86f899d8098072abcf02f9c08c9e02 Mon Sep 17 00:00:00 2001 From: yamanq Date: Sun, 23 Oct 2016 16:02:46 -0400 Subject: [PATCH 05/16] Update README.md --- hourglass/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hourglass/README.md b/hourglass/README.md index ad478f9..acdb3e7 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -4,11 +4,11 @@ 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. ##### Work From 2bfe58b3f14d228aeec2a766faeeac3d41bb5abd Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 16:19:08 -0400 Subject: [PATCH 06/16] prevent overlapping classes --- hourglass/client/profile/profile.html | 2 +- hourglass/server/main.js | 39 ++++++++++++++++----------- 2 files changed, 25 insertions(+), 16 deletions(-) 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/server/main.js b/hourglass/server/main.js index e0f8e86..77ed50f 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -175,21 +175,30 @@ 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.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."); @@ -501,7 +510,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'); } From 9bf40c2c0d4eb7176652ced9806955f251311059 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 16:23:16 -0400 Subject: [PATCH 07/16] improve duplicate function --- hourglass/server/main.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 77ed50f..8102297 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -180,7 +180,9 @@ Meteor.methods({ privacy: false, teacher: input.teacher, hour: input.hour - }).fetch().length < 1) { + }).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) { @@ -197,7 +199,7 @@ Meteor.methods({ Meteor.call('joinClass', [result, input.code]); }); } else { - throw new Meteor.Error("overlap", "This teacher is already teaching a class elsewhere!") + throw new Meteor.Error("overlap", "This teacher is already teaching a class elsewhere!"); } } else { From 0eda7b94b7b0853e744a436c44a4ab05e0598dc0 Mon Sep 17 00:00:00 2001 From: yamanq Date: Sun, 23 Oct 2016 16:34:47 -0400 Subject: [PATCH 08/16] Finish Profile and add User --- hourglass/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hourglass/README.md b/hourglass/README.md index acdb3e7..10ed6d4 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -10,7 +10,7 @@ After logging in with a Google account and setting up your profile, you can redi ##### 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 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,6 +21,10 @@ 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 /user/ to vist a user's profile. #Changelog From b15a7875ac78226bba4d9361e3ce529d0d931b8c Mon Sep 17 00:00:00 2001 From: yamanq Date: Sun, 23 Oct 2016 16:35:23 -0400 Subject: [PATCH 09/16] Update README.md --- hourglass/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hourglass/README.md b/hourglass/README.md index 10ed6d4..199d56b 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -24,7 +24,7 @@ One can join a public class by searching for and then clicking on the class they #### 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 /user/ to vist a user's profile. +You can go to <-url->/user/<-email-> to vist a user's profile. #Changelog From a00591cc550b47d515b5bdae8252bdbccdbb7618 Mon Sep 17 00:00:00 2001 From: yamanq Date: Sun, 23 Oct 2016 16:35:57 -0400 Subject: [PATCH 10/16] Update README.md --- hourglass/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hourglass/README.md b/hourglass/README.md index 199d56b..6449550 100644 --- a/hourglass/README.md +++ b/hourglass/README.md @@ -26,14 +26,14 @@ On this tab, you can see all of your current classes. If you are an admin of the ### User Pages You can go to <-url->/user/<-email-> to vist a user's profile. -#Changelog +##Changelog -## 0.1.2 +### 0.1.2 - First beta version - Fixed resolution / display issues - Bug fixes -## 0.1.1 +### 0.1.1 - Added dynamic resizing, zooming and scaling support for CSS. - Fixed reactive updating on work. - Added personal work. From fab410e8fd79e4d3eca13fda1bf0d97ff16ea21d Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 17:50:05 -0400 Subject: [PATCH 11/16] change export format to ics --- hourglass/client/main/main.js | 37 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/hourglass/client/main/main.js b/hourglass/client/main/main.js index 4111aa6..9515b43 100644 --- a/hourglass/client/main/main.js +++ b/hourglass/client/main/main.js @@ -654,9 +654,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++) { @@ -670,24 +670,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) { From 14b16680af5c05b0a5d4301ae1d095353cc40a77 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 17:50:59 -0400 Subject: [PATCH 12/16] remove Papa --- hourglass/.meteor/packages | 1 - hourglass/.meteor/versions | 1 - 2 files changed, 2 deletions(-) diff --git a/hourglass/.meteor/packages b/hourglass/.meteor/packages index 8912fad..c8dcf26 100644 --- a/hourglass/.meteor/packages +++ b/hourglass/.meteor/packages @@ -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 diff --git a/hourglass/.meteor/versions b/hourglass/.meteor/versions index 6c9e262..f4b0310 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 From a06ed677fe2da3c1df29b071226a351a64c6af77 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 21:42:18 -0400 Subject: [PATCH 13/16] approveClass --- hourglass/server/main.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 8102297..334480f 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -206,6 +206,21 @@ Meteor.methods({ 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.find({ + _id: classId + }); + currentclass.status = true; + Meteor.update({ + _id: classId + }, { + $set: { + currentclass + } + }); + } + }, // For class admins to get code 'getCode': function(classId) { var foundclass = classes.findOne({ From 92b23f6d7869e069ec79697ee1449b3328d7026c Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 21:45:02 -0400 Subject: [PATCH 14/16] toggle approveClass --- hourglass/server/main.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 334480f..8e89164 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -211,7 +211,11 @@ Meteor.methods({ var currentclass = classes.find({ _id: classId }); - currentclass.status = true; + if (currentclass.status) { + currentclass.status = false; + } else { + currentclass.status = true; + } Meteor.update({ _id: classId }, { From 7f0d29ae165576d1df6a898672ed857a0d9e2c48 Mon Sep 17 00:00:00 2001 From: Yaman Qalieh Date: Sun, 23 Oct 2016 21:47:14 -0400 Subject: [PATCH 15/16] optimizations --- hourglass/server/main.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 8e89164..1c3b2c6 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -211,11 +211,7 @@ Meteor.methods({ var currentclass = classes.find({ _id: classId }); - if (currentclass.status) { - currentclass.status = false; - } else { - currentclass.status = true; - } + currentclass.status = !currentclass.status; Meteor.update({ _id: classId }, { From 650e13881b5389ade8f6fca478bfe8887fac250e Mon Sep 17 00:00:00 2001 From: Kenneth Jao Date: Sun, 23 Oct 2016 22:10:02 -0400 Subject: [PATCH 16/16] Added admin buttons for status, and user info --- hourglass/client/admin/admin.css | 56 ++++++++++++++++++++++++++ hourglass/client/admin/admin.html | 17 ++++++++ hourglass/client/admin/admin.js | 66 +++++++++++++++++++++++++++++++ hourglass/collections/main.js | 8 ---- hourglass/lib/constants.js | 22 +++++------ hourglass/server/main.js | 8 ++-- 6 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 hourglass/client/admin/admin.css create mode 100644 hourglass/client/admin/admin.html create mode 100644 hourglass/client/admin/admin.js 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 @@ + + + \ 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/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 61a21e8..c8cd341 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 1c3b2c6..5909dc3 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -208,15 +208,15 @@ Meteor.methods({ }, 'approveClass': function(classId) { if (Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin'])) { - var currentclass = classes.find({ + var currentclass = classes.findOne({ _id: classId }); - currentclass.status = !currentclass.status; - Meteor.update({ + + classes.update({ _id: classId }, { $set: { - currentclass + status: !currentclass.status } }); }