Плагины оболочки
Плагин — веб-компонент продукта, который рутовое приложение показывает не во вкладке, а
рядом с ней: кнопкой в шапке или на боковой панели и раскрывающейся по клику панелью.
Так подключаются уведомления, обратная связь, ассистент — то, что должно быть под рукой
на любом экране. Плагин объявляется в конфигурации рутового приложения (config.json),
собственного кода в оболочке для него не пишут.
Со стороны продукта плагин — обычный веб-компонент на Q.Palette; всё, что ему нужно от
оболочки, он получает через QPluginService из @diasoft/qpalette-visual.
С чего начать
Добавьте запись в массив plugins конфигурации рутового приложения:
{
"plugins": [
{
"endpoint": { "service": "qnotify", "component": "qnotify" },
"slot": "header",
"icon": "pi-bell-outlined",
"caption": "Уведомления"
}
]
}В правой части шапки появится кнопка с колокольчиком и подсказкой «Уведомления». Клик
по ней загружает веб-компонент qnotify и открывает его в панели под кнопкой; повторный
клик, клик вне панели или Escape — закрывает. Веб-компонент загружается при первом
открытии, а не при старте приложения.
Как это устроено
Плагин живёт в одном из трёх слотов. Слот определяет, где стоит кнопка и в какой панели открывается содержимое:
slot | Кнопка | Панель |
|---|---|---|
header | правая часть шапки | выпадающая под кнопкой, размеры задаёт плагин |
toolbar | верх боковой панели (по умолчанию) | боковая панель во всю высоту экрана |
bottom | низ боковой панели | боковая панель во всю высоту экрана |
Открытые панели не мешают друг другу между группами: одновременно могут быть открыты один плагин шапки и один плагин боковой панели. Внутри группы открытие одного плагина закрывает другой.
Разделение ответственности:
- оболочка рисует кнопку (иконка, подсказка, индикатор уведомлений, статус), панель и её геометрию, загружает веб-компонент и передаёт панели высоту;
- плагин — своё содержимое и раскладку внутри панели; закрывает себя, меняет статус
и счётчик на кнопке через
QPluginService.
Настройка
Что загружать: endpoint и bundleUrl
endpoint называет веб-компонент так же, как в остальных местах конфигурации — сервис,
компонент и, при необходимости, маршрут внутри него:
{
"endpoint": { "service": "qdemo", "component": "qdemo", "route": "plugins/assistant" }
}route открывает в панели конкретный экран веб-компонента: без него — маршрут по умолчанию.
bundleUrl нужен, когда веб-компонент лежит не за шлюзом продукта, а отдаётся как файл —
например библиотечный плагин из ассетов:
{
"endpoint": { "service": "qfeedback", "component": "qfeedback" },
"bundleUrl": "/assets/qfeedback/main.js"
}Кнопка: icon, caption, slot
icon — имя иконки из наборов pi-* (PrimeIcons) или qi-* (иконки Q.Palette). Короткая
форма — строка; расширенная — объект, если кнопке нужен свой цвет:
{
"icon": { "name": "qi-feedback", "color": "#ffffff", "background": "var(--q-primary)" }
}color и background принимают любое CSS-значение цвета, включая токены темы
(var(--q-primary)). Кнопка с заданным background сохраняет отклик на наведение и
показывает, что панель открыта — цвет отклика подбирается от текущего цвета иконки, поэтому
одинаково читается на светлом и тёмном фоне.
caption — подпись плагина: показывается подсказкой при наведении на кнопку. Заголовка у панели
нет — его, если нужен, рисует сам плагин.
slot — где стоит кнопка (см. «Как это устроено»). Не задан — toolbar.
Загрузка при старте: initWithApp
По умолчанию веб-компонент загружается при первом открытии панели. initWithApp: true
загружает его вместе с приложением — для плагинов, которые должны работать в фоне ещё до
того, как пользователь их открыл: например, считать уведомления и показывать счётчик на
кнопке.
{
"endpoint": { "service": "qnotify", "component": "qnotify" },
"slot": "header",
"icon": "pi-bell-outlined",
"caption": "Уведомления",
"initWithApp": true
}Цена — загрузка бандла при старте у каждого пользователя, в том числе у тех, кто плагин не откроет. Не включайте, если фоновой работы у плагина нет.
Размеры панели: panel (только slot: "header")
Панель плагина шапки по умолчанию шириной 20rem и высотой по содержимому. Настройка
panel меняет это:
{
"panel": { "width": "28rem", "height": "32rem" }
}width— ширина; любое CSS-значение (28rem,480px).height— высота; без неё панель растёт по содержимому. Заданная высота не выпустит панель за экран: сверху она ограничена расстоянием от кнопки до края окна.bottom— отступ панели от дальнего края окна. Панель растягивается от кнопки до этого отступа;heightпри этом не учитывается. Так делается панель «на всю высоту экрана» без подсчёта высоты шапки:
{
"panel": { "width": "24rem", "bottom": "1rem" }
}На узком экране кнопки шапки уезжают вниз, и панель раскрывается вверх — bottom тогда
отсчитывается от верхнего края. Настройка одна, поведение зеркальное.
Панели боковых слотов (toolbar, bottom) всегда занимают всю высоту экрана; panel на них
не действует.
Как решать типовые задачи
Занять панель целиком
Когда у панели есть определённая высота (panel.height или panel.bottom, а также любой
боковой слот), оболочка передаёт её корневому элементу веб-компонента. Дальше высоту нужно
забрать самому — объявите у корневого компонента плагина:
:host {
display: block;
height: 100%;
}Без этого содержимое прижмётся к верху, а низ панели останется пустым. Внутренняя
раскладка — дело плагина: например, display: grid; grid-template-rows: auto 1fr auto для
шапки, прокручиваемой середины и подвала.
Закрыть панель из плагина
Плагин не знает, в каком слоте он открыт, и не должен искать панель в DOM. Вместо этого он просит оболочку закрыть себя:
import { inject } from '@angular/core';
import { QPluginService } from '@diasoft/qpalette-visual';
export class AssistantComponent {
private readonly plugin = inject(QPluginService);
close(): void {
this.plugin.close();
}
}Оболочка закроет панель того плагина, из которого пришло событие.
Показать счётчик на кнопке
this.plugin.notification(3); // индикатор с числом 3
this.plugin.notification(1); // индикатор без числа — точка
this.plugin.notification(0); // индикатор скрытСчётчик виден и при закрытой панели, поэтому такому плагину обычно нужен initWithApp: true —
иначе считать уведомления некому, пока пользователь не откроет панель.
Пометить кнопку статусом
this.plugin.changeStatus('error'); // QStatus: 'success' | 'info' | 'warn' | 'error'Кнопка окрашивается по статусу (классы p-button-success, p-button-info, p-button-warning,
p-button-danger темы) — например, чтобы показать, что соединение с сервисом потеряно.
Статус виден только на кнопках боковой панели (toolbar, bottom); кнопка в шапке его не показывает.
Открыть в панели конкретный экран
Задайте route в endpoint — маршрут внутри веб-компонента, тот же, что открыл бы
QUrlService продукта:
{
"endpoint": { "service": "qdemo", "component": "qdemo", "route": "plugins/assistant" },
"slot": "bottom",
"icon": "pi-comments-outlined",
"caption": "Ассистент"
}Так один веб-компонент отдаёт и полноценные экраны во вкладках, и облегчённый экран для панели плагина.
Ограничения и типичные ошибки
- На кнопке звезда вместо иконки. У записи нет
icon— оболочка подставляетpi-star-o-outlined. Задайтеicon. - Плагин не загружается, в панели сообщение об ошибке. Оболочка не нашла веб-компонент
по
endpoint(ответ 403/404 шлюза) либоbundleUrlуказывает на отсутствующий файл. Проверьте, что сервис и компонент называются так же, как в реестре, и что бандл лежит по указанному адресу. - Панель пустая снизу. У панели задана высота, а корневой компонент плагина её не забрал — см. «Занять панель целиком».
- Всплывающие элементы плагина обрезаются. Панель с определённой высотой прокручивает
содержимое и обрезает то, что выходит за её границы. Выпадающие списки и подсказки
выводите через
appendTo="body". panelне действует. Настройка учитывается только в слотеheader.
Справочник
Запись в plugins[]
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
endpoint | { service, component, route? } | — | Веб-компонент плагина; route — маршрут внутри него |
bundleUrl | string | — | Адрес файла бандла, если веб-компонент отдаётся не через шлюз продукта |
slot | 'toolbar' | 'bottom' | 'header' | 'toolbar' | Где стоит кнопка и в какой панели открывается содержимое |
icon | string | { name, color?, background? } | pi-star-o-outlined | Иконка кнопки: имя из pi-*/qi-*; в объектной форме — с цветом иконки и фона |
caption | string | — | Подсказка при наведении на кнопку |
initWithApp | boolean | false | Загружать веб-компонент при старте приложения, а не при первом открытии |
panel | { width?, height?, bottom? } | width: '20rem', высота по содержимому | Размеры панели; только для slot: 'header' |
service, component, route | string | — | (устаревшее) То же, что endpoint, полями верхнего уровня. Если задан endpoint, приоритет у него |
Порядок записей в массиве — порядок кнопок в слоте.
QPluginService (@diasoft/qpalette-visual)
| Метод | Что делает |
|---|---|
close(): void | Закрывает панель плагина, из которого вызван |
notification(value: number | boolean): void | Индикатор на кнопке: число больше 1 — с числом, 1 или true — точка, 0 или false — скрыт |
changeStatus(status: QStatus): void | Окрашивает кнопку по статусу 'success' | 'info' | 'warn' | 'error'; только в слотах toolbar и bottom |
Сервис отправляет события через QEventsService того же бандла — работает из любого
компонента плагина, регистрировать ничего не нужно.
Совместимость версий
| Версия | Что изменилось |
|---|---|
| 8.2.0 | icon в объектной форме (цвет иконки и фона); panel — размеры панели плагина шапки, в том числе растяжение до края экрана через bottom |
| 8.0.27 | Слот header с выпадающей панелью и слот bottom; endpoint вместо полей service/component/route верхнего уровня; bundleUrl; секции feedback и notifications конфигурации объявлены устаревшими |
Устаревшее
service,component,routeна верхнем уровне записи — заменены объектомendpoint. Старые поля читаются, пока не заданendpoint.opened— раньше открывал панель при старте. Не учитывается: панель открывается только действием пользователя; фоновая работа плагина — черезinitWithApp.- Манифест плагина
src/assets/manifest/main.js— не читается; всё, что описывал манифест (icon,initWithApp,description), задаётся в записиplugins[]. - Секции
feedbackиnotificationsконфигурации — прежний способ подключить обратную связь и уведомления. Ещё читаются и превращаются в плагины слотаheaderс иконкамиqi-feedbackиpi-bell-outlined; новые продукты объявляют их вplugins[]:
{
"plugins": [
{
"endpoint": { "service": "qfeedback", "component": "qfeedback" },
"bundleUrl": "/assets/qfeedback/main.js",
"slot": "header",
"icon": "qi-feedback",
"caption": "Обратная связь"
}
]
}