From bc514c5ab7da5bcc5ddb7e627a5f8c5c1cbe4904 Mon Sep 17 00:00:00 2001 From: Cemonix Date: Sun, 7 Sep 2025 19:32:43 +0200 Subject: [PATCH 1/2] refactor: Enhance task update logic to prioritize assignment changes and validate permissions --- server/Server/Services/TaskService.cs | 85 +++++++++++++++------------ 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/server/Server/Services/TaskService.cs b/server/Server/Services/TaskService.cs index 62d4ba2..348d299 100644 --- a/server/Server/Services/TaskService.cs +++ b/server/Server/Services/TaskService.cs @@ -231,59 +231,72 @@ public async Task CreateTaskAsync(int projectId, CreateTaskDto createDt return null; } - // Validate task assignment before allowing modifications - if (!string.IsNullOrEmpty(updatingUserId)) - { - await ValidateTaskAssignmentAsync(taskId, updatingUserId, "UPDATE"); - } - - // Update the task properties - if (updateDto.Priority.HasValue) - { - existingTask.Priority = updateDto.Priority.Value; - } - - // Handle assignment - support both userId and email assignment - if (updateDto.AssignedToEmail != null) + // Determine what type of changes are requested + var isAssignmentChangeRequested = updateDto.AssignedToEmail != null || updateDto.AssignedToUserId != null; + var isNonAssignmentChangeRequested = + updateDto.Priority.HasValue || + updateDto.DueDate.HasValue || + updateDto.Status.HasValue || + updateDto.WorkflowStageId.HasValue || + updateDto.Metadata != null || + updateDto.CompletedAt.HasValue || + updateDto.ArchivedAt.HasValue || + updateDto.SuspendedAt.HasValue || + updateDto.DeferredAt.HasValue || + updateDto.WorkingTimeMs.HasValue; + + // Handle assignment changes first (with role-based permission validation) + if (isAssignmentChangeRequested) { string? newAssignedUserId; - // Assignment by email - look up the user ID - if (string.IsNullOrEmpty(updateDto.AssignedToEmail)) + if (updateDto.AssignedToEmail != null) { - // Empty email means unassign - newAssignedUserId = null; + // Assignment by email + if (string.IsNullOrEmpty(updateDto.AssignedToEmail)) + { + // Empty email means unassign + newAssignedUserId = null; + } + else + { + // Find user by email + var user = await _userManager.FindByEmailAsync(updateDto.AssignedToEmail); + if (user == null) + { + _logger.LogWarning("User not found for assignment email: {Email}", updateDto.AssignedToEmail); + throw new NotFoundException($"User with email '{updateDto.AssignedToEmail}' not found"); + } + newAssignedUserId = user.Id; + } } else { - // Find user by email - var user = await _userManager.FindByEmailAsync(updateDto.AssignedToEmail); - if (user == null) - { - _logger.LogWarning("User not found for assignment email: {Email}", updateDto.AssignedToEmail); - throw new NotFoundException($"User with email '{updateDto.AssignedToEmail}' not found"); - } - newAssignedUserId = user.Id; + // Assignment by user ID (legacy) + newAssignedUserId = updateDto.AssignedToUserId; } // Validate assignment permissions if assignment is changing and updatingUserId is provided if (existingTask.AssignedToUserId != newAssignedUserId && !string.IsNullOrEmpty(updatingUserId)) { - await ValidateTaskAssignmentPermissionAsync(existingTask.ProjectId, updatingUserId, newAssignedUserId); + await ValidateTaskAssignmentPermissionAsync(existingTask.ProjectId, updatingUserId!, newAssignedUserId); } + // Apply the assignment change existingTask.AssignedToUserId = newAssignedUserId; } - else if (updateDto.AssignedToUserId != null && updateDto.AssignedToUserId != existingTask.AssignedToUserId) + + // For non-assignment updates, ensure user is assigned to the task + // (This runs AFTER potential assignment changes so self-assignment is considered) + if (isNonAssignmentChangeRequested && !string.IsNullOrEmpty(updatingUserId)) { - // Validate assignment permissions if updatingUserId is provided - if (!string.IsNullOrEmpty(updatingUserId)) - { - await ValidateTaskAssignmentPermissionAsync(existingTask.ProjectId, updatingUserId, updateDto.AssignedToUserId); - } + await ValidateTaskAssignmentAsync(taskId, updatingUserId!, "UPDATE"); + } - // Assignment by userId (legacy support) - only update if explicitly provided - existingTask.AssignedToUserId = updateDto.AssignedToUserId; + // Update the task properties + if (updateDto.Priority.HasValue) + { + existingTask.Priority = updateDto.Priority.Value; } if (updateDto.Status.HasValue) @@ -661,4 +674,4 @@ private async Task ValidateTaskAssignmentAsync(int taskId, string userId, } #endregion -} \ No newline at end of file +} From bb4c94f7153b2f3a731cb412ee895ad06379eb59 Mon Sep 17 00:00:00 2001 From: Cemonix Date: Sun, 7 Sep 2025 19:32:58 +0200 Subject: [PATCH 2/2] feat: Enhance task handling with improved error propagation and toast notifications --- .../common/toast/ToastContainer.vue | 2 +- .../project/task/AssetThumbnailCell.vue | 19 +++++--- .../core/workspace/loader/workspaceLoader.ts | 8 +++- frontend/src/layouts/WorkspaceLayout.vue | 9 +++- .../src/services/project/task/taskService.ts | 33 ++++++++----- frontend/src/stores/workspaceStore.ts | 5 +- frontend/src/views/AnnotationWorkspace.vue | 47 +++++++++++-------- frontend/src/views/project/TasksView.vue | 3 +- 8 files changed, 80 insertions(+), 46 deletions(-) diff --git a/frontend/src/components/common/toast/ToastContainer.vue b/frontend/src/components/common/toast/ToastContainer.vue index e603b1a..bc3b5c3 100644 --- a/frontend/src/components/common/toast/ToastContainer.vue +++ b/frontend/src/components/common/toast/ToastContainer.vue @@ -38,7 +38,7 @@ const handleRemoveToast = (id: string) => { position: fixed; top: 80px; right: 1.5rem; - z-index: 1000; + z-index: 2000; pointer-events: none; @media (max-width: 768px) { diff --git a/frontend/src/components/project/task/AssetThumbnailCell.vue b/frontend/src/components/project/task/AssetThumbnailCell.vue index 42c9b01..ae96ad6 100644 --- a/frontend/src/components/project/task/AssetThumbnailCell.vue +++ b/frontend/src/components/project/task/AssetThumbnailCell.vue @@ -1,5 +1,10 @@