domma-cms 0.9.1 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/admin/js/templates/block-editor.html +163 -163
  2. package/admin/js/templates/form-editor.html +245 -245
  3. package/admin/js/views/action-editor.js +1 -1
  4. package/admin/js/views/block-editor.js +8 -8
  5. package/admin/js/views/collection-editor.js +4 -4
  6. package/admin/js/views/collections.js +1 -1
  7. package/admin/js/views/form-editor.js +7 -7
  8. package/admin/js/views/forms.js +1 -1
  9. package/admin/js/views/navigation.js +14 -14
  10. package/admin/js/views/page-editor.js +35 -35
  11. package/admin/js/views/pages.js +5 -5
  12. package/admin/js/views/plugins.js +13 -10
  13. package/admin/js/views/view-editor.js +1 -1
  14. package/config/plugins.json +25 -0
  15. package/package.json +1 -1
  16. package/plugins/docs/data/documents/57e003f0-68f2-47dc-9c36-ed4b10ed3deb.json +4 -4
  17. package/plugins/docs/data/folders.json +3 -3
  18. package/plugins/docs/data/versions/57e003f0-68f2-47dc-9c36-ed4b10ed3deb/1.json +5 -0
  19. package/plugins/garage/admin/templates/garage.html +30 -0
  20. package/plugins/garage/admin/views/garage.js +62 -1
  21. package/plugins/garage/plugin.json +1 -1
  22. package/plugins/notes/admin/templates/notes.html +2 -11
  23. package/plugins/notes/admin/views/notes.js +108 -129
  24. package/plugins/notes/collections/user-notes/schema.json +2 -1
  25. package/plugins/notes/plugin.json +1 -1
  26. package/plugins/site-search/admin/templates/site-search.html +174 -46
  27. package/plugins/site-search/admin/views/site-search.js +72 -1
  28. package/plugins/site-search/config.js +6 -1
  29. package/plugins/site-search/plugin.json +1 -1
  30. package/plugins/site-search/public/inject-head.html +1 -1
  31. package/plugins/site-search/public/search.css +1 -1
  32. package/plugins/site-search/public/search.js +1 -1
  33. package/plugins/todo/admin/templates/todo.html +2 -8
  34. package/plugins/todo/admin/views/todo.js +123 -106
  35. package/plugins/todo/collections/todos/schema.json +2 -1
  36. package/plugins/todo/plugin.json +1 -1
  37. package/server/routes/api/media.js +127 -118
  38. package/server/routes/api/plugins.js +15 -4
  39. package/server/server.js +288 -285
  40. package/server/services/collections.js +17 -10
  41. package/server/services/plugins.js +77 -67
  42. package/server/services/renderer.js +3 -3
  43. package/plugins/docs/data/documents/452f49b7-9c93-4a67-874d-27f882891ad2.json +0 -11
