Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[WIKI-769] chore: added sort order for pages#8191

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
NarayanBavisetti wants to merge5 commits intopreview
base:preview
Choose a base branch
Loading
fromchore-page-sort-order

Conversation

@NarayanBavisetti
Copy link
Collaborator

@NarayanBavisettiNarayanBavisetti commentedNov 27, 2025
edited by coderabbitaibot
Loading

Description

added sorting of page in project level pages.

Type of Change

  • Feature (non-breaking change which adds functionality)

Summary by CodeRabbit

Release Notes

  • New Features
    • Page sort order now exposed in API responses for improved ordering and management capabilities
    • New pages automatically assigned sort order values when created within a project
    • Existing pages updated with sort order values during system upgrade to ensure data consistency

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitaibot commentedNov 27, 2025
edited
Loading

Walkthrough

This change introduces asort_order field toProjectPage for managing page sorting within projects. A database migration populates existing data with robust duplicate-handling logic, the model initializes sort orders for new pages, the view prefetches related data, and the serializer exposes the computed sort order value.

Changes

Cohort / File(s)Summary
Database Schema & Migration
apps/api/plane/db/migrations/0113_auto_20251215_0934.py
Addssort_order FloatField to ProjectPage with default 65535. Includesset_page_sort_order() function that copies parent sort orders and resolves duplicates by workspace with batched updates. Includes reverse migrationreverse_set_page_sort_order().
Model Layer
apps/api/plane/db/models/page.py
Addssort_order FloatField field to ProjectPage. Introduces_set_sort_for_root_page() initialization method and overridessave() to auto-set sort order for new root pages.
View & Serializer Layer
apps/api/plane/app/views/page/base.py,apps/api/plane/app/serializers/page.py
View adds Prefetch for current-project filteredproject_pages relation. Serializer addssort_order SerializerMethodField withget_sort_order() method that returns prefetched data or DEFAULT_SORT_ORDER fallback.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Migration logic: Batched bulk operations with duplicate detection and per-workspace sort-order reassignment require careful verification
  • Model initialization:_set_sort_for_root_page() logic for computing new sort orders based on project-wide maximums needs validation
  • Prefetch setup: Confirm filter conditions and relation assumptions in view'sget_queryset()
  • Serializer fallback: Verify the prefetch relation is always available when accessed inget_sort_order()

Poem

🐰 A new sort order hops into place,
Pages now dance with numeric grace,
Prefetch and serialize, side by side,
Duplicates handled with batched pride,
Organization's our rabbit delight! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check nameStatusExplanationResolution
Description check⚠️ WarningThe description is incomplete. While it identifies the feature and indicates the type of change, it lacks detail on implementation specifics, test scenarios, and references to related issues.Expand the description to explain how sort order works, add specific test scenarios, and include a reference to issue WIKI-769 linked in the title.
Docstring Coverage⚠️ WarningDocstring coverage is 25.00% which is insufficient. The required threshold is 80.00%.You can run@coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Title check✅ PassedThe title accurately describes the main change: adding sort order functionality for pages. It is concise and clearly summarizes the primary modification across the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branchchore-page-sort-order

Thanks for usingCodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment@coderabbitai help to get the list of available commands and usage tips.

@makeplane
Copy link

Linked to Plane Work Item(s)

This comment was auto-generated byPlane

@dheeru0198dheeru0198 added the 🔄migrationsContains Migration changes labelDec 10, 2025
@NarayanBavisettiNarayanBavisetti marked this pull request as ready for reviewDecember 17, 2025 08:25
CopilotAI review requested due to automatic review settingsDecember 17, 2025 08:25
Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/api/plane/db/models/page.py (2)

154-163:Docstring doesn't match implementation behavior.

The docstring states this setssort_order for pages "when the associated page has no parent," but the method doesn't checkself.page.parent. It unconditionally calculates and assigns a newsort_order for everyProjectPage creation.

