172 lines
9.2 KiB
C#
172 lines
9.2 KiB
C#
using System.Data;
|
|
using Dapper;
|
|
using PlotLine.Models;
|
|
|
|
namespace PlotLine.Data;
|
|
|
|
public interface IProjectBackupRepository
|
|
{
|
|
Task<ProjectBackupExport?> GetProjectBackupAsync(int projectId, int? userId = null);
|
|
}
|
|
|
|
public sealed class ProjectBackupRepository(ISqlConnectionFactory connectionFactory) : IProjectBackupRepository
|
|
{
|
|
public async Task<ProjectBackupExport?> GetProjectBackupAsync(int projectId, int? userId = null)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
using var result = await connection.QueryMultipleAsync(
|
|
"dbo.ProjectBackup_Export",
|
|
new { ProjectID = projectId, UserID = userId },
|
|
commandType: CommandType.StoredProcedure,
|
|
commandTimeout: 180);
|
|
|
|
var project = await result.ReadSingleOrDefaultAsync<Project>();
|
|
var data = new ProjectBackupData
|
|
{
|
|
Books = (await result.ReadAsync<Book>()).ToList(),
|
|
Chapters = (await result.ReadAsync<Chapter>()).ToList(),
|
|
Scenes = (await result.ReadAsync<Scene>()).ToList(),
|
|
ScenePurposes = (await result.ReadAsync<ProjectBackupScenePurpose>()).ToList(),
|
|
SceneOutcomes = (await result.ReadAsync<ProjectBackupSceneOutcome>()).ToList(),
|
|
SceneMetricTypes = (await result.ReadAsync<SceneMetricType>()).ToList(),
|
|
SceneMetricValues = (await result.ReadAsync<SceneMetricValue>()).ToList(),
|
|
TimelineSettings = (await result.ReadAsync<ProjectTimelineSettings>()).ToList(),
|
|
TimelineMetricSettings = (await result.ReadAsync<ProjectTimelineMetricSetting>()).ToList(),
|
|
TimelineViewPresets = (await result.ReadAsync<TimelineViewPreset>()).ToList(),
|
|
PlotLines = (await result.ReadAsync<PlotLineItem>()).ToList(),
|
|
PlotThreads = (await result.ReadAsync<PlotThread>()).ToList(),
|
|
ThreadEvents = (await result.ReadAsync<ThreadEvent>()).ToList(),
|
|
StoryAssets = (await result.ReadAsync<StoryAsset>()).ToList(),
|
|
AssetStates = (await result.ReadAsync<AssetState>()).ToList(),
|
|
AssetEvents = (await result.ReadAsync<AssetEvent>()).ToList(),
|
|
AssetDependencies = (await result.ReadAsync<AssetDependency>()).ToList(),
|
|
AssetCustodyEvents = (await result.ReadAsync<AssetCustodyEvent>()).ToList(),
|
|
AssetCustodyCharacters = (await result.ReadAsync<ProjectBackupAssetCustodyCharacter>()).ToList(),
|
|
Characters = (await result.ReadAsync<Character>()).ToList(),
|
|
SceneCharacters = (await result.ReadAsync<SceneCharacter>()).ToList(),
|
|
CharacterAttributeTypes = (await result.ReadAsync<CharacterAttributeType>()).ToList(),
|
|
CharacterAttributeEvents = (await result.ReadAsync<CharacterAttributeEvent>()).ToList(),
|
|
CharacterKnowledge = (await result.ReadAsync<CharacterKnowledgeItem>()).ToList(),
|
|
CharacterRelationships = (await result.ReadAsync<CharacterRelationship>()).ToList(),
|
|
RelationshipEvents = (await result.ReadAsync<RelationshipEvent>()).ToList(),
|
|
Locations = (await result.ReadAsync<LocationItem>()).ToList(),
|
|
LocationRelationships = (await result.ReadAsync<LocationRelationship>()).ToList(),
|
|
FloorPlans = (await result.ReadAsync<FloorPlan>()).ToList(),
|
|
FloorPlanFloors = (await result.ReadAsync<FloorPlanFloor>()).ToList(),
|
|
FloorPlanBlocks = (await result.ReadAsync<FloorPlanBlock>()).ToList(),
|
|
FloorPlanTransitions = (await result.ReadAsync<FloorPlanTransition>()).ToList(),
|
|
SceneAssetLocations = (await result.ReadAsync<SceneAssetLocation>()).ToList(),
|
|
SceneFloorPlanOccupancy = (await result.ReadAsync<SceneFloorPlanOccupancy>()).ToList(),
|
|
SceneDependencies = (await result.ReadAsync<SceneDependency>()).ToList(),
|
|
ValidationRuns = (await result.ReadAsync<ProjectBackupValidationRun>()).ToList(),
|
|
ContinuityWarnings = (await result.ReadAsync<ContinuityWarning>()).ToList(),
|
|
SceneNotes = (await result.ReadAsync<SceneNote>()).ToList(),
|
|
SceneWorkflow = (await result.ReadAsync<SceneWorkflow>()).ToList(),
|
|
SceneChecklistItems = (await result.ReadAsync<SceneChecklistItem>()).ToList(),
|
|
SceneAttachments = (await result.ReadAsync<SceneAttachment>()).ToList(),
|
|
ChapterGoals = (await result.ReadAsync<ChapterGoal>()).ToList(),
|
|
Scenarios = (await result.ReadAsync<Scenario>()).ToList(),
|
|
ScenarioSceneOrder = (await result.ReadAsync<ProjectBackupScenarioSceneOrder>()).ToList(),
|
|
ScenarioValidationRuns = (await result.ReadAsync<ProjectBackupScenarioValidationRun>()).ToList(),
|
|
ScenarioWarnings = (await result.ReadAsync<ScenarioWarning>()).ToList(),
|
|
GenreMetricPresets = (await result.ReadAsync<GenreMetricPreset>()).ToList(),
|
|
GenreMetricPresetMetrics = (await result.ReadAsync<ProjectBackupGenreMetricPresetMetric>()).ToList(),
|
|
ProjectAccess = (await result.ReadAsync<ProjectBackupAccessRecord>()).ToList(),
|
|
UserFiles = (await result.ReadAsync<UserFile>()).ToList()
|
|
};
|
|
|
|
if (project is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var bookMetadata = (await connection.QueryAsync<Book>(
|
|
"dbo.ProjectBackup_BookMetadata_List",
|
|
new { ProjectID = projectId },
|
|
commandType: CommandType.StoredProcedure)).ToDictionary(x => x.BookID);
|
|
foreach (var book in data.Books)
|
|
{
|
|
if (!bookMetadata.TryGetValue(book.BookID, out var metadata))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
book.Subtitle = metadata.Subtitle;
|
|
book.Tagline = metadata.Tagline;
|
|
book.ShortDescription = metadata.ShortDescription;
|
|
book.Status = metadata.Status;
|
|
book.TargetWordCount = metadata.TargetWordCount;
|
|
book.WritingStartDate = metadata.WritingStartDate;
|
|
book.TargetCompletionDate = metadata.TargetCompletionDate;
|
|
book.PublicationDate = metadata.PublicationDate;
|
|
book.CoverThumbnailPath = metadata.CoverThumbnailPath;
|
|
book.CoverStandardPath = metadata.CoverStandardPath;
|
|
}
|
|
|
|
return new ProjectBackupExport
|
|
{
|
|
ExportedAtUtc = DateTime.UtcNow,
|
|
Project = project,
|
|
Data = data,
|
|
Diagnostics = new ProjectBackupDiagnostics
|
|
{
|
|
ProjectId = projectId,
|
|
IncludedEntitySets =
|
|
[
|
|
nameof(data.Books),
|
|
nameof(data.Chapters),
|
|
nameof(data.Scenes),
|
|
nameof(data.ScenePurposes),
|
|
nameof(data.SceneOutcomes),
|
|
nameof(data.SceneMetricTypes),
|
|
nameof(data.SceneMetricValues),
|
|
nameof(data.TimelineSettings),
|
|
nameof(data.TimelineMetricSettings),
|
|
nameof(data.TimelineViewPresets),
|
|
nameof(data.PlotLines),
|
|
nameof(data.PlotThreads),
|
|
nameof(data.ThreadEvents),
|
|
nameof(data.StoryAssets),
|
|
nameof(data.AssetStates),
|
|
nameof(data.AssetEvents),
|
|
nameof(data.AssetDependencies),
|
|
nameof(data.AssetCustodyEvents),
|
|
nameof(data.AssetCustodyCharacters),
|
|
nameof(data.Characters),
|
|
nameof(data.SceneCharacters),
|
|
nameof(data.CharacterAttributeTypes),
|
|
nameof(data.CharacterAttributeEvents),
|
|
nameof(data.CharacterKnowledge),
|
|
nameof(data.CharacterRelationships),
|
|
nameof(data.RelationshipEvents),
|
|
nameof(data.Locations),
|
|
nameof(data.LocationRelationships),
|
|
nameof(data.FloorPlans),
|
|
nameof(data.FloorPlanFloors),
|
|
nameof(data.FloorPlanBlocks),
|
|
nameof(data.FloorPlanTransitions),
|
|
nameof(data.SceneAssetLocations),
|
|
nameof(data.SceneFloorPlanOccupancy),
|
|
nameof(data.SceneDependencies),
|
|
nameof(data.ValidationRuns),
|
|
nameof(data.ContinuityWarnings),
|
|
nameof(data.SceneNotes),
|
|
nameof(data.SceneWorkflow),
|
|
nameof(data.SceneChecklistItems),
|
|
nameof(data.SceneAttachments),
|
|
nameof(data.ChapterGoals),
|
|
nameof(data.Scenarios),
|
|
nameof(data.ScenarioSceneOrder),
|
|
nameof(data.ScenarioValidationRuns),
|
|
nameof(data.ScenarioWarnings),
|
|
nameof(data.GenreMetricPresets),
|
|
nameof(data.GenreMetricPresetMetrics),
|
|
nameof(data.ProjectAccess),
|
|
nameof(data.UserFiles)
|
|
],
|
|
Note = "Original database IDs are included for diagnostics. Project access records are exported for reference only; importing a project backup creates a new project owned by the importing user and does not recreate collaborators."
|
|
}
|
|
};
|
|
}
|
|
}
|