domma-cms 1.8.8 → 1.8.10

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.
@@ -1,9 +1,9 @@
1
- import{apiRequest as A,getToken as Aa}from"../api.js";import{addBannerAction as Ia}from"../lib/plugin-chrome.js";import{helpPopovers as pt}from"../lib/help-popover.js";import{onceClosed as Na,openMenuAt as H,sidebarCount as N,viewLifetime as Oa}from"../lib/tool-kit.js";import{SHAPES as ct,whileLoading as dt}from"../lib/loading.js";import{fmtDateTime as Da}from"../lib/dates.js";import{applyChoice as Ha,chooseAllPeople as ut,choosePerson as Ua,choiceItems as Ba,cleanOptions as fe,counts as mt,customTypeRows as _a,inviteNote as za,peopleSummary as ja,personMenuItems as Fa,personRow as Wa,reportPersonRow as Ka,defaultOptions as Ne,draftKey as Za,draftQuestion as Va,historyRow as Ja,internalTypeRows as Ya,isDirty as Ga,kindTabs as Xa,liveDrafts as vt,optionsSnapshot as ht,PLAN_FILTERS as wt,planMatches as ft,planRow as Qa,planTiles as bt,productSummary as eo,progressPercent as to,progressText as ao,REPORT_FILTERS as yt,reportMatches as gt,reportRow as oo,stagedRow as so,typeMenuItems as no,withDraft as xt,withListPage as ro,withTypeChoice as lo}from"../lib/wordpress-import-arrange.js";const kt=/^#\/wordpress-import\/?(\?.*)?$/,se="#/wordpress-import",$="/import/wordpress",be=400,io=`
1
+ import{apiRequest as C,getToken as Za}from"../api.js";import{addBannerAction as Va}from"../lib/plugin-chrome.js";import{helpPopovers as yt}from"../lib/help-popover.js";import{onceClosed as Ga,openMenuAt as O,sidebarCount as R,viewLifetime as Ja}from"../lib/tool-kit.js";import{SHAPES as xt,whileLoading as kt}from"../lib/loading.js";import{fmtDateTime as Ya}from"../lib/dates.js";import{applyChoice as Xa,chooseAllPeople as Mt,choosePerson as Qa,choiceItems as Tt,cleanOptions as ye,counts as Et,customTypeRows as es,inviteNote as ts,peopleSummary as as,personMenuItems as ss,personRow as os,reportPersonRow as ns,defaultOptions as He,draftKey as ls,draftQuestion as rs,historyRow as is,internalTypeRows as cs,isDirty as ps,kindTabs as ds,liveDrafts as $t,optionsSnapshot as Lt,PLAN_FILTERS as St,planMatches as Pt,planRow as us,planTiles as Ct,productSummary as ms,progressPercent as hs,progressText as ws,REPORT_FILTERS as Rt,reportMatches as qt,reportRow as vs,stagedRow as fs,typeMenuItems as bs,widgetAreaRows as gs,widgetsFileText as ys,withDraft as At,withFooterChoice as xs,withListPage as ks,withTypeChoice as Ms}from"../lib/wordpress-import-arrange.js";const It=/^#\/wordpress-import\/?(\?.*)?$/,re="#/wordpress-import",$="/import/wordpress",xe=400,Ts=`
2
2
  <div class="wpx-row" data-id="{{id}}" tabindex="0">
3
3
  <span class="wpx-main"><strong>{{title}}</strong><small>{{meta}}</small></span>
4
4
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
5
5
  <button type="button" class="wpx-kebab" aria-label="Actions for {{title}}" title="Actions">\u22EE</button>
6
- </div>`,Mt=`
6
+ </div>`,Nt=`
7
7
  <div class="wpx-row" data-key="{{key}}" tabindex="0">
8
8
  <span class="wpx-main">
9
9
  <strong>{{title}}</strong>
