Skip to content

Display properties - STD fields#6786

Closed
naman-agrawal-shipsy wants to merge 134 commits intomakeplane:previewfrom
shipsy:display_properties--std-fields
Closed

Display properties - STD fields#6786
naman-agrawal-shipsy wants to merge 134 commits intomakeplane:previewfrom
shipsy:display_properties--std-fields

Conversation

@naman-agrawal-shipsy
Copy link

@naman-agrawal-shipsy naman-agrawal-shipsy commented Mar 21, 2025

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Enhanced issue management with additional custom properties and expanded filtering options.
    • Introduced new endpoints for global search and webhook management.
    • Spreadsheet views now include extra fields for more detailed issue reporting.
    • A new CI/CD pipeline for demo deployments is available.
    • New React components for managing and displaying custom properties in issues.
    • Added support for additional properties in issue filters and display options.
  • Improvements

    • Configuration updates enable larger file uploads and improved security headers.
    • Enhanced authentication and permission handling for smoother user management.
    • Improved handling of custom properties in the issue management system.
    • Enhanced sidebar and filter functionalities for better user experience.
  • Bug Fixes

    • Removed outdated UI elements in the upgrade and help sections for a cleaner interface.
    • Fixed issues related to the display and management of additional properties in the UI.

@CLAassistant
Copy link

CLAassistant commented Mar 21, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 4 committers have signed the CLA.

❌ Naman-SIngla-Shipsy
❌ abu-siddique-shipsy
❌ naman-agrawal-shipsy
❌ sumarpreet-kaur-shipsy
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 21, 2025

Walkthrough

This pull request introduces extensive enhancements across both backend and frontend components. New commands and port declarations have been added in Dockerfiles, while numerous API endpoints, serializers, URL routes, and permission classes have been updated to support additional custom properties for issues. Database migrations add new models and fields for issue custom properties with revised constraints. In addition, configuration files, Next.js headers, and other settings have been modified. Frontend types and components now include new filtering and display options for these properties, and various authentication and workspace management flows have been refined.

Changes

File(s) Change Summary
admin/Dockerfile.admin
web/Dockerfile.web
Added container start commands: new CMD and EXPOSE directives to run respective server scripts on port 3000.
apiserver/Dockerfile.api
aio/nginx.conf
Updated API container: added Flower installation and environment variable; added build argument; added new port (5555) for Flower; introduced new Nginx directives (chunked transfer, client body size limits).
apiserver/plane/api/* (serializers, URLs, views, middleware) Modified API endpoints and serializers: introduced new methods in authentication (role assumption header), added IssueCustomProperty and IssueTypeCustomProperty serializers, updated URL routes (switching UUID to string for some parameters), and restructured import statements for new endpoints (e.g., webhook, search, attachment).
apiserver/plane/app/permissions/* Enhanced permission logic: added ProjectEntityGuestPermission and updated existing permission classes to allow superuser bypass and include guest access.
apiserver/plane/authentication/* Adjusted authentication flows: updated username initialization in adapters; modified magic code expiry and error handling; refactored MagicSignIn/SignUp endpoints with additional helper methods for workspace and project membership management.
apiserver/plane/db/migrations/*
apiserver/plane/db/models/*
Introduced new migrations and DB model changes: added models for IssueCustomProperty and IssueTypeCustomProperty; updated field definitions in Issue and IssueType models; applied renaming, unique constraints, and modifications to BaseModel save logic.
apiserver/plane/settings/*
apiserver/plane/supervisord.conf
Updated configuration: loaded environment variables via dotenv; modified CORS, session, CSRF, and AWS S3 settings; added new class variables and methods in storage; introduced a new Supervisor configuration for Celery and Flower.
docker-compose-local.yml
docker-compose.yml
demo.Jenkinsfile
deploy/selfhost/install.sh
Revised deployment configurations: removed RabbitMQ service; updated port mappings for MinIO and PostgreSQL; simplified docker-compose by commenting out many services; added a new Jenkins pipeline; changed repository URL in the install script.
packages/types/src/* (issues, view-props) Extended TypeScript definitions: added optional properties (custom_properties, hub_code, customer_code, etc.) to the TIssue type and updated filter parameters in issue view props.
web/app/*
web/core/components/*
web/core/constants/*
web/helpers/*
web/next.config.js
Frontend changes: introduced new React components and filters for custom properties; updated TypeScript types and constants; modified Next.js header policies; and removed deprecated sidebar items and GitHub links.
web/core/store/*
web/core/services/*
web/core/hooks/*
Enhanced state management and service calls: added methods for retrieving custom properties; updated store filters and helpers to include new issue properties.

Possibly related PRs

  • [WEB-2341] feat: Add display filters and display properties to create/update view dialog #5451: The changes in the main PR related to the addition of custom properties and enhancements to the issue management system are directly connected to the modifications in the retrieved PR, which also focuses on integrating display filters and properties for managing views, indicating a shared goal of improving data handling and user interaction.
  • chore: properties validation. #5718: The changes in the main PR, which involve adding new properties related to issues, are related to the retrieved PR, as both involve modifications to issue properties and their handling in the codebase. Specifically, the addition of properties like hub_code, customer_code, and others in the main PR aligns with the updates to the TIssueAdditionalPropertyValuesUpdateProps type in the retrieved PR.
  • [WEB-2749] fix: display property intake #5993: The changes in the main PR regarding the addition of custom properties and their display in the PeekOverviewProperties component are related to the modifications in the retrieved PR, which also focuses on enhancing the display properties within the same component.

Suggested labels

🌟enhancement, ⚙️backend, 🧹chore

Suggested reviewers

  • sriramveeraghanta
  • pablohashescobar

Poem

In meadows of code I hop with delight,
New fields and endpoints shining bright,
Custom properties bloom with every update,
Migrations and settings harmonize in fate,
A bunny sings in joy through this coding night!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.

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

🔭 Outside diff range comments (1)
aio/nginx.conf (1)

15-15: 🛠️ Refactor suggestion

Potential conflict with new client_max_body_size setting.

Line 8 sets a global client_max_body_size of 50M while this line uses a variable ${FILE_SIZE_LIMIT}. This could lead to unexpected behavior if they differ.

Consider consolidating these settings by:

  1. Using the variable consistently in both places, or
  2. Removing the global setting and keeping only the server-specific one
-    client_max_body_size 50M;
+    client_max_body_size ${FILE_SIZE_LIMIT};
🧹 Nitpick comments (92)
apiserver/plane/db/models/__init__.py (1)

44-44: New model imports added for custom properties

Added imports for IssueCustomProperty and IssueTypeCustomProperty models, which will make these models available throughout the application for handling custom properties for issues and issue types.

According to the static analysis, these imported models may not be used directly. Consider either:

  1. Adding __all__ to explicitly list exported modules
  2. Verifying these imports are actually needed
+# List of public symbols for star imports
+__all__ = [
+    "AnalyticView",
+    "APIActivityLog", 
+    # ...include all other models
+    "IssueCustomProperty",
+    "IssueTypeCustomProperty",
+]

Also applies to: 115-115

🧰 Tools
🪛 Ruff (0.8.2)

44-44: .issue.IssueCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

web/app/[workspaceSlug]/(projects)/header.tsx (1)

3-3: Remove or restore the commented-out imports
Since these imports are now commented out, confirm they are unused. If they are indeed unnecessary, removing them entirely is cleaner than leaving commented code.

-// import Image from "next/image";
-// import githubBlackImage from "/public/logos/github-black.png";
-// import githubWhiteImage from "/public/logos/github-white.png";
-// import { GITHUB_REDIRECTED } from "@/constants/event-tracker";

Also applies to: 7-8, 14-14

apiserver/plane/db/models/base.py (1)

46-48: Minor: Extra newlines added

Extra newlines have been added at the end of the file. While this doesn't affect functionality, it's worth ensuring it follows the project's style guidelines.

Consider maintaining a consistent style for end-of-file newlines across the project.

docker-compose-local.yml (2)

198-198: Unused volume definition.

The rabbitmq_data volume is still defined but no longer used since the plane-mq service has been removed.

Consider removing the unused rabbitmq_data volume definition:

volumes:
  redisdata:
  uploads:
  pgdata:
-  rabbitmq_data:

1-173:

Details

❓ Verification inconclusive

RabbitMQ service (plane-mq) has been removed.

The RabbitMQ message queue service has been completely removed from the docker-compose configuration. This suggests a significant architectural change in how the application handles messaging.

This change may require corresponding updates in the application code if it previously relied on RabbitMQ for message processing. Consider reviewing the application's message processing logic to ensure it's compatible with this change.


🏁 Script executed:

#!/bin/bash
# Check for RabbitMQ references in the codebase that might need updating
echo "Checking for RabbitMQ references in the codebase..."
rg -i "rabbitmq|amqp" --type py ./apiserver/

Length of output: 1057


Action Required: Update Messaging Configuration

The removal of the RabbitMQ (plane-mq) service from the Docker Compose file indicates a significant shift in how messaging is handled. However, our grep shows that RabbitMQ settings are still present in the application configuration (notably in apiserver/plane/settings/common.py). Please verify whether these settings should be removed or updated to match the new messaging architecture. If you're transitioning to a different messaging broker, update the corresponding environment variables and connection logic accordingly; otherwise, ensure that any external RabbitMQ services required by these settings are appropriately managed.

apiserver/plane/utils/constants.py (1)

37-48: Consider a more scalable approach for workspace-specific properties

The implementation uses a hardcoded mapping between workspace name ("heineken") and allowed custom properties. While this works for the immediate need, it has some limitations:

  1. Hardcoding client names in the codebase creates tight coupling between code and specific customers
  2. Adding properties for new workspaces requires code changes
  3. May not scale well if many workspaces need different custom properties

Consider implementing one of these more flexible approaches:

  • Store this configuration in the database instead of code
  • Create an admin interface for managing custom properties per workspace
  • Use a configuration file that can be updated without code changes
apiserver/plane/authentication/adapter/base.py (1)

175-175: Unnecessary blank line added

There's an extra blank line added that doesn't appear to serve any purpose.

-            
+
apiserver/plane/api/serializers/project.py (1)

12-12: Remove unused import

The IssueTypeSerializer is imported but not used anywhere in this file. Removing unused imports helps maintain clean code and prevents confusion about dependencies.

-from .issue_type import IssueTypeSerializer
🧰 Tools
🪛 Ruff (0.8.2)

12-12: .issue_type.IssueTypeSerializer imported but unused

Remove unused import: .issue_type.IssueTypeSerializer

(F401)

web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (2)

40-40: Consider defining these filters in a constants file

The additionalFilters array contains what appear to be business-specific filter keys. Consider moving this to a dedicated constants file to improve maintainability and reusability across the application.


139-145: Implement consistent error handling for missing values

The conditional rendering for additional properties doesn't have the same null/empty array checks that other filter types have. Consider adding similar validation as done in lines 69-70 to ensure consistent behavior.

{additionalFilters?.includes(filterKey) && (
+  Array.isArray(value) && value.length > 0 && (
    <AppliedAdditionalPropertiesFilters
      editable={isEditingAllowed}
      handleRemove={(val) => handleRemoveFilter(filterKey, val)}
      values={value}
    />
+  )
)}
web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1)

14-33: Consider adding a check for empty values array

The component renders filter items but doesn't handle the case when values might be empty. Consider adding a check to handle this case more gracefully, though this might be handled by the parent component.

Also, note that the editable prop is defined in the interface but not used in the component implementation. Either use it to conditionally render the remove button or remove it from the Props interface.

export const AppliedAdditionalPropertiesFilters: React.FC<Props> = observer((props) => {
-  const { handleRemove, values } = props;
+  const { handleRemove, values, editable } = props;

  return (
    <>
      {values.map((element) => (
        <div key={element} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
          {element}
+         {editable && (
          <button
            type="button"
            className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
            onClick={() => handleRemove(element)}
          >
            <X size={10} strokeWidth={2} />
          </button>
+         )}
        </div>
      ))}
    </>
  );
});
apiserver/plane/app/views/base.py (1)

123-124: Improved debugging output for excessive database queries.

Adding detailed query logging when query count exceeds 20 is good for debugging performance issues, but consider using a logging framework instead of print statements for better control.

if len(connection.queries) > 20:
-    print(connection.queries)
+    import logging
+    logger = logging.getLogger(__name__)
+    logger.debug(f"Excessive queries detected: {len(connection.queries)}")
+    for i, query in enumerate(connection.queries):
+        logger.debug(f"Query {i+1}: {query['sql']} (took: {query['time']}s)")
apiserver/plane/api/serializers/webhook.py (1)

18-69: Refactor duplicate hostname resolution and validation logic.

Both create() and the beginning part of update() perform domain resolution checks. Extracting this logic into a shared helper method would reduce duplication and ease future maintenance.

 def _validate_hostname(self, url, request=None):
     # common logic for hostname extraction, resolution, loopback checks, domain restrictions

 def create(self, validated_data):
     url = validated_data.get("url", None)
-    # Extract the hostname, resolve and validate, etc.
+    self._validate_hostname(url, self.context.get("request"))
     return Webhook.objects.create(**validated_data)

 def update(self, instance, validated_data):
     url = validated_data.get("url", None)
     if url:
-        # Repeated logic
+        self._validate_hostname(url, self.context.get("request"))
     return super().update(instance, validated_data)
apiserver/plane/settings/storage.py (3)

16-17: Ensure these class variables are properly documented

Adding these class variables could change the behavior of file storage. The file_overwrite setting prevents files with the same name from being overwritten, while the empty location sets the base storage directory to root.

Consider adding a docstring explaining these settings and their implications for the storage behavior.


49-49: Forced HTTPS scheme might cause issues in certain environments

Always using https:// for the endpoint URL regardless of the original request scheme could cause problems in development or test environments that use HTTP.

Consider preserving the original request scheme:

- f"https://{request.get_host()}"
+ f"{request.scheme}://{request.get_host()}"

91-92: Remove unnecessary blank lines

These added blank lines within the generate_presigned_post method don't serve a functional purpose and affect code style consistency.

try:
-            
     # Generate a presigned URL for the S3 object
     response = self.s3_client.generate_presigned_post(
         ...
     )
-            

Also applies to: 100-100

apiserver/plane/api/serializers/issue_type.py (2)

1-2: Unused import detected

The serializers import from rest_framework isn't directly used.

-from rest_framework import serializers
+from rest_framework import serializers  # TODO: Remove if unused

Or remove it completely if not needed.

🧰 Tools
🪛 Ruff (0.8.2)

1-1: rest_framework.serializers imported but unused

Remove unused import: rest_framework.serializers

(F401)


26-44: Check indentation consistency in IssueTypeCustomPropertySerializer

There's inconsistent indentation in the Meta class (line 39 has extra spaces).

    class Meta:
        model = IssueTypeCustomProperty
        fields = "__all__"
        read_only_fields = [
            "id",
            "issue_type",
            "created_at",
            "updated_at",
            "created_by",
            "updated_by",
            "deleted_at"
        ]
-       
+
    def create(self, validated_data):
apiserver/plane/bgtasks/webhook_task.py (1)

405-405: Remove unnecessary blank line

This added blank line doesn't serve a functional purpose and affects code style consistency.

    if event == "issue_comment":
        webhooks = webhooks.filter(issue_comment=True)
-        
    for webhook in webhooks:
web/core/services/workspace.service.ts (1)

292-300: Fix the extra space in parameter definition

There's an unnecessary space after projectId: string in the parameter list.

-  async getIssueAdditionalProperties(workspaceSlug: string, projectId: string , field: any): Promise<any> {
+  async getIssueAdditionalProperties(workspaceSlug: string, projectId: string, field: any): Promise<any> {
apiserver/plane/middleware/api_log_middleware.py (1)

22-32: Remove or implement commented-out code

This commented-out process_view method seems to be a work in progress or abandoned functionality. Either fully implement it or remove it to keep the codebase clean.

apiserver/plane/app/permissions/project.py (2)

49-49: Remove debug print statement

This print statement appears to be for debugging purposes and should not be included in production code.

-        print("Project ID:: %s" %  view.project_id)

119-152: Potential duplication with ProjectEntityPermission class

The new ProjectEntityGuestPermission class is nearly identical to ProjectEntityPermission. Consider if this duplication is necessary or if the existing class could be modified to handle both cases.

You could potentially refactor these classes to share common code or use a base class with specific permission implementations.

demo.Jenkinsfile (2)

158-228: Consider adding rollback or error-handling logic for failed deployments.
When deploying multiple services in parallel, a single failure might leave the system in a partially updated state. Incorporating rollback or clear error-handling processes will ensure more robust deploys.


231-237: Slack post-build notification is fine, but verify environment label.
Currently labeled "prod"; you might prefer something aligned with "demo" for consistency, or confirm that "prod" is intended.

apiserver/plane/db/models/issue_type.py (2)

62-70: Fix typo in the related_name field.

The related_name in the issue_type foreign key contains a typographical error - "custom_propery_issue_type" should be "custom_property_issue_type".

    issue_type = models.ForeignKey(
        "db.IssueType",
        on_delete=models.CASCADE,
-        related_name="custom_propery_issue_type",
+        related_name="custom_property_issue_type",
    )

71-83: Fix typo in database table name.

The db_table in the Meta class has a typographical error - "isssue_type_custom_properties" (with three 's') should be "issue_type_custom_properties".

    class Meta:
        unique_together = ["issue_type", "name", "deleted_at"]
        constraints = [ 
            models.UniqueConstraint(
                fields=["issue_type", "name"],
                condition=models.Q(deleted_at__isnull=True),
                name="issue_type_custom_property_unique_type_name_when_deleted_at_null",
            )
        ]
        verbose_name = "Issue Type Custom Property"
        verbose_name_plural = "Issue Type Custom Properties"
-        db_table = "isssue_type_custom_properties"
+        db_table = "issue_type_custom_properties"
        ordering = ("-created_at",)
apiserver/plane/api/middleware/api_authentication.py (3)

27-37: Enhance the validate_api_token method documentation.

The method has been updated to accept an additional parameter, but lacks documentation explaining the purpose and usage of this parameter. Additionally, there's a need to explain the new behavior when using the static API token.

def validate_api_token(self, token, assume_role_value=None):
+    """
+    Validate the API token and return the associated user
+    
+    Args:
+        token: The API token to validate
+        assume_role_value: Optional username to assume that user's role when using a static token
+        
+    Returns:
+        A tuple of (user, token)
+    """
    # Check if the token matches the static token from settings
    User = get_user_model()
    if token == settings.STATIC_API_TOKEN:
        if assume_role_value:
            user = User.objects.filter(username=assume_role_value).first()
        else:
            user = User.objects.filter(is_superuser=True).first()
        self.rewite_project_id_in_url()
        return (user, token)

54-57: Fix method name typo and remove debugging code.

There's a typo in the method name ("rewite" → "rewrite") and a commented-out debugging statement that should be removed.

-def rewite_project_id_in_url(self):
+def rewrite_project_id_in_url(self):
    pass
-    # import pdb;pdb.set_trace()

Also, update the reference to this method in validate_api_token:

    if token == settings.STATIC_API_TOKEN:
        if assume_role_value:
            user = User.objects.filter(username=assume_role_value).first()
        else:
            user = User.objects.filter(is_superuser=True).first()
-        self.rewite_project_id_in_url()
+        self.rewrite_project_id_in_url()
        return (user, token)

64-66: Remove debugging print statement.

Debugging print statements should not be present in production code as they can expose sensitive information in logs.

    # Validate the API token
    assume_role_value = request.headers.get(self.assume_header_role, None)
-    print("assume_role",assume_role_value)
apiserver/plane/settings/common.py (3)

33-35: Remove debugging print statement and use standard .env filename.

Debugging print statements should not be in production code. Also, use the standard ".env" filename instead of "file.env".

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-print(f"BASE_DIR: {BASE_DIR}")
-load_dotenv(os.path.join(BASE_DIR, "file.env"))
+load_dotenv(os.path.join(BASE_DIR, ".env"))

365-368: Clean up commented-out code and clarify session cookie settings.

There are commented-out settings that create confusion about the intended behavior. Clean up the commented code and ensure the settings are clear.

-# SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = secure_origins
-# SESSION_COOKIE_SAMESITE = "None"
+SESSION_COOKIE_SAMESITE = "None" if secure_origins else "Lax"
SESSION_COOKIE_HTTPONLY = True

382-385: Clean up commented-out code and clarify CSRF cookie settings.

Similar to the session cookie settings, the CSRF cookie settings have commented-out code that creates confusion. Clean up the commented code and ensure the settings are clear.

-# CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = secure_origins
-# CSRF_COOKIE_SAMESITE = "None"
+CSRF_COOKIE_SAMESITE = "None" if secure_origins else "Lax"
CSRF_COOKIE_HTTPONLY = False
web/core/constants/issue.ts (2)

113-120: Typo in constant name: "whileListedCustomProperties"

The constant name appears to have a typo. It should probably be whiteListedCustomProperties instead of whileListedCustomProperties to better represent its purpose as a list of approved custom properties.

-const whileListedCustomProperties = [
+const whiteListedCustomProperties = [
  { key: "hub_code", title: "Hub Code" },
  { key: "customer_code", title: "Customer Code" },
  { key: "worker_code", title: "Worker Code" },
  { key: "vendor_code", title: "Vendor Code" },
  { key: "trip_reference_number", title: "Trip Reference Number" },
  { key: "reference_number", title: "Reference Number" },
];

456-464: Remove duplicate "custom_properties" entry in filters

There are duplicate entries for custom_properties in the filter list (lines 456 and 463). This redundancy could lead to confusion and potentially issues when applying these filters.

  filters: [
    "priority",
    "state",
    "cycle",
    "module",
    "assignees",
    "mentions",
    "created_by",
    "labels",
    "start_date",
    "target_date",
    "issue_type",
    "custom_properties",
    "hub_code",
    "customer_code",
    "worker_code",
    "vendor_code",
    "trip_reference_number",
    "reference_number",
-   "custom_properties"
  ],
apiserver/plane/api/urls/issue.py (1)

9-10: Remove unused import: IssueTypeAPIEndpoint

The IssueTypeAPIEndpoint is imported but not used anywhere in this file.

from plane.api.views import (
    IssueAPIEndpoint,
    LabelAPIEndpoint,
    IssueLinkAPIEndpoint,
    IssueCommentAPIEndpoint,
    IssueActivityAPIEndpoint,
    WorkspaceIssueAPIEndpoint,
    IssueAttachmentV2Endpoint,
-   IssueTypeAPIEndpoint
)
🧰 Tools
🪛 Ruff (0.8.2)

10-10: plane.api.views.IssueTypeAPIEndpoint imported but unused

Remove unused import: plane.api.views.IssueTypeAPIEndpoint

(F401)

apiserver/plane/api/views/__init__.py (6)

1-4: Remove or use unused imports.

ProjectAPIEndpoint and ProjectArchiveUnarchiveAPIEndpoint are not referenced in this file. If these imports are intended for re-export or future use, consider adding them to __all__. Otherwise, removing them will help maintain a clean and concise import structure.

-from .project import (
-    ProjectAPIEndpoint, 
-    ProjectArchiveUnarchiveAPIEndpoint
-)
+from .project import (
+    ProjectAPIEndpoint, 
+    ProjectArchiveUnarchiveAPIEndpoint,
+)  # Remove or utilize these imports if unneeded
🧰 Tools
🪛 Ruff (0.8.2)

2-2: .project.ProjectAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


3-3: .project.ProjectArchiveUnarchiveAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


15-15: Remove or use unused import.

IssueAttachmentEndpoint is imported but never used. Remove the import or add it to __all__ if you plan to re-export it.

-    IssueAttachmentEndpoint
🧰 Tools
🪛 Ruff (0.8.2)

15-15: .issue.IssueAttachmentEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


17-17: Remove or use unused imports.

IssueTypeAPIEndpoint and IssueTypeCustomPropertyAPIEndpoint are unused imports. Removing them helps avoid confusion and clutter.

-from .issue_type import IssueTypeAPIEndpoint,IssueTypeCustomPropertyAPIEndpoint
🧰 Tools
🪛 Ruff (0.8.2)

17-17: .issue_type.IssueTypeAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


17-17: .issue_type.IssueTypeCustomPropertyAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-18: Remove or use unused import.

IssueAttachmentV2Endpoint is imported but not used in this file. Either remove this import or use it.

-from .attachment import IssueAttachmentV2Endpoint
🧰 Tools
🪛 Ruff (0.8.2)

18-18: .attachment.IssueAttachmentV2Endpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


36-36: Remove or use unused import.

GlobalSearchEndpoint is imported but never referenced. Consider removing or re-exporting it if desired.

-from .search import GlobalSearchEndpoint
🧰 Tools
🪛 Ruff (0.8.2)

36-36: .search.GlobalSearchEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


38-41: Remove or use unused webhook imports.

WebhookEndpoint, WebhookLogsEndpoint, and WebhookSecretRegenerateEndpoint are not referenced. Consider removing them or adding them to __all__ if they are being re-exported.

-from .webhook import (
-    WebhookEndpoint, WebhookLogsEndpoint,
-    WebhookSecretRegenerateEndpoint
-)
🧰 Tools
🪛 Ruff (0.8.2)

39-39: .webhook.WebhookEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


39-39: .webhook.WebhookLogsEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookSecretRegenerateEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/views/base.py (2)

78-78: Avoid printing exceptions directly in production code.

Printing exc can clutter logs or leak sensitive info. Consider using a structured logger or removing it.

-            print(exc)
+            # If needed, log it properly or remove.

89-89: Separate multiple statements for clarity.

Writing import traceback; traceback.print_exc() in one line decreases readability and can trigger style warnings.

-                import traceback; traceback.print_exc()
+                import traceback
+                traceback.print_exc()
🧰 Tools
🪛 Ruff (0.8.2)

89-89: Multiple statements on one line (semicolon)

(E702)

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (2)

248-259: Add a unique key to the <div> element in the map.

React recommends placing the key prop on the top-level element of the mapped array. Currently, you pass key={prop.key} to <FilterAdditionalProperties>, but the lint warns about the <div> lacking a key. Consider moving key={prop.key} to the <div> instead or making the <div> the direct child.

-{ISSUE_ADDITIONAL_PROPERTIES.map((prop: any) => (
-  <div className="py-2">
-    <FilterAdditionalProperties
-      key={prop.key}
+{ISSUE_ADDITIONAL_PROPERTIES.map((prop: any) => (
+  <div key={prop.key} className="py-2">
+    <FilterAdditionalProperties
       appliedFilters={filters[prop.key as keyof IIssueFilterOptions] ?? null}
       ...
🧰 Tools
🪛 Biome (1.9.4)

[error] 249-249: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


261-271: Validate commented-out code.

Line 267 shows a commented-out handler. If it’s no longer needed, remove it to keep the codebase clean. Otherwise, consider a clarifying comment about its intended usage.

-              // handleUpdate={(val) => handleFiltersUpdate("custom_properties", null, val)}
+              // TODO: Clarify or remove if no longer needed
apiserver/plane/authentication/provider/credentials/magic_code.py (3)

87-88: Avoid hard-coding the domain.
Hard-coding "@plane-shipsy.com" limits the provider to a single domain. For a multi-tenant or more flexible setup, consider extracting the domain from configuration or parsing the incoming email domain more dynamically.


117-123: Avoid hard-coding the domain again.
As with lines 87–88, replacing "@plane-shipsy.com" directly might cause domain-related limitations. Consider using a configuration-driven or generic approach.


131-133: Remove sensitive debug prints.
Printing all Redis keys may reveal sensitive or private information (keys, emails, tokens). Consider removing or limiting these debug statements, or use a structured logger with masking.

apiserver/plane/api/views/issue_type.py (3)

6-19: Remove unused imports.
The imports Case, CharField, Exists (here used below for annotation, so confirm usage), F, Func, Max, OuterRef, Q, Value, When, and Subquery appear to be mostly unused. As flagged by static analysis, removing unused imports helps maintain clarity and reduce confusion.

-from django.db.models import (
-    Case,
-    CharField,
-    Exists,
-    F,
-    Func,
-    Max,
-    OuterRef,
-    Q,
-    Value,
-    When,
-    Subquery,
-)
+from django.db.models import Exists, OuterRef  # Retain only the needed imports
🧰 Tools
🪛 Ruff (0.8.2)

8-8: django.db.models.Case imported but unused

Remove unused import

(F401)


9-9: django.db.models.CharField imported but unused

Remove unused import

(F401)


10-10: django.db.models.Exists imported but unused

Remove unused import

(F401)


11-11: django.db.models.F imported but unused

Remove unused import

(F401)


12-12: django.db.models.Func imported but unused

Remove unused import

(F401)


13-13: django.db.models.Max imported but unused

Remove unused import

(F401)


14-14: django.db.models.OuterRef imported but unused

Remove unused import

(F401)


15-15: django.db.models.Q imported but unused

Remove unused import

(F401)


16-16: django.db.models.Value imported but unused

Remove unused import

(F401)


17-17: django.db.models.When imported but unused

Remove unused import

(F401)


18-18: django.db.models.Subquery imported but unused

Remove unused import

(F401)


140-141: Remove or use these variables.
requested_data and current_instance are assigned but never used, indicating possible leftover debugging code or incomplete logic. Removing them will improve clarity and reduce warnings.

- requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
- current_instance = json.dumps(IssueTypeSerializer(issue_comment).data, cls=DjangoJSONEncoder)
🧰 Tools
🪛 Ruff (0.8.2)

140-140: Local variable requested_data is assigned to but never used

Remove assignment to unused variable requested_data

(F841)


141-141: Local variable current_instance is assigned to but never used

Remove assignment to unused variable current_instance

(F841)


200-200: Remove unused workspace variable.
workspace is fetched but never used. Either remove the variable or use it if needed for further validations.

- workspace = Workspace.objects.get(slug=slug)
🧰 Tools
🪛 Ruff (0.8.2)

200-200: Local variable workspace is assigned to but never used

Remove assignment to unused variable workspace

(F841)

apiserver/Dockerfile.api (1)

63-65: Consider moving migrations to container startup

Running migrations at build time may not be ideal as the database state might change between image build and container startup.

Consider moving migrations to the CMD section instead of RUN, so they execute at container startup:

-RUN if [ "${ENV_TYPE}" = "apiserver" ]; then \
-    python manage.py migrate --noinput; \
-    fi

 CMD if [ "${ENV_TYPE}" = "apiserver" ]; then \
+    python manage.py migrate --noinput && \
     gunicorn -w 2 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:8000 --max-requests 1200 --max-requests-jitter 1000 --access-logfile -; \
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (5)

4-5: Remove commented-out import

The unused import for sortBy should be removed to keep the code clean.

- // import sortBy from "lodash/sortBy";
  import { observer } from "mobx-react";

10-10: Remove commented-out imports

Unused imports should be removed for code cleanliness.

- // import { Loader, StateGroupIcon } from "@plane/ui";

40-71: Improve error handling and loading state

The component only logs errors to the console without informing the user of potential issues. Additionally, there's no loading state indication.

Add a loading state and better error handling:

const [groupedProperties, setGroupedProperties] = useState<Record<string, any[]>>({});
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState<string | null>(null);

const appliedFiltersCount = appliedFilters?.length ?? 0;

// ...

React.useEffect(() => {
  const fetchCustomProperties = async (): Promise<void> => {
+   setIsLoading(true);
+   setError(null);
    try {
      const data = await workspaceService.getIssuesCustomProperties(workspaceSlug.toString());
      
      // ... existing code ...
      
    } catch (error) {
      console.error("Error fetching custom properties:", error);
+     setError("Failed to load custom properties");
+   } finally {
+     setIsLoading(false);
    }
  };

  fetchCustomProperties();
}, [workspaceSlug]);

Then in the render section, add loading and error states:

return (
  <>
    <FilterHeader
      title={`Custom Properties${appliedFiltersCount > 0 ? ` (${appliedFiltersCount})` : ""}`}
      isPreviewEnabled={mainPreviewEnabled}
      handleIsPreviewEnabled={() => setMainPreviewEnabled(!mainPreviewEnabled)}
    />
+   {isLoading && <div className="px-4 py-2 text-sm text-custom-text-200">Loading...</div>}
+   {error && <div className="px-4 py-2 text-sm text-red-500">{error}</div>}
    {mainPreviewEnabled && !isLoading && !error && (
      // ... existing render code ...
    )}
  </>
);

121-121: Simplify boolean expression

The ternary expression returning true/false is unnecessary.

- isChecked={appliedFilters?.includes(`${groupKey}:${property}`) ? true : false}
+ isChecked={Boolean(appliedFilters?.includes(`${groupKey}:${property}`))}

Or even simpler:

- isChecked={appliedFilters?.includes(`${groupKey}:${property}`) ? true : false}
+ isChecked={!!appliedFilters?.includes(`${groupKey}:${property}`)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 121-121: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


126-132: Improve "View all/View less" button accessibility

The current button lacks proper styling and accessibility features.

Enhance the button:

{properties.length > 5 ? <button
  type="button"
  className="ml-8 text-xs font-medium text-custom-primary-100"
+ aria-expanded={renderMoreGroupItems[groupKey] ? "true" : "false"}
+ aria-controls={`${groupKey}-properties`}
  onClick={() => handleViewToggle(groupKey)}
>
  {renderMoreGroupItems[groupKey] ? "View less" : "View all"}
</button> : null}

Also consider adding unique IDs to the property lists for better accessibility:

<div>
  {properties
    .slice(0, renderMoreGroupItems[groupKey] ? properties.length : 5)
+   .map((property, index) => (
-   .map((property) => (
      <FilterOption
+       id={`${groupKey}-property-${index}`}
        key={`${groupKey}:${property}`}
        isChecked={!!appliedFilters?.includes(`${groupKey}:${property}`)}
        onClick={() => handleUpdate(`${groupKey}:${property}`)}
        title={property}
      />
    ))}
apiserver/plane/app/views/view/base.py (2)

3-3: Unnecessary import.

The import django.db.models.Count is not used in this file.

- from django.db.models import Count
🧰 Tools
🪛 Ruff (0.8.2)

3-3: django.db.models.Count imported but unused

Remove unused import: django.db.models.Count

(F401)


209-306: Modified get_queryset to handle custom property filtering.

The query now takes a filters parameter and applies custom property filtering through a dynamic query expression. The implementation looks correct but could be refactored slightly for better readability.

Consider extracting the custom property filtering logic into a separate method for better readability:

def _apply_custom_property_filters(self, queryset, custom_properties):
    if not custom_properties:
        return queryset
        
    filters = [
        Q(id__in=IssueCustomProperty.objects.filter(
            issue_id=OuterRef("id"),
            key=group_key,
            value__in=values
        ).values("issue_id"))
        for group_key, values in custom_properties.items()
    ]
    
    return queryset.filter(*filters)

def get_queryset(self, filters):
    custom_properties = filters.get("custom_properties", {})
    queryset = (
        Issue.issue_objects.annotate(
            # ... existing annotations
        )
        # ... existing filters and prefetches
    )
    
    return self._apply_custom_property_filters(queryset, custom_properties)
apiserver/plane/api/views/member.py (2)

271-271: Remove debug print statement.

This print statement should be removed before production deployment.

-        print(created_bys)

286-302: Remove commented code in the filter method.

The commented-out code isn't necessary and should be removed for cleaner production code.

def filter_created_by_username(params, issue_filter, method, prefix=""):
    if method == "GET":
        created_bys = [
            item
            for item in params.get("created_by_username").split(",")
            if item != "null"
        ]
        if len(created_bys) and "" not in created_bys:
            issue_filter[f"{prefix}created_by__username__in"] = created_bys
-    # else:
-    #     if (
-    #         params.get("created_by", None)
-    #         and len(params.get("created_by"))
-    #         and params.get("created_by") != "null"
-    #     ):
-    #         issue_filter[f"{prefix}created_by__in"] = params.get("created_by")
    return issue_filter
apiserver/plane/utils/issue_filters.py (2)

6-6: Remove unused import.

The Q import from django.db.models is not being used in the active code.

-from django.db.models import Q
🧰 Tools
🪛 Ruff (0.8.2)

6-6: django.db.models.Q imported but unused

Remove unused import: django.db.models.Q

(F401)


563-591: Remove commented code and debug print statement.

The implementation contains commented-out code and a debug print statement that should be removed before production deployment.

def filter_custom_properties(params, issue_filter, method, prefix=""):
    if method == "GET":
        custom_properties = [
            item
            for item in params.get("custom_properties").split(",")
            if item != "null"
        ]

-        # query = Q()
-        # for row in custom_properties:
-        #     key, value = row.split(":")
-        #     query &= Q(
-        #         Q(custom_properties__project_custom_property_id=key) &
-        #         Q(custom_properties__value=value)
-        #     )
-        
-        # issue_filter['base'] = query
        
        groupedCustomProperties = {}
        for row in custom_properties:
            key, value = row.split(':')
            if key not in groupedCustomProperties:
                groupedCustomProperties[key] = []
            groupedCustomProperties[key].append(value)

        issue_filter['custom_properties'] = groupedCustomProperties

-    print(issue_filter)
    return issue_filter
apiserver/plane/api/views/attachment.py (3)

9-9: Remove unused import.

The import allow_permission at line 9 is never used. Removing it helps keep the codebase clean.

- from plane.app.permissions import ProjectEntityPermission, allow_permission
+ from plane.app.permissions import ProjectEntityPermission
🧰 Tools
🪛 Ruff (0.8.2)

9-9: plane.app.permissions.allow_permission imported but unused

Remove unused import: plane.app.permissions.allow_permission

(F401)


26-38: Validate file type more robustly.

Currently, this check only compares the MIME type to a predefined list. It might be beneficial to handle edge cases (e.g., empty strings or missing file type). Consider adding fallback checks or error messages that explicitly guide the user to pass a valid file type.


106-121: Consider returning JSON for unuploaded attachments.

Instead of returning a 400 with a static "The asset is not uploaded." message, consider including metadata about why the asset is not available or when it might become available. This can help front-end consumers provide more context to users.

apiserver/plane/api/serializers/issue.py (3)

36-42: Remove assignment to unused variable in is_uuid().

The variable uuid_obj is never used. You can remove the assignment and rely on the exception check alone.

def is_uuid(value):
    try:
-        uuid_obj = uuid.UUID(str(value))
+        uuid.UUID(str(value))
        return True
    except (ValueError, TypeError):
        return False
🧰 Tools
🪛 Ruff (0.8.2)

38-38: Local variable uuid_obj is assigned to but never used

Remove assignment to unused variable uuid_obj

(F841)


179-179: Remove debugging print statements.

There is a print(data) call at line 176 (visible in your snippet). Such debug prints in production code can clutter logs. Consider removing or using proper logging.


273-314: Retaining older custom properties vs. overwriting.

Here, existing IssueCustomProperty entries are deleted before new ones are created. If partial updates are expected, consider a patch-like approach to avoid discarding unmodified entries.

apiserver/plane/bgtasks/issue_activities_task.py (1)

370-380: Graceful handling of unknown user IDs.

set([str(asg) for asg in ...]) might raise an error if the added_asignee or dropped_assignee does not exist as a valid user. Consider safeguarding with a try-except or an existence check to avoid unhandled exceptions.

apiserver/plane/app/views/issue/base.py (7)

60-60: Remove unused import
This import is not referenced anywhere and should be removed.

- from plane.utils.constants import ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP
🧰 Tools
🪛 Ruff (0.8.2)

60-60: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP imported but unused

Remove unused import: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP

(F401)


71-75: Unused imports
ProjectEntityPermission, ProjectLitePermission, and ProjectMemberPermission appear unused in this file.

- from plane.app.permissions import (
-     ProjectEntityPermission,
-     ProjectLitePermission,
-     ProjectMemberPermission,
- )
🧰 Tools
🪛 Ruff (0.8.2)

72-72: plane.app.permissions.ProjectEntityPermission imported but unused

Remove unused import

(F401)


73-73: plane.app.permissions.ProjectLitePermission imported but unused

Remove unused import

(F401)


74-74: plane.app.permissions.ProjectMemberPermission imported but unused

Remove unused import

(F401)


235-285: Custom property filtering logic
These subqueries correctly filter issues by matching each custom property. However, for large queries or numerous filters, it might become expensive. Consider adding database indexes on (issue_id, key, value) or exploring more efficient filtering mechanisms.


439-439: Potential debug leftover
Printing serializer data can clutter logs. Remove this statement before production.

- print(serializer.data)

499-499: Potential debug leftover
Printing the issue is likely for debugging. Consider removing to keep logs clean.

- print(issue)

1218-1260: SearchAPIEndpoint
The logic is correct, but constructing a set in memory may be costly for large datasets. Consider using database-level distinct operations or excluding nulls in the query to reduce memory usage and improve scalability.

- values = Issue.objects.filter(
-     workspace__slug=slug, project_id=project_id,
- ).values_list(field, flat=True)
- unique_values = list(set(filter(None, values)))

+ unique_values_qs = Issue.objects.filter(
+     workspace__slug=slug, project_id=project_id
+ ).exclude(**{field + "__isnull": True}).values_list(field, flat=True).distinct()
+ unique_values = list(unique_values_qs)

1261-1297: SearchSingleValueAPI
Combining exact matches with partial matches is logical. For very large datasets, consider additional database filtering or .distinct() usage to avoid potentially large in-memory sets.

apiserver/plane/api/views/webhook.py (1)

32-38: Catching IntegrityError
Relying on the substring "already exists" in the exception message can be fragile. When possible, detect uniqueness violations using constraint names or a more robust logic that doesn't depend on specific database error strings.

apiserver/plane/api/views/issue.py (3)

36-36: Remove unused import
IssueTypeSerializer is never referenced; consider removing it.

- from plane.api.serializers import IssueTypeSerializer
🧰 Tools
🪛 Ruff (0.8.2)

36-36: plane.api.serializers.IssueTypeSerializer imported but unused

Remove unused import: plane.api.serializers.IssueTypeSerializer

(F401)


55-55: Remove unused import
IssueType is not used in this file and can be removed.

- from plane.db.models import IssueType
🧰 Tools
🪛 Ruff (0.8.2)

55-55: plane.db.models.IssueType imported but unused

Remove unused import: plane.db.models.IssueType

(F401)


151-151: Debug logging
print(query) looks like a leftover debug statement. Consider removing it for production.

- print(query)
apiserver/plane/api/views/search.py (6)

37-49: Consider limiting or paginating workspace search results.
If your dataset grows large, returning all matching workspaces could degrade performance and increase payload size. Paginating or limiting the query would enhance responsiveness at scale.


67-100: Evaluate uniform result size limits for issues.
Here, you limit issues to 100 results ([:100]) but other filter methods return an unbounded list. You may want consistent limits or pagination if you anticipate large datasets.


78-78: Confirm that searching within custom properties is indexed.
Performing icontains queries for JSON-like fields (custom_properties__value) can be expensive in PostgreSQL if not indexed properly. Creating functional or GIN indexes on JSON fields can improve performance.


126-150: Improve readability of filter construction.
Repetitive or logic-heavy query building can obscure intent. Consider extracting common filter-building code into a helper method to keep your code DRY.


205-229: Offer a consistent user experience for view searches.
Similar to other filters, consider adding a limit or pagination for views if your user base grows; it will keep responses predictable and efficient.


230-269: Add optional searching of workspace and project results.
Currently, the MODELS_MAPPER only searches issues. If you want users to search across other entities (like workspaces, projects, cycles, etc.), uncomment or expand the MODELS_MAPPER to include them.

apiserver/plane/authentication/views/app/magic.py (3)

88-101: Separate workspace logic from sign-in flow.
Adding users to a workspace in the middle of the authentication flow can obscure responsibilities, complicating maintenance. Consider a post-sign-in hook or dedicated function to handle workspace membership.


290-290: Remove unused variable is_app.
Static analysis indicates it’s never referenced. Reducing unused variables maintains lean, clean code.

- is_app = request.POST.get("is_app", False)
🧰 Tools
🪛 Ruff (0.8.2)

290-290: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)


186-261: Use consistent error handling for sign-in logic.
The exception flow is partly handled via redirects, but repeated blocks of code can be prone to duplication. Centralizing such logic or employing a shared exception handler can reduce maintenance overhead.

apiserver/plane/db/models/issue.py (1)

142-147: Optional fields may need indexing if frequently queried.
The newly introduced fields hub_code, vendor_code, customer_code, worker_code, reference_number, and trip_reference_number are all CharFields. If you plan to query them regularly, consider adding indexes for efficiency.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 94bf90d and b82176c.

📒 Files selected for processing (105)
  • admin/Dockerfile.admin (1 hunks)
  • admin/ce/components/common/upgrade-button.tsx (1 hunks)
  • admin/core/components/admin-sidebar/help-section.tsx (0 hunks)
  • aio/nginx.conf (1 hunks)
  • apiserver/Dockerfile.api (2 hunks)
  • apiserver/plane/api/middleware/api_authentication.py (3 hunks)
  • apiserver/plane/api/serializers/__init__.py (1 hunks)
  • apiserver/plane/api/serializers/issue.py (11 hunks)
  • apiserver/plane/api/serializers/issue_type.py (1 hunks)
  • apiserver/plane/api/serializers/project.py (2 hunks)
  • apiserver/plane/api/serializers/webhook.py (1 hunks)
  • apiserver/plane/api/urls/__init__.py (2 hunks)
  • apiserver/plane/api/urls/issue.py (2 hunks)
  • apiserver/plane/api/urls/issue_type.py (1 hunks)
  • apiserver/plane/api/urls/project.py (2 hunks)
  • apiserver/plane/api/urls/search.py (1 hunks)
  • apiserver/plane/api/urls/state.py (1 hunks)
  • apiserver/plane/api/urls/webhook.py (1 hunks)
  • apiserver/plane/api/views/__init__.py (3 hunks)
  • apiserver/plane/api/views/attachment.py (1 hunks)
  • apiserver/plane/api/views/base.py (6 hunks)
  • apiserver/plane/api/views/issue.py (11 hunks)
  • apiserver/plane/api/views/issue_type.py (1 hunks)
  • apiserver/plane/api/views/member.py (4 hunks)
  • apiserver/plane/api/views/project.py (3 hunks)
  • apiserver/plane/api/views/search.py (1 hunks)
  • apiserver/plane/api/views/state.py (1 hunks)
  • apiserver/plane/api/views/webhook.py (1 hunks)
  • apiserver/plane/app/permissions/__init__.py (1 hunks)
  • apiserver/plane/app/permissions/project.py (7 hunks)
  • apiserver/plane/app/serializers/issue.py (4 hunks)
  • apiserver/plane/app/urls/issue.py (2 hunks)
  • apiserver/plane/app/urls/views.py (1 hunks)
  • apiserver/plane/app/views/__init__.py (1 hunks)
  • apiserver/plane/app/views/base.py (1 hunks)
  • apiserver/plane/app/views/issue/base.py (14 hunks)
  • apiserver/plane/app/views/view/base.py (6 hunks)
  • apiserver/plane/authentication/adapter/base.py (2 hunks)
  • apiserver/plane/authentication/provider/credentials/magic_code.py (3 hunks)
  • apiserver/plane/authentication/utils/redirection_path.py (1 hunks)
  • apiserver/plane/authentication/views/app/magic.py (5 hunks)
  • apiserver/plane/bgtasks/issue_activities_task.py (4 hunks)
  • apiserver/plane/bgtasks/webhook_task.py (1 hunks)
  • apiserver/plane/db/migrations/0084_projectcustomproperty_issuecustomproperty_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1 hunks)
  • apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1 hunks)
  • apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1 hunks)
  • apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1 hunks)
  • apiserver/plane/db/migrations/0091_issue_customer_code_issue_hub_code_and_more.py (1 hunks)
  • apiserver/plane/db/models/__init__.py (3 hunks)
  • apiserver/plane/db/models/base.py (1 hunks)
  • apiserver/plane/db/models/issue.py (4 hunks)
  • apiserver/plane/db/models/issue_type.py (1 hunks)
  • apiserver/plane/middleware/api_log_middleware.py (2 hunks)
  • apiserver/plane/settings/common.py (7 hunks)
  • apiserver/plane/settings/redis.py (1 hunks)
  • apiserver/plane/settings/storage.py (4 hunks)
  • apiserver/plane/utils/constants.py (1 hunks)
  • apiserver/plane/utils/grouper.py (1 hunks)
  • apiserver/plane/utils/issue_filters.py (6 hunks)
  • apiserver/requirements/base.txt (3 hunks)
  • apiserver/supervisord.conf (1 hunks)
  • apiserver/templates/emails/exports/analytics.html (1 hunks)
  • demo.Jenkinsfile (1 hunks)
  • deploy/selfhost/install.sh (1 hunks)
  • docker-compose-local.yml (3 hunks)
  • docker-compose.yml (1 hunks)
  • packages/types/src/issues/issue.d.ts (1 hunks)
  • packages/types/src/view-props.d.ts (2 hunks)
  • space/core/components/issues/filters/selection.tsx (1 hunks)
  • space/next.config.js (1 hunks)
  • web/Dockerfile.web (1 hunks)
  • web/app/[workspaceSlug]/(projects)/header.tsx (1 hunks)
  • web/app/provider.tsx (2 hunks)
  • web/app/workspace-invitations/page.tsx (1 hunks)
  • web/ce/constants/project/settings/features.tsx (1 hunks)
  • web/core/components/issues/custom-properties.tsx (1 hunks)
  • web/core/components/issues/index.ts (1 hunks)
  • web/core/components/issues/issue-detail/sidebar.tsx (6 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/filters/applied-filters/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (2 hunks)
  • web/core/components/issues/issue-layouts/filters/header/filters/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx (1 hunks)
  • web/core/components/issues/peek-overview/properties.tsx (6 hunks)
  • web/core/components/workspace/sidebar/dropdown.tsx (0 hunks)
  • web/core/components/workspace/sidebar/help-section.tsx (1 hunks)
  • web/core/components/workspace/sidebar/projects-list-item.tsx (0 hunks)
  • web/core/constants/analytics.ts (1 hunks)
  • web/core/constants/dashboard.ts (1 hunks)
  • web/core/constants/issue.ts (8 hunks)
  • web/core/constants/spreadsheet.ts (4 hunks)
  • web/core/hooks/use-group-dragndrop.ts (1 hunks)
  • web/core/services/workspace.service.ts (1 hunks)
  • web/core/store/issue/helpers/issue-filter-helper.store.ts (3 hunks)
  • web/core/store/issue/issue-details/issue.store.ts (1 hunks)
  • web/helpers/issue.helper.ts (1 hunks)
  • web/next.config.js (1 hunks)
💤 Files with no reviewable changes (3)
  • admin/core/components/admin-sidebar/help-section.tsx
  • web/core/components/workspace/sidebar/dropdown.tsx
  • web/core/components/workspace/sidebar/projects-list-item.tsx
🧰 Additional context used
🧬 Code Definitions (38)
apiserver/plane/app/permissions/__init__.py (1)
apiserver/plane/app/permissions/project.py (1) (1)
  • ProjectEntityGuestPermission (119-152)
apiserver/plane/db/models/__init__.py (2)
apiserver/plane/db/models/issue.py (1) (1)
  • IssueCustomProperty (726-747)
apiserver/plane/db/models/issue_type.py (2) (2)
  • IssueType (10-32)
  • IssueTypeCustomProperty (62-83)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (3)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1) (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1) (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1) (1)
  • Migration (7-19)
apiserver/plane/api/serializers/__init__.py (1)
apiserver/plane/api/serializers/issue_type.py (2) (2)
  • IssueTypeSerializer (7-24)
  • IssueTypeCustomPropertySerializer (26-44)
apiserver/plane/app/urls/views.py (1)
apiserver/plane/app/views/view/base.py (1) (1)
  • WorkspaceViewIssuesViewSet (208-467)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (3)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1) (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1) (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1) (1)
  • Migration (6-18)
web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx (1)
web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1) (1)
  • AppliedAdditionalPropertiesFilters (14-33)
apiserver/plane/api/urls/issue_type.py (1)
apiserver/plane/api/views/issue_type.py (2) (2)
  • IssueTypeAPIEndpoint (43-196)
  • IssueTypeCustomPropertyAPIEndpoint (198-240)
apiserver/plane/api/urls/search.py (1)
apiserver/plane/api/views/search.py (1) (1)
  • GlobalSearchEndpoint (29-268)
apiserver/plane/api/views/__init__.py (4)
apiserver/plane/api/views/issue_type.py (1) (1)
  • IssueTypeAPIEndpoint (43-196)
apiserver/plane/api/views/attachment.py (1) (1)
  • IssueAttachmentV2Endpoint (18-174)
apiserver/plane/api/views/search.py (1) (1)
  • GlobalSearchEndpoint (29-268)
apiserver/plane/api/views/webhook.py (1) (1)
  • WebhookEndpoint (16-107)
apiserver/plane/api/serializers/project.py (1)
apiserver/plane/api/serializers/issue_type.py (1) (1)
  • IssueTypeSerializer (7-24)
apiserver/plane/authentication/provider/credentials/magic_code.py (1)
apiserver/plane/authentication/adapter/base.py (1) (1)
  • set_user_data (44-45)
apiserver/plane/api/views/issue_type.py (3)
apiserver/plane/api/serializers/issue_type.py (2) (2)
  • IssueTypeSerializer (7-24)
  • IssueTypeCustomPropertySerializer (26-44)
apiserver/plane/app/permissions/project.py (1) (1)
  • ProjectLitePermission (155-168)
apiserver/plane/db/models/issue_type.py (2) (2)
  • IssueType (10-32)
  • IssueTypeCustomProperty (62-83)
apiserver/plane/api/urls/issue.py (3)
apiserver/plane/api/views/attachment.py (1) (1)
  • IssueAttachmentV2Endpoint (18-174)
apiserver/plane/api/views/issue_type.py (1) (1)
  • IssueTypeAPIEndpoint (43-196)
apiserver/plane/api/views/issue.py (1) (1)
  • IssueAPIEndpoint (122-577)
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1)
web/core/services/workspace.service.ts (1) (1)
  • WorkspaceService (20-301)
apiserver/plane/settings/common.py (2)
apiserver/plane/app/views/analytic/base.py (3) (3)
  • get (33-216)
  • get (247-272)
  • get (349-501)
apiserver/plane/app/views/issue/base.py (4) (4)
  • get (92-211)
  • get (804-809)
  • get (839-853)
  • get (1030-1123)
apiserver/plane/api/urls/state.py (1)
apiserver/plane/api/views/state.py (1) (1)
  • StateAPIEndpoint (16-162)
web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1)
web/core/services/workspace.service.ts (1) (1)
  • WorkspaceService (20-301)
web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (4)
web/core/constants/issue.ts (1) (1)
  • ISSUE_ADDITIONAL_PROPERTIES (531-541)
web/core/components/issues/issue-layouts/filters/header/filters/additional-properties.tsx (1) (1)
  • FilterAdditionalProperties (18-80)
packages/types/src/view-props.d.ts (1) (1)
  • IIssueFilterOptions (94-116)
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx (1) (1)
  • FilterCustomProperty (19-142)
web/core/constants/spreadsheet.ts (1)
web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1) (1)
  • SpreadsheetStandardPropertyColumn (11-21)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (5)
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1) (1)
  • Migration (6-22)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1) (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1) (1)
  • Migration (9-48)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1) (1)
  • Migration (6-18)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1) (1)
  • Migration (6-18)
apiserver/plane/app/serializers/issue.py (2)
apiserver/plane/db/models/issue.py (4) (4)
  • IssueCustomProperty (726-747)
  • Meta (190-194)
  • Meta (279-283)
  • Meta (311-323)
apiserver/plane/api/serializers/issue.py (13) (13)
  • IssueCustomPropertySerializer (43-54)
  • Meta (44-54)
  • Meta (88-100)
  • Meta (363-370)
  • Meta (374-386)
  • Meta (390-402)
  • Meta (446-457)
  • Meta (464-478)
  • Meta (501-506)
  • Meta (512-515)
  • Meta (521-524)
  • Meta (528-534)
  • Meta (544-555)
apiserver/plane/api/views/project.py (4)
apiserver/plane/api/views/base.py (1) (1)
  • BaseAPIView (40-226)
apiserver/plane/db/models/project.py (1) (1)
  • ProjectMember (215-259)
apiserver/plane/api/serializers/project.py (1) (1)
  • create (66-88)
apiserver/plane/db/models/issue.py (1) (1)
  • IssueUserProperty (533-561)
web/core/components/issues/issue-detail/sidebar.tsx (2)
web/core/constants/issue.ts (1) (1)
  • ISSUE_ADDITIONAL_PROPERTIES (531-541)
web/core/components/issues/custom-properties.tsx (1) (1)
  • CustomProperties (13-33)
web/core/constants/issue.ts (1)
packages/types/src/issues/issue.d.ts (1) (1)
  • TIssue (52-73)
apiserver/plane/utils/issue_filters.py (3)
apiserver/plane/api/views/issue.py (7) (7)
  • get (97-120)
  • get (163-308)
  • get (658-676)
  • get (739-763)
  • get (886-904)
  • get (1050-1081)
  • get (1156-1161)
apiserver/plane/app/views/issue/base.py (6) (6)
  • get (92-211)
  • get (804-809)
  • get (839-853)
  • get (1030-1123)
  • get (1221-1259)
  • get (1265-1296)
apiserver/plane/api/views/project.py (1) (1)
  • get (202-240)
apiserver/plane/app/views/__init__.py (1)
apiserver/plane/app/views/issue/base.py (2) (2)
  • SearchAPIEndpoint (1218-1259)
  • SearchSingleValueAPI (1261-1296)
apiserver/plane/api/urls/webhook.py (1)
apiserver/plane/api/views/webhook.py (3) (3)
  • WebhookEndpoint (16-107)
  • WebhookLogsEndpoint (121-129)
  • WebhookSecretRegenerateEndpoint (110-118)
apiserver/plane/api/serializers/issue.py (3)
apiserver/plane/db/models/issue.py (17) (17)
  • IssueCustomProperty (726-747)
  • Meta (190-194)
  • Meta (279-283)
  • Meta (311-323)
  • Meta (339-351)
  • Meta (367-379)
  • Meta (393-397)
  • Meta (427-431)
  • Meta (477-481)
  • Meta (522-526)
  • Meta (545-557)
  • Meta (572-576)
  • Meta (592-596)
  • Meta (609-621)
  • Meta (638-650)
  • Meta (669-681)
  • Meta (704-720)
apiserver/plane/app/views/view/base.py (2) (2)
  • IssueCustomPropertySerializer (63-74)
  • create (652-659)
apiserver/plane/api/serializers/issue_type.py (1) (1)
  • create (40-44)
apiserver/plane/api/views/attachment.py (3)
apiserver/plane/api/serializers/issue.py (3) (3)
  • IssueAttachmentSerializer (445-457)
  • create (181-268)
  • create (419-427)
apiserver/plane/settings/storage.py (2) (2)
  • S3Storage (14-166)
  • generate_presigned_post (66-106)
apiserver/plane/db/models/base.py (1) (1)
  • save (25-42)
apiserver/plane/api/views/search.py (2)
apiserver/plane/api/views/base.py (3) (3)
  • fields (211-217)
  • BaseAPIView (40-226)
  • project_id (199-208)
apiserver/plane/db/models/issue.py (1) (1)
  • Issue (108-268)
apiserver/plane/app/urls/issue.py (1)
apiserver/plane/app/views/issue/base.py (2) (2)
  • SearchAPIEndpoint (1218-1259)
  • SearchSingleValueAPI (1261-1296)
apiserver/plane/app/views/view/base.py (5)
apiserver/plane/db/models/issue.py (9) (9)
  • IssueCustomProperty (726-747)
  • Meta (190-194)
  • Meta (279-283)
  • Meta (311-323)
  • Meta (339-351)
  • Meta (367-379)
  • Meta (393-397)
  • Meta (427-431)
  • Meta (477-481)
apiserver/plane/utils/issue_filters.py (1) (1)
  • issue_filters (611-649)
apiserver/plane/app/views/issue/base.py (10) (10)
  • IssueCustomPropertySerializer (77-88)
  • Meta (78-88)
  • get_queryset (235-286)
  • get_queryset (857-900)
  • get (92-211)
  • get (804-809)
  • get (839-853)
  • get (1030-1123)
  • get (1221-1259)
  • get (1265-1296)
apiserver/plane/app/views/base.py (2) (2)
  • fields (148-154)
  • fields (253-259)
apiserver/plane/app/views/workspace/draft.py (1) (1)
  • get_queryset (50-103)
apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (5)
apiserver/plane/db/migrations/0085_remove_issuecustomproperty_project_custom_property_and_more.py (1) (1)
  • Migration (6-22)
apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (1) (1)
  • Migration (7-24)
apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1) (1)
  • Migration (9-48)
apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1) (1)
  • Migration (7-19)
apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1) (1)
  • Migration (6-18)
apiserver/plane/api/views/webhook.py (1)
apiserver/plane/api/serializers/webhook.py (2) (2)
  • WebhookSerializer (15-128)
  • WebhookLogSerializer (131-135)
apiserver/plane/api/views/issue.py (4)
apiserver/plane/api/serializers/issue_type.py (1) (1)
  • IssueTypeSerializer (7-24)
apiserver/plane/db/models/issue_type.py (1) (1)
  • IssueType (10-32)
apiserver/plane/utils/issue_filters.py (1) (1)
  • issue_filters (611-649)
apiserver/plane/api/views/base.py (1) (1)
  • project_id (199-208)
apiserver/plane/app/views/issue/base.py (2)
apiserver/plane/app/permissions/project.py (3) (3)
  • ProjectEntityPermission (83-116)
  • ProjectLitePermission (155-168)
  • ProjectMemberPermission (47-80)
apiserver/plane/api/serializers/issue.py (1) (1)
  • IssueCustomPropertySerializer (43-54)
apiserver/plane/authentication/views/app/magic.py (3)
apiserver/plane/api/serializers/project.py (2) (2)
  • ProjectSerializer (15-88)
  • create (66-88)
apiserver/plane/api/views/base.py (1) (1)
  • BaseAPIView (40-226)
apiserver/plane/api/views/project.py (1) (1)
  • create_project (34-122)
🪛 Ruff (0.8.2)
apiserver/plane/app/permissions/__init__.py

14-14: .project.ProjectEntityGuestPermission imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/db/models/__init__.py

44-44: .issue.IssueCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


71-71: .project.ProjectPublicMember imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


115-115: .issue_type.IssueType imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


115-115: .issue_type.IssueTypeCustomProperty imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/serializers/__init__.py

14-14: .issue_type.IssueTypeSerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


14-14: .issue_type.IssueTypeCustomPropertySerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/views/__init__.py

2-2: .project.ProjectAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


3-3: .project.ProjectArchiveUnarchiveAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


15-15: .issue.IssueAttachmentEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


17-17: .issue_type.IssueTypeAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


17-17: .issue_type.IssueTypeCustomPropertyAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


18-18: .attachment.IssueAttachmentV2Endpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


36-36: .search.GlobalSearchEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


39-39: .webhook.WebhookEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


39-39: .webhook.WebhookLogsEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


40-40: .webhook.WebhookSecretRegenerateEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/serializers/project.py

12-12: .issue_type.IssueTypeSerializer imported but unused

Remove unused import: .issue_type.IssueTypeSerializer

(F401)

apiserver/plane/api/views/base.py

89-89: Multiple statements on one line (semicolon)

(E702)

apiserver/plane/bgtasks/webhook_task.py

407-407: Local variable event_data is assigned to but never used

Remove assignment to unused variable event_data

(F841)


408-408: Local variable actor_data is assigned to but never used

Remove assignment to unused variable actor_data

(F841)

apiserver/plane/api/views/issue_type.py

8-8: django.db.models.Case imported but unused

Remove unused import

(F401)


9-9: django.db.models.CharField imported but unused

Remove unused import

(F401)


10-10: django.db.models.Exists imported but unused

Remove unused import

(F401)


11-11: django.db.models.F imported but unused

Remove unused import

(F401)


12-12: django.db.models.Func imported but unused

Remove unused import

(F401)


13-13: django.db.models.Max imported but unused

Remove unused import

(F401)


14-14: django.db.models.OuterRef imported but unused

Remove unused import

(F401)


15-15: django.db.models.Q imported but unused

Remove unused import

(F401)


16-16: django.db.models.Value imported but unused

Remove unused import

(F401)


17-17: django.db.models.When imported but unused

Remove unused import

(F401)


18-18: django.db.models.Subquery imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.MultiPartParser imported but unused

Remove unused import

(F401)


25-25: rest_framework.parsers.FormParser imported but unused

Remove unused import

(F401)


35-35: plane.bgtasks.issue_activities_task.issue_activity imported but unused

Remove unused import: plane.bgtasks.issue_activities_task.issue_activity

(F401)


140-140: Local variable requested_data is assigned to but never used

Remove assignment to unused variable requested_data

(F841)


141-141: Local variable current_instance is assigned to but never used

Remove assignment to unused variable current_instance

(F841)


142-142: Undefined name issue_comment

(F821)


162-162: Undefined name issue_comment

(F821)


200-200: Local variable workspace is assigned to but never used

Remove assignment to unused variable workspace

(F841)


236-236: Undefined name ValidationError

(F821)

apiserver/plane/api/serializers/issue_type.py

1-1: rest_framework.serializers imported but unused

Remove unused import: rest_framework.serializers

(F401)

apiserver/plane/api/urls/issue.py

10-10: plane.api.views.IssueTypeAPIEndpoint imported but unused

Remove unused import: plane.api.views.IssueTypeAPIEndpoint

(F401)

apiserver/plane/api/views/project.py

253-253: Undefined name user

(F821)

apiserver/plane/utils/issue_filters.py

6-6: django.db.models.Q imported but unused

Remove unused import: django.db.models.Q

(F401)

apiserver/plane/app/views/__init__.py

135-135: .issue.base.SearchAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


136-136: .issue.base.SearchSingleValueAPI imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/api/serializers/issue.py

38-38: Local variable uuid_obj is assigned to but never used

Remove assignment to unused variable uuid_obj

(F841)

apiserver/plane/api/views/attachment.py

9-9: plane.app.permissions.allow_permission imported but unused

Remove unused import: plane.app.permissions.allow_permission

(F401)

apiserver/plane/app/views/view/base.py

3-3: django.db.models.Count imported but unused

Remove unused import: django.db.models.Count

(F401)

apiserver/plane/api/views/issue.py

36-36: plane.api.serializers.IssueTypeSerializer imported but unused

Remove unused import: plane.api.serializers.IssueTypeSerializer

(F401)


55-55: plane.db.models.IssueType imported but unused

Remove unused import: plane.db.models.IssueType

(F401)

apiserver/plane/app/views/issue/base.py

60-60: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP imported but unused

Remove unused import: plane.utils.constants.ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP

(F401)


72-72: plane.app.permissions.ProjectEntityPermission imported but unused

Remove unused import

(F401)


73-73: plane.app.permissions.ProjectLitePermission imported but unused

Remove unused import

(F401)


74-74: plane.app.permissions.ProjectMemberPermission imported but unused

Remove unused import

(F401)

apiserver/plane/authentication/views/app/magic.py

290-290: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)

🪛 Biome (1.9.4)
web/core/components/issues/issue-layouts/filters/header/filters/custom-properties.tsx

[error] 121-121: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx

[error] 249-249: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (125)
apiserver/plane/app/urls/issue.py (1)

27-28: New imports added for search functionality

The new imports for SearchAPIEndpoint and SearchSingleValueAPI align with the additions to the URL patterns below. These endpoints will enhance search capabilities for issue-related data.

apiserver/plane/app/views/__init__.py (1)

135-136:

Details

❓ Verification inconclusive

Check for unused imports

The static analysis indicates that SearchAPIEndpoint and SearchSingleValueAPI are imported but not used within this file. If these imports are meant to be re-exported for use in other modules, consider adding them to an __all__ list. Otherwise, they should be removed to prevent cluttering the namespace.


🏁 Script executed:

#!/bin/bash
# Check if these imports are actually used elsewhere in the codebase

echo "Checking for imports of SearchAPIEndpoint and SearchSingleValueAPI from plane.app.views"
rg -A 2 -B 2 "from plane.app.views import.*SearchAPIEndpoint|from plane.app.views import.*SearchSingleValueAPI" --type py

Length of output: 308


Verify Unused Imports in apiserver/plane/app/views/init.py

The static analysis flagged that SearchAPIEndpoint and SearchSingleValueAPI are imported but not used within this file. Our initial search for their usage via grep produced no results. This suggests that they may be unused—unless these imports are intentionally meant for re-export in which case they should be added to an explicit __all__ list. Please manually verify if these symbols are indeed utilized elsewhere (for example, by consumers of the plane.app.views module) or if they can be safely removed.

  • Location: apiserver/plane/app/views/__init__.py (Lines 135-136)
  • Action Items:
    • If these imports are intended for global access, add them to an __all__ list.
    • Otherwise, remove the imports to reduce namespace clutter.
🧰 Tools
🪛 Ruff (0.8.2)

135-135: .issue.base.SearchAPIEndpoint imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


136-136: .issue.base.SearchSingleValueAPI imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

web/Dockerfile.web (1)

105-107: LGTM - Docker configuration improved

The addition of the EXPOSE 3000 directive and the CMD instruction properly configures the container to expose its port and specifies how to start the application. This is a good practice for Docker containers.

admin/Dockerfile.admin (1)

86-88: Docker container configuration improvements added

The addition of EXPOSE 3000 and CMD node admin/server.js admin instructions properly configures the Docker container by:

  1. Explicitly exposing the port used by the application
  2. Defining the default command to start the admin server

These changes improve the container's self-sufficiency and follow Docker best practices.

deploy/selfhost/install.sh (1)

185-185:

Details

❓ Verification inconclusive

Repository URL changed from original project to a fork

The code changes the clone URL from makeplane/plane to shipsy/plane, which points to a fork instead of the original repository. This may cause divergence from upstream if not properly maintained.

Is this repository change intentional? If it's for organization-specific customizations, please ensure you have a process to keep the fork updated with upstream changes.


#!/bin/bash
# Verify repository URL usage across the repository

echo "Checking the repository URL in deploy/selfhost/install.sh..."
grep -R "REPO=https://github.com/shipsy/plane.git" deploy/selfhost/install.sh

echo "Searching for references to the original repository (makeplane/plane)..."
rg "github.com/makeplane/plane" -n .

echo "Searching for references to the new repository (shipsy/plane)..."
rg "github.com/shipsy/plane.git" -n .

Repository URL Change Verification – ACTION REQUIRED
In deploy/selfhost/install.sh (line 185), the repository URL has been updated to https://github.com/shipsy/plane.git. This change replaces the original repository (github.com/makeplane/plane) with a fork. Please confirm if this change was intentional. If this is an organization-specific customization, ensure that you have a process to keep the fork updated with upstream changes to prevent divergence.

web/ce/constants/project/settings/features.tsx (1)

87-88: Time Tracking feature now available and enabled for all users

The Time Tracking feature has been changed from a premium feature (isPro: true) to a standard feature (isPro: false) and is now enabled by default (isEnabled: true). This change makes time tracking functionality accessible to all users regardless of their subscription plan.

apiserver/plane/api/urls/project.py (2)

20-21: Consistent update to string type parameter

This change from <uuid:project_id> to <str:project_id> is consistent with the previous pattern change. This standardization across URL patterns improves consistency in the API's handling of project identifiers.


15-16:

Details

❓ Verification inconclusive

Verify the impact of changing UUID to string type parameter

The URL pattern has been modified to accept a string type (<str:pk>) instead of a UUID type (<uuid:pk>). While this change aligns with similar modifications in other URL patterns, we should consider the validation implications.


🏁 Script executed:

#!/bin/bash
# Check if the view has proper validation for string-based project IDs

# Look for validation in ProjectAPIEndpoint
rg -A 10 "class ProjectAPIEndpoint" apiserver/plane/api/views/

# Check if there are any UUID validation functions
rg -A 3 "def is_uuid" apiserver

Length of output: 1084


Subject: Confirm Behavior of <str:pk> in ProjectAPIEndpoint

It appears that while the URL pattern change to <str:pk> aligns with similar patterns elsewhere, the current implementation of ProjectAPIEndpoint does not include any explicit validation for ensuring that the supplied pk conforms to a UUID format. Although we do have an is_uuid helper defined in apiserver/plane/api/serializers/issue.py, its usage is not evident within the endpoint for projects.

  • Verify that the ProjectSerializer or model layer properly handles conversion or raises meaningful errors if an invalid UUID string is provided.
  • Consider reusing existing validation (e.g., the is_uuid function) if stricter UUID format enforcement is required.
  • Confirm through tests that the API behaves as expected with both valid and malformed IDs.
web/core/hooks/use-group-dragndrop.ts (1)

64-65: Good defensive programming by explicit type conversion

Converting moduleKey and cycleKey to strings before checking if they exist in Object.keys(data) is a good practice. This ensures correct type comparison regardless of the underlying type of the keys.

This change prevents potential type mismatches when comparing keys, enhancing the robustness of the code.

apiserver/plane/db/migrations/0087_issuecustomproperty_issue_type_and_more.py (2)

19-23: Increased flexibility for the value field

Modifying the value field to allow blank and null values with a max length of 255 characters provides more flexibility for custom properties. This is appropriate for fields that may not always have a value.


14-18:

Details

✅ Verification successful

Note multiple subsequent migrations modifying this field

This migration adds a new issue_type field as a foreign key to the issuetype model. Be aware that subsequent migrations (0088, 0089, 0090) further modify this field by changing its reference and name.


🏁 Script executed:

#!/bin/bash
# Check the sequence of migrations affecting this field

# List all migrations that modify the issue_type field
rg -A 3 -B 3 "issue_type" apiserver/plane/db/migrations/*.py

# Check the current model definition
rg -A 5 "class IssueCustomProperty" apiserver/plane/db/models

Length of output: 28089


Attention: Multiple Sequential Migrations Impacting issue_type Field

This migration (0087) adds the issue_type field as a foreign key on the IssueCustomProperty model pointing to db.issuetype. Note that subsequent migrations further modify this field:

  • 0088_alter_issuecustomproperty_issue_type.py: Alters the field to reference db.issuetypecustomproperty and updates the related_name to issue_type_custom_property.
  • 0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py: Renames the field from issue_type to issue_type_custom_proerty.
  • 0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py: Renames the field from issue_type_custom_proerty to issue_type_custom_property.

Please verify that these sequential modifications are intentional and correctly reflect the desired evolution of the data model.

apiserver/plane/db/models/base.py (1)

36-38:

Details

❓ Verification inconclusive

Important behavior change in created_by assignment

The updated logic now only sets created_by if it's currently None. This preserves any existing value rather than always overwriting with the current user. This is a significant behavior change that may affect how created_by is handled throughout the application.


🏁 Script executed:

#!/bin/bash
# Check for places that might rely on the previous behavior

# Look for code that explicitly sets created_by before saving
rg "created_by.*save" --glob "*.py" apiserver/

# Look for tests that may verify created_by behavior
rg "created_by.*assert" --glob "*test*.py" apiserver/

Length of output: 331


Attention: Confirm the Updated created_by Behavior

The change now only sets created_by when it isn’t already defined, preserving any preexisting value. Our quick search identified comments in the following files that reference updating created_by (which might imply an expectation of the previous behavior):

  • apiserver/plane/api/views/issue_type.py
  • apiserver/plane/api/views/issue.py

No test assertions directly verifying the old unconditional assignment of created_by were found. Please manually verify that this change doesn’t break any workflows or assumptions in these parts of the application.

web/core/components/workspace/sidebar/help-section.tsx (2)

56-56: Layout alignment has changed in non-collapsed sidebar.

The CSS class changed from "justify-evenly" to "justify-end ml-auto", which will align the controls to the right end of the sidebar instead of distributing them evenly across the space.


43-69:

Details

❓ Verification inconclusive

Significant simplification of the sidebar help section.

The component has been heavily simplified by removing multiple elements:

  • Removed CustomMenu component and its associated options (documentation, messaging support, etc.)
  • Removed WorkspaceEditionBadge component
  • Removed various help resources and links

This change streamlines the UI but potentially limits quick access to help resources for users.


🏁 Script executed:

#!/bin/bash
# Check if there are any other help resources available elsewhere in the application
rg -B 2 -A 2 "documentation|support|help" --type tsx --type jsx ./web/

Length of output: 100


Next Steps: Verify Additional Help References

The simplified sidebar help section removes several help elements (CustomMenu, WorkspaceEditionBadge, and associated links). However, we must confirm that no alternate help resources (e.g. documentation, support links) are available elsewhere in the codebase. The initial search command failed due to incorrect file type handling. Please run the following updated shell script to search all *.tsx and *.jsx files for any help-related references:

#!/bin/bash
# Search for references to documentation, support, or help resources in TSX/JSX files
rg -g "*.{tsx,jsx}" -B2 -A2 "documentation|support|help" ./web/

If this search produces no output, it confirms that these help resources are not used elsewhere in the application. Otherwise, please review any findings to ensure that the removal of the help elements does not unintentionally limit user access.

web/app/workspace-invitations/page.tsx (2)

7-7: Removed Star icon import.

The Star icon import has been removed as it's no longer used in the component.


114-115: GitHub star link has been removed.

The EmptySpaceItem component with the Star icon that provided a link to star the project on GitHub has been removed. This appears to be part of a broader pattern of simplifying the UI and removing external promotion links.

apiserver/plane/api/urls/state.py (2)

12-12:

Details

✅ Verification successful

API URL pattern changed: project_id type changed from UUID to string.

Similar to line 7, the URL pattern for accessing a specific state has been modified to accept project_id as a string rather than a UUID, while maintaining state_id as UUID.

This change should be verified against the database model to ensure that string project IDs are properly handled throughout the application.


🏁 Script executed:

#!/bin/bash
# Check the State model definition to see how project_id is defined
rg -A 10 "class State" ./apiserver/

Length of output: 6648


Action required: Validate consistency of project_id as a string across the codebase

After verifying the code:

  • The URL pattern now accepts project_id as a string, as seen in:
    • The URL in apiserver/plane/api/urls/state.py.
    • Serializer definitions (e.g., in apiserver/plane/app/serializers/state.py).
    • View filtering (e.g., in apiserver/plane/app/views/state/base.py).
  • The usage of project_id as a string is consistent with how the endpoints extract and filter data. Although the State model (likely inheriting project_id from a base model) wasn’t directly inspected here, all observable interactions correctly expect a string.

No further modifications are required.


7-7:

Details

❓ Verification inconclusive

API URL pattern changed: project_id type changed from UUID to string.

The URL pattern for accessing states has been modified to accept project_id as a string rather than a UUID. This change increases flexibility but may impact type validation.


🏁 Script executed:

#!/bin/bash
# Check if this change is consistent across other URL patterns in the codebase
echo "Checking for other URL patterns with project_id..."
rg -A 1 "projects/<(uuid|str):project_id>" --type py ./apiserver/

# Check if the StateAPIEndpoint view properly handles string project_ids
echo "Checking StateAPIEndpoint implementation..."
rg -A 5 "def get_queryset" ./apiserver/plane/api/views/state.py

# Check for any type validation or conversion of project_id in the view
rg "project_id\s*=" ./apiserver/plane/api/views/state.py

Length of output: 29609


Action Required: Verify Consistency of project_id Type Change

The state API URL now accepts a string for project_id, and the corresponding view (StateAPIEndpoint) processes it directly without converting it to a UUID. While this change increases flexibility for state endpoints, the verification shows that most other endpoints continue to use <uuid:project_id>. Please review the following:

  • File: apiserver/plane/api/urls/state.py
    • The URL patterns changed to "workspaces/<str:slug>/projects/<str:project_id>/states/" and its detailed state endpoint still uses <uuid:state_id>.
  • File: apiserver/plane/api/views/state.py
    • The get_queryset method filters using the raw value of project_id from kwargs without any type conversion.
  • Observation:
    • Numerous other API endpoints in the codebase continue to expect project_id as a UUID. This inconsistency may introduce type validation issues or unexpected behavior if downstream components expect a UUID.

Please verify whether this divergence is intentional. If so, consider whether additional type validation or conversion is needed for the state endpoints—or if similar changes should be made in other parts of the API for consistency.

docker-compose-local.yml (3)

23-24: Exposing MinIO console port.

Added port mapping to expose MinIO console (9090) to the host, which allows direct access to the MinIO web interface for managing storage during local development.


38-39: PostgreSQL port exposed to host.

Added port mapping to expose PostgreSQL (5432) to the host, allowing direct database access from the host machine using database clients.


115-116: Interactive terminal enabled for API service.

Added stdin_open: true and tty: true configurations to enable interactive terminal access for the API service. This improves development experience by allowing direct interaction with the container.

web/core/constants/spreadsheet.ts (4)

14-14: New import for the Tags icon added.

The Tags icon from lucide-react has been added to support the new property icons.


36-36: SpreadsheetStandardPropertyColumn now used for standard properties.

Using the existing SpreadsheetStandardPropertyColumn component is appropriate for the new standard properties.


181-234: New standard properties added to SPREADSHEET_PROPERTY_DETAILS.

The implementation follows the established pattern for property details, with appropriate titles, sort options, and icons. This provides consistent UI handling for the new properties.


252-257: New property keys added to SPREADSHEET_PROPERTY_LIST.

All new standard properties have been properly added to the property list, ensuring they'll be available for display in the spreadsheet view.

web/core/constants/dashboard.ts (1)

261-293: Sidebar menu items commented out rather than removed.

The PR has commented out "projects", "active-cycles", and "analytics" menu items while leaving "all-issues" active. This approach preserves the code for potential future reactivation but might lead to confusion about which features are currently supported.

Was this change intentional? If these menu items are no longer needed, consider removing the code entirely rather than commenting it out for cleaner maintenance. If this is a temporary change for testing, please add a TODO comment explaining the intent.

docker-compose.yml (3)

10-13: Added volume mappings for development.

The volume mappings allow mounting local directories into the container, which is useful for development but should be reviewed before production deployment.


13-15: Changed command and commented out dependencies.

Replacing the Node.js server command with tail -f and commenting out dependencies suggests this is intended for development use only.

This configuration will keep the container running but won't start the actual web service. Ensure this change is only meant for development and not accidentally committed for production use.


17-183: Commented out most services in docker-compose.

Most services and volumes have been commented out rather than removed.

Is this change intended for development purposes only? If so, consider creating a separate docker-compose.dev.yml file instead of modifying the main configuration file. If these services are no longer needed, it would be cleaner to remove them entirely rather than commenting them out.

web/core/components/issues/index.ts (1)

15-15: Added export for custom properties module.

This change exports all entities from the custom properties module, making them available to consumers of the issues components.

web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts (1)

15-15: New component export looks good.

The addition of the standard-property-column export follows the existing pattern and convention of the file.

apiserver/templates/emails/exports/analytics.html (1)

1-7: Formatting improvements look good.

The HTML formatting changes improve readability while maintaining the same content and functionality.

web/core/components/issues/issue-layouts/filters/applied-filters/index.ts (1)

12-12: New additional-properties export looks good.

The addition of this export maintains consistency with the existing pattern in the file and integrates well with the filter system.

apiserver/plane/api/serializers/__init__.py (1)

14-14: Exposing new serializers for issue type functionality.

The addition of these serializers aligns with the PR's objectives to enhance issue custom properties support. They will be available for import by other modules that need to serialize or deserialize issue types and their custom properties.

🧰 Tools
🪛 Ruff (0.8.2)

14-14: .issue_type.IssueTypeSerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


14-14: .issue_type.IssueTypeCustomPropertySerializer imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/app/permissions/__init__.py (1)

14-14: Addition of guest permission for enhanced access control.

This change exposes the ProjectEntityGuestPermission class, which allows guest users to view project entities - an important enhancement for supporting the new display properties functionality while maintaining proper access controls.

🧰 Tools
🪛 Ruff (0.8.2)

14-14: .project.ProjectEntityGuestPermission imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

apiserver/plane/db/migrations/0090_rename_issue_type_custom_proerty_issuecustomproperty_issue_type_custom_property.py (1)

1-18: Fixing field name typo in the database schema.

This migration correctly addresses a typo in the field name by renaming issue_type_custom_proerty to issue_type_custom_property. This is a good fix to ensure consistency and proper naming in the database schema.

web/core/constants/analytics.ts (1)

57-57: Fixed array syntax by removing trailing comma.

This small syntax correction improves code quality by replacing the trailing comma with a proper closing brace for the last object in the ANALYTICS_X_AXIS_VALUES array.

apiserver/plane/authentication/utils/redirection_path.py (1)

9-10:

Details

❓ Verification inconclusive

Redirection to onboarding flow has been removed.

The code that previously redirected users to the onboarding path when they were not onboarded has been commented out. This change alters the user flow after authentication, allowing all users to bypass the onboarding step.


🏁 Script executed:

#!/bin/bash
# Check if there are any other references to onboarding flows that might be affected
echo "Checking for other references to onboarding flows..."
rg "is_onboarded" --type py -A 2 -B 2

Length of output: 6766


Action Required: Verify Consistency of Onboarding Flow Changes

The redirection logic in apiserver/plane/authentication/utils/redirection_path.py (lines 9-10) that previously sent users to the onboarding process when profile.is_onboarded was false is now commented out. This change means users will no longer be redirected to onboarding after authentication. However, several other parts of the codebase still reference and update the is_onboarded status (e.g., in apiserver/plane/api/views/member.py, apiserver/plane/app/views/user/base.py, apiserver/plane/authentication/views/app/magic.py, and even within migration scripts).

  • Confirm that bypassing the onboarding step here is an intentional part of the overall workflow change.
  • Verify that any related logic in the other files handling the is_onboarded state is consistent with this update.
  • Ensure that the removal of redirection does not leave orphaned or contradictory onboarding logic elsewhere in the application, especially considering updates in the database migrations.
web/core/components/issues/issue-layouts/filters/header/filters/index.ts (1)

14-14: New additional-properties filter component has been integrated.

This export statement makes the additional-properties filter components available in the filters module, expanding the filtering options for issues.

apiserver/plane/utils/grouper.py (1)

97-102:

Details

❓ Verification inconclusive

New shipping-related fields added to issue results.

Several new fields have been added to the required_fields list for issue results: hub_code, vendor_code, customer_code, worker_code, reference_number, and trip_reference_number. These logistics-related fields enable new grouping and filtering capabilities for issues.


🏁 Script executed:

#!/bin/bash
# Check if these fields are defined in the Issue model
echo "Checking Issue model for new fields..."
rg -A 3 -B 3 "class Issue" --type py

# Check if the fields are being used in serializers
echo "Checking serializers for new fields..."
rg "hub_code|vendor_code|customer_code|worker_code|reference_number|trip_reference_number" --type py --glob "*serializers*.py"

Length of output: 51022


Below is a new verification shell script to re-check the usage of the new shipping-related fields across the codebase (including within files that contain “serializer” in their filename). Please run the script and manually inspect the output to confirm that these fields are properly integrated in the Issue model and related serializers.

#!/bin/bash
echo "Searching for new shipping fields in all Python files..."
rg "hub_code|vendor_code|customer_code|worker_code|reference_number|trip_reference_number" --type py

echo "Searching for new shipping fields in files with 'serializer' in the filename..."
rg "hub_code|vendor_code|customer_code|worker_code|reference_number|trip_reference_number" --type py --glob "*serializer*.py"

Rewritten Review Comment – New Shipping Fields Integration

The new shipping-related fields (hub_code, vendor_code, customer_code, worker_code, reference_number, and trip_reference_number) have been added to the required_fields list in apiserver/plane/utils/grouper.py (lines 97–102) to enable enhanced grouping and filtering for issue results.

Action Items:

  • Please verify that these new fields are correctly defined or mapped in the Issue model (e.g., in apiserver/plane/db/models/issue.py).
  • Confirm that any necessary serializers (look in files with “serializer” in their names) are updated to handle these fields if the use case requires. Note that the previous search for these fields in serializer files returned no matches—this may be due to filtering issues, so manual verification is advised.

Once the above points are verified, we can be confident that the integration of the new fields is complete.

apiserver/plane/db/migrations/0089_rename_issue_type_issuecustomproperty_issue_type_custom_proerty.py (1)

13-17: Typo in field name will need a follow-up correction.

The field is being renamed to issue_type_custom_proerty which contains a typo (missing 'p' in 'property').

I see in the relevant code snippets that this is addressed in migration 0090, which correctly renames it to issue_type_custom_property. This approach of fixing typos through sequential migrations is appropriate for production deployments.

apiserver/plane/db/migrations/0088_alter_issuecustomproperty_issue_type.py (1)

14-18: ForeignKey relationship target has been changed.

The migration changes the issue_type field to reference issuetypecustomproperty model instead of issuetype (as defined in migration 0087). The related_name is also changed from 'custom_issue_type' to 'issue_type_custom_property'.

This change appears to be part of a broader restructuring of the data model to better support custom properties for issues. The change is well structured with appropriate null/blank handling and SET_NULL for the on_delete behavior.

apiserver/requirements/base.txt (2)

13-13: New dependency added.

The python-dotenv package has been added, which is useful for loading environment variables from .env files.

This is a good addition that improves configuration management by allowing environment variables to be loaded from .env files.


33-33: Package version update.

The django-storages package has been updated from 1.14.2 to 1.14.4.

This is a minor version update that likely includes bug fixes or small improvements.

web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx (1)

45-47: Appropriate enhancement passing property information to Column component

Passing the property key to the Column component is a good improvement that allows the component to be aware of which property it's rendering. This enables more flexible and property-specific behavior inside the Column component.

web/helpers/issue.helper.ts (1)

310-315: LGTM: Additional properties implementation looks good

The addition of these standard properties (hub_code, customer_code, etc.) follows the existing pattern for display properties, ensuring consistency with the rest of the codebase.

web/core/components/issues/issue-layouts/filters/applied-filters/additional-properties.tsx (1)

8-12: LGTM: Props interface is well-defined

The Props interface clearly defines the expected types for the component parameters, making the component's API clear and easy to understand.

apiserver/plane/settings/storage.py (1)

22-26: Review the file overwrite implementation

The method conditionally bypasses the parent's get_available_name method when file_overwrite is True, which could lead to unintentional file overwrites.

Verify that this behavior is desired and that there are controls elsewhere to prevent critical files from being accidentally overwritten.

apiserver/plane/api/serializers/issue_type.py (1)

7-25: Well-structured serializer implementation

The IssueTypeSerializer correctly handles workspace context and defines appropriate read-only and excluded fields.

web/core/services/workspace.service.ts (1)

281-290: LGTM: Adds method to fetch custom properties for issues

This method follows the established pattern in the service, providing a clean interface to retrieve custom properties for issues at the workspace level.

apiserver/plane/middleware/api_log_middleware.py (1)

12-17:

Details

❓ Verification inconclusive

Rewriting request path and updating resolver match may have unintended side effects

The code is modifying the request path and resolver match after the response has already been generated. This means the modification won't affect the current request processing but might impact subsequent middleware or request handling. Is this intentional?


🏁 Script executed:

#!/bin/bash
# Check if this middleware is being executed in the expected order
fd --type f --extension py "middleware" | xargs grep -l "APITokenLogMiddleware" | xargs cat

Length of output: 3066


Attention: Confirm Intentional Post-Response Request Modification

It appears that the middleware intentionally rewrites the request path and updates the resolver match after calling get_response(). This design means:

  • The modifications are not used to influence the response since they occur post-response generation.
  • The changes are applied primarily for logging purposes via the subsequent process_request call.
  • If any later middleware or future logic depends on the original request state, this post-response modification could lead to unintended side effects.

Please verify that these modifications are indeed intended only for enriching the log data and that no downstream processing relies on the original request path or resolver match.

apiserver/plane/app/permissions/project.py (2)

18-19: LGTM: Bypass permission checks for superusers

Adding superuser permission bypasses is a standard pattern that simplifies administration tasks.

Also applies to: 53-54, 88-89, 124-125, 160-161


33-33: LGTM: Added Guest role to permission checks

Extending permissions to include the Guest role in appropriate filters is a good improvement for flexibility in access control.

Also applies to: 68-68, 77-77, 113-113, 149-149

apiserver/plane/api/urls/__init__.py (1)

4-4: No issues found for the import of issue_type_patterns.

demo.Jenkinsfile (2)

1-1: Pin your Jenkins library reference to a stable version instead of using master.
This helps avoid unexpected breakages from upstream changes.

- @Library('jenkins-library@master') _
+ @Library('jenkins-library@v1.0.0') _

93-127: Parallel Docker builds look good.
No immediate issues with the approach or arguments for building images.

apiserver/plane/db/migrations/0086_issuetypecustomproperty_delete_projectcustomproperty_and_more.py (1)

24-24: Validate and handle large JSON payloads in the value field.
JSONField can store arbitrarily large objects, so ensure upstream components prevent oversized or malicious data.

web/core/constants/issue.ts (1)

531-541: LGTM! Consistent implementation of additional properties

The implementation of ISSUE_ADDITIONAL_PROPERTIES aligns well with the other constants in the file and properly defines the key-value mapping for the new custom properties.

web/core/components/issues/custom-properties.tsx (2)

3-7: LGTM! Well-structured type definition

The type definition for CustomProperty is clear and concise, properly capturing the necessary properties for custom property objects.


13-33: Well-implemented component with proper edge case handling

The component correctly checks if the input is a valid array and has content before rendering, preventing potential rendering issues with invalid data. The UI structure with appropriate styling enhances readability.

apiserver/plane/api/urls/issue.py (2)

74-78: LGTM! Good addition of attachment endpoint

Adding the new endpoint for issue attachments with a specific ID is a good addition for more granular control over attachments.


20-28:

Details

❓ Verification inconclusive

Verify handling of string project IDs throughout the codebase

The change from <uuid:project_id> to <str:project_id> is significant and might affect the behavior of existing endpoints. Ensure that the view functions (such as IssueAPIEndpoint) are updated to handle string project IDs correctly.


🏁 Script executed:

#!/bin/bash
# Description: Check if IssueAPIEndpoint handles string project IDs correctly

# Check how project_id is handled in the IssueAPIEndpoint view
rg -n "project_id" --type py "apiserver/plane/api/views/issue.py" | grep -B 5 -A 5 "IssueAPIEndpoint" 

# Check for any type conversions or validations of project_id
rg -n "project_id.*uuid|uuid.*project_id" --type py "apiserver/plane/api/views/issue.py"

Length of output: 186


I'm not seeing any output from the initial verification, so I’d like to dig a bit deeper into how the IssueAPIEndpoint (in the file apiserver/plane/api/views/issue.py) handles the project_id parameter. The following shell script will:

• Identify the file(s) where IssueAPIEndpoint is defined.
• Search those files for any references to project_id to check if there's any explicit handling, conversion, or validation.

Please run the script below and share its output for further review:

Once we have the output from this script, we can better verify if there’s any logic (or lack thereof) for handling string project IDs.
[request_verification]


🏁 Script executed:

#!/bin/bash
# Step 1: Identify the file(s) where IssueAPIEndpoint is defined
issue_files=$(rg -l "class IssueAPIEndpoint" --type py)
echo "IssueAPIEndpoint defined in:"
echo "$issue_files"
echo ""

# Step 2: For each file that defines IssueAPIEndpoint, search for references to 'project_id'
for file in $issue_files; do
    echo "---- Searching in file: $file ----"
    rg -n "project_id" --type py "$file"
    echo ""
done

Length of output: 4860


Action Required: Verify consistent handling of string project IDs in IssueAPIEndpoint

The recent changes switching from <uuid:project_id> to <str:project_id> require careful validation. In apiserver/plane/api/views/issue.py, we observed that some endpoints explicitly convert project_id using str(project_id) (e.g., lines 367, 422, 476, etc.) while others, such as those invoking Project.objects.get(pk=project_id) (e.g., lines 311 and 377), pass the parameter directly. Please ensure that:

  • Database lookups and any associated logic properly handle project IDs as strings.
  • There is consistent and intentional conversion or validation of project_id where required.
  • The behavior of endpoints aligns with the intended change, avoiding any regression or unexpected results from the modified URL converter.

Kindly review and verify that all endpoints process the string project ID correctly according to the new design.

web/core/components/issues/peek-overview/properties.tsx (3)

33-34: LGTM! Clean import statements

The import of IssueWorklogProperty and ISSUE_ADDITIONAL_PROPERTIES are appropriate and follow the project's import structure conventions.


306-316: Well-structured rendering of additional properties

The code properly maps through ISSUE_ADDITIONAL_PROPERTIES and conditionally renders each property when it exists in the issue object. The UI structure is consistent with other property displays in the component.


318-318: Good integration of the CustomProperties component

The integration of the CustomProperties component at the end of the properties section ensures a clean separation between standard and custom properties while providing a consistent UI experience.

apiserver/plane/api/views/base.py (5)

11-11: Imports look correct.

The new imports Project and User from plane.db.models are appropriately used in the new helper methods below. No concerns here.


115-118: Confirm intended return flow within dispatch.

After handling kwargs, user creation, and workspace checks, the function calls super().dispatch, then returns the response. Ensure that if an exception occurs later, the logic gracefully returns an appropriate response rather than an exception object.


129-144: Review user assignment logic.

The check_kwargs function automatically adds an admin user to a workspace if a slug is present. Verify that this approach is safe and intentional, especially around data integrity and potential side effects of forcibly adding a superuser to every referenced workspace.


145-164: Validate user creation from headers.

While X-Assume-Role is a common design pattern for role impersonation, automatically creating a new user based on an arbitrary header could lead to unauthorized user entries in the database. Confirm that additional authentication checks (e.g. verifying the header’s authenticity) are performed elsewhere.


166-176: Check membership addition.

ensure_member_in_workspace automatically adds an authenticated user to the workspace if slug is present. Confirm that this membership addition is validated to prevent unauthorized workspace access.

web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx (3)

19-19: Good addition of additional property filters.

Using FilterAdditionalProperties significantly enhances the filter capabilities. No issues found.


25-25: Logical usage of ISSUE_ADDITIONAL_PROPERTIES.

Importing and mapping over these properties is a clean approach for dynamic filters.


30-30: Custom property filter import is well-structured.

FilterCustomProperty complements the additional properties usage.

apiserver/plane/authentication/provider/credentials/magic_code.py (4)

47-52: Reintroduce or handle missing SMTP configuration check.
By commenting out the SMTP configuration check, the code no longer raises an exception when EMAIL_HOST is undefined. This may lead to unforeseen issues if the application tries to send emails without a valid SMTP configuration. Consider reintroducing the check or adding a fallback to avoid email-related failures.


111-114: Confirm the reduced expiry from 600 to 30 seconds.
The token expiry has been shortened to 30 seconds for an existing key, while newly created keys still have a 600-second expiry. Verify that this mismatch is intentional, as it can create inconsistent user experiences.


138-138: Username retrieval looks correct.
Retrieving username from the Redis data is consistent with the newly introduced logic. This appears fine.


145-150: Verify the default password auto-set flag.
The is_password_autoset field has changed to False. Ensure this is the intended default and that it does not disrupt password onboarding flows.

apiserver/plane/api/views/project.py (1)

34-122: General creation logic looks good.
The new create_project helper cleanly organizes project creation steps (member assignment, default states, etc.). This separation can simplify testing and maintenance.

apiserver/Dockerfile.api (4)

33-34: Great addition of Flower for Celery monitoring!

Adding Flower provides valuable visibility into Celery task execution and performance.


51-52: Properly exposing ports for API and Flower

Good practice to document both services' ports in the EXPOSE directive.


54-61: Good approach for environment file configuration

Using build arguments to specify the environment file path provides flexibility for different deployment scenarios.


67-77: Well-structured conditional CMD handling

The CMD instruction effectively handles different environment types with appropriate commands for each service type. The error handling for unknown environment types is also a good practice.

packages/types/src/view-props.d.ts (1)

109-115: Consistent property additions

The new filter properties align well with the TIssueParams type additions.

packages/types/src/issues/issue.d.ts (1)

61-67: Good addition of custom property fields

Adding typed fields for custom properties enhances the extensibility of the issue model while maintaining type safety.

web/core/store/issue/helpers/issue-filter-helper.store.ts (3)

85-85: Added support for custom properties filtering in issues.

This change adds the ability to filter issues by custom properties, aligning with the new custom properties feature being implemented.


107-112: Additional filter properties for domain-specific fields.

These additional filter properties (hub_code, worker_code, customer_code, etc.) enhance the filtering capabilities for domain-specific information.


154-159: Additional filter properties for computedFilters.

Consistent implementation of the same properties in the computedFilters method, ensuring they are properly handled throughout the filtering pipeline.

apiserver/plane/app/views/view/base.py (5)

43-43: Added import for IssueCustomProperty model.

This import is required for the new custom properties functionality.


51-51: Added import for ALLOWED_CUSTOM_PROPERTY_WORKSPACE_MAP constant.

This import is used to determine which custom properties are allowed for each workspace.


63-74: New serializer for IssueCustomProperty.

The serializer correctly defines the necessary fields and read-only attributes for the custom property model.


314-328: New method for listing custom properties.

This method retrieves and groups custom properties based on allowed keys for the workspace. It's a useful addition for the frontend to know what custom properties are available.

Just ensure that this endpoint is properly documented in your API documentation.


332-338: Handle custom properties filtering in the list method.

This change properly isolates the custom_properties filter from other filters to avoid passing it directly to the Django ORM.

apiserver/plane/app/serializers/issue.py (5)

35-35: Added import for IssueCustomProperty model.

This import is required for the new custom properties serializer.


667-678: New serializer for IssueCustomProperty.

This serializer properly defines the fields and read-only properties for the custom property model, consistent with other serializers in the file.


711-716: Added new fields to the IssueSerializer.

These new fields (hub_code, customer_code, reference_number, etc.) enhance the issue model with domain-specific information.

Make sure these fields are properly documented and their purpose is clear to other developers.


754-754: Added custom_properties field to IssueDetailSerializer.

This allows the API to return custom properties when retrieving issue details.


760-760: Updated fields list with custom_properties.

Ensuring custom_properties is included in the serialized output.

apiserver/plane/db/migrations/0084_projectcustomproperty_issuecustomproperty_and_more.py (1)

1-69: Well-structured migration for custom properties models.

The migration properly creates two new models (ProjectCustomProperty and IssueCustomProperty) with appropriate fields, relationships, and constraints. The design follows Django best practices with timestamp tracking, UUID primary keys, and clear foreign key relationships.

apiserver/plane/api/views/member.py (5)

70-71: Good simplification of error message.

Removed the requirement for display_name in the error message which aligns with the validation logic.


94-94: Improved case handling for email.

Converting email to lowercase ensures case-insensitive matching when querying users, which is a good security practice.


117-143: Code refactoring improves maintainability.

Extracting user and member creation into separate methods improves code organization and readability.


150-162: Well-implemented user creation method.

The method properly handles user creation with appropriate default values for required fields.


165-180: Good extraction of member creation logic.

Breaking down workspace and project member creation into separate methods enhances code modularity.

web/core/components/issues/issue-detail/sidebar.tsx (3)

57-57: Good default handling for custom properties.

Using the nullish coalescing operator to default to an empty array prevents potential runtime errors.


304-316: Well-implemented dynamic rendering of additional properties.

The code cleanly maps through the additional properties array, checking for existence before rendering, which prevents displaying empty fields.


318-320: Clean integration of custom properties component.

Ensuring the custom properties array is properly validated before passing it to the component prevents unexpected behavior.

apiserver/plane/utils/issue_filters.py (4)

286-302: Clean implementation of username filtering.

The method properly handles filtering issues by the creator's username, supporting comma-separated values.


593-609: Good implementation of character field filtering.

The function efficiently filters issues by predefined character fields using case-insensitive matching.


624-641: Proper integration of new filter functions.

The new filter functions are correctly added to the ISSUE_FILTER dictionary, making them available for use in the filtering system.


648-648: Good addition of character field filtering.

Adding a direct call to filter_character_fields ensures these filters are always applied, regardless of the query parameters.

apiserver/plane/api/serializers/issue.py (1)

84-85: Custom properties integration looks good.

Introducing custom_properties in the serializer is a clean way to manage extended fields for issues. This approach simplifies future scalability.

apiserver/plane/bgtasks/issue_activities_task.py (1)

602-614: Dynamic verb assignment is well done.

Allowing track_assignees to receive a verb parameter makes this utility more flexible. This is a good enhancement that encourages code reuse for both "created" and "updated" actions.

apiserver/plane/app/views/issue/base.py (6)

8-8: Libraries imported for pagination
No issues found; this import is used for the custom search endpoints.


38-38: BaseSerializer import
Looks good; it's properly used by the new custom property serializer.


51-51: IssueCustomProperty model import
Essential for the newly added serializer and subquery-based filtering.


77-88: IssueCustomPropertySerializer definition
The serializer fields and read-only settings match the model as expected.


299-300: Filtering approach
Separating custom properties from other filters is a clean and readable strategy.


303-303: Chained filtering
Applying both the custom property subquery and the remaining filters is well-structured.

apiserver/plane/api/views/webhook.py (1)

1-130: Overall new file
The webhook CRUD endpoints and secret regeneration are well-structured, with clear permission checks and validations.

apiserver/plane/api/views/issue.py (2)

42-42: Guest-level permissions
Switching to ProjectEntityGuestPermission is appropriate for allowing controlled guest access.


493-497: State field rename
Renaming 'state' to 'state_id' in partial updates is a pragmatic approach that aligns with the model’s fields.

apiserver/plane/api/views/search.py (3)

50-66: Ensure consistent filtering across all returned projects.
The filtering logic is solid; however, because you filter on multiple fields with an OR (q |= Q(...)), you might retrieve more results than intended if user input is partial. Verify this aligns with your expected user experience.


101-125: Check for cyclical usage confusion.
All cycles are returned if no project_id is specified. Ensure this matches your intended behavior, as large sets of cycles might hamper performance if multiple projects exist.


151-204: Validate that module associations in pages are handled correctly.
You annotate pages with project IDs and project identifiers. If a page belongs to multiple projects, confirm that updated references in lines 167–182 don’t break page–project relations unexpectedly.

apiserver/plane/db/models/issue.py (1)

79-84: Confirm necessity of always-visible codes.
The new display properties (hub_code, customer_code, etc.) default to True. Verify whether these fields should be visible by default if they’re optional in the data model.

Comment on lines +330 to +334
path(
"workspaces/<str:slug>/projects/<str:project_id>/filed_search",
SearchSingleValueAPI.as_view(),
name="key-codes"
)
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

Multiple issues with URL pattern definition

This URL pattern has several issues:

  1. It uses the same name "key-codes" as the previous pattern, which can cause URL reversing conflicts
  2. Missing trailing slash inconsistent with Django conventions
  3. Uses <str:project_id> instead of <uuid:project_id> like other patterns
-    path(
-        "workspaces/<str:slug>/projects/<str:project_id>/filed_search",
-        SearchSingleValueAPI.as_view(),
-        name="key-codes"
-    )
+    path(
+        "workspaces/<str:slug>/projects/<uuid:project_id>/filed_search/",
+        SearchSingleValueAPI.as_view(),
+        name="field-search"
+    )
📝 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
path(
"workspaces/<str:slug>/projects/<str:project_id>/filed_search",
SearchSingleValueAPI.as_view(),
name="key-codes"
)
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/filed_search/",
SearchSingleValueAPI.as_view(),
name="field-search"
)

Comment on lines +325 to +334
path(
"workspaces/<str:slug>/projects/<str:project_id>/search",
SearchAPIEndpoint.as_view(),
name="key-codes",
),
path(
"workspaces/<str:slug>/projects/<str:project_id>/filed_search",
SearchSingleValueAPI.as_view(),
name="key-codes"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify search functionality against implementation

Based on the included code snippets, these new endpoints provide search functionality for specific fields like hub_code, worker_code, reference_number, etc. However, the route names ("key-codes") don't clearly reflect their purpose as search endpoints.


🏁 Script executed:

#!/bin/bash
# Check both implementations to verify their purpose
echo "SearchAPIEndpoint implementation:"
rg -A 10 "class SearchAPIEndpoint" --glob "apiserver/plane/app/views/issue/base.py"

echo "\nSearchSingleValueAPI implementation:"
rg -A 10 "class SearchSingleValueAPI" --glob "apiserver/plane/app/views/issue/base.py"

# Check if these fields are defined in the Issue model
echo "\nIssue model fields:"
rg "class Issue\(" -A 30 --glob "apiserver/plane/db/models/**/*.py" | grep -E "hub_code|worker_code|reference_number|trip_reference_number"

