Skip to content

Commit 775ac86

Browse files
authored
(DOCSP-12167): Write Phase 2 Tutorial Text (Node) (#487)
* added annotations to node-cli app * added annotations to index.js * remove bluehawk gen from PR * edited node-cli tutorial text * minor changes
1 parent 5b6980d commit 775ac86

File tree

8 files changed

+230
-149
lines changed

8 files changed

+230
-149
lines changed

source/tutorial/nodejs-cli.txt

Lines changed: 102 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ tracker command line interface (CLI) that allows users to:
3232

3333
- Register themselves with email and password.
3434
- Sign in to their account with their email and password.
35-
- View, create, modify, and delete tasks.
36-
- Watch for changes to the Task collection and get notified in the terminal
37-
window when a change occurs.
35+
- View a list of projects they are a member of.
36+
- View, create, modify, and delete tasks in projects.
37+
- View a list of team members in their project.
38+
- Add and remove team members to their project.
3839

3940
This tutorial should take around 30 minutes to complete.
4041

@@ -111,10 +112,10 @@ multiple platforms. The project root for this tutorial is located in the
111112
files.
112113

113114
This application has a flat project structure: all of the files are in the root
114-
directory. In this tutorial, we'll be focusing on 4 files: ``config.js``,
115-
``users.js``, ``tasks.js``, and ``watch.js``. The other files provide the
115+
directory. In this tutorial, we'll be focusing on 5 files: ``config.js``,
116+
``users.js``, ``tasks.js``, ``team.js``, ``projects.js``. The other files provide the
116117
underlying structure for the CLI. The following table describes the role of
117-
each file in this project:
118+
important files in this project:
118119

119120
.. cssclass:: config-table
120121
.. list-table::
@@ -133,7 +134,8 @@ each file in this project:
133134
throughout its lifecycle and displays the initial logon screen.
134135

135136
* - main.js
136-
- Displays the main menu of choices.
137+
- Displays the main menu of choices. Users can view a list of projects
138+
they are a member of or select a project.
137139

138140
* - output.js
139141
- Responsible for displaying text in the terminal window.
@@ -149,9 +151,13 @@ each file in this project:
149151
- Handles Realm user authentication, including logging in, registering a
150152
new user, and logging out.
151153

152-
* - watch.js
153-
- Adds a listener to a Realm collection to notify the user when a change
154-
occurs.
154+
* - team.js
155+
- Handles the team member related communication between the CLI and Realm.
156+
The methods for listing, adding, and removing team members are contained in
157+
this file.
158+
159+
* - projects.js
160+
- Handles project retrieval and listing.
155161

156162
D. Connect to Your MongoDB Realm App
157163
------------------------------------
@@ -160,9 +166,7 @@ To get the app working with your backend, you first need to add your Realm App I
160166
to the ``config.js`` file. The ``config.js`` module exports a single property,
161167
``realmAppId``, which is currently set to "TODO":
162168

163-
.. code-block:: js
164-
165-
exports.realmAppId = "TODO";
169+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/code/start/config.codeblock.realmAppID.js
166170

167171
Change this value to your Realm App ID.
168172

@@ -172,31 +176,22 @@ Change this value to your Realm App ID.
172176
Your App Id </get-started/find-your-app-id>` doc.
173177

174178
Once you have made that change, you now need to complete the code needed to
175-
open a {+realm+}. In ``index.js``, find the ``openRealm`` function. It will look
176-
like this:
177-
178-
.. code-block:: js
179-
180-
async function openRealm() {
181-
const config = {
182-
schema: [schemas.TaskSchema, schemas.UserSchema, schemas.ProjectSchema],
183-
sync: {
184-
user: users.getAuthedUser(),
185-
partitionValue: "My Project",
186-
},
187-
};
188-
// TODO: open a realm with these configuration settings.
189-
}
179+
open a {+realm+}. In ``index.js``, find the ``openRealm`` function. Replace the ``TODO``
180+
line with a line of code that opens a {+realm+} and assigns it to the ``realm``
181+
property. It will look like this:
190182

191-
Replace the ``TODO`` line with a line of code that opens a {+realm+} and assigns
192-
it to the ``realm`` property:
183+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/code/final/index.codeblock.openRealm.js
184+
:emphasize-lines: 9
193185

194-
.. code-block:: js
186+
Now that you have implemented the ``openRealm`` function, you will now need to
187+
complete the code that retrieves the {+realm+}. In ``index.js``, find the
188+
``getRealm`` function. It will look like this:
195189

196-
realm = new Realm(config);
190+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/code/final/index.codeblock.getRealm.js
191+
:emphasize-lines: 3
197192

198193
At this point, your app is pointing to your backend and opens a connection
199-
to it when you start the app. However, users cannot yet log in, so let's update
194+
to it when you start the app. However, users cannot log in yet, so let's update
200195
that code next.
201196

202197
E. Enable authentication
@@ -208,47 +203,31 @@ an email address and password, and then, within a try-catch block, creates an
208203
credential and passes it to the Realm
209204
:js-sdk:`logIn() <Realm.App.html#logIn>` method.
210205

211-
Find the following comment:
212-
213-
.. code-block:: js
214-
215-
// TODO: create new emailPassword credentials and call app.logIn(...)
216-
217-
And add the following code to create a ``emailPassword`` credential:
218-
219-
.. code-block:: js
220-
221-
const credentials = Realm.Credentials.emailPassword(
222-
input.email,
223-
input.password
224-
);
225-
226-
Immediately below this, add the following code to call the
227-
``logIn()`` method:
228-
229-
.. code-block:: js
230-
231-
const user = await app.logIn(credentials);
206+
Find the the ``logIn`` function and add the following code to create a
207+
``emailPassword`` credential and call the ``logIn()`` method.
232208

209+
.. literalinclude:: tutorial/bluehawk-gen/code/final/users.codeblock.userLogin.js
210+
:emphasize-lines: 17, 18, 19, 22
233211

234212
F. Implement the CRUD methods
235213
-----------------------------
236214

237-
In the ``tasks.js`` file, there are a number of functions to handle typical
215+
In the ``tasks.js`` and ``projects.js`` files, there are a number of functions to handle typical
238216
CRUD functionality: ``getTasks``, ``getTask``, ``createTask``, ``deleteTask``,
239-
``editTask``, and ``changeStatus``. Each of these functions (except ``getTasks``)
240-
prompts the user for input and then makes the appropriate call to Realm. Your
241-
job is to implement the calls to {+service-short+}. The following list provides
242-
guidance on how to complete this task for each function:
217+
``editTask``, ``changeStatus``, and ``getProjects``. Each of these functions
218+
(except ``getTasks`` and ``getProjects``) prompts the user for input and then makes
219+
the appropriate call to Realm. Your job is to implement the calls to {+service-short+}.
220+
The following list provides guidance on how to complete this task for each function.
221+
222+
In ``tasks.js``:
243223

244224
* ``getTasks``
245225

246226
To get all objects, call the :js-sdk:`objects() <Realm.html#objects>` method
247227
and pass in the name of the collection:
248228

249-
.. code-block:: js
250-
251-
const tasks = realm.objects("Task");
229+
.. literalinclude:: tutorial/bluehawk-gen/final/tasks.codeblock.getTasks.js
230+
:emphasize-lines: 3
252231

253232

254233
* ``getTask``
@@ -257,12 +236,8 @@ guidance on how to complete this task for each function:
257236
we call the :js-sdk:`objectForPrimaryKey() <Realm.html#objectForPrimaryKey>`
258237
function to get a task by its Id.
259238

260-
.. code-block:: js
261-
262-
let result = realm.objectForPrimaryKey(
263-
"Task",
264-
new bson.ObjectID(task.id)
265-
);
239+
.. literalinclude:: tutorial/bluehawk-gen/final/tasks.codeblock.getTask.js
240+
:emphasize-lines: 11
266241

267242

268243
* ``createTask``
@@ -274,16 +249,9 @@ guidance on how to complete this task for each function:
274249
the :js-sdk:`create() <Realm.html#create>` function, passing in all of the
275250
required properties:
276251

277-
.. code-block:: js
278-
279-
realm.write(() => {
280-
result = realm.create("Task", {
281-
_id: new bson.ObjectID(),
282-
_partition: "My Project",
283-
name: task.name,
284-
status: task.status,
285-
});
286-
});
252+
.. literalinclude:: tutorial/bluehawk-gen/final/tasks.codeblock.createTask.js
253+
:emphasize-lines: 23, 24, 25, 26, 27, 28
254+
287255

288256
.. note::
289257

@@ -297,16 +265,12 @@ guidance on how to complete this task for each function:
297265
* ``deleteTask``
298266

299267
Deleting objects must also take place within a transaction. As with modifying
300-
an object, we'll use the write() function to handle the transaction for us,
301-
and then call the the :js-sdk:`delete() <Realm.html#delete>` function within
302-
it:
303-
304-
.. code-block:: js
268+
an object, we'll use the write() function to handle the transaction for us.
269+
We'll first call the ``objectForPrimaryKey`` method to get the specific we want
270+
to delete and then the :js-sdk:`delete() <Realm.html#delete>` function on that task:
305271

306-
realm.write(() => {
307-
realm.delete(task);
308-
output.result("Task deleted.");
309-
});
272+
.. literalinclude:: tutorial/bluehawk-gen/code/final/tasks.codeblock.deleteTask.js
273+
:emphasize-lines: 18, 20
310274

311275

312276
* ``modifyTask``
@@ -317,19 +281,62 @@ guidance on how to complete this task for each function:
317281
call to a Realm API to change an object. Rather, you change the *local* object
318282
and Sync ensures the object is updated on the server.
319283

320-
.. code-block:: js
321-
322-
realm.write(() => {
323-
task = realm.objectForPrimaryKey("Task", new bson.ObjectID(answers.id));
324-
task[answers.key] = answers.value;
325-
});
284+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/code/final/tasks.codeblock.modifyTask.js
285+
:emphasize-lines: 6, 7
286+
326287

327288
.. note::
328289

329290
To learn more about Realm Sync, see :doc:`Sync Overview </sync/overview>`.
330291

292+
In ``projects.js``:
293+
294+
* ``getProjects``
295+
296+
As defined by our data model, ``projects`` are an embedded object of the ``users`` object.
297+
To get all projects the user is a part of, we'll have to use the ``objectForPrimaryKey``
298+
method to get the current user and then access the current user's ``memberOf`` property.
299+
300+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/final/projects.codeblock.getProjects.js
301+
:emphasize-lines: 4, 5
302+
303+
G. Use Realm Functions
304+
----------------------
305+
306+
In the ``team.js`` file, there are functions that rely on :ref:`{+service-short+}
307+
functions </functions>`. {+service-short+} functions allow you to execute server-side
308+
logic for your client applications. Each of the following functions require you to
309+
implement the calls to {+service-short+}.
310+
311+
* ``getTeamMembers``
312+
313+
To get all team members, call the ``getMyTeamMembers`` {+service-short+} function
314+
using the ``User.functions`` method.
315+
316+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/final/team.codeblock.getTeamMembers.js
317+
:emphasize-lines: 4
331318

332-
G. Run and Test
319+
* ``addTeamMember``
320+
321+
This function prompts the user for the email of the new team member. You will need
322+
to call the ``addTeamMember`` {+service-short+} function and pass it the ``email``
323+
parameter.
324+
325+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/final/team.codeblock.addTeamMember.js
326+
:emphasize-lines: 12
327+
328+
* ``removeTeamMember``
329+
330+
This functions prompts the user for the email of the team member they would like to
331+
remove from their project. You will need to call the ``removeTeamMember``
332+
{+service-short+} function and pass it the ``email`` parameter.
333+
334+
.. literalinclude:: /tutorial/node-cli/bluehawk-gen/final/team.codeblock.removeTeamMember.js
335+
:emphasize-lines: 15
336+
337+
338+
339+
H. Run and Test
333340
---------------
334341

335342
Once you have completed the code, you should run the app and check functionality.
@@ -357,56 +364,9 @@ Once you have completed the code, you should run the app and check functionality
357364

358365
.. admonition:: Reminder
359366

360-
If something isn't working for you, you can check out the ``main`` branch of
367+
If something isn't working for you, you can check out the ``final`` branch of
361368
this repo to compare your code with our finished solution.
362369

363-
H. Implement the Collection Listener
364-
------------------------------------
365-
366-
A very handy feature in Realm is the ability to add a listener to a collection.
367-
The listener notifies your app when a change occurs in the collection. For our
368-
CLI, we want to listen for changes on the ``Tasks`` collection, and when one
369-
occurs, display a notification in the console window. To do this:
370-
371-
1. In your text editor, open the ``watch.js`` file.
372-
373-
#. Our internal ``listener`` function is a callback function that takes two
374-
parameters: the collection of tasks and a ``changes`` object that is sent
375-
from Realm. The ``changes`` object has the following properties:
376-
377-
* ``changes.deletions`` returns the index of the deleted item *before*
378-
the deletion.
379-
380-
* ``changes.insertions`` returns the index of the new object.
381-
382-
* ``changes.modifications`` returns the index of the modified object.
383-
384-
#. In the ``watchForChanges`` function, you will get all of the objects in
385-
the **Tasks** collection (just as we did in the ``getTasks`` function),
386-
and then call the :js-sdk:`addListener() <Realm.Collection.html#addListener>`
387-
method. Under the ``TODO`` comment, add the following code:
388-
389-
.. code-block:: js
390-
391-
const tasks = realm.objects("Task");
392-
tasks.addListener(listener);
393-
394-
With this code update, you can now re-run the app and watch for changes.
395-
396-
1. In the main menu, choose "Watch for changes". You will see that the UI
397-
stays in a "waiting" state.
398-
399-
2. Open a second terminal window and run the app again. In this second window,
400-
try creating, modifying, and deleting tasks. Each time you perform an action,
401-
the first terminal window will update with a notification.
402-
403-
.. note::
404-
405-
If you want to continue to work in the same process and have the change
406-
notifications appear inline, you can modify the code
407-
in ``main.js``, within the ``case Choices.WatchForChanges`` handler. The
408-
inline code comment explains the change you can make.
409-
410370
What's Next?
411371
------------
412372

tutorial/node-cli/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
// :code-block-start: realmAppID
12
exports.realmAppId = "TODO";
3+
// :code-block-end:

0 commit comments

Comments
 (0)