From 85ac4aac94dcc8700a916fbeaf3393107777d9b4 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 29 Aug 2013 14:55:30 -0400 Subject: [PATCH] group creation and deletion --- public/css/admin.less | 24 +++++++ public/src/forum/admin/groups.js | 70 +++++++++++++++++++++ public/templates/admin/groups.tpl | 100 ++++++++++++++++++++++++++++++ public/templates/admin/header.tpl | 1 + public/templates/config.json | 1 + src/groups.js | 31 +++++---- src/routes/admin.js | 12 +++- src/websockets.js | 25 ++++++++ 8 files changed, 252 insertions(+), 12 deletions(-) create mode 100644 public/src/forum/admin/groups.js create mode 100644 public/templates/admin/groups.tpl diff --git a/public/css/admin.less b/public/css/admin.less index a3b4616261..5f862466e5 100644 --- a/public/css/admin.less +++ b/public/css/admin.less @@ -142,6 +142,30 @@ } } } + + .groups { + li { + list-style-type: none; + margin-bottom: 1em; + padding: 1em; + .zebra; + + h2 { + margin-top: 0; + font-size: 26px; + } + } + + .members { + li { + display: inline-block; + + img { + width: 32px; + } + } + } + } } diff --git a/public/src/forum/admin/groups.js b/public/src/forum/admin/groups.js new file mode 100644 index 0000000000..b5990a4d8d --- /dev/null +++ b/public/src/forum/admin/groups.js @@ -0,0 +1,70 @@ +$(document).ready(function() { + var createEl = document.getElementById('create'), + createModal = $('#create-modal'), + createSubmitBtn = document.getElementById('create-modal-go'), + createNameEl = $('#create-group-name'), + detailsModal = $('#group-details-modal'), + listEl = $('#groups-list'); + + createEl.addEventListener('click', function() { + createModal.modal('show'); + setTimeout(function() { + createNameEl.focus(); + }, 250); + }, false); + + createSubmitBtn.addEventListener('click', function() { + var submitObj = { + name: createNameEl.val(), + description: $('#create-group-desc').val() + }, + errorEl = $('#create-modal-error'), + errorText; + + socket.emit('api:groups.create', submitObj, function(err, data) { + if (err) { + switch(err) { + case 'group-exists': + errorText = 'Please choose another name

There seems to be a group with this name already.

'; + break; + case 'name-too-short': + errorText = 'Please specify a grou name

A group name is required for administrative purposes.

'; + break; + default: + errorText = 'Uh-Oh

There was a problem creating your group. Please try again later!

'; + break; + } + + errorEl.html(errorText).removeClass('hide'); + } else { + createModal.modal('hide'); + errorEl.addClass('hide'); + createNameEl.val(''); + ajaxify.go('admin/groups'); + } + }); + }); + + listEl.on('click', 'button[data-action]', function() { + var action = this.getAttribute('data-action'), + gid = $(this).parents('li[data-gid]').attr('data-gid'); + + switch(action) { + case 'delete': + bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) { + if (confirm) { + socket.emit('api:groups.delete', gid, function(err, data) { + if (data === 'OK') ajaxify.go('admin/groups'); + }); + } + }); + break; + case 'members': + socket.emit('api:groups.get', gid, function(err, groupObj) { + console.log(groupObj); + detailsModal.modal('show'); + }); + break; + } + }); +}); \ No newline at end of file diff --git a/public/templates/admin/groups.tpl b/public/templates/admin/groups.tpl new file mode 100644 index 0000000000..5223a0a116 --- /dev/null +++ b/public/templates/admin/groups.tpl @@ -0,0 +1,100 @@ +

Groups

+ +
+ +
+ + +
+ +
+
+ + + + + + \ No newline at end of file diff --git a/public/templates/admin/header.tpl b/public/templates/admin/header.tpl index 2ec06fdbb1..5847ae259d 100644 --- a/public/templates/admin/header.tpl +++ b/public/templates/admin/header.tpl @@ -74,6 +74,7 @@
  • Home
  • Categories
  • Users
  • +
  • Groups
  • Topics
  • Themes
  • Plugins
  • diff --git a/public/templates/config.json b/public/templates/config.json index d205e35c6f..0414e4da4c 100644 --- a/public/templates/config.json +++ b/public/templates/config.json @@ -13,6 +13,7 @@ "admin/facebook[^]*": "admin/facebook", "admin/gplus[^]*": "admin/gplus", "admin/motd/?$": "admin/motd", + "admin/groups/?$": "admin/groups", "install/?$": "install/mail", "install/mail/?": "install/mail", "install/social/?": "install/social", diff --git a/src/groups.js b/src/groups.js index 0a95912559..0cb4495f35 100644 --- a/src/groups.js +++ b/src/groups.js @@ -1,12 +1,19 @@ var async = require('async'), User = require('./user'), Groups = { - list: function(callback) { + list: function(options, callback) { RDB.hvals('group:gid', function(err, gids) { if (gids.length > 0) { - async.each(gids, function(gid, next) { - Groups.get(gid, next); - }, callback); + async.map(gids, function(gid, next) { + Groups.get(gid, { + expand: options.expand + }, next); + }, function(err, groups) { + callback(err, groups.filter(function(group) { + if (group.deleted === '1') return false; + else return true; + })); + }); } else callback(null, []); }); }, @@ -33,10 +40,10 @@ var async = require('async'), }, function(err, results) { if (err) return callback(err); - results[0].count = results[1].length; - results[0].users = results[1]; + results.base.count = results.users.length; + results.base.members = results.users; - callback(err, results[0]); + callback(err, results.base); }); }, getGidFromName: function(name, callback) { @@ -49,26 +56,28 @@ var async = require('async'), RDB.hexists('group:gid', name, callback); }, create: function(name, description, callback) { + if (name.length === 0) return callback(new Error('name-too-short')); + Groups.exists(name, function(err, exists) { if (!exists) { RDB.incr('next_gid', function(err, gid) { RDB.multi() .hset('group:gid', name, gid) - .hset('gid:' + gid, { + .hmset('gid:' + gid, { gid: gid, name: name, description: description, deleted: '0' }) .exec(function(err) { - callback(err, gid); + Groups.get(gid, {}, callback); }); }); - } + } else callback(new Error('group-exists')) }); }, destroy: function(gid, callback) { - RDB.hset('gid:' + gid, deleted, '1', callback); + RDB.hset('gid:' + gid, 'deleted', '1', callback); }, join: function(gid, uid, callback) { RDB.sadd('gid:' + gid + ':members', uid, callback); diff --git a/src/routes/admin.js b/src/routes/admin.js index 524712ea3f..f3b72d4d3d 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -1,5 +1,6 @@ var user = require('./../user.js'), + Groups = require('../groups'), topics = require('./../topics.js'), RDB = require('./../redis.js'), pkg = require('./../../package.json'), @@ -27,7 +28,7 @@ var user = require('./../user.js'), (function() { var routes = [ 'categories/active', 'categories/disabled', 'users', 'topics', 'settings', 'themes', - 'twitter', 'facebook', 'gplus', 'redis', 'motd', + 'twitter', 'facebook', 'gplus', 'redis', 'motd', 'groups', 'users/latest', 'users/sort-posts', 'users/sort-reputation', 'users/search', 'plugins' ]; @@ -189,6 +190,15 @@ var user = require('./../user.js'), res.json(200, {}); }); + app.get('/api/admin/groups', function(req, res) { + Groups.list({ + expand: true + }, function(err, groups) { + res.json(200, { + groups: groups + }); + }); + }); }; diff --git a/src/websockets.js b/src/websockets.js index f75eeda2a0..8f07e6575e 100644 --- a/src/websockets.js +++ b/src/websockets.js @@ -3,6 +3,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }), cookie = require('cookie'), express = require('express'), user = require('./user.js'), + Groups = require('./groups'), posts = require('./posts.js'), favourites = require('./favourites.js'), utils = require('../public/src/utils.js'), @@ -817,6 +818,30 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }), callback(title, numNotifications); }); }); + + /* + GROUPS + */ + + socket.on('api:groups.create', function(data, callback) { + Groups.create(data.name, data.description, function(err, groupObj) { + callback(err ? err.message : null, groupObj || undefined); + }); + }); + + socket.on('api:groups.delete', function(gid, callback) { + Groups.destroy(gid, function(err) { + callback(err ? err.message : null, err ? null : 'OK'); + }); + }); + + socket.on('api:groups.get', function(gid, callback) { + Groups.get(gid, { + expand: true + }, function(err, groupObj) { + callback(err ? err.message : null, groupObj || undefined); + }); + }); }); }(SocketIO));