diff --git a/client/main.html b/client/main.html index 49f0cc5fb..57a7f6998 100644 --- a/client/main.html +++ b/client/main.html @@ -2,5 +2,5 @@ Loading... - + diff --git a/client/views/comments/comment_edit.js b/client/views/comments/comment_edit.js index d641a5e12..a9ed91450 100644 --- a/client/views/comments/comment_edit.js +++ b/client/views/comments/comment_edit.js @@ -29,18 +29,17 @@ Template[getTemplate('comment_edit')].events({ }); trackEvent("edit comment", {'postId': comment.postId, 'commentId': comment._id}); - Router.go("/posts/"+comment.postId+"/comment/"+comment._id); + Router.go('post_page_comment', {_id: comment.postId, commentId: comment._id}); }, 'click .delete-link': function(e){ var comment = this; e.preventDefault(); - + if(confirm(i18n.t("are_you_sure"))){ Meteor.call('removeComment', comment._id); - Router.go("/posts/"+comment.postId); + Router.go('post_page', {_id: comment.postId}); throwError("Your comment has been deleted."); -// Router.go("/comments/deleted"); } } }); \ No newline at end of file diff --git a/client/views/comments/comment_form.js b/client/views/comments/comment_form.js index 83de2c482..448ede2e0 100644 --- a/client/views/comments/comment_form.js +++ b/client/views/comments/comment_form.js @@ -28,7 +28,10 @@ Template[getTemplate('comment_form')].events({ throwError(error.reason); }else{ trackEvent("newComment", newComment); - Router.go('/posts/'+parentComment.postId+'/comment/'+newComment._id); + Router.go('post_page_comment', { + _id: parentComment.postId, + commentId: newComment._id + }); } }); }else{ diff --git a/client/views/comments/comment_item.html b/client/views/comments/comment_item.html index f58d3a867..f49b553d6 100644 --- a/client/views/comments/comment_item.html +++ b/client/views/comments/comment_item.html @@ -21,9 +21,9 @@ {{authorName}} {{timeAgo ago}}, {{upvotes}} points - {{_ "link"}} + {{_ "link"}} {{#if can_edit}} - | {{_ "edit"}} + | {{_ "edit"}} {{/if}} {{#if isAdmin}} | {{full_date}} @@ -31,7 +31,7 @@
{{{htmlBody}}}
{{#if getSetting "nestedComments" true}} - {{_ "reply"}} + {{_ "reply"}} {{/if}} diff --git a/client/views/common/css.html b/client/views/common/css.html index 39e9af0e5..095a6cb26 100644 --- a/client/views/common/css.html +++ b/client/views/common/css.html @@ -21,8 +21,8 @@ color: {{getSetting "headerTextColor"}}; } .logo-image a{ - height:{{getSetting "logoHeight"}}px; - width:{{getSetting "logoWidth"}}px; + height:{{getSetting "logoHeight"}}px; + width:{{getSetting "logoWidth"}}px; } \ No newline at end of file diff --git a/client/views/nav/nav.js b/client/views/nav/nav.js index bbb9ef008..1d230fad2 100644 --- a/client/views/nav/nav.js +++ b/client/views/nav/nav.js @@ -28,7 +28,7 @@ Template[getTemplate('nav')].helpers({ }, logo_top: function(){ return Math.floor((70-getSetting('logoHeight'))/2); - }, + }, logo_offset: function(){ return -Math.floor(getSetting('logoWidth')/2); }, @@ -43,30 +43,9 @@ Template[getTemplate('nav')].helpers({ } }); -Template[getTemplate('nav')].rendered = function(){ - if(!Meteor.loggingIn() && !Meteor.user()){ - $('.login-link-text').text("Sign Up/Sign In"); - } -}; - Template[getTemplate('nav')].events({ - 'click #logout': function(e){ - e.preventDefault(); - Meteor.logout(); - }, 'click .mobile-menu-button': function(e){ e.preventDefault(); $('body').toggleClass('mobile-nav-open'); - }, - 'click .login-header': function(e){ - e.preventDefault(); - Router.go('/account'); - }, - 'click #login-name-link': function(){ - if(Meteor.user() && !$('account-link').exists()){ - var $loginButtonsLogout = $('#login-buttons-logout'); - $loginButtonsLogout.before('View Profile'); - $loginButtonsLogout.before('Edit Account'); - } } }); \ No newline at end of file diff --git a/client/views/nav/user_menu.html b/client/views/nav/user_menu.html index 698c69093..aad3cf01d 100644 --- a/client/views/nav/user_menu.html +++ b/client/views/nav/user_menu.html @@ -11,7 +11,7 @@ {{else}} - {{_ "sign_in"}} - {{_ "sign_up"}} + {{_ "sign_in"}} + {{_ "sign_up"}} {{/if}} \ No newline at end of file diff --git a/client/views/posts/modules/post_info.html b/client/views/posts/modules/post_info.html index 19b0b860c..0abe143aa 100644 --- a/client/views/posts/modules/post_info.html +++ b/client/views/posts/modules/post_info.html @@ -2,7 +2,7 @@
{{baseScore}} {{pointsUnitDisplayText}} by {{authorName}} {{timeAgo ago}} {{#if can_edit}} - | {{_ "edit"}} + | {{_ "edit"}} {{/if}}
\ No newline at end of file diff --git a/client/views/posts/modules/post_info.js b/client/views/posts/modules/post_info.js index 1711b4df3..a76a64dd0 100644 --- a/client/views/posts/modules/post_info.js +++ b/client/views/posts/modules/post_info.js @@ -9,7 +9,7 @@ Template[getTemplate('postInfo')].helpers({ return getAuthorName(this); }, ago: function(){ - // if post is approved show submission time, else show creation time. + // if post is approved show submission time, else show creation time. time = this.status == STATUS_APPROVED ? this.postedAt : this.createdAt; return time; }, diff --git a/client/views/posts/post_edit.js b/client/views/posts/post_edit.js index 66de7f723..2b83a00bc 100644 --- a/client/views/posts/post_edit.js +++ b/client/views/posts/post_edit.js @@ -26,7 +26,7 @@ AutoForm.hooks({ }else{ // note: find a way to do this in onSuccess instead? trackEvent("edit post", {'postId': post._id}); - Router.go('/posts/'+post._id); + Router.go('post_page', {_id: post._id}); submit.done(); } }); @@ -41,7 +41,7 @@ AutoForm.hooks({ // if(post.status === STATUS_PENDING) // throwError('Thanks, your post is awaiting approval.'); // Router.go('/posts/'+post._id); - }, + }, onError: function(operation, error, template) { console.log(error) diff --git a/client/views/posts/post_submit.js b/client/views/posts/post_submit.js index 5f95144cc..73035a0f2 100644 --- a/client/views/posts/post_submit.js +++ b/client/views/posts/post_submit.js @@ -28,9 +28,10 @@ AutoForm.hooks({ }else{ // note: find a way to do this in onSuccess instead? trackEvent("new post", {'postId': post._id}); - if(post.status === STATUS_PENDING) + if (post.status === STATUS_PENDING) { throwError('Thanks, your post is awaiting approval.'); - Router.go('/posts/'+post._id); + } + Router.go('post_page', {_id: post._id}); submit.done(); } }); @@ -45,7 +46,7 @@ AutoForm.hooks({ // if(post.status === STATUS_PENDING) // throwError('Thanks, your post is awaiting approval.'); // Router.go('/posts/'+post._id); - }, + }, onError: function(operation, error, template) { throwError(error.reason.split('|')[0]); // workaround because error.details returns undefined diff --git a/client/views/posts/posts_digest.html b/client/views/posts/posts_digest.html index 32060bc13..c07baf399 100644 --- a/client/views/posts/posts_digest.html +++ b/client/views/posts/posts_digest.html @@ -11,7 +11,7 @@ {{/if}} - + {{> UI.dynamic template=postsListIncoming data=incoming}} {{#if hasPosts}} diff --git a/client/views/users/user_edit.js b/client/views/users/user_edit.js index ae36adff6..e4368217e 100644 --- a/client/views/users/user_edit.js +++ b/client/views/users/user_edit.js @@ -15,7 +15,7 @@ Template[getTemplate('user_edit')].helpers({ return getGitHubName(this) || ""; }, profileUrl: function(){ - return Meteor.absoluteUrl()+"users/"+this.slug; + return getProfileUrlBySlugOrId(this.slug); }, hasNotificationsUsers : function(){ return getUserSetting('notifications.users', '', this) ? 'checked' : ''; diff --git a/client/views/users/user_profile.html b/client/views/users/user_profile.html index a4aa1ea8e..53e11367e 100644 --- a/client/views/users/user_profile.html +++ b/client/views/users/user_profile.html @@ -65,7 +65,7 @@ {{#each posts}} - {{title}} + {{title}} {{formatDate createdAt "MM/DD/YYYY, HH:mm"}} {{/each}} @@ -90,7 +90,7 @@ {{#each upvotedPosts}} - {{title}} + {{title}} {{formatDate votedAt "MM/DD/YYYY, HH:mm"}} {{/each}} @@ -115,7 +115,7 @@ {{#each downvoted}} - {{title}} + {{title}} {{formatDate votedAt "MM/DD/YYYY, HH:mm"}} {{/each}} @@ -141,7 +141,7 @@ {{#each comments}} - {{postTitle}} + {{postTitle}} {{{htmlBody}}} {{formatDate createdAt "MM/DD/YYYY, HH:mm"}} diff --git a/collections/posts.js b/collections/posts.js index fd6cbd19e..028ea9b8a 100644 --- a/collections/posts.js +++ b/collections/posts.js @@ -39,7 +39,7 @@ postSchemaObject = { editable: true, type: "bootstrap-url" } - }, + }, title: { type: String, optional: false, @@ -188,7 +188,7 @@ postSchemaObject = { return { value: user._id, label: getDisplayName(user) - } + } }); } } @@ -229,12 +229,12 @@ getPostProperties = function (post) { var p = { postAuthorName : getDisplayName(postAuthor), postTitle : cleanUp(post.title), - profileUrl: getProfileUrlById(post.userId), + profileUrl: getProfileUrlBySlugOrId(post.userId), postUrl: getPostPageUrl(post), thumbnailUrl: post.thumbnailUrl, linkUrl: !!post.url ? getOutgoingUrl(post.url) : getPostPageUrl(post._id) }; - + if(post.url) p.url = post.url; @@ -265,7 +265,7 @@ checkForPostsWithSameUrl = function (url) { if(typeof postWithSameLink !== 'undefined'){ Meteor.call('upvotePost', postWithSameLink); - // note: error.details returns undefined on the client, so add post ID to reason + // note: error.details returns undefined on the client, so add post ID to reason throw new Meteor.Error('603', i18n.t('this_link_has_already_been_posted') + '|' + postWithSameLink._id, postWithSameLink._id); } } @@ -351,9 +351,9 @@ Meteor.methods({ inactive: false }; - // UserId + // UserId if(isAdmin(Meteor.user()) && !!post.userId){ // only let admins post as other users - properties.userId = post.userId; + properties.userId = post.userId; } // Status @@ -361,7 +361,7 @@ Meteor.methods({ if(isAdmin(Meteor.user()) && !!post.status){ // if user is admin and a custom status has been set properties.status = post.status; }else{ // else use default status - properties.status = defaultPostStatus; + properties.status = defaultPostStatus; } // CreatedAt @@ -450,7 +450,7 @@ Meteor.methods({ setPostedAt: function(post, customPostedAt){ var postedAt = new Date(); // default to current date and time - + if(isAdmin(Meteor.user()) && typeof customPostedAt !== 'undefined') // if user is admin and a custom datetime has been set postedAt = customPostedAt; @@ -508,7 +508,7 @@ Meteor.methods({ // decrement post count var post = Posts.findOne({_id: postId}); if(!Meteor.userId() || !canEditById(Meteor.userId(), post)) throw new Meteor.Error(606, 'You need permission to edit or delete a post'); - + Meteor.users.update({_id: post.userId}, {$inc: {postCount: -1}}); Posts.remove(postId); } diff --git a/lib/helpers.js b/lib/helpers.js index eedfced4c..7a78f9ccc 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -12,19 +12,23 @@ t=function(message){ var d=new Date(); console.log("### "+message+" rendered at "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()); }; -nl2br= function(str) { -var breakTag = '
'; -return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2'); +nl2br= function(str) { + var breakTag = '
'; + return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2'); }; getAuthorName = function(item){ var user = Meteor.users.findOne(item.userId); return typeof user === 'undefined' ? '' : getDisplayName(user); }; scrollPageTo = function(selector){ - $('body').scrollTop($(selector).offset().top); + $('body').scrollTop($(selector).offset().top); }; getDigestURL = function(moment){ - return '/digest/'+moment.year()+'/'+(moment.month()+1)+'/'+moment.date(); + return Router.routes['posts_digest'].path({ + year: moment.year(), + month: moment.month() + 1, + day: moment.date() + }); }; getDateRange= function(pageNumber){ var now = moment(new Date()); @@ -50,24 +54,27 @@ goTo = function(url){ }; getSignupUrl = function(){ - return Meteor.absoluteUrl()+'sign-up'; + return Router.routes['atSignUp'].url(); }; getSigninUrl = function(){ - return Meteor.absoluteUrl()+'sign-in'; + return Router.routes['atSignIn'].url(); }; getPostUrl = function(id){ - return Meteor.absoluteUrl()+'posts/'+id; + return Router.routes['post_page'].url({_id: id}); }; getPostEditUrl = function(id){ - return Meteor.absoluteUrl()+'posts/'+id+'/edit'; + return Router.routes['post_edit'].url({_id: id}); }; getCommentUrl = function(id){ - return Meteor.absoluteUrl()+'comments/'+id; + return Router.routes['comment_reply'].url({_id: id}); }; getPostCommentUrl = function(postId, commentId){ // get link to a comment on a post page - return Meteor.absoluteUrl()+'posts/'+postId+'/comment/'+commentId; + return Router.routes['post_page_comment'].url({ + _id: postId, + commentId: commentId + }); }; slugify = function(text) { if(text){ @@ -78,7 +85,7 @@ slugify = function(text) { return text; }; getShortUrl = function(post){ - return post.shortUrl ? post.shortUrl : post.url; + return post.shortUrl || post.url; }; getDomain = function(url){ urlObject = Npm.require('url'); @@ -88,7 +95,7 @@ invitesEnabled = function () { return getSetting("requireViewInvite") || getSetting("requirePostInvite"); }; getOutgoingUrl = function(url){ - return getSiteUrl() + 'out?url=' + encodeURIComponent(url); + return Router.routes['out'].url({}, {query: {url: url}}); }; // ---------------------------------- String Helper Functions ----------------------------------- // cleanUp = function(s){ @@ -99,11 +106,11 @@ sanitize = function (s) { // console.log(s) if(Meteor.isServer){ var s = sanitizeHtml(s, { - allowedTags: [ - 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', - 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', - 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', - 'tbody', 'tr', 'th', 'td', 'pre', 'img' + allowedTags: [ + 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', + 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', + 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', + 'tbody', 'tr', 'th', 'td', 'pre', 'img' ] }); // console.log('// after sanitization:') diff --git a/lib/router/filters.js b/lib/router/filters.js index 5ec1931f9..d2852ef1a 100644 --- a/lib/router/filters.js +++ b/lib/router/filters.js @@ -141,7 +141,7 @@ Meteor.startup( function (){ Session.set('categorySlug', null); // if we're not on the search page itself, clear search query and field - if(getCurrentRoute().indexOf('search') == -1){ + if(Router.current().route.getName() !== 'search'){ Session.set('searchQuery', ''); $('.search-field').val('').blur(); } diff --git a/lib/users.js b/lib/users.js index fc4029d61..621253851 100644 --- a/lib/users.js +++ b/lib/users.js @@ -42,13 +42,10 @@ getDisplayNameById = function(userId){ return getDisplayName(Meteor.users.findOne(userId)); }; getProfileUrl = function(user) { - return Meteor.absoluteUrl()+'users/' + slugify(getUserName(user)); + return getProfileUrlBySlugOrId(user.slug); }; -getProfileUrlById = function(id){ - return Meteor.absoluteUrl()+'users/'+ id; -}; -getProfileUrlBySlug = function(slug) { - return Meteor.absoluteUrl()+'users/' + slug; +getProfileUrlBySlugOrId = function(slugOrId) { + return Router.routes['user_profile'].url({_idOrSlug: slugOrId}); }; hasPassword = function(user) { return !!user.services.password; @@ -77,8 +74,8 @@ getTwitterNameById = function(userId){ getEmail = function(user){ if(user.profile && user.profile.email){ return user.profile.email; - }else{ - return null; + }else{ + return null; } }; getEmailHash = function(user){ diff --git a/packages/telescope-notifications/lib/herald.js b/packages/telescope-notifications/lib/herald.js index f5dc6e2bf..b2e998dca 100644 --- a/packages/telescope-notifications/lib/herald.js +++ b/packages/telescope-notifications/lib/herald.js @@ -1,5 +1,5 @@ Meteor.startup(function () { - + Herald.collection.deny({ update: ! can.editById, remove: ! can.editById @@ -27,7 +27,7 @@ var getCommenterProfileUrl = function (comment) { if(user) { return getProfileUrl(user); } else { - return getProfileUrlById(comment.userId) + return getProfileUrlBySlugOrId(comment.userId) } } @@ -37,7 +37,7 @@ var getAuthor = function (comment) { return getUserName(user); } else { return comment.author; - } + } } Herald.addCourier('newPost', { diff --git a/packages/telescope-notifications/lib/server/notifications-server.js b/packages/telescope-notifications/lib/server/notifications-server.js index 2aee0d3bc..45cff0b33 100644 --- a/packages/telescope-notifications/lib/server/notifications-server.js +++ b/packages/telescope-notifications/lib/server/notifications-server.js @@ -1,14 +1,14 @@ getUnsubscribeLink = function(user){ - return Meteor.absoluteUrl()+'unsubscribe/'+user.email_hash; + return Router.routes['unsubscribe'].url({hash: user.email_hash}); }; // given a notification, return the correct subject and html to send an email buildEmailNotification = function (notification) { - + var subject, template; var post = notification.data.post; var comment = notification.data.comment; - + switch(notification.courier){ case 'newReply': subject = 'Someone replied to your comment on "'+post.title+'"'; @@ -18,7 +18,7 @@ buildEmailNotification = function (notification) { case 'newComment': subject = 'A new comment on your post "'+post.title+'"'; template = 'emailNewComment'; - break; + break; default: break; @@ -26,7 +26,7 @@ buildEmailNotification = function (notification) { var emailProperties = _.extend(notification.data, { body: marked(comment.body), - profileUrl: getProfileUrlById(comment.userId), + profileUrl: getProfileUrlBySlugOrId(comment.userId), postCommentUrl: getPostCommentUrl(post._id, comment._id), postLink: getPostLink(post) }); diff --git a/packages/telescope-rss/lib/server/routes.js b/packages/telescope-rss/lib/server/routes.js index 73db1ad1a..50c57f7b2 100644 --- a/packages/telescope-rss/lib/server/routes.js +++ b/packages/telescope-rss/lib/server/routes.js @@ -5,34 +5,49 @@ Meteor.startup(function () { Router.route('/feed.xml', function () { this.response.write(servePostRSS('new', 'feed.xml')); this.response.end(); - }, {where: 'server'}); + }, { + name: 'feed', + where: 'server' + }); // New Post RSS Router.route('/rss/posts/new.xml', function () { this.response.write(servePostRSS('top', 'rss/posts/new.xml')); this.response.end(); - }, {where: 'server'}); + }, { + name: 'rss_posts_new', + where: 'server' + }); // Top Post RSS Router.route('/rss/posts/top.xml', function () { this.response.write(servePostRSS('top', 'rss/posts/top.xml')); this.response.end(); - }, {where: 'server'}); + }, { + name: 'rss_posts_top', + where: 'server' + }); // Best Post RSS Router.route('/rss/posts/best.xml', function () { this.response.write(servePostRSS('best', 'rss/posts/best.xml')); this.response.end(); - }, {where: 'server'}); + }, { + name: 'rss_posts_best', + where: 'server' + }); // Comment RSS Router.route('/rss/comments.xml', function() { this.response.write(serveCommentRSS()); this.response.end(); - }, {where: 'server'}); + }, { + name: 'rss_comments', + where: 'server' + }); }); diff --git a/packages/telescope-rss/lib/server/rss.js b/packages/telescope-rss/lib/server/rss.js index 325814e4f..7e4cabdf3 100644 --- a/packages/telescope-rss/lib/server/rss.js +++ b/packages/telescope-rss/lib/server/rss.js @@ -4,9 +4,9 @@ var getMeta = function(url) { return { title: getSetting('title'), description: getSetting('tagline'), - feed_url: Meteor.absoluteUrl()+url, + feed_url: Meteor.absoluteUrl(url), site_url: Meteor.absoluteUrl(), - image_url: Meteor.absoluteUrl()+'img/favicon.png', + image_url: Meteor.absoluteUrl('img/favicon.png'), }; }; @@ -32,7 +32,7 @@ servePostRSS = function(view, url) { }; serveCommentRSS = function() { - var feed = new RSS(getMeta('rss/comments.xml')); + var feed = new RSS(getMeta(Router.routes['rss_comments'].path())); Comments.find({isDeleted: {$ne: true}}, {sort: {postedAt: -1}, limit: 20}).forEach(function(comment) { post = Posts.findOne(comment.postId); diff --git a/packages/telescope-search/lib/client/views/search.js b/packages/telescope-search/lib/client/views/search.js index 103434b8d..9be30e128 100644 --- a/packages/telescope-search/lib/client/views/search.js +++ b/packages/telescope-search/lib/client/views/search.js @@ -30,7 +30,7 @@ Meteor.startup(function () { // if search field is empty, just do nothing and show an empty template $search.addClass('empty'); Session.set('searchQuery', ''); - Router.go('/search', null, {replaceState: true}); + Router.go('search', null, {replaceState: true}); } else { $search.removeClass('empty'); // if search field is not empty, add a delay to avoid firing new searches for every keystroke @@ -38,10 +38,10 @@ Meteor.startup(function () { Session.set('searchQuery', val); // Update the querystring. - var opts = {query: 'q=' + encodeURIComponent(val)}; + var opts = {query: {q: val}}; // if we're already on the search page, do a replaceState. Otherwise, // just use the pushState default. - if(getCurrentRoute().indexOf('/search') === 0) { + if(Router.current().route.getName() === 'search') { opts.replaceState = true; } Router.go('search', null, opts);