Length of output: 2434


Action Required: Refactor URL Route Names for Clarity

The implementations of both SearchAPIEndpoint and SearchSingleValueAPI clearly show that these endpoints are designed to perform search operations on issues, filtering based on fields such as hub_code, worker_code, reference_number, trip_reference_number, customer_code, and vendor_code. However, using the route name "key-codes" for both endpoints does not adequately communicate their search functionality. Please update the URL route names to reflect their purpose more clearly (for example, "search-issues" and "field-search-issues") to improve code clarity and maintainability.

Comment on lines +325 to +329
path(
"workspaces/<str:slug>/projects/<str:project_id>/search",
SearchAPIEndpoint.as_view(),
name="key-codes",
),
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Parameter type inconsistency detected

The URL pattern uses <str:project_id> while most other patterns in this file use <uuid:project_id>. This inconsistency could lead to compatibility issues if the same parameter is expected to be a UUID in the view implementation.


🏁 Script executed:

#!/bin/bash
# Check if the SearchAPIEndpoint implementation expects project_id as UUID or string
rg -A 3 "def get\(.*?slug, project_id\)" --glob "apiserver/plane/app/views/issue/base.py"

# Check if other places in the codebase handle project_id as UUID
rg -A 2 "project_id\s*=\s*.*?UUID" --type py