@@ -1,23 +1,23 @@
1
- import{api as x}from"../api.js";let I=1;const v=t=>String(t||"").replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;");function S(t){const e=[];return(t||[]).forEach(l=>{const o=I++;e.push({_id:o,text:l.text||"",url:l.url||"",icon:l.icon||"",hidden:l.hidden||!1,bundled:l.bundled||!1,parentId:null}),(l.items||l.children||[]).forEach(a=>{e.push({_id:I++,text:a.text||"",url:a.url||"",icon:a.icon||"",hidden:a.hidden||!1,bundled:a.bundled||!1,parentId:o})})}),e}function F(t){return t.filter(e=>e.parentId===null).map(e=>{const l=t.filter(a=>a.parentId===e._id).map(a=>({text:a.text,url:a.url,...a.icon&&{icon:a.icon},...a.hidden&&{hidden:!0},...a.bundled&&{bundled:!0}})),o={text:e.text,url:e.url,...e.icon&&{icon:e.icon},...e.hidden&&{hidden:!0},...e.bundled&&{bundled:!0}};return l.length&&(o.items=l),o})}function A(t){const e=[];return t.filter(l=>l.parentId===null).forEach(l=>{e.push(l),t.filter(o=>o.parentId===l._id).forEach(o=>e.push(o))}),e}export const navigationView={templateUrl:"/admin/js/templates/navigation.html",async onMount(t){let[e,l]=await Promise.all([x.navigation.get().catch(()=>({brand:{},items:[]})),x.settings.get().catch(()=>({}))]),o=S(e.items),a=(l.footer?.links||[]).map(d=>({text:d.text||"",url:d.url||"",...d.hidden&&{hidden:!0}}));const u=()=>{t.find("#nav-items-list .nav-item-row").each(function(){const i=parseInt($(this).data("id"),10),n=o.find(f=>f._id===i);if(!n)return;n.text=$(this).find(".item-text").val(),n.url=$(this).find(".item-url").val(),n.icon=$(this).find(".item-icon").val(),n.hidden=$(this).find(".btn-toggle-hidden").attr("data-hidden")==="true",n.bundled=$(this).find(".btn-toggle-bundled").attr("data-bundled")==="true";const r=$(this).find(".item-parent").val();n.parentId=r?parseInt(r,10):null});const d=new Set(o.filter(i=>i.parentId!==null).map(i=>i._id));o.forEach(i=>{i.parentId!==null&&d.has(i.parentId)&&(i.parentId=null)})},p=()=>{const d=t.find("#nav-items-list").empty(),i=o.filter(n=>n.parentId===null);A(o).forEach(n=>{const r=n.parentId!==null,f=n.hidden===!0,g='<option value="">\u2014 top-level \u2014</option>'+i.filter(c=>c._id!==n._id).map(c=>`<option value="${c._id}"${c._id===n.parentId?" selected":""}>${v(c.text)||"(untitled)"}</option>`).join("");d.append(`
2
- <div class="nav-item-row${r?" nav-item-row--child":""}${f?" nav-item-row--hidden":""}" data-id="${n._id}">
3
- <span class="nav-col-indent">${r?"\u21B3":""}</span>
4
- <input type="text" class="form-input item-text nav-col-main" value="${v(n.text)}" placeholder="Label">
5
- <input type="text" class="form-input item-url nav-col-main" value="${v(n.url)}" placeholder="/url">
6
- <input type="text" class="form-input item-icon nav-col-icon" value="${v(n.icon)}" placeholder="icon">
1
+ import{api as x}from"../api.js";let k=1;const v=n=>String(n||"").replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;");function S(n){const a=[];return(n||[]).forEach(l=>{const o=k++;a.push({_id:o,text:l.text||"",url:l.url||"",icon:l.icon||"",hidden:l.hidden||!1,bundled:l.bundled||!1,parentId:null}),(l.items||l.children||[]).forEach(e=>{a.push({_id:k++,text:e.text||"",url:e.url||"",icon:e.icon||"",hidden:e.hidden||!1,bundled:e.bundled||!1,parentId:o})})}),a}function B(n){return n.filter(a=>a.parentId===null).map(a=>{const l=n.filter(e=>e.parentId===a._id).map(e=>({text:e.text,url:e.url,...e.icon&&{icon:e.icon},...e.hidden&&{hidden:!0},...e.bundled&&{bundled:!0}})),o={text:a.text,url:a.url,...a.icon&&{icon:a.icon},...a.hidden&&{hidden:!0},...a.bundled&&{bundled:!0}};return l.length&&(o.items=l),o})}function F(n){const a=[];return n.filter(l=>l.parentId===null).forEach(l=>{a.push(l),n.filter(o=>o.parentId===l._id).forEach(o=>a.push(o))}),a}export const navigationView={templateUrl:"/admin/js/templates/navigation.html",async onMount(n){let[a,l]=await Promise.all([x.navigation.get().catch(()=>({brand:{},items:[]})),x.settings.get().catch(()=>({}))]),o=S(a.items),e=(l.footer?.links||[]).map(d=>({text:d.text||"",url:d.url||"",...d.hidden&&{hidden:!0}}));const u=()=>{n.find("#nav-items-list .nav-item-row").each(function(){const i=parseInt($(this).data("id"),10),t=o.find(c=>c._id===i);if(!t)return;t.text=$(this).find(".item-text").val(),t.url=$(this).find(".item-url").val(),t.icon=$(this).find(".item-icon").val(),t.hidden=$(this).find(".btn-toggle-hidden").attr("data-hidden")==="true",t.bundled=$(this).find(".btn-toggle-bundled").attr("data-bundled")==="true";const s=$(this).find(".item-parent").val();t.parentId=s?parseInt(s,10):null});const d=new Set(o.filter(i=>i.parentId!==null).map(i=>i._id));o.forEach(i=>{i.parentId!==null&&d.has(i.parentId)&&(i.parentId=null)})},p=()=>{const d=n.find("#nav-items-list").empty(),i=o.filter(t=>t.parentId===null);F(o).forEach(t=>{const s=t.parentId!==null,c=t.hidden===!0,g='<option value="">\u2014 top-level \u2014</option>'+i.filter(f=>f._id!==t._id).map(f=>`<option value="${f._id}"${f._id===t.parentId?" selected":""}>${v(f.text)||"(untitled)"}</option>`).join("");d.append(`
2
+ <div class="nav-item-row${s?" nav-item-row--child":""}${c?" nav-item-row--hidden":""}" data-id="${t._id}">
3
+ <span class="nav-col-indent">${s?"\u21B3":""}</span>
4
+ <input type="text" class="form-input item-text nav-col-main" value="${v(t.text)}" placeholder="Label">
5
+ <input type="text" class="form-input item-url nav-col-main" value="${v(t.url)}" placeholder="/url">
6
+ <input type="text" class="form-input item-icon nav-col-icon" value="${v(t.icon)}" placeholder="icon">
7
7
  <select class="form-select item-parent nav-col-parent">${g}</select>
