Added comment presenters
This commit is contained in:
parent
16c5740277
commit
16f9c277a1
23 changed files with 577 additions and 81 deletions
5
TODO
5
TODO
|
@ -51,11 +51,6 @@ everything related to tags:
|
||||||
- tag edit history
|
- tag edit history
|
||||||
|
|
||||||
everything related to comments:
|
everything related to comments:
|
||||||
- adding comments
|
|
||||||
- listing comments in post view
|
|
||||||
- listing comments in comment list view
|
|
||||||
- deleting
|
|
||||||
- editing
|
|
||||||
- markdown
|
- markdown
|
||||||
- score
|
- score
|
||||||
|
|
||||||
|
|
92
public_html/css/comments.css
Normal file
92
public_html/css/comments.css
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
.comment-form {
|
||||||
|
margin: 1em 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form .preview {
|
||||||
|
background: lemonchiffon;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5) inset;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment .body,
|
||||||
|
.comment .avatar {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment .avatar {
|
||||||
|
margin-right: 0.5em;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment .content {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment .header {
|
||||||
|
line-height: 16pt;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.comment .date {
|
||||||
|
color: silver;
|
||||||
|
font-size: 80%;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
.comment .header .ops a {
|
||||||
|
color: silver;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
.comment .header .ops a:before {
|
||||||
|
content: '[';
|
||||||
|
}
|
||||||
|
.comment .header .ops a:after {
|
||||||
|
content: ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
#global-comment-list {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#global-comment-list .pagination-content {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
#global-comment-list .comments>ul {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
#global-comment-list ul.posts {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#global-comment-list ul.posts>li>*:last-child:after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
#global-comment-list ul.posts>li {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
#global-comment-list .post {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
#global-comment-list .comment-add,
|
||||||
|
#global-comment-list h1 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#global-comment-list .comments {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
#global-comment-list .post-small a {
|
||||||
|
margin: 0 1em 0 0;
|
||||||
|
}
|
|
@ -9,6 +9,11 @@ body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-variant: small-caps;
|
font-variant: small-caps;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
|
@ -23,32 +23,33 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li a {
|
.post-small a {
|
||||||
display: block;
|
display: inline-block;
|
||||||
margin: 0.4em;
|
margin: 0.4em;
|
||||||
border: 1px solid #999;
|
border: 1px solid #999;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#post-list .posts li img {
|
.post-small img {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li a:focus,
|
.post-small a:focus,
|
||||||
#post-list .posts li a:hover {
|
.post-small a:hover {
|
||||||
background: #afe;
|
background: #afe;
|
||||||
border-color: #5da;
|
border-color: #5da;
|
||||||
box-shadow: 0 0 0 2px #5da;
|
box-shadow: 0 0 0 2px #5da;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li a:focus img,
|
.post-small a:focus img,
|
||||||
#post-list .posts li a:hover img {
|
.post-small a:hover img {
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li a .info {
|
.post-small a .info {
|
||||||
display: none;
|
display: none;
|
||||||
|
text-align: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -56,16 +57,22 @@
|
||||||
background: #5da;
|
background: #5da;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
#post-list .posts li a .info li {
|
.post-small a .info ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.post-small a .info li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0.1em 0.5em;
|
margin: 0.1em 0.5em;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
#post-list .posts li a:focus .info,
|
.post-small a:focus .info,
|
||||||
#post-list .posts li a:hover .info {
|
.post-small a:hover .info {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li:not(.post-type-image) a:before {
|
.post-small:not(.post-type-image) a:before {
|
||||||
display: block;
|
display: block;
|
||||||
content: '';
|
content: '';
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
@ -78,7 +85,7 @@
|
||||||
border-left: 50px solid transparent;
|
border-left: 50px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-list .posts li:not(.post-type-image) a:after {
|
.post-small:not(.post-type-image) a:after {
|
||||||
display: block;
|
display: block;
|
||||||
content: '...';
|
content: '...';
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
@ -93,13 +100,13 @@
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
#post-list .posts li.post-type-youtube a:after {
|
.post-small.post-type-youtube a:after {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
content: 'youtube';
|
content: 'youtube';
|
||||||
}
|
}
|
||||||
#post-list .posts li.post-type-video a:after {
|
.post-small.post-type-video a:after {
|
||||||
content: 'video';
|
content: 'video';
|
||||||
}
|
}
|
||||||
#post-list .posts li.post-type-flash a:after {
|
.post-small.post-type-flash a:after {
|
||||||
content: 'flash';
|
content: 'flash';
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
#post-view-wrapper #sidebar h1 {
|
#post-view-wrapper #sidebar h1 {
|
||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
font-weight: normal;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#post-view-wrapper #sidebar h1:first-of-type {
|
#post-view-wrapper #sidebar h1:first-of-type {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/css/post.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/post.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/history.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/history.css"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/comments.css"/>
|
||||||
<!-- /build -->
|
<!-- /build -->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -96,7 +97,8 @@
|
||||||
<script type="text/javascript" src="/js/Presenters/PostUploadPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/PostUploadPresenter.js"></script>
|
||||||
<script type="text/javascript" src="/js/Presenters/PostPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/PostPresenter.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/Presenters/CommentListPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/GlobalCommentListPresenter.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/Presenters/PostCommentListPresenter.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/Presenters/TagListPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/TagListPresenter.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
var App = App || {};
|
|
||||||
App.Presenters = App.Presenters || {};
|
|
||||||
|
|
||||||
App.Presenters.CommentListPresenter = function(
|
|
||||||
jQuery,
|
|
||||||
topNavigationPresenter) {
|
|
||||||
|
|
||||||
var $el = jQuery('#content');
|
|
||||||
|
|
||||||
function init(args, loaded) {
|
|
||||||
topNavigationPresenter.select('comments');
|
|
||||||
topNavigationPresenter.changeTitle('Comments');
|
|
||||||
render();
|
|
||||||
loaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
$el.html('Comment list placeholder');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
init: init,
|
|
||||||
render: render,
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
App.DI.register('commentListPresenter', ['jQuery', 'topNavigationPresenter'], App.Presenters.CommentListPresenter);
|
|
110
public_html/js/Presenters/GlobalCommentListPresenter.js
Normal file
110
public_html/js/Presenters/GlobalCommentListPresenter.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
var App = App || {};
|
||||||
|
App.Presenters = App.Presenters || {};
|
||||||
|
|
||||||
|
App.Presenters.GlobalCommentListPresenter = function(
|
||||||
|
_,
|
||||||
|
jQuery,
|
||||||
|
util,
|
||||||
|
promise,
|
||||||
|
pagerPresenter,
|
||||||
|
topNavigationPresenter) {
|
||||||
|
|
||||||
|
var $el;
|
||||||
|
var listTemplate;
|
||||||
|
var itemTemplate;
|
||||||
|
var postTemplate;
|
||||||
|
|
||||||
|
function init(args, loaded) {
|
||||||
|
$el = jQuery('#content');
|
||||||
|
topNavigationPresenter.select('comments');
|
||||||
|
|
||||||
|
promise.wait(
|
||||||
|
util.promiseTemplate('global-comment-list'),
|
||||||
|
util.promiseTemplate('global-comment-list-item'),
|
||||||
|
util.promiseTemplate('post-list-item'))
|
||||||
|
.then(function(listHtml, listItemHtml, postItemHtml)
|
||||||
|
{
|
||||||
|
listTemplate = _.template(listHtml);
|
||||||
|
itemTemplate = _.template(listItemHtml);
|
||||||
|
postTemplate = _.template(postItemHtml);
|
||||||
|
|
||||||
|
render();
|
||||||
|
loaded();
|
||||||
|
|
||||||
|
pagerPresenter.init({
|
||||||
|
baseUri: '#/comments',
|
||||||
|
backendUri: '/comments',
|
||||||
|
$target: $el.find('.pagination-target'),
|
||||||
|
updateCallback: function(data, clear) {
|
||||||
|
renderPosts(data.entities, clear);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
onArgsChanged(args);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.fail(function() { console.log(new Error(arguments)); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reinit(args, loaded) {
|
||||||
|
loaded();
|
||||||
|
onArgsChanged(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onArgsChanged(args) {
|
||||||
|
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
|
||||||
|
pagerPresenter.reinit({
|
||||||
|
page: searchArgs.page,
|
||||||
|
searchParams: {
|
||||||
|
query: searchArgs.query,
|
||||||
|
order: searchArgs.order}});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deinit() {
|
||||||
|
pagerPresenter.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
$el.html(listTemplate());
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPosts(data, clear) {
|
||||||
|
var $target = $el.find('.posts');
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
$target.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(data, function(data) {
|
||||||
|
var post = data.post;
|
||||||
|
var comments = data.comments;
|
||||||
|
|
||||||
|
var $post = jQuery('<li>' + itemTemplate({
|
||||||
|
post: post,
|
||||||
|
postTemplate: postTemplate,
|
||||||
|
}) + '</li>');
|
||||||
|
|
||||||
|
var presenter = App.DI.get('postCommentListPresenter');
|
||||||
|
|
||||||
|
presenter.init({
|
||||||
|
post: post,
|
||||||
|
comments: comments,
|
||||||
|
$target: $post.find('.post-comments-target'),
|
||||||
|
}, function() {
|
||||||
|
presenter.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
$target.append($post);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init,
|
||||||
|
reinit: reinit,
|
||||||
|
deinit: deinit,
|
||||||
|
render: render,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
App.DI.register('globalCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'pagerPresenter', 'topNavigationPresenter'], App.Presenters.GlobalCommentListPresenter);
|
|
@ -100,9 +100,8 @@ App.Presenters.PagerPresenter = function(
|
||||||
return util.compileComplexRouteArgs(
|
return util.compileComplexRouteArgs(
|
||||||
baseUri,
|
baseUri,
|
||||||
_.extend(
|
_.extend(
|
||||||
{},
|
{page: pager.getPage()},
|
||||||
pager.getSearchParams(),
|
pager.getSearchParams()));
|
||||||
{page: pager.getPage()}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncUrl() {
|
function syncUrl() {
|
||||||
|
|
194
public_html/js/Presenters/PostCommentListPresenter.js
Normal file
194
public_html/js/Presenters/PostCommentListPresenter.js
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
var App = App || {};
|
||||||
|
App.Presenters = App.Presenters || {};
|
||||||
|
|
||||||
|
App.Presenters.PostCommentListPresenter = function(
|
||||||
|
_,
|
||||||
|
jQuery,
|
||||||
|
util,
|
||||||
|
promise,
|
||||||
|
api,
|
||||||
|
auth,
|
||||||
|
topNavigationPresenter,
|
||||||
|
messagePresenter) {
|
||||||
|
|
||||||
|
var $el;
|
||||||
|
var commentListTemplate;
|
||||||
|
var commentListItemTemplate;
|
||||||
|
var commentFormTemplate;
|
||||||
|
var privileges;
|
||||||
|
|
||||||
|
var post;
|
||||||
|
var comments = [];
|
||||||
|
|
||||||
|
function init(args, loaded) {
|
||||||
|
$el = args.$target;
|
||||||
|
post = args.post;
|
||||||
|
comments = args.comments || [];
|
||||||
|
|
||||||
|
privileges = {
|
||||||
|
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||||
|
canAddComments: auth.hasPrivilege(auth.privileges.addComments),
|
||||||
|
editOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
|
||||||
|
editAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
|
||||||
|
deleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
|
||||||
|
deleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
|
||||||
|
};
|
||||||
|
|
||||||
|
promise.wait(
|
||||||
|
util.promiseTemplate('post-comment-list'),
|
||||||
|
util.promiseTemplate('comment-list-item'),
|
||||||
|
util.promiseTemplate('comment-form'),
|
||||||
|
comments.length === 0 ? api.get('/comments/' + args.post.id) : null)
|
||||||
|
.then(function(
|
||||||
|
commentListHtml,
|
||||||
|
commentListItemHtml,
|
||||||
|
commentFormHtml,
|
||||||
|
commentsResponse)
|
||||||
|
{
|
||||||
|
commentListTemplate = _.template(commentListHtml);
|
||||||
|
commentListItemTemplate = _.template(commentListItemHtml);
|
||||||
|
commentFormTemplate = _.template(commentFormHtml);
|
||||||
|
if (commentsResponse) {
|
||||||
|
comments = commentsResponse.json.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
render();
|
||||||
|
loaded();
|
||||||
|
})
|
||||||
|
.fail(function() { console.log(new Error(arguments)); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
$el.html(commentListTemplate(
|
||||||
|
_.extend(
|
||||||
|
{
|
||||||
|
commentListItemTemplate: commentListItemTemplate,
|
||||||
|
commentFormTemplate: commentFormTemplate,
|
||||||
|
formatRelativeTime: util.formatRelativeTime,
|
||||||
|
formatMarkdown: util.formatMarkdown,
|
||||||
|
comments: comments,
|
||||||
|
post: post,
|
||||||
|
},
|
||||||
|
privileges)));
|
||||||
|
|
||||||
|
$el.find('.comment-add form button[type=submit]').click(function(e) { commentFormSubmitted(e, null); });
|
||||||
|
renderComments(comments, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderComments(comments, clear) {
|
||||||
|
var $target = $el.find('.comments');
|
||||||
|
var $targetList = $el.find('ul');
|
||||||
|
|
||||||
|
if (comments.length > 0) {
|
||||||
|
$target.show();
|
||||||
|
} else {
|
||||||
|
$target.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
$targetList.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(comments, function(comment) {
|
||||||
|
renderComment($targetList, comment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderComment($targetList, comment) {
|
||||||
|
var $item = jQuery('<li>' + commentListItemTemplate({
|
||||||
|
comment: comment,
|
||||||
|
formatRelativeTime: util.formatRelativeTime,
|
||||||
|
formatMarkdown: util.formatMarkdown,
|
||||||
|
canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.editOwnComments : privileges.editAllComments,
|
||||||
|
canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.deleteOwnComments : privileges.deleteAllComments,
|
||||||
|
}) + '</li>');
|
||||||
|
$targetList.append($item);
|
||||||
|
$item.find('a.edit').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
editCommentStart($item, comment);
|
||||||
|
});
|
||||||
|
$item.find('a.delete').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
deleteComment($item, comment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function commentFormSubmitted(e, comment) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $button = jQuery(e.target);
|
||||||
|
var $form = $button.parents('form');
|
||||||
|
var sender = $button.val();
|
||||||
|
if (sender === 'preview') {
|
||||||
|
previewComment($form);
|
||||||
|
} else {
|
||||||
|
submitComment($form, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function previewComment($form) {
|
||||||
|
var $preview = $form.find('.preview');
|
||||||
|
$preview.slideUp('fast', function() {
|
||||||
|
$preview.html(util.formatMarkdown($form.find('textarea').val()));
|
||||||
|
$preview.slideDown('fast');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitComment($form, commentToEdit) {
|
||||||
|
$form.find('.preview').slideUp();
|
||||||
|
var $textarea = $form.find('textarea');
|
||||||
|
|
||||||
|
var data = {text: $textarea.val()};
|
||||||
|
var p;
|
||||||
|
if (commentToEdit) {
|
||||||
|
p = promise.wait(api.put('/comments/' + commentToEdit.id, data));
|
||||||
|
} else {
|
||||||
|
p = promise.wait(api.post('/comments/' + post.id, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
p.then(function(response) {
|
||||||
|
$textarea.val('');
|
||||||
|
var comment = response.json;
|
||||||
|
|
||||||
|
if (commentToEdit) {
|
||||||
|
$form.slideUp(function() {
|
||||||
|
$form.remove();
|
||||||
|
});
|
||||||
|
comments = _.map(comments, function(c) { return c.id === commentToEdit.id ? comment : c; });
|
||||||
|
} else {
|
||||||
|
comments.push(comment);
|
||||||
|
}
|
||||||
|
renderComments(comments, true);
|
||||||
|
}).fail(function(response) {
|
||||||
|
window.alert(response.json && response.json.error || response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function editCommentStart($item, comment) {
|
||||||
|
if ($item.find('.comment-form').length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var $form = jQuery(commentFormTemplate({title: 'Edit comment', text: comment.text}));
|
||||||
|
$item.find('.body').append($form);
|
||||||
|
$item.find('form button[type=submit]').click(function(e) { commentFormSubmitted(e, comment); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteComment($item, comment) {
|
||||||
|
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
promise.wait(api.delete('/comments/' + comment.id))
|
||||||
|
.then(function(response) {
|
||||||
|
comments = _.filter(comments, function(c) { return c.id !== comment.id; });
|
||||||
|
renderComments(comments, true);
|
||||||
|
}).fail(function(response) {
|
||||||
|
window.alert(response.json && response.json.error || response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init,
|
||||||
|
render: render,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
App.DI.register('postCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.PostCommentListPresenter);
|
|
@ -44,14 +44,17 @@ App.Presenters.PostListPresenter = function(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
reinit(args, function() {});
|
onArgsChanged(args);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reinit(args, loaded) {
|
function reinit(args, loaded) {
|
||||||
loaded();
|
loaded();
|
||||||
|
onArgsChanged(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onArgsChanged(args) {
|
||||||
searchArgs = util.parseComplexRouteArgs(args.searchArgs);
|
searchArgs = util.parseComplexRouteArgs(args.searchArgs);
|
||||||
pagerPresenter.reinit({
|
pagerPresenter.reinit({
|
||||||
page: searchArgs.page,
|
page: searchArgs.page,
|
||||||
|
@ -84,18 +87,15 @@ App.Presenters.PostListPresenter = function(
|
||||||
function renderPosts(posts, clear) {
|
function renderPosts(posts, clear) {
|
||||||
var $target = $el.find('.posts');
|
var $target = $el.find('.posts');
|
||||||
|
|
||||||
var all = '';
|
|
||||||
_.each(posts, function(post) {
|
|
||||||
all += itemTemplate({
|
|
||||||
post: post,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
$target.html(all);
|
$target.empty();
|
||||||
} else {
|
|
||||||
$target.append(all);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_.each(posts, function(post) {
|
||||||
|
$target.append(jQuery('<li>' + itemTemplate({
|
||||||
|
post: post,
|
||||||
|
}) + '</li>'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchInputKeyPressed(e) {
|
function searchInputKeyPressed(e) {
|
||||||
|
|
|
@ -10,6 +10,8 @@ App.Presenters.PostPresenter = function(
|
||||||
auth,
|
auth,
|
||||||
router,
|
router,
|
||||||
keyboard,
|
keyboard,
|
||||||
|
presenterManager,
|
||||||
|
postCommentListPresenter,
|
||||||
topNavigationPresenter,
|
topNavigationPresenter,
|
||||||
messagePresenter) {
|
messagePresenter) {
|
||||||
|
|
||||||
|
@ -122,6 +124,10 @@ App.Presenters.PostPresenter = function(
|
||||||
|
|
||||||
$el.find('.post-edit-wrapper form').submit(editFormSubmitted);
|
$el.find('.post-edit-wrapper form').submit(editFormSubmitted);
|
||||||
attachSidebarEvents();
|
attachSidebarEvents();
|
||||||
|
|
||||||
|
presenterManager.initPresenters([
|
||||||
|
[postCommentListPresenter, _.extend({post: post}, {$target: $el.find('#post-comments-target')})]],
|
||||||
|
function() { });
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSidebar() {
|
function renderSidebar() {
|
||||||
|
@ -354,4 +360,17 @@ App.Presenters.PostPresenter = function(
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
App.DI.register('postPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'router', 'keyboard', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.PostPresenter);
|
App.DI.register('postPresenter', [
|
||||||
|
'_',
|
||||||
|
'jQuery',
|
||||||
|
'util',
|
||||||
|
'promise',
|
||||||
|
'api',
|
||||||
|
'auth',
|
||||||
|
'router',
|
||||||
|
'keyboard',
|
||||||
|
'presenterManager',
|
||||||
|
'postCommentListPresenter',
|
||||||
|
'topNavigationPresenter',
|
||||||
|
'messagePresenter'],
|
||||||
|
App.Presenters.PostPresenter);
|
||||||
|
|
|
@ -72,19 +72,16 @@ App.Presenters.UserListPresenter = function(
|
||||||
function renderUsers(users, clear) {
|
function renderUsers(users, clear) {
|
||||||
var $target = $el.find('.users');
|
var $target = $el.find('.users');
|
||||||
|
|
||||||
var all = '';
|
if (clear) {
|
||||||
|
$target.empty();
|
||||||
|
}
|
||||||
|
|
||||||
_.each(users, function(user) {
|
_.each(users, function(user) {
|
||||||
all += itemTemplate({
|
$target.append(jQuery('<li>' + itemTemplate({
|
||||||
user: user,
|
user: user,
|
||||||
formatRelativeTime: util.formatRelativeTime,
|
formatRelativeTime: util.formatRelativeTime,
|
||||||
});
|
}) + '</li>'));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (clear) {
|
|
||||||
$target.html(all);
|
|
||||||
} else {
|
|
||||||
$target.append(all);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function orderLinkClicked(e) {
|
function orderLinkClicked(e) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ App.Router = function(pathJs, _, jQuery, promise, util, appState, presenterManag
|
||||||
inject('#/user/:userName(/:tab)', 'userPresenter');
|
inject('#/user/:userName(/:tab)', 'userPresenter');
|
||||||
inject('#/posts(/:searchArgs)', 'postListPresenter');
|
inject('#/posts(/:searchArgs)', 'postListPresenter');
|
||||||
inject('#/post(/:postNameOrId)', 'postPresenter');
|
inject('#/post(/:postNameOrId)', 'postPresenter');
|
||||||
inject('#/comments(/:searchArgs)', 'commentListPresenter');
|
inject('#/comments(/:searchArgs)', 'globalCommentListPresenter');
|
||||||
inject('#/tags(/:searchArgs)', 'tagListPresenter');
|
inject('#/tags(/:searchArgs)', 'tagListPresenter');
|
||||||
inject('#/help', 'helpPresenter');
|
inject('#/help', 'helpPresenter');
|
||||||
setRoot('#/home');
|
setRoot('#/home');
|
||||||
|
|
|
@ -183,12 +183,18 @@ App.Util = function(_, jQuery, promise) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatMarkdown(text) {
|
||||||
|
//todo
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
promiseTemplate: promiseTemplate,
|
promiseTemplate: promiseTemplate,
|
||||||
parseComplexRouteArgs: parseComplexRouteArgs,
|
parseComplexRouteArgs: parseComplexRouteArgs,
|
||||||
compileComplexRouteArgs: compileComplexRouteArgs,
|
compileComplexRouteArgs: compileComplexRouteArgs,
|
||||||
formatRelativeTime: formatRelativeTime,
|
formatRelativeTime: formatRelativeTime,
|
||||||
formatFileSize: formatFileSize,
|
formatFileSize: formatFileSize,
|
||||||
|
formatMarkdown: formatMarkdown,
|
||||||
enableExitConfirmation: enableExitConfirmation,
|
enableExitConfirmation: enableExitConfirmation,
|
||||||
disableExitConfirmation: disableExitConfirmation,
|
disableExitConfirmation: disableExitConfirmation,
|
||||||
isExitConfirmationEnabled: isExitConfirmationEnabled,
|
isExitConfirmationEnabled: isExitConfirmationEnabled,
|
||||||
|
|
17
public_html/templates/comment-form.tpl
Normal file
17
public_html/templates/comment-form.tpl
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<form class="comment-form">
|
||||||
|
|
||||||
|
<h1><%= title %></h1>
|
||||||
|
|
||||||
|
<div class="preview"></div>
|
||||||
|
|
||||||
|
<div class="form-row text">
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<textarea name="text" cols="50" rows="3"><% if (typeof(text) !== 'undefined') { print(text) } %></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<button type="submit" name="sender" value="preview">Preview</button>
|
||||||
|
<button type="submit" name="sender" value="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
53
public_html/templates/comment-list-item.tpl
Normal file
53
public_html/templates/comment-list-item.tpl
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<div class="comment">
|
||||||
|
<div class="avatar">
|
||||||
|
<% if (comment.user.name) { %>
|
||||||
|
<a href="#/user/<%= comment.user.name %>">
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<img class="author-avatar"
|
||||||
|
src="/data/thumbnails/40x40/avatars/<%= comment.user.name || '!' %>"
|
||||||
|
alt="<%= comment.user.name || 'Anonymous user' %>"/>
|
||||||
|
|
||||||
|
<% if (comment.user.name) { %>
|
||||||
|
</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="body">
|
||||||
|
<div class="header">
|
||||||
|
<span class="nickname">
|
||||||
|
<% if (comment.user.name) { %>
|
||||||
|
<a href="#/user/<%= comment.user.name %>">
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<%= comment.user.name || 'Anonymous user' %>
|
||||||
|
|
||||||
|
<% if (comment.user.name) { %>
|
||||||
|
</a>
|
||||||
|
<% } %>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="date" title="<%= comment.creationTime %>">
|
||||||
|
<%= formatRelativeTime(comment.creationTime) %>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="ops">
|
||||||
|
<% if (canEditComment) { %>
|
||||||
|
<a class="edit" href="#"><!--
|
||||||
|
-->edit<!--
|
||||||
|
--></a>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canDeleteComment) { %>
|
||||||
|
<a class="delete" href="#"><!--
|
||||||
|
-->delete<!--
|
||||||
|
--></a>
|
||||||
|
<% } %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<%= formatMarkdown(comment.text) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
8
public_html/templates/global-comment-list-item.tpl
Normal file
8
public_html/templates/global-comment-list-item.tpl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="post-comment">
|
||||||
|
<div class="post">
|
||||||
|
<%= postTemplate({post: post}) %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="post-comments-target">
|
||||||
|
</div>
|
||||||
|
</div>
|
6
public_html/templates/global-comment-list.tpl
Normal file
6
public_html/templates/global-comment-list.tpl
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div id="global-comment-list">
|
||||||
|
<div class="pagination-target">
|
||||||
|
<ul class="posts">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
13
public_html/templates/post-comment-list.tpl
Normal file
13
public_html/templates/post-comment-list.tpl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<% if (canListComments && comments.length) { %>
|
||||||
|
<div class="comments">
|
||||||
|
<h1>Comments</h1>
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canAddComments) { %>
|
||||||
|
<div class="comment-add">
|
||||||
|
<%= commentFormTemplate({title: 'Add comment'}) %>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
|
@ -1,4 +1,4 @@
|
||||||
<li class="post post-type-<%= post.contentType %> ">
|
<div class="post-small post-type-<%= post.contentType %> ">
|
||||||
<a class="link"
|
<a class="link"
|
||||||
title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>"
|
title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>"
|
||||||
href="#/post/<%= post.id %>">
|
href="#/post/<%= post.id %>">
|
||||||
|
@ -25,4 +25,4 @@
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</div>
|
||||||
|
|
|
@ -230,6 +230,9 @@
|
||||||
|
|
||||||
<%= postContentTemplate({post: post}) %>
|
<%= postContentTemplate({post: post}) %>
|
||||||
|
|
||||||
|
<div id="post-comments-target">
|
||||||
|
</div>
|
||||||
|
|
||||||
<% if (privileges.canViewHistory) { %>
|
<% if (privileges.canViewHistory) { %>
|
||||||
<div class="post-history-wrapper">
|
<div class="post-history-wrapper">
|
||||||
<%= historyTemplate({
|
<%= historyTemplate({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<li class="user">
|
<div class="user">
|
||||||
<a href="#/user/<%= user.name %>">
|
<a href="#/user/<%= user.name %>">
|
||||||
<img src="/data/thumbnails/80x80/avatars/<%= user.name %>" alt="<%= user.name %>"/>
|
<img src="/data/thumbnails/80x80/avatars/<%= user.name %>" alt="<%= user.name %>"/>
|
||||||
</a>
|
</a>
|
||||||
|
@ -15,4 +15,4 @@
|
||||||
Last seen: <%= formatRelativeTime(user.lastLoginTime) %>
|
Last seen: <%= formatRelativeTime(user.lastLoginTime) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue