Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reactions #10

Closed
wants to merge 25 commits into from
Closed

Add reactions #10

wants to merge 25 commits into from

Conversation

abhiabhi94
Copy link
Collaborator

@abhiabhi94 abhiabhi94 commented May 8, 2020

Add reactions to comments.

Tasks:

  • Add models for Reaction and ReactionInstance
    • Add logic for the models.
  • Make changes in the comments model
    • Add a post_save signal that creates a Reaction instance when a comment is created.
    • Add likes and dislikes count as a property.
  • Add urls and views
    • For django.
    • For REST API.
  • Add template tag to return if the current user has shown a particular reaction(like/dislike) on a particular comment.
  • Fix Frontend
    • Display reaction count on the frontend using icons.
    • Perform Reaction using AJAX request for authenticated users.
    • Redirect unauthenticated users to login page with correct path for the next redirect.
  • Add unit tests for
    • models.
    • views.
    • REST API.
    • template tags.
  • Fix leftovers
    • Add additional tests to increase coverage.

The reaction process currently looks something like this:
comment-reactions

Fixes #8, maybe we can move adding flag to a separate issue.

Make comment models a python package
- make other necessary changes to imports everywhere
- move code for manager to manager module

Add reaction models
- add some general property functions to be useful in future

Reorder some import to conform to PEP8
@abhiabhi94 abhiabhi94 marked this pull request as draft May 8, 2020 22:21
Copy link
Owner

@Radi85 Radi85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey,

Many thanks for you efforts.

I would separate show reacted user feature in a different issue so for now just ignore it.

Please consider PEP 8 compatibility and ignore typing for now.

comment/admin.py Outdated Show resolved Hide resolved
comment/models/reactions.py Outdated Show resolved Hide resolved
comment/models/reactions.py Outdated Show resolved Hide resolved
- likes and dislikes are now part of a column.
- add functions to update reactions and their count.

Make changes to the ReactionInstance model
- reaction choices now uses IntegerChoices which is similar to IntEnum

Add the reaction model and reaction instance model to the admin

Change import of comment model
- it is directly imported from the model package rather than going inside the comments module.
comment/admin.py Outdated Show resolved Hide resolved
comment/models/comments.py Show resolved Hide resolved
comment/models/reactions.py Outdated Show resolved Hide resolved
- all comment models are now imported in the __init__ file
Changes made to Reaction model
- Reaction choices are now made from IntEnum, since models.TextChoices is only supported in Django 3.0
- related_name for foreign keys made plural
- move logic for set_reaction to ReactionInstance model

Changes to ReactionInstance
- add function to override save function.
- add a function to be executed on pre-delete signal.
- set_reaction method is now a classmethod.
- clean up set_reaction and refactor it.

Changes to Comment model
- add property for showing like and dislike count.

Add urlpattern for accepting requests for reaction.

Changes to views
- views is now a package, move earlier code to comments module inside it
- add module for reactions

Changes to templates
- show like and dislike count alongside the comment content
Copy link
Owner

@Radi85 Radi85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey,
Thanks a lot. A lot of work has been done.
I would like to use icons instead, thumbs up and down, if your question is realted to the font, feel free to use any light weight version.
As suggested, please move reply, like and dislike to the second row.
Unfortunately I have no more time but I would like to get back to review the models again, nice work!

comment/models/reactions.py Show resolved Hide resolved
comment/models/comments.py Show resolved Hide resolved
comment/api/urls.py Outdated Show resolved Hide resolved
@Radi85
Copy link
Owner

Radi85 commented May 12, 2020

Btw, the work you have already done, could be splitted to more features :D
I will have a look at the tasks a bit later.

comment/views/reactions.py Outdated Show resolved Hide resolved
comment/models/reactions.py Show resolved Hide resolved
comment/models/reactions.py Show resolved Hide resolved
Add svg icons for like and dislike
- fill them if the logged in user has liked or disliked a comment
- add templatetags that make this feature possible

Add post save signal to Comment model
- Reaction instance is created when a new comment is created.

Changes in ReactionInstance model
- change related name for user attribute -> 'reactions' seems more natural.
@Radi85
Copy link
Owner

Radi85 commented May 13, 2020

Well done so far. I like how it looks like.

- Reaction icon's color and count are updated.

Changes in reaction views
- View all returns latest reaction count for the updated reaction -> Updates reaction count as per the last HTTP request

Changes to comment content template
- Remove block for like and dislike icon colors -> the color values are used in javascript too. Obtaining them to javascript from the template would require a hack. Can be done in the future.
- Make or remove element properties as per changes in the javascript.
- cite was probably mistakenly used here.
@abhiabhi94
Copy link
Collaborator Author

