people tags #387
This commit is contained in:
parent
800857aadc
commit
ddbef76d94
@ -19,6 +19,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
string AffiliationTypeName(PersonAffiliationType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case PersonAffiliationType.Minister: return "وزیر/کارگزار";
|
||||
case PersonAffiliationType.Advisor: return "مشاور";
|
||||
case PersonAffiliationType.Courtier: return "درباری/همراه";
|
||||
case PersonAffiliationType.Patron: return "حامی";
|
||||
case PersonAffiliationType.Ally: return "متحد";
|
||||
case PersonAffiliationType.Rival: return "رقیب";
|
||||
case PersonAffiliationType.Servant: return "خدمتگزار";
|
||||
case PersonAffiliationType.Companion: return "همدم";
|
||||
case PersonAffiliationType.Successor: return "جانشین";
|
||||
case PersonAffiliationType.Other: return "نوع دیگر";
|
||||
default: return t.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
string ActionName(PersonRelationSuggestionAction a)
|
||||
{
|
||||
switch (a)
|
||||
@ -49,6 +67,7 @@ else
|
||||
|
||||
<p>
|
||||
<span class="up-badge">@ActionName(s.Action)</span>
|
||||
<span class="up-badge">@(s.Kind == PersonRelationSuggestionKind.Affiliation ? "وابستگی غیرخویشاوندی" : "نسبت خویشاوندی")</span>
|
||||
</p>
|
||||
|
||||
<table>
|
||||
@ -111,25 +130,45 @@ else
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>نوع نسبت</td>
|
||||
<td>@(s.Action == PersonRelationSuggestionAction.Modify && s.ExistingRelation != null ? RelationTypeName(s.ExistingRelation.RelationType) : RelationTypeName(s.SuggestedRelationType))</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td>@RelationTypeName(s.SuggestedRelationType)</td>
|
||||
}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>درجه (در نیا/نواده)</td>
|
||||
<td>@((s.Action == PersonRelationSuggestionAction.Modify && s.ExistingRelation != null ? s.ExistingRelation.DegreeHint : s.SuggestedDegreeHint)?.ToString().ToPersianNumbers())</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td>@s.SuggestedDegreeHint?.ToString().ToPersianNumbers()</td>
|
||||
}
|
||||
</tr>
|
||||
@if (s.Kind == PersonRelationSuggestionKind.Affiliation)
|
||||
{
|
||||
<tr>
|
||||
<td>نوع وابستگی</td>
|
||||
<td>@(s.Action == PersonRelationSuggestionAction.Modify && s.ExistingAffiliation != null ? AffiliationTypeName(s.ExistingAffiliation.AffiliationType) : AffiliationTypeName(s.SuggestedAffiliationType ?? PersonAffiliationType.Other))</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td>@AffiliationTypeName(s.SuggestedAffiliationType ?? PersonAffiliationType.Other)</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
else
|
||||
{
|
||||
<tr>
|
||||
<td>نوع نسبت</td>
|
||||
<td>@(s.Action == PersonRelationSuggestionAction.Modify && s.ExistingRelation != null ? RelationTypeName(s.ExistingRelation.RelationType) : RelationTypeName(s.SuggestedRelationType))</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td>@RelationTypeName(s.SuggestedRelationType)</td>
|
||||
}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>درجه (در نیا/نواده)</td>
|
||||
<td>@((s.Action == PersonRelationSuggestionAction.Modify && s.ExistingRelation != null ? s.ExistingRelation.DegreeHint : s.SuggestedDegreeHint)?.ToString().ToPersianNumbers())</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td>@s.SuggestedDegreeHint?.ToString().ToPersianNumbers()</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>یادداشت</td>
|
||||
<td><small>@(s.Action == PersonRelationSuggestionAction.Modify && s.ExistingRelation != null ? s.ExistingRelation.Note : s.SuggestedNote)</small></td>
|
||||
<td>
|
||||
<small>
|
||||
@(s.Action == PersonRelationSuggestionAction.Modify
|
||||
? (s.Kind == PersonRelationSuggestionKind.Affiliation ? s.ExistingAffiliation?.Note : s.ExistingRelation?.Note)
|
||||
: s.SuggestedNote)
|
||||
</small>
|
||||
</td>
|
||||
@if (s.Action == PersonRelationSuggestionAction.Modify)
|
||||
{
|
||||
<td><small>@s.SuggestedNote</small></td>
|
||||
|
||||
@ -214,29 +214,6 @@
|
||||
document.getElementById('geotag-new-person-name').value = typedText;
|
||||
}
|
||||
);
|
||||
// birth/death location pickers inside the "new person" panel - these only ever pick an
|
||||
// existing location (a brand-new-location-within-a-brand-new-person is one indirection too
|
||||
// many for this form), so an unmatched search has nothing to offer
|
||||
setupLocationAutocomplete(
|
||||
document.getElementById('geotag-new-person-birthlocation-search'),
|
||||
document.getElementById('geotag-new-person-birthlocation-id'),
|
||||
document.getElementById('geotag-new-person-birthlocation-results'),
|
||||
allGeoLocations,
|
||||
null,
|
||||
function (typedText) {
|
||||
upToast('این مکان در فهرست نیست. ابتدا آن را جدا (در بخش «مکان» بالا) بهعنوان مکان جدید پیشنهاد دهید.', 'error');
|
||||
}
|
||||
);
|
||||
setupLocationAutocomplete(
|
||||
document.getElementById('geotag-new-person-deathlocation-search'),
|
||||
document.getElementById('geotag-new-person-deathlocation-id'),
|
||||
document.getElementById('geotag-new-person-deathlocation-results'),
|
||||
allGeoLocations,
|
||||
null,
|
||||
function (typedText) {
|
||||
upToast('این مکان در فهرست نیست. ابتدا آن را جدا (در بخش «مکان» بالا) بهعنوان مکان جدید پیشنهاد دهید.', 'error');
|
||||
}
|
||||
);
|
||||
});
|
||||
var geoDateTagMap = null;
|
||||
var geoDateTagMarker = null;
|
||||
@ -488,21 +465,22 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
var birthLocationId = $('#geotag-new-person-birthlocation-id').val();
|
||||
var deathLocationId = $('#geotag-new-person-deathlocation-id').val();
|
||||
|
||||
// birth/death year, "date is documented" and birth/death location are left out of this
|
||||
// form for now (no real usage of them yet elsewhere) - the shape below still carries all
|
||||
// of PersonGraphNode's fields, just with those ones always null/false, same as any other
|
||||
// field this form doesn't offer a control for.
|
||||
var person = {
|
||||
localKey: 'new',
|
||||
existingPersonId: null,
|
||||
name: name,
|
||||
description: $('#geotag-new-person-description').val() || null,
|
||||
wikiUrl: $('#geotag-new-person-wikiurl').val() || null,
|
||||
birthYearInLHijri: $('#geotag-new-person-birthyear').val() ? parseInt($('#geotag-new-person-birthyear').val()) : null,
|
||||
deathYearInLHijri: $('#geotag-new-person-deathyear').val() ? parseInt($('#geotag-new-person-deathyear').val()) : null,
|
||||
validBirthDate: $('#geotag-new-person-validbirth').is(':checked'),
|
||||
validDeathDate: $('#geotag-new-person-validdeath').is(':checked'),
|
||||
birthLocationId: birthLocationId ? parseInt(birthLocationId) : null,
|
||||
deathLocationId: deathLocationId ? parseInt(deathLocationId) : null,
|
||||
birthYearInLHijri: null,
|
||||
deathYearInLHijri: null,
|
||||
validBirthDate: false,
|
||||
validDeathDate: false,
|
||||
birthLocationId: null,
|
||||
deathLocationId: null,
|
||||
familyTreeCaption: $('#geotag-new-person-familytreecaption').val() || null
|
||||
};
|
||||
|
||||
@ -794,16 +772,6 @@
|
||||
$('#geotag-new-person-name').val('');
|
||||
$('#geotag-new-person-description').val('');
|
||||
$('#geotag-new-person-wikiurl').val('');
|
||||
$('#geotag-new-person-birthyear').val('');
|
||||
$('#geotag-new-person-deathyear').val('');
|
||||
$('#geotag-new-person-validbirth').prop('checked', false);
|
||||
$('#geotag-new-person-validdeath').prop('checked', false);
|
||||
$('#geotag-new-person-birthlocation-id').val('');
|
||||
$('#geotag-new-person-birthlocation-search').val('');
|
||||
$('#geotag-new-person-birthlocation-results').hide().empty();
|
||||
$('#geotag-new-person-deathlocation-id').val('');
|
||||
$('#geotag-new-person-deathlocation-search').val('');
|
||||
$('#geotag-new-person-deathlocation-results').hide().empty();
|
||||
$('#geotag-new-person-familytreecaption').val('');
|
||||
$('#geotag-person-relatives-list').empty();
|
||||
if (document.getElementById('new-person-widget').style.display !== 'none') {
|
||||
@ -2617,36 +2585,6 @@ else
|
||||
<label for="geotag-new-person-wikiurl">لینک ویکیپدیا (اختیاری)</label>
|
||||
<input type="text" id="geotag-new-person-wikiurl" />
|
||||
</div>
|
||||
<div class="up-field-row">
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-birthyear">سال تولد (قمری)</label>
|
||||
<input type="text" id="geotag-new-person-birthyear" />
|
||||
<span class="up-check-row"><input type="checkbox" id="geotag-new-person-validbirth" /><label for="geotag-new-person-validbirth">تاریخ تولد قطعی است</label></span>
|
||||
</div>
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-deathyear">سال وفات (قمری)</label>
|
||||
<input type="text" id="geotag-new-person-deathyear" />
|
||||
<span class="up-check-row"><input type="checkbox" id="geotag-new-person-validdeath" /><label for="geotag-new-person-validdeath">تاریخ وفات قطعی است</label></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="up-field-row">
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-birthlocation-search">محل تولد (اختیاری، فقط از مکانهای موجود در فهرست)</label>
|
||||
<div class="up-autocomplete-wrap">
|
||||
<input type="text" id="geotag-new-person-birthlocation-search" autocomplete="off" placeholder="نام مکان را تایپ کنید..." />
|
||||
<input type="hidden" id="geotag-new-person-birthlocation-id" />
|
||||
<div id="geotag-new-person-birthlocation-results" class="up-autocomplete-results" style="display:none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-deathlocation-search">محل وفات (اختیاری، فقط از مکانهای موجود در فهرست)</label>
|
||||
<div class="up-autocomplete-wrap">
|
||||
<input type="text" id="geotag-new-person-deathlocation-search" autocomplete="off" placeholder="نام مکان را تایپ کنید..." />
|
||||
<input type="hidden" id="geotag-new-person-deathlocation-id" />
|
||||
<div id="geotag-new-person-deathlocation-results" class="up-autocomplete-results" style="display:none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-familytreecaption">عنوان شجرهنامه (اختیاری، فقط اگر این شخصیت ریشهٔ یک خانواده/سلسله شناختهشده است - مثلاً «ساسانیان»)</label>
|
||||
<input type="text" id="geotag-new-person-familytreecaption" />
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
Layout = "_UserPanelLayout";
|
||||
ViewData["Title"] = "پیشنهاد خویشاوند جدید";
|
||||
ViewData["Title"] = "پیشنهاد خویشاوند یا وابستگی جدید";
|
||||
await GanjooRazor.Utils.GanjoorSessionChecker.ApplyPermissionsToViewData(Request, Response, ViewData);
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.LastError))
|
||||
@ -13,11 +13,11 @@
|
||||
else
|
||||
{
|
||||
<div class="up-page-header">
|
||||
<h1>پیشنهاد خویشاوند جدید برای: @Model.Person.Name</h1>
|
||||
<h1>پیشنهاد خویشاوند یا وابستگی جدید برای: @Model.Person.Name</h1>
|
||||
</div>
|
||||
|
||||
<p class="up-hint">
|
||||
این پیشنهاد مستقیماً اعمال نمیشود؛ پس از بررسی و تأیید توسط مدیران، به شجرهنامهٔ
|
||||
این پیشنهاد مستقیماً اعمال نمیشود؛ پس از بررسی و تأیید توسط مدیران، به شجرهنامه/شبکهٔ وابستگیهای
|
||||
<a href="javascript:void(0)" onclick="PersonWindow.open(@Model.Person.Id)">@Model.Person.Name</a> افزوده خواهد شد.
|
||||
</p>
|
||||
|
||||
@ -32,7 +32,7 @@ else
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>خویشاوند:</td>
|
||||
<td>خویشاوند یا شخصیت دیگر:</td>
|
||||
<td>
|
||||
<select asp-for="OtherPersonId">
|
||||
<option value="0">— انتخاب کنید —</option>
|
||||
@ -43,6 +43,18 @@ else
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>نوع پیوند:</td>
|
||||
<td>
|
||||
<select id="RelationKindGroup" asp-for="RelationKindGroup">
|
||||
<option value="family">نسبت خویشاوندی (پدر/مادر، فرزند، همسر، نیا/نواده...)</option>
|
||||
<option value="affiliation">وابستگی غیرخویشاوندی (وزیر، مشاور، حامی، متحد، رقیب...)</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="family-relation-fields">
|
||||
<tr>
|
||||
<td>نسبت با @Model.Person.Name:</td>
|
||||
<td>
|
||||
@ -63,6 +75,35 @@ else
|
||||
</td>
|
||||
<td><input asp-for="DegreeHint" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table id="affiliation-fields" style="display:none">
|
||||
<tr>
|
||||
<td>وابستگی با @Model.Person.Name:</td>
|
||||
<td>
|
||||
<select asp-for="AffiliationKind">
|
||||
<option value="Minister_Other">او وزیر یا کارگزار این شخصیت بود</option>
|
||||
<option value="Minister_Subject">این شخصیت وزیر یا کارگزار او بود</option>
|
||||
<option value="Advisor_Other">او مشاور این شخصیت بود</option>
|
||||
<option value="Advisor_Subject">این شخصیت مشاور او بود</option>
|
||||
<option value="Courtier_Other">او از درباریان/همراهان این شخصیت بود</option>
|
||||
<option value="Courtier_Subject">این شخصیت از درباریان/همراهان او بود</option>
|
||||
<option value="Servant_Other">او خدمتگزار این شخصیت بود</option>
|
||||
<option value="Servant_Subject">این شخصیت خدمتگزار او بود</option>
|
||||
<option value="Patron_Other">او از این شخصیت حمایت میکرد (حامی او بود)</option>
|
||||
<option value="Patron_Subject">این شخصیت از او حمایت میکرد (حامی او بود)</option>
|
||||
<option value="Successor_Other">او جانشین این شخصیت شد (پس از او آمد)</option>
|
||||
<option value="Successor_Subject">این شخصیت جانشین او شد (پس از او آمد)</option>
|
||||
<option value="Ally">با او متحد/همپیمان بود</option>
|
||||
<option value="Rival">با او رقیب/دشمن بود</option>
|
||||
<option value="Companion">با او همراه/همدم بود</option>
|
||||
<option value="Other">نوع دیگر (در یادداشت توضیح دهید)</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>یادداشت (مستندسازی):</td>
|
||||
<td><textarea asp-for="Note" rows="3" cols="60"></textarea></td>
|
||||
@ -77,4 +118,21 @@ else
|
||||
<a role="button" href="javascript:void(0)" onclick="history.back()" class="up-btn up-btn--ghost">انصراف</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var groupSelect = document.getElementById('RelationKindGroup');
|
||||
var familyFields = document.getElementById('family-relation-fields');
|
||||
var affiliationFields = document.getElementById('affiliation-fields');
|
||||
|
||||
function applyKindGroup() {
|
||||
var isAffiliation = groupSelect.value === 'affiliation';
|
||||
familyFields.style.display = isAffiliation ? 'none' : '';
|
||||
affiliationFields.style.display = isAffiliation ? '' : 'none';
|
||||
}
|
||||
|
||||
groupSelect.addEventListener('change', applyKindGroup);
|
||||
applyKindGroup();
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
|
||||
@ -14,14 +14,17 @@ using RMuseum.Models.Ganjoor;
|
||||
namespace GanjooRazor.Areas.User.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// contributor-facing form for suggesting a brand new kinship edge between the subject person
|
||||
/// and another already-approved person - the "Add" counterpart of SuggestPersonRelationEdit.cshtml
|
||||
/// (which only handles Modify/Remove of an already-existing edge). Presents a direction-aware
|
||||
/// "RelationKind" choice (e.g. "فرزند" vs "پدر یا مادر") from the subject's point of view, and
|
||||
/// translates it into the correct Person1Id/Person2Id/RelationType triple before submitting -
|
||||
/// GanjoorPersonRelation itself has no notion of "from the subject's point of view", only
|
||||
/// Person1/Person2, so that translation has to happen somewhere, and doing it here keeps the
|
||||
/// underlying suggestion/moderation code simple and symmetric.
|
||||
/// contributor-facing form for suggesting a brand new edge between the subject person and
|
||||
/// another already-approved person - the "Add" counterpart of SuggestPersonRelationEdit.cshtml
|
||||
/// (which only handles Modify/Remove of an already-existing edge). Covers both kinds of edge:
|
||||
/// a family/kinship tie (GanjoorPersonRelation, via RelationKind) and a non-family affiliation
|
||||
/// tie (GanjoorPersonAffiliation, via AffiliationKind) - RelationKindGroup picks which. Both
|
||||
/// present a direction-aware choice from the subject's point of view (e.g. "فرزند" vs "پدر یا
|
||||
/// مادر", or "او وزیر این شخصیت بود" vs "این شخصیت وزیر او بود") and translate it into the
|
||||
/// symmetric Person1Id/Person2Id/type triple the underlying entity actually stores - neither
|
||||
/// GanjoorPersonRelation nor GanjoorPersonAffiliation has any notion of "from the subject's own
|
||||
/// point of view", only Person1/Person2, so that translation has to happen somewhere, and doing
|
||||
/// it here keeps the underlying suggestion/moderation code simple and symmetric.
|
||||
/// </summary>
|
||||
public class SuggestNewPersonRelationModel : LoginPartialEnabledPageModel
|
||||
{
|
||||
@ -40,9 +43,23 @@ namespace GanjooRazor.Areas.User.Pages
|
||||
[BindProperty]
|
||||
public int OtherPersonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// "family" (default) or "affiliation" - which of RelationKind/AffiliationKind below applies
|
||||
/// </summary>
|
||||
[BindProperty]
|
||||
public string RelationKindGroup { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string RelationKind { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// combined type+direction key for a non-family tie, e.g. "Minister_Subject" meaning
|
||||
/// "this person served as minister to the other person" - see the switch in
|
||||
/// OnPostSuggestAsync for the full list and their direction handling
|
||||
/// </summary>
|
||||
[BindProperty]
|
||||
public string AffiliationKind { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public int? DegreeHint { get; set; }
|
||||
|
||||
@ -112,12 +129,10 @@ namespace GanjooRazor.Areas.User.Pages
|
||||
|
||||
if (OtherPersonId == 0 || OtherPersonId == personId)
|
||||
{
|
||||
LastResult = "لطفاً خویشاوند مورد نظر را انتخاب کنید.";
|
||||
LastResult = "لطفاً خویشاوند یا شخصیت مورد نظر را انتخاب کنید.";
|
||||
return Page();
|
||||
}
|
||||
|
||||
// translate the direction-aware choice (from Person's own point of view) into the
|
||||
// symmetric Person1Id/Person2Id/RelationType triple GanjoorPersonRelation actually stores
|
||||
var suggestion = new GanjoorPersonRelationEditSuggestion()
|
||||
{
|
||||
Action = PersonRelationSuggestionAction.Add,
|
||||
@ -126,41 +141,142 @@ namespace GanjooRazor.Areas.User.Pages
|
||||
SuggestionNote = string.IsNullOrWhiteSpace(SuggestionNote) ? null : SuggestionNote.Trim(),
|
||||
};
|
||||
|
||||
switch (RelationKind)
|
||||
if (RelationKindGroup == "affiliation")
|
||||
{
|
||||
case "Child": // OtherPerson is a child of Person
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Parent;
|
||||
break;
|
||||
case "Parent": // OtherPerson is a parent of Person
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Parent;
|
||||
break;
|
||||
case "Sibling":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Sibling;
|
||||
break;
|
||||
case "Spouse":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Spouse;
|
||||
break;
|
||||
case "DistantAncestor": // OtherPerson is a distant ancestor of Person
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Ancestor;
|
||||
break;
|
||||
case "DistantDescendant": // OtherPerson is a distant descendant of Person
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Ancestor;
|
||||
break;
|
||||
default:
|
||||
LastResult = "نوع نسبت نامعتبر است.";
|
||||
return Page();
|
||||
suggestion.Kind = PersonRelationSuggestionKind.Affiliation;
|
||||
|
||||
// OtherIsPerson1/SubjectIsPerson1 pairs translate the direction-aware choice into the
|
||||
// symmetric Person1Id/Person2Id pair, following the direction each PersonAffiliationType
|
||||
// value's own doc comment defines (Minister/Advisor/Courtier/Servant: Person1 is the
|
||||
// subordinate one; Patron/Successor: Person1 is the patron/later one; Ally/Rival/
|
||||
// Companion/Other: symmetric, direction doesn't matter)
|
||||
switch (AffiliationKind)
|
||||
{
|
||||
case "Minister_Other": // the other person served as minister to this one
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Minister;
|
||||
break;
|
||||
case "Minister_Subject": // this person served as minister to the other one
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Minister;
|
||||
break;
|
||||
case "Advisor_Other":
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Advisor;
|
||||
break;
|
||||
case "Advisor_Subject":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Advisor;
|
||||
break;
|
||||
case "Courtier_Other":
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Courtier;
|
||||
break;
|
||||
case "Courtier_Subject":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Courtier;
|
||||
break;
|
||||
case "Servant_Other":
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Servant;
|
||||
break;
|
||||
case "Servant_Subject":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Servant;
|
||||
break;
|
||||
case "Patron_Other": // the other person was patron of this one
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Patron;
|
||||
break;
|
||||
case "Patron_Subject": // this person was patron of the other one
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Patron;
|
||||
break;
|
||||
case "Successor_Other": // the other person succeeded this one
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Successor;
|
||||
break;
|
||||
case "Successor_Subject": // this person succeeded the other one
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Successor;
|
||||
break;
|
||||
case "Ally":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Ally;
|
||||
break;
|
||||
case "Rival":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Rival;
|
||||
break;
|
||||
case "Companion":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Companion;
|
||||
break;
|
||||
case "Other":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedAffiliationType = PersonAffiliationType.Other;
|
||||
break;
|
||||
default:
|
||||
LastResult = "نوع وابستگی نامعتبر است.";
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
suggestion.Kind = PersonRelationSuggestionKind.Family;
|
||||
|
||||
switch (RelationKind)
|
||||
{
|
||||
case "Child": // OtherPerson is a child of Person
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Parent;
|
||||
break;
|
||||
case "Parent": // OtherPerson is a parent of Person
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Parent;
|
||||
break;
|
||||
case "Sibling":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Sibling;
|
||||
break;
|
||||
case "Spouse":
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Spouse;
|
||||
break;
|
||||
case "DistantAncestor": // OtherPerson is a distant ancestor of Person
|
||||
suggestion.Person1Id = OtherPersonId;
|
||||
suggestion.Person2Id = personId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Ancestor;
|
||||
break;
|
||||
case "DistantDescendant": // OtherPerson is a distant descendant of Person
|
||||
suggestion.Person1Id = personId;
|
||||
suggestion.Person2Id = OtherPersonId;
|
||||
suggestion.SuggestedRelationType = PersonRelationType.Ancestor;
|
||||
break;
|
||||
default:
|
||||
LastResult = "نوع نسبت نامعتبر است.";
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
||||
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
|
||||
|
||||
@ -30,6 +30,17 @@ else
|
||||
<form method="post" action="/User/SuggestPersonEdit?id=@Model.Person.Id&Handler=SuggestEdit">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" asp-for="Suggestion.PersonId" />
|
||||
@* birth/death year, "date is documented" and birth/death location have no UI here for now
|
||||
(no real usage of them elsewhere yet) - carried through as hidden fields instead of
|
||||
dropped outright, so submitting this form never blanks out whatever the person record
|
||||
already has for these on approval (GanjoorRelatedPersonService applies every Suggested*
|
||||
field unconditionally, with no "did they actually change this" check). *@
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedBirthYearInLHijri" />
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedValidBirthDate" />
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedBirthLocationId" />
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedDeathYearInLHijri" />
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedValidDeathDate" />
|
||||
<input type="hidden" asp-for="Suggestion.SuggestedDeathLocationId" />
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@ -47,44 +58,6 @@ else
|
||||
<td>نشانی ویکیپدیا:</td>
|
||||
<td><input style="text-align:left;direction:ltr;" asp-for="Suggestion.SuggestedWikiUrl" size="60" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>زاده:</td>
|
||||
<td><input asp-for="Suggestion.SuggestedBirthYearInLHijri" /> (قمری)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>تاریخ تولد مستند است:</td>
|
||||
<td><input asp-for="Suggestion.SuggestedValidBirthDate" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>زادگاه:</td>
|
||||
<td>
|
||||
<select asp-for="Suggestion.SuggestedBirthLocationId">
|
||||
@foreach (var location in Model.Locations)
|
||||
{
|
||||
<option value="@(location.Id == 0 ? "" : location.Id.ToString())">@location.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>درگذشته:</td>
|
||||
<td><input asp-for="Suggestion.SuggestedDeathYearInLHijri" /> (قمری)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>تاریخ وفات مستند است:</td>
|
||||
<td><input asp-for="Suggestion.SuggestedValidDeathDate" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>آرامگاه:</td>
|
||||
<td>
|
||||
<select asp-for="Suggestion.SuggestedDeathLocationId">
|
||||
@foreach (var location in Model.Locations)
|
||||
{
|
||||
<option value="@(location.Id == 0 ? "" : location.Id.ToString())">@location.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
عنوان شجرهنامه:
|
||||
|
||||
@ -177,6 +177,14 @@ namespace RMuseum.DbContext
|
||||
.HasForeignKey(s => s.ExistingRelationId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// same Restrict treatment as ExistingRelationId above, but for Kind == Affiliation
|
||||
// suggestions targeting a GanjoorPersonAffiliation instead
|
||||
builder.Entity<GanjoorPersonRelationEditSuggestion>()
|
||||
.HasOne(s => s.ExistingAffiliation)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.ExistingAffiliationId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.Entity<GanjoorUserBookmark>()
|
||||
.HasIndex(b => new { b.UserId, b.PoemId, b.CoupletIndex });
|
||||
|
||||
|
||||
6613
RMuseum/Migrations/20260930170542_AddPersonRelationSuggestionAffiliationSupport.Designer.cs
generated
Normal file
6613
RMuseum/Migrations/20260930170542_AddPersonRelationSuggestionAffiliationSupport.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,70 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RMuseum.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPersonRelationSuggestionAffiliationSupport : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Kind",
|
||||
table: "GanjoorPersonRelationEditSuggestions",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SuggestedAffiliationType",
|
||||
table: "GanjoorPersonRelationEditSuggestions",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GanjoorPersonRelationEditSuggestions_ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions",
|
||||
column: "ExistingAffiliationId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GanjoorPersonRelationEditSuggestions_GanjoorPersonAffiliations_ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions",
|
||||
column: "ExistingAffiliationId",
|
||||
principalTable: "GanjoorPersonAffiliations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GanjoorPersonRelationEditSuggestions_GanjoorPersonAffiliations_ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GanjoorPersonRelationEditSuggestions_ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ExistingAffiliationId",
|
||||
table: "GanjoorPersonRelationEditSuggestions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Kind",
|
||||
table: "GanjoorPersonRelationEditSuggestions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SuggestedAffiliationType",
|
||||
table: "GanjoorPersonRelationEditSuggestions");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1557,9 +1557,15 @@ namespace RMuseum.Migrations
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<int?>("ExistingAffiliationId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("ExistingRelationId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Kind")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Person1Id")
|
||||
.HasColumnType("int");
|
||||
|
||||
@ -1581,6 +1587,9 @@ namespace RMuseum.Migrations
|
||||
b.Property<Guid?>("ReviewerUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int?>("SuggestedAffiliationType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("SuggestedDegreeHint")
|
||||
.HasColumnType("int");
|
||||
|
||||
@ -1598,6 +1607,8 @@ namespace RMuseum.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ExistingAffiliationId");
|
||||
|
||||
b.HasIndex("ExistingRelationId");
|
||||
|
||||
b.HasIndex("Person1Id");
|
||||
@ -5514,6 +5525,11 @@ namespace RMuseum.Migrations
|
||||
|
||||
modelBuilder.Entity("RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion", b =>
|
||||
{
|
||||
b.HasOne("RMuseum.Models.Ganjoor.GanjoorPersonAffiliation", "ExistingAffiliation")
|
||||
.WithMany()
|
||||
.HasForeignKey("ExistingAffiliationId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("RMuseum.Models.Ganjoor.GanjoorPersonRelation", "ExistingRelation")
|
||||
.WithMany()
|
||||
.HasForeignKey("ExistingRelationId")
|
||||
@ -5541,6 +5557,8 @@ namespace RMuseum.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("ExistingAffiliation");
|
||||
|
||||
b.Navigation("ExistingRelation");
|
||||
|
||||
b.Navigation("Person1");
|
||||
|
||||
@ -23,17 +23,39 @@ namespace RMuseum.Models.Ganjoor
|
||||
public PersonRelationSuggestionAction Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// for Modify/Remove: the existing GanjoorPersonRelation row this suggestion targets. Null
|
||||
/// for Add, where there's nothing existing yet.
|
||||
/// whether this suggestion is about a kinship edge (Family, using SuggestedRelationType /
|
||||
/// ExistingRelationId / ExistingRelation) or a non-family affiliation edge (Affiliation, using
|
||||
/// SuggestedAffiliationType / ExistingAffiliationId / ExistingAffiliation instead). Defaults
|
||||
/// to Family so rows created before this field existed keep working unchanged.
|
||||
/// </summary>
|
||||
public PersonRelationSuggestionKind Kind { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// for Modify/Remove when Kind is Family: the existing GanjoorPersonRelation row this
|
||||
/// suggestion targets. Null for Add, where there's nothing existing yet, and for any
|
||||
/// Kind == Affiliation suggestion (see ExistingAffiliationId instead).
|
||||
/// </summary>
|
||||
public int? ExistingRelationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the existing relation being modified/removed (for showing a before/after diff to the
|
||||
/// moderator) - null for Add
|
||||
/// moderator) - null for Add, and for Kind == Affiliation
|
||||
/// </summary>
|
||||
public virtual GanjoorPersonRelation ExistingRelation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// for Modify/Remove when Kind is Affiliation: the existing GanjoorPersonAffiliation row this
|
||||
/// suggestion targets. Null for Add, and for any Kind == Family suggestion (see
|
||||
/// ExistingRelationId instead).
|
||||
/// </summary>
|
||||
public int? ExistingAffiliationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the existing affiliation being modified/removed (for showing a before/after diff to the
|
||||
/// moderator) - null unless Kind is Affiliation and Action is Modify/Remove
|
||||
/// </summary>
|
||||
public virtual GanjoorPersonAffiliation ExistingAffiliation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the pair this suggestion is about. For Add, this and Person2Id define the new relation.
|
||||
/// For Modify/Remove, these are copied from ExistingRelation at submission time, so the
|
||||
@ -58,11 +80,19 @@ namespace RMuseum.Models.Ganjoor
|
||||
public virtual GanjoorRelatedPerson Person2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// for Add/Modify: the relation type to create/change to. For Remove: a snapshot of the
|
||||
/// existing relation's type at submission time, purely for display (removing doesn't use it).
|
||||
/// for Add/Modify when Kind is Family: the relation type to create/change to. For Remove: a
|
||||
/// snapshot of the existing relation's type at submission time, purely for display (removing
|
||||
/// doesn't use it). Ignored when Kind is Affiliation - see SuggestedAffiliationType instead.
|
||||
/// </summary>
|
||||
public PersonRelationType SuggestedRelationType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// for Add/Modify when Kind is Affiliation: the affiliation type to create/change to. For
|
||||
/// Remove: a snapshot of the existing affiliation's type at submission time, purely for
|
||||
/// display. Null/ignored when Kind is Family - see SuggestedRelationType instead.
|
||||
/// </summary>
|
||||
public PersonAffiliationType? SuggestedAffiliationType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// see GanjoorPersonRelation.DegreeHint - same for/Add/Modify/Remove-display purpose as
|
||||
/// SuggestedRelationType above
|
||||
|
||||
16
RMuseum/Models/Ganjoor/PersonRelationSuggestionKind.cs
Normal file
16
RMuseum/Models/Ganjoor/PersonRelationSuggestionKind.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace RMuseum.Models.Ganjoor
|
||||
{
|
||||
/// <summary>
|
||||
/// which kind of edge a GanjoorPersonRelationEditSuggestion is about: a kinship tie
|
||||
/// (GanjoorPersonRelation, via SuggestedRelationType/ExistingRelationId) or a non-family
|
||||
/// affiliation tie (GanjoorPersonAffiliation, via SuggestedAffiliationType/ExistingAffiliationId).
|
||||
/// Defaults to Family (0), so every suggestion row created before this field existed keeps being
|
||||
/// read exactly as it was before - a plain kinship suggestion.
|
||||
/// </summary>
|
||||
public enum PersonRelationSuggestionKind
|
||||
{
|
||||
Family = 0,
|
||||
|
||||
Affiliation = 1,
|
||||
}
|
||||
}
|
||||
@ -4955,6 +4955,18 @@
|
||||
<member name="M:RMuseum.Migrations.AddGanjoorPersonRelationEditSuggestion.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:RMuseum.Migrations.AddPersonRelationSuggestionAffiliationSupport">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:RMuseum.Migrations.AddPersonRelationSuggestionAffiliationSupport.Up(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:RMuseum.Migrations.AddPersonRelationSuggestionAffiliationSupport.Down(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:RMuseum.Migrations.AddPersonRelationSuggestionAffiliationSupport.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Accounting.DonationExpenditure">
|
||||
<summary>
|
||||
donation expenditures
|
||||
@ -9590,16 +9602,38 @@
|
||||
what this suggestion proposes doing
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.Kind">
|
||||
<summary>
|
||||
whether this suggestion is about a kinship edge (Family, using SuggestedRelationType /
|
||||
ExistingRelationId / ExistingRelation) or a non-family affiliation edge (Affiliation, using
|
||||
SuggestedAffiliationType / ExistingAffiliationId / ExistingAffiliation instead). Defaults
|
||||
to Family so rows created before this field existed keep working unchanged.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.ExistingRelationId">
|
||||
<summary>
|
||||
for Modify/Remove: the existing GanjoorPersonRelation row this suggestion targets. Null
|
||||
for Add, where there's nothing existing yet.
|
||||
for Modify/Remove when Kind is Family: the existing GanjoorPersonRelation row this
|
||||
suggestion targets. Null for Add, where there's nothing existing yet, and for any
|
||||
Kind == Affiliation suggestion (see ExistingAffiliationId instead).
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.ExistingRelation">
|
||||
<summary>
|
||||
the existing relation being modified/removed (for showing a before/after diff to the
|
||||
moderator) - null for Add
|
||||
moderator) - null for Add, and for Kind == Affiliation
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.ExistingAffiliationId">
|
||||
<summary>
|
||||
for Modify/Remove when Kind is Affiliation: the existing GanjoorPersonAffiliation row this
|
||||
suggestion targets. Null for Add, and for any Kind == Family suggestion (see
|
||||
ExistingRelationId instead).
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.ExistingAffiliation">
|
||||
<summary>
|
||||
the existing affiliation being modified/removed (for showing a before/after diff to the
|
||||
moderator) - null unless Kind is Affiliation and Action is Modify/Remove
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.Person1Id">
|
||||
@ -9627,8 +9661,16 @@
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.SuggestedRelationType">
|
||||
<summary>
|
||||
for Add/Modify: the relation type to create/change to. For Remove: a snapshot of the
|
||||
existing relation's type at submission time, purely for display (removing doesn't use it).
|
||||
for Add/Modify when Kind is Family: the relation type to create/change to. For Remove: a
|
||||
snapshot of the existing relation's type at submission time, purely for display (removing
|
||||
doesn't use it). Ignored when Kind is Affiliation - see SuggestedAffiliationType instead.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.SuggestedAffiliationType">
|
||||
<summary>
|
||||
for Add/Modify when Kind is Affiliation: the affiliation type to create/change to. For
|
||||
Remove: a snapshot of the existing affiliation's type at submission time, purely for
|
||||
display. Null/ignored when Kind is Family - see SuggestedRelationType instead.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonRelationEditSuggestion.SuggestedDegreeHint">
|
||||
@ -11819,6 +11861,15 @@
|
||||
remove the existing relation ExistingRelationId points to outright
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.PersonRelationSuggestionKind">
|
||||
<summary>
|
||||
which kind of edge a GanjoorPersonRelationEditSuggestion is about: a kinship tie
|
||||
(GanjoorPersonRelation, via SuggestedRelationType/ExistingRelationId) or a non-family
|
||||
affiliation tie (GanjoorPersonAffiliation, via SuggestedAffiliationType/ExistingAffiliationId).
|
||||
Defaults to Family (0), so every suggestion row created before this field existed keeps being
|
||||
read exactly as it was before - a plain kinship suggestion.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.PersonRelationType">
|
||||
<summary>
|
||||
the kind of kinship edge a GanjoorPersonRelation represents between two GanjoorRelatedPerson
|
||||
|
||||
@ -465,16 +465,18 @@ namespace RMuseum.Services.Implementation
|
||||
var affiliations = await _context.GanjoorPersonAffiliations
|
||||
.Where(a => a.Person1Id == person.Id || a.Person2Id == person.Id)
|
||||
.ToListAsync();
|
||||
var affiliationIds = affiliations.Select(a => a.Id).ToList();
|
||||
|
||||
// any other still-pending relation-edit suggestion that touches this person directly, or
|
||||
// targets one of the relations we're about to remove, would otherwise dangle or violate
|
||||
// the Restrict FK above - auto-reject those with an explanatory note rather than letting
|
||||
// the delete fail or silently drop them
|
||||
// targets one of the relations/affiliations we're about to remove, would otherwise dangle
|
||||
// or violate the Restrict FKs above - auto-reject those with an explanatory note rather
|
||||
// than letting the delete fail or silently drop them
|
||||
var conflictingRelationSuggestions = await _context.GanjoorPersonRelationEditSuggestions
|
||||
.Where(s => !s.Reviewed && (
|
||||
s.Person1Id == person.Id ||
|
||||
s.Person2Id == person.Id ||
|
||||
(s.ExistingRelationId != null && relationIds.Contains(s.ExistingRelationId.Value))
|
||||
(s.ExistingRelationId != null && relationIds.Contains(s.ExistingRelationId.Value)) ||
|
||||
(s.ExistingAffiliationId != null && affiliationIds.Contains(s.ExistingAffiliationId.Value))
|
||||
))
|
||||
.ToListAsync();
|
||||
foreach (var conflicting in conflictingRelationSuggestions)
|
||||
@ -553,34 +555,65 @@ namespace RMuseum.Services.Implementation
|
||||
}
|
||||
|
||||
GanjoorPersonRelation existingRelation = null;
|
||||
GanjoorPersonAffiliation existingAffiliation = null;
|
||||
if (suggestion.Action == PersonRelationSuggestionAction.Modify || suggestion.Action == PersonRelationSuggestionAction.Remove)
|
||||
{
|
||||
if (suggestion.ExistingRelationId == null)
|
||||
if (suggestion.Kind == PersonRelationSuggestionKind.Affiliation)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر برای ویرایش یا حذف مشخص نشده است.");
|
||||
if (suggestion.ExistingAffiliationId == null)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "وابستگی مورد نظر برای ویرایش یا حذف مشخص نشده است.");
|
||||
}
|
||||
|
||||
existingAffiliation = await _context.GanjoorPersonAffiliations
|
||||
.Include(a => a.Person1)
|
||||
.Include(a => a.Person2)
|
||||
.Where(a => a.Id == suggestion.ExistingAffiliationId.Value)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
if (existingAffiliation == null)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "وابستگی مورد نظر پیدا نشد.");
|
||||
}
|
||||
|
||||
// same trust-the-existing-row convention as the Family branch below
|
||||
suggestion.Person1Id = existingAffiliation.Person1Id;
|
||||
suggestion.Person2Id = existingAffiliation.Person2Id;
|
||||
if (suggestion.Action == PersonRelationSuggestionAction.Remove)
|
||||
{
|
||||
suggestion.SuggestedAffiliationType = existingAffiliation.AffiliationType;
|
||||
suggestion.SuggestedNote = existingAffiliation.Note;
|
||||
}
|
||||
}
|
||||
|
||||
existingRelation = await _context.GanjoorPersonRelations
|
||||
.Include(r => r.Person1)
|
||||
.Include(r => r.Person2)
|
||||
.Where(r => r.Id == suggestion.ExistingRelationId.Value)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
if (existingRelation == null)
|
||||
else
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر پیدا نشد.");
|
||||
}
|
||||
if (suggestion.ExistingRelationId == null)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر برای ویرایش یا حذف مشخص نشده است.");
|
||||
}
|
||||
|
||||
// always trust the existing relation's own Person1Id/Person2Id/type/etc over
|
||||
// whatever the client sent, so the suggestion is guaranteed self-consistent with
|
||||
// what it actually targets, even for a Remove-display
|
||||
suggestion.Person1Id = existingRelation.Person1Id;
|
||||
suggestion.Person2Id = existingRelation.Person2Id;
|
||||
if (suggestion.Action == PersonRelationSuggestionAction.Remove)
|
||||
{
|
||||
suggestion.SuggestedRelationType = existingRelation.RelationType;
|
||||
suggestion.SuggestedDegreeHint = existingRelation.DegreeHint;
|
||||
suggestion.SuggestedNote = existingRelation.Note;
|
||||
existingRelation = await _context.GanjoorPersonRelations
|
||||
.Include(r => r.Person1)
|
||||
.Include(r => r.Person2)
|
||||
.Where(r => r.Id == suggestion.ExistingRelationId.Value)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
if (existingRelation == null)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر پیدا نشد.");
|
||||
}
|
||||
|
||||
// always trust the existing relation's own Person1Id/Person2Id/type/etc over
|
||||
// whatever the client sent, so the suggestion is guaranteed self-consistent with
|
||||
// what it actually targets, even for a Remove-display
|
||||
suggestion.Person1Id = existingRelation.Person1Id;
|
||||
suggestion.Person2Id = existingRelation.Person2Id;
|
||||
if (suggestion.Action == PersonRelationSuggestionAction.Remove)
|
||||
{
|
||||
suggestion.SuggestedRelationType = existingRelation.RelationType;
|
||||
suggestion.SuggestedDegreeHint = existingRelation.DegreeHint;
|
||||
suggestion.SuggestedNote = existingRelation.Note;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Add
|
||||
@ -600,6 +633,7 @@ namespace RMuseum.Services.Implementation
|
||||
|
||||
suggestion.Id = 0;
|
||||
suggestion.ExistingRelation = null;
|
||||
suggestion.ExistingAffiliation = null;
|
||||
suggestion.Person1 = null;
|
||||
suggestion.Person2 = null;
|
||||
suggestion.Date = DateTime.Now;
|
||||
@ -613,17 +647,19 @@ namespace RMuseum.Services.Implementation
|
||||
_context.GanjoorPersonRelationEditSuggestions.Add(suggestion);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
bool isAffiliation = suggestion.Kind == PersonRelationSuggestionKind.Affiliation;
|
||||
string actionTitle = suggestion.Action switch
|
||||
{
|
||||
PersonRelationSuggestionAction.Add => "پیشنهاد نسبت خویشاوندی جدید",
|
||||
PersonRelationSuggestionAction.Modify => "پیشنهاد ویرایش نسبت خویشاوندی",
|
||||
_ => "پیشنهاد حذف نسبت خویشاوندی",
|
||||
PersonRelationSuggestionAction.Add => isAffiliation ? "پیشنهاد وابستگی جدید" : "پیشنهاد نسبت خویشاوندی جدید",
|
||||
PersonRelationSuggestionAction.Modify => isAffiliation ? "پیشنهاد ویرایش وابستگی" : "پیشنهاد ویرایش نسبت خویشاوندی",
|
||||
_ => isAffiliation ? "پیشنهاد حذف وابستگی" : "پیشنهاد حذف نسبت خویشاوندی",
|
||||
};
|
||||
string edgeLabel = isAffiliation ? "وابستگی" : "نسبت خویشاوندی";
|
||||
string actionText = suggestion.Action switch
|
||||
{
|
||||
PersonRelationSuggestionAction.Add => $"کاربری پیشنهاد افزودن نسبت خویشاوندی جدید بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
PersonRelationSuggestionAction.Modify => $"کاربری پیشنهاد ویرایش نسبت خویشاوندی بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
_ => $"کاربری پیشنهاد حذف نسبت خویشاوندی بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
PersonRelationSuggestionAction.Add => $"کاربری پیشنهاد افزودن {edgeLabel} جدید بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
PersonRelationSuggestionAction.Modify => $"کاربری پیشنهاد ویرایش {edgeLabel} بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
_ => $"کاربری پیشنهاد حذف {edgeLabel} بین «{person1.Name}» و «{person2.Name}» را داده است.",
|
||||
};
|
||||
|
||||
await NotifyModeratorsOfPendingSuggestionAsync(
|
||||
@ -652,6 +688,7 @@ namespace RMuseum.Services.Implementation
|
||||
.Include(s => s.Person1)
|
||||
.Include(s => s.Person2)
|
||||
.Include(s => s.ExistingRelation)
|
||||
.Include(s => s.ExistingAffiliation)
|
||||
.Include(s => s.User)
|
||||
.Where(s => s.Reviewed == false)
|
||||
.OrderBy(s => s.Id)
|
||||
@ -715,51 +752,101 @@ namespace RMuseum.Services.Implementation
|
||||
|
||||
if (result == CorrectionReviewResult.Approved)
|
||||
{
|
||||
switch (suggestion.Action)
|
||||
if (suggestion.Kind == PersonRelationSuggestionKind.Affiliation)
|
||||
{
|
||||
case PersonRelationSuggestionAction.Add:
|
||||
_context.GanjoorPersonRelations.Add(new GanjoorPersonRelation()
|
||||
{
|
||||
Person1Id = suggestion.Person1Id,
|
||||
Person2Id = suggestion.Person2Id,
|
||||
RelationType = suggestion.SuggestedRelationType,
|
||||
DegreeHint = suggestion.SuggestedDegreeHint,
|
||||
Note = suggestion.SuggestedNote,
|
||||
});
|
||||
break;
|
||||
case PersonRelationSuggestionAction.Modify:
|
||||
{
|
||||
var existing = await _context.GanjoorPersonRelations.Where(r => r.Id == suggestion.ExistingRelationId.Value).SingleOrDefaultAsync();
|
||||
if (existing == null)
|
||||
switch (suggestion.Action)
|
||||
{
|
||||
case PersonRelationSuggestionAction.Add:
|
||||
_context.GanjoorPersonAffiliations.Add(new GanjoorPersonAffiliation()
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر دیگر وجود ندارد.");
|
||||
}
|
||||
existing.RelationType = suggestion.SuggestedRelationType;
|
||||
existing.DegreeHint = suggestion.SuggestedDegreeHint;
|
||||
existing.Note = suggestion.SuggestedNote;
|
||||
Person1Id = suggestion.Person1Id,
|
||||
Person2Id = suggestion.Person2Id,
|
||||
AffiliationType = suggestion.SuggestedAffiliationType ?? PersonAffiliationType.Other,
|
||||
Note = suggestion.SuggestedNote,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PersonRelationSuggestionAction.Remove:
|
||||
{
|
||||
var existing = await _context.GanjoorPersonRelations.Where(r => r.Id == suggestion.ExistingRelationId.Value).SingleOrDefaultAsync();
|
||||
if (existing != null)
|
||||
case PersonRelationSuggestionAction.Modify:
|
||||
{
|
||||
// any other still-pending suggestion targeting this same relation
|
||||
// would otherwise dangle once it's gone - auto-reject those too
|
||||
var conflicting = await _context.GanjoorPersonRelationEditSuggestions
|
||||
.Where(s => !s.Reviewed && s.Id != suggestion.Id && s.ExistingRelationId == existing.Id)
|
||||
.ToListAsync();
|
||||
foreach (var c in conflicting)
|
||||
var existing = await _context.GanjoorPersonAffiliations.Where(a => a.Id == suggestion.ExistingAffiliationId.Value).SingleOrDefaultAsync();
|
||||
if (existing == null)
|
||||
{
|
||||
c.Reviewed = true;
|
||||
c.Result = CorrectionReviewResult.RejectedBecauseUnnecessaryChange;
|
||||
c.ReviewNote = "این نسبت پیشتر حذف شد.";
|
||||
c.ReviewDate = DateTime.Now;
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "وابستگی مورد نظر دیگر وجود ندارد.");
|
||||
}
|
||||
_context.GanjoorPersonRelations.Remove(existing);
|
||||
existing.AffiliationType = suggestion.SuggestedAffiliationType ?? existing.AffiliationType;
|
||||
existing.Note = suggestion.SuggestedNote;
|
||||
break;
|
||||
}
|
||||
case PersonRelationSuggestionAction.Remove:
|
||||
{
|
||||
var existing = await _context.GanjoorPersonAffiliations.Where(a => a.Id == suggestion.ExistingAffiliationId.Value).SingleOrDefaultAsync();
|
||||
if (existing != null)
|
||||
{
|
||||
// any other still-pending suggestion targeting this same affiliation
|
||||
// would otherwise dangle once it's gone - auto-reject those too
|
||||
var conflicting = await _context.GanjoorPersonRelationEditSuggestions
|
||||
.Where(s => !s.Reviewed && s.Id != suggestion.Id && s.ExistingAffiliationId == existing.Id)
|
||||
.ToListAsync();
|
||||
foreach (var c in conflicting)
|
||||
{
|
||||
c.Reviewed = true;
|
||||
c.Result = CorrectionReviewResult.RejectedBecauseUnnecessaryChange;
|
||||
c.ReviewNote = "این وابستگی پیشتر حذف شد.";
|
||||
c.ReviewDate = DateTime.Now;
|
||||
}
|
||||
_context.GanjoorPersonAffiliations.Remove(existing);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (suggestion.Action)
|
||||
{
|
||||
case PersonRelationSuggestionAction.Add:
|
||||
_context.GanjoorPersonRelations.Add(new GanjoorPersonRelation()
|
||||
{
|
||||
Person1Id = suggestion.Person1Id,
|
||||
Person2Id = suggestion.Person2Id,
|
||||
RelationType = suggestion.SuggestedRelationType,
|
||||
DegreeHint = suggestion.SuggestedDegreeHint,
|
||||
Note = suggestion.SuggestedNote,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PersonRelationSuggestionAction.Modify:
|
||||
{
|
||||
var existing = await _context.GanjoorPersonRelations.Where(r => r.Id == suggestion.ExistingRelationId.Value).SingleOrDefaultAsync();
|
||||
if (existing == null)
|
||||
{
|
||||
return new RServiceResult<GanjoorPersonRelationEditSuggestion>(null, "نسبت مورد نظر دیگر وجود ندارد.");
|
||||
}
|
||||
existing.RelationType = suggestion.SuggestedRelationType;
|
||||
existing.DegreeHint = suggestion.SuggestedDegreeHint;
|
||||
existing.Note = suggestion.SuggestedNote;
|
||||
break;
|
||||
}
|
||||
case PersonRelationSuggestionAction.Remove:
|
||||
{
|
||||
var existing = await _context.GanjoorPersonRelations.Where(r => r.Id == suggestion.ExistingRelationId.Value).SingleOrDefaultAsync();
|
||||
if (existing != null)
|
||||
{
|
||||
// any other still-pending suggestion targeting this same relation
|
||||
// would otherwise dangle once it's gone - auto-reject those too
|
||||
var conflicting = await _context.GanjoorPersonRelationEditSuggestions
|
||||
.Where(s => !s.Reviewed && s.Id != suggestion.Id && s.ExistingRelationId == existing.Id)
|
||||
.ToListAsync();
|
||||
foreach (var c in conflicting)
|
||||
{
|
||||
c.Reviewed = true;
|
||||
c.Result = CorrectionReviewResult.RejectedBecauseUnnecessaryChange;
|
||||
c.ReviewNote = "این نسبت پیشتر حذف شد.";
|
||||
c.ReviewDate = DateTime.Now;
|
||||
}
|
||||
_context.GanjoorPersonRelations.Remove(existing);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -771,11 +858,12 @@ namespace RMuseum.Services.Implementation
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string edgeLabel = suggestion.Kind == PersonRelationSuggestionKind.Affiliation ? "وابستگی" : "نسبت خویشاوندی";
|
||||
string actionLabel = suggestion.Action switch
|
||||
{
|
||||
PersonRelationSuggestionAction.Add => "افزودن نسبت خویشاوندی",
|
||||
PersonRelationSuggestionAction.Modify => "ویرایش نسبت خویشاوندی",
|
||||
_ => "حذف نسبت خویشاوندی",
|
||||
PersonRelationSuggestionAction.Add => $"افزودن {edgeLabel}",
|
||||
PersonRelationSuggestionAction.Modify => $"ویرایش {edgeLabel}",
|
||||
_ => $"حذف {edgeLabel}",
|
||||
};
|
||||
|
||||
if (result == CorrectionReviewResult.Approved)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user