Files
twenty/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/standard-command-menu-item.constant.ts
T
Marie 1d755983ff Feat/advanced text editor capability presets (#23657)
# Email editor for Compose campaigns

## Short version

Campaign bodies are currently plain rich text. This PR turns the
composer into an email editor: a centered email canvas with section,
column, button, divider, image and raw-HTML blocks, each editable
through a settings side panel, rendered to email-safe HTML per recipient
at send time. Modelled on Resend's Broadcast editor.

**Product**

- Email canvas with page/body styling (background, width, padding,
corner radius, border, text colour, alignment)
- Blocks: section, 2/3 columns, button, divider, raw HTML, images —
insertable from a floating left rail or the slash menu
- A **section is a container whose typography cascades to its
contents**, so one part of an email can have its own look
- Block settings panel focuses whatever you select and shows its
effective values
- Per-recipient variables (`{{firstName}}`, `{{lastName}}`,
`{{fullName}}`, `{{email}}`, `{{personId}}`) usable in text,
button/link/image URLs, image labels and raw HTML
- Image upload by drag-drop, paste or file picker

**Technical**

- Presets now declare **capabilities** instead of surfaces forking the
editor; the UI derives itself from loaded extensions
- Editor behavior lives in `twenty-front`; the versioned email-document
schema and structural traversal live in `twenty-shared`; rendering lives
in `twenty-emails` — HTML is produced server-side per recipient
- Section typography cascade is **resolved at render time**, not left to
CSS: react-email hardcodes `fontSize`/`lineHeight` on every paragraph
and Outlook ignores `inherit`
- Logic vendored from Resend (MIT); all controls rebuilt on `twenty-ui`
+ Linaria

**Also fixes:** the unsubscribe footer was being appended *after*
`</html>`, outside the document, where Gmail strips it — legally
significant since unsubscribe is required.


---

## Detailed version

### Product requirements

**Problem.** The Compose campaign body was a single rich-text field.
Marketing email needs layout — banded sections, columns, call-to-action
buttons, images with links — and it needs that layout to survive
Outlook, which means table-based HTML rather than the divs a text editor
produces. It also needs per-recipient personalisation.

**Reference.** Resend's Broadcast editor, chosen because it solves the
same problem (TipTap authoring → react-email output) and is MIT
licensed.

#### What a user can now do

| Area | Capability |
|---|---|
| Canvas | Email renders as a centered page with its own background,
width, padding, corner radius and border |
| Blocks | Section, 2/3 columns, button, divider, raw HTML, image |
| Insertion | Floating left rail (pointer-first) or the `/` slash menu
(keyboard-first) |
| Sections | Own text colour, font size, line height, letter spacing and
alignment, cascading to everything inside |
| Images | Upload by drag-drop, paste or picker; link URL, alt text,
width, spacing, border |
| Raw HTML | Edited as source in the panel, previewed on the canvas with
scripts neutralised |
| Variables | `{{firstName}}`, `{{lastName}}`, `{{fullName}}`,
`{{email}}`, `{{personId}}` in text, button URLs, link hrefs and raw
HTML |
| Settings panel | Follows selection; shows effective values; opens
automatically when a block is clicked |

#### Deliberate product decisions

- **Variables display as literal placeholders**, not prose labels, so
the syntax is copyable into HTML blocks and button URLs by hand.
- **Sections inherit until they override.** The panel shows what
actually renders rather than blank fields, but writes nothing until you
edit — so changing the body text colour still flows into sections.
- **Headings keep their own scale** inside a styled section; only
colour, family and spacing cascade, otherwise every heading would
collapse to body size.
- **Clicking a block opens its settings**, but only on whole-node
selections, so typing inside a section does not reopen a panel you just
closed.

### Technical strategy

#### 1. Capability presets (the foundation)

Per-surface variation previously worked by **forking**: three separate
`useEditor` call sites with hardcoded extension arrays. Inside the
shared tree there was no variation at all — all five surfaces received a
byte-identical extension list, and presets controlled only sizing,
chrome and serialization format. Adding email blocks that way meant
either leaking section/column nodes into the record rich-text field and
workflow email body, or writing a fourth fork.

Now:

- a preset declares a **capability list** (`basicMarks`, `headings`,
`lists`, `links`, `images`, `campaignVariables`, `slashCommand`,
`blocks`, `mentions`)
- capabilities resolve to extensions through a factory registry
- the UI derives itself from the loaded extensions via
`hasEditorExtension` — no capability list is prop-drilled into a menu,
because the `Editor` already knows what it can do

The acceptance test was collapsing the AI chat fork into an `aiChat`
preset with no visible change to that composer. `campaignBody` is the
only preset opting into the shared `EMAIL_DOCUMENT_CAPABILITIES` today.
Workflow email keeps its current field UI, but can opt into the same
canvas, block settings and image uploader later without adding another
schema or renderer.

#### 2. Schema / renderer split

The hard constraint: **our HTML is produced server-side, per recipient,
at send time**, because variables substitute into nodes rather than into
a serialized string. That rules out Resend's
`renderToReactEmail`-on-the-extension pattern.

```
twenty-front     TipTap extensions + node views + shared email settings UI
twenty-shared    versioned email-document schema + structural traversal
twenty-emails    react-email renderers (imported by twenty-server)
twenty-server    surface-specific variable resolution, validation, send
```

Logic was **vendored, not depended on** — Resend's TipTap is 3.17
against our 3.4, and their UI is Radix. We copied the schema/serializer
approach and rebuilt every control on `twenty-ui` + Linaria.

#### 3. Section typography cascade

The subtle part, and the one that would have silently shipped broken.

Section typography *looks* like it should cascade via CSS. It does not:

```js
// react-email's Text
style: { fontSize: "14px", lineHeight: "24px", ...style, ...margins }
```

Every paragraph re-declares `fontSize` and `lineHeight`, overriding any
enclosing section. `inherit` is not a fix either — Outlook's Word engine
ignores it.

So the cascade is **resolved in the renderer**: the tree walk threads
the enclosing section's typography down and writes computed values
explicitly onto each text node. Nested sections refine what they
inherit.

Verified against real rendered output:

| | rendered |
|---|---|
| paragraph inside section | `font-size:22px; color:rgb(255,0,0);
letter-spacing:2px` |
| h1 inside section | `font-size:32px` (own scale) + section colour and
spacing |
| paragraph outside | `font-size:14px`, no colour — untouched |

#### 4. Storage

`bodyTemplate` stays serialized TipTap JSON in a `TEXT` column. Block
attributes are ProseMirror node attrs, so richer blocks add keys to JSON
already being serialized — no migration, and it flows into the existing
500 ms debounced draft save unchanged.

Since the feature has not shipped, the legacy HTML-string body path was
removed rather than maintained. That is a tightening, not just a
deletion: `bodyTemplate` is writable through the record API, and the old
fallback would interpolate an arbitrary string and email it as markup. A
body that is neither empty nor a valid TipTap document is now rejected
at the send gate.

#### 5. Image hosting

Inline assets use an `EmailImage` file folder with
`ignoreExpirationToken: true` and immutable cache headers, because
recipients' mail clients never authenticate and may open an email years
later. The shared uploader returns `{ fileId, url }`; the image node
keeps both the durable file identity and its delivery URL so
ownership/lifecycle or URL resolution can evolve later without a
document migration. The server verifies the uploaded bytes and only
accepts GIF, JPEG, PNG and WebP.

This is intentionally separate from workflow/email **attachments**.
Attachments remain private files that the server reads and embeds as
MIME parts at send time; inline images need a durable recipient-facing
URL. A future workflow canvas should reuse `useUploadEmailImage` for
inline content while keeping its existing attachment control unchanged.

Adding the folder requires three registrations — the folder config, the
route guard's `SUPPORTED_FILE_FOLDERS`, and `DIRECT_UPLOAD_FILE_FOLDERS`
in the upload service.

### Bugs fixed along the way

- **Unsubscribe footer was appended after `</html>`**, outside the
document, where Gmail strips it. Legally significant, since an
unsubscribe link is required. Now inserted before `</body>`.
- **Body text colour never reached the email.**
- **`onImageUpload` was declared but never passed** by any production
call site, so drag-drop and paste image upload were inert everywhere
outside Storybook.
- **Message lists were not user-facing**, so members could not be added
from the list page.
- **Image resize wrote an undeclared `width` attribute** that TipTap
silently dropped.
- **The text bubble menu appeared over selected atom blocks** with
nothing to format.

### Review notes / known limitations

**Security posture to check.** Anything in `EmailImage` is readable by
anyone holding the URL, forever. The server now enforces an image-only
MIME allowlist from sniffed bytes, but it cannot determine whether the
image itself is confidential. This remains a deliberate trade-off for
recipient-visible inline assets.

**Test gap.** The section typography cascade has no regression test:
react-email's `render()` hangs under Jest (tried 60s), and
`twenty-emails` has no test target at all. Verified by rendering through
the built package instead. Adding a test target there is worthwhile
follow-up.

**Sending needs configuration.** `EMAILING_DOMAIN_DRIVER` defaults to
`LOG`, which fakes a messageId, reports any domain as verified, and only
logs — a campaign reaches "sent" with nothing delivered. Real sending
needs `AWS_SES`.

**Unrelated platform bug found.** The pinned "Create new record" command
throws on viewless objects like `messageListMember`, because
`recordIndexId` derives from the current view.

**Not done.** Panel chrome from the reference: breadcrumb (`Page style /
Section`), collapsible groups, per-side spacing grid, and a
variable-insert button inside link fields. All presentation over the
same data.

**Deferred.** Drag-to-reorder blocks.
`@tiptap/extension-drag-handle-react@3.4.2` matches our pinned versions
exactly, so no upgrade is needed, but its behaviour around atom node
views (HTML block, image) is unverified and belongs in its own change.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23657?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2026-08-05 10:38:06 +00:00

1095 lines
46 KiB
TypeScript

import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/enums/command-menu-item-availability-type.enum';
import { EngineComponentKey } from 'src/engine/metadata-modules/command-menu-item/enums/engine-component-key.enum';
export const STANDARD_COMMAND_MENU_ITEMS = {
navigateToNextRecord: {
universalIdentifier: '3db2457d-8e96-4b8e-94c9-ed95d3f95738',
label: 'Navigate to next ${capitalize(objectMetadataItem.labelSingular)}',
icon: 'IconChevronDown',
isPinned: true,
position: 1,
shortLabel: null,
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and not isInSidePanel and objectMetadataItem.nameSingular != "messageCampaign"',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATE_TO_NEXT_RECORD,
hotKeys: null,
},
navigateToPreviousRecord: {
universalIdentifier: 'ec10f871-415b-420b-8150-7e09f6f04833',
label:
'Navigate to previous ${capitalize(objectMetadataItem.labelSingular)}',
icon: 'IconChevronUp',
isPinned: true,
position: 2,
shortLabel: null,
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and not isInSidePanel and objectMetadataItem.nameSingular != "messageCampaign"',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATE_TO_PREVIOUS_RECORD,
hotKeys: null,
},
createNewRecord: {
universalIdentifier: '08d255bf-58cd-47a5-bd82-78c5c58592f1',
label: 'Create new ${capitalize(objectMetadataItem.labelSingular)}',
icon: 'IconPlus',
isPinned: true,
position: 3,
shortLabel: 'New ${capitalize(objectMetadataItem.labelSingular)}',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and objectPermissions.canUpdateObjectRecords and not hasAnySoftDeleteFilterOnView and objectMetadataItem.isUICreatable and objectMetadataItem.isUIEditable and not objectMetadataItem.isRemote',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.CREATE_NEW_RECORD,
hotKeys: null,
},
deleteRecords: {
universalIdentifier: 'd5a55d57-ed1d-4791-89b8-53b7e121d69d',
label: 'Delete ${capitalize(objectMetadataLabel)}',
icon: 'IconTrash',
isPinned: false,
position: 4,
shortLabel: 'Delete',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and not hasAnySoftDeleteFilterOnView and objectPermissions.canSoftDeleteObjectRecords and (isSelectAll or noneDefined(selectedRecords, "deletedAt"))',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DELETE_RECORDS,
hotKeys: null,
},
restoreRecords: {
universalIdentifier: '2d733846-8cc5-4314-ab79-916ae0801baa',
label: 'Restore ${capitalize(objectMetadataLabel)}',
icon: 'IconRefresh',
isPinned: true,
position: 5,
shortLabel: 'Restore',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and (isSelectAll or everyDefined(selectedRecords, "deletedAt")) and objectPermissions.canSoftDeleteObjectRecords and (pageType == "RECORD_PAGE" or hasAnySoftDeleteFilterOnView)',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.RESTORE_RECORDS,
hotKeys: null,
},
destroyRecords: {
universalIdentifier: '0ea2ebc4-02ca-4d15-b424-5352b9e487df',
label: 'Permanently destroy ${capitalize(objectMetadataLabel)}',
icon: 'IconTrashX',
isPinned: false,
position: 6,
shortLabel: 'Destroy',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and objectPermissions.canDestroyObjectRecords and (isSelectAll or everyDefined(selectedRecords, "deletedAt")) and (pageType == "RECORD_PAGE" or hasAnySoftDeleteFilterOnView)',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DESTROY_RECORDS,
hotKeys: null,
},
addToFavorites: {
universalIdentifier: '38bf80c3-bd55-4753-80ba-38aa66429a03',
label: 'Add to Favorites',
icon: 'IconHeart',
isPinned: true,
position: 7,
shortLabel: null,
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'arrayLength(favoriteRecordIds) < numberOfSelectedRecords and noneDefined(selectedRecords, "deletedAt") and not hasAnySoftDeleteFilterOnView and objectMetadataItem.nameSingular != "messageCampaign"',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.ADD_TO_FAVORITES,
hotKeys: null,
},
removeFromFavorites: {
universalIdentifier: '3ea42507-44fa-4895-a36d-cbfef7355a50',
label: 'Remove from Favorites',
icon: 'IconHeartOff',
isPinned: true,
position: 8,
shortLabel: null,
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'arrayLength(favoriteRecordIds) == numberOfSelectedRecords and noneDefined(selectedRecords, "deletedAt") and not hasAnySoftDeleteFilterOnView and objectMetadataItem.nameSingular != "messageCampaign"',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.REMOVE_FROM_FAVORITES,
hotKeys: null,
},
exportNoteToPdf: {
universalIdentifier: '86c8f3aa-9276-4c16-8cff-e295e34fbaf0',
label: 'Export to PDF',
icon: 'IconFileExport',
isPinned: false,
position: 9,
shortLabel: 'Export',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and (objectMetadataItem.nameSingular == "note" or objectMetadataItem.nameSingular == "task") and someNonEmptyString(selectedRecords, "bodyV2.blocknote")',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EXPORT_NOTE_TO_PDF,
hotKeys: null,
},
exportRecords: {
universalIdentifier: 'c6f5c54d-d52b-4e75-8188-2190d77126f2',
label: 'Export ${capitalize(objectMetadataLabel)}',
icon: 'IconFileExport',
isPinned: false,
position: 10,
shortLabel: 'Export',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression: 'permissionFlags.EXPORT_CSV',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EXPORT_RECORDS,
hotKeys: null,
},
updateMultipleRecords: {
universalIdentifier: '2e080651-f098-4a78-bea9-7a70002dc57c',
label: 'Update ${capitalize(objectMetadataItem.labelPlural)}',
icon: 'IconEdit',
isPinned: true,
position: 11,
shortLabel: 'Update',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 2 and objectPermissions.canUpdateObjectRecords',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.UPDATE_MULTIPLE_RECORDS,
hotKeys: null,
},
mergeMultipleRecords: {
universalIdentifier: '6c14eb04-8e7e-4d47-93c0-8ec4834e2e60',
label: 'Merge ${capitalize(objectMetadataItem.labelPlural)}',
icon: 'IconArrowMerge',
isPinned: false,
position: 12,
shortLabel: 'Merge',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'not isSelectAll and numberOfSelectedRecords >= 2 and isDefined(objectMetadataItem.duplicateCriteria) and objectPermissions.canUpdateObjectRecords and objectPermissions.canDestroyObjectRecords and numberOfSelectedRecords <= 9',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.MERGE_MULTIPLE_RECORDS,
hotKeys: null,
},
importRecords: {
universalIdentifier: 'a2dc9de7-4798-422e-bb55-bfad7b9bdbe8',
label: 'Import ${capitalize(objectMetadataItem.labelPlural)}',
icon: 'IconFileImport',
isPinned: false,
position: 13,
shortLabel: 'Import',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and not hasAnySoftDeleteFilterOnView and permissionFlags.IMPORT_CSV',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.IMPORT_RECORDS,
hotKeys: null,
},
exportView: {
universalIdentifier: '80680f2a-c426-48b3-a839-c63a6183dc4b',
label: 'Export View',
icon: 'IconFileExport',
isPinned: false,
position: 14,
shortLabel: 'Export',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and permissionFlags.EXPORT_CSV',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EXPORT_VIEW,
hotKeys: null,
},
seeDeletedRecords: {
universalIdentifier: 'd63c21c3-9785-4750-be87-5f36269b8e0d',
label: 'See deleted ${capitalize(objectMetadataItem.labelPlural)}',
icon: 'IconRotate2',
isPinned: false,
position: 15,
shortLabel: 'Deleted ${capitalize(objectMetadataItem.labelPlural)}',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and not hasAnySoftDeleteFilterOnView',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_DELETED_RECORDS,
hotKeys: null,
},
createNewView: {
universalIdentifier: '6ec7c339-e167-431d-bec6-d1c737df677c',
label: 'Create View',
icon: 'IconLayout',
isPinned: false,
position: 16,
shortLabel: 'Create View',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and not hasAnySoftDeleteFilterOnView',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.CREATE_NEW_VIEW,
hotKeys: null,
},
hideDeletedRecords: {
universalIdentifier: '1420db7f-0fba-49e2-b23e-4b7caa0fafa0',
label: 'Hide deleted ${capitalize(objectMetadataItem.labelPlural)}',
icon: 'IconEyeOff',
isPinned: false,
position: 17,
shortLabel: 'Hide deleted',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and hasAnySoftDeleteFilterOnView',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.HIDE_DELETED_RECORDS,
hotKeys: null,
},
editRecordPageLayout: {
universalIdentifier: 'd9794c67-1799-424f-8871-5ea771dd4a6d',
label: 'Edit Layout',
icon: 'IconPencil',
isPinned: false,
position: 18,
shortLabel: 'Edit Layout',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and not isLayoutCustomizationModeEnabled and noneDefined(selectedRecords, "deletedAt") and objectPermissions.canUpdateObjectRecords and objectMetadataItem.nameSingular != "dashboard"',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EDIT_RECORD_PAGE_LAYOUT,
hotKeys: null,
},
editDashboardLayout: {
universalIdentifier: 'b9b53bbc-3129-4eb9-8344-c3f9628ffa7d',
label: 'Edit Dashboard',
icon: 'IconPencil',
isPinned: true,
position: 19,
shortLabel: 'Edit',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and not isDashboardPageLayoutInEditMode and not isLayoutCustomizationModeEnabled and noneDefined(selectedRecords, "deletedAt") and everyDefined(selectedRecords, "pageLayoutId") and objectPermissions.canUpdateObjectRecords',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.dashboard.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EDIT_DASHBOARD_LAYOUT,
hotKeys: null,
},
saveDashboardLayout: {
universalIdentifier: '18b23908-f816-42ab-bc0a-eb5fae29c695',
label: 'Save Dashboard',
icon: 'IconDeviceFloppy',
isPinned: true,
position: 20,
shortLabel: 'Save',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and isDashboardPageLayoutInEditMode and noneDefined(selectedRecords, "deletedAt") and everyDefined(selectedRecords, "pageLayoutId") and objectPermissions.canUpdateObjectRecords',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.dashboard.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SAVE_DASHBOARD_LAYOUT,
hotKeys: null,
},
cancelDashboardLayout: {
universalIdentifier: '030ecd01-0aaf-4e6d-8400-105996548887',
label: 'Cancel Edition',
icon: 'IconCancel',
isPinned: true,
position: 21,
shortLabel: 'Cancel',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and isDashboardPageLayoutInEditMode and noneDefined(selectedRecords, "deletedAt") and everyDefined(selectedRecords, "pageLayoutId") and objectPermissions.canUpdateObjectRecords',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.dashboard.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.CANCEL_DASHBOARD_LAYOUT,
hotKeys: null,
},
duplicateDashboard: {
universalIdentifier: '2ee07307-60ce-41ef-bfee-7c718f67557e',
label: 'Duplicate Dashboard',
icon: 'IconCopyPlus',
isPinned: false,
position: 22,
shortLabel: 'Duplicate',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'noneDefined(selectedRecords, "deletedAt") and objectPermissions.canUpdateObjectRecords',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.dashboard.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DUPLICATE_DASHBOARD,
hotKeys: null,
},
activateWorkflow: {
universalIdentifier: '44f19c85-0fd0-482f-a14e-da513c60b1b3',
label: 'Activate Workflow',
icon: 'IconPower',
isPinned: true,
position: 23,
shortLabel: 'Activate',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "currentVersion.trigger") and everyDefined(selectedRecords, "currentVersion.steps") and every(selectedRecords, "currentVersion.steps.length") and (everyEquals(selectedRecords, "currentVersion.status", "DRAFT") or includesNone(selectedRecords, "statuses", "ACTIVE")) and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.ACTIVATE_WORKFLOW,
hotKeys: null,
},
deactivateWorkflow: {
universalIdentifier: '57f21a06-a17a-47b1-a123-90d90dbdf0b7',
label: 'Deactivate Workflow',
icon: 'IconPlayerPause',
isPinned: true,
position: 24,
shortLabel: 'Deactivate',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyEquals(selectedRecords, "currentVersion.status", "ACTIVE") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DEACTIVATE_WORKFLOW,
hotKeys: null,
},
discardDraftWorkflow: {
universalIdentifier: '4c227f2e-03bb-4a66-9b13-49f263264f4a',
label: 'Discard Draft',
icon: 'IconNoteOff',
isPinned: true,
position: 25,
shortLabel: 'Discard Draft',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'every(selectedRecords, "lastPublishedVersionId") and everyEquals(selectedRecords, "currentVersion.status", "DRAFT") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DISCARD_DRAFT_WORKFLOW,
hotKeys: null,
},
testWorkflow: {
universalIdentifier: 'f85d552a-87a3-4667-99f7-71b47917539c',
label: 'Test Workflow',
icon: 'IconPlayerPlay',
isPinned: true,
position: 26,
shortLabel: 'Test',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "currentVersion.trigger") and everyDefined(selectedRecords, "currentVersion.steps") and every(selectedRecords, "currentVersion.steps.length") and ((everyEquals(selectedRecords, "currentVersion.trigger.type", "MANUAL") and noneDefined(selectedRecords, "currentVersion.trigger.settings.objectType")) or everyEquals(selectedRecords, "currentVersion.trigger.type", "WEBHOOK") or everyEquals(selectedRecords, "currentVersion.trigger.type", "CRON")) and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.TEST_WORKFLOW,
hotKeys: null,
},
seeActiveVersionWorkflow: {
universalIdentifier: '31790508-75ff-4e4c-a768-83bd1b0718e0',
label: 'See Active Version',
icon: 'IconVersions',
isPinned: false,
position: 27,
shortLabel: 'See Active Version',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'includesEvery(selectedRecords, "statuses", "ACTIVE") and includesEvery(selectedRecords, "statuses", "DRAFT") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_ACTIVE_VERSION_WORKFLOW,
hotKeys: null,
},
seeRunsWorkflow: {
universalIdentifier: 'e57efc2d-00a2-493a-b76c-f2dabd23a5eb',
label: 'See Runs',
icon: 'IconHistoryToggle',
isPinned: true,
position: 28,
shortLabel: 'See Runs',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_RUNS_WORKFLOW,
hotKeys: null,
},
seeVersionsWorkflow: {
universalIdentifier: '92781d24-b875-4282-8cdb-d127f04a5c7d',
label: 'See Versions History',
icon: 'IconVersions',
isPinned: false,
position: 29,
shortLabel: 'See Versions',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_VERSIONS_WORKFLOW,
hotKeys: null,
},
addNodeWorkflow: {
universalIdentifier: '818117fa-6cad-4ebc-83c1-40f4afc28d94',
label: 'Add a Node',
icon: 'IconPlus',
isPinned: true,
position: 30,
shortLabel: 'Add a Node',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and everyDefined(selectedRecords, "currentVersion.trigger") and everyDefined(selectedRecords, "currentVersion.steps") and every(selectedRecords, "currentVersion.steps.length") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.ADD_NODE_WORKFLOW,
hotKeys: null,
},
tidyUpWorkflow: {
universalIdentifier: '1f3a3cab-161a-4775-af47-11be4d0bf411',
label: 'Tidy up Workflow',
icon: 'IconReorder',
isPinned: false,
position: 31,
shortLabel: 'Tidy up',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and everyDefined(selectedRecords, "currentVersion.trigger") and everyDefined(selectedRecords, "currentVersion.steps") and every(selectedRecords, "currentVersion.steps.length") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.TIDY_UP_WORKFLOW,
hotKeys: null,
},
duplicateWorkflow: {
universalIdentifier: '91094438-b4c2-46ad-a23b-8af4b23ba514',
label: 'Duplicate Workflow',
icon: 'IconCopy',
isPinned: false,
position: 32,
shortLabel: 'Duplicate',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "currentVersion") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflow.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.DUPLICATE_WORKFLOW,
hotKeys: null,
},
seeVersionWorkflowRun: {
universalIdentifier: 'cc3a065c-c89e-40ac-9449-4272c55b1bb8',
label: 'See Version',
icon: 'IconVersions',
isPinned: true,
position: 33,
shortLabel: 'See Version',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowRun.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_VERSION_WORKFLOW_RUN,
hotKeys: null,
},
seeWorkflowWorkflowRun: {
universalIdentifier: '9d9cc62d-3543-45c3-93f3-23d2d8979f2b',
label: 'See Workflow',
icon: 'IconSettingsAutomation',
isPinned: true,
position: 34,
shortLabel: 'See Workflow',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowRun.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_WORKFLOW_WORKFLOW_RUN,
hotKeys: null,
},
stopWorkflowRun: {
universalIdentifier: '4c186606-9515-4561-a1eb-9a072b4f5e58',
label: 'Stop',
icon: 'IconPlayerStop',
isPinned: true,
position: 35,
shortLabel: 'Stop',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'isSelectAll or someEquals(selectedRecords, "status", "NOT_STARTED") or someEquals(selectedRecords, "status", "ENQUEUED") or someEquals(selectedRecords, "status", "RUNNING")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowRun.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.STOP_WORKFLOW_RUN,
hotKeys: null,
},
retryWorkflowRun: {
universalIdentifier: '99b97c50-b31b-411a-a532-ec05402123c0',
label: 'Retry',
icon: 'IconRefresh',
isPinned: true,
position: 36,
shortLabel: 'Retry',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'someEquals(selectedRecords, "status", "FAILED")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowRun.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.RETRY_WORKFLOW_RUN,
hotKeys: null,
},
seeRunsWorkflowVersion: {
universalIdentifier: '44e305c7-4f0a-45ec-803f-6471b56455cb',
label: 'See Runs',
icon: 'IconHistoryToggle',
isPinned: true,
position: 37,
shortLabel: 'See Runs',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "workflow")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowVersion.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_RUNS_WORKFLOW_VERSION,
hotKeys: null,
},
seeWorkflowWorkflowVersion: {
universalIdentifier: 'b43052db-023e-4083-9b63-2c2dfbfd1320',
label: 'See Workflow',
icon: 'IconSettingsAutomation',
isPinned: true,
position: 38,
shortLabel: 'See Workflow',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "workflow.id")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowVersion.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_WORKFLOW_WORKFLOW_VERSION,
hotKeys: null,
},
useAsDraftWorkflowVersion: {
universalIdentifier: '483c0c1d-ea4d-4a4d-8a59-2dcf9f8e38f6',
label: 'Use as Draft',
icon: 'IconPencil',
isPinned: true,
position: 39,
shortLabel: 'Use as Draft',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'noneEquals(selectedRecords, "status", "DRAFT")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowVersion.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.USE_AS_DRAFT_WORKFLOW_VERSION,
hotKeys: null,
},
seeVersionsWorkflowVersion: {
universalIdentifier: '1d4abeb7-2750-4af7-9a92-fbadd2a9e4ba',
label: 'See Versions History',
icon: 'IconVersions',
isPinned: false,
position: 40,
shortLabel: 'See Versions',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'everyDefined(selectedRecords, "workflow")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.workflowVersion.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEE_VERSIONS_WORKFLOW_VERSION,
hotKeys: null,
},
searchRecords: {
universalIdentifier: 'fa24e25e-68f8-4548-82ff-c7b5168b7c7d',
label: 'Search',
icon: 'IconSearch',
isPinned: false,
position: 41,
shortLabel: 'Search',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEARCH_RECORDS,
hotKeys: ['/'],
},
searchRecordsFallback: {
universalIdentifier: 'c659890c-7266-46c9-bfe1-75cefff8b6d0',
label: 'Search',
icon: 'IconSearch',
isPinned: false,
position: 42,
shortLabel: 'Search',
availabilityType: CommandMenuItemAvailabilityType.FALLBACK,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEARCH_RECORDS_FALLBACK,
hotKeys: ['/'],
},
askAi: {
universalIdentifier: 'ce5fb54d-2b19-4dd1-b7b4-9532a1761a41',
label: 'Ask AI',
icon: 'IconSparkles',
isPinned: false,
position: 43,
shortLabel: 'Ask AI',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.AI',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.ASK_AI,
hotKeys: ['@'],
},
viewPreviousAiChats: {
universalIdentifier: '3084c3c9-cc23-4dad-9e00-92025f5cba7a',
label: 'View Previous AI Chats',
icon: 'IconHistory',
isPinned: false,
position: 44,
shortLabel: 'Previous AI Chats',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.AI',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.VIEW_PREVIOUS_AI_CHATS,
hotKeys: null,
},
replyToEmailThread: {
universalIdentifier: '8f015cbd-c764-434e-a6c6-bb7581b4be44',
label: 'Reply',
icon: 'IconArrowBackUp',
isPinned: true,
position: 45,
shortLabel: 'Reply',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression: 'numberOfSelectedRecords == 1',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.messageThread.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.REPLY_TO_EMAIL_THREAD,
hotKeys: null,
},
composeEmail: {
universalIdentifier: '96457c5a-b028-4d48-94e3-27f4c41296b8',
label: 'Compose Email',
icon: 'IconMail',
isPinned: false,
position: 46,
shortLabel: 'Compose',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.SEND_EMAIL_TOOL',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
hotKeys: null,
},
composeCampaign: {
universalIdentifier: '30473656-e7cb-42e0-b198-6c4e8b906106',
label: 'Compose Campaign',
icon: 'IconSend',
isPinned: false,
position: 66,
shortLabel: 'Campaign',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'featureFlags.IS_EMAIL_GROUP_ENABLED',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_CAMPAIGN,
hotKeys: null,
},
composeCampaignPinned: {
universalIdentifier: '7ad6f0c7-ac02-4062-b5cf-1f36e1664bc8',
label: 'Create new Campaign',
icon: 'IconPlus',
isPinned: true,
position: 67,
shortLabel: 'New Campaign',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
conditionalAvailabilityExpression:
'pageType == "INDEX_PAGE" and featureFlags.IS_EMAIL_GROUP_ENABLED',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_CAMPAIGN,
hotKeys: null,
},
sendMessageCampaign: {
universalIdentifier: 'b08f4ccd-070b-460f-a4b6-6d0c14f1c44d',
label: 'Send Campaign',
icon: 'IconSend',
isPinned: true,
position: 68,
shortLabel: 'Send',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and everyEquals(selectedRecords, "status", "DRAFT") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEND_MESSAGE_CAMPAIGN,
hotKeys: null,
},
sendMessageCampaignTest: {
universalIdentifier: 'a6e6fd08-2c75-4d43-8795-1baafbac165e',
label: 'Send Test Email',
icon: 'IconMail',
isPinned: true,
position: 69,
shortLabel: 'Test',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and everyEquals(selectedRecords, "status", "DRAFT") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.SEND_MESSAGE_CAMPAIGN_TEST,
hotKeys: null,
},
emailBlockSettings: {
universalIdentifier: '5c8a2f41-97be-4f3d-9a46-2f18d17f30a2',
label: 'Block Settings',
icon: 'IconAdjustments',
isPinned: true,
position: 70,
shortLabel: 'Design',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'pageType == "RECORD_PAGE" and numberOfSelectedRecords == 1 and everyEquals(selectedRecords, "status", "DRAFT") and noneDefined(selectedRecords, "deletedAt")',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.messageCampaign.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.EMAIL_BLOCK_SETTINGS,
hotKeys: null,
},
goToSettings: {
universalIdentifier: 'ef9aba44-0068-453e-930a-f8c182af18ee',
label: 'Go to Settings',
icon: 'IconSettings',
isPinned: false,
position: 47,
shortLabel: 'Settings',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: ['G', 'S'],
payload: { path: '/settings/profile' },
},
goToSettingsExperience: {
universalIdentifier: 'bceb0328-c018-48ba-80d8-a1a97dc0a8ba',
label: 'Go to Experience Settings',
icon: 'IconColorSwatch',
isPinned: false,
position: 48,
shortLabel: 'Experience',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/experience' },
},
goToSettingsAccounts: {
universalIdentifier: '447a65cc-8535-408e-9c48-db24affb7530',
label: 'Go to Accounts Settings',
icon: 'IconAt',
isPinned: false,
position: 49,
shortLabel: 'Accounts',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/accounts' },
},
goToSettingsAccountsEmails: {
universalIdentifier: '4feab22c-165f-4d13-81ca-c9eb6082ca50',
label: 'Go to Emails Settings',
icon: 'IconMail',
isPinned: false,
position: 50,
shortLabel: 'Emails',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/accounts/emails' },
},
goToSettingsAccountsCalendars: {
universalIdentifier: '3267ec0e-9dee-4d9b-8f1b-6005bfd90202',
label: 'Go to Calendars Settings',
icon: 'IconCalendarEvent',
isPinned: false,
position: 51,
shortLabel: 'Calendars',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/accounts/calendars' },
},
goToSettingsGeneral: {
universalIdentifier: 'ad68e516-96ea-455a-a838-c59788e88c23',
label: 'Go to General Settings',
icon: 'IconSettings',
isPinned: false,
position: 52,
shortLabel: 'General',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/general' },
},
goToSettingsObjects: {
universalIdentifier: '9302bfeb-f6cd-4858-ab5b-5f70f4d358c4',
label: 'Go to Data Model Settings',
icon: 'IconHierarchy2',
isPinned: false,
position: 53,
shortLabel: 'Data Model',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.DATA_MODEL',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/objects' },
},
goToSettingsMembers: {
universalIdentifier: 'fb4d9f1b-5b13-49d9-8353-80041719d411',
label: 'Go to Members Settings',
icon: 'IconUsers',
isPinned: false,
position: 54,
shortLabel: 'Members',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE_MEMBERS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/members' },
},
goToSettingsRoles: {
universalIdentifier: '4050f307-c592-4c9f-ad91-89cde330fbf7',
label: 'Go to Roles Settings',
icon: 'IconLock',
isPinned: false,
position: 55,
shortLabel: 'Roles',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE_MEMBERS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/members#roles' },
},
goToSettingsDomains: {
universalIdentifier: '2d071684-fb5e-4222-b560-4c7ab2597fb4',
label: 'Go to Domains Settings',
icon: 'IconWorld',
isPinned: false,
position: 56,
shortLabel: 'Domains',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/domains' },
},
goToSettingsBilling: {
universalIdentifier: 'f46a0fb9-14e9-4d48-801d-c33bdd543f74',
label: 'Go to Billing Settings',
icon: 'IconCurrencyDollar',
isPinned: false,
position: 57,
shortLabel: 'Billing',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/billing' },
},
goToSettingsApiWebhooks: {
universalIdentifier: 'ed2c2fde-1e7a-4a42-ba63-221eaa7c9759',
label: 'Go to MCP & APIs Settings',
icon: 'IconPlug',
isPinned: false,
position: 58,
shortLabel: 'MCP & APIs',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.API_KEYS_AND_WEBHOOKS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/api-webhooks' },
},
goToSettingsApplications: {
universalIdentifier: '44db6d7a-79ac-485e-b3da-da8776bd7777',
label: 'Go to Apps Settings',
icon: 'IconApps',
isPinned: false,
position: 59,
shortLabel: 'Apps',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.APPLICATIONS',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/applications' },
},
goToSettingsAI: {
universalIdentifier: '3eaec228-809d-452d-b5ef-7b777398c538',
label: 'Go to AI Settings',
icon: 'IconSparkles',
isPinned: false,
position: 60,
shortLabel: 'AI',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/ai' },
},
goToSettingsSecurity: {
universalIdentifier: '358e69b2-0789-44e2-add7-bdef68413be8',
label: 'Go to Security Settings',
icon: 'IconKey',
isPinned: false,
position: 61,
shortLabel: 'Security',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: 'permissionFlags.SECURITY',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/security' },
},
goToSettingsAdminPanel: {
universalIdentifier: 'dd22798b-fca6-42af-ba3b-0d48f263afbd',
label: 'Go to Admin Panel Settings',
icon: 'IconServer',
isPinned: false,
position: 62,
shortLabel: 'Admin Panel',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression:
'canImpersonate or canAccessFullAdminPanel',
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/admin-panel' },
},
goToSettingsUpdates: {
universalIdentifier: '5d1ba354-0090-4a42-9a43-601461b26068',
label: 'Go to Community Settings',
icon: 'IconUsers',
isPinned: false,
position: 63,
shortLabel: 'Community',
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
conditionalAvailabilityExpression: null,
availabilityObjectMetadataUniversalIdentifier: null,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.NAVIGATION,
hotKeys: null,
payload: { path: '/settings/community' },
},
composeEmailToPerson: {
universalIdentifier: 'f01d4b8b-2b4e-4ae0-9c6f-0b9a9a3e5b21',
label: 'Send Email',
icon: 'IconMail',
isPinned: true,
position: 64,
shortLabel: 'Send Email',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords >= 1 and permissionFlags.SEND_EMAIL_TOOL',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.person.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
hotKeys: null,
},
composeEmailToCompany: {
universalIdentifier: 'a76d3ab8-4c3a-4e5d-8a4a-1f5d6e7f8a90',
label: 'Send Email',
icon: 'IconMail',
isPinned: true,
position: 65,
shortLabel: 'Send Email',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords == 1 and permissionFlags.SEND_EMAIL_TOOL',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.company.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
hotKeys: null,
},
composeEmailToOpportunity: {
universalIdentifier: 'b3e7c9f2-5d6e-4f7a-8b9c-0d1e2f3a4b5c',
label: 'Send Email',
icon: 'IconMail',
isPinned: true,
position: 66,
shortLabel: 'Send Email',
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
conditionalAvailabilityExpression:
'numberOfSelectedRecords == 1 and permissionFlags.SEND_EMAIL_TOOL',
availabilityObjectMetadataUniversalIdentifier:
STANDARD_OBJECTS.opportunity.universalIdentifier,
frontComponentUniversalIdentifier: null,
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
hotKeys: null,
},
} as const;