Permalink
Browse files

Step 11 of TODO App with React tutorial - using publish-subscribe ins…

…tead of autopublish, and adding "private TODO items" functionality and UI
  • Loading branch information...
itamaro committed Nov 28, 2015
1 parent a4d831b commit 6bbc8357d9173dab2362885ad63973d1dea49233
Showing with 57 additions and 5 deletions.
  1. +0 −1 .meteor/packages
  2. +0 −1 .meteor/versions
  3. +7 −1 App.jsx
  4. +15 −2 Task.jsx
  5. +35 −0 simple-todos-react.jsx
@@ -16,7 +16,6 @@ standard-minifiers # JS/CSS minifiers run for production mode
es5-shim # ECMAScript 5 compatibility for older browsers.
ecmascript # Enable ECMAScript2015+ syntax in app code

autopublish # Publish all data to the clients (for prototyping)
react
accounts-ui
accounts-password
@@ -2,7 +2,6 @@ accounts-base@1.2.2
accounts-password@1.1.4
accounts-ui@1.1.6
accounts-ui-unstyled@1.1.8
autopublish@1.0.4
autoupdate@1.2.4
babel-compiler@5.8.24_1
babel-runtime@0.1.4
@@ -29,7 +29,13 @@ App = React.createClass({
renderTasks() {
// Get tasks from this.data.tasks
return this.data.tasks.map((task) => {
return <Task key={task._id} task={task} />;
const currentUserId = this.data.currentUser && this.data.currentUser._id;
const showPrivateButton = task.owner === currentUserId;

return <Task
key={task._id}
task={task}
showPrivateButton={showPrivateButton} />;
});
},

@@ -3,7 +3,8 @@ Task = React.createClass({
propTypes: {
// This component gets the task to display through a React prop.
// We can use propTypes to indicate it is required
task: React.PropTypes.object.isRequired
task: React.PropTypes.object.isRequired,
showPrivateButton: React.PropTypes.bool.isRequired
},

toggleChecked() {
@@ -15,10 +16,16 @@ Task = React.createClass({
Meteor.call("removeTask", this.props.task._id);
},

togglePrivate() {
Meteor.call("setPrivate", this.props.task._id, ! this.props.task.private);
},

render() {
// Give tasks a different className when they are checked off,
// so that we can style them nicely in CSS
const taskClassName = this.props.task.checked ? "checked" : "";
// Add "checked" and/or "private" to the className when needed
const taskClassName = (this.props.task.checked ? "checked" : "") + " " +
(this.props.task.private ? "private" : "");

return (
<li className={taskClassName}>
@@ -32,6 +39,12 @@ Task = React.createClass({
checked={this.props.task.checked}
onClick={this.toggleChecked} />

{ this.props.showPrivateButton ? (
<button className="toggle-private" onClick={this.togglePrivate}>
{ this.props.task.private ? "Private" : "Public" }
</button>
) : ''}

<span className="text">
<strong>
{this.props.task.username ? this.props.task.username : '<someone>'}
@@ -7,12 +7,26 @@ if (Meteor.isClient) {
passwordSignupFields: "USERNAME_ONLY"
});

Meteor.subscribe("tasks");

Meteor.startup(function () {
// Use Meteor.startup to render the component after the page is ready
React.render(<App />, document.getElementById("render-target"));
});
}

if (Meteor.isServer) {
// Only publish tasks that are public or belong to the current us
Meteor.publish("tasks", function () {
return Tasks.find({
$or: [
{ private: {$ne: true} },
{ owner: this.userId }
]
});
});
}

Meteor.methods({
addTask(text) {
// Make sure the user is logged in before inserting a task
@@ -29,10 +43,31 @@ Meteor.methods({
},

removeTask(taskId) {
const task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can delete it
throw new Meteor.Error("not-authorized");
}
Tasks.remove(taskId);
},

setChecked(taskId, setChecked) {
const task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can check it off
throw new Meteor.Error("not-authorized");
}
Tasks.update(taskId, { $set: { checked: setChecked} });
},

setPrivate(taskId, setToPrivate) {
const task = Tasks.findOne(taskId);

// Make sure only the task owner can make a task private
if (task.owner !== Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}

Tasks.update(taskId, { $set: { private: setToPrivate } });
}
});

0 comments on commit 6bbc835

Please sign in to comment.