Implement critical editor override state
This commit is contained in:
@@ -65,7 +65,11 @@
|
||||
"descriptionText": "Current curated prose",
|
||||
"rawAffixText": "+8H - 2S",
|
||||
"parseStatus": "verified",
|
||||
"parsedJson": "{}",
|
||||
"parsedJson": "{\"version\":1,\"isDescriptionOverridden\":false,\"isRawAffixTextOverridden\":false,\"areEffectsOverridden\":false,\"areBranchesOverridden\":false,\"effects\":[],\"branches\":[]}",
|
||||
"isDescriptionOverridden": false,
|
||||
"isRawAffixTextOverridden": false,
|
||||
"areEffectsOverridden": false,
|
||||
"areBranchesOverridden": false,
|
||||
"validationMessages": [],
|
||||
"effects": [],
|
||||
"branches": []
|
||||
@@ -77,9 +81,21 @@
|
||||
<h2 class="panel-title">Cell re-parse</h2>
|
||||
<p class="panel-copy"><code>POST /api/tables/critical/{slug}/cells/{resultId}/reparse</code></p>
|
||||
<pre class="code-block">{
|
||||
"rawCellText": "Strike to thigh. +8H\nWith greaves: blow glances aside."
|
||||
"currentState": {
|
||||
"rawCellText": "Strike to thigh. +8H\nWith greaves: blow glances aside.",
|
||||
"descriptionText": "Curated prose",
|
||||
"rawAffixText": "+8H",
|
||||
"parseStatus": "partial",
|
||||
"parsedJson": "{}",
|
||||
"isDescriptionOverridden": true,
|
||||
"isRawAffixTextOverridden": false,
|
||||
"areEffectsOverridden": false,
|
||||
"areBranchesOverridden": false,
|
||||
"effects": [],
|
||||
"branches": []
|
||||
}
|
||||
}</pre>
|
||||
<p class="panel-copy">Re-runs the shared single-cell parser and returns a refreshed editor payload without saving changes.</p>
|
||||
<p class="panel-copy">Re-runs the shared single-cell parser, merges the generated result with the current override state, and returns the refreshed editor payload without saving changes.</p>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
@@ -91,6 +107,10 @@
|
||||
"rawAffixText": "+10H - must parry 2 rnds",
|
||||
"parseStatus": "manually_curated",
|
||||
"parsedJson": "{\"reviewed\":true}",
|
||||
"isDescriptionOverridden": true,
|
||||
"isRawAffixTextOverridden": false,
|
||||
"areEffectsOverridden": false,
|
||||
"areBranchesOverridden": false,
|
||||
"effects": [
|
||||
{
|
||||
"effectCode": "direct_hits",
|
||||
@@ -104,7 +124,9 @@
|
||||
"bodyPart": null,
|
||||
"isPermanent": false,
|
||||
"sourceType": "symbol",
|
||||
"sourceText": "+10H"
|
||||
"sourceText": "+10H",
|
||||
"originKey": "base:direct_hits:1",
|
||||
"isOverridden": true
|
||||
}
|
||||
],
|
||||
"branches": []
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
|
||||
try
|
||||
{
|
||||
var response = await LookupService.ReparseCriticalCellAsync(selectedTableSlug, editingResultId.Value, editorModel.RawCellText);
|
||||
var response = await LookupService.ReparseCriticalCellAsync(selectedTableSlug, editingResultId.Value, editorModel.ToRequest());
|
||||
if (response is null)
|
||||
{
|
||||
editorReparseError = "The selected cell could not be re-parsed.";
|
||||
|
||||
@@ -14,6 +14,9 @@ public sealed class CriticalBranchEditorModel
|
||||
public string? RawAffixText { get; set; }
|
||||
public string ParsedJson { get; set; } = "{}";
|
||||
public int SortOrder { get; set; }
|
||||
public string? OriginKey { get; set; }
|
||||
public bool IsOverridden { get; set; }
|
||||
public bool AreEffectsOverridden { get; set; }
|
||||
public List<CriticalEffectEditorModel> Effects { get; set; } = [];
|
||||
|
||||
public static CriticalBranchEditorModel FromItem(CriticalBranchEditorItem item) =>
|
||||
@@ -28,6 +31,9 @@ public sealed class CriticalBranchEditorModel
|
||||
RawAffixText = item.RawAffixText,
|
||||
ParsedJson = item.ParsedJson,
|
||||
SortOrder = item.SortOrder,
|
||||
OriginKey = item.OriginKey,
|
||||
IsOverridden = item.IsOverridden,
|
||||
AreEffectsOverridden = item.AreEffectsOverridden,
|
||||
Effects = item.Effects.Select(CriticalEffectEditorModel.FromItem).ToList()
|
||||
};
|
||||
|
||||
@@ -42,6 +48,9 @@ public sealed class CriticalBranchEditorModel
|
||||
RawAffixText,
|
||||
SerializeParsedEffects(Effects),
|
||||
SortOrder,
|
||||
OriginKey,
|
||||
IsOverridden,
|
||||
AreEffectsOverridden,
|
||||
Effects.Select(effect => effect.ToItem()).ToList());
|
||||
|
||||
private string BuildRawText()
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
}
|
||||
<div class="field-shell">
|
||||
<label>Result Text</label>
|
||||
<InputTextArea class="input-shell critical-editor-textarea compact" @bind-Value="Model.DescriptionText" />
|
||||
<InputTextArea class="input-shell critical-editor-textarea compact" @bind-Value="Model.DescriptionText" @bind-Value:after="MarkDescriptionOverridden" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -134,11 +134,11 @@
|
||||
<div class="critical-editor-branch-line">
|
||||
<div class="field-shell">
|
||||
<label>Condition</label>
|
||||
<InputText class="input-shell" @bind-Value="branch.ConditionText" />
|
||||
<InputText class="input-shell" @bind-Value="branch.ConditionText" @bind-Value:after="() => MarkBranchOverridden(branch)" />
|
||||
</div>
|
||||
<div class="field-shell critical-editor-branch-outcome">
|
||||
<label>Outcome Text</label>
|
||||
<InputText class="input-shell" @bind-Value="branch.DescriptionText" />
|
||||
<InputText class="input-shell" @bind-Value="branch.DescriptionText" @bind-Value:after="() => MarkBranchOverridden(branch)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -321,7 +321,13 @@
|
||||
|
||||
private void AddBaseEffect()
|
||||
{
|
||||
Model?.Effects.Add(CreateDefaultEffectModel());
|
||||
if (Model is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Model.AreEffectsOverridden = true;
|
||||
Model.Effects.Add(CreateDefaultEffectModel());
|
||||
}
|
||||
|
||||
private void RemoveBaseEffect(int index)
|
||||
@@ -331,6 +337,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
Model.AreEffectsOverridden = true;
|
||||
Model.Effects.RemoveAt(index);
|
||||
}
|
||||
|
||||
@@ -344,8 +351,10 @@
|
||||
Model.Branches.Add(new CriticalBranchEditorModel
|
||||
{
|
||||
ConditionText = $"Condition {Model.Branches.Count + 1}",
|
||||
SortOrder = Model.Branches.Count + 1
|
||||
SortOrder = Model.Branches.Count + 1,
|
||||
IsOverridden = true
|
||||
});
|
||||
Model.AreBranchesOverridden = true;
|
||||
}
|
||||
|
||||
private void RemoveBranch(int index)
|
||||
@@ -355,11 +364,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
Model.AreBranchesOverridden = true;
|
||||
Model.Branches.RemoveAt(index);
|
||||
}
|
||||
|
||||
private static void AddBranchEffect(CriticalBranchEditorModel branch)
|
||||
{
|
||||
branch.AreEffectsOverridden = true;
|
||||
branch.Effects.Add(CreateDefaultEffectModel());
|
||||
}
|
||||
|
||||
@@ -370,6 +381,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
branch.AreEffectsOverridden = true;
|
||||
branch.Effects.RemoveAt(index);
|
||||
}
|
||||
|
||||
@@ -377,7 +389,8 @@
|
||||
new()
|
||||
{
|
||||
EffectCode = CriticalEffectCodes.DirectHits,
|
||||
SourceType = "symbol"
|
||||
SourceType = "symbol",
|
||||
IsOverridden = true
|
||||
};
|
||||
|
||||
private static string GetBranchTitle(CriticalBranchEditorModel branch, int index) =>
|
||||
@@ -428,6 +441,25 @@
|
||||
effect.IsPermanent = false;
|
||||
effect.SourceText = null;
|
||||
effect.SourceType = AffixDisplayMap.TryGet(effect.EffectCode, out _) ? "symbol" : "manual";
|
||||
effect.IsOverridden = true;
|
||||
}
|
||||
|
||||
private void MarkDescriptionOverridden()
|
||||
{
|
||||
if (Model is not null)
|
||||
{
|
||||
Model.IsDescriptionOverridden = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkBranchOverridden(CriticalBranchEditorModel branch)
|
||||
{
|
||||
branch.IsOverridden = true;
|
||||
}
|
||||
|
||||
private static void MarkEffectOverridden(CriticalEffectEditorModel effect)
|
||||
{
|
||||
effect.IsOverridden = true;
|
||||
}
|
||||
|
||||
private static string GetAdvancedSummary(CriticalCellEditorModel model)
|
||||
@@ -531,7 +563,7 @@
|
||||
{
|
||||
<div class="field-shell critical-editor-effect-extra">
|
||||
<label>Body Part</label>
|
||||
<InputText class="input-shell" @bind-Value="effect.BodyPart" />
|
||||
<InputText class="input-shell" @bind-Value="effect.BodyPart" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -543,30 +575,30 @@
|
||||
{
|
||||
case CriticalEffectCodes.DirectHits:
|
||||
<label>Hits</label>
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.ValueInteger" />
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.ValueInteger" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
case CriticalEffectCodes.StunnedRounds:
|
||||
case CriticalEffectCodes.MustParryRounds:
|
||||
case CriticalEffectCodes.NoParryRounds:
|
||||
<label>Rounds</label>
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.DurationRounds" />
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.DurationRounds" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
case CriticalEffectCodes.BleedPerRound:
|
||||
<label>Bleed / Round</label>
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.PerRound" />
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.PerRound" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
case CriticalEffectCodes.FoePenalty:
|
||||
case CriticalEffectCodes.AttackerBonusNextRound:
|
||||
<label>Modifier</label>
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.Modifier" />
|
||||
<InputNumber TValue="int?" class="input-shell" @bind-Value="effect.Modifier" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
case CriticalEffectCodes.PowerPointModifier:
|
||||
<label>Expression</label>
|
||||
<InputText class="input-shell" @bind-Value="effect.ValueExpression" />
|
||||
<InputText class="input-shell" @bind-Value="effect.ValueExpression" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
default:
|
||||
<label>Display Text</label>
|
||||
<InputText class="input-shell" @bind-Value="effect.SourceText" />
|
||||
<InputText class="input-shell" @bind-Value="effect.SourceText" @bind-Value:after="() => MarkEffectOverridden(effect)" />
|
||||
break;
|
||||
}
|
||||
</div>;
|
||||
|
||||
@@ -20,6 +20,10 @@ public sealed class CriticalCellEditorModel
|
||||
public string? RawAffixText { get; set; }
|
||||
public string ParseStatus { get; set; } = string.Empty;
|
||||
public string ParsedJson { get; set; } = "{}";
|
||||
public bool IsDescriptionOverridden { get; set; }
|
||||
public bool IsRawAffixTextOverridden { get; set; }
|
||||
public bool AreEffectsOverridden { get; set; }
|
||||
public bool AreBranchesOverridden { get; set; }
|
||||
public List<string> ValidationMessages { get; set; } = [];
|
||||
public List<CriticalEffectEditorModel> Effects { get; set; } = [];
|
||||
public List<CriticalBranchEditorModel> Branches { get; set; } = [];
|
||||
@@ -42,18 +46,27 @@ public sealed class CriticalCellEditorModel
|
||||
RawAffixText = response.RawAffixText,
|
||||
ParseStatus = response.ParseStatus,
|
||||
ParsedJson = response.ParsedJson,
|
||||
IsDescriptionOverridden = response.IsDescriptionOverridden,
|
||||
IsRawAffixTextOverridden = response.IsRawAffixTextOverridden,
|
||||
AreEffectsOverridden = response.AreEffectsOverridden,
|
||||
AreBranchesOverridden = response.AreBranchesOverridden,
|
||||
ValidationMessages = response.ValidationMessages.ToList(),
|
||||
Effects = response.Effects.Select(CriticalEffectEditorModel.FromItem).ToList(),
|
||||
Branches = response.Branches.Select(CriticalBranchEditorModel.FromItem).ToList()
|
||||
};
|
||||
|
||||
public CriticalCellUpdateRequest ToRequest() =>
|
||||
new(
|
||||
public CriticalCellUpdateRequest ToRequest()
|
||||
{
|
||||
var request = new CriticalCellUpdateRequest(
|
||||
RawCellText,
|
||||
DescriptionText,
|
||||
RawAffixText,
|
||||
ResolveParseStatus(Effects, Branches),
|
||||
SerializeParsedEffects(Effects),
|
||||
IsDescriptionOverridden,
|
||||
IsRawAffixTextOverridden,
|
||||
AreEffectsOverridden,
|
||||
AreBranchesOverridden,
|
||||
Effects.Select(effect => effect.ToItem()).ToList(),
|
||||
Branches
|
||||
.OrderBy(branch => branch.SortOrder)
|
||||
@@ -64,6 +77,12 @@ public sealed class CriticalCellEditorModel
|
||||
})
|
||||
.ToList());
|
||||
|
||||
return request with
|
||||
{
|
||||
ParsedJson = CriticalCellEditorSnapshot.FromRequest(request).ToJson()
|
||||
};
|
||||
}
|
||||
|
||||
private static string ResolveParseStatus(
|
||||
IReadOnlyList<CriticalEffectEditorModel> effects,
|
||||
IReadOnlyList<CriticalBranchEditorModel> branches) =>
|
||||
|
||||
@@ -16,6 +16,8 @@ public sealed class CriticalEffectEditorModel
|
||||
public bool IsPermanent { get; set; }
|
||||
public string SourceType { get; set; } = "symbol";
|
||||
public string? SourceText { get; set; }
|
||||
public string? OriginKey { get; set; }
|
||||
public bool IsOverridden { get; set; }
|
||||
|
||||
public static CriticalEffectEditorModel FromItem(CriticalEffectEditorItem item) =>
|
||||
new()
|
||||
@@ -31,7 +33,9 @@ public sealed class CriticalEffectEditorModel
|
||||
BodyPart = item.BodyPart,
|
||||
IsPermanent = item.IsPermanent,
|
||||
SourceType = item.SourceType,
|
||||
SourceText = item.SourceText
|
||||
SourceText = item.SourceText,
|
||||
OriginKey = item.OriginKey,
|
||||
IsOverridden = item.IsOverridden
|
||||
};
|
||||
|
||||
public CriticalEffectEditorItem ToItem() =>
|
||||
@@ -47,5 +51,7 @@ public sealed class CriticalEffectEditorModel
|
||||
BodyPart,
|
||||
IsPermanent,
|
||||
SourceType,
|
||||
SourceText);
|
||||
SourceText,
|
||||
OriginKey,
|
||||
IsOverridden);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user