Bug fix: Writer Workspace Focus project filter is ignored

This commit is contained in:
Nick Beckley 2026-06-14 17:18:18 +01:00
parent 42325ab738
commit cfe95a510f
3 changed files with 21 additions and 18 deletions

View File

@ -13,7 +13,7 @@ public sealed class WriterController(
public async Task<IActionResult> Index(int? projectId) public async Task<IActionResult> Index(int? projectId)
{ {
var model = await writerWorkspace.GetDashboardAsync(projectId); var model = await writerWorkspace.GetDashboardAsync(projectId);
model.WritingSchedule = await writingSchedule.GetTodayDashboardAsync(); model.WritingSchedule = await writingSchedule.GetTodayDashboardAsync(projectId);
return View(model); return View(model);
} }

View File

@ -289,12 +289,12 @@ public interface IWritingScheduleRepository
Task<IReadOnlyList<WritingPlanManagementItem>> GetWritingPlansForManagementAsync(int userId); Task<IReadOnlyList<WritingPlanManagementItem>> GetWritingPlansForManagementAsync(int userId);
Task<IReadOnlyList<WritingScheduleScene>> GetSchedulingScenesAsync(int projectId, int? bookId, bool includeBlockedScenes); Task<IReadOnlyList<WritingScheduleScene>> GetSchedulingScenesAsync(int projectId, int? bookId, bool includeBlockedScenes);
Task ReplaceScheduleItemsAsync(int writingPlanId, IReadOnlyList<WritingScheduleItem> items); Task ReplaceScheduleItemsAsync(int writingPlanId, IReadOnlyList<WritingScheduleItem> items);
Task<IReadOnlyList<WritingPlanSummary>> GetWritingPlanSummariesByUserAsync(int userId); Task<IReadOnlyList<WritingPlanSummary>> GetWritingPlanSummariesByUserAsync(int userId, int? projectId = null);
Task<IReadOnlyList<WritingSchedulePreviewItem>> GetSchedulePreviewItemsAsync(int writingPlanId); Task<IReadOnlyList<WritingSchedulePreviewItem>> GetSchedulePreviewItemsAsync(int writingPlanId);
Task DeleteScheduleItemsByPlanAsync(int writingPlanId); Task DeleteScheduleItemsByPlanAsync(int writingPlanId);
Task<IReadOnlyList<WritingScheduleDashboardItem>> GetActiveScheduleDashboardItemsAsync(int userId); Task<IReadOnlyList<WritingScheduleDashboardItem>> GetActiveScheduleDashboardItemsAsync(int userId, int? projectId = null);
Task<int> UpdatePlannedScheduleItemStatusForUserAsync(int writingScheduleItemId, int userId, string scheduleStatus, DateTime? completedDateUtc); Task<int> UpdatePlannedScheduleItemStatusForUserAsync(int writingScheduleItemId, int userId, string scheduleStatus, DateTime? completedDateUtc);
Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int userId, DateTime today); Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int userId, DateTime today, int? projectId = null);
Task UpdatePlannedScheduleItemDatesAsync(int writingPlanId, IReadOnlyList<WritingScheduleItemDateChange> changes); Task UpdatePlannedScheduleItemDatesAsync(int writingPlanId, IReadOnlyList<WritingScheduleItemDateChange> changes);
} }
@ -1141,7 +1141,7 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
} }
} }
public async Task<IReadOnlyList<WritingPlanSummary>> GetWritingPlanSummariesByUserAsync(int userId) public async Task<IReadOnlyList<WritingPlanSummary>> GetWritingPlanSummariesByUserAsync(int userId, int? projectId = null)
{ {
using var connection = connectionFactory.CreateConnection(); using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<WritingPlanSummary>( var rows = await connection.QueryAsync<WritingPlanSummary>(
@ -1159,9 +1159,10 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
INNER JOIN dbo.Projects p ON p.ProjectID = wp.ProjectID INNER JOIN dbo.Projects p ON p.ProjectID = wp.ProjectID
LEFT JOIN dbo.Books b ON b.BookID = wp.BookID LEFT JOIN dbo.Books b ON b.BookID = wp.BookID
WHERE wp.UserID = @UserID WHERE wp.UserID = @UserID
AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
ORDER BY wp.IsActive DESC, wp.DeadlineDate, wp.PlanName, wp.WritingPlanID; ORDER BY wp.IsActive DESC, wp.DeadlineDate, wp.PlanName, wp.WritingPlanID;
""", """,
new { UserID = userId }); new { UserID = userId, ProjectID = projectId });
return rows.ToList(); return rows.ToList();
} }
@ -1206,7 +1207,7 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
new { WritingPlanID = writingPlanId }); new { WritingPlanID = writingPlanId });
} }
public async Task<IReadOnlyList<WritingScheduleDashboardItem>> GetActiveScheduleDashboardItemsAsync(int userId) public async Task<IReadOnlyList<WritingScheduleDashboardItem>> GetActiveScheduleDashboardItemsAsync(int userId, int? projectId = null)
{ {
using var connection = connectionFactory.CreateConnection(); using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<WritingScheduleDashboardItem>( var rows = await connection.QueryAsync<WritingScheduleDashboardItem>(
@ -1237,9 +1238,10 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
WHERE wp.UserID = @UserID WHERE wp.UserID = @UserID
AND wp.IsActive = 1 AND wp.IsActive = 1
AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
ORDER BY wsi.ScheduledDate, wsi.WritingScheduleItemID; ORDER BY wsi.ScheduledDate, wsi.WritingScheduleItemID;
""", """,
new { UserID = userId }); new { UserID = userId, ProjectID = projectId });
return rows.ToList(); return rows.ToList();
} }
@ -1268,7 +1270,7 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
}); });
} }
public async Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int userId, DateTime today) public async Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int userId, DateTime today, int? projectId = null)
{ {
using var connection = connectionFactory.CreateConnection(); using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<WritingPlanSummary>( var rows = await connection.QueryAsync<WritingPlanSummary>(
@ -1287,6 +1289,7 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
LEFT JOIN dbo.Books b ON b.BookID = wp.BookID LEFT JOIN dbo.Books b ON b.BookID = wp.BookID
WHERE wp.UserID = @UserID WHERE wp.UserID = @UserID
AND wp.IsActive = 1 AND wp.IsActive = 1
AND (@ProjectID IS NULL OR wp.ProjectID = @ProjectID)
AND EXISTS AND EXISTS
( (
SELECT 1 SELECT 1
@ -1297,7 +1300,7 @@ public sealed class WritingScheduleRepository(ISqlConnectionFactory connectionFa
) )
ORDER BY wp.DeadlineDate, wp.PlanName, wp.WritingPlanID; ORDER BY wp.DeadlineDate, wp.PlanName, wp.WritingPlanID;
""", """,
new { UserID = userId, Today = today.Date }); new { UserID = userId, Today = today.Date, ProjectID = projectId });
return rows.ToList(); return rows.ToList();
} }

View File

@ -283,10 +283,10 @@ public interface IWritingScheduleService
Task<WritingScheduleSetupViewModel> GetScheduleSetupAsync(int? projectId); Task<WritingScheduleSetupViewModel> GetScheduleSetupAsync(int? projectId);
Task PopulateScheduleSetupOptionsAsync(WritingScheduleSetupViewModel model); Task PopulateScheduleSetupOptionsAsync(WritingScheduleSetupViewModel model);
Task<WritingScheduleSetupResult> CreateScheduleFromSetupAsync(WritingScheduleSetupViewModel model); Task<WritingScheduleSetupResult> CreateScheduleFromSetupAsync(WritingScheduleSetupViewModel model);
Task<WritingScheduleDashboardViewModel> GetTodayDashboardAsync(); Task<WritingScheduleDashboardViewModel> GetTodayDashboardAsync(int? projectId = null);
Task<bool> MarkScheduleItemCompleteAsync(int writingScheduleItemId); Task<bool> MarkScheduleItemCompleteAsync(int writingScheduleItemId);
Task<bool> SkipScheduleItemAsync(int writingScheduleItemId); Task<bool> SkipScheduleItemAsync(int writingScheduleItemId);
Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(); Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int? projectId = null);
Task<WritingScheduleRebalancePreviewViewModel> PreviewRebalanceAsync(int writingPlanId); Task<WritingScheduleRebalancePreviewViewModel> PreviewRebalanceAsync(int writingPlanId);
Task<WritingScheduleRebalancePreviewViewModel> ApplyRebalanceAsync(int writingPlanId); Task<WritingScheduleRebalancePreviewViewModel> ApplyRebalanceAsync(int writingPlanId);
} }
@ -3671,17 +3671,17 @@ public sealed class WritingScheduleService(
} }
} }
public async Task<WritingScheduleDashboardViewModel> GetTodayDashboardAsync() public async Task<WritingScheduleDashboardViewModel> GetTodayDashboardAsync(int? projectId = null)
{ {
if (!currentUser.UserId.HasValue) if (!currentUser.UserId.HasValue)
{ {
return new WritingScheduleDashboardViewModel(); return new WritingScheduleDashboardViewModel();
} }
var plans = await writingSchedule.GetWritingPlanSummariesByUserAsync(currentUser.UserId.Value); var plans = await writingSchedule.GetWritingPlanSummariesByUserAsync(currentUser.UserId.Value, projectId);
var activePlanCount = plans.Count(x => x.IsActive); var activePlanCount = plans.Count(x => x.IsActive);
var plansRequiringRebalance = await writingSchedule.GetPlansRequiringRebalanceAsync(currentUser.UserId.Value, DateTime.Today); var plansRequiringRebalance = await writingSchedule.GetPlansRequiringRebalanceAsync(currentUser.UserId.Value, DateTime.Today, projectId);
var items = await writingSchedule.GetActiveScheduleDashboardItemsAsync(currentUser.UserId.Value); var items = await writingSchedule.GetActiveScheduleDashboardItemsAsync(currentUser.UserId.Value, projectId);
var today = DateTime.Today; var today = DateTime.Today;
var plannedItems = items var plannedItems = items
.Where(x => string.Equals(x.ScheduleStatus, "Planned", StringComparison.OrdinalIgnoreCase)) .Where(x => string.Equals(x.ScheduleStatus, "Planned", StringComparison.OrdinalIgnoreCase))
@ -3743,14 +3743,14 @@ public sealed class WritingScheduleService(
return affectedRows > 0; return affectedRows > 0;
} }
public async Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync() public async Task<IReadOnlyList<WritingPlanSummary>> GetPlansRequiringRebalanceAsync(int? projectId = null)
{ {
if (!currentUser.UserId.HasValue) if (!currentUser.UserId.HasValue)
{ {
return []; return [];
} }
return await writingSchedule.GetPlansRequiringRebalanceAsync(currentUser.UserId.Value, DateTime.Today); return await writingSchedule.GetPlansRequiringRebalanceAsync(currentUser.UserId.Value, DateTime.Today, projectId);
} }
public async Task<WritingScheduleRebalancePreviewViewModel> PreviewRebalanceAsync(int writingPlanId) public async Task<WritingScheduleRebalancePreviewViewModel> PreviewRebalanceAsync(int writingPlanId)