removing Posts global

This commit is contained in:
Sacha Greif 2016-06-23 11:40:35 +09:00
parent 7a7b72c540
commit d9e69110a6
53 changed files with 198 additions and 89 deletions

View file

@ -1,4 +1,5 @@
import marked from 'marked';
import Posts from "meteor/nova:posts";
// TODO: switch over to Tom's migration package.

View file

@ -4,6 +4,7 @@ import { Button } from 'react-bootstrap';
import moment from 'moment';
import { ModalTrigger } from "meteor/nova:core";
import { Link } from 'react-router';
import Posts from "meteor/nova:posts";
class CustomPostsItem extends Telescope.components.PostsItem {

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
/*
Let's assign a color to each post (why? cause we want to, that's why).
We'll do that by adding a custom field to the Posts collection.

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
serveAPI = function(terms){
var posts = [];

View file

@ -1,5 +1,6 @@
import React from 'react';
import { Link } from 'react-router';
import Posts from "meteor/nova:posts";
const PostsCommenters = ({post}) => {
return (

View file

@ -1,6 +1,7 @@
import React, { PropTypes, Component } from 'react';
import { ListContainer } from "meteor/utilities:react-list-container";
import moment from 'moment';
import Posts from "meteor/nova:posts";
class PostsDay extends Component {

View file

@ -4,6 +4,7 @@ import NovaForm from "meteor/nova:forms";
import { DocumentContainer } from "meteor/utilities:react-list-container";
//import { Messages } from "meteor/nova:core";
//import Actions from "../actions.js";
import Posts from "meteor/nova:posts";
class PostsEditForm extends Component{
@ -18,7 +19,7 @@ class PostsEditForm extends Component{
const deletePostSuccess = this.context.intl.formatMessage({id: "posts.delete_success"}, {title: post.title});
if (window.confirm(deletePostConfirm)) {
this.context.actions.call('posts.deleteById', post._id, (error, result) => {
this.context.actions.call('posts.remove', post._id, (error, result) => {
this.context.messages.flash(deletePostSuccess, "success");
this.context.events.track("post deleted", {'_id': post._id});
});

View file

@ -1,5 +1,6 @@
import React, { PropTypes, Component } from 'react';
import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
import Posts from "meteor/nova:posts";
class PostsHome extends Component {

View file

@ -4,6 +4,7 @@ import { Button } from 'react-bootstrap';
import moment from 'moment';
import { ModalTrigger } from "meteor/nova:core";
import { Link } from 'react-router';
import Posts from "meteor/nova:posts";
class PostsItem extends Component {

View file

@ -2,6 +2,7 @@ import React, { PropTypes, Component } from 'react';
import { intlShape } from 'react-intl';
import NovaForm from "meteor/nova:forms";
import { withRouter } from 'react-router'
import Posts from "meteor/nova:posts";
const PostsNewForm = (props, context) => {

View file

@ -1,4 +1,5 @@
import React from 'react';
import Posts from "meteor/nova:posts";
const PostsPage = ({document, currentUser}) => {

View file

@ -1,5 +1,6 @@
import React from 'react';
import { DocumentContainer } from "meteor/utilities:react-list-container";
import Posts from "meteor/nova:posts";
const PostsSingle = (props, context) => {
return (

View file

@ -1,4 +1,5 @@
import React from 'react';
import Posts from "meteor/nova:posts";
const PostsThumbnail = ({post}) => {
return (

View file

@ -1,6 +1,7 @@
import React, { PropTypes, Component } from 'react';
import { FormattedMessage } from 'react-intl';
import { ListContainer } from "meteor/utilities:react-list-container";
import Posts from "meteor/nova:posts";
const UsersProfile = ({user, currentUser}) => {

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
// generate slug on insert
Categories.before.insert(function (userId, doc) {
// if no slug has been provided, generate one

View file

@ -1,4 +1,5 @@
import PublicationUtils from 'meteor/utilities:smart-publications';
import Posts from "meteor/nova:posts";
Posts.addField(
{

View file

@ -1,3 +1,4 @@
import Posts from "meteor/nova:posts";
/**
* @summary Get all of a category's parents

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Meteor.methods({
"categories.deleteById": function (categoryId) {

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Meteor.publish('categories', function() {
if(Users.can.viewById(this.userId)){
var categories = Categories.find();

View file

@ -1,4 +1,5 @@
import cloudinary from "cloudinary";
import Posts from "meteor/nova:posts";
const Cloudinary = cloudinary.v2;

View file

@ -1,4 +1,5 @@
import marked from 'marked';
import Posts from "meteor/nova:posts";
//////////////////////////////////////////////////////
// Collection Hooks //
@ -58,6 +59,10 @@ Comments.before.update(function (userId, doc, fieldNames, modifier) {
### comments.edit.async
### users.remove.async
- UsersRemoveDeleteComments
*/
// ------------------------------------- comments.new.method -------------------------------- //
@ -277,3 +282,16 @@ Telescope.callbacks.add("comments.edit.method", CommentsEditSubmittedPropertiesC
// ------------------------------------- comments.edit.async -------------------------------- //
// ------------------------------------- users.remove.async -------------------------------- //
function UsersRemoveDeleteComments (user, options) {
if (options.deleteComments) {
var deletedComments = Comments.remove({userId: userId});
} else {
// not sure if anything should be done in that scenario yet
// Comments.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
}
}
Telescope.callbacks.add("users.remove.async", UsersRemoveDeleteComments);

View file

@ -1,4 +1,5 @@
import PublicationUtils from 'meteor/utilities:smart-publications';
import Posts from "meteor/nova:posts";
Posts.addField([
/**

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Comments.methods = {};
// ------------------------------------------------------------------------------------------- //
// -------------------------------------- Submit Comment ------------------------------------- //

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Comments.getNotificationProperties = function (data) {
const comment = data.comment;
var commentAuthor = Meteor.users.findOne(comment.userId);

View file

@ -1,4 +1,5 @@
import PublicationsUtils from 'meteor/utilities:smart-publications';
import Posts from "meteor/nova:posts";
Comments.publishedFields = {};

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Comments._ensureIndex({postId: 1});
Comments._ensureIndex({parentCommentId: 1});

View file

@ -34,8 +34,7 @@ Package.onUse(function(api) {
], 'client');
api.addFiles([
'lib/server/start.js',
'lib/server/routes.js'
'lib/server/start.js'
], ['server']);
api.mainModule("lib/export.js", "server");

View file

@ -1,4 +1,5 @@
import React from 'react';
import Posts from "meteor/nova:posts";
const methodList = Meteor.isServer ? Meteor.server.method_handlers : Meteor.connection._methodHandlers;

View file

@ -1,6 +1,7 @@
import PublicationUtils from 'meteor/utilities:smart-publications';
import EmbedlyURL from './components/EmbedlyURL.jsx';
import ThumbnailURL from './components/ThumbnailURL.jsx';
import Posts from "meteor/nova:posts";
Posts.addField([
{

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
getEmbedlyData = function (url) {
var data = {};
var extractBase = 'http://api.embed.ly/1/extract';

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Users.addField({
fieldName: 'telescope.isDummy',
fieldSchema: {

View file

@ -1,4 +1,5 @@
import moment from 'moment';
import Posts from "meteor/nova:posts";
var toTitleCase = function (str) {
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});

View file

@ -1,4 +1,5 @@
import NewsletterSubscribe from './components/NewsletterSubscribe.jsx';
import Posts from "meteor/nova:posts";
Posts.addField({
fieldName: 'scheduledAt',

View file

@ -1,5 +1,7 @@
import { Avatar } from 'meteor/nova:core';
import moment from 'moment';
import Posts from "meteor/nova:posts";
// import Email from 'meteor/nova:email';
// create new "campaign" view for all posts from the past X days that haven't been scheduled yet

View file

@ -2,6 +2,7 @@ import htmlToText from 'html-to-text';
// import Email from 'meteor/nova:email';
import Campaign from "./campaign.js";
import moment from 'moment';
import Posts from "meteor/nova:posts";
const defaultPosts = 5;

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
import marked from 'marked';
//////////////////////////////////////////////////////
@ -92,6 +92,10 @@ Posts.before.update(function (userId, doc, fieldNames, modifier) {
- PostsApprovedNotification
### users.remove.async
- UsersRemoveDeletePosts
*/
// ------------------------------------- posts.new.method -------------------------------- //
@ -345,3 +349,15 @@ function PostsApprovedNotification (post) {
}
}
Telescope.callbacks.add("posts.approve.async", PostsApprovedNotification);
// ------------------------------------- users.remove.async -------------------------------- //
function UsersRemoveDeletePosts (user, options) {
if (options.deletePosts) {
var deletedPosts = Posts.remove({userId: userId});
} else {
// not sure if anything should be done in that scenario yet
// Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
}
}
Telescope.callbacks.add("users.remove.async", UsersRemoveDeletePosts);

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js';
const adminGroup = {
name: "admin",

View file

@ -1,3 +1,5 @@
import Posts from './namespace.js';
const getPost = (postId) => {
return typeof Posts.findOne(postId) === "undefined" ? {post: Posts.findOne()} : {post: Posts.findOne(postId)};
};

View file

@ -0,0 +1,14 @@
import Posts from './namespace.js';
import './namespace.js';
import './collection.js';
import './parameters.js';
import './notifications.js';
import './views.js';
import './helpers.js';
import './published_fields.js';
import './callbacks.js';
import './emails.js';
import './methods.js';
export default Posts;

View file

@ -1,5 +1,5 @@
import moment from 'moment';
import Posts from './config';
import Posts from './namespace.js';
//////////////////
// Link Helpers //
@ -127,3 +127,36 @@ Posts.getThumbnailUrl = (post) => {
}
};
Posts.helpers({ getThumbnailUrl() { return Posts.getThumbnailUrl(this); } });
///////////////////
// Users Helpers //
///////////////////
/**
* @summary Check if a given user can view a specific post
* @param {Object} user - can be undefined!
* @param {Object} post
*/
Users.can.viewPost = function (user, post) {
if (Users.is.admin(user)) {
return true;
} else {
switch (post.status) {
case Posts.config.STATUS_APPROVED:
return Users.can.view(user);
case Posts.config.STATUS_REJECTED:
case Posts.config.STATUS_SPAM:
case Posts.config.STATUS_PENDING:
return Users.can.view(user) && Users.is.owner(user, post);
case Posts.config.STATUS_DELETED:
return false;
}
}
}
Users.helpers({canViewPost: function () {return Users.can.viewPost(this, post);}});

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
/**
*
@ -48,6 +48,30 @@ Posts.methods.edit = function (postId, modifier, post) {
return Posts.findOne(postId);
};
/**
* @summary Increase the number of clicks on a post
* @param {string} postId the ID of the post being edited
* @param {string} ip the IP of the current user
*/
Posts.methods.increaseClicks = (postId, ip) => {
var clickEvent = {
name: 'click',
properties: {
postId: postId,
ip: ip
}
};
// make sure this IP hasn't previously clicked on this post
var existingClickEvent = Events.findOne({name: 'click', 'properties.postId': postId, 'properties.ip': ip});
if(!existingClickEvent){
Events.log(clickEvent);
Posts.update(postId, { $inc: { clickCount: 1 }});
}
};
// ------------------------------------------------------------------------------------------- //
// ----------------------------------------- Methods ----------------------------------------- //
// ------------------------------------------------------------------------------------------- //
@ -177,7 +201,7 @@ Meteor.methods({
* @isMethod true
* @param {String} postId - the id of the post
*/
'posts.deleteById': function(postId) {
'posts.remove': function(postId) {
check(postId, String);
@ -199,7 +223,7 @@ Meteor.methods({
// delete post
Posts.remove(postId);
Telescope.callbacks.runAsync("postDeleteAsync", post);
Telescope.callbacks.runAsync("posts.remove.async", post);
},

View file

@ -11,7 +11,7 @@ const PostsStub = {
/* we need to handle two scenarios: when the package is called as a Meteor package,
and when it's called as a NPM package */
Posts = typeof Mongo !== "undefined" ? new Mongo.Collection("posts") : PostsStub;
const Posts = typeof Mongo !== "undefined" ? new Mongo.Collection("posts") : PostsStub;
/**
* @summary Posts config namespace

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
Posts.getNotificationProperties = function (data) {
const post = data.post;

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
import moment from 'moment';
/**

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
import PublicationsUtils from 'meteor/utilities:smart-publications';
Posts.publishedFields = {};

View file

@ -1,3 +1,4 @@
import Posts from '../namespace.js';
import { CursorCounts } from "meteor/utilities:react-list-container";
Posts._ensureIndex({"status": 1, "postedAt": 1});

View file

@ -1,21 +1,4 @@
var increasePostClicks = function(postId, ip){
var clickEvent = {
name: 'click',
properties: {
postId: postId,
ip: ip
}
};
// make sure this IP hasn't previously clicked on this post
var existingClickEvent = Events.findOne({name: 'click', 'properties.postId': postId, 'properties.ip': ip});
if(!existingClickEvent){
Events.log(clickEvent);
Posts.update(postId, { $inc: { clickCount: 1 }});
}
};
import Posts from '../namespace.js';
Picker.route('/out', function(params, req, res, next) {
var query = params.query;
@ -23,7 +6,7 @@ Picker.route('/out', function(params, req, res, next) {
var post = Posts.findOne({url: query.url});
if (post) {
var ip = req.connection.remoteAddress;
increasePostClicks(post._id, ip);
Posts.methods.increaseClicks(post._id, ip);
res.writeHead(302, {'Location': query.url});
res.end();
} else {

View file

@ -1,4 +1,4 @@
import Posts from './config'
import Posts from './namespace.js'
/**
* @summary Post views are filters used for subscribing to and viewing posts

View file

@ -28,22 +28,25 @@ Package.onUse(function (api) {
], ['client', 'server'], {weak: true});
api.addFiles([
'lib/config.js',
'lib/collection.js',
'lib/parameters.js',
'lib/notifications.js',
'lib/views.js',
'lib/helpers.js',
'lib/published_fields.js',
'lib/callbacks.js',
'lib/emails.js',
'lib/methods.js'
// 'lib/namespace.js',
// 'lib/collection.js',
// 'lib/parameters.js',
// 'lib/notifications.js',
// 'lib/views.js',
// 'lib/helpers.js',
// 'lib/published_fields.js',
// 'lib/callbacks.js',
// 'lib/emails.js',
// 'lib/methods.js'
], ['client', 'server']);
api.addFiles([
'lib/server/publications.js'
'lib/server/publications.js',
'lib/server/routes.js'
], ['server']);
api.mainModule("lib/export.js", "server");
api.mainModule("lib/export.js", "client");
// var languages = ["ar", "bg", "cs", "da", "de", "el", "en", "es", "et", "fr", "hu", "id", "it", "ja", "kk", "ko", "nl", "pl", "pt-BR", "ro", "ru", "sl", "sv", "th", "tr", "vi", "zh-CN"];
// var languagesPaths = languages.map(function (language) {
@ -51,8 +54,8 @@ Package.onUse(function (api) {
// });
// api.addFiles(languagesPaths, ["client", "server"]);
api.export([
'Posts'
]);
// api.export([
// 'Posts'
// ]);
});

View file

@ -12,10 +12,16 @@ var completeUserProfile = function (userId, modifier, user) {
Users.methods = {};
/**
* @summary Edit a user in the database
* @param {string} userId the ID of the user being edited
* @param {Object} modifier the modifier object
* @param {Object} user - the current user object
*/
Users.methods.edit = (userId, modifier, user) => {
if (typeof user === "undefined") {
user = Posts.findOne(userId);
user = Users.findOne(userId);
}
// ------------------------------ Callbacks ------------------------------ //
@ -128,23 +134,15 @@ Meteor.methods({
},
'users.remove'(userId, removePosts) {
'users.remove'(userId, options) {
if (Users.is.adminById(this.userId)) {
removePosts = (typeof removePosts === "undefined") ? false : removePosts;
const user = Users.findOne(userId);
Meteor.users.remove(userId);
if (removePosts) {
var deletedPosts = Posts.remove({userId: userId});
var deletedComments = Comments.remove({userId: userId});
return "Deleted "+deletedPosts+" posts and "+deletedComments+" comments";
} else {
// not sure if anything should be done in that scenario yet
// Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
// Comments.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
}
Telescope.callbacks.runAsync("users.remove.async", user, options);
}

View file

@ -41,35 +41,6 @@ Users.can.viewById = function (userId) {
};
Users.helpers({canViewById: function () {return Users.can.viewById(this);}});
/**
* @summary Check if a given user can view a specific post
* @param {Object} user - can be undefined!
* @param {Object} post
*/
Users.can.viewPost = function (user, post) {
if (Users.is.admin(user)) {
return true;
} else {
switch (post.status) {
case Posts.config.STATUS_APPROVED:
return Users.can.view(user);
case Posts.config.STATUS_REJECTED:
case Posts.config.STATUS_SPAM:
case Posts.config.STATUS_PENDING:
return Users.can.view(user) && Users.is.owner(user, post);
case Posts.config.STATUS_DELETED:
return false;
}
}
}
Users.helpers({canViewPost: function () {return Users.can.viewPost(this, post);}});
/**
* @summary Check if a given user has permission to submit new posts
* @param {Object} user

View file

@ -1,4 +1,5 @@
import PublicationUtils from 'meteor/utilities:smart-publications';
import Posts from "meteor/nova:posts";
// ------------------------------------- Posts -------------------------------- //

View file

@ -1,3 +1,5 @@
import Posts from "meteor/nova:posts";
Meteor.startup(function () {
var scoreInterval = Telescope.settings.get("scoreUpdateInterval") || 30;
if (scoreInterval > 0) {