Length of output: 2199


Update URL pattern to use UUID converter

The URL for SearchAPIEndpoint still uses <str:project_id>, while the majority of URL patterns in this file use <uuid:project_id>. This inconsistency can lead to situations where the view ends up receiving a string instead of a UUID, which may cause type mismatches (especially when interacting with models or functions that expect a UUID). To maintain consistency and ensure proper type conversion, please update the URL pattern as follows:

  • Change
    "workspaces/<str:slug>/projects/<str:project_id>/search"
    to
    "workspaces/<str:slug>/projects/<uuid:project_id>/search"

Comment on lines +12 to +16
<a></a>
// <a href="https://plane.so/one" target="_blank" className={cn(getButtonStyling("primary", "sm"))}>
// Available on One
// <SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
// </a>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Component rendering an empty anchor element

The upgrade button functionality has been commented out, resulting in an empty <a> tag being rendered. This creates an empty DOM element without any user-visible or functional purpose.

Consider one of the following approaches instead:

  1. If the feature is intentionally disabled, return null instead of an empty anchor:
-  <a></a>
-  // <a href="https://plane.so/one" target="_blank" className={cn(getButtonStyling("primary", "sm"))}>
-  //   Available on One
-  //   <SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
-  // </a>
+  null
  1. If the feature will be reenabled later, use a conditional rendering approach instead of commenting out code:
