[KnackSteem] - Comments, Upvote, Delete, Refactor-Fun
utopian-io·@luschn·
0.000 HBD[KnackSteem] - Comments, Upvote, Delete, Refactor-Fun
The new PR is about showing comments correctly, being able to upvote and delete comments and a lot of other things. This PR includes some refactoring, which is the base for the upcoming edit and reply functionality. ## Repository & Pull Request https://github.com/knacksteem/knacksteem.org https://github.com/knacksteem/knacksteem.org/pull/10 ## 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 upvote function with Steem Connect. * Implement delete function with Steem Connect. * Show links for reply/edit/delete conditionally. * Show filled upvote icon if upvoted by yourself. * Show correct number of comments and upvotes. * Make comments visible in the article detail page. * Show payout value on all articles and comments. * Switch from HTML preview to Markdown preview with ReactMarkdown. * Delete function for unvoted/uncommented posts. * Refactor Editor to be a separate component. * Lots of bugfixes and refactors. Edit and reply are not fully implemented yet. There is an edit action already, but I am waiting for the backend to provide an edit route. I believe it´s being implemented as we speak though :) ## Screenshots ### Article List  ### Article Detail  ## Details The new Editor component can now be used anywhere, before it was implemented directly in the route for new contributions. That route is just a stateless function with a few lines now: ``` /** * Route for adding a new article/contribution with rich text editor */ const NewContribution = () => { return ( <div className="editor"> <Content> <Editor isComment={false} isEdit={false} /> </Content> </div> ); }; ``` (containers/NewContribution/index.js) The component needs those props in order to show tags (there are no tags for comments) and to know if the article is a new one or if the Editor needs to be prefilled for updating. We could omit the props for new contributions because they are set to their defaults, but it´s good to set them anyway: ``` Editor.propTypes = { dispatch: PropTypes.func, articles: PropTypes.object, isComment: PropTypes.bool, isEdit: PropTypes.bool, articleData: PropTypes.object }; Editor.defaultProps = { isComment: false, isEdit: false }; ``` (components/Editor/index.js) Comments needed to be loaded recursively, this was solved with two React components. One for holding the comments in general, it´s a simple stateless function again: ``` const Comments = ({data, onUpvoteSuccess}) => { return ( <div> {data.map((elem) => { return ( <SingleComment key={elem.permlink} data={elem} onUpvoteSuccess={onUpvoteSuccess} /> ); })} </div> ); }; ``` (components/Comments/index.js) The second component is more interesting, it holds one single comment and all its replies - replies are using the exact same component again, and so on. ``` class SingleComment extends React.Component { constructor(props) { super(props); this.state = { isEditMode: false }; } render() { const {data, onUpvoteSuccess} = this.props; return ( <div className="ant-list-item comment"> <div> <Avatar src={data.authorImage} className="comment-avatar" /> <span>{data.author} ({data.authorReputation})</span> <ReactMarkdown source={data.description} /> <ArticleMetaBottom data={data} onUpdate={onUpvoteSuccess} isComment /> </div> <div className="replies"> {data.replies.map((elem) => { return ( <SingleComment key={elem.permlink} data={elem} isReply onUpvoteSuccess={onUpvoteSuccess} /> ); })} </div> </div> ); } } ``` (components/Comments/SingleComment.js) As you can see, there is a state variable called "isEditMode", it will later be used to show the new Editor component. The "isReply" prop is not in use right now. Maybe we need to know if it´s a reply comment or a direct comment of the parent article sooner or later, who knows. Deleting and upvoting is done with a redux action, both actions return a promise so we can react when they are finished. We don´t need to use the backend for this, it´s all just Steem Connect. Deleting was a bit tricky, because there does not seem to be a delete API. No problem with the broadcast API though: ``` /** * delete article or comment * @param permlink permalink of the article of comment */ export const deleteElement = (permlink) => { return async (dispatch, getState) => { const store = getState(); let api = sc2.Initialize({ app: 'knacksteem.app', callbackURL: Config.SteemConnect.callbackURL, accessToken: store.user.accessToken, scope: Config.SteemConnect.scope }); //use broadcast operation to delete comment return await api.broadcast([ ['delete_comment', { 'author': store.user.username, 'permlink': permlink }] ]); }; }; ``` (actions/articles.js) Voting is easier, and right now we just upvote with 100% weight - there are plans to implement something cool for the weight selection :) ``` /** * upvote article or comment * @param author author of the article or comment * @param permlink permalink of the article of comment * @param weight weight of the upvote (10000 is 100%) */ export const upvoteElement = (author, permlink, weight) => { return async (dispatch, getState) => { const store = getState(); let api = sc2.Initialize({ app: 'knacksteem.app', callbackURL: Config.SteemConnect.callbackURL, accessToken: store.user.accessToken, scope: Config.SteemConnect.scope }); return await api.vote(store.user.username, author, permlink, weight); }; }; ``` (actions/articles.js) ## Roadmap * Implement reply and edit functionality for comments and articles. * User route/list for moderative actions. * Bugfixing * ... How to contribute? Talk to @knowledges (or me) :) <hr> My GitHub Account: https://github.com/ateufel
👍 retroboy, earnestcar, vladser58, igorik, cupswavy, cootroach, pullsympathize, zoraivanov92, svetlana1, s6476721, karinegevorgyan, poofwalrus, needlesten, berwynelbow, tamilaisaeva, goringdriver, twitterprime, ivankash, gracefulestrogen, artyr.stepnenkov, synclinereeve, arttempavlov, windowsyak, vika09, izydorjasiski, quantushower, ovariangroups, steemitstats, alex20050503, cheekedrad, nikolastelma, ricklargo, vadimstapov, throwjoke, potatovariscan, pumpdyke, quadratour, snoozesalsa, quicktipps, njoy.thejourney, lipraproductions, gamebot, maybelater, needforsteem, berndpfeiffer, taug, backinblackdevil, dimka10, floorsopera, jupiterpipit, referrednut, shortcrustmend, bohrbowling, asamarin88, boriskamiran, loukosporbola, aleister, yuxi, runningproject, run.vince.run, primersion, noproblemjules, backbonewriter, gaws, wigeonfeatures, fleshtestify, greatestspicy, stinkydescribe, grantdearg, bumpyforster, gutalveoli, securelagan, nissla, maxpatternman, annikafried, sciack, statsexpert, jonesnow, greenorange, jjay, doughtaker, louis88, grzesiekb, limesoda, theaustrianguy, liberviarum, thinkingmind, javalord, hafi001, obvious, lulafleur, corazen, lifeofroman, tineschreibt, k3ldo, tonkatonka, knowledges, bearded-benjamin, derbesserwisser, davidmendel, lichtcatchtoby, tobypics, steemitboard, jack.bot, amosbastian, codingdefined, achiron, fuzzythumb, utopian-io, upheaver, moenawar, asianetwork, armageddonparty, yannh, dream.trip, chanych85, thesimpson, freetousesounds, ccoin, techchat, longphibtc11, jnkb07, amikphoto, vgc5000, emmyem84, moneyinfant, guyfawkes, steem-id, mxzn, ediya, motoengineer, sau412,