Hey, currently the reaction thing works well for authenticated users.

For unauthenticated users, I was thinking of following this workflow

  • Inside the template, add an attribute to the anchor element and set the href attribute accordingly. Then inside the javascript, when the onclick event is triggered, I could check if the attribute is set, redirect them to the login page.

    • An issue here is the next path to the login URL in django redirects through GET requests only?(I may be wrong here). Currently, I had allowed only POST requests for accepting reactions. Should I change the request method there?
  • How should we handle oauth?

Changes in view handling reaction
- bad react requests are handled now
- they were anyway used outside the class

Add tests for unauthenticated users for the has_reacted template tag
- mock an unauthenticated user for the template -> complete coverage for template tags.
@Radi85
Copy link
Owner

Radi85 commented May 14, 2020

For unauthenticated users, I was thinking of following this workflow

To avoid this complex, please use a simple if statement inside the template:

{% if user.is_authenticated %}
 a_tag
{% else %}
div_tag
{% endif %}
  • How should we handle oauth?

I believe django will authenticate the user when using oauth, so you have nothing to do here.

comment/models/reactions.py Show resolved Hide resolved
comment/templates/comment/content.html Show resolved Hide resolved
comment/templatetags/comment_tags.py Outdated Show resolved Hide resolved
@abhiabhi94
Copy link
Collaborator Author

abhiabhi94 commented May 14, 2020

To avoid this complex, please use a simple if statement inside the template:

How will this help in handling the event when triggered through javascript?

I believe django will authenticate the user when using oauth, so you have nothing to do here.

I was concerned about redirecting the user to the like link for the comment. How do we do that?

@Radi85
Copy link
Owner

Radi85 commented May 15, 2020

How will this help in handling the event when triggered through javascript?

Javascript fucntion is triggered here:

 $(document).on("click", ".js-comment-reaction", commentReact);

Add this class to html tag only if the user is authenticated:

<small class="{% if user.is_authenticated %}js-comment-like {% endif %} {% block like_link_cls %} btn btn-link" {% endblock like_link_cls %} href="{% url 'comment:react' comment_id=obj.id reaction='like' %}">{% trans "Like" %}</small>

I was concerned about redirecting the user to the like link for the comment. How do we do that?

I am not sure what redirecting the user to the like link for the comment means. Our app is associated with a given model and our urls are related to that model's urls. I believe this redirecting part shall be handeled by the developer who uses our app.

@abhiabhi94
Copy link
Collaborator Author

abhiabhi94 commented May 15, 2020

I am not sure what redirecting the user to the like link for the comment means. Our app is associated with a given model and our urls are related to that model's urls. I believe this redirecting part shall be handeled by the developer who uses our app

Sorry, I didn't mention this explicitly, but I was talking about unauthenticated users. If they click on the like icon, we would want to redirect them to like URL after they are authenticated. For normal auth, we can put the link something like this /login?next=redirect_link but what to do in this case.

Also, how should we handle the response in this case(after performing the action on the redirected link)? Currently, I am returning JSON response which might not be an ideal scenario.

@abhiabhi94
Copy link
Collaborator Author

We also need to add exception handling to the comment views.
Testing your comment views I found that exception handling has not been handled if the URLs are accessed directly through the browser without form attributes or other values.

- move reactions part to a separate template
- add translation capabilities to this template.

Create new templates for reactions templates
- handles url for unauthenticated users.
- like and dislike icon moved to a separate template.

Remove Reaction manager
- it wasn't used anywhere in the application.

Change request method for reaction
- GET allows redirect for unauthenticated users
- make the corresponding change to the javascript function

Changes in tests
- add tests in models for post delete signal.
- refactor code for view tests.
- remove unnecessary part.
- it was mistakenly copied from the like icon

Add an empty line at the end of the file
@abhiabhi94
Copy link
Collaborator Author

I got one JS issue when running your code locally.

comment.js:238 Uncaught TypeError: Cannot read property 'style' of undefined
    at fillReaction (comment.js:238)
    at Object.commentReactionDone [as success] (comment.js:281)

The issue might be in this line:

if (colorIsNone($likeIcon.style.fill) && colorIsNone($dislikeIcon.style.fill)) {
     $targetReaction.style.fill = fillColor;
}

I have fixed it in the latest commit. It was caused when I was refactoring the templates. I had accidently forgot to change the icon class and filter to the dislike icon file after copying things from the like icon file.

@abhiabhi94
Copy link
Collaborator Author

Any particular reason for this? Each individual commit generally has a reason and descriptive message that indicates the reasons for the change.

I would like to keep git tree clean and I prefer to have one commit per feature.

One feature has a lot of sub-features or substantial subtilities that are required for its implementation. I don't think you can put the whole thing in a single commit.