-  <a></a>
-  // <a href="https://plane.so/one" target="_blank" className={cn(getButtonStyling("primary", "sm"))}>
-  //   Available on One
-  //   <SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
-  // </a>
+  {false && (
+    <a href="https://plane.so/one" target="_blank" className={cn(getButtonStyling("primary", "sm"))}>
+      Available on One
+      <SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
+    </a>
+  )}
📝 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
<a></a>
// <a href="https://plane.so/one" target="_blank" className={cn(getButtonStyling("primary", "sm"))}>
// Available on One
// <SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
// </a>
null

]

def get_queryset(self):
print(self.kwargs.get("project_id"))
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove debugging print statement

There's a print statement that appears to have been added for debugging purposes. This should be removed before pushing to production as it will unnecessarily clutter logs with project_id values.

-        print(self.kwargs.get("project_id"))
📝 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
print(self.kwargs.get("project_id"))

Comment on lines +18 to +80
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = useParams();
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);

const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
const [previewEnabled, setPreviewEnabled] = useState(true);
const [visibleOptions, setVisibleOptions] = useState(5);

useEffect(() => {
const fetchOptions = async () => {
try {
const response = await workspaceService.getIssueAdditionalProperties(workspaceSlug.toString(), projectId.toString(), props.additionalPropertyKey);
const formattedOptions = response.data.map((item: string) => ({ label: item, value: item })) || [];
setOptions(formattedOptions);
} catch (error) {
console.error(`Error fetching ${additionalPropertyKey} options:`, error);
}
};

fetchOptions();
}, [workspaceSlug, projectId, additionalPropertyKey]);

