From 38e07737c3980a2d038f0a6da9990ee23c55ec2f Mon Sep 17 00:00:00 2001
From: Sacha Greif
Date: Fri, 26 Feb 2016 10:42:57 +0900
Subject: [PATCH] rework post new and post edit forms to be collection-agnostic
---
.../base-components/lib/common/Header.jsx | 8 +-
packages/base-components/lib/components.js | 4 +-
packages/base-components/lib/posts/Post.jsx | 3 +-
.../base-components/lib/posts/PostEdit.jsx | 80 ++++++++--------
.../base-components/lib/posts/PostNew.jsx | 96 +++++++++----------
.../lib/posts/list/PostItem.jsx | 7 +-
packages/base-components/lib/routes.jsx | 15 ++-
packages/nova-core/lib/components.js | 4 +-
.../lib/components/EditDocumentForm.jsx | 54 +++++++++++
.../nova-core/lib/components/ModalButton.jsx | 18 +++-
.../lib/components/NewDocumentForm.jsx | 92 +++++++++---------
.../lib/containers/EditContainer.jsx | 0
.../lib/containers/EditDocContainer.jsx | 63 ++++++++++++
.../lib/containers/ItemContainer.jsx | 9 +-
.../lib/containers/ListContainer.jsx | 6 +-
.../nova-core/lib/containers/NewContainer.jsx | 0
.../lib/containers/NewDocContainer.jsx | 59 ++++++++++++
17 files changed, 352 insertions(+), 166 deletions(-)
create mode 100644 packages/nova-core/lib/components/EditDocumentForm.jsx
delete mode 100644 packages/nova-core/lib/containers/EditContainer.jsx
create mode 100644 packages/nova-core/lib/containers/EditDocContainer.jsx
delete mode 100644 packages/nova-core/lib/containers/NewContainer.jsx
create mode 100644 packages/nova-core/lib/containers/NewDocContainer.jsx
diff --git a/packages/base-components/lib/common/Header.jsx b/packages/base-components/lib/common/Header.jsx
index bf4c3b0ec..8c646ec8d 100644
--- a/packages/base-components/lib/common/Header.jsx
+++ b/packages/base-components/lib/common/Header.jsx
@@ -3,7 +3,7 @@ import NoSSR from 'react-no-ssr';
const Header = props => {
- ({Logo, ListContainer, CategoriesList, FlashContainer, NewPostButton, ModalButton, PostNewContainer, CurrentUserContainer, PostNew} = Telescope.components);
+ ({Logo, ListContainer, CategoriesList, FlashContainer, NewPostButton, ModalButton, PostNewContainer, CurrentUserContainer, PostNew, NewDocContainer} = Telescope.components);
const logoUrl = Telescope.settings.get("logoUrl");
const siteTitle = Telescope.settings.get("title", "Telescope");
@@ -16,7 +16,7 @@ const Header = props => {
{tagline ? {tagline}
: "" }
- {}
+
Loading…
}>
@@ -25,7 +25,9 @@ const Header = props => {
{props.currentUser ?
New Comment:
diff --git a/packages/base-components/lib/posts/PostEdit.jsx b/packages/base-components/lib/posts/PostEdit.jsx
index ae60636a9..caaefcbcc 100644
--- a/packages/base-components/lib/posts/PostEdit.jsx
+++ b/packages/base-components/lib/posts/PostEdit.jsx
@@ -1,52 +1,52 @@
-import Core from "meteor/nova:core";
-({Messages, NovaForms} = Core);
+// import Core from "meteor/nova:core";
+// ({Messages, NovaForms} = Core);
-import Formsy from 'formsy-react';
+// import Formsy from 'formsy-react';
-const PostEdit = React.createClass({
+// const PostEdit = React.createClass({
- propTypes: {
- document: React.PropTypes.object.isRequired,
- currentUser: React.PropTypes.object.isRequired
- },
+// propTypes: {
+// document: React.PropTypes.object.isRequired,
+// currentUser: React.PropTypes.object.isRequired
+// },
- submitForm(data) {
- const post = this.props.document;
- const modifier = {$set: _.compactObject(data)};
+// submitForm(data) {
+// const post = this.props.document;
+// const modifier = {$set: _.compactObject(data)};
- event.preventDefault();
+// event.preventDefault();
- Meteor.call('posts.edit', post._id, modifier, (error, post) => {
- if (error) {
- console.log(error)
- Messages.flash(error.message, "error")
- } else {
- Messages.flash("Post edited.", "success")
- FlowRouter.go('posts.single', post);
- }
- });
- },
+// Meteor.call('posts.edit', post._id, modifier, (error, post) => {
+// if (error) {
+// console.log(error)
+// Messages.flash(error.message, "error")
+// } else {
+// Messages.flash("Post edited.", "success")
+// FlowRouter.go('posts.single', post);
+// }
+// });
+// },
- render() {
+// render() {
- ({CanEditPost} = Telescope.components);
+// ({CanEditPost} = Telescope.components);
- const post = this.props.document;
+// const post = this.props.document;
- const fields = Posts.simpleSchema().getEditableFields(this.props.currentUser);
+// const fields = Posts.simpleSchema().getEditableFields(this.props.currentUser);
- return (
-
-
-
Edit Post “{post.title}”
-
- {fields.map(fieldName => NovaForms.getComponent(fieldName, Posts.simpleSchema()._schema[fieldName], post))}
-
-
-
-
- )
- }
-});
+// return (
+//
+//
+//
Edit Post “{post.title}”
+//
+// {fields.map(fieldName => NovaForms.getComponent(fieldName, Posts.simpleSchema()._schema[fieldName], post))}
+//
+//
+//
+//
+// )
+// }
+// });
-module.exports = PostEdit;
\ No newline at end of file
+// module.exports = PostEdit;
\ No newline at end of file
diff --git a/packages/base-components/lib/posts/PostNew.jsx b/packages/base-components/lib/posts/PostNew.jsx
index 6440d0fe0..662851a7d 100644
--- a/packages/base-components/lib/posts/PostNew.jsx
+++ b/packages/base-components/lib/posts/PostNew.jsx
@@ -1,60 +1,60 @@
-import Core from "meteor/nova:core";
-({Messages, NovaForms} = Core);
+// import Core from "meteor/nova:core";
+// ({Messages, NovaForms} = Core);
-import Formsy from 'formsy-react';
+// import Formsy from 'formsy-react';
-const PostNew = React.createClass({
+// const PostNew = React.createClass({
- propTypes: {
- currentUser: React.PropTypes.object,
- postNewCallback: React.PropTypes.func,
- closeModal: React.PropTypes.func
- },
+// propTypes: {
+// currentUser: React.PropTypes.object,
+// postNewCallback: React.PropTypes.func,
+// closeModal: React.PropTypes.func
+// },
- getInitialState() {
- return {
- canSubmit: false
- }
- },
+// getInitialState() {
+// return {
+// canSubmit: false
+// }
+// },
- submitForm(data) {
- // remove any empty properties
- post = _.compactObject(data);
+// submitForm(data) {
+// // remove any empty properties
+// post = _.compactObject(data);
- post = Telescope.callbacks.run("posts.new.client", post);
+// post = Telescope.callbacks.run("posts.new.client", post);
- Meteor.call('posts.new', post, (error, post) => {
- if (error) {
- console.log(error)
- Messages.flash(error.message, "error")
- } else {
- Messages.flash("Post created.", "success");
- FlowRouter.go('posts.single', post);
- if (this.props.closeModal) {
- this.props.closeModal();
- }
- }
- });
- },
+// Meteor.call('posts.new', post, (error, post) => {
+// if (error) {
+// console.log(error)
+// Messages.flash(error.message, "error")
+// } else {
+// Messages.flash("Post created.", "success");
+// FlowRouter.go('posts.single', post);
+// if (this.props.closeModal) {
+// this.props.closeModal();
+// }
+// }
+// });
+// },
- render() {
+// render() {
- ({CanCreatePost} = Telescope.components);
+// ({CanCreatePost} = Telescope.components);
- const fields = Posts.simpleSchema().getEditableFields(this.props.currentUser);
+// const fields = Posts.simpleSchema().getEditableFields(this.props.currentUser);
- return (
-
-
-
New Post
-
- {fields.map(fieldName => NovaForms.getComponent(fieldName, Posts.simpleSchema()._schema[fieldName]))}
-
-
-
-
- )
- }
-});
+// return (
+//
+//
+//
New Post
+//
+// {fields.map(fieldName => NovaForms.getComponent(fieldName, Posts.simpleSchema()._schema[fieldName]))}
+//
+//
+//
+//
+// )
+// }
+// });
-module.exports = PostNew;
\ No newline at end of file
+// module.exports = PostNew;
\ No newline at end of file
diff --git a/packages/base-components/lib/posts/list/PostItem.jsx b/packages/base-components/lib/posts/list/PostItem.jsx
index de9226c35..b51d0075d 100644
--- a/packages/base-components/lib/posts/list/PostItem.jsx
+++ b/packages/base-components/lib/posts/list/PostItem.jsx
@@ -21,7 +21,7 @@ const PostItem = React.createClass({
renderActions() {
- ({ModalButton, ItemContainer, PostEdit} = Telescope.components);
+ ({ModalButton, ItemContainer, EditDocContainer} = Telescope.components);
const component = (
@@ -29,8 +29,9 @@ const PostItem = React.createClass({
collection={Posts}
publication="posts.single"
terms={{_id: this.props.post._id}}
- component={PostEdit}
- />
+ >
+
+
);
diff --git a/packages/base-components/lib/routes.jsx b/packages/base-components/lib/routes.jsx
index 5f5c3174f..6c90e51fb 100644
--- a/packages/base-components/lib/routes.jsx
+++ b/packages/base-components/lib/routes.jsx
@@ -18,9 +18,8 @@ FlowRouter.route('/', {
selector={selector}
options={options}
terms={queryParams}
- component={PostList}
joins={Posts.simpleSchema().getJoins()}
- />})
+ >
})
}
});
@@ -41,9 +40,8 @@ FlowRouter.route('/posts/:_id', {
collection={Posts}
publication="posts.single"
terms={params}
- component={Post}
joins={Posts.simpleSchema().getJoins()}
- />});
+ >
});
}
});
@@ -56,7 +54,7 @@ FlowRouter.route('/posts/:_id/edit', {
publication="posts.single"
terms={{_id: params._id}}
component={PostEdit}
- />});
+ >
});
}
});
@@ -69,8 +67,7 @@ FlowRouter.route('/users/:slug', {
collection={Users}
publication="users.single"
terms={{'telescope.slug': params.slug}}
- component={UsersSingle}
- />});
+ >
});
}
});
@@ -84,7 +81,7 @@ FlowRouter.route('/account', {
publication="users.single"
terms={{_id: Meteor.userId()}}
component={UsersEdit}
- />});
+ >
});
}
});
@@ -98,7 +95,7 @@ FlowRouter.route('/users/:slug/edit', {
publication="users.single"
terms={params}
component={UsersEdit}
- />});
+ >
});
}
});
diff --git a/packages/nova-core/lib/components.js b/packages/nova-core/lib/components.js
index 39b130d96..5627b7a32 100644
--- a/packages/nova-core/lib/components.js
+++ b/packages/nova-core/lib/components.js
@@ -3,5 +3,7 @@ Telescope.registerComponent("ItemContainer", require('./containers/ItemContainer
Telescope.registerComponent("ListContainer", require('./containers/ListContainer.jsx'));
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("ModalButton", require('./components/ModalButton.jsx'));
\ No newline at end of file
+Telescope.registerComponent("ModalButton", require('./components/ModalButton.jsx'));
diff --git a/packages/nova-core/lib/components/EditDocumentForm.jsx b/packages/nova-core/lib/components/EditDocumentForm.jsx
new file mode 100644
index 000000000..941c0b502
--- /dev/null
+++ b/packages/nova-core/lib/components/EditDocumentForm.jsx
@@ -0,0 +1,54 @@
+// import Messages from "../messages.js";
+// import NovaForms from "../forms.jsx";
+
+// import Formsy from 'formsy-react';
+
+// const EditDocumentForm = React.createClass({
+
+// propTypes: {
+// document: React.PropTypes.object.isRequired,
+// currentUser: React.PropTypes.object.isRequired,
+// collection: React.PropTypes.object.isRequired,
+// label: React.PropTypes.string,
+// callback: React.PropTypes.func,
+// methodName: React.PropTypes.string
+// },
+
+// 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.simpleSchema().getEditableFields(this.props.currentUser);
+
+// return (
+//
+//
{this.props.label}
+//
+// {fields.map(fieldName => NovaForms.getComponent(fieldName, collection.simpleSchema()._schema[fieldName], document))}
+//
+//
+//
+// )
+// }
+// });
+
+// module.exports = EditDocumentForm;
\ No newline at end of file
diff --git a/packages/nova-core/lib/components/ModalButton.jsx b/packages/nova-core/lib/components/ModalButton.jsx
index 64014c510..dc0cd140b 100644
--- a/packages/nova-core/lib/components/ModalButton.jsx
+++ b/packages/nova-core/lib/components/ModalButton.jsx
@@ -14,7 +14,6 @@ const customStyles = {
const ModalButton = React.createClass({
propTypes: {
- propsToPass: React.PropTypes.object,
label: React.PropTypes.string.isRequired,
className: React.PropTypes.string
},
@@ -39,7 +38,21 @@ const ModalButton = React.createClass({
// see http://stackoverflow.com/a/32371612/649299
const childrenWithProps = React.Children.map(this.props.children, (child) => {
- return React.cloneElement(child, { ...this.props.propsToPass, closeModal: this.closeModal });
+
+ // if child component already has a callback, create new callback
+ // that both calls original callback and also closes modal
+ let callback;
+ if (child.props.callback) {
+ callback = (document) => {
+ child.props.callback(document);
+ this.closeModal();
+ }
+ } else {
+ callback = this.closeModal;
+ }
+
+ return React.cloneElement(child, { callback: callback });
+
});
return (
@@ -50,7 +63,6 @@ const ModalButton = React.createClass({
onRequestClose={this.closeModal}
style={customStyles} >
-
{childrenWithProps}
diff --git a/packages/nova-core/lib/components/NewDocumentForm.jsx b/packages/nova-core/lib/components/NewDocumentForm.jsx
index 7ef3f50eb..a29234951 100644
--- a/packages/nova-core/lib/components/NewDocumentForm.jsx
+++ b/packages/nova-core/lib/components/NewDocumentForm.jsx
@@ -1,54 +1,58 @@
-import Core from "meteor/nova:core";
-({Messages, NovaForms} = Core);
+// import Messages from "../messages.js";
+// import NovaForms from "../forms.jsx";
-import Formsy from 'formsy-react';
+// import Formsy from 'formsy-react';
-const NewDocumentForm = React.createClass({
+// const NewDocumentForm = React.createClass({
- propTypes: {
- currentUser: React.PropTypes.object,
- categories: React.PropTypes.array,
- collection: React.PropTypes.object,
- postNewCallback: React.PropTypes.func
- },
+// propTypes: {
+// currentUser: React.PropTypes.object.isRequired,
+// collection: React.PropTypes.object.isRequired,
+// label: React.PropTypes.string,
+// callback: React.PropTypes.func,
+// methodName: React.PropTypes.string
+// },
- getInitialState() {
- return {
- canSubmit: false
- }
- },
+// getInitialState() {
+// return {
+// canSubmit: false
+// }
+// },
- submitForm(data) {
- // remove any empty properties
- document = _.compactObject(data);
+// 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(this.props.collection._name+'.create', document, (error, result) => {
- if (error) {
- console.log(error)
- Messages.flash(error.message, "error")
- } else {
- Messages.flash("Document created.", "success");
- if (this.props.postNewCallback) {
- this.props.postNewCallback(result);
- }
- }
- });
- },
+// 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() {
+// render() {
- const fields = this.props.collection.simpleSchema().getEditableFields(this.props.currentUser);
+// const collection = this.props.collection;
+// const fields = collection.simpleSchema().getEditableFields(this.props.currentUser);
- return (
-
-
New
-
- {fields.map(fieldName => NovaForms.getComponent(fieldName, this.props.collection.simpleSchema()._schema[fieldName]))}
-
-
-
- )
- }
-});
+// return (
+//
+//
{this.props.label}
+//
+// {fields.map(fieldName => NovaForms.getComponent(fieldName, collection.simpleSchema()._schema[fieldName]))}
+//
+//
+//
+// )
+// }
+// });
-module.exports = NewDocumentForm;
\ No newline at end of file
+// module.exports = NewDocumentForm;
\ No newline at end of file
diff --git a/packages/nova-core/lib/containers/EditContainer.jsx b/packages/nova-core/lib/containers/EditContainer.jsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/nova-core/lib/containers/EditDocContainer.jsx b/packages/nova-core/lib/containers/EditDocContainer.jsx
new file mode 100644
index 000000000..9e7a5ba63
--- /dev/null
+++ b/packages/nova-core/lib/containers/EditDocContainer.jsx
@@ -0,0 +1,63 @@
+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.simpleSchema().getEditableFields(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/ItemContainer.jsx b/packages/nova-core/lib/containers/ItemContainer.jsx
index 23ef8db13..83f7a3ea1 100644
--- a/packages/nova-core/lib/containers/ItemContainer.jsx
+++ b/packages/nova-core/lib/containers/ItemContainer.jsx
@@ -4,11 +4,10 @@ const ItemContainer = React.createClass({
propTypes: {
collection: React.PropTypes.object.isRequired,
- component: React.PropTypes.func.isRequired,
publication: React.PropTypes.string.isRequired,
terms: React.PropTypes.object,
- propsToPass: React.PropTypes.object,
- joins: React.PropTypes.array
+ joins: React.PropTypes.array,
+ callback: React.PropTypes.func // a callback function to pass through, for modals (note: use Redux?)
},
mixins: [ReactMeteorData],
@@ -55,9 +54,7 @@ const ItemContainer = React.createClass({
const Component = this.props.component; // could be Post or PostEdit
if (this.data.document) {
- return (
-
- )
+ return React.cloneElement(this.props.children, { ...this.data, callback: this.props.callback, collection: this.props.collection });
} else {
return
Loading…
}
diff --git a/packages/nova-core/lib/containers/ListContainer.jsx b/packages/nova-core/lib/containers/ListContainer.jsx
index 864f04939..dcef0b458 100644
--- a/packages/nova-core/lib/containers/ListContainer.jsx
+++ b/packages/nova-core/lib/containers/ListContainer.jsx
@@ -29,7 +29,6 @@ const ListContainer = React.createClass({
propTypes: {
collection: React.PropTypes.object.isRequired, // the collection to paginate
- component: React.PropTypes.func.isRequired, // the component results will be passed to
publication: React.PropTypes.string, // the publication to subscribe to
terms: React.PropTypes.object, // an object passed to the publication
selector: React.PropTypes.object, // the selector used in collection.find()
@@ -134,10 +133,7 @@ const ListContainer = React.createClass({
},
render() {
- const Component = this.props.component;
- return (
-
- )
+ return React.cloneElement(this.props.children, { ...this.data, loadMore: this.loadMore});
}
});
diff --git a/packages/nova-core/lib/containers/NewContainer.jsx b/packages/nova-core/lib/containers/NewContainer.jsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/nova-core/lib/containers/NewDocContainer.jsx b/packages/nova-core/lib/containers/NewDocContainer.jsx
new file mode 100644
index 000000000..f98d4f62f
--- /dev/null
+++ b/packages/nova-core/lib/containers/NewDocContainer.jsx
@@ -0,0 +1,59 @@
+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.simpleSchema().getEditableFields(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