Remove non positive integer constraint on Nav Menu Item (#18081)

To fit with position typed field logic + Ease favorite to nav menu item
migration (which have negative and float position)
This commit is contained in:
Etienne
2026-02-19 12:24:14 +01:00
committed by GitHub
parent 1a13258302
commit 9e54a8082c
7 changed files with 26 additions and 78 deletions
@@ -0,0 +1,19 @@
import { type MigrationInterface, type QueryRunner } from 'typeorm';
export class ChangeNavigationMenuItemPositionToDoublePrecision1771499112046
implements MigrationInterface
{
name = 'ChangeNavigationMenuItemPositionToDoublePrecision1771499112046';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "core"."navigationMenuItem" ALTER COLUMN "position" TYPE double precision`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "core"."navigationMenuItem" ALTER COLUMN "position" TYPE integer`,
);
}
}
@@ -97,7 +97,7 @@ export class NavigationMenuItemEntity
@Column({ nullable: true, type: 'uuid' })
folderId: string | null;
@Column({ nullable: false })
@Column({ nullable: false, type: 'double precision' })
position: number;
@CreateDateColumn({ type: 'timestamptz' })
@@ -177,13 +177,12 @@ export class FlatNavigationMenuItemValidatorService {
if (
isDefined(flatNavigationMenuItem.position) &&
(!Number.isInteger(flatNavigationMenuItem.position) ||
flatNavigationMenuItem.position < 0)
!Number.isFinite(flatNavigationMenuItem.position)
) {
validationResult.errors.push({
code: NavigationMenuItemExceptionCode.INVALID_NAVIGATION_MENU_ITEM_INPUT,
message: t`Position must be a non-negative integer`,
userFriendlyMessage: msg`Position must be a non-negative integer`,
message: t`Position must be a finite number`,
userFriendlyMessage: msg`Position must be a finite number`,
});
}
@@ -307,14 +306,11 @@ export class FlatNavigationMenuItemValidatorService {
const positionUpdate = flatEntityUpdate.position;
if (
isDefined(positionUpdate) &&
(!Number.isInteger(positionUpdate) || positionUpdate < 0)
) {
if (isDefined(positionUpdate) && !Number.isFinite(positionUpdate)) {
validationResult.errors.push({
code: NavigationMenuItemExceptionCode.INVALID_NAVIGATION_MENU_ITEM_INPUT,
message: t`Position must be a non-negative integer`,
userFriendlyMessage: msg`Position must be a non-negative integer`,
message: t`Position must be a finite number`,
userFriendlyMessage: msg`Position must be a finite number`,
});
}
@@ -142,14 +142,3 @@ exports[`NavigationMenuItem creation should fail when creating with missing targ
}
`;
exports[`NavigationMenuItem creation should fail when creating with negative position 1`] = `
{
"extensions": {
"code": "NOT_FOUND",
"subCode": "RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND",
"userFriendlyMessage": "An error occurred.",
},
"message": "Could not find objectMetadata for given targetObjectMetadataId",
"name": "NotFoundError",
}
`;
@@ -71,38 +71,3 @@ exports[`NavigationMenuItem update should fail when updating with missing id 1`]
"name": "ValidationError",
}
`;
exports[`NavigationMenuItem update should fail when updating with negative position 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"navigationMenuItem": [
{
"errors": [
{
"code": "INVALID_NAVIGATION_MENU_ITEM_INPUT",
"message": "Position must be a non-negative integer",
"userFriendlyMessage": "Position must be a non-negative integer",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "navigationMenuItem",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 navigationMenuItem",
"summary": {
"navigationMenuItem": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Metadata validation failed",
},
"message": "Multiple validation errors occurred while updating navigation menu item",
"name": "GraphQLError",
}
`;
@@ -86,16 +86,6 @@ const failingNavigationMenuItemCreationTestCases: EachTestingContext<TestContext
},
},
},
{
title: 'when creating with negative position',
context: {
input: {
targetRecordId: faker.string.uuid(),
targetObjectMetadataId: faker.string.uuid(),
position: -1,
},
},
},
];
describe('NavigationMenuItem creation should fail', () => {
@@ -130,17 +130,6 @@ describe('NavigationMenuItem update should fail', () => {
}),
},
},
{
title: 'when updating with negative position',
context: {
input: (testSetup) => ({
id: testSetup.testNavigationMenuItemId,
update: {
position: -1,
},
}),
},
},
];
it.each(eachTestingContextFilter(failingNavigationMenuItemUpdateTestCases))(