Bump version to 2.0.0, update component ID, and enhance central configuration for MegaMenu

This commit is contained in:
Torsten Brendgen
2026-07-19 23:15:38 +02:00
parent 07583b8122
commit 85c56a1153
11 changed files with 102 additions and 86 deletions

View File

@@ -4,7 +4,7 @@ Barrierearme, dreistufige Portalnavigation auf Basis von SharePoint Managed Meta
| Eigenschaft | Wert |
|---|---|
| Version | 1.1.4 |
| Version | 2.0.0 |
| SharePoint Framework | SPFx 1.4.1 |
| Node.js | 8.17.0 |
| Zieloberfläche | Moderne SharePoint-Seiten |
@@ -43,7 +43,7 @@ MegaMenuApplicationCustomizer
└── responsive Darstellung
```
Das MegaMenu liest seine Laufzeitkonfiguration aus der site-scoped UserCustomAction. Es enthält keine eigene Administrationsoberfläche. Die zentrale Pflege soll über die separate Solution **PortalSettings** erfolgen.
Das MegaMenu wird einmal pro Site Collection konfiguriert. PortalSettings speichert die zentrale Konfiguration im Property Bag des Root Webs und synchronisiert eine identische, web-scoped Runtime-Bindung auf das Root Web und alle vorhandenen Unterwebs. Das MegaMenu selbst enthält keine eigene Administrationsoberfläche.
## Voraussetzungen
@@ -126,10 +126,10 @@ sharepoint/solution/mega-menu.sppkg
1. `mega-menu.sppkg` in den App Catalog laden.
2. Die Solution freigeben.
3. Die App im Root Web der gewünschten Site Collection installieren. Der MegaMenu Application Customizer wird dabei automatisch web-scoped registriert und von PortalSettings erkannt.
3. Die App im Root Web der gewünschten Site Collection installieren. Der MegaMenu Application Customizer wird dort zunächst web-scoped registriert und von PortalSettings erkannt.
4. Das Termset in PortalSettings konfigurieren.
Das folgende Skript ist nur erforderlich, wenn ausdrücklich eine site-scoped Registrierung oder eine vollständig skriptbasierte Vorkonfiguration gewünscht ist.
Das folgende Skript ist nur erforderlich, wenn PortalSettings nicht verwendet wird oder eine vollständig skriptbasierte Vorkonfiguration gewünscht ist.
Empfohlen mit Termset-GUID:
@@ -149,7 +149,7 @@ Abwärtskompatibel nur mit Namen:
-TermSetName 'Global Navigation'
```
Das Skript entfernt ältere web-scoped Registrierungen derselben Komponente und erstellt beziehungsweise aktualisiert eine site-scoped UserCustomAction mit dem Description-Tag `MSFT-Custom-Solution:MegaMenu`. Dieses Tag wird von PortalSettings zur Erkennung verwendet.
Das Skript speichert die Konfiguration zentral unter `PortalSettings.MegaMenu.Configuration`, entfernt alte beziehungsweise doppelte Component IDs und synchronisiert die neue web-scoped Runtime-Bindung idempotent auf alle vorhandenen Webs. Fuer spaeter angelegte Unterwebs kann es ohne Nebenwirkungen erneut ausgefuehrt werden.
## Individuelles Branding
@@ -261,6 +261,13 @@ MegaMenu/
## Versionshistorie
### 2.0.0
- Neue Application-Customizer-ID `c0abbffb-355d-4d4e-bd38-9e15fb811506`, um alte On-Premises-Manifest- und Loader-Zuordnungen sicher zu umgehen.
- Eine zentrale MegaMenu-Konfiguration pro Site Collection im Property Bag des Root Webs.
- Web-scoped Runtime-Bindungen werden auf Root Web und alle vorhandenen Unterwebs synchronisiert.
- Aktivierungsskript entfernt alte Component IDs und kann fuer neue Unterwebs idempotent erneut ausgefuehrt werden.
### 1.1.4
- Unnötige externe Abhängigkeit zu `@microsoft/sp-lodash-subset` entfernt.

View File

