Skip to content
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

[Feature] Organization Project Modules management (Add Tasks) #8538

Merged
merged 12 commits into from
Nov 18, 2024

Conversation

samuelmbabhazi
Copy link
Contributor

@samuelmbabhazi samuelmbabhazi commented Nov 9, 2024

PR

Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.


Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a module selection feature in the task dialog, allowing users to select multiple modules associated with tasks.
    • Enhanced task management capabilities by integrating module selection and retrieval in both the add task and project module dialogs.
    • Added localization support for module selection in multiple languages, improving accessibility for diverse users.
  • Bug Fixes

    • Streamlined the syntax for various components to improve clarity without affecting functionality.

These updates enhance user experience by providing better task and module management options within the application.

@samuelmbabhazi samuelmbabhazi self-assigned this Nov 9, 2024
Copy link
Contributor

coderabbitai bot commented Nov 9, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes introduce a task selection feature within the AddProjectModuleDialogComponent of the Angular application. A new ga-task-selector component is added to the dialog's HTML, allowing users to select multiple tasks associated with a project. The component's TypeScript file is updated to include a TasksService for loading tasks and managing their selection. Additionally, modifications are made to a related TaskSelectorComponent to support multiple selections. Overall, the dialog's functionality is enhanced to facilitate task management alongside project module attributes.

Changes

File Change Summary
.../add-project-module-dialog/add-project-module-dialog.component.html Added a new section for task selection with a ga-task-selector component, including necessary attributes.
.../add-project-module-dialog/add-project-module-dialog.component.ts Introduced TasksService, added tasks property, updated ngOnInit to load tasks, modified populateForm and createOrUpdateModule methods.
.../task-select/task/task.component.html Simplified addTag expression and added multiple input property to ng-select component.
.../task-select/task/task.component.ts Added _multiple property to TaskSelectorComponent, modified taskId setter, and retained existing properties.
.../pages/tasks/components/task/task.component.ts Added modules relation to smartTableSource configuration for enhanced data retrieval.
.../pages/tasks/components/team-task-dialog/team-task-dialog.component.html Introduced nb-select for module selection and updated formatting for improved readability.
.../pages/tasks/components/team-task-dialog/team-task-dialog.component.ts Added OrganizationProjectModuleService, new properties for selected and available modules, and methods for loading and handling modules.
.../add-task-dialog/add-task-dialog.component.html Added a module selection feature with a <nb-select> component for selecting modules.
.../add-task-dialog/add-task-dialog.component.ts Introduced OrganizationProjectModuleService, new properties for selected and available modules, and methods for loading available modules.
.../tasks/tasks-store.service.ts Simplified constructor and method signatures for improved readability without altering functionality.

Possibly related PRs

Suggested reviewers

  • GloireMutaliko21

Poem

🐰 In the meadow where tasks align,
A selector blooms, oh how divine!
With projects and modules, all in a row,
Let's hop and select, let the good times flow!
A dialog bright, with choices galore,
Tasks at our fingertips, who could ask for more? 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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.

@samuelmbabhazi samuelmbabhazi marked this pull request as ready for review November 9, 2024 17:16
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

🧹 Outside diff range and nitpick comments (9)
packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.ts (4)

24-30: Consider enhancing multiple selection implementation.

The multiple selection feature might need additional handling:

  1. The setter should potentially trigger view updates when the selection mode changes
  2. The form control value might need to handle array values for multiple selection

Consider updating the setter:

 @Input() public set multiple(value: boolean) {
   this._multiple = value;
+  // Reset or adjust form value when switching between single/multiple modes
+  if (value && !Array.isArray(this.taskId)) {
+    this.taskId = this.taskId ? [this.taskId] : [];
+  } else if (!value && Array.isArray(this.taskId)) {
+    this.taskId = this.taskId.length ? this.taskId[0] : null;
+  }
 }

Line range hint 143-182: Update task creation to support multiple selection mode.

The createNew method needs to handle the multiple selection mode differently when updating taskId:

 // Update tasks list and taskId
 this.tasks = [...this.tasks, task];
-this.taskId = task.id;
+if (this._multiple) {
+  const currentValue = Array.isArray(this.taskId) ? this.taskId : [];
+  this.taskId = [...currentValue, task.id];
+} else {
+  this.taskId = task.id;
+}

Line range hint 134-142: Update form control integration for multiple selection support.

The writeValue method should handle both single and multiple selection modes:

 writeValue(value: any) {
+  if (this._multiple && !Array.isArray(value)) {
+    this.taskId = value ? [value] : [];
+  } else if (!this._multiple && Array.isArray(value)) {
+    this.taskId = value.length ? value[0] : null;
+  } else {
   this.taskId = value;
+  }
 }

Line range hint 82-91: Enhance type safety and validation for task selection.

The taskId getter/setter should be type-safe and validate the selection mode:

-private _taskId: string;
+private _taskId: string | string[];
-public get taskId(): string {
+public get taskId(): string | string[] {
   return this._taskId;
 }
-public set taskId(value: string) {
+public set taskId(value: string | string[]) {
+  // Validate value type against selection mode
+  if (this._multiple && !Array.isArray(value)) {
+    console.warn('Expected array value in multiple selection mode');
+    value = value ? [value] : [];
+  } else if (!this._multiple && Array.isArray(value)) {
+    console.warn('Expected single value in single selection mode');
+    value = value.length ? value[0] : null;
+  }
   this._taskId = value;
   this.onChange(value);
   this.onTouched(value);
 }
packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.html (2)

142-142: Add aria-label for better accessibility.

The label for task selection should include an aria-label to improve screen reader support.

-<label>{{ 'TIMER_TRACKER.SELECT_TASK' | translate }}</label>
+<label aria-label="{{ 'TIMER_TRACKER.SELECT_TASK' | translate }}">{{ 'TIMER_TRACKER.SELECT_TASK' | translate }}</label>

146-148: Consider adding validation messages for task selection.

The form control 'tasks' is configured for multiple selection and may be required based on organization settings. Consider adding validation messages to inform users about:

  1. Minimum/maximum number of tasks that can be selected
  2. Required selection when organization.requireTask is true
<ga-task-selector
  name="taskId"
  [projectId]="form.get('projectId').value"
  formControlName="tasks"
  [multiple]="true"
  [required]="organization?.requireTask"
+ [validationMessages]="{
+   required: 'MESSAGES.TASK_SELECTION_REQUIRED' | translate
+ }"
></ga-task-selector>
packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.ts (3)

Line range hint 85-86: Consider adding validation for the tasks field.

Since tasks are an integral part of project modules, consider adding validators to ensure proper task selection. For example, you might want to validate:

  • Minimum/maximum number of tasks
  • Task status compatibility
  • Task date ranges within module dates

170-172: Fix comment and optimize task filtering.

  1. The comment "Only valid teams" is incorrect and should be "Only valid tasks"
  2. The filtering logic can be simplified

Consider this optimization:

- this.form.get('tasks').setValue(
-   (this.form.get('tasks').value || []).map((id) => this.tasks.find((e) => e.id === id)).filter((e) => !!e) // Only valid teams
- );
+ const selectedTaskIds = this.form.get('tasks').value || [];
+ const validTasks = selectedTaskIds
+   .map((id) => this.tasks.find((task) => task.id === id))
+   .filter(Boolean); // Only valid tasks
+ this.form.get('tasks').setValue(validTasks);

225-234: Consider implementing task data caching.

To improve performance and reduce API calls, consider implementing a caching mechanism for task data using a shared service. This would be particularly beneficial if tasks are accessed across multiple components.

Example approaches:

  1. Use RxJS BehaviorSubject to cache the latest task list
  2. Implement a TTL-based cache in the TasksService
  3. Consider using NgRx store for state management if the application grows
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a0af6b3 and 69c7217.

📒 Files selected for processing (4)
  • packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.html (1 hunks)
  • packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.ts (7 hunks)
  • packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.html (2 hunks)
  • packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.ts (2 hunks)
🔇 Additional comments (6)
packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.html (1)

3-3: LGTM! Clean up of binding expression.

The simplified binding expression maintains the same logical behavior while being more concise.

packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.ts (1)

Line range hint 183-207: Verify TasksService implementation for multiple selection support.

Ensure that the TasksService methods can handle both single and multiple task selections correctly.

✅ Verification successful

Let me gather more information about the TasksService implementation to verify its support for multiple selection.


Let me check the task component implementation to understand how it handles task selection.


Let me check the template file to see how the multiple selection is implemented in the UI.


Multiple selection support is properly implemented

The TasksService and TaskSelectorComponent fully support both single and multiple task selections:

  • The component has a multiple input property that controls selection mode
  • The ng-select template correctly binds to the multiple property
  • TasksService methods return proper task collections that work with both selection modes
  • The component correctly handles value changes through ControlValueAccessor implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for TasksService implementation and its usages
echo "Searching for TasksService implementation..."
rg -l "class TasksService"

echo "Checking TasksService method signatures..."
ast-grep --pattern 'class TasksService {
  $$$
  getAllTasks($$$) {
    $$$
  }
  $$$
}'

Length of output: 375


Script:

#!/bin/bash
# Get the TasksService implementation details
echo "TasksService implementation:"
cat packages/ui-core/core/src/lib/services/tasks/tasks.service.ts

# Search for task selection related methods
echo -e "\nSearching for task selection methods:"
rg -A 5 "select.*Task" packages/ui-core/core/src/lib/services/tasks/tasks.service.ts

Length of output: 3601


Script:

#!/bin/bash
# Get the task component implementation
echo "Task Component implementation:"
cat "packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.ts"

# Search for selection-related methods and properties
echo -e "\nSearching for selection-related code in the component:"
rg -A 5 "select|multiple|Selection" "packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.ts"

