domma-cms 1.8.3 → 1.8.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.5] - 2026-10-16
4
+
5
+ - **Import from WordPress brings custom post types across.** Content a theme or plugin added to WordPress - events, team members, portfolio pieces - now has its own Custom types section in the preview, with how many there are, a few titles, and what each will become. By default a type becomes a collection (wp-event, wp-team-member…) holding each item's title, address, text, excerpt, date, status and featured image, its categories, and every custom field it had, Advanced Custom Fields included - dates, numbers, links and pictures recognised as such. A list page at the type's old address (/events) shows the published ones, and the old single-item addresses and `?p=` links lead there; drafts come across but are never shown or readable from the site. Or choose Pages - each item a page at its old address, its categories as tags - or Skip. The type's address is read from the export's own links, never guessed. WordPress's and plugins' own housekeeping (revisions, reusable blocks, templates, form definitions, orders…) is listed once with why it is not imported. Run it again and entries you edited here are left alone unless you choose Overwrite, and a collection only ever gains fields - your own fields and labels stay.
6
+
7
+ ## [1.8.4] - 2026-10-16
8
+
9
+ - Restore the visible caret in the email body. The shared smooth caret now positions itself after detached compose editors are mounted, keeping it beside the text during typing, formatting and scrolling, and after reopening compose.
10
+ - **Built against domma-js 0.53.1** - see [its release notes](https://github.com/pinpointzero73/domma/releases/tag/v0.53.1).
11
+
3
12
  ## [1.8.3] - 2026-10-16
4
13
 
5
14
  - **The admin fits a phone.** At phone widths the top bar no longer makes every admin screen scroll sideways: its links show as icons (with the bell's count), a long name is shortened, and a menu button opens the sidebar as a drawer over the screen instead of squeezing the screen beside it. On wider screens the top bar's links now show their icons and tooltips, which were being stripped. View header titles and button rows wrap.
package/CLAUDE.md CHANGED
@@ -361,6 +361,26 @@ A built-in Tool (`wordpress-import` in `services/tools.js`, permission `import.w
361
361
  imported and redirect to the Shop's (`wooPageRole`). The WXR has no currency or weight unit: the Shop's currency
362
362
  and kilograms are assumed, and the preview says so. Orders, customers, coupons, reviews, tax and shipping
363
363
  settings are never imported.
364
+ - **Custom post types** (`custom.js`, pure): every type not handled above is either plumbing - `INTERNAL_TYPES`, the ONE
365
+ list (a string or RegExp per entry, each with the plain reason the preview shows; extend it there) - or content,
366
+ offered per type as `options.types[type]` = collection (default) / pages / skip, plus `options.listPages[type] =
367
+ false` to drop the list page (only non-defaults are sent). The type's address (`rewriteSlugOf`) is read from the
368
+ items' own pretty links, never guessed; with none, the new address is the type name and nothing old is redirected.
369
+ Collection: slug `wp-<type>` (`freePath` on a clash), fields = core seven + one per taxonomy + one per public postmeta
370
+ key (no `_` keys, so ACF values in, its field references out; `META_SKIP` drops SEO/builder keys), types inferred by
371
+ `inferType` (an attachment id -> url to the file here); serialised values only through `readSerialised`, an object
372
+ refused and left empty with a report note. Written with the collections service; `api.read` is created disabled
373
+ because entries include drafts - the list page (`[collection … where_status="published"]`, plan key
374
+ `typepage:<type>`, a `kind: 'page'` row with `listFor`) is what the public sees, and old single-item addresses and
375
+ `?p=` lead to it. Re-runs: the mapping's `collection:<type>` slug is used again and its schema only GAINS fields
376
+ (`mergeFields` - the person's fields and labels stay); entries are `custom:<id>` with a fingerprint of their
377
+ NON-EMPTY values (`entryFingerprintText`), so a re-save that adds blanks is not an edit. A deleted collection is
378
+ offered back ("Import again"), never silently remade. Pages: `custom:<id>` rows with `as: 'pages'` go through the
379
+ ordinary page path (`planDocument`), taxonomies as tags. A `post_type_archive` menu item for a type leads to its list
380
+ page (`archive:<type>`). Switching a type between runs: a `custom:<id>` mapping keeps BOTH halves (page `path`/`hash`,
381
+ entry `collection`/`entryId`/`entryHash`), so switching back finds what was made rather than making it twice, and a
382
+ redirect an earlier run added from an address this run gave a page is removed (report result `removed`). Excerpts lose
383
+ their shortcode tags (`stripShortcodes`) - the list page's display rows go through the later shortcode stages.
364
384
 
365
385
  ## Site search
366
386
 
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools CSS v0.53.0
2
+ * Domma Tools CSS v0.53.1
3
3
  * Dynamic Object Manipulation & Modeling API
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-10-15T22:14:11.256Z
6
- * Commit: e15cc27
5
+ * Built: 2026-10-16T09:48:54.295Z
6
+ * Commit: 0d0765f
7
7
  */
8
8
 
9
9
  /*!
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools v0.53.0
2
+ * Domma Tools v0.53.1
3
3
  * Developer tools: Theme Roller & Page Roller
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-10-15T22:13:57.322Z
6
- * Commit: e15cc27
5
+ * Built: 2026-10-16T09:48:38.993Z
6
+ * Commit: 0d0765f
7
7
  *
8
8
  * Requires: domma.min.js
9
9
  */
@@ -1 +1 @@
1
- export const KIND_LABEL={page:"Page",post:"Post",product:"Product",media:"Media",menu:"Menu",category:"Category"},KIND_PLURAL={page:"Pages",post:"Posts",product:"Products",media:"Media",menu:"Menus",category:"Categories"},KIND_ICON={page:"file-text",post:"edit-3",product:"shopping-bag",media:"image",menu:"menu",category:"tag"},PRODUCT_TYPE_LABEL={simple:"Simple",variable:"With options",grouped:"Grouped",external:"External"},ACTION={create:{text:"New",tone:"ok"},rename:{text:"New, renamed",tone:"warn"},update:{text:"Update",tone:"info"},keep:{text:"Left as is",tone:"muted"},skip:{text:"Skipped",tone:"muted"}},RESULT={created:{text:"Made",tone:"ok"},updated:{text:"Updated",tone:"info"},kept:{text:"Left as is",tone:"muted"},skipped:{text:"Skipped",tone:"muted"},failed:{text:"Failed",tone:"bad"}},PLAN_FILTERS=[{id:"all",label:"All"},{id:"new",label:"New"},{id:"update",label:"Updates"},{id:"renamed",label:"Renamed"},{id:"keep",label:"Left as is"},{id:"skip",label:"Skipped"},{id:"rebuild",label:"Needs rebuilding"}],REPORT_FILTERS=[{id:"all",label:"All"},{id:"created",label:"Made"},{id:"updated",label:"Updated"},{id:"kept",label:"Left as is"},{id:"skipped",label:"Skipped"},{id:"failed",label:"Failed"},{id:"rebuild",label:"Needs rebuilding"}];const p=e=>!!(e.builder||e.needs||e.shortcodes?.length),c=e=>[e.builder?`Built with ${e.builder}`:"",e.needs||"",...(e.shortcodes||[]).map(t=>`[${t}]`)].filter(Boolean).join(" ");export function planMatches(e,t){switch(t){case"new":return e.action==="create"||e.action==="rename";case"update":return e.action==="update";case"renamed":return e.action==="rename"||!!e.replaces;case"keep":return e.action==="keep";case"skip":return e.action==="skip";case"rebuild":return p(e);default:return!0}}export function reportMatches(e,t){return t==="rebuild"?p(e):t==="all"||!t||e.result===t}export function counts(e,t,o,i=""){const a=e.filter(s=>!i||s.kind===i);return Object.fromEntries(t.map(s=>[s.id,a.filter(n=>o(n,s.id)).length]))}export function kindTabs(e){const t=["page","post","product","media","menu","category"],o={};for(const i of e)o[i.kind]=(o[i.kind]||0)+1;return[{id:"",label:"Everything",count:e.length},...t.filter(i=>o[i]).map(i=>({id:i,label:KIND_PLURAL[i],count:o[i]}))]}export function planRow(e){const t=ACTION[e.action]||ACTION.skip,o=e.target?e.kind==="menu"?`Menu "${e.target}"`:e.target:"",i=[KIND_LABEL[e.kind]||e.kind];return e.status&&(e.kind==="page"||e.kind==="post")&&i.push(e.status),e.kind==="product"&&(e.productType&&i.push(PRODUCT_TYPE_LABEL[e.productType]||e.productType),e.variants&&i.push(`${e.variants} option${e.variants===1?"":"s"}`),e.action!=="skip"&&e.status&&i.push(e.status==="active"?"on sale":"draft")),e.comments&&i.push(`${e.comments} comment${e.comments===1?"":"s"}`),e.count&&i.push(`${e.count} item${e.count===1?"":"s"}`),{key:e.key,kind:e.kind,icon:KIND_ICON[e.kind]||"file",title:e.title||"(untitled)",pill:e.replaces?"Replaces a page":t.text,pillClass:`is-${e.replaces?"warn":t.tone}`,where:o,meta:i.join(" \xB7 "),reason:e.reason||"",rebuild:c(e),chosen:!!e.choice}}export function reportRow(e){const t=RESULT[e.result]||RESULT.skipped;return{key:e.key,kind:e.kind,icon:KIND_ICON[e.kind]||"file",title:e.title||"(untitled)",pill:t.text,pillClass:`is-${t.tone}`,where:e.target||"",meta:[KIND_LABEL[e.kind]||e.kind,e.format==="html"?"kept as HTML":""].filter(Boolean).join(" \xB7 "),reason:[e.reason,...e.notes||[]].filter(Boolean).join(" "),rebuild:c(e)}}export function choiceItems(e,t){const o=[];return t&&o.push({id:"reset",label:"Undo my choice",icon:"rotate-ccw"}),t!=="skip"&&e.action!=="skip"&&e.action!=="keep"&&o.push({id:"skip",label:"Skip this",icon:"x-circle"}),t!=="overwrite"&&e.action==="keep"&&o.push({id:"overwrite",label:"Overwrite my changes here",icon:"refresh-cw"}),t!=="overwrite"&&e.action==="rename"&&(e.kind==="page"||e.kind==="post")&&e.wanted&&e.kind==="page"&&o.push({id:"overwrite",label:`Replace the page at ${e.wanted}`,icon:"refresh-cw"}),t!=="import"&&e.action==="skip"&&/Deleted (on this site|from the Blog|from the Shop)/.test(e.reason||"")&&o.push({id:"import",label:"Import again",icon:"download"}),o}export function applyChoice(e,t,o){const i={...e||{}};return!o||o==="reset"?delete i[t]:i[t]=o,i}export function defaultOptions(e=!1){return{posts:e?"blog":"pages",media:"download",comments:!0,menus:!0,redirects:!0,drafts:!0,products:!0,choices:{}}}export function cleanOptions(e={},t=!1){const o=defaultOptions(t),i=(a,s,n)=>s.includes(a)?a:n;return{posts:i(e.posts,t?["blog","pages","skip"]:["pages","skip"],o.posts),media:i(e.media,["download","zip","skip"],o.media),comments:e.comments!==!1,menus:e.menus!==!1,redirects:e.redirects!==!1,drafts:e.drafts!==!1,products:e.products!==!1,choices:Object.fromEntries(Object.entries(e.choices||{}).filter(([a,s])=>typeof a=="string"&&["skip","overwrite","import"].includes(s)))}}export function optionsSnapshot(e){const t=cleanOptions(e,!0),o=Object.keys(t.choices).sort().map(i=>`${i}=${t.choices[i]}`).join(",");return[t.posts,t.media,t.comments,t.menus,t.redirects,t.drafts,t.products,o].join("|")}export const isDirty=(e,t)=>optionsSnapshot(e)!==optionsSnapshot(defaultOptions(t)),draftKey=e=>e?`wordpress-import.draft.${e}`:"";export function liveDrafts(e,t,o){if(!e||typeof e!="object"||!e.items||typeof e.items!="object")return{items:{},pruned:!1};if(e.owner&&o&&e.owner!==o)return{items:{},pruned:!1};const i={};let a=!1;for(const[s,n]of Object.entries(e.items))t.includes(s)&&n?.options&&n.was===s?i[s]=n:a=!0;return{items:i,pruned:a}}export function withDraft(e,t,o,i){const a={...e&&e.owner===t&&e.items||{}};return i?a[o]=i:delete a[o],{owner:t,items:a}}export function draftQuestion({when:e="",file:t=""}={}){return{title:"Choices you left last time",text:`You changed the import options${t?` for ${t}`:""}${e?` (${e})`:""} and left before running it. Throw away those choices and start from the defaults?`,confirmText:"Throw away",cancelText:"Keep them"}}export function progressText(e){if(!e)return"";const t=e.total?` \xB7 ${e.done} of ${e.total}`:"";return`${e.phase||"Working"}${t}${e.current?` \xB7 ${String(e.current).slice(0,80)}`:""}`}export const progressPercent=e=>e?.total?Math.min(100,Math.round(e.done/e.total*100)):0;export function planTiles(e){const t=e?.summary?.counts||{},o=i=>t[i]?t[i].total-t[i].skip:0;return[{id:"page",label:"Pages",value:o("page"),of:t.page?.total||0},{id:"post",label:"Posts",value:o("post"),of:t.post?.total||0},...t.product?[{id:"product",label:"Products",value:o("product"),of:t.product.total}]:[],{id:"media",label:"Media",value:o("media"),of:t.media?.total||0},{id:"menu",label:"Menus",value:o("menu"),of:t.menu?.total||0},{id:"comments",label:"Comments",value:e?.summary?.comments||0,of:0},{id:"redirects",label:"Redirects",value:e?.summary?.redirects||0,of:0}].map(i=>({...i,sub:i.of&&i.of!==i.value?`of ${i.of}`:""}))}export function historyRow(e,t=o=>o){const o=e.summary||{},i=Object.values(o.kinds||{}).reduce((n,l)=>n+(l.created||0),0),a=Object.values(o.kinds||{}).reduce((n,l)=>n+(l.updated||0),0),s=[];return i&&s.push(`${i} made`),a&&s.push(`${a} updated`),o.redirects?.created&&s.push(`${o.redirects.created} redirect${o.redirects.created===1?"":"s"}`),o.rebuild&&s.push(`${o.rebuild} to rebuild`),o.failed&&s.push(`${o.failed} failed`),e.status==="failed"&&s.splice(0,s.length,"Stopped before the end - run it again to finish"),{id:e.id,title:e.siteTitle||e.source||"WordPress site",meta:[t(e.at),e.by,e.file].filter(Boolean).join(" \xB7 "),summary:s.join(", ")||"Nothing changed",pill:e.status==="failed"?"Stopped":e.status==="partial"?"Some failed":"Done",pillClass:e.status==="failed"||e.status==="partial"?"is-bad":"is-ok"}}export function stagedRow(e,t=o=>o){const o=e.counts||{},i=[o.page&&`${o.page} pages`,o.post&&`${o.post} posts`,o.product&&`${o.product} products`,o.attachment&&`${o.attachment} media`].filter(Boolean);return{id:e.id,title:e.siteTitle||e.fileName||"WordPress export",meta:[e.fileName,t(e.at),i.join(", ")].filter(Boolean).join(" \xB7 "),pill:e.uploads?"Uploads zip added":"Waiting",pillClass:e.uploads?"is-ok":"is-muted"}}export function productSummary(e){const t=e?.summary?.products;if(!t?.total)return null;const o=t.shop||e.shop||{},i=e.options?.products!==!1,a=Object.entries(t.types||{}).map(([d,u])=>`${u} ${(PRODUCT_TYPE_LABEL[d]||d).toLowerCase()}`).join(", "),s=e.summary.counts?.product||{},n=[{label:"In the export",value:`${t.total}${a?` (${a})`:""}`}];o.available&&i&&(n.push({label:"On sale in the Shop",value:String(t.onSale||0)}),n.push({label:"As drafts",value:String(t.drafts||0)}),s.keep&&n.push({label:"Left as is",value:String(s.keep)}),n.push({label:"Skipped",value:String(s.skip||0)})),t.rebuild&&n.push({label:"Need rebuilding",value:String(t.rebuild)});let l,r="info";return o.available?i?l=`Products go to the Shop at ${o.basePath||"/shop"}.`:l='Products are not being imported - switch on "WooCommerce products" above to bring them in.':(l=o.reason||"Switch on the Shop to bring these in.",r="warn"),{note:l,tone:r,rows:n,notes:Array.isArray(t.notes)?t.notes:[]}}
1
+ export const KIND_LABEL={page:"Page",post:"Post",product:"Product",custom:"Custom item",collection:"Collection",media:"Media",menu:"Menu",category:"Category"},KIND_PLURAL={page:"Pages",post:"Posts",product:"Products",custom:"Custom items",collection:"Collections",media:"Media",menu:"Menus",category:"Categories"},KIND_ICON={page:"file-text",post:"edit-3",product:"shopping-bag",custom:"box",collection:"database",media:"image",menu:"menu",category:"tag"},TYPE_AS={collection:{text:"Collection",tone:"ok"},pages:{text:"Pages",tone:"info"},skip:{text:"Skipped",tone:"muted"}},PRODUCT_TYPE_LABEL={simple:"Simple",variable:"With options",grouped:"Grouped",external:"External"},ACTION={create:{text:"New",tone:"ok"},rename:{text:"New, renamed",tone:"warn"},update:{text:"Update",tone:"info"},keep:{text:"Left as is",tone:"muted"},skip:{text:"Skipped",tone:"muted"}},RESULT={created:{text:"Made",tone:"ok"},updated:{text:"Updated",tone:"info"},kept:{text:"Left as is",tone:"muted"},skipped:{text:"Skipped",tone:"muted"},failed:{text:"Failed",tone:"bad"}},PLAN_FILTERS=[{id:"all",label:"All"},{id:"new",label:"New"},{id:"update",label:"Updates"},{id:"renamed",label:"Renamed"},{id:"keep",label:"Left as is"},{id:"skip",label:"Skipped"},{id:"rebuild",label:"Needs rebuilding"}],REPORT_FILTERS=[{id:"all",label:"All"},{id:"created",label:"Made"},{id:"updated",label:"Updated"},{id:"kept",label:"Left as is"},{id:"skipped",label:"Skipped"},{id:"failed",label:"Failed"},{id:"rebuild",label:"Needs rebuilding"}];const d=e=>!!(e.builder||e.needs||e.shortcodes?.length),u=e=>[e.builder?`Built with ${e.builder}`:"",e.needs||"",...(e.shortcodes||[]).map(t=>`[${t}]`)].filter(Boolean).join(" ");export function planMatches(e,t){switch(t){case"new":return e.action==="create"||e.action==="rename";case"update":return e.action==="update";case"renamed":return e.action==="rename"||!!e.replaces;case"keep":return e.action==="keep";case"skip":return e.action==="skip";case"rebuild":return d(e);default:return!0}}export function reportMatches(e,t){return t==="rebuild"?d(e):t==="all"||!t||e.result===t}export function counts(e,t,s,i=""){const n=e.filter(o=>!i||o.kind===i);return Object.fromEntries(t.map(o=>[o.id,n.filter(a=>s(a,o.id)).length]))}export function kindTabs(e){const t=["page","post","product","custom","collection","media","menu","category"],s={};for(const i of e)s[i.kind]=(s[i.kind]||0)+1;return[{id:"",label:"Everything",count:e.length},...t.filter(i=>s[i]).map(i=>({id:i,label:KIND_PLURAL[i],count:s[i]}))]}export function planRow(e){const t=ACTION[e.action]||ACTION.skip;let s=e.target?e.kind==="menu"?`Menu "${e.target}"`:e.kind==="collection"?`Collection "${e.target}"`:e.target:"";e.kind==="custom"&&e.as==="collection"&&e.collection&&e.action!=="skip"&&(s=`In the collection "${e.collection}"${e.listAt?`, listed at ${e.listAt}`:""}`);const i=[e.kind==="custom"&&e.postType?`${KIND_LABEL.custom} (${e.postType})`:KIND_LABEL[e.kind]||e.kind];return e.listFor&&i.push("list page"),e.status&&(e.kind==="page"||e.kind==="post"||e.kind==="custom")&&i.push(e.status),e.kind==="collection"&&e.fields&&i.push(`${e.fields} fields`),e.kind==="product"&&(e.productType&&i.push(PRODUCT_TYPE_LABEL[e.productType]||e.productType),e.variants&&i.push(`${e.variants} option${e.variants===1?"":"s"}`),e.action!=="skip"&&e.status&&i.push(e.status==="active"?"on sale":"draft")),e.comments&&i.push(`${e.comments} comment${e.comments===1?"":"s"}`),e.count&&i.push(`${e.count} item${e.count===1?"":"s"}`),{key:e.key,kind:e.kind,icon:KIND_ICON[e.kind]||"file",title:e.title||"(untitled)",pill:e.replaces?"Replaces a page":t.text,pillClass:`is-${e.replaces?"warn":t.tone}`,where:s,meta:i.join(" \xB7 "),reason:e.reason||"",rebuild:u(e),chosen:!!e.choice}}export function reportRow(e){const t=RESULT[e.result]||RESULT.skipped;return{key:e.key,kind:e.kind,icon:KIND_ICON[e.kind]||"file",title:e.title||"(untitled)",pill:t.text,pillClass:`is-${t.tone}`,where:e.target||"",meta:[KIND_LABEL[e.kind]||e.kind,e.format==="html"?"kept as HTML":""].filter(Boolean).join(" \xB7 "),reason:[e.reason,...e.notes||[]].filter(Boolean).join(" "),rebuild:u(e)}}export function choiceItems(e,t){const s=[];return t&&s.push({id:"reset",label:"Undo my choice",icon:"rotate-ccw"}),t!=="skip"&&e.action!=="skip"&&e.action!=="keep"&&s.push({id:"skip",label:"Skip this",icon:"x-circle"}),t!=="overwrite"&&e.action==="keep"&&s.push({id:"overwrite",label:"Overwrite my changes here",icon:"refresh-cw"}),t!=="overwrite"&&e.action==="rename"&&(e.kind==="page"||e.kind==="post")&&e.wanted&&e.kind==="page"&&s.push({id:"overwrite",label:`Replace the page at ${e.wanted}`,icon:"refresh-cw"}),t!=="import"&&e.action==="skip"&&/Deleted (on this site|from the Blog|from the Shop|from the collection)/.test(e.reason||"")&&s.push({id:"import",label:"Import again",icon:"download"}),s}export function applyChoice(e,t,s){const i={...e||{}};return!s||s==="reset"?delete i[t]:i[t]=s,i}export function defaultOptions(e=!1){return{posts:e?"blog":"pages",media:"download",comments:!0,menus:!0,redirects:!0,drafts:!0,products:!0,types:{},listPages:{},choices:{}}}export function cleanOptions(e={},t=!1){const s=defaultOptions(t),i=(n,o,a)=>o.includes(n)?n:a;return{posts:i(e.posts,t?["blog","pages","skip"]:["pages","skip"],s.posts),media:i(e.media,["download","zip","skip"],s.media),comments:e.comments!==!1,menus:e.menus!==!1,redirects:e.redirects!==!1,drafts:e.drafts!==!1,products:e.products!==!1,types:Object.fromEntries(Object.entries(e.types||{}).filter(([n,o])=>f.test(n)&&(o==="pages"||o==="skip"))),listPages:Object.fromEntries(Object.entries(e.listPages||{}).filter(([n,o])=>f.test(n)&&o===!1)),choices:Object.fromEntries(Object.entries(e.choices||{}).filter(([n,o])=>typeof n=="string"&&["skip","overwrite","import"].includes(o)))}}export function optionsSnapshot(e){const t=cleanOptions(e,!0),s=Object.keys(t.choices).sort().map(o=>`${o}=${t.choices[o]}`).join(","),i=Object.keys(t.types).sort().map(o=>`${o}=${t.types[o]}`).join(","),n=Object.keys(t.listPages).sort().join(",");return[t.posts,t.media,t.comments,t.menus,t.redirects,t.drafts,t.products,s,i,n].join("|")}const f=/^[a-z0-9_-]{1,40}$/;export function withTypeChoice(e,t,s){const i={...e.types||{}};return s==="pages"||s==="skip"?i[t]=s:delete i[t],{...e,types:i}}export function withListPage(e,t,s){const i={...e.listPages||{}};return s?delete i[t]:i[t]=!1,{...e,listPages:i}}export const isDirty=(e,t)=>optionsSnapshot(e)!==optionsSnapshot(defaultOptions(t)),draftKey=e=>e?`wordpress-import.draft.${e}`:"";export function liveDrafts(e,t,s){if(!e||typeof e!="object"||!e.items||typeof e.items!="object")return{items:{},pruned:!1};if(e.owner&&s&&e.owner!==s)return{items:{},pruned:!1};const i={};let n=!1;for(const[o,a]of Object.entries(e.items))t.includes(o)&&a?.options&&a.was===o?i[o]=a:n=!0;return{items:i,pruned:n}}export function withDraft(e,t,s,i){const n={...e&&e.owner===t&&e.items||{}};return i?n[s]=i:delete n[s],{owner:t,items:n}}export function draftQuestion({when:e="",file:t=""}={}){return{title:"Choices you left last time",text:`You changed the import options${t?` for ${t}`:""}${e?` (${e})`:""} and left before running it. Throw away those choices and start from the defaults?`,confirmText:"Throw away",cancelText:"Keep them"}}export function progressText(e){if(!e)return"";const t=e.total?` \xB7 ${e.done} of ${e.total}`:"";return`${e.phase||"Working"}${t}${e.current?` \xB7 ${String(e.current).slice(0,80)}`:""}`}export const progressPercent=e=>e?.total?Math.min(100,Math.round(e.done/e.total*100)):0;export function planTiles(e){const t=e?.summary?.counts||{},s=i=>t[i]?t[i].total-t[i].skip:0;return[{id:"page",label:"Pages",value:s("page"),of:t.page?.total||0},{id:"post",label:"Posts",value:s("post"),of:t.post?.total||0},...t.product?[{id:"product",label:"Products",value:s("product"),of:t.product.total}]:[],...t.custom?[{id:"custom",label:"Custom items",value:s("custom"),of:t.custom.total}]:[],{id:"media",label:"Media",value:s("media"),of:t.media?.total||0},{id:"menu",label:"Menus",value:s("menu"),of:t.menu?.total||0},{id:"comments",label:"Comments",value:e?.summary?.comments||0,of:0},{id:"redirects",label:"Redirects",value:e?.summary?.redirects||0,of:0}].map(i=>({...i,sub:i.of&&i.of!==i.value?`of ${i.of}`:""}))}export function historyRow(e,t=s=>s){const s=e.summary||{},i=Object.values(s.kinds||{}).reduce((a,l)=>a+(l.created||0),0),n=Object.values(s.kinds||{}).reduce((a,l)=>a+(l.updated||0),0),o=[];return i&&o.push(`${i} made`),n&&o.push(`${n} updated`),s.redirects?.created&&o.push(`${s.redirects.created} redirect${s.redirects.created===1?"":"s"}`),s.rebuild&&o.push(`${s.rebuild} to rebuild`),s.failed&&o.push(`${s.failed} failed`),e.status==="failed"&&o.splice(0,o.length,"Stopped before the end - run it again to finish"),{id:e.id,title:e.siteTitle||e.source||"WordPress site",meta:[t(e.at),e.by,e.file].filter(Boolean).join(" \xB7 "),summary:o.join(", ")||"Nothing changed",pill:e.status==="failed"?"Stopped":e.status==="partial"?"Some failed":"Done",pillClass:e.status==="failed"||e.status==="partial"?"is-bad":"is-ok"}}export function stagedRow(e,t=s=>s){const s=e.counts||{},i=[s.page&&`${s.page} pages`,s.post&&`${s.post} posts`,s.product&&`${s.product} products`,s.attachment&&`${s.attachment} media`].filter(Boolean);return{id:e.id,title:e.siteTitle||e.fileName||"WordPress export",meta:[e.fileName,t(e.at),i.join(", ")].filter(Boolean).join(" \xB7 "),pill:e.uploads?"Uploads zip added":"Waiting",pillClass:e.uploads?"is-ok":"is-muted"}}export function productSummary(e){const t=e?.summary?.products;if(!t?.total)return null;const s=t.shop||e.shop||{},i=e.options?.products!==!1,n=Object.entries(t.types||{}).map(([r,m])=>`${m} ${(PRODUCT_TYPE_LABEL[r]||r).toLowerCase()}`).join(", "),o=e.summary.counts?.product||{},a=[{label:"In the export",value:`${t.total}${n?` (${n})`:""}`}];s.available&&i&&(a.push({label:"On sale in the Shop",value:String(t.onSale||0)}),a.push({label:"As drafts",value:String(t.drafts||0)}),o.keep&&a.push({label:"Left as is",value:String(o.keep)}),a.push({label:"Skipped",value:String(o.skip||0)})),t.rebuild&&a.push({label:"Need rebuilding",value:String(t.rebuild)});let l,c="info";return s.available?i?l=`Products go to the Shop at ${s.basePath||"/shop"}.`:l='Products are not being imported - switch on "WooCommerce products" above to bring them in.':(l=s.reason||"Switch on the Shop to bring these in.",c="warn"),{note:l,tone:c,rows:a,notes:Array.isArray(t.notes)?t.notes:[]}}const p=(e,t,s=`${t}s`)=>`${e} ${e===1?t:s}`;export function customTypeRows(e){return(e?.summary?.customTypes||[]).map(t=>{const s=TYPE_AS[t.as]?t.as:"collection",i=TYPE_AS[s],n=t.rewrite?`was at /${t.rewrite}/\u2026`:"its old addresses are not in the export";let o;if(s==="skip")o="Nothing - left out.";else if(s==="pages")o=`${p(t.importing||0,"page")} under ${t.prefix}${t.drafts?` (${t.drafts} as draft${t.drafts===1?"":"s"})`:""}.`;else{const a=t.collection||{},l=a.action==="skip"?`The collection "${a.slug}" was deleted here - choose Import again on it below.`:`${a.action==="update"?"The collection":"A new collection"} "${a.slug}" with ${p(t.fields?.length||0,"field")}: ${p(t.importing||0,"entry","entries")}${t.drafts?` (${t.drafts} draft${t.drafts===1?"":"s"}, not shown on the site)`:""}.`,c=t.listPage?t.listAt?` A list page at ${t.listAt}${t.listAction==="keep"?" (edited here - left as it is)":""}; the old addresses lead there.`:"":" No list page - the old addresses are not redirected.";o=`${l}${c}`}return{type:t.type,label:t.label||t.type,meta:[p(t.count||0,"item"),`"${t.type}"`,n].join(" \xB7 "),samples:(t.samples||[]).length?`For example: ${t.samples.join(", ")}`:"",creates:o,pill:i.text,pillClass:`is-${i.tone}`,as:s,listOn:s==="collection"&&t.listPage!==!1,canList:s==="collection",listLabel:`List page at ${t.prefix||`/${t.type}`}`,segCollection:s==="collection"?"is-on":"",segPages:s==="pages"?"is-on":"",segSkip:s==="skip"?"is-on":""}})}export function internalTypeRows(e){return(e?.summary?.internalTypes||[]).map(t=>({type:t.type,text:`${t.type} (${t.count}) - ${t.reason}`}))}export function typeMenuItems(e){if(!e)return[];const t=[];return e.as!=="collection"&&t.push({id:"collection",label:"Import as a collection",icon:"database"}),e.as!=="pages"&&t.push({id:"pages",label:"Import as pages",icon:"file-text"}),e.as!=="skip"&&t.push({id:"skip",label:"Leave this type out",icon:"x-circle"}),e.as==="collection"&&t.push(e.listOn?{id:"nolist",label:"No list page",icon:"eye-off"}:{id:"list",label:"Make a list page",icon:"list"}),t.push({id:"show",label:"Show its items",icon:"filter"}),t}
@@ -127,9 +127,19 @@
127
127
  <ul class="wpx-note wpx-product-notes" data-each="productNotes.value key=text"></ul>
128
128
  </div>
129
129
 
130
+ <div class="wpx-card wpx-custom" hidden data-bind-hidden="!hasCustom.value">
131
+ <div class="wpx-card-title"><span data-icon="box" data-icon-size="16"></span> Custom types
132
+ <span data-help-title="Custom types" data-help="Content a theme or plugin added to WordPress - events, team members, portfolio pieces. Collection (the usual choice): each type becomes a collection named wp-…, with the title, address, text, excerpt, date, status and featured image of each item, plus its categories and every custom field it had (Advanced Custom Fields included). Drafts come across but are never shown on the site. A list page at the type's old address shows the published ones, and the old single-item addresses lead to it. Pages: each item becomes a page at its old address, its categories as tags. Skip: left out. Run it again later and entries you edited here are left alone unless you choose Overwrite; a collection only ever gains fields."></span></div>
133
+ <div class="wpx-list wpx-types" data-each="typeRows.value key=type"></div>
134
+ <details class="wpx-internal-box" hidden data-bind-hidden="!internalRows.value.length">
135
+ <summary data-bind-text="internalSummary.value"></summary>
136
+ <ul class="wpx-note wpx-internal" data-each="internalRows.value key=type"></ul>
137
+ </details>
138
+ </div>
139
+
130
140
  <div class="wpx-card">
131
141
  <div class="wpx-card-title">Item by item
132
- <span data-help-title="Item by item" data-help="What happens to each page, post, product, file and menu. New: made here. Renamed: its address is taken here, so it gets the next free one (the old address redirects to it). Update: made by an earlier import and unchanged here since - refreshed. Left as is: made by an earlier import but edited here since - not touched unless you choose Overwrite. Right-click (or ⋮, or Shift+F10) an item to skip it or change what happens. Needs rebuilding: shortcodes and page builders this site has no equivalent for - the text stays, the layout is yours to rebuild."></span>
142
+ <span data-help-title="Item by item" data-help="What happens to each page, post, product, custom item, collection, file and menu. New: made here. Renamed: its address is taken here, so it gets the next free one (the old address redirects to it). Update: made by an earlier import and unchanged here since - refreshed. Left as is: made by an earlier import but edited here since - not touched unless you choose Overwrite. Right-click (or ⋮, or Shift+F10) an item to skip it or change what happens. Needs rebuilding: shortcodes and page builders this site has no equivalent for - the text stays, the layout is yours to rebuild."></span>
133
143
  <span class="wpx-spacer"></span>
134
144
  <small class="wpx-note" hidden data-bind-hidden="!refreshing.value">Updating…</small></div>
135
145
  <div class="wpx-bar-row">
@@ -236,6 +246,10 @@
236
246
  .wpx-chip.is-chosen { box-shadow: inset 0 0 0 1px var(--dm-primary); }
237
247
  .wpx-kebab { border: 0; background: none; cursor: pointer; font-size: var(--dm-text-lg); color: var(--dm-text-muted); border-radius: var(--dm-radius-sm); padding: 0 .3rem; }
238
248
  .wpx-kebab:hover { color: var(--dm-primary); }
249
+ .wpx-type-ctl { display: flex; flex-wrap: wrap; gap: .4rem .9rem; align-items: center; margin: .3rem 0 .15rem; cursor: default; }
250
+ .wpx-type-row .wpx-where { font-family: inherit; font-size: var(--dm-text-sm); }
251
+ .wpx-internal-box summary { cursor: pointer; color: var(--dm-text-muted); font-size: var(--dm-text-sm); }
252
+ .wpx-internal { padding-left: 1.1rem; margin: .4rem 0 0; display: flex; flex-direction: column; gap: .25rem; }
239
253
  .wpx-report { display: flex; flex-direction: column; gap: .75rem; padding: .25rem 0; }
240
254
  @media (max-width: 720px) { .wpx-toggles { grid-template-columns: 1fr; } .wpx-row { flex-wrap: wrap; } .wpx-chips { justify-content: flex-start; } }
241
255
  </style>
@@ -1,9 +1,9 @@
1
- import{apiRequest as q,getToken as ea}from"../api.js";import{addBannerAction as ta}from"../lib/plugin-chrome.js";import{helpPopovers as We}from"../lib/help-popover.js";import{onceClosed as aa,openMenuAt as X,sidebarCount as R,viewLifetime as oa}from"../lib/tool-kit.js";import{SHAPES as Ze,whileLoading as Ve}from"../lib/loading.js";import{fmtDateTime as sa}from"../lib/dates.js";import{applyChoice as na,choiceItems as ra,cleanOptions as ue,counts as Je,defaultOptions as Le,draftKey as ia,draftQuestion as la,historyRow as ca,isDirty as pa,kindTabs as da,liveDrafts as Ge,optionsSnapshot as Xe,PLAN_FILTERS as Ye,planMatches as Qe,planRow as ua,planTiles as et,productSummary as ma,progressPercent as fa,progressText as va,REPORT_FILTERS as tt,reportMatches as at,reportRow as ha,stagedRow as wa,withDraft as ot}from"../lib/wordpress-import-arrange.js";const st=/^#\/wordpress-import\/?(\?.*)?$/,Y="#/wordpress-import",$="/import/wordpress",me=400,ba=`
1
+ import{apiRequest as q,getToken as ua}from"../api.js";import{addBannerAction as ma}from"../lib/plugin-chrome.js";import{helpPopovers as Qe}from"../lib/help-popover.js";import{onceClosed as ha,openMenuAt as U,sidebarCount as C,viewLifetime as va}from"../lib/tool-kit.js";import{SHAPES as et,whileLoading as tt}from"../lib/loading.js";import{fmtDateTime as fa}from"../lib/dates.js";import{applyChoice as wa,choiceItems as ba,cleanOptions as he,counts as at,customTypeRows as ya,defaultOptions as Pe,draftKey as ga,draftQuestion as xa,historyRow as ka,internalTypeRows as Ma,isDirty as Ta,kindTabs as Ea,liveDrafts as st,optionsSnapshot as ot,PLAN_FILTERS as nt,planMatches as rt,planRow as $a,planTiles as it,productSummary as La,progressPercent as Sa,progressText as qa,REPORT_FILTERS as lt,reportMatches as ct,reportRow as Ca,stagedRow as Pa,typeMenuItems as Ra,withDraft as pt,withListPage as Aa,withTypeChoice as Ia}from"../lib/wordpress-import-arrange.js";const dt=/^#\/wordpress-import\/?(\?.*)?$/,ee="#/wordpress-import",$="/import/wordpress",ve=400,Da=`
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>`,nt=`
6
+ </div>`,ut=`
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,35 @@ import{apiRequest as q,getToken as ea}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>`,rt=`
17
+ </div>`,mt=`
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>`,ga=`
22
+ </div>`,Oa=`
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>`,it='<div class="wpx-tile"><strong>{{value}}</strong><small>{{label}} <span data-bind-hidden="!sub">{{sub}}</span></small></div>',lt='<p class="wpx-alert"><span>{{text}}</span></p>',ya="<li>{{text}}</li>",xa='<div class="wpx-fact"><dt>{{label}}</dt><dd>{{value}}</dd></div>',qe='<button type="button" data-on-click="$root.pickSeg($data)" data-bind-class="cls">{{label}} <b>{{count}}</b></button>',x=oa(st);function ct(l,n,i){return new Promise((w,y)=>{const p=new XMLHttpRequest,L=new FormData;L.append("file",n),p.open("POST",`/api${l}`);const v=ea();v&&p.setRequestHeader("Authorization",`Bearer ${v}`),p.upload.onprogress=c=>{c.lengthComputable&&i(c.loaded/c.total)},p.onload=()=>{let c=null;try{c=JSON.parse(p.responseText)}catch{}p.status>=200&&p.status<300?w(c):y(new Error(c?.error||`The upload failed (${p.status}).`))},p.onerror=()=>y(new Error("The upload failed - the connection dropped.")),p.send(L),x.add(()=>{p.readyState!==4&&p.abort()})})}const fe=l=>l>=1048576?`${Math.round(l/1048576)} MB`:`${Math.max(1,Math.round(l/1024))} KB`,N=l=>String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function ka(l){const n=document.createElement("template");return n.innerHTML=l.trim(),n.content.firstElementChild}async function ve(l,n){const i=E.confirm(l,n);let w=null;try{w=[...document.querySelectorAll(".dm-dialog-overlay")].at(-1)??null}catch{}const y=x.add(()=>{if(!w)return;const p=w;w=null;try{p.querySelector(".dm-dialog-cancel")?.click(),p.remove()}catch{}});try{return await i}finally{w=null,y()}}function pt(l){navigator.clipboard?.writeText(l).then(()=>E.toast("Copied.",{type:"success"}),()=>E.toast(l,{type:"info",duration:8e3}))}function he(l,n,i,w){const y=E.contextMenu(l,{cursor:"glyph",match:n,inherit:!1,density:"compact",items:i});x.add(()=>y?.destroy?.());const p=v=>{const c=v.target.closest(n);if(!c||!l.contains(c))return;const d=v.target.closest(".wpx-kebab");if(d){X(d);return}w?.(c)},L=v=>{const c=v.target.closest(n);c&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),X(c)):v.key==="Enter"&&v.target===c&&w&&(v.preventDefault(),v.stopPropagation(),w(c)))};l.addEventListener("click",p),l.addEventListener("keydown",L),x.add(()=>{l.removeEventListener("click",p),l.removeEventListener("keydown",L)})}export const wordpressImportView={templateUrl:"/admin/js/templates/wordpress-import.html",async onMount(l){x.reset();const n=l.get(0).querySelector(".wpx")||l.get(0),i=()=>st.test(location.hash)&&n.isConnected;let w="";try{w=S.get("auth_user")?.id||""}catch{}const y=ia(w),p=()=>{try{return y?S.get(y):null}catch{return null}},L=e=>{try{y&&S.set(y,e)}catch{}},v=n.querySelector(".wpx-loading");let c;try{c=await Ve(v,q(`${$}/status`),Ze.rows)}catch(e){if(!n.isConnected)return;v&&(v.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(!i())return;v&&(v.hidden=!0),n.querySelector(".wpx-body").hidden=!1;const d=M.observable(c.staged||[]),A=M.observable(c.history||[]),H=M.observable(c.blog||{available:!1}),Ce=M.observable(c.shop||{available:!1}),_=c.limits||{},b=M.observable(c.running||null),u=M.observable(""),g=M.observable(null),Q=M.observable(!1),we=M.observable(!1),be=M.observable(""),h=M.observable(Le(H.peek().available)),z=M.observable("all"),P=M.observable(""),ee=M.observable(""),te=M.observable(""),j=M.observable(""),ae=M.observable(""),oe=M.observable(!1);let se=!0;const Ma=()=>d.peek().find(e=>e.id===u.peek())||null,ge=M.computed(()=>d.value.find(e=>e.id===u.value)||null),dt=M.computed(()=>u.value?"preview":"start"),C=M.computed(()=>!!H.value.available),ut=M.computed(()=>!!(g.value?.shop||Ce.value).available),Re=M.computed(()=>!!u.value&&pa(h.value,C.value)),B=e=>M.computed({read:()=>h.value[e]!==!1,write:t=>{h.value={...h.peek(),[e]:!!t}}}),D=e=>{h.value={...h.peek(),...e}},F=e=>{try{return sa(e)}catch{return e}},mt=M.computed(()=>d.value.map(e=>wa(e,F))),ft=M.computed(()=>A.value.map(e=>ca(e,F))),K=M.computed(()=>(g.value?.items||[]).map(e=>({...e,choice:h.value.choices?.[e.key]}))),vt=M.computed(()=>da(K.value).map(e=>({...e,cls:P.value===e.id?"is-on":"",seg:"kind"}))),ht=M.computed(()=>Je(K.value,Ye,Qe,P.value)),wt=M.computed(()=>Ye.map(e=>({...e,count:ht.value[e.id],cls:z.value===e.id?"is-on":"",seg:"filter"}))),ye=M.computed(()=>{const e=ee.value.trim().toLowerCase();return K.value.filter(t=>(!P.value||t.kind===P.value)&&Qe(t,z.value)&&(!e||`${t.title} ${t.target} ${t.oldUrl}`.toLowerCase().includes(e)))}),bt=M.computed(()=>ye.value.slice(0,me).map(e=>{const t=ua(e);return{...t,pillCls:`${t.pillClass}${e.choice?" is-chosen":""}`}})),gt=M.computed(()=>ye.value.length>me?`Showing the first ${me} of ${ye.value.length} - search or filter to find the rest.`:""),yt=M.computed(()=>K.value.length?"Nothing matches.":"This export has nothing to import."),xt=M.computed(()=>et(g.value)),kt=M.computed(()=>(g.value?.notes||[]).map(e=>({text:e}))),Mt=M.computed(()=>(g.value?.redirects||[]).slice(0,me).map(e=>({...e,pill:e.action==="skip"?"Skipped":e.action==="update"?"Update":"New",pillClass:e.action==="skip"?"is-muted":"is-ok"}))),Tt=M.computed(()=>String((g.value?.redirects||[]).filter(e=>e.action!=="skip").length)),Et=M.computed(()=>g.value?.site?.title||ge.value?.siteTitle||"WordPress export"),$t=M.computed(()=>{const e=ge.value,t=g.value?.site;return[t?.url||e?.siteUrl,e?.fileName,t?.wxrVersion&&`WXR ${t.wxrVersion}`,e?.at&&`uploaded ${F(e.at)}`].filter(Boolean).join(" \xB7 ")}),W=M.computed(()=>ma(g.value)),St=M.computed(()=>W.value?.note||""),Lt=M.computed(()=>W.value?.tone==="warn"?"is-warn":"is-info"),qt=M.computed(()=>(W.value?.rows||[]).map(e=>({...e,id:e.label}))),Ct=M.computed(()=>(W.value?.notes||[]).map(e=>({text:e}))),Rt=M.computed(()=>!!W.value),Pt=M.computed(()=>C.value?`Posts go to ${H.value.basePath||"/blog"}.`:H.value.reason||"No Blog is switched on here."),ne=M.computed(()=>ge.value?.uploads||null),At=M.computed(()=>{const e=ne.value;return e?`${e.fileName} - ${e.files} file${e.files===1?"":"s"}, ${fe(e.size)}${e.unsafe?`. ${e.unsafe} with unsafe names (like ../) were ignored`:""}.`:`Zip the wp-content/uploads folder and upload it here (up to ${fe(_.uploads||0)}).`}),It=M.computed(()=>ne.value?"Replace the zip":"Upload the uploads zip"),Pe=M.computed(()=>!!g.value&&!b.value&&!Q.value&&!(h.value.media==="zip"&&!ne.value)),Dt=M.computed(()=>b.value?`Importing${b.value.siteTitle?` ${b.value.siteTitle}`:""}\u2026`:""),Ot=M.computed(()=>va(b.value)),Ae=M.computed(()=>fa(b.value)),Ut=M.observable(fe(_.wxr||0)),Ie=n.querySelector(".wpx-running .wpx-bar-fill");x.add(M.effect(()=>{Ie&&(Ie.style.width=`${Ae.value}%`)}));async function xe(){const e=await q(`${$}/status`);return i()?(d.value=e.staged||[],A.value=e.history||[],H.value=e.blog||{available:!1},Ce.value=e.shop||{available:!1},e.running&&!b.peek()&&(b.value=e.running,V()),e):null}let re=0,ke=null;async function ie({first:e=!1}={}){const t=u.peek();if(!t)return;const a=++re;be.value="";const s=q(`${$}/staged/${t}/preview`,{method:"POST",body:JSON.stringify({options:ue(h.peek(),C.peek())})});try{let f;if(e?(Q.value=!0,f=await Ve(n.querySelector(".wpx-plan-loading"),s,Ze.table)):(we.value=!0,f=await s),a!==re||!i()||u.peek()!==t)return;g.value=f.plan}catch(f){if(a!==re||!i())return;if(f.status===404){E.toast("That upload has gone - upload the export again.",{type:"warning"}),Z(),xe().catch(()=>{});return}be.value=`Could not read the export: ${f.message||f}`}finally{a===re&&(Q.value=!1,we.value=!1)}}let le="";x.add(M.effect(()=>{const e=`${u.value}|${Xe(h.value)}`;if(e===le)return;const t=le.split("|")[0];le=e,!(!u.value||t!==u.value)&&(clearTimeout(ke),ke=setTimeout(()=>ie(),250))})),x.add(()=>clearTimeout(ke)),x.add(M.effect(()=>{const e=u.value,t=h.value,a=Re.value;if(!e||!se||!y)return;const s=p();L(ot(s,w,e,a?{options:ue(t,!0),at:new Date().toISOString(),was:e}:null))}));const Me=e=>{y&&L(ot(p(),w,e,null))};async function ce(e){if(!d.peek().some(m=>m.id===e))return;const t=d.peek().find(m=>m.id===e),a=Ge(p(),d.peek().map(m=>m.id),w).items[e];if(se=!a,g.value=null,z.value="all",P.value="",ee.value="",h.value=Le(C.peek()),le=`${e}|${Xe(h.peek())}`,u.value=e,await ie({first:!0}),!i()||u.peek()!==e||!a)return;await new Promise(m=>setTimeout(m,0));const s=la({when:a.at?F(a.at):"",file:t?.fileName||""}),f=await ve(N(s.text),{title:s.title,confirmText:s.confirmText,cancelText:s.cancelText});!i()||u.peek()!==e||(se=!0,f?Me(e):h.value=ue(a.options,C.peek()))}function Z(){u.value="",g.value=null,se=!0}async function De(e=u.peek()){const t=d.peek().find(a=>a.id===e);if(t&&await ve(`Discard the upload of <strong>${N(t.siteTitle||t.fileName)}</strong>? Nothing has been imported from it.`,{title:"Discard upload",confirmText:"Discard",danger:!0}))try{if(await q(`${$}/staged/${e}`,{method:"DELETE"}),Me(e),!i())return;u.peek()===e&&Z(),d.value=d.peek().filter(a=>a.id!==e),R(Y)}catch(a){E.toast(`Not discarded: ${a.message||a}`,{type:"error"})}}async function Oe(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(_.wxr&&e.size>_.wxr*1.2&&/\.xml$/i.test(e.name)){j.value=`That file is over ${fe(_.wxr)}.`;return}const t=n.querySelector(".wpx-start .wpx-upload .wpx-bar-fill");te.value=`Uploading ${e.name}\u2026`;try{const a=await ct(`${$}/upload`,e,s=>{t&&(t.style.width=`${Math.round(s*100)}%`),te.value=s<1?`Uploading ${e.name} - ${Math.round(s*100)}%`:`Reading ${e.name}\u2026`});if(!i())return;d.value=[a,...d.peek().filter(s=>s.id!==a.id)],R(Y),await ce(a.id)}catch(a){i()&&(j.value=a.message||String(a))}finally{i()&&(te.value="",t&&(t.style.width="0"))}}async function Nt(e){const t=u.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");ae.value=`Uploading ${e.name}\u2026`;try{const s=await ct(`${$}/staged/${t}/uploads`,e,f=>{a&&(a.style.width=`${Math.round(f*100)}%`),ae.value=f<1?`Uploading ${e.name} - ${Math.round(f*100)}%`:`Checking ${e.name}\u2026`});if(!i())return;d.value=d.peek().map(f=>f.id===s.id?s:f),u.peek()===t&&ie()}catch(s){i()&&E.toast(s.message||String(s),{type:"error"})}finally{i()&&(ae.value="",a&&(a.style.width="0"))}}async function Ht(){const e=u.peek();try{const t=await q(`${$}/staged/${e}/uploads`,{method:"DELETE"});if(!i())return;d.value=d.peek().map(a=>a.id===t.id?t:a),ie()}catch(t){E.toast(`Not removed: ${t.message||t}`,{type:"error"})}}async function _t(){const e=u.peek(),t=g.peek();if(!e||!t||!Pe.peek())return;const s=et(t).filter(m=>m.value&&m.id!=="comments").map(m=>`${m.value} ${m.label.toLowerCase()}`);if(!(!await ve(`Import <strong>${N(t.site?.title||"this export")}</strong>: ${N(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()||u.peek()!==e))try{const m=await q(`${$}/staged/${e}/run`,{method:"POST",body:JSON.stringify({options:ue(h.peek(),C.peek())})});if(Me(e),!i())return;b.value={...m.job,siteTitle:t.site?.title||""},Z(),R(Y),V()}catch(m){E.toast(`The import did not start: ${m.message||m}`,{type:"error"})}}let Te=null;function V(){clearTimeout(Te);const e=b.peek();e&&(Te=setTimeout(async()=>{try{const t=await q(`${$}/jobs/${e.id}`);if(!i())return;if(b.value={...t.job,siteTitle:e.siteTitle},t.job.status==="running")return V();if(b.value=null,await xe().catch(()=>{}),R(Y),R("#/pages"),R("#/media"),R("#/plugins/shopping-cart"),!i())return;t.job.status==="done"?(E.toast("The import has finished - here is its report.",{type:"success"}),pe(t.job.reportId)):(E.toast(`The import stopped: ${t.job.error||"an error"}`,{type:"error"}),t.job.reportId&&pe(t.job.reportId))}catch(t){if(!i())return;if(t.status===404){b.value=null,xe().catch(()=>{});return}V()}},700))}x.add(()=>clearTimeout(Te)),b.peek()&&V();let O=!1;async function pe(e){if(O||!e)return;O=!0;let t;try{t=await q(`${$}/history/${e}`)}catch(o){O=!1,E.toast(`Could not open the report: ${o.message||o}`,{type:"error"});return}if(!i()){O=!1;return}let a;try{a=E.slideover({title:N(`Report - ${t.run?.siteTitle||"WordPress import"}`),size:"lg",position:"right"})}catch(o){throw O=!1,o}const s=ka(`
27
+ </div>`,Ha=`
28
+ <div class="wpx-row wpx-type-row" data-type="{{type}}" tabindex="0">
29
+ <span class="wpx-main">
30
+ <strong>{{label}}</strong>
31
+ <small>{{meta}}</small>
32
+ <span class="wpx-reason" data-bind-hidden="!samples">{{samples}}</span>
33
+ <span class="wpx-type-ctl">
34
+ <span class="wpx-seg" role="group" aria-label="Import {{label}} as">
35
+ <button type="button" data-as="collection" data-bind-class="segCollection">Collection</button>
36
+ <button type="button" data-as="pages" data-bind-class="segPages">Pages</button>
37
+ <button type="button" data-as="skip" data-bind-class="segSkip">Skip</button>
38
+ </span>
39
+ <label class="wpx-toggle" data-bind-hidden="!canList"><input type="checkbox" class="form-switch" data-list-page data-bind-checked="listOn"> {{listLabel}}</label>
40
+ </span>
41
+ <span class="wpx-where">{{creates}}</span>
42
+ </span>
43
+ <span class="wpx-chips"><span class="wpx-chip" data-bind-class="pillClass">{{pill}}</span></span>
44
+ <button type="button" class="wpx-kebab" aria-label="Actions for {{label}}" title="Actions">\u22EE</button>
45
+ </div>`,ht='<div class="wpx-tile"><strong>{{value}}</strong><small>{{label}} <span data-bind-hidden="!sub">{{sub}}</span></small></div>',vt='<p class="wpx-alert"><span>{{text}}</span></p>',ft="<li>{{text}}</li>",Na='<div class="wpx-fact"><dt>{{label}}</dt><dd>{{value}}</dd></div>',Re='<button type="button" data-on-click="$root.pickSeg($data)" data-bind-class="cls">{{label}} <b>{{count}}</b></button>',g=va(dt);function wt(l,n,i){return new Promise((w,x)=>{const d=new XMLHttpRequest,L=new FormData;L.append("file",n),d.open("POST",`/api${l}`);const f=ua();f&&d.setRequestHeader("Authorization",`Bearer ${f}`),d.upload.onprogress=c=>{c.lengthComputable&&i(c.loaded/c.total)},d.onload=()=>{let c=null;try{c=JSON.parse(d.responseText)}catch{}d.status>=200&&d.status<300?w(c):x(new Error(c?.error||`The upload failed (${d.status}).`))},d.onerror=()=>x(new Error("The upload failed - the connection dropped.")),d.send(L),g.add(()=>{d.readyState!==4&&d.abort()})})}const fe=l=>l>=1048576?`${Math.round(l/1048576)} MB`:`${Math.max(1,Math.round(l/1024))} KB`,_=l=>String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function Ua(l){const n=document.createElement("template");return n.innerHTML=l.trim(),n.content.firstElementChild}async function we(l,n){const i=E.confirm(l,n);let w=null;try{w=[...document.querySelectorAll(".dm-dialog-overlay")].at(-1)??null}catch{}const x=g.add(()=>{if(!w)return;const d=w;w=null;try{d.querySelector(".dm-dialog-cancel")?.click(),d.remove()}catch{}});try{return await i}finally{w=null,x()}}function bt(l){navigator.clipboard?.writeText(l).then(()=>E.toast("Copied.",{type:"success"}),()=>E.toast(l,{type:"info",duration:8e3}))}function te(l,n,i,w){const x=E.contextMenu(l,{cursor:"glyph",match:n,inherit:!1,density:"compact",items:i});g.add(()=>x?.destroy?.());const d=f=>{const c=f.target.closest(n);if(!c||!l.contains(c))return;const u=f.target.closest(".wpx-kebab");if(u){U(u);return}w?.(c)},L=f=>{const c=f.target.closest(n);c&&(f.key==="F10"&&f.shiftKey?(f.preventDefault(),U(c)):f.key==="Enter"&&f.target===c&&w&&(f.preventDefault(),f.stopPropagation(),w(c)))};l.addEventListener("click",d),l.addEventListener("keydown",L),g.add(()=>{l.removeEventListener("click",d),l.removeEventListener("keydown",L)})}export const wordpressImportView={templateUrl:"/admin/js/templates/wordpress-import.html",async onMount(l){g.reset();const n=l.get(0).querySelector(".wpx")||l.get(0),i=()=>dt.test(location.hash)&&n.isConnected;let w="";try{w=S.get("auth_user")?.id||""}catch{}const x=ga(w),d=()=>{try{return x?S.get(x):null}catch{return null}},L=e=>{try{x&&S.set(x,e)}catch{}},f=n.querySelector(".wpx-loading");let c;try{c=await tt(f,q(`${$}/status`),et.rows)}catch(e){if(!n.isConnected)return;f&&(f.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(!i())return;f&&(f.hidden=!0),n.querySelector(".wpx-body").hidden=!1;const u=M.observable(c.staged||[]),A=M.observable(c.history||[]),z=M.observable(c.blog||{available:!1}),Ae=M.observable(c.shop||{available:!1}),B=c.limits||{},y=M.observable(c.running||null),m=M.observable(""),b=M.observable(null),ae=M.observable(!1),be=M.observable(!1),ye=M.observable(""),p=M.observable(Pe(z.peek().available)),D=M.observable("all"),P=M.observable(""),j=M.observable(""),se=M.observable(""),F=M.observable(""),oe=M.observable(""),ne=M.observable(!1);let re=!0;const _a=()=>u.peek().find(e=>e.id===m.peek())||null,ge=M.computed(()=>u.value.find(e=>e.id===m.value)||null),yt=M.computed(()=>m.value?"preview":"start"),R=M.computed(()=>!!z.value.available),gt=M.computed(()=>!!(b.value?.shop||Ae.value).available),Ie=M.computed(()=>!!m.value&&Ta(p.value,R.value)),K=e=>M.computed({read:()=>p.value[e]!==!1,write:t=>{p.value={...p.peek(),[e]:!!t}}}),O=e=>{p.value={...p.peek(),...e}},W=e=>{try{return fa(e)}catch{return e}},xt=M.computed(()=>u.value.map(e=>Pa(e,W))),kt=M.computed(()=>A.value.map(e=>ka(e,W))),Z=M.computed(()=>(b.value?.items||[]).map(e=>({...e,choice:p.value.choices?.[e.key]}))),Mt=M.computed(()=>Ea(Z.value).map(e=>({...e,cls:P.value===e.id?"is-on":"",seg:"kind"}))),Tt=M.computed(()=>at(Z.value,nt,rt,P.value)),Et=M.computed(()=>nt.map(e=>({...e,count:Tt.value[e.id],cls:D.value===e.id?"is-on":"",seg:"filter"}))),xe=M.computed(()=>{const e=j.value.trim().toLowerCase();return Z.value.filter(t=>(!P.value||t.kind===P.value)&&rt(t,D.value)&&(!e||`${t.title} ${t.target} ${t.oldUrl} ${t.postType||""}`.toLowerCase().includes(e)))}),$t=M.computed(()=>xe.value.slice(0,ve).map(e=>{const t=$a(e);return{...t,pillCls:`${t.pillClass}${e.choice?" is-chosen":""}`}})),Lt=M.computed(()=>xe.value.length>ve?`Showing the first ${ve} of ${xe.value.length} - search or filter to find the rest.`:""),St=M.computed(()=>Z.value.length?"Nothing matches.":"This export has nothing to import."),qt=M.computed(()=>it(b.value)),Ct=M.computed(()=>(b.value?.notes||[]).map(e=>({text:e}))),Pt=M.computed(()=>(b.value?.redirects||[]).slice(0,ve).map(e=>({...e,pill:e.action==="skip"?"Skipped":e.action==="update"?"Update":"New",pillClass:e.action==="skip"?"is-muted":"is-ok"}))),Rt=M.computed(()=>String((b.value?.redirects||[]).filter(e=>e.action!=="skip").length)),At=M.computed(()=>b.value?.site?.title||ge.value?.siteTitle||"WordPress export"),It=M.computed(()=>{const e=ge.value,t=b.value?.site;return[t?.url||e?.siteUrl,e?.fileName,t?.wxrVersion&&`WXR ${t.wxrVersion}`,e?.at&&`uploaded ${W(e.at)}`].filter(Boolean).join(" \xB7 ")}),V=M.computed(()=>La(b.value)),Dt=M.computed(()=>V.value?.note||""),Ot=M.computed(()=>V.value?.tone==="warn"?"is-warn":"is-info"),Ht=M.computed(()=>(V.value?.rows||[]).map(e=>({...e,id:e.label}))),Nt=M.computed(()=>(V.value?.notes||[]).map(e=>({text:e}))),Ut=M.computed(()=>!!V.value),ke=M.computed(()=>ya(b.value)),Me=M.computed(()=>Ma(b.value)),_t=M.computed(()=>!!(ke.value.length||Me.value.length)),zt=M.computed(()=>{const e=Me.value.length;return e?`Not imported: ${e} kind${e===1?"":"s"} of WordPress or plugin housekeeping`:""}),Bt=M.computed(()=>R.value?`Posts go to ${z.value.basePath||"/blog"}.`:z.value.reason||"No Blog is switched on here."),ie=M.computed(()=>ge.value?.uploads||null),jt=M.computed(()=>{const e=ie.value;return e?`${e.fileName} - ${e.files} file${e.files===1?"":"s"}, ${fe(e.size)}${e.unsafe?`. ${e.unsafe} with unsafe names (like ../) were ignored`:""}.`:`Zip the wp-content/uploads folder and upload it here (up to ${fe(B.uploads||0)}).`}),Ft=M.computed(()=>ie.value?"Replace the zip":"Upload the uploads zip"),De=M.computed(()=>!!b.value&&!y.value&&!ae.value&&!(p.value.media==="zip"&&!ie.value)),Kt=M.computed(()=>y.value?`Importing${y.value.siteTitle?` ${y.value.siteTitle}`:""}\u2026`:""),Wt=M.computed(()=>qa(y.value)),Oe=M.computed(()=>Sa(y.value)),Zt=M.observable(fe(B.wxr||0)),He=n.querySelector(".wpx-running .wpx-bar-fill");g.add(M.effect(()=>{He&&(He.style.width=`${Oe.value}%`)}));async function Te(){const e=await q(`${$}/status`);return i()?(u.value=e.staged||[],A.value=e.history||[],z.value=e.blog||{available:!1},Ae.value=e.shop||{available:!1},e.running&&!y.peek()&&(y.value=e.running,Y()),e):null}let le=0,Ee=null;async function ce({first:e=!1}={}){const t=m.peek();if(!t)return;const a=++le;ye.value="";const o=q(`${$}/staged/${t}/preview`,{method:"POST",body:JSON.stringify({options:he(p.peek(),R.peek())})});try{let v;if(e?(ae.value=!0,v=await tt(n.querySelector(".wpx-plan-loading"),o,et.table)):(be.value=!0,v=await o),a!==le||!i()||m.peek()!==t)return;b.value=v.plan}catch(v){if(a!==le||!i())return;if(v.status===404){E.toast("That upload has gone - upload the export again.",{type:"warning"}),J(),Te().catch(()=>{});return}ye.value=`Could not read the export: ${v.message||v}`}finally{a===le&&(ae.value=!1,be.value=!1)}}let pe="";g.add(M.effect(()=>{const e=`${m.value}|${ot(p.value)}`;if(e===pe)return;const t=pe.split("|")[0];pe=e,!(!m.value||t!==m.value)&&(clearTimeout(Ee),Ee=setTimeout(()=>ce(),250))})),g.add(()=>clearTimeout(Ee)),g.add(M.effect(()=>{const e=m.value,t=p.value,a=Ie.value;if(!e||!re||!x)return;const o=d();L(pt(o,w,e,a?{options:he(t,!0),at:new Date().toISOString(),was:e}:null))}));const $e=e=>{x&&L(pt(d(),w,e,null))};async function de(e){if(!u.peek().some(h=>h.id===e))return;const t=u.peek().find(h=>h.id===e),a=st(d(),u.peek().map(h=>h.id),w).items[e];if(re=!a,b.value=null,D.value="all",P.value="",j.value="",p.value=Pe(R.peek()),pe=`${e}|${ot(p.peek())}`,m.value=e,await ce({first:!0}),!i()||m.peek()!==e||!a)return;await new Promise(h=>setTimeout(h,0));const o=xa({when:a.at?W(a.at):"",file:t?.fileName||""}),v=await we(_(o.text),{title:o.title,confirmText:o.confirmText,cancelText:o.cancelText});!i()||m.peek()!==e||(re=!0,v?$e(e):p.value=he(a.options,R.peek()))}function J(){m.value="",b.value=null,re=!0}async function Ne(e=m.peek()){const t=u.peek().find(a=>a.id===e);if(t&&await we(`Discard the upload of <strong>${_(t.siteTitle||t.fileName)}</strong>? Nothing has been imported from it.`,{title:"Discard upload",confirmText:"Discard",danger:!0}))try{if(await q(`${$}/staged/${e}`,{method:"DELETE"}),$e(e),!i())return;m.peek()===e&&J(),u.value=u.peek().filter(a=>a.id!==e),C(ee)}catch(a){E.toast(`Not discarded: ${a.message||a}`,{type:"error"})}}async function Ue(e){if(!e)return;if(F.value="",!/\.(xml|zip)$/i.test(e.name)){F.value="Upload the .xml file WordPress exports, or a .zip holding it.";return}if(B.wxr&&e.size>B.wxr*1.2&&/\.xml$/i.test(e.name)){F.value=`That file is over ${fe(B.wxr)}.`;return}const t=n.querySelector(".wpx-start .wpx-upload .wpx-bar-fill");se.value=`Uploading ${e.name}\u2026`;try{const a=await wt(`${$}/upload`,e,o=>{t&&(t.style.width=`${Math.round(o*100)}%`),se.value=o<1?`Uploading ${e.name} - ${Math.round(o*100)}%`:`Reading ${e.name}\u2026`});if(!i())return;u.value=[a,...u.peek().filter(o=>o.id!==a.id)],C(ee),await de(a.id)}catch(a){i()&&(F.value=a.message||String(a))}finally{i()&&(se.value="",t&&(t.style.width="0"))}}async function Vt(e){const t=m.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");oe.value=`Uploading ${e.name}\u2026`;try{const o=await wt(`${$}/staged/${t}/uploads`,e,v=>{a&&(a.style.width=`${Math.round(v*100)}%`),oe.value=v<1?`Uploading ${e.name} - ${Math.round(v*100)}%`:`Checking ${e.name}\u2026`});if(!i())return;u.value=u.peek().map(v=>v.id===o.id?o:v),m.peek()===t&&ce()}catch(o){i()&&E.toast(o.message||String(o),{type:"error"})}finally{i()&&(oe.value="",a&&(a.style.width="0"))}}async function Jt(){const e=m.peek();try{const t=await q(`${$}/staged/${e}/uploads`,{method:"DELETE"});if(!i())return;u.value=u.peek().map(a=>a.id===t.id?t:a),ce()}catch(t){E.toast(`Not removed: ${t.message||t}`,{type:"error"})}}async function Yt(){const e=m.peek(),t=b.peek();if(!e||!t||!De.peek())return;const o=it(t).filter(h=>h.value&&h.id!=="comments").map(h=>`${h.value} ${h.label.toLowerCase()}`);if(!(!await we(`Import <strong>${_(t.site?.title||"this export")}</strong>: ${_(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"})||!i()||m.peek()!==e))try{const h=await q(`${$}/staged/${e}/run`,{method:"POST",body:JSON.stringify({options:he(p.peek(),R.peek())})});if($e(e),!i())return;y.value={...h.job,siteTitle:t.site?.title||""},J(),C(ee),Y()}catch(h){E.toast(`The import did not start: ${h.message||h}`,{type:"error"})}}let Le=null;function Y(){clearTimeout(Le);const e=y.peek();e&&(Le=setTimeout(async()=>{try{const t=await q(`${$}/jobs/${e.id}`);if(!i())return;if(y.value={...t.job,siteTitle:e.siteTitle},t.job.status==="running")return Y();if(y.value=null,await Te().catch(()=>{}),C(ee),C("#/pages"),C("#/media"),C("#/plugins/shopping-cart"),C("#/collections"),!i())return;t.job.status==="done"?(E.toast("The import has finished - here is its report.",{type:"success"}),ue(t.job.reportId)):(E.toast(`The import stopped: ${t.job.error||"an error"}`,{type:"error"}),t.job.reportId&&ue(t.job.reportId))}catch(t){if(!i())return;if(t.status===404){y.value=null,Te().catch(()=>{});return}Y()}},700))}g.add(()=>clearTimeout(Le)),y.peek()&&Y();let H=!1;async function ue(e){if(H||!e)return;H=!0;let t;try{t=await q(`${$}/history/${e}`)}catch(s){H=!1,E.toast(`Could not open the report: ${s.message||s}`,{type:"error"});return}if(!i()){H=!1;return}let a;try{a=E.slideover({title:_(`Report - ${t.run?.siteTitle||"WordPress import"}`),size:"lg",position:"right"})}catch(s){throw H=!1,s}const o=Ua(`
28
46
  <div class="wpx wpx-report">
29
47
  <p class="wpx-note" data-bind-text="meta.value"></p>
30
48
  <div class="wpx-tiles" data-each="tiles.value key=id"></div>
@@ -35,4 +53,4 @@ import{apiRequest as q,getToken as ea}from"../api.js";import{addBannerAction as
35
53
  <div class="wpx-list wpx-report-items" data-each="rows.value key=key"></div>
36
54
  <div class="wpx-card-title" data-bind-hidden="!redirects.value.length">Redirects</div>
37
55
  <div class="wpx-list wpx-report-redirects" data-each="redirects.value key=from"></div>
38
- </div>`);s.querySelector(".wpx-tiles").innerHTML=it,s.querySelector(".wpx-note-list").innerHTML=lt,s.querySelector(".wpx-seg").innerHTML=qe,s.querySelector(".wpx-report-items").innerHTML=nt,s.querySelector(".wpx-report-redirects").innerHTML=rt;const f=M.observable(t.run?.summary?.failed?"failed":"all"),m=t.items||[],Be=Je(m,tt,at),G=t.run?.summary||{},$e=o=>Object.values(G.kinds||{}).reduce((r,k)=>r+(k[o]||0),0),Kt={meta:M.observable([F(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:$e("created"),sub:""},{id:"updated",label:"Updated",value:$e("updated"),sub:""},{id:"kept",label:"Left as is",value:$e("kept"),sub:""},{id:"redirects",label:"Redirects",value:(G.redirects?.created||0)+(G.redirects?.updated||0),sub:""},{id:"comments",label:"Comments",value:G.comments||0,sub:""},{id:"failed",label:"Failed",value:G.failed||0,sub:""}]),notes:M.observable((t.notes||[]).map(o=>({text:o}))),filters:M.computed(()=>tt.filter(o=>o.id==="all"||Be[o.id]).map(o=>({...o,count:Be[o.id],cls:f.value===o.id?"is-on":""}))),rows:M.computed(()=>m.filter(o=>at(o,f.value)).slice(0,1e3).map(o=>{const r=ha(o);return{...r,pillCls:r.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 Wt=M.applyBindings(Kt,s,{methods:{pickSeg:o=>{f.value=o.id}}}),Zt=We(s),Fe=new Map(m.map(o=>[o.key,o])),Vt=s.querySelector(".wpx-report-items"),Jt=o=>{const r=Fe.get(o.dataset.key);if(!r)return[];const k=typeof r.target=="string"&&r.target.startsWith("/")?r.target:"",T=[{header:r.title}];return k&&r.result!=="failed"&&r.result!=="skipped"&&T.push({label:"Open on the site",icon:"external-link",action:()=>window.open(k,"_blank","noopener")}),k&&r.kind==="page"&&(r.result==="created"||r.result==="updated"||r.result==="kept")&&T.push({label:"Edit the page",icon:"edit",action:()=>{a.close(),location.hash=`#/pages/edit${k}`}}),r.kind==="product"&&r.entryId&&/^[\w-]{1,64}$/.test(r.entryId)&&T.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)&&T.push({label:"Open the old address",icon:"link",action:()=>window.open(r.oldUrl,"_blank","noopener,noreferrer")}),k&&T.push({label:"Copy the new address",icon:"copy",action:()=>pt(new URL(k,location.origin).href)}),T},Gt=E.contextMenu(Vt,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:Jt}),Xt=s.querySelector(".wpx-report-redirects"),Yt=E.contextMenu(Xt,{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"}}]}),Se=o=>{const r=o.target.closest(".wpx-kebab");if(r){X(r);return}const k=o.target.closest(".wpx-report-items .wpx-row");if(!k)return;const T=Fe.get(k.dataset.key);T?.target?.startsWith("/")&&T.result!=="failed"&&T.result!=="skipped"&&window.open(T.target,"_blank","noopener")},Ke=o=>{const r=o.target.closest(".wpx-row");r&&(o.key==="F10"&&o.shiftKey?(o.preventDefault(),X(r)):o.key==="Enter"&&o.target===r&&(o.preventDefault(),o.stopPropagation(),Se({target:r})))};s.addEventListener("click",Se),s.addEventListener("keydown",Ke);const Qt=x.add(()=>a.close());aa(a,()=>{O=!1,Wt.dispose(),Zt(),Gt?.destroy?.(),Yt?.destroy?.(),s.removeEventListener("click",Se),s.removeEventListener("keydown",Ke),Qt()}),a.open(),I.scan(s)}async function zt(e){const t=A.peek().find(a=>a.id===e);if(t&&await ve(`Remove the import of <strong>${N(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 q(`${$}/history/${e}`,{method:"DELETE"}),!i())return;A.value=A.peek().filter(a=>a.id!==e),R(Y)}catch(a){E.toast(`Not removed: ${a.message||a}`,{type:"error"})}}n.querySelector(".wpx-staged").innerHTML=ba,n.querySelector(".wpx-items").innerHTML=nt,n.querySelector(".wpx-redirects").innerHTML=rt,n.querySelector(".wpx-history").innerHTML=ga,n.querySelector(".wpx-tiles").innerHTML=it,n.querySelector(".wpx-note-list").innerHTML=lt,n.querySelector(".wpx-kinds").innerHTML=qe,n.querySelector(".wpx-filters").innerHTML=qe,n.querySelector(".wpx-facts").innerHTML=xa,n.querySelector(".wpx-product-notes").innerHTML=ya;const jt={mode:dt,job:b,jobTitle:Dt,jobText:Ot,jobPct:Ae,staged:d,stagedRows:mt,historyRows:ft,plan:g,planLoading:Q,planError:be,refreshing:we,opt:h,blogAvailable:C,blogNote:Pt,dirty:Re,canRun:Pe,siteTitle:Et,siteMeta:$t,tiles:xt,notes:kt,kinds:vt,filters:wt,rows:bt,moreText:gt,emptyText:yt,redirectRows:Mt,redirectCount:Tt,query:ee,uploadText:te,uploadError:j,dropping:oe,wxrLimit:Ut,zipInfo:ne,zipText:At,zipButton:It,zipUploadText:ae,shopAvailable:ut,hasProducts:Rt,productNote:St,productNoteCls:Lt,productFacts:qt,productNotes:Ct,optComments:B("comments"),optMenus:B("menus"),optRedirects:B("redirects"),optDrafts:B("drafts"),optProducts:B("products")},Bt=M.applyBindings(jt,n,{methods:{back:()=>Z(),discard:()=>De(),run:()=>_t(),resetChoices:()=>{h.value=Le(C.peek())},postsBlog:()=>D({posts:"blog"}),postsPages:()=>D({posts:"pages"}),postsSkip:()=>D({posts:"skip"}),mediaDownload:()=>D({media:"download"}),mediaZip:()=>D({media:"zip"}),mediaSkip:()=>D({media:"skip"}),removeZip:()=>Ht(),pickSeg:e=>{e.seg==="kind"?P.value=e.id:z.value=e.id},showProducts:()=>{P.value="product",z.value="all",ee.value="",n.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})}}});x.add(()=>Bt.dispose()),x.add(We(n,{position:"bottom"}));const J=n.querySelector(".wpx-file"),Ue=()=>{const e=J.files?.[0];J.value="",Oe(e)};J.addEventListener("change",Ue);const U=n.querySelector(".wpx-drop"),Ne=e=>{e.preventDefault(),oe.value=!0},He=()=>{oe.value=!1},_e=e=>{e.preventDefault(),oe.value=!1,Oe(e.dataTransfer?.files?.[0])};U.addEventListener("dragover",Ne),U.addEventListener("dragleave",He),U.addEventListener("drop",_e);const de=n.querySelector(".wpx-zip-file"),ze=()=>{const e=de.files?.[0];de.value="",Nt(e)};de.addEventListener("change",ze),x.add(()=>{J.removeEventListener("change",Ue),U.removeEventListener("dragover",Ne),U.removeEventListener("dragleave",He),U.removeEventListener("drop",_e),de.removeEventListener("change",ze)}),he(n.querySelector(".wpx-staged"),".wpx-row",e=>[{header:d.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Upload"},{label:"Preview the import",icon:"eye",action:()=>ce(e.dataset.id)},{label:"Discard the upload",icon:"trash-2",action:()=>De(e.dataset.id)}],e=>ce(e.dataset.id));const Ft=(e,t)=>{h.value={...h.peek(),choices:na(h.peek().choices,e,t)}};he(n.querySelector(".wpx-items"),".wpx-row",e=>{const t=K.peek().find(s=>s.key===e.dataset.key);if(!t)return[];const a=[{header:t.title}];for(const s of ra(t,t.choice))a.push({label:s.label,icon:s.icon,action:()=>Ft(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=>X(e.querySelector(".wpx-kebab")||e)),he(n.querySelector(".wpx-redirects"),".wpx-row",e=>[{header:e.dataset.from},{label:"Copy the old address",icon:"copy",action:()=>pt(e.dataset.from)}],null),he(n.querySelector(".wpx-history"),".wpx-row",e=>[{header:A.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Import"},{label:"Open the report",icon:"file-text",action:()=>pe(e.dataset.id)},{label:"Remove from the history",icon:"trash-2",action:()=>zt(e.dataset.id)}],e=>pe(e.dataset.id)),ta(l,{id:"wpx-upload",icon:"upload",title:"Upload an export",onClick:()=>{u.peek()&&Z(),setTimeout(()=>J.click(),0)}}),I.scan(n);const Ee=Ge(p(),d.peek().map(e=>e.id),w);Ee.pruned&&y&&L({owner:w,items:Ee.items});const je=Object.entries(Ee.items).sort((e,t)=>String(t[1].at).localeCompare(String(e[1].at)))[0];je&&!b.peek()&&await ce(je[0])}};
56
+ </div>`);o.querySelector(".wpx-tiles").innerHTML=ht,o.querySelector(".wpx-note-list").innerHTML=vt,o.querySelector(".wpx-seg").innerHTML=Re,o.querySelector(".wpx-report-items").innerHTML=ut,o.querySelector(".wpx-report-redirects").innerHTML=mt;const v=M.observable(t.run?.summary?.failed?"failed":"all"),h=t.items||[],Ye=at(h,lt,ct),Q=t.run?.summary||{},qe=s=>Object.values(Q.kinds||{}).reduce((r,T)=>r+(T[s]||0),0),aa={meta:M.observable([W(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:qe("created"),sub:""},{id:"updated",label:"Updated",value:qe("updated"),sub:""},{id:"kept",label:"Left as is",value:qe("kept"),sub:""},{id:"redirects",label:"Redirects",value:(Q.redirects?.created||0)+(Q.redirects?.updated||0),sub:""},{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}))),filters:M.computed(()=>lt.filter(s=>s.id==="all"||Ye[s.id]).map(s=>({...s,count:Ye[s.id],cls:v.value===s.id?"is-on":""}))),rows:M.computed(()=>h.filter(s=>ct(s,v.value)).slice(0,1e3).map(s=>{const r=Ca(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 sa=M.applyBindings(aa,o,{methods:{pickSeg:s=>{v.value=s.id}}}),oa=Qe(o),Ge=new Map(h.map(s=>[s.key,s])),na=o.querySelector(".wpx-report-items"),ra=s=>{const r=Ge.get(s.dataset.key);if(!r)return[];const T=typeof r.target=="string"&&r.target.startsWith("/")?r.target:"",k=[{header:r.title}];if(T&&r.result!=="failed"&&r.result!=="skipped"&&k.push({label:"Open on the site",icon:"external-link",action:()=>window.open(T,"_blank","noopener")}),T&&(r.kind==="page"||r.kind==="custom"&&!r.collection)&&(r.result==="created"||r.result==="updated"||r.result==="kept")&&k.push({label:"Edit the page",icon:"edit",action:()=>{a.close(),location.hash=`#/pages/edit${T}`}}),(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 da=r.kind==="collection"?r.target:r.collection;k.push({label:"Open the collection",icon:"database",action:()=>{a.close(),location.hash=`#/collections/${da}/entries`}})}return r.kind==="product"&&r.entryId&&/^[\w-]{1,64}$/.test(r.entryId)&&k.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)&&k.push({label:"Open the old address",icon:"link",action:()=>window.open(r.oldUrl,"_blank","noopener,noreferrer")}),T&&k.push({label:"Copy the new address",icon:"copy",action:()=>bt(new URL(T,location.origin).href)}),k},ia=E.contextMenu(na,{cursor:"glyph",match:".wpx-row",inherit:!1,density:"compact",items:ra}),la=o.querySelector(".wpx-report-redirects"),ca=E.contextMenu(la,{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"}}]}),Ce=s=>{const r=s.target.closest(".wpx-kebab");if(r){U(r);return}const T=s.target.closest(".wpx-report-items .wpx-row");if(!T)return;const k=Ge.get(T.dataset.key);k?.target?.startsWith("/")&&k.result!=="failed"&&k.result!=="skipped"&&window.open(k.target,"_blank","noopener")},Xe=s=>{const r=s.target.closest(".wpx-row");r&&(s.key==="F10"&&s.shiftKey?(s.preventDefault(),U(r)):s.key==="Enter"&&s.target===r&&(s.preventDefault(),s.stopPropagation(),Ce({target:r})))};o.addEventListener("click",Ce),o.addEventListener("keydown",Xe);const pa=g.add(()=>a.close());ha(a,()=>{H=!1,sa.dispose(),oa(),ia?.destroy?.(),ca?.destroy?.(),o.removeEventListener("click",Ce),o.removeEventListener("keydown",Xe),pa()}),a.open(),I.scan(o)}async function Gt(e){const t=A.peek().find(a=>a.id===e);if(t&&await we(`Remove the import of <strong>${_(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 q(`${$}/history/${e}`,{method:"DELETE"}),!i())return;A.value=A.peek().filter(a=>a.id!==e),C(ee)}catch(a){E.toast(`Not removed: ${a.message||a}`,{type:"error"})}}n.querySelector(".wpx-staged").innerHTML=Da,n.querySelector(".wpx-items").innerHTML=ut,n.querySelector(".wpx-redirects").innerHTML=mt,n.querySelector(".wpx-history").innerHTML=Oa,n.querySelector(".wpx-tiles").innerHTML=ht,n.querySelector(".wpx-note-list").innerHTML=vt,n.querySelector(".wpx-kinds").innerHTML=Re,n.querySelector(".wpx-filters").innerHTML=Re,n.querySelector(".wpx-facts").innerHTML=Na,n.querySelector(".wpx-product-notes").innerHTML=ft,n.querySelector(".wpx-types").innerHTML=Ha,n.querySelector(".wpx-internal").innerHTML=ft;const Xt={mode:yt,job:y,jobTitle:Kt,jobText:Wt,jobPct:Oe,staged:u,stagedRows:xt,historyRows:kt,plan:b,planLoading:ae,planError:ye,refreshing:be,opt:p,blogAvailable:R,blogNote:Bt,dirty:Ie,canRun:De,siteTitle:At,siteMeta:It,tiles:qt,notes:Ct,kinds:Mt,filters:Et,rows:$t,moreText:Lt,emptyText:St,redirectRows:Pt,redirectCount:Rt,query:j,uploadText:se,uploadError:F,dropping:ne,wxrLimit:Zt,zipInfo:ie,zipText:jt,zipButton:Ft,zipUploadText:oe,shopAvailable:gt,hasProducts:Ut,productNote:Dt,productNoteCls:Ot,productFacts:Ht,productNotes:Nt,typeRows:ke,internalRows:Me,hasCustom:_t,internalSummary:zt,optComments:K("comments"),optMenus:K("menus"),optRedirects:K("redirects"),optDrafts:K("drafts"),optProducts:K("products")},Qt=M.applyBindings(Xt,n,{methods:{back:()=>J(),discard:()=>Ne(),run:()=>Yt(),resetChoices:()=>{p.value=Pe(R.peek())},postsBlog:()=>O({posts:"blog"}),postsPages:()=>O({posts:"pages"}),postsSkip:()=>O({posts:"skip"}),mediaDownload:()=>O({media:"download"}),mediaZip:()=>O({media:"zip"}),mediaSkip:()=>O({media:"skip"}),removeZip:()=>Jt(),pickSeg:e=>{e.seg==="kind"?P.value=e.id:D.value=e.id},showProducts:()=>{P.value="product",D.value="all",j.value="",n.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})}}});g.add(()=>Qt.dispose()),g.add(Qe(n,{position:"bottom"}));const G=n.querySelector(".wpx-file"),_e=()=>{const e=G.files?.[0];G.value="",Ue(e)};G.addEventListener("change",_e);const N=n.querySelector(".wpx-drop"),ze=e=>{e.preventDefault(),ne.value=!0},Be=()=>{ne.value=!1},je=e=>{e.preventDefault(),ne.value=!1,Ue(e.dataTransfer?.files?.[0])};N.addEventListener("dragover",ze),N.addEventListener("dragleave",Be),N.addEventListener("drop",je);const me=n.querySelector(".wpx-zip-file"),Fe=()=>{const e=me.files?.[0];me.value="",Vt(e)};me.addEventListener("change",Fe),g.add(()=>{G.removeEventListener("change",_e),N.removeEventListener("dragover",ze),N.removeEventListener("dragleave",Be),N.removeEventListener("drop",je),me.removeEventListener("change",Fe)}),te(n.querySelector(".wpx-staged"),".wpx-row",e=>[{header:u.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Upload"},{label:"Preview the import",icon:"eye",action:()=>de(e.dataset.id)},{label:"Discard the upload",icon:"trash-2",action:()=>Ne(e.dataset.id)}],e=>de(e.dataset.id));const ea=(e,t)=>{p.value={...p.peek(),choices:wa(p.peek().choices,e,t)}};te(n.querySelector(".wpx-items"),".wpx-row",e=>{const t=Z.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:()=>ea(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=>U(e.querySelector(".wpx-kebab")||e));const Ke=(e,t)=>{p.value=Ia(p.peek(),e,t)},We=(e,t)=>{p.value=Aa(p.peek(),e,t)},ta=e=>{P.value="",D.value="all",j.value=e,n.querySelector(".wpx-items")?.closest(".wpx-card")?.scrollIntoView({behavior:"smooth",block:"start"})},X=n.querySelector(".wpx-types"),Ze=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&&Ke(o.dataset.type,a.dataset.as)},Ve=e=>{const t=e.target.closest("input[data-list-page]"),a=e.target.closest(".wpx-type-row");t&&a&&We(a.dataset.type,t.checked)};X.addEventListener("click",Ze,!0),X.addEventListener("change",Ve),g.add(()=>{X.removeEventListener("click",Ze,!0),X.removeEventListener("change",Ve)}),te(X,".wpx-type-row",e=>{const t=ke.peek().find(a=>a.type===e.dataset.type);return t?[{header:`${t.label} ("${t.type}")`},...Ra(t).map(a=>({label:a.label,icon:a.icon,action:()=>{a.id==="show"?ta(t.type):a.id==="list"||a.id==="nolist"?We(t.type,a.id==="list"):Ke(t.type,a.id)}}))]:[]},e=>U(e.querySelector(".wpx-kebab")||e)),te(n.querySelector(".wpx-redirects"),".wpx-row",e=>[{header:e.dataset.from},{label:"Copy the old address",icon:"copy",action:()=>bt(e.dataset.from)}],null),te(n.querySelector(".wpx-history"),".wpx-row",e=>[{header:A.peek().find(t=>t.id===e.dataset.id)?.siteTitle||"Import"},{label:"Open the report",icon:"file-text",action:()=>ue(e.dataset.id)},{label:"Remove from the history",icon:"trash-2",action:()=>Gt(e.dataset.id)}],e=>ue(e.dataset.id)),ma(l,{id:"wpx-upload",icon:"upload",title:"Upload an export",onClick:()=>{m.peek()&&J(),setTimeout(()=>G.click(),0)}}),I.scan(n);const Se=st(d(),u.peek().map(e=>e.id),w);Se.pruned&&x&&L({owner:w,items:Se.items});const Je=Object.entries(Se.items).sort((e,t)=>String(t[1].at).localeCompare(String(e[1].at)))[0];Je&&!y.peek()&&await de(Je[0])}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.8.3",
3
+ "version": "1.8.5",
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",
@@ -84,7 +84,7 @@
84
84
  "@fastify/rate-limit": "^10.3.0",
85
85
  "@fastify/static": "9.1.1",
86
86
  "bcryptjs": "^3.0.3",
87
- "domma-js": "0.53.0",
87
+ "domma-js": "0.53.1",
88
88
  "dotenv": "^17.2.3",
89
89
  "fastify": "5.8.5",
90
90
  "gray-matter": "^4.0.3",
@@ -65,7 +65,10 @@ export function planForScreen(plan, blog, shop = {}) {
65
65
  target: r.target || '', oldUrl: r.oldUrl || '', status: r.status || '', wpStatus: r.wpStatus || '',
66
66
  shortcodes: r.shortcodes || [], builder: r.builder || '', comments: r.comments || 0, count: r.count || 0,
67
67
  replaces: Boolean(r.replaces), wanted: r.wanted || '',
68
- ...(r.kind === 'product' && {productType: r.productType || '', variants: r.variants || 0, needs: r.needs || ''})
68
+ ...(r.kind === 'product' && {productType: r.productType || '', variants: r.variants || 0, needs: r.needs || ''}),
69
+ ...(r.kind === 'custom' && {as: r.as || '', postType: r.postType || '', collection: r.collection || '', listAt: r.listAt || ''}),
70
+ ...(r.kind === 'collection' && {postType: r.postType || '', fields: r.fields || 0}),
71
+ ...(r.listFor && {listFor: r.listFor})
69
72
  })),
70
73
  redirects: plan.redirects.map(r => ({from: r.from, to: r.to, action: r.action, reason: r.reason || ''}))
71
74
  };