Aktualisiere Versionsnummer auf 2.1.8 in README.md, package.json, package-lock.json und package-solution.json. Füge Logik hinzu, um site-scoped UserCustomAction für Custom-Branding- und MegaMenu-Konfigurationen zu erstellen und alte Web-Einträge zu entfernen.

This commit is contained in:
Torsten Brendgen
2026-07-19 22:13:09 +02:00
parent 2e15907117
commit d7d469adb0
6 changed files with 15 additions and 7 deletions

View File

@@ -88,13 +88,16 @@ function parseSolutionConfig(key,rawValue){var parsed={};if(typeof rawValue==='s
function normalizeBrandingConfig(config){var normalized={cssfiles:[],placeholdertop:{elements:[]},placeholderbottom:{elements:[]}};if(config&&Array.isArray(config.cssfiles)){normalized.cssfiles=config.cssfiles.filter(function(item){return item&&typeof item.path==='string'&&item.path.trim().length>0;}).map(function(item){return{path:item.path.trim()};});}if(config&&config.placeholdertop&&Array.isArray(config.placeholdertop.elements)){normalized.placeholdertop.elements=config.placeholdertop.elements;}else if(config&&Array.isArray(config.elements)){normalized.placeholdertop.elements=config.elements;}if(config&&config.placeholderbottom&&Array.isArray(config.placeholderbottom.elements)){normalized.placeholderbottom.elements=config.placeholderbottom.elements;}return normalized;}
function normalizeMegaMenuConfig(config){var cacheMinutes=config?Number(config.cacheMinutes):15;return{termSetId:config&&typeof config.termSetId==='string'?config.termSetId.trim():'',termSetName:config&&typeof config.termSetName==='string'?config.termSetName.trim():'',cacheMinutes:isFinite(cacheMinutes)?Math.min(Math.max(Math.floor(cacheMinutes),1),1440):15,debug:!!(config&&config.debug===true)};}
function parseJsonArray(textareaId,label){var textarea=document.getElementById(textareaId);var rawValue=textarea.value.trim();if(!rawValue){return [];}var parsedValue;try{parsedValue=JSON.parse(rawValue);}catch(error){throw new Error(label+' enthaelt kein gueltiges JSON: '+error.message);}if(!Array.isArray(parsedValue)){throw new Error(label+' muss ein JSON-Array sein.');}return parsedValue;}
function updateSolutionAction(key,config,onSuccess,onError){var solution=state.solutions[key];if(!solution||!solution.info||!solution.info.action){onError('Die passende UserCustomAction wurde nicht gefunden.');return;}var actionId=solution.info.action.Id;if(!actionId){onError('Die UserCustomAction hat keine gueltige Id.');return;}var updateUrl=solution.info.updateBaseUrl+'(guid\''+actionId+'\')';var payload={__metadata:{type:solution.info.actionType||'SP.UserCustomAction'},ClientSideComponentProperties:JSON.stringify(config)};postJsonMerge(updateUrl,payload,onSuccess,onError);}
function updateSolutionAction(key,config,onSuccess,onError){var solution=state.solutions[key];if(!solution||!solution.info||!solution.info.action){onError('Die passende UserCustomAction wurde nicht gefunden.');return;}if(solution.info.scopeLabel!=='Site Collection'){promoteSolutionActionToSiteCollection(key,config,onSuccess,onError);return;}var actionId=solution.info.action.Id;if(!actionId){onError('Die UserCustomAction hat keine gueltige Id.');return;}var updateUrl=solution.info.updateBaseUrl+'(guid\''+actionId+'\')';var payload={__metadata:{type:solution.info.actionType||'SP.UserCustomAction'},ClientSideComponentProperties:JSON.stringify(config)};postJsonMerge(updateUrl,payload,onSuccess,onError);}
function promoteSolutionActionToSiteCollection(key,config,onSuccess,onError){var solution=state.solutions[key];var definition=solution.definition;var oldInfo=solution.info;var oldAction=oldInfo.action;var siteActionsUrl=getSiteUrl().replace(/\/$/,'')+'/_api/site/UserCustomActions';var payload={__metadata:{type:'SP.UserCustomAction'},Name:oldAction.Name||definition.key,Title:oldAction.Title||definition.label,Description:definition.descriptionTag||CUSTOM_SOLUTION_TAG,Location:'ClientSideExtension.ApplicationCustomizer',ClientSideComponentId:definition.componentId,ClientSideComponentProperties:JSON.stringify(config)};postJsonResult(siteActionsUrl,payload,function(createdPayload){var createdAction=createdPayload&&createdPayload.d?createdPayload.d:createdPayload;var oldActionId=oldAction.Id;function finish(){solution.info={action:createdAction&&createdAction.Id?createdAction:{Id:createdAction&&createdAction.Id?createdAction.Id:'',Title:payload.Title,Name:payload.Name,Description:payload.Description,Location:payload.Location,ClientSideComponentId:payload.ClientSideComponentId,ClientSideComponentProperties:payload.ClientSideComponentProperties},updateBaseUrl:siteActionsUrl,actionType:'SP.UserCustomAction',scopeLabel:'Site Collection'};onSuccess();}if(!oldActionId||!oldInfo.updateBaseUrl){finish();return;}var oldUrl=oldInfo.updateBaseUrl+'(guid\''+oldActionId+'\')';postJsonDelete(oldUrl,finish,function(message){if(window.console&&console.warn){console.warn('Die site-scoped Registrierung wurde erstellt, der alte Web-Eintrag konnte aber nicht entfernt werden: '+message);}finish();});},function(message){onError('Die site-scoped UserCustomAction konnte nicht erstellt werden: '+message);});}
function readCustomizerActionInfo(definition,onSuccess,onError){var baseSiteUrl=getSiteUrl().replace(/\/$/,'');var endpoints=[{scopeLabel:'Site Collection',readUrl:baseSiteUrl+'/_api/site/UserCustomActions',updateBaseUrl:baseSiteUrl+'/_api/site/UserCustomActions'},{scopeLabel:'Web',readUrl:baseSiteUrl+'/_api/site/rootweb/UserCustomActions',updateBaseUrl:baseSiteUrl+'/_api/site/rootweb/UserCustomActions'}];readCustomizerActionInfoFromEndpoints(definition,endpoints,0,[],onSuccess,onError);}
function readCustomizerActionInfoFromEndpoints(definition,endpoints,index,errors,onSuccess,onError){if(index>=endpoints.length){if(errors.length){onError(errors.join(' | '));return;}onSuccess(null);return;}var endpoint=endpoints[index];getJson(endpoint.readUrl,function(payload){try{var actions=getResultArray(payload);var action=findActiveCustomizerAction(actions,definition);if(action){onSuccess({action:action,updateBaseUrl:endpoint.updateBaseUrl,actionType:action.__metadata&&action.__metadata.type?action.__metadata.type:'SP.UserCustomAction',scopeLabel:endpoint.scopeLabel});return;}readCustomizerActionInfoFromEndpoints(definition,endpoints,index+1,errors,onSuccess,onError);}catch(error){errors.push(error.message||String(error));readCustomizerActionInfoFromEndpoints(definition,endpoints,index+1,errors,onSuccess,onError);}},function(message){errors.push(message);readCustomizerActionInfoFromEndpoints(definition,endpoints,index+1,errors,onSuccess,onError);});}
function findActiveCustomizerAction(actions,definition){if(!Array.isArray(actions)||!definition){return null;}var expected=normalizeGuid(definition.componentId);var tagged=null;var applicationCustomizer=null;var componentFallback=null;for(var i=0;i<actions.length;i++){var action=actions[i];if(normalizeGuid(action&&action.ClientSideComponentId)!==expected){continue;}if(!componentFallback){componentFallback=action;}var isApplicationCustomizer=typeof action.Location==='string'&&action.Location.indexOf('ClientSideExtension.ApplicationCustomizer')!==-1;if(isApplicationCustomizer&&!applicationCustomizer){applicationCustomizer=action;}if(matchesSolutionTag(action,definition)){if(isApplicationCustomizer){return action;}if(!tagged){tagged=action;}}}return tagged||applicationCustomizer||componentFallback;}function matchesSolutionTag(action,definition){var description=action&&typeof action.Description==='string'?action.Description:'';if(description.indexOf(CUSTOM_SOLUTION_TAG)===-1){return false;}if(definition&&typeof definition.descriptionTag==='string'&&definition.descriptionTag){return description.indexOf(definition.descriptionTag)!==-1||description===CUSTOM_SOLUTION_TAG;}return true;}
function getJson(url,onSuccess,onError){try{var request=new XMLHttpRequest();request.open('GET',url,true);request.setRequestHeader('Accept','application/json;odata=verbose');request.onreadystatechange=function(){if(request.readyState!==4){return;}if(request.status>=200&&request.status<300){try{onSuccess(JSON.parse(request.responseText||'{}'));}catch(error){onError('Antwort konnte nicht gelesen werden: '+(error.message||String(error)));}return;}onError(buildRequestErrorMessage(request));};request.onerror=function(){onError('Netzwerkfehler beim Lesen von '+url);};request.send();}catch(error){onError(error.message||String(error));}}
function postJson(url,payload,onSuccess,onError){try{var digest=getRequestDigest();if(!digest){onError('Kein Request Digest gefunden. Laden Sie die Seite neu und versuchen Sie es erneut.');return;}var request=new XMLHttpRequest();request.open('POST',url,true);request.setRequestHeader('Accept','application/json;odata=verbose');request.setRequestHeader('Content-Type','application/json;odata=verbose');request.setRequestHeader('X-RequestDigest',digest);request.onreadystatechange=function(){if(request.readyState!==4){return;}if(request.status>=200&&request.status<300){onSuccess();return;}onError(buildRequestErrorMessage(request));};request.onerror=function(){onError('Netzwerkfehler beim Erstellen unter '+url);};request.send(JSON.stringify(payload));}catch(error){onError(error.message||String(error));}}
function postJsonMerge(url,payload,onSuccess,onError){try{var digest=getRequestDigest();if(!digest){onError('Kein Request Digest gefunden. Laden Sie die Seite neu und versuchen Sie es erneut.');return;}var request=new XMLHttpRequest();request.open('POST',url,true);request.setRequestHeader('Accept','application/json;odata=verbose');request.setRequestHeader('Content-Type','application/json;odata=verbose');request.setRequestHeader('X-RequestDigest',digest);request.setRequestHeader('IF-MATCH','*');request.setRequestHeader('X-HTTP-Method','MERGE');request.onreadystatechange=function(){if(request.readyState!==4){return;}if(request.status>=200&&request.status<300){onSuccess();return;}onError(buildRequestErrorMessage(request));};request.onerror=function(){onError('Netzwerkfehler beim Aktualisieren von '+url);};request.send(JSON.stringify(payload));}catch(error){onError(error.message||String(error));}}
function postJsonResult(url,payload,onSuccess,onError){try{var digest=getRequestDigest();if(!digest){onError('Kein Request Digest gefunden. Laden Sie die Seite neu und versuchen Sie es erneut.');return;}var request=new XMLHttpRequest();request.open('POST',url,true);request.setRequestHeader('Accept','application/json;odata=verbose');request.setRequestHeader('Content-Type','application/json;odata=verbose');request.setRequestHeader('X-RequestDigest',digest);request.onreadystatechange=function(){if(request.readyState!==4){return;}if(request.status>=200&&request.status<300){try{onSuccess(request.responseText?JSON.parse(request.responseText):{});}catch(error){onError('Erstellte UserCustomAction konnte nicht gelesen werden: '+(error.message||String(error)));}return;}onError(buildRequestErrorMessage(request));};request.onerror=function(){onError('Netzwerkfehler beim Erstellen unter '+url);};request.send(JSON.stringify(payload));}catch(error){onError(error.message||String(error));}}
function postJsonDelete(url,onSuccess,onError){try{var digest=getRequestDigest();if(!digest){onError('Kein Request Digest gefunden.');return;}var request=new XMLHttpRequest();request.open('POST',url,true);request.setRequestHeader('Accept','application/json;odata=verbose');request.setRequestHeader('X-RequestDigest',digest);request.setRequestHeader('IF-MATCH','*');request.setRequestHeader('X-HTTP-Method','DELETE');request.onreadystatechange=function(){if(request.readyState!==4){return;}if(request.status>=200&&request.status<300){onSuccess();return;}onError(buildRequestErrorMessage(request));};request.onerror=function(){onError('Netzwerkfehler beim Entfernen von '+url);};request.send();}catch(error){onError(error.message||String(error));}}
function getRequestDigest(){var digestField=document.getElementById('__REQUESTDIGEST');return digestField&&digestField.value?digestField.value:'';}
function getResultArray(payload){if(payload&&payload.d&&Array.isArray(payload.d.results)){return payload.d.results;}if(payload&&Array.isArray(payload.value)){return payload.value;}return [];}
function normalizeGuid(value){if(typeof value!=='string'){return '';}var normalized=value.replace(/[{}]/g,'').toLowerCase();return normalized==='00000000-0000-0000-0000-000000000000'?'':normalized;}