const filteredOptions = searchQuery
? options.filter((option: any) => option?.label.toLowerCase().includes(searchQuery.toLowerCase()))
: options;

return (
<>
<FilterHeader
title={`${additionalPropertyTitle} ${appliedFilters?.length ? `(${appliedFilters.length})` : ""}`}
isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/>
{previewEnabled && (
<div>
{filteredOptions.length > 0 ? (
<>
{filteredOptions.slice(0, visibleOptions).map(({ label, value }) => (
<FilterOption
key={value}
isChecked={appliedFilters?.includes(value) ?? false}
onClick={() => handleUpdate(value)}
title={label}
/>
))}
{filteredOptions.length > 5 && (
<button
className="text-blue-500 text-xs mt-2"
onClick={() => setVisibleOptions(visibleOptions === 5 ? filteredOptions.length : 5)}
>
{visibleOptions === 5 ? "View More" : "View Less"}
</button>
)}
</>
) : (
<p className="text-xs italic text-custom-text-400">No Matches Found</p>
)}
</div>
)}
</>
);
}); No newline at end of file
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

New component for filtering by additional properties.

The FilterAdditionalProperties component provides UI for filtering issues by custom properties. The implementation follows React best practices with proper state management and rendering.

However, there are a few issues to address:

  1. Missing dependency in useEffect:
- }, [workspaceSlug, projectId, additionalPropertyKey]);
+ }, [workspaceSlug, projectId, additionalPropertyKey, workspaceService, props.additionalPropertyKey]);
  1. Missing type safety for URL parameters:
- const response = await workspaceService.getIssueAdditionalProperties(workspaceSlug.toString(), projectId.toString(), props.additionalPropertyKey);
+ const response = await workspaceService.getIssueAdditionalProperties(
+   workspaceSlug?.toString() || "",
+   projectId?.toString() || "",
+   props.additionalPropertyKey
+ );
  1. Consider adding a loading state indicator while fetching data:
  const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
  const [previewEnabled, setPreviewEnabled] = useState(true);
  const [visibleOptions, setVisibleOptions] = useState(5); 
+ const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const fetchOptions = async () => {
+     setIsLoading(true);
      try {
        const response = await workspaceService.getIssueAdditionalProperties(workspaceSlug.toString(), projectId.toString(), props.additionalPropertyKey);
        const formattedOptions = response.data.map((item: string) => ({ label: item, value: item })) || [];
        setOptions(formattedOptions);
      } catch (error) {
        console.error(`Error fetching ${additionalPropertyKey} options:`, error);
+     } finally {
+       setIsLoading(false);
      }
    };

    fetchOptions();
  }, [workspaceSlug, projectId, additionalPropertyKey]);
  1. Add a loading state in the component rendering:
      {previewEnabled && (
        <div>
+         {isLoading ? (
+           <p className="text-xs text-custom-text-400">Loading...</p>
+         ) : (
          {filteredOptions.length > 0 ? (
            <>
              {filteredOptions.slice(0, visibleOptions).map(({ label, value }) => (
                <FilterOption
                  key={value}
                  isChecked={appliedFilters?.includes(value) ?? false}
                  onClick={() => handleUpdate(value)}
                  title={label}
                />
              ))}
              {filteredOptions.length > 5 && (
                <button
                  className="text-blue-500 text-xs mt-2"
                  onClick={() => setVisibleOptions(visibleOptions === 5 ? filteredOptions.length : 5)}
                >
                  {visibleOptions === 5 ? "View More" : "View Less"}
                </button>
              )}
            </>
          ) : (
            <p className="text-xs italic text-custom-text-400">No Matches Found</p>
          )}
+         )}
        </div>
      )}
