SET ANSI_NULLS ON; GO SET QUOTED_IDENTIFIER ON; GO IF OBJECT_ID(N'dbo.ProjectTimelineSettings', N'U') IS NULL BEGIN CREATE TABLE dbo.ProjectTimelineSettings ( ProjectTimelineSettingsID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_ProjectTimelineSettings PRIMARY KEY, ProjectID int NOT NULL, ShowSceneCards bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowSceneCards DEFAULT 1, ShowMetricShape bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowMetricShape DEFAULT 1, ShowPlotLines bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowPlotLines DEFAULT 1, ShowStoryAssets bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowStoryAssets DEFAULT 1, ShowCharacterAppearances bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowCharacterAppearances DEFAULT 1, ShowWarnings bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowWarnings DEFAULT 1, CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_CreatedDate DEFAULT SYSUTCDATETIME(), UpdatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_UpdatedDate DEFAULT SYSUTCDATETIME(), CONSTRAINT UQ_ProjectTimelineSettings_ProjectID UNIQUE(ProjectID), CONSTRAINT FK_ProjectTimelineSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID) ); END; GO IF OBJECT_ID(N'dbo.ProjectTimelineMetricSettings', N'U') IS NULL BEGIN CREATE TABLE dbo.ProjectTimelineMetricSettings ( ProjectID int NOT NULL, MetricTypeID int NOT NULL, SortOrder int NOT NULL, CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineMetricSettings_CreatedDate DEFAULT SYSUTCDATETIME(), CONSTRAINT PK_ProjectTimelineMetricSettings PRIMARY KEY(ProjectID, MetricTypeID), CONSTRAINT FK_ProjectTimelineMetricSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID), CONSTRAINT FK_ProjectTimelineMetricSettings_SceneMetricTypes FOREIGN KEY(MetricTypeID) REFERENCES dbo.SceneMetricTypes(MetricTypeID) ); END; GO CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID int AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0) RETURN; IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID) BEGIN INSERT dbo.ProjectTimelineSettings (ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings) VALUES (@ProjectID, 1, 1, 1, 1, 1, 1); END; IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID) BEGIN INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder) SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder FROM dbo.SceneMetricTypes mt WHERE mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID) AND mt.MetricName IN (N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action'); END; END; GO CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_Get @ProjectID int AS BEGIN SET NOCOUNT ON; EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID; SELECT ProjectTimelineSettingsID, ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings, CreatedDate, UpdatedDate FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID; END; GO CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_MetricTypes @ProjectID int AS BEGIN SET NOCOUNT ON; SELECT MetricTypeID, ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive FROM dbo.SceneMetricTypes WHERE IsActive = 1 AND (ProjectID IS NULL OR ProjectID = @ProjectID) ORDER BY SortOrder, MetricName; END; GO CREATE OR ALTER PROCEDURE dbo.ProjectTimelineMetricSettings_List @ProjectID int AS BEGIN SET NOCOUNT ON; EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID; SELECT ptms.ProjectID, ptms.MetricTypeID, mt.MetricName, mt.SortOrder FROM dbo.ProjectTimelineMetricSettings ptms INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID WHERE ptms.ProjectID = @ProjectID AND mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID) ORDER BY ptms.SortOrder, mt.SortOrder, mt.MetricName; END; GO CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_Save @ProjectID int, @ShowSceneCards bit, @ShowMetricShape bit, @ShowPlotLines bit, @ShowStoryAssets bit, @ShowCharacterAppearances bit, @ShowWarnings bit, @MetricTypeIDs nvarchar(max) = NULL AS BEGIN SET NOCOUNT ON; EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID; UPDATE dbo.ProjectTimelineSettings SET ShowSceneCards = @ShowSceneCards, ShowMetricShape = @ShowMetricShape, ShowPlotLines = @ShowPlotLines, ShowStoryAssets = @ShowStoryAssets, ShowCharacterAppearances = @ShowCharacterAppearances, ShowWarnings = @ShowWarnings, UpdatedDate = SYSUTCDATETIME() WHERE ProjectID = @ProjectID; DELETE FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID; IF @MetricTypeIDs IS NOT NULL AND LTRIM(RTRIM(@MetricTypeIDs)) <> N'' BEGIN INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder) SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder FROM dbo.SceneMetricTypes mt INNER JOIN ( SELECT DISTINCT TRY_CONVERT(int, value) AS MetricTypeID FROM string_split(@MetricTypeIDs, N',') WHERE TRY_CONVERT(int, value) IS NOT NULL ) selected ON selected.MetricTypeID = mt.MetricTypeID WHERE mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID); END; END; GO CREATE OR ALTER PROCEDURE dbo.Timeline_GetByProject @ProjectID int, @BookID int = NULL, @IncludeMetrics bit = 1, @SelectedMetricTypeIDs nvarchar(max) = NULL, @IncludePlotLines bit = 1 AS BEGIN SET NOCOUNT ON; DECLARE @MetricSelection TABLE (MetricTypeID int NOT NULL PRIMARY KEY); INSERT @MetricSelection (MetricTypeID) SELECT DISTINCT TRY_CONVERT(int, value) FROM string_split(COALESCE(@SelectedMetricTypeIDs, N''), N',') WHERE TRY_CONVERT(int, value) IS NOT NULL; SELECT ProjectID, ProjectName, Description, CreatedDate, UpdatedDate, IsArchived FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0; SELECT BookID, ProjectID, BookTitle, BookNumber, Description, SortOrder, CreatedDate, UpdatedDate, IsArchived FROM dbo.Books WHERE ProjectID = @ProjectID AND IsArchived = 0 AND (@BookID IS NULL OR BookID = @BookID) ORDER BY SortOrder, BookNumber; SELECT c.ChapterID, c.BookID, c.ChapterNumber, c.ChapterTitle, c.POVCharacterID, c.Summary, c.SortOrder, c.RevisionStatusID, rs.StatusName AS RevisionStatusName, c.CreatedDate, c.UpdatedDate, c.IsArchived FROM dbo.Chapters c INNER JOIN dbo.Books b ON b.BookID = c.BookID INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = c.RevisionStatusID WHERE b.ProjectID = @ProjectID AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID) ORDER BY b.SortOrder, c.SortOrder; SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID, s.PrimaryLocationID, location.LocationName AS PrimaryLocationName, location.LocationPath AS PrimaryLocationPath, s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime, s.EndDateTime, s.DurationAmount, s.DurationUnitID, du.DurationUnitName, s.RelativeTimeText, s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes, s.SceneOutcomeNotes, s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived FROM dbo.Scenes s INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID LEFT JOIN dbo.LocationPaths location ON location.LocationID = s.PrimaryLocationID WHERE b.ProjectID = @ProjectID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID) ORDER BY b.SortOrder, c.SortOrder, s.SortOrder; SELECT sp.SceneID, spt.ScenePurposeTypeID, spt.PurposeName, spt.SortOrder FROM dbo.ScenePurposes sp INNER JOIN dbo.ScenePurposeTypes spt ON spt.ScenePurposeTypeID = sp.ScenePurposeTypeID INNER JOIN dbo.Scenes s ON s.SceneID = sp.SceneID INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID WHERE b.ProjectID = @ProjectID AND (@BookID IS NULL OR b.BookID = @BookID) ORDER BY spt.SortOrder; SELECT MetricTypeID, ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive FROM dbo.SceneMetricTypes WHERE @IncludeMetrics = 1 AND IsActive = 1 AND (ProjectID IS NULL OR ProjectID = @ProjectID) AND (NOT EXISTS (SELECT 1 FROM @MetricSelection) OR MetricTypeID IN (SELECT MetricTypeID FROM @MetricSelection)) ORDER BY SortOrder; SELECT s.SceneID, mt.MetricTypeID, mt.MetricName, COALESCE(smv.Value, mt.DefaultValue) AS Value, smv.Notes FROM dbo.Scenes s INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID INNER JOIN dbo.SceneMetricTypes mt ON mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID) LEFT JOIN dbo.SceneMetricValues smv ON smv.SceneID = s.SceneID AND smv.MetricTypeID = mt.MetricTypeID WHERE @IncludeMetrics = 1 AND b.ProjectID = @ProjectID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID) AND (NOT EXISTS (SELECT 1 FROM @MetricSelection) OR mt.MetricTypeID IN (SELECT MetricTypeID FROM @MetricSelection)) ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, mt.SortOrder; SELECT pl.PlotLineID, pl.ProjectID, pl.BookID, b.BookTitle, pl.PlotLineName, pl.PlotLineTypeID, plt.TypeName AS PlotLineTypeName, pl.Description, pl.ParentPlotLineID, parent.PlotLineName AS ParentPlotLineName, pl.SortOrder, pl.Colour, pl.IsMainPlot, pl.IsVisibleOnTimeline, pl.CreatedDate, pl.UpdatedDate, pl.IsArchived FROM dbo.PlotLines pl INNER JOIN dbo.PlotLineTypes plt ON plt.PlotLineTypeID = pl.PlotLineTypeID LEFT JOIN dbo.Books b ON b.BookID = pl.BookID LEFT JOIN dbo.PlotLines parent ON parent.PlotLineID = pl.ParentPlotLineID WHERE @IncludePlotLines = 1 AND pl.ProjectID = @ProjectID AND pl.IsArchived = 0 AND pl.IsVisibleOnTimeline = 1 AND (@BookID IS NULL OR pl.BookID IS NULL OR pl.BookID = @BookID) ORDER BY pl.SortOrder, pl.PlotLineName; SELECT te.ThreadEventID, te.PlotThreadID, pt.ThreadTitle, pt.PlotLineID, pl.PlotLineName, pl.Colour, te.SceneID, te.EventTypeID, tet.TypeName AS EventTypeName, tet.MarkerText, te.EventTitle, te.EventDescription, te.CreatedDate, te.UpdatedDate FROM dbo.ThreadEvents te INNER JOIN dbo.PlotThreads pt ON pt.PlotThreadID = te.PlotThreadID INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID INNER JOIN dbo.ThreadEventTypes tet ON tet.ThreadEventTypeID = te.EventTypeID INNER JOIN dbo.Scenes s ON s.SceneID = te.SceneID INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID WHERE @IncludePlotLines = 1 AND b.ProjectID = @ProjectID AND pl.IsArchived = 0 AND pt.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID) ORDER BY pl.SortOrder, pt.ThreadTitle, b.SortOrder, c.SortOrder, s.SortOrder; END; GO