mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 01:51:40 -05:00
Merge branch 'devel' of https://github.com/TelescopeJS/Telescope into devel
This commit is contained in:
commit
4194595944
8 changed files with 77 additions and 11 deletions
|
@ -62,7 +62,7 @@ class PostsItem extends Component {
|
||||||
|
|
||||||
<div className="posts-item-meta">
|
<div className="posts-item-meta">
|
||||||
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
||||||
<div className="posts-item-date"><FormattedRelative value={post.postedAt}/></div>
|
<div className="posts-item-date">{post.postedAt ? <FormattedRelative value={post.postedAt}/> : <FormattedMessage id="posts.dateNotDefined"/>}</div>
|
||||||
<div className="posts-item-comments">
|
<div className="posts-item-comments">
|
||||||
<Link to={Posts.getPageUrl(post)}>
|
<Link to={Posts.getPageUrl(post)}>
|
||||||
<FormattedMessage id="comments.count" values={{count: post.commentCount}}/>
|
<FormattedMessage id="comments.count" values={{count: post.commentCount}}/>
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import DateTimeField from 'react-datetime';
|
import DateTimePicker from 'react-datetime';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
class DateTime extends Component {
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="form-group row">
|
<div className="form-group row">
|
||||||
<label className="control-label col-sm-3">{this.props.label}</label>
|
<label className="control-label col-sm-3">{this.props.label}</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<DateTimeField
|
<DateTimePicker
|
||||||
value={this.props.value || new Date()}
|
value={this.props.value || new Date()}
|
||||||
defaultValue={moment().format("x")}
|
// newDate argument is a Moment object given by react-datetime
|
||||||
onChange={newDate => this.props.updateCurrentValue(this.props.name, newDate._d)}
|
onChange={newDate => { this.props.updateCurrentValue(this.props.name, newDate._d)}}
|
||||||
format={"x"}
|
format={"x"}
|
||||||
inputProps={{name: this.props.name}}
|
inputProps={{name: this.props.name}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -30,6 +30,7 @@ Telescope.strings.en = {
|
||||||
"posts.created_message": "Post created.",
|
"posts.created_message": "Post created.",
|
||||||
"posts.rate_limit_error": "Please wait {details} seconds before posting again.",
|
"posts.rate_limit_error": "Please wait {details} seconds before posting again.",
|
||||||
"posts.postedAt": "Posted at",
|
"posts.postedAt": "Posted at",
|
||||||
|
"posts.dateNotDefined": "Date not defined",
|
||||||
|
|
||||||
"comments.comments": "Comments",
|
"comments.comments": "Comments",
|
||||||
"comments.count": "{count, plural, =0 {No comments} one {# comment} other {# comments}}",
|
"comments.count": "{count, plural, =0 {No comments} one {# comment} other {# comments}}",
|
||||||
|
|
|
@ -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 no post status has been set, set it now
|
||||||
if (!post.status) {
|
// if (!post.status) {
|
||||||
post.status = Posts.getDefaultStatus(user);
|
// post.status = Posts.getDefaultStatus(user);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// if no userId has been set, default to current user id
|
// if no userId has been set, default to current user id
|
||||||
if (!post.userId) {
|
if (!post.userId) {
|
||||||
|
@ -197,7 +197,7 @@ function PostsNewRequiredPropertiesCheck (post, user) {
|
||||||
const defaultProperties = {
|
const defaultProperties = {
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
author: Users.getDisplayNameById(post.userId),
|
author: Users.getDisplayNameById(post.userId),
|
||||||
status: Posts.getDefaultStatus()
|
status: Posts.getDefaultStatus(user)
|
||||||
};
|
};
|
||||||
|
|
||||||
post = _.extend(defaultProperties, post);
|
post = _.extend(defaultProperties, post);
|
||||||
|
@ -205,6 +205,11 @@ function PostsNewRequiredPropertiesCheck (post, user) {
|
||||||
// generate slug
|
// generate slug
|
||||||
post.slug = Telescope.utils.slugify(post.title);
|
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
|
// 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
|
// note: pending posts get their postedAt date only once theyre approved
|
||||||
if (Posts.isApproved(post) && !post.postedAt) {
|
if (Posts.isApproved(post) && !post.postedAt) {
|
||||||
|
@ -318,6 +323,12 @@ Telescope.callbacks.add("posts.edit.sync", PostsEditForceStickyToFalse);
|
||||||
* @summary Set postedAt date
|
* @summary Set postedAt date
|
||||||
*/
|
*/
|
||||||
function PostsEditSetPostedAt (post, oldPost) {
|
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
|
// 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
|
// note: pending posts get their postedAt date only once theyre approved
|
||||||
if (Posts.isApproved(post) && !post.postedAt) {
|
if (Posts.isApproved(post) && !post.postedAt) {
|
||||||
|
|
|
@ -30,6 +30,10 @@ Posts.config.postStatuses = [
|
||||||
{
|
{
|
||||||
value: 5,
|
value: 5,
|
||||||
label: 'deleted'
|
label: 'deleted'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 6,
|
||||||
|
label: 'scheduled'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -38,6 +42,7 @@ Posts.config.STATUS_APPROVED = 2;
|
||||||
Posts.config.STATUS_REJECTED = 3;
|
Posts.config.STATUS_REJECTED = 3;
|
||||||
Posts.config.STATUS_SPAM = 4;
|
Posts.config.STATUS_SPAM = 4;
|
||||||
Posts.config.STATUS_DELETED = 5;
|
Posts.config.STATUS_DELETED = 5;
|
||||||
|
Posts.config.STATUS_SCHEDULED = 6;
|
||||||
|
|
||||||
const adminGroup = {
|
const adminGroup = {
|
||||||
name: "admin",
|
name: "admin",
|
||||||
|
|
|
@ -2,5 +2,6 @@ import Posts from './modules.js';
|
||||||
|
|
||||||
import './server/publications.js';
|
import './server/publications.js';
|
||||||
import './server/routes.js';
|
import './server/routes.js';
|
||||||
|
import './server/cron.js';
|
||||||
|
|
||||||
export default Posts;
|
export default Posts;
|
40
packages/nova-posts/lib/server/cron.js
Normal file
40
packages/nova-posts/lib/server/cron.js
Normal file
|
@ -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();
|
||||||
|
});
|
||||||
|
|
|
@ -83,7 +83,9 @@ Posts.views.add("rejected", function (terms) {
|
||||||
*/
|
*/
|
||||||
Posts.views.add("scheduled", function (terms) {
|
Posts.views.add("scheduled", function (terms) {
|
||||||
return {
|
return {
|
||||||
selector: {postedAt: {$gte: new Date()}},
|
selector: {
|
||||||
|
status: Posts.config.STATUS_SCHEDULED
|
||||||
|
},
|
||||||
options: {sort: {postedAt: -1}},
|
options: {sort: {postedAt: -1}},
|
||||||
showFuture: true
|
showFuture: true
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue