From 733887ca2b2a178f4adf6cc36281305dd31c58fe Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Mon, 21 Mar 2016 10:27:43 +0900 Subject: [PATCH 1/7] working on voting feature; added methods to cheatsheet --- .meteor/packages | 2 +- .meteor/versions | 1 + packages/base-components/lib/common/Icon.jsx | 10 ++++ packages/base-components/lib/components.js | 3 + .../base-components/lib/debug/Cheatsheet.jsx | 12 ++++ .../base-components/lib/posts/PostStats.jsx | 16 +++++ packages/base-components/lib/posts/Vote.jsx | 59 +++++++++++++++++++ .../lib/posts/list/PostItem.jsx | 5 +- packages/base-styles/lib/stylesheets/main.css | 9 +++ packages/nova-posts/lib/methods.js | 2 + .../{_nova-voting => nova-voting}/README.md | 0 .../lib/custom_fields.js | 10 ++-- .../lib/scoring.js | 0 .../lib/server/cron.js | 2 +- .../{_nova-voting => nova-voting}/lib/vote.js | 0 .../{_nova-voting => nova-voting}/package.js | 5 ++ 16 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 packages/base-components/lib/common/Icon.jsx create mode 100644 packages/base-components/lib/posts/PostStats.jsx create mode 100644 packages/base-components/lib/posts/Vote.jsx rename packages/{_nova-voting => nova-voting}/README.md (100%) rename packages/{_nova-voting => nova-voting}/lib/custom_fields.js (81%) rename packages/{_nova-voting => nova-voting}/lib/scoring.js (100%) rename packages/{_nova-voting => nova-voting}/lib/server/cron.js (94%) rename packages/{_nova-voting => nova-voting}/lib/vote.js (100%) rename packages/{_nova-voting => nova-voting}/package.js (82%) diff --git a/.meteor/packages b/.meteor/packages index 4d7a6c497..97341908e 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -21,8 +21,8 @@ nova:notifications nova:getting-started nova:categories nova:share +nova:voting -# nova:voting # nova:migrations # nova:api # nova:email diff --git a/.meteor/versions b/.meteor/versions index ad4c95570..562eb68c8 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -104,6 +104,7 @@ nova:search@0.25.7 nova:settings@0.25.7 nova:share@0.25.7 nova:users@0.25.7 +nova:voting@0.25.7 npm-bcrypt@0.7.8_2 npm-mongo@1.4.41-rc.2 oauth@1.1.8-rc.2 diff --git a/packages/base-components/lib/common/Icon.jsx b/packages/base-components/lib/common/Icon.jsx new file mode 100644 index 000000000..63b903a43 --- /dev/null +++ b/packages/base-components/lib/common/Icon.jsx @@ -0,0 +1,10 @@ +const Icon = ({ name, iconClass }) => { + const icons = Telescope.utils.icons; + const iconCode = !!icons[name] ? icons[name] : name; + iconClass = (typeof iconClass === 'string') ? ' '+iconClass : ''; + const c = 'icon fa fa-fw fa-' + iconCode + ' icon-' + name + iconClass; + return ; +} + +module.exports = Icon; +export default Icon; \ No newline at end of file diff --git a/packages/base-components/lib/components.js b/packages/base-components/lib/components.js index 2cfc46e86..4ad8003d5 100644 --- a/packages/base-components/lib/components.js +++ b/packages/base-components/lib/components.js @@ -7,6 +7,7 @@ Telescope.registerComponent("Logo", require('./common/Logo.jsx')); Telescope.registerComponent("Flash", require('./common/Flash.jsx')); Telescope.registerComponent("FlashMessages", require('./common/FlashMessages.jsx')); Telescope.registerComponent("NewsletterForm", require('./common/NewsletterForm.jsx')); +Telescope.registerComponent("Icon", require('./common/Icon.jsx')); // posts @@ -20,6 +21,8 @@ Telescope.registerComponent("PostList", require('./posts/list/PostList.jsx')); Telescope.registerComponent("PostCategories", require('./posts/list/PostCategories.jsx')); Telescope.registerComponent("PostCommenters", require('./posts/list/PostCommenters.jsx')); Telescope.registerComponent("Post", require('./posts/Post.jsx')); +Telescope.registerComponent("PostStats", require('./posts/PostStats.jsx')); +Telescope.registerComponent("Vote", require('./posts/Vote.jsx')); // comments diff --git a/packages/base-components/lib/debug/Cheatsheet.jsx b/packages/base-components/lib/debug/Cheatsheet.jsx index 6da2e8cf5..33f72f72c 100644 --- a/packages/base-components/lib/debug/Cheatsheet.jsx +++ b/packages/base-components/lib/debug/Cheatsheet.jsx @@ -45,6 +45,10 @@ const Cheatsheet = props => { +

