From ee8776feb3221b14fbf9f3809a5508c07cadc258 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 31 Jul 2015 19:51:21 -0700 Subject: [PATCH] removes comments moves upvote to main page add more info page closes #955 --- public/js/main_0.0.3.js | 56 ++---- server/boot/story.js | 213 +---------------------- server/views/stories/comments.jade | 164 ----------------- server/views/stories/hot-stories.jade | 27 ++- server/views/stories/index.jade | 4 +- server/views/stories/new-stories.jade | 55 ------ server/views/stories/news-nav.jade | 4 +- server/views/stories/search-stories.jade | 0 server/views/stories/show.jade | 42 +---- server/views/stories/submit-story.jade | 5 - 10 files changed, 48 insertions(+), 522 deletions(-) delete mode 100755 server/views/stories/comments.jade delete mode 100644 server/views/stories/new-stories.jade delete mode 100644 server/views/stories/search-stories.jade diff --git a/public/js/main_0.0.3.js b/public/js/main_0.0.3.js index 2519a4f66d..8db2d2769d 100644 --- a/public/js/main_0.0.3.js +++ b/public/js/main_0.0.3.js @@ -277,34 +277,32 @@ $(document).ready(function() { $('#long-instructions').hide(); }); - var upvoteHandler = function () { - var id = storyId; - $('#upvote').unbind('click'); + function upvoteHandler(e) { + e.preventDefault(); + var upvoteBtn = this; + var id = upvoteBtn.id; + var upVotes = $(upvoteBtn).data().upVotes; + var username = typeof username !== 'undefined' ? username : ''; var alreadyUpvoted = false; for (var i = 0; i < upVotes.length; i++) { - if (upVotes[i].upVotedBy === B3BA669EC5C1DD70FB478221E067A7E1B686929C569F5E73561B69C8F42129B) { + if (upVotes[i].upVotedBy === username) { alreadyUpvoted = true; break; } } if (!alreadyUpvoted) { - $.post('/stories/upvote', - { - data: { - id: id - } + $.post('/stories/upvote', { id: id }) + .fail(function(xhr, textStatus, errorThrown) { + $(upvoteBtn).bind('click', upvoteHandler); }) - .fail(function (xhr, textStatus, errorThrown) { - $('#upvote').bind('click', upvoteHandler); - }) - .done(function (data, textStatus, xhr) { - $('#upvote').text('Upvoted!').addClass('disabled'); + .done(function(data, textStatus, xhr) { + $(upvoteBtn).text('Upvoted!').addClass('disabled'); $('#storyRank').text(data.rank + " points"); }); } }; - $('#upvote').on('click', upvoteHandler); + $('#story-list').on('click', 'button.btn-upvote', upvoteHandler); var storySubmitButtonHandler = function storySubmitButtonHandler() { @@ -322,7 +320,6 @@ $(document).ready(function() { description: description, storyMetaDescription: storyMetaDescription, rank: 1, - comments: [], image: storyImage } }) @@ -336,29 +333,6 @@ $(document).ready(function() { $('#story-submit').on('click', storySubmitButtonHandler); - var commentSubmitButtonHandler = function commentSubmitButtonHandler() { - $('#comment-button').unbind('click'); - var data = $('#comment-box').val(); - - $('#comment-button').attr('disabled', 'disabled'); - $.post('/stories/comment/', - { - data: { - associatedPost: storyId, - originalStoryLink: originalStoryLink, - originalStoryAuthorEmail: originalStoryAuthorEmail, - body: data - } - }) - .fail(function (xhr, textStatus, errorThrown) { - $('#comment-button').attr('disabled', false); - $('#comment-button').bind('click', commentSubmitButtonHandler); - }) - .done(function (data, textStatus, xhr) { - window.location.reload(); - }); - }; - //fakeiphone positioning hotfix if($('.iphone-position').html() !==undefined || $('.iphone').html() !== undefined){ var startIphonePosition = parseInt($('.iphone-position').css('top').replace('px', '')); @@ -405,9 +379,7 @@ $(document).ready(function() { lockTop(initOff); }); } - } - - $('#comment-button').on('click', commentSubmitButtonHandler); + } }); var profileValidation = angular.module('profileValidation', diff --git a/server/boot/story.js b/server/boot/story.js index 9b7e40fe15..c90fbff4b1 100755 --- a/server/boot/story.js +++ b/server/boot/story.js @@ -1,5 +1,4 @@ var Rx = require('rx'), - nodemailer = require('nodemailer'), assign = require('object.assign'), sanitizeHtml = require('sanitize-html'), moment = require('moment'), @@ -19,23 +18,6 @@ var unDasherize = utils.unDasherize; var dasherize = utils.dasherize; var getURLTitle = utils.getURLTitle; -var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } -}); - -function sendMailWhillyNilly(mailOptions) { - transporter.sendMail(mailOptions, function(err) { - if (err) { - console.log('err sending mail whilly nilly', err); - console.log('logging err but not carring'); - } - }); -} - function hotRank(timeValue, rank) { /* * Hotness ranking algorithm: http://amix.dk/blog/post/19588 @@ -69,7 +51,6 @@ module.exports = function(app) { var router = app.loopback.Router(); var User = app.models.User; var findUserById = observeMethod(User, 'findById'); - var findOneUser = observeMethod(User, 'findOne'); var Story = app.models.Story; var findStory = observeMethod(Story, 'find'); @@ -77,14 +58,7 @@ module.exports = function(app) { var findStoryById = observeMethod(Story, 'findById'); var countStories = observeMethod(Story, 'count'); - var Comment = app.models.Comment; - var findCommentById = observeMethod(Comment, 'findById'); - - router.get('/stories/hotStories', hotJSON); - router.get('/stories/comments/:id', comments); - router.post('/stories/comment/', commentSubmit); - router.post('/stories/comment/:id/comment', commentOnCommentSubmit); - router.put('/stories/comment/:id/edit', commentEdit); + router.get('/news/hot', hotJSON); router.get('/stories/submit', submitNew); router.get('/stories/submit/new-story', preSubmit); router.post('/stories/preliminary', newStory); @@ -194,7 +168,6 @@ module.exports = function(app) { description: story.description, rank: story.upVotes.length, upVotes: story.upVotes, - comments: story.comments, id: story.id, timeAgo: moment(story.timePosted).fromNow(), image: story.image, @@ -224,7 +197,6 @@ module.exports = function(app) { rank: 1, upVotes: 1, author: 1, - comments: 1, image: 1, storyLink: 1, metaDescription: 1, @@ -250,7 +222,7 @@ module.exports = function(app) { } function upvote(req, res, next) { - var id = req.body.data.id; + const { id } = req.body; var story$ = findStoryById(id).shareReplay(); story$.flatMap(function(story) { @@ -284,16 +256,6 @@ module.exports = function(app) { ); } - function comments(req, res, next) { - var id = req.params.id; - findCommentById(id).subscribe( - function(comment) { - res.send(comment); - }, - next - ); - } - function newStory(req, res, next) { if (!req.user) { return next(new Error('Must be logged in')); @@ -407,7 +369,6 @@ module.exports = function(app) { username: req.user.username, email: req.user.email }, - comments: [], image: data.image, storyLink: storyLink, metaDescription: data.storyMetaDescription, @@ -428,174 +389,4 @@ module.exports = function(app) { next ); } - - function commentSubmit(req, res, next) { - var data = req.body.data; - if (!req.user) { - return next(new Error('Not authorized')); - } - var sanitizedBody = cleanData(data.body); - - if (data.body !== sanitizedBody) { - req.flash('errors', { - msg: 'HTML is not allowed' - }); - return res.send(true); - } - var comment = new Comment({ - associatedPost: data.associatedPost, - originalStoryLink: data.originalStoryLink, - originalStoryAuthorEmail: data.originalStoryAuthorEmail, - body: sanitizedBody, - rank: 0, - upvotes: 0, - author: { - picture: req.user.picture, - userId: req.user.id, - username: req.user.username, - email: req.user.email - }, - comments: [], - topLevel: true, - commentOn: Date.now() - }); - - commentSave(comment, findStoryById).subscribe( - function() {}, - next, - function() { - res.send(true); - } - ); - } - - function commentOnCommentSubmit(req, res, next) { - var data = req.body.data; - if (!req.user) { - return next(new Error('Not authorized')); - } - - var sanitizedBody = cleanData(data.body); - - if (data.body !== sanitizedBody) { - req.flash('errors', { - msg: 'HTML is not allowed' - }); - return res.send(true); - } - - var comment = new Comment({ - associatedPost: data.associatedPost, - body: sanitizedBody, - rank: 0, - upvotes: 0, - originalStoryLink: data.originalStoryLink, - originalStoryAuthorEmail: data.originalStoryAuthorEmail, - author: { - picture: req.user.picture, - userId: req.user.id, - username: req.user.username, - email: req.user.email - }, - comments: [], - topLevel: false, - commentOn: Date.now() - }); - commentSave(comment, findCommentById).subscribe( - function() {}, - next, - function() { - res.send(true); - } - ); - } - - function commentEdit(req, res, next) { - findCommentById(req.params.id) - .doOnNext(function(comment) { - if (!req.user && comment.author.userId !== req.user.id) { - throw new Error('Not authorized'); - } - }) - .flatMap(function(comment) { - var sanitizedBody = cleanData(req.body.body); - if (req.body.body !== sanitizedBody) { - req.flash('errors', { - msg: 'HTML is not allowed' - }); - } - comment.body = sanitizedBody; - comment.commentOn = Date.now(); - return saveInstance(comment); - }) - .subscribe( - function() { - res.send(true); - }, - next - ); - } - - function commentSave(comment, findContextById) { - return saveInstance(comment) - .flatMap(function(comment) { - // Based on the context retrieve the parent - // object of the comment (Story/Comment) - return findContextById(comment.associatedPost); - }) - .flatMap(function(associatedContext) { - if (associatedContext) { - associatedContext.comments.push(comment.id); - } - // NOTE(berks): saveInstance is safe - // it will automatically call onNext with null and onCompleted if - // argument is falsey or has no method save - return saveInstance(associatedContext); - }) - .flatMap(function(associatedContext) { - // Find the author of the parent object - // if no username - var username = associatedContext && associatedContext.author ? - associatedContext.author.username : - null; - - var query = { where: { username: username } }; - return findOneUser(query); - }) - // if no user is found we don't want to hit the doOnNext - // filter here will call onCompleted without running through the following - // steps - .filter(function(user) { - return !!user; - }) - // if this is called user is guarenteed to exits - // this is a side effect, hence we use do/tap observable methods - .doOnNext(function(user) { - // If the emails of both authors differ, - // only then proceed with email notification - if ( - comment.author && - comment.author.email && - user.email && - (comment.author.email !== user.email) - ) { - sendMailWhillyNilly({ - to: user.email, - from: 'Team@freecodecamp.com', - subject: comment.author.username + - ' replied to your post on Camper News', - text: [ - 'Just a quick heads-up: ', - comment.author.username, - ' replied to you on Camper News.', - 'You can keep this conversation going.', - 'Just head back to the discussion here: ', - 'http://freecodecamp.com/stories/', - comment.originalStoryLink, - '- the Free Code Camp Volunteer Team' - ].join('\n') - }); - } - }); - } }; diff --git a/server/views/stories/comments.jade b/server/views/stories/comments.jade deleted file mode 100755 index e8f1372df0..0000000000 --- a/server/views/stories/comments.jade +++ /dev/null @@ -1,164 +0,0 @@ -.text-left - div#comment-list - - script(src="https://cdn.jsdelivr.net/ramda/0.10.0/ramda.min.js") - script(src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js") - script. - var sentinel = 0; - var renderComments = function renderComments(comments, containerSelector, level) { - var commentDetails; - R.forEach(function displayComments(comment) { - - $.ajax({ - type: 'GET', - url: '/stories/comments/' + comment, - error: function (xhr, textStatus, errorThrown) { - commentDetails = { - error: true, - body: 'There seems to be a problem fetching this comment.' - } - }, - success: function (data, textStatus, xhr) { - commentDetails = data; - var div = document.createElement('div'); - var editButton = ""; - // todo - if (commentDetails.author.username === DF105CFA89562196E702912B3818C6A5B46E80D262442FDF29976621E5AF0D23) { - if ((Date.now() - commentDetails.commentOn) < 600000){ - editButton = "Edit · "; - } - } - $(div) - .html( - '
' + - '
' + - "" + - '' + commentDetails.author.username + '' + - '' + - '
' + - '
' + - '
' + - '