8
8
  <span class="nav-col-action">
9
- <button class="btn btn-sm btn-ghost btn-toggle-bundled${n.bundled?" active":""}" data-id="${n._id}" data-bundled="${!!n.bundled}" data-tooltip="${n.bundled?"Unbundle":"Bundle (seed on install)"}"><span data-icon="package"></span></button>
10
- <button class="btn btn-sm btn-ghost btn-toggle-hidden${f?" active":""}" data-id="${n._id}" data-hidden="${f}" data-tooltip="${f?"Show":"Hide"}"><span data-icon="eye-off"></span></button>
11
- <button class="btn btn-sm btn-danger btn-remove-item" data-id="${n._id}" data-tooltip="Remove"><span data-icon="trash"></span></button>
9
+ <button class="btn btn-sm btn-ghost btn-toggle-bundled${t.bundled?" active":""}" data-id="${t._id}" data-bundled="${!!t.bundled}" data-tooltip="${t.bundled?"Unbundle":"Bundle (seed on install)"}"><span data-icon="package"></span></button>
10
+ <button class="btn btn-sm btn-ghost btn-toggle-hidden${c?" active":""}" data-id="${t._id}" data-hidden="${c}" data-tooltip="${c?"Show":"Hide"}"><span data-icon="eye-off"></span></button>
11
+ <button class="btn btn-sm btn-danger btn-remove-item" data-id="${t._id}" data-tooltip="Remove"><span data-icon="trash"></span></button>
12
12
  </span>
13
13
  </div>
14
- `)}),Domma.icons.scan("#nav-items-list"),document.querySelectorAll("#nav-items-list [data-tooltip]").forEach(n=>{E.tooltip(n,{content:n.getAttribute("data-tooltip"),position:"top"})})},b=()=>{const d=t.find("#footer-links-list").empty();a.forEach((i,n)=>{const r=i.hidden===!0;d.append(`
15
- <div class="nav-item-row${r?" nav-item-row--hidden":""}" data-footer-idx="${n}">
14
+ `)}),Domma.icons.scan("#nav-items-list"),document.querySelectorAll("#nav-items-list [data-tooltip]").forEach(t=>{E.tooltip(t,{content:t.getAttribute("data-tooltip"),position:"top"})})},m=()=>{const d=n.find("#footer-links-list").empty();e.forEach((i,t)=>{const s=i.hidden===!0;d.append(`
15
+ <div class="nav-item-row${s?" nav-item-row--hidden":""}" data-footer-idx="${t}">
16
16
  <input type="text" class="form-input footer-link-text nav-col-main" value="${v(i.text)}" placeholder="Label">
17
17
  <input type="text" class="form-input footer-link-url nav-col-main" value="${v(i.url)}" placeholder="/url">
18
18
  <span class="nav-col-action">
