Skip to content

feat: tasks management with periodic schedule #1781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 76 commits into from
Apr 16, 2025
Merged

Conversation

ab-smith
Copy link
Contributor

@ab-smith ab-smith commented Mar 29, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive task management system with task templates and task nodes.
    • Added scheduling capabilities for recurring and one-time tasks with customizable intervals and frequencies.
    • Integrated task calendar views showing tasks alongside applied controls and risk acceptances.
    • Included user-specific task retrieval and management APIs.
    • Added frontend forms and components for creating and editing tasks and templates.
    • Expanded navigation menu and localization support for task-related functionality.
    • Enhanced filtering and list views for task entities with status-based filters.
    • Added calendar navigation by year and month with URL-based routing and task filtering options.
    • Added a calendar side panel for detailed day view and task filtering toggle.
    • Improved date handling and task scheduling utilities for accurate recurrence and occurrence management.
  • Bug Fixes

    • Corrected typographical errors in localization keys across multiple languages.
  • Documentation

    • Updated architecture documentation to include the new task data model and scheduling schema.
  • Tests

    • Added comprehensive backend tests covering task scheduling utilities and occurrence calculations.
  • Chores

    • Updated permissions and access controls to include task management roles.
    • Specified the frontend package manager for consistent development environment.

Copy link
Contributor

coderabbitai bot commented Mar 29, 2025

Walkthrough

This update introduces a comprehensive task management system to the application. It adds new backend models (TaskTemplate, TaskNode), serializers, views, permissions, and related migrations to support recurring and one-off tasks. Utility functions for scheduling logic and test coverage are implemented. The API is extended with endpoints for managing and viewing tasks and their templates. On the frontend, new forms, schemas, navigation items, and table configurations are created for task templates and nodes. The calendar feature is refactored to display tasks alongside existing controls and risk acceptances, with internationalization support expanded for task-related terminology. Documentation is updated to reflect the new data model.

Changes

File(s) Change Summary
backend/core/models.py, backend/core/migrations/0068_tasktemplate_tasknode.py Introduced TaskTemplate and TaskNode models, their fields, relationships, and a migration for database schema changes.
backend/core/serializers.py Added serializers for reading and writing TaskTemplate and TaskNode instances.
backend/core/views.py Created TaskTemplateViewSet and TaskNodeViewSet with calendar and synchronization logic; updated filtering on existing filtersets.
backend/core/urls.py Registered new API routes for task templates and nodes.
backend/core/utils.py Added utility functions for date conversion, schedule matching, recurrence calculation, and task occurrence generation.
backend/core/startup.py Updated permissions lists to include task and task template permissions for various user roles.
backend/core/tests/test_task.py Added unit tests for task scheduling utility functions.
documentation/architecture/data-model.md Replaced asset compliance section with a detailed "Tasks" section, defining the new entities and their relationships.
frontend/src/lib/utils/crud.ts Added task templates and nodes to the model map, defining their relationships and UI configuration.
frontend/src/lib/utils/schemas.ts Introduced Zod schemas for task templates and nodes, and registered them in the schema map.
frontend/src/lib/utils/table.ts Added list view and filter configurations for task templates and nodes.
frontend/src/lib/utils/types.ts Added task-templates and task-nodes to the list of URL models.
frontend/src/lib/components/Forms/ModelForm.svelte Integrated TaskTemplateForm and TaskNodeForm for their respective models.
frontend/src/lib/components/Forms/ModelForm/TaskTemplateForm.svelte, frontend/src/lib/components/Forms/ModelForm/TaskNodeForm.svelte Added new Svelte components for task template and node forms with comprehensive field support.
frontend/src/lib/components/Forms/AutocompleteSelect.svelte, frontend/src/lib/components/Forms/NumberField.svelte, frontend/src/lib/components/Forms/Select.svelte, frontend/src/lib/components/Forms/TextField.svelte Enhanced form components to support nested value paths for more flexible data handling.
frontend/src/lib/components/SideBar/navData.ts Added a sidebar navigation entry for tasks.
frontend/messages/en.json, frontend/messages/fr.json Added comprehensive task-related localization keys and help texts.
frontend/messages/ar.json, frontend/messages/cs.json, frontend/messages/de.json, frontend/messages/es.json, frontend/messages/hi.json, frontend/messages/id.json, frontend/messages/nl.json, frontend/messages/pl.json, frontend/messages/pt.json, frontend/messages/ro.json, frontend/messages/ur.json Fixed a typographical error in the password setting key across multiple languages.
frontend/package.json Declared the package manager used for the project.
frontend/src/lib/components/Calendar/Calendar.svelte Refactored calendar navigation to use anchor links and removed notification logic.
frontend/src/routes/(app)/(internal)/calendar/+page.server.ts Changed calendar page logic to redirect to the current month/year.
frontend/src/routes/(app)/(internal)/calendar/+page.svelte Removed the old calendar page component.
frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.server.ts, frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte Added new calendar page components to display tasks, controls, and acceptances for a specific month/year.
frontend/tests/functional/detailed/login.test.ts, frontend/tests/functional/nav.test.ts Updated navigation and login tests to expect dynamic calendar URLs; added a test for login redirect behavior.
frontend/src/routes/(authentication)/first-connexion/+page.svelte Fixed a typo in the password setting method call.
documentation/functional_testing/architecture.md Added a blank line for formatting consistency.
frontend/src/lib/utils/stores.ts Added a persisted store showAllEvents to control task visibility filtering in the UI.
frontend/src/lib/components/Calendar/Day.svelte Refactored day cell rendering to use reactive declarations, dynamic classes, and side panel interaction.
frontend/src/lib/components/Calendar/Notifications.svelte Removed the notifications component from the calendar UI.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant API
    participant DB

    User->>Frontend: Navigates to /calendar/{year}/{month}
    Frontend->>API: GET applied-controls, risk-acceptances, user tasks (for month)
    API->>DB: Fetch applied controls, risk acceptances, task nodes/templates
    DB-->>API: Return data
    API-->>Frontend: Return controls, acceptances, tasks
    Frontend->>User: Renders calendar with all events