' + commentDetails.body + '

' + - '
' + - '
' + - "Reply · " + - editButton + - "commented " + moment(commentDetails.commentOn).fromNow() + " by " + - "@" + commentDetails.author.username + "" + - '
' + - '
' + - '
' + - '
' + - '
' - ) - .addClass('comment-wrapper positive-10') - .appendTo($(containerSelector)); - - sentinel += commentDetails.comments.length; - - renderComments(commentDetails.comments, '.comment_' + commentDetails.id, ++level); - - }, - complete: function () { - sentinel--; - if (!sentinel) { - $('.comment-a-comment').on('click', 'a', function() { - var editOrComment = 'comment'; - if ($(this).hasClass("edit-btn")){ - editOrComment = 'edit'; - } - if (!isLoggedIn) { - window.location.href = '/signin'; - return; - } - $(this).unbind('click'); - $('.comment-to-comment-formgroup').empty(); - $('#initial-comment-submit').addClass('hidden-element'); - var div = document.createElement('div'); - var commentId = $(this).attr('id'); - $(div).html( - "
" + - '
' + - "
" + - "" + - "" + - "" + - "" + - "
" + - "
" + - "
" + - "
" - ) - .addClass('row') - .appendTo($(this).closest('.media-body-wrapper')); - var text_max = 140; - $('#textarea-comment-feedback').html(text_max + ' characters remaining'); - $('#comment-to-comment-textinput').keyup(function (e) { - if (e.which === 13 || e === 13) { - $('#submit-comment-to-comment').click(); - $('#submit-comment-to-edit').click(); - } - var text_length = $('#comment-to-comment-textinput').val().length; - var text_remaining = text_max - text_length; - $('#textarea-comment-feedback').html(text_remaining + ' characters remaining'); - }); - var submitCommentToCommentHandler = function submitCommentToCommentHandler() { - $('#submit-comment-to-comment').unbind('click'); - $.post('/stories/comment/' + commentId + '/comment', - { - data: { - associatedPost: commentId, - originalStoryLink: originalStoryLink, - originalStoryAuthorEmail: originalStoryAuthorEmail, - body: $('#comment-to-comment-textinput').val(), - } - }) - .fail(function (xhr, textStatus, errorThrown) { - $('#submit-comment-to-comment').bind('click', submitCommentToCommentHandler); - }) - .done(function (data, textStatus, xhr) { - window.location.reload(); - }); - - }; - // todo - var submitCommentForEditToCommentHandler = function submitCommentForEditToCommentHandler() { - $('#submit-comment-to-edit').unbind('click'); - - $.ajax({ - type: "PUT", - url: '/stories/comment/' + commentId + '/edit', - data: { - associatedPost: commentId, - originalStoryLink: originalStoryLink, - body: $('#comment-to-comment-textinput').val() - }, - dataType: "json", - success: function (msg) { - window.location.reload(); - }, - error: function (err){ - $('#submit-comment-to-edit').bind('click', submitCommentForEditToCommentHandler); - } - }); - }; - - $('#submit-comment-to-edit').on('click', submitCommentForEditToCommentHandler) - $('#submit-comment-to-comment').on('click', submitCommentToCommentHandler); - }); - } - } - }) - - - }, comments); - } - sentinel += comments.length; - - - renderComments(comments, $('#comment-list'), 0); - - - - - diff --git a/server/views/stories/hot-stories.jade b/server/views/stories/hot-stories.jade index 425588dd05..0fe150ec54 100644 --- a/server/views/stories/hot-stories.jade +++ b/server/views/stories/hot-stories.jade @@ -9,7 +9,7 @@ return name.trim().toLowerCase().replace(/\s/g, '-'); } $.ajax({ - url: '/stories/hotStories', + url: '/news/hot', type: 'GET' }) .success( @@ -18,6 +18,12 @@ var div = document.createElement('div'); var linkedName = getLinkedName(data[i].storyLink); var rank = data[i].rank; + var alreadyUpvoted = false; + if (typeof username !== 'undefined') { + alreadyUpvoted = data[i].upVotes.some(function(vote) { + return vote.upVotedByUsername === username + }); + } $(div) .html( @@ -38,7 +44,11 @@ " by @" + data[i].author.username + " " + "" + "
" + - "
discuss" + + "
" + + (typeof username !== 'undefined' ? + "" : + "upvote") + + "more info..." + "
" + "" + "" + "
" + - "discuss · " + + (typeof username !== 'undefined' ? + "" : + "upvote") + + " · more info... · " + rank + (rank > 1 ? " points" : " point") + " · posted " + moment(data[i].timePosted).fromNow() + " by @" + data[i].author.username + " " + @@ -68,5 +81,13 @@ ); $(div).addClass('story-list news-box') $(div).appendTo($('#story-list')); + $(div).find('.btn-upvote').each(function(idx, btn) { + var $btn = $(btn); + if (alreadyUpvoted) { + $btn.addClass('disabled'); + $btn.text('upvoted!'); + } + $btn.data('upVotes', data[i].upVotes); + }); } }); diff --git a/server/views/stories/index.jade b/server/views/stories/index.jade index 0204840763..196c1bcd3d 100644 --- a/server/views/stories/index.jade +++ b/server/views/stories/index.jade @@ -3,8 +3,8 @@ block content if (user) script. var isLoggedIn = true; - var B3BA669EC5C1DD70FB478221E067A7E1B686929C569F5E73561B69C8F42129B = !{JSON.stringify(user.id)}; - var DF105CFA89562196E702912B3818C6A5B46E80D262442FDF29976621E5AF0D23 = !{JSON.stringify(user.username)}; + var userId = !{JSON.stringify(user.id)}; + var username = !{JSON.stringify(user.username)}; else script. var isLoggedIn = false; diff --git a/server/views/stories/new-stories.jade b/server/views/stories/new-stories.jade deleted file mode 100644 index 97a6aa02d6..0000000000 --- a/server/views/stories/new-stories.jade +++ /dev/null @@ -1,55 +0,0 @@ -.spacer -.col-xs-12 - #story-list.story-list - - script(src="https://cdn.jsdelivr.net/ramda/0.10.0/ramda.min.js") - script. - - var getLinkedName = function getLinkedName(name) { - return name.trim().toLowerCase().replace(/\s/g, '-'); - } - $.ajax({ - url: '/stories/recentStories', - type: 'GET' - }) - .success( - function(data) { - for (var i = 0; i < data.length; i++) { - var div = document.createElement('div'); - var linkedName = getLinkedName(data[i].storyLink); - var rank = data[i].rank; - - $(div) - .html( - "
" + - "

