v2 - new interface, many new page for fine tuning
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/* Identity editing: admin-protected API, optimistic revision checks, no HTML injection. */
|
||||
(() => {
|
||||
'use strict';
|
||||
const $=id=>document.getElementById(id);
|
||||
let csrf='',revision='',dirty=false,busy=false;
|
||||
const msg=(s,error=false,id='idMessage')=>{const e=$(id);e.textContent=s;e.classList.toggle('error',error);};
|
||||
const setName=name=>{
|
||||
const n=String(name||'Assistant').trim();
|
||||
const initial=Array.from(n)[0]?.toLocaleUpperCase('fr-FR')||'A';
|
||||
$('idName').textContent=n;$('idInitial').textContent=initial;
|
||||
$('idActiveName').textContent=n;$('idAvatar').textContent=initial;
|
||||
document.title='Identité · '+n;
|
||||
};
|
||||
function updateCount(){$('idCount').textContent=$('idText').value.length.toLocaleString('fr-FR')+' caractères';}
|
||||
async function jsonFetch(url,options={}){
|
||||
const r=await fetch(url,{credentials:'same-origin',cache:'no-store',...options});
|
||||
const d=await r.json().catch(()=>({}));
|
||||
if(!r.ok)throw Error(d.error||'Erreur HTTP '+r.status);
|
||||
return d;
|
||||
}
|
||||
async function auth(){
|
||||
const a=await jsonFetch('/api/control/auth');
|
||||
csrf=a.csrf||'';
|
||||
$('idLoginPanel').hidden=!!a.authenticated;
|
||||
$('idEditor').hidden=!a.authenticated;
|
||||
$('idBadge').textContent=a.authenticated?'Administrateur connecté':'Connexion requise';
|
||||
$('idBadge').classList.toggle('ok',!!a.authenticated);
|
||||
if(a.authenticated)await load();
|
||||
}
|
||||
async function load(){
|
||||
try{
|
||||
const d=await jsonFetch('/api/control/identity');
|
||||
$('idText').value=d.text;revision=d.revision;dirty=false;
|
||||
setName(d.name);updateCount();msg('Document chargé.');
|
||||
}catch(e){msg(e.message,true);}
|
||||
}
|
||||
$('idLoginForm').addEventListener('submit',async e=>{
|
||||
e.preventDefault();
|
||||
try{
|
||||
await jsonFetch('/api/control/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:$('idPassword').value})});
|
||||
$('idPassword').value='';await auth();
|
||||
}catch(err){msg(err.message,true,'idLoginMessage');}
|
||||
});
|
||||
$('idText').addEventListener('input',()=>{dirty=true;updateCount();msg('Modifications non enregistrées.');});
|
||||
$('idSave').addEventListener('click',async()=>{
|
||||
if(busy||!revision)return;
|
||||
busy=true;$('idSave').disabled=true;
|
||||
try{
|
||||
const d=await jsonFetch('/api/control/identity',{
|
||||
method:'POST',headers:{'Content-Type':'application/json','X-Alfred-CSRF':csrf},
|
||||
body:JSON.stringify({text:$('idText').value,revision})
|
||||
});
|
||||
revision=d.revision;dirty=false;msg(d.updated?'Identité enregistrée. Nouvelle version sauvegardée.':'Aucun changement à enregistrer.');
|
||||
}catch(e){msg(e.message,true);}
|
||||
finally{busy=false;$('idSave').disabled=false;}
|
||||
});
|
||||
$('idReload').addEventListener('click',()=>{if(dirty&&!confirm('Abandonner les modifications non enregistrées ?'))return;load();});
|
||||
window.addEventListener('beforeunload',event=>{if(dirty){event.preventDefault();event.returnValue='';}});
|
||||
auth().catch(e=>{msg(e.message,true,'idLoginMessage');$('idLoginPanel').hidden=false;});
|
||||
})();
|
||||
Reference in New Issue
Block a user