@@ -14,17 +14,17 @@ import{apiRequest as A,getToken as Aa}from"../api.js";import{addBannerAction as
14
14
  </span>
15
15
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillCls">{{pill}}</span></span>
16
16
  <button type="button" class="wpx-kebab" aria-label="Actions for {{title}}" title="Actions">\u22EE</button>
17
- </div>`,Tt=`
17
+ </div>`,Ot=`
18
18
  <div class="wpx-row" data-from="{{from}}" tabindex="0">
19
19
  <span class="wpx-main"><span class="wpx-where">{{from}} \u2192 {{to}}</span><span class="wpx-reason" data-bind-hidden="!reason">{{reason}}</span></span>
20
20
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
21
21
  <button type="button" class="wpx-kebab" aria-label="Actions for {{from}}" title="Actions">\u22EE</button>
22
- </div>`,po=`
22
+ </div>`,Es=`
23
23
  <div class="wpx-row" data-id="{{id}}" tabindex="0">
24
24
  <span class="wpx-main"><strong>{{title}}</strong><small>{{meta}}</small><span class="wpx-reason">{{summary}}</span></span>
25
25
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
26
26
  <button type="button" class="wpx-kebab" aria-label="Actions for {{title}}" title="Actions">\u22EE</button>
27
- </div>`,co=`
27
+ </div>`,$s=`
28
28
  <div class="wpx-row wpx-type-row" data-type="{{type}}" tabindex="0">
29
29
  <span class="wpx-main">
30
30
  <strong>{{label}}</strong>
@@ -42,7 +42,7 @@ import{apiRequest as A,getToken as Aa}from"../api.js";import{addBannerAction as
42
42
  </span>
43
43
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
44
44
  <button type="button" class="wpx-kebab" aria-label="Actions for {{label}}" title="Actions">\u22EE</button>
45
- </div>`,uo=`
45
+ </div>`,Ls=`
46
46
  <div class="wpx-row wpx-person" data-key="{{key}}" tabindex="0">
47
47
  <span class="wpx-main">
48
48
  <strong>{{name}}</strong>
@@ -57,12 +57,26 @@ import{apiRequest as A,getToken as Aa}from"../api.js";import{addBannerAction as
57
57
  </span>
58
58
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
59
59
  <button type="button" class="wpx-kebab" aria-label="Actions for {{name}}" title="Actions">\u22EE</button>
60
- </div>`,mo=`
60
+ </div>`,Ss=`
61
61
  <div class="wpx-row" data-key="{{key}}" tabindex="0">
62
62
  <span class="wpx-main"><strong>{{name}}</strong><small>{{meta}}</small><span class="wpx-reason" data-bind-hidden="!reason">{{reason}}</span></span>
63
63
  <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
64
64
  <button type="button" class="wpx-kebab" aria-label="Actions for {{name}}" title="Actions">\u22EE</button>
65
- </div>`,Et='<div class="wpx-tile"><strong>{{value}}</strong><small>{{label}} <span data-bind-hidden="!sub">{{sub}}</span></small></div>',St='<p class="wpx-alert"><span>{{text}}</span></p>',$t="<li>{{text}}</li>",vo='<div class="wpx-fact"><dt>{{label}}</dt><dd>{{value}}</dd></div>',Oe='<button type="button" data-on-click="$root.pickSeg($data)" data-bind-class="cls">{{label}} <b>{{count}}</b></button>',y=Oa(kt);function Lt(d,n,p){return new Promise((f,k)=>{const m=new XMLHttpRequest,P=new FormData;P.append("file",n),m.open("POST",`/api${d}`);const w=Aa();w&&m.setRequestHeader("Authorization",`Bearer ${w}`),m.upload.onprogress=u=>{u.lengthComputable&&p(u.loaded/u.total)},m.onload=()=>{let u=null;try{u=JSON.parse(m.responseText)}catch{}m.status>=200&&m.status<300?f(u):k(new Error(u?.error||`The upload failed (${m.status}).`))},m.onerror=()=>k(new Error("The upload failed - the connection dropped.")),m.send(P),y.add(()=>{m.readyState!==4&&m.abort()})})}const ye=d=>d>=1048576?`${Math.round(d/1048576)} MB`:`${Math.max(1,Math.round(d/1024))} KB`,F=d=>String(d??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function ho(d){const n=document.createElement("template");return n.innerHTML=d.trim(),n.content.firstElementChild}async function ge(d,n){const p=E.confirm(d,n);let f=null;try{f=[...document.querySelectorAll(".dm-dialog-overlay")].at(-1)??null}catch{}const k=y.add(()=>{if(!f)return;const m=f;f=null;try{m.querySelector(".dm-dialog-cancel")?.click(),m.remove()}catch{}});try{return await p}finally{f=null,k()}}function De(d){navigator.clipboard?.writeText(d).then(()=>E.toast("Copied.",{type:"success"}),()=>E.toast(d,{type:"info",duration:8e3}))}function W(d,n,p,f){const k=E.contextMenu(d,{cursor:"glyph",match:n,inherit:!1,density:"compact",items:p});y.add(()=>k?.destroy?.());const m=w=>{const u=w.target.closest(n);if(!u||!d.contains(u))return;const v=w.target.closest(".wpx-kebab");if(v){H(v);return}f?.(u)},P=w=>{const u=w.target.closest(n);u&&(w.key==="F10"&&w.shiftKey?(w.preventDefault(),H(u)):w.key==="Enter"&&w.target===u&&f&&(w.preventDefault(),w.stopPropagation(),f(u)))};d.addEventListener("click",m),d.addEventListener("keydown",P),y.add(()=>{d.removeEventListener("click",m),d.removeEventListener("keydown",P)})}export const wordpressImportView={templateUrl:"/admin/js/templates/wordpress-import.html",async onMount(d){y.reset();const n=d.get(0).querySelector(".wpx")||d.get(0),p=()=>kt.test(location.hash)&&n.isConnected;let f="";try{f=S.get("auth_user")?.id||""}catch{}const k=Za(f),m=()=>{try{return k?S.get(k):null}catch{return null}},P=e=>{try{k&&S.set(k,e)}catch{}},w=n.querySelector(".wpx-loading");let u;try{u=await dt(w,A(`${$}/status`),ct.rows)}catch(e){if(!n.isConnected)return;w&&(w.hidden=!0);const t=n.querySelector(".wpx-failed");t&&(t.textContent=`Could not load the importer: ${e.message||e}. Reload the page to try again.`,t.hidden=!1);return}if(!p())return;w&&(w.hidden=!0),n.querySelector(".wpx-body").hidden=!1;const v=M.observable(u.staged||[]),U=M.observable(u.history||[]),K=M.observable(u.blog||{available:!1}),He=M.observable(u.shop||{available:!1}),Z=u.limits||{},Ue=u.people?.defaultRole||"",g=M.observable(u.running||null),h=M.observable(""),b=M.observable(null),ne=M.observable(!1),xe=M.observable(!1),ke=M.observable(""),l=M.observable(Ne(K.peek().available)),B=M.observable("all"),O=M.observable(""),V=M.observable(""),re=M.observable(""),J=M.observable(""),le=M.observable(""),ie=M.observable(!1);let pe=!0;const wo=()=>v.peek().find(e=>e.id===h.peek())||null,Me=M.computed(()=>v.value.find(e=>e.id===h.value)||null),Ct=M.computed(()=>h.value?"preview":"start"),D=M.computed(()=>!!K.value.available),Pt=M.computed(()=>!!(b.value?.shop||He.value).available),Be=M.computed(()=>!!h.value&&Ga(l.value,D.value)),Y=e=>M.computed({read:()=>l.value[e]!==!1,write:t=>{l.value={...l.peek(),[e]:!!t}}}),L=e=>{l.value={...l.peek(),...e}},G=e=>{try{return Da(e)}catch{return e}},Rt=M.computed(()=>v.value.map(e=>so(e,G))),qt=M.computed(()=>U.value.map(e=>Ja(e,G))),X=M.computed(()=>(b.value?.items||[]).map(e=>({...e,choice:l.value.choices?.[e.key]}))),At=M.computed(()=>Xa(X.value).map(e=>({...e,cls:O.value===e.id?"is-on":"",seg:"kind"}))),It=M.computed(()=>mt(X.value,wt,ft,O.value)),Nt=M.computed(()=>wt.map(e=>({...e,count:It.value[e.id],cls:B.value===e.id?"is-on":"",seg:"filter"}))),Te=M.computed(()=>{const e=V.value.trim().toLowerCase();return X.value.filter(t=>(!O.value||t.kind===O.value)&&ft(t,B.value)&&(!e||`${t.title} ${t.target} ${t.oldUrl} ${t.postType||""}`.toLowerCase().includes(e)))}),Ot=M.computed(()=>Te.value.slice(0,be).map(e=>{const t=Qa(e);return{...t,pillCls:`${t.pillClass}${e.choice?" is-chosen":""}`}})),Dt=M.computed(()=>Te.value.length>be?`Showing the first ${be} of ${Te.value.length} - search or filter to find the rest.`:""),Ht=M.computed(()=>X.value.length?"Nothing matches.":"This export has nothing to import."),Ut=M.computed(()=>bt(b.value)),Bt=M.computed(()=>(b.value?.notes||[]).map(e=>({text:e}))),_t=M.computed(()=>(b.value?.redirects||[]).slice(0,be).map(e=>({...e,pill:e.action==="skip"?"Skipped":e.action==="update"?"Update":"New",pillClass:e.action==="skip"?"is-muted":"is-ok"}))),zt=M.computed(()=>String((b.value?.redirects||[]).filter(e=>e.action!=="skip").length)),jt=M.computed(()=>b.value?.site?.title||Me.value?.siteTitle||"WordPress export"),Ft=M.computed(()=>{const e=Me.value,t=b.value?.site;return[t?.url||e?.siteUrl,e?.fileName,t?.wxrVersion&&`WXR ${t.wxrVersion}`,e?.at&&`uploaded ${G(e.at)}`].filter(Boolean).join(" \xB7 ")}),Q=M.computed(()=>eo(b.value)),Wt=M.computed(()=>Q.value?.note||""),Kt=M.computed(()=>Q.value?.tone==="warn"?"is-warn":"is-info"),Zt=M.computed(()=>(Q.value?.rows||[]).map(e=>({...e,id:e.label}))),Vt=M.computed(()=>(Q.value?.notes||[]).map(e=>({text:e}))),Jt=M.computed(()=>!!Q.value),Ee=M.computed(()=>_a(b.value)),Se=M.computed(()=>Ya(b.value)),Yt=M.computed(()=>!!(Ee.value.length||Se.value.length)),Gt=M.computed(()=>{const e=Se.value.length;return e?`Not imported: ${e} kind${e===1?"":"s"} of WordPress or plugin housekeeping`:""}),T=M.computed(()=>b.value?.people||null),Xt=M.computed(()=>!!T.value?.rows?.length),Qt=M.computed(()=>(T.value?.rows||[]).map(Wa)),ea=M.computed(()=>!!T.value?.canCreate),ta=M.computed(()=>(T.value?.rows||[]).some(e=>e.choosable)),_e=M.computed(()=>ja(T.value)),aa=M.computed(()=>_e.value.text),oa=M.computed(()=>_e.value.tone==="warn"?"is-warn":"is-info"),sa=M.computed(()=>!!(T.value?.canCreate&&T.value?.mailReady&&T.value?.counts?.create)),na=M.computed(()=>za(T.value)),ra=M.computed({read:()=>l.value.invite===!0,write:e=>{l.value={...l.peek(),invite:!!e}}}),la=M.computed(()=>D.value?`Posts go to ${K.value.basePath||"/blog"}.`:K.value.reason||"No Blog is switched on here."),ce=M.computed(()=>Me.value?.uploads||null),ia=M.computed(()=>{const e=ce.value;return e?`${e.fileName} - ${e.files} file${e.files===1?"":"s"}, ${ye(e.size)}${e.unsafe?`. ${e.unsafe} with unsafe names (like ../) were ignored`:""}.`:`Zip the wp-content/uploads folder and upload it here (up to ${ye(Z.uploads||0)}).`}),pa=M.computed(()=>ce.value?"Replace the zip":"Upload the uploads zip"),ze=M.computed(()=>!!b.value&&!g.value&&!ne.value&&!(l.value.media==="zip"&&!ce.value)),ca=M.computed(()=>g.value?`Importing${g.value.siteTitle?` ${g.value.siteTitle}`:""}\u2026`:""),da=M.computed(()=>ao(g.value)),je=M.computed(()=>to(g.value)),ua=M.observable(ye(Z.wxr||0)),Fe=n.querySelector(".wpx-running .wpx-bar-fill");y.add(M.effect(()=>{Fe&&(Fe.style.width=`${je.value}%`)}));async function $e(){const e=await A(`${$}/status`);return p()?(v.value=e.staged||[],U.value=e.history||[],K.value=e.blog||{available:!1},He.value=e.shop||{available:!1},e.running&&!g.peek()&&(g.value=e.running,te()),e):null}let de=0,Le=null;async function ue({first:e=!1}={}){const t=h.peek();if(!t)return;const a=++de;ke.value="";const o=A(`${$}/staged/${t}/preview`,{method:"POST",body:JSON.stringify({options:fe(l.peek(),D.peek())})});try{let i;if(e?(ne.value=!0,i=await dt(n.querySelector(".wpx-plan-loading"),o,ct.table)):(xe.value=!0,i=await o),a!==de||!p()||h.peek()!==t)return;b.value=i.plan}catch(i){if(a!==de||!p())return;if(i.status===404){E.toast("That upload has gone - upload the export again.",{type:"warning"}),ee(),$e().catch(()=>{});return}ke.value=`Could not read the export: ${i.message||i}`}finally{a===de&&(ne.value=!1,xe.value=!1)}}let me="";y.add(M.effect(()=>{const e=`${h.value}|${ht(l.value)}`;if(e===me)return;const t=me.split("|")[0];me=e,!(!h.value||t!==h.value)&&(clearTimeout(Le),Le=setTimeout(()=>ue(),250))})),y.add(()=>clearTimeout(Le)),y.add(M.effect(()=>{const e=h.value,t=l.value,a=Be.value;if(!e||!pe||!k)return;const o=m();P(xt(o,f,e,a?{options:fe(t,!0),at:new Date().toISOString(),was:e}:null))}));const Ce=e=>{k&&P(xt(m(),f,e,null))};async function ve(e){if(!v.peek().some(c=>c.id===e))return;const t=v.peek().find(c=>c.id===e),a=vt(m(),v.peek().map(c=>c.id),f).items[e];if(pe=!a,b.value=null,B.value="all",O.value="",V.value="",l.value=Ne(D.peek()),me=`${e}|${ht(l.peek())}`,h.value=e,await ue({first:!0}),!p()||h.peek()!==e||!a)return;await new Promise(c=>setTimeout(c,0));const o=Va({when:a.at?G(a.at):"",file:t?.fileName||""}),i=await ge(F(o.text),{title:o.title,confirmText:o.confirmText,cancelText:o.cancelText});!p()||h.peek()!==e||(pe=!0,i?Ce(e):l.value=fe(a.options,D.peek()))}function ee(){h.value="",b.value=null,pe=!0}async function We(e=h.peek()){const t=v.peek().find(a=>a.id===e);if(t&&await ge(`Discard the upload of <strong>${F(t.siteTitle||t.fileName)}</strong>? Nothing has been imported from it.`,{title:"Discard upload",confirmText:"Discard",danger:!0}))try{if(await A(`${$}/staged/${e}`,{method:"DELETE"}),Ce(e),!p())return;h.peek()===e&&ee(),v.value=v.peek().filter(a=>a.id!==e),N(se)}catch(a){E.toast(`Not discarded: ${a.message||a}`,{type:"error"})}}async function Ke(e){if(!e)return;if(J.value="",!/\.(xml|zip)$/i.test(e.name)){J.value="Upload the .xml file WordPress exports, or a .zip holding it.";return}if(Z.wxr&&e.size>Z.wxr*1.2&&/\.xml$/i.test(e.name)){J.value=`That file is over ${ye(Z.wxr)}.`;return}const t=n.querySelector(".wpx-start .wpx-upload .wpx-bar-fill");re.value=`Uploading ${e.name}\u2026`;try{const a=await Lt(`${$}/upload`,e,o=>{t&&(t.style.width=`${Math.round(o*100)}%`),re.value=o<1?`Uploading ${e.name} - ${Math.round(o*100)}%`:`Reading ${e.name}\u2026`});if(!p())return;v.value=[a,...v.peek().filter(o=>o.id!==a.id)],N(se),await ve(a.id)}catch(a){p()&&(J.value=a.message||String(a))}finally{p()&&(re.value="",t&&(t.style.width="0"))}}async function ma(e){const t=h.peek();if(!e||!t)return;if(!/\.zip$/i.test(e.name)){E.toast("Zip the wp-content/uploads folder and upload the .zip.",{type:"warning"});return}const a=n.querySelector(".wpx-zip-fill");le.value=`Uploading ${e.name}\u2026`;try{const o=await Lt(`${$}/staged/${t}/uploads`,e,i=>{a&&(a.style.width=`${Math.round(i*100)}%`),le.value=i<1?`Uploading ${e.name} - ${Math.round(i*100)}%`:`Checking ${e.name}\u2026`});if(!p())return;v.value=v.peek().map(i=>i.id===o.id?o:i),h.peek()===t&&ue()}catch(o){p()&&E.toast(o.message||String(o),{type:"error"})}finally{p()&&(le.value="",a&&(a.style.width="0"))}}async function va(){const e=h.peek();try{const t=await A(`${$}/staged/${e}/uploads`,{method:"DELETE"});if(!p())return;v.value=v.peek().map(a=>a.id===t.id?t:a),ue()}catch(t){E.toast(`Not removed: ${t.message||t}`,{type:"error"})}}async function ha(){const e=h.peek(),t=b.peek();if(!e||!t||!ze.peek())return;const o=bt(t).filter(c=>c.value&&c.id!=="comments").map(c=>`${c.value} ${c.label.toLowerCase()}`);if(!(!await ge(`Import <strong>${F(t.site?.title||"this export")}</strong>: ${F(o.join(", ")||"nothing new")}? Pages edited here since an earlier import are left alone unless you chose Overwrite.`,{title:"Run the import",confirmText:"Run import"})||!p()||h.peek()!==e))try{const c=await A(`${$}/staged/${e}/run`,{method:"POST",body:JSON.stringify({options:fe(l.peek(),D.peek())})});if(Ce(e),!p())return;g.value={...c.job,siteTitle:t.site?.title||""},ee(),N(se),te()}catch(c){E.toast(`The import did not start: ${c.message||c}`,{type:"error"})}}let Pe=null;function te(){clearTimeout(Pe);const e=g.peek();e&&(Pe=setTimeout(async()=>{try{const t=await A(`${$}/jobs/${e.id}`);if(!p())return;if(g.value={...t.job,siteTitle:e.siteTitle},t.job.status==="running")return te();if(g.value=null,await $e().catch(()=>{}),N(se),N("#/pages"),N("#/media"),N("#/plugins/shopping-cart"),N("#/collections"),!p())return;t.job.status==="done"?(E.toast("The import has finished - here is its report.",{type:"success"}),he(t.job.reportId)):(E.toast(`The import stopped: ${t.job.error||"an error"}`,{type:"error"}),t.job.reportId&&he(t.job.reportId))}catch(t){if(!p())return;if(t.status===404){g.value=null,$e().catch(()=>{});return}te()}},700))}y.add(()=>clearTimeout(Pe)),g.peek()&&te();let _=!1;async function he(e){if(_||!e)return;_=!0;let t;try{t=await A(`${$}/history/${e}`)}catch(s){_=!1,E.toast(`Could not open the report: ${s.message||s}`,{type:"error"});return}if(!p()){_=!1;return}let a;try{a=E.slideover({title:F(`Report - ${t.run?.siteTitle||"WordPress import"}`),size:"lg",position:"right"})}catch(s){throw _=!1,s}const o=ho(`
65
+ </div>`,Ps=`
66
+ <div class="wpx-row wpx-widget-row" data-area="{{area}}" tabindex="0">
67
+ <span class="wpx-main">
68
+ <strong>{{label}}</strong>
69
+ <small>{{meta}}</small>
70
+ <span class="wpx-where">{{creates}}</span>
71
+ <span class="wpx-type-ctl" data-bind-hidden="!canPlace">
72
+ <label class="wpx-toggle"><input type="checkbox" class="form-switch" data-footer data-bind-checked="placeOn"> Place in the footer</label>
73
+ </span>
74
+ <span class="wpx-reason" data-bind-hidden="!placeText">{{placeText}}</span>
75
+ <span class="wpx-rebuild" data-bind-hidden="!rebuild">{{rebuild}}</span>
76
+ </span>
77
+ <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
78
+ <button type="button" class="wpx-kebab" aria-label="Actions for {{label}}" title="Actions">\u22EE</button>
79
+ </div>`,Dt='<div class="wpx-tile"><strong>{{value}}</strong><small>{{label}} <span data-bind-hidden="!sub">{{sub}}</span></small></div>',Ut='<p class="wpx-alert"><span>{{text}}</span></p>',Ht="<li>{{text}}</li>",Cs='<div class="wpx-fact"><dt>{{label}}</dt><dd>{{value}}</dd></div>',Be='<button type="button" data-on-click="$root.pickSeg($data)" data-bind-class="cls">{{label}} <b>{{count}}</b></button>',f=Ja(It);function _e(u,l,i){return new Promise((b,k)=>{const w=new XMLHttpRequest,q=new FormData;q.append("file",l),w.open("POST",`/api${u}`);const v=Za();v&&w.setRequestHeader("Authorization",`Bearer ${v}`),w.upload.onprogress=m=>{m.lengthComputable&&i(m.loaded/m.total)},w.onload=()=>{let m=null;try{m=JSON.parse(w.responseText)}catch{}w.status>=200&&w.status<300?b(m):k(new Error(m?.error||`The upload failed (${w.status}).`))},w.onerror=()=>k(new Error("The upload failed - the connection dropped.")),w.send(q),f.add(()=>{w.readyState!==4&&w.abort()})})}const ke=u=>u>=1048576?`${Math.round(u/1048576)} MB`:`${Math.max(1,Math.round(u/1024))} KB`,V=u=>String(u??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function Rs(u){const l=document.createElement("template");return l.innerHTML=u.trim(),l.content.firstElementChild}async function Me(u,l){const i=E.confirm(u,l);let b=null;try{b=[...document.querySelectorAll(".dm-dialog-overlay")].at(-1)??null}catch{}const k=f.add(()=>{if(!b)return;const w=b;b=null;try{w.querySelector(".dm-dialog-cancel")?.click(),w.remove()}catch{}});try{return await i}finally{b=null,k()}}function ze(u){navigator.clipboard?.writeText(u).then(()=>E.toast("Copied.",{type:"success"}),()=>E.toast(u,{type:"info",duration:8e3}))}function H(u,l,i,b){const k=E.contextMenu(u,{cursor:"glyph",match:l,inherit:!1,density:"compact",items:i});f.add(()=>k?.destroy?.());const w=v=>{const m=v.target.closest(l);if(!m||!u.contains(m))return;const p=v.target.closest(".wpx-kebab");if(p){O(p);return}b?.(m)},q=v=>{const m=v.target.closest(l);m&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),O(m)):v.key==="Enter"&&v.target===m&&b&&(v.preventDefault(),v.stopPropagation(),b(m)))};u.addEventListener("click",w),u.addEventListener("keydown",q),f.add(()=>{u.removeEventListener("click",w),u.removeEventListener("keydown",q)})}export const wordpressImportView={templateUrl:"/admin/js/templates/wordpress-import.html",async onMount(u){f.reset();const l=u.get(0).querySelector(".wpx")||u.get(0),i=()=>It.test(location.hash)&&l.isConnected;let b="";try{b=S.get("auth_user")?.id||""}catch{}const k=ls(b),w=()=>{try{return k?S.get(k):null}catch{return null}},q=e=>{try{k&&S.set(k,e)}catch{}},v=l.querySelector(".wpx-loading");let m;try{m=await kt(v,C(`${$}/status`),xt.rows)}catch(e){if(!l.isConnected)return;v&&(v.hidden=!0);const t=l.querySelector(".wpx-failed");t&&(t.textContent=`Could not load the importer: ${e.message||e}. Reload the page to try again.`,t.hidden=!1);return}if(!i())return;v&&(v.hidden=!0),l.querySelector(".wpx-body").hidden=!1;const p=M.observable(m.staged||[]),B=M.observable(m.history||[]),G=M.observable(m.blog||{available:!1}),je=M.observable(m.shop||{available:!1}),_=m.limits||{},We=m.people?.defaultRole||"",y=M.observable(m.running||null),h=M.observable(""),g=M.observable(null),ie=M.observable(!1),Te=M.observable(!1),Ee=M.observable(""),c=M.observable(He(G.peek().available)),z=M.observable("all"),D=M.observable(""),J=M.observable(""),ce=M.observable(""),Y=M.observable(""),pe=M.observable(""),de=M.observable(!1);let ue=!0;const qs=()=>p.peek().find(e=>e.id===h.peek())||null,X=M.computed(()=>p.value.find(e=>e.id===h.value)||null),Bt=M.computed(()=>h.value?"preview":"start"),U=M.computed(()=>!!G.value.available),_t=M.computed(()=>!!(g.value?.shop||je.value).available),Fe=M.computed(()=>!!h.value&&ps(c.value,U.value)),Q=e=>M.computed({read:()=>c.value[e]!==!1,write:t=>{c.value={...c.peek(),[e]:!!t}}}),P=e=>{c.value={...c.peek(),...e}},ee=e=>{try{return Ya(e)}catch{return e}},zt=M.computed(()=>p.value.map(e=>fs(e,ee))),jt=M.computed(()=>B.value.map(e=>is(e,ee))),j=M.computed(()=>(g.value?.items||[]).map(e=>({...e,choice:c.value.choices?.[e.key]}))),Wt=M.computed(()=>ds(j.value).map(e=>({...e,cls:D.value===e.id?"is-on":"",seg:"kind"}))),Ft=M.computed(()=>Et(j.value,St,Pt,D.value)),Kt=M.computed(()=>St.map(e=>({...e,count:Ft.value[e.id],cls:z.value===e.id?"is-on":"",seg:"filter"}))),$e=M.computed(()=>{const e=J.value.trim().toLowerCase();return j.value.filter(t=>(!D.value||t.kind===D.value)&&Pt(t,z.value)&&(!e||`${t.title} ${t.target} ${t.oldUrl} ${t.postType||""}`.toLowerCase().includes(e)))}),Zt=M.computed(()=>$e.value.slice(0,xe).map(e=>{const t=us(e);return{...t,pillCls:`${t.pillClass}${e.choice?" is-chosen":""}`}})),Vt=M.computed(()=>$e.value.length>xe?`Showing the first ${xe} of ${$e.value.length} - search or filter to find the rest.`:""),Gt=M.computed(()=>j.value.length?"Nothing matches.":"This export has nothing to import."),Jt=M.computed(()=>Ct(g.value)),Yt=M.computed(()=>(g.value?.notes||[]).map(e=>({text:e}))),Xt=M.computed(()=>(g.value?.redirects||[]).slice(0,xe).map(e=>({...e,pill:e.action==="skip"?"Skipped":e.action==="update"?"Update":"New",pillClass:e.action==="skip"?"is-muted":"is-ok"}))),Qt=M.computed(()=>String((g.value?.redirects||[]).filter(e=>e.action!=="skip").length)),ea=M.computed(()=>g.value?.site?.title||X.value?.siteTitle||"WordPress export"),ta=M.computed(()=>{const e=X.value,t=g.value?.site;return[t?.url||e?.siteUrl,e?.fileName,t?.wxrVersion&&`WXR ${t.wxrVersion}`,e?.at&&`uploaded ${ee(e.at)}`].filter(Boolean).join(" \xB7 ")}),te=M.computed(()=>ms(g.value)),aa=M.computed(()=>te.value?.note||""),sa=M.computed(()=>te.value?.tone==="warn"?"is-warn":"is-info"),oa=M.computed(()=>(te.value?.rows||[]).map(e=>({...e,id:e.label}))),na=M.computed(()=>(te.value?.notes||[]).map(e=>({text:e}))),la=M.computed(()=>!!te.value),Le=M.computed(()=>es(g.value)),Se=M.computed(()=>cs(g.value)),ra=M.computed(()=>!!(Le.value.length||Se.value.length)),ia=M.computed(()=>{const e=Se.value.length;return e?`Not imported: ${e} kind${e===1?"":"s"} of WordPress or plugin housekeeping`:""}),T=M.computed(()=>g.value?.people||null),ca=M.computed(()=>!!T.value?.rows?.length),pa=M.computed(()=>(T.value?.rows||[]).map(os)),da=M.computed(()=>!!T.value?.canCreate),ua=M.computed(()=>(T.value?.rows||[]).some(e=>e.choosable)),Ke=M.computed(()=>as(T.value)),ma=M.computed(()=>Ke.value.text),ha=M.computed(()=>Ke.value.tone==="warn"?"is-warn":"is-info"),wa=M.computed(()=>!!(T.value?.canCreate&&T.value?.mailReady&&T.value?.counts?.create)),va=M.computed(()=>ts(T.value)),fa=M.computed({read:()=>c.value.invite===!0,write:e=>{c.value={...c.peek(),invite:!!e}}}),ba=M.computed(()=>U.value?`Posts go to ${G.value.basePath||"/blog"}.`:G.value.reason||"No Blog is switched on here."),me=M.computed(()=>X.value?.uploads||null),ga=M.computed(()=>{const e=me.value;return e?`${e.fileName} - ${e.files} file${e.files===1?"":"s"}, ${ke(e.size)}${e.unsafe?`. ${e.unsafe} with unsafe names (like ../) were ignored`:""}.`:`Zip the wp-content/uploads folder and upload it here (up to ${ke(_.uploads||0)}).`}),ya=M.computed(()=>me.value?"Replace the zip":"Upload the uploads zip"),Ze=M.computed(()=>X.value?.widgets||null),xa=M.computed(()=>ys(X.value,_.widgets||0)),ka=M.computed(()=>Ze.value?"Replace the widgets file":"Upload the widgets file"),Pe=M.observable(""),Ve=M.computed(()=>gs(g.value)),Ge=M.computed(()=>!!g.value&&!y.value&&!ie.value&&!(c.value.media==="zip"&&!me.value)),Ma=M.computed(()=>y.value?`Importing${y.value.siteTitle?` ${y.value.siteTitle}`:""}\u2026`:""),Ta=M.computed(()=>ws(y.value)),Je=M.computed(()=>hs(y.value)),Ea=M.observable(ke(_.wxr||0)),Ye=l.querySelector(".wpx-running .wpx-bar-fill");f.add(M.effect(()=>{Ye&&(Ye.style.width=`${Je.value}%`)}));async function Ce(){const e=await C(`${$}/status`);return i()?(p.value=e.staged||[],B.value=e.history||[],G.value=e.blog||{available:!1},je.value=e.shop||{available:!1},e.running&&!y.peek()&&(y.value=e.running,se()),e):null}let he=0,Re=null;async function W({first:e=!1}={}){const t=h.peek();if(!t)return;const a=++he;Ee.value="";const s=C(`${$}/staged/${t}/preview`,{method:"POST",body:JSON.stringify({options:ye(c.peek(),U.peek())})});try{let r;if(e?(ie.value=!0,r=await kt(l.querySelector(".wpx-plan-loading"),s,xt.table)):(Te.value=!0,r=await s),a!==he||!i()||h.peek()!==t)return;g.value=r.plan}catch(r){if(a!==he||!i())return;if(r.status===404){E.toast("That upload has gone - upload the export again.",{type:"warning"}),ae(),Ce().catch(()=>{});return}Ee.value=`Could not read the export: ${r.message||r}`}finally{a===he&&(ie.value=!1,Te.value=!1)}}let we="";f.add(M.effect(()=>{const e=`${h.value}|${Lt(c.value)}`;if(e===we)return;const t=we.split("|")[0];we=e,!(!h.value||t!==h.value)&&(clearTimeout(Re),Re=setTimeout(()=>W(),250))})),f.add(()=>clearTimeout(Re)),f.add(M.effect(()=>{const e=h.value,t=c.value,a=Fe.value;if(!e||!ue||!k)return;const s=w();q(At(s,b,e,a?{options:ye(t,!0),at:new Date().toISOString(),was:e}:null))}));const qe=e=>{k&&q(At(w(),b,e,null))};async function ve(e){if(!p.peek().some(d=>d.id===e))return;const t=p.peek().find(d=>d.id===e),a=$t(w(),p.peek().map(d=>d.id),b).items[e];if(ue=!a,g.value=null,z.value="all",D.value="",J.value="",c.value=He(U.peek()),we=`${e}|${Lt(c.peek())}`,h.value=e,await W({first:!0}),!i()||h.peek()!==e||!a)return;await new Promise(d=>setTimeout(d,0));const s=rs({when:a.at?ee(a.at):"",file:t?.fileName||""}),r=await Me(V(s.text),{title:s.title,confirmText:s.confirmText,cancelText:s.cancelText});!i()||h.peek()!==e||(ue=!0,r?qe(e):c.value=ye(a.options,U.peek()))}function ae(){h.value="",g.value=null,ue=!0}async function Xe(e=h.peek()){const t=p.peek().find(a=>a.id===e);if(t&&await Me(`Discard the upload of <strong>${V(t.siteTitle||t.fileName)}</strong>? Nothing has been imported from it.`,{title:"Discard upload",confirmText:"Discard",danger:!0}))try{if(await C(`${$}/staged/${e}`,{method:"DELETE"}),qe(e),!i())return;h.peek()===e&&ae(),p.value=p.peek().filter(a=>a.id!==e),R(re)}catch(a){E.toast(`Not discarded: ${a.message||a}`,{type:"error"})}}async function Qe(e){if(!e)return;if(Y.value="",!/\.(xml|zip)$/i.test(e.name)){Y.value="Upload the .xml file WordPress exports, or a .zip holding it.";return}if(_.wxr&&e.size>_.wxr*1.2&&/\.xml$/i.test(e.name)){Y.value=`That file is over ${ke(_.wxr)}.`;return}const t=l.querySelector(".wpx-start .wpx-upload .wpx-bar-fill");ce.value=`Uploading ${e.name}\u2026`;try{const a=await _e(`${$}/upload`,e,s=>{t&&(t.style.width=`${Math.round(s*100)}%`),ce.value=s<1?`Uploading ${e.name} - ${Math.round(s*100)}%`:`Reading ${e.name}\u2026`});if(!i())return;p.value=[a,...p.peek().filter(s=>s.id!==a.id)],R(re),await ve(a.id)}catch(a){i()&&(Y.value=a.message||String(a))}finally{i()&&(ce.value="",t&&(t.style.width="0"))}}async function $a(e){const t=h.peek();if(!e||!t)return;if(!/\.zip$/i.test(e.name)){E.toast("Zip the wp-content/uploads folder and upload the .zip.",{type:"warning"});return}const a=l.querySelector(".wpx-zip-fill");pe.value=`Uploading ${e.name}\u2026`;try{const s=await _e(`${$}/staged/${t}/uploads`,e,r=>{a&&(a.style.width=`${Math.round(r*100)}%`),pe.value=r<1?`Uploading ${e.name} - ${Math.round(r*100)}%`:`Checking ${e.name}\u2026`});if(!i())return;p.value=p.peek().map(r=>r.id===s.id?s:r),h.peek()===t&&W()}catch(s){i()&&E.toast(s.message||String(s),{type:"error"})}finally{i()&&(pe.value="",a&&(a.style.width="0"))}}async function La(e){const t=h.peek();if(!(!e||!t)){if(!/\.(wie|json)$/i.test(e.name)){E.toast('Upload the .wie file the "Widget Importer & Exporter" plugin exports.',{type:"warning"});return}Pe.value=`Reading ${e.name}\u2026`;try{const a=await _e(`${$}/staged/${t}/widgets`,e,()=>{});if(!i())return;p.value=p.peek().map(s=>s.id===a.id?a:s),h.peek()===t&&W()}catch(a){i()&&E.toast(a.message||String(a),{type:"error"})}finally{i()&&(Pe.value="")}}}async function Sa(){const e=h.peek();try{const t=await C(`${$}/staged/${e}/widgets`,{method:"DELETE"});if(!i())return;p.value=p.peek().map(a=>a.id===t.id?t:a),W()}catch(t){E.toast(`Not removed: ${t.message||t}`,{type:"error"})}}async function Pa(){const e=h.peek();try{const t=await C(`${$}/staged/${e}/uploads`,{method:"DELETE"});if(!i())return;p.value=p.peek().map(a=>a.id===t.id?t:a),W()}catch(t){E.toast(`Not removed: ${t.message||t}`,{type:"error"})}}async function Ca(){const e=h.peek(),t=g.peek();if(!e||!t||!Ge.peek())return;const s=Ct(t).filter(d=>d.value&&d.id!=="comments").map(d=>`${d.value} ${d.label.toLowerCase()}`);if(!(!await Me(`Import <strong>${V(t.site?.title||"this export")}</strong>: ${V(s.join(", ")||"nothing new")}? Pages edited here since an earlier import are left alone unless you chose Overwrite.`,{title:"Run the import",confirmText:"Run import"})||!i()||h.peek()!==e))try{const d=await C(`${$}/staged/${e}/run`,{method:"POST",body:JSON.stringify({options:ye(c.peek(),U.peek())})});if(qe(e),!i())return;y.value={...d.job,siteTitle:t.site?.title||""},ae(),R(re),se()}catch(d){E.toast(`The import did not start: ${d.message||d}`,{type:"error"})}}let Ae=null;function se(){clearTimeout(Ae);const e=y.peek();e&&(Ae=setTimeout(async()=>{try{const t=await C(`${$}/jobs/${e.id}`);if(!i())return;if(y.value={...t.job,siteTitle:e.siteTitle},t.job.status==="running")return se();if(y.value=null,await Ce().catch(()=>{}),R(re),R("#/pages"),R("#/media"),R("#/plugins/shopping-cart"),R("#/collections"),R("#/blocks"),!i())return;t.job.status==="done"?(E.toast("The import has finished - here is its report.",{type:"success"}),fe(t.job.reportId)):(E.toast(`The import stopped: ${t.job.error||"an error"}`,{type:"error"}),t.job.reportId&&fe(t.job.reportId))}catch(t){if(!i())return;if(t.status===404){y.value=null,Ce().catch(()=>{});return}se()}},700))}f.add(()=>clearTimeout(Ae)),y.peek()&&se();let F=!1;async function fe(e){if(F||!e)return;F=!0;let t;try{t=await C(`${$}/history/${e}`)}catch(o){F=!1,E.toast(`Could not open the report: ${o.message||o}`,{type:"error"});return}if(!i()){F=!1;return}let a;try{a=E.slideover({title:V(`Report - ${t.run?.siteTitle||"WordPress import"}`),size:"lg",position:"right"})}catch(o){throw F=!1,o}const s=Rs(`
66
80
  <div class="wpx wpx-report">
67
81
  <p class="wpx-note" data-bind-text="meta.value"></p>
68
82
  <div class="wpx-tiles" data-each="tiles.value key=id"></div>
@@ -76,4 +90,4 @@ import{apiRequest as A,getToken as Aa}from"../api.js";import{addBannerAction as
76
90
  <div class="wpx-list wpx-report-people" data-each="people.value key=key"></div>
77
91
  <div class="wpx-card-title" data-bind-hidden="!redirects.value.length">Redirects</div>
78
92
  <div class="wpx-list wpx-report-redirects" data-each="redirects.value key=from"></div>
79
- </div>`);o.querySelector(".wpx-tiles").innerHTML=Et,o.querySelector(".wpx-note-list").innerHTML=St,o.querySelector(".wpx-seg").innerHTML=Oe,o.querySelector(".wpx-report-items").innerHTML=Mt,o.querySelector(".wpx-report-redirects").innerHTML=Tt,o.querySelector(".wpx-report-people").innerHTML=mo;const i=M.observable(t.run?.summary?.failed?"failed":"all"),c=t.items||[],rt=mt(c,yt,gt),q=t.run?.summary||{},Ae=s=>Object.values(q.kinds||{}).reduce((r,x)=>r+(x[s]||0),0),xa={meta:M.observable([G(t.run?.at),t.run?.by,t.run?.file,t.run?.durationMs?`${Math.max(1,Math.round(t.run.durationMs/1e3))} s`:""].filter(Boolean).join(" \xB7 ")),tiles:M.observable([{id:"made",label:"Made",value:Ae("created"),sub:""},{id:"updated",label:"Updated",value:Ae("updated"),sub:""},{id:"kept",label:"Left as is",value:Ae("kept"),sub:""},{id:"redirects",label:"Redirects",value:(q.redirects?.created||0)+(q.redirects?.updated||0),sub:""},...q.people?[{id:"people",label:"Accounts made",value:q.people.created||0,sub:q.people.invited?`${q.people.invited} emailed`:""}]:[],{id:"comments",label:"Comments",value:q.comments||0,sub:""},{id:"failed",label:"Failed",value:q.failed||0,sub:""}]),notes:M.observable((t.notes||[]).map(s=>({text:s}))),people:M.observable((t.people||[]).map(Ka)),filters:M.computed(()=>yt.filter(s=>s.id==="all"||rt[s.id]).map(s=>({...s,count:rt[s.id],cls:i.value===s.id?"is-on":""}))),rows:M.computed(()=>c.filter(s=>gt(s,i.value)).slice(0,1e3).map(s=>{const r=oo(s);return{...r,pillCls:r.pillClass}})),redirects:M.observable((t.redirects||[]).filter(s=>s.result!=="skipped").slice(0,1e3).map(s=>({...s,reason:s.error||"",pill:s.result==="failed"?"Failed":s.result==="updated"?"Updated":"Added",pillClass:s.result==="failed"?"is-bad":"is-ok"})))};a.element.appendChild(o);const ka=M.applyBindings(xa,o,{methods:{pickSeg:s=>{i.value=s.id}}}),Ma=pt(o),lt=new Map(c.map(s=>[s.key,s])),Ta=o.querySelector(".wpx-report-items"),Ea=s=>{const r=lt.get(s.dataset.key);if(!r)return[];const x=typeof r.target=="string"&&r.target.startsWith("/")?r.target:"",C=[{header:r.title}];if(x&&r.result!=="failed"&&r.result!=="skipped"&&C.push({label:"Open on the site",icon:"external-link",action:()=>window.open(x,"_blank","noopener")}),x&&(r.kind==="page"||r.kind==="custom"&&!r.collection)&&(r.result==="created"||r.result==="updated"||r.result==="kept")&&C.push({label:"Edit the page",icon:"edit",action:()=>{a.close(),location.hash=`#/pages/edit${x}`}}),(r.kind==="collection"||r.kind==="custom")&&r.result!=="failed"&&r.result!=="skipped"&&/^[a-z0-9-]{1,80}$/.test(r.kind==="collection"?r.target:r.collection||"")){const j=r.kind==="collection"?r.target:r.collection;C.push({label:"Open the collection",icon:"database",action:()=>{a.close(),location.hash=`#/collections/${j}/entries`}})}return r.kind==="product"&&r.entryId&&/^[\w-]{1,64}$/.test(r.entryId)&&C.push({label:"Edit in the Shop",icon:"shopping-bag",action:()=>{a.close(),location.hash=`#/plugins/shopping-cart/products/${encodeURIComponent(r.entryId)}`}}),/^https?:\/\//i.test(r.oldUrl)&&C.push({label:"Open the old address",icon:"link",action:()=>window.open(r.oldUrl,"_blank","noopener,noreferrer")}),x&&C.push({label:"Copy the new address",icon:"copy",action:()=>De(new URL(x,location.origin).href)}),C},Sa=E.contextMenu(Ta,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:Ea}),$a=o.querySelector(".wpx-report-people"),La=new Map((t.people||[]).map(s=>[s.key,s])),Ca=E.contextMenu($a,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:s=>{const r=La.get(s.dataset.key);if(!r)return[];const x=/^[0-9a-f-]{36}$/i.test(r.userId||"")?r.userId:"";return[{header:r.name},...x&&r.result!=="skipped"?[{label:"Open their account",icon:"user",action:()=>{a.close(),location.hash=`#/users/edit/${x}`}}]:[],{label:"Open Users",icon:"users",action:()=>{a.close(),location.hash="#/users"}}]}}),Pa=o.querySelector(".wpx-report-redirects"),Ra=E.contextMenu(Pa,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:s=>[{header:s.dataset.from},...s.dataset.from.includes("*")?[]:[{label:"Try it on the site",icon:"external-link",action:()=>window.open(s.dataset.from,"_blank","noopener")}],{label:"Open SEO \u203A Redirects",icon:"corner-up-right",action:()=>{a.close(),location.hash="#/seo/redirects"}}]}),Ie=s=>{const r=s.target.closest(".wpx-kebab");if(r){H(r);return}const x=s.target.closest(".wpx-report-people .wpx-row");if(x){H(x.querySelector(".wpx-kebab")||x);return}const C=s.target.closest(".wpx-report-items .wpx-row");if(!C)return;const j=lt.get(C.dataset.key);j?.target?.startsWith("/")&&j.result!=="failed"&&j.result!=="skipped"&&window.open(j.target,"_blank","noopener")},it=s=>{const r=s.target.closest(".wpx-row");r&&(s.key==="F10"&&s.shiftKey?(s.preventDefault(),H(r)):s.key==="Enter"&&s.target===r&&(s.preventDefault(),s.stopPropagation(),Ie({target:r})))};o.addEventListener("click",Ie),o.addEventListener("keydown",it);const qa=y.add(()=>a.close());Na(a,()=>{_=!1,ka.dispose(),Ma(),Sa?.destroy?.(),Ra?.destroy?.(),Ca?.destroy?.(),o.removeEventListener("click",Ie),o.removeEventListener("keydown",it),qa()}),a.open(),I.scan(o)}async function wa(e){const t=U.peek().find(a=>a.id===e);if(t&&await ge(`Remove the import of <strong>${F(t.siteTitle||t.source)}</strong> from this list? Everything it imported stays on the site.`,{title:"Remove from the history",confirmText:"Remove"}))try{if(await A(`${$}/history/${e}`,{method:"DELETE"}),!p())return;U.value=U.peek().filter(a=>a.id!==e),N(se)}catch(a){E.toast(`Not removed: ${a.message||a}`,{type:"error"})}}n.querySelector(".wpx-staged").innerHTML=io,n.querySelector(".wpx-items").innerHTML=Mt,n.querySelector(".wpx-redirects").innerHTML=Tt,n.querySelector(".wpx-history").innerHTML=po,n.querySelector(".wpx-tiles").innerHTML=Et,n.querySelector(".wpx-note-list").innerHTML=St,n.querySelector(".wpx-kinds").innerHTML=Oe,n.querySelector(".wpx-filters").innerHTML=Oe,n.querySelector(".wpx-facts").innerHTML=vo,n.querySelector(".wpx-product-notes").innerHTML=$t,n.querySelector(".wpx-types").innerHTML=co,n.querySelector(".wpx-internal").innerHTML=$t,n.querySelector(".wpx-people-list").innerHTML=uo;const fa={mode:Ct,job:g,jobTitle:ca,jobText:da,jobPct:je,staged:v,stagedRows:Rt,historyRows:qt,plan:b,planLoading:ne,planError:ke,refreshing:xe,opt:l,blogAvailable:D,blogNote:la,dirty:Be,canRun:ze,siteTitle:jt,siteMeta:Ft,tiles:Ut,notes:Bt,kinds:At,filters:Nt,rows:Ot,moreText:Dt,emptyText:Ht,redirectRows:_t,redirectCount:zt,query:V,uploadText:re,uploadError:J,dropping:ie,wxrLimit:ua,zipInfo:ce,zipText:ia,zipButton:pa,zipUploadText:le,hasPeople:Xt,peopleRows:Qt,peopleCanCreate:ea,peopleChoosable:ta,peopleNote:aa,peopleNoteCls:oa,inviteAvailable:sa,inviteText:na,optInvite:ra,shopAvailable:Pt,hasProducts:Jt,productNote:Wt,productNoteCls:Kt,productFacts:Zt,productNotes:Vt,typeRows:Ee,internalRows:Se,hasCustom:Yt,internalSummary:Gt,optComments:Y("comments"),optMenus:Y("menus"),optRedirects:Y("redirects"),optDrafts:Y("drafts"),optProducts:Y("products")},ba=M.applyBindings(fa,n,{methods:{back:()=>ee(),discard:()=>We(),run:()=>ha(),resetChoices:()=>{l.value=Ne(D.peek())},postsBlog:()=>L({posts:"blog"}),postsPages:()=>L({posts:"pages"}),postsSkip:()=>L({posts:"skip"}),mediaDownload:()=>L({media:"download"}),mediaZip:()=>L({media:"zip"}),mediaSkip:()=>L({media:"skip"}),removeZip:()=>va(),peopleAll:()=>L({users:ut(T.peek(),"create")}),peopleNone:()=>L({users:ut(T.peek(),"skip")}),pickSeg:e=>{e.seg==="kind"?O.value=e.id:B.value=e.id},showProducts:()=>{O.value="product",B.value="all",V.value="",n.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})}}});y.add(()=>ba.dispose()),y.add(pt(n,{position:"bottom"}));const ae=n.querySelector(".wpx-file"),Ze=()=>{const e=ae.files?.[0];ae.value="",Ke(e)};ae.addEventListener("change",Ze);const z=n.querySelector(".wpx-drop"),Ve=e=>{e.preventDefault(),ie.value=!0},Je=()=>{ie.value=!1},Ye=e=>{e.preventDefault(),ie.value=!1,Ke(e.dataTransfer?.files?.[0])};z.addEventListener("dragover",Ve),z.addEventListener("dragleave",Je),z.addEventListener("drop",Ye);const we=n.querySelector(".wpx-zip-file"),Ge=()=>{const e=we.files?.[0];we.value="",ma(e)};we.addEventListener("change",Ge),y.add(()=>{ae.removeEventListener("change",Ze),z.removeEventListener("dragover",Ve),z.removeEventListener("dragleave",Je),z.removeEventListener("drop",Ye),we.removeEventListener("change",Ge)}),W(n.querySelector(".wpx-staged"),".wpx-row",e=>[{header:v.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Upload"},{label:"Preview the import",icon:"eye",action:()=>ve(e.dataset.id)},{label:"Discard the upload",icon:"trash-2",action:()=>We(e.dataset.id)}],e=>ve(e.dataset.id));const ya=(e,t)=>{l.value={...l.peek(),choices:Ha(l.peek().choices,e,t)}};W(n.querySelector(".wpx-items"),".wpx-row",e=>{const t=X.peek().find(o=>o.key===e.dataset.key);if(!t)return[];const a=[{header:t.title}];for(const o of Ba(t,t.choice))a.push({label:o.label,icon:o.icon,action:()=>ya(t.key,o.id)});return t.oldUrl&&/^https?:\/\//i.test(t.oldUrl)&&a.push({label:"Open the old address",icon:"link",action:()=>window.open(t.oldUrl,"_blank","noopener,noreferrer")}),t.target?.startsWith("/")&&(t.action==="update"||t.action==="keep")&&a.push({label:"Open it on this site",icon:"external-link",action:()=>window.open(t.target,"_blank","noopener")}),a.length===1&&a.push({label:"Nothing to change here",icon:"info",disabled:!0,action:()=>{}}),a},e=>H(e.querySelector(".wpx-kebab")||e));const Xe=(e,t)=>{l.value=lo(l.peek(),e,t)},Qe=(e,t)=>{l.value=ro(l.peek(),e,t)},ga=e=>{O.value="",B.value="all",V.value=e,n.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})},oe=n.querySelector(".wpx-types"),et=e=>{if(!e.target.closest(".wpx-type-ctl"))return;e.stopPropagation();const a=e.target.closest("button[data-as]"),o=e.target.closest(".wpx-type-row");a&&o&&Xe(o.dataset.type,a.dataset.as)},tt=e=>{const t=e.target.closest("input[data-list-page]"),a=e.target.closest(".wpx-type-row");t&&a&&Qe(a.dataset.type,t.checked)};oe.addEventListener("click",et,!0),oe.addEventListener("change",tt),y.add(()=>{oe.removeEventListener("click",et,!0),oe.removeEventListener("change",tt)}),W(oe,".wpx-type-row",e=>{const t=Ee.peek().find(a=>a.type===e.dataset.type);return t?[{header:`${t.label} ("${t.type}")`},...no(t).map(a=>({label:a.label,icon:a.icon,action:()=>{a.id==="show"?ga(t.type):a.id==="list"||a.id==="nolist"?Qe(t.type,a.id==="list"):Xe(t.type,a.id)}}))]:[]},e=>H(e.querySelector(".wpx-kebab")||e));const at=(e,t)=>{const a=T.peek()?.rows?.find(o=>o.key===e);a&&L({users:Ua(l.peek().users,a,t)})},Re=n.querySelector(".wpx-people-list"),ot=e=>{if(!e.target.closest(".wpx-type-ctl"))return;e.stopPropagation();const a=e.target.closest("button[data-user]"),o=e.target.closest(".wpx-person");a&&o&&at(o.dataset.key,a.dataset.user)};Re.addEventListener("click",ot,!0),y.add(()=>Re.removeEventListener("click",ot,!0)),W(Re,".wpx-person",e=>{const t=T.peek()?.rows?.find(a=>a.key===e.dataset.key);return t?[{header:t.name},...Fa(t).map(a=>({label:a.label,icon:a.icon,disabled:!!a.disabled,action:()=>{a.disabled||(a.id==="copy"?De(t.email):at(t.key,a.id))}}))]:[]},e=>H(e.querySelector(".wpx-kebab")||e));const R=n.querySelector(".wpx-role");y.add(M.effect(()=>{const e=T.value;if(!R)return;const t=e?.roles||[],a=e?.role||"",o=`${t.map(i=>i.name).join(",")}|${a}`;R.dataset.sig!==o&&(R.dataset.sig=o,R.replaceChildren(...t.map(i=>{const c=document.createElement("option");return c.value=i.name,c.textContent=i.name===Ue?`${i.label} (default)`:i.label,c})),R.value=a)}));const st=()=>L({userRole:R.value===Ue?"":R.value});R?.addEventListener("change",st),y.add(()=>R?.removeEventListener("change",st)),W(n.querySelector(".wpx-redirects"),".wpx-row",e=>[{header:e.dataset.from},{label:"Copy the old address",icon:"copy",action:()=>De(e.dataset.from)}],null),W(n.querySelector(".wpx-history"),".wpx-row",e=>[{header:U.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Import"},{label:"Open the report",icon:"file-text",action:()=>he(e.dataset.id)},{label:"Remove from the history",icon:"trash-2",action:()=>wa(e.dataset.id)}],e=>he(e.dataset.id)),Ia(d,{id:"wpx-upload",icon:"upload",title:"Upload an export",onClick:()=>{h.peek()&&ee(),setTimeout(()=>ae.click(),0)}}),I.scan(n);const qe=vt(m(),v.peek().map(e=>e.id),f);qe.pruned&&k&&P({owner:f,items:qe.items});const nt=Object.entries(qe.items).sort((e,t)=>String(t[1].at).localeCompare(String(e[1].at)))[0];nt&&!g.peek()&&await ve(nt[0])}};
93
+ </div>`);s.querySelector(".wpx-tiles").innerHTML=Dt,s.querySelector(".wpx-note-list").innerHTML=Ut,s.querySelector(".wpx-seg").innerHTML=Be,s.querySelector(".wpx-report-items").innerHTML=Nt,s.querySelector(".wpx-report-redirects").innerHTML=Ot,s.querySelector(".wpx-report-people").innerHTML=Ss;const r=M.observable(t.run?.summary?.failed?"failed":"all"),d=t.items||[],ft=Et(d,Rt,qt),N=t.run?.summary||{},De=o=>Object.values(N.kinds||{}).reduce((n,x)=>n+(x[o]||0),0),Na={meta:M.observable([ee(t.run?.at),t.run?.by,t.run?.file,t.run?.durationMs?`${Math.max(1,Math.round(t.run.durationMs/1e3))} s`:""].filter(Boolean).join(" \xB7 ")),tiles:M.observable([{id:"made",label:"Made",value:De("created"),sub:""},{id:"updated",label:"Updated",value:De("updated"),sub:""},{id:"kept",label:"Left as is",value:De("kept"),sub:""},{id:"redirects",label:"Redirects",value:(N.redirects?.created||0)+(N.redirects?.updated||0),sub:""},...N.people?[{id:"people",label:"Accounts made",value:N.people.created||0,sub:N.people.invited?`${N.people.invited} emailed`:""}]:[],{id:"comments",label:"Comments",value:N.comments||0,sub:""},{id:"failed",label:"Failed",value:N.failed||0,sub:""}]),notes:M.observable((t.notes||[]).map(o=>({text:o}))),people:M.observable((t.people||[]).map(ns)),filters:M.computed(()=>Rt.filter(o=>o.id==="all"||ft[o.id]).map(o=>({...o,count:ft[o.id],cls:r.value===o.id?"is-on":""}))),rows:M.computed(()=>d.filter(o=>qt(o,r.value)).slice(0,1e3).map(o=>{const n=vs(o);return{...n,pillCls:n.pillClass}})),redirects:M.observable((t.redirects||[]).filter(o=>o.result!=="skipped").slice(0,1e3).map(o=>({...o,reason:o.error||"",pill:o.result==="failed"?"Failed":o.result==="updated"?"Updated":"Added",pillClass:o.result==="failed"?"is-bad":"is-ok"})))};a.element.appendChild(s);const Oa=M.applyBindings(Na,s,{methods:{pickSeg:o=>{r.value=o.id}}}),Da=yt(s),bt=new Map(d.map(o=>[o.key,o])),Ua=s.querySelector(".wpx-report-items"),Ha=o=>{const n=bt.get(o.dataset.key);if(!n)return[];const x=typeof n.target=="string"&&n.target.startsWith("/")?n.target:"",L=[{header:n.title}];if(x&&n.result!=="failed"&&n.result!=="skipped"&&L.push({label:"Open on the site",icon:"external-link",action:()=>window.open(x,"_blank","noopener")}),x&&(n.kind==="page"||n.kind==="custom"&&!n.collection)&&(n.result==="created"||n.result==="updated"||n.result==="kept")&&L.push({label:"Edit the page",icon:"edit",action:()=>{a.close(),location.hash=`#/pages/edit${x}`}}),n.kind==="widgets"&&/^[a-z0-9][a-z0-9-]{0,79}$/.test(n.target||"")&&["created","updated","kept"].includes(n.result)&&(L.push({label:"Edit the block",icon:"edit",action:()=>{a.close(),location.hash=`#/blocks/edit/${n.target}`}}),n.footer&&L.push({label:"Footer settings",icon:"settings",action:()=>{a.close(),location.hash="#/settings"}})),(n.kind==="collection"||n.kind==="custom")&&n.result!=="failed"&&n.result!=="skipped"&&/^[a-z0-9-]{1,80}$/.test(n.kind==="collection"?n.target:n.collection||"")){const Z=n.kind==="collection"?n.target:n.collection;L.push({label:"Open the collection",icon:"database",action:()=>{a.close(),location.hash=`#/collections/${Z}/entries`}})}return n.kind==="product"&&n.entryId&&/^[\w-]{1,64}$/.test(n.entryId)&&L.push({label:"Edit in the Shop",icon:"shopping-bag",action:()=>{a.close(),location.hash=`#/plugins/shopping-cart/products/${encodeURIComponent(n.entryId)}`}}),/^https?:\/\//i.test(n.oldUrl)&&L.push({label:"Open the old address",icon:"link",action:()=>window.open(n.oldUrl,"_blank","noopener,noreferrer")}),x&&L.push({label:"Copy the new address",icon:"copy",action:()=>ze(new URL(x,location.origin).href)}),L},Ba=E.contextMenu(Ua,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:Ha}),_a=s.querySelector(".wpx-report-people"),za=new Map((t.people||[]).map(o=>[o.key,o])),ja=E.contextMenu(_a,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:o=>{const n=za.get(o.dataset.key);if(!n)return[];const x=/^[0-9a-f-]{36}$/i.test(n.userId||"")?n.userId:"";return[{header:n.name},...x&&n.result!=="skipped"?[{label:"Open their account",icon:"user",action:()=>{a.close(),location.hash=`#/users/edit/${x}`}}]:[],{label:"Open Users",icon:"users",action:()=>{a.close(),location.hash="#/users"}}]}}),Wa=s.querySelector(".wpx-report-redirects"),Fa=E.contextMenu(Wa,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:o=>[{header:o.dataset.from},...o.dataset.from.includes("*")?[]:[{label:"Try it on the site",icon:"external-link",action:()=>window.open(o.dataset.from,"_blank","noopener")}],{label:"Open SEO \u203A Redirects",icon:"corner-up-right",action:()=>{a.close(),location.hash="#/seo/redirects"}}]}),Ue=o=>{const n=o.target.closest(".wpx-kebab");if(n){O(n);return}const x=o.target.closest(".wpx-report-people .wpx-row");if(x){O(x.querySelector(".wpx-kebab")||x);return}const L=o.target.closest(".wpx-report-items .wpx-row");if(!L)return;const Z=bt.get(L.dataset.key);Z?.target?.startsWith("/")&&Z.result!=="failed"&&Z.result!=="skipped"&&window.open(Z.target,"_blank","noopener")},gt=o=>{const n=o.target.closest(".wpx-row");n&&(o.key==="F10"&&o.shiftKey?(o.preventDefault(),O(n)):o.key==="Enter"&&o.target===n&&(o.preventDefault(),o.stopPropagation(),Ue({target:n})))};s.addEventListener("click",Ue),s.addEventListener("keydown",gt);const Ka=f.add(()=>a.close());Ga(a,()=>{F=!1,Oa.dispose(),Da(),Ba?.destroy?.(),Fa?.destroy?.(),ja?.destroy?.(),s.removeEventListener("click",Ue),s.removeEventListener("keydown",gt),Ka()}),a.open(),I.scan(s)}async function Ra(e){const t=B.peek().find(a=>a.id===e);if(t&&await Me(`Remove the import of <strong>${V(t.siteTitle||t.source)}</strong> from this list? Everything it imported stays on the site.`,{title:"Remove from the history",confirmText:"Remove"}))try{if(await C(`${$}/history/${e}`,{method:"DELETE"}),!i())return;B.value=B.peek().filter(a=>a.id!==e),R(re)}catch(a){E.toast(`Not removed: ${a.message||a}`,{type:"error"})}}l.querySelector(".wpx-staged").innerHTML=Ts,l.querySelector(".wpx-items").innerHTML=Nt,l.querySelector(".wpx-redirects").innerHTML=Ot,l.querySelector(".wpx-history").innerHTML=Es,l.querySelector(".wpx-tiles").innerHTML=Dt,l.querySelector(".wpx-note-list").innerHTML=Ut,l.querySelector(".wpx-kinds").innerHTML=Be,l.querySelector(".wpx-filters").innerHTML=Be,l.querySelector(".wpx-facts").innerHTML=Cs,l.querySelector(".wpx-product-notes").innerHTML=Ht,l.querySelector(".wpx-types").innerHTML=$s,l.querySelector(".wpx-internal").innerHTML=Ht,l.querySelector(".wpx-people-list").innerHTML=Ls,l.querySelector(".wpx-widget-areas").innerHTML=Ps;const qa={mode:Bt,job:y,jobTitle:Ma,jobText:Ta,jobPct:Je,staged:p,stagedRows:zt,historyRows:jt,plan:g,planLoading:ie,planError:Ee,refreshing:Te,opt:c,blogAvailable:U,blogNote:ba,dirty:Fe,canRun:Ge,siteTitle:ea,siteMeta:ta,tiles:Jt,notes:Yt,kinds:Wt,filters:Kt,rows:Zt,moreText:Vt,emptyText:Gt,redirectRows:Xt,redirectCount:Qt,query:J,uploadText:ce,uploadError:Y,dropping:de,wxrLimit:Ea,zipInfo:me,zipText:ga,zipButton:ya,zipUploadText:pe,hasPeople:ca,peopleRows:pa,peopleCanCreate:da,peopleChoosable:ua,peopleNote:ma,peopleNoteCls:ha,inviteAvailable:wa,inviteText:va,optInvite:fa,shopAvailable:_t,hasProducts:la,productNote:aa,productNoteCls:sa,productFacts:oa,productNotes:na,typeRows:Le,internalRows:Se,hasCustom:ra,internalSummary:ia,widgetsInfo:Ze,widgetsText:xa,widgetsButton:ka,widgetsUploadText:Pe,widgetRows:Ve,optComments:Q("comments"),optMenus:Q("menus"),optRedirects:Q("redirects"),optDrafts:Q("drafts"),optProducts:Q("products")},Aa=M.applyBindings(qa,l,{methods:{back:()=>ae(),discard:()=>Xe(),run:()=>Ca(),resetChoices:()=>{c.value=He(U.peek())},postsBlog:()=>P({posts:"blog"}),postsPages:()=>P({posts:"pages"}),postsSkip:()=>P({posts:"skip"}),mediaDownload:()=>P({media:"download"}),mediaZip:()=>P({media:"zip"}),mediaSkip:()=>P({media:"skip"}),removeZip:()=>Pa(),removeWidgets:()=>Sa(),peopleAll:()=>P({users:Mt(T.peek(),"create")}),peopleNone:()=>P({users:Mt(T.peek(),"skip")}),pickSeg:e=>{e.seg==="kind"?D.value=e.id:z.value=e.id},showProducts:()=>{D.value="product",z.value="all",J.value="",l.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})}}});f.add(()=>Aa.dispose()),f.add(yt(l,{position:"bottom"}));const oe=l.querySelector(".wpx-file"),et=()=>{const e=oe.files?.[0];oe.value="",Qe(e)};oe.addEventListener("change",et);const K=l.querySelector(".wpx-drop"),tt=e=>{e.preventDefault(),de.value=!0},at=()=>{de.value=!1},st=e=>{e.preventDefault(),de.value=!1,Qe(e.dataTransfer?.files?.[0])};K.addEventListener("dragover",tt),K.addEventListener("dragleave",at),K.addEventListener("drop",st);const be=l.querySelector(".wpx-zip-file"),ot=()=>{const e=be.files?.[0];be.value="",$a(e)};be.addEventListener("change",ot);const ge=l.querySelector(".wpx-wie-file"),nt=()=>{const e=ge.files?.[0];ge.value="",La(e)};ge.addEventListener("change",nt),f.add(()=>ge.removeEventListener("change",nt)),f.add(()=>{oe.removeEventListener("change",et),K.removeEventListener("dragover",tt),K.removeEventListener("dragleave",at),K.removeEventListener("drop",st),be.removeEventListener("change",ot)}),H(l.querySelector(".wpx-staged"),".wpx-row",e=>[{header:p.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Upload"},{label:"Preview the import",icon:"eye",action:()=>ve(e.dataset.id)},{label:"Discard the upload",icon:"trash-2",action:()=>Xe(e.dataset.id)}],e=>ve(e.dataset.id));const lt=(e,t)=>{c.value={...c.peek(),choices:Xa(c.peek().choices,e,t)}};H(l.querySelector(".wpx-items"),".wpx-row",e=>{const t=j.peek().find(s=>s.key===e.dataset.key);if(!t)return[];const a=[{header:t.title}];for(const s of Tt(t,t.choice))a.push({label:s.label,icon:s.icon,action:()=>lt(t.key,s.id)});return t.oldUrl&&/^https?:\/\//i.test(t.oldUrl)&&a.push({label:"Open the old address",icon:"link",action:()=>window.open(t.oldUrl,"_blank","noopener,noreferrer")}),t.target?.startsWith("/")&&(t.action==="update"||t.action==="keep")&&a.push({label:"Open it on this site",icon:"external-link",action:()=>window.open(t.target,"_blank","noopener")}),a.length===1&&a.push({label:"Nothing to change here",icon:"info",disabled:!0,action:()=>{}}),a},e=>O(e.querySelector(".wpx-kebab")||e));const rt=(e,t)=>{c.value=Ms(c.peek(),e,t)},it=(e,t)=>{c.value=ks(c.peek(),e,t)},Ia=e=>{D.value="",z.value="all",J.value=e,l.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})},ne=l.querySelector(".wpx-types"),ct=e=>{if(!e.target.closest(".wpx-type-ctl"))return;e.stopPropagation();const a=e.target.closest("button[data-as]"),s=e.target.closest(".wpx-type-row");a&&s&&rt(s.dataset.type,a.dataset.as)},pt=e=>{const t=e.target.closest("input[data-list-page]"),a=e.target.closest(".wpx-type-row");t&&a&&it(a.dataset.type,t.checked)};ne.addEventListener("click",ct,!0),ne.addEventListener("change",pt),f.add(()=>{ne.removeEventListener("click",ct,!0),ne.removeEventListener("change",pt)}),H(ne,".wpx-type-row",e=>{const t=Le.peek().find(a=>a.type===e.dataset.type);return t?[{header:`${t.label} ("${t.type}")`},...bs(t).map(a=>({label:a.label,icon:a.icon,action:()=>{a.id==="show"?Ia(t.type):a.id==="list"||a.id==="nolist"?it(t.type,a.id==="list"):rt(t.type,a.id)}}))]:[]},e=>O(e.querySelector(".wpx-kebab")||e));const Ie=(e,t)=>{c.value=xs(c.peek(),e,t)},le=l.querySelector(".wpx-widget-areas"),dt=e=>{e.target.closest(".wpx-type-ctl")&&e.stopPropagation()},ut=e=>{const t=e.target.closest("input[data-footer]"),a=e.target.closest(".wpx-widget-row");t&&a&&Ie(a.dataset.area,t.checked)};le.addEventListener("click",dt,!0),le.addEventListener("change",ut),f.add(()=>{le.removeEventListener("click",dt,!0),le.removeEventListener("change",ut)}),H(le,".wpx-widget-row",e=>{const t=Ve.peek().find(r=>r.area===e.dataset.area),a=j.peek().find(r=>r.key===`widgets:${e.dataset.area}`);if(!t)return[];const s=[{header:`${t.label} ("${t.area}")`}];if(t.canPlace&&s.push(t.placeOn?{label:"Leave it out of the footer",icon:"eye-off",action:()=>Ie(t.area,!1)}:{label:"Place in the footer",icon:"layout",action:()=>Ie(t.area,!0)}),a)for(const r of Tt(a,a.choice))s.push({label:r.label,icon:r.icon,action:()=>lt(a.key,r.id)});return s.length===1&&s.push({label:"Nothing to change here",icon:"info",disabled:!0,action:()=>{}}),s},e=>O(e.querySelector(".wpx-kebab")||e));const mt=(e,t)=>{const a=T.peek()?.rows?.find(s=>s.key===e);a&&P({users:Qa(c.peek().users,a,t)})},Ne=l.querySelector(".wpx-people-list"),ht=e=>{if(!e.target.closest(".wpx-type-ctl"))return;e.stopPropagation();const a=e.target.closest("button[data-user]"),s=e.target.closest(".wpx-person");a&&s&&mt(s.dataset.key,a.dataset.user)};Ne.addEventListener("click",ht,!0),f.add(()=>Ne.removeEventListener("click",ht,!0)),H(Ne,".wpx-person",e=>{const t=T.peek()?.rows?.find(a=>a.key===e.dataset.key);return t?[{header:t.name},...ss(t).map(a=>({label:a.label,icon:a.icon,disabled:!!a.disabled,action:()=>{a.disabled||(a.id==="copy"?ze(t.email):mt(t.key,a.id))}}))]:[]},e=>O(e.querySelector(".wpx-kebab")||e));const A=l.querySelector(".wpx-role");f.add(M.effect(()=>{const e=T.value;if(!A)return;const t=e?.roles||[],a=e?.role||"",s=`${t.map(r=>r.name).join(",")}|${a}`;A.dataset.sig!==s&&(A.dataset.sig=s,A.replaceChildren(...t.map(r=>{const d=document.createElement("option");return d.value=r.name,d.textContent=r.name===We?`${r.label} (default)`:r.label,d})),A.value=a)}));const wt=()=>P({userRole:A.value===We?"":A.value});A?.addEventListener("change",wt),f.add(()=>A?.removeEventListener("change",wt)),H(l.querySelector(".wpx-redirects"),".wpx-row",e=>[{header:e.dataset.from},{label:"Copy the old address",icon:"copy",action:()=>ze(e.dataset.from)}],null),H(l.querySelector(".wpx-history"),".wpx-row",e=>[{header:B.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Import"},{label:"Open the report",icon:"file-text",action:()=>fe(e.dataset.id)},{label:"Remove from the history",icon:"trash-2",action:()=>Ra(e.dataset.id)}],e=>fe(e.dataset.id)),Va(u,{id:"wpx-upload",icon:"upload",title:"Upload an export",onClick:()=>{h.peek()&&ae(),setTimeout(()=>oe.click(),0)}}),I.scan(l);const Oe=$t(w(),p.peek().map(e=>e.id),b);Oe.pruned&&k&&q({owner:b,items:Oe.items});const vt=Object.entries(Oe.items).sort((e,t)=>String(t[1].at).localeCompare(String(e[1].at)))[0];vt&&!y.peek()&&await ve(vt[0])}};
package/docs/cache.md CHANGED
@@ -37,6 +37,8 @@ page:<urlPath>:m<fileMtime>:role<roles>:o<origin>
37
37
 
38
38
  For example: `page:/about:m1727430000000:roleanon:ohttps://example.com`.
39
39
 
40
+ Domma Docs pages (`/domma-docs/...`) are cached the same way under `docs:<path>:role<roles>:o<origin>`, because their navbar, footers and overlays filter by role too. Both keys build the role part with `viewerRoleKey()` in `server/services/userRoles.js` - use it for any new cached render whose output depends on the viewer, and never key on the user id.
41
+
40
42
  Admin API responses, login pages and error pages are not cached. Drafts (including draft previews) are never cached, and a page containing a row-level `[view]` is rendered fresh for each signed-in viewer.
41
43
 
42
44
  Cache keys are versioned with a `v1:` prefix. Bumping the version (in `server/services/cache/index.js`) auto-invalidates the entire cache without needing `clear()` - useful if the cached value shape ever changes.
@@ -253,6 +253,7 @@ the host is empty you get, in order of how likely you are to see it:
253
253
  | `copyright` | string | Copyright line - above the footer navigation in the one-row layout, at the left of the bottom bar in the columns layout |
254
254
  | `layout` | string | `auto` (default), `columns` or `row`. **Columns**: the brand (the navbar's text, logo or icon), the blurb and the social links beside one column per group of the `footer-primary` menu (a top-level item with sub-items; its text is the heading, a link only if it has a URL), over a bottom bar of copyright, the `footer-legal` menu and the motion control. **Row**: everything on one wrapped row, as before. **Auto**: columns when the footer menu has groups, else a row. Site Settings > Footer > Layout. |
255
255
  | `blurb` | string | A sentence or two under the brand in the columns layout. Plain text. |
256
+ | `blocks` | array | Block names (`content/blocks/<name>.html`) drawn side by side at the top of the footer on every page, in order - up to 8, lower-case letters, digits and hyphens. Rendered by the server (`buildFooterBlocks()` in `renderer.js`, both render paths) as `[block template="…" /]`, so sanitised like a page; a name that is not a block is left out. Site Settings > Footer > Footer blocks; Import from WordPress adds a site's footer widget areas here. |
256
257
  | `showMotionToggle` | boolean | Whether the footer shows the "Reduce motion" accessibility switch. **Defaults to `true`** - omit the key and the switch appears, so sites that predate this setting are unchanged. Editable from Site Settings > Footer. |
257
258
  | `class` | string | Your own CSS classes on the site footer (`#site-footer`). Site Settings > Footer. |
258
259
  | `socialClass` | string | Your own CSS classes on every social media icon link in the footer. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.8.8",
3
+ "version": "1.8.10",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",