mirror of
https://github.com/vale981/Vulcan
synced 2025-03-05 17:41: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:spiderable
|
||||||
# telescope:subscribe-to-posts # notifications
|
# telescope:subscribe-to-posts # notifications
|
||||||
# telescope:tagline-banner
|
# telescope:tagline-banner
|
||||||
# telescope:tags
|
|
||||||
|
telescope:tags
|
||||||
|
|
||||||
# telescope:theme-base
|
# telescope:theme-base
|
||||||
# telescope:theme-hubble
|
# telescope:theme-hubble
|
||||||
# telescope:update-prompt
|
# telescope:update-prompt
|
||||||
|
|
|
@ -112,6 +112,7 @@ telescope:lib@0.25.7
|
||||||
telescope:posts@0.25.7
|
telescope:posts@0.25.7
|
||||||
telescope:search@0.25.7
|
telescope:search@0.25.7
|
||||||
telescope:settings@0.25.7
|
telescope:settings@0.25.7
|
||||||
|
telescope:tags@0.25.7
|
||||||
telescope:users@0.25.7
|
telescope:users@0.25.7
|
||||||
templating@1.1.6-modules.8
|
templating@1.1.6-modules.8
|
||||||
templating-tools@1.0.1-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 Header = props => {
|
||||||
|
|
||||||
const Logo = Telescope.getComponent("Logo");
|
({Logo, ListContainer, CategoriesList} = Telescope.components);
|
||||||
|
|
||||||
const logoUrl = Telescope.settings.get("logoUrl");
|
const logoUrl = Telescope.settings.get("logoUrl");
|
||||||
const siteTitle = Telescope.settings.get("title", "Telescope");
|
const siteTitle = Telescope.settings.get("title", "Telescope");
|
||||||
|
@ -13,9 +13,7 @@ const Header = props => {
|
||||||
{tagline ? <h2 className="tagline">{tagline}</h2> : "" }
|
{tagline ? <h2 className="tagline">{tagline}</h2> : "" }
|
||||||
</div>
|
</div>
|
||||||
<div className="nav">
|
<div className="nav">
|
||||||
<ul>
|
<ListContainer collection={Categories} publication="categories" component={CategoriesList} limit={0}/>
|
||||||
<li>Nav link</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,4 +19,8 @@ Telescope.registerComponent("PostEdit", require('./posts/PostEdit.jsx'));
|
||||||
// comments
|
// comments
|
||||||
|
|
||||||
Telescope.registerComponent("CommentItem", require('./comments/list/CommentItem.jsx'));
|
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: {
|
_id: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The `_id` of the parent comment, if there is one
|
The `_id` of the parent comment, if there is one
|
||||||
|
@ -25,6 +26,7 @@ Comments.schema = new SimpleSchema({
|
||||||
max: 500,
|
max: 500,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
optional: true,
|
optional: true,
|
||||||
|
public: true,
|
||||||
autoform: {
|
autoform: {
|
||||||
omit: true // never show this
|
omit: true // never show this
|
||||||
}
|
}
|
||||||
|
@ -38,6 +40,7 @@ Comments.schema = new SimpleSchema({
|
||||||
max: 500,
|
max: 500,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
optional: true,
|
optional: true,
|
||||||
|
public: true,
|
||||||
autoform: {
|
autoform: {
|
||||||
omit: true // never show this
|
omit: true // never show this
|
||||||
}
|
}
|
||||||
|
@ -47,14 +50,16 @@ Comments.schema = new SimpleSchema({
|
||||||
*/
|
*/
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: Date,
|
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
|
The timestamp of the comment being posted. For now, comments are always created and posted at the same time
|
||||||
*/
|
*/
|
||||||
postedAt: {
|
postedAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The comment body (Markdown)
|
The comment body (Markdown)
|
||||||
|
@ -63,6 +68,7 @@ Comments.schema = new SimpleSchema({
|
||||||
type: String,
|
type: String,
|
||||||
max: 3000,
|
max: 3000,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
|
public: true,
|
||||||
autoform: {
|
autoform: {
|
||||||
rows: 5,
|
rows: 5,
|
||||||
afFormGroup: {
|
afFormGroup: {
|
||||||
|
@ -75,7 +81,8 @@ Comments.schema = new SimpleSchema({
|
||||||
*/
|
*/
|
||||||
htmlBody: {
|
htmlBody: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The comment's base score (doesn't factor in comment age)
|
The comment's base score (doesn't factor in comment age)
|
||||||
|
@ -83,7 +90,8 @@ Comments.schema = new SimpleSchema({
|
||||||
baseScore: {
|
baseScore: {
|
||||||
type: Number,
|
type: Number,
|
||||||
decimal: true,
|
decimal: true,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The comment's current score (factors in comment age)
|
The comment's current score (factors in comment age)
|
||||||
|
@ -91,49 +99,56 @@ Comments.schema = new SimpleSchema({
|
||||||
score: {
|
score: {
|
||||||
type: Number,
|
type: Number,
|
||||||
decimal: true,
|
decimal: true,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The number of upvotes the comment has received
|
The number of upvotes the comment has received
|
||||||
*/
|
*/
|
||||||
upvotes: {
|
upvotes: {
|
||||||
type: Number,
|
type: Number,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
An array containing the `_id`s of upvoters
|
An array containing the `_id`s of upvoters
|
||||||
*/
|
*/
|
||||||
upvoters: {
|
upvoters: {
|
||||||
type: [String],
|
type: [String],
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The number of downvotes the comment has received
|
The number of downvotes the comment has received
|
||||||
*/
|
*/
|
||||||
downvotes: {
|
downvotes: {
|
||||||
type: Number,
|
type: Number,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
An array containing the `_id`s of downvoters
|
An array containing the `_id`s of downvoters
|
||||||
*/
|
*/
|
||||||
downvoters: {
|
downvoters: {
|
||||||
type: [String],
|
type: [String],
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The comment author's name
|
The comment author's name
|
||||||
*/
|
*/
|
||||||
author: {
|
author: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Whether the comment is inactive. Inactive comments' scores gets recalculated less often
|
Whether the comment is inactive. Inactive comments' scores gets recalculated less often
|
||||||
*/
|
*/
|
||||||
inactive: {
|
inactive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post's `_id`
|
The post's `_id`
|
||||||
|
@ -141,6 +156,7 @@ Comments.schema = new SimpleSchema({
|
||||||
postId: {
|
postId: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true,
|
optional: true,
|
||||||
|
public: true,
|
||||||
// regEx: SimpleSchema.RegEx.Id,
|
// regEx: SimpleSchema.RegEx.Id,
|
||||||
max: 500,
|
max: 500,
|
||||||
// editableBy: ["member", "admin"], // TODO: should users be able to set postId, but not modify it?
|
// editableBy: ["member", "admin"], // TODO: should users be able to set postId, but not modify it?
|
||||||
|
@ -153,14 +169,16 @@ Comments.schema = new SimpleSchema({
|
||||||
*/
|
*/
|
||||||
userId: {
|
userId: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Whether the comment is deleted. Delete comments' content doesn't appear on the site.
|
Whether the comment is deleted. Delete comments' content doesn't appear on the site.
|
||||||
*/
|
*/
|
||||||
isDeleted: {
|
isDeleted: {
|
||||||
type: Boolean,
|
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)){
|
if(Users.can.viewById(this.userId)){
|
||||||
var parameters = Comments.parameters.get(terms);
|
var parameters = Comments.parameters.get(terms);
|
||||||
console.log(terms)
|
|
||||||
console.log(parameters)
|
|
||||||
var comments = Comments.find(parameters.find, parameters.options);
|
var comments = Comments.find(parameters.find, parameters.options);
|
||||||
|
|
||||||
// if there are comments, find out which posts were commented on
|
// 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:lib@0.25.7',
|
||||||
// 'telescope:i18n@0.25.7',
|
// 'telescope:i18n@0.25.7',
|
||||||
'telescope:settings@0.25.7',
|
'telescope:settings@0.25.7',
|
||||||
|
'telescope:posts@0.25.7',
|
||||||
'telescope:users@0.25.7'
|
'telescope:users@0.25.7'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ Package.onUse(function (api) {
|
||||||
'lib/views.js',
|
'lib/views.js',
|
||||||
'lib/parameters.js',
|
'lib/parameters.js',
|
||||||
'lib/helpers.js',
|
'lib/helpers.js',
|
||||||
|
'lib/custom_fields.js',
|
||||||
// 'lib/routes.js'
|
// 'lib/routes.js'
|
||||||
], ['client', 'server']);
|
], ['client', 'server']);
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,17 @@ const ListContainer = React.createClass({
|
||||||
mixins: [ReactMeteorData],
|
mixins: [ReactMeteorData],
|
||||||
|
|
||||||
getMeteorData() {
|
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 subscription = Meteor.subscribe(this.props.publication, terms);
|
||||||
|
|
||||||
const totalCount = Counts.get(this.props.publication);
|
const totalCount = Counts.get(this.props.publication);
|
||||||
|
|
|
@ -48,4 +48,4 @@ Telescope.subscriptions = [];
|
||||||
*/
|
*/
|
||||||
Telescope.subscriptions.preload = function (subscription, args) {
|
Telescope.subscriptions.preload = function (subscription, args) {
|
||||||
Telescope.subscriptions.push({name: subscription, arguments: args});
|
Telescope.subscriptions.push({name: subscription, arguments: args});
|
||||||
};
|
};
|
||||||
|
|
|
@ -252,3 +252,11 @@ Telescope.getNestedProperty = function (obj, desc) {
|
||||||
while(arr.length && (obj = obj[arr.shift()]));
|
while(arr.length && (obj = obj[arr.shift()]));
|
||||||
return obj;
|
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: {
|
_id: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Timetstamp of post creation
|
Timetstamp of post creation
|
||||||
*/
|
*/
|
||||||
createdAt: {
|
createdAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Timestamp of post first appearing on the site (i.e. being approved)
|
Timestamp of post first appearing on the site (i.e. being approved)
|
||||||
|
@ -24,10 +26,11 @@ Posts.schema = new SimpleSchema({
|
||||||
type: Date,
|
type: Date,
|
||||||
optional: true,
|
optional: true,
|
||||||
editableBy: ["admin"],
|
editableBy: ["admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// group: 'admin',
|
autoform: {
|
||||||
// type: "bootstrap-datetimepicker"
|
group: 'admin',
|
||||||
// }
|
type: "bootstrap-datetimepicker"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
URL
|
URL
|
||||||
|
@ -37,10 +40,11 @@ Posts.schema = new SimpleSchema({
|
||||||
optional: true,
|
optional: true,
|
||||||
max: 500,
|
max: 500,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// type: "bootstrap-url",
|
autoform: {
|
||||||
// order: 10
|
type: "bootstrap-url",
|
||||||
// }
|
order: 10
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Title
|
Title
|
||||||
|
@ -50,16 +54,18 @@ Posts.schema = new SimpleSchema({
|
||||||
optional: false,
|
optional: false,
|
||||||
max: 500,
|
max: 500,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// order: 20
|
autoform: {
|
||||||
// }
|
order: 20
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Slug
|
Slug
|
||||||
*/
|
*/
|
||||||
slug: {
|
slug: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Post body (markdown)
|
Post body (markdown)
|
||||||
|
@ -69,52 +75,43 @@ Posts.schema = new SimpleSchema({
|
||||||
optional: true,
|
optional: true,
|
||||||
max: 3000,
|
max: 3000,
|
||||||
editableBy: ["member", "admin"],
|
editableBy: ["member", "admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// rows: 5,
|
autoform: {
|
||||||
// order: 30
|
rows: 5,
|
||||||
// }
|
order: 30
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
HTML version of the post body
|
HTML version of the post body
|
||||||
*/
|
*/
|
||||||
htmlBody: {
|
htmlBody: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Count of how many times the post's page was viewed
|
Count of how many times the post's page was viewed
|
||||||
*/
|
*/
|
||||||
viewCount: {
|
viewCount: {
|
||||||
type: Number,
|
type: Number,
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
public: 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
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Timestamp of the last comment
|
Timestamp of the last comment
|
||||||
*/
|
*/
|
||||||
lastCommentedAt: {
|
lastCommentedAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Count of how many times the post's link was clicked
|
Count of how many times the post's link was clicked
|
||||||
*/
|
*/
|
||||||
clickCount: {
|
clickCount: {
|
||||||
type: Number,
|
type: Number,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post's base score (not factoring in the post's age)
|
The post's base score (not factoring in the post's age)
|
||||||
|
@ -122,35 +119,8 @@ Posts.schema = new SimpleSchema({
|
||||||
baseScore: {
|
baseScore: {
|
||||||
type: Number,
|
type: Number,
|
||||||
decimal: true,
|
decimal: true,
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
public: 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
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post's current score (factoring in age)
|
The post's current score (factoring in age)
|
||||||
|
@ -158,7 +128,8 @@ Posts.schema = new SimpleSchema({
|
||||||
score: {
|
score: {
|
||||||
type: Number,
|
type: Number,
|
||||||
decimal: true,
|
decimal: true,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post's status. One of pending (`1`), approved (`2`), or deleted (`3`)
|
The post's status. One of pending (`1`), approved (`2`), or deleted (`3`)
|
||||||
|
@ -167,6 +138,7 @@ Posts.schema = new SimpleSchema({
|
||||||
type: Number,
|
type: Number,
|
||||||
optional: true,
|
optional: true,
|
||||||
editableBy: ["admin"],
|
editableBy: ["admin"],
|
||||||
|
public: true,
|
||||||
autoValue: function () {
|
autoValue: function () {
|
||||||
// only provide a default value
|
// only provide a default value
|
||||||
// 1) this is an insert operation
|
// 1) this is an insert operation
|
||||||
|
@ -175,11 +147,11 @@ Posts.schema = new SimpleSchema({
|
||||||
if (this.isInsert && !this.isSet)
|
if (this.isInsert && !this.isSet)
|
||||||
return Posts.getDefaultStatus(user);
|
return Posts.getDefaultStatus(user);
|
||||||
},
|
},
|
||||||
// autoform: {
|
autoform: {
|
||||||
// noselect: true,
|
noselect: true,
|
||||||
// options: Posts.config.postStatuses,
|
options: Posts.config.postStatuses,
|
||||||
// group: 'admin'
|
group: 'admin'
|
||||||
// }
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Whether the post is sticky (pinned to the top of posts lists)
|
Whether the post is sticky (pinned to the top of posts lists)
|
||||||
|
@ -189,39 +161,45 @@ Posts.schema = new SimpleSchema({
|
||||||
optional: true,
|
optional: true,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
editableBy: ["admin"],
|
editableBy: ["admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// group: 'admin',
|
autoform: {
|
||||||
// leftLabel: "Sticky"
|
group: 'admin',
|
||||||
// }
|
leftLabel: "Sticky"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Whether the post is inactive. Inactive posts see their score recalculated less often
|
Whether the post is inactive. Inactive posts see their score recalculated less often
|
||||||
*/
|
*/
|
||||||
inactive: {
|
inactive: {
|
||||||
type: Boolean,
|
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
|
Save info for later spam checking on a post. We will use this for the akismet package
|
||||||
*/
|
*/
|
||||||
userIP: {
|
userIP: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: false,
|
||||||
},
|
},
|
||||||
userAgent: {
|
userAgent: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: false,
|
||||||
},
|
},
|
||||||
referrer: {
|
referrer: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: false,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post author's name
|
The post author's name
|
||||||
*/
|
*/
|
||||||
author: {
|
author: {
|
||||||
type: String,
|
type: String,
|
||||||
optional: true
|
optional: true,
|
||||||
|
public: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post author's `_id`.
|
The post author's `_id`.
|
||||||
|
@ -231,17 +209,18 @@ Posts.schema = new SimpleSchema({
|
||||||
optional: true,
|
optional: true,
|
||||||
// regEx: SimpleSchema.RegEx.Id,
|
// regEx: SimpleSchema.RegEx.Id,
|
||||||
editableBy: ["admin"],
|
editableBy: ["admin"],
|
||||||
// autoform: {
|
public: true,
|
||||||
// group: 'admin',
|
autoform: {
|
||||||
// options: function () {
|
group: 'admin',
|
||||||
// return Meteor.users.find().map(function (user) {
|
options: function () {
|
||||||
// return {
|
return Meteor.users.find().map(function (user) {
|
||||||
// value: user._id,
|
return {
|
||||||
// label: Users.getDisplayName(user)
|
value: user._id,
|
||||||
// };
|
label: Users.getDisplayName(user)
|
||||||
// });
|
};
|
||||||
// }
|
});
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,124 +1,99 @@
|
||||||
Posts._ensureIndex({"status": 1, "postedAt": 1});
|
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) {
|
Meteor.publish('posts.list', function(terms) {
|
||||||
|
|
||||||
var parameters = Posts.parameters.get(terms),
|
this.unblock();
|
||||||
posts = Posts.find(parameters.find, parameters.options);
|
|
||||||
|
|
||||||
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) {
|
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/parameters.js',
|
||||||
'lib/views.js',
|
'lib/views.js',
|
||||||
'lib/helpers.js',
|
'lib/helpers.js',
|
||||||
|
'lib/fields.js',
|
||||||
// 'lib/modules.js',
|
// 'lib/modules.js',
|
||||||
// 'lib/callbacks.js',
|
// 'lib/callbacks.js',
|
||||||
// 'lib/methods.js',
|
// 'lib/methods.js',
|
||||||
|
|
|
@ -47,22 +47,14 @@ Categories.schema = new SimpleSchema({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Meteor.startup(function(){
|
// Meteor.startup(function(){
|
||||||
Categories.internationalize();
|
// Categories.internationalize();
|
||||||
});
|
// });
|
||||||
|
|
||||||
Categories.attachSchema(Categories.schema);
|
Categories.attachSchema(Categories.schema);
|
||||||
|
|
||||||
Meteor.startup(function () {
|
|
||||||
Categories.allow({
|
|
||||||
insert: Users.is.adminById,
|
|
||||||
update: Users.is.adminById,
|
|
||||||
remove: Users.is.adminById
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
Telescope.settings.collection.addField([
|
||||||
Settings.addField([
|
|
||||||
{
|
{
|
||||||
fieldName: 'categoriesBehavior',
|
fieldName: 'categoriesBehavior',
|
||||||
fieldSchema: {
|
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([
|
api.addFiles([
|
||||||
'lib/categories.js',
|
'lib/categories.js',
|
||||||
'lib/helpers.js',
|
'lib/helpers.js',
|
||||||
'lib/callbacks.js',
|
// 'lib/callbacks.js',
|
||||||
'lib/parameters.js',
|
// 'lib/parameters.js',
|
||||||
'lib/custom_fields.js',
|
// 'lib/custom_fields.js',
|
||||||
'lib/methods.js',
|
// 'lib/methods.js',
|
||||||
'lib/modules.js',
|
// 'lib/modules.js',
|
||||||
'lib/routes.js',
|
// 'lib/routes.js',
|
||||||
'package-tap.i18n'
|
// 'package-tap.i18n'
|
||||||
], ['client', 'server']);
|
], ['client', 'server']);
|
||||||
|
|
||||||
api.addFiles([
|
api.addFiles([
|
||||||
'lib/client/scss/categories.scss',
|
// 'lib/client/scss/categories.scss',
|
||||||
'lib/client/templates/categories_admin.html',
|
// 'lib/client/templates/categories_admin.html',
|
||||||
'lib/client/templates/categories_admin.js',
|
// 'lib/client/templates/categories_admin.js',
|
||||||
'lib/client/templates/category_item.html',
|
// 'lib/client/templates/category_item.html',
|
||||||
'lib/client/templates/category_item.js',
|
// 'lib/client/templates/category_item.js',
|
||||||
'lib/client/templates/categories_menu.html',
|
// 'lib/client/templates/categories_menu.html',
|
||||||
'lib/client/templates/categories_menu.js',
|
// 'lib/client/templates/categories_menu.js',
|
||||||
'lib/client/templates/categories_menu_item.html',
|
// 'lib/client/templates/categories_menu_item.html',
|
||||||
'lib/client/templates/categories_menu_item.js',
|
// 'lib/client/templates/categories_menu_item.js',
|
||||||
'lib/client/templates/category_title.html',
|
// 'lib/client/templates/category_title.html',
|
||||||
'lib/client/templates/category_title.js',
|
// 'lib/client/templates/category_title.js',
|
||||||
'lib/client/templates/posts_category.html',
|
// 'lib/client/templates/posts_category.html',
|
||||||
'lib/client/templates/post_categories.html',
|
// 'lib/client/templates/post_categories.html',
|
||||||
'lib/client/templates/post_categories.js',
|
// 'lib/client/templates/post_categories.js',
|
||||||
'lib/client/templates/autoform_category.html',
|
// 'lib/client/templates/autoform_category.html',
|
||||||
'lib/client/templates/autoform_category.js'
|
// 'lib/client/templates/autoform_category.js'
|
||||||
], ['client']);
|
], ['client']);
|
||||||
|
|
||||||
api.addFiles([
|
api.addFiles([
|
||||||
'lib/server/publications.js'
|
'lib/server/publications.js'
|
||||||
], ['server']);
|
], ['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 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) {
|
// var languagesPaths = languages.map(function (language) {
|
||||||
return "i18n/"+language+".i18n.json";
|
// return "i18n/"+language+".i18n.json";
|
||||||
});
|
// });
|
||||||
api.addFiles(languagesPaths, ["client", "server"]);
|
// api.addFiles(languagesPaths, ["client", "server"]);
|
||||||
|
|
||||||
api.export([
|
api.export([
|
||||||
'Categories'
|
'Categories'
|
||||||
|
|
|
@ -27,7 +27,7 @@ Package.onUse(function (api) {
|
||||||
// 'lib/modules.js',
|
// 'lib/modules.js',
|
||||||
'lib/helpers.js',
|
'lib/helpers.js',
|
||||||
// 'lib/menus.js',
|
// 'lib/menus.js',
|
||||||
// 'lib/pubsub.js',
|
'lib/pubsub.js',
|
||||||
// 'lib/methods.js',
|
// 'lib/methods.js',
|
||||||
// 'lib/routes.js'
|
// 'lib/routes.js'
|
||||||
], ['client', 'server']);
|
], ['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([
|
api.addFiles([
|
||||||
// 'package-tap.i18n',
|
// 'package-tap.i18n',
|
||||||
'lib/vote.js'
|
'lib/vote.js',
|
||||||
|
'lib/custom_fields.js'
|
||||||
], ['client', 'server']);
|
], ['client', 'server']);
|
||||||
|
|
||||||
api.addFiles([
|
api.addFiles([
|
||||||
|
|
Loading…
Add table
Reference in a new issue