Anyways it is your call. I believe Github gives the owners/maintainers option to squash the commits while merging.

@Radi85
Copy link
Owner

Radi85 commented May 16, 2020

Unexpected behavior here ⬇️ like and dislike both are filled for the same user.
Screenshot 2020-05-16 at 13 45 47

@Radi85
Copy link
Owner

Radi85 commented May 16, 2020

One feature has a lot of sub-features or substantial subtilities that are required for its implementation. I don't think you can put the whole thing in a single commit.

Anyways it is your call. I believe Github gives the owners/maintainers option to squash the commits while merging.

Don't worry about it then, I will take care of it.

@abhiabhi94
Copy link
Collaborator Author

Unexpected behavior here arrow_down like and dislike both are filled for the same user.
Screenshot 2020-05-16 at 13 45 47

Was this behaviour after you clicked on the icons or when the page was rendered?

@abhiabhi94
Copy link
Collaborator Author

If you mean the migration file, yes please.

No the db.sqlite3 file.

Doesn't matter since it is used for testing purpose only.

Maybe we can put the file in .gitignore to stop it from being tracked, to stop it from causing issues with version control.

@Radi85
Copy link
Owner

Radi85 commented May 16, 2020

Was this behaviour after you clicked on the icons or when the page was rendered?

After rendreing the page.

@Radi85
Copy link
Owner

Radi85 commented May 16, 2020

Maybe we can put the file in .gitignore to stop it from being tracked, to stop it from causing issues with version control.

I actually keep this db for the demo project so who would like to use app, can directly find an example with less efforts.

@abhiabhi94
Copy link
Collaborator Author

Was this behaviour after you clicked on the icons or when the page was rendered?

After rendreing the page.

Are you sure? This means the template filter is not working correctly then. Just to make sure, have you pulled in the latest commits?

@abhiabhi94
Copy link
Collaborator Author

abhiabhi94 commented May 16, 2020

I forgot to mention the icons were picked from https://feathericons.com. Please don't forget to give them credit in the documentation.

@Radi85
Copy link
Owner

Radi85 commented May 16, 2020

I forgot to mention the icons were picked from https://feathericons.com. Please don't forget to give them credit in the documentation.

Thanks for mentioning. Just small thing regarding the icons, could you please make them with the count text a little bit small?

@abhiabhi94
Copy link
Collaborator Author

abhiabhi94 commented May 16, 2020

I forgot to mention the icons were picked from https://feathericons.com. Please don't forget to give them credit in the documentation.

Thanks for mentioning. Just small thing regarding the icons, could you please make them with the count text a little bit small?

Height and width of size 20 for icons look fine to me. Just try and tell me if it looks good to you before I push in the change.
.

- remove the filter used for chaining.
- change tests accordingly

Like and Dislike icon are now filled using a class
- make appropriate changes to the javascript file
- add classes to the css file
- this change was made because style property was sometimes not overiding the fill property of svg element

Fixes like and dislike icons filling now hopefully.
- make corresponding changes in the url and tests.
@Radi85
Copy link
Owner

Radi85 commented May 17, 2020

FAIL: test_create_comment (comment.tests.test_views.CreateCommentTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/Radi85/Comment/comment/tests/test_views.py", line 45, in test_create_comment
    self.assertIsNone(response.context.get('comment'))
AssertionError: reply by test-1: child comment body is not None

The test is failing due to passing the reply comment object to the context data as comment which is treated as a parent, I used to differentiate the parent from the child in the context data like so:

context['comment'] = PARENT_COMMENT
context['reply'] = CHILD_COMMENT

As I see this is a bad design and I am going to refactor the code.
For now please comment out this line self.assertIsNone(response.context.get('comment')) in test_create_comment line 45 in order to make the test passing and merge your PR before start refacotring.

Add type checking for reaction type in model
- add clean function in views also
Copy link
Owner

@Radi85 Radi85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got 405 (Method Not Allowed) error when try to react to a comment.

@abhiabhi94
Copy link
Collaborator Author

I got 405 (Method Not Allowed) error when try to react to a comment.

Yes, I too get this error now. I had not checked the response by testing it from a browser after the database issue. Since the tests were passing, I assumed it should pass. I will fix this soon and commit.

- change made after refactoring view to a class based one.
@abhiabhi94 abhiabhi94 requested a review from Radi85 May 17, 2020 15:00
@Radi85 Radi85 mentioned this pull request May 17, 2020
@Radi85
Copy link
Owner

Radi85 commented May 17, 2020

Merged in #16

@Radi85 Radi85 closed this May 17, 2020
@Radi85 Radi85 added the merged label May 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Reactions
2 participants