mirror of
https://github.com/vale981/Vulcan
synced 2025-03-05 09:31:43 -05:00
reworking publications
This commit is contained in:
parent
38af000a4f
commit
9f8a094ab8
23 changed files with 372 additions and 290 deletions
|
@ -41,7 +41,9 @@ telescope:comments
|
|||
# telescope:spiderable
|
||||
# telescope:subscribe-to-posts # notifications
|
||||
# telescope:tagline-banner
|
||||
# telescope:tags
|
||||
|
||||
telescope:tags
|
||||
|
||||
# telescope:theme-base
|
||||
# telescope:theme-hubble
|
||||
# telescope:update-prompt
|
||||
|
|
|
@ -112,6 +112,7 @@ telescope:lib@0.25.7
|
|||
telescope:posts@0.25.7
|
||||
telescope:search@0.25.7
|
||||
telescope:settings@0.25.7
|
||||
telescope:tags@0.25.7
|
||||
telescope:users@0.25.7
|
||||
templating@1.1.6-modules.8
|
||||
templating-tools@1.0.1-modules.8
|
||||
|
|
21
README.md
21
README.md
|
@ -1,21 +1,4 @@
|
|||
Telescope is an open-source, real-time social news site built with [Meteor](http://meteor.com)
|
||||
# Telescope: Nova
|
||||
|
||||
**Note:** Telescope is beta software. Most of it should work but it's still a little unpolished and you'll probably find some bugs. Use at your own risk :)
|
||||
**Nova** is a top-secret, highly unstable experimental branch of Telescope with a really cool name.
|
||||
|
||||
Note that Telescope is distributed under the [MIT License](http://opensource.org/licenses/MIT)
|
||||
|
||||
### Getting Started
|
||||
|
||||
Note that while simply cloning this repository will work, it is recommended you clone the [sample project](https://github.com/TelescopeJS/sample-project/) repository instead for a simpler workflow.
|
||||
|
||||
Please refer to [the documentation](http://telescope.readme.io/v0.20/docs/installing-telescope) for more instructions on installing Telescope.
|
||||
|
||||
### Learn More
|
||||
|
||||
- [Homepage](http://telescopeapp.org)
|
||||
- [Demo](http://demo2.telescopeapp.org)
|
||||
- [Sample Project](https://github.com/TelescopeJS/sample-project/)
|
||||
- [Documentation](http://telescope.readme.io)
|
||||
- [Roadmap](https://trello.com/b/oLMMqjVL/telescope-roadmap)
|
||||
- [Slack](http://slack.telescopeapp.org/)
|
||||
- [Meta](http://meta.telescopeapp.org/) – Discussions about Telescope
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
const CategoriesList = props => {
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{props.results.map(category => <li key={category._id}>{category.name}</li>)}
|
||||
</ul>
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
module.exports = CategoriesList;
|
|
@ -1,6 +1,6 @@
|
|||
const Header = props => {
|
||||
|
||||
const Logo = Telescope.getComponent("Logo");
|
||||
({Logo, ListContainer, CategoriesList} = Telescope.components);
|
||||
|
||||
const logoUrl = Telescope.settings.get("logoUrl");
|
||||
const siteTitle = Telescope.settings.get("title", "Telescope");
|
||||
|
@ -13,9 +13,7 @@ const Header = props => {
|
|||
{tagline ? <h2 className="tagline">{tagline}</h2> : "" }
|
||||
</div>
|
||||
<div className="nav">
|
||||
<ul>
|
||||
<li>Nav link</li>
|
||||
</ul>
|
||||
<ListContainer collection={Categories} publication="categories" component={CategoriesList} limit={0}/>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
|
|
@ -19,4 +19,8 @@ Telescope.registerComponent("PostEdit", require('./posts/PostEdit.jsx'));
|
|||
// comments
|
||||
|
||||
Telescope.registerComponent("CommentItem", require('./comments/list/CommentItem.jsx'));
|
||||
Telescope.registerComponent("CommentList", require('./comments/list/CommentList.jsx'));
|
||||
Telescope.registerComponent("CommentList", require('./comments/list/CommentList.jsx'));
|
||||
|
||||
// categories
|
||||
|
||||
Telescope.registerComponent("CategoriesList", require('./categories/list/CategoriesList.jsx'));
|
|
@ -14,7 +14,8 @@ Comments.schema = new SimpleSchema({
|
|||
*/
|
||||
_id: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The `_id` of the parent comment, if there is one
|
||||
|
@ -25,6 +26,7 @@ Comments.schema = new SimpleSchema({
|
|||
max: 500,
|
||||
editableBy: ["member", "admin"],
|
||||
optional: true,
|
||||
public: true,
|
||||
autoform: {
|
||||
omit: true // never show this
|
||||
}
|
||||
|
@ -38,6 +40,7 @@ Comments.schema = new SimpleSchema({
|
|||
max: 500,
|
||||
editableBy: ["member", "admin"],
|
||||
optional: true,
|
||||
public: true,
|
||||
autoform: {
|
||||
omit: true // never show this
|
||||
}
|
||||
|
@ -47,14 +50,16 @@ Comments.schema = new SimpleSchema({
|
|||
*/
|
||||
createdAt: {
|
||||
type: Date,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The timestamp of the comment being posted. For now, comments are always created and posted at the same time
|
||||
*/
|
||||
postedAt: {
|
||||
type: Date,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The comment body (Markdown)
|
||||
|
@ -63,6 +68,7 @@ Comments.schema = new SimpleSchema({
|
|||
type: String,
|
||||
max: 3000,
|
||||
editableBy: ["member", "admin"],
|
||||
public: true,
|
||||
autoform: {
|
||||
rows: 5,
|
||||
afFormGroup: {
|
||||
|
@ -75,7 +81,8 @@ Comments.schema = new SimpleSchema({
|
|||
*/
|
||||
htmlBody: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The comment's base score (doesn't factor in comment age)
|
||||
|
@ -83,7 +90,8 @@ Comments.schema = new SimpleSchema({
|
|||
baseScore: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The comment's current score (factors in comment age)
|
||||
|
@ -91,49 +99,56 @@ Comments.schema = new SimpleSchema({
|
|||
score: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The number of upvotes the comment has received
|
||||
*/
|
||||
upvotes: {
|
||||
type: Number,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of upvoters
|
||||
*/
|
||||
upvoters: {
|
||||
type: [String],
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The number of downvotes the comment has received
|
||||
*/
|
||||
downvotes: {
|
||||
type: Number,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of downvoters
|
||||
*/
|
||||
downvoters: {
|
||||
type: [String],
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The comment author's name
|
||||
*/
|
||||
author: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Whether the comment is inactive. Inactive comments' scores gets recalculated less often
|
||||
*/
|
||||
inactive: {
|
||||
type: Boolean,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The post's `_id`
|
||||
|
@ -141,6 +156,7 @@ Comments.schema = new SimpleSchema({
|
|||
postId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
public: true,
|
||||
// regEx: SimpleSchema.RegEx.Id,
|
||||
max: 500,
|
||||
// editableBy: ["member", "admin"], // TODO: should users be able to set postId, but not modify it?
|
||||
|
@ -153,14 +169,16 @@ Comments.schema = new SimpleSchema({
|
|||
*/
|
||||
userId: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Whether the comment is deleted. Delete comments' content doesn't appear on the site.
|
||||
*/
|
||||
isDeleted: {
|
||||
type: Boolean,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
}
|
||||
});
|
||||
|
||||
|
|
27
packages/telescope-comments/lib/custom_fields.js
Normal file
27
packages/telescope-comments/lib/custom_fields.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
Posts.addField([
|
||||
/**
|
||||
Count of the post's comments
|
||||
*/
|
||||
{
|
||||
fieldName: "commentCount",
|
||||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
public: true
|
||||
}
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of commenters
|
||||
*/
|
||||
{
|
||||
fieldName: "commenters",
|
||||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true,
|
||||
public: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
Posts.publicationFields.list.push("commentCount", "commenters");
|
||||
Posts.publicationFields.single.push("commentCount", "commenters");
|
|
@ -13,8 +13,6 @@ Meteor.publish('comments.list', function(terms) {
|
|||
|
||||
if(Users.can.viewById(this.userId)){
|
||||
var parameters = Comments.parameters.get(terms);
|
||||
console.log(terms)
|
||||
console.log(parameters)
|
||||
var comments = Comments.find(parameters.find, parameters.options);
|
||||
|
||||
// if there are comments, find out which posts were commented on
|
||||
|
|
|
@ -13,6 +13,7 @@ Package.onUse(function (api) {
|
|||
'telescope:lib@0.25.7',
|
||||
// 'telescope:i18n@0.25.7',
|
||||
'telescope:settings@0.25.7',
|
||||
'telescope:posts@0.25.7',
|
||||
'telescope:users@0.25.7'
|
||||
]);
|
||||
|
||||
|
@ -23,6 +24,7 @@ Package.onUse(function (api) {
|
|||
'lib/views.js',
|
||||
'lib/parameters.js',
|
||||
'lib/helpers.js',
|
||||
'lib/custom_fields.js',
|
||||
// 'lib/routes.js'
|
||||
], ['client', 'server']);
|
||||
|
||||
|
|
|
@ -23,12 +23,17 @@ const ListContainer = React.createClass({
|
|||
mixins: [ReactMeteorData],
|
||||
|
||||
getMeteorData() {
|
||||
const terms = {...this.props.terms, limit: this.state.limit};
|
||||
const parameters = this.props.collection.parameters.get(terms);
|
||||
const find = parameters.find;
|
||||
const options = parameters.options;
|
||||
options.limit = this.state.limit;
|
||||
|
||||
let terms = {...this.props.terms, limit: this.state.limit};
|
||||
let find = {};
|
||||
let options = {limit: this.state.limit};
|
||||
|
||||
if (this.props.collection.parameters) {
|
||||
const parameters = this.props.collection.parameters.get(terms);
|
||||
find = parameters.find;
|
||||
options = parameters.options;
|
||||
}
|
||||
|
||||
const subscription = Meteor.subscribe(this.props.publication, terms);
|
||||
|
||||
const totalCount = Counts.get(this.props.publication);
|
||||
|
|
|
@ -48,4 +48,4 @@ Telescope.subscriptions = [];
|
|||
*/
|
||||
Telescope.subscriptions.preload = function (subscription, args) {
|
||||
Telescope.subscriptions.push({name: subscription, arguments: args});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -252,3 +252,11 @@ Telescope.getNestedProperty = function (obj, desc) {
|
|||
while(arr.length && (obj = obj[arr.shift()]));
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert an array of fields to publish into a Mongo fields specifier
|
||||
* @param {Array} fieldsArray
|
||||
*/
|
||||
Telescope.utils.arrayToFields = function (fieldsArray) {
|
||||
return _.object(fieldsArray, _.map(fieldsArray, function () {return true}));
|
||||
};
|
29
packages/telescope-posts/lib/fields.js
Normal file
29
packages/telescope-posts/lib/fields.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
Posts.publicationFields = {};
|
||||
|
||||
/**
|
||||
* Specify which fields should be published by the posts.list publication
|
||||
* @array Posts.publicationFields.list
|
||||
*/
|
||||
Posts.publicationFields.list = [
|
||||
"_id",
|
||||
"postedAt",
|
||||
"url",
|
||||
"title",
|
||||
"slug",
|
||||
"htmlBody",
|
||||
"viewCount",
|
||||
"lastCommentedAt",
|
||||
"clickCount",
|
||||
"baseScore",
|
||||
"score",
|
||||
"status",
|
||||
"sticky",
|
||||
"author",
|
||||
"userId"
|
||||
];
|
||||
|
||||
/**
|
||||
* Specify which fields should be published by the posts.single publication
|
||||
* @array Posts.publicationFields.single
|
||||
*/
|
||||
Posts.publicationFields.single = Posts.simpleSchema().getPublicFields();
|
|
@ -8,14 +8,16 @@ Posts.schema = new SimpleSchema({
|
|||
*/
|
||||
_id: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true
|
||||
},
|
||||
/**
|
||||
Timetstamp of post creation
|
||||
*/
|
||||
createdAt: {
|
||||
type: Date,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true
|
||||
},
|
||||
/**
|
||||
Timestamp of post first appearing on the site (i.e. being approved)
|
||||
|
@ -24,10 +26,11 @@ Posts.schema = new SimpleSchema({
|
|||
type: Date,
|
||||
optional: true,
|
||||
editableBy: ["admin"],
|
||||
// autoform: {
|
||||
// group: 'admin',
|
||||
// type: "bootstrap-datetimepicker"
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
group: 'admin',
|
||||
type: "bootstrap-datetimepicker"
|
||||
}
|
||||
},
|
||||
/**
|
||||
URL
|
||||
|
@ -37,10 +40,11 @@ Posts.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
max: 500,
|
||||
editableBy: ["member", "admin"],
|
||||
// autoform: {
|
||||
// type: "bootstrap-url",
|
||||
// order: 10
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
type: "bootstrap-url",
|
||||
order: 10
|
||||
}
|
||||
},
|
||||
/**
|
||||
Title
|
||||
|
@ -50,16 +54,18 @@ Posts.schema = new SimpleSchema({
|
|||
optional: false,
|
||||
max: 500,
|
||||
editableBy: ["member", "admin"],
|
||||
// autoform: {
|
||||
// order: 20
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
order: 20
|
||||
}
|
||||
},
|
||||
/**
|
||||
Slug
|
||||
*/
|
||||
slug: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Post body (markdown)
|
||||
|
@ -69,52 +75,43 @@ Posts.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
max: 3000,
|
||||
editableBy: ["member", "admin"],
|
||||
// autoform: {
|
||||
// rows: 5,
|
||||
// order: 30
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
rows: 5,
|
||||
order: 30
|
||||
}
|
||||
},
|
||||
/**
|
||||
HTML version of the post body
|
||||
*/
|
||||
htmlBody: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Count of how many times the post's page was viewed
|
||||
*/
|
||||
viewCount: {
|
||||
type: Number,
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
Count of the post's comments
|
||||
*/
|
||||
commentCount: {
|
||||
type: Number,
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of commenters
|
||||
*/
|
||||
commenters: {
|
||||
type: [String],
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Timestamp of the last comment
|
||||
*/
|
||||
lastCommentedAt: {
|
||||
type: Date,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
Count of how many times the post's link was clicked
|
||||
*/
|
||||
clickCount: {
|
||||
type: Number,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The post's base score (not factoring in the post's age)
|
||||
|
@ -122,35 +119,8 @@ Posts.schema = new SimpleSchema({
|
|||
baseScore: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
How many upvotes the post has received
|
||||
*/
|
||||
upvotes: {
|
||||
type: Number,
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of the post's upvoters
|
||||
*/
|
||||
upvoters: {
|
||||
type: [String],
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
How many downvotes the post has received
|
||||
*/
|
||||
downvotes: {
|
||||
type: Number,
|
||||
optional: true
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of the post's downvoters
|
||||
*/
|
||||
downvoters: {
|
||||
type: [String],
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The post's current score (factoring in age)
|
||||
|
@ -158,7 +128,8 @@ Posts.schema = new SimpleSchema({
|
|||
score: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The post's status. One of pending (`1`), approved (`2`), or deleted (`3`)
|
||||
|
@ -167,6 +138,7 @@ Posts.schema = new SimpleSchema({
|
|||
type: Number,
|
||||
optional: true,
|
||||
editableBy: ["admin"],
|
||||
public: true,
|
||||
autoValue: function () {
|
||||
// only provide a default value
|
||||
// 1) this is an insert operation
|
||||
|
@ -175,11 +147,11 @@ Posts.schema = new SimpleSchema({
|
|||
if (this.isInsert && !this.isSet)
|
||||
return Posts.getDefaultStatus(user);
|
||||
},
|
||||
// autoform: {
|
||||
// noselect: true,
|
||||
// options: Posts.config.postStatuses,
|
||||
// group: 'admin'
|
||||
// }
|
||||
autoform: {
|
||||
noselect: true,
|
||||
options: Posts.config.postStatuses,
|
||||
group: 'admin'
|
||||
}
|
||||
},
|
||||
/**
|
||||
Whether the post is sticky (pinned to the top of posts lists)
|
||||
|
@ -189,39 +161,45 @@ Posts.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
defaultValue: false,
|
||||
editableBy: ["admin"],
|
||||
// autoform: {
|
||||
// group: 'admin',
|
||||
// leftLabel: "Sticky"
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
group: 'admin',
|
||||
leftLabel: "Sticky"
|
||||
}
|
||||
},
|
||||
/**
|
||||
Whether the post is inactive. Inactive posts see their score recalculated less often
|
||||
*/
|
||||
inactive: {
|
||||
type: Boolean,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: false,
|
||||
},
|
||||
/**
|
||||
Save info for later spam checking on a post. We will use this for the akismet package
|
||||
*/
|
||||
userIP: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: false,
|
||||
},
|
||||
userAgent: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: false,
|
||||
},
|
||||
referrer: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: false,
|
||||
},
|
||||
/**
|
||||
The post author's name
|
||||
*/
|
||||
author: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
public: true,
|
||||
},
|
||||
/**
|
||||
The post author's `_id`.
|
||||
|
@ -231,17 +209,18 @@ Posts.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
// regEx: SimpleSchema.RegEx.Id,
|
||||
editableBy: ["admin"],
|
||||
// autoform: {
|
||||
// group: 'admin',
|
||||
// options: function () {
|
||||
// return Meteor.users.find().map(function (user) {
|
||||
// return {
|
||||
// value: user._id,
|
||||
// label: Users.getDisplayName(user)
|
||||
// };
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
public: true,
|
||||
autoform: {
|
||||
group: 'admin',
|
||||
options: function () {
|
||||
return Meteor.users.find().map(function (user) {
|
||||
return {
|
||||
value: user._id,
|
||||
label: Users.getDisplayName(user)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,124 +1,99 @@
|
|||
Posts._ensureIndex({"status": 1, "postedAt": 1});
|
||||
|
||||
// ------------------------------------- Helpers -------------------------------- //
|
||||
|
||||
/**
|
||||
* Get all users relevant to a list of posts
|
||||
* (authors of the listed posts, and first four commenters of each post)
|
||||
* @param {Object} posts
|
||||
*/
|
||||
const getPostsListUsers = posts => {
|
||||
|
||||
// add the userIds of each post authors
|
||||
let userIds = _.pluck(posts.fetch(), 'userId');
|
||||
|
||||
// for each post, also add first four commenter's userIds to userIds array
|
||||
posts.forEach(function (post) {
|
||||
userIds = userIds.concat(_.first(post.commenters,4));
|
||||
});
|
||||
|
||||
userIds = _.unique(userIds);
|
||||
|
||||
return Meteor.users.find({_id: {$in: userIds}}, {fields: Users.pubsub.avatarProperties});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all users relevant to a single post
|
||||
* (author of the current post, authors of its comments, and upvoters & downvoters of the post)
|
||||
* @param {Object} post
|
||||
*/
|
||||
const getSinglePostUsers = post => {
|
||||
|
||||
let users = [post.userId]; // publish post author's ID
|
||||
|
||||
// get IDs from all commenters on the post
|
||||
const comments = Comments.find({postId: post._id}).fetch();
|
||||
if (comments.length) {
|
||||
users = users.concat(_.pluck(comments, "userId"));
|
||||
}
|
||||
|
||||
// add upvoters
|
||||
if (post.upvoters && post.upvoters.length) {
|
||||
users = users.concat(post.upvoters);
|
||||
}
|
||||
|
||||
// add downvoters
|
||||
if (post.downvoters && post.downvoters.length) {
|
||||
users = users.concat(post.downvoters);
|
||||
}
|
||||
|
||||
// remove any duplicate IDs
|
||||
users = _.unique(users);
|
||||
|
||||
return Meteor.users.find({_id: {$in: users}}, {fields: Users.pubsub.publicProperties});
|
||||
};
|
||||
|
||||
// ------------------------------------- Publications -------------------------------- //
|
||||
|
||||
/**
|
||||
* posts.list publication
|
||||
* @param {Object} terms
|
||||
*/
|
||||
Meteor.publish('posts.list', function(terms) {
|
||||
|
||||
var parameters = Posts.parameters.get(terms),
|
||||
posts = Posts.find(parameters.find, parameters.options);
|
||||
this.unblock();
|
||||
|
||||
Counts.publish(this, 'posts.list', Posts.find(parameters.find, parameters.options));
|
||||
const currentUser = Meteor.users.findOne(this.userId);
|
||||
|
||||
return posts;
|
||||
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||
({find, options} = Posts.parameters.get(terms));
|
||||
|
||||
Counts.publish(this, 'posts.list', Posts.find(find, options));
|
||||
|
||||
options.fields = Telescope.utils.arrayToFields(Posts.publicationFields.list);
|
||||
|
||||
const posts = Posts.find(find, options);
|
||||
const users = getPostsListUsers(posts);
|
||||
|
||||
return Users.can.view(currentUser) ? [posts, users] : [];
|
||||
});
|
||||
|
||||
/**
|
||||
* posts.item publication
|
||||
* @param {Object} terms
|
||||
*/
|
||||
Meteor.publish('posts.single', function(terms) {
|
||||
|
||||
return Posts.find(terms);
|
||||
check(terms, {_id: String});
|
||||
|
||||
});
|
||||
this.unblock();
|
||||
|
||||
// Publish a list of posts
|
||||
const currentUser = Meteor.users.findOne(this.userId);
|
||||
const options = {fields: Telescope.utils.arrayToFields(Posts.publicationFields.single)};
|
||||
const post = Posts.find(terms, options);
|
||||
const users = getSinglePostUsers(post);
|
||||
|
||||
// Meteor.publish('postsList', function(terms) {
|
||||
return Users.can.viewPost(currentUser, post) ? [post, users] : [];
|
||||
|
||||
// this.unblock();
|
||||
|
||||
// if (this.userId) { // add currentUserId to terms if a user is logged in
|
||||
// terms.currentUserId = this.userId;
|
||||
// }
|
||||
|
||||
// if(Users.can.viewById(this.userId)){
|
||||
// var parameters = Posts.parameters.get(terms),
|
||||
// posts = Posts.find(parameters.find, parameters.options);
|
||||
|
||||
// return posts;
|
||||
// }
|
||||
// return [];
|
||||
// });
|
||||
|
||||
// // Publish all the users that have posted the currently displayed list of posts
|
||||
// // plus the commenters for each post
|
||||
|
||||
// Meteor.publish('postsListUsers', function(terms) {
|
||||
|
||||
// this.unblock();
|
||||
|
||||
// if (this.userId) {
|
||||
// terms.currentUserId = this.userId; // add userId to terms
|
||||
// }
|
||||
|
||||
// if(Users.can.viewById(this.userId)){
|
||||
// var parameters = Posts.parameters.get(terms),
|
||||
// posts = Posts.find(parameters.find, parameters.options),
|
||||
// userIds = _.pluck(posts.fetch(), 'userId');
|
||||
|
||||
// // for each post, add first four commenter's userIds to userIds array
|
||||
// posts.forEach(function (post) {
|
||||
// userIds = userIds.concat(_.first(post.commenters,4));
|
||||
// });
|
||||
|
||||
// userIds = _.unique(userIds);
|
||||
|
||||
// return Meteor.users.find({_id: {$in: userIds}}, {fields: Users.pubsub.avatarProperties, multi: true});
|
||||
// }
|
||||
// return [];
|
||||
// });
|
||||
|
||||
// // Publish a single post
|
||||
|
||||
// Meteor.publish('singlePost', function(postId) {
|
||||
|
||||
// check(postId, String);
|
||||
// this.unblock();
|
||||
|
||||
// var user = Meteor.users.findOne(this.userId);
|
||||
// var post = Posts.findOne(postId);
|
||||
|
||||
// if (Users.can.viewPost(user, post)){
|
||||
// return Posts.find(postId);
|
||||
// } else {
|
||||
// return [];
|
||||
// }
|
||||
|
||||
// });
|
||||
|
||||
// // Publish author of the current post, authors of its comments, and upvoters of the post
|
||||
|
||||
// Meteor.publish('postUsers', function(postId) {
|
||||
|
||||
// check(postId, String);
|
||||
// this.unblock();
|
||||
|
||||
// if (Users.can.viewById(this.userId)){
|
||||
// // publish post author and post commenters
|
||||
// var post = Posts.findOne(postId);
|
||||
// var users = [];
|
||||
|
||||
// if (post) {
|
||||
|
||||
// users.push(post.userId); // publish post author's ID
|
||||
|
||||
// // get IDs from all commenters on the post
|
||||
// var comments = Comments.find({postId: post._id}).fetch();
|
||||
// if (comments.length) {
|
||||
// users = users.concat(_.pluck(comments, "userId"));
|
||||
// }
|
||||
|
||||
// // publish upvoters
|
||||
// if (post.upvoters && post.upvoters.length) {
|
||||
// users = users.concat(post.upvoters);
|
||||
// }
|
||||
|
||||
// // publish downvoters
|
||||
// if (post.downvoters && post.downvoters.length) {
|
||||
// users = users.concat(post.downvoters);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // remove any duplicate IDs
|
||||
// users = _.unique(users);
|
||||
|
||||
// return Meteor.users.find({_id: {$in: users}}, {fields: Users.pubsub.publicProperties});
|
||||
// }
|
||||
// return [];
|
||||
// });
|
||||
});
|
|
@ -29,6 +29,7 @@ Package.onUse(function (api) {
|
|||
'lib/parameters.js',
|
||||
'lib/views.js',
|
||||
'lib/helpers.js',
|
||||
'lib/fields.js',
|
||||
// 'lib/modules.js',
|
||||
// 'lib/callbacks.js',
|
||||
// 'lib/methods.js',
|
||||
|
|
|
@ -47,22 +47,14 @@ Categories.schema = new SimpleSchema({
|
|||
}
|
||||
});
|
||||
|
||||
Meteor.startup(function(){
|
||||
Categories.internationalize();
|
||||
});
|
||||
// Meteor.startup(function(){
|
||||
// Categories.internationalize();
|
||||
// });
|
||||
|
||||
Categories.attachSchema(Categories.schema);
|
||||
|
||||
Meteor.startup(function () {
|
||||
Categories.allow({
|
||||
insert: Users.is.adminById,
|
||||
update: Users.is.adminById,
|
||||
remove: Users.is.adminById
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Settings.addField([
|
||||
Telescope.settings.collection.addField([
|
||||
{
|
||||
fieldName: 'categoriesBehavior',
|
||||
fieldSchema: {
|
||||
|
|
|
@ -22,3 +22,6 @@ Posts.addField(
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
Posts.publicationFields.list.push("categories");
|
||||
Posts.publicationFields.single.push("categories");
|
||||
|
|
|
@ -14,43 +14,43 @@ Package.onUse(function (api) {
|
|||
api.addFiles([
|
||||
'lib/categories.js',
|
||||
'lib/helpers.js',
|
||||
'lib/callbacks.js',
|
||||
'lib/parameters.js',
|
||||
'lib/custom_fields.js',
|
||||
'lib/methods.js',
|
||||
'lib/modules.js',
|
||||
'lib/routes.js',
|
||||
'package-tap.i18n'
|
||||
// 'lib/callbacks.js',
|
||||
// 'lib/parameters.js',
|
||||
// 'lib/custom_fields.js',
|
||||
// 'lib/methods.js',
|
||||
// 'lib/modules.js',
|
||||
// 'lib/routes.js',
|
||||
// 'package-tap.i18n'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
'lib/client/scss/categories.scss',
|
||||
'lib/client/templates/categories_admin.html',
|
||||
'lib/client/templates/categories_admin.js',
|
||||
'lib/client/templates/category_item.html',
|
||||
'lib/client/templates/category_item.js',
|
||||
'lib/client/templates/categories_menu.html',
|
||||
'lib/client/templates/categories_menu.js',
|
||||
'lib/client/templates/categories_menu_item.html',
|
||||
'lib/client/templates/categories_menu_item.js',
|
||||
'lib/client/templates/category_title.html',
|
||||
'lib/client/templates/category_title.js',
|
||||
'lib/client/templates/posts_category.html',
|
||||
'lib/client/templates/post_categories.html',
|
||||
'lib/client/templates/post_categories.js',
|
||||
'lib/client/templates/autoform_category.html',
|
||||
'lib/client/templates/autoform_category.js'
|
||||
// 'lib/client/scss/categories.scss',
|
||||
// 'lib/client/templates/categories_admin.html',
|
||||
// 'lib/client/templates/categories_admin.js',
|
||||
// 'lib/client/templates/category_item.html',
|
||||
// 'lib/client/templates/category_item.js',
|
||||
// 'lib/client/templates/categories_menu.html',
|
||||
// 'lib/client/templates/categories_menu.js',
|
||||
// 'lib/client/templates/categories_menu_item.html',
|
||||
// 'lib/client/templates/categories_menu_item.js',
|
||||
// 'lib/client/templates/category_title.html',
|
||||
// 'lib/client/templates/category_title.js',
|
||||
// 'lib/client/templates/posts_category.html',
|
||||
// 'lib/client/templates/post_categories.html',
|
||||
// 'lib/client/templates/post_categories.js',
|
||||
// 'lib/client/templates/autoform_category.html',
|
||||
// 'lib/client/templates/autoform_category.js'
|
||||
], ['client']);
|
||||
|
||||
api.addFiles([
|
||||
'lib/server/publications.js'
|
||||
], ['server']);
|
||||
|
||||
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) {
|
||||
return "i18n/"+language+".i18n.json";
|
||||
});
|
||||
api.addFiles(languagesPaths, ["client", "server"]);
|
||||
// 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) {
|
||||
// return "i18n/"+language+".i18n.json";
|
||||
// });
|
||||
// api.addFiles(languagesPaths, ["client", "server"]);
|
||||
|
||||
api.export([
|
||||
'Categories'
|
||||
|
|
|
@ -27,7 +27,7 @@ Package.onUse(function (api) {
|
|||
// 'lib/modules.js',
|
||||
'lib/helpers.js',
|
||||
// 'lib/menus.js',
|
||||
// 'lib/pubsub.js',
|
||||
'lib/pubsub.js',
|
||||
// 'lib/methods.js',
|
||||
// 'lib/routes.js'
|
||||
], ['client', 'server']);
|
||||
|
|
45
packages/telescope-vote/lib/custom_fields.js
Normal file
45
packages/telescope-vote/lib/custom_fields.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
Telescope.settings.addField([
|
||||
/**
|
||||
How many upvotes the post has received
|
||||
*/
|
||||
{
|
||||
fieldName: "upvotes",
|
||||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of the post's upvoters
|
||||
*/
|
||||
{
|
||||
fieldName: "upvoters",
|
||||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
/**
|
||||
How many downvotes the post has received
|
||||
*/
|
||||
{
|
||||
fieldName: "downvotes",
|
||||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
/**
|
||||
An array containing the `_id`s of the post's downvoters
|
||||
*/
|
||||
{
|
||||
fieldName: "downvoters",
|
||||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
Posts.publicationFields.list.push("upvotes", "downvotes");
|
||||
Posts.publicationFields.single.push("upvotes", "upvoters", "downvotes", "downvoters");
|
|
@ -15,7 +15,8 @@ Package.onUse(function (api) {
|
|||
|
||||
api.addFiles([
|
||||
// 'package-tap.i18n',
|
||||
'lib/vote.js'
|
||||
'lib/vote.js',
|
||||
'lib/custom_fields.js'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
|
|
Loading…
Add table
Reference in a new issue