Browse Source

Closes #381

Signed-off-by: Mary Anthony <mary@blockstack.com>
feat/clarity-updates
Mary Anthony 6 years ago
parent
commit
706a898612
  1. BIN
      _browser/images/todo-app.png
  2. BIN
      _browser/images/todo-sign-in.png
  3. 221
      _browser/todo-list.md

BIN
_browser/images/todo-app.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 39 KiB

BIN
_browser/images/todo-sign-in.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 41 KiB

221
_browser/todo-list.md

@ -7,9 +7,9 @@ permalink: /:collection/:path.html
{:.no_toc}
In this tutorial, you build the code for and run a single-page application (SPA)
with Blockstack and Vue.js. Once the application is running, you take a tour
with Blockstack and React. Once the application is running, you take a tour
through the applications’ Blockstack functionality. You’ll learn how it manages
authentiation using a Blockstack ID and how it stores information associated
authentcation using a Blockstack ID and how it stores information associated
with that ID using Blockstack Storage (Gaia).
* TOC
@ -17,11 +17,9 @@ with that ID using Blockstack Storage (Gaia).
{% include note.html content="On macOS, Blockstack requires macOS High Sierra. This tutorial was written on macOS High Sierra 10.13.4. If you use a Windows or Linux system, you can still follow along. However, you will need to \"translate\" appropriately for your operating system. Additionally, this tutorial assumes you are accessing the Blockstack Browser web application via Chrome. The application you build will also work with a local installation and/or with browsers other than Chrome. " %}
If you prefer a video, you can view <a href="https://www.youtube.com/embed/oyvg-h0obFw" target="\_blank">a video of the tutorial</a>.
## Before you begin
The application you build is a Vue.js application that is completely decentralized and server-less. While not strictly required to follow along, basic familiarity with Vue.js is helpful. When complete, the app is capable of the following:
The application you build is a React application that is completely decentralized and server-less. While not strictly required to follow along, basic familiarity with React is helpful. When complete, the app is capable of the following:
* authenticating users using Blockstack
* posting new statuses
@ -31,20 +29,10 @@ The application you build is a Vue.js application that is completely decentraliz
For this tutorial, you will use the following tools:
* your workstation's command line
* `git` to clone the tutorial code
* `npm` to manage dependencies and scripts
The basic identity and storage services are provided by blockstack.js. To test the application, you need to have already registered a Blockstack ID.
### Verify you have git installed
This tutorial uses `git` to clone the tutorial code. Verify you have installed `git` using the `which` command to verify.
```bash
$ which git
/usr/local/bin/npm
```
### Verify you have npm installed
The tutorial relies on the `npm` dependency manager. Before you begin, verify you have installed `npm` using the `which` command to verify.
@ -53,6 +41,7 @@ The tutorial relies on the `npm` dependency manager. Before you begin, verify yo
$ which npm
/usr/local/bin/npm
```
If you don’t find `npm` in your system, [install it](https://www.npmjs.com/get-npm).
### Make sure you have a Blockstack ID
@ -62,10 +51,7 @@ You’ll use this ID to interact with the application.
## Task 1: Install the code and retrieve the dependencies
You can clone the source code with `git` or [download and unzip the code from
the
repository](https://github.com/blockstack/blockstack-todos/archive/master.zip).
These instructions assume you are cloning.
You can clone the source code with `git` or [download and unzip the code from the repository](https://github.com/blockstack/blockstack-todos/archive/master.zip). These instructions assume you are cloning.
1. Install the code by cloning it.
@ -80,6 +66,9 @@ These instructions assume you are cloning.
$ cd blockstack-todos
```
If you downloaded the zip file, the contents unzip into a `blockstack-todos-master` directory.
3. Use `npm` to install the dependencies.
@ -87,15 +76,14 @@ These instructions assume you are cloning.
$ npm install
```
The Todo application has a basic Vue.js structure. There are several configuration files but the central programming files are in the `src` directory:
The Todo application has a basic React structure. There are several configuration files but the central programming files are in the `src/components` directory:
| File | Description |
|-----------------|-------------|
| `main.js` | Application initialization. |
| `App.vue ` | Code for handling the `authResponse`. |
| `components/Landing.vue ` | Code for the initial sign on page. |
| `components/Dashboard.vue` | Application data storage and user sign out. |
| `index.js` | Application initialization. |
| `components/App.js ` | Code for handling the `authResponse`. |
| `components/Signin.js ` | Code for the initial sign on page. |
| `components/Profile.js` | Application data storage and user sign out. |
## Task 2: Sign into the application
@ -113,22 +101,23 @@ The example application runs in a node server on your local host. In the this se
2. Start the application in your local environment.
```bash
$ npm run serve
$ npm start
```
You should see output similar to the following:
You should see output similar to the following:
```bash
98% after emitting CopyPlugin s
DONE Compiled successfully in 5854ms 7:34:28 PM
```bash
Compiled successfully!
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.0.12:8080/
You can now view bs-todo in the browser.
http://127.0.0.1:3000/
Note that the development build is not optimized.
To create a production build, run npm run build.
```
2. Open your local browser to the `http://localhost:8080` URL.
To create a production build, use npm run build.
```
2. Open your local browser to the `http://localhost:3000` URL.
You should see a simple application:
@ -193,45 +182,50 @@ in and sign out is handled in each of these files:
| File | Description |
|-----------------|-------------|
| `App.vue ` | Handles the `authResponse`. |
| `Landing.vue ` | Generates the `authRequest`. |
| `Dashboard.vue` | Handles sign out. |
| `components/App.js ` | Code for handling the `authResponse`. |
| `components/Signin.js ` | Code for the initial sign on page. |
| `components/Profile.js` | Application data storage and user sign out. |
The `src/components/Landing.vue` code configures an `AppConfig` object and then uses this to create a `UserSession`. Then, the application calls a [`redirectToSignIn()`](https://blockstack.github.io/blockstack.js#redirectToSignIn) function which generates the `authRequest` and redirects the user to the Blockstack authenticator:
The `src/components/App.js` code configures an `AppConfig` object and then uses this to create a `UserSession`. Then, the application calls a [`redirectToSignIn()`](https://blockstack.github.io/blockstack.js#redirectToSignIn) function which generates the `authRequest` and redirects the user to the Blockstack authenticator:
```js
signIn () {
const appConfig = new this.blockstack.AppConfig(['store_write', 'publish_data'])
const UserSession = new this.blockstack.UserSession({ appConfig: appConfig })
UserSession.redirectToSignIn()
}
...
const userSession = new UserSession({ appConfig })
export default class App extends Component {
handleSignIn(e) {
e.preventDefault();
userSession.redirectToSignIn();
}
...
```
Once the user authenticates, the application handles the `authResponse` in the `src/App.vue` file. :
Once the user authenticates, the application handles the `authResponse` in the `src/components/Profile.js` file. :
```js
mounted () {
const UserSession = this.UserSession
if (UserSession.isUserSignedIn()) {
this.userData = UserSession.loadUserData()
this.user = new this.blockstack.Person(this.userData.profile)
this.user.username = this.userData.username
} else if (UserSession.isSignInPending()) {
UserSession.handlePendingSignIn()
.then((userData) => {
window.location = window.location.origin
})
...
componentWillMount() {
if (userSession.isSignInPending()) {
userSession.handlePendingSignIn().then((userData) => {
//if (!userData.username) {
// throw new Error('This app requires a username.')
//}
window.location = window.location.origin;
});
}
},
}
...
```
If [`blockstack.isUserSignedIn()`](https://blockstack.github.io/blockstack.js/#isusersignedin) is true, the user was previously signed in so Blockstack pulls the data from the browser and uses it in our application. If the check on [`blockstack.UserSession.isSignInPending()`](https://blockstack.github.io/blockstack.js/#issigninpending) is true, a previous `authResponse` was sent to the application but hasn't been processed yet. The `handlePendingSignIn()` function processes any pending sign in.
If [`isUserSignedIn()`](https://blockstack.github.io/blockstack.js/#isusersignedin) is true, the user was previously signed in so Blockstack pulls the data from the browser and uses it in our application. If the check on [`UserSession.isSignInPending()`](https://blockstack.github.io/blockstack.js/#issigninpending) is true, a previous `authResponse` was sent to the application but hasn't been processed yet. The `handlePendingSignIn()` function processes any pending sign in.
Signout is handled in `src/components/Dashboard.vue`.
Signout is handled in `src/components/App.js`.
```js
signOut () {
this.UserSession.signUserOut(window.location.href)
handleSignOut(e) {
e.preventDefault();
userSession.signUserOut(window.location.origin);
}
```
@ -245,101 +239,38 @@ Now, trying adding a few items to the todo list. For example, try making a list
![](images/make-a-list.png)
Each list is immediately stored in the Gaia Hub linked to your Blockstack ID.
For more information about the Gaia hub, [see the overview in this documentation]({{ site.baseurl }}/storage/overview.html#). You can fetch the `todos.json`
file you just added by opening the Javascript console and running the following
command:
```Javascript
userSession.getFile("todos.json", { decrypt: true }).then((file) => {console.log(file)})
```
You should see a JSON with the todos you just added:
```json
[
{
"id":2,
"text":"Software package manager secured by the blockchain",
"completed":false
},
{
"id":1,
"text":"Mutable torrents with human readable names",
"completed":false
},
{
"id":0,
"text":"Decentralized twitter",
"completed":false
}
]
```
Add another todo and check it off. When you fetch the newly generated file
using the Javascript console, the results reflect your change. Look for `"completed":true`:
```json
[
{
"id":3,
"text":"Blockstack Todo",
"completed":true
},
{
"id":2,
"text":"Software package manager secured by the blockchain",
"completed":false
},
...
]
```
Now that you have seen the application in action, dig into how it works.
For more information about the Gaia hub, [see the overview in this documentation]({{ site.baseurl }}/storage/overview.html#). Now that you have seen the application in action, dig into how it works.
## Task 7: Implement storage
Go to the underlying `blockstack-todo` code you cloned or downloaded. The
application interactions with your Gaia Hub originate in the
`src/components/Dashboard.vue` file. First, examine where the changes to the
Todos are processed:
Go to the underlying `blockstack-todo` code you cloned or downloaded. The application interactions with your Gaia Hub originate in the `src/components/Profile.js` file. First, examine where the changes to the Todos are processed in the `Profile.js` file.
The code needs to read the Todo items from the storage with the [`getFile()`](https://blockstack.github.io/blockstack.js/#getfile) method which returns a promise:
```js
watch: {
todos: {
handler: function (todos) {
const UserSession = this.UserSession
return UserSession.putFile(STORAGE_FILE, JSON.stringify(todos))
},
deep: true
}
},
loadTasks() {
const options = { decrypt: true };
this.props.userSession.getFile(TASKS_FILENAME, options)
.then((content) => {
if(content) {
const tasks = JSON.parse(content);
this.setState({tasks});
}
})
}
```
The `todos` data is retrieved from the promise. By default, the `getFile()` decrypts data for you. For more information on the available options, see the <a href="https://blockstack.github.io/blockstack.js/interfaces/getfileoptions.html" taraget="_blank">the blockstack.js</a> library for details on the `GetFileOptions` interface.
The `todos` JSON object is passed in and the
[`blockstack.UserSession.putFile()`](https://blockstack.github.io/blockstack.js/#putfile)
method to store it in a Gaia Hub. By default, `putFile()` encrypts data when it stores it.
The code needs to read the Todo items from the storage with the [`blockstack.UserSession.getFile()`](https://blockstack.github.io/blockstack.js/#getfile) method which returns a promise:
During the creation of a `todos`, a JSON object is passed in and the [`putFile()`](https://blockstack.github.io/blockstack.js/#putfile) method to store it in a Gaia Hub. By default, `putFile()` encrypts data when it stores it.
```js
fetchData () {
const UserSession = this.UserSession
UserSession.getFile(STORAGE_FILE)
.then((todosText) => {
var todos = JSON.parse(todosText || '[]')
todos.forEach(function (todo, index) {
todo.id = index
})
this.uidCount = todos.length
this.todos = todos
})
},
saveTasks(tasks) {
const options = { encrypt: true };
this.props.userSession.putFile(TASKS_FILENAME, JSON.stringify(tasks), options);
}
```
The `todos` data is retrieved from the promise. By default, the `getFile()` decrypts data for you. For more information on the available options, see the <a href="https://blockstack.github.io/blockstack.js/interfaces/getfileoptions.html" taraget="_blank">the blockstack.js</a> library for details on the `GetFileOptions` interface.
## Summary
{:.no_toc}

Loading…
Cancel
Save