#495 comment ratings

This commit is contained in:
Hamid Reza Mohammadi 2026-08-04 18:24:35 +03:30
parent dff2ec9ac5
commit ff3e82e897
11 changed files with 92 additions and 7 deletions

View File

@ -213,6 +213,23 @@ namespace GanjooRazor.Pages
});
}
/// <summary>
/// like / dislike / clear rating for a comment (AJAX, called from rateComment() in bk.js)
/// </summary>
public Task<IActionResult> OnPostRateCommentAsync(int id, short value)
{
return WithSecureClientAsync(async secureClient =>
{
var response = await secureClient.PostAsync($"{APIRoot.Url}/api/ganjoor/poem/comment/{id}/rate?value={value}", null);
if (!response.IsSuccessStatusCode)
{
return new BadRequestObjectResult(await ReadErrorMessageAsync(response));
}
var result = JsonConvert.DeserializeObject<GanjoorCommentRatingResultViewModel>(await response.Content.ReadAsStringAsync());
return new JsonResult(result);
});
}
/// <summary>
/// Poets (for this page's own #hdr2 author dropdown - same pattern as Search/Simi/etc.)
/// </summary>

View File

@ -23,7 +23,7 @@
font-family: 'Vazirmatn'
}
</style>
<script src="/js/bk.js?version=81"></script>
<script src="/js/bk.js?version=83"></script>
<script src="~/js/jquery-1.10.2.min.js"></script>
<script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script>

View File

@ -15,7 +15,7 @@
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="گنجور" href="https://ganjoor.net/search.xml" />
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/js/bk.js?version=81"></script>
<script src="/js/bk.js?version=83"></script>
<script>
var cookieValue = getCookie("playerScrollLock");
var playerScrollLock = cookieValue === "true";

View File

@ -44,6 +44,16 @@ else
}
<a role="button" title="پاسخگویی به این حاشیه" onclick="replyComment(@Model.Comment.Id, @(Model.LoggedIn ? "true" : "false"), '@Model.DivSuffix')"><i class="notranslate pageicons">reply</i></a>
@if (!Model.Comment.MyComment)
{
<a role="button" title="پسندیدن" id="like-btn-@Model.Comment.Id@Model.DivSuffix" class="cursor-pointer@(Model.Comment.CurrentUserRatingValue == 1 ? " green-color" : "")" onclick="rateComment(@Model.Comment.Id, 1, @(Model.LoggedIn ? "true" : "false"), '@Model.DivSuffix')"><i class="notranslate pageicons">thumb_up</i></a>
}
<small id="like-count-@Model.Comment.Id@Model.DivSuffix">@Model.Comment.LikeCount.ToPersianNumbers()</small>
@if (!Model.Comment.MyComment)
{
<a role="button" title="نپسندیدن" id="dislike-btn-@Model.Comment.Id@Model.DivSuffix" class="cursor-pointer@(Model.Comment.CurrentUserRatingValue == -1 ? " red-color" : "")" onclick="rateComment(@Model.Comment.Id, -1, @(Model.LoggedIn ? "true" : "false"), '@Model.DivSuffix')"><i class="notranslate pageicons">thumb_down</i></a>
}
<small id="dislike-count-@Model.Comment.Id@Model.DivSuffix">@Model.Comment.DislikeCount.ToPersianNumbers()</small>
<a href="/ReportComment/?CommentId=@Model.Comment.Id" title="گزارش حاشیهٔ نامناسب" onclick="wpopen(this.href); return false"><i class="notranslate pageicons">flag</i></a>
<a role="button" onclick="copyCommentUrl(@Model.Comment.Id)"><i class="notranslate pageicons">link</i></a>
@if (Model.LoggedIn)

View File

@ -150,7 +150,7 @@
</p>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/bk.js?version=81"></script>
<script src="~/js/bk.js?version=83"></script>
<script src="~/js/jplayersupport.js"></script>
<script src="~/js/vaabd.js?version=10"></script>
<script src="~/dist/jplayer/jquery.jplayer.min.js"></script>

View File

@ -238,7 +238,7 @@
<script src="~/js/bk.js?version=81"></script>
<script src="~/js/bk.js?version=83"></script>
<script src="~/js/jplayersupport.js"></script>
<script src="~/js/vaabd.js?version=10"></script>
<script src="~/dist/jplayer/jquery.jplayer.min.js"></script>