If this is intentional (all newProjectPage entries get a unique sort order), update the docstring. If only root pages should get a calculated sort order, add a parent check:

 def _set_sort_for_root_page(self):     """-    Set sort_order for project pages when the associated page has no parent in the workspace.+    Set sort_order for newly created project pages.     """+    # Optionally, if only root pages should get unique sort:+    # if self.page.parent_id is not None:+    #     return     largest_sort_order = ProjectPage.objects.filter(project=self.project).aggregate(         largest=models.Max("sort_order")     )["largest"]

165-168:Consider race condition on concurrent inserts.

Multiple concurrentProjectPage creations for the same project could read the samelargest value and assign duplicatesort_order values. While this doesn't break functionality (duplicates just affect display order), you may want to add advisory locking similar to theIssue model pattern if strict ordering is required:

withtransaction.atomic():lock_key=convert_uuid_to_integer(self.project_id)withconnection.cursor()ascursor:cursor.execute("SELECT pg_advisory_xact_lock(%s)", [lock_key])# ... rest of sort_order logic

If duplicate sort orders are acceptable, this can be deferred.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweendf710e0 and80d2ee6.

📒 Files selected for processing (4)
  • apps/api/plane/app/serializers/page.py (3 hunks)
  • apps/api/plane/app/views/page/base.py (2 hunks)
  • apps/api/plane/db/migrations/0113_auto_20251215_0934.py (1 hunks)
  • apps/api/plane/db/models/page.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
apps/api/plane/app/serializers/page.py (1)
apps/api/plane/db/models/page.py (1)
  • Page (19-73)
apps/api/plane/app/views/page/base.py (1)
apps/api/plane/db/models/page.py (1)
  • ProjectPage (131-168)
apps/api/plane/db/models/page.py (2)
apps/api/plane/db/models/issue.py (2)
  • save (182-246)
  • save (475-524)
apps/api/plane/db/models/favorite.py (1)
  • save (48-61)
