PlotDirector Phase 17I - Relationship Editor Migration
This commit is contained in:
parent
36a4c76921
commit
2af1feb412
@ -133,6 +133,15 @@ public sealed class ScenesController(
|
||||
: PartialView("~/Views/Shared/SceneInspectorV2/_SceneKnowledgeEditor.cshtml", model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> SceneRelationshipsEditor(int sceneId)
|
||||
{
|
||||
var model = await scenes.GetEditAsync(sceneId);
|
||||
return model is null
|
||||
? NotFound()
|
||||
: PartialView("~/Views/Shared/SceneInspectorV2/_SceneRelationshipsEditor.cshtml", model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> SceneLocationsEditor(int sceneId)
|
||||
{
|
||||
@ -1170,7 +1179,38 @@ public sealed class ScenesController(
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> AddRelationshipEvent(RelationshipEventCreateViewModel model)
|
||||
{
|
||||
await characters.AddRelationshipEventAsync(model);
|
||||
try
|
||||
{
|
||||
await characters.AddRelationshipEventAsync(model);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
if (IsAjaxRequest())
|
||||
{
|
||||
return BadRequest(new { success = false, message = ex.Message });
|
||||
}
|
||||
|
||||
TempData["RelationshipEventAddError"] = ex.Message;
|
||||
}
|
||||
|
||||
if (IsAjaxRequest())
|
||||
{
|
||||
return await ScenePeopleContinuityRefreshJsonAsync(model.SceneID);
|
||||
}
|
||||
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> UpdateRelationshipEvent(RelationshipEventCreateViewModel model)
|
||||
{
|
||||
await characters.UpdateRelationshipEventAsync(model);
|
||||
if (IsAjaxRequest())
|
||||
{
|
||||
return await ScenePeopleContinuityRefreshJsonAsync(model.SceneID);
|
||||
}
|
||||
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
@ -1179,6 +1219,11 @@ public sealed class ScenesController(
|
||||
public async Task<IActionResult> DeleteRelationshipEvent(int id, int sceneId, int? projectId, int? bookId)
|
||||
{
|
||||
await characters.DeleteRelationshipEventAsync(id);
|
||||
if (IsAjaxRequest())
|
||||
{
|
||||
return await ScenePeopleContinuityRefreshJsonAsync(sceneId);
|
||||
}
|
||||
|
||||
return RedirectForScene(sceneId, projectId, bookId);
|
||||
}
|
||||
|
||||
@ -1392,6 +1437,11 @@ public sealed class ScenesController(
|
||||
}
|
||||
|
||||
private async Task<IActionResult> SceneKnowledgeRefreshJsonAsync(int sceneId)
|
||||
{
|
||||
return await ScenePeopleContinuityRefreshJsonAsync(sceneId);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> ScenePeopleContinuityRefreshJsonAsync(int sceneId)
|
||||
{
|
||||
var updated = await scenes.GetEditAsync(sceneId);
|
||||
if (updated is null)
|
||||
|
||||
@ -264,6 +264,7 @@ public interface ICharacterService
|
||||
Task<int> UpdateKnowledgeAsync(CharacterKnowledgeCreateViewModel model);
|
||||
Task DeleteKnowledgeAsync(int characterKnowledgeId);
|
||||
Task<int> AddRelationshipEventAsync(RelationshipEventCreateViewModel model);
|
||||
Task<int> UpdateRelationshipEventAsync(RelationshipEventCreateViewModel model);
|
||||
Task DeleteRelationshipEventAsync(int relationshipEventId);
|
||||
string DisplayAge(Character character, DateTime? sceneStartDateTime = null);
|
||||
}
|
||||
@ -9577,6 +9578,17 @@ public sealed class CharacterService(
|
||||
return relationshipEventId;
|
||||
}
|
||||
|
||||
public Task<int> UpdateRelationshipEventAsync(RelationshipEventCreateViewModel model) => characters.SaveRelationshipEventAsync(new RelationshipEvent
|
||||
{
|
||||
RelationshipEventID = model.RelationshipEventID,
|
||||
CharacterRelationshipID = model.CharacterRelationshipID.GetValueOrDefault(),
|
||||
SceneID = model.SceneID,
|
||||
RelationshipStateID = model.RelationshipStateID,
|
||||
Intensity = model.Intensity,
|
||||
IsKnownToOtherCharacter = model.IsKnownToOtherCharacter,
|
||||
Description = model.Description
|
||||
});
|
||||
|
||||
public Task DeleteRelationshipEventAsync(int relationshipEventId) => characters.DeleteRelationshipEventAsync(relationshipEventId);
|
||||
|
||||
public string DisplayAge(Character character, DateTime? sceneStartDateTime = null)
|
||||
|
||||
@ -60,6 +60,7 @@ public sealed class ProjectAccessFilter(IProjectAccessService access, ICurrentUs
|
||||
["PlotThreadID"] = "PlotThread",
|
||||
["CharacterRelationshipID"] = "CharacterRelationship",
|
||||
["CharacterKnowledgeID"] = "CharacterKnowledge",
|
||||
["RelationshipEventID"] = "RelationshipEvent",
|
||||
["TimelineViewPresetID"] = "TimelineViewPreset",
|
||||
["ScenarioID"] = "Scenario"
|
||||
};
|
||||
|
||||
@ -2039,6 +2039,7 @@ public sealed class CharacterKnowledgeCreateViewModel
|
||||
|
||||
public sealed class RelationshipEventCreateViewModel
|
||||
{
|
||||
public int RelationshipEventID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int? CharacterRelationshipID { get; set; }
|
||||
public int? CharacterAID { get; set; }
|
||||
|
||||
@ -54,6 +54,6 @@
|
||||
<div class="scene-inspector-v2-actions">
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="characters" data-scene-id="@Model.SceneID" data-scene-editor-url="@Url.Action("SceneCharactersEditor", "Scenes", new { sceneId = Model.SceneID })">Manage characters</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="knowledge" data-scene-id="@Model.SceneID" data-scene-editor-url="@Url.Action("SceneKnowledgeEditor", "Scenes", new { sceneId = Model.SceneID })">Manage knowledge</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="relationships" data-scene-id="@Model.SceneID">Manage relationships</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="relationships" data-scene-id="@Model.SceneID" data-scene-editor-url="@Url.Action("SceneRelationshipsEditor", "Scenes", new { sceneId = Model.SceneID })">Manage relationships</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@ -0,0 +1,175 @@
|
||||
@model SceneEditViewModel
|
||||
|
||||
<div class="scene-inspector-editor-form">
|
||||
<div class="scene-inspector-editor-fields">
|
||||
<section class="scene-structure-editor-section">
|
||||
<div class="scene-structure-editor-heading">
|
||||
<span>Relationship events</span>
|
||||
<strong>@Model.RelationshipEvents.Count</strong>
|
||||
</div>
|
||||
|
||||
@if (!Model.RelationshipEvents.Any())
|
||||
{
|
||||
<p class="muted">No relationship events are recorded for this scene yet.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="scene-structure-editor-list">
|
||||
@foreach (var item in Model.RelationshipEvents)
|
||||
{
|
||||
<article class="scene-structure-editor-card">
|
||||
<div class="scene-structure-card-header">
|
||||
<div>
|
||||
<h4>@item.CharacterAName -> @item.CharacterBName</h4>
|
||||
<p>@item.RelationshipTypeName</p>
|
||||
</div>
|
||||
<span class="scene-structure-marker">@item.RelationshipStateName</span>
|
||||
</div>
|
||||
|
||||
<p class="muted">Intensity @(item.Intensity?.ToString() ?? "not set")@(item.IsKnownToOtherCharacter ? " / known to other character" : "")</p>
|
||||
@if (!string.IsNullOrWhiteSpace(item.Description))
|
||||
{
|
||||
<p>@item.Description</p>
|
||||
}
|
||||
|
||||
<form asp-controller="Scenes" asp-action="UpdateRelationshipEvent" method="post" class="scene-structure-editor-form" data-scene-editor-form>
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="RelationshipEventID" value="@item.RelationshipEventID" />
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
|
||||
<div class="scene-inspector-editor-error" data-scene-editor-error hidden></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RelationshipEvent_@(item.RelationshipEventID)__CharacterRelationshipID">Relationship</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipEvent_@(item.RelationshipEventID)__CharacterRelationshipID" name="CharacterRelationshipID">
|
||||
@foreach (var option in Model.RelationshipOptions)
|
||||
{
|
||||
<option value="@option.Value" selected="@(option.Value == item.CharacterRelationshipID.ToString())">@option.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="scene-inspector-editor-grid">
|
||||
<div class="form-group">
|
||||
<label for="RelationshipEvent_@(item.RelationshipEventID)__RelationshipStateID">Relationship state</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipEvent_@(item.RelationshipEventID)__RelationshipStateID" name="RelationshipStateID">
|
||||
@foreach (var option in Model.RelationshipStateOptions)
|
||||
{
|
||||
<option value="@option.Value" selected="@(option.Value == item.RelationshipStateID.ToString())">@option.Text</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="RelationshipEvent_@(item.RelationshipEventID)__Intensity">Intensity <output>@(item.Intensity ?? 5)</output></label>
|
||||
<input class="form-range" id="RelationshipEvent_@(item.RelationshipEventID)__Intensity" name="Intensity" type="range" min="1" max="10" step="1" value="@(item.Intensity ?? 5)" data-scene-metric-range />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="scene-structure-inline-check">
|
||||
<input type="checkbox" name="IsKnownToOtherCharacter" value="true" checked="@item.IsKnownToOtherCharacter" />
|
||||
<input type="hidden" name="IsKnownToOtherCharacter" value="false" />
|
||||
<span>Other character knows</span>
|
||||
</label>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RelationshipEvent_@(item.RelationshipEventID)__Description">Notes</label>
|
||||
<textarea class="form-control form-control-sm" id="RelationshipEvent_@(item.RelationshipEventID)__Description" name="Description" rows="3">@item.Description</textarea>
|
||||
</div>
|
||||
|
||||
<div class="scene-structure-action-row">
|
||||
<button class="btn btn-sm btn-primary" type="submit" data-scene-editor-save>Save relationship</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form asp-controller="Scenes" asp-action="DeleteRelationshipEvent" method="post" class="scene-structure-delete-form" data-scene-editor-form>
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="id" value="@item.RelationshipEventID" />
|
||||
<input type="hidden" name="sceneId" value="@Model.SceneID" />
|
||||
<input type="hidden" name="projectId" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="bookId" value="@Model.ReturnBookID" />
|
||||
<div class="scene-inspector-editor-error" data-scene-editor-error hidden></div>
|
||||
<button class="btn btn-sm btn-outline-danger" type="submit" data-scene-editor-save>Remove relationship</button>
|
||||
</form>
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
|
||||
<section class="scene-structure-editor-section">
|
||||
<div class="scene-structure-editor-heading">
|
||||
<span>Add relationship event</span>
|
||||
</div>
|
||||
|
||||
<form asp-controller="Scenes" asp-action="AddRelationshipEvent" method="post" class="scene-structure-editor-card scene-structure-editor-form" data-scene-editor-form>
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
|
||||
<div class="scene-inspector-editor-error" data-scene-editor-error hidden></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RelationshipCharacterRelationshipID">Relationship</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipCharacterRelationshipID" name="CharacterRelationshipID" asp-items="Model.RelationshipOptions">
|
||||
<option value="">Create or choose relationship</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="scene-inspector-editor-grid">
|
||||
<div class="form-group">
|
||||
<label for="RelationshipCharacterAID">Character A</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipCharacterAID" name="CharacterAID" asp-items="Model.CharacterOptions">
|
||||
<option value="">Character A</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="RelationshipCharacterBID">Character B</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipCharacterBID" name="CharacterBID" asp-items="Model.CharacterOptions">
|
||||
<option value="">Character B</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RelationshipTypeID">Relationship type</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipTypeID" name="RelationshipTypeID" asp-items="Model.RelationshipTypeOptions">
|
||||
<option value="">Relationship type</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="scene-inspector-editor-grid">
|
||||
<div class="form-group">
|
||||
<label for="RelationshipStateID">Relationship state</label>
|
||||
<select class="form-control form-control-sm" id="RelationshipStateID" name="RelationshipStateID" asp-items="Model.RelationshipStateOptions"></select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="RelationshipIntensity">Intensity <output>5</output></label>
|
||||
<input class="form-range" id="RelationshipIntensity" name="Intensity" type="range" min="1" max="10" step="1" value="5" data-scene-metric-range />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="scene-structure-inline-check">
|
||||
<input type="checkbox" name="IsKnownToOtherCharacter" value="true" />
|
||||
<input type="hidden" name="IsKnownToOtherCharacter" value="false" />
|
||||
<span>Other character knows</span>
|
||||
</label>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="RelationshipDescription">Notes</label>
|
||||
<textarea class="form-control form-control-sm" id="RelationshipDescription" name="Description" rows="3" placeholder="Relationship event description"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="scene-structure-action-row">
|
||||
<button class="btn btn-sm btn-primary" type="submit" data-scene-editor-save>Add relationship event</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="scene-inspector-editor-footer">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" data-scene-editor-close>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user