19
- <button class="btn btn-sm btn-ghost btn-toggle-hidden${r?" active":""}" data-idx="${n}" data-hidden="${r}" data-tooltip="${r?"Show":"Hide"}"><span data-icon="eye-off"></span></button>
20
- <button class="btn btn-sm btn-danger btn-remove-footer" data-idx="${n}" data-tooltip="Remove"><span data-icon="trash"></span></button>
19
+ <button class="btn btn-sm btn-ghost btn-toggle-hidden${s?" active":""}" data-idx="${t}" data-hidden="${s}" data-tooltip="${s?"Show":"Hide"}"><span data-icon="eye-off"></span></button>
20
+ <button class="btn btn-sm btn-danger btn-remove-footer" data-idx="${t}" data-tooltip="Remove"><span data-icon="trash"></span></button>
21
21
  </span>
22
22
  </div>
23
- `)}),Domma.icons.scan("#footer-links-list"),document.querySelectorAll("#footer-links-list [data-tooltip]").forEach(i=>{E.tooltip(i,{content:i.getAttribute("data-tooltip"),position:"top"})})},h=()=>{a=[],t.find("#footer-links-list .nav-item-row").each(function(){const d=$(this).find(".btn-toggle-hidden").attr("data-hidden")==="true",i={text:$(this).find(".footer-link-text").val().trim(),url:$(this).find(".footer-link-url").val().trim()};d&&(i.hidden=!0),a.push(i)})};t.find("#add-footer-link").on("click",()=>{h(),a.push({text:"",url:"",hidden:!1}),b()}),t.off("click",".btn-remove-footer").on("click",".btn-remove-footer",function(){h();const d=parseInt($(this).data("idx"),10);a.splice(d,1),b()}),t.find("#field-brand-text").val(e.brand?.text||""),t.find("#field-brand-url").val(e.brand?.url||"/"),t.find("#field-brand-icon").val(e.brand?.icon||""),t.find("#field-nav-variant").val(e.variant||"dark"),t.find("#field-brand-tagline").val(e.brand?.tagline||""),t.find("#field-brand-logo").val(e.brand?.logo||""),t.find("#field-nav-position").val(e.position||"sticky"),t.find("#field-brand-size").val(e.brand?.size||"md"),t.find("#field-nav-font-family").val(e.style?.fontFamily||""),t.find("#field-nav-font-size").val(e.style?.fontSize||""),t.find("#field-nav-font-weight").val(e.style?.fontWeight||""),t.find("#field-nav-letter-spacing").val(e.style?.letterSpacing||""),t.find("#field-nav-icon-size").val(e.style?.iconSize||""),t.find("#field-admin-brand-title").val(l.adminBrand?.title||""),t.find("#field-admin-brand-icon").val(l.adminBrand?.icon||""),t.find("#field-admin-brand-logo").val(l.adminBrand?.logo||""),p(),b(),E.tabs(t.find("#nav-tabs").get(0)),t.find("#add-nav-item").on("click",()=>{u(),o.push({_id:I++,text:"",url:"",icon:"",hidden:!1,parentId:null}),p()}),t.off("click",".btn-remove-item").on("click",".btn-remove-item",function(){u();const d=parseInt($(this).data("id"),10);o=o.filter(i=>i._id!==d&&i.parentId!==d),p()}),t.off("click","#nav-items-list .btn-toggle-bundled").on("click","#nav-items-list .btn-toggle-bundled",function(d){d.stopPropagation(),u();const i=parseInt($(this).data("id"),10),n=o.find(r=>r._id===i);n&&(n.bundled=!n.bundled),p()}),t.off("click","#nav-items-list .btn-toggle-hidden").on("click","#nav-items-list .btn-toggle-hidden",function(d){d.stopPropagation(),u();const i=parseInt($(this).data("id"),10),n=o.find(r=>r._id===i);n&&(n.hidden=!n.hidden),p()}),t.off("click","#footer-links-list .btn-toggle-hidden").on("click","#footer-links-list .btn-toggle-hidden",function(d){d.stopPropagation(),h();const i=parseInt($(this).data("idx"),10);a[i]&&(a[i].hidden=!a[i].hidden),b()}),t.off("change",".item-parent").on("change",".item-parent",function(){u(),p()}),t.find("#save-nav-btn").on("click",async()=>{u(),h();const d=F(o.map(s=>({...s,text:s.text.trim(),url:s.url.trim(),icon:s.icon.trim()}))).filter(s=>s.text||s.url),i=t.find("#field-brand-icon").val().trim(),n=t.find("#field-brand-tagline").val().trim(),r=t.find("#field-brand-logo").val().trim(),f=t.find("#field-brand-size").val(),g={brand:{text:t.find("#field-brand-text").val().trim(),url:t.find("#field-brand-url").val().trim()||"/",...r&&{logo:r},...i&&!r&&{icon:i},...n&&{tagline:n},...f!=="md"&&{size:f}},items:d,variant:t.find("#field-nav-variant").val(),position:t.find("#field-nav-position").val()||"sticky",style:{...t.find("#field-nav-font-family").val()&&{fontFamily:t.find("#field-nav-font-family").val()},...t.find("#field-nav-font-size").val()&&{fontSize:t.find("#field-nav-font-size").val()},...t.find("#field-nav-font-weight").val()&&{fontWeight:t.find("#field-nav-font-weight").val()},...t.find("#field-nav-letter-spacing").val()&&{letterSpacing:t.find("#field-nav-letter-spacing").val()},...t.find("#field-nav-icon-size").val()&&{iconSize:t.find("#field-nav-icon-size").val()}}},c=a.filter(s=>s.text||s.url);try{await x.navigation.save(g),e=g,o=S(e.items),p(),E.toast("Navigation saved.",{type:"success"})}catch(s){console.error("[navigation] save failed:",s),E.toast("Failed to save navigation.",{type:"error"});return}const y=t.find("#field-admin-brand-logo").val().trim(),k=t.find("#field-admin-brand-icon").val().trim(),_=t.find("#field-admin-brand-title").val().trim(),m={..._&&{title:_},...y&&{logo:y},...!y&&k&&{icon:k}};try{await x.settings.save({adminBrand:m,footer:{links:c}}),l={...l,adminBrand:m},a=c,b();const s=m.title||"CMS Admin",L=m.icon||"layout",w=m.logo||"",z=$("#admin-topbar .topbar-brand");w?z.html(`<img src="${w}" class="topbar-brand-logo" alt="${s}"><span class="topbar-brand-text">${s}</span>`):z.html(`<span data-icon="${L}"></span><span class="topbar-brand-text">${s}</span>`),Domma.icons.scan("#admin-topbar .topbar-brand")}catch(s){console.error("[navigation] admin brand / footer save failed:",s),E.toast(`Admin brand save failed: ${s.message||s}`,{type:"error"})}})}};
23
+ `)}),Domma.icons.scan("#footer-links-list"),document.querySelectorAll("#footer-links-list [data-tooltip]").forEach(i=>{E.tooltip(i,{content:i.getAttribute("data-tooltip"),position:"top"})})},h=()=>{e=[],n.find("#footer-links-list .nav-item-row").each(function(){const d=$(this).find(".btn-toggle-hidden").attr("data-hidden")==="true",i={text:$(this).find(".footer-link-text").val().trim(),url:$(this).find(".footer-link-url").val().trim()};d&&(i.hidden=!0),e.push(i)})};n.find("#add-footer-link").on("click",()=>{h(),e.push({text:"",url:"",hidden:!1}),m()}),n.off("click",".btn-remove-footer").on("click",".btn-remove-footer",function(){h();const d=parseInt($(this).data("idx"),10);e.splice(d,1),m()}),n.find("#field-brand-text").val(a.brand?.text||""),n.find("#field-brand-url").val(a.brand?.url||"/"),n.find("#field-brand-icon").val(a.brand?.icon||""),n.find("#field-nav-variant").val(a.variant||"dark"),n.find("#field-brand-tagline").val(a.brand?.tagline||""),n.find("#field-brand-logo").val(a.brand?.logo||""),n.find("#field-nav-position").val(a.position||"sticky"),n.find("#field-brand-size").val(a.brand?.size||"md"),n.find("#field-nav-font-family").val(a.style?.fontFamily||""),n.find("#field-nav-font-size").val(a.style?.fontSize||""),n.find("#field-nav-font-weight").val(a.style?.fontWeight||""),n.find("#field-nav-letter-spacing").val(a.style?.letterSpacing||""),n.find("#field-nav-icon-size").val(a.style?.iconSize||""),n.find("#field-admin-brand-title").val(l.adminBrand?.title||""),n.find("#field-admin-brand-icon").val(l.adminBrand?.icon||""),n.find("#field-admin-brand-logo").val(l.adminBrand?.logo||""),p(),m(),E.tabs(n.find("#nav-tabs").get(0)),n.find("#add-nav-item").on("click",()=>{u(),o.push({_id:k++,text:"",url:"",icon:"",hidden:!1,parentId:null}),p()}),n.off("click",".btn-remove-item").on("click",".btn-remove-item",function(){u();const d=parseInt($(this).data("id"),10);o=o.filter(i=>i._id!==d&&i.parentId!==d),p()}),n.off("click","#nav-items-list .btn-toggle-bundled").on("click","#nav-items-list .btn-toggle-bundled",function(d){d.stopPropagation(),u();const i=parseInt($(this).data("id"),10),t=o.find(s=>s._id===i);t&&(t.bundled=!t.bundled),p()}),n.off("click","#nav-items-list .btn-toggle-hidden").on("click","#nav-items-list .btn-toggle-hidden",function(d){d.stopPropagation(),u();const i=parseInt($(this).data("id"),10),t=o.find(s=>s._id===i);t&&(t.hidden=!t.hidden),p()}),n.off("click","#footer-links-list .btn-toggle-hidden").on("click","#footer-links-list .btn-toggle-hidden",function(d){d.stopPropagation(),h();const i=parseInt($(this).data("idx"),10);e[i]&&(e[i].hidden=!e[i].hidden),m()}),n.off("change",".item-parent").on("change",".item-parent",function(){u(),p()}),n.find("#save-nav-btn").on("click",async()=>{u(),h();const d=B(o.map(r=>({...r,text:r.text.trim(),url:r.url.trim(),icon:r.icon.trim()}))).filter(r=>r.text||r.url),i=n.find("#field-brand-icon").val().trim(),t=n.find("#field-brand-tagline").val().trim(),s=n.find("#field-brand-logo").val().trim(),c=n.find("#field-brand-size").val(),g={brand:{text:n.find("#field-brand-text").val().trim(),url:n.find("#field-brand-url").val().trim()||"/",...s&&{logo:s},...i&&!s&&{icon:i},...t&&{tagline:t},...c!=="md"&&{size:c}},items:d,variant:n.find("#field-nav-variant").val(),position:n.find("#field-nav-position").val()||"sticky",style:{...n.find("#field-nav-font-family").val()&&{fontFamily:n.find("#field-nav-font-family").val()},...n.find("#field-nav-font-size").val()&&{fontSize:n.find("#field-nav-font-size").val()},...n.find("#field-nav-font-weight").val()&&{fontWeight:n.find("#field-nav-font-weight").val()},...n.find("#field-nav-letter-spacing").val()&&{letterSpacing:n.find("#field-nav-letter-spacing").val()},...n.find("#field-nav-icon-size").val()&&{iconSize:n.find("#field-nav-icon-size").val()}}},f=e.filter(r=>r.text||r.url);try{await x.navigation.save(g),a=g,o=S(a.items),p(),E.toast("Navigation saved.",{type:"success"})}catch(r){console.error("[navigation] save failed:",r),E.toast("Failed to save navigation.",{type:"error"});return}const y=n.find("#field-admin-brand-logo").val().trim(),I=n.find("#field-admin-brand-icon").val().trim(),_=n.find("#field-admin-brand-title").val().trim(),b={..._&&{title:_},...y&&{logo:y},...!y&&I&&{icon:I}};try{await x.settings.save({adminBrand:b,footer:{links:f}}),l={...l,adminBrand:b},e=f,m();const r=b.title||"CMS Admin",A=b.icon||"layout",w=b.logo||"",z=$("#admin-topbar .topbar-brand");w?z.html(`<img src="${w}" class="topbar-brand-logo" alt="${r}"><span class="topbar-brand-text">${r}</span>`):z.html(`<span data-icon="${A}"></span><span class="topbar-brand-text">${r}</span>`),Domma.icons.scan("#admin-topbar .topbar-brand")}catch(r){console.error("[navigation] admin brand / footer save failed:",r),E.toast(`Admin brand save failed: ${r.message||r}`,{type:"error"})}})}};