Манифест 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 | Название в каталоге |
version | Semver (1.0.0) |
category | Группа в каталоге |
icon | Font Awesome класс |
entry | Путь к .dll внутри ZIP — обычно dist/{AssemblyName}.dll из .csproj |
entryType | Полное имя C#-класса (Namespace.Class), реализующего IWebPart |
runtime | Всегда dotnet |
entry / entryType должны совпадать с AssemblyName, RootNamespace и именем класса в .csproj / .cs. Шаблон dotnet new выставляет их согласованно; подробнее: Сборка пакета — .csproj.
| styles | CSS-файлы (пути внутри ZIP, см. ниже) |
| scripts | JS-файлы для клиентской логики после SSR (опционально) |
| properties | Схема Property Pane — пошагово: Параметры WebPart |
CSS и JavaScript в пакете
Заголовок раздела «CSS и JavaScript в пакете»WebPart — гибрид SSR: HTML генерирует C# (IWebPart.RenderAsync), а стили и клиентский код поставляются вместе с пакетом, а не через frontend/ платформы.
Структура файлов
Заголовок раздела «Структура файлов»Исходники проекта (после dotnet new portal-webpart):
my-widget/├── manifest.json├── MyWidget.csproj├── MyWidgetHandler.cs├── Templates/│ └── widget.html└── assets/ ← опционально ├── main.css ← копируется в ZIP как dist/main.css └── main.js ← опциональноВ manifest.json пути — как внутри ZIP (без версии в имени):
{ "styles": ["dist/main.css"], "scripts": ["dist/main.js"]}Сборка — скриптом из SDK:
./portal-sdk-1.0.0/scripts/pack-portalpart.sh ./my-widgetpack-portalpart публикует DLL, копирует assets/main.css / main.js в dist/, переименовывает их в main.v{version}.css / .js и обновляет styles / scripts в манифесте внутри ZIP.
Можно подключить несколько файлов — они загружаются в порядке массива.
Как платформа подключает ассеты
Заголовок раздела «Как платформа подключает ассеты»- При монтировании WebPart на странице фронтенд читает
stylesheetsиscriptsиз каталога (заполняются при установке пакета). - CSS и JS загружаются с API, например:
/api/v1/webparts/assets/{manifestKey}/dist/main.v1.0.0.css?v=1.0.0(требуется авторизация). - Стили вставляются в
<head>, скрипты выполняются один раз за версию пакета; при сменеversionстарые теги удаляются. - После каждого SSR-рендера и action вызывается
PortalWebPartClients[id].bind(container).
CSS обязателен для оформления SSR-разметки. JS нужен, если после серверного HTML требуется интерактив (модалки, обработчики кликов, синхронизация формы).
CSS: рекомендации
Заголовок раздела «CSS: рекомендации»- Для кнопок, полей и сообщений используйте встроенные классы PortalUI (
btn,tbx__control,webpart-hint…) — см. Стили и контролы PortalUI. - Свой layout — с префиксом корневого контейнера (например
.webpart-room-booking), чтобы не конфликтовать с глобальными стилями. - Цвета — через переменные (
var(--color-border, #e5e7eb),var(--color-surface)), не хардкод. - Исходники CSS/JS кладите в
assets/(main.css,main.js);pack-portalpartкопирует их вdist/внутри ZIP.
JavaScript: хук bind
Заголовок раздела «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)
Заголовок раздела «Типы свойств (Property Pane)»Полный справочник (сценарии, dependsOn, чтение в C#): Параметры WebPart.
| type | Кратко | Подробнее |
|---|---|---|
text | Строка | §6.1 |
multiline | Текстовая область | §6.2 |
number | Число (min/max) | §6.3 |
boolean | Флажок | §6.4 |
choice | Select (choices: [{value, label}]) | §6.5 |
color | Цвет #rrggbb | §6.6 |
listPicker | Списки узла страницы; с dependsOn на nodePicker — списки выбранного узла (в т.ч. другого раздела) | §3, §6.7 |
libraryPicker | Библиотеки только узла страницы (dependsOn не поддерживается) | §6.8 |
nodePicker | Дочерние узлы; "scope": "subtree" — любой узел портала | §6.9 |
viewPicker | Представления списка (dependsOn → параметр со списком) | §6.10 |
linksEditor | Таблица ссылок (title, url, icon) | §6.11 |
Модель страницы (zones_content)
Заголовок раздела «Модель страницы (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
Заголовок раздела «Встроенные WebPart»| key | Назначение |
|---|---|
portal.hero | Баннер с заголовком и кнопкой |
portal.announcement | Информационный блок (статичный callout) |
portal.list-view | Таблица списка |
portal.document-list | Файлы библиотеки |
portal.quick-links | Быстрые ссылки |
portal.child-nodes | Подразделы узла |