diff --git a/packages/nova-base-components/lib/posts/PostsItem.jsx b/packages/nova-base-components/lib/posts/PostsItem.jsx index 0a76ab288..5697c04a4 100644 --- a/packages/nova-base-components/lib/posts/PostsItem.jsx +++ b/packages/nova-base-components/lib/posts/PostsItem.jsx @@ -62,7 +62,7 @@ class PostsItem extends Component {
{post.user?
: null} -
+
{post.postedAt ? : }
diff --git a/packages/nova-forms/lib/DateTime.jsx b/packages/nova-forms/lib/DateTime.jsx index 185454f2c..ef8c408b3 100644 --- a/packages/nova-forms/lib/DateTime.jsx +++ b/packages/nova-forms/lib/DateTime.jsx @@ -1,17 +1,23 @@ import React, { PropTypes, Component } from 'react'; -import DateTimeField from 'react-datetime'; +import DateTimePicker from 'react-datetime'; import moment from 'moment'; class DateTime extends Component { + + // when the datetime picker mounts, NovaForm will catch the date value (no formsy mixin in this component) + componentWillMount() { + this.props.updateCurrentValue(this.props.name, this.props.value || new Date()); + } + render() { return (
- this.props.updateCurrentValue(this.props.name, newDate._d)} + // newDate argument is a Moment object given by react-datetime + onChange={newDate => { this.props.updateCurrentValue(this.props.name, newDate._d)}} format={"x"} inputProps={{name: this.props.name}} /> diff --git a/packages/nova-i18n-en-us/lib/en_US.js b/packages/nova-i18n-en-us/lib/en_US.js index ccc96a3c6..228c1352d 100644 --- a/packages/nova-i18n-en-us/lib/en_US.js +++ b/packages/nova-i18n-en-us/lib/en_US.js @@ -30,6 +30,7 @@ Telescope.strings.en = { "posts.created_message": "Post created.", "posts.rate_limit_error": "Please wait {details} seconds before posting again.", "posts.postedAt": "Posted at", + "posts.dateNotDefined": "Date not defined", "comments.comments": "Comments", "comments.count": "{count, plural, =0 {No comments} one {# comment} other {# comments}}", diff --git a/packages/nova-posts/lib/callbacks.js b/packages/nova-posts/lib/callbacks.js index c0fc1def9..f059786b5 100644 --- a/packages/nova-posts/lib/callbacks.js +++ b/packages/nova-posts/lib/callbacks.js @@ -160,11 +160,11 @@ function PostsNewSubmittedPropertiesCheck (post, user) { } }); - + // note: not needed there anymore, this is already set in the next callback 'posts.new.sync' with other related properties (status, createdAt) // if no post status has been set, set it now - if (!post.status) { - post.status = Posts.getDefaultStatus(user); - } + // if (!post.status) { + // post.status = Posts.getDefaultStatus(user); + // } // if no userId has been set, default to current user id if (!post.userId) { @@ -197,7 +197,7 @@ function PostsNewRequiredPropertiesCheck (post, user) { const defaultProperties = { createdAt: new Date(), author: Users.getDisplayNameById(post.userId), - status: Posts.getDefaultStatus() + status: Posts.getDefaultStatus(user) }; post = _.extend(defaultProperties, post); @@ -205,6 +205,11 @@ function PostsNewRequiredPropertiesCheck (post, user) { // generate slug post.slug = Telescope.utils.slugify(post.title); + // post is not pending and has been scheduled to be posted in the future by a moderator/admin + if (post.status !== Posts.config.STATUS_PENDING && post.postedAt && post.postedAt > post.createdAt) { + post.status = Posts.config.STATUS_SCHEDULED; + } + // if post is approved but doesn't have a postedAt date, give it a default date // note: pending posts get their postedAt date only once theyre approved if (Posts.isApproved(post) && !post.postedAt) { @@ -318,6 +323,12 @@ Telescope.callbacks.add("posts.edit.sync", PostsEditForceStickyToFalse); * @summary Set postedAt date */ function PostsEditSetPostedAt (post, oldPost) { + + // post is not pending and has been scheduled to be posted in the future by a moderator/admin + if (post.status !== Posts.config.STATUS_PENDING && post.postedAt && post.postedAt > new Date()) { + Posts.update(post._id, {$set: {status: Posts.config.STATUS_SCHEDULED}}); + } + // if post is approved but doesn't have a postedAt date, give it a default date // note: pending posts get their postedAt date only once theyre approved if (Posts.isApproved(post) && !post.postedAt) { diff --git a/packages/nova-posts/lib/schema.js b/packages/nova-posts/lib/schema.js index bdc978a7f..1fb4231d6 100644 --- a/packages/nova-posts/lib/schema.js +++ b/packages/nova-posts/lib/schema.js @@ -30,6 +30,10 @@ Posts.config.postStatuses = [ { value: 5, label: 'deleted' + }, + { + value: 6, + label: 'scheduled' } ]; @@ -38,6 +42,7 @@ Posts.config.STATUS_APPROVED = 2; Posts.config.STATUS_REJECTED = 3; Posts.config.STATUS_SPAM = 4; Posts.config.STATUS_DELETED = 5; +Posts.config.STATUS_SCHEDULED = 6; const adminGroup = { name: "admin", diff --git a/packages/nova-posts/lib/server.js b/packages/nova-posts/lib/server.js index 41fc382d9..385bf6d2f 100644 --- a/packages/nova-posts/lib/server.js +++ b/packages/nova-posts/lib/server.js @@ -2,5 +2,6 @@ import Posts from './modules.js'; import './server/publications.js'; import './server/routes.js'; +import './server/cron.js'; export default Posts; \ No newline at end of file diff --git a/packages/nova-posts/lib/server/cron.js b/packages/nova-posts/lib/server/cron.js new file mode 100644 index 000000000..c96997a13 --- /dev/null +++ b/packages/nova-posts/lib/server/cron.js @@ -0,0 +1,40 @@ +import Posts from '../collection.js'; +import moment from 'moment'; + +SyncedCron.options = { + log: true, + collectionName: 'cronHistory', + utc: false, + collectionTTL: 172800 +}; + + +const addJob = function () { + SyncedCron.add({ + name: 'checkScheduledPosts', + schedule(parser) { + return parser.text('every 10 minutes'); + }, + job() { + // fetch all posts tagged as scheduled + const scheduledPosts = Posts.find({status: Posts.config.STATUS_SCHEDULED}, {fields: {_id: 1, status: 1, postedAt: 1, userId: 1, title: 1}}).fetch(); + + if (scheduledPosts) { + // filter the scheduled posts to retrieve only the one that should update, considering their schedule + const postsToUpdate = scheduledPosts.filter(post => post.postedAt <= new Date()); + + // update all posts with status approved + const postsIds = _.pluck(postsToUpdate, '_id'); + Posts.update({_id: {$in: postsIds}}, {$set: {status: Posts.config.STATUS_APPROVED}}, {multi: true}); + + // log the action + console.log('// Scheduled posts approved:', postsIds); + } + } + }); +}; + +Meteor.startup(function () { + addJob(); +}); + diff --git a/packages/nova-posts/lib/views.js b/packages/nova-posts/lib/views.js index 2805fe64a..f0420f20b 100644 --- a/packages/nova-posts/lib/views.js +++ b/packages/nova-posts/lib/views.js @@ -83,7 +83,9 @@ Posts.views.add("rejected", function (terms) { */ Posts.views.add("scheduled", function (terms) { return { - selector: {postedAt: {$gte: new Date()}}, + selector: { + status: Posts.config.STATUS_SCHEDULED + }, options: {sort: {postedAt: -1}}, showFuture: true };