diff --git a/hourglass/client/admin/admin.css b/hourglass/client/admin/admin.css index 395809f..78098ff 100644 --- a/hourglass/client/admin/admin.css +++ b/hourglass/client/admin/admin.css @@ -1,4 +1,41 @@ -.adminUserIcon { +.content-wrapper { + background-image: url("/Backgrounds/escheresque_ste.png"); +} + +.content-wrapper h4 { + color: #FEFEFE; +} + +.col-lg-3 { + -webkit-filter: drop-shadow(2px 2px 2px #CCC); + filter: drop-shadow(2px 2px 2px #666); +} + +.main-header .logo { + background-color: #222d32; +} +.main-sidebar { + box-shadow: -2px 1px 1px 5px #666; +} + +.navbar { + background-color: #2F414A !important; + box-shadow: 7px -2px 1px 5px #666; +} + +.content-header h1, #adminAddWrapper { + background-color: #FFF; + border: 5px solid #FFF; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.breadcrumb { + margin-right: 1%; +} + +.adminUserIcon, .simpleUserIcon { width: 2.7vw; margin: 1%; @@ -52,5 +89,47 @@ } .approveStatus .fa-toggle-on { - color: #288cd3; -} \ No newline at end of file + color: #288CD3; +} + +.addAdmin { + width: 35% !important; +} + +.simpleUserIcon { + margin: 0.5% 0.3% 0.5% 0.2%; + display: inline-block; + vertical-align: top; + cursor: default; +} + +.simpleUserInfo { + margin: 0.5% 0.3% 0.5% 0.2%; + background-color: #FFF; + display: inline-block; + vertical-align: top; +} + +.simpleUserInfo p { + margin: 1%; +} + +.simpleUserInfo p:first-child { + font-weight: 400; +} + +.simpleUserInfo p:last-child { + font-weight: 200; + color: #D8D8D8; +} + +.addAdmin { + margin: 0 0 1% 1%; + display: inline-block !important; +} + +#addAdmin { + margin-left: 1%; + display: inline-block; +} + diff --git a/hourglass/client/admin/admin.html b/hourglass/client/admin/admin.html index 9df4827..fa53103 100644 --- a/hourglass/client/admin/admin.html +++ b/hourglass/client/admin/admin.html @@ -14,4 +14,38 @@
+ + + + + + + + + \ No newline at end of file diff --git a/hourglass/client/admin/admin.js b/hourglass/client/admin/admin.js index b2f827c..9dafce6 100644 --- a/hourglass/client/admin/admin.js +++ b/hourglass/client/admin/admin.js @@ -12,7 +12,7 @@ Template.adminUserDisplay.helpers({ email: user.services.google.email, id: user._id, icon: user.services.google.picture - }) + }); } return userInfo; } @@ -20,7 +20,6 @@ Template.adminUserDisplay.helpers({ Template.statusButton.helpers({ status() { - console.log(this.value); return (this.value) ? "on" : "off"; } }); @@ -51,16 +50,54 @@ Template.AdminLTE.events({ if(!event.target.className.includes("adminUserInfo") && !event.target.className.includes("adminUserIcon") && openUserDisplay !== null) { - openUserDisplay.fadeOut(200); - openUserDisplay = null; + if(!openUserDisplay[0].contains(event.target)) { + openUserDisplay.fadeOut(200, function() { + openUserDisplay = null; + }); + } } } }); Template.statusButton.events({ 'click .approveStatus' () { - console.log(this.doc._id); Meteor.call("approveClass", this.doc._id); } -}) +}); +Template.userEditor.helpers({ + userInfo : function() { + return Session.get("admin_doc") + }, + superAdmin: function() { + return Roles.userIsInRole(Meteor.userId(), ['superadmin']); + } +}); + +Template.createAdmin.helpers({ + userComplete() { + return { + position: "bottom", + limit: 7, + rules: [{ + token: '', + collection: Meteor.users, + field: 'services.google.email', + filter: {roles: {$not: {$elemMatch: {$eq: "admin"}}}}, + template: Template.simpleUser + }] + }; + }, + superAdmin: function() { + return Roles.userIsInRole(Meteor.userId(), ['superadmin']); + } +}); + +Template.createAdmin.events({ + 'click #addAdmin' () { + var value = document.getElementsByClassName("form-control")[0].value; + var user = Meteor.users.findOne({'services.google.email': value}); + if(user === undefined) return; + Meteor.call("addAdmin", user._id); + } +}) \ No newline at end of file diff --git a/hourglass/client/profile/profile.css b/hourglass/client/profile/profile.css index 4c87e99..4d1ba54 100644 --- a/hourglass/client/profile/profile.css +++ b/hourglass/client/profile/profile.css @@ -221,7 +221,7 @@ animation: expand .7s ease 1; } -.-autocomplete-container { +.noScroll .-autocomplete-container { display: none; } diff --git a/hourglass/collections/main.js b/hourglass/collections/main.js index c844bbd..7cfa5be 100644 --- a/hourglass/collections/main.js +++ b/hourglass/collections/main.js @@ -2,6 +2,7 @@ schools = new Mongo.Collection("Schools"); classes = new Mongo.Collection("Classes"); work = new Mongo.Collection("Work"); requests = new Mongo.Collection("Requests"); +admins = Meteor.users; schools.schema = new SimpleSchema({ name: {type: String}, @@ -23,7 +24,6 @@ classes.schema = new SimpleSchema({ subscribers: {type: [String], optional: true} }); - work.schema = new SimpleSchema({ name: {type: String}, class: {type: String}, @@ -41,7 +41,19 @@ work.schema = new SimpleSchema({ requests.schema = new SimpleSchema({ requestor: {type: String}, request: {type: String}, - timeRequested: {type: Date} + timeRequested: {type: Date}, + 'info.users': {type: [Object], label: "Debug Users"}, + 'info.userInfo': {type: Object, label: "Debug User Info"}, + 'info.userClasses': {type: [Object], label: "Debug User Classes"} +}); + +userSchema = new SimpleSchema({ + 'profile.name': {type: String, label: "Name"}, + 'profile.grade': {type: Number, label: "Graduation Year"}, + 'profile.school': {type: String, label: "School"}, + 'services.google.email': {type: String, label: "Email"}, + 'services.google.picture': {type: String, label: "Icon URL"}, + 'profile.classes': {type: [String], label: "Classes"} }); schools.attachSchema(schools.schema); diff --git a/hourglass/lib/adminConfig.js b/hourglass/lib/adminConfig.js new file mode 100644 index 0000000..bef4086 --- /dev/null +++ b/hourglass/lib/adminConfig.js @@ -0,0 +1,110 @@ +AdminConfig = { + name: 'Hourglass', + collections: { + schools: { + icon: 'university', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'Name', name: 'name' } + ], + color: 'red', + label: 'Schools' + }, + classes: { + icon: 'graduation-cap', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'School', name: 'school' }, + { label: 'Name', name: 'name' }, + { label: 'Hour', name: 'hour' }, + { label: 'Teacher', name: 'teacher' }, + { 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', template: 'adminUserDisplay' }, + { label: 'Banned', name: 'banned', template: 'adminUserDisplay' }, + { label: 'Subscribers', name: 'subscribers', template: 'adminUserDisplay'} + ], + color: 'blue', + label: 'Classes' + }, + work: { + icon: 'pencil', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'Class', name: 'class' }, + { label: 'Name', name: 'name' }, + { label: 'Due Date', name: 'dueDate' }, + { label: 'Description', name: 'description' }, + { label: 'Creator', name: 'creator', template: 'adminUserDisplay' }, + { label: 'Comments', name: 'comments' }, + { label: 'Confirmations', name: 'confirmations', template: 'adminUserDisplay' }, + { label: 'Reports', name: 'reports', template: 'adminUserDisplay' }, + { label: 'Done', name: 'done', template: 'adminUserDisplay' }, + { label: 'Type', name: 'type' } + ], + color: 'yellow', + label: 'Work' + }, + requests: { + icon: 'exclamation-triangle', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'User', name: 'requestor', template: 'adminUserDisplay' }, + { label: 'Request', name: 'request' }, + { label: 'Time', name: 'timeRequested' } + ], + color: 'green', + label: 'Requests' + }, + 'Meteor.users': { + icon: 'user', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'Email', name: 'services.google.email' }, + { label: 'Name', name: 'profile.name' }, + { label: 'School', name: 'profile.school' }, + { label: 'Graduation Year', name:'profile.grade' }, + { label: 'Icon', name: '_id', template: 'adminUserDisplay' }, + ], + templates: { + new: { + name: 'disableUser' + }, + edit: { + name: 'userEditor' + } + }, + color: 'light-blue', + label: 'Users' + }, + admins: { + icon: 'user-plus', + tableColumns: [ + { label: 'ID', name: '_id' }, + { label: 'Email', name: 'services.google.email' }, + { label: 'Name', name: 'profile.name' }, + { label: 'School', name: 'profile.school' }, + { label: 'Graduation Year', name:'profile.grade' }, + { label: 'Icon', name: '_id', template: 'adminUserDisplay' }, + ], + templates: { + new: { + name: 'createAdmin' + }, + edit: { + name: 'disableUser' + } + }, + selector: function() { + return {roles: {$elemMatch: {$eq: "admin"}}} + }, + showEditColumn: false, + color: 'purple', + label: 'Admins' + }, + + } +}; \ No newline at end of file diff --git a/hourglass/lib/constants.js b/hourglass/lib/constants.js index 79ecb6e..16a9540 100644 --- a/hourglass/lib/constants.js +++ b/hourglass/lib/constants.js @@ -121,79 +121,4 @@ options = { ] } -AdminConfig = { - name: 'Hourglass', - collections: { - schools: { - icon: 'university', - tableColumns: [ - { label: 'ID', name: '_id' }, - { label: 'Name', name: 'name' } - ], - color: 'red', - label: 'Schools' - }, - classes: { - icon: 'graduation-cap', - tableColumns: [ - { label: 'ID', name: '_id' }, - { label: 'School', name: 'school' }, - { label: 'Name', name: 'name' }, - { label: 'Hour', name: 'hour' }, - { label: 'Teacher', name: 'teacher' }, - { 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', template: 'adminUserDisplay' }, - { label: 'Banned', name: 'banned', template: 'adminUserDisplay' }, - { label: 'Subscribers', name: 'subscribers', template: 'adminUserDisplay'} - ], - color: 'blue', - label: 'Classes' - }, - work: { - icon: 'pencil', - tableColumns: [ - { label: 'ID', name: '_id' }, - { label: 'Class', name: 'class' }, - { label: 'Name', name: 'name' }, - { label: 'Due Date', name: 'dueDate' }, - { label: 'Description', name: 'description' }, - { label: 'Creator', name: 'creator', template: 'adminUserDisplay' }, - { label: 'Comments', name: 'comments' }, - { label: 'Confirmations', name: 'confirmations', template: 'adminUserDisplay' }, - { label: 'Reports', name: 'reports', template: 'adminUserDisplay' }, - { label: 'Done', name: 'done', template: 'adminUserDisplay' }, - { label: 'Type', name: 'type' } - ], - color: 'yellow', - label: 'Work' - }, - requests: { - icon: 'exclamation-triangle', - tableColumns: [ - { label: 'ID', name: '_id' }, - { label: 'User', name: 'requestor', template: 'adminUserDisplay' }, - { label: 'Request', name: 'request' }, - { label: 'Time', name: 'timeRequested' } - ], - color: 'green', - label: 'Requests' - }, - 'Meteor.users': { - icon: 'user', - tableColumns: [ - { label: 'ID', name: '_id' }, - { label: 'Email', name: 'services.google.email' }, - { label: 'Name', name: 'profile.name' }, - { label: 'Icon', name: '_id', template: 'adminUserDisplay' } - ], - color: 'purple', - label: 'Users' - } - } -}; - serverData = null; \ No newline at end of file diff --git a/hourglass/lib/router.js b/hourglass/lib/router.js index ebaf3b2..a168743 100644 --- a/hourglass/lib/router.js +++ b/hourglass/lib/router.js @@ -80,19 +80,6 @@ Router.route('/user/:email', { } }); -/*Router.route('/admin', { - data: function() { - return true; - }, - action: function() { - if (!Roles.userIsInRole(Meteor.userId(), ['admin', 'superadmin'])) { - this.redirect("/"); - } else { - this.render("admin"); - } - } -});*/ - Router.configure({ notFoundTemplate: "NotFound" }); diff --git a/hourglass/packages/meteor-admin/lib/client/js/events.coffee b/hourglass/packages/meteor-admin/lib/client/js/events.coffee index e3add30..a69443b 100644 --- a/hourglass/packages/meteor-admin/lib/client/js/events.coffee +++ b/hourglass/packages/meteor-admin/lib/client/js/events.coffee @@ -12,8 +12,15 @@ Template.AdminDeleteModal.events 'click #confirm-delete': () -> collection = Session.get 'admin_collection_name' _id = Session.get 'admin_id' - Meteor.call 'adminRemoveDoc', collection, _id, (e,r)-> - $('#admin-delete-modal').modal('hide') + if collection == 'classes' + Meteor.call 'deleteClass', _id, (e,r) -> + $('#admin-delete-modal').modal('hide') + else if collection == 'admins' + Meteor.call 'deleteAdmin', _id, (e,r) -> + $('#admin-delete-modal').modal('hide') + else + Meteor.call 'adminRemoveDoc', collection, _id, (e,r)-> + $('#admin-delete-modal').modal('hide') Template.AdminDashboardUsersEdit.events 'click .btn-add-role': (e,t) -> diff --git a/hourglass/packages/meteor-admin/lib/client/js/helpers.coffee b/hourglass/packages/meteor-admin/lib/client/js/helpers.coffee index 25ecbd6..8c73c20 100644 --- a/hourglass/packages/meteor-admin/lib/client/js/helpers.coffee +++ b/hourglass/packages/meteor-admin/lib/client/js/helpers.coffee @@ -88,6 +88,8 @@ UI.registerHelper 'adminCollectionLabel', (collection)-> UI.registerHelper 'adminCollectionCount', (collection)-> if collection == 'Users' Meteor.users.find().count() + else if collection == 'admins' + Meteor.users.find({roles: {$elemMatch: {$eq: "admin"}}}).count() else AdminCollectionsCount.findOne({collection: collection})?.count diff --git a/hourglass/server/main.js b/hourglass/server/main.js index 00f7390..db1ec44 100644 --- a/hourglass/server/main.js +++ b/hourglass/server/main.js @@ -15,6 +15,12 @@ var superadmins = [ var worktype = ["test", "quiz", "project", "normal", "other"]; +Meteor.users.allow({ + update: function(userId, doc, fields, modifier) { + return Roles.userIsInRole(userId, ['superadmin']); + } +}); + Meteor.publish('schools', function() { return schools.find(); }); @@ -234,7 +240,7 @@ function securityCheck(checklist, input) { break; // Request too long case 19: - if (typeof input.request !== "string" || input.request.length > 500) error = 16; + if (typeof input.content !== "string" || input.content.length > 500) error = 16; break; // Is valid work type case 20: @@ -258,7 +264,7 @@ function securityCheck(checklist, input) { break; // User is logged in case 25: - if (Meteor.userId === null) error = errors.length - 1; + if (Meteor.userId() === null) error = errors.length - 1; break; } results.push(error);