dev-3.0 #1

Merged
Torsten merged 10 commits from dev-3.0 into main 2026-08-18 20:49:15 +00:00
10 changed files with 85 additions and 24 deletions
Showing only changes of commit eb1ad7ba1e - Show all commits
+10 -13
View File
@@ -6,14 +6,14 @@ PortalSettings V3 ist ein providerbasiertes SPFx-WebPart für SharePoint Server
| Eigenschaft | Wert | | Eigenschaft | Wert |
|---|---| |---|---|
| Version | 3.1.0 | | Version | 3.2.0 |
| SharePoint Framework | 1.4.1 | | SharePoint Framework | 1.4.1 |
| Build-Node | 8.17.0 | | Build-Node | 8.17.0 |
| npm | 6.x | | npm | 6.x |
| Gulp | lokal 3.9.1 | | Gulp | lokal 3.9.1 |
| Komponente | Client-Side WebPart | | Komponente | Client-Side WebPart |
Die frühere provisionierte `PortalSettings.aspx` und der leere Application Customizer wurden entfernt. Die Oberfläche wird vollständig vom WebPart erzeugt und verwendet kein `innerHTML`. Die Oberfläche wird vollständig vom WebPart erzeugt und verwendet kein `innerHTML`. Ein schlankes SharePoint-Feature provisioniert beim Installieren der App im Root-Web automatisch die moderne `SitePages/PortalSettings.aspx` und platziert dort genau eine Instanz des WebParts.
## Unterstützte Solutions ## Unterstützte Solutions
@@ -164,22 +164,20 @@ sharepoint/solution/portal-settings.sppkg
## Installation ## Installation
1. `portal-settings.sppkg` im App Catalog durch Version `3.1.0.0` ersetzen. 1. `portal-settings.sppkg` im App Catalog durch Version `3.2.0.0` ersetzen.
2. Die App im Root Web der gewünschten Site Collection installieren oder aktualisieren. 2. Die App im Root Web der gewünschten Site Collection installieren oder aktualisieren.
3. Eine moderne Seite erstellen. 3. Die App provisioniert automatisch die veröffentlichte Seite `SitePages/PortalSettings.aspx` mit dem WebPart.
4. Das WebPart **Portal Settings** einmal auf der Seite hinzufügen. 4. Eine bereits vorhandene `PortalSettings.aspx` wird nicht überschrieben.
5. Die Seite veröffentlichen und nur für die gewünschte Administratorgruppe verlinken.
Optional kann eine Seite per PnP PowerShell erzeugt werden: Optional kann eine Seite per PnP PowerShell erzeugt werden:
```powershell ```powershell
.\deployment\Add-PortalSettingsPage.ps1 ` .\deployment\Add-PortalSettingsPage.ps1 `
-SiteUrl 'http://clshp001/sites/target' ` -SiteUrl 'http://clshp001/sites/target' `
-PageName 'PortalSettingsV3' `
-Publish -Publish
``` ```
Die Standardseite heißt absichtlich `PortalSettingsV3.aspx`, damit die alte V2-Seite während der Abnahme erhalten bleiben kann. Das Skript bleibt als Reparaturweg erhalten und verwendet standardmäßig ebenfalls `PortalSettings.aspx`.
## Migration von V2 ## Migration von V2
@@ -191,11 +189,10 @@ V3 liest die vorhandenen Konfigurationsorte direkt weiter:
Es ist keine Datenmigration in eine neue Liste erforderlich. Empfohlenes Vorgehen: Es ist keine Datenmigration in eine neue Liste erforderlich. Empfohlenes Vorgehen:
1. V3-Paket installieren. 1. Paket aktualisieren und die App im Root-Web aktualisieren.
2. `PortalSettingsV3.aspx` parallel zur alten Seite bereitstellen. 2. Fehlt `PortalSettings.aspx`, wird sie durch das Feature angelegt. Eine vorhandene Seite bleibt unverändert.
3. Alle drei Provider laden und Konfigurationen testweise speichern. 3. Falls eine vorhandene Seite das WebPart noch nicht enthält, das PnP-Skript als Reparaturweg ausführen.
4. Root Web und Subwebs prüfen. 4. Alle Provider laden, Konfigurationen testweise speichern und Root Web sowie Subwebs prüfen.
5. Erst danach die alte `PortalSettings.aspx` löschen oder archivieren.
## Diagnose ## Diagnose
+4 -3
View File
@@ -2,7 +2,7 @@
Stand: 21.07.2026 Stand: 21.07.2026
Branch: `dev-3.0` Branch: `dev-3.0`
Zielversion: 3.1.0 Zielversion: 3.2.0
## Architektur ## Architektur
@@ -51,7 +51,8 @@ Zielversion: 3.1.0
- [x] Versionen auf 3.0.0 angehoben. - [x] Versionen auf 3.0.0 angehoben.
- [x] Node-Engine auf SPFx-1.4.1-Buildumgebung begrenzt. - [x] Node-Engine auf SPFx-1.4.1-Buildumgebung begrenzt.
- [x] Alte Feature-, Upgrade-, Copy- und Azure-Assets entfernt. - [x] Alte monolithische Seiten-, Copy- und Azure-Assets entfernt.
- [x] Schlankes Feature zur automatischen Provisionierung der modernen PortalSettings.aspx ergänzt.
- [x] Altes Gulp-Copy-Task entfernt. - [x] Altes Gulp-Copy-Task entfernt.
- [x] Serve-Konfiguration auf WebPart Workbench umgestellt. - [x] Serve-Konfiguration auf WebPart Workbench umgestellt.
- [x] Tests laufen vor der Paketierung. - [x] Tests laufen vor der Paketierung.
@@ -74,7 +75,7 @@ Zielversion: 3.1.0
- [ ] Ship-Paket mit Node.js 8.17.0 erstellen. - [ ] Ship-Paket mit Node.js 8.17.0 erstellen.
- [ ] App im Root Web aktualisieren. - [ ] App im Root Web aktualisieren.
- [ ] Moderne `PortalSettingsV3.aspx` provisionieren. - [ ] Automatisch provisionierte `PortalSettings.aspx` und enthaltenes WebPart prüfen.
- [ ] MegaMenu-Termsets laden und speichern. - [ ] MegaMenu-Termsets laden und speichern.
- [ ] CustomBranding laden und schemaerhaltend speichern. - [ ] CustomBranding laden und schemaerhaltend speichern.
- [ ] ExpiryIndicator-Standard speichern. - [ ] ExpiryIndicator-Standard speichern.
+15 -2
View File
@@ -3,9 +3,22 @@
"solution": { "solution": {
"name": "portal-settings-client-side-solution", "name": "portal-settings-client-side-solution",
"id": "1c98e32d-bb7b-43b7-9625-074d6e4ea286", "id": "1c98e32d-bb7b-43b7-9625-074d6e4ea286",
"version": "3.1.0.0", "version": "3.2.0.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": false "skipFeatureDeployment": false,
"features": [
{
"title": "Portal Settings Page",
"description": "Provisioniert die moderne PortalSettings.aspx im Root-Web.",
"id": "71841e33-8bbd-4007-83a6-d950453226a2",
"version": "3.2.0.0",
"assets": {
"elementManifests": ["elements.xml"],
"elementFiles": ["PortalSettings.aspx"],
"upgradeActions": ["upgrade-actions.xml"]
}
}
]
}, },
"paths": { "paths": {
"zippedPackage": "solution/portal-settings.sppkg" "zippedPackage": "solution/portal-settings.sppkg"
+1 -1
View File
@@ -2,7 +2,7 @@ param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$SiteUrl, [string]$SiteUrl,
[string]$PageName = 'PortalSettingsV3', [string]$PageName = 'PortalSettings',
[switch]$Publish [switch]$Publish
) )
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "portal-settings", "name": "portal-settings",
"version": "3.1.0", "version": "3.2.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "portal-settings", "name": "portal-settings",
"version": "3.1.0", "version": "3.2.0",
"private": true, "private": true,
"main": "lib/index.js", "main": "lib/index.js",
"engines": { "engines": {
+16
View File
@@ -0,0 +1,16 @@
<%@ Page language="C#" Inherits="Microsoft.SharePoint.WebControls.ClientSidePage, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<!--[if gte mso 9]><SharePoint:CTFieldRefs runat="server" Prefix="mso:" FieldList="FileLeafRef,Title,ContentTypeId,ClientSideApplicationId,PageLayoutType,CanvasContent1,BannerImageUrl,PromotedState"><xml>
<mso:CustomDocumentProperties>
<mso:Title msdt:dt="string">Portal Settings</mso:Title>
<mso:ContentTypeId msdt:dt="string">0x0101009D1CB255DA76424F860D91F20E6C4118</mso:ContentTypeId>
<mso:ClientSideApplicationId msdt:dt="string">b6917cb1-93a0-4b97-a84d-7cf49975d4ec</mso:ClientSideApplicationId>
<mso:PageLayoutType msdt:dt="string">Article</mso:PageLayoutType>
<mso:PromotedState msdt:dt="string">0</mso:PromotedState>
</mso:CustomDocumentProperties>
</xml></SharePoint:CTFieldRefs><![endif]-->
</head>
<body></body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="PortalSettingsModernPage" Url="SitePages" RootWebOnly="TRUE">
<File Path="PortalSettings.aspx" Url="PortalSettings.aspx" Type="GhostableInLibrary" Level="Published" IgnoreIfAlreadyExists="TRUE">
<Property Name="Title" Value="Portal Settings" />
<Property Name="ContentTypeId" Value="0x0101009D1CB255DA76424F860D91F20E6C4118" />
<Property Name="ClientSideApplicationId" Value="b6917cb1-93a0-4b97-a84d-7cf49975d4ec" />
<Property Name="PageLayoutType" Value="Article" />
<Property Name="PromotedState" Value="0" />
<Property Name="BannerImageUrl" Value="/_layouts/15/images/sitepagethumbnail.png" />
<Property Name="CanvasContent1" Value="&lt;div&gt;&lt;div data-sp-canvascontrol=&quot;&quot; data-sp-canvasdataversion=&quot;1.0&quot; data-sp-controldata=&quot;&amp;#123;&amp;quot;controlType&amp;quot;:3,&amp;quot;id&amp;quot;:&amp;quot;7f1bf9be-7eca-4952-937f-4c72daccfc26&amp;quot;,&amp;quot;position&amp;quot;:&amp;#123;&amp;quot;zoneIndex&amp;quot;:1,&amp;quot;sectionIndex&amp;quot;:1,&amp;quot;controlIndex&amp;quot;:1,&amp;quot;layoutIndex&amp;quot;:1,&amp;quot;sectionFactor&amp;quot;:12&amp;#125;,&amp;quot;webPartId&amp;quot;:&amp;quot;c41d05ec-0682-4af0-b807-649806ed56b3&amp;quot;,&amp;quot;addedFromPersistedData&amp;quot;:true&amp;#125;&quot;&gt;&lt;div data-sp-webpart=&quot;&quot; data-sp-webpartdataversion=&quot;1.0&quot; data-sp-webpartdata=&quot;&amp;#123;&amp;quot;id&amp;quot;:&amp;quot;c41d05ec-0682-4af0-b807-649806ed56b3&amp;quot;,&amp;quot;instanceId&amp;quot;:&amp;quot;7f1bf9be-7eca-4952-937f-4c72daccfc26&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;Portal Settings&amp;quot;,&amp;quot;description&amp;quot;:&amp;quot;Zentrale Verwaltung installierter Portal-Erweiterungen.&amp;quot;,&amp;quot;serverProcessedContent&amp;quot;:&amp;#123;&amp;quot;htmlStrings&amp;quot;:&amp;#123;&amp;#125;,&amp;quot;searchablePlainTexts&amp;quot;:&amp;#123;&amp;#125;,&amp;quot;imageSources&amp;quot;:&amp;#123;&amp;#125;,&amp;quot;links&amp;quot;:&amp;#123;&amp;#125;&amp;#125;,&amp;quot;dataVersion&amp;quot;:&amp;quot;1.0&amp;quot;,&amp;quot;properties&amp;quot;:&amp;#123;&amp;quot;title&amp;quot;:&amp;quot;Zentrale Verwaltung der Portal-Erweiterungen&amp;quot;&amp;#125;&amp;#125;&quot;&gt;&lt;div data-sp-componentid=&quot;&quot;&gt;c41d05ec-0682-4af0-b807-649806ed56b3&lt;/div&gt;&lt;div data-sp-htmlproperties=&quot;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;" />
</File>
</Module>
</Elements>
+3
View File
@@ -0,0 +1,3 @@
<ApplyElementManifests>
<ElementManifest Location="71841e33-8bbd-4007-83a6-d950453226a2\elements.xml" />
</ApplyElementManifests>
+20 -3
View File
@@ -15,19 +15,36 @@ var config = json('config/config.json');
var copyAssets = json('config/copy-assets.json'); var copyAssets = json('config/copy-assets.json');
var manifest = json('src/webparts/portalSettings/PortalSettingsWebPart.manifest.json'); var manifest = json('src/webparts/portalSettings/PortalSettingsWebPart.manifest.json');
var styles = read('src/webparts/portalSettings/PortalSettings.scss'); var styles = read('src/webparts/portalSettings/PortalSettings.scss');
var pageAsset = read('sharepoint/assets/PortalSettings.aspx');
var elements = read('sharepoint/assets/elements.xml');
var upgradeActions = read('sharepoint/assets/upgrade-actions.xml');
var sourceFiles = [ var sourceFiles = [
'src/ui/Dom.ts', 'src/ui/Dom.ts',
'src/ui/DynamicFormRenderer.ts', 'src/ui/DynamicFormRenderer.ts',
'src/ui/PortalSettingsApp.ts' 'src/ui/PortalSettingsApp.ts'
].map(read).join('\n'); ].map(read).join('\n');
assert(packageJson.version === '3.1.0', 'Package-Version ist nicht 3.1.0.'); assert(packageJson.version === '3.2.0', 'Package-Version ist nicht 3.2.0.');
assert(solution.version === '3.1.0.0', 'Solution-Version ist nicht 3.1.0.0.'); assert(solution.version === '3.2.0.0', 'Solution-Version ist nicht 3.2.0.0.');
assert(!solution.features, 'Alte ASPX-Feature-Assets sind noch registriert.'); assert(solution.features && solution.features.length === 1, 'Das Seiten-Provisioning-Feature fehlt.');
assert(solution.features[0].assets.elementManifests.indexOf('elements.xml') >= 0 &&
solution.features[0].assets.elementFiles.indexOf('PortalSettings.aspx') >= 0 &&
solution.features[0].assets.upgradeActions.indexOf('upgrade-actions.xml') >= 0,
'Die Provisioning-Assets sind nicht vollständig registriert.');
assert(!!config.bundles['portal-settings-web-part'], 'WebPart-Bundle fehlt.'); assert(!!config.bundles['portal-settings-web-part'], 'WebPart-Bundle fehlt.');
assert(copyAssets.deployCdnPath === 'temp/deploy', 'Ship-Assets werden nicht nach temp/deploy geschrieben.'); assert(copyAssets.deployCdnPath === 'temp/deploy', 'Ship-Assets werden nicht nach temp/deploy geschrieben.');
assert(manifest.componentType === 'WebPart', 'Komponente ist kein WebPart.'); assert(manifest.componentType === 'WebPart', 'Komponente ist kein WebPart.');
assert(!fs.existsSync(path.join(root, 'src/assets/PortalSettings.aspx')), 'Alte ASPX-Seite ist noch vorhanden.'); assert(!fs.existsSync(path.join(root, 'src/assets/PortalSettings.aspx')), 'Alte ASPX-Seite ist noch vorhanden.');
assert(pageAsset.indexOf('Microsoft.SharePoint.WebControls.ClientSidePage') >= 0,
'Das provisionierte Asset ist keine moderne SharePoint-Seite.');
assert(elements.indexOf('Url="PortalSettings.aspx"') >= 0 && elements.indexOf('RootWebOnly="TRUE"') >= 0 &&
elements.indexOf('IgnoreIfAlreadyExists="TRUE"') >= 0 && elements.indexOf('Level="Published"') >= 0,
'PortalSettings.aspx wird nicht sicher im Root-Web provisioniert.');
assert(elements.indexOf('CanvasContent1') >= 0 &&
elements.indexOf('c41d05ec-0682-4af0-b807-649806ed56b3') >= 0,
'Das PortalSettings-WebPart fehlt im provisionierten Canvas.');
assert(upgradeActions.indexOf('71841e33-8bbd-4007-83a6-d950453226a2\\elements.xml') >= 0,
'Die Upgrade-Provisionierung fehlt.');
assert(!fs.existsSync(path.join(root, 'src/extensions/portalSettings/PortalSettingsApplicationCustomizer.ts')), 'Alter Application Customizer ist noch vorhanden.'); assert(!fs.existsSync(path.join(root, 'src/extensions/portalSettings/PortalSettingsApplicationCustomizer.ts')), 'Alter Application Customizer ist noch vorhanden.');
assert(sourceFiles.indexOf('innerHTML') < 0, 'UI darf innerHTML nicht verwenden.'); assert(sourceFiles.indexOf('innerHTML') < 0, 'UI darf innerHTML nicht verwenden.');
['themePrimary', 'neutralPrimary', 'neutralLight', 'white'].forEach(function (slot) { ['themePrimary', 'neutralPrimary', 'neutralLight', 'white'].forEach(function (slot) {