" + - (i + 1) + - "

" + - "
" + - "" + - "" + - "" + - "
" + - "
" + - "
" + - "
" + - "" + - data[i].headline + - "" + - "
" + - "
" + - "" + - "discuss · " + - rank + (rank > 1 ? " points" : " point") + " · posted " + - moment(data[i].timePosted).fromNow() + - " by @" + data[i].author.username + " " +" " + - "" + - "
" + - "
" + - "
" + - "
" - ); - $(div).addClass('story-list') - $(div).appendTo($('#story-list')); - } - }); \ No newline at end of file diff --git a/server/views/stories/news-nav.jade b/server/views/stories/news-nav.jade index 52ddf6c9f5..f28f1788f1 100644 --- a/server/views/stories/news-nav.jade +++ b/server/views/stories/news-nav.jade @@ -84,7 +84,7 @@ script. "
" + "
" + "
" + - "discuss" + + "more info..." + "
" + "" + "" + @@ -103,7 +103,7 @@ script. "" + "" + "
" + - "discuss · " + + "more info.more info... · " + rank + (rank > 1 ? " points" : " point") + " · posted " + moment(data[i].timePosted).fromNow() + " by @" + data[i].author.username + diff --git a/server/views/stories/search-stories.jade b/server/views/stories/search-stories.jade deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/server/views/stories/show.jade b/server/views/stories/show.jade index b96559b264..7d9ddbeb7f 100644 --- a/server/views/stories/show.jade +++ b/server/views/stories/show.jade @@ -2,7 +2,6 @@ script. var storyId = !{JSON.stringify(id)}; var originalStoryLink = !{JSON.stringify(originalStoryLink)}; var originalStoryAuthorEmail = !{JSON.stringify(originalStoryAuthorEmail)}; - var comments = !{JSON.stringify(comments)}; var upVotes = !{JSON.stringify(upVotes)}; var image = !{JSON.stringify(image)}; var hasUserVoted = !{JSON.stringify(hasUserVoted)}; @@ -26,52 +25,19 @@ h3.row .col-xs-12 h4= description .negative-5 - if !user - a#upvote.btn.signup-btn.btn-xs(href='/signin') Sign in to reply or upvote + if !hasUserVoted + a#upvote.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvote |  ·  else - a#reply-to-main-post.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Reply - |  ·   - if !hasUserVoted - a#upvote.btn.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvote - |  ·  - else - a#upvote.btn.disabled.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvoted! - |  ·  + a#upvote.btn.disabled.btn-no-shadow.btn-primary.btn-xs.btn-primary-ghost Upvoted! + |  ·  span#storyRank= rank + (rank > 1 ? " points" : " point") |  ·  span Posted #{timeAgo} span  by  a(href="/" + author.username) @#{author.username} -if (user !== null) - .col-xs-12#reply-area - .hidden-element#initial-comment-submit - form.form-horizontal.control-label-story-submission - .col-xs-12 - .input-group - input#comment-box.big-text-field.field-responsive.form-control(type='text', placeholder='Enter your reply', autofocus) - span.input-group-btn - button#comment-button.btn.btn-big.btn-primary.btn-responsive(type='button') Send - span.spacer.pull-left#textarea_feedback - script. if (image) { $('#image-display').removeClass('hidden-element') } - $('#reply-to-main-post').on('click', function() { - $('#initial-comment-submit').removeClass('hidden-element'); - $(this).unbind('click'); - $('.comment-to-comment-formgroup').empty(); - }); - var text_max = 140; - $('#textarea_feedback').html(text_max + ' characters remaining'); - $('#comment-box').keyup(function (e) { - if (e.which === 13 || e === 13) { - $('#comment-button').click(); - } - var text_length = $('#comment-box').val().length; - var text_remaining = text_max - text_length; - $('#textarea_feedback').html(text_remaining + ' characters remaining'); - }); -include comments diff --git a/server/views/stories/submit-story.jade b/server/views/stories/submit-story.jade index dbe42dd1e7..dda1aa63ea 100644 --- a/server/views/stories/submit-story.jade +++ b/server/views/stories/submit-story.jade @@ -22,11 +22,6 @@ alert(type='danger') span.ion-close-circled | A headline is required to submit. - .form-group - .col-xs-12.col-md-1 - label.control-label.control-label-story-submission(for='name') Comment - .col-xs-12.col-md-11 - input#description-box.form-control(name="comment-box", placeholder="Kick off the discussion with an optional comment about this link" maxlength='140') .form-group .col-xs-12.col-md-offset-1 span.pull-left#textarea_feedback