mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 10:01:40 -05:00
Merge branch 'devel'
This commit is contained in:
commit
57bc830fc9
81 changed files with 645 additions and 491 deletions
|
@ -50,19 +50,18 @@ jparker:gravatar@0.4.1
|
|||
jquery@1.11.8
|
||||
kadira:debug@3.2.2
|
||||
kadira:dochead@1.5.0
|
||||
kadira:flow-router-ssr@3.13.0
|
||||
kadira:runtime-dev@0.0.1
|
||||
livedata@1.0.18
|
||||
localstorage@1.0.9
|
||||
logging@1.0.12
|
||||
matb33:collection-hooks@0.8.1
|
||||
mdg:validation-error@0.2.0
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.1.14
|
||||
meteor-base@1.0.4
|
||||
meteorhacks:fast-render@2.14.0
|
||||
meteorhacks:inject-data@2.0.0
|
||||
meteorhacks:inject-initial@1.0.4
|
||||
meteorhacks:kadira@2.28.7
|
||||
meteorhacks:kadira@2.28.5
|
||||
meteorhacks:kadira-binary-deps@1.4.0
|
||||
meteorhacks:kadira-profiler@1.2.1
|
||||
meteorhacks:meteorx@1.4.1
|
||||
|
@ -123,13 +122,14 @@ rate-limit@1.0.4
|
|||
react-meteor-data@0.2.9
|
||||
reactive-dict@1.1.7
|
||||
reactive-var@1.0.9
|
||||
reactrouter:react-router-ssr@3.1.3
|
||||
reload@1.1.8
|
||||
retry@1.0.7
|
||||
routepolicy@1.0.10
|
||||
service-configuration@1.0.9
|
||||
session@1.1.5
|
||||
sha@1.0.7
|
||||
softwarerero:accounts-t9n@1.3.4
|
||||
softwarerero:accounts-t9n@1.3.3
|
||||
spacebars@1.0.11
|
||||
spacebars-compiler@1.0.11
|
||||
srp@1.0.8
|
||||
|
@ -147,7 +147,7 @@ ui@1.0.11
|
|||
underscore@1.0.8
|
||||
url@1.0.9
|
||||
utilities:react-list-container@0.1.12
|
||||
utilities:smart-methods@0.1.4
|
||||
utilities:smart-methods@0.1.5
|
||||
utilities:smart-publications@0.1.4
|
||||
webapp@1.2.8
|
||||
webapp-hashing@1.0.9
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"formsy-react": "^0.18.0",
|
||||
"formsy-react-components": "^0.7.1",
|
||||
"handlebars": "^4.0.5",
|
||||
"history": "^3.0.0",
|
||||
"html-to-text": "^2.1.0",
|
||||
"intl": "^1.2.4",
|
||||
"intl-locales-supported": "^1.0.0",
|
||||
|
@ -25,14 +26,17 @@
|
|||
"react-bootstrap-datetimepicker": "0.0.22",
|
||||
"react-cookie": "^0.4.6",
|
||||
"react-dom": "^15.0.0",
|
||||
"react-intl": "^2.1.2",
|
||||
"react-intl": "^2.1.3",
|
||||
"react-komposer": "^1.8.0",
|
||||
"react-mounter": "^1.2.0",
|
||||
"react-no-ssr": "^1.1.0",
|
||||
"react-router": "^3.0.0-alpha.1",
|
||||
"react-router-bootstrap": "^0.23.0",
|
||||
"sanitize-html": "^1.11.4",
|
||||
"speakingurl": "^9.0.0",
|
||||
"tracker-component": "^1.3.14",
|
||||
"url": "^0.11.0"
|
||||
"url": "^0.11.0",
|
||||
"use-named-routes": "^0.3.1"
|
||||
},
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const Actions = {}
|
||||
|
||||
Actions.call = Meteor.call;
|
||||
|
||||
export default Actions;
|
|
@ -2,8 +2,8 @@ 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 { Messages } from "meteor/nova:core";
|
||||
//import Actions from "../actions.js";
|
||||
|
||||
class CategoriesEditForm extends Component{
|
||||
|
||||
|
@ -15,11 +15,11 @@ class CategoriesEditForm extends Component{
|
|||
deleteCategory() {
|
||||
const category = this.props.category;
|
||||
if (window.confirm(`Delete category “${category.name}”?`)) {
|
||||
Actions.call("categories.deleteById", category._id, (error, result) => {
|
||||
this.context.actions.call("categories.deleteById", category._id, (error, result) => {
|
||||
if (error) {
|
||||
Messages.flash(error.message, "error");
|
||||
this.context.messages.flash(error.message, "error");
|
||||
} else {
|
||||
Messages.flash(`Category “${category.name}” deleted and removed from ${result} posts.`, "success");
|
||||
this.context.messages.flash(`Category “${category.name}” deleted and removed from ${result} posts.`, "success");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class CategoriesEditForm extends Component{
|
|||
currentUser={this.context.currentUser}
|
||||
methodName="categories.edit"
|
||||
successCallback={(category)=>{
|
||||
Messages.flash("Category edited.", "success");
|
||||
this.context.messages.flash("Category edited.", "success");
|
||||
}}
|
||||
/>
|
||||
<hr/>
|
||||
|
@ -50,7 +50,9 @@ CategoriesEditForm.propTypes = {
|
|||
}
|
||||
|
||||
CategoriesEditForm.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
};
|
||||
|
||||
module.exports = CategoriesEditForm;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Button, DropdownButton, MenuItem, Modal } from 'react-bootstrap';
|
||||
import Router from "../router.js"
|
||||
import { ModalTrigger, ContextPasser } from "meteor/nova:core";
|
||||
import { /* ModalTrigger, */ ContextPasser } from "meteor/nova:core";
|
||||
import { withRouter } from 'react-router'
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
|
||||
// note: cannot use ModalTrigger component because of https://github.com/react-bootstrap/react-bootstrap/issues/1808
|
||||
|
||||
|
@ -40,7 +41,7 @@ class CategoriesList extends Component {
|
|||
<Modal.Title><FormattedMessage id="categories.edit"/></Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<ContextPasser currentUser={this.context.currentUser} closeCallback={this.closeModal}>
|
||||
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} closeCallback={this.closeModal}>
|
||||
<Telescope.components.CategoriesEditForm category={category}/>
|
||||
</ContextPasser>
|
||||
</Modal.Body>
|
||||
|
@ -56,7 +57,7 @@ class CategoriesList extends Component {
|
|||
<Modal.Title><FormattedMessage id="categories.new"/></Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<ContextPasser currentUser={this.context.currentUser} closeCallback={this.closeModal}>
|
||||
<ContextPasser currentUser={this.context.currentUser} messages={this.context.messages} closeCallback={this.closeModal}>
|
||||
<Telescope.components.CategoriesNewForm/>
|
||||
</ContextPasser>
|
||||
</Modal.Body>
|
||||
|
@ -78,9 +79,8 @@ class CategoriesList extends Component {
|
|||
|
||||
const categories = this.props.categories;
|
||||
const context = this.context;
|
||||
|
||||
const currentRoute = context.currentRoute;
|
||||
const currentCategorySlug = currentRoute.queryParams.cat;
|
||||
const currentQuery = _.clone(this.props.router.location.query);
|
||||
delete currentQuery.cat;
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -90,8 +90,14 @@ class CategoriesList extends Component {
|
|||
title={<FormattedMessage id="categories"/>}
|
||||
id="categories-dropdown"
|
||||
>
|
||||
<div className="category-menu-item dropdown-item"><MenuItem href={Router.path("posts.list")} eventKey={0}><FormattedMessage id="categories.all"/></MenuItem></div>
|
||||
{categories && categories.length > 0 ? categories.map((category, index) => <Telescope.components.Category key={index} category={category} index={index} currentCategorySlug={currentCategorySlug} openModal={_.partial(this.openCategoryEditModal, index)}/>) : null}
|
||||
<div className="category-menu-item dropdown-item">
|
||||
<LinkContainer to={{pathname:"/", query: currentQuery}} activeClassName="category-active">
|
||||
<MenuItem eventKey={0}>
|
||||
<FormattedMessage id="categories.all"/>
|
||||
</MenuItem>
|
||||
</LinkContainer>
|
||||
</div>
|
||||
{categories && categories.length > 0 ? categories.map((category, index) => <Telescope.components.Category key={index} category={category} index={index} openModal={_.partial(this.openCategoryEditModal, index)}/>) : null}
|
||||
{Users.is.admin(this.context.currentUser) ? this.renderCategoryNewButton() : null}
|
||||
</DropdownButton>
|
||||
<div>
|
||||
|
@ -111,8 +117,8 @@ CategoriesList.propTypes = {
|
|||
|
||||
CategoriesList.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
currentRoute: React.PropTypes.object
|
||||
messages: React.PropTypes.object,
|
||||
};
|
||||
|
||||
module.exports = CategoriesList;
|
||||
export default CategoriesList;
|
||||
module.exports = withRouter(CategoriesList);
|
||||
export default withRouter(CategoriesList);
|
|
@ -1,8 +1,5 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Router from '../router.js'
|
||||
|
||||
import { Messages } from "meteor/nova:core";
|
||||
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
|
||||
const CategoriesNewForm = (props, context) => {
|
||||
|
@ -14,7 +11,7 @@ const CategoriesNewForm = (props, context) => {
|
|||
currentUser={context.currentUser}
|
||||
methodName="categories.new"
|
||||
successCallback={(category)=>{
|
||||
Messages.flash("Category created.", "success");
|
||||
context.messages.flash("Category created.", "success");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -24,7 +21,8 @@ const CategoriesNewForm = (props, context) => {
|
|||
CategoriesNewForm.displayName = "CategoriesNewForm";
|
||||
|
||||
CategoriesNewForm.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
};
|
||||
|
||||
module.exports = CategoriesNewForm;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Actions from "../actions.js"
|
||||
import Router from "../router.js"
|
||||
import { Button, DropdownButton, MenuItem } from 'react-bootstrap';
|
||||
import classNames from "classnames";
|
||||
import { Messages, ModalTrigger } from "meteor/nova:core";
|
||||
//import { Messages, ModalTrigger } from 'meteor/nova:core';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
class Category extends Component {
|
||||
|
||||
|
@ -18,20 +18,24 @@ class Category extends Component {
|
|||
|
||||
render() {
|
||||
|
||||
const {category, index, currentCategorySlug} = this.props;
|
||||
const {category, index, router} = this.props;
|
||||
|
||||
const categoryClass = classNames("category-menu-item", "dropdown-item", {"category-active": currentCategorySlug === category.slug});
|
||||
const currentQuery = router.location.query;
|
||||
const currentCategorySlug = router.location.query.cat;
|
||||
const newQuery = _.clone(router.location.query);
|
||||
newQuery.cat = category.slug;
|
||||
|
||||
return (
|
||||
<div className={categoryClass}>
|
||||
<MenuItem
|
||||
href={Router.extendPathWithQueryParams("posts.list", {}, {cat: category.slug})}
|
||||
eventKey={index+1}
|
||||
key={category._id}
|
||||
>
|
||||
{currentCategorySlug === category.slug ? <Telescope.components.Icon name="voted"/> : null}
|
||||
{category.name}
|
||||
</MenuItem>
|
||||
<div className="category-menu-item dropdown-item">
|
||||
<LinkContainer to={{pathname:"/", query: newQuery}} activeClassName="category-active">
|
||||
<MenuItem
|
||||
eventKey={index+1}
|
||||
key={category._id}
|
||||
>
|
||||
{currentCategorySlug === category.slug ? <Telescope.components.Icon name="voted"/> : null}
|
||||
{category.name}
|
||||
</MenuItem>
|
||||
</LinkContainer>
|
||||
{Users.is.admin(this.context.currentUser) ? this.renderEdit() : null}
|
||||
</div>
|
||||
)
|
||||
|
@ -49,5 +53,5 @@ Category.contextTypes = {
|
|||
currentUser: React.PropTypes.object
|
||||
};
|
||||
|
||||
module.exports = Category;
|
||||
export default Category;
|
||||
module.exports = withRouter(Category);
|
||||
export default withRouter(Category);
|
|
@ -1,5 +1,4 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Actions from '../actions.js';
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
|
||||
class CommentsEdit extends Component {
|
||||
|
|
|
@ -49,8 +49,8 @@ class CommentsItem extends Component{
|
|||
|
||||
if (window.confirm(deleteConfirmMessage)) {
|
||||
Meteor.call('comments.deleteById', comment._id, (error, result) => {
|
||||
Messages.flash(deleteSuccessMessage, "success");
|
||||
Events.track("comment deleted", {'_id': comment._id});
|
||||
this.context.messages.flash(deleteSuccessMessage, "success");
|
||||
this.context.events.track("comment deleted", {'_id': comment._id});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,8 @@ CommentsItem.propTypes = {
|
|||
}
|
||||
|
||||
CommentsItem.contextTypes = {
|
||||
messages: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Actions from '../actions.js';
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
|
||||
class CommentsNew extends Component {
|
||||
|
|
|
@ -17,22 +17,23 @@ class App extends Component {
|
|||
|
||||
return {
|
||||
currentUser: this.props.currentUser,
|
||||
currentRoute: this.props.currentRoute,
|
||||
actions: this.props.actions,
|
||||
events: this.props.events,
|
||||
messages: this.props.messages,
|
||||
intl: intl
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.props.ready) {
|
||||
return (
|
||||
<IntlProvider locale={this.getLocale()} messages={Telescope.strings[this.getLocale()]}>
|
||||
<Telescope.components.Layout currentUser={this.props.currentUser}>{this.props.content}</Telescope.components.Layout>
|
||||
</IntlProvider>
|
||||
)
|
||||
} else {
|
||||
return <Telescope.components.AppLoading />
|
||||
}
|
||||
return (
|
||||
<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.AppLoading />
|
||||
}
|
||||
</IntlProvider>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,12 +41,16 @@ class App extends Component {
|
|||
App.propTypes = {
|
||||
ready: React.PropTypes.bool,
|
||||
currentUser: React.PropTypes.object,
|
||||
currentRoute: React.PropTypes.object
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
}
|
||||
|
||||
App.childContextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
currentRoute: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
|
||||
import { Messages } from "meteor/nova:core";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
class Flash extends Component{
|
||||
|
||||
|
@ -11,12 +10,12 @@ class Flash extends Component{
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
Messages.markAsSeen(this.props.message._id);
|
||||
this.context.messages.markAsSeen(this.props.message._id);
|
||||
}
|
||||
|
||||
dismissFlash(e) {
|
||||
e.preventDefault();
|
||||
Messages.clear(this.props.message._id);
|
||||
this.context.messages.clear(this.props.message._id);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -36,4 +35,8 @@ Flash.propTypes = {
|
|||
message: React.PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
Flash.contextTypes = {
|
||||
messages: React.PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
module.exports = Flash;
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Messages } from "meteor/nova:core";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
const Header = ({currentUser}) => {
|
||||
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import React from 'react';
|
||||
import { IndexLink } from 'react-router';
|
||||
|
||||
const Logo = ({logoUrl, siteTitle}) => {
|
||||
if (logoUrl) {
|
||||
return (
|
||||
<h1 className="logo-image ">
|
||||
<a href="/">
|
||||
<IndexLink to={{pathname: "/"}}>
|
||||
<img src={logoUrl} alt={siteTitle} style={{maxWidth: "100px", maxHeight: "100px"}} />
|
||||
</a>
|
||||
</IndexLink>
|
||||
</h1>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<h1 className="logo-text"><a href="/">{siteTitle}</a></h1>
|
||||
<h1 className="logo-text">
|
||||
<IndexLink to={{pathname: "/"}}>{siteTitle}</IndexLink>
|
||||
</h1>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ 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 Actions from "../actions.js";
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Cookie from 'react-cookie';
|
||||
|
||||
import { Messages } from "meteor/nova:core";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
|
||||
class Newsletter extends Component {
|
||||
|
@ -37,10 +36,10 @@ class Newsletter extends Component {
|
|||
}
|
||||
|
||||
subscribeEmail(data) {
|
||||
Actions.call("newsletter.addEmail", data.email, (error, result) => {
|
||||
this.context.actions.call("newsletter.addEmail", data.email, (error, result) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
Messages.flash(error.message, "error");
|
||||
this.context.messages.flash(error.message, "error");
|
||||
} else {
|
||||
this.successCallbackSubscription(result);
|
||||
}
|
||||
|
@ -48,7 +47,7 @@ class Newsletter extends Component {
|
|||
}
|
||||
|
||||
successCallbackSubscription(result) {
|
||||
Messages.flash(this.context.intl.formatMessage({id: "newsletter.success_message"}), "success");
|
||||
this.context.messages.flash(this.context.intl.formatMessage({id: "newsletter.success_message"}), "success");
|
||||
this.dismissBanner();
|
||||
}
|
||||
|
||||
|
@ -99,6 +98,8 @@ class Newsletter extends Component {
|
|||
|
||||
Newsletter.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class NewsletterButton extends Component {
|
|||
Meteor.call(action, this.context.currentUser, (error, result) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
Messages.flash(error.message, "error");
|
||||
this.context.messages.flash(error.message, "error");
|
||||
} else {
|
||||
this.props.successCallback(result);
|
||||
}
|
||||
|
@ -42,10 +42,9 @@ NewsletterButton.propTypes = {
|
|||
successCallback: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
||||
|
||||
NewsletterButton.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
}
|
||||
|
||||
module.exports = NewsletterButton;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { intlShape } from 'react-intl';
|
||||
import Router from '../router.js'
|
||||
import Formsy from 'formsy-react';
|
||||
import FRC from 'formsy-react-components';
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
const Input = FRC.Input;
|
||||
|
||||
|
@ -17,37 +17,38 @@ const delay = (function(){
|
|||
|
||||
class SearchForm extends Component{
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.search = this.search.bind(this);
|
||||
this.state = {
|
||||
search: props.router.location.query.query || ''
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
search: this.props.router.location.query.query || ''
|
||||
});
|
||||
}
|
||||
|
||||
search(data) {
|
||||
|
||||
if (Router.getRouteName() !== "posts.list") {
|
||||
Router.go("posts.list");
|
||||
}
|
||||
|
||||
if (data.searchQuery === '') {
|
||||
data.searchQuery = null;
|
||||
}
|
||||
const router = this.props.router;
|
||||
const query = data.searchQuery === '' ? {} : {query: data.searchQuery};
|
||||
|
||||
delay(function(){
|
||||
Router.setQueryParams({query: data.searchQuery});
|
||||
delay(() => {
|
||||
router.push({pathname: "/", query: query});
|
||||
}, 700 );
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const currentQuery = this.context.currentRoute.queryParams.query;
|
||||
|
||||
return (
|
||||
<div className="search-form">
|
||||
<Formsy.Form onChange={this.search}>
|
||||
<Input
|
||||
name="searchQuery"
|
||||
value={currentQuery}
|
||||
value={this.state.search}
|
||||
placeholder={this.context.intl.formatMessage({id: "posts.search"})}
|
||||
type="text"
|
||||
layout="elementOnly"
|
||||
|
@ -64,5 +65,5 @@ SearchForm.contextTypes = {
|
|||
intl: intlShape
|
||||
}
|
||||
|
||||
module.exports = SearchForm;
|
||||
export default SearchForm;
|
||||
module.exports = withRouter(SearchForm);
|
||||
export default withRouter(SearchForm);
|
|
@ -2,7 +2,7 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
import { Messages } from "meteor/nova:core";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
class SettingsEditForm extends Component{
|
||||
|
||||
|
@ -23,7 +23,7 @@ class SettingsEditForm extends Component{
|
|||
currentUser: this.context.currentUser,
|
||||
methodName: "settings.edit",
|
||||
successCallback: (category) => {
|
||||
Messages.flash(this.context.intl.formatMessage({id: "settings.edited"}), "success");
|
||||
this.context.messages.flash(this.context.intl.formatMessage({id: "settings.edited"}), "success");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -34,6 +34,7 @@ class SettingsEditForm extends Component{
|
|||
|
||||
SettingsEditForm.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Actions from "../actions.js";
|
||||
import { Messages } from "meteor/nova:core";
|
||||
//import Actions from "../actions.js";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
import classNames from 'classnames';
|
||||
|
||||
class Vote extends Component {
|
||||
|
@ -17,14 +17,14 @@ class Vote extends Component {
|
|||
const user = this.context.currentUser;
|
||||
|
||||
if(!user){
|
||||
Messages.flash("Please log in first");
|
||||
this.context.messages.flash("Please log in first");
|
||||
} else if (user.hasUpvoted(post)) {
|
||||
Actions.call('posts.cancelUpvote', post._id, function(){
|
||||
Events.track("post upvote cancelled", {'_id': post._id});
|
||||
this.context.actions.call('posts.cancelUpvote', post._id, function(){
|
||||
this.context.events.track("post upvote cancelled", {'_id': post._id});
|
||||
});
|
||||
} else {
|
||||
Actions.call('posts.upvote', post._id, function(){
|
||||
Events.track("post upvoted", {'_id': post._id});
|
||||
this.context.actions.call('posts.upvote', post._id, function(){
|
||||
this.context.events.track("post upvoted", {'_id': post._id});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,10 @@ Vote.propTypes = {
|
|||
}
|
||||
|
||||
Vote.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
};
|
||||
|
||||
module.exports = Vote;
|
||||
|
|
|
@ -20,6 +20,8 @@ Telescope.registerComponent("SettingsEditForm", require('./common/SettingsEd
|
|||
|
||||
// posts
|
||||
|
||||
Telescope.registerComponent("PostsHome", require('./posts/PostsHome.jsx'));
|
||||
Telescope.registerComponent("PostsSingle", require('./posts/PostsSingle.jsx'));
|
||||
Telescope.registerComponent("PostsNewButton", require('./posts/PostsNewButton.jsx'));
|
||||
Telescope.registerComponent("PostsLoadMore", require('./posts/PostsLoadMore.jsx'));
|
||||
Telescope.registerComponent("PostsNoMore", require('./posts/PostsNoMore.jsx'));
|
||||
|
@ -66,6 +68,8 @@ Telescope.registerComponent("CanEditUser", require('./permissions/CanEd
|
|||
|
||||
// users
|
||||
|
||||
Telescope.registerComponent("UsersSingle", require('./users/UsersSingle.jsx'));
|
||||
Telescope.registerComponent("UsersAccount", require('./users/UsersAccount.jsx'));
|
||||
Telescope.registerComponent("UsersEdit", require('./users/UsersEdit.jsx'));
|
||||
Telescope.registerComponent("UsersProfile", require('./users/UsersProfile.jsx'));
|
||||
Telescope.registerComponent("UsersProfileCheck", require('./users/UsersProfileCheck.jsx'));
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React from 'react';
|
||||
import Router from '../router.js';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
const PostsCategories = ({post}) => {
|
||||
return (
|
||||
<div className="posts-categories">
|
||||
{post.categoriesArray.map(category => <a className="posts-category" key={category._id} href={Router.path("posts.list", {}, {cat: category.slug})}>{category.name}</a>)}
|
||||
{post.categoriesArray.map(category =>
|
||||
<Link className="posts-category" key={category._id} to={{pathname: "/", query: {cat: category.slug}}}>{category.name}</Link>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
const PostsCommenters = ({post}) => {
|
||||
return (
|
||||
|
@ -7,11 +8,11 @@ const PostsCommenters = ({post}) => {
|
|||
{post.commentersArray.map(user => <Telescope.components.UsersAvatar key={user._id} user={user}/>)}
|
||||
</div>
|
||||
<div className="posts-commenters-discuss">
|
||||
<a href={Posts.getPageUrl(post)}>
|
||||
<Link to={`/posts/${post._id}/${post.slug}/`}>
|
||||
<Telescope.components.Icon name="comment" />
|
||||
<span className="posts-commenters-comments-count">{post.commentCount}</span>
|
||||
<span className="sr-only">Comments</span>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -2,8 +2,8 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage, intlShape } 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 { Messages } from "meteor/nova:core";
|
||||
//import Actions from "../actions.js";
|
||||
|
||||
class PostsEditForm extends Component{
|
||||
|
||||
|
@ -18,9 +18,9 @@ class PostsEditForm extends Component{
|
|||
const deletePostSuccess = this.context.intl.formatMessage({id: "posts.delete_success"}, {title: post.title});
|
||||
|
||||
if (window.confirm(deletePostConfirm)) {
|
||||
Actions.call('posts.deleteById', post._id, (error, result) => {
|
||||
Messages.flash(deletePostSuccess, "success");
|
||||
Events.track("post deleted", {'_id': post._id});
|
||||
this.context.actions.call('posts.deleteById', post._id, (error, result) => {
|
||||
this.context.messages.flash(deletePostSuccess, "success");
|
||||
this.context.events.track("post deleted", {'_id': post._id});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,10 @@ class PostsEditForm extends Component{
|
|||
// note: the document prop will be passed from DocumentContainer
|
||||
collection: Posts,
|
||||
currentUser: this.context.currentUser,
|
||||
methodName: "posts.edit"
|
||||
methodName: "posts.edit",
|
||||
successCallback: (post) => {
|
||||
this.context.messages.flash(this.context.intl.formatMessage({id: "posts.edit_success"}, {title: post.title}), 'success')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<hr/>
|
||||
|
@ -67,6 +70,9 @@ PostsEditForm.propTypes = {
|
|||
|
||||
PostsEditForm.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
|
||||
|
|
30
packages/nova-base-components/lib/posts/PostsHome.jsx
Normal file
30
packages/nova-base-components/lib/posts/PostsHome.jsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
|
||||
const PostsHome = (props, context) => {
|
||||
|
||||
const params = _.isEmpty(props.location.query) ? {view: 'top'} : _.clone(props.location.query);
|
||||
params.listId = "posts.list.main";
|
||||
|
||||
const {selector, options} = Posts.parameters.get(params);
|
||||
|
||||
return (
|
||||
<ListContainer
|
||||
collection={Posts}
|
||||
publication="posts.list"
|
||||
selector={selector}
|
||||
options={options}
|
||||
terms={params}
|
||||
joins={Posts.getJoins()}
|
||||
component={Telescope.components.PostsList}
|
||||
cacheSubscription={false}
|
||||
listId={params.listId}
|
||||
limit={Telescope.settings.get("postsPerPage", 10)}
|
||||
/>
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
PostsHome.displayName = "PostsHome";
|
||||
|
||||
module.exports = PostsHome;
|
|
@ -3,6 +3,7 @@ import { FormattedMessage, FormattedRelative } from 'react-intl';
|
|||
import { Button } from 'react-bootstrap';
|
||||
import moment from 'moment';
|
||||
import { ModalTrigger } from "meteor/nova:core";
|
||||
import { Link } from 'react-router';
|
||||
|
||||
class PostsItem extends Component {
|
||||
|
||||
|
@ -51,15 +52,20 @@ class PostsItem extends Component {
|
|||
<div className="posts-item-content">
|
||||
|
||||
<h3 className="posts-item-title">
|
||||
<a className="posts-item-title-link" href={Posts.getLink(post)} target={Posts.getLinkTarget(post)}>{post.title}</a>
|
||||
<Link to={`posts/${post._id}/${post.slug}/`} /*to={{name: "posts.single", params: {_id: post._id, slug: post.slug}}}*/ className="posts-item-title-link" target={Posts.getLinkTarget(post)}>
|
||||
{post.title}
|
||||
</Link>
|
||||
{this.renderCategories()}
|
||||
</h3>
|
||||
|
||||
<div className="posts-item-meta">
|
||||
{post.user? <div className="posts-item-user"><Telescope.components.UsersAvatar user={post.user} size="small"/><Telescope.components.UsersName user={post.user}/></div> : null}
|
||||
<div className="posts-item-date"><FormattedRelative value={post.postedAt}/></div>
|
||||
<div className="posts-item-comments"><a href={Posts.getPageUrl(post)}><FormattedMessage id="comments.count" values={{count: post.commentCount}}/></a></div>
|
||||
|
||||
<div className="posts-item-comments">
|
||||
<Link to={`posts/${post._id}/${post.slug}/`} /*to={{name: "posts.single", params: {_id: post._id, slug: post.slug}}}*/>
|
||||
<FormattedMessage id="comments.count" values={{count: post.commentCount}}/>
|
||||
</Link>
|
||||
</div>
|
||||
{(this.context.currentUser && this.context.currentUser.isAdmin) ?<Telescope.components.PostsStats post={post} />:null}
|
||||
{this.renderActions()}
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@ PostsNewButton.displayName = "PostsNewButton";
|
|||
|
||||
PostsNewButton.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { intlShape } from 'react-intl';
|
||||
import Router from '../router.js'
|
||||
|
||||
import { Messages } from "meteor/nova:core";
|
||||
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
const PostsNewForm = (props, context) => {
|
||||
|
||||
const router = props.router;
|
||||
|
||||
return (
|
||||
<Telescope.components.CanCreatePost>
|
||||
|
@ -16,8 +15,8 @@ const PostsNewForm = (props, context) => {
|
|||
currentUser={context.currentUser}
|
||||
methodName="posts.new"
|
||||
successCallback={(post)=>{
|
||||
Messages.flash(context.intl.formatMessage({id: "posts.created_message"}), "success");
|
||||
Router.go('posts.single', post);
|
||||
context.messages.flash(context.intl.formatMessage({id: "posts.created_message"}), "success");
|
||||
router.push({pathname: Posts.getPageUrl(post)});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -27,10 +26,11 @@ const PostsNewForm = (props, context) => {
|
|||
|
||||
PostsNewForm.contextTypes = {
|
||||
currentUser: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
intl: intlShape
|
||||
};
|
||||
|
||||
PostsNewForm.displayName = "PostsNewForm";
|
||||
|
||||
module.exports = PostsNewForm;
|
||||
export default PostsNewForm;
|
||||
module.exports = withRouter(PostsNewForm);
|
||||
export default withRouter(PostsNewForm);
|
19
packages/nova-base-components/lib/posts/PostsSingle.jsx
Normal file
19
packages/nova-base-components/lib/posts/PostsSingle.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
|
||||
const PostsSingle = (props, context) => {
|
||||
return (
|
||||
<DocumentContainer
|
||||
collection={Posts}
|
||||
publication="posts.single"
|
||||
selector={{_id: props.params._id}}
|
||||
terms={props.params}
|
||||
joins={Posts.getJoins()}
|
||||
component={Telescope.components.PostsPage}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
||||
PostsSingle.displayName = "PostsSingle";
|
||||
|
||||
module.exports = PostsSingle;
|
|
@ -1,7 +1,8 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import Router from '../router.js';
|
||||
import { Button, ButtonGroup, DropdownButton, MenuItem } from 'react-bootstrap';
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
const PostsViews = (props, context) => {
|
||||
|
||||
|
@ -12,18 +13,10 @@ const PostsViews = (props, context) => {
|
|||
views = views.concat(adminViews);
|
||||
}
|
||||
|
||||
const currentRoute = context.currentRoute;
|
||||
const currentView = currentRoute.queryParams.view || props.defaultView;
|
||||
// console.log(currentRoute);
|
||||
|
||||
const query = _.clone(props.router.location.query);
|
||||
|
||||
return (
|
||||
<div className="posts-views">
|
||||
{/*
|
||||
<ButtonGroup>
|
||||
{views.map(view => <Button className={currentRoute.route.name === "posts.list" && currentView === view ? "post-view-active" : "post-view-inactive"} bsStyle="default" key={view} href={Router.extendPathWithQueryParams("posts.list", {}, {view: view})}>{Telescope.utils.capitalise(view)}</Button>)}
|
||||
</ButtonGroup>
|
||||
<Button bsStyle="default" href={Router.path("posts.daily")} className={currentRoute.route.name === "posts.daily" ? "post-view-active" : "post-view-inactive"} >Daily</Button>
|
||||
*/}
|
||||
<DropdownButton
|
||||
bsStyle="default"
|
||||
className="views btn-secondary"
|
||||
|
@ -31,11 +24,17 @@ const PostsViews = (props, context) => {
|
|||
id="views-dropdown"
|
||||
>
|
||||
{views.map(view =>
|
||||
<MenuItem key={view} href={Router.extendPathWithQueryParams("posts.list", {}, {view: view})} className={currentRoute.route.name === "posts.list" && currentView === view ? "dropdown-item post-view-active" : "dropdown-item post-view-inactive"}>
|
||||
<FormattedMessage id={"posts."+view}/>
|
||||
</MenuItem>
|
||||
<LinkContainer key={view} to={{pathname: "/", query: {...query, view: view}}} /*to={}*/ className="dropdown-item" activeClassName="posts-view-active">
|
||||
<MenuItem>
|
||||
<FormattedMessage id={"posts."+view}/>
|
||||
</MenuItem>
|
||||
</LinkContainer>
|
||||
)}
|
||||
<MenuItem href={Router.path("posts.daily")} className={currentRoute.route.name === "posts.daily" ? "dropdown-item post-view-active" : "dropdown-item post-view-inactive"} ><FormattedMessage id="posts.daily"/></MenuItem>
|
||||
<LinkContainer to={"/daily"} /*to={{name: "posts.daily"}}*/ className="dropdown-item" activeClassName="posts-view-active">
|
||||
<MenuItem className={"bar"}>
|
||||
<FormattedMessage id="posts.daily"/>
|
||||
</MenuItem>
|
||||
</LinkContainer>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
)
|
||||
|
@ -57,4 +56,4 @@ PostsViews.contextTypes = {
|
|||
|
||||
PostsViews.displayName = "PostsViews";
|
||||
|
||||
module.exports = PostsViews;
|
||||
module.exports = withRouter(PostsViews);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
const Router = FlowRouter;
|
||||
|
||||
export default Router;
|
23
packages/nova-base-components/lib/users/UsersAccount.jsx
Normal file
23
packages/nova-base-components/lib/users/UsersAccount.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
|
||||
const UsersAccount = (props, context) => {
|
||||
const params = props.params.slug ? props.params : {_id: context.currentUser._id};
|
||||
return (
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={params}
|
||||
terms={params}
|
||||
component={Telescope.components.UsersEdit}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
||||
UsersAccount.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
}
|
||||
|
||||
UsersAccount.displayName = "PostsSingle";
|
||||
|
||||
module.exports = UsersAccount;
|
|
@ -1,7 +1,5 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import Router from '../router.js';
|
||||
import { Button, FormControl } from 'react-bootstrap';
|
||||
|
||||
import { Accounts } from 'meteor/std:accounts-ui';
|
||||
|
||||
const UsersAccountForm = () => {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Row, Col } from 'react-bootstrap';
|
||||
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
//import { Messages } from "meteor/nova:core";
|
||||
|
||||
import { Messages } from "meteor/nova:core";
|
||||
|
||||
const UsersEdit = ({document, currentUser}) => {
|
||||
const UsersEdit = ({document, currentUser}, context) => {
|
||||
|
||||
const user = document;
|
||||
//const label = `Edit profile for ${Users.getDisplayName(user)}`;
|
||||
|
@ -21,7 +19,7 @@ const UsersEdit = ({document, currentUser}) => {
|
|||
document={user}
|
||||
methodName="users.edit"
|
||||
successCallback={(user)=>{
|
||||
Messages.flash("User updated.", "success");
|
||||
context.messages.flash("User updated.", "success");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -35,6 +33,10 @@ UsersEdit.propTypes = {
|
|||
currentUser: React.PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
UsersEdit.contextTypes = {
|
||||
messages: React.PropTypes.object
|
||||
};
|
||||
|
||||
UsersEdit.displayName = "UsersEdit";
|
||||
|
||||
module.exports = UsersEdit;
|
||||
|
|
|
@ -2,9 +2,9 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Accounts } from 'meteor/std:accounts-ui';
|
||||
import Router from '../router.js';
|
||||
import { Modal, Dropdown, MenuItem } from 'react-bootstrap';
|
||||
import { ContextPasser } from "meteor/nova:core";
|
||||
import { LinkContainer } from 'react-router-bootstrap';
|
||||
|
||||
class UsersMenu extends Component {
|
||||
|
||||
|
@ -33,7 +33,7 @@ class UsersMenu extends Component {
|
|||
<Modal.Title><FormattedMessage id="settings.edit"/></Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<ContextPasser currentUser={this.props.user} closeCallback={this.closeModal}>
|
||||
<ContextPasser currentUser={this.props.user} messages={this.context.messages} closeCallback={this.closeModal}>
|
||||
<SettingsEditForm/>
|
||||
</ContextPasser>
|
||||
</Modal.Body>
|
||||
|
@ -53,8 +53,12 @@ class UsersMenu extends Component {
|
|||
<div>{Users.getDisplayName(user)}</div>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<MenuItem className="dropdown-item" eventKey="1" href={Router.path("users.single", {slug: user.telescope.slug})}><FormattedMessage id="users.profile"/></MenuItem>
|
||||
<MenuItem className="dropdown-item" eventKey="2" href={Router.path("account")}><FormattedMessage id="users.edit_account"/></MenuItem>
|
||||
<LinkContainer to={`/users/${user.telescope.slug}`} /*to={{name: "users.single", params: {slug: user.telescope.slug}}}*/>
|
||||
<MenuItem className="dropdown-item" eventKey="1"><FormattedMessage id="users.profile"/></MenuItem>
|
||||
</LinkContainer>
|
||||
<LinkContainer to={`/account`} /*to={{name: "account"}}*/>
|
||||
<MenuItem className="dropdown-item" eventKey="2"><FormattedMessage id="users.edit_account"/></MenuItem>
|
||||
</LinkContainer>
|
||||
{Users.is.admin(user) ? <MenuItem className="dropdown-item" eventKey="3" onClick={this.openModal}><FormattedMessage id="settings"/></MenuItem> : null}
|
||||
<MenuItem className="dropdown-item" eventKey="4" onClick={() => Meteor.logout(Accounts.ui._options.onSignedOutHook())}><FormattedMessage id="users.log_out"/></MenuItem>
|
||||
</Dropdown.Menu>
|
||||
|
@ -70,5 +74,9 @@ UsersMenu.propTypes = {
|
|||
user: React.PropTypes.object
|
||||
}
|
||||
|
||||
UsersMenu.contextTypes = {
|
||||
messages: React.PropTypes.object
|
||||
}
|
||||
|
||||
module.exports = UsersMenu;
|
||||
export default UsersMenu;
|
|
@ -1,10 +1,10 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
import Router from '../router.js';
|
||||
import NovaForm from "meteor/nova:forms";
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
const UsersProfileCheckModal = ({currentUser, show}) => {
|
||||
const UsersProfileCheckModal = ({currentUser, show, router}) => {
|
||||
|
||||
// return fields that are required by the schema but haven't been filled out yet
|
||||
const schema = Users.simpleSchema()._schema;
|
||||
|
@ -29,7 +29,7 @@ const UsersProfileCheckModal = ({currentUser, show}) => {
|
|||
/>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<FormattedMessage id="app.or"/> <a className="complete-profile-logout" onClick={ () => Meteor.logout(() => Router.go('/')) }><FormattedMessage id="users.log_out"/></a>
|
||||
<FormattedMessage id="app.or"/> <a className="complete-profile-logout" onClick={ () => Meteor.logout(() => router.push({pathname: '/'})) }><FormattedMessage id="users.log_out"/></a>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
)
|
||||
|
@ -48,5 +48,5 @@ UsersProfileCheck.contextTypes = {
|
|||
|
||||
UsersProfileCheck.displayName = "UsersProfileCheck";
|
||||
|
||||
module.exports = UsersProfileCheck;
|
||||
export default UsersProfileCheck;
|
||||
module.exports = withRouter(UsersProfileCheck);
|
||||
export default withRouter(UsersProfileCheck);
|
19
packages/nova-base-components/lib/users/UsersSingle.jsx
Normal file
19
packages/nova-base-components/lib/users/UsersSingle.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
import { DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
|
||||
const UsersSingle = (props, context) => {
|
||||
return (
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={{'telescope.slug': props.params.slug}}
|
||||
terms={{'telescope.slug': props.params.slug}}
|
||||
component={Telescope.components.UsersProfile}
|
||||
documentPropName="user"
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
||||
UsersSingle.displayName = "PostsSingle";
|
||||
|
||||
module.exports = UsersSingle;
|
|
@ -1,132 +1,53 @@
|
|||
import React from 'react';
|
||||
import {mount} from 'react-mounter';
|
||||
|
||||
import { IndexRoute, Route, useRouterHistory, browserHistory, createMemoryHistory } from 'react-router';
|
||||
import { ReactRouterSSR } from 'meteor/reactrouter:react-router-ssr';
|
||||
import { ListContainer, DocumentContainer } from "meteor/utilities:react-list-container";
|
||||
import useNamedRoutes from 'use-named-routes';
|
||||
import createBrowserHistory from 'history/lib/createBrowserHistory';
|
||||
|
||||
Telescope.routes = {};
|
||||
// // ------------------------------------- Other -------------------------------- //
|
||||
|
||||
Telescope.addRoutes = (newRoutes) => {
|
||||
Telescope.routes = Object.assign(Telescope.routes, newRoutes);
|
||||
}
|
||||
// FlowRouter.notFound = {
|
||||
// action() {
|
||||
// ({App, Error404} = Telescope.components);
|
||||
// mount(App, {content: <Error404/>});
|
||||
// }
|
||||
// };
|
||||
|
||||
Telescope.addRoutes({
|
||||
Meteor.startup(() => {
|
||||
|
||||
// ------------------------------------- Posts -------------------------------- //
|
||||
Telescope.routes.add([
|
||||
{name:"posts.daily", path:"daily", component:Telescope.components.PostsDaily},
|
||||
{name:"posts.single", path:"posts/:_id(/:slug)", component:Telescope.components.PostsSingle},
|
||||
{name:"users.single", path:"users/:slug", component:Telescope.components.UsersSingle},
|
||||
{name:"users.account", path:"account", component:Telescope.components.UsersAccount},
|
||||
{name:"users.edit", path:"users/:slug/edit", component:Telescope.components.UsersAccount}
|
||||
]);
|
||||
|
||||
"posts.list": {
|
||||
path: "/",
|
||||
action(params, queryParams) {
|
||||
|
||||
({App, PostsList} = Telescope.components);
|
||||
queryParams = _.isEmpty(queryParams) ? {view: 'new'} : _.clone(queryParams);
|
||||
queryParams.listId = "posts.list.main";
|
||||
|
||||
({selector, options} = Posts.parameters.get(queryParams));
|
||||
|
||||
const postsPerPage = Telescope.settings.get("postsPerPage", 10);
|
||||
|
||||
mount(App, {content:
|
||||
<ListContainer
|
||||
collection={Posts}
|
||||
publication="posts.list"
|
||||
selector={selector}
|
||||
options={options}
|
||||
terms={queryParams}
|
||||
joins={Posts.getJoins()}
|
||||
component={PostsList}
|
||||
cacheSubscription={false}
|
||||
listId={queryParams.listId}
|
||||
limit={postsPerPage}
|
||||
/>})
|
||||
}
|
||||
},
|
||||
|
||||
"posts.daily": {
|
||||
path: "/daily/:days?",
|
||||
action(params, queryParams) {
|
||||
|
||||
({App, PostsDaily} = Telescope.components);
|
||||
|
||||
mount(App, {content: <PostsDaily days={params.days}/>})
|
||||
}
|
||||
},
|
||||
|
||||
"posts.single": {
|
||||
path: "/posts/:_id/:slug?",
|
||||
action(params, queryParams) {
|
||||
({App, PostsPage} = Telescope.components);
|
||||
mount(App, {content:
|
||||
<DocumentContainer
|
||||
collection={Posts}
|
||||
publication="posts.single"
|
||||
selector={{_id: params._id}}
|
||||
terms={params}
|
||||
joins={Posts.getJoins()}
|
||||
component={PostsPage}
|
||||
/>});
|
||||
}
|
||||
},
|
||||
|
||||
// ------------------------------------- Users -------------------------------- //
|
||||
|
||||
"users.single": {
|
||||
path: "/users/:slug",
|
||||
action(params, queryParams) {
|
||||
({App, UsersProfile} = Telescope.components);
|
||||
mount(App, {content:
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={{'telescope.slug': params.slug}}
|
||||
terms={{'telescope.slug': params.slug}}
|
||||
component={UsersProfile}
|
||||
documentPropName="user"
|
||||
/>});
|
||||
}
|
||||
},
|
||||
|
||||
"account": {
|
||||
path: "/account",
|
||||
action(params, queryParams) {
|
||||
({App, UsersEdit} = Telescope.components);
|
||||
mount(App, {content:
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={{_id: Meteor.userId()}}
|
||||
terms={{_id: Meteor.userId()}}
|
||||
component={UsersEdit}
|
||||
/>});
|
||||
}
|
||||
},
|
||||
|
||||
"users.edit": {
|
||||
path: "/users/:slug/edit",
|
||||
action(params, queryParams) {
|
||||
({App, UsersEdit} = Telescope.components);
|
||||
mount(App, {content:
|
||||
<DocumentContainer
|
||||
collection={Users}
|
||||
publication="users.single"
|
||||
selector={params}
|
||||
terms={params}
|
||||
component={UsersEdit}
|
||||
/>});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_.forEach(Telescope.routes, (route, routeName) => {
|
||||
FlowRouter.route(route.path, {
|
||||
name: routeName,
|
||||
action: route.action
|
||||
});
|
||||
});
|
||||
|
||||
// ------------------------------------- Other -------------------------------- //
|
||||
|
||||
FlowRouter.notFound = {
|
||||
action() {
|
||||
({App, Error404} = Telescope.components);
|
||||
mount(App, {content: <Error404/>});
|
||||
const AppRoutes = {
|
||||
path: '/',
|
||||
component: Telescope.components.App,
|
||||
indexRoute: { name: "posts.list", component: Telescope.components.PostsHome },
|
||||
childRoutes: Telescope.routes.routes
|
||||
}
|
||||
};
|
||||
|
||||
let history;
|
||||
|
||||
const clientOptions = {}, serverOptions = {};
|
||||
|
||||
if (Meteor.isClient) {
|
||||
history = useNamedRoutes(useRouterHistory(createBrowserHistory))({ routes: AppRoutes });
|
||||
}
|
||||
|
||||
if (Meteor.isServer) {
|
||||
history = useNamedRoutes(useRouterHistory(createMemoryHistory))({ routes: AppRoutes });
|
||||
}
|
||||
|
||||
clientOptions.props = {onUpdate: Events.analyticsRequest};
|
||||
|
||||
// ReactRouterSSR.Run(AppRoutes, {historyHook: () => history}, {historyHook: () => history});
|
||||
ReactRouterSSR.Run(AppRoutes, clientOptions, serverOptions);
|
||||
|
||||
});
|
|
@ -30,4 +30,10 @@
|
|||
text-transform: uppercase;
|
||||
font-size: $smaller-font;
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.dropdown-item.active{
|
||||
a{
|
||||
color: $white;
|
||||
}
|
||||
}
|
|
@ -42,10 +42,10 @@
|
|||
// @include border-radius;
|
||||
// padding: 3px 5px;
|
||||
// margin-right: 5px;
|
||||
&.post-view-inactive{
|
||||
&.posts-view-inactive{
|
||||
@include activeHover;
|
||||
}
|
||||
&.post-view-active{
|
||||
&.posts-view-active{
|
||||
background: $light-blue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ Categories.getUrl = function (category, isAbsolute) {
|
|||
var isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Telescope.utils.getSiteUrl().slice(0,-1) : "";
|
||||
// return prefix + FlowRouter.path("postsCategory", category);
|
||||
return prefix + FlowRouter.path("posts.list", {}, {cat: [category.slug]});
|
||||
return `${prefix}/?cat=${category.slug}`;
|
||||
};
|
||||
Categories.helpers({getUrl: function () {return Categories.getUrl(this);}});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
Comments.getPageUrl = function(comment, isAbsolute){
|
||||
var isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Telescope.utils.getSiteUrl().slice(0,-1) : "";
|
||||
return prefix + FlowRouter.path("posts.single", {_id: comment.postId}) + "#"+comment._id;
|
||||
return prefix + "foo" + "#"+comment._id;
|
||||
};
|
||||
Comments.helpers({getPageUrl: function () {return Comments.getPageUrl(this);}});
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@ class ContextPasser extends Component {
|
|||
getChildContext() {
|
||||
return {
|
||||
closeCallback: this.props.closeCallback,
|
||||
currentUser: this.props.currentUser // pass on currentUser
|
||||
currentUser: this.props.currentUser, // pass on currentUser,
|
||||
actions: this.props.actions,
|
||||
events: this.props.events,
|
||||
messages: this.props.messages,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -16,12 +19,18 @@ class ContextPasser extends Component {
|
|||
|
||||
ContextPasser.propTypes = {
|
||||
closeCallback: React.PropTypes.func,
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
};
|
||||
|
||||
ContextPasser.childContextTypes = {
|
||||
closeCallback: React.PropTypes.func,
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object,
|
||||
};
|
||||
|
||||
export default ContextPasser;
|
||||
|
|
|
@ -48,7 +48,13 @@ class ModalTrigger extends Component {
|
|||
<Modal bsSize={this.props.size} show={this.state.modalIsOpen} onHide={this.closeModal}>
|
||||
{this.props.title ? this.renderHeader() : null}
|
||||
<Modal.Body>
|
||||
<ContextPasser currentUser={this.context.currentUser} closeCallback={this.closeModal}>
|
||||
<ContextPasser
|
||||
currentUser={this.context.currentUser}
|
||||
actions={this.context.actions}
|
||||
events={this.context.events}
|
||||
messages={this.context.messages}
|
||||
closeCallback={this.closeModal}
|
||||
>
|
||||
{this.props.children}
|
||||
</ContextPasser>
|
||||
</Modal.Body>
|
||||
|
@ -68,7 +74,10 @@ ModalTrigger.defaultProps = {
|
|||
}
|
||||
|
||||
ModalTrigger.contextTypes = {
|
||||
currentUser: React.PropTypes.object
|
||||
currentUser: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
events: React.PropTypes.object,
|
||||
messages: React.PropTypes.object
|
||||
};
|
||||
|
||||
// ModalTrigger.childContextTypes = {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import { composeWithTracker } from 'react-komposer';
|
||||
import Messages from '../messages.js';
|
||||
|
||||
function composer(props, onData) {
|
||||
|
||||
const subscriptions = Telescope.subscriptions.map((sub) => Meteor.subscribe(sub.name, sub.arguments));
|
||||
|
||||
FlowRouter.watchPathChange();
|
||||
|
||||
const data = {
|
||||
currentUser: Meteor.user(),
|
||||
currentRoute: FlowRouter.current()
|
||||
actions: {call: Meteor.call},
|
||||
events: Events,
|
||||
messages: Messages
|
||||
}
|
||||
|
||||
Meteor.call("settings.getJSON", (error, result) => {
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
import Messages from "./messages.js";
|
||||
// import Messages from "./messages.js";
|
||||
|
||||
FlowRouter.extendPathWithQueryParams = (path, params, newQueryParams) => {
|
||||
const current = FlowRouter.current();
|
||||
const currentQueryParams = _.clone(current.queryParams);
|
||||
return FlowRouter.path(path, params, _.extend(currentQueryParams, newQueryParams));
|
||||
};
|
||||
|
||||
FlowRouter.triggers.exit([() => Messages.clearSeen()]);
|
||||
|
||||
FlowRouter.addToQueryArray = function (key, value) {
|
||||
var keyArray = FlowRouter.getQueryParam(key) || [];
|
||||
keyArray.push(value);
|
||||
var params = {};
|
||||
params[key] = keyArray;
|
||||
FlowRouter.setQueryParams(params);
|
||||
}
|
||||
|
||||
FlowRouter.removeFromQueryArray = function (key, value) {
|
||||
var keyArray = FlowRouter.getQueryParam(key);
|
||||
keyArray = _.without(keyArray, value);
|
||||
var params = {};
|
||||
params[key] = keyArray;
|
||||
FlowRouter.setQueryParams(params);
|
||||
}
|
||||
|
||||
if(Meteor.isServer) {
|
||||
var timeInMillis = 1000 * 30; // 30 secs
|
||||
FlowRouter.setPageCacheTimeout(timeInMillis);
|
||||
FlowRouter.setDeferScriptLoading(true);
|
||||
}
|
||||
|
||||
// FlowRouter.notFound = {
|
||||
// action: function() {
|
||||
// if (Meteor.isClient) {
|
||||
// DocHead.addMeta({
|
||||
// name: "name",
|
||||
// property: "prerender-status-code",
|
||||
// content: "404"
|
||||
// });
|
||||
// DocHead.addMeta({
|
||||
// name: "name",
|
||||
// property: "robots",
|
||||
// content: "noindex, nofollow"
|
||||
// });
|
||||
// }
|
||||
// BlazeLayout.render("layout", {main: "not_found"});
|
||||
// }
|
||||
// FlowRouter.extendPathWithQueryParams = (path, params, newQueryParams) => {
|
||||
// const current = FlowRouter.current();
|
||||
// const currentQueryParams = _.clone(current.queryParams);
|
||||
// return FlowRouter.path(path, params, _.extend(currentQueryParams, newQueryParams));
|
||||
// };
|
||||
|
||||
if (typeof Events !== "undefined" && Meteor.isClient) {
|
||||
FlowRouter.triggers.enter([function () {Events.analyticsRequest()}]);
|
||||
}
|
||||
// FlowRouter.triggers.exit([() => Messages.clearSeen()]);
|
||||
|
||||
// FlowRouter.addToQueryArray = function (key, value) {
|
||||
// var keyArray = FlowRouter.getQueryParam(key) || [];
|
||||
// keyArray.push(value);
|
||||
// var params = {};
|
||||
// params[key] = keyArray;
|
||||
// FlowRouter.setQueryParams(params);
|
||||
// }
|
||||
|
||||
// FlowRouter.removeFromQueryArray = function (key, value) {
|
||||
// var keyArray = FlowRouter.getQueryParam(key);
|
||||
// keyArray = _.without(keyArray, value);
|
||||
// var params = {};
|
||||
// params[key] = keyArray;
|
||||
// FlowRouter.setQueryParams(params);
|
||||
// }
|
||||
|
||||
// if(Meteor.isServer) {
|
||||
// var timeInMillis = 1000 * 30; // 30 secs
|
||||
// FlowRouter.setPageCacheTimeout(timeInMillis);
|
||||
// FlowRouter.setDeferScriptLoading(true);
|
||||
// }
|
||||
|
||||
// // FlowRouter.notFound = {
|
||||
// // action: function() {
|
||||
// // if (Meteor.isClient) {
|
||||
// // DocHead.addMeta({
|
||||
// // name: "name",
|
||||
// // property: "prerender-status-code",
|
||||
// // content: "404"
|
||||
// // });
|
||||
// // DocHead.addMeta({
|
||||
// // name: "name",
|
||||
// // property: "robots",
|
||||
// // content: "noindex, nofollow"
|
||||
// // });
|
||||
// // }
|
||||
// // BlazeLayout.render("layout", {main: "not_found"});
|
||||
// // }
|
||||
// // };
|
||||
|
||||
// if (typeof Events !== "undefined" && Meteor.isClient) {
|
||||
// FlowRouter.triggers.enter([function () {Events.analyticsRequest()}]);
|
||||
// }
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
const Router = FlowRouter;
|
||||
|
||||
export default Router;
|
|
@ -1,28 +1,9 @@
|
|||
import React from 'react';
|
||||
import Router from './router.js'
|
||||
import {mount} from 'react-mounter';
|
||||
|
||||
import Cheatsheet from './components/Cheatsheet.jsx';
|
||||
import Settings from './components/Settings.jsx';
|
||||
import Emails from './components/Emails.jsx';
|
||||
|
||||
Router.route('/cheatsheet', {
|
||||
name: 'cheatsheet',
|
||||
action() {
|
||||
mount(Telescope.components.App, {content: <Cheatsheet/>});
|
||||
}
|
||||
});
|
||||
|
||||
Router.route('/settings', {
|
||||
name: 'settings',
|
||||
action() {
|
||||
mount(Telescope.components.App, {content: <Settings/>});
|
||||
}
|
||||
});
|
||||
|
||||
Router.route('/emails', {
|
||||
name: 'emails',
|
||||
action() {
|
||||
mount(Telescope.components.App, {content: <Emails/>});
|
||||
}
|
||||
});
|
||||
Telescope.routes.add([
|
||||
{name: "cheatsheet", path: "/cheatsheet", component: Cheatsheet},
|
||||
{name: "settings", path: "/settings", component: Settings},
|
||||
{name: "emails", path: "/emails", component: Emails},
|
||||
]);
|
|
@ -2,6 +2,7 @@ import React, { PropTypes, Component } from 'react';
|
|||
import {mount} from 'react-mounter';
|
||||
import MoviesWrapper from './demo-components.jsx';
|
||||
import Core from 'meteor/nova:core';
|
||||
import { Route } from 'react-router';
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Collection & Schema //
|
||||
|
@ -56,12 +57,8 @@ Movies.attachSchema(schema);
|
|||
// Route //
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
FlowRouter.route('/demo', {
|
||||
name: 'demo',
|
||||
action() {
|
||||
mount(MoviesWrapper);
|
||||
}
|
||||
});
|
||||
// Telescope.routes.add(<Route name="demo" path="/demo" component={MoviesWrapper} />);
|
||||
Telescope.routes.add({name:"demo", path:"/demo", component:MoviesWrapper});
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Methods //
|
||||
|
|
|
@ -2,7 +2,7 @@ Events.analyticsRequest = function() {
|
|||
// Google Analytics
|
||||
if (typeof window.ga !== 'undefined'){
|
||||
window.ga('send', 'pageview', {
|
||||
'page': FlowRouter.current().path
|
||||
'page': window.location.pathname
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,6 +20,14 @@ This package can generate new document and edit document forms from a [SimpleSch
|
|||
- Support for custom form controls.
|
||||
- Submission to Meteor methods.
|
||||
|
||||
### NPM Dependencies
|
||||
|
||||
```
|
||||
react react-intl formsy-react react-bootstrap formsy-react-components
|
||||
```
|
||||
|
||||
You also need to load Bootstrap's CSS separately.
|
||||
|
||||
### Usage
|
||||
|
||||
Example schema:
|
||||
|
@ -97,6 +105,10 @@ Edit document form:
|
|||
|
||||
The collection in which to edit or insert a document.
|
||||
|
||||
###### `schema`
|
||||
|
||||
If you prefer, you can also specify a schema instead of a collection.
|
||||
|
||||
###### `document`
|
||||
|
||||
If present, the document to edit. If not present, the form will be a “new document” form.
|
||||
|
@ -187,7 +199,7 @@ An object containing optional autofilled properties.
|
|||
|
||||
###### `addToAutofilledValues({name: value})`
|
||||
|
||||
A function that takes a property, and adds it to the `prefilledValues` object.
|
||||
A function that takes a property, and adds it to the `autofilledValues` object.
|
||||
|
||||
###### `throwError({content, type})`
|
||||
|
||||
|
@ -202,3 +214,17 @@ The component handles three different layers of input values:
|
|||
- An “autofilled” value, typically provided by an *other* form element (i.e. autofilling the post title from its URL).
|
||||
|
||||
The highest-priority value is the user input. If there is no user input, we default to the database value provided by the `props`. And if that one is empty too, we then look for autofilled values.
|
||||
|
||||
### i18n
|
||||
|
||||
This package uses [React Intl](https://github.com/yahoo/react-intl/) to automatically translate all labels. In order to do so it expects an `intl` object ot be passed as part of its context. For example, in a parent component:
|
||||
|
||||
```
|
||||
getChildContext() {
|
||||
const intlProvider = new IntlProvider({locale: myLocale}, myMessages);
|
||||
const {intl} = intlProvider.getChildContext();
|
||||
return {
|
||||
intl: intl
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
20
packages/nova-forms/lib/Flash.jsx
Normal file
20
packages/nova-forms/lib/Flash.jsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React, { PropTypes, Component } from 'react';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
|
||||
const Flash = () => {
|
||||
|
||||
let type = this.props.message.type;
|
||||
type = type === "error" ? "danger" : type; // if type is "error", use "danger" instead
|
||||
|
||||
return (
|
||||
<Alert className="flash-message" bsStyle={type}>
|
||||
{this.props.message.content}
|
||||
</Alert>
|
||||
)
|
||||
}
|
||||
|
||||
Flash.propTypes = {
|
||||
message: React.PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default Flash;
|
|
@ -48,7 +48,7 @@ class FormComponent extends Component {
|
|||
return <Checkbox {...properties} />;
|
||||
// note: checkboxgroup cause React refs error
|
||||
case "checkboxgroup":
|
||||
return <CheckboxGroup {...properties} />;
|
||||
return <CheckboxGroup {...properties} />;
|
||||
case "radiogroup":
|
||||
return <RadioGroup {...properties} />;
|
||||
case "select":
|
||||
|
|
|
@ -2,9 +2,9 @@ import React, { PropTypes, Component } from 'react';
|
|||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import Formsy from 'formsy-react';
|
||||
import { Button } from 'react-bootstrap';
|
||||
|
||||
import Flash from "./Flash.jsx";
|
||||
import FormGroup from "./FormGroup.jsx";
|
||||
import Utils from './utils.js';
|
||||
import { flatten, deepValue, getEditableFields, getInsertableFields } from './utils.js';
|
||||
|
||||
/*
|
||||
|
||||
|
@ -48,9 +48,14 @@ class NovaForm extends Component{
|
|||
// ------------------------------- Helpers ----------------------------- //
|
||||
// --------------------------------------------------------------------- //
|
||||
|
||||
// return the current schema based on either the schema or collection prop
|
||||
getSchema() {
|
||||
return this.props.schema ? this.props.schema : this.props.collection.simpleSchema()._schema;
|
||||
}
|
||||
|
||||
getFieldGroups() {
|
||||
|
||||
const schema = this.props.collection.simpleSchema()._schema;
|
||||
const schema = this.getSchema();
|
||||
|
||||
// build fields array by iterating over the list of field names
|
||||
let fields = this.getFieldNames().map(fieldName => {
|
||||
|
@ -73,7 +78,7 @@ class NovaForm extends Component{
|
|||
field.label = (typeof this.props.labelFunction === "function") ? this.props.labelFunction(intlFieldName) : intlFieldName,
|
||||
|
||||
// add value
|
||||
field.value = this.getDocument() && Utils.deepValue(this.getDocument(), fieldName) ? Utils.deepValue(this.getDocument(), fieldName) : "";
|
||||
field.value = this.getDocument() && deepValue(this.getDocument(), fieldName) ? deepValue(this.getDocument(), fieldName) : "";
|
||||
|
||||
// replace value by prefilled value if value is empty
|
||||
if (fieldSchema.autoform && fieldSchema.autoform.prefill) {
|
||||
|
@ -144,10 +149,10 @@ class NovaForm extends Component{
|
|||
|
||||
// get relevant fields
|
||||
getFieldNames() {
|
||||
const { collection, fields } = this.props;
|
||||
const fields = this.props.fields;
|
||||
|
||||
// get all editable/insertable fields (depending on current form type)
|
||||
let relevantFields = this.getFormType() === "edit" ? collection.getEditableFields(this.props.currentUser, this.getDocument()) : collection.getInsertableFields(this.props.currentUser);
|
||||
let relevantFields = this.getFormType() === "edit" ? getEditableFields(this.getSchema(), this.props.currentUser, this.getDocument()) : getInsertableFields(this.getSchema(), this.props.currentUser);
|
||||
|
||||
// if "fields" prop is specified, restrict list of fields to it
|
||||
if (typeof fields !== "undefined" && fields.length > 0) {
|
||||
|
@ -207,7 +212,6 @@ class NovaForm extends Component{
|
|||
|
||||
// render errors
|
||||
renderErrors() {
|
||||
Flash = Telescope.components.Flash;
|
||||
return <div className="form-errors">{this.state.errors.map(message => <Flash key={message} message={message}/>)}</div>
|
||||
}
|
||||
|
||||
|
@ -288,7 +292,6 @@ class NovaForm extends Component{
|
|||
this.setState({disabled: true});
|
||||
|
||||
const fields = this.getFieldNames();
|
||||
const collection = this.props.collection;
|
||||
|
||||
// if there's a submit callback, run it
|
||||
if (this.props.submitCallback) this.props.submitCallback();
|
||||
|
@ -296,7 +299,7 @@ class NovaForm extends Component{
|
|||
if (this.getFormType() === "new") { // new document form
|
||||
|
||||
// remove any empty properties
|
||||
let document = _.compactObject(Utils.flatten(data));
|
||||
let document = _.compactObject(flatten(data));
|
||||
|
||||
// add prefilled properties
|
||||
if (this.props.prefilledProps) {
|
||||
|
@ -311,7 +314,7 @@ class NovaForm extends Component{
|
|||
const document = this.getDocument();
|
||||
|
||||
// put all keys with data on $set
|
||||
const set = _.compactObject(Utils.flatten(data));
|
||||
const set = _.compactObject(flatten(data));
|
||||
|
||||
// put all keys without data on $unset
|
||||
const unsetKeys = _.difference(fields, _.keys(set));
|
||||
|
@ -354,7 +357,8 @@ class NovaForm extends Component{
|
|||
}
|
||||
|
||||
NovaForm.propTypes = {
|
||||
collection: React.PropTypes.object.isRequired,
|
||||
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,
|
||||
|
|
|
@ -1,24 +1,13 @@
|
|||
// import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
|
||||
// checkNpmVersions({
|
||||
// "formsy-react": "^0.18.0",
|
||||
// "formsy-react-components": "^0.7.1",
|
||||
// "react-bootstrap": "^0.29.0"
|
||||
// // 'rebass': '^0.2.4',
|
||||
// });
|
||||
if (typeof SimpleSchema !== "undefined") {
|
||||
SimpleSchema.extendOptions({
|
||||
control: Match.Optional(Match.Any), // NovaForm control (String or React component)
|
||||
order: Match.Optional(Number), // order in the form
|
||||
group: Match.Optional(Object), // form fieldset group
|
||||
insertableIf: Match.Optional(Function),
|
||||
editableIf: Match.Optional(Function)
|
||||
});
|
||||
}
|
||||
|
||||
SimpleSchema.extendOptions({
|
||||
control: Match.Optional(Match.Any), // NovaForm control (String or React component)
|
||||
order: Match.Optional(Number), // order in the form
|
||||
group: Match.Optional(Object) // form fieldset group
|
||||
});
|
||||
|
||||
// import NewDocument from "./NewDocument.jsx";
|
||||
// import EditDocument from "./EditDocument.jsx";
|
||||
import NovaForm from "./NovaForm.jsx";
|
||||
|
||||
SimpleSchema.extendOptions({
|
||||
insertableIf: Match.Optional(Function),
|
||||
editableIf: Match.Optional(Function)
|
||||
});
|
||||
|
||||
export default NovaForm;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
const Utils = {};
|
||||
|
||||
// add support for nested properties
|
||||
Utils.deepValue = function(obj, path){
|
||||
const deepValue = function(obj, path){
|
||||
for (var i=0, path=path.split('.'), len=path.length; i<len; i++){
|
||||
obj = obj[path[i]];
|
||||
};
|
||||
|
@ -9,7 +7,7 @@ Utils.deepValue = function(obj, path){
|
|||
};
|
||||
|
||||
// see http://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects
|
||||
Utils.flatten = function(data) {
|
||||
const flatten = function(data) {
|
||||
var result = {};
|
||||
function recurse (cur, prop) {
|
||||
|
||||
|
@ -34,4 +32,30 @@ Utils.flatten = function(data) {
|
|||
return result;
|
||||
}
|
||||
|
||||
export default Utils;
|
||||
/**
|
||||
* @method Mongo.Collection.getInsertableFields
|
||||
* Get an array of all fields editable by a specific user for a given collection
|
||||
* @param {Object} user – the user for which to check field permissions
|
||||
*/
|
||||
const getInsertableFields = function (schema, user) {
|
||||
const fields = _.filter(_.keys(schema), function (fieldName) {
|
||||
var field = schema[fieldName];
|
||||
return field.insertableIf && field.insertableIf(user);
|
||||
});
|
||||
return fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @method Mongo.Collection.getEditableFields
|
||||
* Get an array of all fields editable by a specific user for a given collection
|
||||
* @param {Object} user – the user for which to check field permissions
|
||||
*/
|
||||
const getEditableFields = function (schema, user, document) {
|
||||
const fields = _.filter(_.keys(schema), function (fieldName) {
|
||||
var field = schema[fieldName];
|
||||
return field.editableIf && field.editableIf(user, document);
|
||||
});
|
||||
return fields;
|
||||
};
|
||||
|
||||
export { flatten, deepValue, getInsertableFields, getEditableFields };
|
|
@ -12,10 +12,8 @@ Package.onUse(function(api) {
|
|||
api.use([
|
||||
'ecmascript',
|
||||
'check',
|
||||
'tmeasday:check-npm-versions@0.3.1',
|
||||
'aldeed:simple-schema@1.5.3',
|
||||
'aldeed:collection2@2.8.0',
|
||||
'utilities:smart-methods@0.1.4',
|
||||
'fourseven:scss@3.4.1'
|
||||
]);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Telescope.strings.en = {
|
|||
|
||||
"posts.new_post": "New Post",
|
||||
"posts.edit": "Edit",
|
||||
"posts.edit_success": "Post “{title}” edited.",
|
||||
"posts.delete": "Delete",
|
||||
"posts.delete_confirm": "Delete post “{title}”?",
|
||||
"posts.delete_success": "Post “{title}” deleted.",
|
||||
|
@ -102,6 +103,10 @@ Telescope.strings.en = {
|
|||
"settings.facebookPage": "Facebook Page",
|
||||
"settings.googleAnalyticsId": "Google Analytics ID",
|
||||
"settings.locale": "Locale",
|
||||
"settings.requireViewInvite": "Require View Invite",
|
||||
"settings.requirePostInvite": "Require Post Invite",
|
||||
"settings.requirePostsApproval": "Require Posts Approval",
|
||||
"settings.scoreUpdateInterval": "Score Update Interval",
|
||||
|
||||
"app.loading": "Loading…",
|
||||
"app.404": "Sorry, we couldn't find what you were looking for.",
|
||||
|
|
|
@ -15,6 +15,7 @@ Telescope.VERSION = '0.26.3-nova';
|
|||
*/
|
||||
Telescope.config = {};
|
||||
|
||||
|
||||
// ------------------------------------- Schemas -------------------------------- //
|
||||
|
||||
SimpleSchema.extendOptions({
|
||||
|
@ -58,4 +59,16 @@ Telescope.subscriptions.preload = function (subscription, args) {
|
|||
Telescope.subscriptions.push({name: subscription, arguments: args});
|
||||
};
|
||||
|
||||
// ------------------------------------- Strings -------------------------------- //
|
||||
|
||||
Telescope.strings = {};
|
||||
|
||||
// ------------------------------------- Routes -------------------------------- //
|
||||
|
||||
Telescope.routes = {
|
||||
routes: [],
|
||||
add(routeOrRouteArray) {
|
||||
const addedRoutes = Array.isArray(routeOrRouteArray) ? routeOrRouteArray : [routeOrRouteArray];
|
||||
this.routes = this.routes.concat(addedRoutes);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
var areIntlLocalesSupported = require('intl-locales-supported');
|
||||
|
||||
var localesMyAppSupports = [
|
||||
Telescope.settings.get("locale")
|
||||
Telescope.settings.get("locale", "en")
|
||||
];
|
||||
|
||||
if (global.Intl) {
|
|
@ -38,7 +38,8 @@ Package.onUse(function (api) {
|
|||
'jparker:gravatar@0.4.1',
|
||||
'tmeasday:publish-counts@0.7.3',
|
||||
'meteorhacks:unblock@1.1.0',
|
||||
'kadira:flow-router-ssr@3.13.0',
|
||||
// 'kadira:flow-router-ssr@3.13.0',
|
||||
"reactrouter:react-router-ssr@3.1.3",
|
||||
// 'kadira:flow-router@2.12.1',
|
||||
'utilities:smart-publications@0.1.4',
|
||||
'utilities:smart-methods@0.1.4',
|
||||
|
@ -57,12 +58,12 @@ Package.onUse(function (api) {
|
|||
'lib/settings.js',
|
||||
'lib/collections.js',
|
||||
'lib/deep.js',
|
||||
'lib/deep_extend.js'
|
||||
'lib/deep_extend.js',
|
||||
'lib/intl-polyfill.js'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
'lib/server/server-config.js',
|
||||
'lib/server/intl-polyfill.js'
|
||||
'lib/server/server-config.js'
|
||||
], ['server']);
|
||||
|
||||
api.export([
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import MailChimpList from './mailchimp.js';
|
||||
|
||||
function subscribeUserOnProfileCompletion (user) {
|
||||
if (!!Telescope.settings.get('autoSubscribe') && !!Users.getEmail(user)) {
|
||||
addToMailChimpList(user, false, function (error, result) {
|
||||
MailChimpList.add(user, false, function (error, result) {
|
||||
console.log(error);
|
||||
console.log(result);
|
||||
});
|
|
@ -132,7 +132,7 @@ MailChimpList.add = function(userOrEmail, confirm, done){
|
|||
|
||||
// mark user as subscribed
|
||||
if (!!user) {
|
||||
Users.setSetting(user, 'newsletter_subscribeToNewsletter', true);
|
||||
Users.methods.setSetting(user._id, 'newsletter_subscribeToNewsletter', true);
|
||||
}
|
||||
|
||||
console.log("// User subscribed");
|
||||
|
@ -175,7 +175,7 @@ MailChimpList.remove = (user) => {
|
|||
var subscribe = api.call('lists', 'unsubscribe', subscribeOptions);
|
||||
|
||||
// mark user as unsubscribed
|
||||
Users.setSetting(user, 'newsletter_subscribeToNewsletter', false);
|
||||
Users.methods.setSetting(user._id, 'newsletter_subscribeToNewsletter', false);
|
||||
|
||||
console.log("// User unsubscribed");
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ Package.onUse(function (api) {
|
|||
api.addFiles([
|
||||
// 'package-tap.i18n',
|
||||
// 'lib/collection.js',
|
||||
'lib/callbacks.js',
|
||||
'lib/custom_fields.js',
|
||||
'lib/emails.js'
|
||||
], ['client', 'server']);
|
||||
|
@ -29,7 +28,8 @@ Package.onUse(function (api) {
|
|||
'lib/server/cron.js',
|
||||
'lib/server/emails.js',
|
||||
'lib/server/methods.js',
|
||||
'lib/server/mailchimp_api.js'
|
||||
'lib/server/mailchimp_api.js',
|
||||
'lib/server/callbacks.js'
|
||||
], ['server']);
|
||||
|
||||
api.mainModule('lib/server.js', 'server');
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Posts from './config'
|
||||
import marked from 'marked';
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Posts from './config'
|
||||
|
||||
const adminGroup = {
|
||||
name: "admin",
|
||||
order: 2
|
||||
|
@ -7,7 +9,7 @@ const adminGroup = {
|
|||
* @summary Posts schema
|
||||
* @type {SimpleSchema}
|
||||
*/
|
||||
Posts.schema = new SimpleSchema({
|
||||
Posts.schemaJSON = {
|
||||
/**
|
||||
ID
|
||||
*/
|
||||
|
@ -226,15 +228,9 @@ Posts.schema = new SimpleSchema({
|
|||
collection: () => Meteor.users
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// schema transforms
|
||||
// Meteor.startup(function(){
|
||||
// // needs to happen after every fields were added
|
||||
// Posts.internationalize();
|
||||
// });
|
||||
|
||||
/**
|
||||
* @summary Attach schema to Posts collection
|
||||
*/
|
||||
Posts.attachSchema(Posts.schema);
|
||||
if (typeof SimpleSchema !== "undefined") {
|
||||
Posts.schema = new SimpleSchema(Posts.schemaJSON);
|
||||
Posts.attachSchema(Posts.schema);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
// import { Mongo } from './imports.js';
|
||||
|
||||
/**
|
||||
* @summary The global namespace/collection for Posts.
|
||||
* @namespace Posts
|
||||
*/
|
||||
Posts = new Mongo.Collection("posts");
|
||||
|
||||
const PostsStub = {
|
||||
helpers: x => x
|
||||
}
|
||||
|
||||
/* we need to handle two scenarios: when the package is called as a Meteor package,
|
||||
and when it's called as a NPM package */
|
||||
Posts = typeof Mongo !== "undefined" ? new Mongo.Collection("posts") : PostsStub;
|
||||
|
||||
/**
|
||||
* @summary Posts config namespace
|
||||
|
@ -10,7 +19,6 @@ Posts = new Mongo.Collection("posts");
|
|||
*/
|
||||
Posts.config = {};
|
||||
|
||||
|
||||
/**
|
||||
* @summary Post Statuses
|
||||
*/
|
||||
|
@ -41,4 +49,6 @@ Posts.config.STATUS_PENDING = 1;
|
|||
Posts.config.STATUS_APPROVED = 2;
|
||||
Posts.config.STATUS_REJECTED = 3;
|
||||
Posts.config.STATUS_SPAM = 4;
|
||||
Posts.config.STATUS_DELETED = 5;
|
||||
Posts.config.STATUS_DELETED = 5;
|
||||
|
||||
export default Posts;
|
|
@ -1,4 +1,5 @@
|
|||
import moment from 'moment';
|
||||
import Posts from './config';
|
||||
|
||||
//////////////////
|
||||
// Link Helpers //
|
||||
|
@ -36,23 +37,12 @@ Posts.helpers({getLinkTarget: function () {return Posts.getLinkTarget(this);}});
|
|||
* @param {Object} post
|
||||
*/
|
||||
Posts.getPageUrl = function(post, isAbsolute){
|
||||
var isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Telescope.utils.getSiteUrl().slice(0,-1) : "";
|
||||
return prefix + FlowRouter.path("posts.single", post);
|
||||
return `${prefix}/posts/${post._id}/${post.slug}`;
|
||||
};
|
||||
Posts.helpers({getPageUrl: function (isAbsolute) {return Posts.getPageUrl(this, isAbsolute);}});
|
||||
|
||||
/**
|
||||
* @summary Get post edit page URL.
|
||||
* @param {String} id
|
||||
*/
|
||||
Posts.getEditUrl = function(post, isAbsolute){
|
||||
var isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Telescope.utils.getSiteUrl().slice(0,-1) : "";
|
||||
return prefix + FlowRouter.path("posts.edit", post);
|
||||
};
|
||||
Posts.helpers({getEditUrl: function (isAbsolute) {return Posts.getEditUrl(this, isAbsolute);}});
|
||||
|
||||
///////////////////
|
||||
// Other Helpers //
|
||||
///////////////////
|
||||
|
@ -114,7 +104,7 @@ Posts.checkForSameUrl = function (url) {
|
|||
* @summary When on a post page, return the current post
|
||||
*/
|
||||
Posts.current = function () {
|
||||
return Posts.findOne(FlowRouter.getParam("_id"));
|
||||
return Posts.findOne("foo");
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Posts from './config'
|
||||
|
||||
/**
|
||||
*
|
||||
* Post Methods
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Posts from './config'
|
||||
|
||||
Posts.getNotificationProperties = function (data) {
|
||||
const post = data.post;
|
||||
const postAuthor = Meteor.users.findOne(post.userId);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Posts from './config'
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Posts from './config'
|
||||
import PublicationsUtils from 'meteor/utilities:smart-publications';
|
||||
|
||||
Posts.publishedFields = {};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Posts from './config'
|
||||
|
||||
/**
|
||||
* @summary Post views are filters used for subscribing to and viewing posts
|
||||
* @namespace Posts.views
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Users from './namespace.js';
|
||||
import marked from 'marked';
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Users from './namespace.js';
|
||||
|
||||
const adminGroup = {
|
||||
name: "admin",
|
||||
order: 10
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Users from './namespace.js';
|
||||
import moment from 'moment';
|
||||
|
||||
////////////////////
|
||||
|
@ -67,7 +68,7 @@ Users.getProfileUrl = function (user, isAbsolute) {
|
|||
isAbsolute = typeof isAbsolute === "undefined" ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Telescope.utils.getSiteUrl().slice(0,-1) : "";
|
||||
if (user.telescope && user.telescope.slug) {
|
||||
return prefix + FlowRouter.path("users.single", {slug: user.telescope.slug});
|
||||
return `${prefix}/users/${user.telescope.slug}`;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
@ -169,19 +170,6 @@ Users.getSetting = function (user, settingName, defaultValue) {
|
|||
};
|
||||
Users.helpers({getSetting: function (settingName, defaultValue) {return Users.getSetting(this, settingName, defaultValue);}});
|
||||
|
||||
/**
|
||||
* @summary Set a user setting
|
||||
* @param {Object} user
|
||||
* @param {String} settingName
|
||||
* @param {Object} defaultValue
|
||||
*/
|
||||
Users.setSetting = function (user, settingName, value) {
|
||||
if (user) {
|
||||
Meteor.call("users.setSetting", user._id, settingName, value);
|
||||
}
|
||||
};
|
||||
Users.helpers({setSetting: function () {return Users.setSetting(this);}});
|
||||
|
||||
/**
|
||||
* @summary Check if a user has upvoted a post
|
||||
* @param {Object} user
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Users from './namespace.js';
|
||||
|
||||
var completeUserProfile = function (userId, modifier, user) {
|
||||
|
||||
Users.update(userId, modifier);
|
||||
|
@ -33,6 +35,16 @@ Users.methods.edit = (userId, modifier, user) => {
|
|||
|
||||
}
|
||||
|
||||
Users.methods.setSetting = (userId, settingName, value) => {
|
||||
// all settings should be in the user.telescope namespace, so add "telescope." if needed
|
||||
var field = settingName.slice(0,10) === "telescope." ? settingName : "telescope." + settingName;
|
||||
|
||||
var modifier = {$set: {}};
|
||||
modifier.$set[field] = value;
|
||||
|
||||
Users.update(userId, modifier);
|
||||
}
|
||||
|
||||
Meteor.methods({
|
||||
'users.compleProfile'(modifier, userId) {
|
||||
|
||||
|
@ -152,13 +164,7 @@ Meteor.methods({
|
|||
throw new Meteor.Error(601, __('sorry_you_cannot_edit_this_user'));
|
||||
}
|
||||
|
||||
// all settings should be in the user.telescope namespace, so add "telescope." if needed
|
||||
var field = settingName.slice(0,10) === "telescope." ? settingName : "telescope." + settingName;
|
||||
|
||||
var modifier = {$set: {}};
|
||||
modifier.$set[field] = value;
|
||||
|
||||
Users.update(userId, modifier);
|
||||
Users.methods.setSetting(userId, settingName, value);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
* @namespace Users
|
||||
*/
|
||||
Users = Meteor.users;
|
||||
|
||||
export default Users;
|
|
@ -1,3 +1,5 @@
|
|||
import Users from './namespace.js';
|
||||
|
||||
Users.getNotificationProperties = function (user) {
|
||||
const properties = {
|
||||
profileUrl: Users.getProfileUrl(user),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Users from './namespace.js';
|
||||
|
||||
// note: using collection helpers here is probably a bad idea,
|
||||
// because they'll throw an error when the user is undefined
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import Users from './namespace.js';
|
||||
import PublicationsUtils from 'meteor/utilities:smart-publications';
|
||||
|
||||
Users.publishedFields = {};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Users from './namespace.js';
|
||||
|
||||
/**
|
||||
* @summary Telescope roles
|
||||
* @namespace Users.is
|
||||
|
|
Loading…
Add table
Reference in a new issue