📝 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
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = useParams();
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);
const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
const [previewEnabled, setPreviewEnabled] = useState(true);
const [visibleOptions, setVisibleOptions] = useState(5);
useEffect(() => {
const fetchOptions = async () => {
try {
const response = await workspaceService.getIssueAdditionalProperties(workspaceSlug.toString(), projectId.toString(), props.additionalPropertyKey);
const formattedOptions = response.data.map((item: string) => ({ label: item, value: item })) || [];
setOptions(formattedOptions);
} catch (error) {
console.error(`Error fetching ${additionalPropertyKey} options:`, error);
}
};
fetchOptions();
}, [workspaceSlug, projectId, additionalPropertyKey]);
const filteredOptions = searchQuery
? options.filter((option: any) => option?.label.toLowerCase().includes(searchQuery.toLowerCase()))
: options;
return (
<>
<FilterHeader
title={`${additionalPropertyTitle} ${appliedFilters?.length ? `(${appliedFilters.length})` : ""}`}
isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/>
{previewEnabled && (
<div>
{filteredOptions.length > 0 ? (
<>
{filteredOptions.slice(0, visibleOptions).map(({ label, value }) => (
<FilterOption
key={value}
isChecked={appliedFilters?.includes(value) ?? false}
onClick={() => handleUpdate(value)}
title={label}
/>
))}
{filteredOptions.length > 5 && (
<button
className="text-blue-500 text-xs mt-2"
onClick={() => setVisibleOptions(visibleOptions === 5 ? filteredOptions.length : 5)}
>
{visibleOptions === 5 ? "View More" : "View Less"}
</button>
)}
</>
) : (
<p className="text-xs italic text-custom-text-400">No Matches Found</p>
)}
</div>
)}
</>
);
});
export const FilterAdditionalProperties: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = useParams();
const { appliedFilters, handleUpdate, searchQuery, additionalPropertyTitle, additionalPropertyKey } = props;
const workspaceService = new WorkspaceService(API_BASE_URL);
const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
const [previewEnabled, setPreviewEnabled] = useState(true);
const [visibleOptions, setVisibleOptions] = useState(5);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const fetchOptions = async () => {
setIsLoading(true);
try {
const response = await workspaceService.getIssueAdditionalProperties(
workspaceSlug?.toString() || "",
projectId?.toString() || "",
props.additionalPropertyKey
);
const formattedOptions = response.data.map((item: string) => ({ label: item, value: item })) || [];
setOptions(formattedOptions);
} catch (error) {
console.error(`Error fetching ${additionalPropertyKey} options:`, error);
} finally {
setIsLoading(false);
}
};
fetchOptions();
}, [workspaceSlug, projectId, additionalPropertyKey, workspaceService, props.additionalPropertyKey]);
const filteredOptions = searchQuery
? options.filter((option: any) => option?.label.toLowerCase().includes(searchQuery.toLowerCase()))
: options;
return (
<>
<FilterHeader
title={`${additionalPropertyTitle} ${appliedFilters?.length ? `(${appliedFilters.length})` : ""}`}
isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/>
{previewEnabled && (
<div>
{isLoading ? (
<p className="text-xs text-custom-text-400">Loading...</p>
) : (
filteredOptions.length > 0 ? (
<>
{filteredOptions.slice(0, visibleOptions).map(({ label, value }) => (
<FilterOption
key={value}
isChecked={appliedFilters?.includes(value) ?? false}
onClick={() => handleUpdate(value)}
title={label}
/>
))}
{filteredOptions.length > 5 && (
<button
className="text-blue-500 text-xs mt-2"
onClick={() => setVisibleOptions(visibleOptions === 5 ? filteredOptions.length : 5)}
>
{visibleOptions === 5 ? "View More" : "View Less"}
</button>
)}
</>
) : (
<p className="text-xs italic text-custom-text-400">No Matches Found</p>
)
)}
</div>
)}
</>
);
});

Comment on lines +143 to +174
def patch(self, request, slug, project_id, issue_id, pk):
issue_attachment = FileAsset.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id
)
serializer = IssueAttachmentSerializer(issue_attachment)

# Send this activity only if the attachment is not uploaded before
if not issue_attachment.is_uploaded:
issue_activity.delay(
type="attachment.activity.created",
requested_data=None,
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
current_instance=json.dumps(
serializer.data,
cls=DjangoJSONEncoder,
),
epoch=int(timezone.now().timestamp()),
notification=True,
origin=request.META.get("HTTP_ORIGIN"),
)

# Update the attachment
issue_attachment.is_uploaded = True
issue_attachment.created_by = request.user

# Get the storage metadata
if not issue_attachment.storage_metadata:
get_asset_object_metadata.delay(str(issue_attachment.id))
issue_attachment.save()
return Response(status=status.HTTP_204_NO_CONTENT) No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Ensure concurrency safety when marking attachments as uploaded.

If multiple requests or background tasks simultaneously modify the same attachment’s status, there’s a possibility of inconsistent states. Confirm that the application logic or database layer properly handles concurrent updates (e.g., via transactional integrity in Django ORM).


🏁 Script executed:

#!/bin/bash
# Check for references to concurrency locks or transaction atomic blocks
rg -A 4 --case-sensitive "transaction\.atomic" 

Length of output: 1245


Concurrency safety for attachment updates needs to be addressed.
The current patch method in apiserver/plane/api/views/attachment.py checks and updates the attachment's is_uploaded and created_by fields without an explicit transactional safeguard. Our repository shows that similar update operations in other parts (see usage of transaction.atomic in apiserver/plane/db/models/issue.py and apiserver/plane/app/views/view/base.py) are wrapped in transaction blocks to ensure consistency. To prevent race conditions when concurrent requests attempt to update the same attachment, please consider wrapping the check-and-update logic in a transaction.atomic block and, if necessary, using select_for_update when fetching the attachment record.

  • Location: apiserver/plane/api/views/attachment.py, patch method (lines 143–174)
  • Suggested Change: Wrap the if not issue_attachment.is_uploaded: block and subsequent updates in a with transaction.atomic(): block to enforce transactional integrity.

Comment on lines +159 to +175
if self.instance is None:
if not is_uuid(data.get('created_by')):
if User.objects.filter(username=data['created_by']).exists():
data['created_by'] = User.objects.get(username=data['created_by'])
else:
user_data = {
"email": data['created_by'] + '@plane-shipsy.com',
"username": data['created_by'],
"role": 5,
"display_name": data['created_by']
}
from plane.api.views import ProjectMemberAPIEndpoint
PMObj = ProjectMemberAPIEndpoint()
user = PMObj.create_user(user_data)
PMObj.create_workspace_member(self.context.get("workspace_id"), user,5)
PMObj.create_project_member(self.context.get("project_id"), user,5)
data['created_by'] = user
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

Avoid view-layer imports in the serializer.

The code directly imports and calls ProjectMemberAPIEndpoint from within the serializer, coupling the serializers and views. This may make the code harder to maintain or test. Consider extracting user-creation logic into a shared service or manager class.

Comment on lines 65 to +70
email = request.data.get("email", False)
if not email:
username = request.data.get("username", False)
if username:
email = username + "@plane-shipsy.com"
print(email)
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

Beware of potential email collision.
Generating an email by appending “@plane-shipsy.com” could create duplicates if different users share the same username. Consider validating email uniqueness or informing the user on conflicts.

Comment on lines +726 to +747
class IssueCustomProperty(ProjectBaseModel):
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="custom_properties"
)
key = models.CharField(max_length=255)
value = models.CharField(max_length=255, null=True, blank=True)
issue_type_custom_property = models.ForeignKey(
"db.IssueTypeCustomProperty",
on_delete=models.SET_NULL,
related_name="issue_type_custom_property",
null=True,
blank=True,
)

class Meta:
verbose_name = "Issue Custom Property"
verbose_name_plural = "Issue Custom Properties"
db_table = "issue_custom_properties"
ordering = ("-created_at",)

def __str__(self):
return f"{self.issue.name} {self.key}" No newline at end of file
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

Enhance concurrency and validation for custom properties.
The new IssueCustomProperty model allows flexible additions of key-value pairs. If these properties can be updated frequently or in parallel, consider an optimistic lock or additional validation to prevent conflicting writes.

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 (7)
apiserver/plane/authentication/views/app/magic.py (7)

70-70: Remove debug print statement.

Remove the print statement before pushing to production.

-        print(email)

95-101: Method name does not fully reflect its functionality.

The add_user_to_workspace method does more than just add a user to a workspace - it also creates workspaces and adds users to projects. Consider renaming to better reflect the full scope, such as setup_user_workspace_access.


104-127: Improve exception handling in add_to_workspace method.

The exception is caught but only printed to console, which isn't appropriate for production code. Consider proper logging and error handling.

         try:
             user.profile.last_workspace_id = workspace.id
             user.profile.onboarding_step.update({
                 'profile_complete': True,
                 'workspace_join': True
             })
             user.profile.is_tour_completed = True
             user.profile.is_onboarded = True
             user.is_password_autoset = False
             user.profile.company_name = workspace.name
             user.save()
             user.profile.save()
         except Exception as e:
-            print(e)
+            # Use proper logging
+            import logging
+            logger = logging.getLogger(__name__)
+            logger.error("Error updating user profile: %s", str(e))

158-183: Improve error handling in get_or_create_project method.

The serializer validation errors are raised as a generic Exception, which makes error handling less precise. Consider returning a more descriptive error or using a specific exception type.

        prSer.is_valid()
        if prSer.errors:
-            raise Exception(prSer.errors)
+            from rest_framework.exceptions import ValidationError
+            raise ValidationError(prSer.errors)

188-188: Remove debug print statement.

Remove the print statement before pushing to production.

-        print(base_host(request=request, is_app=True))

262-262: Remove debug print statement.

Remove the print statement before pushing to production.

-            print(params)

287-287: Unused variable 'is_app'.

The variable is_app is assigned but never used in the method, as flagged by static analysis.

Either use this variable or remove it:

-        is_app = request.POST.get("is_app", False)

Or if it's intended for future use, add a comment:

        is_app = request.POST.get("is_app", False)
+        # TODO: is_app will be used in future implementation
🧰 Tools
🪛 Ruff (0.8.2)

287-287: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b82176c and ddcd4fb.

📒 Files selected for processing (3)
  • apiserver/plane/authentication/views/app/magic.py (5 hunks)
  • apiserver/plane/db/models/issue_type.py (1 hunks)
  • web/core/constants/spreadsheet.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apiserver/plane/db/models/issue_type.py
🧰 Additional context used
🧬 Code Definitions (2)
web/core/constants/spreadsheet.ts (1)
web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1) (1)
  • SpreadsheetStandardPropertyColumn (11-21)
apiserver/plane/authentication/views/app/magic.py (3)
apiserver/plane/api/serializers/project.py (2) (2)
  • ProjectSerializer (15-88)
  • create (66-88)
apiserver/plane/api/views/base.py (2) (2)
  • BaseAPIView (40-226)
  • workspace_slug (195-196)
apiserver/plane/api/views/project.py (1) (1)
  • create_project (34-122)
🪛 Ruff (0.8.2)
apiserver/plane/authentication/views/app/magic.py

287-287: Local variable is_app is assigned to but never used

Remove assignment to unused variable is_app

(F841)

🔇 Additional comments (12)
web/core/constants/spreadsheet.ts (6)

14-14: Icon import addition looks good.

The addition of the Tags icon import is appropriate for the new standard properties being added.


36-36: SpreadsheetStandardPropertyColumn import is properly added.

This component is required for the new standard properties and is correctly imported.


181-189: Hub Code property implementation looks good.

The property follows the established pattern with appropriate title, ordering keys, and component usage.


190-234: Standard properties implementation is consistent.

All the new properties (customer_code, worker_code, vendor_code, trip_reference_number, reference_number) follow the same consistent pattern with appropriate titles, ordering keys, and use of the Tags icon.


252-257: Property list updated correctly.

The SPREADSHEET_PROPERTY_LIST has been properly updated to include all the new standard properties.


181-234:

Details

❓ Verification inconclusive

Verify type definitions and backend support.

Please ensure that the IIssueDisplayProperties type definition has been updated to include these new properties, and that the backend API supports these fields for issues.


🏁 Script executed:

#!/bin/bash
# Check if IIssueDisplayProperties interface includes the new properties
fd -e "ts" -e "tsx" "IIssueDisplayProperties" --exec grep -l "IIssueDisplayProperties" {} \; | xargs cat

Length of output: 101


Action Required: Manually Verify Interface and Backend Updates

It appears that our automated search did not return any results for the IIssueDisplayProperties interface. Please confirm manually that the interface now includes the new properties:

  • hub_code
  • customer_code
  • worker_code
  • vendor_code
  • trip_reference_number
  • reference_number

Also, verify that the backend API supports these fields for issues.

apiserver/plane/authentication/views/app/magic.py (6)

27-32: Good organization of imports.

The added imports are well-structured and logically grouped into related components (models, serializers). This promotes better code maintainability.


66-70: Beware of potential email collision.

Generating an email by appending "@plane-shipsy.com" could create duplicates if different users share the same username. Consider validating email uniqueness or informing the user on conflicts.


79-79: Return value modification to include token.

The response now returns both key and token, which appears to be an intentional change. Make sure any clients consuming this API are updated to handle the new response format.


212-234: User flow logic has been improved.

The logic for handling non-existing users has been improved to authenticate the user, create a profile, add them to the workspace, and redirect them appropriately. This provides a smoother onboarding experience.


245-258: User flow for existing users updated to include workspace addition.

The existing user flow now includes adding the user to the workspace before login, which ensures a consistent experience for both new and existing users.


41-44:

Details

✅ Verification successful

Security concern: Commented out permission classes.

The permission classes are commented out but the base class has changed from APIView to BaseAPIView. Verify whether BaseAPIView includes appropriate permission classes, as removing AllowAny permissions without replacement could create unintended authentication requirements.


🏁 Script executed:

#!/bin/bash
# Check the BaseAPIView implementation for permission classes
cat apiserver/plane/api/views/base.py | grep -A 10 "class BaseAPIView"

Length of output: 349


Security Check: Inherited Permissions from BaseAPIView

The MagicGenerateEndpoint now relies on BaseAPIView, which explicitly sets its permission classes to [IsAuthenticated]. This confirms that the intentional removal of the AllowAny permission is safe—as long as the desired behavior is to require authentication. If you intended for the endpoint to allow anonymous access, you'll need to override the inherited permissions.

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 (1)
web/core/constants/spreadsheet.ts (1)

181-234: Consider using more visually distinct icons for different property types.

While the implementation of the new properties (hub_code, customer_code, worker_code, vendor_code, trip_reference_number, reference_number) is structurally sound, they all use the same Tags icon. Consider using different icons for different categories of properties to improve visual distinction in the UI.

For example:

  • Building/location icons for hub_code
  • Person icons for worker_code and customer_code
  • Document/number icons for reference numbers

Additionally, consider adding comments to describe what each of these properties represents and their purpose within the system.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2b96095 and bb68517.

📒 Files selected for processing (1)
  • web/core/constants/spreadsheet.ts (4 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
web/core/constants/spreadsheet.ts (1)
web/core/components/issues/issue-layouts/spreadsheet/columns/standard-property-column.tsx (1) (1)
  • SpreadsheetStandardPropertyColumn (11-21)
🔇 Additional comments (3)
web/core/constants/spreadsheet.ts (3)

14-14: Import addition looks good.

The addition of the Tags icon from lucide-react is appropriate for the new properties that will use this icon.


36-36: Import of SpreadsheetStandardPropertyColumn is appropriate.

Good inclusion of the necessary component that will be used for rendering the new standard properties.


252-257: Property list addition is correct.

The new properties have been correctly added to the SPREADSHEET_PROPERTY_LIST array, making them available for display in the spreadsheet view.

mmkhak added a commit to mmkhak/plane that referenced this pull request Mar 21, 2025
* Added Persian (فارسی) to the list of supported languages.
* Updated the TranslationStore to include Persian translations.
* Extended TLanguage type to include "fa".
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.

7 participants