mirror of
https://github.com/vale981/Vulcan
synced 2025-03-04 17:21:37 -05:00
eslint & clean up code, also fixed some bugs (#1515)
* [eslint] update eslint rules & add .eslintignore to ignore non-ready nova packages * [clean-up] nova-voting * [clean-up] [bug] nova-users: missing user parameter * [clean-up] nova-users * [clean-up] nova-subscribe * [clean-up] nova-settings * [clean-up] nova-rss * [clean-up] [bug] nova-posts: correct UsersRemoveDeletePosts * [clean-up] nova-posts * [clean-up] nova-notifications * [clean-up] [bug] nova-newsletter: no error.message on throw error * [clean-up] nova-newsletter * [clean-up] nova-lib * [clean-up] nova-kadira * [clean-up] nova-inject-data * [clean-up] nova-getting-started * [clean-up] nova-forms * [clean-up] nova-events * [clean-up] [bug] nova-embedly: no FlowRouter * [clean-up] nova-embedly * [clean-up] nova-email-templates * [clean-up] nova-email * [clean-up] nova-debug * [clean-up] nova-core * [clean-up] [bug] nova-comments: correct UsersRemoveDeleteComments * [clean-up] nova-comments * [clean-up] [bug] nova-cloudinary: use Telescope.settings.collection instand * [clean-up] nova-cloudinary * [clean-up] nova-categories * [clean-up] nova-base-components * [clean-up] nova-api * [eslint] extends react recommended * [clean-up] for jsx files * [eslint] extends meteor recommended * i forgot this one little change
This commit is contained in:
parent
99c8d6ef34
commit
464e20a96c
102 changed files with 548 additions and 457 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
packages/_*
|
29
.eslintrc
29
.eslintrc
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended"
|
"eslint:recommended",
|
||||||
|
"plugin:meteor/recommended",
|
||||||
|
"plugin:react/recommended"
|
||||||
],
|
],
|
||||||
"parser": "babel-eslint",
|
"parser": "babel-eslint",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
|
@ -10,7 +12,17 @@
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"babel/generator-star-spacing": 0,
|
"babel/generator-star-spacing": 0,
|
||||||
"babel/new-cap": 1,
|
"babel/new-cap": [1, {
|
||||||
|
"capIsNewExceptions": [
|
||||||
|
"Optional",
|
||||||
|
"OneOf",
|
||||||
|
"Maybe",
|
||||||
|
"MailChimpAPI",
|
||||||
|
"Juice",
|
||||||
|
"Run",
|
||||||
|
"AppComposer"
|
||||||
|
]
|
||||||
|
}],
|
||||||
"babel/array-bracket-spacing": 0,
|
"babel/array-bracket-spacing": 0,
|
||||||
"babel/object-curly-spacing": 0,
|
"babel/object-curly-spacing": 0,
|
||||||
"babel/object-shorthand": 0,
|
"babel/object-shorthand": 0,
|
||||||
|
@ -20,8 +32,14 @@
|
||||||
"key-spacing": 0,
|
"key-spacing": 0,
|
||||||
"no-extra-boolean-cast": 0,
|
"no-extra-boolean-cast": 0,
|
||||||
"no-undef": 1,
|
"no-undef": 1,
|
||||||
"no-unused-vars": 1,
|
"no-unused-vars": [1, {
|
||||||
"no-console": 1
|
"vars": "all",
|
||||||
|
"args": "none",
|
||||||
|
"varsIgnorePattern": "React|PropTypes|Component"
|
||||||
|
}],
|
||||||
|
"no-console": 1,
|
||||||
|
"react/prop-types": 0,
|
||||||
|
"meteor/audit-argument-checks": 0
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
|
@ -32,7 +50,8 @@
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"babel",
|
"babel",
|
||||||
"meteor"
|
"meteor",
|
||||||
|
"react"
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"import/resolver": "meteor"
|
"import/resolver": "meteor"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
The original Newsletter components is defined using an
|
The original Newsletter components is defined using an
|
||||||
ES6 class, so we use the "class foo extends bar" syntax
|
ES6 class, so we use the "class foo extends bar" syntax
|
||||||
to extend it. This way, we can simply redefine the
|
to extend it. This way, we can simply redefine the
|
||||||
render method to change it, while preserving
|
render method to change it, while preserving
|
||||||
all of the class's other methods (other render
|
all of the class's other methods (other render
|
||||||
functions, event handlers, etc.).
|
functions, event handlers, etc.).
|
||||||
|
@ -9,7 +9,7 @@ functions, event handlers, etc.).
|
||||||
|
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage, intlShape } from 'react-intl';
|
import { FormattedMessage /*, intlShape */ } from 'react-intl';
|
||||||
|
|
||||||
class CustomNewsletter extends Telescope.components.Newsletter {
|
class CustomNewsletter extends Telescope.components.Newsletter {
|
||||||
|
|
||||||
|
@ -27,4 +27,4 @@ class CustomNewsletter extends Telescope.components.Newsletter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CustomNewsletter;
|
export default CustomNewsletter;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import Posts from "meteor/nova:posts";
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage, FormattedRelative } from 'react-intl';
|
import { FormattedMessage, FormattedRelative } from 'react-intl';
|
||||||
import { Button } from 'react-bootstrap';
|
|
||||||
import moment from 'moment';
|
|
||||||
import { ModalTrigger } from "meteor/nova:core";
|
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import Posts from "meteor/nova:posts";
|
// import { Button } from 'react-bootstrap';
|
||||||
import Categories from "meteor/nova:categories";
|
// import moment from 'moment';
|
||||||
|
// import { ModalTrigger } from "meteor/nova:core";
|
||||||
|
// import Categories from "meteor/nova:categories";
|
||||||
|
|
||||||
class CustomPostsItem extends Telescope.components.PostsItem {
|
class CustomPostsItem extends Telescope.components.PostsItem {
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class CustomPostsItem extends Telescope.components.PostsItem {
|
||||||
|
|
||||||
const post = this.props.post;
|
const post = this.props.post;
|
||||||
|
|
||||||
let postClass = "posts-item";
|
let postClass = "posts-item";
|
||||||
if (post.sticky) postClass += " posts-sticky";
|
if (post.sticky) postClass += " posts-sticky";
|
||||||
|
|
||||||
// ⭐ custom code starts here ⭐
|
// ⭐ custom code starts here ⭐
|
||||||
|
@ -25,22 +25,22 @@ class CustomPostsItem extends Telescope.components.PostsItem {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={postClass}>
|
<div className={postClass}>
|
||||||
|
|
||||||
<div className="posts-item-vote">
|
<div className="posts-item-vote">
|
||||||
<Telescope.components.Vote post={post} />
|
<Telescope.components.Vote post={post} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
||||||
|
|
||||||
<div className="posts-item-content">
|
<div className="posts-item-content">
|
||||||
|
|
||||||
<h3 className="posts-item-title">
|
<h3 className="posts-item-title">
|
||||||
<Link to={Posts.getLink(post)} className="posts-item-title-link" target={Posts.getLinkTarget(post)}>
|
<Link to={Posts.getLink(post)} className="posts-item-title-link" target={Posts.getLinkTarget(post)}>
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
{this.renderCategories()}
|
{this.renderCategories()}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="posts-item-meta">
|
<div className="posts-item-meta">
|
||||||
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
||||||
<div className="posts-item-date"><FormattedRelative value={post.postedAt}/></div>
|
<div className="posts-item-date"><FormattedRelative value={post.postedAt}/></div>
|
||||||
|
@ -56,13 +56,13 @@ class CustomPostsItem extends Telescope.components.PostsItem {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.renderCommenters()}
|
{this.renderCommenters()}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
CustomPostsItem.propTypes = {
|
CustomPostsItem.propTypes = {
|
||||||
post: React.PropTypes.object.isRequired
|
post: React.PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
@ -71,4 +71,4 @@ CustomPostsItem.contextTypes = {
|
||||||
currentUser: React.PropTypes.object
|
currentUser: React.PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CustomPostsItem;
|
export default CustomPostsItem;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Picker } from 'meteor/meteorhacks:picker';
|
||||||
import { servePostsApi } from './api.js';
|
import { servePostsApi } from './api.js';
|
||||||
|
|
||||||
// for backwards compatibility's sake, accept a "limit" segment
|
// for backwards compatibility's sake, accept a "limit" segment
|
||||||
|
@ -6,4 +7,4 @@ Picker.route('/api/:limit?', function(params, req, res, next) {
|
||||||
params.query.limit = params.limit;
|
params.query.limit = params.limit;
|
||||||
}
|
}
|
||||||
res.end(servePostsApi(params.query));
|
res.end(servePostsApi(params.query));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import NovaForm from "meteor/nova:forms";
|
||||||
|
import Categories from "meteor/nova:categories";
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import NovaForm from "meteor/nova:forms";
|
// import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
|
||||||
import Categories from "meteor/nova:categories";
|
|
||||||
|
|
||||||
class CategoriesEditForm extends Component{
|
class CategoriesEditForm extends Component{
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class CategoriesEditForm extends Component{
|
||||||
|
|
||||||
deleteCategory() {
|
deleteCategory() {
|
||||||
const category = this.props.category;
|
const category = this.props.category;
|
||||||
if (window.confirm(`Delete category “${category.name}”?`)) {
|
if (window.confirm(`Delete category “${category.name}”?`)) {
|
||||||
this.context.actions.call("categories.deleteById", category._id, (error, result) => {
|
this.context.actions.call("categories.deleteById", category._id, (error, result) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
this.context.messages.flash(error.message, "error");
|
this.context.messages.flash(error.message, "error");
|
||||||
|
@ -30,7 +30,7 @@ class CategoriesEditForm extends Component{
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="categories-edit-form">
|
<div className="categories-edit-form">
|
||||||
<NovaForm
|
<NovaForm
|
||||||
document={this.props.category}
|
document={this.props.category}
|
||||||
collection={Categories}
|
collection={Categories}
|
||||||
methodName="categories.edit"
|
methodName="categories.edit"
|
||||||
|
@ -57,4 +57,4 @@ CategoriesEditForm.contextTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = CategoriesEditForm;
|
module.exports = CategoriesEditForm;
|
||||||
export default CategoriesEditForm;
|
export default CategoriesEditForm;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import { /* ModalTrigger, */ ContextPasser } from "meteor/nova:core";
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Button, DropdownButton, MenuItem, Modal } from 'react-bootstrap';
|
import { Button, DropdownButton, MenuItem, Modal } from 'react-bootstrap';
|
||||||
import { /* ModalTrigger, */ ContextPasser } from "meteor/nova:core";
|
|
||||||
import { withRouter } from 'react-router'
|
import { withRouter } from 'react-router'
|
||||||
import { LinkContainer } from 'react-router-bootstrap';
|
import { LinkContainer } from 'react-router-bootstrap';
|
||||||
import Users from 'meteor/nova:users';
|
// import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
// note: cannot use ModalTrigger component because of https://github.com/react-bootstrap/react-bootstrap/issues/1808
|
// note: cannot use ModalTrigger component because of https://github.com/react-bootstrap/react-bootstrap/issues/1808
|
||||||
|
|
||||||
|
@ -36,12 +36,12 @@ class CategoriesList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCategoryEditModal(category, index) {
|
renderCategoryEditModal(category, index) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal key={index} show={this.state.openModal === index+1} onHide={this.closeModal}>
|
<Modal key={index} show={this.state.openModal === index+1} onHide={this.closeModal}>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title><FormattedMessage id="categories.edit"/></Modal.Title>
|
<Modal.Title><FormattedMessage id="categories.edit"/></Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} actions={this.context.actions} closeCallback={this.closeModal}>
|
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} actions={this.context.actions} closeCallback={this.closeModal}>
|
||||||
<Telescope.components.CategoriesEditForm category={category}/>
|
<Telescope.components.CategoriesEditForm category={category}/>
|
||||||
|
@ -52,12 +52,12 @@ class CategoriesList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCategoryNewModal() {
|
renderCategoryNewModal() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal show={this.state.openModal === 0} onHide={this.closeModal}>
|
<Modal show={this.state.openModal === 0} onHide={this.closeModal}>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title><FormattedMessage id="categories.new"/></Modal.Title>
|
<Modal.Title><FormattedMessage id="categories.new"/></Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} closeCallback={this.closeModal}>
|
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} closeCallback={this.closeModal}>
|
||||||
<Telescope.components.CategoriesNewForm/>
|
<Telescope.components.CategoriesNewForm/>
|
||||||
|
@ -82,18 +82,18 @@ class CategoriesList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const categories = this.props.categories;
|
const categories = this.props.categories;
|
||||||
const context = this.context;
|
// const context = this.context;
|
||||||
const currentQuery = _.clone(this.props.router.location.query);
|
const currentQuery = _.clone(this.props.router.location.query);
|
||||||
delete currentQuery.cat;
|
delete currentQuery.cat;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
bsStyle="default"
|
bsStyle="default"
|
||||||
className="categories-list btn-secondary"
|
className="categories-list btn-secondary"
|
||||||
title={<FormattedMessage id="categories"/>}
|
title={<FormattedMessage id="categories"/>}
|
||||||
id="categories-dropdown"
|
id="categories-dropdown"
|
||||||
>
|
>
|
||||||
<div className="category-menu-item dropdown-item">
|
<div className="category-menu-item dropdown-item">
|
||||||
|
@ -115,7 +115,7 @@ class CategoriesList extends Component {
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
CategoriesList.propTypes = {
|
CategoriesList.propTypes = {
|
||||||
categories: React.PropTypes.array
|
categories: React.PropTypes.array
|
||||||
|
@ -128,4 +128,4 @@ CategoriesList.contextTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = withRouter(CategoriesList);
|
module.exports = withRouter(CategoriesList);
|
||||||
export default withRouter(CategoriesList);
|
export default withRouter(CategoriesList);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import Users from 'meteor/nova:users';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { Button, DropdownButton, MenuItem } from 'react-bootstrap';
|
|
||||||
import classNames from "classnames";
|
|
||||||
//import { Messages, ModalTrigger } from 'meteor/nova:core';
|
|
||||||
import { LinkContainer } from 'react-router-bootstrap';
|
import { LinkContainer } from 'react-router-bootstrap';
|
||||||
import { withRouter } from 'react-router'
|
import { withRouter } from 'react-router'
|
||||||
import Users from 'meteor/nova:users';
|
import { /* Button, DropdownButton, */ MenuItem } from 'react-bootstrap';
|
||||||
|
// import classNames from "classnames";
|
||||||
|
// import { Messages, ModalTrigger } from 'meteor/nova:core';
|
||||||
|
|
||||||
class Category extends Component {
|
class Category extends Component {
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class Category extends Component {
|
||||||
|
|
||||||
const {category, index, router} = this.props;
|
const {category, index, router} = this.props;
|
||||||
|
|
||||||
const currentQuery = router.location.query;
|
// const currentQuery = router.location.query;
|
||||||
const currentCategorySlug = router.location.query.cat;
|
const currentCategorySlug = router.location.query.cat;
|
||||||
const newQuery = _.clone(router.location.query);
|
const newQuery = _.clone(router.location.query);
|
||||||
newQuery.cat = category.slug;
|
newQuery.cat = category.slug;
|
||||||
|
@ -34,9 +34,9 @@ class Category extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="category-menu-item dropdown-item">
|
<div className="category-menu-item dropdown-item">
|
||||||
<LinkContainer to={{pathname:"/", query: newQuery}}>
|
<LinkContainer to={{pathname:"/", query: newQuery}}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
eventKey={index+1}
|
eventKey={index+1}
|
||||||
key={category._id}
|
key={category._id}
|
||||||
>
|
>
|
||||||
{currentCategorySlug === category.slug ? <Telescope.components.Icon name="voted"/> : null}
|
{currentCategorySlug === category.slug ? <Telescope.components.Icon name="voted"/> : null}
|
||||||
{category.name}
|
{category.name}
|
||||||
|
@ -60,4 +60,4 @@ Category.contextTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = withRouter(Category);
|
module.exports = withRouter(Category);
|
||||||
export default withRouter(Category);
|
export default withRouter(Category);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
import { intlShape, FormattedMessage, FormattedRelative } from 'react-intl';
|
import { intlShape, FormattedMessage, FormattedRelative } from 'react-intl';
|
||||||
import Users from 'meteor/nova:users';
|
// import moment from 'moment';
|
||||||
|
// import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
class CommentsItem extends Component{
|
class CommentsItem extends Component{
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class CommentsItem extends Component{
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.setState({showEdit: true});
|
this.setState({showEdit: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
editCancelCallback(event) {
|
editCancelCallback(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.setState({showEdit: false});
|
this.setState({showEdit: false});
|
||||||
|
@ -44,11 +44,11 @@ class CommentsItem extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteComment() {
|
deleteComment() {
|
||||||
|
|
||||||
const comment = this.props.comment;
|
const comment = this.props.comment;
|
||||||
const deleteConfirmMessage = this.context.intl.formatMessage({id: "comments.delete_confirm"}, {body: Telescope.utils.trimWords(comment.body, 20)});
|
const deleteConfirmMessage = this.context.intl.formatMessage({id: "comments.delete_confirm"}, {body: Telescope.utils.trimWords(comment.body, 20)});
|
||||||
const deleteSuccessMessage = this.context.intl.formatMessage({id: "comments.delete_success"}, {body: Telescope.utils.trimWords(comment.body, 20)});
|
const deleteSuccessMessage = this.context.intl.formatMessage({id: "comments.delete_success"}, {body: Telescope.utils.trimWords(comment.body, 20)});
|
||||||
|
|
||||||
if (window.confirm(deleteConfirmMessage)) {
|
if (window.confirm(deleteConfirmMessage)) {
|
||||||
this.context.actions.call('comments.deleteById', comment._id, (error, result) => {
|
this.context.actions.call('comments.deleteById', comment._id, (error, result) => {
|
||||||
this.context.messages.flash(deleteSuccessMessage, "success");
|
this.context.messages.flash(deleteSuccessMessage, "success");
|
||||||
|
@ -70,7 +70,7 @@ class CommentsItem extends Component{
|
||||||
<a className="comments-item-reply-link" onClick={this.showReply}>
|
<a className="comments-item-reply-link" onClick={this.showReply}>
|
||||||
<Telescope.components.Icon name="reply"/> <FormattedMessage id="comments.reply"/>
|
<Telescope.components.Icon name="reply"/> <FormattedMessage id="comments.reply"/>
|
||||||
</a> : null}
|
</a> : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +78,12 @@ class CommentsItem extends Component{
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="comments-item-reply">
|
<div className="comments-item-reply">
|
||||||
<Telescope.components.CommentsNew
|
<Telescope.components.CommentsNew
|
||||||
postId={this.props.comment.postId}
|
postId={this.props.comment.postId}
|
||||||
parentComment={this.props.comment}
|
parentComment={this.props.comment}
|
||||||
successCallback={this.replySuccessCallback}
|
successCallback={this.replySuccessCallback}
|
||||||
cancelCallback={this.replyCancelCallback}
|
cancelCallback={this.replyCancelCallback}
|
||||||
type="reply"
|
type="reply"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -92,9 +92,9 @@ class CommentsItem extends Component{
|
||||||
renderEdit() {
|
renderEdit() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Telescope.components.CommentsEdit
|
<Telescope.components.CommentsEdit
|
||||||
comment={this.props.comment}
|
comment={this.props.comment}
|
||||||
successCallback={this.editSuccessCallback}
|
successCallback={this.editSuccessCallback}
|
||||||
cancelCallback={this.editCancelCallback}
|
cancelCallback={this.editCancelCallback}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {injectIntl, FormattedMessage} from 'react-intl';
|
import {/* injectIntl, */ FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
const CommentsList = ({results, hasMore, ready, count, totalCount, loadMore}) => {
|
const CommentsList = ({results, hasMore, ready, count, totalCount, loadMore}) => {
|
||||||
|
|
||||||
|
@ -24,11 +24,11 @@ const CommentsList = ({results, hasMore, ready, count, totalCount, loadMore}) =>
|
||||||
<FormattedMessage id="comments.no_comments"/>
|
<FormattedMessage id="comments.no_comments"/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CommentsList.displayName = "CommentsList";
|
CommentsList.displayName = "CommentsList";
|
||||||
|
|
||||||
module.exports = CommentsList;
|
module.exports = CommentsList;
|
||||||
|
|
|
@ -18,8 +18,8 @@ class CommentsNew extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="comments-new-form">
|
<div className="comments-new-form">
|
||||||
<NovaForm
|
<NovaForm
|
||||||
collection={Comments}
|
collection={Comments}
|
||||||
methodName="comments.new"
|
methodName="comments.new"
|
||||||
prefilledProps={prefilledProps}
|
prefilledProps={prefilledProps}
|
||||||
successCallback={this.props.successCallback}
|
successCallback={this.props.successCallback}
|
||||||
|
@ -30,7 +30,7 @@ class CommentsNew extends Component {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
CommentsNew.propTypes = {
|
CommentsNew.propTypes = {
|
||||||
postId: React.PropTypes.string.isRequired,
|
postId: React.PropTypes.string.isRequired,
|
||||||
|
@ -46,4 +46,4 @@ CommentsNew.contextTypes = {
|
||||||
currentUser: React.PropTypes.object
|
currentUser: React.PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = CommentsNew;
|
module.exports = CommentsNew;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import React, { PropTypes, Component } from 'react';
|
||||||
class CommentsNode extends Component {
|
class CommentsNode extends Component {
|
||||||
|
|
||||||
renderComment(comment) {
|
renderComment(comment) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Telescope.components.CommentsItem comment={comment} key={comment._id} />
|
<Telescope.components.CommentsItem comment={comment} key={comment._id} />
|
||||||
)
|
)
|
||||||
|
@ -22,7 +22,7 @@ class CommentsNode extends Component {
|
||||||
|
|
||||||
const comment = this.props.comment;
|
const comment = this.props.comment;
|
||||||
const children = this.props.comment.childrenResults;
|
const children = this.props.comment.childrenResults;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="comments-node">
|
<div className="comments-node">
|
||||||
{this.renderComment(comment)}
|
{this.renderComment(comment)}
|
||||||
|
@ -31,7 +31,7 @@ class CommentsNode extends Component {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
CommentsNode.propTypes = {
|
CommentsNode.propTypes = {
|
||||||
comment: React.PropTypes.object.isRequired, // the current comment
|
comment: React.PropTypes.object.isRequired, // the current comment
|
||||||
|
@ -41,4 +41,4 @@ CommentsNode.contextTypes = {
|
||||||
currentUser: React.PropTypes.object, // the current user
|
currentUser: React.PropTypes.object, // the current user
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = CommentsNode;
|
module.exports = CommentsNode;
|
||||||
|
|
|
@ -10,10 +10,10 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildContext() {
|
getChildContext() {
|
||||||
|
|
||||||
const messages = Telescope.strings[this.getLocale()] || {};
|
const messages = Telescope.strings[this.getLocale()] || {};
|
||||||
const intlProvider = new IntlProvider({locale: this.getLocale()}, messages);
|
const intlProvider = new IntlProvider({locale: this.getLocale()}, messages);
|
||||||
|
|
||||||
const {intl} = intlProvider.getChildContext();
|
const {intl} = intlProvider.getChildContext();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -29,8 +29,8 @@ class App extends Component {
|
||||||
return (
|
return (
|
||||||
<IntlProvider locale={this.getLocale()} messages={Telescope.strings[this.getLocale()]}>
|
<IntlProvider locale={this.getLocale()} messages={Telescope.strings[this.getLocale()]}>
|
||||||
{
|
{
|
||||||
this.props.ready ?
|
this.props.ready ?
|
||||||
<Telescope.components.Layout>{this.props.children}</Telescope.components.Layout>
|
<Telescope.components.Layout>{this.props.children}</Telescope.components.Layout>
|
||||||
: <Telescope.components.AppLoading />
|
: <Telescope.components.AppLoading />
|
||||||
}
|
}
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
|
@ -56,4 +56,4 @@ App.childContextTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AppComposer(App);
|
module.exports = AppComposer(App);
|
||||||
export default AppComposer(App);
|
export default AppComposer(App);
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Newsletter extends Component {
|
||||||
subscribeEmail(data) {
|
subscribeEmail(data) {
|
||||||
this.context.actions.call("newsletter.addEmail", data.email, (error, result) => {
|
this.context.actions.call("newsletter.addEmail", data.email, (error, result) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
this.context.messages.flash(error.message, "error");
|
this.context.messages.flash(error.message, "error");
|
||||||
} else {
|
} else {
|
||||||
this.successCallbackSubscription(result);
|
this.successCallbackSubscription(result);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Button } from 'react-bootstrap';
|
import { Button } from 'react-bootstrap';
|
||||||
import { Messages } from 'meteor/nova:core';
|
// import { Messages } from 'meteor/nova:core';
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
class NewsletterButton extends Component {
|
class NewsletterButton extends Component {
|
||||||
|
@ -15,7 +15,7 @@ class NewsletterButton extends Component {
|
||||||
'newsletter.removeUser' : 'newsletter.addUser';
|
'newsletter.removeUser' : 'newsletter.addUser';
|
||||||
this.context.actions.call(action, this.props.user, (error, result) => {
|
this.context.actions.call(action, this.props.user, (error, result) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
this.context.messages.flash(error.message, "error");
|
this.context.messages.flash(error.message, "error");
|
||||||
} else {
|
} else {
|
||||||
this.props.successCallback(result);
|
this.props.successCallback(result);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { T9n } from 'meteor/softwarerero:accounts-t9n';
|
||||||
|
|
||||||
// import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
|
// import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
|
||||||
// checkNpmVersions({
|
// checkNpmVersions({
|
||||||
|
@ -16,4 +17,4 @@ Users.avatar.setOptions({
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/softwarerero/meteor-accounts-t9n
|
// https://github.com/softwarerero/meteor-accounts-t9n
|
||||||
T9n.setLanguage(Telescope.settings.get("locale", "en"));
|
T9n.setLanguage(Telescope.settings.get("locale", "en"));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Telescope from "meteor/nova:lib";
|
import Telescope from "meteor/nova:lib";
|
||||||
import React, { PropTypes, Component } from "react";
|
import React, { PropTypes, Component } from "react";
|
||||||
import { Button } from "react-bootstrap";
|
// import { Button } from "react-bootstrap";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
|
||||||
import { ListContainer } from "meteor/utilities:react-list-container";
|
|
||||||
import moment from 'moment';
|
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
|
import { ListContainer } from "meteor/utilities:react-list-container";
|
||||||
|
import React, { PropTypes, Component } from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
class PostsDay extends Component {
|
class PostsDay extends Component {
|
||||||
|
|
||||||
|
@ -19,19 +19,19 @@ class PostsDay extends Component {
|
||||||
listId: `posts.list.${moment(date).format("YYYY-MM-DD")}`
|
listId: `posts.list.${moment(date).format("YYYY-MM-DD")}`
|
||||||
};
|
};
|
||||||
|
|
||||||
({selector, options} = Posts.parameters.get(terms));
|
const {selector, options} = Posts.parameters.get(terms);
|
||||||
|
|
||||||
const postsPerPage = Telescope.settings.get("postsPerPage", 10);
|
const postsPerPage = Telescope.settings.get("postsPerPage", 10);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="posts-day">
|
<div className="posts-day">
|
||||||
<h4 className="posts-day-heading">{moment(date).format("dddd, MMMM Do YYYY")}</h4>
|
<h4 className="posts-day-heading">{moment(date).format("dddd, MMMM Do YYYY")}</h4>
|
||||||
<ListContainer
|
<ListContainer
|
||||||
collection={Posts}
|
collection={Posts}
|
||||||
publication="posts.list"
|
publication="posts.list"
|
||||||
selector={selector}
|
selector={selector}
|
||||||
options={options}
|
options={options}
|
||||||
terms={terms}
|
terms={terms}
|
||||||
joins={Posts.getJoins()}
|
joins={Posts.getJoins()}
|
||||||
component={Telescope.components.PostsList}
|
component={Telescope.components.PostsList}
|
||||||
componentProps={{showHeader: false}}
|
componentProps={{showHeader: false}}
|
||||||
|
@ -51,4 +51,4 @@ PostsDay.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = PostsDay;
|
module.exports = PostsDay;
|
||||||
export default PostsDay;
|
export default PostsDay;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
|
||||||
import { FormattedMessage, intlShape } from 'react-intl';
|
|
||||||
import NovaForm from "meteor/nova:forms";
|
import NovaForm from "meteor/nova:forms";
|
||||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||||
//import { Messages } from "meteor/nova:core";
|
|
||||||
//import Actions from "../actions.js";
|
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
import Users from 'meteor/nova:users';
|
import React, { PropTypes, Component } from 'react';
|
||||||
|
import { FormattedMessage, intlShape } from 'react-intl';
|
||||||
|
// import { Messages } from "meteor/nova:core";
|
||||||
|
// import Actions from "../actions.js";
|
||||||
|
// import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
class PostsEditForm extends Component{
|
class PostsEditForm extends Component{
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class PostsEditForm extends Component{
|
||||||
const deletePostConfirm = this.context.intl.formatMessage({id: "posts.delete_confirm"}, {title: post.title});
|
const deletePostConfirm = this.context.intl.formatMessage({id: "posts.delete_confirm"}, {title: post.title});
|
||||||
const deletePostSuccess = this.context.intl.formatMessage({id: "posts.delete_success"}, {title: post.title});
|
const deletePostSuccess = this.context.intl.formatMessage({id: "posts.delete_success"}, {title: post.title});
|
||||||
|
|
||||||
if (window.confirm(deletePostConfirm)) {
|
if (window.confirm(deletePostConfirm)) {
|
||||||
this.context.actions.call('posts.remove', post._id, (error, result) => {
|
this.context.actions.call('posts.remove', post._id, (error, result) => {
|
||||||
this.context.messages.flash(deletePostSuccess, "success");
|
this.context.messages.flash(deletePostSuccess, "success");
|
||||||
this.context.events.track("post deleted", {'_id': post._id});
|
this.context.events.track("post deleted", {'_id': post._id});
|
||||||
|
@ -41,13 +41,13 @@ class PostsEditForm extends Component{
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="posts-edit-form">
|
<div className="posts-edit-form">
|
||||||
{this.renderAdminArea()}
|
{this.renderAdminArea()}
|
||||||
<DocumentContainer
|
<DocumentContainer
|
||||||
collection={Posts}
|
collection={Posts}
|
||||||
publication="posts.single"
|
publication="posts.single"
|
||||||
selector={{_id: this.props.post._id}}
|
selector={{_id: this.props.post._id}}
|
||||||
terms={{_id: this.props.post._id}}
|
terms={{_id: this.props.post._id}}
|
||||||
joins={Posts.getJoins()}
|
joins={Posts.getJoins()}
|
||||||
|
@ -57,7 +57,7 @@ class PostsEditForm extends Component{
|
||||||
collection: Posts,
|
collection: Posts,
|
||||||
currentUser: this.context.currentUser,
|
currentUser: this.context.currentUser,
|
||||||
methodName: "posts.edit",
|
methodName: "posts.edit",
|
||||||
successCallback: (post) => {
|
successCallback: (post) => {
|
||||||
this.context.messages.flash(this.context.intl.formatMessage({id: "posts.edit_success"}, {title: post.title}), 'success')
|
this.context.messages.flash(this.context.intl.formatMessage({id: "posts.edit_success"}, {title: post.title}), 'success')
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -82,4 +82,4 @@ PostsEditForm.contextTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = PostsEditForm;
|
module.exports = PostsEditForm;
|
||||||
export default PostsEditForm;
|
export default PostsEditForm;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
|
import { ListContainer /* , DocumentContainer */ } from "meteor/utilities:react-list-container";
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
|
|
||||||
class PostsHome extends Component {
|
class PostsHome extends Component {
|
||||||
|
@ -8,19 +8,19 @@ class PostsHome extends Component {
|
||||||
getDefaultView() {
|
getDefaultView() {
|
||||||
return {view: 'top'}
|
return {view: 'top'}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const params = {...this.getDefaultView(), ...this.props.location.query, listId: "posts.list.main"};
|
const params = {...this.getDefaultView(), ...this.props.location.query, listId: "posts.list.main"};
|
||||||
const {selector, options} = Posts.parameters.get(params);
|
const {selector, options} = Posts.parameters.get(params);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListContainer
|
<ListContainer
|
||||||
collection={Posts}
|
collection={Posts}
|
||||||
publication="posts.list"
|
publication="posts.list"
|
||||||
selector={selector}
|
selector={selector}
|
||||||
options={options}
|
options={options}
|
||||||
terms={params}
|
terms={params}
|
||||||
joins={Posts.getJoins()}
|
joins={Posts.getJoins()}
|
||||||
component={Telescope.components.PostsList}
|
component={Telescope.components.PostsList}
|
||||||
cacheSubscription={true}
|
cacheSubscription={true}
|
||||||
|
@ -29,6 +29,6 @@ class PostsHome extends Component {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = PostsHome;
|
module.exports = PostsHome;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import { ModalTrigger } from "meteor/nova:core";
|
||||||
|
import Posts from "meteor/nova:posts";
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage, FormattedRelative } from 'react-intl';
|
import { FormattedMessage, FormattedRelative } from 'react-intl';
|
||||||
import { Button } from 'react-bootstrap';
|
|
||||||
import moment from 'moment';
|
|
||||||
import { ModalTrigger } from "meteor/nova:core";
|
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import Posts from "meteor/nova:posts";
|
// import { Button } from 'react-bootstrap';
|
||||||
import Users from 'meteor/nova:users';
|
// import moment from 'moment';
|
||||||
|
// import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
class PostsItem extends Component {
|
class PostsItem extends Component {
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@ class PostsItem extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const post = this.props.post;
|
const post = this.props.post;
|
||||||
|
|
||||||
let postClass = "posts-item";
|
let postClass = "posts-item";
|
||||||
if (post.sticky) postClass += " posts-sticky";
|
if (post.sticky) postClass += " posts-sticky";
|
||||||
|
|
||||||
// console.log(post)
|
// console.log(post)
|
||||||
|
@ -45,22 +45,22 @@ class PostsItem extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={postClass}>
|
<div className={postClass}>
|
||||||
|
|
||||||
<div className="posts-item-vote">
|
<div className="posts-item-vote">
|
||||||
<Telescope.components.Vote post={post} />
|
<Telescope.components.Vote post={post} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
||||||
|
|
||||||
<div className="posts-item-content">
|
<div className="posts-item-content">
|
||||||
|
|
||||||
<h3 className="posts-item-title">
|
<h3 className="posts-item-title">
|
||||||
<Link to={Posts.getLink(post)} className="posts-item-title-link" target={Posts.getLinkTarget(post)}>
|
<Link to={Posts.getLink(post)} className="posts-item-title-link" target={Posts.getLinkTarget(post)}>
|
||||||
{post.title}
|
{post.title}
|
||||||
</Link>
|
</Link>
|
||||||
{this.renderCategories()}
|
{this.renderCategories()}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div className="posts-item-meta">
|
<div className="posts-item-meta">
|
||||||
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
||||||
<div className="posts-item-date">{post.postedAt ? <FormattedRelative value={post.postedAt}/> : <FormattedMessage id="posts.dateNotDefined"/>}</div>
|
<div className="posts-item-date">{post.postedAt ? <FormattedRelative value={post.postedAt}/> : <FormattedMessage id="posts.dateNotDefined"/>}</div>
|
||||||
|
@ -76,13 +76,13 @@ class PostsItem extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.renderCommenters()}
|
{this.renderCommenters()}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
PostsItem.propTypes = {
|
PostsItem.propTypes = {
|
||||||
post: React.PropTypes.object.isRequired
|
post: React.PropTypes.object.isRequired
|
||||||
}
|
}
|
||||||
|
@ -92,4 +92,4 @@ PostsItem.contextTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = PostsItem;
|
module.exports = PostsItem;
|
||||||
export default PostsItem;
|
export default PostsItem;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage, intlShape } from 'react-intl';
|
import { FormattedMessage, intlShape } from 'react-intl';
|
||||||
import { Button, ButtonGroup, DropdownButton, MenuItem } from 'react-bootstrap';
|
import { /* Button, ButtonGroup, */ DropdownButton, MenuItem } from 'react-bootstrap';
|
||||||
import { LinkContainer } from 'react-router-bootstrap';
|
import { LinkContainer } from 'react-router-bootstrap';
|
||||||
import { withRouter } from 'react-router'
|
import { withRouter } from 'react-router'
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
@ -9,7 +9,7 @@ const PostsViews = (props, context) => {
|
||||||
|
|
||||||
let views = ["top", "new", "best"];
|
let views = ["top", "new", "best"];
|
||||||
const adminViews = ["pending", "rejected", "scheduled"];
|
const adminViews = ["pending", "rejected", "scheduled"];
|
||||||
|
|
||||||
if (Users.canDo(context.currentUser, "posts.edit.all")) {
|
if (Users.canDo(context.currentUser, "posts.edit.all")) {
|
||||||
views = views.concat(adminViews);
|
views = views.concat(adminViews);
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,13 @@ const PostsViews = (props, context) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="posts-views">
|
<div className="posts-views">
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
bsStyle="default"
|
bsStyle="default"
|
||||||
className="views btn-secondary"
|
className="views btn-secondary"
|
||||||
title={context.intl.formatMessage({id: "posts.view"})}
|
title={context.intl.formatMessage({id: "posts.view"})}
|
||||||
id="views-dropdown"
|
id="views-dropdown"
|
||||||
>
|
>
|
||||||
{views.map(view =>
|
{views.map(view =>
|
||||||
<LinkContainer key={view} to={{pathname: "/", query: {...query, view: view}}} /*to={}*/ className="dropdown-item">
|
<LinkContainer key={view} to={{pathname: "/", query: {...query, view: view}}} /*to={}*/ className="dropdown-item">
|
||||||
<MenuItem>
|
<MenuItem>
|
||||||
<FormattedMessage id={"posts."+view}/>
|
<FormattedMessage id={"posts."+view}/>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Accounts } from 'meteor/std:accounts-ui';
|
||||||
const UsersAccountForm = () => {
|
const UsersAccountForm = () => {
|
||||||
return (
|
return (
|
||||||
<Accounts.ui.LoginForm />
|
<Accounts.ui.LoginForm />
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = UsersAccountForm;
|
module.exports = UsersAccountForm;
|
||||||
|
@ -23,12 +23,12 @@ class AccountsButton extends Accounts.ui.Button {
|
||||||
render () {
|
render () {
|
||||||
const {label, href, type, disabled, className, onClick} = this.props;
|
const {label, href, type, disabled, className, onClick} = this.props;
|
||||||
if (type === 'link') {
|
if (type === 'link') {
|
||||||
return <a href={ href } className={ className } onClick={ onClick }>{ label }</a>;
|
return <a href={ href } className={ className } onClick={ onClick }>{ label }</a>;
|
||||||
}
|
}
|
||||||
return <Button
|
return <Button
|
||||||
bsStyle="primary"
|
bsStyle="primary"
|
||||||
className={ className }
|
className={ className }
|
||||||
type={ type }
|
type={ type }
|
||||||
disabled={ disabled }
|
disabled={ disabled }
|
||||||
onClick={ onClick }>{ label }
|
onClick={ onClick }>{ label }
|
||||||
</Button>;
|
</Button>;
|
||||||
|
@ -44,13 +44,13 @@ class AccountsField extends Accounts.ui.Field {
|
||||||
onChange({ target: { value: this.input.value } })
|
onChange({ target: { value: this.input.value } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { id, hint, label, type = 'text', onChange, className = "field", defaultValue = "" } = this.props;
|
const { id, hint, /* label, */ type = 'text', onChange, className = "field", defaultValue = "" } = this.props;
|
||||||
const { mount = true } = this.state;
|
const { mount = true } = this.state;
|
||||||
return mount ? (
|
return mount ? (
|
||||||
<div className={ className }>
|
<div className={ className }>
|
||||||
<FormControl id={ id } type={ type } onChange={ onChange } placeholder={ hint } defaultValue={ defaultValue } />
|
<FormControl id={ id } type={ type } onChange={ onChange } placeholder={ hint } defaultValue={ defaultValue } />
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
}
|
}
|
||||||
|
@ -99,4 +99,4 @@ class AccountsField extends Accounts.ui.Field {
|
||||||
Accounts.ui.Button = AccountsButton;
|
Accounts.ui.Button = AccountsButton;
|
||||||
Accounts.ui.Field = AccountsField;
|
Accounts.ui.Field = AccountsField;
|
||||||
// Accounts.ui.SocialButtons = AccountsSocialButtons;
|
// Accounts.ui.SocialButtons = AccountsSocialButtons;
|
||||||
// Accounts.ui.PasswordOrService = AccountsPasswordOrService;
|
// Accounts.ui.PasswordOrService = AccountsPasswordOrService;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Dropdown, Button } from 'react-bootstrap';
|
import { Dropdown /* , Button */ } from 'react-bootstrap';
|
||||||
|
|
||||||
const UsersAccountMenu = () => {
|
const UsersAccountMenu = () => {
|
||||||
|
|
||||||
|
@ -14,10 +14,10 @@ const UsersAccountMenu = () => {
|
||||||
<Telescope.components.UsersAccountForm />
|
<Telescope.components.UsersAccountForm />
|
||||||
</Dropdown.Menu>
|
</Dropdown.Menu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
UsersAccountMenu.displayName = "UsersAccountMenu";
|
UsersAccountMenu.displayName = "UsersAccountMenu";
|
||||||
|
|
||||||
module.exports = UsersAccountMenu;
|
module.exports = UsersAccountMenu;
|
||||||
export default UsersAccountMenu;
|
export default UsersAccountMenu;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage, intlShape } from 'react-intl';
|
import { FormattedMessage, intlShape } from 'react-intl';
|
||||||
import { Row, Col } from 'react-bootstrap';
|
// import { Row, Col } from 'react-bootstrap';
|
||||||
import NovaForm from "meteor/nova:forms";
|
import NovaForm from "meteor/nova:forms";
|
||||||
//import { Messages } from "meteor/nova:core";
|
//import { Messages } from "meteor/nova:core";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
@ -9,21 +9,21 @@ import Users from 'meteor/nova:users';
|
||||||
const UsersEdit = (props, context) => {
|
const UsersEdit = (props, context) => {
|
||||||
|
|
||||||
const user = props.user;
|
const user = props.user;
|
||||||
const currentUser = props.currentUser;
|
// const currentUser = props.currentUser;
|
||||||
|
|
||||||
//const label = `Edit profile for ${Users.getDisplayName(user)}`;
|
//const label = `Edit profile for ${Users.getDisplayName(user)}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Telescope.components.CanDo
|
<Telescope.components.CanDo
|
||||||
action="users.edit"
|
action="users.edit"
|
||||||
document={user}
|
document={user}
|
||||||
displayNoPermissionMessage={true}
|
displayNoPermissionMessage={true}
|
||||||
>
|
>
|
||||||
<div className="page users-edit-form">
|
<div className="page users-edit-form">
|
||||||
<h2 className="page-title users-edit-form-title"><FormattedMessage id="users.edit_account"/></h2>
|
<h2 className="page-title users-edit-form-title"><FormattedMessage id="users.edit_account"/></h2>
|
||||||
<NovaForm
|
<NovaForm
|
||||||
collection={Users}
|
collection={Users}
|
||||||
document={user}
|
document={user}
|
||||||
methodName="users.edit"
|
methodName="users.edit"
|
||||||
successCallback={(user)=>{
|
successCallback={(user)=>{
|
||||||
context.messages.flash(context.intl.formatMessage({id: "users.edit_success"}, {name: Users.getDisplayName(user)}), 'success')
|
context.messages.flash(context.intl.formatMessage({id: "users.edit_success"}, {name: Users.getDisplayName(user)}), 'success')
|
||||||
|
@ -34,7 +34,7 @@ const UsersEdit = (props, context) => {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
UsersEdit.propTypes = {
|
UsersEdit.propTypes = {
|
||||||
user: React.PropTypes.object.isRequired,
|
user: React.PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -48,4 +48,4 @@ UsersEdit.contextTypes = {
|
||||||
UsersEdit.displayName = "UsersEdit";
|
UsersEdit.displayName = "UsersEdit";
|
||||||
|
|
||||||
module.exports = UsersEdit;
|
module.exports = UsersEdit;
|
||||||
export default UsersEdit;
|
export default UsersEdit;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Accounts, STATES } from 'meteor/std:accounts-ui';
|
import { Accounts, STATES } from 'meteor/std:accounts-ui';
|
||||||
|
import { T9n } from 'meteor/softwarerero:accounts-t9n';
|
||||||
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
|
||||||
class UsersResetPassword extends Component {
|
class UsersResetPassword extends Component {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React from 'react';
|
|
||||||
import {mount} from 'react-mounter';
|
|
||||||
import { Messages } from 'meteor/nova:core';
|
import { Messages } from 'meteor/nova:core';
|
||||||
import { IndexRoute, Route, useRouterHistory, browserHistory, createMemoryHistory } from 'react-router';
|
|
||||||
import { ReactRouterSSR } from 'meteor/reactrouter:react-router-ssr';
|
|
||||||
import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
|
|
||||||
// import useNamedRoutes from 'use-named-routes';
|
|
||||||
import createBrowserHistory from 'history/lib/createBrowserHistory';
|
|
||||||
import Events from "meteor/nova:events";
|
import Events from "meteor/nova:events";
|
||||||
|
import { ReactRouterSSR } from 'meteor/reactrouter:react-router-ssr';
|
||||||
|
import React from 'react';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Cookie from 'react-cookie';
|
import Cookie from 'react-cookie';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
// import {mount} from 'react-mounter';
|
||||||
|
// import { IndexRoute, Route, useRouterHistory, browserHistory, createMemoryHistory } from 'react-router';
|
||||||
|
// import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
|
||||||
|
// import useNamedRoutes from 'use-named-routes';
|
||||||
|
// import createBrowserHistory from 'history/lib/createBrowserHistory';
|
||||||
|
|
||||||
Telescope.routes.indexRoute = { name: "posts.list", component: Telescope.components.PostsHome };
|
Telescope.routes.indexRoute = { name: "posts.list", component: Telescope.components.PostsHome };
|
||||||
|
|
||||||
|
@ -33,13 +33,13 @@ Meteor.startup(() => {
|
||||||
childRoutes: Telescope.routes.routes
|
childRoutes: Telescope.routes.routes
|
||||||
}
|
}
|
||||||
|
|
||||||
let history;
|
// let history;
|
||||||
|
|
||||||
const clientOptions = {
|
const clientOptions = {
|
||||||
renderHook: ReactDOM.render,
|
renderHook: ReactDOM.render,
|
||||||
props: {
|
props: {
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
Events.analyticsRequest();
|
Events.analyticsRequest();
|
||||||
Messages.clearSeen();
|
Messages.clearSeen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,15 +48,15 @@ Meteor.startup(() => {
|
||||||
const serverOptions = {
|
const serverOptions = {
|
||||||
htmlHook: (html) => {
|
htmlHook: (html) => {
|
||||||
const head = Helmet.rewind();
|
const head = Helmet.rewind();
|
||||||
return html.replace('<head>', '<head>'+ head.title + head.meta + head.link);
|
return html.replace('<head>', '<head>'+ head.title + head.meta + head.link);
|
||||||
},
|
},
|
||||||
preRender: (req, res) => {
|
preRender: (req, res) => {
|
||||||
Cookie.plugToRequest(req, res);
|
Cookie.plugToRequest(req, res);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactRouterSSR.Run(AppRoutes, clientOptions, serverOptions);
|
ReactRouterSSR.Run(AppRoutes, clientOptions, serverOptions);
|
||||||
|
|
||||||
// note: we did like this at first
|
// note: we did like this at first
|
||||||
// if (Meteor.isClient) {
|
// if (Meteor.isClient) {
|
||||||
// history = useNamedRoutes(useRouterHistory(createBrowserHistory))({ routes: AppRoutes });
|
// history = useNamedRoutes(useRouterHistory(createBrowserHistory))({ routes: AppRoutes });
|
||||||
|
@ -66,4 +66,4 @@ Meteor.startup(() => {
|
||||||
// }
|
// }
|
||||||
// ReactRouterSSR.Run(AppRoutes, {historyHook: () => history}, {historyHook: () => history});
|
// ReactRouterSSR.Run(AppRoutes, {historyHook: () => history}, {historyHook: () => history});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,8 @@ Categories.getParents = function (category) {
|
||||||
categoriesArray.push(parent);
|
categoriesArray.push(parent);
|
||||||
recurse(parent);
|
recurse(parent);
|
||||||
}
|
}
|
||||||
}(category);
|
};
|
||||||
|
getParents(category);
|
||||||
|
|
||||||
return categoriesArray;
|
return categoriesArray;
|
||||||
};
|
};
|
||||||
|
@ -37,7 +38,8 @@ Categories.getChildren = function (category) {
|
||||||
categoriesArray = categoriesArray.concat(children);
|
categoriesArray = categoriesArray.concat(children);
|
||||||
recurse(children);
|
recurse(children);
|
||||||
}
|
}
|
||||||
}([category]);
|
};
|
||||||
|
getChildren([category]);
|
||||||
|
|
||||||
return categoriesArray;
|
return categoriesArray;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Categories from "./collection.js";
|
import Categories from "./collection.js";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
const canInsert = user => Users.canDo(user, "categories.new");
|
const canInsert = user => Users.canDo(user, "categories.new");
|
||||||
const canEdit = user => Users.canDo(user, "categories.edit.all");
|
const canEdit = user => Users.canDo(user, "categories.edit.all");
|
||||||
|
@ -79,7 +80,7 @@ Telescope.settings.collection.addField([
|
||||||
optional: true,
|
optional: true,
|
||||||
form: {
|
form: {
|
||||||
group: 'categories',
|
group: 'categories',
|
||||||
instructions: 'Let users filter by one or multiple categories at a time.',
|
instructions: 'Let users filter by one or multiple categories at a time.',
|
||||||
options: function () {
|
options: function () {
|
||||||
return [
|
return [
|
||||||
{value: "single", label: "categories_behavior_one_at_a_time"},
|
{value: "single", label: "categories_behavior_one_at_a_time"},
|
||||||
|
@ -100,4 +101,4 @@ Telescope.settings.collection.addField([
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -19,7 +19,7 @@ if (Meteor.settings && Meteor.settings.categories) {
|
||||||
} else {
|
} else {
|
||||||
// if not, create it
|
// if not, create it
|
||||||
Categories.insert(category);
|
Categories.insert(category);
|
||||||
console.log(`// Creating category “${category.name}”`);
|
console.log(`// Creating category “${category.name}”`); // eslint-disable-line
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import Posts from "meteor/nova:posts";
|
// import Posts from "meteor/nova:posts";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
import Categories from "../collection.js";
|
import Categories from "../collection.js";
|
||||||
|
|
||||||
Meteor.publish('categories', function() {
|
Meteor.publish('categories', function() {
|
||||||
|
|
||||||
const currentUser = this.userId && Users.findOne(this.userId);
|
const currentUser = this.userId && Users.findOne(this.userId);
|
||||||
|
|
||||||
if(Users.canDo(currentUser, "posts.view.approved.all")){
|
if(Users.canDo(currentUser, "posts.view.approved.all")){
|
||||||
|
|
||||||
var categories = Categories.find({}, {fields: Categories.publishedFields.list});
|
var categories = Categories.find({}, {fields: Categories.publishedFields.list});
|
||||||
|
|
||||||
|
/*
|
||||||
var publication = this;
|
var publication = this;
|
||||||
|
|
||||||
categories.forEach(function (category) {
|
categories.forEach(function (category) {
|
||||||
|
@ -17,8 +19,9 @@ Meteor.publish('categories', function() {
|
||||||
var cursor = Posts.find({$and: [{categories: {$in: categoryIds}}, {status: Posts.config.STATUS_APPROVED}]});
|
var cursor = Posts.find({$and: [{categories: {$in: categoryIds}}, {status: Posts.config.STATUS_APPROVED}]});
|
||||||
// Counts.publish(publication, category.getCounterName(), cursor, { noReady: true });
|
// Counts.publish(publication, category.getCounterName(), cursor, { noReady: true });
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
import PublicationUtils from 'meteor/utilities:smart-publications';
|
import PublicationUtils from 'meteor/utilities:smart-publications';
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ Posts.addField([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (typeof Settings !== "undefined") {
|
if (typeof Settings !== "undefined") {
|
||||||
Settings.addField([
|
Telescope.settings.collection.addField([
|
||||||
{
|
{
|
||||||
fieldName: 'cloudinaryCloudName',
|
fieldName: 'cloudinaryCloudName',
|
||||||
fieldSchema: {
|
fieldSchema: {
|
||||||
|
|
|
@ -14,7 +14,7 @@ Cloudinary.config({
|
||||||
});
|
});
|
||||||
|
|
||||||
const CloudinaryUtils = {
|
const CloudinaryUtils = {
|
||||||
|
|
||||||
// send an image URL to Cloudinary and get a cloudinary result object in return
|
// send an image URL to Cloudinary and get a cloudinary result object in return
|
||||||
uploadImage(imageUrl) {
|
uploadImage(imageUrl) {
|
||||||
try {
|
try {
|
||||||
|
@ -26,8 +26,8 @@ const CloudinaryUtils = {
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("// Cloudinary upload failed for URL: "+imageUrl);
|
console.log("// Cloudinary upload failed for URL: "+imageUrl); // eslint-disable-line
|
||||||
console.log(error.stack);
|
console.log(error.stack); // eslint-disable-line
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ const CloudinaryUtils = {
|
||||||
getUrls(cloudinaryId) {
|
getUrls(cloudinaryId) {
|
||||||
return Telescope.settings.get("cloudinaryFormats").map(format => {
|
return Telescope.settings.get("cloudinaryFormats").map(format => {
|
||||||
const url = Cloudinary.url(cloudinaryId, {
|
const url = Cloudinary.url(cloudinaryId, {
|
||||||
width: format.width,
|
width: format.width,
|
||||||
height: format.height,
|
height: format.height,
|
||||||
crop: 'fill',
|
crop: 'fill',
|
||||||
sign_url: true,
|
sign_url: true,
|
||||||
fetch_format: "auto",
|
fetch_format: "auto",
|
||||||
|
@ -56,7 +56,7 @@ Meteor.methods({
|
||||||
if (Users.isAdmin(Meteor.user())) {
|
if (Users.isAdmin(Meteor.user())) {
|
||||||
thumbnailUrl = typeof thumbnailUrl === "undefined" ? "http://www.telescopeapp.org/images/logo.png" : thumbnailUrl;
|
thumbnailUrl = typeof thumbnailUrl === "undefined" ? "http://www.telescopeapp.org/images/logo.png" : thumbnailUrl;
|
||||||
const data = CloudinaryUtils.uploadImage(thumbnailUrl);
|
const data = CloudinaryUtils.uploadImage(thumbnailUrl);
|
||||||
console.log(data);
|
console.log(data); // eslint-disable-line
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cachePostThumbnails: function (limit = 20) {
|
cachePostThumbnails: function (limit = 20) {
|
||||||
|
@ -71,16 +71,16 @@ Meteor.methods({
|
||||||
postsWithUncachedThumbnails.forEach(Meteor.bindEnvironment((post, index) => {
|
postsWithUncachedThumbnails.forEach(Meteor.bindEnvironment((post, index) => {
|
||||||
|
|
||||||
Meteor.setTimeout(function () {
|
Meteor.setTimeout(function () {
|
||||||
console.log(`// ${index}. Caching thumbnail for post “${post.title}” (_id: ${post._id})`);
|
console.log(`// ${index}. Caching thumbnail for post “${post.title}” (_id: ${post._id})`); // eslint-disable-line
|
||||||
|
|
||||||
const data = CloudinaryUtils.uploadImage(post.thumbnailUrl);
|
const data = CloudinaryUtils.uploadImage(post.thumbnailUrl);
|
||||||
Posts.update(post._id, {$set:{
|
Posts.update(post._id, {$set:{
|
||||||
cloudinaryId: data.cloudinaryId,
|
cloudinaryId: data.cloudinaryId,
|
||||||
cloudinaryUrls: data.urls
|
cloudinaryUrls: data.urls
|
||||||
}});
|
}});
|
||||||
|
|
||||||
}, index * 1000);
|
}, index * 1000);
|
||||||
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ Telescope.callbacks.add("posts.new.async", cachePostThumbnailOnSubmit);
|
||||||
function cachePostThumbnailOnEdit (newPost, oldPost) {
|
function cachePostThumbnailOnEdit (newPost, oldPost) {
|
||||||
if (Telescope.settings.get("cloudinaryAPIKey")) {
|
if (Telescope.settings.get("cloudinaryAPIKey")) {
|
||||||
if (newPost.thumbnailUrl && newPost.thumbnailUrl !== oldPost.thumbnailUrl) {
|
if (newPost.thumbnailUrl && newPost.thumbnailUrl !== oldPost.thumbnailUrl) {
|
||||||
|
|
||||||
const data = CloudinaryUtils.uploadImage(newPost.thumbnailUrl);
|
const data = CloudinaryUtils.uploadImage(newPost.thumbnailUrl);
|
||||||
Posts.update(newPost._id, {$set:{
|
Posts.update(newPost._id, {$set:{
|
||||||
cloudinaryId: data.cloudinaryId,
|
cloudinaryId: data.cloudinaryId,
|
||||||
|
@ -118,4 +118,4 @@ function cachePostThumbnailOnEdit (newPost, oldPost) {
|
||||||
}
|
}
|
||||||
Telescope.callbacks.add("posts.edit.async", cachePostThumbnailOnEdit);
|
Telescope.callbacks.add("posts.edit.async", cachePostThumbnailOnEdit);
|
||||||
|
|
||||||
export default CloudinaryUtils;
|
export default CloudinaryUtils;
|
||||||
|
|
|
@ -232,7 +232,7 @@ function CommentsNewNotifications (comment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ Telescope.callbacks.add("comments.edit.method", CommentsEditSubmittedPropertiesC
|
||||||
|
|
||||||
function UsersRemoveDeleteComments (user, options) {
|
function UsersRemoveDeleteComments (user, options) {
|
||||||
if (options && options.deleteComments) {
|
if (options && options.deleteComments) {
|
||||||
Comments.remove({userId: userId});
|
Comments.remove({userId: user._id});
|
||||||
} else {
|
} else {
|
||||||
// not sure if anything should be done in that scenario yet
|
// not sure if anything should be done in that scenario yet
|
||||||
// Comments.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
|
// Comments.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
* @summary The global namespace for Comments.
|
* @summary The global namespace for Comments.
|
||||||
* @namespace Comments
|
* @namespace Comments
|
||||||
*/
|
*/
|
||||||
Comments = new Mongo.Collection("comments");
|
const Comments = new Mongo.Collection("comments");
|
||||||
|
|
||||||
export default Comments;
|
export default Comments;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import PublicationUtils from 'meteor/utilities:smart-publications';
|
import PublicationUtils from 'meteor/utilities:smart-publications';
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from 'meteor/nova:posts';
|
||||||
import Users from "meteor/nova:users";
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
Posts.addField([
|
Posts.addField([
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
// import Telescope from 'meteor/nova:lib';
|
||||||
import Comments from './collection.js';
|
import Comments from './collection.js';
|
||||||
import Posts from 'meteor/nova:posts';
|
import Posts from 'meteor/nova:posts';
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Comments from './collection.js';
|
import Comments from './collection.js';
|
||||||
import PublicationsUtils from 'meteor/utilities:smart-publications';
|
import PublicationsUtils from 'meteor/utilities:smart-publications';
|
||||||
import Posts from "meteor/nova:posts";
|
// import Posts from "meteor/nova:posts";
|
||||||
|
|
||||||
Comments.publishedFields = {};
|
Comments.publishedFields = {};
|
||||||
|
|
||||||
|
@ -26,4 +26,4 @@ Comments.publishedFields.list = PublicationsUtils.arrayToFields([
|
||||||
* @summary Specify which fields should be published by the posts.single publication
|
* @summary Specify which fields should be published by the posts.single publication
|
||||||
* @array Posts.publishedFields.single
|
* @array Posts.publishedFields.single
|
||||||
*/
|
*/
|
||||||
Comments.publishedFields.single = PublicationsUtils.arrayToFields(Comments.getPublishedFields());
|
Comments.publishedFields.single = PublicationsUtils.arrayToFields(Comments.getPublishedFields());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Comments from './collection.js';
|
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
import Comments from './collection.js';
|
||||||
|
|
||||||
// check if user can create a new comment
|
// check if user can create a new comment
|
||||||
const canInsert = user => Users.canDo(user, "comments.new");
|
const canInsert = user => Users.canDo(user, "comments.new");
|
||||||
|
@ -10,7 +10,7 @@ const canInsert = user => Users.canDo(user, "comments.new");
|
||||||
const canEdit = Users.canEdit;
|
const canEdit = Users.canEdit;
|
||||||
|
|
||||||
// check if user can edit *all* comments
|
// check if user can edit *all* comments
|
||||||
const canEditAll = user => Users.canDo(user, "comments.edit.all");
|
// const canEditAll = user => Users.canDo(user, "comments.edit.all");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Comments schema
|
* @summary Comments schema
|
||||||
|
@ -126,7 +126,7 @@ Comments.schema = new SimpleSchema({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
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,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import Comments from '../collection.js';
|
||||||
|
|
||||||
Comments._ensureIndex({postId: 1});
|
Comments._ensureIndex({postId: 1});
|
||||||
Comments._ensureIndex({parentCommentId: 1});
|
Comments._ensureIndex({parentCommentId: 1});
|
||||||
|
@ -9,11 +10,11 @@ Comments._ensureIndex({parentCommentId: 1});
|
||||||
* @param {Object} terms
|
* @param {Object} terms
|
||||||
*/
|
*/
|
||||||
Meteor.publish('comments.list', function (terms) {
|
Meteor.publish('comments.list', function (terms) {
|
||||||
|
|
||||||
const currentUser = this.userId && Users.findOne(this.userId);
|
const currentUser = this.userId && Users.findOne(this.userId);
|
||||||
|
|
||||||
terms.currentUserId = this.userId; // add currentUserId to terms
|
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||||
({selector, options} = Comments.parameters.get(terms));
|
const {selector, options} = Comments.parameters.get(terms);
|
||||||
|
|
||||||
// commenting this because of FR-SSR issue
|
// commenting this because of FR-SSR issue
|
||||||
// Counts.publish(this, 'comments.list', Comments.find(selector, options));
|
// Counts.publish(this, 'comments.list', Comments.find(selector, options));
|
||||||
|
@ -41,12 +42,12 @@ Meteor.publish('comments.list', function (terms) {
|
||||||
|
|
||||||
// check(terms, {_id: String});
|
// check(terms, {_id: String});
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
// let commentIds = [terms._id];
|
// let commentIds = [terms._id];
|
||||||
// const childCommentIds = _.pluck(Comments.find({parentCommentId: terms._id}, {fields: {_id: 1}}).fetch(), '_id');
|
// const childCommentIds = _.pluck(Comments.find({parentCommentId: terms._id}, {fields: {_id: 1}}).fetch(), '_id');
|
||||||
// commentIds = commentIds.concat(childCommentIds);
|
// commentIds = commentIds.concat(childCommentIds);
|
||||||
|
|
||||||
// return Users.canView(currentUser) ? Comments.find({_id: {$in: commentIds}}, {sort: {score: -1, postedAt: -1}}) : [];
|
// return Users.canView(currentUser) ? Comments.find({_id: {$in: commentIds}}, {sort: {score: -1, postedAt: -1}}) : [];
|
||||||
|
|
||||||
// });
|
// });
|
||||||
|
@ -60,7 +61,7 @@ Meteor.publish('comments.list', function (terms) {
|
||||||
|
|
||||||
// check(commentId, String);
|
// check(commentId, String);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
// if(Users.canViewById(this.userId)){
|
// if(Users.canViewById(this.userId)){
|
||||||
// var comment = Comments.findOne(commentId);
|
// var comment = Comments.findOne(commentId);
|
||||||
|
@ -75,8 +76,8 @@ Meteor.publish('comments.list', function (terms) {
|
||||||
|
|
||||||
// check(commentId, String);
|
// check(commentId, String);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
// var userIds = [];
|
// var userIds = [];
|
||||||
|
|
||||||
// if(Users.canViewById(this.userId)){
|
// if(Users.canViewById(this.userId)){
|
||||||
|
@ -92,11 +93,11 @@ Meteor.publish('comments.list', function (terms) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return Users.find({_id: {$in: userIds}}, {fields: Users.pubsub.publicProperties});
|
// return Users.find({_id: {$in: userIds}}, {fields: Users.pubsub.publicProperties});
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return [];
|
// return [];
|
||||||
|
|
||||||
// });
|
// });
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
// import Telescope from 'meteor/nova:lib';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Update an item's (post or comment) score
|
* @summary Update an item's (post or comment) score
|
||||||
|
@ -7,6 +7,8 @@ import Telescope from 'meteor/nova:lib';
|
||||||
* @param {object} collection - The collection the item belongs to
|
* @param {object} collection - The collection the item belongs to
|
||||||
* @param {string} operation - The operation being performed
|
* @param {string} operation - The operation being performed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
function updateScore (item, user, collection, operation) {
|
function updateScore (item, user, collection, operation) {
|
||||||
Telescope.updateScore({collection: collection, item: item, forceUpdate: true});
|
Telescope.updateScore({collection: collection, item: item, forceUpdate: true});
|
||||||
}
|
}
|
||||||
|
@ -14,6 +16,7 @@ Telescope.callbacks.add("upvote.async", updateScore);
|
||||||
Telescope.callbacks.add("downvote.async", updateScore);
|
Telescope.callbacks.add("downvote.async", updateScore);
|
||||||
Telescope.callbacks.add("cancelUpvote.async", updateScore);
|
Telescope.callbacks.add("cancelUpvote.async", updateScore);
|
||||||
Telescope.callbacks.add("cancelDownvote.async", updateScore);
|
Telescope.callbacks.add("cancelDownvote.async", updateScore);
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Update the profile of the user doing the operation
|
* @summary Update the profile of the user doing the operation
|
||||||
|
@ -22,6 +25,8 @@ Telescope.callbacks.add("cancelDownvote.async", updateScore);
|
||||||
* @param {object} collection - The collection the item belongs to
|
* @param {object} collection - The collection the item belongs to
|
||||||
* @param {string} operation - The operation being performed
|
* @param {string} operation - The operation being performed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
function updateUser (item, user, collection, operation) {
|
function updateUser (item, user, collection, operation) {
|
||||||
|
|
||||||
var update = {};
|
var update = {};
|
||||||
|
@ -39,10 +44,10 @@ function updateUser (item, user, collection, operation) {
|
||||||
case "downvote":
|
case "downvote":
|
||||||
update.$addToSet = {'telescope.downvotedPosts': vote};
|
update.$addToSet = {'telescope.downvotedPosts': vote};
|
||||||
break;
|
break;
|
||||||
case "cancelUpvote":
|
case "cancelUpvote":
|
||||||
update.$pull = {'telescope.upvotedPosts': {itemId: item._id}};
|
update.$pull = {'telescope.upvotedPosts': {itemId: item._id}};
|
||||||
break;
|
break;
|
||||||
case "cancelDownvote":
|
case "cancelDownvote":
|
||||||
update.$pull = {'telescope.downvotedPosts': {itemId: item._id}};
|
update.$pull = {'telescope.downvotedPosts': {itemId: item._id}};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +59,7 @@ Telescope.callbacks.add("upvote.async", updateUser);
|
||||||
Telescope.callbacks.add("downvote.async", updateUser);
|
Telescope.callbacks.add("downvote.async", updateUser);
|
||||||
Telescope.callbacks.add("cancelUpvote.async", updateUser);
|
Telescope.callbacks.add("cancelUpvote.async", updateUser);
|
||||||
Telescope.callbacks.add("cancelDownvote.async", updateUser);
|
Telescope.callbacks.add("cancelDownvote.async", updateUser);
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Update the karma of the item's owner
|
* @summary Update the karma of the item's owner
|
||||||
|
@ -62,11 +68,13 @@ Telescope.callbacks.add("cancelDownvote.async", updateUser);
|
||||||
* @param {object} collection - The collection the item belongs to
|
* @param {object} collection - The collection the item belongs to
|
||||||
* @param {string} operation - The operation being performed
|
* @param {string} operation - The operation being performed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
function updateKarma (item, user, collection, operation) {
|
function updateKarma (item, user, collection, operation) {
|
||||||
|
|
||||||
var votePower = Telescope.getVotePower(user);
|
var votePower = Telescope.getVotePower(user);
|
||||||
var karmaAmount = (operation === "upvote" || operation === "cancelDownvote") ? votePower : -votePower;
|
var karmaAmount = (operation === "upvote" || operation === "cancelDownvote") ? votePower : -votePower;
|
||||||
|
|
||||||
// only update karma is the operation isn't done by the item's author
|
// only update karma is the operation isn't done by the item's author
|
||||||
if (item.userId !== user._id) {
|
if (item.userId !== user._id) {
|
||||||
Users.update({_id: item.userId}, {$inc: {"telescope.karma": karmaAmount}});
|
Users.update({_id: item.userId}, {$inc: {"telescope.karma": karmaAmount}});
|
||||||
|
@ -76,4 +84,5 @@ function updateKarma (item, user, collection, operation) {
|
||||||
Telescope.callbacks.add("upvote.async", updateKarma);
|
Telescope.callbacks.add("upvote.async", updateKarma);
|
||||||
Telescope.callbacks.add("downvote.async", updateKarma);
|
Telescope.callbacks.add("downvote.async", updateKarma);
|
||||||
Telescope.callbacks.add("cancelUpvote.async", updateKarma);
|
Telescope.callbacks.add("cancelUpvote.async", updateKarma);
|
||||||
Telescope.callbacks.add("cancelDownvote.async", updateKarma);
|
Telescope.callbacks.add("cancelDownvote.async", updateKarma);
|
||||||
|
*/
|
||||||
|
|
|
@ -48,7 +48,7 @@ class ModalTrigger extends Component {
|
||||||
<Modal bsSize={this.props.size} show={this.state.modalIsOpen} onHide={this.closeModal}>
|
<Modal bsSize={this.props.size} show={this.state.modalIsOpen} onHide={this.closeModal}>
|
||||||
{this.props.title ? this.renderHeader() : null}
|
{this.props.title ? this.renderHeader() : null}
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<ContextPasser
|
<ContextPasser
|
||||||
currentUser={this.context.currentUser}
|
currentUser={this.context.currentUser}
|
||||||
actions={this.context.actions}
|
actions={this.context.actions}
|
||||||
events={this.context.events}
|
events={this.context.events}
|
||||||
|
@ -62,7 +62,7 @@ class ModalTrigger extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
ModalTrigger.propTypes = {
|
ModalTrigger.propTypes = {
|
||||||
component: React.PropTypes.object.isRequired,
|
component: React.PropTypes.object.isRequired,
|
||||||
|
@ -86,4 +86,4 @@ ModalTrigger.contextTypes = {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
module.exports = ModalTrigger;
|
module.exports = ModalTrigger;
|
||||||
export default ModalTrigger;
|
export default ModalTrigger;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import {Inject} from 'meteor/meteorhacks:inject-initial';
|
|
||||||
import Events from "meteor/nova:events";
|
import Events from "meteor/nova:events";
|
||||||
|
import { Inject } from 'meteor/meteorhacks:inject-initial';
|
||||||
|
import { SyncedCron } from 'meteor/percolatestudio:synced-cron';
|
||||||
|
|
||||||
Meteor.startup(function () {
|
Meteor.startup(function () {
|
||||||
Events.log({
|
Events.log({
|
||||||
|
@ -20,4 +21,4 @@ Meteor.startup(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Inject.obj('serverTimezoneOffset', {offset: new Date().getTimezoneOffset()});
|
Inject.obj('serverTimezoneOffset', {offset: new Date().getTimezoneOffset()});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Posts from "meteor/nova:posts";
|
// import Posts from "meteor/nova:posts";
|
||||||
import Comments from "meteor/nova:comments";
|
// import Comments from "meteor/nova:comments";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
const Group = ({name, actions}) => {
|
const Group = ({name, actions}) => {
|
||||||
|
@ -32,11 +32,11 @@ const Groups = props => {
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = Groups
|
module.exports = Groups
|
||||||
export default Groups
|
export default Groups
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable no-undef */
|
||||||
|
|
||||||
import TelescopeImport from 'meteor/nova:lib';
|
import TelescopeImport from 'meteor/nova:lib';
|
||||||
import PostsImport from "meteor/nova:posts";
|
import PostsImport from "meteor/nova:posts";
|
||||||
import CommentsImport from "meteor/nova:comments";
|
import CommentsImport from "meteor/nova:comments";
|
||||||
|
|
|
@ -4,14 +4,14 @@ import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
"email.test": function (emailName) {
|
"email.test": function (emailName) {
|
||||||
|
|
||||||
const email = NovaEmail.emails[emailName];
|
const email = NovaEmail.emails[emailName];
|
||||||
|
|
||||||
if(Users.isAdminById(this.userId)){
|
if(Users.isAdminById(this.userId)){
|
||||||
|
|
||||||
console.log("// testing email ["+emailName+"]");
|
console.log("// testing email ["+emailName+"]"); // eslint-disable-line
|
||||||
let html, properties;
|
let html, properties;
|
||||||
|
|
||||||
// if email has a custom way of generating its HTML, use it
|
// if email has a custom way of generating its HTML, use it
|
||||||
if (typeof email.getTestHTML !== "undefined") {
|
if (typeof email.getTestHTML !== "undefined") {
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ Meteor.methods({
|
||||||
const subject = "[Test] " + email.subject.bind(email)(properties);
|
const subject = "[Test] " + email.subject.bind(email)(properties);
|
||||||
|
|
||||||
NovaEmail.send (Telescope.settings.get('defaultEmail'), subject, html)
|
NovaEmail.send (Telescope.settings.get('defaultEmail'), subject, html)
|
||||||
|
|
||||||
return subject;
|
return subject;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Meteor.Error("must_be_admin", "You must be an admin to send test emails");
|
throw new Meteor.Error("must_be_admin", "You must be an admin to send test emails");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
/* global Movies:true */
|
||||||
|
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
|
||||||
import {mount} from 'react-mounter';
|
|
||||||
import MoviesWrapper from './demo-components.jsx';
|
|
||||||
import Core from 'meteor/nova:core';
|
|
||||||
import { Route } from 'react-router';
|
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
import React, { PropTypes, Component } from 'react';
|
||||||
|
import MoviesWrapper from './demo-components.jsx';
|
||||||
|
// import {mount} from 'react-mounter';
|
||||||
|
// import Core from 'meteor/nova:core';
|
||||||
|
// import { Route } from 'react-router';
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// Collection & Schema //
|
// Collection & Schema //
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
/* global Movies */
|
||||||
|
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { ListContainer } from "meteor/utilities:react-list-container";
|
import { ListContainer } from "meteor/utilities:react-list-container";
|
||||||
import NovaForm from "meteor/nova:forms";
|
import NovaForm from "meteor/nova:forms";
|
||||||
import { Button } from 'react-bootstrap';
|
import { Button } from 'react-bootstrap';
|
||||||
import { Accounts } from 'meteor/std:accounts-ui';
|
import { Accounts } from 'meteor/std:accounts-ui';
|
||||||
import { ModalTrigger, Messages, FlashContainer } from "meteor/nova:core";
|
import { ModalTrigger, /* Messages, */ FlashContainer } from "meteor/nova:core";
|
||||||
|
|
||||||
const FlashMessages = Telescope.components.FlashMessages;
|
const FlashMessages = Telescope.components.FlashMessages;
|
||||||
|
|
||||||
|
@ -24,8 +26,8 @@ class MoviesWrapper extends Component {
|
||||||
<FlashContainer component={FlashMessages}/>
|
<FlashContainer component={FlashMessages}/>
|
||||||
|
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<ListContainer
|
<ListContainer
|
||||||
collection={Movies}
|
collection={Movies}
|
||||||
publication="movies.list"
|
publication="movies.list"
|
||||||
terms={{options: {sort: {createdAt: -1}}}}
|
terms={{options: {sort: {createdAt: -1}}}}
|
||||||
options={{sort: {createdAt: -1}}}
|
options={{sort: {createdAt: -1}}}
|
||||||
|
@ -48,23 +50,23 @@ class MoviesWrapper extends Component {
|
||||||
class MoviesList extends Component {
|
class MoviesList extends Component {
|
||||||
|
|
||||||
renderNew() {
|
renderNew() {
|
||||||
|
|
||||||
const component = (
|
const component = (
|
||||||
<div className="add-movie">
|
<div className="add-movie">
|
||||||
<ModalTrigger
|
<ModalTrigger
|
||||||
title="Add Movie"
|
title="Add Movie"
|
||||||
component={<Button bsStyle="primary">Add Movie</Button>}
|
component={<Button bsStyle="primary">Add Movie</Button>}
|
||||||
>
|
>
|
||||||
<NovaForm
|
<NovaForm
|
||||||
collection={Movies}
|
collection={Movies}
|
||||||
methodName="movies.create"
|
methodName="movies.create"
|
||||||
currentUser={this.props.currentUser}
|
currentUser={this.props.currentUser}
|
||||||
/>
|
/>
|
||||||
</ModalTrigger>
|
</ModalTrigger>
|
||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
return !!this.props.currentUser ? component : "";
|
return !!this.props.currentUser ? component : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ class MoviesList extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// Movie //
|
// Movie //
|
||||||
|
@ -91,14 +93,14 @@ class Movie extends Component {
|
||||||
const movie = this.props;
|
const movie = this.props;
|
||||||
|
|
||||||
const component = (
|
const component = (
|
||||||
<ModalTrigger
|
<ModalTrigger
|
||||||
label="Edit Movie"
|
label="Edit Movie"
|
||||||
component={<Button bsStyle="primary">Edit Movie</Button>}
|
component={<Button bsStyle="primary">Edit Movie</Button>}
|
||||||
>
|
>
|
||||||
<NovaForm
|
<NovaForm
|
||||||
collection={Movies}
|
collection={Movies}
|
||||||
currentUser={this.props.currentUser}
|
currentUser={this.props.currentUser}
|
||||||
document={movie}
|
document={movie}
|
||||||
methodName="movies.edit"
|
methodName="movies.edit"
|
||||||
/>
|
/>
|
||||||
</ModalTrigger>
|
</ModalTrigger>
|
||||||
|
@ -112,7 +114,7 @@ class Movie extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const movie = this.props;
|
const movie = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -124,8 +126,8 @@ class Movie extends Component {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
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
|
export default MoviesWrapper
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { Picker } from 'meteor/meteorhacks:picker';
|
||||||
|
|
||||||
import NovaEmail from 'meteor/nova:email';
|
import NovaEmail from 'meteor/nova:email';
|
||||||
|
|
||||||
Meteor.startup(function () {
|
Meteor.startup(function () {
|
||||||
|
@ -29,7 +31,7 @@ Meteor.startup(function () {
|
||||||
|
|
||||||
// return html
|
// return html
|
||||||
res.end(html);
|
res.end(html);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// raw template
|
// raw template
|
||||||
|
@ -38,5 +40,5 @@ Meteor.startup(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,10 +77,10 @@ NovaEmail.send = function(to, subject, html, text){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('//////// sending email…');
|
console.log('//////// sending email…'); // eslint-disable-line
|
||||||
console.log('from: '+from);
|
console.log('from: '+from); // eslint-disable-line
|
||||||
console.log('to: '+to);
|
console.log('to: '+to); // eslint-disable-line
|
||||||
console.log('subject: '+subject);
|
console.log('subject: '+subject); // eslint-disable-line
|
||||||
// console.log('html: '+html);
|
// console.log('html: '+html);
|
||||||
// console.log('text: '+text);
|
// console.log('text: '+text);
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ NovaEmail.send = function(to, subject, html, text){
|
||||||
try {
|
try {
|
||||||
Email.send(email);
|
Email.send(email);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("// error while sending email:")
|
console.log("// error while sending email:"); // eslint-disable-line
|
||||||
console.log(error)
|
console.log(error); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
return email;
|
return email;
|
||||||
|
|
|
@ -24,16 +24,16 @@ class EmbedlyURL extends Component {
|
||||||
|
|
||||||
// the URL has changed, get a new thumbnail
|
// the URL has changed, get a new thumbnail
|
||||||
this.context.actions.call("getEmbedlyData", url, (error, result) => {
|
this.context.actions.call("getEmbedlyData", url, (error, result) => {
|
||||||
|
|
||||||
console.log("querying Embedly…");
|
console.log("querying Embedly…"); // eslint-disable-line
|
||||||
|
|
||||||
this.setState({loading: false});
|
this.setState({loading: false});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log(error)
|
console.log(error); // eslint-disable-line
|
||||||
this.context.throwError({content: error.message, type: "error"});
|
this.context.throwError({content: error.message, type: "error"});
|
||||||
} else {
|
} else {
|
||||||
console.log(result)
|
console.log(result); // eslint-disable-line
|
||||||
this.context.addToAutofilledValues({
|
this.context.addToAutofilledValues({
|
||||||
title: result.title,
|
title: result.title,
|
||||||
body: result.description,
|
body: result.description,
|
||||||
|
@ -46,7 +46,7 @@ class EmbedlyURL extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const Loading = Telescope.components.Loading;
|
const Loading = Telescope.components.Loading;
|
||||||
|
|
||||||
const wrapperStyle = {
|
const wrapperStyle = {
|
||||||
|
@ -61,16 +61,16 @@ class EmbedlyURL extends Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
loadingStyle.display = this.state.loading ? "block" : "none";
|
loadingStyle.display = this.state.loading ? "block" : "none";
|
||||||
|
|
||||||
// see https://facebook.github.io/react/warnings/unknown-prop.html
|
// see https://facebook.github.io/react/warnings/unknown-prop.html
|
||||||
const {document, updateCurrentValue, control, ...rest} = this.props;
|
const {document, updateCurrentValue, control, ...rest} = this.props; // eslint-disable-line
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="embedly-url-field" style={wrapperStyle}>
|
<div className="embedly-url-field" style={wrapperStyle}>
|
||||||
<Input
|
<Input
|
||||||
{...rest}
|
{...rest}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
type="text"
|
type="text"
|
||||||
ref={ref => this.input = ref}
|
ref={ref => this.input = ref}
|
||||||
/>
|
/>
|
||||||
<div className="embedly-url-field-loading" style={loadingStyle}>
|
<div className="embedly-url-field-loading" style={loadingStyle}>
|
||||||
|
@ -93,4 +93,4 @@ EmbedlyURL.contextTypes = {
|
||||||
actions: React.PropTypes.object,
|
actions: React.PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EmbedlyURL;
|
export default EmbedlyURL;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Formsy from 'formsy-react';
|
// import Formsy from 'formsy-react';
|
||||||
import FRC from 'formsy-react-components';
|
import FRC from 'formsy-react-components';
|
||||||
const Input = FRC.Input;
|
const Input = FRC.Input;
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ class ThumbnailURL extends Component {
|
||||||
renderThumbnail() {
|
renderThumbnail() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
className="embedly-thumbnail"
|
className="embedly-thumbnail"
|
||||||
src={this.props.value}
|
src={this.props.value}
|
||||||
style={{
|
style={{
|
||||||
"width": 150,
|
"width": 150,
|
||||||
"height": Telescope.settings.get('thumbnailHeight', 150) * 150 / Telescope.settings.get('thumbnailWidth', 150)
|
"height": Telescope.settings.get('thumbnailHeight', 150) * 150 / Telescope.settings.get('thumbnailWidth', 150)
|
||||||
|
@ -44,7 +44,7 @@ class ThumbnailURL extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const {name, value, label} = this.props;
|
const {name, /* value, */ label} = this.props;
|
||||||
|
|
||||||
const inputType = this.state.showInput ? "text" : "hidden";
|
const inputType = this.state.showInput ? "text" : "hidden";
|
||||||
|
|
||||||
|
@ -73,4 +73,4 @@ ThumbnailURL.contextTypes = {
|
||||||
deleteValue: React.PropTypes.func
|
deleteValue: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ThumbnailURL;
|
export default ThumbnailURL;
|
||||||
|
|
|
@ -10,7 +10,7 @@ Telescope.callbacks.add("postClass", addThumbnailClass);
|
||||||
function checkIfPreviouslyPosted (data) {
|
function checkIfPreviouslyPosted (data) {
|
||||||
Meteor.call("checkForDuplicates", data.url, function (error, result) {
|
Meteor.call("checkForDuplicates", data.url, function (error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
Messages.flash(error.reason + '. <a href="'+FlowRouter.path("postPage", {_id: error.details})+'">'+"go_to_post"+'</a>');
|
// Messages.flash(error.reason + '. <a href="'+FlowRouter.path("postPage", {_id: error.details})+'">'+"go_to_post"+'</a>');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -2,8 +2,8 @@ import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
getEmbedlyData = function (url) {
|
var getEmbedlyData = function (url) {
|
||||||
var data = {};
|
// var data = {};
|
||||||
var extractBase = 'http://api.embed.ly/1/extract';
|
var extractBase = 'http://api.embed.ly/1/extract';
|
||||||
var embedlyKey = Telescope.settings.get('embedlyKey');
|
var embedlyKey = Telescope.settings.get('embedlyKey');
|
||||||
var thumbnailWidth = Telescope.settings.get('thumbnailWidth', 200);
|
var thumbnailWidth = Telescope.settings.get('thumbnailWidth', 200);
|
||||||
|
@ -11,7 +11,7 @@ getEmbedlyData = function (url) {
|
||||||
|
|
||||||
if(!embedlyKey) {
|
if(!embedlyKey) {
|
||||||
// fail silently to still let the post be submitted as usual
|
// fail silently to still let the post be submitted as usual
|
||||||
console.log("Couldn't find an Embedly API key! Please add it to your Telescope settings or remove the Embedly module.");
|
console.log("Couldn't find an Embedly API key! Please add it to your Telescope settings or remove the Embedly module."); // eslint-disable-line
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ getEmbedlyData = function (url) {
|
||||||
return embedlyData;
|
return embedlyData;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error); // eslint-disable-line
|
||||||
// the first 13 characters of the Embedly errors are "failed [400] ", so remove them and parse the rest
|
// the first 13 characters of the Embedly errors are "failed [400] ", so remove them and parse the rest
|
||||||
var errorObject = JSON.parse(error.message.substring(13));
|
var errorObject = JSON.parse(error.message.substring(13));
|
||||||
throw new Meteor.Error(errorObject.error_code, errorObject.error_message);
|
throw new Meteor.Error(errorObject.error_code, errorObject.error_message);
|
||||||
|
@ -111,7 +111,7 @@ var regenerateThumbnail = function (post) {
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
testGetEmbedlyData: function (url) {
|
testGetEmbedlyData: function (url) {
|
||||||
check(url, String);
|
check(url, String);
|
||||||
console.log(getEmbedlyData(url));
|
console.log(getEmbedlyData(url)); // eslint-disable-line
|
||||||
},
|
},
|
||||||
getEmbedlyData: function (url) {
|
getEmbedlyData: function (url) {
|
||||||
check(url, String);
|
check(url, String);
|
||||||
|
@ -129,11 +129,11 @@ Meteor.methods({
|
||||||
generateThumbnails: function (limit = 20, mode = "generate") {
|
generateThumbnails: function (limit = 20, mode = "generate") {
|
||||||
// mode = "generate" : generate thumbnails only for all posts that don't have one
|
// mode = "generate" : generate thumbnails only for all posts that don't have one
|
||||||
// mode = "all" : regenerate thumbnais for all posts
|
// mode = "all" : regenerate thumbnais for all posts
|
||||||
|
|
||||||
if (Users.isAdmin(Meteor.user())) {
|
if (Users.isAdmin(Meteor.user())) {
|
||||||
|
|
||||||
console.log("// Generating thumbnails…")
|
console.log("// Generating thumbnails…"); // eslint-disable-line
|
||||||
|
|
||||||
const selector = {url: {$exists: true}};
|
const selector = {url: {$exists: true}};
|
||||||
if (mode === "generate") {
|
if (mode === "generate") {
|
||||||
selector.thumbnailUrl = {$exists: false};
|
selector.thumbnailUrl = {$exists: false};
|
||||||
|
@ -143,11 +143,11 @@ Meteor.methods({
|
||||||
|
|
||||||
posts.forEach((post, index) => {
|
posts.forEach((post, index) => {
|
||||||
Meteor.setTimeout(function () {
|
Meteor.setTimeout(function () {
|
||||||
console.log(`// ${index}. fetching thumbnail for “${post.title}” (_id: ${post._id})`);
|
console.log(`// ${index}. fetching thumbnail for “${post.title}” (_id: ${post._id})`); // eslint-disable-line
|
||||||
try {
|
try {
|
||||||
regenerateThumbnail(post);
|
regenerateThumbnail(post);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
}
|
}
|
||||||
}, index * 1000);
|
}, index * 1000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
const Events = new Mongo.Collection('events');
|
const Events = new Mongo.Collection('events');
|
||||||
|
|
||||||
Events.schema = new SimpleSchema({
|
Events.schema = new SimpleSchema({
|
||||||
|
@ -63,4 +65,4 @@ Events.track = function(event, properties){
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Events;
|
export default Events;
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Tags extends Component {
|
||||||
|
|
||||||
const tags = this.state.tags;
|
const tags = this.state.tags;
|
||||||
tags.splice(i, 1);
|
tags.splice(i, 1);
|
||||||
|
|
||||||
const value = this.state.value;
|
const value = this.state.value;
|
||||||
value.splice(i,1);
|
value.splice(i,1);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class Tags extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddition(tag) {
|
handleAddition(tag) {
|
||||||
|
|
||||||
// first, check if added tag is part of the possible options
|
// first, check if added tag is part of the possible options
|
||||||
const option = _.findWhere(this.props.options, {label: tag});
|
const option = _.findWhere(this.props.options, {label: tag});
|
||||||
|
|
||||||
|
@ -69,14 +69,14 @@ class Tags extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const {name, value, label} = this.props;
|
const {name, /* value, */ label} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="form-group row">
|
<div className="form-group row">
|
||||||
<label className="control-label col-sm-3">{label}</label>
|
<label className="control-label col-sm-3">{label}</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<div className="tags-field">
|
<div className="tags-field">
|
||||||
<ReactTags
|
<ReactTags
|
||||||
tags={this.state.tags}
|
tags={this.state.tags}
|
||||||
suggestions={this.state.suggestions}
|
suggestions={this.state.suggestions}
|
||||||
handleDelete={this.handleDelete}
|
handleDelete={this.handleDelete}
|
||||||
|
@ -105,4 +105,4 @@ Tags.propTypes = {
|
||||||
label: React.PropTypes.string
|
label: React.PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Tags;
|
export default Tags;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { PropTypes, Component } from 'react';
|
import React, { PropTypes, Component } from 'react';
|
||||||
import DateTimePicker from 'react-datetime';
|
import DateTimePicker from 'react-datetime';
|
||||||
import moment from 'moment';
|
// import moment from 'moment';
|
||||||
|
|
||||||
class DateTime extends Component {
|
class DateTime extends Component {
|
||||||
// when the datetime picker mounts, NovaForm will catch the date value (no formsy mixin in this component)
|
// when the datetime picker mounts, NovaForm will catch the date value (no formsy mixin in this component)
|
||||||
|
@ -13,11 +13,11 @@ class DateTime extends Component {
|
||||||
<div className="form-group row">
|
<div className="form-group row">
|
||||||
<label className="control-label col-sm-3">{this.props.label}</label>
|
<label className="control-label col-sm-3">{this.props.label}</label>
|
||||||
<div className="col-sm-9">
|
<div className="col-sm-9">
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
value={this.props.value || new Date()}
|
value={this.props.value || new Date()}
|
||||||
// newDate argument is a Moment object given by react-datetime
|
// newDate argument is a Moment object given by react-datetime
|
||||||
onChange={newDate => { this.context.addToAutofilledValues({[this.props.name]: newDate._d}) }}
|
onChange={newDate => { this.context.addToAutofilledValues({[this.props.name]: newDate._d}) }}
|
||||||
format={"x"}
|
format={"x"}
|
||||||
inputProps={{name: this.props.name}}
|
inputProps={{name: this.props.name}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import FRC from 'formsy-react-components';
|
||||||
|
|
||||||
import DateTime from './DateTime.jsx';
|
import DateTime from './DateTime.jsx';
|
||||||
|
|
||||||
import Utils from './utils.js';
|
// import Utils from './utils.js';
|
||||||
|
|
||||||
const Checkbox = FRC.Checkbox;
|
const Checkbox = FRC.Checkbox;
|
||||||
// const CheckboxGroup = FRC.CheckboxGroup;
|
// const CheckboxGroup = FRC.CheckboxGroup;
|
||||||
|
@ -30,7 +30,7 @@ class FormComponent extends Component {
|
||||||
renderComponent() {
|
renderComponent() {
|
||||||
|
|
||||||
// see https://facebook.github.io/react/warnings/unknown-prop.html
|
// see https://facebook.github.io/react/warnings/unknown-prop.html
|
||||||
const { control, group, updateCurrentValue, document, ...rest } = this.props;
|
const { control, group, updateCurrentValue, document, ...rest } = this.props; // eslint-disable-line
|
||||||
|
|
||||||
const base = this.props.control === "function" ? this.props : rest;
|
const base = this.props.control === "function" ? this.props : rest;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class FormComponent extends Component {
|
||||||
case "textarea":
|
case "textarea":
|
||||||
return <Textarea {...properties} />;
|
return <Textarea {...properties} />;
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
return <Checkbox {...properties} />;
|
return <Checkbox {...properties} />;
|
||||||
// note: checkboxgroup cause React refs error
|
// note: checkboxgroup cause React refs error
|
||||||
case "checkboxgroup":
|
case "checkboxgroup":
|
||||||
return <CheckboxGroup {...properties} />;
|
return <CheckboxGroup {...properties} />;
|
||||||
|
@ -63,7 +63,7 @@ class FormComponent extends Component {
|
||||||
return <Select {...properties} />;
|
return <Select {...properties} />;
|
||||||
case "datetime":
|
case "datetime":
|
||||||
return <DateTime {...properties} />;
|
return <DateTime {...properties} />;
|
||||||
default:
|
default:
|
||||||
return <Input {...properties} type="text" />;
|
return <Input {...properties} type="text" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ FormComponent.propTypes = {
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
value: React.PropTypes.any,
|
value: React.PropTypes.any,
|
||||||
placeholder: React.PropTypes.string,
|
placeholder: React.PropTypes.string,
|
||||||
prefilledValue: React.PropTypes.any,
|
prefilledValue: React.PropTypes.any,
|
||||||
options: React.PropTypes.any,
|
options: React.PropTypes.any,
|
||||||
control: React.PropTypes.any,
|
control: React.PropTypes.any,
|
||||||
datatype: React.PropTypes.any,
|
datatype: React.PropTypes.any,
|
||||||
|
|
|
@ -85,7 +85,7 @@ class NovaForm extends Component{
|
||||||
// backward compatibility from 'autoform' to 'form'
|
// backward compatibility from 'autoform' to 'form'
|
||||||
if (fieldSchema.autoform) {
|
if (fieldSchema.autoform) {
|
||||||
fieldSchema.form = fieldSchema.autoform;
|
fieldSchema.form = fieldSchema.autoform;
|
||||||
console.warn(`🔭 Telescope Nova Warning: The 'autoform' field is deprecated. You should rename it to 'form' instead. It was defined on your '${fieldName}' field on the '${this.props.collection._name}' collection`);
|
console.warn(`🔭 Telescope Nova Warning: The 'autoform' field is deprecated. You should rename it to 'form' instead. It was defined on your '${fieldName}' field on the '${this.props.collection._name}' collection`); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace value by prefilled value if value is empty
|
// replace value by prefilled value if value is empty
|
||||||
|
@ -96,7 +96,7 @@ class NovaForm extends Component{
|
||||||
field.value = prefilledValue;
|
field.value = prefilledValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace empty value, which has not been prefilled, by the default value from the schema
|
// replace empty value, which has not been prefilled, by the default value from the schema
|
||||||
if (fieldSchema.defaultValue && field.value === "") {
|
if (fieldSchema.defaultValue && field.value === "") {
|
||||||
field.value = fieldSchema.defaultValue;
|
field.value = fieldSchema.defaultValue;
|
||||||
|
@ -291,7 +291,7 @@ class NovaForm extends Component{
|
||||||
|
|
||||||
this.setState({disabled: false});
|
this.setState({disabled: false});
|
||||||
|
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
|
|
||||||
const errorContent = this.context.intl.formatMessage({id: error.reason}, {details: error.details})
|
const errorContent = this.context.intl.formatMessage({id: error.reason}, {details: error.details})
|
||||||
// add error to state
|
// add error to state
|
||||||
|
@ -326,7 +326,7 @@ class NovaForm extends Component{
|
||||||
|
|
||||||
// complete the data with values from custom components which are not being catched by Formsy mixin
|
// complete the data with values from custom components which are not being catched by Formsy mixin
|
||||||
// note: it follows the same logic as NovaForm's getDocument method
|
// note: it follows the same logic as NovaForm's getDocument method
|
||||||
data = {
|
data = {
|
||||||
...this.state.autofilledValues, // ex: can be values from EmbedlyURL or NewsletterSubscribe component
|
...this.state.autofilledValues, // ex: can be values from EmbedlyURL or NewsletterSubscribe component
|
||||||
...data, // original data generated thanks to Formsy
|
...data, // original data generated thanks to Formsy
|
||||||
...this.state.currentValues, // ex: can be values from DateTime component
|
...this.state.currentValues, // ex: can be values from DateTime component
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable react/display-name */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
@ -156,4 +158,4 @@ module.exports = {
|
||||||
}
|
}
|
||||||
return (this.isValid() === false);
|
return (this.isValid() === false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
if (typeof SimpleSchema !== "undefined") {
|
if (typeof SimpleSchema !== "undefined") {
|
||||||
SimpleSchema.extendOptions({
|
SimpleSchema.extendOptions({
|
||||||
control: Match.Optional(Match.Any), // NovaForm control (String or React component)
|
control: Match.Optional(Match.Any), // NovaForm control (String or React component)
|
||||||
|
|
|
@ -92,7 +92,7 @@ var createDummyComments = function () {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteDummyContent = function () {
|
var deleteDummyContent = function () {
|
||||||
Users.remove({'profile.isDummy': true});
|
Users.remove({'profile.isDummy': true});
|
||||||
Posts.remove({isDummy: true});
|
Posts.remove({isDummy: true});
|
||||||
Comments.remove({isDummy: true});
|
Comments.remove({isDummy: true});
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* global InjectData */
|
||||||
|
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
var dom = $('script[type="text/inject-data"]', document);
|
var dom = $('script[type="text/inject-data"]', document);
|
||||||
var injectedDataString = $.trim(dom.text());
|
var injectedDataString = $.trim(dom.text());
|
||||||
|
@ -8,4 +10,4 @@ InjectData.getData = function(key, callback) {
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
callback(InjectData._data[key]);
|
callback(InjectData._data[key]);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
InjectData = {};
|
/* eslint-disable */
|
||||||
|
|
||||||
|
InjectData = {};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
var http = Npm.require('http');
|
/* global InjectData */
|
||||||
|
|
||||||
|
// var http = Npm.require('http');
|
||||||
|
|
||||||
var templateText = Assets.getText('lib/inject.html');
|
var templateText = Assets.getText('lib/inject.html');
|
||||||
var injectDataTemplate = _.template(templateText);
|
var injectDataTemplate = _.template(templateText);
|
||||||
|
@ -43,7 +45,7 @@ InjectData._hijackWriteIfNeeded = function(res) {
|
||||||
'warn: injecting data turned off due to CORS headers. ' +
|
'warn: injecting data turned off due to CORS headers. ' +
|
||||||
'read more: http://goo.gl/eGwb4e';
|
'read more: http://goo.gl/eGwb4e';
|
||||||
|
|
||||||
console.warn(warnMessage);
|
console.warn(warnMessage); // eslint-disable-line
|
||||||
originalWrite.call(res, chunk, encoding);
|
originalWrite.call(res, chunk, encoding);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* global InjectData */
|
||||||
|
|
||||||
InjectData._encode = function(ejson) {
|
InjectData._encode = function(ejson) {
|
||||||
var ejsonString = EJSON.stringify(ejson);
|
var ejsonString = EJSON.stringify(ejson);
|
||||||
return encodeURIComponent(ejsonString);
|
return encodeURIComponent(ejsonString);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
var fs = Npm.require('fs');
|
// var fs = Npm.require('fs');
|
||||||
var path = Npm.require('path');
|
// var path = Npm.require('path');
|
||||||
|
|
||||||
// We use this patch to avoid data injection failure during server-side rendering on Meteor 1.4
|
// We use this patch to avoid data injection failure during server-side rendering on Meteor 1.4
|
||||||
// All the credits for this package goes to Arunoda, Kadira's team & @rigconfig
|
// All the credits for this package goes to Arunoda, Kadira's team & @rigconfig
|
||||||
// see https://github.com/meteor/meteor/issues/7992
|
// see https://github.com/meteor/meteor/issues/7992
|
||||||
|
|
||||||
Package.describe({
|
Package.describe({
|
||||||
"summary": "A way to inject data to the client with initial HTML",
|
"summary": "A way to inject data to the client with initial HTML",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
|
import { Kadira } from 'meteor/meteorhacks:kadira';
|
||||||
|
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
if(process.env.NODE_ENV === "production" && !!Telescope.settings.get('kadiraAppId') && !!Telescope.settings.get('kadiraAppSecret')){
|
if(process.env.NODE_ENV === "production" && !!Telescope.settings.get('kadiraAppId') && !!Telescope.settings.get('kadiraAppSecret')){
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Telescope from './config.js';
|
import Telescope from './config.js';
|
||||||
import moment from 'moment';
|
// import moment from 'moment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Callback hooks provide an easy way to add extra steps to common operations.
|
* @summary Callback hooks provide an easy way to add extra steps to common operations.
|
||||||
* @namespace Telescope.callbacks
|
* @namespace Telescope.callbacks
|
||||||
*/
|
*/
|
||||||
Telescope.callbacks = {};
|
Telescope.callbacks = {};
|
||||||
|
@ -95,7 +95,7 @@ Telescope.callbacks.runAsync = function () {
|
||||||
callback.apply(this, args);
|
callback.apply(this, args);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
import Telescope from './config.js';
|
import Telescope from './config.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Kick off the global namespace for Telescope.
|
* @summary Kick off the global namespace for Telescope.
|
||||||
* @namespace Telescope
|
* @namespace Telescope
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Telescope = {};
|
const Telescope = {};
|
||||||
|
|
||||||
Telescope.VERSION = '0.27.4-nova';
|
Telescope.VERSION = '0.27.4-nova';
|
||||||
|
|
||||||
|
@ -106,4 +108,4 @@ Telescope.statuses = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default Telescope;
|
export default Telescope;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable */
|
||||||
// see https://gist.github.com/furf/3208381
|
// see https://gist.github.com/furf/3208381
|
||||||
|
|
||||||
_.mixin({
|
_.mixin({
|
||||||
|
|
|
@ -60,7 +60,7 @@ Telescope.utils.camelCaseify = function(str) {
|
||||||
* @param {Number} numWords - Number of words to trim sentence to.
|
* @param {Number} numWords - Number of words to trim sentence to.
|
||||||
*/
|
*/
|
||||||
Telescope.utils.trimWords = function(s, numWords) {
|
Telescope.utils.trimWords = function(s, numWords) {
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ Telescope.utils.capitalise = function(str) {
|
||||||
|
|
||||||
Telescope.utils.t = function(message) {
|
Telescope.utils.t = function(message) {
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
console.log("### "+message+" rendered at "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds());
|
console.log("### "+message+" rendered at "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()); // eslint-disable-line
|
||||||
};
|
};
|
||||||
|
|
||||||
Telescope.utils.nl2br = function(str) {
|
Telescope.utils.nl2br = function(str) {
|
||||||
|
@ -147,7 +147,7 @@ Telescope.utils.slugify = function (s) {
|
||||||
Telescope.utils.getUnusedSlug = function (collection, slug) {
|
Telescope.utils.getUnusedSlug = function (collection, slug) {
|
||||||
let suffix = "";
|
let suffix = "";
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
// handle edge case for Users collection
|
// handle edge case for Users collection
|
||||||
const field = collection._name === 'users' ? 'telescope.slug' : 'slug';
|
const field = collection._name === 'users' ? 'telescope.slug' : 'slug';
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ Telescope.utils.checkNested = function(obj /*, level1, level2, ... levelN*/) {
|
||||||
|
|
||||||
Telescope.log = function (s) {
|
Telescope.log = function (s) {
|
||||||
if(Telescope.settings.get('debug', false) || process.env.NODE_ENV === "development") {
|
if(Telescope.settings.get('debug', false) || process.env.NODE_ENV === "development") {
|
||||||
console.log(s);
|
console.log(s); // eslint-disable-line
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -313,4 +313,4 @@ Telescope.utils.getLogoUrl = () => {
|
||||||
// the logo may be hosted on another website
|
// the logo may be hosted on another website
|
||||||
return logoUrl.indexOf('://') > -1 ? logoUrl : prefix + logoUrl;
|
return logoUrl.indexOf('://') > -1 ? logoUrl : prefix + logoUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,10 +5,10 @@ import Users from 'meteor/nova:users';
|
||||||
function subscribeUserOnProfileCompletion (user) {
|
function subscribeUserOnProfileCompletion (user) {
|
||||||
if (!!Telescope.settings.get('autoSubscribe') && !!Users.getEmail(user)) {
|
if (!!Telescope.settings.get('autoSubscribe') && !!Users.getEmail(user)) {
|
||||||
MailChimpList.add(user, false, function (error, result) {
|
MailChimpList.add(user, false, function (error, result) {
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
console.log(result);
|
console.log(result); // eslint-disable-line
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
Telescope.callbacks.add("users.profileCompleted.async", subscribeUserOnProfileCompletion);
|
Telescope.callbacks.add("users.profileCompleted.async", subscribeUserOnProfileCompletion);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Newsletter from '../namespace.js';
|
import { SyncedCron } from 'meteor/percolatestudio:synced-cron';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import Newsletter from '../namespace.js';
|
||||||
|
|
||||||
const defaultFrequency = [1]; // every monday
|
const defaultFrequency = [1]; // every monday
|
||||||
const defaultTime = '00:00'; // GMT
|
const defaultTime = '00:00'; // GMT
|
||||||
|
@ -45,7 +46,7 @@ var getSchedule = function (parser) {
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
getNextJob: function () {
|
getNextJob: function () {
|
||||||
var nextJob = SyncedCron.nextScheduledAtDate('scheduleNewsletter');
|
var nextJob = SyncedCron.nextScheduledAtDate('scheduleNewsletter');
|
||||||
console.log(nextJob);
|
console.log(nextJob); // eslint-disable-line
|
||||||
return nextJob;
|
return nextJob;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -60,8 +61,8 @@ var addJob = function () {
|
||||||
job: function() {
|
job: function() {
|
||||||
// only schedule newsletter campaigns in production
|
// only schedule newsletter campaigns in production
|
||||||
if (process.env.NODE_ENV === "production" || Telescope.settings.get("enableNewsletterInDev", false)) {
|
if (process.env.NODE_ENV === "production" || Telescope.settings.get("enableNewsletterInDev", false)) {
|
||||||
console.log("// Scheduling newsletter…")
|
console.log("// Scheduling newsletter…"); // eslint-disable-line
|
||||||
console.log(new Date());
|
console.log(new Date()); // eslint-disable-line
|
||||||
Newsletter.scheduleNextWithMailChimp();
|
Newsletter.scheduleNextWithMailChimp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ const MailChimp = function ( apiKey, options ) {
|
||||||
|
|
||||||
if ( !mailChimpOptions.apiKey || mailChimpOptions.apiKey === '' ) {
|
if ( !mailChimpOptions.apiKey || mailChimpOptions.apiKey === '' ) {
|
||||||
|
|
||||||
console.error( '[MailChimp] Error: No API Key defined!' );
|
console.error( '[MailChimp] Error: No API Key defined!' ); // eslint-disable-line
|
||||||
|
|
||||||
throw new Meteor.Error(
|
throw new Meteor.Error(
|
||||||
'No API Key',
|
'No API Key',
|
||||||
|
@ -89,4 +89,4 @@ MailChimp.prototype.call = function ( section, method, options, callback ) {
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
export default MailChimp;
|
export default MailChimp;
|
||||||
|
|
|
@ -30,7 +30,7 @@ MailChimpList.add = function(userOrEmail, confirm, done){
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
console.log('// Adding "'+email+'" to MailChimp list…');
|
console.log('// Adding "'+email+'" to MailChimp list…'); // eslint-disable-line
|
||||||
|
|
||||||
var api = new MailChimp(apiKey);
|
var api = new MailChimp(apiKey);
|
||||||
var subscribeOptions = {
|
var subscribeOptions = {
|
||||||
|
@ -47,7 +47,7 @@ MailChimpList.add = function(userOrEmail, confirm, done){
|
||||||
Users.methods.setSetting(user._id, 'newsletter.subscribed', true);
|
Users.methods.setSetting(user._id, 'newsletter.subscribed', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("// User subscribed");
|
console.log("// User subscribed"); // eslint-disable-line
|
||||||
|
|
||||||
return subscribe;
|
return subscribe;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ MailChimpList.add = function(userOrEmail, confirm, done){
|
||||||
throw new Meteor.Error("subscription-failed", error.message);
|
throw new Meteor.Error("subscription-failed", error.message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Meteor.Error("Please provide your MailChimp API key and list ID", error.message);
|
throw new Meteor.Error("Please provide your MailChimp API key and list ID");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ MailChimpList.remove = (user) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
console.log('// Removing "'+email+'" from MailChimp list…');
|
console.log('// Removing "'+email+'" from MailChimp list…'); // eslint-disable-line
|
||||||
|
|
||||||
var api = new MailChimp(apiKey);
|
var api = new MailChimp(apiKey);
|
||||||
var subscribeOptions = {
|
var subscribeOptions = {
|
||||||
|
@ -89,7 +89,7 @@ MailChimpList.remove = (user) => {
|
||||||
// mark user as unsubscribed
|
// mark user as unsubscribed
|
||||||
Users.methods.setSetting(user._id, 'newsletter.subscribed', false);
|
Users.methods.setSetting(user._id, 'newsletter.subscribed', false);
|
||||||
|
|
||||||
console.log("// User unsubscribed");
|
console.log("// User unsubscribed"); // eslint-disable-line
|
||||||
|
|
||||||
return subscribe;
|
return subscribe;
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ MailChimpList.remove = (user) => {
|
||||||
throw new Meteor.Error("unsubscription-failed", error.message);
|
throw new Meteor.Error("unsubscription-failed", error.message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Meteor.Error("Please provide your MailChimp API key and list ID", error.message);
|
throw new Meteor.Error("Please provide your MailChimp API key and list ID");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
// newsletter scheduling with MailChimp
|
// newsletter scheduling with MailChimp
|
||||||
|
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Newsletter from '../../namespace.js';
|
import Posts from 'meteor/nova:posts';
|
||||||
import MailChimp from './mailchimp_api.js';
|
|
||||||
import NovaEmail from 'meteor/nova:email';
|
import NovaEmail from 'meteor/nova:email';
|
||||||
import htmlToText from 'html-to-text';
|
import htmlToText from 'html-to-text';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import Newsletter from '../../namespace.js';
|
||||||
|
import MailChimp from './mailchimp_api.js';
|
||||||
|
|
||||||
const defaultPosts = 5;
|
const defaultPosts = 5;
|
||||||
|
|
||||||
|
@ -68,14 +71,14 @@ Newsletter.scheduleWithMailChimp = function (campaign, isTest = false) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// schedule campaign
|
// schedule campaign
|
||||||
var schedule = api.call('campaigns', 'schedule', scheduleOptions);
|
var schedule = api.call('campaigns', 'schedule', scheduleOptions); // eslint-disable-line
|
||||||
|
|
||||||
console.log('// Newsletter scheduled for '+scheduledTime);
|
console.log('// Newsletter scheduled for '+scheduledTime);
|
||||||
// console.log(schedule)
|
// console.log(schedule)
|
||||||
|
|
||||||
// if this is not a test, mark posts as sent
|
// if this is not a test, mark posts as sent
|
||||||
if (!isTest)
|
if (!isTest)
|
||||||
var updated = Posts.update({_id: {$in: campaign.postIds}}, {$set: {scheduledAt: new Date()}}, {multi: true})
|
var updated = Posts.update({_id: {$in: campaign.postIds}}, {$set: {scheduledAt: new Date()}}, {multi: true}) // eslint-disable-line
|
||||||
|
|
||||||
// send confirmation email
|
// send confirmation email
|
||||||
var confirmationHtml = NovaEmail.getTemplate('newsletterConfirmation')({
|
var confirmationHtml = NovaEmail.getTemplate('newsletterConfirmation')({
|
||||||
|
@ -90,4 +93,4 @@ Newsletter.scheduleWithMailChimp = function (campaign, isTest = false) {
|
||||||
}
|
}
|
||||||
return subject;
|
return subject;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import moment from 'moment';
|
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
import Comments from "meteor/nova:comments";
|
import Comments from "meteor/nova:comments";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
import Categories from "meteor/nova:categories";
|
import Categories from "meteor/nova:categories";
|
||||||
import NovaEmail from 'meteor/nova:email';
|
import NovaEmail from 'meteor/nova:email';
|
||||||
|
import { SyncedCron } from 'meteor/percolatestudio:synced-cron';
|
||||||
|
import moment from 'moment';
|
||||||
import Newsletter from '../namespace.js';
|
import Newsletter from '../namespace.js';
|
||||||
|
|
||||||
// create new "newsletter" view for all posts from the past X days that haven't been scheduled yet
|
// create new "newsletter" view for all posts from the past X days that haven't been scheduled yet
|
||||||
|
@ -14,7 +15,7 @@ Posts.views.add("newsletter", function (terms) {
|
||||||
scheduledAt: {$exists: false}
|
scheduledAt: {$exists: false}
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
sort: {baseScore: -1},
|
sort: {baseScore: -1},
|
||||||
limit: terms.limit
|
limit: terms.limit
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -32,14 +33,14 @@ Newsletter.getPosts = function (postsCount) {
|
||||||
// if there is a last newsletter and it was sent less than 7 days ago use its date, else default to posts from the last 7 days
|
// if there is a last newsletter and it was sent less than 7 days ago use its date, else default to posts from the last 7 days
|
||||||
var lastWeek = moment().subtract(7, 'days');
|
var lastWeek = moment().subtract(7, 'days');
|
||||||
var after = (lastNewsletter && moment(lastNewsletter.finishedAt).isAfter(lastWeek)) ? lastNewsletter.finishedAt : lastWeek.format("YYYY-MM-DD");
|
var after = (lastNewsletter && moment(lastNewsletter.finishedAt).isAfter(lastWeek)) ? lastNewsletter.finishedAt : lastWeek.format("YYYY-MM-DD");
|
||||||
|
|
||||||
// get parameters using "newsletter" view
|
// get parameters using "newsletter" view
|
||||||
var params = Posts.parameters.get({
|
var params = Posts.parameters.get({
|
||||||
view: "newsletter",
|
view: "newsletter",
|
||||||
after: after,
|
after: after,
|
||||||
limit: postsCount
|
limit: postsCount
|
||||||
});
|
});
|
||||||
|
|
||||||
return Posts.find(params.selector, params.options).fetch();
|
return Posts.find(params.selector, params.options).fetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ Newsletter.build = function (postsArray) {
|
||||||
|
|
||||||
// get the two highest-scoring comments
|
// get the two highest-scoring comments
|
||||||
properties.popularComments = Comments.find({postId: post._id}, {sort: {score: -1}, limit: 2, transform: function (comment) {
|
properties.popularComments = Comments.find({postId: post._id}, {sort: {score: -1}, limit: 2, transform: function (comment) {
|
||||||
|
|
||||||
// get comment author
|
// get comment author
|
||||||
var user = Users.findOne(comment.userId);
|
var user = Users.findOne(comment.userId);
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ Newsletter.build = function (postsArray) {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
comment.authorAvatarUrl = false;
|
comment.authorAvatarUrl = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment;
|
return comment;
|
||||||
|
|
||||||
}}).fetch();
|
}}).fetch();
|
||||||
|
@ -151,13 +152,13 @@ Newsletter.build = function (postsArray) {
|
||||||
var emailHTML = NovaEmail.buildTemplate(newsletterHTML, {
|
var emailHTML = NovaEmail.buildTemplate(newsletterHTML, {
|
||||||
date: moment().format("dddd, MMMM D YYYY")
|
date: moment().format("dddd, MMMM D YYYY")
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. build campaign object and return it
|
// 4. build campaign object and return it
|
||||||
var campaign = {
|
var campaign = {
|
||||||
postIds: _.pluck(postsArray, '_id'),
|
postIds: _.pluck(postsArray, '_id'),
|
||||||
subject: Telescope.utils.trimWords(subject, 15),
|
subject: Telescope.utils.trimWords(subject, 15),
|
||||||
html: emailHTML
|
html: emailHTML
|
||||||
};
|
};
|
||||||
|
|
||||||
return campaign;
|
return campaign;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@ Telescope.notifications.create = (userIds, notificationName, data) => {
|
||||||
if (!!userEmail) {
|
if (!!userEmail) {
|
||||||
NovaEmail.buildAndSendHTML(Users.getEmail(user), subject, html);
|
NovaEmail.buildAndSendHTML(Users.getEmail(user), subject, html);
|
||||||
} else {
|
} else {
|
||||||
console.log(`// Couldn't send notification: admin user ${user._id} doesn't have an email`);
|
console.log(`// Couldn't send notification: admin user ${user._id} doesn't have an email`); // eslint-disable-line
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,7 @@ Telescope.callbacks.add("posts.edit.sync", PostsEditSetPostedAt);
|
||||||
// ------------------------------------- posts.edit.async -------------------------------- //
|
// ------------------------------------- posts.edit.async -------------------------------- //
|
||||||
|
|
||||||
function PostsEditRunPostApprovedCallbacks (post, oldPost) {
|
function PostsEditRunPostApprovedCallbacks (post, oldPost) {
|
||||||
var now = new Date();
|
// var now = new Date();
|
||||||
|
|
||||||
if (Posts.isApproved(post) && !Posts.isApproved(oldPost)) {
|
if (Posts.isApproved(post) && !Posts.isApproved(oldPost)) {
|
||||||
Telescope.callbacks.runAsync("posts.approve.async", post);
|
Telescope.callbacks.runAsync("posts.approve.async", post);
|
||||||
|
@ -388,7 +388,7 @@ Telescope.callbacks.add("posts.approve.async", PostsApprovedNotification);
|
||||||
|
|
||||||
function UsersRemoveDeletePosts (user, options) {
|
function UsersRemoveDeletePosts (user, options) {
|
||||||
if (options && options.deletePosts) {
|
if (options && options.deletePosts) {
|
||||||
Posts.remove({userId: userId});
|
Posts.remove({userId: user._id});
|
||||||
} else {
|
} else {
|
||||||
// not sure if anything should be done in that scenario yet
|
// not sure if anything should be done in that scenario yet
|
||||||
// Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
|
// Posts.update({userId: userId}, {$set: {author: "\[deleted\]"}}, {multi: true});
|
||||||
|
|
|
@ -4,16 +4,16 @@ const returnEmptyObject = function () {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(Mongo)
|
console.log(Mongo); // eslint-disable-line
|
||||||
|
|
||||||
const Mongo = typeof Mongo !== "undefined" ? Mongo : {
|
const Mongo = typeof Mongo !== "undefined" ? Mongo : {
|
||||||
Collection: function () {
|
Collection: function () {
|
||||||
return {attachSchema: returnEmptyObject}
|
return {attachSchema: returnEmptyObject}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("// Mongo")
|
console.log("// Mongo"); // eslint-disable-line
|
||||||
console.log(Mongo)
|
console.log(Mongo); // eslint-disable-line
|
||||||
|
|
||||||
const Meteor = typeof Meteor !== "undefined" ? Meteor : {
|
const Meteor = typeof Meteor !== "undefined" ? Meteor : {
|
||||||
methods: returnEmptyObject
|
methods: returnEmptyObject
|
||||||
|
@ -22,4 +22,4 @@ const Meteor = typeof Meteor !== "undefined" ? Meteor : {
|
||||||
const SimpleSchema = typeof SimpleSchema !== "undefined" ? SimpleSchema : returnEmptyObject;
|
const SimpleSchema = typeof SimpleSchema !== "undefined" ? SimpleSchema : returnEmptyObject;
|
||||||
|
|
||||||
const Foo = "bar"
|
const Foo = "bar"
|
||||||
export { Mongo, Foo }
|
export { Mongo, Foo }
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from './collection.js'
|
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
import Events from "meteor/nova:events";
|
import Events from 'meteor/nova:events';
|
||||||
|
import { Messages } from 'meteor/nova:core';
|
||||||
|
import Posts from './collection.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -113,7 +114,7 @@ Meteor.methods({
|
||||||
* @param {Object} modifier - the update modifier
|
* @param {Object} modifier - the update modifier
|
||||||
*/
|
*/
|
||||||
'posts.edit': function (postId, modifier) {
|
'posts.edit': function (postId, modifier) {
|
||||||
|
|
||||||
Posts.simpleSchema().namedContext("posts.edit").validate(modifier, {modifier: true});
|
Posts.simpleSchema().namedContext("posts.edit").validate(modifier, {modifier: true});
|
||||||
check(postId, String);
|
check(postId, String);
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ Meteor.methods({
|
||||||
'posts.approve': function(postId){
|
'posts.approve': function(postId){
|
||||||
|
|
||||||
check(postId, String);
|
check(postId, String);
|
||||||
|
|
||||||
const post = Posts.findOne(postId);
|
const post = Posts.findOne(postId);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ Meteor.methods({
|
||||||
if (!post.postedAt) {
|
if (!post.postedAt) {
|
||||||
set.postedAt = now;
|
set.postedAt = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
Posts.update(post._id, {$set: set});
|
Posts.update(post._id, {$set: set});
|
||||||
|
|
||||||
Telescope.callbacks.runAsync("posts.approve.async", post);
|
Telescope.callbacks.runAsync("posts.approve.async", post);
|
||||||
|
@ -164,15 +165,15 @@ Meteor.methods({
|
||||||
'posts.reject': function(postId){
|
'posts.reject': function(postId){
|
||||||
|
|
||||||
check(postId, String);
|
check(postId, String);
|
||||||
|
|
||||||
const post = Posts.findOne(postId);
|
const post = Posts.findOne(postId);
|
||||||
|
|
||||||
if(Users.isAdmin(Meteor.user())){
|
if(Users.isAdmin(Meteor.user())){
|
||||||
|
|
||||||
Posts.update(post._id, {$set: {status: Posts.config.STATUS_REJECTED}});
|
Posts.update(post._id, {$set: {status: Posts.config.STATUS_REJECTED}});
|
||||||
|
|
||||||
Telescope.callbacks.runAsync("postRejectAsync", post);
|
Telescope.callbacks.runAsync("postRejectAsync", post);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
Messages.flash('You need to be an admin to do that.', "error");
|
Messages.flash('You need to be an admin to do that.', "error");
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ Meteor.methods({
|
||||||
|
|
||||||
check(postId, String);
|
check(postId, String);
|
||||||
check(sessionId, Match.Any);
|
check(sessionId, Match.Any);
|
||||||
|
|
||||||
// only let users increment a post's view counter once per session
|
// only let users increment a post's view counter once per session
|
||||||
var view = {_id: postId, userId: this.userId, sessionId: sessionId};
|
var view = {_id: postId, userId: this.userId, sessionId: sessionId};
|
||||||
|
|
||||||
|
@ -237,7 +238,7 @@ Meteor.methods({
|
||||||
* @param {String} url - the URL to check
|
* @param {String} url - the URL to check
|
||||||
*/
|
*/
|
||||||
'posts.checkForDuplicates': function (url) {
|
'posts.checkForDuplicates': function (url) {
|
||||||
Posts.checkForSameUrl(url);
|
Posts.checkForSameUrl(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from './collection.js'
|
import { Injected } from 'meteor/meteorhacks:inject-initial';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import Posts from './collection.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Parameter callbacks let you add parameters to subscriptions
|
* @summary Parameter callbacks let you add parameters to subscriptions
|
||||||
* @namespace Posts.parameters
|
* @namespace Posts.parameters
|
||||||
*/
|
*/
|
||||||
Posts.parameters = {};
|
Posts.parameters = {};
|
||||||
|
@ -32,25 +33,25 @@ Posts.parameters.get = function (terms) {
|
||||||
|
|
||||||
// iterate over posts.parameters callbacks
|
// iterate over posts.parameters callbacks
|
||||||
parameters = Telescope.callbacks.run("posts.parameters", parameters, _.clone(terms));
|
parameters = Telescope.callbacks.run("posts.parameters", parameters, _.clone(terms));
|
||||||
|
|
||||||
// if sort options are not provided, default to "createdAt" sort
|
// if sort options are not provided, default to "createdAt" sort
|
||||||
if (_.isEmpty(parameters.options.sort)) {
|
if (_.isEmpty(parameters.options.sort)) {
|
||||||
parameters.options.sort = {sticky: -1, createdAt: -1};
|
parameters.options.sort = {sticky: -1, createdAt: -1};
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend sort to sort posts by _id to break ties
|
// extend sort to sort posts by _id to break ties
|
||||||
// NOTE: always do this last to avoid _id sort overriding another sort
|
// NOTE: always do this last to avoid _id sort overriding another sort
|
||||||
parameters = Telescope.utils.deepExtend(true, parameters, {options: {sort: {_id: -1}}});
|
parameters = Telescope.utils.deepExtend(true, parameters, {options: {sort: {_id: -1}}});
|
||||||
|
|
||||||
// console.log(parameters);
|
// console.log(parameters);
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameter callbacks
|
// Parameter callbacks
|
||||||
|
|
||||||
// View Parameter
|
// View Parameter
|
||||||
// Add a "view" property to terms which can be used to filter posts.
|
// Add a "view" property to terms which can be used to filter posts.
|
||||||
function addViewParameter (parameters, terms) {
|
function addViewParameter (parameters, terms) {
|
||||||
|
|
||||||
// if view is not defined, default to "new"
|
// if view is not defined, default to "new"
|
||||||
|
@ -65,25 +66,25 @@ function addViewParameter (parameters, terms) {
|
||||||
Telescope.callbacks.add("posts.parameters", addViewParameter);
|
Telescope.callbacks.add("posts.parameters", addViewParameter);
|
||||||
|
|
||||||
// View Parameter
|
// View Parameter
|
||||||
// Add "after" and "before" properties to terms which can be used to limit posts in time.
|
// Add "after" and "before" properties to terms which can be used to limit posts in time.
|
||||||
function addTimeParameter (parameters, terms) {
|
function addTimeParameter (parameters, terms) {
|
||||||
|
|
||||||
// console.log("// addTimeParameter")
|
// console.log("// addTimeParameter")
|
||||||
|
|
||||||
if (typeof parameters.selector.postedAt === "undefined") {
|
if (typeof parameters.selector.postedAt === "undefined") {
|
||||||
|
|
||||||
let postedAt = {}, mAfter, mBefore, startOfDay, endOfDay, clientTimezoneOffset, serverTimezoneOffset, timeDifference;
|
let postedAt = {}, mAfter, mBefore, startOfDay, endOfDay, clientTimezoneOffset, serverTimezoneOffset, timeDifference;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
If we're on the client, add the time difference between client and server
|
If we're on the client, add the time difference between client and server
|
||||||
|
|
||||||
Example: client is on Japanese time (+9 hours),
|
Example: client is on Japanese time (+9 hours),
|
||||||
server on UCT (Greenwich) time (+0 hours), for a total difference of +9 hours.
|
server on UCT (Greenwich) time (+0 hours), for a total difference of +9 hours.
|
||||||
|
|
||||||
So the time "00:00, UCT" is equivalent to "09:00, JST".
|
So the time "00:00, UCT" is equivalent to "09:00, JST".
|
||||||
|
|
||||||
So if we want to express the timestamp "00:00, UCT" on the client,
|
So if we want to express the timestamp "00:00, UCT" on the client,
|
||||||
we *add* 9 hours to "00:00, JST" on the client to get "09:00, JST" and
|
we *add* 9 hours to "00:00, JST" on the client to get "09:00, JST" and
|
||||||
sync up both times.
|
sync up both times.
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ function addTimeParameter (parameters, terms) {
|
||||||
clientTimezoneOffset = -1 * new Date().getTimezoneOffset();
|
clientTimezoneOffset = -1 * new Date().getTimezoneOffset();
|
||||||
serverTimezoneOffset = -1 * Injected.obj('serverTimezoneOffset').offset;
|
serverTimezoneOffset = -1 * Injected.obj('serverTimezoneOffset').offset;
|
||||||
timeDifference = clientTimezoneOffset - serverTimezoneOffset;
|
timeDifference = clientTimezoneOffset - serverTimezoneOffset;
|
||||||
|
|
||||||
// console.log("client time:"+clientTimezoneOffset);
|
// console.log("client time:"+clientTimezoneOffset);
|
||||||
// console.log("server time:"+serverTimezoneOffset);
|
// console.log("server time:"+serverTimezoneOffset);
|
||||||
// console.log("difference: "+timeDifference);
|
// console.log("difference: "+timeDifference);
|
||||||
|
@ -127,7 +128,7 @@ function addTimeParameter (parameters, terms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
postedAt.$lt = endOfDay.toDate();
|
postedAt.$lt = endOfDay.toDate();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(postedAt)) {
|
if (!_.isEmpty(postedAt)) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from './collection.js';
|
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
import Posts from './collection.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Posts config namespace
|
* @summary Posts config namespace
|
||||||
|
@ -235,7 +236,7 @@ Posts.schemaJSON = {
|
||||||
publish: true,
|
publish: true,
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
The post author's `_id`.
|
The post author's `_id`.
|
||||||
*/
|
*/
|
||||||
userId: {
|
userId: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { SyncedCron } from 'meteor/percolatestudio:synced-cron';
|
||||||
|
// import moment from 'moment';
|
||||||
import Posts from '../collection.js';
|
import Posts from '../collection.js';
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
SyncedCron.options = {
|
SyncedCron.options = {
|
||||||
log: true,
|
log: true,
|
||||||
|
@ -18,17 +19,17 @@ const addJob = function () {
|
||||||
job() {
|
job() {
|
||||||
// fetch all posts tagged as future
|
// fetch all posts tagged as future
|
||||||
const scheduledPosts = Posts.find({isFuture: true}, {fields: {_id: 1, status: 1, postedAt: 1, userId: 1, title: 1}}).fetch();
|
const scheduledPosts = Posts.find({isFuture: true}, {fields: {_id: 1, status: 1, postedAt: 1, userId: 1, title: 1}}).fetch();
|
||||||
|
|
||||||
// filter the scheduled posts to retrieve only the one that should update, considering their schedule
|
// filter the scheduled posts to retrieve only the one that should update, considering their schedule
|
||||||
const postsToUpdate = scheduledPosts.filter(post => post.postedAt <= new Date());
|
const postsToUpdate = scheduledPosts.filter(post => post.postedAt <= new Date());
|
||||||
|
|
||||||
// update posts found
|
// update posts found
|
||||||
if (!_.isEmpty(postsToUpdate)) {
|
if (!_.isEmpty(postsToUpdate)) {
|
||||||
const postsIds = _.pluck(postsToUpdate, '_id');
|
const postsIds = _.pluck(postsToUpdate, '_id');
|
||||||
Posts.update({_id: {$in: postsIds}}, {$set: {isFuture: false}}, {multi: true});
|
Posts.update({_id: {$in: postsIds}}, {$set: {isFuture: false}}, {multi: true});
|
||||||
|
|
||||||
// log the action
|
// log the action
|
||||||
console.log('// Scheduled posts approved:', postsIds);
|
console.log('// Scheduled posts approved:', postsIds); // eslint-disable-line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Posts from '../collection.js';
|
|
||||||
// import Comments from "meteor/nova:comments";
|
// import Comments from "meteor/nova:comments";
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { Counts } from 'meteor/tmeasday:publish-counts';
|
||||||
|
import Posts from '../collection.js';
|
||||||
|
|
||||||
Posts._ensureIndex({"status": 1, "postedAt": 1});
|
Posts._ensureIndex({"status": 1, "postedAt": 1});
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ const getPostsListUsers = posts => {
|
||||||
userIds = _.unique(userIds);
|
userIds = _.unique(userIds);
|
||||||
|
|
||||||
return Users.find({_id: {$in: userIds}}, {fields: Users.publishedFields.list});
|
return Users.find({_id: {$in: userIds}}, {fields: Users.publishedFields.list});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,12 +38,12 @@ const getSinglePostUsers = post => {
|
||||||
|
|
||||||
let users = [post.userId]; // publish post author's ID
|
let users = [post.userId]; // publish post author's ID
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NOTE: to avoid circular dependencies between nova:posts and nova:comments,
|
NOTE: to avoid circular dependencies between nova:posts and nova:comments,
|
||||||
use callback hook to get comment authors
|
use callback hook to get comment authors
|
||||||
*/
|
*/
|
||||||
users = Telescope.callbacks.run("posts.single.getUsers", users, post);
|
users = Telescope.callbacks.run("posts.single.getUsers", users, post);
|
||||||
|
|
||||||
// add upvoters
|
// add upvoters
|
||||||
if (post.upvoters && post.upvoters.length) {
|
if (post.upvoters && post.upvoters.length) {
|
||||||
users = users.concat(post.upvoters);
|
users = users.concat(post.upvoters);
|
||||||
|
@ -67,15 +68,15 @@ const getSinglePostUsers = post => {
|
||||||
*/
|
*/
|
||||||
Meteor.publish('posts.list', function (terms) {
|
Meteor.publish('posts.list', function (terms) {
|
||||||
|
|
||||||
// this.unblock(); // causes bug where publication returns 0 results
|
// this.unblock(); // causes bug where publication returns 0 results
|
||||||
|
|
||||||
this.autorun(function () {
|
this.autorun(function () {
|
||||||
|
|
||||||
const currentUser = this.userId && Users.findOne(this.userId);
|
const currentUser = this.userId && Users.findOne(this.userId);
|
||||||
|
|
||||||
terms.currentUserId = this.userId; // add currentUserId to terms
|
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||||
const {selector, options} = Posts.parameters.get(terms);
|
const {selector, options} = Posts.parameters.get(terms);
|
||||||
|
|
||||||
Counts.publish(this, terms.listId, Posts.find(selector, options), {noReady: true});
|
Counts.publish(this, terms.listId, Posts.find(selector, options), {noReady: true});
|
||||||
|
|
||||||
options.fields = Posts.publishedFields.list;
|
options.fields = Posts.publishedFields.list;
|
||||||
|
@ -90,7 +91,7 @@ Meteor.publish('posts.list', function (terms) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return Users.canDo(currentUser, "posts.view.approved.all") ? [posts, users] : [];
|
return Users.canDo(currentUser, "posts.view.approved.all") ? [posts, users] : [];
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -112,8 +113,8 @@ Meteor.publish('posts.single', function (terms) {
|
||||||
const users = getSinglePostUsers(post);
|
const users = getSinglePostUsers(post);
|
||||||
return Users.canView(currentUser, post) ? [posts, users] : [];
|
return Users.canView(currentUser, post) ? [posts, users] : [];
|
||||||
} else {
|
} else {
|
||||||
console.log(`// posts.single: no post found for _id “${terms._id}”`)
|
console.log(`// posts.single: no post found for _id “${terms._id}”`); // eslint-disable-line
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import Posts from '../collection.js';
|
import { Picker } from 'meteor/meteorhacks:picker';
|
||||||
import escapeStringRegexp from 'escape-string-regexp';
|
import escapeStringRegexp from 'escape-string-regexp';
|
||||||
|
import Posts from '../collection.js';
|
||||||
|
|
||||||
Picker.route('/out', function(params, req, res, next) {
|
Picker.route('/out', function(params, req, res, next) {
|
||||||
var query = params.query;
|
var query = params.query;
|
||||||
if(query.url){ // for some reason, query.url doesn't need to be decoded
|
if(query.url){ // for some reason, query.url doesn't need to be decoded
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the URL passed to ?url= is in plain text, any hash fragment
|
If the URL passed to ?url= is in plain text, any hash fragment
|
||||||
will get stripped out.
|
will get stripped out.
|
||||||
So we search for any post whose URL contains the current URL to get a match
|
So we search for any post whose URL contains the current URL to get a match
|
||||||
|
@ -25,4 +26,4 @@ Picker.route('/out', function(params, req, res, next) {
|
||||||
} else {
|
} else {
|
||||||
res.end("Please provide a URL");
|
res.end("Please provide a URL");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Users from 'meteor/nova:users';
|
||||||
import Posts from './collection.js'
|
import Posts from './collection.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,7 +104,7 @@ Posts.views.add("userPosts", function (terms) {
|
||||||
isFuture: {$ne: true}
|
isFuture: {$ne: true}
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
limit: 5,
|
limit: 5,
|
||||||
sort: {
|
sort: {
|
||||||
postedAt: -1
|
postedAt: -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Picker } from 'meteor/meteorhacks:picker';
|
||||||
import { servePostRSS, serveCommentRSS } from './rss.js';
|
import { servePostRSS, serveCommentRSS } from './rss.js';
|
||||||
|
|
||||||
Picker.route('/feed.xml', function(params, req, res, next) {
|
Picker.route('/feed.xml', function(params, req, res, next) {
|
||||||
|
|
|
@ -52,9 +52,9 @@ const serveCommentRSS = function (terms, url) {
|
||||||
var feed = new RSS(getMeta(url));
|
var feed = new RSS(getMeta(url));
|
||||||
|
|
||||||
Comments.find({isDeleted: {$ne: true}}, {sort: {postedAt: -1}, limit: 20}).forEach(function(comment) {
|
Comments.find({isDeleted: {$ne: true}}, {sort: {postedAt: -1}, limit: 20}).forEach(function(comment) {
|
||||||
post = Posts.findOne(comment.postId);
|
var post = Posts.findOne(comment.postId);
|
||||||
feed.item({
|
feed.item({
|
||||||
title: 'Comment on '+post.title,
|
title: 'Comment on ' + post.title,
|
||||||
description: `${comment.body}</br></br><a href="${comment.getPageUrl(true)}">Discuss</a>`,
|
description: `${comment.body}</br></br><a href="${comment.getPageUrl(true)}">Discuss</a>`,
|
||||||
author: comment.author,
|
author: comment.author,
|
||||||
date: comment.postedAt,
|
date: comment.postedAt,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Users from 'meteor/nova:users';
|
import Users from 'meteor/nova:users';
|
||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
const isInSettingsJSON = function () {
|
const isInSettingsJSON = function () {
|
||||||
// settings can either be in settings json's public, or in the special object we publish only for admins for private settings
|
// settings can either be in settings json's public, or in the special object we publish only for admins for private settings
|
||||||
|
@ -371,4 +372,4 @@ Telescope.settings.schema = new SimpleSchema({
|
||||||
|
|
||||||
Telescope.settings.collection.attachSchema(Telescope.settings.schema);
|
Telescope.settings.collection.attachSchema(Telescope.settings.schema);
|
||||||
|
|
||||||
Telescope.subscriptions.preload("settings");
|
Telescope.subscriptions.preload("settings");
|
||||||
|
|
|
@ -16,7 +16,7 @@ Meteor.methods({
|
||||||
"settings.exportToJSON": function () {
|
"settings.exportToJSON": function () {
|
||||||
if (Users.isAdminById(this.userId)) {
|
if (Users.isAdminById(this.userId)) {
|
||||||
let settings = Telescope.settings.collection.findOne();
|
let settings = Telescope.settings.collection.findOne();
|
||||||
const schema = Telescope.settings.collection.simpleSchema()._schema;
|
// const schema = Telescope.settings.collection.simpleSchema()._schema;
|
||||||
const publicFields = Telescope.settings.collection.getPublicFields();
|
const publicFields = Telescope.settings.collection.getPublicFields();
|
||||||
delete settings._id;
|
delete settings._id;
|
||||||
settings.public = {};
|
settings.public = {};
|
||||||
|
@ -26,7 +26,7 @@ Meteor.methods({
|
||||||
delete settings[key];
|
delete settings[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(JSON.stringify(settings, null, 2));
|
console.log(JSON.stringify(settings, null, 2)); // eslint-disable-line
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -36,4 +36,4 @@ Meteor.methods({
|
||||||
Telescope.settings.collection.update(settings._id, {}, {validate: false});
|
Telescope.settings.collection.update(settings._id, {}, {validate: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import PublicationUtils from 'meteor/utilities:smart-publications';
|
import PublicationUtils from 'meteor/utilities:smart-publications';
|
||||||
import Users from "meteor/nova:users";
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
Users.addField([
|
Users.addField([
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,13 +6,13 @@ import Users from 'meteor/nova:users';
|
||||||
* @param {Collection} collection
|
* @param {Collection} collection
|
||||||
* @param {String} itemId
|
* @param {String} itemId
|
||||||
* @param {Object} user
|
* @param {Object} user
|
||||||
* @returns {Object} collectionName, fields: object, item, hasSubscribedItem: boolean
|
* @returns {Object} collectionName, fields: object, item, hasSubscribedItem: boolean
|
||||||
*/
|
*/
|
||||||
const prepareSubscription = (action, collection, itemId, user) => {
|
const prepareSubscription = (action, collection, itemId, user) => {
|
||||||
|
|
||||||
// get item's collection name
|
// get item's collection name
|
||||||
const collectionName = collection._name.slice(0,1).toUpperCase() + collection._name.slice(1);
|
const collectionName = collection._name.slice(0,1).toUpperCase() + collection._name.slice(1);
|
||||||
|
|
||||||
// get item data
|
// get item data
|
||||||
const item = collection.findOne(itemId);
|
const item = collection.findOne(itemId);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const prepareSubscription = (action, collection, itemId, user) => {
|
||||||
if (!user || !item) {
|
if (!user || !item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// edge case: Users collection
|
// edge case: Users collection
|
||||||
if (collectionName === 'Users') {
|
if (collectionName === 'Users') {
|
||||||
// someone can't subscribe to themself, abort process
|
// someone can't subscribe to themself, abort process
|
||||||
|
@ -35,12 +35,12 @@ const prepareSubscription = (action, collection, itemId, user) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the right fields depending on the collection
|
// assign the right fields depending on the collection
|
||||||
const fields = {
|
const fields = {
|
||||||
subscribers: collectionName === 'Users' ? 'telescope.subscribers' : 'subscribers',
|
subscribers: collectionName === 'Users' ? 'telescope.subscribers' : 'subscribers',
|
||||||
subscriberCount: collectionName === 'Users' ? 'telescope.subscriberCount' : 'subscriberCount',
|
subscriberCount: collectionName === 'Users' ? 'telescope.subscriberCount' : 'subscriberCount',
|
||||||
};
|
};
|
||||||
|
|
||||||
// return true if the item has the subscriber's id in its fields
|
// return true if the item has the subscriber's id in its fields
|
||||||
const hasSubscribedItem = !!_.deep(item, fields.subscribers) && _.deep(item, fields.subscribers) && _.deep(item, fields.subscribers).indexOf(user._id) !== -1;
|
const hasSubscribedItem = !!_.deep(item, fields.subscribers) && _.deep(item, fields.subscribers) && _.deep(item, fields.subscribers).indexOf(user._id) !== -1;
|
||||||
|
|
||||||
// assign the right update operator and count depending on the action type
|
// assign the right update operator and count depending on the action type
|
||||||
|
@ -107,7 +107,7 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
||||||
itemId: item._id,
|
itemId: item._id,
|
||||||
};
|
};
|
||||||
|
|
||||||
// in case of subscription, log also the date
|
// in case of subscription, log also the date
|
||||||
if (action === 'subscribe') {
|
if (action === 'subscribe') {
|
||||||
loggedItem = {
|
loggedItem = {
|
||||||
...loggedItem,
|
...loggedItem,
|
||||||
|
@ -129,11 +129,12 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Generate methods 'collection.subscribe' & 'collection.unsubscribe' automatically
|
* @summary Generate methods 'collection.subscribe' & 'collection.unsubscribe' automatically
|
||||||
* @params {Array[Collections]} collections
|
* @params {Array[Collections]} collections
|
||||||
*/
|
*/
|
||||||
|
let subscribeMethodsGenerator;
|
||||||
export default subscribeMethodsGenerator = (collection) => {
|
export default subscribeMethodsGenerator = (collection) => {
|
||||||
|
|
||||||
// generic method function calling the performSubscriptionAction
|
// generic method function calling the performSubscriptionAction
|
||||||
const genericMethodFunction = (col, action) => {
|
const genericMethodFunction = (col, action) => {
|
||||||
// return the method code
|
// return the method code
|
||||||
|
@ -151,7 +152,7 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
||||||
return performSubscriptionAction(action, col, docId, user);
|
return performSubscriptionAction(action, col, docId, user);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const collectionName = collection._name;
|
const collectionName = collection._name;
|
||||||
// return an object of the shape expected by Meteor.methods
|
// return an object of the shape expected by Meteor.methods
|
||||||
return {
|
return {
|
||||||
|
@ -162,7 +163,7 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
||||||
|
|
||||||
// Finally. Add the methods to the Meteor namespace 🖖
|
// Finally. Add the methods to the Meteor namespace 🖖
|
||||||
|
|
||||||
// nova:users is a dependency of this package, it is alreay imported
|
// nova:users is a dependency of this package, it is alreay imported
|
||||||
Meteor.methods(subscribeMethodsGenerator(Users));
|
Meteor.methods(subscribeMethodsGenerator(Users));
|
||||||
|
|
||||||
// check if nova:posts exists, if yes, add the methods to Posts
|
// check if nova:posts exists, if yes, add the methods to Posts
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
if (typeof Package['nova:posts'] !== "undefined") {
|
if (typeof Package['nova:posts'] !== "undefined") {
|
||||||
import Posts from "meteor/nova:posts";
|
import Posts from "meteor/nova:posts";
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Gravatar } from 'meteor/jparker:gravatar';
|
||||||
import Users from './collection.js';
|
import Users from './collection.js';
|
||||||
|
|
||||||
// var _ = require('underscore');
|
// var _ = require('underscore');
|
||||||
|
@ -191,7 +192,7 @@ Users.avatar = {
|
||||||
return service[0];
|
return service[0];
|
||||||
},
|
},
|
||||||
|
|
||||||
computeUrl: function(prop) {
|
computeUrl: function(prop, user) {
|
||||||
if (typeof prop === 'function') {
|
if (typeof prop === 'function') {
|
||||||
prop = prop.call(user);
|
prop = prop.call(user);
|
||||||
}
|
}
|
||||||
|
@ -210,9 +211,9 @@ Users.avatar = {
|
||||||
|
|
||||||
var customProp = user && this.options.customImageProperty;
|
var customProp = user && this.options.customImageProperty;
|
||||||
if (typeof customProp === 'function') {
|
if (typeof customProp === 'function') {
|
||||||
return this.computeUrl(customProp);
|
return this.computeUrl(customProp, user);
|
||||||
} else if (customProp) {
|
} else if (customProp) {
|
||||||
return this.computeUrl(this.getDescendantProp(user, customProp));
|
return this.computeUrl(this.getDescendantProp(user, customProp), user);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -230,7 +231,7 @@ Users.avatar = {
|
||||||
}
|
}
|
||||||
|
|
||||||
var emailOrHash = this.getUserEmail(user) || Users.getEmailHash(user);
|
var emailOrHash = this.getUserEmail(user) || Users.getEmailHash(user);
|
||||||
var secure = true;
|
// var secure = true;
|
||||||
var options = {
|
var options = {
|
||||||
// NOTE: Gravatar's default option requires a publicly accessible URL,
|
// NOTE: Gravatar's default option requires a publicly accessible URL,
|
||||||
// so it won't work when your app is running on localhost and you're
|
// so it won't work when your app is running on localhost and you're
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Users from './collection.js';
|
|
||||||
import marked from 'marked';
|
|
||||||
import Events from "meteor/nova:events";
|
import Events from "meteor/nova:events";
|
||||||
import NovaEmail from 'meteor/nova:email';
|
import NovaEmail from 'meteor/nova:email';
|
||||||
|
import { Gravatar } from 'meteor/jparker:gravatar';
|
||||||
|
import marked from 'marked';
|
||||||
|
import Users from './collection.js';
|
||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// Collection Hooks //
|
// Collection Hooks //
|
||||||
|
@ -130,7 +131,7 @@ function setupUser (user, options) {
|
||||||
user.telescope.displayName = user.services.linkedin.firstName + " " + user.services.linkedin.lastName;
|
user.telescope.displayName = user.services.linkedin.firstName + " " + user.services.linkedin.lastName;
|
||||||
} else {
|
} else {
|
||||||
user.telescope.displayName = user.username;
|
user.telescope.displayName = user.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a basic slug from display name and then modify it if this slugs already exists;
|
// create a basic slug from display name and then modify it if this slugs already exists;
|
||||||
const basicSlug = Telescope.utils.slugify(user.telescope.displayName);
|
const basicSlug = Telescope.utils.slugify(user.telescope.displayName);
|
||||||
|
|
|
@ -39,7 +39,7 @@ Users.getUserName = function (user) {
|
||||||
return user.services.twitter.screenName;
|
return user.services.twitter.screenName;
|
||||||
}
|
}
|
||||||
catch (error){
|
catch (error){
|
||||||
console.log(error);
|
console.log(error); // eslint-disable-line
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Telescope from 'meteor/nova:lib';
|
import Telescope from 'meteor/nova:lib';
|
||||||
import Users from './collection.js';
|
import Users from './collection.js';
|
||||||
|
|
||||||
|
/*
|
||||||
var completeUserProfile = function (userId, modifier, user) {
|
var completeUserProfile = function (userId, modifier, user) {
|
||||||
|
|
||||||
Users.update(userId, modifier);
|
Users.update(userId, modifier);
|
||||||
|
@ -10,6 +11,7 @@ var completeUserProfile = function (userId, modifier, user) {
|
||||||
return Users.findOne(userId);
|
return Users.findOne(userId);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
Users.methods = {};
|
Users.methods = {};
|
||||||
|
|
||||||
|
@ -97,7 +99,7 @@ Meteor.methods({
|
||||||
},
|
},
|
||||||
|
|
||||||
'users.remove'(userId, options) {
|
'users.remove'(userId, options) {
|
||||||
|
|
||||||
// do the user which to delete his account or another user?
|
// do the user which to delete his account or another user?
|
||||||
const actionType = this.userId === userId ? "own" : "all";
|
const actionType = this.userId === userId ? "own" : "all";
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue