diff --git a/.meteor/versions b/.meteor/versions
index 229e9f163..f30dde810 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -143,6 +143,7 @@ twitter@1.1.6-beta.11
ui@1.0.8
underscore@1.0.5-beta.11
url@1.0.6-beta.11
+utilities:react-form-containers@0.1.0
utilities:react-list-container@0.1.0
utilities:smart-methods@0.1.0
utilities:smart-publications@0.1.1
diff --git a/packages/base-styles/lib/stylesheets/main.css b/packages/base-styles/lib/stylesheets/main.css
index 15b675d9a..0800ac757 100644
--- a/packages/base-styles/lib/stylesheets/main.css
+++ b/packages/base-styles/lib/stylesheets/main.css
@@ -55,4 +55,8 @@ body{
.comment-body{
border: 1px solid #ddd;
padding: 10px;
+}
+
+.new-post-button{
+ margin-bottom: 15px;
}
\ No newline at end of file
diff --git a/packages/nova-core/lib/components.js b/packages/nova-core/lib/components.js
index 90071fbfc..f1fe1842d 100644
--- a/packages/nova-core/lib/components.js
+++ b/packages/nova-core/lib/components.js
@@ -1,4 +1,5 @@
import SmartContainers from "meteor/utilities:react-list-container";
+import FormContainers from "meteor/utilities:react-form-containers";
Telescope.registerComponent("AppContainer", require('./containers/AppContainer.jsx'));
// Telescope.registerComponent("ItemContainer", require('./containers/ItemContainer.jsx'));
@@ -12,7 +13,11 @@ Telescope.registerComponent("ListContainer", SmartContainers.ListContainer);
Telescope.registerComponent("FlashContainer", require('./containers/FlashContainer.jsx'));
Telescope.registerComponent("CurrentUserContainer", require('./containers/CurrentUserContainer.jsx'));
-Telescope.registerComponent("NewDocContainer", require('./containers/NewDocContainer.jsx'));
-Telescope.registerComponent("EditDocContainer", require('./containers/EditDocContainer.jsx'));
+
+// Telescope.registerComponent("NewDocContainer", require('./containers/NewDocContainer.jsx'));
+// Telescope.registerComponent("EditDocContainer", require('./containers/EditDocContainer.jsx'));
+
+Telescope.registerComponent("NewDocContainer", FormContainers.NewDocContainer);
+Telescope.registerComponent("EditDocContainer", FormContainers.EditDocContainer);
Telescope.registerComponent("ModalButton", require('./components/ModalButton.jsx'));
diff --git a/packages/nova-core/lib/components/ModalButton.jsx b/packages/nova-core/lib/components/ModalButton.jsx
index dc0cd140b..22a124762 100644
--- a/packages/nova-core/lib/components/ModalButton.jsx
+++ b/packages/nova-core/lib/components/ModalButton.jsx
@@ -51,7 +51,7 @@ const ModalButton = React.createClass({
callback = this.closeModal;
}
- return React.cloneElement(child, { callback: callback });
+ return React.cloneElement(child, { successCallback: callback });
});
@@ -71,4 +71,5 @@ const ModalButton = React.createClass({
}
});
-module.exports = ModalButton;
\ No newline at end of file
+module.exports = ModalButton;
+export default ModalButton;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/AppContainer.jsx b/packages/nova-core/lib/containers/AppContainer.jsx
index fffad6559..358c3f7f4 100644
--- a/packages/nova-core/lib/containers/AppContainer.jsx
+++ b/packages/nova-core/lib/containers/AppContainer.jsx
@@ -34,4 +34,5 @@ const AppContainer = React.createClass({
});
-module.exports = AppContainer;
\ No newline at end of file
+module.exports = AppContainer;
+export default AppContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/CurrentUserContainer.jsx b/packages/nova-core/lib/containers/CurrentUserContainer.jsx
index 75e1121a6..9b10024ab 100644
--- a/packages/nova-core/lib/containers/CurrentUserContainer.jsx
+++ b/packages/nova-core/lib/containers/CurrentUserContainer.jsx
@@ -15,4 +15,5 @@ const CurrentUserContainer = React.createClass({
});
-module.exports = CurrentUserContainer;
\ No newline at end of file
+module.exports = CurrentUserContainer;
+export default CurrentUserContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/EditDocContainer.jsx b/packages/nova-core/lib/containers/EditDocContainer.jsx
deleted file mode 100644
index c03d1391f..000000000
--- a/packages/nova-core/lib/containers/EditDocContainer.jsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import Messages from "../messages.js";
-import NovaForms from "../forms.jsx";
-
-import Formsy from 'formsy-react';
-
-const EditDocContainer = React.createClass({
-
- propTypes: {
- document: React.PropTypes.object, // required but might be passed later on
- collection: React.PropTypes.object, // required but might be passed later on
- label: React.PropTypes.string,
- callback: React.PropTypes.func,
- methodName: React.PropTypes.string
- },
-
- mixins: [ReactMeteorData],
-
- getMeteorData() {
- console.log(this)
-
- return {
- currentUser: Meteor.user()
- };
- },
-
- submitForm(data) {
- const document = this.props.document;
- const modifier = {$set: _.compactObject(data)};
- const collection = this.props.collection;
- const methodName = this.props.methodName ? this.props.methodName : collection._name+'.edit';
-
- Meteor.call(methodName, document._id, modifier, (error, document) => {
- if (error) {
- console.log(error)
- Messages.flash(error.message, "error")
- } else {
- Messages.flash("Document edited.", "success");
- if (this.props.callback) {
- this.props.callback(document);
- }
- }
- });
- },
-
- render() {
-
- const document = this.props.document;
- const collection = this.props.collection;
- const fields = collection.getInsertableFields(this.data.currentUser);
-
- return (
-
-
{this.props.label}
-
- {fields.map(fieldName => NovaForms.getComponent(fieldName, collection.simpleSchema()._schema[fieldName], document))}
-
-
-
- )
- }
-});
-
-module.exports = EditDocContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/FlashContainer.jsx b/packages/nova-core/lib/containers/FlashContainer.jsx
index 45d7fe612..202f6ff2f 100644
--- a/packages/nova-core/lib/containers/FlashContainer.jsx
+++ b/packages/nova-core/lib/containers/FlashContainer.jsx
@@ -24,4 +24,5 @@ const FlashContainer = React.createClass({
});
-module.exports = FlashContainer;
\ No newline at end of file
+module.exports = FlashContainer;
+export default FlashContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/ItemContainer.jsx b/packages/nova-core/lib/containers/ItemContainer.jsx
deleted file mode 100644
index 3cb0a4fa8..000000000
--- a/packages/nova-core/lib/containers/ItemContainer.jsx
+++ /dev/null
@@ -1,61 +0,0 @@
-// const ItemContainer = React.createClass({
-
-// propTypes: {
-// collection: React.PropTypes.object.isRequired,
-// selector: React.PropTypes.object.isRequired,
-// publication: React.PropTypes.string,
-// joins: React.PropTypes.array,
-// loading: React.PropTypes.func
-// },
-
-// mixins: [ReactMeteorData],
-
-// getMeteorData() {
-
-// // subscribe if necessary
-// if (this.props.publication) {
-// const subscription = Meteor.subscribe(this.props.publication, this.props.selector);
-// }
-
-// const collection = this.props.collection;
-// const document = collection.findOne(this.props.selector);
-
-// // look for any specified joins
-// if (document && this.props.joins) {
-
-// // loop over each join
-// this.props.joins.forEach(join => {
-
-// // get the property containing the id or ids
-// const joinProperty = document[join.property];
-// const collection = Meteor.isClient ? window[join.collection] : global[join.collection];
-
-// // perform the join
-// if (Array.isArray(joinProperty)) { // join property is an array of ids
-// document[join.joinAs] = collection.find({_id: {$in: joinProperty}}).fetch();
-// } else { // join property is a single id
-// document[join.joinAs] = collection.findOne({_id: joinProperty});
-// }
-
-// });
-
-// }
-
-// return {
-// document: document,
-// currentUser: Meteor.user()
-// };
-// },
-
-// render() {
-// const loadingComponent = this.props.loading ? this.props.loading : Loading…
-// if (this.data.document) {
-// return React.cloneElement(this.props.children, { ...this.data, collection: this.props.collection });
-// } else {
-// return loadingComponent;
-// }
-// }
-
-// });
-
-// module.exports = ItemContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/ListContainer.jsx b/packages/nova-core/lib/containers/ListContainer.jsx
deleted file mode 100644
index b445d33e3..000000000
--- a/packages/nova-core/lib/containers/ListContainer.jsx
+++ /dev/null
@@ -1,144 +0,0 @@
-// /*
-// Example code:
-
-//
-
-// Note that the joins are client-side only, and expect you to
-// make the relevant data available separately.
-
-// */
-
-// const ListContainer = React.createClass({
-
-// propTypes: {
-// collection: React.PropTypes.object.isRequired, // the collection to paginate
-// selector: React.PropTypes.object, // the selector used in collection.find()
-// options: React.PropTypes.object, // the options used in collection.find()
-// publication: React.PropTypes.string, // the publication to subscribe to
-// terms: React.PropTypes.object, // an object passed to the publication
-// limit: React.PropTypes.number, // the limit used to increase pagination
-// joins: React.PropTypes.array, // joins to apply to the results
-// parentProperty: React.PropTypes.string // if provided, use to generate tree
-// },
-
-// getDefaultProps: function() {
-// return {
-// limit: 5
-// };
-// },
-
-// getInitialState() {
-// return {
-// limit: this.props.limit
-// };
-// },
-
-// mixins: [ReactMeteorData],
-
-// getMeteorData() {
-
-// // initialize data object with current user, and default to data being ready
-// let data = {
-// currentUser: Meteor.user(),
-// ready: true
-// };
-
-// // subscribe if needed. Note: always subscribe first, otherwise
-// // it won't work when server-side rendering with FlowRouter SSR
-// if (this.props.publication) {
-// let terms = {...this.props.terms, limit: this.state.limit};
-// const subscription = Meteor.subscribe(this.props.publication, terms);
-// data.ready = subscription.ready();
-// }
-
-// const selector = this.props.selector || {};
-// const options = {...this.props.options, limit: this.state.limit};
-
-// const cursor = this.props.collection.find(selector, options);
-// const count = cursor.count();
-// // when rendering on the server, we want to get a count without the limit
-// const optionsNoLimit = {...this.props.options, limit: 0};
-// const cursorNoLimit = this.props.collection.find(selector, optionsNoLimit);
-
-// const totalCount = Meteor.isClient ? Counts.get(this.props.publication) : cursorNoLimit.count();
-
-// let results = cursor.fetch();
-
-// // look for any specified joins
-// if (this.props.joins) {
-
-// // loop over each document in the results
-// results.forEach(doc => {
-
-// // loop over each join
-// this.props.joins.forEach(join => {
-
-// // get the property containing the id or ids
-// const joinProperty = doc[join.property];
-// const collection = join.collection();
-// const joinLimit = join.limit ? join.limit : 0;
-
-// // perform the join
-// if (Array.isArray(joinProperty)) { // join property is an array of ids
-// doc[join.joinAs] = collection.find({_id: {$in: joinProperty}}, {limit: joinLimit}).fetch();
-// } else { // join property is a single id
-// doc[join.joinAs] = collection.findOne({_id: joinProperty});
-// }
-
-// });
-
-// // return the updated document
-// return doc;
-
-// });
-// }
-
-// // transform list into tree
-// if (this.props.parentProperty) {
-// results = Telescope.utils.unflatten(results, "_id", this.props.parentProperty);
-// }
-
-// data = {
-// ...data,
-// results: results,
-// count: count,
-// totalCount: totalCount,
-// hasMore: count < totalCount
-// };
-
-// return data;
-// },
-
-// loadMore(event) {
-// event.preventDefault();
-// this.setState({
-// limit: this.state.limit+this.props.limit
-// });
-// },
-
-// render() {
-// return React.cloneElement(this.props.children, { ...this.data, loadMore: this.loadMore});
-// }
-
-// });
-
-// // export default PostListContainer;
-
-// module.exports = ListContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/NewDocContainer.jsx b/packages/nova-core/lib/containers/NewDocContainer.jsx
deleted file mode 100644
index 3d1398b3a..000000000
--- a/packages/nova-core/lib/containers/NewDocContainer.jsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import Messages from "../messages.js";
-import NovaForms from "../forms.jsx";
-
-import Formsy from 'formsy-react';
-
-const NewDocContainer = React.createClass({
-
- propTypes: {
- collection: React.PropTypes.object.isRequired,
- label: React.PropTypes.string,
- callback: React.PropTypes.func,
- methodName: React.PropTypes.string
- },
-
- mixins: [ReactMeteorData],
-
- getMeteorData() {
- return {
- currentUser: Meteor.user()
- };
- },
-
- submitForm(data) {
- // remove any empty properties
- const document = _.compactObject(data);
- const collection = this.props.collection;
- const methodName = this.props.methodName ? this.props.methodName : collection._name+'.create';
-
- Meteor.call(methodName, document, (error, document) => {
- if (error) {
- console.log(error)
- Messages.flash(error.message, "error")
- } else {
- Messages.flash("Document created.", "success");
- if (this.props.callback) {
- this.props.callback(document);
- }
- }
- });
- },
-
- render() {
-
- const collection = this.props.collection;
- const fields = collection.getInsertableFields(this.data.currentUser);
-
- return (
-
-
{this.props.label}
-
- {fields.map(fieldName => NovaForms.getComponent(fieldName, collection.simpleSchema()._schema[fieldName]))}
-
-
-
- )
- }
-});
-
-module.exports = NewDocContainer;
\ No newline at end of file
diff --git a/packages/nova-core/lib/core.js b/packages/nova-core/lib/core.js
index 5bdb30b52..b29c29b56 100644
--- a/packages/nova-core/lib/core.js
+++ b/packages/nova-core/lib/core.js
@@ -1,4 +1,7 @@
import Messages from "./messages.js";
-import NovaForms from "./forms.jsx";
-export default {Messages, NovaForms};
\ No newline at end of file
+import FlashContainer from "./containers/FlashContainer.jsx";
+
+import ModalButton from "./components/ModalButton.jsx";
+
+export default {Messages, FlashContainer, ModalButton};
\ No newline at end of file
diff --git a/packages/nova-core/lib/forms.jsx b/packages/nova-core/lib/forms.jsx
deleted file mode 100644
index 3b6a3c1a8..000000000
--- a/packages/nova-core/lib/forms.jsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import Formsy from 'formsy-react';
-import FRC from 'formsy-react-components';
-
-const Checkbox = FRC.Checkbox;
-const CheckboxGroup = FRC.CheckboxGroup;
-const Input = FRC.Input;
-const RadioGroup = FRC.RadioGroup;
-const Select = FRC.Select;
-const Textarea = FRC.Textarea;
-
-const NovaForms = {};
-
-NovaForms.getComponent = (fieldName, field, document) => {
-
- let options = [];
- if (field.autoform && field.autoform.options) {
- options = typeof field.autoform.options === "function" ? field.autoform.options() : field.autoform.options;
- }
-
- const value = document && document[fieldName] ? document[fieldName] : "";
-
- switch (field.control) {
-
- case "text":
- return ;
- case "textarea":
- return ;
- case "checkbox":
- return ;
- case "checkboxgroup":
- return ;
- case "radiogroup":
- return ;
- case "select":
- return ;
- default:
- return ;
- }
-}
-
-export default NovaForms;
\ No newline at end of file
diff --git a/packages/nova-core/package.js b/packages/nova-core/package.js
index af1ff0efb..2ccc1a366 100644
--- a/packages/nova-core/package.js
+++ b/packages/nova-core/package.js
@@ -15,7 +15,8 @@ Package.onUse(function(api) {
'nova:i18n@0.25.7', // lib
'nova:events@0.25.7', // lib, i18n
'nova:settings@0.25.7', // lib, i18n
- 'utilities:react-list-container'
+ 'utilities:react-list-container',
+ 'utilities:react-form-containers'
];
api.use(packages);
diff --git a/packages/nova-demo/demo-app.jsx b/packages/nova-demo/demo-app.jsx
index 71492a767..904bb70c9 100644
--- a/packages/nova-demo/demo-app.jsx
+++ b/packages/nova-demo/demo-app.jsx
@@ -1,16 +1,5 @@
import {mount} from 'react-mounter';
-//////////////////////////////////////////////////////
-// Route //
-//////////////////////////////////////////////////////
-
-FlowRouter.route('/demo', {
- name: 'demo',
- action(params, queryParams) {
- mount(MoviesWrapper);
- }
-});
-
//////////////////////////////////////////////////////
// Collection & Schema //
//////////////////////////////////////////////////////
@@ -18,7 +7,7 @@ FlowRouter.route('/demo', {
Movies = new Mongo.Collection("movies");
const isLoggedIn = user => !!user;
-const isOwner = (user, document) => {user._id === document.userId};
+const isOwner = (user, document) => user._id === document.userId;
const schema = new SimpleSchema({
name: {
@@ -60,12 +49,23 @@ const schema = new SimpleSchema({
Movies.attachSchema(schema);
+//////////////////////////////////////////////////////
+// Route //
+//////////////////////////////////////////////////////
+
+FlowRouter.route('/demo', {
+ name: 'demo',
+ action() {
+ mount(MoviesWrapper);
+ }
+});
+
//////////////////////////////////////////////////////
// Methods //
//////////////////////////////////////////////////////
Movies.smartMethods({
- createCallback: function (document) {
+ createCallback: function (user, document) {
document = _.extend(document, {
createdAt: new Date(),
userId: Meteor.userId()
diff --git a/packages/nova-demo/demo-component.jsx b/packages/nova-demo/demo-component.jsx
index afbf66aa1..ae5e7c973 100644
--- a/packages/nova-demo/demo-component.jsx
+++ b/packages/nova-demo/demo-component.jsx
@@ -1,5 +1,15 @@
import NoSSR from 'react-no-ssr';
+import Core from 'meteor/nova:core';
+import SmartContainers from "meteor/utilities:react-list-container";
+import FormContainers from "meteor/utilities:react-form-containers";
+
+FlashContainer = Core.FlashContainer;
+ModalButton = Core.ModalButton;
+NewDocContainer = FormContainers.NewDocContainer;
+EditDocContainer = FormContainers.EditDocContainer;
+ListContainer = SmartContainers.ListContainer;
+
//////////////////////////////////////////////////////
// MoviesWrapper //
//////////////////////////////////////////////////////
@@ -8,10 +18,8 @@ MoviesWrapper = React.createClass({
render() {
- ({ListContainer, FlashContainer} = Telescope.components);
-
return (
-
+
Loading…}>
@@ -26,7 +34,6 @@ MoviesWrapper = React.createClass({
terms={{options: {sort: {createdAt: -1}}}}
options={{sort: {createdAt: -1}}}
joins={Movies.getJoins()}
- limit={4}
>
@@ -35,7 +42,7 @@ MoviesWrapper = React.createClass({
)
}
-})
+});
//////////////////////////////////////////////////////
// MoviesList //
@@ -45,8 +52,6 @@ MoviesList = React.createClass({
renderNew() {
- ({ModalButton, NewDocContainer} = Telescope.components);
-
const component = (
@@ -57,7 +62,6 @@ MoviesList = React.createClass({
},
render() {
- ({LoadMore} = Telescope.components);
return (
@@ -68,18 +72,14 @@ MoviesList = React.createClass({
)
}
});
-
//////////////////////////////////////////////////////
// Movie //
//////////////////////////////////////////////////////
-
Movie = React.createClass({
renderEdit() {
- ({ModalButton, EditDocContainer} = Telescope.components);
-
const movie = this.props;
const component = (
@@ -108,4 +108,6 @@ Movie = React.createClass({
)
}
-});
\ No newline at end of file
+});
+
+const LoadMore = props =>
Load More ({props.count}/{props.totalCount})
\ No newline at end of file