Length of output: 6794


Script:

#!/bin/bash
# Get the task component template
echo "Task Component Template:"
cat "packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.html"

Length of output: 511

packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.html (2)

138-152: LGTM! The task selection integration looks solid.

The new task selection section is well-integrated into the form structure:

  • Proper form control binding
  • Reactive form integration
  • Consistent styling with other form sections
  • Appropriate validation based on organization settings

143-149: Verify task selector's dependency on project selection.

The task selector's projectId is bound to the form's project control. Please ensure that:

  1. Tasks are refreshed when project selection changes
  2. Proper error handling exists when no project is selected
  3. Previously selected tasks are cleared when project changes
✅ Verification successful

Based on the code analysis, I can now provide a final response:

Task selector's project dependency is properly handled

The task selector implementation correctly handles project dependency through the TaskSelectorService:

  1. Tasks are refreshed when project changes - The service loads tasks based on the selected project ID from ProjectSelectorQuery
  2. Error handling exists - The service includes proper error handling and loading states
  3. Tasks are properly scoped - The service fetches tasks specific to the selected project, ensuring task list is always in sync with project selection

Key implementation details:

  • TaskSelectorService uses ProjectSelectorQuery to get the current project ID
  • Task loading includes proper error handling and notifications
  • Tasks are filtered by project ID in the backend request
  • The service maintains proper loading states during data fetching
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for project selection change handler and task refresh logic
ast-grep --pattern 'projectId.valueChanges.subscribe($$$)'

Length of output: 60


Script:

#!/bin/bash
# Let's search for the component's TypeScript file and check form handling
fd "add-project-module-dialog.component.ts" --exec cat {}

# Also search for task selector component to understand its implementation
fd "task-selector.component.ts" --exec cat {}

Length of output: 11619


Script:

#!/bin/bash
# Let's check the task selector service implementation for project-related logic
fd "task-selector.service.ts" --exec cat {}

# Also check for any value changes subscription in the component
rg -A 5 "projectId.*valueChanges" 

Length of output: 4707

packages/ui-core/shared/src/lib/project/project-module/add-project-module-dialog/add-project-module-dialog.component.ts (2)

18-18: LGTM: Import and property declarations are well-structured.

The additions of ITask interface import, TasksService, and the tasks property array are properly typed and aligned with the task management feature requirements.

Also applies to: 28-29, 44-44


64-65: LGTM: Service injection follows Angular best practices.

The TasksService is correctly injected as a private readonly dependency.

@samuelmbabhazi
Copy link
Contributor Author

@GloireMutaliko21 GloireMutaliko21 marked this pull request as draft November 12, 2024 06:34
@GloireMutaliko21 GloireMutaliko21 marked this pull request as draft November 12, 2024 06:34
Copy link

nx-cloud bot commented Nov 12, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit c7ebcc3. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 1 target

Sent with 💌 from NxCloud.

@samuelmbabhazi samuelmbabhazi marked this pull request as ready for review November 15, 2024 05:29
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: 5

🧹 Outside diff range and nitpick comments (17)
apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.html (1)

198-198: Consider modules validation in save button.

The save button's disabled state should also consider the modules selection if it's required.

-<button (click)="onSave()" [disabled]="form.invalid || (teams && teams.length === 0)" nbButton status="success">
+<button (click)="onSave()" [disabled]="form.invalid || (teams && teams.length === 0) || (form.get('modules').errors?.required)" nbButton status="success">
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.html (3)

55-67: Add validation feedback to module selector.

For consistency with other form controls (like estimateHours), consider adding validation status and error messages:

 						<nb-select
 							formControlName="modules"
 							[placeholder]="'TASKS_PAGE.SELECT_MODULE' | translate"
 							[selected]="selectedModules"
 							(selectedChange)="onModulesSelected($event)"
+							[status]="form.get('modules').touched && form.get('modules').errors ? 'danger' : 'basic'"
 							fullWidth
 							multiple
 						>
 							<nb-option *ngFor="let module of availableModules" [value]="module.id">
 								{{ module.name }}
 							</nb-option>
 						</nb-select>
+						<ng-container *ngIf="form.get('modules').touched && form.get('modules').errors as errors">
+							<p class="caption status-danger" *ngIf="errors?.required">
+								{{ 'TASKS_PAGE.MODULE_REQUIRED' | translate }}
+							</p>
+						</ng-container>

63-65: Consider enhancing module option display.

For better user context, consider showing additional module metadata in the options, similar to other selectors in the form:

-							<nb-option *ngFor="let module of availableModules" [value]="module.id">
-								{{ module.name }}
+							<nb-option *ngFor="let module of availableModules" [value]="module.id">
+								<div class="d-flex align-items-center">
+									<span>{{ module.name }}</span>
+									<small class="ml-2 text-muted">({{ module.description }})</small>
+								</div>

55-62: Improve accessibility for module selection.

