(Part 8) Steem JavaScript API Tutorial - User Page, Reputation and User Posts pt8

in #utopian-io6 years ago

Repository

https://github.com/igormuba/Steem-Feed-Example-/tree/AuthorPage

What Will I Learn?

  • Create a new JavaScript reactive page (no need to reload)
  • Load the user profile
  • Calculate the user reputation
  • Append child divs inside the shadow element

Requirements

  • Internet connection
  • Code editor
  • Browser
  • Reading the previous classes on making a Steem Feed is recommended but not necessary

Difficulty

  • Advanced

Tutorial Contents

For the first time I think it is time to classify my tutorial as "advanced", I will try to cover everything is the most beginner friendly way I can, but building reactive pages without a reactive library (like react JS) can become messy, but I think it is a important path to take so you can have a true understanding on how the reactive page works without having to reload anything, users hate reloading pages

Our new JS file

On a reactive page the JavaScript create the HTML page, so everything is dinamically displayed or hidden as the user interacts with the application without having to reload anything.
So, to create the profile page, instead of creating a profile.html like we used to do for other pages, we will create a profile.js instead, because this is the Javascript that will generate the HTML page.

So, inside the JS directory of our project, create a file profile.js

And do not forget to import the new JavaScript inside our only HTML page, the index.html

<script src="js/profile.js"></script>
<script src="js/myscript.js"></script>

Small changes on the myscript.js

Think for a moment about what do we need to do to send the author information from the index page to the profile page. What do you think?
We need to pass the author name, right?
So, we could do this using global variables, but it is better to avoid those, we could also use the cookies, but that is unnecessary.

The solution I have applied is to call from the myscript.js a function from the profile.js, you are free and I incentivize you to try other solutions, maybe using the cookies, so you get hands on practice :)

So, I am gonna put an anchor tag around the author name from the post, and this anchor tag is gonna call a function that is to be defined inside the profile.js

<a href="javascript:;" onclick="loadProfile('`+result[i].author+`')">by: @`+result[i].author+`</a>

So, the h2 with the author name looks like this

<h2 class="post-author"><em><a href="javascript:;" onclick="loadProfile('`+result[i].author+`')">by: @`+result[i].author+`</a></em></h2>

The href="javascript:;" onclick="loadprofile" means that we want this to be a link that actually calls a JavaScript function instead of a new page, and as an argument for that function we pass the author name.
If you didn't follow the past 2 tutorials I highly recommend you to do so to understand what are we doing, the list of all the classes are on the bottom of this post.

The loadProfile function from profile.js

On the profile.js we already have an idea of what argument will it receive, so we can already define

loadProfile(author){

}

As I have said, we are going to use the same page, so it is better to clean everything before proceeding, right?
on the first line of the function above, call a function that we will define later called clearPosts() to clear all the divs from the page so we can change their content.

loadProfile(author){
clearPosts();
}

Cleaning the posts

Now, to clean the posts it is relatively easy, just do

function clearPosts(){
    for (let i = 1; i<=3;i++){ 
        document.getElementById(i).innerHTML="";
    }
}

So it will iterate through every div and clean the content.

Getting the author data

We have used this function in previous classes but for other purposes, here we will use this to get the user reputation.

Inside the loadProfile do

