From 800857aadc22ac6e8fcc01208623186cd0f4f100 Mon Sep 17 00:00:00 2001 From: Hamid Reza Mohammadi Date: Wed, 30 Sep 2026 19:14:17 +0330 Subject: [PATCH] people tags #387 --- GanjooRazor/Areas/User/Pages/Edits.cshtml | 27 +++++++++- GanjooRazor/Areas/User/Pages/Edits.cshtml.cs | 9 +++- .../User/Pages/PoemCorrectionsHistory.cshtml | 24 ++++++++- .../Pages/PoemCorrectionsHistory.cshtml.cs | 9 +++- .../Utils/GeoDateTagCorrectionDisplay.cs | 51 +++++++++++++++++++ 5 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 GanjooRazor/Utils/GeoDateTagCorrectionDisplay.cs diff --git a/GanjooRazor/Areas/User/Pages/Edits.cshtml b/GanjooRazor/Areas/User/Pages/Edits.cshtml index ca4a4c27..7ec1c252 100644 --- a/GanjooRazor/Areas/User/Pages/Edits.cshtml +++ b/GanjooRazor/Areas/User/Pages/Edits.cshtml @@ -2,6 +2,7 @@ @model GanjooRazor.Areas.User.Pages.EditsModel @using DNTPersianUtils.Core @using RMuseum.Models.Ganjoor +@using GanjooRazor.Utils @{ Layout = "_UserPanelLayout"; ViewData["Title"] = "ویرایش‌های من"; @@ -279,7 +280,7 @@ else { - برچسب جغرافیایی/تاریخی - + @(GeoDateTagCorrectionDisplay.IsPersonTag(geoTag) ? "شخصیت" : "برچسب جغرافیایی/تاریخی") - @if (geoTag.CoupletIndex == null) { کل شعر @@ -304,6 +305,30 @@ else } + else if (GeoDateTagCorrectionDisplay.IsPersonTag(geoTag)) + { + + +

-

+ + +

+ @if (geoTag.PersonId != null) + { + @(geoTag.Person != null ? geoTag.Person.Name : $"شخصیت #{geoTag.PersonId}") + } + else + { + var suggestedPersonName = GeoDateTagCorrectionDisplay.GetSuggestedPersonName(geoTag.SuggestedPersonGraphJson); + شخصیت جدید@(string.IsNullOrEmpty(suggestedPersonName) ? "" : $": {suggestedPersonName}") + } +