Add ARIA attributes to enhance screen reader support:

 						<nb-select
 							formControlName="modules"
 							[placeholder]="'TASKS_PAGE.SELECT_MODULE' | translate"
 							[selected]="selectedModules"
 							(selectedChange)="onModulesSelected($event)"
+							[attr.aria-label]="'TASKS_PAGE.MODULE' | translate"
+							[attr.aria-multiselectable]="true"
 							fullWidth
 							multiple
 						>
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (4)

64-65: Add readonly modifier for consistency.

The organizationProjectModuleService should be marked as readonly for consistency with other injected services.

-		private organizationProjectModuleService: OrganizationProjectModuleService
+		private readonly organizationProjectModuleService: OrganizationProjectModuleService

87-87: Consider adding initial value and validators for modules field.

The modules form control might benefit from an initial empty array value and validators to ensure proper data structure.

-			modules: [],
+			modules: [[], [Validators.required]],

175-175: Refactor form save logic for better maintainability.

The form save logic for modules follows the same pattern as members and teams. Consider extracting this pattern into a helper method.

+	private setFormArrayValue<T>(
+		formKey: string,
+		selectedIds: string[],
+		items: T[],
+		idField: keyof T = 'id'
+	) {
+		this.form.get(formKey).setValue(
+			(selectedIds || [])
+				.map((id) => items.find((item) => item[idField] === id))
+				.filter((item) => !!item)
+		);
+	}
+
 	onSave() {
 		if (this.form.valid) {
 			this.form.get('members').setValue([]);
 			this.form.get('teams').setValue([]);
 
 			if (this.participants === TaskParticipantEnum.EMPLOYEES) {
-				this.form.get('members').setValue(
-					(this.selectedMembers || [])
-						.map((id) => this.employees.find((e) => e.id === id))
-						.filter((e) => !!e)
-				);
+				this.setFormArrayValue('members', this.selectedMembers, this.employees);
 			} else if (this.participants === TaskParticipantEnum.TEAMS) {
-				this.form.get('teams').setValue(
-					(this.selectedTeams || [])
-						.map((id) => this.teams.find((e) => e.id === id))
-						.filter((e) => !!e)
-				);
+				this.setFormArrayValue('teams', this.selectedTeams, this.teams);
 			}
 
-			this.form.get('modules').setValue(
-				(this.selectedModules || [])
-					.map((id) => this.availableModules.find((e) => e.id === id))
-					.filter((e) => !!e)
-			);
+			this.setFormArrayValue('modules', this.selectedModules, this.availableModules);

Also applies to: 182-182, 203-203, 226-234


Test coverage needs improvement for module selection functionality

The test file only contains a basic component creation test. Missing test coverage for:

  • loadAvailableModules() method
  • Module selection handling via onModulesSelected()
  • Form validation with modules
  • Integration with OrganizationProjectModuleService

Key areas to add tests:

  • Loading modules when project ID changes
  • Handling empty/null project ID scenarios
  • Module selection state management
  • Form validation with selected modules
  • Error handling during module loading
🔗 Analysis chain

Line range hint 1-319: Verify test coverage for the new module selection functionality.

Please ensure that unit tests are added/updated to cover:

  1. Module loading functionality
  2. Module selection handling
  3. Form validation with modules
  4. Error scenarios in module loading
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test file and its coverage
fd -e spec.ts "add-task-dialog.component" | xargs cat

Length of output: 744

apps/gauzy/src/app/pages/tasks/components/task/task.component.ts (4)

Line range hint 423-435: Consider grouping related relations for better maintainability

The relations array is quite long and mixes different types of relations. Consider grouping them by domain for better maintainability.

 relations: [
-  'members',
-  'members.user',
-  'project',
-  'modules',
-  'tags',
-  'teams',
-  'teams.members',
-  'teams.members.employee',
-  'teams.members.employee.user',
-  'creator',
-  'organizationSprint',
-  'taskStatus',
-  'taskSize',
-  'taskPriority'
+  // User relations
+  'members',
+  'members.user',
+  'creator',
+  // Project relations
+  'project',
+  'modules',
+  'organizationSprint',
+  // Team relations
+  'teams',
+  'teams.members',
+  'teams.members.employee',
+  'teams.members.employee.user',
+  // Task metadata
+  'tags',
+  'taskStatus',
+  'taskSize',
+  'taskPriority'
 ]

Line range hint 1-1024: Consider breaking down this large component

This component is quite large (1000+ lines) and handles multiple responsibilities (CRUD operations, different views, smart table configuration). Consider breaking it down into smaller, more focused components following the Single Responsibility Principle.

Suggested refactoring:

  1. Extract smart table configuration into a separate service
  2. Create separate components for different views (all tasks, my tasks, team tasks)
  3. Move CRUD operations to a separate service

Line range hint 8-21: Consider organizing imports

The imports section is quite large and mixes different types of imports (Angular core, RxJS, third-party libraries, internal imports). Consider organizing them for better readability.

+ // Angular
 import { Component, OnDestroy, OnInit } from '@angular/core';
 import { ActivatedRoute, Router } from '@angular/router';
 import { HttpClient } from '@angular/common/http';
+ 
+ // RxJS
 import { combineLatest, firstValueFrom, Observable, Subject } from 'rxjs';
 import { debounceTime, filter, first, tap } from 'rxjs/operators';
+ 
+ // Third-party
 import { TranslateService } from '@ngx-translate/core';
 import { Cell } from 'angular2-smart-table';
 import { NbDialogService } from '@nebular/theme';
 import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
+ 
+ // Internal
 import {
   ErrorHandlingService,
   // ... rest of the imports
 } from '@gauzy/ui-core/core';

Line range hint 85-85: Consider using TypeScript strict mode

The component has properties that could benefit from explicit typing:

  • settingsSmartTable: object could be more strictly typed
  • viewComponentName: ComponentEnum should have an initial value or be marked as !

Also applies to: 93-93

apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (5)

77-77: Ensure consistent use of readonly in constructor parameters

In the constructor, the organizationProjectModuleService parameter lacks the readonly modifier, unlike the other injected services. For consistency and to prevent accidental reassignment, consider adding readonly.

Apply this diff to add the readonly modifier:

 constructor(
     public readonly dialogRef: NbDialogRef<TeamTaskDialogComponent>,
     private readonly fb: UntypedFormBuilder,
     private readonly store: Store,
     private readonly _organizationsStore: Store,
     private readonly organizationProjectsService: OrganizationProjectsService,
     readonly translateService: TranslateService,
     private readonly toastrService: ToastrService,
     private readonly errorHandler: ErrorHandlingService,
     private readonly organizationTeamsService: OrganizationTeamsService,
-    private organizationProjectModuleService: OrganizationProjectModuleService
+    private readonly organizationProjectModuleService: OrganizationProjectModuleService
 ) {
     super(translateService);
 }

125-129: Prevent unnecessary service calls when projectId is undefined

In the ngOnInit method, the subscription to projectId changes calls loadAvailableModules() even when projectId is undefined. This can result in unnecessary service calls. Consider checking if projectId has a value before calling loadAvailableModules().

Apply this diff to conditionally call loadAvailableModules():

 this.form
     .get('projectId')
     .valueChanges
     .pipe(untilDestroyed(this))
-    .subscribe(() => this.loadAvailableModules());
+    .subscribe((projectId) => {
+        if (projectId) {
+            this.loadAvailableModules();
+        } else {
+            this.availableModules = [];
+        }
+    });

208-213: Optimize module mapping in onSave method

In the onSave method, mapping selected module IDs to module objects uses find within a loop, which can be inefficient for large lists. Consider creating a map of availableModules to improve lookup performance.

Apply this diff to optimize module mapping:

+        const modulesMap = new Map(
+            this.availableModules.map((module) => [module.id, module])
+        );
         this.form
             .get('modules')
             .setValue(
                 (this.selectedModules || [])
-                    .map((id) => this.availableModules.find((e) => e.id === id))
+                    .map((id) => modulesMap.get(id))
                     .filter((e) => !!e)
             );

56-58: Initialize selectedModules and availableModules properly

Ensure that selectedModules and availableModules are initialized even if the data is not immediately available to prevent potential undefined issues.

Consider initializing them as empty arrays to guarantee they have a default value:

 selectedModules: string[] = [];
 selectedTask: ITask;
 availableModules: IOrganizationProjectModule[] = [];

Line range hint 140-152: Correctly initialize modules field in the form

In the initializeForm method, ensure that the modules control is correctly populated with the selected module IDs to reflect the current state.

Apply this diff to fix the initialization:

 initializeForm({
     title,
     description,
     project,
     status,
     members,
     teams,
     modules,
     estimate,
     dueDate,
     tags,
     priority,
     size,
     taskStatus,
     taskSize,
     taskPriority
 }: ITask) {
     const duration = moment.duration(estimate, 'seconds');
     this.selectedTeams = (teams || []).map((team) => team.id);
-    this.selectedModules = (modules || []).map((module) => module.id);
+    this.selectedModules = modules ? modules.map((module) => module.id) : [];
     this.form.patchValue({
         title,
         project,
         projectId: project ? project.id : null,
         status,
         priority,
         size,
         modules: this.selectedModules,
         estimateDays: duration.days(),
         estimateHours: duration.hours(),
         estimateMinutes: duration.minutes(),
         dueDate: dueDate ? new Date(dueDate) : null,
         members,
         description,
         tags,
         teams: this.selectedTeams,
         taskStatus,
         taskSize,
         taskPriority
     });
     this.tags = this.form.get('tags').value || [];
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 69c7217 and 437c9cf.

📒 Files selected for processing (7)
  • apps/gauzy/src/app/pages/tasks/components/task/task.component.ts (1 hunks)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.html (7 hunks)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (10 hunks)
  • packages/ui-core/core/src/lib/services/tasks/tasks-store.service.ts (3 hunks)
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.html (1 hunks)
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (11 hunks)
  • packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.html (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/ui-core/core/src/lib/services/tasks/tasks-store.service.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ui-core/shared/src/lib/tasks/task-select/task/task.component.html
🔇 Additional comments (9)
apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.html (4)

7-7: LGTM! Clean and readable translation expression.

The simplified translation expression improves code readability while maintaining functionality.


27-27: LGTM! Consistent translation usage.

The translation expressions are properly implemented and maintain consistency across labels and placeholders.

Also applies to: 40-40, 42-42


78-78: LGTM! Clean team selection implementation.

The team selection component is well-structured with proper translations and option rendering.

Also applies to: 80-80


Line range hint 88-189: LGTM! Comprehensive task details implementation.

The task details section is well-structured with:

  • Proper form controls and validations
  • Consistent translation usage
  • Input validation for estimate fields
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (2)

15-15: LGTM: Import statements are properly organized.

The new imports for module-related functionality are correctly added and well-organized.

Also applies to: 24-30


44-46: LGTM: Properties are properly typed and initialized.

The new properties for managing module selection are correctly implemented with appropriate types.

apps/gauzy/src/app/pages/tasks/components/task/task.component.ts (3)

424-424: LGTM: Addition of 'modules' relation

The addition of the 'modules' relation to the smartTableSource configuration is correct and aligns with the PR objectives for Organization Project Modules management.


424-424: Verify module relation data usage

The 'modules' relation has been added, but there's no visible usage of the module data in the component's template or result mapping. Verify if additional changes are needed to display or utilize this data.

#!/bin/bash
# Description: Check for module data usage in templates and components

# Search for module-related template bindings
echo "Searching for module usage in templates..."
rg -l "task\.modules|modules\." --type html

# Search for module data mapping in components
echo "Searching for module data mapping..."
ast-grep --pattern 'resultMap = $_ => { $$$ modules $$$ }'

Also applies to: 447-471


Line range hint 447-471: Verify project filtering logic with modules

The project filtering logic in the where clause needs to be verified to ensure it correctly handles the new modules relation.

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: 3

🧹 Outside diff range and nitpick comments (7)
apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (2)

89-89: Add validation for the modules form control

Consider adding validators to ensure the modules selection meets your requirements (e.g., required, minimum selection).

-  modules: [],
+  modules: [[], Validators.required],  // if modules are mandatory

126-129: Consider debouncing projectId changes

The current implementation might trigger multiple unnecessary API calls if projectId changes rapidly. Consider adding a debounceTime operator.

 this.form
   .get('projectId')
   .valueChanges.pipe(
+    debounceTime(300),
     untilDestroyed(this)
   )
   .subscribe(() => this.loadAvailableModules());
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (1)

226-234: Add error handling for module processing.

While the module processing follows the same pattern as members/teams, it could benefit from error handling.

Consider this enhancement:

+    try {
       this.form
         .get('modules')
         .setValue(
           (this.selectedModules || [])
             .map((id) => {
+              const module = this.availableModules.find((e) => e.id === id);
+              if (!module) {
+                console.warn(`Module with id ${id} not found in available modules`);
+              }
+              return module;
+            })
             .filter((e) => !!e)
         );
+    } catch (error) {
+      console.error('Error processing modules:', error);
+      // Consider showing a user-friendly error message
+    }
packages/ui-core/i18n/assets/i18n/zh.json (2)

2609-2611: Consider enhancing the SELECT_MODULE translation

The translation looks correct but could be improved for better clarity:

  "MODULE": "模块",
- "SELECT_MODULE": "模块"
+ "SELECT_MODULE": "选择模块"

Adding the verb "选择" (select) would make the action clearer for users.


2609-2611: Note: Identical translations may cause confusion

Currently both "MODULE" and "SELECT_MODULE" are translated to the same Chinese text "模块". While technically correct, having identical translations for different keys could potentially cause confusion during maintenance or when referenced in the UI.

Consider differentiating them to make their purposes clearer in the interface.

packages/ui-core/i18n/assets/i18n/he.json (1)

2630-2632: Translations look good with minor suggestion.

The Hebrew translations are well-formatted and grammatically correct. However, there's a minor inconsistency where "SELECT_MODULE" is translated as plural "מודולים" (modules) while the English key suggests singular "Select Module". Consider changing it to singular "מודול" for better consistency.

  "SETTINGS": "הגדרות",
  "MODULE": "מודול", 
- "SELECT_MODULE": "מודולים"
+ "SELECT_MODULE": "מודול"
packages/ui-core/i18n/assets/i18n/es.json (1)

2611-2613: LGTM! The Spanish translations for module functionality look good.

The translations for "MODULE" and "SELECT_MODULE" are properly formatted and linguistically correct.

Consider adding a newline before these new entries to improve readability:

  "SETTINGS": "Ajustes",
+
  "MODULE": "Módulo",
  "SELECT_MODULE": "Módulo(s)"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 437c9cf and 3df0fd1.

📒 Files selected for processing (18)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.html (7 hunks)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (11 hunks)
  • packages/ui-core/i18n/assets/i18n/ach.json (2 hunks)
  • packages/ui-core/i18n/assets/i18n/ar.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/bg.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/de.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/en.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/es.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/fr.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/he.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/it.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/nl.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/pl.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/pt.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/ru.json (1 hunks)
  • packages/ui-core/i18n/assets/i18n/zh.json (1 hunks)
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.html (1 hunks)
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (11 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/ui-core/i18n/assets/i18n/bg.json
  • packages/ui-core/i18n/assets/i18n/ru.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.html
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.html
🔇 Additional comments (14)
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (5)

15-16: LGTM: Property and import additions are well-structured.

The new properties for module management are properly typed and initialized following Angular best practices.

Also applies to: 44-46


64-65: LGTM: Service injection follows Angular DI patterns.

The OrganizationProjectModuleService is properly injected as a private dependency.


175-175: LGTM: Form initialization properly handles module data.

The changes correctly handle module initialization from the selected task and update the form accordingly.

Also applies to: 182-182, 203-203


303-319: Previous review comment about error handling is still applicable.

The error handling and loading state management improvements suggested in the previous review should be implemented.


87-87: Verify if validation rules are needed for the modules field.

The modules form control is added without validation rules. Please verify if this is intentional or if we should add validation (e.g., required, minimum selection).

✅ Verification successful

Let me gather more context about the validation patterns in these components.


Let me check specifically for the add-task-dialog component's form validation patterns.


Let me try a different approach to check the form initialization.


Let me try one final approach to understand the form structure.


No validation rules needed for the modules field

After reviewing the code, the modules field is intentionally left without validation rules. This is consistent with other similar optional fields in the form like tags, teams, and taskStatus. The field is properly handled in the onSave() method where it's processed only if modules are selected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar form controls in the codebase to verify validation patterns
rg -A 3 "modules.*\[.*\].*," --type ts

Length of output: 1338


Script:

#!/bin/bash
# Check for validation rules in the task dialog components
ast-grep --pattern 'this.form = this.fb.group({
  $$$
})'

Length of output: 40800


Script:

#!/bin/bash
# Search for the form initialization in add-task-dialog component
ast-grep --pattern 'this.form = this.fb.group({
  $$$
  modules: $_,
  $$$
})'

Length of output: 80


Script:

#!/bin/bash
# Get the full context of the add-task-dialog component
rg -A 20 "form = this.fb.group" packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts

Length of output: 116


Script:

#!/bin/bash
# Get the entire file content to understand the form structure
cat packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts

Length of output: 9130

packages/ui-core/i18n/assets/i18n/ach.json (1)

2405-2407: LGTM! The new translation keys for project module management look good.

The additions of "SETTINGS", "MODULE" and "SELECT_MODULE" translations in the Ach language are appropriate for the project module management functionality.

Let's verify these keys exist in other language files for consistency:

✅ Verification successful

Let me verify the remaining "SETTINGS" key before making the final response.


Translation keys are consistently present across all language files

The verification confirms that all three translation keys ("SETTINGS", "MODULE", and "SELECT_MODULE") are present across all language files in the i18n directory. The Ach language translations are properly aligned with other language files, maintaining consistency in the localization structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new translation keys exist in other language files
# Expected: The keys should exist in all language files

# Search for MODULE translation key
rg '"MODULE":' packages/ui-core/i18n/assets/i18n/

# Search for SELECT_MODULE translation key  
rg '"SELECT_MODULE":' packages/ui-core/i18n/assets/i18n/

Length of output: 1989


Script:

#!/bin/bash
# Check for SETTINGS translation key
rg '"SETTINGS":' packages/ui-core/i18n/assets/i18n/

Length of output: 10371

packages/ui-core/i18n/assets/i18n/ar.json (1)

Line range hint 1-2606: LGTM! Rest of the translations look good

The remaining Arabic translations maintain good quality, consistency and proper formatting.

Also applies to: 2610-4607

packages/ui-core/i18n/assets/i18n/en.json (1)

2732-2734: LGTM! The new translation keys are properly structured.

The additions follow the established naming conventions and maintain consistency with the existing translations.

packages/ui-core/i18n/assets/i18n/nl.json (1)

2609-2611: LGTM! The Dutch translations for task module labels look good.

The added translations for "MODULE" and "SELECT_MODULE" are properly formatted and use correct Dutch terminology that matches the context of the task module functionality.

packages/ui-core/i18n/assets/i18n/pl.json (1)

2609-2611: LGTM! Polish translations added for module management.

The new translations are properly formatted and provide accurate Polish equivalents for the module management UI elements.

packages/ui-core/i18n/assets/i18n/it.json (1)

2609-2611: LGTM! New task module translations added correctly

The new Italian translations for module functionality are properly formatted and accurately translated:

  • "MODULE": "Modulo"
  • "SELECT_MODULE": "Modulo(i)"

The translations maintain consistency with the existing structure and are grammatically correct in Italian.

packages/ui-core/i18n/assets/i18n/pt.json (1)

2609-2611: LGTM! The Portuguese translations for module functionality are accurate and well-structured.

The added translations for "MODULE" and "SELECT_MODULE" are appropriate for Portuguese and follow the established translation patterns in the file. The placement within the "TASKS_PAGE" section is logical.

packages/ui-core/i18n/assets/i18n/de.json (1)

2605-2607: LGTM! The new translations look good.

The added German translations for module management are appropriate and maintain consistency with the rest of the localization file.

packages/ui-core/i18n/assets/i18n/fr.json (1)

2610-2612: LGTM! The task module translations look good.

The added French translations for task module settings and selection are properly structured and accurately translated.

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

🧹 Outside diff range and nitpick comments (8)
apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (3)

57-57: Consider initializing selectedModules from task input

The selectedModules and availableModules arrays are initialized empty, but should ideally be populated from the input task property if it exists, similar to how selectedTeams is handled.

- selectedModules: string[] = [];
+ selectedModules: string[] = this.task?.modules?.map(module => module.id) || [];

Also applies to: 59-59


126-129: Consider using takeUntil for better subscription management

While untilDestroyed is used, consider using takeUntil with a destroy$ subject for more explicit subscription cleanup. This is especially important for components with multiple subscriptions.

+ private destroy$ = new Subject<void>();

  ngOnInit() {
    this.form
      .get('projectId')
      .valueChanges
-     .pipe(untilDestroyed(this))
+     .pipe(
+       takeUntil(this.destroy$)
+     )
      .subscribe(() => this.loadAvailableModules());
  }

+ ngOnDestroy() {
+   this.destroy$.next();
+   this.destroy$.complete();
+ }

208-212: Add type safety to module mapping

The module mapping logic could benefit from explicit type annotations to ensure type safety throughout the transformation.

- const selectedModules = this.selectedModules || [];
- const mappedModules = selectedModules
+ const selectedModules: string[] = this.selectedModules || [];
+ const mappedModules: IOrganizationProjectModule[] = selectedModules
    .map((id) => this.availableModules?.find((e) => e?.id === id))
    .filter(Boolean);
packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (5)

44-44: Add access modifiers to class properties.

Consider adding appropriate access modifiers (public/private) to the new properties for better encapsulation.

-selectedModules: string[] = [];
-availableModules: IOrganizationProjectModule[] = [];
+public selectedModules: string[] = [];
+public availableModules: IOrganizationProjectModule[] = [];

Also applies to: 46-46


87-87: Consider adding validators for the modules form control.

The modules form control might benefit from validation to ensure proper module selection.

-modules: [],
+modules: [[], [Validators.required]], // If modules are mandatory

182-182: Add type guard for modules array.

Consider adding a type guard to ensure modules array elements are of the correct type.

-this.selectedModules = (modules || []).map((module) => module.id);
+this.selectedModules = (modules || [])
+  .filter((module): module is IOrganizationProjectModule => !!module)
+  .map((module) => module.id);

227-231: Simplify module mapping logic.

The current implementation can be made more concise and type-safe.

-const selectedModules = this.selectedModules || [];
-const mappedModules = selectedModules
-  .map((id) => this.availableModules?.find((e) => e?.id === id))
-  .filter(Boolean);
+const mappedModules = (this.selectedModules || [])
+  .map((id) => this.availableModules.find((module): module is IOrganizationProjectModule => 
+    module?.id === id
+  ))
+  .filter(Boolean);

301-303: Add input validation to onModulesSelected.

Consider validating the input array to ensure it contains valid module IDs.

-onModulesSelected(modules: string[]) {
-  this.selectedModules = modules;
+onModulesSelected(modules: string[]) {
+  this.selectedModules = modules.filter(id => 
+    this.availableModules.some(module => module.id === id)
+  );
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3df0fd1 and ba20d53.

📒 Files selected for processing (2)
  • apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (11 hunks)
  • packages/ui-core/shared/src/lib/tasks/add-task-dialog/add-task-dialog.component.ts (11 hunks)
🔇 Additional comments (1)
apps/gauzy/src/app/pages/tasks/components/team-task-dialog/team-task-dialog.component.ts (1)

89-89: LGTM: Form initialization for modules is well implemented

The module-related form control and initialization logic follows the established pattern in the component and properly handles both new and existing tasks.

Also applies to: 141-141, 153-153, 170-170

@rahul-rocket rahul-rocket merged commit 1489cf2 into develop Nov 18, 2024
8 of 18 checks passed
@rahul-rocket rahul-rocket deleted the feat/#8131-project-modules-management branch November 18, 2024 05:17
@coderabbitai coderabbitai bot mentioned this pull request Dec 23, 2024
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants