mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 10:01:40 -05:00
commit
84a090f01a
87 changed files with 420 additions and 444 deletions
1
Dockerfile
Normal file
1
Dockerfile
Normal file
|
@ -0,0 +1 @@
|
|||
FROM abernix/meteord:onbuild
|
47
History.md
47
History.md
|
@ -1,8 +1,35 @@
|
|||
## vNEXT
|
||||
|
||||
Apollo integration, Webpack build (work in progress on `apollo` & `webpack` branches).
|
||||
|
||||
## v0.27.3
|
||||
|
||||
- Explain with more details how to deploy with Meteor Up (PR [#1456](https://github.com/TelescopeJS/Telescope/pull/1456), thanks [@asmita005](https://github.com/asmita005)!).
|
||||
- Add slug to `newPendingPost` notifications, fixes [#1254](https://github.com/TelescopeJS/Telescope/issues/1254).
|
||||
- Ensure slug unicity on user's slug as done as category's slug (use of `Telescope.utils.getUnusedSlug`), fixes [#1213](https://github.com/TelescopeJS/Telescope/issues/1213).
|
||||
- Remove some dead code from Telescope Legacy.
|
||||
- Use of Comment's `getPageUrl` helper in `nova:rss`.
|
||||
- Prefer `Users` namespace to `Meteor.users` in active packages.
|
||||
- If you used the property `autoform` on your custom fields, it's now entitled `form`. This was an old reference to [AutoForm](https://github.com/aldeed/meteor-autoform) used by Telescope Legacy. We will give you a console warning if you still use it to advice you to change it.
|
||||
- Fix errors on `nova:forms`: callbacks from components wrapping a `NovaForm` (ex: `ModalTrigger`) are not fired anymore when it has already been unmounted.
|
||||
- Fix errors when logging out from the "profile check modal" (`UsersProfileCheck`).
|
||||
- Prevent errors when creating/editing a category with custom fields (load order of smart methods with extended schema).
|
||||
- The callback on `nova:subscribe` related to categories has been updated to prevent a user from receiving multiple emails if he/she is subscribed to multiple categories (PR [#1466](https://github.com/TelescopeJS/Telescope/pull/1466), thanks [@chptung](https://github.com/chptung)).
|
||||
- You can now submit a post/comments (or any `NovaForm` comp) with CMD + Enter / Ctrl + Enter shortcuts (PR [#1472](https://github.com/TelescopeJS/Telescope/pull/1472), thanks [@aszx87410](https://github.com/aszx87410)).
|
||||
- You can run Telescope Nova inside Docker without deploying (see [this awesome guide](http://spartatek.se/meteor_blog/docker/2016/01/12/running-telescope.html)), fixes [#1477](https://github.com/TelescopeJS/Telescope/issues/1477)
|
||||
- Add `flex-wrap: wrap;` to posts-categories class for better styling if a user creates a post with too many categories (PR [#1469](https://github.com/TelescopeJS/Telescope/pull/1469), thanks [@chptung](https://github.com/chptung)).
|
||||
|
||||
**Changes that may break some parts of your app:**
|
||||
- Some callbacks have been renamed for consistency purposes: `postsParameters` becomes `posts.parameters`, `profileCompletedAsync` becomes `users.profileCompleted.async`, `profileCompletedChecks` becomes `users.profileCompleted.sync`, `onCreateUserAsync` becomes `users.new.async`, `onCreateUser` becomes `users.new.sync`, `UsersEdit` becomes `users.edit.sync`, `UsersEditAsync` becomes `users.edit.async`.
|
||||
- The use of `react-bootstrap@0.30.3` is now forced in `package.json`: the latest versions break the dropdown at the moment (see [#1463](https://github.com/TelescopeJS/Telescope/issues/1463)). You should re-run `npm install` if you update from a previous version.
|
||||
- The `currentUser` props has been removed, the current user is explicitly passed through the context as a matter of consistency across the app. If one of your custom components extending one of `nova:base-components` used `currentUser` as a props, you should update it to use it via the context and add the corresponding contextTypes. See commit [b04cb52](https://github.com/TelescopeJS/Telescope/commit/b04cb5247027fc431f7aa1704ef823ac8ce5fdd1).
|
||||
|
||||
## v0.27.2
|
||||
- Move `updateCurrentValue` function from `propTypes` to `contextTypes` in the datetime picker`DateTime` (`nova:forms`) (#1449).
|
||||
- Check duplicate links on post's edit (#247).
|
||||
- Cloudinary images from `nova:cloudinary` are now served over HTTPS (#1224).
|
||||
- Add year and name to licence (#1117).
|
||||
|
||||
- Move `updateCurrentValue` function from `propTypes` to `contextTypes` in the datetime picker`DateTime` (`nova:forms`) ([#1449](https://github.com/TelescopeJS/Telescope/issues/1449)).
|
||||
- Check duplicate links on post's edit [(#247](https://github.com/TelescopeJS/Telescope/issues/247)).
|
||||
- Cloudinary images from `nova:cloudinary` are now served over HTTPS ([#1224](https://github.com/TelescopeJS/Telescope/issues/1224)).
|
||||
- Add year and name to licence ([#1117](https://github.com/TelescopeJS/Telescope/issues/1117)).
|
||||
- Clean Legacy's issues & PRs. Be ready for the [Hacktoberfest](https://hacktoberfest.digitalocean.com/)!! 🍻
|
||||
|
||||
## v0.27.1
|
||||
|
@ -13,16 +40,16 @@
|
|||
- Added support for a custom CSS class for `SubscribeTo` component.
|
||||
- No more global variable in `nova:api` (the last one? \o/).
|
||||
- Fix a version problem with `fourseven:scss`, now running on 3.9.0.
|
||||
- Remove unnecessary NPM dependency on `load-script` (thanks @MHerszak!).
|
||||
- You can now run Nova in Brazilian Portuguese by [adding this package](https://github.com/lukasag/nova-i18n-pt-br) (thanks @lukasag!).
|
||||
- Added support for a `defaultValue` property in `nova:forms`. You can define it in your custom fields, it will be added if no value nor prefilled value is defined (thanks @beeva-franciscocalle!).
|
||||
- Fixed edge bug when users don't have an `username`, use `displayName` instead (thanks @jeffreywyman!).
|
||||
- Remove unnecessary NPM dependency on `load-script` (thanks [@MHerszak](https://github.com/mherszak)!).
|
||||
- You can now run Nova in Brazilian Portuguese by [adding this package](https://github.com/lukasag/nova-i18n-pt-br) (thanks [@lukasag](https://github.com/lukasag)!).
|
||||
- Added support for a `defaultValue` property in `nova:forms`. You can define it in your custom fields, it will be added if no value nor prefilled value is defined (thanks [@beeva-franciscocalle](https://github.com/beeva-franciscocalle)!).
|
||||
- Fixed edge bug when users don't have an `username`, use `displayName` instead (thanks [@jeffreywyman](https://github.com/jeffreywyman)!).
|
||||
|
||||
## v0.27.0
|
||||
|
||||
- Remove Telescope global variable.
|
||||
- Update to Meteor 1.4.
|
||||
- A user can now subscribe to any collection with `nova:subscribe` package ([docs](https://github.com/TelescopeJS/Telescope/tree/master/packages/nova-subscribe)) and a reusable `SubscribeTo` component (thanks @schabluk!).
|
||||
- A user can now subscribe to any collection with `nova:subscribe` package ([docs](https://github.com/TelescopeJS/Telescope/tree/master/packages/nova-subscribe)) and a reusable `SubscribeTo` component (thanks [@schabluk](https://github.com/schabluk)!).
|
||||
|
||||
*The rest of the modifications are not yet documented, you can [browse the commits history from there](https://github.com/TelescopeJS/Telescope/commits/2b34713c0b6dbf094668f8a87d007443a1e2c580).*
|
||||
|
||||
|
@ -57,7 +84,7 @@
|
|||
- You can now see a post's ID and stats in the post edit form if you're an admin.
|
||||
- Fixed bug (I hope?) where daily view would become messed up when client and server were on different timezones.
|
||||
- Now showing a user's posts on their profile page.
|
||||
- Added soft delete for comments (thanks @justintime4tea!).
|
||||
- Added soft delete for comments (thanks [@justintime4tea](https://github.com/justintime4tea)!).
|
||||
- Fixed posts notifications bugs.
|
||||
- Got rid of a lot of Meteor packages in favor of NPM equivalents.
|
||||
|
||||
|
|
107
README.md
107
README.md
|
@ -15,8 +15,8 @@ Note that both versions use the same data format, so you can go back and forth b
|
|||
- [Getting Started](#getting-started)
|
||||
- [Updating](#updating)
|
||||
- [Resources](#resources)
|
||||
- [Deployment](#deployment)
|
||||
- [Settings](#settings)
|
||||
- [Deployment](#deployment)
|
||||
- [Categories](#categories)
|
||||
- [Social Login](#social-login)
|
||||
- [Packages](#packages)
|
||||
|
@ -36,11 +36,14 @@ Note that both versions use the same data format, so you can go back and forth b
|
|||
- [Groups & Permissions](#groups--permissions)
|
||||
- [Internationalization](#internationalization)
|
||||
- [Cheatsheet](#cheatsheet)
|
||||
- [Third-Party packages](#third-party-packages)
|
||||
|
||||
## Getting Started
|
||||
|
||||
### First Steps
|
||||
|
||||
Install the latest version of Node and NPM. We recommend the usage of [NVM](http://nvm.sh).
|
||||
|
||||
[Install Meteor](https://www.meteor.com/install):
|
||||
|
||||
```sh
|
||||
|
@ -111,10 +114,6 @@ For local development, an easy way to do that is to simply copy the `.meteor/loc
|
|||
|
||||
The best ways to get support are [Telescope Meta](http://meta.telescopeapp.org) and the [Telescope Slack Chatroom](http://slack.telescopeapp.org).
|
||||
|
||||
## Deployment
|
||||
|
||||
The recommended way to deploy Nova is by using [Mup](https://github.com/kadirahq/meteor-up/), at least v1.0.3.
|
||||
|
||||
## Settings
|
||||
|
||||
Settings can be configured in your `settings.json` file. For legacy compatibility reasons, settings can also be specified in your database, but note that settings specified in `settings.json` take priority over those stored in the database.
|
||||
|
@ -124,7 +123,78 @@ Settings can be public (meaning they will be published to the client) or private
|
|||
To use your `settings.json` file:
|
||||
|
||||
- Development: `meteor --settings settings.json`
|
||||
- Production: specify the path to `settings.json` in `mup.json`
|
||||
- Production: specify the path to `settings.json` in the tool you use to deploy (i.e. `mup deploy --settings settings.json`, see below)
|
||||
|
||||
## Deployment
|
||||
|
||||
The recommended way to deploy Nova is by using [Mup](https://github.com/kadirahq/meteor-up/), at least v1.0.3.
|
||||
|
||||
#### Configuration
|
||||
|
||||
You should have a Linux server online, for instance [a Digital Ocean droplet running with Ubuntu](https://www.digitalocean.com).
|
||||
|
||||
Install globally the latest `kadirahq/meteor-up`.
|
||||
|
||||
```
|
||||
npm install -g mup
|
||||
```
|
||||
|
||||
Create Meteor Up configuration files in your project directory with `mup init`. In the example below, the configuration files are created in a `.deploy` directory at the root of your app.
|
||||
|
||||
```
|
||||
cd my-app-folder
|
||||
mkdir .deploy
|
||||
cd .deploy
|
||||
mup init
|
||||
```
|
||||
|
||||
This will create two files :
|
||||
|
||||
```
|
||||
mup.js - Meteor Up configuration file
|
||||
settings.json - Settings for Meteor's settings API
|
||||
```
|
||||
|
||||
Then, replace the content of the newly created `settings.json` with your own settings (you can use the content of `sample_settings.json` as a starter).
|
||||
|
||||
Fill `mup.js` with your credentials and optional settings (check the [Mup repo](https://github.com/kadirahq/meteor-up) for additional docs).
|
||||
|
||||
**Note:** the `ROOT_URL` field should be the absolute url of your deploy ; and you need to explicitly point out to use `abernix/meteord:base` docker image with a `docker` field within the `meteor` object.
|
||||
|
||||
```
|
||||
...
|
||||
meteor: {
|
||||
...
|
||||
path: '../' // relative path of the app considering your mup config files
|
||||
env: {
|
||||
ROOT_URL: 'http://nova-app.com', // absolute url of your deploy
|
||||
...
|
||||
},
|
||||
...
|
||||
docker: {
|
||||
image:'abernix/meteord:base' // docker image working with meteor 1.4 & node 4
|
||||
},
|
||||
...
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
You can take inspiration (or copy/paste) on this [`mup.js` example](https://gist.github.com/xavcz/6ddc2bb6f67fe0936c8328ab3314641d).
|
||||
|
||||
#### Setup your server
|
||||
|
||||
From this folder, you can now setup Docker & Mongo your server with:
|
||||
```
|
||||
mup setup
|
||||
```
|
||||
|
||||
#### Deploy your app to your server
|
||||
|
||||
Still in the same folder, to deploy your app with your settings file:
|
||||
|
||||
```
|
||||
mup --settings settings.json
|
||||
```
|
||||
|
||||
## Categories
|
||||
|
||||
|
@ -304,7 +374,26 @@ If a component deals with a collection (`Posts`, `Comments`, etc.) its name shou
|
|||
|
||||
For example: `PostsShare`.
|
||||
|
||||
The outermost HTML element within the component will have a class of the same name, but with a dash instead: `posts-share`. If possible, classes for all other elements within the component will start with the component's class: `posts-share-button`, `posts-share-divider`, etc.
|
||||
The outermost HTML element within the component will have a class of the same name, but with a dash instead: `posts-share`. If possible, classes for all other elements within the component will start with the component's class: `posts-share-button`, `posts-share-divider`, etc.
|
||||
|
||||
### Get current user
|
||||
|
||||
The current user is given to the components via the React context. You can access it via `this.context.currentUser` (class) or `context.currentUser` (stateless-component).
|
||||
|
||||
The component needs to define `currentUser` in its `contextTypes`. If `contextTypes` is not defined, then `context` will be an empty object and you won't be able to access to the current user.
|
||||
|
||||
Example :
|
||||
```js
|
||||
const CustomHeader = (props, context) => {
|
||||
// if a user is connected, show its username; else say hello
|
||||
return context.currentUser ? <div>Hey ${context.currentUser.username}!</div> : <div>Hello!</div>
|
||||
};
|
||||
|
||||
// if you don't define `contextTypes` for `CustomHeader`, then the `context` argument will be an empty object
|
||||
CustomHeader.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
};
|
||||
```
|
||||
|
||||
## Customizing Emails
|
||||
|
||||
|
@ -458,7 +547,7 @@ function addSearchQueryParameter (parameters, terms) {
|
|||
}
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", addSearchQueryParameter);
|
||||
Telescope.callbacks.add("posts.parameters", addSearchQueryParameter);
|
||||
```
|
||||
|
||||
The callback takes two arguments: the current MongoDB `parameters` (an object with a `selector` and `options` properties), and the `terms` extracted from the URL.
|
||||
|
@ -647,7 +736,7 @@ If you create a new internationalization package, let us know so we can add it h
|
|||
|
||||
You can access a dynamically generated cheatsheet of Nova's main functions at [http://localhost:3000/cheatsheet](/cheatsheet) (replace with your own development URL).
|
||||
|
||||
## Third-Party Plugins
|
||||
## Third-Party Packages
|
||||
|
||||
- [Post By Feed](https://github.com/xavcz/nova-post-by-feed): register RSS feeds that will be fetched every 30 minutes to create new posts automatically.
|
||||
- [Post To Slack](https://github.com/xavcz/nova-slack): A package that automatically sends your posts as messages to any connected Slack Team.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"moment": "^2.13.0",
|
||||
"react": "^15.3.2",
|
||||
"react-addons-pure-render-mixin": "^15.3.2",
|
||||
"react-bootstrap": "^0.30.3",
|
||||
"react-bootstrap": "0.30.3",
|
||||
"react-bootstrap-datetimepicker": "0.0.22",
|
||||
"react-cookie": "^0.4.6",
|
||||
"react-datetime": "^2.3.2",
|
||||
|
|
|
@ -27,7 +27,7 @@ class CustomPostsItem extends Telescope.components.PostsItem {
|
|||
<div className={postClass}>
|
||||
|
||||
<div className="posts-item-vote">
|
||||
<Telescope.components.Vote post={post} currentUser={this.context.currentUser}/>
|
||||
<Telescope.components.Vote post={post} />
|
||||
</div>
|
||||
|
||||
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
||||
|
@ -49,7 +49,7 @@ class CustomPostsItem extends Telescope.components.PostsItem {
|
|||
<FormattedMessage id="comments.count" values={{count: post.commentCount}}/>
|
||||
</Link>
|
||||
</div>
|
||||
{(this.context.currentUser && this.context.currentUser.isAdmin) ?<Telescope.components.PostsStats post={post} />:null}
|
||||
{this.context.currentUser && this.context.currentUser.isAdmin ? <Telescope.components.PostsStats post={post} /> : null}
|
||||
{this.renderActions()}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ Posts.addField(
|
|||
optional: true, // this field is not required
|
||||
insertableIf: canInsert,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
options: function () { // options for the select form control
|
||||
return [
|
||||
{value: "white", label: "White"},
|
||||
|
|
|
@ -3,8 +3,6 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
//import Actions from "../actions.js";
|
||||
import Categories from "meteor/nova:categories";
|
||||
|
||||
class CategoriesEditForm extends Component{
|
||||
|
@ -35,7 +33,6 @@ class CategoriesEditForm extends Component{
|
|||
<NovaForm
|
||||
document={this.props.category}
|
||||
collection={Categories}
|
||||
currentUser={this.context.currentUser}
|
||||
methodName="categories.edit"
|
||||
successCallback={(category)=>{
|
||||
this.context.messages.flash("Category edited.", "success");
|
||||
|
|
|
@ -9,7 +9,6 @@ const CategoriesNewForm = (props, context) => {
|
|||
<div className="categories-new-form">
|
||||
<NovaForm
|
||||
collection={Categories}
|
||||
currentUser={context.currentUser}
|
||||
methodName="categories.new"
|
||||
successCallback={(category)=>{
|
||||
context.messages.flash("Category created.", "success");
|
||||
|
|
|
@ -10,7 +10,6 @@ class CommentsEdit extends Component {
|
|||
<NovaForm
|
||||
collection={Comments}
|
||||
document={this.props.comment}
|
||||
currentUser={this.context.currentUser}
|
||||
methodName="comments.edit"
|
||||
successCallback={this.props.successCallback}
|
||||
layout="elementOnly"
|
||||
|
|
|
@ -123,8 +123,7 @@ class CommentsItem extends Component{
|
|||
|
||||
CommentsItem.propTypes = {
|
||||
comment: React.PropTypes.object.isRequired, // the current comment
|
||||
//currentUser: React.PropTypes.object, // the current user
|
||||
}
|
||||
};
|
||||
|
||||
CommentsItem.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
|
@ -132,6 +131,6 @@ CommentsItem.contextTypes = {
|
|||
messages: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CommentsItem;
|
||||
|
|
|
@ -2,12 +2,12 @@ import Telescope from 'meteor/nova:lib';
|
|||
import React from 'react';
|
||||
import {injectIntl, FormattedMessage} from 'react-intl';
|
||||
|
||||
const CommentsList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore}) => {
|
||||
const CommentsList = ({results, hasMore, ready, count, totalCount, loadMore}) => {
|
||||
|
||||
if (!!results.length) {
|
||||
return (
|
||||
<div className="comments-list">
|
||||
{results.map(comment => <Telescope.components.CommentsNode comment={comment} key={comment._id} currentUser={currentUser}/>)}
|
||||
{results.map(comment => <Telescope.components.CommentsNode comment={comment} key={comment._id} />)}
|
||||
{hasMore ? (ready ? <Telescope.components.CommentsLoadMore loadMore={loadMore} count={count} totalCount={totalCount} /> : <Telescope.components.Loading/>) : null}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -20,7 +20,6 @@ class CommentsNew extends Component {
|
|||
<div className="comments-new-form">
|
||||
<NovaForm
|
||||
collection={Comments}
|
||||
currentUser={this.context.currentUser}
|
||||
methodName="comments.new"
|
||||
prefilledProps={prefilledProps}
|
||||
successCallback={this.props.successCallback}
|
||||
|
|
|
@ -6,14 +6,14 @@ class CommentsNode extends Component {
|
|||
renderComment(comment) {
|
||||
|
||||
return (
|
||||
<Telescope.components.CommentsItem comment={comment} key={comment._id} currentUser={this.props.currentUser}/>
|
||||
<Telescope.components.CommentsItem comment={comment} key={comment._id} />
|
||||
)
|
||||
}
|
||||
|
||||
renderChildren(children) {
|
||||
return (
|
||||
<div className="comments-children">
|
||||
{children.map(comment => <CommentsNode comment={comment} key={comment._id} currentUser={this.props.currentUser}/>)}
|
||||
{children.map(comment => <CommentsNode comment={comment} key={comment._id} />)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -35,7 +35,10 @@ class CommentsNode extends Component {
|
|||
|
||||
CommentsNode.propTypes = {
|
||||
comment: React.PropTypes.object.isRequired, // the current comment
|
||||
};
|
||||
|
||||
CommentsNode.contextTypes = {
|
||||
currentUser: React.PropTypes.object, // the current user
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CommentsNode;
|
|
@ -30,7 +30,7 @@ class App extends Component {
|
|||
<IntlProvider locale={this.getLocale()} messages={Telescope.strings[this.getLocale()]}>
|
||||
{
|
||||
this.props.ready ?
|
||||
<Telescope.components.Layout currentUser={this.props.currentUser}>{this.props.children}</Telescope.components.Layout>
|
||||
<Telescope.components.Layout>{this.props.children}</Telescope.components.Layout>
|
||||
: <Telescope.components.AppLoading />
|
||||
}
|
||||
</IntlProvider>
|
||||
|
|
|
@ -2,7 +2,7 @@ import Telescope from 'meteor/nova:lib';
|
|||
import React from 'react';
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
const Header = ({currentUser}) => {
|
||||
const Header = (props, {currentUser}) => {
|
||||
|
||||
const logoUrl = Telescope.settings.get("logoUrl");
|
||||
const siteTitle = Telescope.settings.get("title", "Nova");
|
||||
|
@ -21,7 +21,7 @@ const Header = ({currentUser}) => {
|
|||
<div className="nav">
|
||||
|
||||
<div className="nav-user">
|
||||
{currentUser ? <Telescope.components.UsersMenu user={currentUser}/> : <Telescope.components.UsersAccountMenu/>}
|
||||
{currentUser ? <Telescope.components.UsersMenu/> : <Telescope.components.UsersAccountMenu/>}
|
||||
</div>
|
||||
|
||||
<div className="nav-new-post">
|
||||
|
@ -37,4 +37,8 @@ const Header = ({currentUser}) => {
|
|||
|
||||
Header.displayName = "Header";
|
||||
|
||||
Header.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
};
|
||||
|
||||
module.exports = Header;
|
||||
|
|
|
@ -3,10 +3,8 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import Formsy from 'formsy-react';
|
||||
import { Input } from 'formsy-react-components';
|
||||
//import Actions from "../actions.js";
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Cookie from 'react-cookie';
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
import Users from 'meteor/nova:users';
|
||||
|
||||
class Newsletter extends Component {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
import React, { PropTypes, Component } from 'react';
|
||||
//import Actions from "../actions.js";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
import classNames from 'classnames';
|
||||
import Users from 'meteor/nova:users';
|
||||
|
||||
|
@ -61,8 +59,7 @@ class Vote extends Component {
|
|||
|
||||
Vote.propTypes = {
|
||||
post: React.PropTypes.object.isRequired, // the current post
|
||||
// currentUser: React.PropTypes.object, // the current user
|
||||
}
|
||||
};
|
||||
|
||||
Vote.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { ListContainer } from "meteor/utilities:react-list-container";
|
|||
import { ModalTrigger } from "meteor/nova:core";
|
||||
import Comments from "meteor/nova:comments";
|
||||
|
||||
const PostsCommentsThread = ({document, currentUser}) => {
|
||||
const PostsCommentsThread = ({document}, {currentUser}) => {
|
||||
|
||||
const post = document;
|
||||
|
||||
|
@ -39,5 +39,9 @@ const PostsCommentsThread = ({document, currentUser}) => {
|
|||
|
||||
PostsCommentsThread.displayName = "PostsCommentsThread";
|
||||
|
||||
PostsCommentsThread.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
};
|
||||
|
||||
module.exports = PostsCommentsThread;
|
||||
export default PostsCommentsThread;
|
|
@ -47,7 +47,7 @@ class PostsItem extends Component {
|
|||
<div className={postClass}>
|
||||
|
||||
<div className="posts-item-vote">
|
||||
<Telescope.components.Vote post={post} currentUser={this.context.currentUser}/>
|
||||
<Telescope.components.Vote post={post} />
|
||||
</div>
|
||||
|
||||
{post.thumbnailUrl ? <Telescope.components.PostsThumbnail post={post}/> : null}
|
||||
|
@ -69,7 +69,7 @@ class PostsItem extends Component {
|
|||
<FormattedMessage id="comments.count" values={{count: post.commentCount}}/>
|
||||
</Link>
|
||||
</div>
|
||||
{(this.context.currentUser && this.context.currentUser.isAdmin) ?<Telescope.components.PostsStats post={post} />:null}
|
||||
{this.context.currentUser && this.context.currentUser.isAdmin ? <Telescope.components.PostsStats post={post} /> : null}
|
||||
{this.renderActions()}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,18 +3,12 @@ import React from 'react';
|
|||
|
||||
const PostsList = ({results, currentUser, hasMore, ready, count, totalCount, loadMore, showHeader = true}) => {
|
||||
|
||||
// console.log(results);
|
||||
// console.log(ready);
|
||||
// console.log(hasMore);
|
||||
// console.log(totalCount);
|
||||
// console.log(count);
|
||||
|
||||
if (!!results.length) {
|
||||
return (
|
||||
<div className="posts-list">
|
||||
{showHeader ? <Telescope.components.PostsListHeader /> : null}
|
||||
<div className="posts-list-content">
|
||||
{results.map(post => <Telescope.components.PostsItem post={post} currentUser={currentUser} key={post._id}/>)}
|
||||
{results.map(post => <Telescope.components.PostsItem post={post} key={post._id}/>)}
|
||||
</div>
|
||||
{hasMore ? (ready ? <Telescope.components.PostsLoadMore loadMore={loadMore} count={count} totalCount={totalCount} /> : <Telescope.components.PostsLoading/>) : <Telescope.components.PostsNoMore/>}
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,6 @@ const PostsNewForm = (props, context) => {
|
|||
<div className="posts-new-form">
|
||||
<NovaForm
|
||||
collection={Posts}
|
||||
currentUser={context.currentUser}
|
||||
methodName="posts.new"
|
||||
successCallback={(post)=>{
|
||||
context.messages.flash(context.intl.formatMessage({id: "posts.created_message"}), "success");
|
||||
|
|
|
@ -18,7 +18,7 @@ const PostsPage = ({document, currentUser}) => {
|
|||
|
||||
{/*<SocialShare url={ Posts.getLink(post) } title={ post.title }/>*/}
|
||||
|
||||
<Telescope.components.PostsCommentsThread document={post} currentUser={currentUser}/>
|
||||
<Telescope.components.PostsCommentsThread document={post} />
|
||||
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -7,14 +7,18 @@ const UsersAccount = (props, context) => {
|
|||
const terms = props.params.slug ? {"telescope.slug": props.params.slug} : context.currentUser ? {_id: context.currentUser._id } : undefined;
|
||||
return (
|
||||
<Telescope.components.CanDo action="users.edit.own" displayNoPermissionMessage={true}>
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={terms}
|
||||
terms={terms}
|
||||
documentPropName="user"
|
||||
component={Telescope.components.UsersEdit}
|
||||
/>
|
||||
{
|
||||
// do not try to render DocumentContainer without required prop 'terms'
|
||||
typeof terms === "undefined" ? null
|
||||
: <DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={terms}
|
||||
terms={terms}
|
||||
documentPropName="user"
|
||||
component={Telescope.components.UsersEdit}
|
||||
/>
|
||||
}
|
||||
</Telescope.components.CanDo>
|
||||
)
|
||||
};
|
||||
|
|
|
@ -22,8 +22,7 @@ const UsersEdit = (props, context) => {
|
|||
<div className="page users-edit-form">
|
||||
<h2 className="page-title users-edit-form-title"><FormattedMessage id="users.edit_account"/></h2>
|
||||
<NovaForm
|
||||
currentUser={currentUser}
|
||||
collection={Meteor.users}
|
||||
collection={Users}
|
||||
document={user}
|
||||
methodName="users.edit"
|
||||
successCallback={(user)=>{
|
||||
|
@ -41,6 +40,7 @@ UsersEdit.propTypes = {
|
|||
};
|
||||
|
||||
UsersEdit.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
};
|
||||
|
|
|
@ -3,8 +3,7 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Accounts } from 'meteor/std:accounts-ui';
|
||||
import { Modal, Dropdown, MenuItem } from 'react-bootstrap';
|
||||
import { ContextPasser } from "meteor/nova:core";
|
||||
import { Dropdown, MenuItem } from 'react-bootstrap';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import Users from 'meteor/nova:users';
|
||||
|
||||
|
@ -12,20 +11,20 @@ class UsersMenu extends Component {
|
|||
|
||||
render() {
|
||||
|
||||
const user = this.props.user;
|
||||
const {currentUser} = this.context;
|
||||
|
||||
return (
|
||||
<div className="users-menu">
|
||||
<Dropdown id="user-dropdown">
|
||||
<Dropdown.Toggle>
|
||||
<Telescope.components.UsersAvatar size="small" user={user} link={false} />
|
||||
<div>{Users.getDisplayName(user)}</div>
|
||||
<Telescope.components.UsersAvatar size="small" user={currentUser} link={false} />
|
||||
<div>{Users.getDisplayName(currentUser)}</div>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<LinkContainer to={`/users/${user.telescope.slug}`} /*to={{name: "users.single", params: {slug: user.telescope.slug}}}*/>
|
||||
<LinkContainer to={`/users/${currentUser.telescope.slug}`}>
|
||||
<MenuItem className="dropdown-item" eventKey="1"><FormattedMessage id="users.profile"/></MenuItem>
|
||||
</LinkContainer>
|
||||
<LinkContainer to={`/account`} /*to={{name: "account"}}*/>
|
||||
<LinkContainer to={`/account`}>
|
||||
<MenuItem className="dropdown-item" eventKey="2"><FormattedMessage id="users.edit_account"/></MenuItem>
|
||||
</LinkContainer>
|
||||
<MenuItem className="dropdown-item" eventKey="4" onClick={() => Meteor.logout(Accounts.ui._options.onSignedOutHook())}><FormattedMessage id="users.log_out"/></MenuItem>
|
||||
|
@ -37,11 +36,8 @@ class UsersMenu extends Component {
|
|||
|
||||
}
|
||||
|
||||
UsersMenu.propTypes = {
|
||||
user: React.PropTypes.object
|
||||
}
|
||||
|
||||
UsersMenu.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,15 @@ import { Modal } from 'react-bootstrap';
|
|||
import NovaForm from "meteor/nova:forms";
|
||||
import { withRouter } from 'react-router'
|
||||
import Users from 'meteor/nova:users';
|
||||
import { Accounts } from 'meteor/std:accounts-ui';
|
||||
|
||||
const UsersProfileCheckModal = ({currentUser, show, router}) => {
|
||||
const UsersProfileCheckModal = ({show, router}, {currentUser}) => {
|
||||
|
||||
// return fields that are required by the schema but haven't been filled out yet
|
||||
const schema = Users.simpleSchema()._schema;
|
||||
const requiredFields = _.filter(_.keys(schema), function (fieldName) {
|
||||
const requiredFields = _.filter(_.keys(schema), (fieldName) => {
|
||||
var field = schema[fieldName];
|
||||
return !!field.required && !Telescope.getNestedProperty(Meteor.user(), fieldName);
|
||||
return !!field.required && !Telescope.getNestedProperty(currentUser, fieldName);
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -22,31 +23,31 @@ const UsersProfileCheckModal = ({currentUser, show, router}) => {
|
|||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<NovaForm
|
||||
currentUser={ currentUser }
|
||||
collection={ Meteor.users }
|
||||
collection={ Users }
|
||||
document={ currentUser }
|
||||
methodName="users.edit"
|
||||
successCallback={ (user) => Telescope.callbacks.runAsync("profileCompletedAsync", user) }
|
||||
successCallback={ (user) => Telescope.callbacks.runAsync("users.profileCompleted.async", user) }
|
||||
fields={ requiredFields }
|
||||
/>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<FormattedMessage id="app.or"/> <a className="complete-profile-logout" onClick={ () => Meteor.logout(() => router.push({pathname: '/'})) }><FormattedMessage id="users.log_out"/></a>
|
||||
<FormattedMessage id="app.or"/> <a className="complete-profile-logout" onClick={ () => Meteor.logout(Accounts.ui._options.onSignedOutHook()) }><FormattedMessage id="users.log_out"/></a>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
)
|
||||
};
|
||||
|
||||
class UsersProfileCheck extends Component {
|
||||
render() {
|
||||
const currentUser = this.context.currentUser;
|
||||
return currentUser ? <UsersProfileCheckModal currentUser={currentUser} show={!Users.hasCompletedProfile(currentUser)}/> : null
|
||||
}
|
||||
}
|
||||
const UsersProfileCheck = (props, {currentUser}) => {
|
||||
return currentUser ? <UsersProfileCheckModal show={!Users.hasCompletedProfile(currentUser)}/> : null;
|
||||
};
|
||||
|
||||
UsersProfileCheck.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
}
|
||||
};
|
||||
|
||||
UsersProfileCheckModal.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
};
|
||||
|
||||
UsersProfileCheck.displayName = "UsersProfileCheck";
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@
|
|||
}
|
||||
|
||||
.posts-categories{
|
||||
flex-wrap: wrap;
|
||||
@include medium-large{
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
@ -294,4 +295,4 @@
|
|||
@include flex-center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: $vmargin * 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ Posts.addField(
|
|||
optional: true,
|
||||
insertableIf: canInsert,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
noselect: true,
|
||||
type: "bootstrap-category",
|
||||
order: 50,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Meteor } from 'meteor/meteor';
|
||||
import Posts from "meteor/nova:posts";
|
||||
import Users from 'meteor/nova:users';
|
||||
import Categories from "./collection.js";
|
||||
|
@ -28,7 +29,10 @@ Meteor.methods({
|
|||
}
|
||||
});
|
||||
|
||||
Categories.smartMethods({
|
||||
createName: "categories.new",
|
||||
editName: "categories.edit"
|
||||
// assign smart methods on startup so the method code generated takes care of categories' custom fields (extended schema) -> prevent bug on create/edit categories with custom fields
|
||||
Meteor.startup(() => {
|
||||
Categories.smartMethods({
|
||||
createName: "categories.new",
|
||||
editName: "categories.edit"
|
||||
});
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
import Categories from "./collection.js";
|
||||
|
||||
// Category Parameter
|
||||
// Category Posts Parameters
|
||||
// Add a "categories" property to terms which can be used to filter *all* existing Posts views.
|
||||
function addCategoryParameter (parameters, terms) {
|
||||
|
||||
|
@ -32,4 +32,4 @@ function addCategoryParameter (parameters, terms) {
|
|||
}
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", addCategoryParameter);
|
||||
Telescope.callbacks.add("posts.parameters", addCategoryParameter);
|
|
@ -19,7 +19,7 @@ Categories.schema = new SimpleSchema({
|
|||
insertableIf: canInsert,
|
||||
editableIf: canEdit,
|
||||
publish: true,
|
||||
autoform: {
|
||||
form: {
|
||||
rows: 3
|
||||
}
|
||||
},
|
||||
|
@ -50,7 +50,7 @@ Categories.schema = new SimpleSchema({
|
|||
insertableIf: canInsert,
|
||||
editableIf: canEdit,
|
||||
publish: true,
|
||||
autoform: {
|
||||
form: {
|
||||
options: function () {
|
||||
var categories = Categories.find().map(function (category) {
|
||||
return {
|
||||
|
@ -77,7 +77,7 @@ Telescope.settings.collection.addField([
|
|||
fieldSchema: {
|
||||
type: String,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'categories',
|
||||
instructions: 'Let users filter by one or multiple categories at a time.',
|
||||
options: function () {
|
||||
|
@ -94,7 +94,7 @@ Telescope.settings.collection.addField([
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'categories',
|
||||
instructions: 'Hide empty categories in navigation'
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -26,7 +26,7 @@ if (typeof Settings !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: String,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'cloudinary'
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ if (typeof Settings !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'cloudinary',
|
||||
class: 'private-field'
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ if (typeof Settings !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'cloudinary',
|
||||
class: 'private-field'
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -80,8 +80,8 @@ Telescope.callbacks.add("comments.new.method", CommentsNewUserCheck);
|
|||
|
||||
function CommentsNewRateLimit (comment, user) {
|
||||
if (!Users.isAdmin(user)) {
|
||||
var timeSinceLastComment = Users.timeSinceLast(user, Comments),
|
||||
commentInterval = Math.abs(parseInt(Telescope.settings.get('commentInterval',15)));
|
||||
const timeSinceLastComment = Users.timeSinceLast(user, Comments);
|
||||
const commentInterval = Math.abs(parseInt(Telescope.settings.get('commentInterval',15)));
|
||||
// check that user waits more than 15 seconds between comments
|
||||
if((timeSinceLastComment < commentInterval)) {
|
||||
throw new Meteor.Error("CommentsNewRateLimit", "comments.rate_limit_error", commentInterval-timeSinceLastComment);
|
||||
|
@ -156,7 +156,7 @@ function CommentsNewOperations (comment) {
|
|||
var userId = comment.userId;
|
||||
|
||||
// increment comment count
|
||||
Meteor.users.update({_id: userId}, {
|
||||
Users.update({_id: userId}, {
|
||||
$inc: {'telescope.commentCount': 1}
|
||||
});
|
||||
|
||||
|
@ -175,7 +175,7 @@ function CommentsNewUpvoteOwnComment (comment) {
|
|||
|
||||
if (typeof Telescope.operateOnItem !== "undefined") {
|
||||
|
||||
var commentAuthor = Meteor.users.findOne(comment.userId);
|
||||
var commentAuthor = Users.findOne(comment.userId);
|
||||
|
||||
// upvote comment
|
||||
Telescope.operateOnItem(Comments, comment._id, commentAuthor, "upvote");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
import Comments from './collection.js';
|
||||
import Posts from 'meteor/nova:posts';
|
||||
import Users from 'meteor/nova:users';
|
||||
|
||||
Comments.helpers({getCollection: () => Comments});
|
||||
Comments.helpers({getCollectionName: () => "comments"});
|
||||
|
@ -16,7 +18,7 @@ Comments.getPageUrl = function(comment, isAbsolute = false){
|
|||
const post = Posts.findOne(comment.postId);
|
||||
return `${Posts.getPageUrl(post, isAbsolute)}/#${comment._id}`;
|
||||
};
|
||||
Comments.helpers({getPageUrl: function () {return Comments.getPageUrl(this);}});
|
||||
Comments.helpers({getPageUrl: function (isAbsolute) {return Comments.getPageUrl(this, isAbsolute);}});
|
||||
|
||||
///////////////////
|
||||
// Other Helpers //
|
||||
|
@ -27,7 +29,7 @@ Comments.helpers({getPageUrl: function () {return Comments.getPageUrl(this);}});
|
|||
* @param {Object} comment
|
||||
*/
|
||||
Comments.getAuthorName = function (comment) {
|
||||
var user = Meteor.users.findOne(comment.userId);
|
||||
var user = Users.findOne(comment.userId);
|
||||
return user ? user.getDisplayName() : comment.author;
|
||||
};
|
||||
Comments.helpers({getAuthorName: function () {return Comments.getAuthorName(this);}});
|
||||
|
|
|
@ -2,6 +2,7 @@ import Telescope from 'meteor/nova:lib';
|
|||
import Comments from './collection.js';
|
||||
import Posts from "meteor/nova:posts";
|
||||
import Users from 'meteor/nova:users';
|
||||
import { Messages } from 'meteor/nova:core';
|
||||
|
||||
Comments.methods = {};
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
@ -10,7 +11,7 @@ Comments.methods = {};
|
|||
|
||||
Comments.methods.new = function (comment) {
|
||||
|
||||
const currentUser = Meteor.users.findOne(comment.userId);
|
||||
const currentUser = Users.findOne(comment.userId);
|
||||
|
||||
comment = Telescope.callbacks.run("comments.new.sync", comment, currentUser);
|
||||
|
||||
|
@ -97,7 +98,6 @@ Meteor.methods({
|
|||
var user = Meteor.user();
|
||||
|
||||
if(Users.canEdit(user, comment)){
|
||||
|
||||
// decrement post comment count and remove user ID from post
|
||||
Posts.update(comment.postId, {
|
||||
$inc: {commentCount: -1},
|
||||
|
@ -105,7 +105,7 @@ Meteor.methods({
|
|||
});
|
||||
|
||||
// decrement user comment count and remove comment ID from user
|
||||
Meteor.users.update({_id: comment.userId}, {
|
||||
Users.update({_id: comment.userId}, {
|
||||
$inc: {'telescope.commentCount': -1}
|
||||
});
|
||||
|
||||
|
@ -117,11 +117,8 @@ Meteor.methods({
|
|||
htmlBody: 'Deleted',
|
||||
isDeleted: true
|
||||
}});
|
||||
|
||||
}else{
|
||||
|
||||
} else {
|
||||
Messages.flash("You don't have permission to delete this comment.", "error");
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import Comments from './collection.js';
|
||||
import Posts from "meteor/nova:posts";
|
||||
import Users from 'meteor/nova:users';
|
||||
|
||||
Comments.getNotificationProperties = function (data) {
|
||||
const comment = data.comment;
|
||||
const commentAuthor = Meteor.users.findOne(comment.userId);
|
||||
const commentAuthor = Users.findOne(comment.userId);
|
||||
const post = Posts.findOne(comment.postId);
|
||||
const properties = {
|
||||
profileUrl: commentAuthor && commentAuthor.getProfileUrl(true),
|
||||
|
|
|
@ -109,7 +109,7 @@ Comments.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
// regEx: SimpleSchema.RegEx.Id,
|
||||
max: 500,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true // never show this
|
||||
}
|
||||
},
|
||||
|
@ -122,7 +122,7 @@ Comments.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
join: {
|
||||
joinAs: "user",
|
||||
collection: () => Meteor.users
|
||||
collection: () => Users
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
@ -158,7 +158,7 @@ if (typeof Telescope.notifications !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ Comments._ensureIndex({parentCommentId: 1});
|
|||
*/
|
||||
Meteor.publish('comments.list', function (terms) {
|
||||
|
||||
const currentUser = this.userId && Meteor.users.findOne(this.userId);
|
||||
const currentUser = this.userId && Users.findOne(this.userId);
|
||||
|
||||
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||
({selector, options} = Comments.parameters.get(terms));
|
||||
|
@ -22,7 +22,7 @@ Meteor.publish('comments.list', function (terms) {
|
|||
|
||||
const comments = Comments.find(selector, options);
|
||||
const posts = Posts.find({_id: {$in: _.pluck(comments.fetch(), 'postId')}}, {fields: Posts.publishedFields.list});
|
||||
const users = Meteor.users.find({_id: {$in: _.pluck(comments.fetch(), 'userId')}}, {fields: Users.publishedFields.list});
|
||||
const users = Users.find({_id: {$in: _.pluck(comments.fetch(), 'userId')}}, {fields: Users.publishedFields.list});
|
||||
|
||||
return Users.canDo(currentUser, "comments.view.all") ? [comments, posts, users] : [];
|
||||
|
||||
|
@ -91,7 +91,7 @@ Meteor.publish('comments.list', function (terms) {
|
|||
// userIds.push(post.userId);
|
||||
// }
|
||||
|
||||
// return Meteor.users.find({_id: {$in: userIds}}, {fields: Users.pubsub.publicProperties});
|
||||
// return Users.find({_id: {$in: userIds}}, {fields: Users.pubsub.publicProperties});
|
||||
|
||||
// }
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
|
||||
var modifyKarma = function (userId, karma) {
|
||||
Meteor.users.update({_id: userId}, {$inc: {"telescope.karma": karma}});
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Update an item's (post or comment) score
|
||||
* @param {object} item - The item being operated on
|
||||
|
@ -51,7 +47,7 @@ function updateUser (item, user, collection, operation) {
|
|||
break;
|
||||
}
|
||||
|
||||
Meteor.users.update({_id: user._id}, update);
|
||||
Users.update({_id: user._id}, update);
|
||||
|
||||
}
|
||||
Telescope.callbacks.add("upvote.async", updateUser);
|
||||
|
@ -73,7 +69,7 @@ function updateKarma (item, user, collection, operation) {
|
|||
|
||||
// only update karma is the operation isn't done by the item's author
|
||||
if (item.userId !== user._id) {
|
||||
Meteor.users.update({_id: item.userId}, {$inc: {"telescope.karma": karmaAmount}});
|
||||
Users.update({_id: item.userId}, {$inc: {"telescope.karma": karmaAmount}});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ const renderSetting = (field, key) => {
|
|||
<td>{field.type && field.type.name}</td>
|
||||
<td>{field.private ? <span className="private">private</span> : Telescope.settings.get(key)}</td>
|
||||
<td>{field.defaultValue && field.defaultValue.toString()}</td>
|
||||
<td>{field.autoform && field.autoform.instructions}</td>
|
||||
<td>{field.form && field.form.instructions}</td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ 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';
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Collection & Schema //
|
||||
|
@ -45,7 +46,7 @@ const schema = new SimpleSchema({
|
|||
type: String,
|
||||
publish: true,
|
||||
join: {
|
||||
collection: () => Meteor.users,
|
||||
collection: () => Users,
|
||||
joinAs: "user",
|
||||
fields: ["_id", "username"]
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_"
|
||||
}
|
|
@ -71,7 +71,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'embedly',
|
||||
class: 'private-field'
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'embedly'
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'embedly'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -81,7 +81,6 @@ New document form:
|
|||
```jsx
|
||||
<NovaForm
|
||||
collection={Posts}
|
||||
currentUser={currentUser},
|
||||
methodName="posts.new"
|
||||
/>
|
||||
```
|
||||
|
@ -91,9 +90,8 @@ Edit document form:
|
|||
```jsx
|
||||
<NovaForm
|
||||
collection={Posts}
|
||||
currentUser={currentUser},
|
||||
methodName="posts.edit",
|
||||
document={post},
|
||||
methodName="posts.edit"
|
||||
document={post}
|
||||
labelFunction={capitalize}
|
||||
successCallback={closeModal}
|
||||
/>
|
||||
|
|
|
@ -21,7 +21,10 @@ class FormComponent extends Component {
|
|||
}
|
||||
|
||||
handleBlur() {
|
||||
this.props.updateCurrentValue(this.props.name, this.formControl.getValue());
|
||||
// see https://facebook.github.io/react/docs/more-about-refs.html
|
||||
if (this.formControl !== null) {
|
||||
this.props.updateCurrentValue(this.props.name, this.formControl.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
renderComponent() {
|
||||
|
|
|
@ -32,6 +32,7 @@ class NovaForm extends Component{
|
|||
this.throwError = this.throwError.bind(this);
|
||||
this.clearErrors = this.clearErrors.bind(this);
|
||||
this.updateCurrentValue = this.updateCurrentValue.bind(this);
|
||||
this.formKeyDown = this.formKeyDown.bind(this);
|
||||
|
||||
// a debounced version of seState that only updates state every 500 ms (not used)
|
||||
this.debouncedSetState = _.debounce(this.setState, 500);
|
||||
|
@ -81,9 +82,15 @@ class NovaForm extends Component{
|
|||
// add value
|
||||
field.value = this.getDocument() && deepValue(this.getDocument(), fieldName) ? deepValue(this.getDocument(), fieldName) : "";
|
||||
|
||||
// backward compatibility from 'autoform' to 'form'
|
||||
if (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`);
|
||||
}
|
||||
|
||||
// replace value by prefilled value if value is empty
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.prefill) {
|
||||
const prefilledValue = typeof fieldSchema.autoform.prefill === "function" ? fieldSchema.autoform.prefill.call(fieldSchema) : fieldSchema.autoform.prefill;
|
||||
if (fieldSchema.form && fieldSchema.form.prefill) {
|
||||
const prefilledValue = typeof fieldSchema.form.prefill === "function" ? fieldSchema.form.prefill.call(fieldSchema) : fieldSchema.form.prefill;
|
||||
if (!!prefilledValue && !field.value) {
|
||||
field.prefilledValue = prefilledValue;
|
||||
field.value = prefilledValue;
|
||||
|
@ -96,21 +103,21 @@ class NovaForm extends Component{
|
|||
}
|
||||
|
||||
// add options if they exist
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.options) {
|
||||
field.options = typeof fieldSchema.autoform.options === "function" ? fieldSchema.autoform.options.call(fieldSchema) : fieldSchema.autoform.options;
|
||||
if (fieldSchema.form && fieldSchema.form.options) {
|
||||
field.options = typeof fieldSchema.form.options === "function" ? fieldSchema.form.options.call(fieldSchema) : fieldSchema.form.options;
|
||||
}
|
||||
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.disabled) {
|
||||
field.disabled = typeof fieldSchema.autoform.disabled === "function" ? fieldSchema.autoform.disabled.call(fieldSchema) : fieldSchema.autoform.disabled;
|
||||
if (fieldSchema.form && fieldSchema.form.disabled) {
|
||||
field.disabled = typeof fieldSchema.form.disabled === "function" ? fieldSchema.form.disabled.call(fieldSchema) : fieldSchema.form.disabled;
|
||||
}
|
||||
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.help) {
|
||||
field.help = typeof fieldSchema.autoform.help === "function" ? fieldSchema.autoform.help.call(fieldSchema) : fieldSchema.autoform.help;
|
||||
if (fieldSchema.form && fieldSchema.form.help) {
|
||||
field.help = typeof fieldSchema.form.help === "function" ? fieldSchema.form.help.call(fieldSchema) : fieldSchema.form.help;
|
||||
}
|
||||
|
||||
// add placeholder
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.placeholder) {
|
||||
field.placeholder = fieldSchema.autoform.placeholder;
|
||||
if (fieldSchema.form && fieldSchema.form.placeholder) {
|
||||
field.placeholder = fieldSchema.form.placeholder;
|
||||
}
|
||||
|
||||
if (fieldSchema.beforeComponent) field.beforeComponent = fieldSchema.beforeComponent;
|
||||
|
@ -172,7 +179,7 @@ class NovaForm extends Component{
|
|||
const fields = this.props.fields;
|
||||
|
||||
// get all editable/insertable fields (depending on current form type)
|
||||
let relevantFields = this.getFormType() === "edit" ? getEditableFields(this.getSchema(), this.props.currentUser, this.getDocument()) : getInsertableFields(this.getSchema(), this.props.currentUser);
|
||||
let relevantFields = this.getFormType() === "edit" ? getEditableFields(this.getSchema(), this.context.currentUser, this.getDocument()) : getInsertableFields(this.getSchema(), this.context.currentUser);
|
||||
|
||||
// if "fields" prop is specified, restrict list of fields to it
|
||||
if (typeof fields !== "undefined" && fields.length > 0) {
|
||||
|
@ -223,10 +230,11 @@ class NovaForm extends Component{
|
|||
// ------------------------------- Errors ------------------------------ //
|
||||
// --------------------------------------------------------------------- //
|
||||
|
||||
// clear all errors
|
||||
// clear all errors and re-enable the form
|
||||
clearErrors() {
|
||||
this.setState({
|
||||
errors: []
|
||||
errors: [],
|
||||
disabled: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -276,11 +284,11 @@ class NovaForm extends Component{
|
|||
// common callback for both new and edit forms
|
||||
methodCallback(error, document) {
|
||||
|
||||
this.setState({disabled: false});
|
||||
|
||||
if (error) { // error
|
||||
|
||||
console.log(error)
|
||||
this.setState({disabled: false});
|
||||
|
||||
console.log(error);
|
||||
|
||||
const errorContent = this.context.intl.formatMessage({id: error.reason}, {details: error.details})
|
||||
// add error to state
|
||||
|
@ -294,8 +302,6 @@ class NovaForm extends Component{
|
|||
|
||||
} else { // success
|
||||
|
||||
this.clearErrors();
|
||||
|
||||
// reset form if this is a new document form
|
||||
if (this.getFormType() === "new") this.refs.form.reset();
|
||||
|
||||
|
@ -304,6 +310,9 @@ class NovaForm extends Component{
|
|||
|
||||
// run close callback if it exists in context (i.e. we're inside a modal)
|
||||
if (this.context.closeCallback) this.context.closeCallback();
|
||||
// else there is no close callback (i.e. we're not inside a modal), call the clear errors method
|
||||
// note: we don't want to update the state of an unmounted component
|
||||
else this.clearErrors();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -361,6 +370,23 @@ class NovaForm extends Component{
|
|||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// note: patch to cancel closeCallback given by parent
|
||||
// we clean the event by hand
|
||||
// example : the closeCallback is a function that closes a modal by calling setState, this modal being the parent of this NovaForm component
|
||||
// if this componentWillUnmount hook is triggered, that means that the modal doesn't exist anymore!
|
||||
// let's not call setState on an unmounted component (avoid no-op / memory leak)
|
||||
this.context.closeCallback = f => f;
|
||||
}
|
||||
|
||||
// key down handler
|
||||
formKeyDown(event) {
|
||||
|
||||
if( (event.ctrlKey || event.metaKey) && event.keyCode === 13) {
|
||||
this.submitForm(this.refs.form.getModel());
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------- //
|
||||
// ------------------------------- Render ------------------------------ //
|
||||
// --------------------------------------------------------------------- //
|
||||
|
@ -373,6 +399,7 @@ class NovaForm extends Component{
|
|||
<div className={"document-"+this.getFormType()}>
|
||||
<Formsy.Form
|
||||
onSubmit={this.submitForm}
|
||||
onKeyDown={this.formKeyDown}
|
||||
disabled={this.state.disabled}
|
||||
ref="form"
|
||||
>
|
||||
|
@ -391,7 +418,6 @@ NovaForm.propTypes = {
|
|||
collection: React.PropTypes.object,
|
||||
schema: React.PropTypes.object,
|
||||
document: React.PropTypes.object, // if a document is passed, this will be an edit form
|
||||
currentUser: React.PropTypes.object,
|
||||
submitCallback: React.PropTypes.func,
|
||||
successCallback: React.PropTypes.func,
|
||||
errorCallback: React.PropTypes.func,
|
||||
|
@ -409,6 +435,7 @@ NovaForm.defaultProps = {
|
|||
|
||||
NovaForm.contextTypes = {
|
||||
closeCallback: React.PropTypes.func,
|
||||
currentUser: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Users.addField({
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ Posts.addField({
|
|||
fieldSchema: {
|
||||
type: String,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ Posts.addField({
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fieldName: 'isDummy',
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ var createPost = function (slug, postedAt, username, thumbnail) {
|
|||
title: toTitleCase(slug.replace(/_/g, ' ')),
|
||||
dummySlug: slug,
|
||||
isDummy: true,
|
||||
userId: Meteor.users.findOne({username: username})._id
|
||||
userId: Users.findOne({username: username})._id
|
||||
};
|
||||
|
||||
if (typeof thumbnail !== "undefined")
|
||||
|
@ -28,7 +28,7 @@ var createComment = function (slug, username, body, parentBody) {
|
|||
|
||||
var comment = {
|
||||
postId: Posts.findOne({dummySlug: slug})._id,
|
||||
userId: Meteor.users.findOne({username: username})._id,
|
||||
userId: Users.findOne({username: username})._id,
|
||||
body: body,
|
||||
isDummy: true,
|
||||
disableNotifications: true
|
||||
|
@ -93,7 +93,7 @@ var createDummyComments = function () {
|
|||
};
|
||||
|
||||
deleteDummyContent = function () {
|
||||
Meteor.users.remove({'profile.isDummy': true});
|
||||
Users.remove({'profile.isDummy': true});
|
||||
Posts.remove({isDummy: true});
|
||||
Comments.remove({isDummy: true});
|
||||
};
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -6,7 +6,7 @@ var kadiraAppIdProperty = {
|
|||
fieldSchema: {
|
||||
type: String,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: "kadira"
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ var kadiraAppSecretProperty = {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: "kadira",
|
||||
class: "private-field"
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -25,7 +25,8 @@ SimpleSchema.extendOptions({
|
|||
required: Match.Optional(Boolean), // required: true means the field is required to have a complete profile
|
||||
profile: Match.Optional(Boolean), // profile: true means the field is shown on user profiles
|
||||
template: Match.Optional(String), // template used to display the field
|
||||
autoform: Match.Optional(Object), // autoform placeholder
|
||||
form: Match.Optional(Object), // form placeholder
|
||||
autoform: Match.Optional(Object), // legacy form placeholder; backward compatibility
|
||||
control: Match.Optional(Match.Any), // NovaForm control (String or React component)
|
||||
order: Match.Optional(Number), // position in the form
|
||||
group: Match.Optional(Object) // form fieldset group
|
||||
|
|
|
@ -131,35 +131,6 @@ Telescope.utils.getOutgoingUrl = function (url) {
|
|||
return Telescope.utils.getSiteUrl() + "out?url=" + encodeURIComponent(url);
|
||||
};
|
||||
|
||||
// This function should only ever really be necessary server side
|
||||
// Client side using .path() is a better option since it's relative
|
||||
// and shouldn't care about the siteUrl.
|
||||
Telescope.utils.getRouteUrl = function (routeName, params, options) {
|
||||
options = options || {};
|
||||
var route = FlowRouter.path(
|
||||
routeName,
|
||||
params || {},
|
||||
options
|
||||
);
|
||||
return route;
|
||||
};
|
||||
|
||||
Telescope.utils.getSignupUrl = function() {
|
||||
return this.getRouteUrl('signUp');
|
||||
};
|
||||
Telescope.utils.getSigninUrl = function() {
|
||||
return this.getRouteUrl('signIn');
|
||||
};
|
||||
|
||||
//TODO: fix this
|
||||
Telescope.utils.getPostCommentUrl = function(postId, commentId) {
|
||||
// get link to a comment on a post page
|
||||
return this.getRouteUrl('post_page_comment', {
|
||||
_id: postId,
|
||||
commentId: commentId
|
||||
});
|
||||
};
|
||||
|
||||
Telescope.utils.slugify = function (s) {
|
||||
var slug = getSlug(s, {
|
||||
truncate: 60
|
||||
|
@ -174,8 +145,8 @@ Telescope.utils.slugify = function (s) {
|
|||
};
|
||||
|
||||
Telescope.utils.getUnusedSlug = function (collection, slug) {
|
||||
var suffix = "";
|
||||
var index = 0;
|
||||
let suffix = "";
|
||||
let index = 0;
|
||||
|
||||
// test if slug is already in use
|
||||
while (!!collection.findOne({slug: slug+suffix})) {
|
||||
|
|
|
@ -46,7 +46,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'Enable newsletter (requires restart).'
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'Enable newsletter in development too (requires restart).'
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: "newsletter",
|
||||
class: "private-field"
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
private: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'The ID of the list you want to send to.',
|
||||
class: "private-field"
|
||||
|
@ -93,7 +93,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter'
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: [Number],
|
||||
optional: true,
|
||||
defaultValue: [2,4,6],
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'Defaults to once a week on Monday. Changes require restarting your app to take effect.',
|
||||
noselect: true,
|
||||
|
@ -147,7 +147,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '00:00',
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'Defaults to 00:00/12:00 AM. Time to send out newsletter if enabled (GMT).',
|
||||
type: 'time'
|
||||
|
@ -159,7 +159,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'newsletter',
|
||||
instructions: 'Automatically subscribe new users on sign-up.'
|
||||
}
|
||||
|
|
|
@ -11,4 +11,4 @@ function subscribeUserOnProfileCompletion (user) {
|
|||
}
|
||||
return user;
|
||||
}
|
||||
Telescope.callbacks.add("profileCompletedAsync", subscribeUserOnProfileCompletion);
|
||||
Telescope.callbacks.add("users.profileCompleted.async", subscribeUserOnProfileCompletion);
|
|
@ -59,7 +59,7 @@ Newsletter.build = function (postsArray) {
|
|||
subject += post.title;
|
||||
|
||||
// get author of the current post
|
||||
var postUser = Meteor.users.findOne(post.userId);
|
||||
var postUser = Users.findOne(post.userId);
|
||||
|
||||
// the naked post object as stored in the database is missing a few properties, so let's add them
|
||||
var properties = _.extend(post, {
|
||||
|
@ -93,7 +93,7 @@ Newsletter.build = function (postsArray) {
|
|||
properties.popularComments = Comments.find({postId: post._id}, {sort: {score: -1}, limit: 2, transform: function (comment) {
|
||||
|
||||
// get comment author
|
||||
var user = Meteor.users.findOne(comment.userId);
|
||||
var user = Users.findOne(comment.userId);
|
||||
|
||||
// add properties to comment
|
||||
comment.body = Telescope.utils.trimHTML(comment.htmlBody, 20);
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -34,7 +34,7 @@ if (typeof Telescope.settings.collection !== "undefined") {
|
|||
type: Boolean,
|
||||
optional: true,
|
||||
defaultValue: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'notifications',
|
||||
instructions: 'Enable email notifications for new posts and new comments (requires restart).'
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
|
||||
getUnsubscribeLink = function(user){
|
||||
return Telescope.utils.getRouteUrl('unsubscribe', {hash: user.telescope.emailHash});
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
unsubscribeUser : function(hash){
|
||||
check(hash, String);
|
||||
// TO-DO: currently, if you have somebody's email you can unsubscribe them
|
||||
// A user-specific salt should be added to the hashing method to prevent this
|
||||
var user = Meteor.users.findOne({"telescope.emailHash": hash});
|
||||
if(user){
|
||||
Meteor.users.update(user._id, {
|
||||
$set: {
|
||||
'profile.notifications.users' : 0,
|
||||
'profile.notifications.posts' : 0,
|
||||
'profile.notifications.comments' : 0,
|
||||
'profile.notifications.replies' : 0
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -20,8 +20,4 @@ Package.onUse(function (api) {
|
|||
'lib/custom_fields.js'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
'lib/server/notifications-server.js'
|
||||
], ['server']);
|
||||
|
||||
});
|
|
@ -207,11 +207,6 @@ function PostsNewRequiredPropertiesCheck (post, user) {
|
|||
// generate slug
|
||||
post.slug = Telescope.utils.slugify(post.title);
|
||||
|
||||
// post is not pending and has been scheduled to be posted in the future by a moderator/admin
|
||||
if (post.status !== Posts.config.STATUS_PENDING && post.postedAt && post.postedAt > post.createdAt) {
|
||||
post.status = Posts.config.STATUS_SCHEDULED;
|
||||
}
|
||||
|
||||
// if post is approved but doesn't have a postedAt date, give it a default date
|
||||
// note: pending posts get their postedAt date only once theyre approved
|
||||
if (Posts.isApproved(post) && !post.postedAt) {
|
||||
|
@ -238,7 +233,7 @@ Telescope.callbacks.add("posts.new.sync", PostsNewSetFuture);
|
|||
*/
|
||||
function PostsNewIncrementPostCount (post) {
|
||||
var userId = post.userId;
|
||||
Meteor.users.update({_id: userId}, {$inc: {"telescope.postCount": 1}});
|
||||
Users.update({_id: userId}, {$inc: {"telescope.postCount": 1}});
|
||||
}
|
||||
Telescope.callbacks.add("posts.new.async", PostsNewIncrementPostCount);
|
||||
|
||||
|
@ -247,7 +242,7 @@ Telescope.callbacks.add("posts.new.async", PostsNewIncrementPostCount);
|
|||
*/
|
||||
function PostsNewUpvoteOwnPost (post) {
|
||||
if (typeof Telescope.operateOnItem !== "undefined") {
|
||||
var postAuthor = Meteor.users.findOne(post.userId);
|
||||
var postAuthor = Users.findOne(post.userId);
|
||||
Telescope.operateOnItem(Posts, post._id, postAuthor, "upvote");
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +258,7 @@ function PostsNewNotifications (post) {
|
|||
var adminIds = _.pluck(Users.adminUsers({fields: {_id:1}}), '_id');
|
||||
var notifiedUserIds = _.pluck(Users.find({'telescope.notifications_posts': true}, {fields: {_id:1}}).fetch(), '_id');
|
||||
var notificationData = {
|
||||
post: _.pick(post, '_id', 'userId', 'title', 'url')
|
||||
post: _.pick(post, '_id', 'userId', 'title', 'url', 'slug')
|
||||
};
|
||||
|
||||
// remove post author ID from arrays
|
||||
|
|
|
@ -57,7 +57,7 @@ Posts.helpers({getPageUrl: function (isAbsolute) {return Posts.getPageUrl(this,
|
|||
* @param {Object} post
|
||||
*/
|
||||
Posts.getAuthorName = function (post) {
|
||||
var user = Meteor.users.findOne(post.userId);
|
||||
var user = Users.findOne(post.userId);
|
||||
if (user) {
|
||||
return user.getDisplayName();
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,7 @@ Posts.methods = {};
|
|||
*/
|
||||
Posts.methods.new = function (post) {
|
||||
|
||||
const currentUser = Meteor.users.findOne(post.userId);
|
||||
const currentUser = Users.findOne(post.userId);
|
||||
|
||||
post = Telescope.callbacks.run("posts.new.sync", post, currentUser);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import Users from 'meteor/nova:users';
|
|||
|
||||
Posts.getNotificationProperties = function (data) {
|
||||
const post = data.post;
|
||||
const postAuthor = Meteor.users.findOne(post.userId);
|
||||
const postAuthor = Users.findOne(post.userId);
|
||||
const properties = {
|
||||
postAuthorName : Posts.getAuthorName(post),
|
||||
postTitle : Telescope.utils.cleanUp(post.title),
|
||||
|
|
|
@ -30,8 +30,8 @@ Posts.parameters.get = function (terms) {
|
|||
options: {}
|
||||
};
|
||||
|
||||
// iterate over postsParameters callbacks
|
||||
parameters = Telescope.callbacks.run("postsParameters", parameters, _.clone(terms));
|
||||
// iterate over posts.parameters callbacks
|
||||
parameters = Telescope.callbacks.run("posts.parameters", parameters, _.clone(terms));
|
||||
|
||||
// if sort options are not provided, default to "createdAt" sort
|
||||
if (_.isEmpty(parameters.options.sort)) {
|
||||
|
@ -62,7 +62,7 @@ function addViewParameter (parameters, terms) {
|
|||
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", addViewParameter);
|
||||
Telescope.callbacks.add("posts.parameters", addViewParameter);
|
||||
|
||||
// View Parameter
|
||||
// Add "after" and "before" properties to terms which can be used to limit posts in time.
|
||||
|
@ -138,7 +138,7 @@ function addTimeParameter (parameters, terms) {
|
|||
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", addTimeParameter);
|
||||
Telescope.callbacks.add("posts.parameters", addTimeParameter);
|
||||
|
||||
// limit the number of items that can be requested at once
|
||||
function limitPosts (parameters, terms) {
|
||||
|
@ -172,4 +172,4 @@ function limitPosts (parameters, terms) {
|
|||
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", limitPosts);
|
||||
Telescope.callbacks.add("posts.parameters", limitPosts);
|
||||
|
|
|
@ -167,11 +167,11 @@ Posts.schemaJSON = {
|
|||
// only provide a default value
|
||||
// 1) this is an insert operation
|
||||
// 2) status field is not set in the document being inserted
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
var user = Users.findOne(this.userId);
|
||||
if (this.isInsert && !this.isSet)
|
||||
return Posts.getDefaultStatus(user);
|
||||
},
|
||||
autoform: {
|
||||
form: {
|
||||
noselect: true,
|
||||
options: Telescope.statuses,
|
||||
group: 'admin'
|
||||
|
@ -245,10 +245,10 @@ Posts.schemaJSON = {
|
|||
// editableIf: canEditAll,
|
||||
control: "select",
|
||||
publish: true,
|
||||
autoform: {
|
||||
form: {
|
||||
group: 'admin',
|
||||
options: function () {
|
||||
return Meteor.users.find().map(function (user) {
|
||||
return Users.find().map(function (user) {
|
||||
return {
|
||||
value: user._id,
|
||||
label: Users.getDisplayName(user)
|
||||
|
@ -258,7 +258,7 @@ Posts.schemaJSON = {
|
|||
},
|
||||
join: {
|
||||
joinAs: "user",
|
||||
collection: () => Meteor.users
|
||||
collection: () => Users
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ const getPostsListUsers = posts => {
|
|||
|
||||
userIds = _.unique(userIds);
|
||||
|
||||
return Meteor.users.find({_id: {$in: userIds}}, {fields: Users.publishedFields.list});
|
||||
return Users.find({_id: {$in: userIds}}, {fields: Users.publishedFields.list});
|
||||
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ const getSinglePostUsers = post => {
|
|||
// remove any duplicate IDs
|
||||
users = _.unique(users);
|
||||
|
||||
return Meteor.users.find({_id: {$in: users}}, {fields: Users.publishedFields.list});
|
||||
return Users.find({_id: {$in: users}}, {fields: Users.publishedFields.list});
|
||||
};
|
||||
|
||||
// ------------------------------------- Publications -------------------------------- //
|
||||
|
@ -71,7 +71,7 @@ Meteor.publish('posts.list', function (terms) {
|
|||
|
||||
this.autorun(function () {
|
||||
|
||||
const currentUser = this.userId && Meteor.users.findOne(this.userId);
|
||||
const currentUser = this.userId && Users.findOne(this.userId);
|
||||
|
||||
terms.currentUserId = this.userId; // add currentUserId to terms
|
||||
const {selector, options} = Posts.parameters.get(terms);
|
||||
|
@ -103,7 +103,7 @@ Meteor.publish('posts.single', function (terms) {
|
|||
|
||||
check(terms, Match.OneOf({_id: String}, {_id: String, slug: Match.Any}));
|
||||
|
||||
const currentUser = this.userId && Meteor.users.findOne(this.userId);
|
||||
const currentUser = this.userId && Users.findOne(this.userId);
|
||||
const options = {fields: Posts.publishedFields.single};
|
||||
const posts = Posts.find(terms._id, options);
|
||||
const post = posts.fetch()[0];
|
||||
|
|
|
@ -115,7 +115,7 @@ Posts.views.add("userPosts", function (terms) {
|
|||
* @summary User upvoted posts view
|
||||
*/
|
||||
Posts.views.add("userUpvotedPosts", function (terms) {
|
||||
var user = Meteor.users.findOne(terms.userId);
|
||||
var user = Users.findOne(terms.userId);
|
||||
var postsIds = _.pluck(user.telescope.upvotedPosts, "itemId");
|
||||
return {
|
||||
selector: {_id: {$in: postsIds}, userId: {$ne: terms.userId}}, // exclude own posts
|
||||
|
@ -127,7 +127,7 @@ Posts.views.add("userUpvotedPosts", function (terms) {
|
|||
* @summary User downvoted posts view
|
||||
*/
|
||||
Posts.views.add("userDownvotedPosts", function (terms) {
|
||||
var user = Meteor.users.findOne(terms.userId);
|
||||
var user = Users.findOne(terms.userId);
|
||||
var postsIds = _.pluck(user.telescope.downvotedPosts, "itemId");
|
||||
// TODO: sort based on votedAt timestamp and not postedAt, if possible
|
||||
return {
|
||||
|
|
|
@ -55,7 +55,7 @@ const serveCommentRSS = function (terms, url) {
|
|||
post = Posts.findOne(comment.postId);
|
||||
feed.item({
|
||||
title: 'Comment on '+post.title,
|
||||
description: comment.body+'</br></br>'+'<a href="'+Telescope.utils.getPostCommentUrl(post._id, comment._id)+'">Discuss</a>',
|
||||
description: `${comment.body}</br></br><a href="${comment.getPageUrl(true)}">Discuss</a>`,
|
||||
author: comment.author,
|
||||
date: comment.postedAt,
|
||||
url: comment.getPageUrl(true),
|
||||
|
|
|
@ -21,4 +21,4 @@ function addSearchQueryParameter (parameters, terms) {
|
|||
}
|
||||
return parameters;
|
||||
}
|
||||
Telescope.callbacks.add("postsParameters", addSearchQueryParameter);
|
||||
Telescope.callbacks.add("posts.parameters", addSearchQueryParameter);
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -21,7 +21,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
publish: true,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
instructions: "Your site's title.",
|
||||
|
@ -35,7 +35,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
// regEx: SimpleSchema.RegEx.Url,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general",
|
||||
|
@ -49,7 +49,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general"
|
||||
|
@ -61,7 +61,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general",
|
||||
|
@ -76,7 +76,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
regEx: SimpleSchema.RegEx.Url,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general",
|
||||
|
@ -90,7 +90,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
control: "checkbox",
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: 'invites',
|
||||
|
@ -104,7 +104,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
control: "checkbox",
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: 'invites',
|
||||
|
@ -118,7 +118,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
control: "checkbox",
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general",
|
||||
|
@ -131,7 +131,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "06_email",
|
||||
|
@ -144,7 +144,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
optional: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "06_email",
|
||||
|
@ -158,7 +158,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
defaultValue: 30,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: '01_general',
|
||||
|
@ -173,7 +173,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
defaultValue: 30,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "02_posts",
|
||||
|
@ -187,7 +187,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
control: "radiogroup",
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "02_posts",
|
||||
|
@ -204,7 +204,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
defaultValue: 15,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "03_comments",
|
||||
|
@ -218,7 +218,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
defaultValue: 30,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "02_posts",
|
||||
|
@ -232,7 +232,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: 'invites'
|
||||
|
@ -245,7 +245,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "02_posts"
|
||||
|
@ -257,7 +257,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "04_logo"
|
||||
|
@ -269,7 +269,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "04_logo"
|
||||
|
@ -281,7 +281,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "04_logo"
|
||||
|
@ -293,7 +293,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "04_logo"
|
||||
|
@ -305,7 +305,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
// optional: true,
|
||||
// insertableIf: canEdit,
|
||||
// editableIf: canEdit,
|
||||
// autoform: {
|
||||
// form: {
|
||||
// group: "01_general",
|
||||
// instructions: 'The app\'s language. Defaults to English.',
|
||||
// options: function () {
|
||||
|
@ -325,7 +325,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "07_integrations"
|
||||
|
@ -337,7 +337,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "07_integrations"
|
||||
|
@ -349,7 +349,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "07_integrations"
|
||||
|
@ -361,7 +361,7 @@ Telescope.settings.schema = new SimpleSchema({
|
|||
publish: true,
|
||||
insertableIf: canEdit,
|
||||
editableIf: canEdit,
|
||||
autoform: {
|
||||
form: {
|
||||
disabled: isInSettingsJSON,
|
||||
prefill: getFromJSON,
|
||||
group: "01_general"
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
|
@ -90,7 +90,7 @@ if (typeof Package['nova:posts'] !== "undefined") {
|
|||
|
||||
if (!!subscribers && !!subscribers.length) {
|
||||
// remove userIds of users that have already been notified and of post's author
|
||||
let subscriberIdsToNotify = _.difference(subscribers, userIdsNotified, [post.userId]);
|
||||
let subscriberIdsToNotify = _.uniq(_.difference(subscribers, userIdsNotified, [post.userId]));
|
||||
|
||||
Telescope.notifications.create(subscriberIdsToNotify, 'newPost', notificationData);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Users.addField([
|
|||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ Users.addField([
|
|||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
},
|
||||
publish: true,
|
||||
|
@ -33,7 +33,7 @@ Users.addField([
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ if (typeof Package['nova:posts'] !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
},
|
||||
publish: true,
|
||||
|
@ -65,7 +65,7 @@ if (typeof Package['nova:posts'] !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ if (typeof Package['nova:categories'] !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: [String],
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
},
|
||||
publish: true,
|
||||
|
@ -99,7 +99,7 @@ if (typeof Package['nova:categories'] !== "undefined") {
|
|||
fieldSchema: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
autoform: {
|
||||
form: {
|
||||
omit: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ if (typeof Package['nova:posts'] !== "undefined") {
|
|||
import Posts from "meteor/nova:posts";
|
||||
|
||||
Posts.views.add("userSubscribedPosts", function (terms) {
|
||||
var user = Meteor.users.findOne(terms.userId),
|
||||
var user = Users.findOne(terms.userId),
|
||||
postsIds = [];
|
||||
|
||||
if (user && user.telescope.subscribedItems && user.telescope.subscribedItems.Posts) {
|
||||
|
|
|
@ -14,11 +14,11 @@ import NovaEmail from 'meteor/nova:email';
|
|||
Users.after.insert(function (userId, user) {
|
||||
|
||||
// run create user async callbacks
|
||||
Telescope.callbacks.runAsync("onCreateUserAsync", user);
|
||||
Telescope.callbacks.runAsync("users.new.async", user);
|
||||
|
||||
// check if all required fields have been filled in. If so, run profile completion callbacks
|
||||
if (Users.hasCompletedProfile(user)) {
|
||||
Telescope.callbacks.runAsync("profileCompletedAsync", user);
|
||||
Telescope.callbacks.runAsync("users.profileCompleted.async", user);
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -132,23 +132,24 @@ function setupUser (user, options) {
|
|||
user.telescope.displayName = user.username;
|
||||
}
|
||||
|
||||
// create slug from display name
|
||||
user.telescope.slug = Telescope.utils.slugify(user.telescope.displayName);
|
||||
// create a basic slug from display name and then modify it if this slugs already exists;
|
||||
const basicSlug = Telescope.utils.slugify(user.telescope.displayName);
|
||||
user.telescope.slug = Telescope.utils.getUnusedSlug(Users, basicSlug);
|
||||
|
||||
// if this is not a dummy account, and is the first user ever, make them an admin
|
||||
user.isAdmin = (!user.profile.isDummy && Meteor.users.find({'profile.isDummy': {$ne: true}}).count() === 0) ? true : false;
|
||||
user.isAdmin = (!user.profile.isDummy && Users.find({'profile.isDummy': {$ne: true}}).count() === 0) ? true : false;
|
||||
|
||||
Events.track('new user', {username: user.telescope.displayName, email: user.telescope.email});
|
||||
|
||||
return user;
|
||||
}
|
||||
Telescope.callbacks.add("onCreateUser", setupUser);
|
||||
Telescope.callbacks.add("users.new.sync", setupUser);
|
||||
|
||||
|
||||
function hasCompletedProfile (user) {
|
||||
return Users.hasCompletedProfile(user);
|
||||
}
|
||||
Telescope.callbacks.add("profileCompletedChecks", hasCompletedProfile);
|
||||
Telescope.callbacks.add("users.profileCompleted.sync", hasCompletedProfile);
|
||||
|
||||
function adminUserCreationNotification (user) {
|
||||
// send notifications to admins
|
||||
|
@ -162,4 +163,4 @@ function adminUserCreationNotification (user) {
|
|||
});
|
||||
return user;
|
||||
}
|
||||
Telescope.callbacks.add("onCreateUser", adminUserCreationNotification);
|
||||
Telescope.callbacks.add("users.new.sync", adminUserCreationNotification);
|
||||
|
|
|
@ -21,7 +21,7 @@ Users.getUser = function (userOrUserId) {
|
|||
return Meteor.user();
|
||||
}
|
||||
} else if (typeof userOrUserId === "string") {
|
||||
return Meteor.users.findOne(userOrUserId);
|
||||
return Users.findOne(userOrUserId);
|
||||
} else {
|
||||
return userOrUserId;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ Users.getUserName = function (user) {
|
|||
}
|
||||
};
|
||||
Users.helpers({getUserName: function () {return Users.getUserName(this);}});
|
||||
Users.getUserNameById = function (userId) {return Users.getUserName(Meteor.users.findOne(userId))};
|
||||
Users.getUserNameById = function (userId) {return Users.getUserName(Users.findOne(userId))};
|
||||
|
||||
/**
|
||||
* @summary Get a user's display name (not unique, can take special characters and spaces)
|
||||
|
@ -58,7 +58,7 @@ Users.getDisplayName = function (user) {
|
|||
}
|
||||
};
|
||||
Users.helpers({getDisplayName: function () {return Users.getDisplayName(this);}});
|
||||
Users.getDisplayNameById = function (userId) {return Users.getDisplayName(Meteor.users.findOne(userId));};
|
||||
Users.getDisplayNameById = function (userId) {return Users.getDisplayName(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Get a user's profile URL
|
||||
|
@ -105,7 +105,7 @@ Users.getTwitterName = function (user) {
|
|||
return null;
|
||||
};
|
||||
Users.helpers({getTwitterName: function () {return Users.getTwitterName(this);}});
|
||||
Users.getTwitterNameById = function (userId) {return Users.getTwitterName(Meteor.users.findOne(userId));};
|
||||
Users.getTwitterNameById = function (userId) {return Users.getTwitterName(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Get a user's GitHub name
|
||||
|
@ -121,7 +121,7 @@ Users.getGitHubName = function (user) {
|
|||
return null;
|
||||
};
|
||||
Users.helpers({getGitHubName: function () {return Users.getGitHubName(this);}});
|
||||
Users.getGitHubNameById = function (userId) {return Users.getGitHubName(Meteor.users.findOne(userId));};
|
||||
Users.getGitHubNameById = function (userId) {return Users.getGitHubName(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Get a user's email
|
||||
|
@ -135,7 +135,7 @@ Users.getEmail = function (user) {
|
|||
}
|
||||
};
|
||||
Users.helpers({getEmail: function () {return Users.getEmail(this);}});
|
||||
Users.getEmailById = function (userId) {return Users.getEmail(Meteor.users.findOne(userId));};
|
||||
Users.getEmailById = function (userId) {return Users.getEmail(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Get a user's email hash
|
||||
|
@ -145,7 +145,7 @@ Users.getEmailHash = function (user) {
|
|||
return user.telescope.emailHash;
|
||||
};
|
||||
Users.helpers({getEmailHash: function () {return Users.getEmailHash(this);}});
|
||||
Users.getEmailHashById = function (userId) {return Users.getEmailHash(Meteor.users.findOne(userId));};
|
||||
Users.getEmailHashById = function (userId) {return Users.getEmailHash(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Get a user setting
|
||||
|
@ -182,7 +182,7 @@ Users.hasCompletedProfile = function (user) {
|
|||
});
|
||||
};
|
||||
Users.helpers({hasCompletedProfile: function () {return Users.hasCompletedProfile(this);}});
|
||||
Users.hasCompletedProfileById = function (userId) {return Users.hasCompletedProfile(Meteor.users.findOne(userId));};
|
||||
Users.hasCompletedProfileById = function (userId) {return Users.hasCompletedProfile(Users.findOne(userId));};
|
||||
|
||||
/**
|
||||
* @summary Check if a user has upvoted a document
|
||||
|
@ -272,6 +272,6 @@ Users.getCurrentUserEmail = function () {
|
|||
};
|
||||
|
||||
Users.findByEmail = function (email) {
|
||||
return Meteor.users.findOne({"telescope.email": email});
|
||||
return Users.findOne({"telescope.email": email});
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ var completeUserProfile = function (userId, modifier, user) {
|
|||
|
||||
Users.update(userId, modifier);
|
||||
|
||||
Telescope.callbacks.runAsync("profileCompletedAsync", Users.findOne(userId));
|
||||
Telescope.callbacks.runAsync("users.profileCompleted.async", Users.findOne(userId));
|
||||
|
||||
return Users.findOne(userId);
|
||||
|
||||
|
@ -27,7 +27,7 @@ Users.methods.edit = (userId, modifier, user) => {
|
|||
|
||||
// ------------------------------ Callbacks ------------------------------ //
|
||||
|
||||
modifier = Telescope.callbacks.run("UsersEdit", modifier, user);
|
||||
modifier = Telescope.callbacks.run("users.edit.sync", modifier, user);
|
||||
|
||||
// ------------------------------ Update ------------------------------ //
|
||||
|
||||
|
@ -35,7 +35,7 @@ Users.methods.edit = (userId, modifier, user) => {
|
|||
|
||||
// ------------------------------ Callbacks ------------------------------ //
|
||||
|
||||
Telescope.callbacks.runAsync("UsersEditAsync", Users.findOne(userId), user);
|
||||
Telescope.callbacks.runAsync("users.edit.async", Users.findOne(userId), user);
|
||||
|
||||
// ------------------------------ After Update ------------------------------ //
|
||||
return Users.findOne(userId);
|
||||
|
@ -61,53 +61,6 @@ Users.methods.removeGroup = (userId, groupName) => {
|
|||
};
|
||||
|
||||
Meteor.methods({
|
||||
'users.compleProfile'(modifier, userId) {
|
||||
|
||||
check(modifier, Match.OneOf({$set: Object}, {$unset: Object}, {$set: Object, $unset: Object}));
|
||||
check(userId, String);
|
||||
|
||||
var currentUser = Meteor.user(),
|
||||
user = Users.findOne(userId),
|
||||
schema = Users.simpleSchema()._schema;
|
||||
|
||||
// ------------------------------ Checks ------------------------------ //
|
||||
|
||||
// check that user can edit document
|
||||
if (!user || !Users.canEdit(currentUser, user)) {
|
||||
throw new Meteor.Error(601, 'sorry_you_cannot_edit_this_user');
|
||||
}
|
||||
|
||||
// if an $unset modifier is present, it means one or more of the fields is missing
|
||||
if (modifier.$unset) {
|
||||
throw new Meteor.Error(601, 'all_fields_are_required');
|
||||
}
|
||||
|
||||
// check for existing emails and throw error if necessary
|
||||
// NOTE: redundant with collection hook, but better to throw the error here to avoid wiping out the form
|
||||
if (modifier.$set && modifier.$set["telescope.email"]) {
|
||||
var email = modifier.$set["telescope.email"];
|
||||
if (Users.findByEmail(email)) {
|
||||
throw new Meteor.Error("email_taken1", "this_email_is_already_taken" + " (" + email + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// go over each field and throw an error if it's not editable
|
||||
// loop over each operation ($set, $unset, etc.)
|
||||
_.each(modifier, function (operation) {
|
||||
// loop over each property being operated on
|
||||
_.keys(operation).forEach(function (fieldName) {
|
||||
var field = schema[fieldName];
|
||||
if (!Users.canEditField(user, field, user)) {
|
||||
throw new Meteor.Error("disallowed_property", 'disallowed_property_detected' + ": " + fieldName);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
completeUserProfile(userId, modifier, user);
|
||||
},
|
||||
|
||||
'users.edit'(userId, modifier) {
|
||||
|
||||
// checking might be redundant because SimpleSchema already enforces the schema, but you never know
|
||||
|
@ -149,7 +102,7 @@ Meteor.methods({
|
|||
|
||||
const user = Users.findOne(userId);
|
||||
|
||||
Meteor.users.remove(userId);
|
||||
Users.remove(userId);
|
||||
|
||||
Telescope.callbacks.runAsync("users.remove.async", user, options);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ Telescope.schemas.userData = new SimpleSchema({
|
|||
control: "textarea",
|
||||
insertableIf: canInsert,
|
||||
editableIf: canEdit,
|
||||
// autoform: {
|
||||
// form: {
|
||||
// rows: 5
|
||||
// }
|
||||
},
|
||||
|
@ -116,7 +116,7 @@ Telescope.schemas.userData = new SimpleSchema({
|
|||
publish: true,
|
||||
profile: true,
|
||||
optional: true,
|
||||
// autoform: {
|
||||
// form: {
|
||||
// omit: true
|
||||
// },
|
||||
template: "user_profile_bio"
|
||||
|
@ -146,7 +146,7 @@ Telescope.schemas.userData = new SimpleSchema({
|
|||
// optional: true,
|
||||
// editableIf: canEdit,
|
||||
// blackbox: true,
|
||||
// autoform: {
|
||||
// form: {
|
||||
// omit: true
|
||||
// }
|
||||
// },
|
||||
|
@ -209,7 +209,7 @@ Telescope.schemas.userData = new SimpleSchema({
|
|||
control: "checkboxgroup",
|
||||
insertableIf: canEditAll,
|
||||
editableIf: canEditAll,
|
||||
autoform: {
|
||||
form: {
|
||||
options: function () {
|
||||
const groups = _.without(_.keys(Users.groups), "anonymous", "default", "admins");
|
||||
return groups.map(group => {return {value: group, label: group};});
|
||||
|
@ -260,7 +260,7 @@ Users.schema = new SimpleSchema({
|
|||
insertableIf: canEditAll,
|
||||
editableIf: canEditAll,
|
||||
group: adminGroup
|
||||
// autoform: {
|
||||
// form: {
|
||||
// omit: true
|
||||
// }
|
||||
},
|
||||
|
@ -285,6 +285,6 @@ Users.schema = new SimpleSchema({
|
|||
// });
|
||||
|
||||
/**
|
||||
* @summary Attach schema to Meteor.users collection
|
||||
* @summary Attach schema to Users (Meteor.users at the moment) collection
|
||||
*/
|
||||
Users.attachSchema(Users.schema);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Telescope from 'meteor/nova:lib';
|
||||
|
||||
function telescopeCreateUserCallback (options, user) {
|
||||
user = Telescope.callbacks.run("onCreateUser", user, options);
|
||||
user = Telescope.callbacks.run("users.new.sync", user, options);
|
||||
return user;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ import Users from '../modules.js';
|
|||
Meteor.publish('users.single', function (terms) {
|
||||
|
||||
var idOrSlug = terms._id || terms['telescope.slug'];
|
||||
var findById = Meteor.users.findOne(idOrSlug);
|
||||
var findBySlug = Meteor.users.findOne({"telescope.slug": idOrSlug});
|
||||
var findById = Users.findOne(idOrSlug);
|
||||
var findBySlug = Users.findOne({"telescope.slug": idOrSlug});
|
||||
var user = typeof findById !== 'undefined' ? findById : findBySlug;
|
||||
var options = Users.isAdmin(this.userId) ? {} : {fields: Users.publishedFields.public};
|
||||
return user ? Meteor.users.find({_id: user._id}, options) : [];
|
||||
return user ? Users.find({_id: user._id}, options) : [];
|
||||
|
||||
});
|
||||
|
||||
|
@ -19,7 +19,7 @@ Meteor.publish('users.single', function (terms) {
|
|||
* @summary Publish the current user
|
||||
*/
|
||||
Meteor.publish('users.current', function () {
|
||||
const user = Meteor.users.find({_id: this.userId}, {fields: {'services.password.bcrypt': false}});
|
||||
const user = Users.find({_id: this.userId}, {fields: {'services.password.bcrypt': false}});
|
||||
return user || [];
|
||||
});
|
||||
|
||||
|
@ -32,7 +32,7 @@ Meteor.publish('users.current', function () {
|
|||
|
||||
// var selector = Settings.get('requirePostInvite') ? {isInvited: true} : {}; // only users that can post
|
||||
// if (Users.isAdminById(this.userId)) {
|
||||
// return Meteor.users.find(selector, {fields: Users.pubsub.avatarProperties});
|
||||
// return Users.find(selector, {fields: Users.pubsub.avatarProperties});
|
||||
// }
|
||||
// return [];
|
||||
// });
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"translation_function_name": "__",
|
||||
"helper_name": "_",
|
||||
"namespace": "project"
|
||||
}
|
Loading…
Add table
Reference in a new issue