people tags #387
This commit is contained in:
parent
0c98df8526
commit
4ba7da57b8
@ -108,6 +108,11 @@ else
|
||||
<td>@p.FamilyTreeCaption</td>
|
||||
<td>@s.SuggestedFamilyTreeCaption</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>درجهٔ اهمیت</td>
|
||||
<td>@Model.ImportanceLabel(p.Importance)</td>
|
||||
<td>@Model.ImportanceLabel(s.SuggestedImportance)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>توضیحات</td>
|
||||
<td><small>@p.Description</small></td>
|
||||
|
||||
@ -56,6 +56,19 @@ namespace GanjooRazor.Areas.Admin.Pages
|
||||
return loc == null ? "" : loc.Name;
|
||||
}
|
||||
|
||||
public string ImportanceLabel(PersonImportance importance)
|
||||
{
|
||||
switch (importance)
|
||||
{
|
||||
case PersonImportance.Important:
|
||||
return "مهم";
|
||||
case PersonImportance.VeryImportant:
|
||||
return "بسیار مهم";
|
||||
default:
|
||||
return "معمولی";
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult OnPost()
|
||||
{
|
||||
Skip = string.IsNullOrEmpty(Request.Query["skip"]) ? 0 : int.Parse(Request.Query["skip"]);
|
||||
|
||||
@ -560,7 +560,8 @@
|
||||
validDeathDate: false,
|
||||
birthLocationId: null,
|
||||
deathLocationId: null,
|
||||
familyTreeCaption: $('#geotag-new-person-familytreecaption').val() || null
|
||||
familyTreeCaption: $('#geotag-new-person-familytreecaption').val() || null,
|
||||
importance: $('#geotag-new-person-importance').val()
|
||||
};
|
||||
|
||||
var relatedPeople = [];
|
||||
@ -852,6 +853,7 @@
|
||||
$('#geotag-new-person-description').val('');
|
||||
$('#geotag-new-person-wikiurl').val('');
|
||||
$('#geotag-new-person-familytreecaption').val('');
|
||||
$('#geotag-new-person-importance').val('Normal');
|
||||
$('#geotag-person-relatives-list').empty();
|
||||
if (document.getElementById('new-person-widget').style.display !== 'none') {
|
||||
toggleNewPersonWidget();
|
||||
@ -2668,6 +2670,15 @@ else
|
||||
<label for="geotag-new-person-familytreecaption">عنوان تبارنامه (اختیاری، فقط اگر این نامبرده ریشهٔ یک خانواده/سلسله شناختهشده است - مثلاً «ساسانیان»)</label>
|
||||
<input type="text" id="geotag-new-person-familytreecaption" />
|
||||
</div>
|
||||
<div class="up-field">
|
||||
<label for="geotag-new-person-importance">درجهٔ اهمیت</label>
|
||||
<select id="geotag-new-person-importance">
|
||||
<option value="Normal" selected="selected">معمولی</option>
|
||||
<option value="Important">مهم</option>
|
||||
<option value="VeryImportant">بسیار مهم</option>
|
||||
</select>
|
||||
<p class="up-hint"><small>فقط اندازهٔ نمایش این نامبرده را در نمودار شخصیتها تعیین میکند.</small></p>
|
||||
</div>
|
||||
|
||||
<p class="up-hint">
|
||||
اگر خویشاوندی یا وابستگی این نامبرده با نامبردۀ دیگری را میدانید، میتوانید همینجا اضافه کنید (نامبردۀ دیگر باید از قبل در فهرست موجود باشد؛
|
||||
|
||||
@ -65,6 +65,19 @@ else
|
||||
</td>
|
||||
<td><input asp-for="Suggestion.SuggestedFamilyTreeCaption" size="40" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
درجهٔ اهمیت:
|
||||
<p class="up-hint"><small>صِرفاً تعیین میکند این نامبرده در نمودار شخصیتها (شخصیتها/شبکهٔ کامل) با چه اندازه نشان داده شود؛ در هیچ فهرست یا جستجویی تأثیری ندارد.</small></p>
|
||||
</td>
|
||||
<td>
|
||||
<select asp-for="Suggestion.SuggestedImportance">
|
||||
<option value="Normal">معمولی</option>
|
||||
<option value="Important">مهم</option>
|
||||
<option value="VeryImportant">بسیار مهم</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>توضیحات:</td>
|
||||
<td><textarea asp-for="Suggestion.SuggestedDescription" rows="10" cols="60"></textarea></td>
|
||||
|
||||
@ -89,6 +89,7 @@ namespace GanjooRazor.Areas.User.Pages
|
||||
SuggestedBirthLocationId = Person.BirthLocationId,
|
||||
SuggestedDeathLocationId = Person.DeathLocationId,
|
||||
SuggestedFamilyTreeCaption = Person.FamilyTreeCaption,
|
||||
SuggestedImportance = Person.Importance,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -4,14 +4,17 @@
|
||||
// self-hosted, dependency-light front-end code over pulling in something like d3-force.
|
||||
//
|
||||
// Data shape (RMuseum.Models.Ganjoor.ViewModels.GanjoorPersonGraphViewModel, camelCased) -
|
||||
// { nodes: [{id, name, hasFamilyTree, directlyTagged}], edges: [{person1Id, person1Name,
|
||||
// { nodes: [{id, name, hasFamilyTree, directlyTagged, importance}], edges: [{person1Id, person1Name,
|
||||
// person2Id, person2Name, category, typeValue, degreeHint, note}] } where category is
|
||||
// "Relation" (typeValue is PersonRelationType: 0=Parent,1=Sibling,2=Spouse,3=Ancestor) or
|
||||
// "Affiliation" (typeValue is PersonAffiliationType: 0=Minister,1=Advisor,2=Courtier,3=Patron,
|
||||
// 4=Ally,5=Rival,6=Servant,7=Companion,8=Successor,9=Panegyrized,10=Satirized,99=Other). directlyTagged is false only on
|
||||
// the category-scoped graph (GET api/ganjoor/cat/{id}/persongraph, the "characters in this work"
|
||||
// tab): such a node was pulled in as a one-hop relative/affiliate of someone actually named in the
|
||||
// work's verses, and is never false on the whole-site graph fed by PeopleExplorer.cshtml.
|
||||
// work's verses, and is never false on the whole-site graph fed by PeopleExplorer.cshtml. importance
|
||||
// is PersonImportance (0=Normal,1=Important,2=VeryImportant), an editorial prominence set on the
|
||||
// person themselves (see Editor.cshtml's new-person widget and SuggestPersonEdit.cshtml) - used
|
||||
// below, alongside hasFamilyTree and degree, to size a node's circle (see nodeRadius()).
|
||||
//
|
||||
// Called with an options object (see PeopleExplorer.cshtml and _PersonGraphPartial.cshtml for two
|
||||
// call sites with different element-id prefixes and data payloads), so the same renderer serves
|
||||
@ -87,7 +90,7 @@
|
||||
var nodesById = {};
|
||||
var nodes = data.nodes.map(function (n) {
|
||||
var node = {
|
||||
id: n.id, name: n.name, hasFamilyTree: n.hasFamilyTree,
|
||||
id: n.id, name: n.name, hasFamilyTree: n.hasFamilyTree, importance: n.importance || 0,
|
||||
// absent on the whole-site graph payload (always directly tagged there) - default true
|
||||
directlyTagged: n.directlyTagged !== false,
|
||||
x: W / 2 + (Math.random() - 0.5) * W * 0.6,
|
||||
@ -204,8 +207,14 @@
|
||||
return { el: line, edge: e };
|
||||
});
|
||||
|
||||
// importance (PersonImportance: 0=Normal,1=Important,2=VeryImportant) is the dominant term -
|
||||
// a VeryImportant person should read as clearly bigger even with few edges - hasFamilyTree
|
||||
// adds a smaller, independent bump on top (a tree root is worth noting regardless of its
|
||||
// own importance), and degree only fine-tunes within that.
|
||||
var IMPORTANCE_RADIUS_BUMP = { 0: 0, 1: 4, 2: 9 };
|
||||
function nodeRadius(n) {
|
||||
return (n.hasFamilyTree ? 10 : 7) + Math.min(6, n.degree * 0.6);
|
||||
var base = (n.hasFamilyTree ? 10 : 7) + (IMPORTANCE_RADIUS_BUMP[n.importance] || 0);
|
||||
return base + Math.min(6, n.degree * 0.6);
|
||||
}
|
||||
|
||||
var nodeEls = nodes.map(function (n) {
|
||||
|
||||
@ -108,6 +108,11 @@ namespace RMuseum.Models.Ganjoor
|
||||
/// </summary>
|
||||
public string SuggestedFamilyTreeCaption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// suggested importance (see GanjoorRelatedPerson.Importance)
|
||||
/// </summary>
|
||||
public PersonImportance SuggestedImportance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// true if this suggestion is actually a request to delete the person outright, not to
|
||||
/// change their fields - when true, every Suggested* field above is ignored on approval
|
||||
|
||||
@ -78,5 +78,11 @@
|
||||
/// needs one set).
|
||||
/// </summary>
|
||||
public string FamilyTreeCaption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// editorial prominence, used to size this person's node in the people graph larger or
|
||||
/// smaller (see PersonImportance and peoplegraph.js's nodeRadius()) - defaults to Normal
|
||||
/// </summary>
|
||||
public PersonImportance Importance { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
26
RMuseum/Models/Ganjoor/PersonImportance.cs
Normal file
26
RMuseum/Models/Ganjoor/PersonImportance.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace RMuseum.Models.Ganjoor
|
||||
{
|
||||
/// <summary>
|
||||
/// how editorially prominent a GanjoorRelatedPerson is treated as - purely a display/sizing
|
||||
/// hint (see GanjoorRelatedPerson.Importance, GanjoorPersonGraphNode.Importance and
|
||||
/// peoplegraph.js's nodeRadius()), never used to filter, rank or otherwise affect query
|
||||
/// results. New values can be appended safely later (stored as int).
|
||||
/// </summary>
|
||||
public enum PersonImportance
|
||||
{
|
||||
/// <summary>
|
||||
/// default - no special prominence, drawn at the normal node size
|
||||
/// </summary>
|
||||
Normal = 0,
|
||||
|
||||
/// <summary>
|
||||
/// somewhat prominent (e.g. a well-known minister or local ruler) - drawn larger than Normal
|
||||
/// </summary>
|
||||
Important = 1,
|
||||
|
||||
/// <summary>
|
||||
/// most prominent (e.g. a major poet or king) - drawn largest
|
||||
/// </summary>
|
||||
VeryImportant = 2,
|
||||
}
|
||||
}
|
||||
@ -54,6 +54,12 @@ namespace RMuseum.Models.Ganjoor.ViewModels
|
||||
/// as secondary (e.g. dashed/dimmer) since it's context the reader wasn't shown directly.
|
||||
/// </summary>
|
||||
public bool DirectlyTagged { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// numeric value of PersonImportance (0=Normal, 1=Important, 2=VeryImportant) - used
|
||||
/// client-side to size this node larger or smaller, see peoplegraph.js's nodeRadius()
|
||||
/// </summary>
|
||||
public int Importance { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -60,6 +60,13 @@ namespace RMuseum.Models.Ganjoor.ViewModels
|
||||
/// to be a tree's named root
|
||||
/// </summary>
|
||||
public string FamilyTreeCaption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// name of a PersonImportance value ("Normal", "Important", "VeryImportant") - same
|
||||
/// string-enum convention as PersonGraphRelationEntry.RelationType/AffiliationType below.
|
||||
/// Null/empty is treated as Normal.
|
||||
/// </summary>
|
||||
public string Importance { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -9517,6 +9517,11 @@
|
||||
suggested family tree caption
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonEditSuggestion.SuggestedImportance">
|
||||
<summary>
|
||||
suggested importance (see GanjoorRelatedPerson.Importance)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorPersonEditSuggestion.SuggestedForDeletion">
|
||||
<summary>
|
||||
true if this suggestion is actually a request to delete the person outright, not to
|
||||
@ -11317,6 +11322,12 @@
|
||||
needs one set).
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.GanjoorRelatedPerson.Importance">
|
||||
<summary>
|
||||
editorial prominence, used to size this person's node in the people graph larger or
|
||||
smaller (see PersonImportance and peoplegraph.js's nodeRadius()) - defaults to Normal
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.GanjoorSiteBanner">
|
||||
<summary>
|
||||
ganjoor.net site banner
|
||||
@ -11884,6 +11895,29 @@
|
||||
doesn't fit any of the above - rely on Note for what the tie actually is
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.PersonImportance">
|
||||
<summary>
|
||||
how editorially prominent a GanjoorRelatedPerson is treated as - purely a display/sizing
|
||||
hint (see GanjoorRelatedPerson.Importance, GanjoorPersonGraphNode.Importance and
|
||||
peoplegraph.js's nodeRadius()), never used to filter, rank or otherwise affect query
|
||||
results. New values can be appended safely later (stored as int).
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RMuseum.Models.Ganjoor.PersonImportance.Normal">
|
||||
<summary>
|
||||
default - no special prominence, drawn at the normal node size
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RMuseum.Models.Ganjoor.PersonImportance.Important">
|
||||
<summary>
|
||||
somewhat prominent (e.g. a well-known minister or local ruler) - drawn larger than Normal
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RMuseum.Models.Ganjoor.PersonImportance.VeryImportant">
|
||||
<summary>
|
||||
most prominent (e.g. a major poet or king) - drawn largest
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.PersonRelationSuggestionAction">
|
||||
<summary>
|
||||
what a GanjoorPersonRelationEditSuggestion proposes doing to the kinship graph
|
||||
@ -13528,6 +13562,12 @@
|
||||
as secondary (e.g. dashed/dimmer) since it's context the reader wasn't shown directly.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorPersonGraphNode.Importance">
|
||||
<summary>
|
||||
numeric value of PersonImportance (0=Normal, 1=Important, 2=VeryImportant) - used
|
||||
client-side to size this node larger or smaller, see peoplegraph.js's nodeRadius()
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.ViewModels.GanjoorPersonGraphEdge">
|
||||
<summary>
|
||||
one edge of the people graph - either a kinship edge or a non-family tie, flattened to a
|
||||
@ -15063,6 +15103,13 @@
|
||||
to be a tree's named root
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.ViewModels.PersonGraphNode.Importance">
|
||||
<summary>
|
||||
name of a PersonImportance value ("Normal", "Important", "VeryImportant") - same
|
||||
string-enum convention as PersonGraphRelationEntry.RelationType/AffiliationType below.
|
||||
Null/empty is treated as Normal.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.ViewModels.PersonGraphRelationEntry">
|
||||
<summary>
|
||||
one edge in a PersonGraphSuggestion, between two nodes referenced by their LocalKey (Person1/
|
||||
|
||||
@ -421,6 +421,7 @@ namespace RMuseum.Services.Implementation
|
||||
person.BirthLocationId = suggestion.SuggestedBirthLocationId;
|
||||
person.DeathLocationId = suggestion.SuggestedDeathLocationId;
|
||||
person.FamilyTreeCaption = suggestion.SuggestedFamilyTreeCaption;
|
||||
person.Importance = suggestion.SuggestedImportance;
|
||||
// Id and MachineGenerated on the person are intentionally left untouched
|
||||
}
|
||||
}
|
||||
@ -1115,6 +1116,7 @@ namespace RMuseum.Services.Implementation
|
||||
Name = p.Name,
|
||||
HasFamilyTree = !string.IsNullOrEmpty(p.FamilyTreeCaption),
|
||||
DirectlyTagged = directlyTaggedIds == null || directlyTaggedIds.Contains(p.Id),
|
||||
Importance = (int)p.Importance,
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
|
||||
@ -904,6 +904,12 @@ namespace RMuseum.Services.Implementation
|
||||
return new Tuple<int, string>(0, "نام یکی از افراد پیشنهادی وارد نشده است.");
|
||||
}
|
||||
|
||||
var importance = PersonImportance.Normal;
|
||||
if (!string.IsNullOrWhiteSpace(node.Importance) && !Enum.TryParse<PersonImportance>(node.Importance, out importance))
|
||||
{
|
||||
return new Tuple<int, string>(0, $"درجهٔ اهمیت «{node.Importance}» نامعتبر است.");
|
||||
}
|
||||
|
||||
var newPerson = new GanjoorRelatedPerson()
|
||||
{
|
||||
Name = node.Name.Trim(),
|
||||
@ -916,6 +922,7 @@ namespace RMuseum.Services.Implementation
|
||||
BirthLocationId = node.BirthLocationId,
|
||||
DeathLocationId = node.DeathLocationId,
|
||||
FamilyTreeCaption = string.IsNullOrWhiteSpace(node.FamilyTreeCaption) ? null : node.FamilyTreeCaption.Trim(),
|
||||
Importance = importance,
|
||||
MachineGenerated = false,
|
||||
};
|
||||
_context.GanjoorRelatedPersons.Add(newPerson);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user