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

Манифест 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 — обычно 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 |

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-widget

pack-portalpart публикует DLL, копирует assets/main.css / main.js в dist/, переименовывает их в main.v{version}.css / .js и обновляет styles / scripts в манифесте внутри 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 требуется интерактив (модалки, обработчики кликов, синхронизация формы).

  • Для кнопок, полей и сообщений используйте встроенные классы 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.

Если 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.

Полный справочник (сценарии, dependsOn, чтение в C#): Параметры WebPart.

typeКраткоПодробнее
textСтрока§6.1
multilineТекстовая область§6.2
numberЧисло (min/max)§6.3
booleanФлажок§6.4
choiceSelect (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
{
"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 — отдельные острова с собственной настройкой.

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