@@ -113,7 +113,7 @@ Use one of these methods:
````powershell
# Connect to SharePoint site
Add-PnPCustomAction -Name "MegaMenuConfig" -Location "ClientSideExtension.ApplicationCustomizer" `
-ClientSideComponentId "abc3361f-bb2d-491f-aba3-cd51c19a299b" `
-ClientSideComponentId "c0abbffb-355d-4d4e-bd38-9e15fb811506" `
-ClientSideComponentProperties '{"termSetName":"Your Navigation Termset","cssUrl":"/SiteAssets/custom-menu.css"}'
````
@@ -269,4 +269,4 @@ Write-Host "✓ Same CSS as SPFx version" -ForegroundColor Green
Write-Host "✓ Same service logic (extracted to standalone)" -ForegroundColor Green
Write-Host "✓ Same configuration system" -ForegroundColor Green
Write-Host "✓ Same menu rendering output" -ForegroundColor Green
Write-Host "✓ No SPFx dependencies in classic version" -ForegroundColor Green
Write-Host "✓ No SPFx dependencies in classic version" -ForegroundColor Green

View File

@@ -19,7 +19,7 @@
(function() {
'use strict';
var MEGAMENU_UCA_ID = 'abc3361f-bb2d-491f-aba3-cd51c19a299b'; // Same as in MegaMenuApplicationCustomizer.ts
var MEGAMENU_UCA_ID = 'c0abbffb-355d-4d4e-bd38-9e15fb811506'; // Same as in MegaMenuApplicationCustomizer.ts
var config = window.MegaMenuConfig || {
containerId: 's4-titlerow',
@@ -262,4 +262,4 @@
log('MegaMenu Classic wrapper loaded. Waiting for dependencies...');
})();
})();

View File

@@ -3,7 +3,7 @@
"solution": {
"name": "mega-menu-client-side-solution",
"id": "f4660e06-ce08-43ee-bfb7-5c4464e01133",
"version": "1.1.4.0",
"version": "2.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": false,
"features": [
@@ -11,7 +11,7 @@
"title": "MegaMenu extension registration",
"description": "Registers the MegaMenu Application Customizer in the host web.",
"id": "1e4fdc74-8053-48b2-a15b-e975d61eb71f",
"version": "1.1.4.0",
"version": "2.0.0.0",
"assets": {
"elementManifests": [
"elements.xml"

View File

@@ -6,7 +6,7 @@
"default": {
"pageUrl": "https://sharepoint.contoso.local/SitePages/Neues-Zuhause.aspx",
"customActions": {
"abc3361f-bb2d-491f-aba3-cd51c19a299b": {
"c0abbffb-355d-4d4e-bd38-9e15fb811506": {
"location": "ClientSideExtension.ApplicationCustomizer",
"properties": {
"termSetName": "Horizontale Navigation",
@@ -18,7 +18,7 @@
"megaMenu": {
"pageUrl": "https://contoso.sharepoint.com/sites/mySite/SitePages/myPage.aspx",
"customActions": {
"abc3361f-bb2d-491f-aba3-cd51c19a299b": {
"c0abbffb-355d-4d4e-bd38-9e15fb811506": {
"location": "ClientSideExtension.ApplicationCustomizer",
"properties": {
"testMessage": "Test message"

View File

@@ -17,90 +17,99 @@ param(
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
$componentId = 'abc3361f-bb2d-491f-aba3-cd51c19a299b'
$componentId = [Guid]'c0abbffb-355d-4d4e-bd38-9e15fb811506'
$legacyComponentId = [Guid]'abc3361f-bb2d-491f-aba3-cd51c19a299b'
$location = 'ClientSideExtension.ApplicationCustomizer'
$name = 'MegaMenu'
$title = 'Mega Menu'
$configurationProperty = 'PortalSettings.MegaMenu.Configuration'
function Get-MegaMenuPropertiesJson {
param(
[string]$CurrentTermSetName,
[string]$CurrentTermSetId,
[int]$CurrentCacheMinutes,
[bool]$CurrentDebug
$properties = @{
termSetName = $TermSetName
termSetId = $TermSetId
cacheMinutes = $CacheMinutes
debug = [bool]$EnableDebug.IsPresent
} | ConvertTo-Json -Depth 10 -Compress
$site = Get-SPSite -Identity $SiteUrl
try {
$rootWeb = $site.RootWeb
$rootWeb.AllProperties[$configurationProperty] = $properties
$rootWeb.Update()
$siteActions = @(
$site.UserCustomActions |
Where-Object {
$_.ClientSideComponentId -eq $componentId -or
$_.ClientSideComponentId -eq $legacyComponentId
}
)
return (@{
termSetName = $CurrentTermSetName
termSetId = $CurrentTermSetId
cacheMinutes = $CurrentCacheMinutes
debug = $CurrentDebug
} | ConvertTo-Json -Depth 10 -Compress)
}
foreach ($siteAction in $siteActions) {
$siteAction.Delete()
}
function Remove-WebScopedComponentActions {
param(
[Microsoft.SharePoint.SPSite]$CurrentSite,
[string]$CurrentComponentId,
[string]$CurrentLocation
)
$created = 0
$updated = 0
$removedLegacy = 0
$removedCount = 0
foreach ($web in $CurrentSite.AllWebs) {
foreach ($web in $site.AllWebs) {
try {
$webActions = @($web.UserCustomActions | Where-Object {
$_.Location -eq $CurrentLocation -and
$_.ClientSideComponentId -and
$_.ClientSideComponentId.ToString().ToLower() -eq $CurrentComponentId
})
$actions = @(
$web.UserCustomActions |
Where-Object {
$_.ClientSideComponentId -eq $componentId -or
$_.ClientSideComponentId -eq $legacyComponentId
}
)
foreach ($webAction in $webActions) {
$web.UserCustomActions.Delete($webAction.Id)
$removedCount++
$currentAction = $actions |
Where-Object {
$_.ClientSideComponentId -eq $componentId
} |
Select-Object -First 1
foreach ($existingAction in $actions) {
if ($currentAction -and $existingAction.Id -eq $currentAction.Id) {
continue
}
$existingAction.Delete()
$removedLegacy++
}
if ($webActions.Count -gt 0) {
$web.Update()
if (-not $currentAction) {
$currentAction = $web.UserCustomActions.Add()
$currentAction.Name = [Guid]::NewGuid().ToString('B')
$created++
}
else {
$updated++
}
$currentAction.Title = 'MegaMenu Application Customizer'
$currentAction.Description = $Description
$currentAction.Location = $location
$currentAction.ClientSideComponentId = $componentId
$currentAction.ClientSideComponentProperties = $properties
$currentAction.Sequence = 100
$currentAction.Update()
$web.Update()
Write-Host ('MegaMenu synchronisiert: ' + $web.Url) -ForegroundColor Green
}
finally {
$web.Dispose()
}
}
return $removedCount
}
$site = Get-SPSite -Identity $SiteUrl
try {
$removedWebScopedActions = Remove-WebScopedComponentActions -CurrentSite $site -CurrentComponentId $componentId -CurrentLocation $location
$existingAction = $site.UserCustomActions | Where-Object {
$_.Location -eq $location -and $_.ClientSideComponentId -and $_.ClientSideComponentId.ToString().ToLower() -eq $componentId
} | Select-Object -First 1
if ($existingAction) {
$action = $existingAction
Write-Host 'Aktualisiere vorhandene site-scoped Mega Menu UserCustomAction...' -ForegroundColor Yellow
}
else {
$action = $site.UserCustomActions.Add()
Write-Host 'Erstelle neue site-scoped Mega Menu UserCustomAction...' -ForegroundColor Yellow
}
$action.Name = $name
$action.Title = $title
$action.Description = $Description
$action.Location = $location
$action.ClientSideComponentId = [Guid]$componentId
$action.ClientSideComponentProperties = Get-MegaMenuPropertiesJson -CurrentTermSetName $TermSetName -CurrentTermSetId $TermSetId -CurrentCacheMinutes $CacheMinutes -CurrentDebug ([bool]$EnableDebug.IsPresent)
$action.Update()
Write-Host 'Mega Menu wurde site-scoped registriert.' -ForegroundColor Green
Write-Host ('Entfernte web-scoped Eintraege: ' + $removedWebScopedActions)
Write-Host ('Beschreibung: ' + $Description)
Write-Host ('Properties: ' + $action.ClientSideComponentProperties)
Write-Host ''
Write-Host 'MegaMenu wurde fuer die gesamte Site Collection konfiguriert.' -ForegroundColor Green
Write-Host ('Zentrale Konfiguration: ' + $configurationProperty)
Write-Host ('Neu registrierte Webs: ' + $created)
Write-Host ('Aktualisierte Webs: ' + $updated)
Write-Host ('Entfernte alte oder doppelte Registrierungen: ' + $removedLegacy)
Write-Host ('Properties: ' + $properties)
Write-Host 'Neue Unterwebs koennen durch erneutes Ausfuehren idempotent synchronisiert werden.' -ForegroundColor Yellow
}
finally {
if ($site) {

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "mega-menu",
"version": "1.1.4",
"version": "2.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "mega-menu",
"version": "1.1.4",
"version": "2.0.0",
"private": true,
"main": "lib/index.js",
"engines": {

View File

@@ -3,6 +3,6 @@
<CustomAction
Title="MegaMenu Application Customizer"
Location="ClientSideExtension.ApplicationCustomizer"
ClientSideComponentId="abc3361f-bb2d-491f-aba3-cd51c19a299b"
ClientSideComponentId="c0abbffb-355d-4d4e-bd38-9e15fb811506"
ClientSideComponentProperties="{}" />
</Elements>

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-extension-manifest.schema.json",
"id": "abc3361f-bb2d-491f-aba3-cd51c19a299b",
"id": "c0abbffb-355d-4d4e-bd38-9e15fb811506",
"alias": "MegaMenuApplicationCustomizer",
"componentType": "Extension",
"extensionType": "ApplicationCustomizer",

View File

@@ -19,7 +19,7 @@ import { debugError, debugLog, debugWarn } from '../../services/MegaMenuDebug';
import './MegaMenu.module.scss';
const LOG_SOURCE: string = 'MegaMenuApplicationCustomizer';
export const UserCustomActionMegaMenuId: string = 'abc3361f-bb2d-491f-aba3-cd51c19a299b';
export const UserCustomActionMegaMenuId: string = 'c0abbffb-355d-4d4e-bd38-9e15fb811506';
export interface IMegaMenuApplicationCustomizerProperties {
termSetName?: string;
@@ -40,7 +40,7 @@ export default class MegaMenuApplicationCustomizer
const debug: boolean = this._isDebugEnabled();
debugLog(debug, LOG_SOURCE, 'onInit started.', {
componentId: UserCustomActionMegaMenuId,
version: '1.1.4',
version: '2.0.0',
properties: this.properties || {},
pageUrl: window.location.href,
webUrl: this.context.pageContext.web.absoluteUrl,