327 lines
14 KiB
C#
327 lines
14 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using PlotLine.Models;
|
|
|
|
namespace PlotLine.ViewModels;
|
|
|
|
public sealed class FeatureRequestIndexViewModel
|
|
{
|
|
public IReadOnlyList<FeatureRequest> Requests { get; set; } = [];
|
|
}
|
|
|
|
public sealed class FeatureRequestRoadmapViewModel
|
|
{
|
|
public IReadOnlyList<FeatureRequestRoadmapSection> Sections { get; set; } = [];
|
|
}
|
|
|
|
public sealed class FeatureRequestCreateViewModel
|
|
{
|
|
[Required(ErrorMessage = "Enter a title.")]
|
|
[StringLength(200, ErrorMessage = "Title must be 200 characters or fewer.")]
|
|
public string Title { get; set; } = string.Empty;
|
|
|
|
[Required(ErrorMessage = "Describe the problem or suggestion.")]
|
|
[Display(Name = "Description / Problem")]
|
|
public string Description { get; set; } = string.Empty;
|
|
|
|
[StringLength(100, ErrorMessage = "App area must be 100 characters or fewer.")]
|
|
[Display(Name = "App Area")]
|
|
public string? AppArea { get; set; }
|
|
|
|
[StringLength(50, ErrorMessage = "Importance must be 50 characters or fewer.")]
|
|
public string? Importance { get; set; }
|
|
|
|
public IReadOnlyList<string> AppAreas { get; set; } = FeatureRequestOptions.AppAreas;
|
|
public IReadOnlyList<string> ImportanceOptions { get; set; } = FeatureRequestOptions.ImportanceOptions;
|
|
}
|
|
|
|
public sealed class FeatureRequestDetailsViewModel
|
|
{
|
|
public FeatureRequest Request { get; set; } = new();
|
|
public IReadOnlyList<FeatureRequestMessage> Messages { get; set; } = [];
|
|
public FeatureRequestReplyViewModel Reply { get; set; } = new();
|
|
public bool IsAdminView { get; set; }
|
|
public IReadOnlyList<string> StatusOptions { get; set; } = FeatureRequestStatuses.All;
|
|
}
|
|
|
|
public sealed class FeatureRequestReplyViewModel
|
|
{
|
|
public int FeatureRequestID { get; set; }
|
|
|
|
[Required(ErrorMessage = "Enter a message.")]
|
|
public string MessageBody { get; set; } = string.Empty;
|
|
}
|
|
|
|
public sealed class AdminFeatureRequestIndexViewModel
|
|
{
|
|
public IReadOnlyList<FeatureRequest> Requests { get; set; } = [];
|
|
public string? Status { get; set; }
|
|
public string? AppArea { get; set; }
|
|
public string? Importance { get; set; }
|
|
public string? Search { get; set; }
|
|
public string Sort { get; set; } = FeatureRequestSortOptions.LatestActivity;
|
|
public IReadOnlyList<string> StatusOptions { get; set; } = FeatureRequestStatuses.All;
|
|
public IReadOnlyList<string> AppAreas { get; set; } = FeatureRequestOptions.AppAreas;
|
|
public IReadOnlyList<string> ImportanceOptions { get; set; } = FeatureRequestOptions.ImportanceOptions;
|
|
public IReadOnlyList<(string Value, string Label)> SortOptions { get; set; } = FeatureRequestSortOptions.All;
|
|
}
|
|
|
|
public sealed class AdminFeatureRequestUpdateViewModel
|
|
{
|
|
public int FeatureRequestID { get; set; }
|
|
public string Status { get; set; } = FeatureRequestStatuses.New;
|
|
public bool IsPublicCandidate { get; set; }
|
|
public string? AdminNotes { get; set; }
|
|
}
|
|
|
|
public sealed class AdminDashboardViewModel
|
|
{
|
|
public FeatureRequestAdminSummary FeatureRequestSummary { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StoryIntelligenceDiagnosticsViewModel
|
|
{
|
|
public string Model { get; set; } = string.Empty;
|
|
public string ChapterStructureModel { get; set; } = string.Empty;
|
|
public string SceneIntelligenceModel { get; set; } = string.Empty;
|
|
public int MaxOutputTokens { get; set; }
|
|
public int TimeoutSeconds { get; set; }
|
|
public bool ApiKeyConfigured { get; set; }
|
|
public bool ClientConstructed { get; set; }
|
|
public string ConnectionStatus { get; set; } = string.Empty;
|
|
public bool PromptRepositoryHealthy { get; set; }
|
|
public string PromptFileName { get; set; } = string.Empty;
|
|
public bool ScenePromptLoaded { get; set; }
|
|
public int ScenePromptLength { get; set; }
|
|
public string PromptVersion { get; set; } = string.Empty;
|
|
public bool RuntimeSubstitutionWorks { get; set; }
|
|
public string? ErrorMessage { get; set; }
|
|
}
|
|
|
|
public sealed class StoryIntelligenceDryRunViewModel
|
|
{
|
|
public StoryIntelligenceDryRunForm Form { get; set; } = StoryIntelligenceDryRunForm.Default();
|
|
public StoryIntelligenceDryRunResultViewModel? Result { get; set; }
|
|
}
|
|
|
|
public sealed class StoryIntelligenceDryRunForm
|
|
{
|
|
public int? ProjectID { get; set; }
|
|
public int? BookID { get; set; }
|
|
public int? ChapterID { get; set; }
|
|
public int? SceneID { get; set; }
|
|
public decimal? ChapterNumber { get; set; }
|
|
public decimal? SceneNumber { get; set; }
|
|
public string SourceLabel { get; set; } = "Admin test scene";
|
|
public string SceneText { get; set; } = string.Empty;
|
|
|
|
public static StoryIntelligenceDryRunForm Default() => new()
|
|
{
|
|
ProjectID = null,
|
|
BookID = null,
|
|
ChapterID = null,
|
|
SceneID = null,
|
|
ChapterNumber = 1,
|
|
SceneNumber = 1,
|
|
SourceLabel = "Admin test scene",
|
|
SceneText = "Mara found the brass key under the loose stair. Elias watched from the doorway and asked whether she had told the captain. Mara hid the key in her glove and said the captain would learn soon enough."
|
|
};
|
|
}
|
|
|
|
public sealed class StoryIntelligenceDryRunResultViewModel
|
|
{
|
|
public bool Success { get; init; }
|
|
public string PromptVersion { get; init; } = string.Empty;
|
|
public string Model { get; init; } = string.Empty;
|
|
public string SceneContextJson { get; init; } = string.Empty;
|
|
public string Duration { get; init; } = string.Empty;
|
|
public int RetryCount { get; init; }
|
|
public int? InputTokens { get; init; }
|
|
public int? OutputTokens { get; init; }
|
|
public string RawResponseText { get; init; } = string.Empty;
|
|
public string SceneJsonText { get; init; } = string.Empty;
|
|
public SceneIntelligenceScene? ParsedScene { get; init; }
|
|
public PlotLine.Models.StoryIntelligence.ValidationResult? Validation { get; init; }
|
|
public string? ErrorMessage { get; init; }
|
|
}
|
|
|
|
public sealed class ChapterStructureDryRunViewModel
|
|
{
|
|
public ChapterStructureDryRunForm Form { get; set; } = ChapterStructureDryRunForm.Default();
|
|
public ChapterStructureDryRunResultViewModel? Result { get; set; }
|
|
}
|
|
|
|
public sealed class ChapterStructureDryRunForm
|
|
{
|
|
public int? ProjectID { get; set; }
|
|
public int? BookID { get; set; }
|
|
public int? ChapterID { get; set; }
|
|
public decimal? ChapterNumber { get; set; }
|
|
public string SourceLabel { get; set; } = "Admin test chapter";
|
|
public string ChapterText { get; set; } = string.Empty;
|
|
|
|
public static ChapterStructureDryRunForm Default() => new()
|
|
{
|
|
ProjectID = null,
|
|
BookID = null,
|
|
ChapterID = null,
|
|
ChapterNumber = 1,
|
|
SourceLabel = "Admin test chapter",
|
|
ChapterText = string.Join(
|
|
Environment.NewLine + Environment.NewLine,
|
|
[
|
|
"Mara waited in the shuttered kitchen while rain tapped against the narrow windows. She counted the coins in her palm and listened for the baker's cart.",
|
|
"Elias arrived before dawn with mud on his boots and a warning folded into his sleeve. He said the bridge guards had doubled their watch.",
|
|
"They argued in whispers over the cold stove until Mara decided they would leave by the canal instead.",
|
|
"By noon the rain had stopped and the city gate was three miles behind them. The canal boat moved slowly through reeds bright with summer light.",
|
|
"Elias watched the towpath and admitted he had seen the captain speaking with the bridge guards the night before.",
|
|
"That evening, in an abandoned lockkeeper's cottage, Mara found the captain's seal pressed into a scrap of blue wax.",
|
|
"She set it beside the warning and understood that someone had wanted them away from the bridge.",
|
|
"Outside, a horse stopped on the road, and both of them went silent."
|
|
])
|
|
};
|
|
}
|
|
|
|
public sealed class ChapterStructureDryRunResultViewModel
|
|
{
|
|
public bool Success { get; init; }
|
|
public string PromptVersion { get; init; } = string.Empty;
|
|
public string Model { get; init; } = string.Empty;
|
|
public string ChapterContextJson { get; init; } = string.Empty;
|
|
public int ParagraphCount { get; init; }
|
|
public string Duration { get; init; } = string.Empty;
|
|
public int RetryCount { get; init; }
|
|
public int? InputTokens { get; init; }
|
|
public int? OutputTokens { get; init; }
|
|
public string RawResponseText { get; init; } = string.Empty;
|
|
public string ChapterJsonText { get; init; } = string.Empty;
|
|
public ChapterStructureModel? ParsedChapter { get; init; }
|
|
public PlotLine.Models.StoryIntelligence.ValidationResult? Validation { get; init; }
|
|
public string? ErrorMessage { get; init; }
|
|
}
|
|
|
|
public sealed class ChapterStoryIntelligenceDryRunViewModel
|
|
{
|
|
public ChapterStoryIntelligenceDryRunForm Form { get; set; } = ChapterStoryIntelligenceDryRunForm.Default();
|
|
public ChapterStoryIntelligenceDryRunResultViewModel? Result { get; set; }
|
|
}
|
|
|
|
public sealed class ChapterStoryIntelligenceDryRunForm
|
|
{
|
|
public int? ProjectID { get; set; }
|
|
public int? BookID { get; set; }
|
|
public int? ChapterID { get; set; }
|
|
public decimal? ChapterNumber { get; set; }
|
|
public string SourceLabel { get; set; } = "Admin pipeline test chapter";
|
|
public string ChapterText { get; set; } = string.Empty;
|
|
|
|
public static ChapterStoryIntelligenceDryRunForm Default() => new()
|
|
{
|
|
ProjectID = null,
|
|
BookID = null,
|
|
ChapterID = null,
|
|
ChapterNumber = 1,
|
|
SourceLabel = "Admin pipeline test chapter",
|
|
ChapterText = ChapterStructureDryRunForm.Default().ChapterText
|
|
};
|
|
}
|
|
|
|
public sealed class ChapterStoryIntelligenceDryRunResultViewModel
|
|
{
|
|
public bool Success { get; init; }
|
|
public bool PipelineStopped { get; init; }
|
|
public string StopReason { get; init; } = string.Empty;
|
|
public string ChapterPromptVersion { get; init; } = string.Empty;
|
|
public string ScenePromptVersion { get; init; } = string.Empty;
|
|
public string Model { get; init; } = string.Empty;
|
|
public string ChapterContextJson { get; init; } = string.Empty;
|
|
public int ParagraphCount { get; init; }
|
|
public string TotalDuration { get; init; } = string.Empty;
|
|
public long? TotalDurationMs { get; init; }
|
|
public int? TotalInputTokens { get; init; }
|
|
public int? TotalOutputTokens { get; init; }
|
|
public string ChapterDuration { get; init; } = string.Empty;
|
|
public long? ChapterDurationMs { get; init; }
|
|
public int ChapterRetryCount { get; init; }
|
|
public int? ChapterInputTokens { get; init; }
|
|
public int? ChapterOutputTokens { get; init; }
|
|
public string ChapterRawResponseText { get; init; } = string.Empty;
|
|
public string ChapterJsonText { get; init; } = string.Empty;
|
|
public ChapterStructureModel? ParsedChapter { get; init; }
|
|
public PlotLine.Models.StoryIntelligence.ValidationResult? ChapterValidation { get; init; }
|
|
public IReadOnlyList<ChapterStorySceneBlockViewModel> SceneBlocks { get; init; } = [];
|
|
public string? ErrorMessage { get; init; }
|
|
}
|
|
|
|
public sealed record ChapterStorySceneBlockViewModel
|
|
{
|
|
public int TemporarySceneNumber { get; init; }
|
|
public int StartParagraph { get; init; }
|
|
public int EndParagraph { get; init; }
|
|
public string BoundaryReason { get; init; } = string.Empty;
|
|
public decimal? BoundaryConfidence { get; init; }
|
|
public string SceneContextJson { get; init; } = string.Empty;
|
|
public string SceneText { get; init; } = string.Empty;
|
|
public string SceneTextPreview { get; init; } = string.Empty;
|
|
public bool SplitValid { get; init; }
|
|
public string SplitErrorMessage { get; init; } = string.Empty;
|
|
public bool Success { get; init; }
|
|
public string Duration { get; init; } = string.Empty;
|
|
public long? DurationMs { get; init; }
|
|
public int RetryCount { get; init; }
|
|
public int? InputTokens { get; init; }
|
|
public int? OutputTokens { get; init; }
|
|
public string RawResponseText { get; init; } = string.Empty;
|
|
public string SceneJsonText { get; init; } = string.Empty;
|
|
public SceneIntelligenceScene? ParsedScene { get; init; }
|
|
public PlotLine.Models.StoryIntelligence.ValidationResult? Validation { get; init; }
|
|
public string? ErrorMessage { get; init; }
|
|
}
|
|
|
|
public sealed class StoryIntelligenceSaveRunForm
|
|
{
|
|
public string Payload { get; set; } = string.Empty;
|
|
}
|
|
|
|
public sealed class StoryIntelligenceSavedRunsViewModel
|
|
{
|
|
public IReadOnlyList<StoryIntelligenceSavedRunListItem> Runs { get; init; } = [];
|
|
}
|
|
|
|
public sealed class StoryIntelligenceSavedRunDetailViewModel
|
|
{
|
|
public StoryIntelligenceSavedRun? Run { get; init; }
|
|
public StoryIntelligenceSavedChapterResult? ChapterResult { get; init; }
|
|
public IReadOnlyList<StoryIntelligenceSavedSceneResult> SceneResults { get; init; } = [];
|
|
public StoryIntelligenceImportPreview? ImportPreview { get; init; }
|
|
public StoryIntelligenceImportCommit? ImportCommit { get; init; }
|
|
}
|
|
|
|
public sealed class StoryIntelligenceImportConfirmationViewModel
|
|
{
|
|
public StoryIntelligenceSavedRun Run { get; init; } = new();
|
|
public StoryIntelligenceImportCommit? ExistingCommit { get; init; }
|
|
public string ProjectName { get; init; } = string.Empty;
|
|
public string BookTitle { get; init; } = string.Empty;
|
|
public string ChapterLabel { get; init; } = string.Empty;
|
|
public int ExistingSceneCount { get; init; }
|
|
public string CommitMode { get; init; } = string.Empty;
|
|
public int ScenesToCreate { get; init; }
|
|
public int MetricsToImport { get; init; }
|
|
public IReadOnlyList<string> MetricNames { get; init; } = [];
|
|
public IReadOnlyList<string> Warnings { get; init; } = [];
|
|
public IReadOnlyList<string> Blockers { get; init; } = [];
|
|
public IReadOnlyList<StoryIntelligenceSceneImportItem> Scenes { get; init; } = [];
|
|
public bool HasCompletedCommit => ExistingCommit is not null
|
|
&& string.Equals(ExistingCommit.Status, StoryIntelligenceImportCommitStatuses.Completed, StringComparison.OrdinalIgnoreCase);
|
|
public bool CanCommit => Blockers.Count == 0 && !HasCompletedCommit;
|
|
}
|
|
|
|
public sealed class AdminFeatureRequestFilter
|
|
{
|
|
public string? Status { get; set; }
|
|
public string? AppArea { get; set; }
|
|
public string? Importance { get; set; }
|
|
public string? Search { get; set; }
|
|
public string Sort { get; set; } = FeatureRequestSortOptions.LatestActivity;
|
|
}
|