steem.api.getAccounts([author], function(err, result) {
console.log(err, result);

}

This will load all the information from the author account and print on the console so we can know what do we want

In this case, we want result[0].name and result[0].reputation

We will fill the first div with this information so it looks dettached from the posts we will put below, let us fill the sahdow element with the information

But you may notice that this gets the raw reputation from the user, we want to show the reputation level, which is the number we are used to see on Steemit and other interfaces

You can read more about the Steem reputation at
https://www.steem.center/index.php?title=Reputation_System

Sadly, on that post they teach how to calculate the reputation using pure Ruby
But I have found a very interesting post by @pilcrow on how to calculate it using JavaScript!
Check his post here
https://steemit.com/steemdev/@pilcrow/calculating-a-user-s-steemit-reputation-score-in-javascript-bonus-content-an-angular-pipe-that-does-it-for-you

The function he uses is

function simplifyReputation(raw) {
    const isNegative = (raw < 0);
    let reputation = Math.log10(Math.abs(raw));

    reputation = Math.max(reputation - 9, 0);
    reputation *= isNegative ? -9 : 9;
    reputation += 25;

    return Math.floor(reputation);
}

And this is the one we are going to use to translate the raw reputation into the reputation level

document.getElementById(1).innerHTML=`
        <hr class="horizontal-ruler">
        <h1>@`+result[0].name+`</h1>
        <p>Reputation Level: `+simplifyReputation(result[0].reputation)+`</p>
        <hr class="horizontal-ruler">
        `;

The above reactive element manipulation is very similar to the one we did to load the feed posts

And this is the result we get

Getting the posts from the user

The loadProfile function is the main one, so we will call the function that fills the posts inside this one

function loadProfile(author){
    clearPosts();
    steem.api.getAccounts([author], function(err, result) {
        console.log(err, result);
        document.getElementById(1).innerHTML=`
        <hr class="horizontal-ruler">
        <h1>@`+result[0].name+`</h1>
        <p>Reputation Level: `+simplifyReputation(result[0].reputation)+`</p>
        <hr class="horizontal-ruler">
        `;
    });
    
    getUserFeed(author); //we pass the author so it knows it since we have cleaned the divs
}

Now we must define the getUserFeedand we know it will receive the name of the user.
The way we will do it is very similar to how we got the posts from the feed of the user, but instead of steem.api.getDiscussionsByFeed we will use steem.api.getDiscussionsByAuthorBeforeDate
And we this time create new divs and insert them inside the h2 div!

so, outside of the function, we will create a variable to host the posts from the user

let userPosts;

And inside the function we call the Steem function

steem.api.getDiscussionsByAuthorBeforeDate

According to the Steem JS documentation this function needs the following arguments

You can read more about the documentation at
https://github.com/steemit/steem-js/tree/master/doc

So we will pass

(user, "", '2019-05-01T00:00:00', 4, function (err, result)

So far it looks like

 steem.api.getDiscussionsByAuthorBeforeDate(user, "", '2019-05-01T00:00:00', 4, function (err, result) {
        console.log(err, result);
        userPosts=result; //this stores the posts from the author
}

Now, we copy the technique we have used to fill in the feed but we give it some tweaks, I will first show how it looks then explain what is changed and why

let userPosts;
function getUserFeed(user){

    steem.api.getDiscussionsByAuthorBeforeDate(user, "", '2019-05-01T00:00:00', 4, function (err, result) {
        console.log(err, result);
        userPosts=result;
        for (let i=0; i<3; i++) {
            let iToString = (i+1).toString();
            let converter = new showdown.Converter()
            let text = result[i].body
            let html = converter.makeHtml(text);
// until now nothing changed from the feed
            
            let newDiv = document.createElement("div"); //created a new div
            
            newDiv.innerHTML = `
            <hr class="horizontal-ruler">
            <h1>`+result[i].title+`</h1>
            <h2 class="post-author"><em><a href="javascript:;" onclick="loadProfile('`+result[i].author+`')">by: @`+result[i].author+`</a></em></h2>
            <hr class="horizontal-ruler">
            <p>`+html+`</p>
            <hr class="horizontal-ruler">
            `; //sets the contents of the div

            document.getElementById(2).appendChild(newDiv); //adds the created div inside the div 2!
        }
    });
}

We won't use the div 3, so,above we are doing the same as the feed, but we are getting the posts from the user, not from his feed, and iterating through them all and adding them inside the div 2, instead of replacing divs by them!
the let newDiv = document.createElement("div") created a logical div but does not put it anywhere
The newDiv.innerHTML = tells what is the content from the div, it is the exact same as from the feed as the format is the same

Now the big change is document.getElementById(2).appendChild(newDiv);, instead of replacing the HTML content from the div it adds content, so we can append the posts from the user in here using this.

How it looks like

In the end it will look very much like a real Steem interface, we have in this project the feed and when we click on the author we load his posts

Curriculum

Include a list of related tutorials you have already shared on Utopian that make up a Course Curriculum, if applicable.

I AM A STEEM WITNESS

To vote for me, simply use the SteemConnect link below
https://steemconnect.com/sign/account-witness-vote?witness=igormuba&approve=1

or go to https://steemit.com/~witnesses

(note, it is /~witnesses, not /witness)
Scroll all the way down to "If you would like to vote for a witness outside of the top 100, enter the account name below to cast a vote."

type igormuba and click vote

Sort:  

Thank you for your contribution @igormuba.
After analyzing your tutorial we suggest the following points listed below:

  • We suggest that this tutorial has the difficulty level as basic. The features that you explain in your tutorial are not complex to implement.

  • Put more comments in the code sections. Comments are very important in the code and help less experienced users understand what they are developing.

Good work on the development of this tutorial, we hope for more tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thank you for your review, @portugalcoin! Keep up the good work!

Hi @igormuba!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Very useful! Thank you so much !

Posted using Partiko Android

Hi, @igormuba!

You just got a 0.38% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Hey, @igormuba!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.030
BTC 66709.93
ETH 3505.67
USDT 1.00
SBD 2.71