Merge branch 'master' of git://github.com/Abijeet/BookStack into Abijeet-master

This commit is contained in:
Dan Brown
2017-08-01 19:24:33 +01:00
42 changed files with 1420 additions and 11 deletions

View File

@ -675,4 +675,225 @@ module.exports = function (ngApp, events) {
}]);
// Controller used to reply to and add new comments
ngApp.controller('CommentReplyController', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
const MarkdownIt = require("markdown-it");
const md = new MarkdownIt({html: true});
let vm = this;
vm.saveComment = function () {
let pageId = $scope.comment.pageId || $scope.pageId;
let comment = $scope.comment.text;
if (!comment) {
return events.emit('warning', trans('errors.empty_comment'));
}
let commentHTML = md.render($scope.comment.text);
let serviceUrl = `/ajax/page/${pageId}/comment/`;
let httpMethod = 'post';
let reqObj = {
text: comment,
html: commentHTML
};
if ($scope.isEdit === true) {
// this will be set when editing the comment.
serviceUrl = `/ajax/page/${pageId}/comment/${$scope.comment.id}`;
httpMethod = 'put';
} else if ($scope.isReply === true) {
// if its reply, get the parent comment id
reqObj.parent_id = $scope.parentId;
}
$http[httpMethod](window.baseUrl(serviceUrl), reqObj).then(resp => {
if (!isCommentOpSuccess(resp)) {
return;
}
// hide the comments first, and then retrigger the refresh
if ($scope.isEdit) {
updateComment($scope.comment, resp.data);
$scope.$emit('evt.comment-success', $scope.comment.id);
} else {
$scope.comment.text = '';
if ($scope.isReply === true && $scope.parent.sub_comments) {
$scope.parent.sub_comments.push(resp.data.comment);
} else {
$scope.$emit('evt.new-comment', resp.data.comment);
}
$scope.$emit('evt.comment-success', null, true);
}
$scope.comment.is_hidden = true;
$timeout(function() {
$scope.comment.is_hidden = false;
});
events.emit('success', trans(resp.data.message));
}, checkError);
};
function checkError(response) {
let msg = null;
if (isCommentOpSuccess(response)) {
// all good
return;
} else if (response.data) {
msg = response.data.message;
} else {
msg = trans('errors.comment_add');
}
if (msg) {
events.emit('success', msg);
}
}
}]);
// Controller used to delete comments
ngApp.controller('CommentDeleteController', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
let vm = this;
vm.delete = function(comment) {
$http.delete(window.baseUrl(`/ajax/comment/${comment.id}`)).then(resp => {
if (!isCommentOpSuccess(resp)) {
return;
}
updateComment(comment, resp.data, $timeout, true);
}, function (resp) {
if (isCommentOpSuccess(resp)) {
events.emit('success', trans('entities.comment_deleted'));
} else {
events.emit('error', trans('error.comment_delete'));
}
});
};
}]);
// Controller used to fetch all comments for a page
ngApp.controller('CommentListController', ['$scope', '$http', '$timeout', '$location', function ($scope, $http, $timeout, $location) {
let vm = this;
$scope.errors = {};
// keep track of comment levels
$scope.level = 1;
vm.totalCommentsStr = trans('entities.comments_loading');
vm.permissions = {};
vm.trans = window.trans;
$scope.$on('evt.new-comment', function (event, comment) {
// add the comment to the comment list.
vm.comments.push(comment);
++vm.totalComments;
setTotalCommentMsg();
event.stopPropagation();
event.preventDefault();
});
vm.canEditDelete = function (comment, prop) {
if (!comment.active) {
return false;
}
let propAll = prop + '_all';
let propOwn = prop + '_own';
if (vm.permissions[propAll]) {
return true;
}
if (vm.permissions[propOwn] && comment.created_by.id === vm.current_user_id) {
return true;
}
return false;
};
vm.canComment = function () {
return vm.permissions.comment_create;
};
// check if there are is any direct linking
let linkedCommentId = $location.search().cm;
$timeout(function() {
$http.get(window.baseUrl(`/ajax/page/${$scope.pageId}/comments/`)).then(resp => {
if (!isCommentOpSuccess(resp)) {
// just show that no comments are available.
vm.totalComments = 0;
setTotalCommentMsg();
return;
}
vm.comments = resp.data.comments;
vm.totalComments = +resp.data.total;
vm.permissions = resp.data.permissions;
vm.current_user_id = resp.data.user_id;
setTotalCommentMsg();
if (!linkedCommentId) {
return;
}
$timeout(function() {
// wait for the UI to render.
focusLinkedComment(linkedCommentId);
});
}, checkError);
});
function setTotalCommentMsg () {
if (vm.totalComments === 0) {
vm.totalCommentsStr = trans('entities.no_comments');
} else if (vm.totalComments === 1) {
vm.totalCommentsStr = trans('entities.one_comment');
} else {
vm.totalCommentsStr = trans('entities.x_comments', {
numComments: vm.totalComments
});
}
}
function focusLinkedComment(linkedCommentId) {
let comment = angular.element('#' + linkedCommentId);
if (comment.length === 0) {
return;
}
window.setupPageShow.goToText(linkedCommentId);
}
function checkError(response) {
let msg = null;
if (isCommentOpSuccess(response)) {
// all good
return;
} else if (response.data) {
msg = response.data.message;
} else {
msg = trans('errors.comment_list');
}
if (msg) {
events.emit('success', msg);
}
}
}]);
function updateComment(comment, resp, $timeout, isDelete) {
comment.text = resp.comment.text;
comment.updated = resp.comment.updated;
comment.updated_by = resp.comment.updated_by;
comment.active = resp.comment.active;
if (isDelete && !resp.comment.active) {
comment.html = trans('entities.comment_deleted');
} else {
comment.html = resp.comment.html;
}
if (!$timeout) {
return;
}
comment.is_hidden = true;
$timeout(function() {
comment.is_hidden = false;
});
}
function isCommentOpSuccess(resp) {
if (resp && resp.data && resp.data.status === 'success') {
return true;
}
return false;
}
};

