mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-10 20:53:11 +02:00
closes #2132
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
@import "./manage/categories";
|
||||
@import "./manage/groups";
|
||||
@import "./manage/tags";
|
||||
@import "./manage/flags";
|
||||
@import "./manage/users";
|
||||
@import "./appearance/customise";
|
||||
@import "./appearance/themes";
|
||||
@@ -23,6 +24,11 @@
|
||||
padding: 0px 15px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width:24px;
|
||||
height:24px;
|
||||
}
|
||||
|
||||
.nodebb-logo {
|
||||
img {
|
||||
height: 31px;
|
||||
@@ -44,7 +50,7 @@
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
|
||||
|
||||
|
||||
-webkit-transform: translateX(-190px);
|
||||
transform: translateX(-190px);
|
||||
|
||||
@@ -81,7 +87,7 @@
|
||||
max-height: 100%;
|
||||
cursor: pointer;
|
||||
max-height: 38px;
|
||||
|
||||
|
||||
&.open {
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
1
public/less/admin/manage/flags.less
Normal file
1
public/less/admin/manage/flags.less
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
68
public/src/forum/admin/manage/flags.js
Normal file
68
public/src/forum/admin/manage/flags.js
Normal file
@@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
/*global define, socket, app, admin, utils, bootbox, RELATIVE_PATH*/
|
||||
|
||||
define('forum/admin/manage/flags', ['forum/infinitescroll', 'admin/selectable'], function(infinitescroll, selectable) {
|
||||
var Flags = {};
|
||||
|
||||
Flags.init = function() {
|
||||
handleDismiss();
|
||||
handleDelete();
|
||||
handleInfiniteScroll();
|
||||
};
|
||||
|
||||
function handleDismiss() {
|
||||
$('.flags').on('click', '.dismiss', function() {
|
||||
var btn = $(this);
|
||||
var pid = btn.siblings('[data-pid]').attr('data-pid');
|
||||
|
||||
socket.emit('admin.dismissFlag', pid, function(err) {
|
||||
done(err, btn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleDelete() {
|
||||
$('.flags').on('click', '.delete', function() {
|
||||
var btn = $(this);
|
||||
var pid = btn.siblings('[data-pid]').attr('data-pid');
|
||||
var tid = btn.siblings('[data-pid]').attr('data-tid');
|
||||
socket.emit('posts.delete', {pid: pid, tid: tid}, function(err) {
|
||||
done(err, btn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function done(err, btn) {
|
||||
if (err) {
|
||||
return app.alertError(err.messaage);
|
||||
}
|
||||
btn.parent().fadeOut(function() {
|
||||
btn.remove();
|
||||
});
|
||||
if (!$('.flags [data-pid]').length) {
|
||||
$('.post-container').text('No flagged posts!');
|
||||
}
|
||||
}
|
||||
|
||||
function handleInfiniteScroll() {
|
||||
infinitescroll.init(function(direction) {
|
||||
if (direction < 0 && !$('.flags').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
infinitescroll.loadMore('admin.getMoreFlags', $('[data-next]').attr('data-next'), function(data, done) {
|
||||
if (data.posts && data.posts.length) {
|
||||
infinitescroll.parseAndTranslate('admin/manage/flags', 'posts', {posts: data.posts}, function(html) {
|
||||
$('[data-next]').attr('data-next', data.next);
|
||||
$('.post-container').append(html);
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Flags;
|
||||
});
|
||||
@@ -6,6 +6,7 @@ var async = require('async'),
|
||||
|
||||
user = require('../user'),
|
||||
categories = require('../categories'),
|
||||
posts = require('../posts'),
|
||||
topics = require('../topics'),
|
||||
meta = require('../meta'),
|
||||
db = require('../database'),
|
||||
@@ -21,6 +22,7 @@ var async = require('async'),
|
||||
var adminController = {
|
||||
categories: {},
|
||||
tags: {},
|
||||
flags: {},
|
||||
topics: {},
|
||||
groups: {},
|
||||
appearance: {},
|
||||
@@ -154,6 +156,17 @@ adminController.tags.get = function(req, res, next) {
|
||||
});
|
||||
};
|
||||
|
||||
adminController.flags.get = function(req, res, next) {
|
||||
var uid = req.user ? parseInt(req.user.uid, 10) : 0;
|
||||
posts.getFlags(uid, 0, 19, function(err, posts) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.render('admin/manage/flags', {posts: posts, next: 20});
|
||||
});
|
||||
};
|
||||
|
||||
adminController.database.get = function(req, res, next) {
|
||||
db.info(function (err, data) {
|
||||
res.render('admin/advanced/database', data);
|
||||
|
||||
@@ -28,6 +28,7 @@ var async = require('async'),
|
||||
(function(Posts) {
|
||||
require('./posts/recent')(Posts);
|
||||
require('./posts/delete')(Posts);
|
||||
require('./posts/flags')(Posts);
|
||||
|
||||
Posts.create = function(data, callback) {
|
||||
var uid = data.uid,
|
||||
@@ -237,6 +238,7 @@ var async = require('async'),
|
||||
Posts.getPostSummaryByPids = function(pids, uid, options, callback) {
|
||||
options.stripTags = options.hasOwnProperty('stripTags') ? options.stripTags : false;
|
||||
options.parse = options.hasOwnProperty('parse') ? options.parse : true;
|
||||
options.extraFields = options.hasOwnProperty('extraFields') ? options.extraFields : [];
|
||||
|
||||
if (!Array.isArray(pids) || !pids.length) {
|
||||
return callback(null, []);
|
||||
@@ -246,7 +248,9 @@ var async = require('async'),
|
||||
return 'post:' + pid;
|
||||
});
|
||||
|
||||
db.getObjectsFields(keys, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(err, posts) {
|
||||
var fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'].concat(options.extraFields);
|
||||
|
||||
db.getObjectsFields(keys, fields, function(err, posts) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
45
src/posts/flags.js
Normal file
45
src/posts/flags.js
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
db = require('../database');
|
||||
|
||||
|
||||
module.exports = function(Posts) {
|
||||
Posts.flag = function(pid, callback) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
db.sortedSetAdd('posts:flagged', Date.now(), pid, next);
|
||||
},
|
||||
function(next) {
|
||||
db.incrObjectField('post:' + pid, 'flags', next);
|
||||
}
|
||||
], function(err, results) {
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
Posts.dismissFlag = function(pid, callback) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
db.sortedSetRemove('posts:flagged', pid, next);
|
||||
},
|
||||
function(next) {
|
||||
db.deleteObjectField('post:' + pid, 'flags', next);
|
||||
}
|
||||
], function(err, results) {
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
Posts.getFlags = function(uid, start, end, callback) {
|
||||
db.getSortedSetRevRange('posts:flagged', start, end, function(err, pids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
Posts.getPostSummaryByPids(pids, uid, {stripTags: false, extraFields: ['flags']}, callback);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -46,6 +46,8 @@ function addRoutes(router, middleware, controllers) {
|
||||
|
||||
router.get('/manage/tags', controllers.admin.tags.get);
|
||||
|
||||
router.get('/manage/flags', controllers.admin.flags.get);
|
||||
|
||||
router.get('/manage/users', controllers.admin.users.sortByJoinDate);
|
||||
router.get('/manage/users/search', controllers.admin.users.search);
|
||||
router.get('/manage/users/latest', controllers.admin.users.sortByJoinDate);
|
||||
|
||||
@@ -12,6 +12,7 @@ var async = require('async'),
|
||||
widgets = require('../widgets'),
|
||||
user = require('../user'),
|
||||
topics = require('../topics'),
|
||||
posts = require('../posts'),
|
||||
categories = require('../categories'),
|
||||
logger = require('../logger'),
|
||||
events = require('../events'),
|
||||
@@ -249,4 +250,22 @@ SocketAdmin.getMoreEvents = function(socket, next, callback) {
|
||||
};
|
||||
|
||||
|
||||
SocketAdmin.dismissFlag = function(socket, pid, callback) {
|
||||
if (!pid) {
|
||||
return callback('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
posts.dismissFlag(pid, callback);
|
||||
};
|
||||
|
||||
SocketAdmin.getMoreFlags = function(socket, after, callback) {
|
||||
if (!parseInt(after, 10)) {
|
||||
return callback('[[error:invalid-data]]');
|
||||
}
|
||||
after = parseInt(after, 10);
|
||||
posts.getFlags(socket.uid, after, after + 19, function(err, posts) {
|
||||
callback(err, {posts: posts, next: after + 20});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = SocketAdmin;
|
||||
|
||||
@@ -322,6 +322,9 @@ SocketPosts.flag = function(socket, pid, callback) {
|
||||
notifications.push(notification, adminGroup.members, next);
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
posts.flag(pid, next);
|
||||
},
|
||||
function(next) {
|
||||
if (!parseInt(post.uid, 10)) {
|
||||
return next();
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
<li><a href="{relative_path}/admin/manage/tags">Tags</a></li>
|
||||
<li><a href="{relative_path}/admin/manage/users">Users</a></li>
|
||||
<li><a href="{relative_path}/admin/manage/groups">Groups</a></li>
|
||||
<li><a href="{relative_path}/admin/manage/flags">Flags</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sidebar-nav">
|
||||
|
||||
46
src/views/admin/manage/flags.tpl
Normal file
46
src/views/admin/manage/flags.tpl
Normal file
@@ -0,0 +1,46 @@
|
||||
<div class="flags">
|
||||
<div class="col-lg-9">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-flag"></i> Flags</div>
|
||||
<div class="panel-body post-container" data-next="{next}">
|
||||
|
||||
<!-- IF !posts.length -->
|
||||
No flagged posts!
|
||||
<!-- ENDIF !posts.length-->
|
||||
|
||||
<!-- BEGIN posts -->
|
||||
<div>
|
||||
<div class="panel panel-default" data-pid="{posts.pid}" data-tid="{posts.topic.tid}">
|
||||
<div class="panel-body">
|
||||
<a href="{relative_path}/user/{posts.user.userslug}">
|
||||
<img title="{posts.user.username}" class="img-rounded user-img" src="{posts.user.picture}">
|
||||
</a>
|
||||
|
||||
<a href="{relative_path}/user/{posts.user.userslug}">
|
||||
<strong><span>{posts.user.username}</span></strong>
|
||||
</a>
|
||||
<div class="content">
|
||||
<p>{posts.content}</p>
|
||||
<p class="fade-out"></p>
|
||||
</div>
|
||||
<small>
|
||||
<span class="pull-right footer">
|
||||
Posted in <a href="{relative_path}/category/{posts.category.slug}"><i class="fa {posts.category.icon}"></i> {posts.category.name}</a>, <span class="timeago" title="{posts.relativeTime}"></span> •
|
||||
<a href="{relative_path}/topic/{posts.topic.slug}/{posts.index}">Read More</a>
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="badge badge-warning"><i class="fa fa-flag"></i> {posts.flags}</span>
|
||||
<button class="btn btn-warning dismiss">Dismiss</button>
|
||||
<button class="btn btn-danger delete">Delete</button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
<!-- END posts -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user