';}host.innerHTML=html;document.getElementById('expiryIndicatorChip').textContent=String(solution.info.bindings.length);}
function selectExpiryBinding(index){var solution=state.solutions.expiryindicator;if(!solution||!solution.info||!solution.info.bindings[index]){return;}var binding=solution.info.bindings[index];document.getElementById('expiryWebUrl').value=binding.webUrl||getWebUrl();document.getElementById('expiryListTitle').value=binding.listTitle||'';document.getElementById('expiryFieldName').value=binding.fieldInternalName||'ExpiryDate';loadExpiryIndicatorConfig();}
diff --git a/src/assets/PortalSettings.aspx b/src/assets/PortalSettings.aspx
index 64602da..8676ad6 100644
--- a/src/assets/PortalSettings.aspx
+++ b/src/assets/PortalSettings.aspx
@@ -52,7 +52,8 @@ function bindingListUrl(target){return target.webUrl+"/_api/web/lists/getbytitle
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=propertyBagJson(properties,EXPIRY_BINDINGS_PROPERTY,[]);if(!Array.isArray(bindings)){bindings=[];}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.0',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 propertyBagJson(properties,key,fallback){if(!properties){return fallback;}var value;Object.keys(properties).some(function(name){if(name.toLowerCase()===key.toLowerCase()){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 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 readExpiryProviderInfo(onSuccess,onError){getJson(getSiteUrl().replace(/\/$/,'')+'/_api/web/AllProperties',function(payload){var properties=payload.d||payload||{};var descriptor=propertyBagJson(properties,EXPIRY_DESCRIPTOR_PROPERTY,null);var bindings=propertyBagJson(properties,EXPIRY_BINDINGS_PROPERTY,[]);var siteDefaults=propertyBagJson(properties,EXPIRY_DEFAULTS_PROPERTY,null);if(!Array.isArray(bindings)){bindings=[];}if(!descriptor&&!siteDefaults&&!bindings.length){onSuccess(null);return;}onSuccess({descriptor:descriptor,bindings:bindings,siteDefaults:siteDefaults||defaultExpiryIndicatorConfig('ExpiryDate'),rootProperties:properties,selected:null});},onError);}
function renderExpiryBindings(){var solution=state.solutions.expiryindicator;var host=document.getElementById('expiryBindingsList');if(!solution||!solution.info||!solution.info.bindings.length){host.innerHTML='
Keine Bindungen registriert. Aktivieren Sie ExpiryIndicator 2.1 erneut an den gewuenschten Listen.
';}host.innerHTML=html;document.getElementById('expiryIndicatorChip').textContent=String(solution.info.bindings.length);}
function selectExpiryBinding(index){var solution=state.solutions.expiryindicator;if(!solution||!solution.info||!solution.info.bindings[index]){return;}var binding=solution.info.bindings[index];document.getElementById('expiryWebUrl').value=binding.webUrl||getWebUrl();document.getElementById('expiryListTitle').value=binding.listTitle||'';document.getElementById('expiryFieldName').value=binding.fieldInternalName||'ExpiryDate';loadExpiryIndicatorConfig();}