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 @@
+
+
+
+ {{#if superAdmin}}
+ {{> quickForm id="editUser" collection="Meteor.users" doc=userInfo schema="userSchema" type="update"}}
+ {{else}}
+ You are not authorized to edit users.
+ {{/if}}
+
+
+
+ {{#if superAdmin}}
+
+
Search
+
+ {{> inputAutocomplete settings=userComplete class="form-control addAdmin" type="text" placeholder="Example: 1234@abc.xyz" }}
+
+
+
+ {{else}}
+ {{> disableUser}}
+ {{/if}}
+
+
+
+ You are not authorized to edit this.
+
+
+
+
+
+
{{profile.name}}
+
{{services.google.email}}
+
\ 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);