Introduce standalone page (#19675)

Add support for standalone pages: a new `PageLayout` type
(`STANDALONE_PAGE`) that can be rendered independently at
`/page/:pageLayoutId`, not tied to any record or object context.

- New `STANDALONE_PAGE` page layout type
- New `PAGE_LAYOUT` navigation menu item type: adds a `pageLayoutId`
foreign key to `NavigationMenuItemEntity`, allowing sidebar items to
link directly to standalone pages
- New `GLOBAL_OBJECT_CONTEXT` command menu availability type: separates
object-context-dependent commands (Create Record, Import, Export, See
Deleted, Create View, Hide Deleted) from truly global ones, so
standalone pages only show relevant commands
- Frontend routing & rendering: adds a `/page/:pageLayoutId` route with
its own page component, header, and command menu
- Widget rendering refactor
- Instance commands: two fast 1.22 migrations: `pageLayoutId` column +
`STANDALONE_PAGE` enum, and `GLOBAL_OBJECT_CONTEXT` availability type
enum
- Workspace command: backfills existing command menu items from `GLOBAL`
to `GLOBAL_OBJECT_CONTEXT` where appropriate
- Dev seeds: adds a sample "Star History" standalone page with an iframe
widget for local development
This commit is contained in:
Raphaël Bosi
2026-04-14 17:52:45 +02:00
committed by GitHub
parent 43249d80e8
commit a88d1f4442
122 changed files with 2250 additions and 836 deletions
@@ -1169,6 +1169,11 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
toStringify: false,
universalProperty: 'targetObjectMetadataUniversalIdentifier',
},
pageLayoutId: {
toCompare: false,
toStringify: false,
universalProperty: 'pageLayoutUniversalIdentifier',
},
},
permissionFlag: {
flag: {
@@ -64,6 +64,9 @@ export const ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY = {
view: {
foreignKey: 'viewId',
},
pageLayout: {
foreignKey: 'pageLayoutId',
},
},
fieldMetadata: {
object: {
@@ -112,6 +112,13 @@ export const ALL_MANY_TO_ONE_METADATA_RELATIONS = {
isNullable: true,
universalForeignKey: 'viewUniversalIdentifier',
},
pageLayout: {
metadataName: 'pageLayout',
foreignKey: 'pageLayoutId',
inverseOneToManyProperty: null,
isNullable: true,
universalForeignKey: 'pageLayoutUniversalIdentifier',
},
},
fieldMetadata: {
object: {
@@ -73,6 +73,7 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
navigationMenuItem: {
objectMetadata: true,
view: true,
pageLayout: true,
},
permissionFlag: {
role: true,
@@ -44,6 +44,7 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
"objectMetadata",
"navigationMenuItem",
"view",
"pageLayout",
]
`;
@@ -3,8 +3,8 @@
exports[`sortMetadataNamesChildrenFirst should return metadata names sorted with children first (most manyToOne relations first) 1`] = `
[
"rowLevelPermissionPredicate",
"fieldPermission",
"navigationMenuItem",
"fieldPermission",
"viewField",
"viewFilter",
"commandMenuItem",