Перейти к содержимому

Манифест WebPart

Манифест WebPart

Файл manifest.json в корне пакета .portalpart:

{
"id": "contoso.tasks-widget",
"title": "Задачи отдела",
"version": "1.0.0",
"category": "Списки",
"icon": "fa-list-check",
"runtime": "dotnet",
"entry": "dist/MyWebPart.dll",
"entryType": "Contoso.TasksWidget.TasksWidgetWebPart",
"styles": ["dist/main.css"],
"scripts": ["dist/main.js"],
"properties": {
"listId": { "type": "listPicker", "label": "Список", "required": true },
"viewId": { "type": "viewPicker", "label": "Представление", "dependsOn": "listId" },
"pageSize": { "type": "number", "label": "Записей", "default": 10 }
}
}

Поля манифеста

ПолеОписание
idУникальный ключ vendor.name (латиница, точки)
titleНазвание в каталоге
versionSemver (1.0.0)
categoryГруппа в каталоге
iconFont Awesome класс
entryПуть к .dll внутри ZIP
entryTypeПолное имя C#-класса (IWebPart)
runtimeВсегда dotnet
stylesCSS-файлы (пути внутри ZIP, см. ниже)
scriptsJS-файлы для клиентской логики после SSR (опционально)
propertiesСхема Property Pane

CSS и JavaScript в пакете

WebPart — гибрид SSR: HTML генерирует C# (IWebPart.RenderAsync), а стили и клиентский код поставляются вместе с пакетом, а не через frontend/ платформы.

Структура файлов

my-widget/
├── manifest.json
├── MyWidgetWebPart.cs
├── dist/
│ ├── main.css ← styles в manifest.json
│ ├── main.js ← scripts в manifest.json (опционально)
│ └── MyWidget.dll ← entry в manifest.json
└── build.sh

В manifest.json укажите пути относительно корня ZIP (в исходниках — без версии в имени):

{
"styles": ["dist/main.css"],
"scripts": ["dist/main.js"]
}

При сборке build.sh файлы переименовываются в dist/main.v{version}.css / .js, а manifest в ZIP обновляется автоматически.

Можно подключить несколько файлов — они загружаются в порядке массива.

Как платформа подключает ассеты

  1. При монтировании WebPart на странице фронтенд читает stylesheets и scripts из каталога (заполняются при установке пакета).
  2. CSS и JS загружаются с API, например: /api/v1/webparts/assets/{manifestKey}/dist/main.v1.0.0.css?v=1.0.0 (требуется авторизация).
  3. Стили вставляются в <head>, скрипты выполняются один раз за версию пакета; при смене version старые теги удаляются.
  4. После каждого SSR-рендера и action вызывается PortalWebPartClients[id].bind(container).

CSS обязателен для оформления SSR-разметки. JS нужен, если после серверного HTML требуется интерактив (модалки, обработчики кликов, синхронизация формы).

CSS: рекомендации

  • Используйте префикс классов по корневому контейнеру (например .webpart-room-booking), чтобы не конфликтовать с глобальными стилями портала.
  • CSS-переменные портала (--color-border, --color-surface) можно использовать как fallback: var(--color-border, #e5e7eb).
  • Файлы кладите в dist/ и включайте в ZIP при сборке (build.sh копирует dist/main.css в пакет).

JavaScript: хук bind

Если WebPart требует интерактива после серверного рендера (модалки, обработчики DOM), добавьте scripts в манифест и зарегистрируйте хук в dist/main.js:

(function () {
const MANIFEST_KEY = 'contoso.tasks-widget';
function bind(root) {
if (!root || root.dataset.uiBound === '1') return;
root.dataset.uiBound = '1';
// root — корневой элемент WebPart (.webpart-… или id из SSR)
root.querySelectorAll('[data-wp-action]').forEach(/* … */);
}
window.PortalWebPartClients = window.PortalWebPartClients || {};
window.PortalWebPartClients[MANIFEST_KEY] = { bind };
})();
  • Ключ в PortalWebPartClients должен совпадать с id в manifest.json.
  • bind вызывается после каждого SSR-рендера и action — защищайтесь от повторной привязки (dataset.uiBound, делегирование).
  • Действия с сервером из разметки: атрибут data-wp-action="имя" — платформа отправляет POST /webparts/invoke/{key}/action (см. SDK).

Полный пример с CSS + JS: meeting-room-booking.

Подробнее: Интерфейс, контролы и API — разметка контролов, три паттерна взаимодействия, серверный и клиентский API.

Типы свойств (Property Pane)

typeОписание
textСтрока
multilineТекстовая область
numberЧисло
booleanФлажок
choiceSelect (choices: [{value, label}])
listPickerСписок узла; с dependsOn — списки выбранного узла
libraryPickerБиблиотека текущего узла
nodePickerДочерний узел текущей страницы; scope: "subtree" — все узлы портала с путём «Родитель / Узел»
viewPickerПредставление списка (dependsOn: listId)
linksEditorРедактор списка ссылок (title, url, icon)
colorЦвет (input type=color)

Модель страницы (zones_content)

{
"layoutTemplate": "2-equal",
"zones": [
[
{ "type": "richtext", "id": "uuid", "html": "<p>Текст</p>" },
{
"type": "webpart",
"instanceId": "uuid",
"definitionKey": "portal.list-view",
"properties": { "listId": "..." }
}
]
]
}

Quill редактирует только блоки richtext (тип richtext в zones, не WebPart). WebPart — отдельные острова с собственной настройкой.

Встроенные WebPart

keyНазначение
portal.heroБаннер с заголовком и кнопкой
portal.announcementИнформационное объявление
portal.list-viewТаблица списка
portal.document-listФайлы библиотеки
portal.quick-linksБыстрые ссылки
portal.child-nodesПодразделы узла