For this experience, you will create the Contacts collection, seed it with data on startup, and access it in the List Contacts page. When finished, the page will look like this:
Notice that the UI hasn’t changed, but one less contact is shown when logged in as john@foo.com, since he only owns two of the three contacts.
First, I suggest you watch my screencast before trying this WOD for the first time. I have not been able to find suitable resources for you to read prior to doing this WOD to cover all of the Meteor concepts I will cover. So, it’s best for you to watch the solution one time through to orient yourself.
Second, be sure to review the chapters of the Meteor Guide listed in the Readings section, particularly the ones on Collections and Publications.
At the conclusion of the last WOD, your List Contacts Page mockup was in a branch called list-contacts-page-1 (and list-contacts-page-2).
Quit meteor if it is running.
Now switch to the master branch in GitHub Desktop, and merge one of your landing page branches into it. Push your master branch to GitHub after the merge completes.
Start meteor using meteor npm run start
, and check http://localhost:3000 (and the console) to ensure that the merge worked correctly.
Now you’re ready to do this practice WOD. There are two rounds to this WOD, each timed individually.
Start your timer.
Create a branch called contacts-collection-1 using GitHub Desktop, and publish this branch to GitHub.
If necessary, start up your application using meteor npm run start
. Check to see that it’s running at http://localhost:3000. Take a look at the console to be sure there are no errors.
Define the Contacts collection. Make a copy of the app/api/stuff directory, and call it contact. Rename contact/stuff.js to contact/contact.js, and edit contact/index.js to import contact.js.
In api/contact/contact.js, rename the collection to Contacts. Rename StuffSchema to ContactSchema, and provide fields firstName, lastName, address, image, description, and owner. All are Strings.
Load the Contacts collection definition on both client and server when the system starts up. Edit app/imports/startup/both/index.js to load api/contact.
Initialize the collection with sample Contacts. In app/imports/startup/server/, make a copy of stuff.js and call it contact.js. Edit app/imports/startup/server/index.js to load contact.js. Rename the publication.
Edit app/imports/startup/server/contact.js to load some seed contact data on startup if there are no documents in the Contacts collection.
Edit api/startup/server/index.js to import contact.js.
Edit config/settings.development.json to define a field called “defaultContacts” with objects. Copy the contacts array from ListContacts.jsx and use that as seed data. Note: You must add a ‘owner’ field: use john@foo.com for two of the data items and admin@foo.com for the other.
Stop Meteor, invoke meteor reset
to clear the database, then meteor npm run start
. You should see the following printed out:
[~/github/philipmjohnson/digits/app]-> meteor reset
Project reset.
[~/github/philipmjohnson/digits/app]-> meteor npm run start
> meteor-application-template-react@ start /Users/philipjohnson/github/philipmjohnson/digits/app
> meteor --no-release-check --settings ../config/settings.development.json
[[[[[ ~/github/philipmjohnson/digits/app ]]]]]
=> Started proxy.
=> Started MongoDB.
I20180302-17:07:09.981(-10)? Creating the default user(s)
I20180302-17:07:10.007(-10)? Creating user admin@foo.com.
I20180302-17:07:10.008(-10)? Creating user john@foo.com.
I20180302-17:07:10.008(-10)? Creating default data.
I20180302-17:07:10.008(-10)? Adding: Basket (john@foo.com)
I20180302-17:07:10.008(-10)? Adding: Bicycle (john@foo.com)
I20180302-17:07:10.008(-10)? Adding: Banana (admin@foo.com)
I20180302-17:07:10.008(-10)? Adding: Boogie Board (admin@foo.com)
I20180302-17:07:10.009(-10)? Creating default contacts.
I20180302-17:07:10.009(-10)? Adding: Johnson (john@foo.com)
I20180302-17:07:10.009(-10)? Adding: Casanova (john@foo.com)
I20180302-17:07:10.009(-10)? Adding: Binsted (admin@foo.com)
W20180302-17:07:10.009(-10)? (STDERR) Note: you are using a pure-JavaScript implementation of bcrypt.
W20180302-17:07:10.010(-10)? (STDERR) While this implementation will work correctly, it is known to be
W20180302-17:07:10.010(-10)? (STDERR) approximately three times slower than the native implementation.
W20180302-17:07:10.010(-10)? (STDERR) In order to use the native implementation instead, run
W20180302-17:07:10.010(-10)? (STDERR)
W20180302-17:07:10.011(-10)? (STDERR) meteor npm install --save bcrypt
W20180302-17:07:10.011(-10)? (STDERR)
W20180302-17:07:10.011(-10)? (STDERR) in the root directory of your application.
=> Started your app.
=> App running at: http://localhost:3000/
This console output indicates that three contacts are created by default.
Edit app/imports/startup/server/contact.js to define a publication called “Contacts” that publishes all of the contacts associated with the currently logged in user. Also create a “ContactsAdmin” publication to publish all the Contacts when the logged in user is the Admin.
Edit ListContacts.jsx to remove the contacts field, subscribe to the Contacts publication, and map through this.props.contacts to generate the displayed contacts.
When you are finished, the List Contacts page for john@foo.com should look like this:
If you log out and log in as admin@foo.com, then the page should look like this:
As you can see, only the Contacts associated with the logged in user are displayed.
Now let’s implement the Admin page:
Make a copy of app/imports/ui/components/Contact.jsx called ContactAdmin.jsx. Change the component name to ContactAdmin. Add a new Card.Content field at the bottom that contains this.props.contact.owner. Add the “extra” property.
Make a copy of app/imports/ui/pages/ListContacts.jsx called ListContactsAdmin.jsx. Change the component name to ListContactsAdmin. Subscribe to “ContactsAdmin” rather than “Contacts”. Map to ContactAdmin, not Contact.
In app/imports/ui/layouts/App.jsx, make the admin route go to ListContactsAdmin rather than ListStuffAdmin.
When you’ve finished, the Admin page should look like this:
Notice that the Admin can subscribe to a publication that gets all the Contacts regardless of who the owner is. Only users with the Admin role can do that.
When your page renders correctly,
To ensure that you understand this material, you must do this WOD a second time.
Switch back to the master branch. This will revert your local repo to its state just before the start of this WOD.
Create a new branch called contacts-collection-2.
Go through the WOD again. When you’re done, commit and push your contacts-collection-2 branch to GitHub with the message ‘contacts collection finished in NN minutes.’, where NN is the number of minutes it took you to do it according to your timer.
Danny will be checking to see that both branches are in GitHub.
Rx: <16 min Av: 16-20 min Sd: 20-25 min DNF: 25+ min
Here’s a screencast of me working through this problem. You can watch this prior to attempting it for the first time yourself.
By the time and date indicated on the Schedule page, submit this assignment via Laulima.
Your submission should contain:
You will receive full credit for this practice WOD as long as you have attempted it the required number of times and submitted the email with all required data before the due date. Your code does not have to run perfectly for you to receive full credit. However, if you do not repeat each practice WOD until you can finish it successfully in at least AV time, you are unlikely to do well on the in-class WOD. To reduce the stress associated with this course, I recommend that you repeat each practice WOD as many times as necessary to achieve at least AV before its due date.