fix(admin): align UTM notes and block obsolete chb publication
deploy-preland / deploy zoomstage.online (push) Successful in 54s
deploy-preland / deploy zoomstage.online (push) Successful in 54s
This commit is contained in:
1 parent
f2097d4800
commit
84f70b1c71
14 files changed
+93
-29
No files matched your search
@@ -5,6 +5,7 @@
|
||||
/* Overview and link builder retain the existing CPanel / Bootstrap surface. */
|
||||
.overview-wrapper{margin-top:15px}.overview-table{min-width:760px;table-layout:fixed}.overview-table th:first-child{width:110px}.overview-table th:not(:first-child){min-width:190px}.overview-table th,.overview-table td{vertical-align:top;overflow-wrap:anywhere}.overview-table th:first-child,.overview-table td:first-child{position:sticky;left:0;background:#f5f5f5;z-index:1}.overview-table caption{text-align:left;padding:8px 0}.overview-domain{font-size:15px;margin-bottom:6px}.overview-status{font-size:12px;font-weight:400;margin:8px 0}.overview-weights{list-style:none;padding:0;margin:7px 0 0}.overview-weights li{margin:3px 0}.overview-warning{color:#8a6d3b;margin-top:8px;font-size:12px}.overview-error{color:#a94442}.overview-table .toolbar{gap:6px;margin-bottom:0}.builder-domain{display:block;max-width:450px;margin:15px 0}.builder-field{display:block}.builder-field select{margin-top:5px}#builder-fields{margin:15px 0}#builder-result{margin-top:18px}#builder-url{font-family:monospace}#builder-state{margin-top:10px}#builder-warnings .alert{padding:10px}#builder-save{margin-top:5px}@media(max-width:600px){.overview-table{min-width:720px}.overview-table th:first-child{width:90px}.overview-table .btn{padding:4px 8px}.builder-domain{max-width:100%}}
|
||||
.overview-plain{white-space:pre-wrap}
|
||||
.overview-default{font-weight:400}.overview-table tr[data-utm-note] th{font-size:16px}.overview-table tr[data-overview-utm] th{background:#fafafa}
|
||||
.login-panel .remember-choice{display:flex;align-items:center;gap:6px;font-weight:400}.login-panel .remember-choice input{flex:0 0 auto;margin:0}
|
||||
/* #23: compact numeric percentages; note rows span the whole matrix without sticky cells. */
|
||||
.overview-percent{display:block;margin:6px 0;line-height:1.35}.overview-percent:first-child{margin-top:0}.overview-percent:last-child{margin-bottom:0}.overview-raw{font-size:12px;overflow-wrap:anywhere}#overview-table td.utm-note-cell{position:static;left:auto;width:auto;min-width:0;z-index:auto;background:#fafafa;white-space:normal}.utm-note-title{display:block;font-size:12px;color:#707070;margin-bottom:6px}.utm-note-text{white-space:pre-wrap;overflow-wrap:anywhere;margin:0 0 8px}.utm-note-textarea{width:100%;max-width:100%;min-width:0;resize:vertical;min-height:90px}.utm-note-status{margin:6px 0 0;white-space:pre-wrap;overflow-wrap:anywhere}.utm-note-status:empty{display:none}.utm-note-edit .toolbar{margin-bottom:0}.utm-note-cell .btn{white-space:normal}.utm-note-read:has(.utm-note-text[hidden]){display:flex;align-items:center}
|
||||
@@ -35,17 +35,17 @@
|
||||
if(defaultDigit&&!seen.has(defaultDigit))variants.push({digit:defaultDigit,weight:0});
|
||||
variants.sort((a,b)=>Number(a.digit)-Number(b.digit));
|
||||
const maximum=Math.max(0,...variants.map(v=>v.weight)),sum=maximum>0?variants.reduce((total,v)=>total+v.weight/maximum,0):0;
|
||||
for(const variant of variants){const percent=sum>0?Math.round((variant.weight/maximum)/sum*10000)/100:0;const text=variant.digit+' ('+percent+'%)'+(variant.digit===defaultDigit?' - default':'');cell.append(el(percent>0?'strong':'span',{class:'overview-percent',text}));}
|
||||
for(const variant of variants){const percent=sum>0?Math.round((variant.weight/maximum)/sum*10000)/100:0;const line=el('div',{class:'overview-percent'},el(percent>0?'strong':'span',{class:'overview-value',text:variant.digit+' ('+percent+'%)'}));if(variant.digit===defaultDigit)line.append(el('span',{class:'overview-default',text:' - default'}));cell.append(line);}
|
||||
if(!variants.length)cell.append(el('span',{class:'text-muted',text:'Вариантов нет'}));
|
||||
return cell;
|
||||
}
|
||||
const utmNotes={entries:new Map(),loading:false,error:'',serial:0};
|
||||
function noteEntry(marker){
|
||||
if(utmNotes.entries.has(marker)){const entry=utmNotes.entries.get(marker);entry.cell.colSpan=state.targets.length+1;return entry;}
|
||||
if(utmNotes.entries.has(marker)){const entry=utmNotes.entries.get(marker);entry.cell.colSpan=Math.max(1,state.targets.length);return entry;}
|
||||
const entry={marker,epoch:0,note:null,draft:'',baseVersion:'',editing:false,saving:false,loading:false,error:'',conflict:false};
|
||||
const makeButton=(text,action)=>el('button',{type:'button',class:'btn btn-default btn-xs',text,onclick:()=>run(action)});
|
||||
entry.row=el('tr',{'data-utm-note':marker});entry.cell=el('td',{class:'utm-note-cell'});entry.row.append(entry.cell);
|
||||
entry.title=el('span',{class:'utm-note-title',text:'Заметка '+marker});entry.text=el('div',{class:'utm-note-text'});
|
||||
entry.row=el('tr',{'data-utm-note':marker});entry.cell=el('td',{class:'utm-note-cell'});entry.row.append(el('th',{scope:'row',text:marker}),entry.cell);
|
||||
entry.text=el('div',{class:'utm-note-text'});
|
||||
entry.edit=makeButton('Добавить заметку',()=>{if(!entry.note)return;entry.epoch++;entry.draft=entry.note.text;entry.baseVersion=entry.note.version;entry.editing=true;entry.error='';entry.conflict=false;renderNote(entry);entry.textarea.focus();});
|
||||
entry.edit.setAttribute('aria-label','Добавить заметку '+marker);
|
||||
entry.readView=el('div',{class:'utm-note-read'},entry.text,entry.edit);
|
||||
@@ -57,10 +57,10 @@
|
||||
entry.editView=el('div',{class:'utm-note-edit'},entry.textarea,el('div',{class:'toolbar'},entry.save,entry.cancel,entry.reload));
|
||||
entry.retry=makeButton('Повторить загрузку заметок',loadNotes);entry.retry.setAttribute('aria-label','Повторить загрузку заметок '+marker);
|
||||
entry.status=el('p',{class:'utm-note-status text-muted',role:'status','aria-live':'polite'});
|
||||
entry.cell.append(entry.title,entry.readView,entry.editView,entry.status,entry.retry);utmNotes.entries.set(marker,entry);renderNote(entry);return entry;
|
||||
entry.cell.append(entry.readView,entry.editView,entry.status,entry.retry);utmNotes.entries.set(marker,entry);renderNote(entry);return entry;
|
||||
}
|
||||
function renderNote(entry){
|
||||
entry.cell.colSpan=state.targets.length+1;entry.text.textContent=entry.note?.text||'';entry.text.hidden=!entry.note?.text;
|
||||
entry.cell.colSpan=Math.max(1,state.targets.length);entry.text.textContent=entry.note?.text||'';entry.text.hidden=!entry.note?.text;
|
||||
entry.readView.hidden=entry.editing;entry.editView.hidden=!entry.editing;
|
||||
entry.edit.textContent=entry.note?.text?'Редактировать':'Добавить заметку';entry.edit.setAttribute('aria-label',(entry.note?.text?'Редактировать':'Добавить')+' заметку '+entry.marker);entry.edit.disabled=!entry.note||entry.loading;
|
||||
if(entry.textarea.value!==entry.draft)entry.textarea.value=entry.draft;
|
||||
@@ -93,14 +93,13 @@
|
||||
function overviewExtra(config){
|
||||
const values=new Map(),secretKeys=new Set(['secret','password','private_key','privatekey','credential','credentials','api_key','apikey','access_token','accesstoken','refresh_token','refreshtoken','authorization']);
|
||||
const visit=(path,value)=>{const key=path.join('.');if(path.some(part=>secretKeys.has(String(part).toLowerCase().replace(/-/g,'_')))){values.set(key,{label:key,text:'Скрытое поле'});return;}
|
||||
if(path.length===1&&path[0]==='requisites'&&Array.isArray(value)&&value.every(v=>typeof v==='string')){values.set(key,{label:'Реквизиты',text:value.length?value.join('\n'):'Пустой массив'});return;}
|
||||
if(value!==null&&typeof value==='object'){const entries=Object.entries(value);if(!entries.length){values.set(key,{label:key,text:Array.isArray(value)?'Пустой массив':'Пустой объект'});return;}for(const [child,next]of entries)visit([...path,child],next);return;}
|
||||
const text=value===null?'null':typeof value==='boolean'?(value?'Да':'Нет')+' (boolean)':typeof value==='number'?String(value)+' (число)':String(value);
|
||||
values.set(key,{label:key==='host'?'Основной сайт':key,text});
|
||||
};
|
||||
for(const [key,value]of Object.entries(config||{}))if(key!=='utm')visit([key],value);
|
||||
for(const [key,value]of Object.entries(config||{}))if(!['utm','requisites'].includes(key))visit([key],value);
|
||||
const utm=config?.utm;
|
||||
if(utm&&typeof utm==='object'&&!Array.isArray(utm)){for(const [key,value]of Object.entries(utm)){
|
||||
if(utm&&typeof utm==='object'&&!Array.isArray(utm)){for(const [key,value]of Object.entries(utm)){if(key==='chb')continue;
|
||||
const marker=key==='registration'?'reg':['chob','bchoice'].includes(key)?'banch':key;
|
||||
if(!markers.includes(marker))visit(['utm',key],value);
|
||||
else if(groupFor(config,marker).conflict.length)visit(['utm',key],value);
|
||||
@@ -121,9 +120,9 @@
|
||||
table.querySelector('thead').replaceChildren(head);const body=table.querySelector('tbody');body.replaceChildren();
|
||||
const extraByTarget=new Map(),extraKeys=new Map();
|
||||
for(const target of state.targets){const extra=overviewExtra(overview.entries.get(target.id)?.data?.config);extraByTarget.set(target.id,extra);for(const [key,value]of extra)extraKeys.set(key,value.label);}
|
||||
const orderedKeys=[...extraKeys.keys()].sort((a,b)=>{const rank=key=>key==='host'?0:key==='requisites'?1:2;return rank(a)-rank(b)||a.localeCompare(b,'ru');});
|
||||
const orderedKeys=[...extraKeys.keys()].sort((a,b)=>{const rank=key=>key==='host'?0:1;return rank(a)-rank(b)||a.localeCompare(b,'ru');});
|
||||
for(const key of orderedKeys){const row=el('tr',{'data-overview-extra':key},el('th',{scope:'row',text:extraKeys.get(key)}));for(const target of state.targets){const entry=overview.entries.get(target.id),value=extraByTarget.get(target.id)?.get(key);row.append(el('td',{class:'overview-plain',text:value?value.text:entry?.data?'Поле отсутствует':'Нет прочитанного конфига'}));}body.append(row);}
|
||||
for(const marker of markers){const row=el('tr',{'data-overview-utm':marker},el('th',{scope:'row',text:marker}));for(const target of state.targets){const entry=overview.entries.get(target.id);row.append(entry?.data?overviewCell(entry.data.config,marker):el('td',{class:'text-muted',text:entry?.status==='loading'?'Загрузка…':'Нет прочитанного конфига'}));}body.append(row);body.append(noteEntry(marker).row);}
|
||||
for(const marker of markers){const row=el('tr',{'data-overview-utm':marker},el('th',{'aria-hidden':'true',text:''}));for(const target of state.targets){const entry=overview.entries.get(target.id);row.append(entry?.data?overviewCell(entry.data.config,marker):el('td',{class:'text-muted',text:entry?.status==='loading'?'Загрузка…':'Нет прочитанного конфига'}));}body.append(noteEntry(marker).row,row);}
|
||||
if(noteFocus?.node.isConnected&&!noteFocus.node.disabled){noteFocus.node.focus({preventScroll:true});noteFocus.node.setSelectionRange(noteFocus.start,noteFocus.end,noteFocus.direction);noteFocus.node.scrollTop=noteFocus.scroll;}
|
||||
if(builder.target&&builder.entries.get(builder.target)?.ready)updateBuilderState();
|
||||
}
|
||||
@@ -281,7 +280,7 @@
|
||||
for(const [key,value]of Object.entries(config))if(key!=='utm'){
|
||||
if(key==='requisites'){
|
||||
// По просьбе владельца (#22/comment3770) редактирование реквизитов отключено.
|
||||
// Ключ config и отображение в сводке сохраняются; в state.fields реквизитов нет.
|
||||
// Данные config сохраняются; реквизитов нет в сводке и state.fields (#24).
|
||||
// typed(container,[key],value,'Реквизиты');
|
||||
continue;
|
||||
}
|
||||
@@ -289,7 +288,7 @@
|
||||
}
|
||||
if(config.utm&&typeof config.utm==='object'){
|
||||
for(const marker of markers){const key=Object.hasOwn(config.utm,marker)?marker:aliases[marker]&&Object.hasOwn(config.utm,aliases[marker])?aliases[marker]:marker==='banch'&&Object.hasOwn(config.utm,'chob')?'chob':null;if(key)utmGroup(container,key,config.utm[key],marker);else container.append(el('div',{class:'field-block'},el('h2',{text:marker+'= UTM'}),el('p',{class:'text-muted',text:'Группа отсутствует в этом config.json; автоматически не добавляется.'})));}
|
||||
for(const [key,value]of Object.entries(config.utm))if(!markers.includes(key)&&!Object.values(aliases).includes(key)&&key!=='chob')typed(container,['utm',key],value,key);
|
||||
for(const [key,value]of Object.entries(config.utm))if(!markers.includes(key)&&!Object.values(aliases).includes(key)&&key!=='chob'&&key!=='chb')typed(container,['utm',key],value,key);
|
||||
}
|
||||
$('read-state').textContent='Прочитано '+formatDate(new Date())+' · версия '+read.version.slice(0,12);
|
||||
$('warnings').replaceChildren(...(read.warnings||[]).map(w=>el('p',{class:'alert alert-warning',text:typeof w==='string'?w:JSON.stringify(w)})));
|
||||
|
||||
Reference in new issue
Block a user