Methods

+
@@ -53,6 +57,10 @@ const Cheatsheet = props => { +

Methods

+
@@ -61,6 +69,10 @@ const Cheatsheet = props => { +

Methods

+
diff --git a/packages/base-components/lib/posts/PostStats.jsx b/packages/base-components/lib/posts/PostStats.jsx new file mode 100644 index 000000000..5774b7c0d --- /dev/null +++ b/packages/base-components/lib/posts/PostStats.jsx @@ -0,0 +1,16 @@ +const PostStats = ({post}) => { + + ({Icon} = Telescope.components); + + return ( +
+ {Math.floor(post.score*100)/100} Score + {post.upvotes} Upvotes + {post.clickCount} Clicks + {post.viewCount} Views +
+ ) +} + +module.exports = PostStats; +export default PostStats; \ No newline at end of file diff --git a/packages/base-components/lib/posts/Vote.jsx b/packages/base-components/lib/posts/Vote.jsx new file mode 100644 index 000000000..681c0be7e --- /dev/null +++ b/packages/base-components/lib/posts/Vote.jsx @@ -0,0 +1,59 @@ +import React, { PropTypes, Component } from 'react'; + +class Vote extends Component { + + constructor() { + super(); + this.upvote = this.upvote.bind(this); + } + + upvote(e) { + e.preventDefault(); + + const post = this.props.post; + const user = this.props.currentUser; + + if(!user){ + FlowRouter.go('signIn'); + Messages.flash(__("please_log_in_first"), "info"); + } else if (user.hasUpvoted(post)) { + Meteor.call('posts.cancelUpvote', post._id, function(){ + Events.track("post upvote cancelled", {'_id': post._id}); + }); + } else { + Meteor.call('posts.upvote', post._id, function(){ + Events.track("post upvoted", {'_id': post._id}); + }); + } + + } + + render() { + + ({Icon} = Telescope.components); + + const user = this.props.currentUser; + + let actionsClass = "vote"; + if (user.hasUpvoted(this)) actionsClass += " voted upvoted"; + if (user.hasDownvoted(this)) actionsClass += " voted downvoted"; + + return ( +
+ + + Upvote + +
+ ) + } + +} + +Vote.propTypes = { + post: React.PropTypes.object.isRequired, // the current comment + currentUser: React.PropTypes.object, // the current user +} + +module.exports = Vote; +export default Vote; \ No newline at end of file diff --git a/packages/base-components/lib/posts/list/PostItem.jsx b/packages/base-components/lib/posts/list/PostItem.jsx index 94c1ed16e..d40ffa68d 100644 --- a/packages/base-components/lib/posts/list/PostItem.jsx +++ b/packages/base-components/lib/posts/list/PostItem.jsx @@ -40,16 +40,19 @@ class PostItem extends Component { render() { - ({UserAvatar} = Telescope.components); + ({UserAvatar, Vote, PostStats} = Telescope.components); const post = this.props.post; return (
+

{post.title}

{Users.getDisplayName(post.user)}, {moment(post.postedAt).fromNow()}, {post.commentCount} comments

+ + {this.renderCategories()} {this.renderCommenters()} {this.renderActions()} diff --git a/packages/base-styles/lib/stylesheets/main.css b/packages/base-styles/lib/stylesheets/main.css index 5c9f10295..26125c06b 100644 --- a/packages/base-styles/lib/stylesheets/main.css +++ b/packages/base-styles/lib/stylesheets/main.css @@ -97,6 +97,7 @@ code{ } .cheatsheet h3{ margin-bottom: 10px; + font-weight: bold; } .cheatsheet code{ font-size: 13px; @@ -106,4 +107,12 @@ code{ height: 24px; width: 24px; display: inline-block; +} + +.sr-only{ + display: none; +} + +.upvoted .upvote{ + opacity: 0.5; } \ No newline at end of file diff --git a/packages/nova-posts/lib/methods.js b/packages/nova-posts/lib/methods.js index 2989c263f..72bc6f28b 100644 --- a/packages/nova-posts/lib/methods.js +++ b/packages/nova-posts/lib/methods.js @@ -213,6 +213,7 @@ Meteor.methods({ 'posts.upvote': function (postId) { check(postId, String); + console.log("upvote") return Telescope.operateOnItem.call(this, Posts, postId, Meteor.user(), "upvote"); }, @@ -223,6 +224,7 @@ Meteor.methods({ 'posts.cancelUpvote': function (postId) { check(postId, String); + console.log("cancelUpvote") return Telescope.operateOnItem.call(this, Posts, postId, Meteor.user(), "cancelUpvote"); }, diff --git a/packages/_nova-voting/README.md b/packages/nova-voting/README.md similarity index 100% rename from packages/_nova-voting/README.md rename to packages/nova-voting/README.md diff --git a/packages/_nova-voting/lib/custom_fields.js b/packages/nova-voting/lib/custom_fields.js similarity index 81% rename from packages/_nova-voting/lib/custom_fields.js rename to packages/nova-voting/lib/custom_fields.js index c325a1a47..fd9ea20ef 100644 --- a/packages/_nova-voting/lib/custom_fields.js +++ b/packages/nova-voting/lib/custom_fields.js @@ -1,3 +1,5 @@ +import PublicationUtils from 'meteor/utilities:smart-publications'; + // ------------------------------------- Posts -------------------------------- // Posts.addField([ @@ -67,8 +69,8 @@ Posts.addField([ }, ]); -Telescope.utils.addToFields(Posts.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]); -Telescope.utils.addToFields(Posts.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); +PublicationUtils.addToFields(Posts.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]); +PublicationUtils.addToFields(Posts.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); // ------------------------------------- Comments -------------------------------- // @@ -143,5 +145,5 @@ Comments.addField([ }, ]); -Telescope.utils.addToFields(Comments.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]); -Telescope.utils.addToFields(Comments.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); +PublicationUtils.addToFields(Comments.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]); +PublicationUtils.addToFields(Comments.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); diff --git a/packages/_nova-voting/lib/scoring.js b/packages/nova-voting/lib/scoring.js similarity index 100% rename from packages/_nova-voting/lib/scoring.js rename to packages/nova-voting/lib/scoring.js diff --git a/packages/_nova-voting/lib/server/cron.js b/packages/nova-voting/lib/server/cron.js similarity index 94% rename from packages/_nova-voting/lib/server/cron.js rename to packages/nova-voting/lib/server/cron.js index c14dc146e..823767312 100644 --- a/packages/_nova-voting/lib/server/cron.js +++ b/packages/nova-voting/lib/server/cron.js @@ -1,5 +1,5 @@ Meteor.startup(function () { - var scoreInterval = Settings.get("scoreUpdateInterval") || 30; + var scoreInterval = Telescope.settings.get("scoreUpdateInterval") || 30; if (scoreInterval > 0) { // active items get updated every N seconds diff --git a/packages/_nova-voting/lib/vote.js b/packages/nova-voting/lib/vote.js similarity index 100% rename from packages/_nova-voting/lib/vote.js rename to packages/nova-voting/lib/vote.js diff --git a/packages/_nova-voting/package.js b/packages/nova-voting/package.js similarity index 82% rename from packages/_nova-voting/package.js rename to packages/nova-voting/package.js index 1120fded9..8064ead71 100644 --- a/packages/_nova-voting/package.js +++ b/packages/nova-voting/package.js @@ -11,6 +11,11 @@ Package.onUse(function (api) { api.use(['nova:core@0.25.7']); + api.use([ + 'nova:posts@0.25.7', + 'nova:comments@0.25.7' + ], ['client', 'server']); + api.addFiles([ 'lib/scoring.js', 'lib/vote.js', From c470057babce2f0721a0d985488639c07a338f7c Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Mon, 21 Mar 2016 10:46:00 +0900 Subject: [PATCH 2/7] finish upvote button --- packages/base-components/lib/posts/Vote.jsx | 7 ++++--- packages/base-styles/lib/stylesheets/main.css | 2 +- packages/nova-voting/lib/custom_fields.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/base-components/lib/posts/Vote.jsx b/packages/base-components/lib/posts/Vote.jsx index 681c0be7e..ede4a469d 100644 --- a/packages/base-components/lib/posts/Vote.jsx +++ b/packages/base-components/lib/posts/Vote.jsx @@ -32,15 +32,16 @@ class Vote extends Component { ({Icon} = Telescope.components); + const post = this.props.post; const user = this.props.currentUser; let actionsClass = "vote"; - if (user.hasUpvoted(this)) actionsClass += " voted upvoted"; - if (user.hasDownvoted(this)) actionsClass += " voted downvoted"; + if (user.hasUpvoted(post)) actionsClass += " voted upvoted"; + if (user.hasDownvoted(post)) actionsClass += " voted downvoted"; return (
- + Upvote diff --git a/packages/base-styles/lib/stylesheets/main.css b/packages/base-styles/lib/stylesheets/main.css index 26125c06b..a15e19fa7 100644 --- a/packages/base-styles/lib/stylesheets/main.css +++ b/packages/base-styles/lib/stylesheets/main.css @@ -114,5 +114,5 @@ code{ } .upvoted .upvote{ - opacity: 0.5; + opacity: 0.3; } \ No newline at end of file diff --git a/packages/nova-voting/lib/custom_fields.js b/packages/nova-voting/lib/custom_fields.js index fd9ea20ef..bba9df9c6 100644 --- a/packages/nova-voting/lib/custom_fields.js +++ b/packages/nova-voting/lib/custom_fields.js @@ -69,7 +69,7 @@ Posts.addField([ }, ]); -PublicationUtils.addToFields(Posts.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]); +PublicationUtils.addToFields(Posts.publishedFields.list, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); PublicationUtils.addToFields(Posts.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]); // ------------------------------------- Comments -------------------------------- // From d6649a716d415573d9979b8069ffe76dbe2f71a0 Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Mon, 21 Mar 2016 10:50:22 +0900 Subject: [PATCH 3/7] handle user not logged in --- packages/base-components/lib/posts/Vote.jsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/base-components/lib/posts/Vote.jsx b/packages/base-components/lib/posts/Vote.jsx index ede4a469d..24fb2a1c0 100644 --- a/packages/base-components/lib/posts/Vote.jsx +++ b/packages/base-components/lib/posts/Vote.jsx @@ -1,5 +1,8 @@ import React, { PropTypes, Component } from 'react'; +import Core from "meteor/nova:core"; +const Messages = Core.Messages; + class Vote extends Component { constructor() { @@ -14,8 +17,7 @@ class Vote extends Component { const user = this.props.currentUser; if(!user){ - FlowRouter.go('signIn'); - Messages.flash(__("please_log_in_first"), "info"); + Messages.flash("Please log in first"); } else if (user.hasUpvoted(post)) { Meteor.call('posts.cancelUpvote', post._id, function(){ Events.track("post upvote cancelled", {'_id': post._id}); @@ -36,8 +38,8 @@ class Vote extends Component { const user = this.props.currentUser; let actionsClass = "vote"; - if (user.hasUpvoted(post)) actionsClass += " voted upvoted"; - if (user.hasDownvoted(post)) actionsClass += " voted downvoted"; + if (Users.hasUpvoted(user, post)) actionsClass += " voted upvoted"; + if (Users.hasDownvoted(user, post)) actionsClass += " voted downvoted"; return (
From 3daef42d74622e2dbd8c90b1f6f9393da5346d1a Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Mon, 21 Mar 2016 10:56:14 +0900 Subject: [PATCH 4/7] fix cheatsheet SSR --- packages/base-components/lib/debug/Cheatsheet.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/base-components/lib/debug/Cheatsheet.jsx b/packages/base-components/lib/debug/Cheatsheet.jsx index 33f72f72c..a72d089f1 100644 --- a/packages/base-components/lib/debug/Cheatsheet.jsx +++ b/packages/base-components/lib/debug/Cheatsheet.jsx @@ -1,3 +1,5 @@ +const methodList = Meteor.isServer ? Meteor.server.method_handlers : Meteor.connection._methodHandlers; + const renderFunction = (func, name) => { const s = func.toString(); const openParen = s.indexOf("("); @@ -47,7 +49,7 @@ const Cheatsheet = props => {

Methods

    - {_.map(Meteor.connection._methodHandlers, (item, key) => (key.indexOf("users.") !== -1 ? renderFunction(item, key) : null))} + {_.map(methodList, (item, key) => (key.indexOf("users.") !== -1 ? renderFunction(item, key) : null))}
@@ -59,7 +61,7 @@ const Cheatsheet = props => {

Methods

    - {_.map(Meteor.connection._methodHandlers, (item, key) => (key.indexOf("posts.") !== -1 ? renderFunction(item, key) : null))} + {_.map(methodList, (item, key) => (key.indexOf("posts.") !== -1 ? renderFunction(item, key) : null))}
@@ -71,7 +73,7 @@ const Cheatsheet = props => {

Methods

    - {_.map(Meteor.connection._methodHandlers, (item, key) => (key.indexOf("comments.") !== -1 ? renderFunction(item, key) : null))} + {_.map(methodList, (item, key) => (key.indexOf("comments.") !== -1 ? renderFunction(item, key) : null))}
From cb3918f933d8d062e4cc324cb7810c2a89750f09 Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Tue, 22 Mar 2016 10:22:46 +0900 Subject: [PATCH 5/7] adding daily view at /daily --- packages/base-components/lib/components.js | 2 + .../base-components/lib/posts/PostDaily.jsx | 45 +++++++++++++++++++ .../base-components/lib/posts/PostDay.jsx | 40 +++++++++++++++++ .../lib/posts/list/PostList.jsx | 8 ++-- packages/base-components/lib/routes.jsx | 10 +++++ packages/base-styles/lib/stylesheets/main.css | 4 ++ packages/nova-demo/demo-app.jsx | 2 + ...demo-component.jsx => demo-components.jsx} | 38 ++++++++-------- packages/nova-demo/package.js | 1 - .../nova-posts/lib/server/publications.js | 3 +- 10 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 packages/base-components/lib/posts/PostDaily.jsx create mode 100644 packages/base-components/lib/posts/PostDay.jsx rename packages/nova-demo/{demo-component.jsx => demo-components.jsx} (83%) diff --git a/packages/base-components/lib/components.js b/packages/base-components/lib/components.js index 4ad8003d5..bfc35605d 100644 --- a/packages/base-components/lib/components.js +++ b/packages/base-components/lib/components.js @@ -22,6 +22,8 @@ Telescope.registerComponent("PostCategories", require('./posts/list/PostCategori Telescope.registerComponent("PostCommenters", require('./posts/list/PostCommenters.jsx')); Telescope.registerComponent("Post", require('./posts/Post.jsx')); Telescope.registerComponent("PostStats", require('./posts/PostStats.jsx')); +Telescope.registerComponent("PostDaily", require('./posts/PostDaily.jsx')); +Telescope.registerComponent("PostDay", require('./posts/PostDay.jsx')); Telescope.registerComponent("Vote", require('./posts/Vote.jsx')); // comments diff --git a/packages/base-components/lib/posts/PostDaily.jsx b/packages/base-components/lib/posts/PostDaily.jsx new file mode 100644 index 000000000..8b94d8b9b --- /dev/null +++ b/packages/base-components/lib/posts/PostDaily.jsx @@ -0,0 +1,45 @@ +import React, { PropTypes, Component } from 'react'; + +// for a number of days "n" return dates object for the past n days +const getLastNDates = n => { + return _.range(n).map( + i => moment().subtract(i, 'days').startOf('day').toDate() + ); +}; + +class PostDaily extends Component{ + + constructor(props) { + super(props); + this.loadMoreDays = this.loadMoreDays.bind(this); + this.state = {days: props.days}; + } + + loadMoreDays(e) { + e.preventDefault(); + this.setState({ + days: this.state.days + 5 + }); + } + + render() { + ({PostDay} = Telescope.components); + return ( +
+ {getLastNDates(this.state.days).map((date, index) => )} + Load More Days +
+ ) + } +} + +PostDaily.propTypes = { + days: React.PropTypes.number +} + +PostDaily.defaultProps = { + days: 5 +} + +module.exports = PostDaily; +export default PostDaily; diff --git a/packages/base-components/lib/posts/PostDay.jsx b/packages/base-components/lib/posts/PostDay.jsx new file mode 100644 index 000000000..67af16cb6 --- /dev/null +++ b/packages/base-components/lib/posts/PostDay.jsx @@ -0,0 +1,40 @@ +import React, { PropTypes, Component } from 'react'; + +const PostDay = ({date, number}) => { + + ({PostList} = Telescope.components); + + const terms = { + view: "top", + date: date, + after: moment(date).format("YYYY-MM-DD"), + before: moment(date).format("YYYY-MM-DD"), + enableCache: number <= 15 ? true : false // only cache first 15 days + }; + + ({selector, options} = Posts.parameters.get(terms)); + + return ( +
+

{moment(date).format("dddd, MMMM Do YYYY")}

+ +
+ ) +} + +PostDay.propTypes = { + date: React.PropTypes.object, + number: React.PropTypes.number +} + +module.exports = PostDay; +export default PostDay; \ No newline at end of file diff --git a/packages/base-components/lib/posts/list/PostList.jsx b/packages/base-components/lib/posts/list/PostList.jsx index 3e0755341..2834dc1f7 100644 --- a/packages/base-components/lib/posts/list/PostList.jsx +++ b/packages/base-components/lib/posts/list/PostList.jsx @@ -1,11 +1,11 @@ -const PostList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore}) => { +const PostList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore, showViews = true}) => { ({PostItem, LoadMore, PostsLoading, NoPosts, NoMorePosts, PostViews} = Telescope.components); if (!!results.length) { return (
- + {showViews ? : null}
{results.map(post => )}
@@ -15,7 +15,7 @@ const PostList = ({results, currentUser, hasMore, ready, count, totalCount, load } else if (!ready) { return (
- + {showViews ? : null}
@@ -24,7 +24,7 @@ const PostList = ({results, currentUser, hasMore, ready, count, totalCount, load } else { return (
- + {showViews ? : null}
diff --git a/packages/base-components/lib/routes.jsx b/packages/base-components/lib/routes.jsx index 6177a3a40..912615ed8 100644 --- a/packages/base-components/lib/routes.jsx +++ b/packages/base-components/lib/routes.jsx @@ -24,6 +24,16 @@ FlowRouter.route('/', { } }); +FlowRouter.route('/daily/:days?', { + name: 'posts.list', + action(params, queryParams) { + + ({AppContainer, PostDaily} = Telescope.components); + + mount(AppContainer, {content: }) + } +}); + FlowRouter.route('/posts/:_id', { name: 'posts.single', action(params, queryParams) { diff --git a/packages/base-styles/lib/stylesheets/main.css b/packages/base-styles/lib/stylesheets/main.css index a15e19fa7..6b85f4025 100644 --- a/packages/base-styles/lib/stylesheets/main.css +++ b/packages/base-styles/lib/stylesheets/main.css @@ -115,4 +115,8 @@ code{ .upvoted .upvote{ opacity: 0.3; +} + +.post-day h2{ + font-weight: bold; } \ No newline at end of file diff --git a/packages/nova-demo/demo-app.jsx b/packages/nova-demo/demo-app.jsx index 904bb70c9..efc0764c1 100644 --- a/packages/nova-demo/demo-app.jsx +++ b/packages/nova-demo/demo-app.jsx @@ -1,5 +1,7 @@ import {mount} from 'react-mounter'; +import MoviesWrapper from './demo-components.jsx'; + ////////////////////////////////////////////////////// // Collection & Schema // ////////////////////////////////////////////////////// diff --git a/packages/nova-demo/demo-component.jsx b/packages/nova-demo/demo-components.jsx similarity index 83% rename from packages/nova-demo/demo-component.jsx rename to packages/nova-demo/demo-components.jsx index d196c3ee5..8bd4aac72 100644 --- a/packages/nova-demo/demo-component.jsx +++ b/packages/nova-demo/demo-components.jsx @@ -6,20 +6,20 @@ import Core from 'meteor/nova:core'; import SmartContainers from "meteor/utilities:react-list-container"; import FormContainers from "meteor/utilities:react-form-containers"; -FlashContainer = Core.FlashContainer; -ModalButton = Core.ModalButton; -NewDocContainer = FormContainers.NewDocContainer; -EditDocContainer = FormContainers.EditDocContainer; -ListContainer = SmartContainers.ListContainer; +const ModalButton = Core.ModalButton; +const NewDocContainer = FormContainers.NewDocContainer; +const EditDocContainer = FormContainers.EditDocContainer; +const ListContainer = SmartContainers.ListContainer; + +const FlashContainer = Telescope.components.FlashContainer; +const FlashMessages = Telescope.components.FlashMessages; ////////////////////////////////////////////////////// // MoviesWrapper // ////////////////////////////////////////////////////// -MoviesWrapper = React.createClass({ - +class MoviesWrapper extends Component { render() { - return (
@@ -27,7 +27,7 @@ MoviesWrapper = React.createClass({ - +
) } -}); +} ////////////////////////////////////////////////////// // MoviesList // ////////////////////////////////////////////////////// -MoviesList = React.createClass({ +class MoviesList extends Component { renderNew() { @@ -62,7 +62,7 @@ MoviesList = React.createClass({ ) return !!this.props.currentUser ? component : ""; - }, + } render() { @@ -74,12 +74,12 @@ MoviesList = React.createClass({
) } -}); +}; + ////////////////////////////////////////////////////// // Movie // ////////////////////////////////////////////////////// -Movie = React.createClass({ - +class Movie extends Component { renderEdit() { @@ -96,7 +96,7 @@ Movie = React.createClass({ {this.props.currentUser && this.props.currentUser._id === movie.userId ? component : ""}
) - }, + } render() { @@ -111,6 +111,8 @@ Movie = React.createClass({ ) } -}); +}; -const LoadMore = props => Load More ({props.count}/{props.totalCount}) \ No newline at end of file +const LoadMore = props => Load More ({props.count}/{props.totalCount}) + +export default MoviesWrapper \ No newline at end of file diff --git a/packages/nova-demo/package.js b/packages/nova-demo/package.js index 83b12d04e..169ecef40 100644 --- a/packages/nova-demo/package.js +++ b/packages/nova-demo/package.js @@ -24,7 +24,6 @@ Package.onUse(function (api) { ]); api.addFiles([ - 'demo-component.jsx', 'demo-app.jsx' ], ['client', 'server']); diff --git a/packages/nova-posts/lib/server/publications.js b/packages/nova-posts/lib/server/publications.js index 2a523c66c..73d0aff27 100644 --- a/packages/nova-posts/lib/server/publications.js +++ b/packages/nova-posts/lib/server/publications.js @@ -70,7 +70,8 @@ Meteor.publish('posts.list', function (terms) { terms.currentUserId = this.userId; // add currentUserId to terms ({selector, options} = Posts.parameters.get(terms)); - Counts.publish(this, 'posts.list', Posts.find(selector, options)); + // disabled for now because of FlowRouterSSR issue + // Counts.publish(this, 'posts.list', Posts.find(selector, options)); options.fields = Posts.publishedFields.list; From e3cd1fb017f1ada3d305556d07b59e64a75445ae Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Tue, 22 Mar 2016 10:38:57 +0900 Subject: [PATCH 6/7] small scoring tweaks --- packages/base-components/lib/posts/Post.jsx | 9 +++++++-- packages/base-components/lib/posts/PostStats.jsx | 2 +- packages/nova-voting/lib/scoring.js | 6 ++---- packages/nova-voting/lib/server/cron.js | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/base-components/lib/posts/Post.jsx b/packages/base-components/lib/posts/Post.jsx index 50e052e58..d7539ca86 100644 --- a/packages/base-components/lib/posts/Post.jsx +++ b/packages/base-components/lib/posts/Post.jsx @@ -1,6 +1,6 @@ -const Post = ({document}) => { +const Post = ({document, currentUser}) => { - ({ListContainer, CommentList, CommentNew, PostCategories, SocialShare} = Telescope.components); + ({ListContainer, CommentList, CommentNew, PostCategories, SocialShare, Vote, PostStats} = Telescope.components); const post = document; const htmlBody = {__html: post.htmlBody}; @@ -8,10 +8,15 @@ const Post = ({document}) => { return (
+ +

{post.title}

{post.commentCount} comments

{moment(post.postedAt).fromNow()}

+ + + {post.categoriesArray ? : ""}
diff --git a/packages/base-components/lib/posts/PostStats.jsx b/packages/base-components/lib/posts/PostStats.jsx index 5774b7c0d..d5d3a19df 100644 --- a/packages/base-components/lib/posts/PostStats.jsx +++ b/packages/base-components/lib/posts/PostStats.jsx @@ -4,7 +4,7 @@ const PostStats = ({post}) => { return (
- {Math.floor(post.score*100)/100} Score + {post.score ? {Math.floor(post.score*10000)/10000} Score : ""} {post.upvotes} Upvotes {post.clickCount} Clicks {post.viewCount} Views diff --git a/packages/nova-voting/lib/scoring.js b/packages/nova-voting/lib/scoring.js index 1ecfb2cba..4ea2e707e 100644 --- a/packages/nova-voting/lib/scoring.js +++ b/packages/nova-voting/lib/scoring.js @@ -37,10 +37,8 @@ Telescope.updateScore = function (args) { // time decay factor var f = 1.3; - // use baseScore if defined, if not just use the number of votes - // note: for transition period, also use votes if there are more votes than baseScore - // var baseScore = Math.max(item.votes || 0, item.baseScore || 0); - var baseScore = item.baseScore; + // use baseScore if defined, if not just use 0 + var baseScore = item.baseScore || 0; // HN algorithm var newScore = baseScore / Math.pow(ageInHours + 2, f); diff --git a/packages/nova-voting/lib/server/cron.js b/packages/nova-voting/lib/server/cron.js index 823767312..7034bf49c 100644 --- a/packages/nova-voting/lib/server/cron.js +++ b/packages/nova-voting/lib/server/cron.js @@ -4,6 +4,7 @@ Meteor.startup(function () { // active items get updated every N seconds Meteor.setInterval(function () { + var updatedPosts = 0; var updatedComments = 0; // console.log('tick ('+scoreInterval+')'); From 16d71bbb9df2f086fe501756c5fad8576cef559b Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Tue, 22 Mar 2016 11:04:59 +0900 Subject: [PATCH 7/7] adding search form --- .../base-components/lib/common/Header.jsx | 4 +- .../base-components/lib/common/SearchForm.jsx | 65 +++++++++++++++++++ packages/base-components/lib/components.js | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 packages/base-components/lib/common/SearchForm.jsx diff --git a/packages/base-components/lib/common/Header.jsx b/packages/base-components/lib/common/Header.jsx index 2a91544f2..8a793015d 100644 --- a/packages/base-components/lib/common/Header.jsx +++ b/packages/base-components/lib/common/Header.jsx @@ -5,7 +5,7 @@ const Messages = Core.Messages; const Header = ({currentUser}) => { - ({Logo, ListContainer, CategoriesList, FlashContainer, FlashMessages, ModalButton, NewDocContainer, CanCreatePost, CurrentUserContainer, NewsletterForm} = Telescope.components); + ({Logo, ListContainer, CategoriesList, FlashContainer, FlashMessages, ModalButton, NewDocContainer, CanCreatePost, CurrentUserContainer, NewsletterForm, SearchForm} = Telescope.components); const logoUrl = Telescope.settings.get("logoUrl"); const siteTitle = Telescope.settings.get("title", "Telescope"); @@ -41,6 +41,8 @@ const Header = ({currentUser}) => { + + diff --git a/packages/base-components/lib/common/SearchForm.jsx b/packages/base-components/lib/common/SearchForm.jsx new file mode 100644 index 000000000..4b780f96f --- /dev/null +++ b/packages/base-components/lib/common/SearchForm.jsx @@ -0,0 +1,65 @@ +import React, { PropTypes, Component } from 'react'; +import Formsy from 'formsy-react'; +import FRC from 'formsy-react-components'; + +const Input = FRC.Input; + +// see: http://stackoverflow.com/questions/1909441/jquery-keyup-delay +const delay = (function(){ + var timer = 0; + return function(callback, ms){ + clearTimeout (timer); + timer = setTimeout(callback, ms); + }; +})(); + +class SearchForm extends Component{ + + constructor() { + super(); + this.search = this.search.bind(this); + } + + search(data) { + + if (FlowRouter.getRouteName() !== "posts.list") { + FlowRouter.go("posts.list"); + } + + if (data.searchQuery === '') { + data.searchQuery = null; + } + + delay(function(){ + FlowRouter.setQueryParams({query: data.searchQuery}); + }, 700 ); + + } + + render() { + + return ( +
+ + + +
+ ) + } +} + +SearchForm.propTypes = { + labelText: React.PropTypes.string +} + +SearchForm.defaultProps = { + labelText: "Search" +}; + +module.exports = SearchForm; +export default SearchForm; \ No newline at end of file diff --git a/packages/base-components/lib/components.js b/packages/base-components/lib/components.js index bfc35605d..37d61740c 100644 --- a/packages/base-components/lib/components.js +++ b/packages/base-components/lib/components.js @@ -8,6 +8,7 @@ Telescope.registerComponent("Flash", require('./common/Flash.jsx')); Telescope.registerComponent("FlashMessages", require('./common/FlashMessages.jsx')); Telescope.registerComponent("NewsletterForm", require('./common/NewsletterForm.jsx')); Telescope.registerComponent("Icon", require('./common/Icon.jsx')); +Telescope.registerComponent("SearchForm", require('./common/SearchForm.jsx')); // posts