From 9872a4b772ce40bf0b6828dd95f6aa4ebe1abb71 Mon Sep 17 00:00:00 2001 From: Hamid Reza Mohammadi Date: Fri, 25 Sep 2026 15:04:19 +0330 Subject: [PATCH] #421 geo tag moderaion --- .../Areas/Admin/Pages/ReviewEdits.cshtml | 57 ++++++++++++++++++ .../Areas/Admin/Pages/ReviewEdits.cshtml.cs | 58 +++++++++++++++++++ GanjooRazor/Models/PoemMoerationStructure.cs | 14 +++++ 3 files changed, 129 insertions(+) diff --git a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml index 90295126..9c335907 100644 --- a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml +++ b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml @@ -2,6 +2,7 @@ @model GanjooRazor.Areas.Admin.Pages.ReviewEditsModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @using DNTPersianUtils.Core +@using RMuseum.Models.Ganjoor @{ Layout = "_AdminLayout"; ViewData["Title"] = "بازبینی ویرایش‌ها"; @@ -38,6 +39,13 @@ } } + function toggleGeoTagNewLocationFields(geoIndex) { + var select = document.getElementById('geotag' + geoIndex + '_location_select'); + var fields = document.getElementById('geotag' + geoIndex + '_new_location_fields'); + if (!select || !fields) return; + fields.style.display = (select.value === '0') ? '' : 'none'; + } + function moderatePoemCorrections(verseCount, correctionId, geoTagCount) { $('#moderatecorrections').hide(); @@ -135,12 +143,22 @@ var geoTagReviewResult = []; var geoTagReviewNotes = []; + var geoTagLocationId = []; + var geoTagLocationName = []; + var geoTagLatitude = []; + var geoTagLongitude = []; for (var g = 0; g < (geoTagCount || 0); g++) { var geoElementId = '#geotag' + (g + 1).toString() + '_review_result_Approved'; if ($(geoElementId).length > 0) { var geoElementName = 'geotag' + (g + 1).toString() + '_review_result'; geoTagReviewResult.push($('input[name=' + geoElementName + ']:checked').val()) geoTagReviewNotes.push($('#geotag' + (g + 1).toString() + '_review_note').val()) + + var geoLocationSelect = $('#geotag' + (g + 1).toString() + '_location_select'); + geoTagLocationId.push(geoLocationSelect.length > 0 ? geoLocationSelect.val() : '0'); + geoTagLocationName.push($('#geotag' + (g + 1).toString() + '_location_name').val() || null); + geoTagLatitude.push($('#geotag' + (g + 1).toString() + '_latitude').val() || null); + geoTagLongitude.push($('#geotag' + (g + 1).toString() + '_longitude').val() || null); } } @@ -164,6 +182,10 @@ pms.poemformatReviewNote= $('#poemformat_review_note') == null ? null : $('#poemformat_review_note').val(); pms.geoTagReviewResult= geoTagReviewResult; pms.geoTagReviewNotes= geoTagReviewNotes; + pms.geoTagLocationId= geoTagLocationId; + pms.geoTagLocationName= geoTagLocationName; + pms.geoTagLatitude= geoTagLatitude; + pms.geoTagLongitude= geoTagLongitude; $.ajax({ type: "POST", @@ -852,6 +874,41 @@ else } + + +

+ اگر کاربر در نام مکان یا مختصات آن اشتباه کرده اما پیشنهادش در اصل ارزش تأیید دارد، به‌جای رد کردن می‌توانید همین‌جا آن را اصلاح کنید: +

