diff --git a/README.md b/README.md
index 1695fc8..05a2404 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Das Paket liegt danach unter `sharepoint/solution/portal-settings.sppkg`.
## Installation und Upgrade
-1. `portal-settings.sppkg` im App Catalog durch Version `2.1.4.0` ersetzen.
+1. `portal-settings.sppkg` im App Catalog durch Version `2.1.5.0` ersetzen.
2. PortalSettings im Root Web der Site Collection installieren beziehungsweise aktualisieren.
3. `expiry-indicator.sppkg` durch Version `2.1.0.0` ersetzen und die App aktualisieren.
4. `/SitePages/PortalSettings.aspx` mit geleertem Browsercache laden.
diff --git a/config/package-solution.json b/config/package-solution.json
index b70408c..dde85ab 100644
--- a/config/package-solution.json
+++ b/config/package-solution.json
@@ -3,7 +3,7 @@
"solution": {
"name": "portal-settings-client-side-solution",
"id": "1c98e32d-bb7b-43b7-9625-074d6e4ea286",
- "version": "2.1.4.0",
+ "version": "2.1.5.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": false,
"features": [
@@ -11,7 +11,7 @@
"title": "Portal Settings",
"description": "Provisioniert die zentrale Settings-Seite fuer aktive Portal-Erweiterungen.",
"id": "57bd9daf-48f9-49e2-aebd-11b15a0b5e93",
- "version": "2.1.4.0",
+ "version": "2.1.5.0",
"assets": {
"elementManifests": [
"elements-v2.xml"
diff --git a/package-lock.json b/package-lock.json
index 6668aa9..6604d34 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "portal-settings",
- "version": "2.1.4",
+ "version": "2.1.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 9f89f6c..32de845 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "portal-settings",
- "version": "2.1.4",
+ "version": "2.1.5",
"private": true,
"main": "lib/index.js",
"engines": {
diff --git a/sharepoint/assets/PortalSettings.aspx b/sharepoint/assets/PortalSettings.aspx
index 574b307..2ce1151 100644
--- a/sharepoint/assets/PortalSettings.aspx
+++ b/sharepoint/assets/PortalSettings.aspx
@@ -51,7 +51,7 @@ function getExpiryBindingInput(){var webUrl=document.getElementById('bindExpiryW
function bindingListUrl(target){return target.webUrl+"/_api/web/lists/getbytitle('"+target.listTitle.replace(/'/g,"''")+"')";}
function bindExpiryIndicatorFromDialog(){var target;try{target=getExpiryBindingInput();}catch(error){showStatus(error.message,'error',true);return;}var button=document.getElementById('bindExpirySubmit');button.disabled=true;showStatus('Pruefe Liste und Ablaufdatumsfeld...','info',true);var listUrl=bindingListUrl(target);getJson(listUrl+'?$select=Id,Title,BaseType',function(listPayload){var list=listPayload.d||listPayload;getJson(listUrl+"/fields/getbyinternalnameortitle('"+target.fieldName+"')?$select=Id,InternalName,TypeAsString,ClientSideComponentId,ClientSideComponentProperties",function(fieldPayload){var field=fieldPayload.d||fieldPayload;var currentComponent=normalizeGuid(field.ClientSideComponentId);if(currentComponent&¤tComponent!==normalizeGuid(EXPIRY_FIELD_COMPONENT_ID)){button.disabled=false;showStatus('Das Feld ist bereits mit einem anderen Field Customizer verbunden. Die Bindung wurde nicht geaendert.','error',true);return;}if(field.TypeAsString&&field.TypeAsString!=='DateTime'){button.disabled=false;showStatus('Das angegebene Feld ist kein DateTime-Feld.','error',true);return;}var properties=field.ClientSideComponentProperties;if(!properties||!String(properties).trim()){properties=JSON.stringify({schemaVersion:2,expiryField:field.InternalName,inheritSiteDefaults:true});}var payload={__metadata:{type:field.__metadata&&field.__metadata.type?field.__metadata.type:'SP.Field'},ClientSideComponentId:EXPIRY_FIELD_COMPONENT_ID,ClientSideComponentProperties:properties};postJsonMerge(listUrl+"/fields(guid'"+normalizeGuid(field.Id)+"')",payload,function(){var info={target:target,list:list,field:field,listUrl:listUrl};function finish(classicWarning){registerExpiryBinding(info,function(){button.disabled=false;closeExpiryBindingDialog();reloadSolutions('expiryindicator');if(classicWarning){showStatus('Die moderne Bindung wurde angelegt. Classic konnte nicht vollstaendig registriert werden: '+classicWarning,'warning',true);}else{showStatus('ExpiryIndicator wurde erfolgreich angebunden und zentral registriert.','success');}},function(message){button.disabled=false;showStatus('Das Feld wurde gebunden, aber das zentrale Inventar konnte nicht aktualisiert werden: '+message,'warning',true);});}if(target.classic){ensureExpiryClassicRegistration(info,function(warning){finish(warning);});}else{finish('');}},function(message){button.disabled=false;showStatus('Das Feld konnte nicht mit dem ExpiryIndicator verbunden werden: '+message,'error',true);});},function(message){button.disabled=false;showStatus('Das Ablaufdatumsfeld konnte nicht gelesen werden: '+message,'error',true);});},function(message){button.disabled=false;showStatus('Die Liste oder Bibliothek konnte nicht gelesen werden: '+message,'error',true);});}
function registerExpiryBinding(info,onSuccess,onError){getJson(getSiteUrl().replace(/\/$/,'')+'/_api/web/AllProperties',function(payload){var properties=payload.d||payload||{};var bindings=normalizeExpiryBindings(propertyBagJson(properties,EXPIRY_BINDINGS_PROPERTY,[]));var webUrl=info.target.webUrl.replace(/\/$/,'');var listId=normalizeGuid(info.list.Id);bindings=bindings.filter(function(item){return !(String(item.webUrl||'').replace(/\/$/,'').toLowerCase()===webUrl.toLowerCase()&&normalizeGuid(item.listId)===listId);});bindings.push({webUrl:webUrl,listId:listId,listTitle:info.list.Title,fieldInternalName:info.field.InternalName,fieldId:normalizeGuid(info.field.Id)});var descriptor={key:'ExpiryIndicator',displayName:'Expiry Indicator',version:'2.1.1',provider:'expiryIndicator',componentIds:[EXPIRY_FIELD_COMPONENT_ID,'cd58f5d9-ffc8-4df7-a910-3054842d7abf','95691218-bcb1-4fad-adda-02bb12014d15'],settingsScope:['siteCollection','web','list']};setRootPropertyBagValue(EXPIRY_DESCRIPTOR_PROPERTY,JSON.stringify(descriptor),function(){setRootPropertyBagValue(EXPIRY_BINDINGS_PROPERTY,JSON.stringify(bindings),onSuccess,onError);},onError);},onError);}
-function ensureExpiryClassicRegistration(info,onComplete){var webActionsUrl=info.target.webUrl+'/_api/web/UserCustomActions';getJson(webActionsUrl,function(webPayload){var webActions=getResultArray(webPayload);var hasScript=webActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.ScriptLink';});function ensureRibbon(){var listActionsUrl=info.listUrl+'/UserCustomActions';getJson(listActionsUrl,function(listPayload){var listActions=getResultArray(listPayload);var hasRibbon=listActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.Ribbon';});if(hasRibbon){onComplete('');return;}var ribbonLocation=Number(info.list.BaseType)===1?'Ribbon.Library.Actions.Controls._children':'Ribbon.List.Actions.Controls._children';var ribbonXml='';postJson(listActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.Ribbon',Title:'ExpiryIndicator Classic ribbon command',Location:'CommandUI.Ribbon',CommandUIExtension:ribbonXml,Sequence:651},function(){onComplete('');},onComplete);},onComplete);}if(hasScript){ensureRibbon();return;}postJson(webActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.ScriptLink',Title:'ExpiryIndicator Classic runtime',Location:'ScriptLink',ScriptSrc:'~sitecollection/SiteAssets/ExpiryIndicator/ExpiryIndicatorClassic.js',Sequence:650},ensureRibbon,onComplete);},onComplete);}
+function ensureExpiryClassicRegistration(info,onComplete){var webActionsUrl=info.target.webUrl+'/_api/web/UserCustomActions';getJson(webActionsUrl,function(webPayload){var webActions=getResultArray(webPayload);var hasScript=webActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.ScriptLink';});function ensureRibbon(){var listActionsUrl=info.listUrl+'/UserCustomActions';getJson(listActionsUrl,function(listPayload){var listActions=getResultArray(listPayload);var ribbonAction=null;for(var i=0;i';var payload={__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.Ribbon',Title:'ExpiryIndicator Classic ribbon command',Location:'CommandUI.Ribbon',CommandUIExtension:ribbonXml,Sequence:651};if(ribbonAction){if(String(ribbonAction.CommandUIExtension||'').indexOf(ribbonLocation)>=0){onComplete('');return;}postJsonMerge(listActionsUrl+"(guid'"+normalizeGuid(ribbonAction.Id)+"')",payload,function(){onComplete('');},onComplete);return;}postJson(listActionsUrl,payload,function(){onComplete('');},onComplete);},onComplete);}if(hasScript){ensureRibbon();return;}postJson(webActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.ScriptLink',Title:'ExpiryIndicator Classic runtime',Location:'ScriptLink',ScriptSrc:'~sitecollection/SiteAssets/ExpiryIndicator/ExpiryIndicatorClassic.js',Sequence:650},ensureRibbon,onComplete);},onComplete);}
function normalizePropertyBagKey(value){return String(value||'').replace(/_x002e_/gi,'.').toLowerCase();}
function propertyBagJson(properties,key,fallback){if(!properties){return fallback;}var value;var expected=normalizePropertyBagKey(key);Object.keys(properties).some(function(name){if(normalizePropertyBagKey(name)===expected){value=properties[name];return true;}return false;});if(typeof value==='undefined'||value===null||value===''){return fallback;}if(typeof value==='object'){return value;}try{return JSON.parse(value);}catch(ignore){return fallback;}}
function normalizeExpiryBindings(value){var result=[];function visit(item){if(Array.isArray(item)){item.forEach(visit);return;}if(!item||typeof item!=='object'){return;}if(item.webUrl&&item.listId&&item.fieldInternalName){result.push(item);}}visit(value);return result;}
diff --git a/src/assets/PortalSettings.aspx b/src/assets/PortalSettings.aspx
index 574b307..2ce1151 100644
--- a/src/assets/PortalSettings.aspx
+++ b/src/assets/PortalSettings.aspx
@@ -51,7 +51,7 @@ function getExpiryBindingInput(){var webUrl=document.getElementById('bindExpiryW
function bindingListUrl(target){return target.webUrl+"/_api/web/lists/getbytitle('"+target.listTitle.replace(/'/g,"''")+"')";}
function bindExpiryIndicatorFromDialog(){var target;try{target=getExpiryBindingInput();}catch(error){showStatus(error.message,'error',true);return;}var button=document.getElementById('bindExpirySubmit');button.disabled=true;showStatus('Pruefe Liste und Ablaufdatumsfeld...','info',true);var listUrl=bindingListUrl(target);getJson(listUrl+'?$select=Id,Title,BaseType',function(listPayload){var list=listPayload.d||listPayload;getJson(listUrl+"/fields/getbyinternalnameortitle('"+target.fieldName+"')?$select=Id,InternalName,TypeAsString,ClientSideComponentId,ClientSideComponentProperties",function(fieldPayload){var field=fieldPayload.d||fieldPayload;var currentComponent=normalizeGuid(field.ClientSideComponentId);if(currentComponent&¤tComponent!==normalizeGuid(EXPIRY_FIELD_COMPONENT_ID)){button.disabled=false;showStatus('Das Feld ist bereits mit einem anderen Field Customizer verbunden. Die Bindung wurde nicht geaendert.','error',true);return;}if(field.TypeAsString&&field.TypeAsString!=='DateTime'){button.disabled=false;showStatus('Das angegebene Feld ist kein DateTime-Feld.','error',true);return;}var properties=field.ClientSideComponentProperties;if(!properties||!String(properties).trim()){properties=JSON.stringify({schemaVersion:2,expiryField:field.InternalName,inheritSiteDefaults:true});}var payload={__metadata:{type:field.__metadata&&field.__metadata.type?field.__metadata.type:'SP.Field'},ClientSideComponentId:EXPIRY_FIELD_COMPONENT_ID,ClientSideComponentProperties:properties};postJsonMerge(listUrl+"/fields(guid'"+normalizeGuid(field.Id)+"')",payload,function(){var info={target:target,list:list,field:field,listUrl:listUrl};function finish(classicWarning){registerExpiryBinding(info,function(){button.disabled=false;closeExpiryBindingDialog();reloadSolutions('expiryindicator');if(classicWarning){showStatus('Die moderne Bindung wurde angelegt. Classic konnte nicht vollstaendig registriert werden: '+classicWarning,'warning',true);}else{showStatus('ExpiryIndicator wurde erfolgreich angebunden und zentral registriert.','success');}},function(message){button.disabled=false;showStatus('Das Feld wurde gebunden, aber das zentrale Inventar konnte nicht aktualisiert werden: '+message,'warning',true);});}if(target.classic){ensureExpiryClassicRegistration(info,function(warning){finish(warning);});}else{finish('');}},function(message){button.disabled=false;showStatus('Das Feld konnte nicht mit dem ExpiryIndicator verbunden werden: '+message,'error',true);});},function(message){button.disabled=false;showStatus('Das Ablaufdatumsfeld konnte nicht gelesen werden: '+message,'error',true);});},function(message){button.disabled=false;showStatus('Die Liste oder Bibliothek konnte nicht gelesen werden: '+message,'error',true);});}
function registerExpiryBinding(info,onSuccess,onError){getJson(getSiteUrl().replace(/\/$/,'')+'/_api/web/AllProperties',function(payload){var properties=payload.d||payload||{};var bindings=normalizeExpiryBindings(propertyBagJson(properties,EXPIRY_BINDINGS_PROPERTY,[]));var webUrl=info.target.webUrl.replace(/\/$/,'');var listId=normalizeGuid(info.list.Id);bindings=bindings.filter(function(item){return !(String(item.webUrl||'').replace(/\/$/,'').toLowerCase()===webUrl.toLowerCase()&&normalizeGuid(item.listId)===listId);});bindings.push({webUrl:webUrl,listId:listId,listTitle:info.list.Title,fieldInternalName:info.field.InternalName,fieldId:normalizeGuid(info.field.Id)});var descriptor={key:'ExpiryIndicator',displayName:'Expiry Indicator',version:'2.1.1',provider:'expiryIndicator',componentIds:[EXPIRY_FIELD_COMPONENT_ID,'cd58f5d9-ffc8-4df7-a910-3054842d7abf','95691218-bcb1-4fad-adda-02bb12014d15'],settingsScope:['siteCollection','web','list']};setRootPropertyBagValue(EXPIRY_DESCRIPTOR_PROPERTY,JSON.stringify(descriptor),function(){setRootPropertyBagValue(EXPIRY_BINDINGS_PROPERTY,JSON.stringify(bindings),onSuccess,onError);},onError);},onError);}
-function ensureExpiryClassicRegistration(info,onComplete){var webActionsUrl=info.target.webUrl+'/_api/web/UserCustomActions';getJson(webActionsUrl,function(webPayload){var webActions=getResultArray(webPayload);var hasScript=webActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.ScriptLink';});function ensureRibbon(){var listActionsUrl=info.listUrl+'/UserCustomActions';getJson(listActionsUrl,function(listPayload){var listActions=getResultArray(listPayload);var hasRibbon=listActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.Ribbon';});if(hasRibbon){onComplete('');return;}var ribbonLocation=Number(info.list.BaseType)===1?'Ribbon.Library.Actions.Controls._children':'Ribbon.List.Actions.Controls._children';var ribbonXml='';postJson(listActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.Ribbon',Title:'ExpiryIndicator Classic ribbon command',Location:'CommandUI.Ribbon',CommandUIExtension:ribbonXml,Sequence:651},function(){onComplete('');},onComplete);},onComplete);}if(hasScript){ensureRibbon();return;}postJson(webActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.ScriptLink',Title:'ExpiryIndicator Classic runtime',Location:'ScriptLink',ScriptSrc:'~sitecollection/SiteAssets/ExpiryIndicator/ExpiryIndicatorClassic.js',Sequence:650},ensureRibbon,onComplete);},onComplete);}
+function ensureExpiryClassicRegistration(info,onComplete){var webActionsUrl=info.target.webUrl+'/_api/web/UserCustomActions';getJson(webActionsUrl,function(webPayload){var webActions=getResultArray(webPayload);var hasScript=webActions.some(function(action){return action.Name==='ExpiryIndicator.Classic.ScriptLink';});function ensureRibbon(){var listActionsUrl=info.listUrl+'/UserCustomActions';getJson(listActionsUrl,function(listPayload){var listActions=getResultArray(listPayload);var ribbonAction=null;for(var i=0;i';var payload={__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.Ribbon',Title:'ExpiryIndicator Classic ribbon command',Location:'CommandUI.Ribbon',CommandUIExtension:ribbonXml,Sequence:651};if(ribbonAction){if(String(ribbonAction.CommandUIExtension||'').indexOf(ribbonLocation)>=0){onComplete('');return;}postJsonMerge(listActionsUrl+"(guid'"+normalizeGuid(ribbonAction.Id)+"')",payload,function(){onComplete('');},onComplete);return;}postJson(listActionsUrl,payload,function(){onComplete('');},onComplete);},onComplete);}if(hasScript){ensureRibbon();return;}postJson(webActionsUrl,{__metadata:{type:'SP.UserCustomAction'},Name:'ExpiryIndicator.Classic.ScriptLink',Title:'ExpiryIndicator Classic runtime',Location:'ScriptLink',ScriptSrc:'~sitecollection/SiteAssets/ExpiryIndicator/ExpiryIndicatorClassic.js',Sequence:650},ensureRibbon,onComplete);},onComplete);}
function normalizePropertyBagKey(value){return String(value||'').replace(/_x002e_/gi,'.').toLowerCase();}
function propertyBagJson(properties,key,fallback){if(!properties){return fallback;}var value;var expected=normalizePropertyBagKey(key);Object.keys(properties).some(function(name){if(normalizePropertyBagKey(name)===expected){value=properties[name];return true;}return false;});if(typeof value==='undefined'||value===null||value===''){return fallback;}if(typeof value==='object'){return value;}try{return JSON.parse(value);}catch(ignore){return fallback;}}
function normalizeExpiryBindings(value){var result=[];function visit(item){if(Array.isArray(item)){item.forEach(visit);return;}if(!item||typeof item!=='object'){return;}if(item.webUrl&&item.listId&&item.fieldInternalName){result.push(item);}}visit(value);return result;}