[KnackSteem] - Edit/Reply for Articles and Comments

in #utopian-io6 years ago

This is the last major update for the article detail page of the upcoming KnackSteem relaunch, it is now fully working with all its features. This PR is about adding edit and reply functions to articles and comments.

Repository & Pull Request

https://github.com/knacksteem/knacksteem.org
https://github.com/knacksteem/knacksteem.org/pull/11

About knacksteem.org

"Do you have any talent? If yes! then KnackSteem is for you."
"Rewards people with talents, it can be any talent, anything you know how to do best is highly welcome on the platform."

Technology Stack

  • JavaScript ES6+ with Babel
  • React + Redux
  • Ant Design

Changes / New Features

  • Implement edit function for articles and comments with Steem Connect.
  • Implement reply to articles/comments function with Steem Connect.
  • Use current origin/protocol/hostname to make sure the project works on the production server.
  • Other/Minor Bugfixes marked with "bugfix: " in the commit history.

Screenshots

Reply Comment

knacksteem-reply-comment.png

Edit Article

knacksteem-edit-article.png

Details

The articles actions for posting end editing articles had to be updated to work with comments and articles:

//post to blockchain
if (isComment) {
  //generate unique permalink for new comment
  const newPermLink = getUniquePermalinkComment(parentPermlink);
  await api.comment(parentAuthor, parentPermlink, store.user.username, newPermLink, '', body, {});
} else {
  //generate unique permalink for new article
  const newPermLink = getUniquePermalink(title);
  await api.comment('', tags[0], store.user.username, newPermLink, title, body, {tags: tags});

  //successfully posted to blockchain, now posting to backend with permalink and category
  await apiPost('/posts/create', {
    author: store.user.username,
    permlink: newPermLink,
    access_token: store.user.accessToken,
    category: tags[1],
    tags: tags
  });
}

(actions/articles.js - postArticle)

The editArticle function is similar, comments do not need call to the backend API of KnackSteem because they only get stored in the blockchain and an API call to the backend gets the comments with SteemConnect - server side.
Side note: Posting and editing comments needs an empty object for the last parameter (JSON Metadata).

The Editor component is in use for new contributions, editing contributions, new comments (replies) and editing comments now. One component to rule them all :)
Several properties have been added to make the component versatile, including some code comments to make it clear what they are being used for. Different functions are being called when the user clicks on the button for posting/updating (it will be a different label depending on the operation). And if there is a callback function (as React prop), it will get called right after the editing or posting happened:

if (isEdit) {
  await dispatch(editArticle(title, value.toString('markdown'), tags, articleData, isComment, parentPermlink, parentAuthor));
} else {
  await dispatch(postArticle(title, value.toString('markdown'), tags, isComment, parentPermlink, parentAuthor));
}
if (onDone) {
  onDone();
}

(components/Editor/index.js)

Editing and posting are similar to some extend, so we may be able to combine them later. I wanted to keep them separate for now though, just in case there´s more to be added. It is a different operation after all.
Side Note: Parent permalink and author name are always needed for posting and editing comments in the blockchain, so I had to add those as props as well. It could just be included in the comment response of the backend later though, that would reduce some code in the frontend.

Configuration for the SteemConnect callback can be found in the main config file. It depended on the dev/prod flag earlier, this PR changes it to an URL that should always be correct - no matter if it´s the dev build or the prod build:

//general configuration for the app
export default {
  SteemConnect: {
    scope: ['login', 'custom_json', 'claim_reward_balance', 'vote', 'comment', 'delete_comment'],
    callbackURL: `${window.location.origin}/callback`
  }
};

(config.js)

The article detail page and the component for a single comment have new state variables and callback functions for activating the editor for editing and replying:

onEditClick = () => {
  this.setState({
    isEditMode: true
  });
};
onReplyClick = () => {
  this.setState({
    isReplyMode: true
  });
};
onCancelEditorClick = () => {
  this.setState({
    isEditMode: false,
    isReplyMode: false
  });
};
onDoneEditorClick = () => {
  this.setState({
    isEditMode: false,
    isReplyMode: false,
    isLoading: true
  });
  //reload after update
  this.getArticle();
};

(containers/ArticleDetail/index.js)

For example, a click on the reply link only sets the state variable isReplyModeto true. The rest is taken care of by React in the render function with conditional rendering:

{isReplyMode && <Editor isEdit={false} isComment={true} onCancel={this.onCancelEditorClick} onDone={this.onDoneEditorClick} parentPermlink={data.permlink} parentAuthor={data.author} />}

(containers/ArticleDetail/index.js)

Generating the permalink for comments works in a different way, so i had to add a separate function for that. It takes the parent permalink and adds a re- at the beginning and a random string at the end:

//generate unique permalink for comments
export const getUniquePermalinkComment = (permlink) => {
  return `re-${permlink}-${Math.random().toString(36).substr(2, 16)}`;
};

(services/functions.js)

Roadmap

  • User route/list for moderative actions.
  • Bugfixing and UI improvements.
  • ...

How to contribute?

Talk to @knowledges (or me) :)


My GitHub Account: https://github.com/ateufel
Sort:  

Hi there, this is great work! You've detailed your work that's good.

Let's go for the review:

Aside from the use of redux that I find a bit weird your code is great! Good job on this pull request!

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]

Thanx, that is great feedback! About redux action binding: I am actually using your suggestion in another project (with Next.js), so I know exactly what you mean and you are absolutely right. I also like the way how you avoid a separate mapStateToProps function by just putting it in the connect param in your screenshot. Still readable, but more compact.
About awaiting the dispatch: There´s some routing and other stuff involved, so while I agree that actions should handle success responses, in this case it´s a lot easier to just use async/await to wait for the dispatch to return. Although, put that into an action that does the routing or other stuff...will consider that for a refactoring session :)
Again, thanx for the valuable and detailed feedback!

Hey @gregory.latinier
Here's a tip for your valuable feedback! @Utopian-io loves and incentivises informative comments.

Contributing on Utopian
Learn how to contribute on our website.

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

Vote for Utopian Witness!

"comment" nazzi ahhahaahahah

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

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

Vote for Utopian Witness!