Skip to content

Item nav order APIs update#3916

Draft
jmendeza wants to merge 2 commits into
craftercms:developfrom
jmendeza:feature/6061-item-orders
Draft

Item nav order APIs update#3916
jmendeza wants to merge 2 commits into
craftercms:developfrom
jmendeza:feature/6061-item-orders

Conversation

@jmendeza
Copy link
Copy Markdown
Member

@jmendeza jmendeza commented Apr 30, 2026

craftercms/craftercms#6061
Item nav order APIs update

Summary by CodeRabbit

  • New Features

    • Added v2 content ordering API: retrieve ordered child items and reorder using before/after/insert-between strategies.
  • Deprecations / Breaking Changes

    • Removed legacy v1 content-ordering endpoints and associated server-side ordering implementation and scripting helpers—clients must migrate to the new v2 APIs.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Removes legacy v1 navigation-order persistence, services, Spring beans, Groovy wrappers and v1 REST scripts; adds v2 OpenAPI endpoints and a polymorphic ReorderItemRequest model; introduces controller stubs and updates internal wiring and tests accordingly.

Changes

Content Ordering API Migration (v1 → v2)

Layer / File(s) Summary
V2 OpenAPI, request model, controller and constants
src/main/api/studio-api.yaml, src/main/java/org/craftercms/studio/model/rest/content/order/ReorderItemRequest.java, src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java, src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
Adds GET /api/2/content/{siteId}/order and POST /api/2/content/{siteId}/order/reorder in OpenAPI; introduces discriminated polymorphic ReorderItemRequest and controller stubs plus mapping constants.
Removed v1 implementation and persistence
src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java, src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml, src/main/resources/crafter/studio/database-context.xml, src/main/resources/crafter/studio/studio-services-context.xml
Deletes DmPageNavigationOrderServiceImpl, MyBatis mapper XML, mapper bean and Spring bean wiring for page nav order sequences.
Service API and internal cleanup
src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java, src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java, src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
Removes reorderItems(...) contract and implementation, drops DmPageNavigationOrderService dependency and setter, adds updateNavOrder(...) stub in internal impl and replaces previous delegations; comments out move/copy delegation calls.
Groovy API & REST script cleanup
src/main/webapp/default-site/scripts/api/ContentServices.groovy, src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy, src/main/webapp/default-site/scripts/api/impl/content/*, src/main/webapp/default-site/scripts/rest/api/1/content/*, src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
Removes static delegations and Groovy page-navigation wrappers, deletes v1 REST GET handlers for item orders, next item order and reorder endpoints, and removes ServiceFactory page-nav factory method and SpringPageNavigationOrderServices wrapper.
Tests
src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
Removes mock/import for DmPageNavigationOrderService and corresponding verify assertion in testMovePageSuccess.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • rart
  • sumerjabri
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Item nav order APIs update' is vague and generic, using non-descriptive terms that do not clearly convey the specific nature of the changes. Consider a more specific title such as 'Replace v1 content ordering APIs with v2 endpoints' or 'Migrate item navigation order from v1 to v2 API' to better reflect the primary change of removing legacy v1 endpoints and introducing new v2 endpoints.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! 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.

Copy link
Copy Markdown

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

🧹 Nitpick comments (1)
src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java (1)

31-36: Consider allowing optional boundary anchors to support first/last position reorders.

The current requirement for both pathBefore and pathAfter to be non-empty prevents reordering items to first or last position, where one anchor is naturally absent. When implementing the reorder service, consider making one anchor optional and validating that at least one is provided.

Optional DTO adjustment for future implementation
 import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.AssertTrue;
 import org.craftercms.commons.validation.annotations.param.ValidExistingContentPath;
+import org.springframework.util.StringUtils;
@@
 	`@NotEmpty`
 	`@ValidExistingContentPath`
 	private String parentPath;
-	`@NotEmpty`
+	`@ValidExistingContentPath`
 	private String pathBefore;
-	`@NotEmpty`
+	`@ValidExistingContentPath`
 	private String pathAfter;
+
+	`@AssertTrue`(message = "Either pathBefore or pathAfter must be provided")
+	public boolean hasAnchor() {
+		return StringUtils.hasText(pathBefore) || StringUtils.hasText(pathAfter);
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java`
around lines 31 - 36, Rework the ReorderItemRequest DTO so reordering can target
first/last: remove the `@NotEmpty` requirement from at least one of the two fields
(pathBefore and pathAfter) and add a class-level validation that enforces "at
least one anchor present" (e.g., implement a custom validator annotation like
`@AtLeastOneAnchor` or add an isValid() method used by a class-level `@AssertTrue`)
that checks (pathBefore != null && !pathBefore.isEmpty()) || (pathAfter != null
&& !pathAfter.isEmpty()); keep or adapt `@ValidExistingContentPath` checks to only
run when the corresponding field is non-empty. Ensure validators reference the
ReorderItemRequest class and the pathBefore/pathAfter fields so the service
handling reorders can accept null/empty for one anchor but not both.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/api/studio-api.yaml`:
- Around line 5482-5483: The schema property nextOrder is declared as type
"integer" which will reject valid fractional ordering values; update the OpenAPI
schema entries declaring nextOrder (and any identical order-like fields at the
other occurrence) to use type "number" instead of "integer" so calculated or
between-item order values are accepted; locate the nextOrder definitions in the
YAML (the shown block and the similar block at the other occurrence) and change
their type to "number" while preserving any existing descriptions or
constraints.
- Around line 5475-5491: The response objects for these new TODO endpoints are
missing an interim 501 Not Implemented entry; update the response blocks that
currently list '200', '400', '401', '404', and '500' (including the shown block
and the two other new endpoint response blocks introduced alongside it) by
adding a '501' response entry that references the shared NotImplemented response
(e.g., "501": $ref: '#/components/responses/NotImplemented') so clients see the
interim behavior.
- Line 5460: The OpenAPI spec has a duplicate operationId "getNextItemOrder"
(declared twice), which breaks codegen; rename one of the operations to a unique
identifier (e.g., "getNextItemOrderV2" or a more specific name like
"getNextItemOrderForCollection") and update any references that rely on that
operationId (generated client method names, $ref usages, or tooling configs) so
they point to the new name; ensure the operationId change is applied in the
operation object where "operationId: getNextItemOrder" is declared and verify
downstream codegen and tests compile against the new identifier.

In
`@src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java`:
- Around line 376-377: The endpoint mappings in the controller are out of sync
with the OpenAPI spec; update the mapping constants and `@GetMapping/`@PostMapping
annotations so the routes use the spec's paths (e.g., "/item/next-order",
"/item/orders", "/item/reorder") instead of the current ".../order/..."
variants: rename or adjust GET_ITEM_NEXT_ORDER and its handler getNextItemOrder,
the corresponding constant and handler for the item orders endpoint (referenced
around the getItemOrders method), and the reorder endpoint constant/handler
(around the reorderItems/reorder method) so each mapping and constant exactly
match the OpenAPI contract.
- Around line 376-380: The three REST handlers currently returning null (e.g.,
getNextItemOrder) must call the appropriate content service methods to compute
the values and return them wrapped in a Result payload instead of null; locate
getNextItemOrder (and the two adjacent unimplemented methods referenced) and
replace the TODO/null with calls to your domain service (e.g.,
contentService.getNextItemOrder(siteId, parentPath) or the equivalent method
names used in this class), handle/translate any checked exceptions into proper
error Results, and return Result.success(theComputedValue) (or the project’s
standard Result factory) so the endpoints produce valid responses.

In
`@src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java`:
- Around line 70-72: The path constants GET_ITEM_NEXT_ORDER, GET_ITEMS_ORDER,
and REORDER_ITEM currently use "/order" segments but must match the OpenAPI v2
spec; update the constant values in RequestMappingConstants to SITE_ID +
"/item/next-order", SITE_ID + "/item/orders", and SITE_ID + "/item/reorder"
respectively so the controller-registered routes (GET_ITEM_NEXT_ORDER,
GET_ITEMS_ORDER, REORDER_ITEM) align with the published API paths.

In
`@src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java`:
- Around line 529-531: The method updateNavOrder(String siteId, String path,
Document document) currently returns false unconditionally which silently allows
stale nav-order data; change it to fail fast by throwing an
UnsupportedOperationException (or IllegalStateException) with a clear message
like "updateNavOrder not implemented — legacy nav-order logic removed" inside
ContentServiceInternalImpl.updateNavOrder so callers (page writes/copies and
updateNavOrderForMove) cannot proceed silently; ensure the exception text names
updateNavOrder and suggests the replacement work is required.

---

Nitpick comments:
In
`@src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java`:
- Around line 31-36: Rework the ReorderItemRequest DTO so reordering can target
first/last: remove the `@NotEmpty` requirement from at least one of the two fields
(pathBefore and pathAfter) and add a class-level validation that enforces "at
least one anchor present" (e.g., implement a custom validator annotation like
`@AtLeastOneAnchor` or add an isValid() method used by a class-level `@AssertTrue`)
that checks (pathBefore != null && !pathBefore.isEmpty()) || (pathAfter != null
&& !pathAfter.isEmpty()); keep or adapt `@ValidExistingContentPath` checks to only
run when the corresponding field is non-empty. Ensure validators reference the
ReorderItemRequest class and the pathBefore/pathAfter fields so the service
handling reorders can accept null/empty for one anchor but not both.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ac1fffea-e171-4114-974f-f75a65826175

📥 Commits

Reviewing files that changed from the base of the PR and between e87478b and fa7060e.

📒 Files selected for processing (23)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
💤 Files with no reviewable changes (17)
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java

Comment thread src/main/api/studio-api.yaml Outdated
Comment thread src/main/api/studio-api.yaml Outdated
Comment thread src/main/api/studio-api.yaml Outdated
Comment thread src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java Outdated
Comment on lines +376 to +380
@GetMapping(GET_ITEM_NEXT_ORDER)
public Result getNextItemOrder(@ValidSiteId @PathVariable String siteId, @NotEmpty @ValidExistingContentPath @RequestParam String parentPath) {
// TODO
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

These new API handlers are unimplemented and currently return null.

All three endpoints are exposed but non-functional, which will produce invalid responses for consumers and block the feature objective. Please implement service calls and return proper Result payloads before merge.

Also applies to: 387-391, 394-398

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java`
around lines 376 - 380, The three REST handlers currently returning null (e.g.,
getNextItemOrder) must call the appropriate content service methods to compute
the values and return them wrapped in a Result payload instead of null; locate
getNextItemOrder (and the two adjacent unimplemented methods referenced) and
replace the TODO/null with calls to your domain service (e.g.,
contentService.getNextItemOrder(siteId, parentPath) or the equivalent method
names used in this class), handle/translate any checked exceptions into proper
error Results, and return Result.success(theComputedValue) (or the project’s
standard Result factory) so the endpoints produce valid responses.

Comment on lines +529 to +531
private boolean updateNavOrder(String siteId, String path, Document document) {
// TODO: Check the nav order exists in the document, if not, add it with the next item order value
return false;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't ship updateNavOrder(...) as a no-op.

This method is now the only nav-order hook used by page writes/copies and by updateNavOrderForMove(...). Returning false unconditionally means page descriptors stop getting nav-order updates once the legacy service is removed, so copy/move/write flows can silently persist stale ordering data. At minimum, this should fail fast until the replacement logic is implemented instead of succeeding with broken ordering.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java`
around lines 529 - 531, The method updateNavOrder(String siteId, String path,
Document document) currently returns false unconditionally which silently allows
stale nav-order data; change it to fail fast by throwing an
UnsupportedOperationException (or IllegalStateException) with a clear message
like "updateNavOrder not implemented — legacy nav-order logic removed" inside
ContentServiceInternalImpl.updateNavOrder so callers (page writes/copies and
updateNavOrderForMove) cannot proceed silently; ensure the exception text names
updateNavOrder and suggests the replacement work is required.

@jmendeza jmendeza force-pushed the feature/6061-item-orders branch from fa7060e to b9e01ce Compare May 5, 2026 00:09
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/api/studio-api.yaml`:
- Around line 5345-5353: The 200 responses return bare payload fields (e.g.,
nextOrder, order and array item schemas) instead of the v2 ApiResponse envelope;
update each affected response schema (the ones returning nextOrder and the
array/item responses referenced around the diff) to wrap the existing schema
under a top-level object property named response (i.e., replace the current
schema with an object that has properties.response equal to the original schema
and preserves type/description), so clients receive { response:
<originalPayload> } consistent with ApiResponse; ensure the referenced fields
nextOrder and any array item schemas are moved unchanged into response.

In
`@src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java`:
- Around line 31-36: ReorderItemRequest currently requires both pathBefore and
pathAfter which prevents boundary moves; decide if boundary reorders are
allowed, then either (A) if boundaries supported: remove the `@NotEmpty`
constraint from pathBefore/pathAfter (make them nullable) and add a class-level
validator (e.g., an `@Constraint` on ReorderItemRequest or an `@AssertTrue` boolean
method) that enforces the business rule (at least one present or exactly one
present depending on the requirement) and update the reorderItem endpoint
contract to reflect the rule, or (B) if boundaries are not supported: keep
`@NotEmpty` but add documentation to the reorderItem API contract stating both
neighbors are required. Ensure validators reference
ReorderItemRequest.pathBefore and .pathAfter and the endpoint reorderItem in
tests/contract docs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4b14727f-70cd-4317-9296-34bb814ef90f

📥 Commits

Reviewing files that changed from the base of the PR and between fa7060e and b9e01ce.

📒 Files selected for processing (23)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
💤 Files with no reviewable changes (17)
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java

Comment thread src/main/api/studio-api.yaml Outdated
Comment thread src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java Outdated
@jmendeza jmendeza force-pushed the feature/6061-item-orders branch 4 times, most recently from a55aa73 to a751208 Compare May 5, 2026 17:55
Copy link
Copy Markdown

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

♻️ Duplicate comments (3)
src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java (1)

379-387: ⚠️ Potential issue | 🔴 Critical

Endpoints are still exposed as stubs returning null.

Both getItemsOrder(...) and reorderItem(...) are mapped but unimplemented, so these APIs currently return invalid responses instead of a Result payload backed by service logic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java`
around lines 379 - 387, Implement the two stub endpoints to delegate to the
content service and return a proper Result: in getItemsOrder(String siteId,
String parentPath) call the service method that retrieves item order (e.g.,
contentService.getItemsOrder(siteId, parentPath) or equivalent), wrap the
returned data into a successful Result payload and return it; in
reorderItem(String siteId, ReorderItemRequest request) call the service method
that applies the reorder (e.g., contentService.reorderItem(siteId, request)),
handle validation/exceptions as before in this controller, and return a Result
indicating success (or the updated order) instead of null; keep existing
annotations (`@ValidSiteId`, `@ValidExistingContentPath`, `@Valid`) and reuse the
controller’s standard Result creation pattern/methods for consistent response
shape.
src/main/api/studio-api.yaml (2)

5414-5415: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return order as number (double), not integer.

At Line 5415, order is declared as integer, which can reject valid fractional ordering values produced by reorder calculations.

Suggested fix
                                     order:
-                                        type: integer
+                                        type: number
+                                        format: double
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/api/studio-api.yaml` around lines 5414 - 5415, The OpenAPI schema
property named "order" is currently declared as type: integer which will reject
fractional reorder values; change the "order" property in the studio-api YAML
schema from type: integer to type: number and (optionally) add format: double so
fractional ordering values are accepted (update the property definition for
"order" accordingly).

5349-5356: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use a top-level v2 response envelope instead of per-item response.

At Line 5350 the 200 schema is an array, and at Line 5354 each item contains response. This makes the API contract inconsistent with the v2 envelope pattern used elsewhere ({ response, ... }) and complicates generated clients.

Suggested minimal shape fix
                 '200':
                     description: OK
                     content:
                         application/json:
                             schema:
-                                type: array
-                                items:
-                                    type: object
-                                    properties:
-                                        response:
-                                            $ref: '#/components/schemas/ApiResponse'
-                                        path:
-                                            type: string
-                                        order:
-                                            type: number
-                                            format: double
-                                        label:
-                                            type: string
+                                type: object
+                                properties:
+                                    response:
+                                        $ref: '#/components/schemas/ApiResponse'
+                                    items:
+                                        type: array
+                                        items:
+                                            type: object
+                                            properties:
+                                                path:
+                                                    type: string
+                                                order:
+                                                    type: number
+                                                    format: double
+                                                label:
+                                                    type: string
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/api/studio-api.yaml` around lines 5349 - 5356, The 200 response
currently defines an array whose items each contain a per-item "response" field
(referenced as ApiResponse), which violates the v2 top-level envelope; change
the schema so the operation returns a single object with a top-level "response"
property whose value is the array of item objects. Concretely, replace the
existing schema: type: array / items: { type: object / properties: { response:
$ref: '#/components/schemas/ApiResponse', ... } } with schema: type: object /
properties: { response: { type: array, items: { type: object, properties: { /*
move item properties here except per-item response */ } } } } so ApiResponse is
referenced at the top-level "response" instead of per-item.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/main/api/studio-api.yaml`:
- Around line 5414-5415: The OpenAPI schema property named "order" is currently
declared as type: integer which will reject fractional reorder values; change
the "order" property in the studio-api YAML schema from type: integer to type:
number and (optionally) add format: double so fractional ordering values are
accepted (update the property definition for "order" accordingly).
- Around line 5349-5356: The 200 response currently defines an array whose items
each contain a per-item "response" field (referenced as ApiResponse), which
violates the v2 top-level envelope; change the schema so the operation returns a
single object with a top-level "response" property whose value is the array of
item objects. Concretely, replace the existing schema: type: array / items: {
type: object / properties: { response: $ref: '#/components/schemas/ApiResponse',
... } } with schema: type: object / properties: { response: { type: array,
items: { type: object, properties: { /* move item properties here except
per-item response */ } } } } so ApiResponse is referenced at the top-level
"response" instead of per-item.

In
`@src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java`:
- Around line 379-387: Implement the two stub endpoints to delegate to the
content service and return a proper Result: in getItemsOrder(String siteId,
String parentPath) call the service method that retrieves item order (e.g.,
contentService.getItemsOrder(siteId, parentPath) or equivalent), wrap the
returned data into a successful Result payload and return it; in
reorderItem(String siteId, ReorderItemRequest request) call the service method
that applies the reorder (e.g., contentService.reorderItem(siteId, request)),
handle validation/exceptions as before in this controller, and return a Result
indicating success (or the updated order) instead of null; keep existing
annotations (`@ValidSiteId`, `@ValidExistingContentPath`, `@Valid`) and reuse the
controller’s standard Result creation pattern/methods for consistent response
shape.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c55bed0-f18b-4dca-8965-7c0e4157c51f

📥 Commits

Reviewing files that changed from the base of the PR and between b9e01ce and a751208.

📒 Files selected for processing (23)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
💤 Files with no reviewable changes (17)
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/org/craftercms/studio/model/rest/content/ReorderItemRequest.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java

@jmendeza jmendeza force-pushed the feature/6061-item-orders branch from a751208 to e577469 Compare May 5, 2026 19:49
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/api/studio-api.yaml`:
- Around line 10750-10792: The base schema ReorderItemRequestBase currently
permits all three type values which allows invalid combinations; restrict the
subtype schemas by adding a concrete type enum in each allOf: update
ReorderItemReferencePathRequest to include a properties.type enum limited to the
reference-path variants (e.g., ["addBefore","addAfter"]) and update
ReorderItemInsertBetweenRequest to include properties.type enum
["insertBetween"] (or equivalent values you use for insertBetween), so each
derived schema narrows the allowed type and enforces correct discriminator
behavior.