View File

@ -35,7 +35,7 @@
});
</script>
<script src="/js/bk.js?version=81"></script>
<script src="/js/bk.js?version=83"></script>
<script>
function editBanner(bannerId) {
var url = '?handler=Edit';

View File

@ -34,7 +34,7 @@
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="گنجور" href="https://ganjoor.net/search.xml" />
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/js/bk.js?version=81"></script>
<script src="/js/bk.js?version=83"></script>
<script>
var cookieValue = getCookie("playerScrollLock");
var playerScrollLock = cookieValue === "true";

View File

@ -32,7 +32,7 @@
});
</script>
<script src="/lib/diff.js"></script>
<script src="/js/bk.js?version=81"></script>
<script src="/js/bk.js?version=83"></script>
<script>
function compareCorrectionBlocks(originalElemenyId, editedElementId, resultElementId) {
var a = document.getElementById(originalElemenyId);

View File

@ -504,6 +504,54 @@ function switchBookmarkInternal(poemId, coupletIndex, divSuffix) {
});
}
function rateComment(commentId, value, loggedIn, divSuffix) {
if (!loggedIn) {
alert('برای رأی دادن به حاشیه‌ها لازم است با نام کاربری خود وارد گنجور شوید.');
return;
}
var likeBtn = document.getElementById('like-btn-' + commentId + divSuffix);
var dislikeBtn = document.getElementById('dislike-btn-' + commentId + divSuffix);
// clicking the already-active button clears the rating instead of re-sending the same value
var newValue = value;
if (value == 1 && likeBtn.classList.contains('green-color')) newValue = 0;
if (value == -1 && dislikeBtn.classList.contains('red-color')) newValue = 0;
$.ajax({
type: "POST",
url: '?handler=RateComment',
data: {
id: commentId,
value: newValue
},
error: function (err) {
alert('خطا در ثبت رأی: ' + err.responseText);
},
success: function (result) {
_applyCommentRatingResult(commentId, divSuffix, result);
if (divSuffix != '') {
_applyCommentRatingResult(commentId, '', result);
}
},
});
}
function _applyCommentRatingResult(commentId, divSuffix, result) {
var likeBtn = document.getElementById('like-btn-' + commentId + divSuffix);
var dislikeBtn = document.getElementById('dislike-btn-' + commentId + divSuffix);
var likeCount = document.getElementById('like-count-' + commentId + divSuffix);
var dislikeCount = document.getElementById('dislike-count-' + commentId + divSuffix);
if (likeCount != null) likeCount.innerText = toPersianNumber(result.likeCount);
if (dislikeCount != null) dislikeCount.innerText = toPersianNumber(result.dislikeCount);
if (likeBtn != null) likeBtn.classList.remove('green-color');
if (dislikeBtn != null) dislikeBtn.classList.remove('red-color');
if (result.currentUserRatingValue == 1 && likeBtn != null) likeBtn.classList.add('green-color');
if (result.currentUserRatingValue == -1 && dislikeBtn != null) dislikeBtn.classList.add('red-color');
}
function checkIfBookmarked(poemId) {
if (document.getElementById('bookmark-icon') == null) return;
setTimeout(function () {
@ -1787,6 +1835,11 @@ function persianToEnglishNumber(str) {
return str.replace(/[۰-۹]/g, d => persianDigits.indexOf(d));
}
function toPersianNumber(n) {
const persianDigits = '۰۱۲۳۴۵۶۷۸۹';
return String(n).replace(/[0-9]/g, d => persianDigits[d]);
}
function plotChart(tableId, maxCols = 9) {

View File

@ -35,6 +35,11 @@ namespace RMuseum.Services.Implementation
return new RServiceResult<GanjoorCommentRatingResultViewModel>(null, "comment == null");
}
if (comment.UserId != null && comment.UserId == userId)
{
return new RServiceResult<GanjoorCommentRatingResultViewModel>(null, "امکان رأی دادن به حاشیهٔ خودتان وجود ندارد.");
}
var oldRating = await _context.GanjoorCommentReactions.Where(c => c.GanjoorCommentId == commentId && c.UserId == userId).SingleOrDefaultAsync();
if (value == 0 && oldRating == null)
{