--- title: Элементы меню команд description: Отображайте фронтенд-компоненты как быстрые действия и элементы командного меню (Cmd+K) с помощью `defineCommandMenuItem`. icon: terminal --- **Элемент командного меню** — это мост между пользователем и [фронтенд-компонентом](/l/ru/developers/extend/apps/layout/front-components). Он регистрирует компонент в командном меню Twenty (Cmd+K) и, при необходимости, как закреплённую кнопку быстрого действия в правом верхнем углу страницы. ```ts src/command-menu-items/open-dashboard.command-menu-item.ts import { defineCommandMenuItem } from 'twenty-sdk/define'; export default defineCommandMenuItem({ universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', label: 'Open Dashboard', shortLabel: 'Dashboard', icon: 'IconLayoutDashboard', isPinned: true, availabilityType: 'GLOBAL', frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948', }); ``` ## Поля конфигурации | Поле | Обязательно | Описание | | --------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `universalIdentifier` | Да | Стабильный уникальный идентификатор для команды | | `label` | Да | Полная метка, отображаемая в меню команд (Cmd+K) | | `frontComponentUniversalIdentifier` | Да | `universalIdentifier` фронтенд-компонента, который открывается этой командой | | `shortLabel` | Нет | Короткая метка, отображаемая на закреплённой кнопке быстрого действия | | `icon` | Нет | Имя значка, отображаемое рядом с меткой (например, `'IconBolt'`, `'IconSend'`) | | `isPinned` | Нет | При значении `true` показывает команду как кнопку быстрого действия в правом верхнем углу страницы | | `availabilityType` | Нет | Определяет, где отображается команда: `'GLOBAL'` (доступна всегда), `'RECORD_SELECTION'` (только при выборе записей) или `'FALLBACK'` (показывается, когда другие команды не подходят) | | `availabilityObjectUniversalIdentifier` | Нет | Ограничивает команду страницами определённого типа объектов (например, только для записей Company) | | `conditionalAvailabilityExpression` | Нет | Логическое выражение, которое динамически управляет видимостью (см. ниже) | ## Команды без интерфейса Элемент командного меню в паре с [фронтенд-компонентом без интерфейса](/l/ru/developers/extend/apps/layout/front-components#headless-vs-non-headless) — идиоматичный способ предоставить действие в один клик: выполнить код, перейти или подтвердить и выполнить. Страница Front Components описывает [SDK Command components](/l/ru/developers/extend/apps/layout/front-components#sdk-command-components) (`Command`, `CommandLink`, `CommandModal`, `CommandOpenSidePanelPage`), которые реализуют шаблон «действие и размонтирование». Типичный сценарий: ```tsx src/front-components/run-action.tsx import { defineFrontComponent } from 'twenty-sdk/define'; import { Command } from 'twenty-sdk/command'; import { CoreApiClient } from 'twenty-sdk/clients'; const RunAction = () => { const execute = async () => { const client = new CoreApiClient(); await client.mutation({ createTask: { __args: { data: { title: 'Created by my app' } }, id: true, }, }); }; return ; }; export default defineFrontComponent({ universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234', name: 'run-action', description: 'Creates a task from the command menu', component: RunAction, isHeadless: true, }); ``` ```ts src/command-menu-items/run-action.command-menu-item.ts import { defineCommandMenuItem } from 'twenty-sdk/define'; export default defineCommandMenuItem({ universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345', label: 'Run my action', icon: 'IconPlayerPlay', frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234', }); ``` ## Выражения условной доступности Поле `conditionalAvailabilityExpression` позволяет управлять видимостью команды в зависимости от текущего контекста страницы. Импортируйте типизированные переменные и операторы из `twenty-sdk`, чтобы составлять выражения: ```ts src/command-menu-items/bulk-update.command-menu-item.ts import { defineCommandMenuItem } from 'twenty-sdk/define'; import { objectPermissions, everyEquals, } from 'twenty-sdk/front-component'; export default defineCommandMenuItem({ universalIdentifier: '...', label: 'Bulk Update', availabilityType: 'RECORD_SELECTION', frontComponentUniversalIdentifier: '...', conditionalAvailabilityExpression: everyEquals( objectPermissions, 'canUpdateObjectRecords', true, ), }); ``` ### Переменные контекста Они представляют текущее состояние страницы: | Переменная | Тип | Описание | | ------------------------------ | --------- | ------------------------------------------------------------------------ | | `pageType` | `string` | Текущий тип страницы (например, `'RecordIndexPage'`, `'RecordShowPage'`) | | `isInSidePanel` | `boolean` | Указывает, рендерится ли компонент в боковой панели | | `numberOfSelectedRecords` | `number` | Количество выбранных в данный момент записей | | `isSelectAll` | `boolean` | Активен ли режим "выбрать все" | | `selectedRecords` | `array` | Объекты выбранных записей | | `favoriteRecordIds` | `array` | ID избранных записей | | `objectPermissions` | `object` | Разрешения для текущего типа объекта | | `targetObjectReadPermissions` | `object` | Права на чтение для целевого объекта | | `targetObjectWritePermissions` | `object` | Права на запись для целевого объекта | | `featureFlags` | `object` | Активные флаги функций | | `objectMetadataItem` | `object` | Метаданные текущего типа объекта | | `hasAnySoftDeleteFilterOnView` | `boolean` | Есть ли у текущего представления фильтр мягкого удаления | ### Операторы Комбинируйте переменные в логические выражения: | Оператор | Описание | | ----------------------------------- | ------------------------------------------------------------------------- | | `isDefined(value)` | `true`, если значение не null/undefined | | `isNonEmptyString(value)` | `true`, если значение — непустая строка | | `includes(array, value)` | `true`, если массив содержит значение | | `includesEvery(array, prop, value)` | `true`, если свойство каждого элемента включает значение | | `every(array, prop)` | `true`, если свойство истинно для каждого элемента | | `everyDefined(array, prop)` | `true`, если свойство определено у каждого элемента | | `everyEquals(array, prop, value)` | `true`, если свойство равно значению у каждого элемента | | `some(array, prop)` | `true`, если свойство истинно хотя бы у одного элемента | | `someDefined(array, prop)` | `true`, если свойство определено хотя бы у одного элемента | | `someEquals(array, prop, value)` | `true`, если свойство равно значению хотя бы у одного элемента | | `someNonEmptyString(array, prop)` | `true`, если свойство является непустой строкой хотя бы у одного элемента | | `none(array, prop)` | `true`, если свойство ложно для каждого элемента | | `noneDefined(array, prop)` | `true`, если свойство не определено ни у одного элемента | | `noneEquals(array, prop, value)` | `true`, если свойство не равно значению ни у одного элемента |