Added comment presenters

This commit is contained in:
Marcin Kurczewski
2014-10-04 14:06:44 +02:00
parent 16c5740277
commit 16f9c277a1
23 changed files with 577 additions and 81 deletions

View File

@ -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);

View 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);

View File

@ -100,9 +100,8 @@ App.Presenters.PagerPresenter = function(
return util.compileComplexRouteArgs(
baseUri,
_.extend(
{},
pager.getSearchParams(),
{page: pager.getPage()}));
{page: pager.getPage()},
pager.getSearchParams()));
}
function syncUrl() {

View 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);

View File

@ -44,14 +44,17 @@ App.Presenters.PostListPresenter = function(
},
},
function() {
reinit(args, function() {});
onArgsChanged(args);
});
});
}
function reinit(args, loaded) {
loaded();
onArgsChanged(args);
}
function onArgsChanged(args) {
searchArgs = util.parseComplexRouteArgs(args.searchArgs);
pagerPresenter.reinit({
page: searchArgs.page,
@ -84,18 +87,15 @@ App.Presenters.PostListPresenter = function(
function renderPosts(posts, clear) {
var $target = $el.find('.posts');
var all = '';
_.each(posts, function(post) {
all += itemTemplate({
post: post,
});
});
if (clear) {
$target.html(all);
} else {
$target.append(all);
$target.empty();
}
_.each(posts, function(post) {
$target.append(jQuery('<li>' + itemTemplate({
post: post,
}) + '</li>'));
});
}
function searchInputKeyPressed(e) {

View File

@ -10,6 +10,8 @@ App.Presenters.PostPresenter = function(
auth,
router,
keyboard,
presenterManager,
postCommentListPresenter,
topNavigationPresenter,
messagePresenter) {
@ -122,6 +124,10 @@ App.Presenters.PostPresenter = function(
$el.find('.post-edit-wrapper form').submit(editFormSubmitted);
attachSidebarEvents();
presenterManager.initPresenters([
[postCommentListPresenter, _.extend({post: post}, {$target: $el.find('#post-comments-target')})]],
function() { });
}
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);

View File

@ -72,19 +72,16 @@ App.Presenters.UserListPresenter = function(
function renderUsers(users, clear) {
var $target = $el.find('.users');
var all = '';
if (clear) {
$target.empty();
}
_.each(users, function(user) {
all += itemTemplate({
$target.append(jQuery('<li>' + itemTemplate({
user: user,
formatRelativeTime: util.formatRelativeTime,
});
}) + '</li>'));
});
if (clear) {
$target.html(all);
} else {
$target.append(all);
}
}
function orderLinkClicked(e) {

View File

@ -40,7 +40,7 @@ App.Router = function(pathJs, _, jQuery, promise, util, appState, presenterManag
inject('#/user/:userName(/:tab)', 'userPresenter');
inject('#/posts(/:searchArgs)', 'postListPresenter');
inject('#/post(/:postNameOrId)', 'postPresenter');
inject('#/comments(/:searchArgs)', 'commentListPresenter');
inject('#/comments(/:searchArgs)', 'globalCommentListPresenter');
inject('#/tags(/:searchArgs)', 'tagListPresenter');
inject('#/help', 'helpPresenter');
setRoot('#/home');

View File

@ -183,12 +183,18 @@ App.Util = function(_, jQuery, promise) {
});
}
function formatMarkdown(text) {
//todo
return text;
}
return {
promiseTemplate: promiseTemplate,
parseComplexRouteArgs: parseComplexRouteArgs,
compileComplexRouteArgs: compileComplexRouteArgs,
formatRelativeTime: formatRelativeTime,
formatFileSize: formatFileSize,
formatMarkdown: formatMarkdown,
enableExitConfirmation: enableExitConfirmation,
disableExitConfirmation: disableExitConfirmation,
isExitConfirmationEnabled: isExitConfirmationEnabled,