Loading
sequenceDiagram
    participant Admin
    participant Frontend
    participant API
    participant DB

    Admin->>Frontend: Creates/updates TaskTemplate via form
    Frontend->>API: POST/PUT TaskTemplate
    API->>DB: Save TaskTemplate
    API->>API: Sync TaskNodes for template (generate occurrences)
    API->>DB: Create/update/delete TaskNode records as needed
    DB-->>API: Confirmation
    API-->>Frontend: Response with updated TaskTemplate/TaskNodes
    Frontend->>Admin: Shows updated template and instances
Loading

Poem

🐇✨
Tasks now hop with nimble feet,
Templates guide their steady beat.
Nodes appear on calendar days,
Recurring chores in bunny ways.
With forms and lists, our work’s complete—
A burrow full of tasks, so neat!
Let’s leap ahead, the future’s bright—
For every task, a rabbit’s delight!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 432bd3a and f25424a.

📒 Files selected for processing (3)
  • frontend/messages/en.json (1 hunks)
  • frontend/messages/fr.json (1 hunks)
  • frontend/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/package.json
  • frontend/messages/fr.json
  • frontend/messages/en.json
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: test (3.12)
  • GitHub Check: build (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ab-smith ab-smith changed the title feat: periodic tasks feat: tasks management with periodic schedule Mar 31, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
backend/core/views.py (4)

5173-5179: Update comment to match implementation.

The comment mentions "next 10 upcoming tasks" but the code doesn't limit to 10 tasks - it processes all tasks.

Update the comment to reflect the actual implementation:

- # Process all past tasks and next 10 upcoming tasks
+ # Process all past tasks and all upcoming tasks

5302-5304: Fix parameter name typo in status method.

There's a typo in the parameter name: srlf instead of self.

-    def status(srlf, request):
+    def status(self, request):
🧰 Tools
🪛 Ruff (0.8.2)

5304-5304: TaskNode may be undefined, or defined from star imports

(F405)


5305-5310: Don't call save() redundantly in perform_create.

The perform_create method calls save() on the instance, but the serializer.save() already does this. This is redundant and could potentially cause issues.

def perform_create(self, serializer):
    instance: TaskNode = serializer.save()
-    instance.save()
    return super().perform_create(serializer)
🧰 Tools
🪛 Ruff (0.8.2)

5307-5307: TaskNode may be undefined, or defined from star imports

(F405)


5264-5282: Implement pagination for the calendar endpoint to handle large volumes of tasks.

The calendar endpoint retrieves all enabled task templates without pagination, which could lead to performance issues with a large number of templates.

Consider adding pagination support or limiting the number of tasks returned:

@action(
    detail=False,
    name="Get tasks for the calendar",
    url_path="calendar/(?P<start>.+)/(?P<end>.+)",
)
def calendar(
    self,
    request,
    start=None,
    end=None,
):
    if start is None:
        start = timezone.now().date()
    if end is None:
        end = timezone.now().date() + relativedelta.relativedelta(months=1)
+   
+   # Get limit from query params or use default
+   limit = request.query_params.get('limit', None)
+   if limit:
+       try:
+           limit = int(limit)
+       except ValueError:
+           return Response({"error": "Invalid limit parameter"}, status=400)
+   
+   # Get all tasks
+   tasks = self.task_calendar(
+       task_templates=TaskTemplate.objects.filter(enabled=True),
+       start=start,
+       end=end,
+   )
+   
+   # Apply limit if specified
+   if limit:
+       tasks = tasks[:limit]
    
-   return Response(
-       self.task_calendar(
-           task_templates=TaskTemplate.objects.filter(enabled=True),
-           start=start,
-           end=end,
-       )
-   )
+   return Response(tasks)
🧰 Tools
🪛 Ruff (0.8.2)

5277-5277: TaskTemplate may be undefined, or defined from star imports

(F405)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87f1ac9 and 03100b7.

📒 Files selected for processing (1)
  • backend/core/views.py (6 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
backend/core/views.py

2216-2216: TaskTemplate may be undefined, or defined from star imports

(F405)


5140-5140: TaskTemplate may be undefined, or defined from star imports

(F405)


5201-5201: TaskTemplate may be undefined, or defined from star imports

(F405)


5202-5202: TaskNode may be undefined, or defined from star imports

(F405)


5213-5213: TaskNodeReadSerializer may be undefined, or defined from star imports

(F405)


5217-5217: TaskTemplate may be undefined, or defined from star imports

(F405)


5219-5219: TaskNode may be undefined, or defined from star imports

(F405)


5245-5245: TaskTemplate may be undefined, or defined from star imports

(F405)


5251-5251: TaskNode may be undefined, or defined from star imports

(F405)


5258-5258: TaskNode may be undefined, or defined from star imports

(F405)


5277-5277: TaskTemplate may be undefined, or defined from star imports

(F405)


5299-5299: TaskNode may be undefined, or defined from star imports

(F405)


5304-5304: TaskNode may be undefined, or defined from star imports

(F405)


5307-5307: TaskNode may be undefined, or defined from star imports

(F405)

🪛 GitHub Actions: Backend Linters
backend/core/views.py

[error] 1-1: Ruff formatting check failed. File would be reformatted. Run 'ruff format' to fix code style issues.

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
backend/core/views.py (1)

1989-1995: Good enhancement for time-based filtering.

Adding 'month' and 'year' filters to the expiry_date field in RiskAcceptanceFilterSet enhances the API's filtering capabilities for calendar-based views.

@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
@intuitem intuitem deleted a comment from coderabbitai bot Apr 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
backend/core/views.py (2)

5149-5156: Ensure logic aligns with code comments regarding "next 10 tasks."

The comment mentions "next 10 upcoming tasks," but the code doesn't actually limit to 10 tasks. This mismatch might cause confusion for maintainers.


5192-5235: 🛠️ Refactor suggestion

Consider more targeted updates to prevent data loss.

The current implementation marks all task nodes for deletion upfront and then conditionally recreates them. If an error occurs during processing, all task nodes might be deleted without proper replacements.

Use a transaction to ensure atomicity and handle cleanup properly:

def _sync_task_nodes(self, task_template: TaskTemplate):
+   with transaction.atomic():
        # Soft-delete all existing TaskNode instances associated with this TaskTemplate
        TaskNode.objects.filter(task_template=task_template).update(to_delete=True)

        # Determine the end date based on the frequency
        if task_template.is_recurrent:
            # ... existing code ...
            
        else:
            TaskNode.objects.create(
                due_date=task_template.task_date,
                status="pending",
                task_template=task_template,
                folder=task_template.folder,
            )
        # garbage-collect
        TaskNode.objects.filter(to_delete=True).delete()
🧰 Tools
🪛 Ruff (0.8.2)

5192-5192: TaskTemplate may be undefined, or defined from star imports

(F405)


5195-5195: TaskNode may be undefined, or defined from star imports

(F405)


5221-5221: TaskTemplate may be undefined, or defined from star imports

(F405)


5227-5227: TaskNode may be undefined, or defined from star imports

(F405)


5234-5234: TaskNode may be undefined, or defined from star imports

(F405)

🧹 Nitpick comments (4)
backend/core/views.py (4)

11-11: Redundant import found.

You have two imports for relativedelta from dateutil at lines 11 and 97 - one as the default name and one aliased as rd. This could cause confusion for developers.

-from dateutil import relativedelta
+from dateutil import relativedelta
 # ... other imports ...
-from dateutil import relativedelta as rd
+# Use the already imported relativedelta

Also applies to: 97-97


5115-5115: Make imports explicit instead of using star imports.

The code refers to models and serializers (TaskTemplate, TaskNode, TaskNodeReadSerializer) imported from star imports (line 110: from .models import * and line 111: from .serializers import *). This makes it harder to understand dependencies and can lead to name collisions.

Import these classes explicitly:

-from .models import *
+from .models import (
+    AppliedControl,
+    # ... other existing models ...
+    TaskTemplate,
+    TaskNode,
+)

-from .serializers import *
+from .serializers import (
+    AppliedControlReadSerializer,
+    # ... other existing serializers ...
+    TaskNodeReadSerializer,
+)

Also applies to: 5176-5176, 5177-5177, 5188-5188, 5195-5195, 5221-5221, 5227-5227, 5234-5234, 5253-5253, 5277-5277, 5282-5282, 5285-5285

🧰 Tools
🪛 Ruff (0.8.2)

5115-5115: TaskTemplate may be undefined, or defined from star imports

(F405)


5157-5191: Avoid in-place modification of tasks_list.

The code modifies tasks_list in-place while iterating through it, which could lead to unexpected behavior if the list is used elsewhere or if the iteration pattern changes.

Instead of modifying the original list, consider creating a new list with the processed tasks:

-# Directly modify tasks in the original tasks_list
-for i in range(len(tasks_list)):
-    task = tasks_list[i]
+processed_tasks = []
+for task in tasks_list:
     task_date = task["due_date"]
     task_template_id = task["task_template"]

     # Create a unique identifier for this task to avoid duplication
     task_identifier = (task_template_id, task_date)

     # Skip if we've already processed this task
     if task_identifier in processed_tasks_identifiers:
-        continue
+        processed_tasks.append(task)
+        continue

     # Check if this task should be processed (is in past or next 10)
     if task in tasks_to_process:
         processed_tasks_identifiers.add(task_identifier)

         # Get or create the TaskNode
         task_template = TaskTemplate.objects.get(id=task_template_id)
         task_node, created = TaskNode.objects.get_or_create(
             task_template=task_template,
             due_date=task_date,
             defaults={
                 "status": "pending",
                 "folder": task_template.folder,
             },
         )
         task_node.to_delete = False
         task_node.save(update_fields=["to_delete"])
         # Replace the task dictionary with the actual TaskNode in the original list
-        tasks_list[i] = TaskNodeReadSerializer(task_node).data
+        processed_tasks.append(TaskNodeReadSerializer(task_node).data)
+     else:
+        processed_tasks.append(task)

-return tasks_list
+return processed_tasks
🧰 Tools
🪛 Ruff (0.8.2)

5176-5176: TaskTemplate may be undefined, or defined from star imports

(F405)


5177-5177: TaskNode may be undefined, or defined from star imports

(F405)


5188-5188: TaskNodeReadSerializer may be undefined, or defined from star imports

(F405)


5281-5282: Fix typo in method parameter name.

There's a typo in the parameter name (srlf instead of self).

-def status(srlf, request):
+def status(self, request):
     return Response(dict(TaskNode.TASK_STATUS_CHOICES))
🧰 Tools
🪛 Ruff (0.8.2)

5282-5282: TaskNode may be undefined, or defined from star imports

(F405)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03100b7 and 332b108.

📒 Files selected for processing (9)
  • backend/core/models.py (1 hunks)
  • backend/core/serializers.py (1 hunks)
  • backend/core/views.py (5 hunks)
  • frontend/messages/en.json (1 hunks)
  • frontend/messages/fr.json (1 hunks)
  • frontend/src/lib/components/Calendar/Calendar.svelte (4 hunks)
  • frontend/src/lib/utils/stores.ts (1 hunks)
  • frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.server.ts (1 hunks)
  • frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • frontend/src/lib/utils/stores.ts
  • frontend/messages/fr.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.server.ts
  • frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte
  • frontend/messages/en.json
  • backend/core/models.py
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/core/serializers.py (2)
backend/core/serializer_fields.py (1)
  • FieldsRelatedField (24-86)
backend/core/models.py (14)
  • risk_assessments (934-935)
  • risk_assessments (2158-2159)
  • assigned_to (4333-4334)
  • next_occurrence (4259-4264)
  • last_occurrence_status (4267-4279)
  • Meta (124-125)
  • Meta (179-180)
  • Meta (207-208)
  • Meta (212-214)
  • Meta (811-813)
  • Meta (877-879)
  • Meta (1008-1010)
  • TaskTemplate (4147-4298)
  • TaskNode (4301-4338)
🪛 Ruff (0.8.2)
backend/core/views.py

5115-5115: TaskTemplate may be undefined, or defined from star imports

(F405)


5176-5176: TaskTemplate may be undefined, or defined from star imports

(F405)


5177-5177: TaskNode may be undefined, or defined from star imports

(F405)


5188-5188: TaskNodeReadSerializer may be undefined, or defined from star imports

(F405)


5192-5192: TaskTemplate may be undefined, or defined from star imports

(F405)


5195-5195: TaskNode may be undefined, or defined from star imports

(F405)


5221-5221: TaskTemplate may be undefined, or defined from star imports

(F405)


5227-5227: TaskNode may be undefined, or defined from star imports

(F405)


5234-5234: TaskNode may be undefined, or defined from star imports

(F405)


5253-5253: TaskTemplate may be undefined, or defined from star imports

(F405)


5277-5277: TaskNode may be undefined, or defined from star imports

(F405)


5282-5282: TaskNode may be undefined, or defined from star imports

(F405)


5285-5285: TaskNode may be undefined, or defined from star imports

(F405)

backend/core/serializers.py

1419-1419: TaskTemplate may be undefined, or defined from star imports

(F405)


1425-1425: TaskTemplate may be undefined, or defined from star imports

(F405)


1439-1439: TaskNode may be undefined, or defined from star imports

(F405)


1445-1445: TaskNode may be undefined, or defined from star imports

(F405)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: test (3.12)
  • GitHub Check: build (3.12)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (15)
frontend/src/lib/components/Calendar/Calendar.svelte (9)

4-6: Imports look good.

The newly introduced imports for SlideToggle, page store, and showAllTasks are correctly declared without any apparent issues.


12-16: Validated date calculations.

Using new Date(year, month, 0) to get the last day of the month and new Date(year, month - 1, 1).getDay() for the first day is a well-known pattern and appears logically correct with the 1-based month approach.


42-44: Simple function for current month navigation.

This function correctly generates a path to the current month and year. Confirm that the route /calendar/<year>/<month> is valid in the rest of the application.


46-51: Month navigation logic (nextMonth).

The logic properly handles transitioning from December to January of the next year.


54-60: Month navigation logic (prevMonth).

The logic correctly handles transitioning from January to December of the previous year.


62-71: Reactive filtering of tasks.

The conditional logic ensures that if showAllTasks is false, tasks are filtered to those assigned to the current user. Consider verifying that each event's users field always exists to prevent potential undefined property access.


80-90: Anchor-based navigation elements.

Replacing button-based navigation with anchor links is straightforward. The references to prevMonth(year, month) and nextMonth(year, month) meet the desired routing approach.


111-113: Key block usage for filtered events.

Wrapping <Day> components with {#key filteredInfo} ensures reactivity when the filtered list changes. This is a solid approach.


117-127: SlideToggle integration for task visibility.

Binding $showAllTasks to the SlideToggle is a concise way to manage state. The link to currentMonth() is also correctly implemented.

backend/core/serializers.py (4)

1408-1421: Introducing TaskTemplateReadSerializer.

This serializer exposes relationship fields and computed properties (e.g., next_occurrence, last_occurrence_status) while excluding schedule. Ensure all needed fields are included or excluded as intended.

🧰 Tools
🪛 Ruff (0.8.2)

1419-1419: TaskTemplate may be undefined, or defined from star imports

(F405)


1423-1427: Write serializer includes schedule?

TaskTemplateWriteSerializer uses fields = "__all__", which implicitly includes the schedule field. This may be intentional, but confirm that it aligns with your plan to exclude schedule from reads while allowing it on writes.

🧰 Tools
🪛 Ruff (0.8.2)

1425-1425: TaskTemplate may be undefined, or defined from star imports

(F405)


1429-1441: TaskNodeReadSerializer logic.

Exposing task_template, folder, and the dynamic name field referencing the template looks consistent with the model. Also note that you exclude to_delete from output.

🧰 Tools
🪛 Ruff (0.8.2)

1439-1439: TaskNode may be undefined, or defined from star imports

(F405)


1443-1447: TaskNodeWriteSerializer excludes task_template.

Hiding the task_template field on writes suggests it’s set automatically or managed in code. Verify that you don’t need to capture user input for task_template in create/update operations.

🧰 Tools
🪛 Ruff (0.8.2)

1445-1445: TaskNode may be undefined, or defined from star imports

(F405)

backend/core/views.py (2)

1316-1316: Good addition of month and year filtering.

Adding month and year filtering options to date fields in AppliedControlFilterSet and RiskAcceptanceFilterSet is a valuable enhancement for calendar-based filtering.

Also applies to: 1994-1994


5269-5273: Good transaction handling in object method.

The override of the object action includes a call to _sync_task_nodes to ensure task nodes are synchronized when fetching a task template, which maintains data consistency.



class TaskTemplateReadSerializer(BaseModelSerializer):
folder = FieldsRelatedField()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace wildcard import with explicit imports.

Static analysis flags TaskTemplate and TaskNode as potentially undefined due to from core.models import *. To resolve these warnings and follow best practices, replace the star import with explicit imports:

- from core.models import *
+ from core.models import TaskTemplate, TaskNode

Also applies to: 1419-1419, 1425-1425, 1439-1439, 1445-1445

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
frontend/src/lib/components/Calendar/Day.svelte (3)

8-10: Add type definitions for exported stores

The exported stores selectedDay and showSidePanel lack type definitions, which could lead to type safety issues. Consider adding proper TypeScript interfaces to improve type safety and code maintainability.

-export let info: any[];
-export let selectedDay;
-export let showSidePanel;
+export let info: any[]; // Consider defining a more specific type for calendar items
+export let selectedDay: import('svelte/store').Writable<{day: number, month: number, year: number} | null>;
+export let showSidePanel: import('svelte/store').Writable<boolean>;

23-28: Consider performance optimization for filtering

The day info filtering is performed independently in each Day component, which could become inefficient if there are many events or calendar days. Consider moving this filtering logic up to the parent Calendar component and passing down only the relevant items for each day.

-$: dayInfo = info.filter(
-	(item) =>
-		item.date.getDate() === day &&
-		item.date.getMonth() + 1 === month &&
-		item.date.getFullYear() === year
-);
+export let dayInfo: any[]; // Receive pre-filtered info from parent

39-44: Consider extracting utility function

The truncateLabel function is a good utility that might be useful in other components. Consider moving it to a shared utilities file if it's used elsewhere in the application.

frontend/src/lib/components/Calendar/Calendar.svelte (2)

20-27: Add type definitions for side panel stores

Similar to the Day component, the writable stores lack type definitions. Consider adding proper TypeScript interfaces:

-export const selectedDay = writable(null);
-export const showSidePanel = writable(false);
+export const selectedDay = writable<{day: number, month: number, year: number} | null>(null);
+export const showSidePanel = writable<boolean>(false);

136-138: Consider performance optimization with memoized filtering

Similar to the comment for the Day component, consider pre-filtering the info for each day at the Calendar level rather than passing the entire info array to each Day component. This could improve performance, especially with many events.

-<Day {day} {month} {year} info={filteredInfo} {selectedDay} {showSidePanel} />
+{#key day}
+  {@const dayInfo = filteredInfo.filter(item => 
+    item.date.getDate() === day && 
+    item.date.getMonth() + 1 === month && 
+    item.date.getFullYear() === year
+  )}
+  <Day {day} {month} {year} dayInfo={dayInfo} {selectedDay} {showSidePanel} />
+{/key}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 332b108 and 1c0dd40.

📒 Files selected for processing (5)
  • frontend/messages/en.json (1 hunks)
  • frontend/messages/fr.json (1 hunks)
  • frontend/src/lib/components/Calendar/Calendar.svelte (3 hunks)
  • frontend/src/lib/components/Calendar/Day.svelte (1 hunks)
  • frontend/src/lib/components/Calendar/Notifications.svelte (0 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/lib/components/Calendar/Notifications.svelte
✅ Files skipped from review due to trivial changes (2)
  • frontend/messages/fr.json
  • frontend/messages/en.json
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (14)
frontend/src/lib/components/Calendar/Day.svelte (6)

12-13: LGTM: Clear constant definitions

The constants for today's date and the maximum number of items to display are well-defined.


15-21: LGTM: Well-implemented date comparisons

The reactive declarations for isToday and isPast are cleanly implemented and provide good semantics for styling and interaction logic.


30-32: LGTM: Efficient calculation of visible and extra items

The reactive declarations for calculating visible items and extra items count are well-implemented.


34-37: LGTM: Clean side panel management

The openSidePanel function appropriately updates both stores to show the selected day's details.


48-60: LGTM: Clean button implementation with dynamic styling

The day button element has well-structured conditional styling that reflects the day's state (current day, past, etc.) and proper event handling.


62-89: LGTM: Well-organized display of day information

The conditional rendering of day information with a limit on visible items and a "+N" button for additional items is well-implemented and provides a clean user experience.

frontend/src/lib/components/Calendar/Calendar.svelte (8)

4-8: LGTM: Appropriate imports for enhanced functionality

The new imports support the enhanced calendar functionality well, particularly the SlideToggle for task filtering and the stores for state management.


14-19: LGTM: Well-structured calendar date management

The export of month and year variables with defaults to the current date and the reactive calculations for calendar structure are clean and effective.


29-37: LGTM: Efficient filtering of selected day items

The reactive declaration for filtering items for the selected day is well-implemented.


63-81: LGTM: Improved navigation with URL-based approach

The navigation functions now return URL strings instead of mutating state, which is a better approach for maintainability and bookmarkable routes.


95-116: LGTM: Responsive layout with dynamic width adjustment

The flex layout with dynamic width adjustment based on side panel visibility provides a good user experience, and the month navigation links are clean.


141-156: LGTM: Well-designed control section

The calendar controls section with today button and task filtering toggle is well-designed and provides good functionality.


158-195: LGTM: Excellent side panel implementation

The side panel implementation with smooth transitions and detailed day information provides a great user experience. The conditional rendering and styling are well done.


83-92:

❓ Verification inconclusive

Verify user property access

The filtering logic assumes user.id is available. Ensure you have proper null checks for cases where user data might not be loaded yet:

-filteredInfo = info.filter((event) => event.users.some((userObj) => userObj.id === user.id));
+filteredInfo = info.filter((event) => user && event.users.some((userObj) => userObj.id === user.id));

🏁 Script executed:

#!/bin/bash
# Checking how user data is handled elsewhere in the codebase
rg -A 2 "page.data.user" --type svelte

Length of output: 69


Below is an updated script to explicitly search for the user data usage in Svelte files. This will help verify how the user object is accessed in the codebase:

Once this script is executed and you have the output, we can better confirm whether a null-check is needed around user in the filtering logic. Please run this script for manual verification of the user property usage.


🏁 Script executed:

#!/bin/bash
# Re-run rg search to correctly identify occurrences of "$page.data.user" in .svelte files
rg -A 4 "\$page\.data\.user" -g "*.svelte"

Length of output: 165


Null Check on user Required:
The filtering logic in frontend/src/lib/components/Calendar/Calendar.svelte assumes that the user object (sourced from $page.data.user) is always available. To guard against runtime errors in scenarios where user data might not have loaded yet, update the filter condition as follows:

- filteredInfo = info.filter((event) => event.users.some((userObj) => userObj.id === user.id));
+ filteredInfo = info.filter((event) => user && event.users.some((userObj) => userObj.id === user.id));

Please verify that this change aligns with how user data is managed across the app, ensuring that a null or undefined user does not cause unintended failures in event filtering.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte (3)

11-40: Consider enhancing type safety with more specific interfaces.

The createCalendarEvents function uses Record<string, string> for all input parameters, but the actual objects likely have more specific structures. Using dedicated interfaces would improve type safety and code readability.

+interface AppliedControl {
+  id: string;
+  name: string;
+  eta: string;
+  owner: string[];
+}
+
+interface RiskAcceptance {
+  id: string;
+  name: string;
+  expiry_date: string;
+  approver?: string;
+}
+
+interface Task {
+  id: string;
+  name: string;
+  due_date: string;
+  assigned_to: string[];
+  virtual: boolean;
+}
+
 function createCalendarEvents(
-  appliedControls: Record<string, string>[],
-  riskAcceptances: Record<string, string>[],
-  tasks: Record<string, string>[]
+  appliedControls: AppliedControl[],
+  riskAcceptances: RiskAcceptance[],
+  tasks: Task[]
 ): Array<{ label: string; date: Date; link: string; users: string[]; color: string }> {

34-34: Add a comment explaining the virtual property.

The code checks for task.virtual to determine the link URL, but it's not immediately clear what this property represents. A brief comment would improve code readability.

-  link: task.virtual ? `/task-templates/${task.id}` : `/task-nodes/${task.id}`,
+  // Virtual tasks are templates, non-virtual tasks are individual task nodes
+  link: task.virtual ? `/task-templates/${task.id}` : `/task-nodes/${task.id}`,

11-42: Consider moving the createCalendarEvents function to a utility file.

The createCalendarEvents function is a good candidate for extraction to a separate utility file, especially if it might be reused elsewhere in the application. This would improve code organization and maintainability.

Consider creating a new file like $lib/utils/calendar.ts and moving this function there. Then import it in this component.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd26406 and 432bd3a.

📒 Files selected for processing (3)
  • frontend/src/lib/components/Calendar/Calendar.svelte (3 hunks)
  • frontend/src/lib/components/Calendar/Day.svelte (1 hunks)
  • frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/lib/components/Calendar/Day.svelte
  • frontend/src/lib/components/Calendar/Calendar.svelte
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: Analyze (python)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
frontend/src/routes/(app)/(internal)/calendar/[year]/[month]/+page.svelte (1)

1-46: Good integration of tasks into the calendar view.

The component effectively integrates tasks alongside existing applied controls and risk acceptances in the calendar view. The consistent color coding and labeling will help users distinguish between different types of events.

Comment on lines +19 to +20
date: new Date(control.eta),
link: `/applied-controls/${control.id}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for date parsing and missing fields.

The code creates Date objects directly from strings without validation. If a date string is invalid or missing, this could lead to unexpected behavior. Consider adding error handling or validation.

 ...appliedControls.map((control: Record<string, string>) => ({
   label: `AC: ${control.name}`,
-  date: new Date(control.eta),
+  date: control.eta ? new Date(control.eta) : new Date(),
   link: `/applied-controls/${control.id}`,
   users: control.owner,
   color: 'tertiary'
 })),
 ...riskAcceptances.map((ra: Record<string, string>) => ({
   label: `RA: ${ra.name}`,
-  date: new Date(ra.expiry_date),
+  date: ra.expiry_date ? new Date(ra.expiry_date) : new Date(),
   link: `/risk-acceptances/${ra.id}`,
   users: ra.approver ? [ra.approver] : [],
   color: 'secondary'
 })),
 ...tasks.map((task: Record<string, string>) => ({
   label: `TA: ${task.name}`,
-  date: new Date(task.due_date),
+  date: task.due_date ? new Date(task.due_date) : new Date(),
   link: task.virtual ? `/task-templates/${task.id}` : `/task-nodes/${task.id}`,

Also applies to: 26-27, 33-34

appliedControls: Record<string, string>[],
riskAcceptances: Record<string, string>[],
tasks: Record<string, string>[]
): Array<{ label: string; date: Date; link: string }> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Return type should include all properties.

The function's return type only lists some of the properties (label, date, link) but the actual return includes additional properties (users, color). Update the return type to match the actual implementation.

-): Array<{ label: string; date: Date; link: string }> {
+): Array<{ label: string; date: Date; link: string; users: string[] | []; color: string }> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
): Array<{ label: string; date: Date; link: string }> {
): Array<{ label: string; date: Date; link: string; users: string[] | []; color: string }> {

Copy link
Collaborator

@Mohamed-Hacene Mohamed-Hacene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0k

@ab-smith ab-smith merged commit 5210639 into main Apr 16, 2025
21 checks passed
@ab-smith ab-smith deleted the feat_tasks_management branch April 16, 2025 16:13
@github-actions github-actions bot locked and limited conversation to collaborators Apr 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants