diff --git a/hourglass/client/main/main.css b/hourglass/client/main/main.css index 5a643a0..083284b 100644 --- a/hourglass/client/main/main.css +++ b/hourglass/client/main/main.css @@ -243,7 +243,7 @@ input, textarea { filter: drop-shadow(2px 2px 5px #666); } -.fa-plus, .fa-minus, .fa-tasks, .fa-graduation-cap { +.fa-plus, .fa-minus, .fa-tasks, .fa-graduation-cap, .fa-exchange { font-size: 130%; padding: 5%; -webkit-filter: drop-shadow(2px 2px 5px #666); diff --git a/hourglass/client/main/main.js b/hourglass/client/main/main.js index 6220528..da9b446 100644 --- a/hourglass/client/main/main.js +++ b/hourglass/client/main/main.js @@ -52,7 +52,7 @@ Template.registerHelper('divColor', (div) => { }); Template.registerHelper('overlayDim', (part) => { - var dim = [window.innerWidth * 0.2, window.innerHeight * 0.2]; + var dim = [window.innerWidth * 0.2, window.innerHeight * 0.25]; var width = "width:" + dim[0].toString() + "px;"; var height = "height:" + dim[1].toString() + "px;"; var margin = "margin-left:" + (-dim[0] / 2).toString() + "px;"; diff --git a/hourglass/client/profile/profile.css b/hourglass/client/profile/profile.css index c521be7..414ebcf 100644 --- a/hourglass/client/profile/profile.css +++ b/hourglass/client/profile/profile.css @@ -200,7 +200,7 @@ display: inline; } -#profClassSearch, .userAddInput { +#profClassSearch { font-size: 125%; width: 30%; margin-top: 3%; @@ -210,6 +210,10 @@ animation: expand .7s ease 1; } +#profClassSearch .-autocomplete-container { + display: none; +} + @-webkit-keyframes expand { 0% { width: 0%; } 100% { width: 30%; } @@ -324,10 +328,10 @@ margin-right: 5% !important; margin-bottom: 0 !important; position: relative; - overflow: hidden !important; + } -#formContainer div { +.formDiv { margin: 3% 6% 5% 6%; width: 35%; display: inline-block; @@ -345,7 +349,6 @@ .-autocomplete-container { margin: 0 0 0 0 !important; position: absolute; - display: none; } #creSubmit { @@ -416,18 +419,173 @@ #createdClasses { width: 25%; - margin-right: -80%; - padding: 3%; + margin-right: -40%; + padding: 2.5%; - border-top: 5px solid #2E4F74; + border-top: 5px solid #27646D; box-shadow: -1px 2px 5px 1px #444; position: absolute; - top: 30%; + top: 20%; right: 0; -webkit-transition: margin 0.4s ease; -moz-transition: margin 0.4s ease; -ms-transition: margin 0.4s ease; transition: margin 0.4s ease; +} + +#code { + font-size: 120%; + width: 30%; +} + +#codetext { + width: 15% !important; +} + +#copy, #deleteClass { + margin-left: 1%; + padding: 2%; + + background-color: rgba(0,0,0,0.2); + cursor: pointer; + + -webkit-transition: background-color 0.4s ease; + -moz-transition: background-color 0.4s ease; + -ms-transition: background-color 0.4s ease; + transition: background-color 0.4s ease +} + +#copy:hover, #deleteClass:hover { + background-color: rgba(0,0,0,0.1); +} + +.userAddInput { + font-size: 100%; + width: 50%; + padding: 2%; +} + +#createdClasses h3 { + font-weight: 400; + font-size: 200%; +} + +#createdClasses h4 { + width: 25%; + padding-right: 0; +} + +#createdClasses .fa-plus { + cursor: pointer; + + -webkit-transition: color 0.4s ease; + -moz-transition: color 0.4s ease; + -ms-transition: color 0.4s ease; + transition: color 0.4s ease; +} + +#createdClasses .fa-plus:hover { + color: #519C39; +} + +.userHolder { + width: 100%; + max-height: 10%; + margin-left: 5%; + padding: 2%; + padding-right: 20%; + + overflow-y: scroll; + overflow-x: hidden; +} + +.userBox { + font-size: 100%; + width: 80%; + margin-bottom: 3%; + padding: 4%; + + box-shadow: 2px 2px 5px 3px #666; + display: table; +} + +.email { + margin-right: 5%; +} + +.realname { + margin-right: 5%; +} + +.userBox .fa-times { + font-size: 150%; + + -webkit-transition: color 0.4s ease; + -moz-transition: color 0.4s ease; + -ms-transition: color 0.4s ease; + transition: color 0.4s ease; +} + +.userBox .fa-times:hover { + color: #CC4444; +} + +#deleteClass { + font-size: 150%; + width: 29%; + margin: 5% 30% 0 30%; +} + +#changeAdmin span { + font-size: 90%; + padding: 3%; + + background-color: rgba(0,0,0,0.2); + display: inline-block; + cursor: pointer; + + -webkit-transition: background-color 0.4s ease; + -moz-transition: background-color 0.4s ease; + -ms-transition: background-color 0.4s ease; + transition: background-color 0.4s ease +} + +#changeAdmin span:hover { + background-color: rgba(0,0,0,0.1); +} + +#changeAdmin input { + font-size: 100%; + width: 50%; + margin-left: 3%; + margin-right: 5%; + padding: 2%; + + -webkit-animation: expand2 .7s ease 1; + animation: expand2 .7s ease 1; +} + +@-webkit-keyframes expand2 { + 0% { width: 0%; } + 100% { width: 50%; } +} + +@keyframes expand2 { + 0% { width: 0%; } + 100% { width: 50%; } +} + +.fa-exchange { + padding: 0 !important; + + -webkit-transition: color 0.4s ease; + -moz-transition: color 0.4s ease; + -ms-transition: color 0.4s ease; + transition: color 0.4s ease +} + +.fa-exchange:hover { + color: #CC4444; } \ No newline at end of file diff --git a/hourglass/client/profile/profile.html b/hourglass/client/profile/profile.html index 649a446..4affb4c 100644 --- a/hourglass/client/profile/profile.html +++ b/hourglass/client/profile/profile.html @@ -91,23 +91,23 @@

Insert description and rules of create a class --Will style later--

-
+

School:

{{> inputAutocomplete settings=schoolcomplete class="form-control creInput" type="text" name="school" placeholder="Example: International Academy" }}
-
+

Hour:

-
+

Teacher:

{{> inputAutocomplete settings=teachercomplete class="form-control creInput" type="text" name="teacher" placeholder="Example: Woods" }}
-
+

Class Name:

-
+

Privacy:

@@ -115,7 +115,7 @@

Private

-
+

Category:

@@ -142,27 +142,40 @@
-
+

{{selectedClass 'name'}}

-

Code: {{selectedClass 'code'}}

+

Code:

+ + {{#if code}} +

Copy Code

+ {{/if}}
-

Moderators:

+

Moderators:

+
- {{#each selectedClass 'moderators'}} - {{> userDisplay}} - {{/each}} +
+ {{#each selectedClass 'moderators'}} + {{> userDisplay}} + {{/each}} +
-
+
-

View only:

+

Banned:

+ -
- {{#each selectedClass 'blockEdit'}} - {{> userDisplay}} - {{/each}} +
+
+ {{#each selectedClass 'banned'}} + {{> userDisplay}} + {{/each}} +
+
+ Change Owner +
Delete Class
@@ -180,6 +193,7 @@
{{name}} +
diff --git a/hourglass/client/profile/profile.js b/hourglass/client/profile/profile.js index cb3a590..9ab182b 100644 --- a/hourglass/client/profile/profile.js +++ b/hourglass/client/profile/profile.js @@ -17,7 +17,8 @@ Session.set("serverData", null); Session.set("autocompleteDivs", null); Session.set("confirmText", null); Session.set("selectedClass",null); -Session.set("adding",null); +Session.set("selectClassId",null); +Session.set("code",null); var themeColors = { "light": { @@ -144,9 +145,9 @@ Template.profile.helpers({ privacy: {$eq: false}, _id: {$nin: Meteor.user().profile.classes} }, - {sort: {subscribers: -1 }}, - {limit: 20} - ).fetch(); + {sort: {subscribers: -1 }}, + {limit: 20} + ).fetch(); }, profClassHeight() { return 0.6 * window.innerHeight.toString() + "px"; @@ -181,7 +182,36 @@ Template.profile.helpers({ return Session.get("confirmText"); }, selectedClass(val) { - return Session.get("selectedClass")[val]; + var usertype = ["moderators","banned"]; + var attribute = Session.get("selectClassId"); + var array = classes.findOne({_id:attribute}); + + if(array.code === "") { + array.code = "None"; + Session.set("code", false); + } else { + Session.set("code", true); + } + + for(var i = 0; i < usertype.length; i++) { + var users = array[usertype[i]]; + array[usertype[i]] = []; + for(var j = 0; j < users.length; j++) { + var detailusers = {}; + var user = Meteor.users.findOne({_id:users[j]}); + detailusers._id = user._id; + detailusers.email = user.services.google.email; + detailusers.name = user.profile.name; + array[usertype[i]].push(detailusers); + } + } + return array[val]; + }, + code() { + return Session.get("code"); + }, + userHolder() { + return 0.15 * window.innerHeight.toString() + "px"; } }); @@ -257,21 +287,19 @@ Template.profile.events({ Session.set("radioDiv", null); Session.set("radioOffset", null); } - if(event.target.className !== "userAddInput" && - Session.get("adding")) { - var inputs = document.getElementsByClassName("userAddInput"); - for(var i = 0; i < inputs.length; i++) { - try { - inputs[i].parentNode.removeChild(inputs[i]); - } catch(err) {} - } - Session.set("adding",false); - } - if(!document.getElementById("createdClasses").contains(event.target) && - Session.get("selectedClass") !== null) { - document.getElementById("createdClasses").style.marginRight = "-40%"; - setTimeout(function() { Session.set("selectedClass", null); }, 300); - } + if(!document.getElementById("createdClasses").contains(event.target) && + Session.get("code") !== null && + !event.target.className.includes("fa-times-circle-o")) { + document.getElementById("createdClasses").style.marginRight = "-40%"; + setTimeout(function() { Session.set("selectedClass", null); }, 300); + } + if(Session.get("changeAdmin") && + !document.getElementById("changeAdmin").contains(event.target)) { + Session.set("changeAdmin",false); + var div = document.getElementById("changeAdmin"); + div.removeChild(div.childNodes[3]); + div.removeChild(div.childNodes[3]); + } }, 'keydown' (event) { var sessval = Session.get("modifying"); @@ -338,20 +366,20 @@ Template.profile.events({ }, 300);     },     'click .manageClass' () {         - var functionHolder = document.getElementById("profClassInfoHolder"); - closeDivFade(functionHolder);         - setTimeout(function() {             - Session.set("profClassTab", "manClass");             - openDivFade(functionHolder);         - }, 300);     + var functionHolder = document.getElementById("profClassInfoHolder"); + closeDivFade(functionHolder);         + setTimeout(function() {             + Session.set("profClassTab", "manClass");             + openDivFade(functionHolder);         + }, 300);     },     'click .createClass' () {         - var functionHolder = document.getElementById("profClassInfoHolder");         - closeDivFade(functionHolder);         - setTimeout(function() {             - Session.set("profClassTab", "creClass");             - openDivFade(functionHolder);         - }, 300);     + var functionHolder = document.getElementById("profClassInfoHolder");         + closeDivFade(functionHolder);         + setTimeout(function() {             + Session.set("profClassTab", "creClass");             + openDivFade(functionHolder);         + }, 300);     }, 'click .fa-search' () { Session.set("searching", true); @@ -409,8 +437,8 @@ Template.profile.events({ sendData(Session.get("confirm")); closeDivFade(document.getElementsByClassName("overlay")[0]); if(Session.get("confirm") === "createClass") { - var form = document.getElementById("create"); - for(var i = 0; i < form.length; i++) form[i].value = ""; + var form = document.getElementById("create"); + for(var i = 0; i < form.length; i++) form[i].value = ""; } Session.set("serverData", null); Session.set("confirm", null); @@ -420,16 +448,6 @@ Template.profile.events({ Session.set("serverData", null); Session.set("confirm", null); }, - 'click #save' () { - Session.set("serverData", getProfileData()); - Session.set("confirm", "editProfile"); - Session.set("confirmText", "Save new profile settings?"); - - openDivFade(document.getElementsByClassName("overlay")[0]); - setTimeout(function() { - document.getElementsByClassName("overlay")[0].style.opacity = "1"; - }, 200); - }, 'click #creSubmit' () { var data = getCreateFormData(); if (data === null) return; @@ -438,44 +456,82 @@ Template.profile.events({ Session.set("confirmText", "Submit request?"); openDivFade(document.getElementsByClassName("overlay")[0]); - setTimeout(function() { - document.getElementsByClassName("overlay")[0].style.opacity = "1"; - }, 200); }, 'focus .op' (event) { event.target.click(); }, 'click .owned' (event) { - if (event.target.id === "label") return; + if (event.target.id === "label") return; if (!event.target.className.includes("owned")) { var attribute = event.target.parentNode.getAttribute("classid"); } else { var attribute = event.target.getAttribute("classid"); } - var usertype = ["moderators","banned","blockEdit"]; - var array = classes.findOne({_id:attribute}); - - if(array.code === "") array.code = "None"; - for(var i = 0; i < usertype.length; i++) { - var users = array[usertype[i]]; - for(var j = 0; j < users.length; j++) { - var detailusers = {}; - var user = Meteor.users.findOne({_id:users[j]}); - detailusers._id = user._id; - detailusers.email = user.name + "hi"; - detailusers.name = user.name; - array[usertype[i]] = detailusers; - } - } - document.getElementById("createdClasses").style.marginRight = "0"; - Session.set("selectedClass",array); + Session.set("selectClassId",attribute); + document.getElementById("createdClasses").style.marginRight = "0"; }, 'click .userAdder .fa-plus' (event) { - if(Session.get("adding")) return; - var input = document.createElement("input"); - input.className = "userAddInput"; - event.target.parentNode.appendChild(input); - Session.set("adding", true); + var input = event.target.parentNode.childNodes[3]; + input.placeholder = "1234@abc.xyz"; + input.className.replace(" formInvalid",""); + var value = input.value; + input.value = ""; + if(checkUser(value)) { + input.className += " formInvalid"; + input.placeholder = "Not a valid user"; + return; + } + var user = Meteor.users.findOne({"services.google.email":input.value}); + Session.set("serverData", [ + user._id, + document.getElementById("createdClasses").getAttribute("classid"), + event.target.parentNode.childNodes[1].childNodes[0].nodeValue.replace(":","").toLowerCase() + ]); + sendData("trackUserInClass"); + + }, + 'click .userBox .fa-times' (event) { + var box = event.target.parentNode; + Session.set("serverData", [ + box.getAttribute("userid"), + document.getElementById("createdClasses").getAttribute("classid"), + box.parentNode.parentNode.childNodes[1].childNodes[1].childNodes[0].nodeValue.replace(":","").toLowerCase() + ]) + sendData("untrackUserInClass"); + }, + 'click #copy' () { + if(document.getElementById("code").value === "None") return; + document.getElementById("code").select(); + document.execCommand("copy"); + }, + 'click #deleteClass' () { + Session.set("serverData",document.getElementById("createdClasses").getAttribute("classid")); + Session.set("confirm", "deleteClass"); + Session.set("confirmText", "Delete this class?"); + openDivFade(document.getElementsByClassName("overlay")[0]); + }, + 'click #changeAdmin span' (event) { + if(Session.get("changeAdmin")) return; + Session.set("changeAdmin",true); + var input = document.createElement("input"); + input.placeholder = "1234@abc.xyz"; + var i = document.createElement("i"); + i.className = "fa fa-exchange"; + i.setAttribute("aria-hidden","true"); + event.target.parentNode.appendChild(input); + event.target.parentNode.appendChild(i); + }, + 'click .fa-exchange' (event) { + var input = event.target.parentNode.childNodes[3]; + input.placeholder = "1234@abc.xyz"; + input.className.replace(" formInvalid",""); + var value = input.value; + input.value = ""; + if(checkUser(value)) { + input.className += " formInvalid"; + input.placeholder = "Not a valid user"; + return; + } } }); @@ -542,7 +598,7 @@ function getCreateFormData() { var stop; var form = document.getElementsByClassName("creInput"); for (var i = 0; i < form.length; i++) { - if(i === 1 || i === 2) continue; + if(i === 1 || i === 2) continue; if (form[i].value === "") { form[i].focus(); form[i].placeholder = "Missing field"; @@ -575,3 +631,12 @@ function getCreateFormData() { code: "" }; } + +function checkUser(email) { + var user = Meteor.users.findOne({"services.google.email":email}); + if(user === undefined) { + return true; + } else { + return false; + } +} \ No newline at end of file diff --git a/hourglass/collections/main.js b/hourglass/collections/main.js index 7359ffd..073e80c 100644 --- a/hourglass/collections/main.js +++ b/hourglass/collections/main.js @@ -20,7 +20,7 @@ classes.schema = new SimpleSchema({ privacy: {type: Boolean}, category: {type: String}, moderators: {type: [String], optional: true}, - blockEdit: {type: [String], optional: true}, + banned: {type: [String], optional: true}, subscribers: {type: [String], optional: true} }); diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 33799fe..267c81f 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -16,7 +16,7 @@ superadmins = [ ]; worktype = ["test", "quiz", "project", "normal"]; -var possiblelist = ["moderators","blockEdit"]; +var possiblelist = ["moderators","banned"]; for (var i = 0; i < superadmins.length; i++) { var superadmin = superadmins[i]; @@ -57,7 +57,7 @@ Meteor.publish('classes', function() { privacy: 1, category: 1, moderators: 1, - blockEdit: 1, + banned: 1, subscribers: 1 } }); @@ -148,7 +148,7 @@ Meteor.methods({ input.category = "other"; } input.moderators = []; - input.blockEdit = []; + input.banned = []; classes.insert(input); Meteor.call('joinClass', classes.findOne(input)._id, input.code, function(error, result) {}); return 1; @@ -162,14 +162,14 @@ Meteor.methods({ if (Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin'])) { classes.update({_id: input[1]}, {$set: {admin: input[0]}}); } else if (found && foundclass && foundclass.admin == Meteor.userId() && - foundclass.blockEdit.indexOf(input[0]) != -1) { + foundclass.banned.indexOf(input[0]) != -1) { classes.update({_id: input[1]}, {$set: {admin: input[0]}}); } else { throw "Unauthorized"; } }, 'trackUserInClass': function(input) { - var foundclass = Meteor.findOne({_id: input[1]}); + var foundclass = classes.findOne({_id: input[1]}); var userlist = input[2]; var index = possiblelist.indexOf(input[2]); var set = {}; @@ -183,11 +183,13 @@ Meteor.methods({ } }, 'untrackUserInClass': function(input) { - var foundclass = Meteor.findOne({_id: input[1]}); + var foundclass = classes.findOne({_id: input[1]}); var userlist = input[2]; var index = possiblelist.indexOf(input[2]); var set = {}; - set[userlist] = foundclass[userlist].splice(foundclass[userlist].indexOf(input[0]), 1); + foundclass[userlist].splice(foundclass[userlist].indexOf(input[0]), 1); + set[userlist] = foundclass[userlist]; + if (Roles.userIsInRole(Meteor.userId(), ['superadmin', 'admin'])) { classes.update({_id: input[1]}, {$set: set}); } else if (foundclass && foundclass.admin == Meteor.userId() && index !== -1 && @@ -227,7 +229,7 @@ Meteor.methods({ if (Meteor.user() !== null && found !== null && Meteor.user().profile.classes.indexOf(input.class) !== -1 && - found.blockEdit.indexOf(Meteor.userId()) === -1 && + found.banned.indexOf(Meteor.userId()) === -1 && input.dueDate instanceof Date && input.dueDate.getTime() >= ref && worktype.indexOf(input.type) != -1 && input.name.length <= 50 && input.description.length <= 150) { @@ -303,7 +305,7 @@ Meteor.methods({ var user = Meteor.userId(); if (typeof comment === "string" && comment.length <= 200 && currentclass.subscribers.indexOf(Meteor.userId()) != -1 && - currentclass.blockEdit.indexOf(Meteor.userId()) === -1) { + currentclass.banned.indexOf(Meteor.userId()) === -1) { var comments = workobject.comments.concat(comment); work.update({ _id: input[1]