apps/api/plane/db/migrations/0113_auto_20251215_0934.py (1)
apps/api/plane/db/models/page.py (2)
  • Page (19-73)
  • ProjectPage (131-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: check:format
  • GitHub Check: Build packages
  • GitHub Check: Lint API
  • GitHub Check: Agent
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/api/plane/app/views/page/base.py (1)

102-110:LGTM!

ThePrefetch correctly filtersProjectPage entries for the current project withdeleted_at__isnull=True, andto_attr="current_project_page" stores the result as a list for efficient access in the serializer'sget_sort_order method.

apps/api/plane/app/serializers/page.py (1)

126-132:LGTM!

The implementation correctly handles the prefetchedcurrent_project_page list, accessing the first element'ssort_order when available and falling back toPage.DEFAULT_SORT_ORDER otherwise.

Comment on lines +20 to +31
project_pages=ProjectPage.objects.filter(page__parent_id__isnull=False).select_related("page")
project_pages_to_update= []
forproject_pageinproject_pages.iterator(chunk_size=BATCH_SIZE):
project_page.sort_order=project_page.page.sort_order
project_pages_to_update.append(project_page)
iflen(project_pages_to_update)>=BATCH_SIZE:
ProjectPage.objects.bulk_update(project_pages_to_update, ["sort_order"],batch_size=BATCH_SIZE)
project_pages_to_update= []

# Update remaining items
ifproject_pages_to_update:
ProjectPage.objects.bulk_update(project_pages_to_update, ["sort_order"],batch_size=BATCH_SIZE)
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 |🟠 Major

Existing root pages retain duplicatesort_order values.

This loop copiesPage.sort_order toProjectPage.sort_order only for child pages (parent_id__isnull=False). Existing root pages (withparent_id=None) will all have the default65535 in theirProjectPage records.

Consider also assigning uniquesort_order values toProjectPage entries for root pages:

# After updating child pages, handle root pages similarlyroot_project_pages=ProjectPage.objects.filter(page__parent_id__isnull=True).select_related("page")# Assign unique sort_order per project...

Comment on lines +52 to +56
pages=list[Any](
Page.objects
.filter(workspace_id=workspace_id,sort_order=DEFAULT)
.only("id","sort_order")
)
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 |🔴 Critical

Syntax error:list[Any] is a type hint, not callable.

list[Any](...) will raise aTypeError at runtime. Uselist(...) to convert the queryset to a list:

-        pages = list[Any](+        pages = list(             Page.objects             .filter(workspace_id=workspace_id, sort_order=DEFAULT)             .only("id", "sort_order")         )

Also, theAny import on line 3 becomes unused after this fix.

🤖 Prompt for AI Agents
In apps/api/plane/db/migrations/0113_auto_20251215_0934.py around lines 52 to56, the code uses the type hint `list[Any](...)` which is invalid at runtime;replace `list[Any](Page.objects.filter(...).only(...))` with a plain`list(Page.objects.filter(...).only(...))` to materialize the queryset, andremove the now-unused `Any` import from the top of the file.

Comment on lines +68 to +71
defreverse_set_page_sort_order(apps,schema_editor):
ProjectPage=apps.get_model("db","ProjectPage")
DEFAULT_SORT_ORDER=65535
ProjectPage.objects.update(sort_order=DEFAULT_SORT_ORDER)
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 |🟡 Minor

Reverse migration doesn't restorePage.sort_order changes.

The forward migration modifies bothProjectPage.sort_order (lines 20-31) andPage.sort_order (lines 61-65), but the reverse only resetsProjectPage.sort_order. If the migration is rolled back,Page.sort_order values will remain modified.

If reversibility is important, consider either:

  1. Storing original values and restoring them in reverse
  2. Documenting thatPage.sort_order changes are permanent
🤖 Prompt for AI Agents
In apps/api/plane/db/migrations/0113_auto_20251215_0934.py around lines 68-71,the reverse_set_page_sort_order currently only resets ProjectPage.sort_order anddoes not undo the changes made to Page.sort_order in the forward migration;update the reverse function to also restore Page.sort_order (either by settingit back to the same DEFAULT_SORT_ORDER constant used for ProjectPage or, iforiginal values were captured, restore those original values) so the rollbackfully reverts both models, or explicitly document in the migration header thatPage.sort_order changes are irreversible if you choose not to implementrestoration.

Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds sort order functionality to project-level pages by introducing asort_order field to theProjectPage model. The feature enables ordering of pages within projects, moving beyond the current creation-date-based sorting.

  • Addssort_order FloatField toProjectPage model with default value fromPage.DEFAULT_SORT_ORDER (65535)
  • Migrates existing page sort orders to theProjectPage model for child pages
  • Exposessort_order through thePageSerializer via a prefetch mechanism

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

FileDescription
apps/api/plane/db/models/page.pyAddssort_order field toProjectPage model and implements auto-incrementing logic in save() method
apps/api/plane/db/migrations/0113_auto_20251215_0934.pyMigration that adds the field and backfills sort_order values from related Page models
apps/api/plane/app/views/page/base.pyAdds prefetch for ProjectPage to make sort_order available in querysets
apps/api/plane/app/serializers/page.pyAddsget_sort_order method to expose sort_order from prefetched ProjectPage instances

💡Add Copilot custom instructions for smarter, more guided reviews.Learn how to get started.

Comment on lines +52 to +56
pages=list[Any](
Page.objects
.filter(workspace_id=workspace_id,sort_order=DEFAULT)
.only("id","sort_order")
)

Choose a reason for hiding this comment

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

Invalid type annotation syntax. The expression 'listAny' attempts to call 'list[Any]' as a function, but this is not valid Python. This should be either a list comprehension or use the list() constructor without the type parameter. The correct syntax would be 'pages = list(Page.objects.filter(...))' or simply assign the queryset directly if you need to iterate over it multiple times.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +157
def_set_sort_for_root_page(self):
"""
Set sort_order for project pages when the associated page has no parent in the workspace.
"""

Choose a reason for hiding this comment

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

The documentation states this method sets sort_order "when the associated page has no parent in the workspace," but the implementation doesn't check whether the page has a parent. The method always sets the sort_order for any new ProjectPage. Consider either updating the documentation to match the implementation or adding a check for 'self.page.parent_id is None' if the behavior should only apply to root pages.

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +168
defsave(self,*args,**kwargs):
ifself._state.adding:
self._set_sort_for_root_page()
super(ProjectPage,self).save(*args,**kwargs)

Choose a reason for hiding this comment

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

Inconsistency between migration logic and model behavior. The migration (lines 20-31) copies sort_order from Page to ProjectPage only for pages WITH a parent (parent_id__isnull=False), but the model's save() method sets sort_order for ALL new ProjectPages regardless of parent status. This creates different behavior for existing vs new records. The logic should be aligned: either both should handle all pages, or both should only handle root/child pages consistently.

Copilot uses AI. Check for mistakes.
to_attr="current_project_page",
)
)
.order_by("-is_favorite","-created_at")

