-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[WEB-5647] chore: list layout work item identifier enhancements #8326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
|
|
||
| # Module imports | ||
| from .base import BaseSerializer, DynamicBaseSerializer | ||
| from django.db.models import Max | ||
| from plane.app.serializers.workspace import WorkspaceLiteSerializer | ||
| from plane.app.serializers.user import UserLiteSerializer, UserAdminLiteSerializer | ||
| from plane.db.models import ( | ||
|
|
@@ -12,6 +13,7 @@ | |
| ProjectIdentifier, | ||
| DeployBoard, | ||
| ProjectPublicMember, | ||
| IssueSequence | ||
| ) | ||
| from plane.utils.content_validator import ( | ||
| validate_html_content, | ||
|
|
@@ -105,6 +107,7 @@ class ProjectListSerializer(DynamicBaseSerializer): | |
| members = serializers.SerializerMethodField() | ||
| cover_image_url = serializers.CharField(read_only=True) | ||
| inbox_view = serializers.BooleanField(read_only=True, source="intake_view") | ||
| next_work_item_sequence = serializers.SerializerMethodField() | ||
|
|
||
| def get_members(self, obj): | ||
| project_members = getattr(obj, "members_list", None) | ||
|
|
@@ -113,6 +116,11 @@ def get_members(self, obj): | |
| return [member.member_id for member in project_members if member.is_active and not member.member.is_bot] | ||
| return [] | ||
|
|
||
| def get_next_work_item_sequence(self, obj): | ||
| """Get the next sequence ID that will be assigned to a new issue""" | ||
| max_sequence = IssueSequence.objects.filter(project_id=obj.id).aggregate(max_seq=Max("sequence"))["max_seq"] | ||
| return (max_sequence + 1) if max_sequence else 1 | ||
|
Comment on lines
+119
to
+122
|
||
|
|
||
| class Meta: | ||
| model = Project | ||
| fields = "__all__" | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -748,3 +748,18 @@ export const isFiltersApplied = (filters: IIssueFilterOptions): boolean => | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Array.isArray(value)) return value.length > 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return value !== undefined && value !== null && value !== ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Calculates the minimum width needed for issue identifiers in list layouts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param projectIdentifierLength - Length of the project identifier (e.g., "PROJ" = 4) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param maxSequenceId - Maximum sequence ID in the project (e.g., 1234) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns Width in pixels needed to display the identifier | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * // For "PROJ-1234" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * calculateIdentifierWidth(4, 1234) // Returns width for "PROJ" + "-" + "1234" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const calculateIdentifierWidth = (projectIdentifierLength: number, maxSequenceId: number): number => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const sequenceDigits = Math.max(1, Math.floor(Math.log10(maxSequenceId)) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const sequenceDigits = Math.max(1, Math.floor(Math.log10(maxSequenceId)) + 1); | |
| // Ensure maxSequenceId is at least 1 to avoid Math.log10(0) or negative numbers | |
| const safeSequenceId = maxSequenceId > 0 ? maxSequenceId : 1; | |
| const sequenceDigits = Math.floor(Math.log10(safeSequenceId)) + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clamp maxSequenceId to avoid NaN widths.
If maxSequenceId is ever non-finite, sequenceDigits becomes NaN and the function returns NaN, which can break inline styles.
export const calculateIdentifierWidth = (projectIdentifierLength: number, maxSequenceId: number): number => {
- const sequenceDigits = Math.max(1, Math.floor(Math.log10(maxSequenceId)) + 1);
+ const safeMax = Number.isFinite(maxSequenceId) && maxSequenceId > 0 ? Math.floor(maxSequenceId) : 1;
+ const sequenceDigits = Math.max(1, Math.floor(Math.log10(safeMax)) + 1);
return projectIdentifierLength * 7 + 7 + sequenceDigits * 7; // project identifier chars + dash + sequence digits
};📝 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.
| /** | |
| * Calculates the minimum width needed for issue identifiers in list layouts | |
| * @param projectIdentifierLength - Length of the project identifier (e.g., "PROJ" = 4) | |
| * @param maxSequenceId - Maximum sequence ID in the project (e.g., 1234) | |
| * @returns Width in pixels needed to display the identifier | |
| * | |
| * @example | |
| * // For "PROJ-1234" | |
| * calculateIdentifierWidth(4, 1234) // Returns width for "PROJ" + "-" + "1234" | |
| */ | |
| export const calculateIdentifierWidth = (projectIdentifierLength: number, maxSequenceId: number): number => { | |
| const sequenceDigits = Math.max(1, Math.floor(Math.log10(maxSequenceId)) + 1); | |
| return projectIdentifierLength * 7 + 7 + sequenceDigits * 7; // project identifier chars + dash + sequence digits | |
| }; | |
| /** | |
| * Calculates the minimum width needed for issue identifiers in list layouts | |
| * @param projectIdentifierLength - Length of the project identifier (e.g., "PROJ" = 4) | |
| * @param maxSequenceId - Maximum sequence ID in the project (e.g., 1234) | |
| * @returns Width in pixels needed to display the identifier | |
| * | |
| * @example | |
| * // For "PROJ-1234" | |
| * calculateIdentifierWidth(4, 1234) // Returns width for "PROJ" + "-" + "1234" | |
| */ | |
| export const calculateIdentifierWidth = (projectIdentifierLength: number, maxSequenceId: number): number => { | |
| const safeMax = Number.isFinite(maxSequenceId) && maxSequenceId > 0 ? Math.floor(maxSequenceId) : 1; | |
| const sequenceDigits = Math.max(1, Math.floor(Math.log10(safeMax)) + 1); | |
| return projectIdentifierLength * 7 + 7 + sequenceDigits * 7; // project identifier chars + dash + sequence digits | |
| }; |
🤖 Prompt for AI Agents
In apps/web/core/components/issues/issue-layouts/utils.tsx around lines 752 to
765, protect calculateIdentifierWidth from non-finite or non-positive
maxSequenceId values by clamping/coercing maxSequenceId to a finite integer >= 1
before computing digits; specifically, create a safeMax (e.g., if
Number.isFinite(maxSequenceId) && maxSequenceId > 0 use
Math.floor(maxSequenceId) else 1), then compute sequenceDigits via
Math.floor(Math.log10(safeMax)) + 1 and return the width using that value so the
function never yields NaN for inline styles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Django import should be grouped with other Django/third-party imports at the top. Currently, django.db.models.Max is placed between local module imports. Consider moving it to line 3, after the rest_framework import, to follow Python import conventions (standard library, third-party, local modules).