mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 18:11:40 -05:00
update with latest commits of nova
This commit is contained in:
commit
c3eb63b7f4
27 changed files with 344 additions and 40 deletions
|
@ -21,8 +21,8 @@ nova:notifications
|
|||
nova:getting-started
|
||||
nova:categories
|
||||
nova:share
|
||||
nova:voting
|
||||
|
||||
# nova:voting
|
||||
# nova:migrations
|
||||
# nova:api
|
||||
# nova:email
|
||||
|
|
|
@ -104,6 +104,7 @@ nova:search@0.25.7
|
|||
nova:settings@0.25.7
|
||||
nova:share@0.25.7
|
||||
nova:users@0.25.7
|
||||
nova:voting@0.25.7
|
||||
npm-bcrypt@0.7.8_2
|
||||
npm-mongo@1.4.41-rc.2
|
||||
oauth@1.1.8-rc.2
|
||||
|
|
|
@ -4,8 +4,8 @@ import Core from "meteor/nova:core";
|
|||
const Messages = Core.Messages;
|
||||
|
||||
const Header = ({currentUser}) => {
|
||||
|
||||
({Logo, ListContainer, CategoriesList, FlashContainer, FlashMessages, ModalButton, NewDocContainer, CanCreatePost, CurrentUserContainer, NewsletterForm, HeadTags} = Telescope.components);
|
||||
|
||||
({Logo, ListContainer, CategoriesList, FlashContainer, FlashMessages, ModalButton, NewDocContainer, CanCreatePost, CurrentUserContainer, NewsletterForm, SearchForm, HeadTags} = Telescope.components);
|
||||
|
||||
const logoUrl = Telescope.settings.get("logoUrl");
|
||||
const siteTitle = Telescope.settings.get("title", "Telescope");
|
||||
|
@ -42,6 +42,8 @@ const Header = ({currentUser}) => {
|
|||
|
||||
<CurrentUserContainer component={NewsletterForm} />
|
||||
|
||||
<SearchForm/>
|
||||
|
||||
<FlashContainer component={FlashMessages}/>
|
||||
|
||||
</header>
|
||||
|
|
10
packages/base-components/lib/common/Icon.jsx
Normal file
10
packages/base-components/lib/common/Icon.jsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
const Icon = ({ name, iconClass }) => {
|
||||
const icons = Telescope.utils.icons;
|
||||
const iconCode = !!icons[name] ? icons[name] : name;
|
||||
iconClass = (typeof iconClass === 'string') ? ' '+iconClass : '';
|
||||
const c = 'icon fa fa-fw fa-' + iconCode + ' icon-' + name + iconClass;
|
||||
return <i className={c} aria-hidden="true"></i>;
|
||||
}
|
||||
|
||||
module.exports = Icon;
|
||||
export default Icon;
|
65
packages/base-components/lib/common/SearchForm.jsx
Normal file
65
packages/base-components/lib/common/SearchForm.jsx
Normal file
|
@ -0,0 +1,65 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Formsy from 'formsy-react';
|
||||
import FRC from 'formsy-react-components';
|
||||
|
||||
const Input = FRC.Input;
|
||||
|
||||
// see: http://stackoverflow.com/questions/1909441/jquery-keyup-delay
|
||||
const delay = (function(){
|
||||
var timer = 0;
|
||||
return function(callback, ms){
|
||||
clearTimeout (timer);
|
||||
timer = setTimeout(callback, ms);
|
||||
};
|
||||
})();
|
||||
|
||||
class SearchForm extends Component{
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.search = this.search.bind(this);
|
||||
}
|
||||
|
||||
search(data) {
|
||||
|
||||
if (FlowRouter.getRouteName() !== "posts.list") {
|
||||
FlowRouter.go("posts.list");
|
||||
}
|
||||
|
||||
if (data.searchQuery === '') {
|
||||
data.searchQuery = null;
|
||||
}
|
||||
|
||||
delay(function(){
|
||||
FlowRouter.setQueryParams({query: data.searchQuery});
|
||||
}, 700 );
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div className="search-form">
|
||||
<Formsy.Form onChange={this.search}>
|
||||
<Input
|
||||
name="searchQuery"
|
||||
value=""
|
||||
label={this.props.labelText}
|
||||
type="text"
|
||||
/>
|
||||
</Formsy.Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SearchForm.propTypes = {
|
||||
labelText: React.PropTypes.string
|
||||
}
|
||||
|
||||
SearchForm.defaultProps = {
|
||||
labelText: "Search"
|
||||
};
|
||||
|
||||
module.exports = SearchForm;
|
||||
export default SearchForm;
|
|
@ -8,6 +8,8 @@ Telescope.registerComponent("Flash", require('./common/Flash.jsx'));
|
|||
Telescope.registerComponent('HeadTags', require('./common/HeadTags.jsx'));
|
||||
Telescope.registerComponent("FlashMessages", require('./common/FlashMessages.jsx'));
|
||||
Telescope.registerComponent("NewsletterForm", require('./common/NewsletterForm.jsx'));
|
||||
Telescope.registerComponent("Icon", require('./common/Icon.jsx'));
|
||||
Telescope.registerComponent("SearchForm", require('./common/SearchForm.jsx'));
|
||||
|
||||
// posts
|
||||
|
||||
|
@ -21,6 +23,10 @@ Telescope.registerComponent("PostList", require('./posts/list/PostList.jsx'));
|
|||
Telescope.registerComponent("PostCategories", require('./posts/list/PostCategories.jsx'));
|
||||
Telescope.registerComponent("PostCommenters", require('./posts/list/PostCommenters.jsx'));
|
||||
Telescope.registerComponent("Post", require('./posts/Post.jsx'));
|
||||
Telescope.registerComponent("PostStats", require('./posts/PostStats.jsx'));
|
||||
Telescope.registerComponent("PostDaily", require('./posts/PostDaily.jsx'));
|
||||
Telescope.registerComponent("PostDay", require('./posts/PostDay.jsx'));
|
||||
Telescope.registerComponent("Vote", require('./posts/Vote.jsx'));
|
||||
|
||||
// comments
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const methodList = Meteor.isServer ? Meteor.server.method_handlers : Meteor.connection._methodHandlers;
|
||||
|
||||
const renderFunction = (func, name) => {
|
||||
const s = func.toString();
|
||||
const openParen = s.indexOf("(");
|
||||
|
@ -45,6 +47,10 @@ const Cheatsheet = props => {
|
|||
<ul>
|
||||
{_.map(Users.is, renderFunction)}
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<ul>
|
||||
{_.map(methodList, (item, key) => (key.indexOf("users.") !== -1 ? renderFunction(item, key) : null))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="cheatsheet-block">
|
||||
|
@ -53,6 +59,10 @@ const Cheatsheet = props => {
|
|||
<ul>
|
||||
{_.map(Posts, (item, key) => (key[0] !== "_" ? renderFunction(item, key) : null) )}
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<ul>
|
||||
{_.map(methodList, (item, key) => (key.indexOf("posts.") !== -1 ? renderFunction(item, key) : null))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="cheatsheet-block">
|
||||
|
@ -61,6 +71,10 @@ const Cheatsheet = props => {
|
|||
<ul>
|
||||
{_.map(Comments, (item, key) => (key[0] !== "_" ? renderFunction(item, key) : null) )}
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<ul>
|
||||
{_.map(methodList, (item, key) => (key.indexOf("comments.") !== -1 ? renderFunction(item, key) : null))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="cheatsheet-block">
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
const Post = ({document}) => {
|
||||
|
||||
({ListContainer, CommentList, CommentNew, PostCategories, SocialShare, HeadTags} = Telescope.components);
|
||||
const Post = ({document, currentUser}) => {
|
||||
|
||||
({ListContainer, CommentList, CommentNew, PostCategories, SocialShare, Vote, PostStats, HeadTags} = Telescope.components);
|
||||
|
||||
const post = document;
|
||||
const htmlBody = {__html: post.htmlBody};
|
||||
return (
|
||||
<div className="post">
|
||||
|
||||
<Vote post={post} currentUser={currentUser}/>
|
||||
|
||||
<h3>{post.title}</h3>
|
||||
<HeadTags url={Posts.getLink(post)} title={post.title}/>
|
||||
<SocialShare url={ Posts.getLink(post) } title={ post.title }/>
|
||||
<p>{post.commentCount} comments</p>
|
||||
<p>{moment(post.postedAt).fromNow()}</p>
|
||||
|
||||
<PostStats post={post} />
|
||||
|
||||
{post.categoriesArray ? <PostCategories categories={post.categoriesArray} /> : ""}
|
||||
<div dangerouslySetInnerHTML={htmlBody}></div>
|
||||
|
||||
|
|
45
packages/base-components/lib/posts/PostDaily.jsx
Normal file
45
packages/base-components/lib/posts/PostDaily.jsx
Normal file
|
@ -0,0 +1,45 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
|
||||
// for a number of days "n" return dates object for the past n days
|
||||
const getLastNDates = n => {
|
||||
return _.range(n).map(
|
||||
i => moment().subtract(i, 'days').startOf('day').toDate()
|
||||
);
|
||||
};
|
||||
|
||||
class PostDaily extends Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.loadMoreDays = this.loadMoreDays.bind(this);
|
||||
this.state = {days: props.days};
|
||||
}
|
||||
|
||||
loadMoreDays(e) {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
days: this.state.days + 5
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
({PostDay} = Telescope.components);
|
||||
return (
|
||||
<div className="post-daily">
|
||||
{getLastNDates(this.state.days).map((date, index) => <PostDay key={index} date={date} number={index}/>)}
|
||||
<a href="#" className="button button--primary" onClick={this.loadMoreDays}>Load More Days</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
PostDaily.propTypes = {
|
||||
days: React.PropTypes.number
|
||||
}
|
||||
|
||||
PostDaily.defaultProps = {
|
||||
days: 5
|
||||
}
|
||||
|
||||
module.exports = PostDaily;
|
||||
export default PostDaily;
|
40
packages/base-components/lib/posts/PostDay.jsx
Normal file
40
packages/base-components/lib/posts/PostDay.jsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
|
||||
const PostDay = ({date, number}) => {
|
||||
|
||||
({PostList} = Telescope.components);
|
||||
|
||||
const terms = {
|
||||
view: "top",
|
||||
date: date,
|
||||
after: moment(date).format("YYYY-MM-DD"),
|
||||
before: moment(date).format("YYYY-MM-DD"),
|
||||
enableCache: number <= 15 ? true : false // only cache first 15 days
|
||||
};
|
||||
|
||||
({selector, options} = Posts.parameters.get(terms));
|
||||
|
||||
return (
|
||||
<div className="post-day">
|
||||
<h2>{moment(date).format("dddd, MMMM Do YYYY")}</h2>
|
||||
<ListContainer
|
||||
collection={Posts}
|
||||
publication="posts.list"
|
||||
selector={selector}
|
||||
options={options}
|
||||
terms={terms}
|
||||
joins={Posts.getJoins()}
|
||||
component={PostList}
|
||||
componentProps={{showViews: false}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
PostDay.propTypes = {
|
||||
date: React.PropTypes.object,
|
||||
number: React.PropTypes.number
|
||||
}
|
||||
|
||||
module.exports = PostDay;
|
||||
export default PostDay;
|
16
packages/base-components/lib/posts/PostStats.jsx
Normal file
16
packages/base-components/lib/posts/PostStats.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
const PostStats = ({post}) => {
|
||||
|
||||
({Icon} = Telescope.components);
|
||||
|
||||
return (
|
||||
<div className="post-stats">
|
||||
{post.score ? <span title="Score"><Icon name="score"/> {Math.floor(post.score*10000)/10000} <span className="sr-only">Score</span></span> : ""}
|
||||
<span title="Upvotes"><Icon name="upvote"/> {post.upvotes} <span className="sr-only">Upvotes</span></span>
|
||||
<span title="Clicks"><Icon name="clicks"/> {post.clickCount} <span className="sr-only">Clicks</span></span>
|
||||
<span title="Views"><Icon name="views"/> {post.viewCount} <span className="sr-only">Views</span></span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = PostStats;
|
||||
export default PostStats;
|
62
packages/base-components/lib/posts/Vote.jsx
Normal file
62
packages/base-components/lib/posts/Vote.jsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
|
||||
import Core from "meteor/nova:core";
|
||||
const Messages = Core.Messages;
|
||||
|
||||
class Vote extends Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.upvote = this.upvote.bind(this);
|
||||
}
|
||||
|
||||
upvote(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const post = this.props.post;
|
||||
const user = this.props.currentUser;
|
||||
|
||||
if(!user){
|
||||
Messages.flash("Please log in first");
|
||||
} else if (user.hasUpvoted(post)) {
|
||||
Meteor.call('posts.cancelUpvote', post._id, function(){
|
||||
Events.track("post upvote cancelled", {'_id': post._id});
|
||||
});
|
||||
} else {
|
||||
Meteor.call('posts.upvote', post._id, function(){
|
||||
Events.track("post upvoted", {'_id': post._id});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
({Icon} = Telescope.components);
|
||||
|
||||
const post = this.props.post;
|
||||
const user = this.props.currentUser;
|
||||
|
||||
let actionsClass = "vote";
|
||||
if (Users.hasUpvoted(user, post)) actionsClass += " voted upvoted";
|
||||
if (Users.hasDownvoted(user, post)) actionsClass += " voted downvoted";
|
||||
|
||||
return (
|
||||
<div className={actionsClass}>
|
||||
<a href="#" className="button button--secondary upvote" onClick={this.upvote}>
|
||||
<Icon name="upvote" />
|
||||
<span className="sr-only">Upvote</span>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vote.propTypes = {
|
||||
post: React.PropTypes.object.isRequired, // the current comment
|
||||
currentUser: React.PropTypes.object, // the current user
|
||||
}
|
||||
|
||||
module.exports = Vote;
|
||||
export default Vote;
|
|
@ -40,16 +40,19 @@ class PostItem extends Component {
|
|||
|
||||
render() {
|
||||
|
||||
({UserAvatar} = Telescope.components);
|
||||
({UserAvatar, Vote, PostStats} = Telescope.components);
|
||||
|
||||
const post = this.props.post;
|
||||
|
||||
return (
|
||||
<div className="post-item">
|
||||
|
||||
<Vote post={post} currentUser={this.props.currentUser}/>
|
||||
<h3 className="post-title"><a href={Posts.getLink(post)} target={Posts.getLinkTarget(post)}>{post.title}</a></h3>
|
||||
<p><a href={Users.getProfileUrl(post.user)}><UserAvatar user={post.user}/>{Users.getDisplayName(post.user)}</a>, {moment(post.postedAt).fromNow()}, {post.commentCount} comments</p>
|
||||
|
||||
<PostStats post={post} />
|
||||
|
||||
{this.renderCategories()}
|
||||
{this.renderCommenters()}
|
||||
{this.renderActions()}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const PostList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore}) => {
|
||||
const PostList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore, showViews = true}) => {
|
||||
|
||||
({PostItem, LoadMore, PostsLoading, NoPosts, NoMorePosts, PostViews} = Telescope.components);
|
||||
|
||||
if (!!results.length) {
|
||||
return (
|
||||
<div className="postList">
|
||||
<PostViews />
|
||||
{showViews ? <PostViews /> : null}
|
||||
<div className="post-list-content">
|
||||
{results.map(post => <PostItem post={post} currentUser={currentUser} key={post._id}/>)}
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@ const PostList = ({results, currentUser, hasMore, ready, count, totalCount, load
|
|||
} else if (!ready) {
|
||||
return (
|
||||
<div className="postList">
|
||||
<PostViews />
|
||||
{showViews ? <PostViews /> : null}
|
||||
<div className="post-list-content">
|
||||
<PostsLoading/>
|
||||
</div>
|
||||
|
@ -24,7 +24,7 @@ const PostList = ({results, currentUser, hasMore, ready, count, totalCount, load
|
|||
} else {
|
||||
return (
|
||||
<div className="postList">
|
||||
<PostViews />
|
||||
{showViews ? <PostViews /> : null}
|
||||
<div className="post-list-content">
|
||||
<NoPosts/>
|
||||
</div>
|
||||
|
|
|
@ -24,6 +24,16 @@ FlowRouter.route('/', {
|
|||
}
|
||||
});
|
||||
|
||||
FlowRouter.route('/daily/:days?', {
|
||||
name: 'posts.list',
|
||||
action(params, queryParams) {
|
||||
|
||||
({AppContainer, PostDaily} = Telescope.components);
|
||||
|
||||
mount(AppContainer, {content: <PostDaily days={params.days}/>})
|
||||
}
|
||||
});
|
||||
|
||||
FlowRouter.route('/posts/:_id', {
|
||||
name: 'posts.single',
|
||||
action(params, queryParams) {
|
||||
|
|
|
@ -97,6 +97,7 @@ code{
|
|||
}
|
||||
.cheatsheet h3{
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cheatsheet code{
|
||||
font-size: 13px;
|
||||
|
@ -106,4 +107,16 @@ code{
|
|||
height: 24px;
|
||||
width: 24px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.sr-only{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.upvoted .upvote{
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.post-day h2{
|
||||
font-weight: bold;
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import {mount} from 'react-mounter';
|
||||
|
||||
import MoviesWrapper from './demo-components.jsx';
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Collection & Schema //
|
||||
//////////////////////////////////////////////////////
|
||||
|
|
|
@ -6,20 +6,20 @@ import Core from 'meteor/nova:core';
|
|||
import SmartContainers from "meteor/utilities:react-list-container";
|
||||
import FormContainers from "meteor/utilities:react-form-containers";
|
||||
|
||||
FlashContainer = Core.FlashContainer;
|
||||
ModalButton = Core.ModalButton;
|
||||
NewDocContainer = FormContainers.NewDocContainer;
|
||||
EditDocContainer = FormContainers.EditDocContainer;
|
||||
ListContainer = SmartContainers.ListContainer;
|
||||
const ModalButton = Core.ModalButton;
|
||||
const NewDocContainer = FormContainers.NewDocContainer;
|
||||
const EditDocContainer = FormContainers.EditDocContainer;
|
||||
const ListContainer = SmartContainers.ListContainer;
|
||||
|
||||
const FlashContainer = Telescope.components.FlashContainer;
|
||||
const FlashMessages = Telescope.components.FlashMessages;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// MoviesWrapper //
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
MoviesWrapper = React.createClass({
|
||||
|
||||
class MoviesWrapper extends Component {
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div className="wrapper">
|
||||
|
||||
|
@ -27,7 +27,7 @@ MoviesWrapper = React.createClass({
|
|||
<LogInButtons />
|
||||
</NoSSR>
|
||||
|
||||
<FlashContainer />
|
||||
<FlashContainer component={FlashMessages}/>
|
||||
|
||||
<div className="main">
|
||||
<ListContainer
|
||||
|
@ -45,13 +45,13 @@ MoviesWrapper = React.createClass({
|
|||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// MoviesList //
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
MoviesList = React.createClass({
|
||||
class MoviesList extends Component {
|
||||
|
||||
renderNew() {
|
||||
|
||||
|
@ -62,7 +62,7 @@ MoviesList = React.createClass({
|
|||
)
|
||||
|
||||
return !!this.props.currentUser ? component : "";
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
|
@ -74,12 +74,12 @@ MoviesList = React.createClass({
|
|||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Movie //
|
||||
//////////////////////////////////////////////////////
|
||||
Movie = React.createClass({
|
||||
|
||||
class Movie extends Component {
|
||||
|
||||
renderEdit() {
|
||||
|
||||
|
@ -96,7 +96,7 @@ Movie = React.createClass({
|
|||
{this.props.currentUser && this.props.currentUser._id === movie.userId ? component : ""}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
|
@ -111,6 +111,8 @@ Movie = React.createClass({
|
|||
)
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
const LoadMore = props => <a href="#" className="load-more button button--primary" onClick={props.loadMore}>Load More ({props.count}/{props.totalCount})</a>
|
||||
const LoadMore = props => <a href="#" className="load-more button button--primary" onClick={props.loadMore}>Load More ({props.count}/{props.totalCount})</a>
|
||||
|
||||
export default MoviesWrapper
|
|
@ -24,7 +24,6 @@ Package.onUse(function (api) {
|
|||
]);
|
||||
|
||||
api.addFiles([
|
||||
'demo-component.jsx',
|
||||
'demo-app.jsx'
|
||||
], ['client', 'server']);
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ Meteor.methods({
|
|||
|
||||
'posts.upvote': function (postId) {
|
||||
check(postId, String);
|
||||
console.log("upvote")
|
||||
return Telescope.operateOnItem.call(this, Posts, postId, Meteor.user(), "upvote");
|
||||
},
|
||||
|
||||
|
@ -223,6 +224,7 @@ Meteor.methods({
|
|||
|
||||
'posts.cancelUpvote': function (postId) {
|
||||
check(postId, String);
|
||||
console.log("cancelUpvote")
|
||||
return Telescope.operateOnItem.call(this, Posts, postId, Meteor.user(), "cancelUpvote");
|
||||
},
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ Meteor.publish('posts.list', function (terms) {
|
|||
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||
({selector, options} = Posts.parameters.get(terms));
|
||||
|
||||
Counts.publish(this, 'posts.list', Posts.find(selector, options));
|
||||
// disabled for now because of FlowRouterSSR issue
|
||||
// Counts.publish(this, 'posts.list', Posts.find(selector, options));
|
||||
|
||||
options.fields = Posts.publishedFields.list;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import PublicationUtils from 'meteor/utilities:smart-publications';
|
||||
|
||||
// ------------------------------------- Posts -------------------------------- //
|
||||
|
||||
Posts.addField([
|
||||
|
@ -67,8 +69,8 @@ Posts.addField([
|
|||
},
|
||||
]);
|
||||
|
||||
Telescope.utils.addToFields(Posts.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]);
|
||||
Telescope.utils.addToFields(Posts.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]);
|
||||
PublicationUtils.addToFields(Posts.publishedFields.list, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]);
|
||||
PublicationUtils.addToFields(Posts.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]);
|
||||
|
||||
// ------------------------------------- Comments -------------------------------- //
|
||||
|
||||
|
@ -143,5 +145,5 @@ Comments.addField([
|
|||
},
|
||||
]);
|
||||
|
||||
Telescope.utils.addToFields(Comments.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]);
|
||||
Telescope.utils.addToFields(Comments.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]);
|
||||
PublicationUtils.addToFields(Comments.publishedFields.list, ["upvotes", "downvotes", "baseScore", "score"]);
|
||||
PublicationUtils.addToFields(Comments.publishedFields.single, ["upvotes", "upvoters", "downvotes", "downvoters", "baseScore", "score"]);
|
|
@ -37,10 +37,8 @@ Telescope.updateScore = function (args) {
|
|||
// time decay factor
|
||||
var f = 1.3;
|
||||
|
||||
// use baseScore if defined, if not just use the number of votes
|
||||
// note: for transition period, also use votes if there are more votes than baseScore
|
||||
// var baseScore = Math.max(item.votes || 0, item.baseScore || 0);
|
||||
var baseScore = item.baseScore;
|
||||
// use baseScore if defined, if not just use 0
|
||||
var baseScore = item.baseScore || 0;
|
||||
|
||||
// HN algorithm
|
||||
var newScore = baseScore / Math.pow(ageInHours + 2, f);
|
|
@ -1,9 +1,10 @@
|
|||
Meteor.startup(function () {
|
||||
var scoreInterval = Settings.get("scoreUpdateInterval") || 30;
|
||||
var scoreInterval = Telescope.settings.get("scoreUpdateInterval") || 30;
|
||||
if (scoreInterval > 0) {
|
||||
|
||||
// active items get updated every N seconds
|
||||
Meteor.setInterval(function () {
|
||||
|
||||
var updatedPosts = 0;
|
||||
var updatedComments = 0;
|
||||
// console.log('tick ('+scoreInterval+')');
|
|
@ -11,6 +11,11 @@ Package.onUse(function (api) {
|
|||
|
||||
api.use(['nova:core@0.25.7']);
|
||||
|
||||
api.use([
|
||||
'nova:posts@0.25.7',
|
||||
'nova:comments@0.25.7'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
'lib/scoring.js',
|
||||
'lib/vote.js',
|
Loading…
Add table
Reference in a new issue