[FRONT COMPONENTS] Headless components (#18096)
## Description - Add `isHeadless` field to `FrontComponent` entity so front components can run without rendering UI in the command menu - Introduce headless front component mounting logic: `HeadlessFrontComponentMountRoot` at the application root, `useMountHeadlessFrontComponent`, and `useUnmountHeadlessFrontComponent` hooks to mount/unmount headless components - Expand the SDK with new action components (`Action`, `ActionLink`, `ActionOpenSidePanelPage`) and host communication functions (`openSidePanelPage`, `unmountFrontComponent`) - Move `CommandMenuPages` type to twenty-shared so the SDK can reference it for side panel navigation ## Video QA https://github.com/user-attachments/assets/4f9e3bb1-fcd1-42be-b3f4-a97e80c2add2
This commit is contained in:
+1
@@ -59,6 +59,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should ma
|
||||
"sourceComponentPath",
|
||||
"builtComponentPath",
|
||||
"componentName",
|
||||
"isHeadless",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
|
||||
+5
@@ -1221,6 +1221,11 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
isHeadless: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
createdAt: {
|
||||
toCompare: false,
|
||||
toStringify: false,
|
||||
|
||||
+1
@@ -7,4 +7,5 @@ export const FLAT_FRONT_COMPONENT_EDITABLE_PROPERTIES = [
|
||||
'sourceComponentPath',
|
||||
'builtComponentPath',
|
||||
'componentName',
|
||||
'isHeadless',
|
||||
] as const satisfies MetadataEntityPropertyName<'frontComponent'>[];
|
||||
|
||||
+1
@@ -33,6 +33,7 @@ export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
|
||||
builtComponentPath: createFrontComponentInput.builtComponentPath,
|
||||
componentName: createFrontComponentInput.componentName,
|
||||
builtComponentChecksum: createFrontComponentInput.builtComponentChecksum,
|
||||
isHeadless: false,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ export const fromFlatFrontComponentToFrontComponentDto = (
|
||||
: undefined,
|
||||
workspaceId: flatFrontComponent.workspaceId,
|
||||
applicationId: flatFrontComponent.applicationId,
|
||||
isHeadless: flatFrontComponent.isHeadless,
|
||||
createdAt: new Date(flatFrontComponent.createdAt),
|
||||
updatedAt: new Date(flatFrontComponent.updatedAt),
|
||||
});
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ export const fromFrontComponentEntityToFlatFrontComponent = ({
|
||||
builtComponentPath: frontComponentEntity.builtComponentPath,
|
||||
componentName: frontComponentEntity.componentName,
|
||||
builtComponentChecksum: frontComponentEntity.builtComponentChecksum,
|
||||
isHeadless: frontComponentEntity.isHeadless,
|
||||
workspaceId: frontComponentEntity.workspaceId,
|
||||
universalIdentifier: frontComponentEntity.universalIdentifier,
|
||||
applicationId: frontComponentEntity.applicationId,
|
||||
|
||||
+5
@@ -1,6 +1,7 @@
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
IsBoolean,
|
||||
IsDateString,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
@@ -63,6 +64,10 @@ export class FrontComponentDTO {
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@IsBoolean()
|
||||
@Field()
|
||||
isHeadless: boolean;
|
||||
|
||||
@Field(() => ApplicationTokenPairDTO, { nullable: true })
|
||||
applicationTokenPair?: ApplicationTokenPairDTO;
|
||||
}
|
||||
|
||||
+3
@@ -34,6 +34,9 @@ export class FrontComponentEntity
|
||||
@Column({ nullable: false })
|
||||
builtComponentChecksum: string;
|
||||
|
||||
@Column({ default: false })
|
||||
isHeadless: boolean;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user