+ + + @if (geoTag.LocationId == null) + { +
+
+ + + + + + +
+ } + + } diff --git a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs index 53420ad4..02746089 100644 --- a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs +++ b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net.Http; using System.Text; @@ -61,6 +63,12 @@ namespace GanjooRazor.Areas.Admin.Pages /// public Tuple[] Couplets { get; set; } + /// + /// full location catalog, offered as an alternative to a user's new-location suggestion so the + /// moderator can correct a mistyped/duplicate name by linking it to the existing entry instead + /// + public List Locations { get; set; } + /// /// groups verses into couplets - same logic as SuggestQuoted.cshtml.cs's/Editor.cshtml.cs's GetCouplets, /// duplicated here rather than shared, so this page doesn't take on a cross-file dependency on those @@ -175,6 +183,19 @@ namespace GanjooRazor.Areas.Admin.Pages Couplets = GetCouplets(PageInformation.Poem.Verses); + if (Correction.GeoDateTags != null && Correction.GeoDateTags.Any()) + { + var responseLocations = await secureClient.GetAsync($"{APIRoot.Url}/api/locations"); + if (!responseLocations.IsSuccessStatusCode) + { + FatalError = JsonConvert.DeserializeObject(await responseLocations.Content.ReadAsStringAsync()); + return Page(); + } + Locations = new List(); + Locations.Add(new GanjoorGeoLocation() { Id = 0, Latitude = 0, Longitude = 0, Name = "" }); + Locations.AddRange(JsonConvert.DeserializeObject(await responseLocations.Content.ReadAsStringAsync())); + } + if (PageInformation.Poem.Sections.Where(s => s.SectionType == PoemSectionType.WholePoem && !string.IsNullOrEmpty(s.RhymeLetters)).Any()) { RhymeLetters = PageInformation.Poem.Sections.Where(s => s.SectionType == PoemSectionType.WholePoem && !string.IsNullOrEmpty(s.RhymeLetters)).OrderBy(s => s.VerseType).First().RhymeLetters; @@ -390,6 +411,43 @@ namespace GanjooRazor.Areas.Admin.Pages { return new BadRequestObjectResult("لطفاً تکلیف بررسی تمام برچسب‌های جغرافیایی/تاریخی پیشنهادی را مشخص کنید."); } + + if (!Correction.GeoDateTags[i].MarkForDelete) + { + // let the moderator fix a mistyped location name / wrong coordinates, or link to an + // existing catalog location, before the tag is approved - rather than only being able + // to approve the user's suggestion as-is or reject it outright + string correctedLocationIdText = (pms.geoTagLocationId != null && i < pms.geoTagLocationId.Length) ? pms.geoTagLocationId[i] : null; + if (!string.IsNullOrWhiteSpace(correctedLocationIdText) && int.TryParse(correctedLocationIdText, out int correctedLocationId) && correctedLocationId > 0) + { + Correction.GeoDateTags[i].LocationId = correctedLocationId; + Correction.GeoDateTags[i].SuggestedLocationName = null; + Correction.GeoDateTags[i].SuggestedLatitude = null; + Correction.GeoDateTags[i].SuggestedLongitude = null; + } + else if (Correction.GeoDateTags[i].LocationId == null) + { + string correctedName = (pms.geoTagLocationName != null && i < pms.geoTagLocationName.Length) ? pms.geoTagLocationName[i] : null; + string correctedLatText = (pms.geoTagLatitude != null && i < pms.geoTagLatitude.Length) ? pms.geoTagLatitude[i] : null; + string correctedLngText = (pms.geoTagLongitude != null && i < pms.geoTagLongitude.Length) ? pms.geoTagLongitude[i] : null; + if (!string.IsNullOrWhiteSpace(correctedName)) + { + Correction.GeoDateTags[i].SuggestedLocationName = correctedName.Trim(); + } + if (!string.IsNullOrWhiteSpace(correctedLatText) && !string.IsNullOrWhiteSpace(correctedLngText)) + { + if (!double.TryParse(correctedLatText, NumberStyles.Float, CultureInfo.InvariantCulture, out double correctedLat) + || !double.TryParse(correctedLngText, NumberStyles.Float, CultureInfo.InvariantCulture, out double correctedLng) + || correctedLat < -90 || correctedLat > 90 || correctedLng < -180 || correctedLng > 180) + { + return new BadRequestObjectResult("مقدار اصلاح‌شدهٔ عرض/طول جغرافیایی نامعتبر است."); + } + Correction.GeoDateTags[i].SuggestedLatitude = correctedLat; + Correction.GeoDateTags[i].SuggestedLongitude = correctedLng; + } + } + } + Correction.GeoDateTags[i].Result = (CorrectionReviewResult)Enum.Parse(typeof(CorrectionReviewResult), pms.geoTagReviewResult[i]); Correction.GeoDateTags[i].ReviewNote = (pms.geoTagReviewNotes != null && i < pms.geoTagReviewNotes.Length) ? pms.geoTagReviewNotes[i] : null; } diff --git a/GanjooRazor/Models/PoemMoerationStructure.cs b/GanjooRazor/Models/PoemMoerationStructure.cs index 93eca773..9a11ad4e 100644 --- a/GanjooRazor/Models/PoemMoerationStructure.cs +++ b/GanjooRazor/Models/PoemMoerationStructure.cs @@ -18,5 +18,19 @@ public string poemformatReviewNote { get; set; } public string[] geoTagReviewResult { get; set; } public string[] geoTagReviewNotes { get; set; } + /// + /// moderator's corrected location for each geo tag, if they picked an existing catalog location + /// instead of what the user suggested (empty/"0" means no change to LocationId) + /// + public string[] geoTagLocationId { get; set; } + /// + /// moderator's corrected new-location name (fixes a typo in the user's suggestion), if any + /// + public string[] geoTagLocationName { get; set; } + /// + /// moderator's corrected new-location latitude/longitude (fixes wrong coordinates), if any + /// + public string[] geoTagLatitude { get; set; } + public string[] geoTagLongitude { get; set; } } }