Skip to content

Точки монтирования ​

Точка монтирования — это место в админ-панели, где может появиться ваш виджет. Нужные вы объявляете в bito.locations.surfaces; точка, в которой код действительно работает, лежит в bito.context.surface.

json
{
    "bito": {
        "locations": {
            "surfaces": ["customer_profile", "card_phone", "list:customers", "global"],
            "persistent": true
        }
    }
}

Элемент должен быть одной из именованных точек ниже, строкой list:<page_name> или global. Всё остальное, как и дубликат, не проходит валидацию при загрузке.

Пять вкладок профилей ​

ТочкаЭкран
customer_profileПрофиль клиента
supplier_profileПрофиль поставщика
employee_profileПрофиль сотрудника
natural_person_profileПрофиль физического лица
legal_person_profileПрофиль юридического лица

Они монтируются напрямую, вкладкой в собственной ленте вкладок профиля, — никакого меню, из которого пользователь сначала выбирает вас, нет. Место вкладки берётся из сохранённого компанией порядка разделов профиля, и её можно перетаскивать, как любой другой раздел. В bito.context.entity_id лежит идентификатор просматриваемого профиля.

widget_page ​

Точка монтирования страниц левого меню. Её не нужно указывать в bito.locations.surfaces и самим добавлять в меню действий: страницы создаёт объявление bito.left_menu. Их URL — /widget/{widget_code}[/{subitem}] и {префикс модуля}/widget/{widget_code}/{subitem}; они строятся из кода виджета вашего приложения, а если его нет — из client_id.

Bito монтирует виджет с bito.context.surface, равным widget_page, и с открытой страницей в bito.context.menu: { location, item_code, subitem_code }. После bind_actions он вызывает initMenuPage с тем же объектом и вызывает его снова, без перемонтирования, когда пользователь переходит к другому подпункту того же блока.

Страница открывается только для установленного релиза с принятым согласием, а монтирование отклоняется для релиза, в манифесте которого нет left_menu. Названия меню разрешаются из i18n архива при загрузке, поэтому текст навигации не расходится с проверенным пакетом.

sale_order_card ​

Лента вкладок карточки заказа на канбан-доске. Контракт монтирования тот же, что у вкладки профиля, но в bito.context.entity_id лежит заказ. Карточка сначала спрашивает, какие виджеты объявили эту точку, и только потом рисует вкладки, поэтому ваша появляется рядом со встроенными.

Компания может переставлять эти вкладки как угодно, с одним исключением: первая вкладка карточки закреплена, потому что несёт собственные поля заказа. Лента не даёт ни перетащить её, ни бросить что-либо выше неё — так что ваша вкладка может встать на любое место начиная со второго.

card_phone ​

Это не вкладка. Виджет, объявивший card_phone, предлагается пунктом в меню клика по номеру телефона в карточке, рядом с «Копировать» и «Позвонить». Пока пользователь не выберет пункт, ничего не монтируется; затем виджет монтируется в модальном окне, номер лежит в bito.context.phone, а запись карточки — в bito.context.entity_id.

Это точка для телефонии и мессенджеров: интеграции click-to-dial отдельная вкладка не нужна.

Это не обход чего-либо. Монтирование идёт через тот же эндпоинт mount и тот же экран согласия на релиз, что и у остальных точек, — просто происходит позже, когда пользователь сам его попросит.

Точки list: ​

Точка list: помещает ваш виджет в меню действий страницы-списка. page_name — это собственное имя таблицы в админ-панели; строка должна быть list:, затем строчная буква, затем строчные буквы, цифры или подчёркивания: list:customers, list:sale_order.

Пользователь выделяет строки, открывает меню и выбирает ваш пункт. entity_id вы при этом не получаете — у действия над списком нет одной записи. Вместо него приходит bito.context.selection:

js
var sel = bito.context.selection
// { ids: ["6712...", "6713..."], isAll: false, page_name: "customers" }

isAll означает, что пользователь выбрал всё, что попадает под текущий фильтр, а не только идентификаторы из ids.

global ​

Постоянный, всегда смонтированный слот. Он живёт вне маршрутизатора, поэтому переживает переходы между страницами и монтируется один раз на вкладку браузера, и он пропускается на экранах без интерфейсной обвязки — вход, печать, встраивание и онбординг.

Два важных момента:

TIP

Включает любая из двух форм. И persistent: true, и указание global в surfaces читаются как согласие на постоянный слот — одним общим предикатом, который используют и список глобальных виджетов, и ограничение ниже, так что разойтись они не могут. Предпочитайте persistent: true: это явная, документированная форма, которая говорит то, что означает.

Глобальный виджет работает без обвязки: ни карточки, ни спиннера, ни оповещения об ошибке, ни иконки настроек. Сдерживание сбоев при этом действует — виджет, дважды бросивший исключение, всё так же отключается, — просто он падает молча, а не выталкивает карточку ошибки на каждый экран. Хотите быть видимым — рисуйте собственный интерфейс.

У компании одновременно может быть включено не более пяти постоянных виджетов. Ограничение применяется на сервере в момент принятия согласия, то есть в момент, когда виджет начинает работать. Шестой получает отдельную ошибку, а не тихо отбрасывается.

Что должно быть верно до монтирования ​

Монтирование отклоняется, если не выполнено всё перечисленное:

  • приложение установлено в этой компании;
  • релиз находится в статусе approved (либо вы — владеющий им активный разработчик, который смотрит собственный черновик);
  • его файлы распакованы;
  • компания приняла согласие именно на этот релиз.

Пока согласие не принято, ответ на mount вообще не содержит адреса скрипта, поэтому виджет без согласия не может исполниться — он может только показать запрос согласия.

Предпросмотр до одобрения ​

Активный разработчик может смонтировать собственный черновой релиз в своей же компании — через отдельный эндпоинт предпросмотра, который явно принимает идентификатор релиза. Боевой путь монтирования идентификатор релиза принять не способен в принципе, поэтому случайно предпросмотреть через него нельзя. В предпросмотре настроек установки нет — bito.settings.get() пуст.

Bito 2.0 Integration API