How to build a Web App using Blockchain — Part 2
In the previous article, we saw together what we are going to build, why we want to use the Blockchain and how we plan to do it. Then we prepared all our development environment and routes as well as empty views. We are now ready to build our Web App content! If you didn’t read the part 1, please start there.
PART 1
a) Define the project
b) Why use Blockchain?
c) Initiate the project
PART 2
d) Create the HTML for your INDEX views
e) Create a GetData and Settings Classes
f) Create the Index javascript logics
PART 3
g) Create the HTML for your ADMIN views
h) Create the Admin javascript logic
i) Integrate Waves Signer
PART 4
j) Create the Smart Contract
k) Deploy the Smart Contract
l) Conclustion
D) CREATE THE INDEX VIEW
To get the step 2 code click here.
To get the complete web app code click here.
Let’s start with the views, remember we already defined ours routes for index and admin, we now needs to builds these templates, lets start with index.ejs.
What do we needs and how i structured it:
Edit button
This button is a link to the admin page, anyone can go there and connect with his own Waves account, he then can start add data.
Remember, the web app is deployed with a settings.js file (that we will create later) so the root url of the Web App will only show data based on the account defined in this settings file but anyone can have his own page simply by adding his account address (the one he used to add data in the admin page) after the root url.
Title
The title for the displayed page, this is administrable in the admin page, it can be the name of an university, a city, an hospital or anything to identify the data source.
Description
Here you can describe the data, for example “Welcome to the COVID19 Tracking Data page of the XXXX City”
Graph
A graph displaying the number of cases by day, this is to give a visual about the situation, to see quickly if it’s going up or down.
Filters
You can filter every columns of the table to group the data according to your own criterias
Widgets
Four separated widgets will display the counts of Total, Confirmed, Recovered and Deceased Cases, each identified with a different color.
Data in a sortable table
Pretty self explanatory, this will display all the data and allow you to sort them on each columns.
Pagination options
Basic pagination options.
Links
Here will be displayed the address of the dApp account, which is where the displayed data are stored as well as the owner account address, which is the address of the account that is managing these data.
THE CSS
To keep this tutorial “short”, i wont spend any time on the css part, just open the style.css file in ./public/stylesheets/ and add the content from this file.
THE INDEX HTML
https://github.com/christopheSeeka/covstats-tuto/blob/step2/views/index.ejs
We include in this page several libraries needed for the different displays such as dataTable, CanvasJs, Jquery, Bootstrap and our fonts from google.
Check the <head> section of the index file to see these changes:
Then we strucure the <body> part with 4 container:
You will find at lines:
- 21: the edit button, the title and and the description, these data will be retrieved from the blockchain API
- 30: the widgets, this include a <div id=”chartContainer”> element, this is empty and will receive the chart dynamically created later based on the dApp Storage data.
- 64: the table that will contain all the data, the tbody of the table is empty and will be populated later with dynamic data from the Blockchain Data Storage through Node API calls.
- 89: the footer that will contain our links, some link will be added dynamically later.
Get the code here and use it as replacement for the ./views/index.ejs file
Also create a canvasjs.min.js into ./public/javascripts/ and add in it the content from this file.
Our index view is now ready to receive data, before moving to the associated javascript logics, we will create 2 simple classes to simplify our work.
E) GETDATA & SETTINGS CLASSES
Here we will create two classes to simplify the Web App configuration and the get requests on the Node API.
THE SETTINGS CLASS
https://github.com/christopheSeeka/covstats-tuto/blob/step2/settings.js
To allow easy configuration of the Web App, i made a settings.js file at the root of the project, this file will be imported in our getData class and used in the different javascript logics later.
First create a new file named settings.js at the root folder and add the following:
This class allow us to define the following:
- this.network is the network we want to use, ether “T” for Testnet, “W” for Mainnet or “S” for Stagenet.
- this.nodeURL is the Node API URL for our get request on the data storage.
- this.providerUrl is the url of the Waves Signer provider we want to use, here is waves.exchange, which is where your account will be manageable.
- this.userAddress is the address of the account managing the main data (the one displayed on the root url). Leave it by default for now.
- this.dappAddress is the address of the dApp account where the data are validated and stored. Leave by default for now.
Then we have a getter to easily get these data from anywhere.
THE GETDATA CLASS
https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/getData.js
To easily get our data i created another small class that will do get requests to the Node API everytime we needs data.
Create a file named getData in ./src/getData.js and add the following content from this file:
Here we import the settings file we just created earlier and initiate it in a “config” variable. Then we start writting the class, in the constructor, we match the fields based on the settings file using the getter (config.get())
There is also an “explorerSegment” field we didn’t mention yet, you will see that later.
Then we have a conditional block that will check if we have a Waves address as url segment (well, it check if there is something, we could add a isAddress verification method later as improvement), if we do, then we use this as userAddress to get the data, if not, we use the userAddress defined in our settings
Remember, if you access the root url of the webapp, it use the userAddress you defined in setting, if we access the url/address then it use this address from the url segment.
Finally we have the async method that will call the node API with a simple fetch get request using the node url we defined in our settings.js (https://nodes-testnet.wavesnodes.com). To this nodeUrl we attach the path of the end point we needs (see the node api end points list here) and the dappAddress then we use the “ match” method with the key we are looking for, exemple:
Note the (.*) at the end here, which mean anything after our string is allowed.
F) THE INDEX JAVASCRIPT LOGIC
https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/main.js
Now we needs to write our javascript logics that will basically retrieve our data from the dApp Data Storage and do all the data processing, for that we will use our getData class.
We will then inject all these data into our index html.
Remember to start your watchers if they are not active from last part, open a first terminal and run:
npm run watch
and a second one where you type:
nodemon
First of all, there is one more plugin we needs to add and its sanitize-html, we want clean up all string from any possible javascript code to avoid XSS attacks, at least for the front end display. If you use public data from Blockchain i would recommand to always sanitize it before displaying.
Open a 3rd terminal and run the following command:
npm install sanitize-html
Now, go to ./src/main.js and copy the code from this file into your file, remember ./src/main.js is the file compiled into ./public/javascripts/bundle-main.js which is then included at the bottom of our index.ejs.
The code is a bit long so i wont go in detail over everything but i commented the key points:
What are we doing hre:
So, first we import sanitize-html and our getData class so we can use the getDataByKey method.
We then declare some variable and start retrieving our data, example:
Here we pass the {userAddress}_name as parameter of getDataByKey, this is the key we are looking for in the data storage of the dApp, it will give us the name/title of the page, we then inject it into the html <h1 id=”title”>.
We do the same for description, with the key {userAddress}_description and inject the result into the <p id=”introtop”>.
After that we see two functions, initTable() and initChart(), i wont go into details as it would be very long but in short, they get the data from the view and will filter, sort and organize all of them as needed.
But before that, we needs to retrieve and process all the data from the data storage and add them to the view, which is what next code do with another getDataByKey call.
You see here that we use the key {userAddress}_counterNum, this is because each account using the dApp storage will have an auto incrementing “counter” that will serve as identifiant for new entry. So we do a call on this key, if there is no result for {userAddress}_counterNum that mean no data, else, there is data and we start processing them, generating each lines of our table and add it to the view. Then we populate our different counting widgets, our footer urls (this is where we use the explorerSegment because depending of the network we use, it would change) and finally we call our initTable().
InitTable() will initiate the dataTable plugin and if all go well, end by calling the initChart plugin, from there canvasJs will do his job to generate our chart and inject it into the <div id=”chartContainer“> element.
If you go to localhost:3000 you will see the same page as https://covtest.sign-web.app/, for now it is using the default userAddress and dappAddress, later on you will use your own.
And that’s it for the index!!
Was a bit of a work! but remember, i said it will be “quite easy”, easy is not necessary short :) Here we are building a complete, working Blockchain Web App from scratch so it require a bit of work of course.
In the STEP 3 we will work on the ADMIN page and implement Waves Signer! Stay tuned and if any question, comment or message me.
The STEP 2 code:
https://github.com/christopheSeeka/covstats-tuto/tree/step2
The complete web app code:
https://github.com/christopheSeeka/cov-stats
The webapp example on TESTNET:
https://covtest.sign-web.app/
The webapp on MAINNET:
https://cov-stats.sign-web.app/