diff --git a/docs/source/getting-started/first-feature.rst b/docs/source/getting-started/first-feature.rst index 581f08ad97..25ae8f8d2f 100644 --- a/docs/source/getting-started/first-feature.rst +++ b/docs/source/getting-started/first-feature.rst @@ -4,32 +4,32 @@ Your First Feature ****************** -Let's dive into implementing a new feature for our social network app. -This will give us a better idea how to develop Daml applications using our template. +To get a better idea of how to develop Daml applications, let’s try implementing a new feature for our social network app. -At the moment, our app lets us follow users in the network, but we have no way to communicate with them! +At the moment, our app lets us follow users in the network, but we have no way to communicate with them. Let's fix that by adding a *direct messaging* feature. -This should let users that follow each other send messages, respecting *authorization* and *privacy*. +This should let users that follow each other send messages to each other, respecting *authorization* and *privacy*. This means: - 1. You cannot send a message to someone unless they have given you the authority by following you back. - 2. You cannot see a message unless you sent it or it was sent to you. + - You cannot send a message to someone unless they have given you the authority by following you back. + - You cannot see a message unless you sent it or it was sent to you. -We will see that Daml lets us implement these guarantees in a direct and intuitive way. +Daml lets us implement these guarantees in a direct and intuitive way. -There are three parts to building and running the messaging feature: +Creating a feature involves four steps: 1. Adding the necessary changes to the Daml model - 2. Making the corresponding changes in the UI - 3. Running the app with the new feature. + 2. Running the feature + 3. Making the corresponding changes in the UI + 4. Running the app with the new feature As usual, we must start with the Daml model and base our UI changes on top of that. Daml Changes ============ -As mentioned in the :doc:`architecture ` section, the Daml code defines the *data* and *workflow* of the application. -The workflow aspect refers to the interactions between parties that are permitted by the system. +The Daml code defines the *data* and *workflow* of the application; you can read about this in more detail in the :doc:`architecture ` section. +The workflow refers to the interactions between parties that are permitted by the system. In the context of a messaging feature, these are essentially the authorization and privacy concerns listed above. For the authorization part, we take the following approach: a user Bob can message another user Alice when Alice starts following Bob back. @@ -46,7 +46,7 @@ Indentation is important: it should be at the top level like the original ``User This template is very simple: it contains the data for a message and no choices. The interesting part is the ``signatory`` clause: both the ``sender`` and ``receiver`` are signatories on the template. -This enforces the fact that creation and archival of ``Message`` contracts must be authorized by both parties. +This enforces that creation and archival of ``Message`` contracts must be authorized by both parties. Now we can add messaging into the workflow by adding a new choice to the ``User`` template. Copy the following choice to the ``User`` template after the ``Follow`` choice. The indentation for the ``SendMessage`` choice must match the one of ``Follow`` . *Make sure you save the file after copying the code*. @@ -74,16 +74,15 @@ Navigate to the terminal window where the ``daml start`` process is running and - Update the JavaScript library under ``ui/daml.js`` to connect the UI with your Daml code - Upload the *new DAR file* to the sandbox -As mentioned at the beginning of this *Getting Started with Daml* guide, Daml Sandbox uses an -in-memory store, which means it loses its state when stopped or restarted. That means that all user -data and follower relationships are lost. +As mentioned previously, Daml Sandbox uses an +in-memory store, which means it loses its state – which here includes all user data and follower relationships – when stopped or restarted. Now let's integrate the new functionality into the UI. Messaging UI ============ -The UI for messaging will consist of a new *Messages* panel in addition to the *Follow* and *Network* panel. +The UI for messaging consists of a new *Messages* panel in addition to the *Follow* and *Network* panel. This panel will have two parts: 1. A list of messages you've received with their senders. @@ -97,7 +96,7 @@ MessageList Component The goal of the ``MessageList`` component is to query all ``Message`` contracts where the ``receiver`` is the current user, and display their contents and senders in a list. The entire component is shown below. -You should copy this into a new ``MessageList.tsx`` file in ``ui/src/components`` and save it. +Copy this into a new ``MessageList.tsx`` file in ``ui/src/components`` and save it. .. TODO Include file in template with placeholder for component logic. @@ -111,8 +110,7 @@ The streaming aspect means that we don't need to reload the page when new messag For each contract in the stream, we destructure the *payload* (the data as opposed to metadata like the contract ID) into the ``{sender, receiver, content}`` object pattern. Then we construct a ``ListItem`` UI element with the details of the message. -There is one important point about privacy here. -No matter how we write our ``Message`` query in the UI code, it is impossible to break the privacy rules given by the Daml model. +An important point about privacy: no matter how we write our ``Message`` query in the UI code, it is impossible to break the privacy rules given by the Daml model. That is, it is impossible to see a ``Message`` contract of which you are not the ``sender`` or the ``receiver`` (the only parties that can observe the contract). This is a major benefit of writing apps on Daml: the burden of ensuring privacy and authorization is confined to the Daml model. @@ -120,7 +118,7 @@ MessageEdit Component --------------------- Next we need the ``MessageEdit`` component to compose and send messages to our followers. -Again we show the entire component here; you should copy this into a new ``MessageEdit.tsx`` file in ``ui/src/components`` and save it. +Again we show the entire component here; copy this into a new ``MessageEdit.tsx`` file in ``ui/src/components`` and save it. .. TODO Include file in template with placeholder for component logic. @@ -144,7 +142,7 @@ The result of a successful call to ``submitMessage`` is a new ``Message`` contra The return value of this component is the React ``Form`` element. This contains a dropdown menu to select a receiver from the ``followers``, a text field for the message content, and a *Send* button which triggers ``submitMessage``. -There is again an important point here, in this case about how *authorization* is enforced. +Note how *authorization* is enforced here. Due to the logic of the ``SendMessage`` choice, it is impossible to send a message to a user who is not following us (even if you could somehow access their ``User`` contract). The assertion that ``elem sender following`` in ``SendMessage`` ensures this: no mistake or malice by the UI programmer could breach this. @@ -161,24 +159,24 @@ Open the ``ui/src/components/MainView.tsx`` file and start by adding imports for :end-before: // IMPORTS_END Next, find where the *Network* ``Segment`` closes, towards the end of the component. -This is where we'll add a new ``Segment`` for *Messages*. Make sure you've saved the file after copying the code. +This is where we'll add a new ``Segment`` for *Messages*. Make sure you save the file after copying over the code. .. literalinclude:: code/templates-tarball/create-daml-app/ui/src/components/MainView.tsx :language: tsx :start-after: {/* MESSAGES_SEGMENT_BEGIN */} :end-before: {/* MESSAGES_SEGMENT_END */} -You can see we simply follow the formatting of the previous panels and include the new messaging components: ``MessageEdit`` supplied with the usernames of all visible parties as props, and ``MessageList`` to display all messages. +Following the formatting of the previous panels, we include the new messaging components: ``MessageEdit`` supplied with the usernames of all visible parties as props, and ``MessageList`` to display all messages. That is all for the implementation! Let's give the new functionality a spin. -Running the updated UI +Running the Updated UI ====================== -If you have the frontend UI up and running you're all set. In case you don't have the UI running open a new terminal window and navigate to the ``create-daml-app/ui`` folder and run the ``npm start`` command, which will start the UI. +If you have the frontend UI up and running you're all set. If you don't have the UI running, open a new terminal window and navigate to the ``create-daml-app/ui`` folder, then run the ``npm start`` command to start the UI. -Once you've done all these changes you should see the same login page as before at http://localhost:3000. +You should see the same login page as before at http://localhost:3000. .. figure:: images/create-daml-app-login-screen.png :scale: 50 % @@ -190,15 +188,15 @@ Once you've logged in, you'll see a familiar UI but with our new *Messages* pane .. figure:: images/create-daml-app-messaging-feature.png :alt: You can now see the messaging feature in the create-daml-app -Go ahead and add follow more users, and log in as some of those users in separate browser windows to follow yourself back. -Then, if you click on the dropdown menu in the *Messages* panel, you'll be able to see some followers to message! +Go ahead and follow more users, and log in as some of those users in separate browser windows to follow yourself back. +Then click on the dropdown menu in the *Messages* panel to see a choice of followers to message! .. figure:: images/create-daml-app-messaging-select-user.png :scale: 50 % :alt: Select a follower from a dropdown list in the create-daml-app Send some messages between users and make sure you can see each one from the other side. -You'll notice that new messages appear in the UI as soon as they are sent (due to the *streaming* React hooks). +Notice that each new message appears in the UI as soon as it is sent (due to the *streaming* React hooks). .. figure:: images/create-daml-app-message-received.png :scale: 50 %