In
`@src/main/java/org/craftercms/studio/model/rest/content/order/ReorderItemRequest.java`:
- Around line 34-35: Replace the `@NotEmpty` annotation with `@NotBlank` on all path
fields in the ReorderItemRequest class so whitespace-only strings are rejected
up-front; specifically update the annotations on parentPath, referencePath,
previousPath, nextPath (and the fifth path field annotated similarly) to use
javax.validation.constraints.NotBlank instead of NotEmpty so constraint
validation returns a 400 for blank paths before reaching
`@ValidExistingContentPath`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 50430f18-2688-4255-8792-2fde9650fdcf

📥 Commits

Reviewing files that changed from the base of the PR and between a751208 and e577469.

📒 Files selected for processing (23)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/rest/content/order/ReorderItemRequest.java
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
💤 Files with no reviewable changes (17)
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequence.java
  • src/main/java/org/craftercms/studio/api/v1/service/content/DmPageNavigationOrderService.java
  • src/main/webapp/default-site/scripts/api/ContentServices.groovy
  • src/main/webapp/default-site/scripts/api/impl/content/SpringPageNavigationOrderServices.groovy
  • src/main/webapp/default-site/scripts/api/PageNavigationOrderServices.groovy
  • src/main/resources/crafter/studio/database-context.xml
  • src/main/java/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.java
  • src/main/webapp/default-site/scripts/api/impl/content/SpringContentServices.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-item-orders.get.groovy
  • src/main/java/org/craftercms/studio/api/v1/service/content/ContentService.java
  • src/main/resources/crafter/studio/studio-services-context.xml
  • src/main/resources/org/craftercms/studio/api/v1/dal/NavigationOrderSequenceMapper.xml
  • src/main/webapp/default-site/scripts/rest/api/1/content/reorder-items.get.groovy
  • src/main/webapp/default-site/scripts/rest/api/1/content/get-next-item-order.get.groovy
  • src/test/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImplTest.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/DmPageNavigationOrderServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v1/service/content/ContentServiceImpl.java
✅ Files skipped from review due to trivial changes (2)
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/impl/v2/service/content/internal/ContentServiceInternalImpl.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/craftercms/studio/controller/rest/v2/ContentController.java
  • src/main/webapp/default-site/scripts/api/ServiceFactory.groovy

Comment thread src/main/api/studio-api.yaml
@jmendeza jmendeza force-pushed the feature/6061-item-orders branch 2 times, most recently from cc20aad to 816c727 Compare May 5, 2026 20:05
@jmendeza jmendeza force-pushed the feature/6061-item-orders branch from 816c727 to f2a4381 Compare May 22, 2026 22:35
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.

1 participant