Choose a reason for hiding this comment

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

The queryset is ordering by "-is_favorite" and "-created_at" but the newly added sort_order field is not being used for ordering. Since the PR description states this is to "add sorting of page in project level pages," you should update the order_by clause to include sort_order. For example: .order_by("-is_favorite", "sort_order", "-created_at") to order by favorites first, then by sort order, then by creation date.

Copilot uses AI. Check for mistakes.
def__str__(self):
returnf"{self.project.name}{self.page.name}"

def_set_sort_for_root_page(self):

Choose a reason for hiding this comment

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

The method name '_set_sort_for_root_page' implies it only applies to root pages (pages without a parent), but it's actually called for all new ProjectPage instances. Consider renaming to '_set_sort_order' or '_set_initial_sort_order' to better reflect its actual behavior, which sets sort_order for any new ProjectPage regardless of whether the associated page has a parent.

Copilot uses AI. Check for mistakes.
.values_list("workspace_id",flat=True)
)

forworkspace_idinworkspace_ids.iterator(chunk_size=500):

Choose a reason for hiding this comment

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

Calling .iterator() on a values_list QuerySet is unnecessary and potentially problematic. The values_list() already returns a QuerySet, and calling iterator() on line 43 before iterating creates an additional layer. Since workspace_ids is already a QuerySet that will be lazily evaluated, you can directly iterate over it with 'for workspace_id in workspace_ids:'. The chunk_size parameter on iterator() is also redundant here since you're iterating over workspace IDs (which should be a small set), not large model instances.

Copilot uses AI. Check for mistakes.
Comment on lines 100 to 111
.order_by(self.request.GET.get("order_by","-created_at"))
.prefetch_related("labels")
.prefetch_related(
Prefetch(
"project_pages",
queryset=ProjectPage.objects.filter(
project_id=self.kwargs.get("project_id"),deleted_at__isnull=True
),
to_attr="current_project_page",
)
)
.order_by("-is_favorite","-created_at")

Choose a reason for hiding this comment

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

There are two order_by() calls in the queryset chain - one at line 100 and another at line 111. In Django's QuerySet chaining, the second order_by() call will completely override the first one. This means the order_by clause at line 100 that uses the request parameter is ineffective. You should either remove line 100 or combine both ordering strategies into a single order_by() call.

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@coderabbitaicoderabbitai[bot]coderabbitai[bot] left review comments

Copilot code reviewCopilotCopilot left review comments

@dheeru0198dheeru0198Awaiting requested review from dheeru0198

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

🔄migrationsContains Migration changes

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@NarayanBavisetti@dheeru0198

[8]ページ先頭

©2009-2025 Movatter.jp