+ + + + + + } else { diff --git a/GanjooRazor/Areas/User/Pages/Edits.cshtml.cs b/GanjooRazor/Areas/User/Pages/Edits.cshtml.cs index 3268de44..7d23d6f9 100644 --- a/GanjooRazor/Areas/User/Pages/Edits.cshtml.cs +++ b/GanjooRazor/Areas/User/Pages/Edits.cshtml.cs @@ -287,6 +287,11 @@ namespace GanjooRazor.Areas.User.Pages var geoDateTagsRollback = new List(); foreach (var geoTag in currentCorrection.GeoDateTags.Where(g => g.Result == CorrectionReviewResult.Approved)) { + // PersonId (if the deleted tag was a person tag) is part of what got snapshotted + // onto this same record when the delete request was approved, so it's already + // available here for GeoDateTagCorrectionDisplay.IsPersonTag to tell the two kinds + // of tag apart for the note text below. + var geoTagLabel = GeoDateTagCorrectionDisplay.IsPersonTag(geoTag) ? "شخصیت" : "برچسب جغرافیایی/تاریخی"; if (geoTag.MarkForDelete) { // the original request deleted an existing tag - undo that by re-adding a tag with @@ -302,7 +307,7 @@ namespace GanjooRazor.Areas.User.Pages LunarDay = geoTag.LunarDay, PersonId = geoTag.PersonId, IgnoreInCategory = geoTag.IgnoreInCategory, - SuggestionNote = $"برگشت حذف برچسب جغرافیایی/تاریخی با کد {correctionId}" + SuggestionNote = $"برگشت حذف {geoTagLabel} با کد {correctionId}" }); } else if (geoTag.ExistingTagId != null) @@ -314,7 +319,7 @@ namespace GanjooRazor.Areas.User.Pages CoupletIndex = geoTag.CoupletIndex, MarkForDelete = true, ExistingTagId = geoTag.ExistingTagId, - SuggestionNote = $"برگشت افزودن برچسب جغرافیایی/تاریخی با کد {correctionId}" + SuggestionNote = $"برگشت افزودن {geoTagLabel} با کد {correctionId}" }); } } diff --git a/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml b/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml index 31918a1d..232aff67 100644 --- a/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml +++ b/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml @@ -4,6 +4,7 @@ @using RMuseum.Models.Ganjoor @using RMuseum.Services.Implementation @using DNTPersianUtils.Core; +@using GanjooRazor.Utils @{ Layout = "_UserPanelLayout"; ViewData["Title"] = "سوابق ویرایش"; @@ -173,7 +174,7 @@ else { - برچسب جغرافیایی/تاریخی - + @(GeoDateTagCorrectionDisplay.IsPersonTag(geoTag) ? "شخصیت" : "برچسب جغرافیایی/تاریخی") - @if (geoTag.CoupletIndex == null) { کل شعر @@ -195,6 +196,27 @@ else } + else if (GeoDateTagCorrectionDisplay.IsPersonTag(geoTag)) + { + + +

-

+ + +

+ @if (geoTag.PersonId != null) + { + @(geoTag.Person != null ? geoTag.Person.Name : $"شخصیت #{geoTag.PersonId}") + } + else + { + var suggestedPersonName = GeoDateTagCorrectionDisplay.GetSuggestedPersonName(geoTag.SuggestedPersonGraphJson); + شخصیت جدید@(string.IsNullOrEmpty(suggestedPersonName) ? "" : $": {suggestedPersonName}") + } +

+ + + } else { diff --git a/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml.cs b/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml.cs index 87a743b4..e4958e4c 100644 --- a/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml.cs +++ b/GanjooRazor/Areas/User/Pages/PoemCorrectionsHistory.cshtml.cs @@ -247,6 +247,11 @@ namespace GanjooRazor.Areas.User.Pages var geoDateTagsRollback = new List(); foreach (var geoTag in currentCorrection.GeoDateTags.Where(g => g.Result == CorrectionReviewResult.Approved)) { + // PersonId (if the deleted tag was a person tag) is part of what got snapshotted + // onto this same record when the delete request was approved, so it's already + // available here for GeoDateTagCorrectionDisplay.IsPersonTag to tell the two kinds + // of tag apart for the note text below. + var geoTagLabel = GeoDateTagCorrectionDisplay.IsPersonTag(geoTag) ? "شخصیت" : "برچسب جغرافیایی/تاریخی"; if (geoTag.MarkForDelete) { // the original request deleted an existing tag - undo that by re-adding a tag with @@ -262,7 +267,7 @@ namespace GanjooRazor.Areas.User.Pages LunarDay = geoTag.LunarDay, PersonId = geoTag.PersonId, IgnoreInCategory = geoTag.IgnoreInCategory, - SuggestionNote = $"برگشت حذف برچسب جغرافیایی/تاریخی با کد {correctionId}" + SuggestionNote = $"برگشت حذف {geoTagLabel} با کد {correctionId}" }); } else if (geoTag.ExistingTagId != null) @@ -274,7 +279,7 @@ namespace GanjooRazor.Areas.User.Pages CoupletIndex = geoTag.CoupletIndex, MarkForDelete = true, ExistingTagId = geoTag.ExistingTagId, - SuggestionNote = $"برگشت افزودن برچسب جغرافیایی/تاریخی با کد {correctionId}" + SuggestionNote = $"برگشت افزودن {geoTagLabel} با کد {correctionId}" }); } } diff --git a/GanjooRazor/Utils/GeoDateTagCorrectionDisplay.cs b/GanjooRazor/Utils/GeoDateTagCorrectionDisplay.cs new file mode 100644 index 00000000..e625d77e --- /dev/null +++ b/GanjooRazor/Utils/GeoDateTagCorrectionDisplay.cs @@ -0,0 +1,51 @@ +using Newtonsoft.Json; +using RMuseum.Models.Ganjoor; +using RMuseum.Models.Ganjoor.ViewModels; + +namespace GanjooRazor.Utils +{ + /// + /// GanjoorPoemGeoDateTagCorrection (Editor.cshtml's combined geo/date/person tag suggestion row) + /// carries both kinds of tag in one flat shape - see that class's own doc comment for why. The + /// review-history pages (Edits.cshtml, PoemCorrectionsHistory.cshtml) need to tell the two kinds + /// apart to render each sensibly (a place+date vs. a person's name), so that little bit of shared + /// logic lives here once instead of being duplicated - and previously drifting out of sync - in + /// both .cshtml files. + /// + public static class GeoDateTagCorrectionDisplay + { + /// + /// true if this suggestion is a person (شخصیت) tag rather than a geo/date tag - mirrors the + /// client-side _getSuggestionUiKind() helper in Editor.cshtml's script block, but only for the + /// "adding a new tag" case: a MarkForDelete row carries neither PersonId nor a location, so its + /// kind can't be recovered from the correction alone (the callers fall back to the generic + /// "برچسب موجود" wording for those, same as before this helper existed). + /// + public static bool IsPersonTag(GanjoorPoemGeoDateTagCorrection tag) + { + if (tag == null) return false; + return tag.PersonId != null || !string.IsNullOrEmpty(tag.SuggestedPersonGraphJson); + } + + /// + /// best-effort display name for a brand-new person suggested via SuggestedPersonGraphJson - + /// just the name typed into the "new person" panel, ignoring any relatives/relations also + /// carried in that JSON (those aren't relevant to a one-line history row). Returns null if the + /// JSON is missing, malformed, or (defensively) has no person node. + /// + public static string GetSuggestedPersonName(string suggestedPersonGraphJson) + { + if (string.IsNullOrEmpty(suggestedPersonGraphJson)) return null; + try + { + var suggestion = JsonConvert.DeserializeObject(suggestedPersonGraphJson); + return suggestion?.Person?.Name; + } + catch (JsonException) + { + // malformed JSON shouldn't blow up a history page - just fall back to no name + return null; + } + } + } +}