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:
+1
@@ -62,6 +62,7 @@ export const PinnedCommandMenuItemButtonsEditMode = () => {
|
||||
() =>
|
||||
new Set<CommandMenuItemAvailabilityType>([
|
||||
CommandMenuItemAvailabilityType.GLOBAL,
|
||||
CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
|
||||
mainContextStoreHasSelectedRecords
|
||||
? CommandMenuItemAvailabilityType.RECORD_SELECTION
|
||||
: CommandMenuItemAvailabilityType.FALLBACK,
|
||||
|
||||
+17
-8
@@ -21,7 +21,7 @@ import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomState
|
||||
import { type DropResult } from '@hello-pangea/dnd';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CommandMenuContextApiPageType } from 'twenty-shared/types';
|
||||
import { ContextStorePageType } from 'twenty-shared/types';
|
||||
import {
|
||||
interpolateCommandMenuItemTemplate,
|
||||
isDefined,
|
||||
@@ -71,9 +71,13 @@ export const SidePanelCommandMenuItemEditPage = () => {
|
||||
const currentObjectMetadataItemId =
|
||||
commandMenuContextApi.objectMetadataItem.id;
|
||||
|
||||
const hasObjectContext = isDefined(currentObjectMetadataItemId);
|
||||
|
||||
const isRecordPage =
|
||||
commandMenuContextApi.pageType ===
|
||||
CommandMenuContextApiPageType.RECORD_PAGE;
|
||||
commandMenuContextApi.pageType === ContextStorePageType.Record;
|
||||
|
||||
const isIndexPage =
|
||||
commandMenuContextApi.pageType === ContextStorePageType.Index;
|
||||
|
||||
const mainContextStoreHasSelectedRecords = useAtomStateValue(
|
||||
mainContextStoreHasSelectedRecordsSelector,
|
||||
@@ -93,6 +97,9 @@ export const SidePanelCommandMenuItemEditPage = () => {
|
||||
|
||||
const allowedAvailabilityTypes = new Set<CommandMenuItemAvailabilityType>([
|
||||
CommandMenuItemAvailabilityType.GLOBAL,
|
||||
...(isIndexPage || isRecordPage
|
||||
? [CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT]
|
||||
: []),
|
||||
mainContextStoreHasSelectedRecords
|
||||
? CommandMenuItemAvailabilityType.RECORD_SELECTION
|
||||
: CommandMenuItemAvailabilityType.FALLBACK,
|
||||
@@ -231,11 +238,13 @@ export const SidePanelCommandMenuItemEditPage = () => {
|
||||
|
||||
return (
|
||||
<StyledContainer data-click-outside-id={COMMAND_MENU_CLICK_OUTSIDE_ID}>
|
||||
<StyledViewbar>
|
||||
<CommandMenuItemEditRecordSelectionDropdown
|
||||
isRecordPage={isRecordPage}
|
||||
/>
|
||||
</StyledViewbar>
|
||||
{hasObjectContext && (
|
||||
<StyledViewbar>
|
||||
<CommandMenuItemEditRecordSelectionDropdown
|
||||
isRecordPage={isRecordPage}
|
||||
/>
|
||||
</StyledViewbar>
|
||||
)}
|
||||
<StyledContent>
|
||||
<SidePanelList selectableItemIds={selectableItemIds}>
|
||||
<SidePanelGroup heading={t`Pinned`}>
|
||||
|
||||
Reference in New Issue
Block a user