From 5ce578cbfefa7ed81d64df1a5a424220d59cafb0 Mon Sep 17 00:00:00 2001 From: harshtandiya Date: Thu, 7 Nov 2024 11:34:56 +0530 Subject: [PATCH] feat: like button for candidate forms --- ballot/api/candidate.py | 2 +- ballot/api/like.py | 112 ++++++++++++++++++ frontend/src/components/ui/LikeButton.vue | 62 ++++++++++ .../election/CandidatureSubmissionPublic.vue | 9 +- frontend/src/utils/like.js | 55 +++++++++ 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 ballot/api/like.py create mode 100644 frontend/src/components/ui/LikeButton.vue create mode 100644 frontend/src/utils/like.js diff --git a/ballot/api/candidate.py b/ballot/api/candidate.py index 63104a3..4eca2d1 100644 --- a/ballot/api/candidate.py +++ b/ballot/api/candidate.py @@ -39,7 +39,7 @@ def get_candidate_details(candidate: str): form = frappe.db.get_value( "Election Candidate Application", candidate, - ["photo", "full_name", "designation", "organization", "submission_meta"], + ["photo", "full_name", "designation", "organization", "submission_meta", "name"], as_dict=1, ) diff --git a/ballot/api/like.py b/ballot/api/like.py new file mode 100644 index 0000000..9ae7d58 --- /dev/null +++ b/ballot/api/like.py @@ -0,0 +1,112 @@ +import frappe + + +@frappe.whitelist() +def toggle_like(reference_doctype: str, reference_name: str, comment_email: str) -> None: + """ + Add a 'Like' comment to the specified document. + + Args: + reference_doctype (str): The doctype of the document being liked. + reference_name (str): The name of the document being liked. + comment_email (str): The email of the user liking the document. + + Returns: + None + + Raises: + ValueError: If any of the input parameters are invalid. + frappe.exceptions.ValidationError: If the document cannot be inserted. + """ + if not reference_doctype or not reference_name or not comment_email: + raise ValueError("All parameters must be provided and non-empty.") + + try: + if is_already_liked( + reference_doctype=reference_doctype, + reference_name=reference_name, + comment_email=comment_email, + ): + frappe.db.delete( + "Comment", + { + "reference_doctype": reference_doctype, + "reference_name": reference_name, + "comment_email": comment_email, + "comment_type": "Like", + }, + ) + else: + like = frappe.get_doc( + { + "doctype": "Comment", + "comment_type": "Like", + "reference_doctype": reference_doctype, + "reference_name": reference_name, + "comment_email": comment_email, + "content": "Liked", + } + ) + like.insert(ignore_permissions=True) + except Exception as e: + frappe.log_error(message=str(e), title="Like Doc Insertion Failed") + frappe.throw(frappe.ValidationError) + + +@frappe.whitelist(allow_guest=True) +def get_likes_count(reference_doctype: str, reference_name: str) -> int: + """ + Get the count of likes for the specified document. + + Args: + reference_doctype (str): The doctype of the document. + reference_name (str): The name of the document. + + Returns: + int: The number of likes for the document. + """ + + if not reference_doctype or not reference_name: + raise ValueError( + "Both reference_doctype and reference_name must be provided and non-empty." + ) + + return frappe.db.count( + "Comment", + filters={ + "reference_doctype": reference_doctype, + "reference_name": reference_name, + "comment_type": "Like", + }, + ) + + +@frappe.whitelist() +def is_already_liked(reference_doctype: str, reference_name: str, comment_email: str) -> bool: + """ + Check if the specified document has already been liked by the given email. + + Args: + reference_doctype (str): The doctype of the document. + reference_name (str): The name of the document. + comment_email (str): The email of the user. + + Returns: + bool: True if the document is already liked by the given email, False otherwise. + """ + + if not reference_doctype or not reference_name or not comment_email: + raise ValueError("All parameters must be provided and non-empty.") + + return ( + frappe.db.exists( + "Comment", + { + "reference_doctype": reference_doctype, + "reference_name": reference_name, + "comment_email": comment_email, + "comment_type": "Like", + }, + ) + is not None + ) diff --git a/frontend/src/components/ui/LikeButton.vue b/frontend/src/components/ui/LikeButton.vue new file mode 100644 index 0000000..dee2a5c --- /dev/null +++ b/frontend/src/components/ui/LikeButton.vue @@ -0,0 +1,62 @@ + + diff --git a/frontend/src/pages/election/CandidatureSubmissionPublic.vue b/frontend/src/pages/election/CandidatureSubmissionPublic.vue index 3779e82..48a0d79 100644 --- a/frontend/src/pages/election/CandidatureSubmissionPublic.vue +++ b/frontend/src/pages/election/CandidatureSubmissionPublic.vue @@ -34,6 +34,11 @@ :field="field" /> + { + return createResource({ + url: 'ballot.api.like.toggle_like', + makeParams() { + return { + reference_doctype: reference_doctype, + reference_name: reference_name, + comment_email: comment_email, + } + }, + onSuccess() { + return [1, 'Liked Successfully'] + }, + onError(err) { + return [0, err.messages] + }, + }) +} + +export const checkAlreadyLiked = ( + reference_doctype, + reference_name, + comment_email, +) => { + return createResource({ + url: 'ballot.api.like.is_already_liked', + makeParams() { + return { + comment_email: comment_email, + reference_doctype: reference_doctype, + reference_name: reference_name, + } + }, + auto: true, + }) +} + +export const getLikeCount = (reference_doctype, reference_name) => { + return createResource({ + url: 'ballot.api.like.get_likes_count', + makeParams() { + return { + reference_doctype: reference_doctype, + reference_name: reference_name, + } + }, + auto: true, + }) +}