View File

@ -863,4 +863,128 @@ module.exports = function (ngApp, events) {
}
};
}]);
ngApp.directive('commentReply', [function () {
return {
restrict: 'E',
templateUrl: 'comment-reply.html',
scope: {
pageId: '=',
parentId: '=',
parent: '='
},
link: function (scope, element) {
scope.isReply = true;
element.find('textarea').focus();
scope.$on('evt.comment-success', function (event) {
// no need for the event to do anything more.
event.stopPropagation();
event.preventDefault();
scope.closeBox();
});
scope.closeBox = function () {
element.remove();
scope.$destroy();
};
}
};
}]);
ngApp.directive('commentEdit', [function () {
return {
restrict: 'E',
templateUrl: 'comment-reply.html',
scope: {
comment: '='
},
link: function (scope, element) {
scope.isEdit = true;
element.find('textarea').focus();
scope.$on('evt.comment-success', function (event, commentId) {
// no need for the event to do anything more.
event.stopPropagation();
event.preventDefault();
if (commentId === scope.comment.id && !scope.isNew) {
scope.closeBox();
}
});
scope.closeBox = function () {
element.remove();
scope.$destroy();
};
}
};
}]);
ngApp.directive('commentReplyLink', ['$document', '$compile', function ($document, $compile) {
return {
scope: {
comment: '='
},
link: function (scope, element, attr) {
element.on('$destroy', function () {
element.off('click');
scope.$destroy();
});
element.on('click', function (e) {
e.preventDefault();
var $container = element.parents('.comment-actions').first();
if (!$container.length) {
console.error('commentReplyLink directive should be placed inside a container with class comment-box!');
return;
}
if (attr.noCommentReplyDupe) {
removeDupe();
}
compileHtml($container, scope, attr.isReply === 'true');
});
}
};
function compileHtml($container, scope, isReply) {
let lnkFunc = null;
if (isReply) {
lnkFunc = $compile('<comment-reply page-id="comment.pageId" parent-id="comment.id" parent="comment"></comment-reply>');
} else {
lnkFunc = $compile('<comment-edit comment="comment"></comment-add>');
}
var compiledHTML = lnkFunc(scope);
$container.append(compiledHTML);
}
function removeDupe() {
let $existingElement = $document.find('.comments-list comment-reply, .comments-list comment-edit');
if (!$existingElement.length) {
return;
}
$existingElement.remove();
}
}]);
ngApp.directive('commentDeleteLink', ['$window', function ($window) {
return {
controller: 'CommentDeleteController',
scope: {
comment: '='
},
link: function (scope, element, attr, ctrl) {
element.on('click', function(e) {
e.preventDefault();
var resp = $window.confirm(trans('entities.comment_delete_confirm'));
if (!resp) {
return;
}
ctrl.delete(scope.comment);
});
}
};
}]);
};

View File

@ -161,6 +161,8 @@ let setupPageShow = window.setupPageShow = function (pageId) {
}
});
// in order to call from other places.
window.setupPageShow.goToText = goToText;
};
module.exports = setupPageShow;