+ اگر کاربر فرد را اشتباه تشخیص داده (مثلاً فردی که از قبل در فهرست است را بهعنوان فرد جدید پیشنهاد کرده)، بهجای رد کردن میتوانید آن را به فرد موجود متصل کنید؛
+ برای فرد تازه فقط نام قابل اصلاح است - اصلاح روابط/تاریخها نیازمند رد کردن و ارسال دوبارهٔ پیشنهاد توسط کاربر است:
+
+
+
+
+
+
+
+
برای اتصال به یک فرد موجود، نام او را تایپ کنید و از فهرست انتخاب کنید؛ برای رها کردن اتصال و پیشنهاد بهعنوان فرد جدید، این فیلد را خالی کنید.
+
+ @if (geoTag.PersonId == null)
+ {
+
+
+
+
+
+ }
+
+
+ }
}
diff --git a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs
index 22d23976..10e82d35 100644
--- a/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs
+++ b/GanjooRazor/Areas/Admin/Pages/ReviewEdits.cshtml.cs
@@ -79,6 +79,24 @@ namespace GanjooRazor.Areas.Admin.Pages
new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() }
);
+ ///
+ /// full people catalog, offered as an alternative to a user's new-person suggestion so the
+ /// moderator can correct a duplicate/misidentified suggestion by linking it to the existing
+ /// entry instead - same purpose as Locations above
+ ///
+ public List People { get; set; }
+
+ ///
+ /// camelCase JSON of People (id/name/birthYearInLHijri/deathYearInLHijri only), used
+ /// client-side for the search-as-you-type person picker on each geo tag (see
+ /// setupPersonAutocomplete in bk.js) - same shape/purpose as Editor.cshtml.cs's AllPeopleJson
+ ///
+ public string AllPeopleJson =>
+ JsonConvert.SerializeObject(
+ (People ?? new List()).Select(p => new { p.Id, p.Name, p.BirthYearInLHijri, p.DeathYearInLHijri }),
+ new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() }
+ );
+
///
/// 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
@@ -204,6 +222,16 @@ namespace GanjooRazor.Areas.Admin.Pages
Locations = new List();
Locations.Add(new GanjoorGeoLocation() { Id = 0, Latitude = 0, Longitude = 0, Name = "" });
Locations.AddRange(JsonConvert.DeserializeObject(await responseLocations.Content.ReadAsStringAsync()));
+
+ var responsePeople = await secureClient.GetAsync($"{APIRoot.Url}/api/people");
+ if (!responsePeople.IsSuccessStatusCode)
+ {
+ FatalError = JsonConvert.DeserializeObject(await responsePeople.Content.ReadAsStringAsync());
+ return Page();
+ }
+ People = new List();
+ People.Add(new GanjoorRelatedPerson() { Id = 0, Name = "" });
+ People.AddRange(JsonConvert.DeserializeObject(await responsePeople.Content.ReadAsStringAsync()));
}
if (PageInformation.Poem.Sections.Where(s => s.SectionType == PoemSectionType.WholePoem && !string.IsNullOrEmpty(s.RhymeLetters)).Any())
@@ -456,6 +484,37 @@ namespace GanjooRazor.Areas.Admin.Pages
Correction.GeoDateTags[i].SuggestedLongitude = correctedLng;
}
}
+
+ // same pattern as the location correction above, but for a suggested person
+ // instead of a suggested location - let the moderator link a suggestion to an
+ // existing catalog person (e.g. the contributor didn't find them in the search),
+ // or just fix a typo in a brand new person's name, before approving
+ string correctedPersonIdText = (pms.geoTagPersonId != null && i < pms.geoTagPersonId.Length) ? pms.geoTagPersonId[i] : null;
+ if (!string.IsNullOrWhiteSpace(correctedPersonIdText) && int.TryParse(correctedPersonIdText, out int correctedPersonId) && correctedPersonId > 0)
+ {
+ Correction.GeoDateTags[i].PersonId = correctedPersonId;
+ Correction.GeoDateTags[i].SuggestedPersonGraphJson = null;
+ }
+ else if (Correction.GeoDateTags[i].PersonId == null && !string.IsNullOrWhiteSpace(Correction.GeoDateTags[i].SuggestedPersonGraphJson))
+ {
+ string correctedPersonName = (pms.geoTagPersonName != null && i < pms.geoTagPersonName.Length) ? pms.geoTagPersonName[i] : null;
+ if (!string.IsNullOrWhiteSpace(correctedPersonName))
+ {
+ try
+ {
+ var personGraph = JObject.Parse(Correction.GeoDateTags[i].SuggestedPersonGraphJson);
+ if (personGraph["person"] != null)
+ {
+ personGraph["person"]["name"] = correctedPersonName.Trim();
+ Correction.GeoDateTags[i].SuggestedPersonGraphJson = personGraph.ToString(Newtonsoft.Json.Formatting.None);
+ }
+ }
+ catch (Exception)
+ {
+ return new BadRequestObjectResult("برچسب فرد پیشنهادی قابل تفسیر نیست.");
+ }
+ }
+ }
}
Correction.GeoDateTags[i].Result = (CorrectionReviewResult)Enum.Parse(typeof(CorrectionReviewResult), pms.geoTagReviewResult[i]);
diff --git a/GanjooRazor/Models/PoemMoerationStructure.cs b/GanjooRazor/Models/PoemMoerationStructure.cs
index 9a11ad4e..f6beab7a 100644
--- a/GanjooRazor/Models/PoemMoerationStructure.cs
+++ b/GanjooRazor/Models/PoemMoerationStructure.cs
@@ -32,5 +32,17 @@
///
public string[] geoTagLatitude { get; set; }
public string[] geoTagLongitude { get; set; }
+ ///
+ /// moderator's corrected person for each geo tag, if they picked an existing catalog person
+ /// instead of what the user suggested (empty/"0" means no change to PersonId) - same
+ /// purpose as geoTagLocationId above
+ ///
+ public string[] geoTagPersonId { get; set; }
+ ///
+ /// moderator's corrected name for a brand new person suggestion (fixes a typo in the user's
+ /// suggestion), if any - only the name can be corrected this way; deeper fixes (relations,
+ /// dates, etc.) require rejecting and asking the contributor to resubmit
+ ///
+ public string[] geoTagPersonName { get; set; }
}
}