@micacms/editor-ui 0.4.0 → 0.5.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/assets/ChangesView-CSjnT0fh.js +7 -0
  2. package/dist/assets/ChangesView-CSjnT0fh.js.map +1 -0
  3. package/dist/assets/{CollectionView-D3W4tRXa.js → CollectionView-BlLAhVVi.js} +2 -2
  4. package/dist/assets/{CollectionView-D3W4tRXa.js.map → CollectionView-BlLAhVVi.js.map} +1 -1
  5. package/dist/assets/{ConfirmDialog.vue_vue_type_script_setup_true_lang-BhOQwoeA.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-C073kW3p.js} +2 -2
  6. package/dist/assets/{ConfirmDialog.vue_vue_type_script_setup_true_lang-BhOQwoeA.js.map → ConfirmDialog.vue_vue_type_script_setup_true_lang-C073kW3p.js.map} +1 -1
  7. package/dist/assets/DashboardView-BpelkVGe.js +2 -0
  8. package/dist/assets/DashboardView-BpelkVGe.js.map +1 -0
  9. package/dist/assets/EntryView-DZuhqJnd.js +2 -0
  10. package/dist/assets/EntryView-DZuhqJnd.js.map +1 -0
  11. package/dist/assets/{LoginView-BCrrdqnf.js → LoginView-BmnX2zOD.js} +2 -2
  12. package/dist/assets/{LoginView-BCrrdqnf.js.map → LoginView-BmnX2zOD.js.map} +1 -1
  13. package/dist/assets/{MediaView-KlQHfWAi.js → MediaView-Dp2botAQ.js} +2 -2
  14. package/dist/assets/{MediaView-KlQHfWAi.js.map → MediaView-Dp2botAQ.js.map} +1 -1
  15. package/dist/assets/{NotFoundView-C9bEHUGC.js → NotFoundView-ByEOgkxm.js} +2 -2
  16. package/dist/assets/{NotFoundView-C9bEHUGC.js.map → NotFoundView-ByEOgkxm.js.map} +1 -1
  17. package/dist/assets/{ObjectField-gxr2a2pp.js → ObjectField-BSITpnGH.js} +2 -2
  18. package/dist/assets/{ObjectField-gxr2a2pp.js.map → ObjectField-BSITpnGH.js.map} +1 -1
  19. package/dist/assets/{PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js → PageHeader.vue_vue_type_script_setup_true_lang-DJWhe1Ye.js} +2 -2
  20. package/dist/assets/{PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js.map → PageHeader.vue_vue_type_script_setup_true_lang-DJWhe1Ye.js.map} +1 -1
  21. package/dist/assets/{RepeaterField-obOWml_P.js → RepeaterField-BnXDf3wL.js} +2 -2
  22. package/dist/assets/{RepeaterField-obOWml_P.js.map → RepeaterField-BnXDf3wL.js.map} +1 -1
  23. package/dist/assets/SingletonView-Cb8Qq_gr.js +2 -0
  24. package/dist/assets/SingletonView-Cb8Qq_gr.js.map +1 -0
  25. package/dist/assets/{SystemView-CBvzzAoO.css → SystemView-AMhNiUgh.css} +1 -1
  26. package/dist/assets/SystemView-C6RAZvd2.js +3 -0
  27. package/dist/assets/SystemView-C6RAZvd2.js.map +1 -0
  28. package/dist/assets/{arrow-right-DJTAYrz5.js → arrow-right-DD5BWXHV.js} +2 -2
  29. package/dist/assets/{arrow-right-DJTAYrz5.js.map → arrow-right-DD5BWXHV.js.map} +1 -1
  30. package/dist/assets/{arrow-up-CibOjHj-.js → arrow-up-Bdxg9_RJ.js} +2 -2
  31. package/dist/assets/{arrow-up-CibOjHj-.js.map → arrow-up-Bdxg9_RJ.js.map} +1 -1
  32. package/dist/assets/{chevron-down-Bmt8sf-v.js → chevron-down-CcJtiSTR.js} +2 -2
  33. package/dist/assets/{chevron-down-Bmt8sf-v.js.map → chevron-down-CcJtiSTR.js.map} +1 -1
  34. package/dist/assets/{index-Colfqb-9.js → index-BsOOwFCf.js} +9 -9
  35. package/dist/assets/index-BsOOwFCf.js.map +1 -0
  36. package/dist/assets/{plus-D_aoCFbi.js → plus-CgaTSYYb.js} +2 -2
  37. package/dist/assets/{plus-D_aoCFbi.js.map → plus-CgaTSYYb.js.map} +1 -1
  38. package/dist/assets/{useField-BDSV5ZPo.js → useField-BxptRsz_.js} +2 -2
  39. package/dist/assets/{useField-BDSV5ZPo.js.map → useField-BxptRsz_.js.map} +1 -1
  40. package/dist/assets/{useUnsavedChanges-B0WVqgI4.js → useUnsavedChanges-FB5XcFfI.js} +4 -4
  41. package/dist/assets/{useUnsavedChanges-B0WVqgI4.js.map → useUnsavedChanges-FB5XcFfI.js.map} +1 -1
  42. package/dist/index.html +1 -1
  43. package/package.json +2 -2
  44. package/dist/assets/ChangesView-DoLhwPxu.js +0 -7
  45. package/dist/assets/ChangesView-DoLhwPxu.js.map +0 -1
  46. package/dist/assets/DashboardView-JZ2Eaw1_.js +0 -2
  47. package/dist/assets/DashboardView-JZ2Eaw1_.js.map +0 -1
  48. package/dist/assets/EntryView-BwERaZkJ.js +0 -2
  49. package/dist/assets/EntryView-BwERaZkJ.js.map +0 -1
  50. package/dist/assets/SingletonView-BNJCcl7V.js +0 -2
  51. package/dist/assets/SingletonView-BNJCcl7V.js.map +0 -1
  52. package/dist/assets/SystemView-CB8CT0Pa.js +0 -3
  53. package/dist/assets/SystemView-CB8CT0Pa.js.map +0 -1
  54. package/dist/assets/index-Colfqb-9.js.map +0 -1
package/dist/index.html CHANGED
@@ -10,7 +10,7 @@
10
10
  <link rel="icon" href="/admin/brand/favicon.ico" sizes="48x48" />
11
11
  <link rel="icon" href="/admin/brand/micacms-favicon.svg" type="image/svg+xml" />
12
12
  <link rel="apple-touch-icon" href="/admin/brand/apple-touch-icon.png" />
13
- <script type="module" crossorigin src="/admin/assets/index-Colfqb-9.js"></script>
13
+ <script type="module" crossorigin src="/admin/assets/index-BsOOwFCf.js"></script>
14
14
  <link rel="stylesheet" crossorigin href="/admin/assets/index-bRiiEobC.css">
15
15
  </head>
16
16
  <body class="h-full">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micacms/editor-ui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0-rc.1",
4
4
  "type": "module",
5
5
  "description": "The Mica editor SPA — identity-neutral Vue administration UI, shipped as built assets and mounted by a composing app.",
6
6
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "vue": "^3.5.13",
38
38
  "vue-router": "^4.5.0",
39
39
  "vue-tsc": "^2.2.0",
40
- "@micacms/core": "0.4.0"
40
+ "@micacms/core": "0.5.0-rc.1"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=22.12.0"
@@ -1,7 +0,0 @@
1
- import{D as ie,d as X,h as t,c as n,b as w,a as l,F as x,k as S,C as B,t as f,e as R,g as $,q as le,o as re,j as L,w as V,l as _,z as ue,s as de,v as ce,m as he,r as A,i as N,A as D,n as me,x as W,R as pe,S as fe,y as ge}from"./index-Colfqb-9.js";import{h as be}from"./useField-BDSV5ZPo.js";import{_ as ve}from"./ConfirmDialog.vue_vue_type_script_setup_true_lang-BhOQwoeA.js";import{_ as ye}from"./PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js";/**
2
- * @license @lucide/vue v1.37.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const ke=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],_e=ie("refresh-cw",ke);function xe(d,o,s){return z(d,o,s,[],[])}function z(d,o,s,r,m){const p=[];for(const[g,a]of Object.entries(d)){if(a.hidden)continue;const u=o===null?void 0:o[g],v=s===null?void 0:s[g],y=[...r,g],c=[...m,a.label??be(g)];if(a.kind==="object"){p.push(...z(a.fields,o===null?null:F(u)??{},s===null?null:F(v)??{},y,c));continue}if(a.kind==="repeater"){p.push(...we(a.fields,a.itemLabel,Q(u),Q(v),y,c,{before:o!==null,after:s!==null}));continue}O(u)!==O(v)&&p.push({path:y.join("."),label:c,kind:a.kind,before:o===null?null:K(a,u),after:s===null?null:K(a,v)})}return p}function we(d,o,s,r,m,p,g){const a=[],u=Math.max((s==null?void 0:s.length)??0,(r==null?void 0:r.length)??0);for(let v=0;v<u;v++){const y=(s==null?void 0:s[v])??(g.before?{}:null),c=(r==null?void 0:r[v])??(g.after?{}:null),C=k=>{const j=o?k==null?void 0:k[o]:void 0;return typeof j=="string"&&j!==""?j:`${v+1}`};a.push(...z(d,y,c,[...m,String(v)],[...p,C(c??y)]))}return a}function K(d,o){if(o==null||o==="")return"Empty";if(d.kind==="boolean")return o===!0?"Yes":"No";if(d.kind==="select")return(Array.isArray(o)?o:[o]).map(r=>{var m;return((m=d.options.find(p=>p.value===r))==null?void 0:m.label)??String(r)}).join(", ");if(d.kind==="media"){const s=Array.isArray(o)?o:[o];return s.length===0?"Empty":s.map(r=>String(r).split("/").at(-1)??String(r)).join(", ")}if(d.kind==="coordinates"){const s=F(o);if(s&&typeof s.lat=="number"&&typeof s.lng=="number")return`${s.lat.toFixed(5)}, ${s.lng.toFixed(5)}`}return Array.isArray(o)?o.map(String).join(", "):typeof o=="object"?O(o):String(o)}function F(d){return d!==null&&typeof d=="object"&&!Array.isArray(d)?d:null}function Q(d){return Array.isArray(d)?d:null}function O(d){return JSON.stringify(d??null,(o,s)=>{if(s===null||typeof s!="object"||Array.isArray(s))return s;const r=s,m={};for(const p of Object.keys(r).sort())m[p]=r[p];return m})}const Ce={class:"mt-3 rounded-md border border-line bg-canvas/60 p-3 text-xs"},$e={key:0,class:"mb-2 font-medium text-success"},Ae={key:1,class:"mb-2 font-medium text-danger"},Se={key:2,class:"grid grid-cols-2 gap-3"},Pe={class:"list-decimal space-y-0.5 pl-5"},Re={class:"list-decimal space-y-0.5 pl-5"},je={key:0,class:"text-muted"},Te={key:1,class:"space-y-3"},Me={class:"mb-1 font-medium"},Ne={key:0,class:"text-muted","aria-hidden":"true"},De={key:0,class:"max-h-48 overflow-y-auto whitespace-pre-wrap break-words rounded-sm border border-danger/15 bg-danger-soft/60 p-2"},Be={key:1,class:"max-h-48 overflow-y-auto whitespace-pre-wrap break-words rounded-sm border border-success/15 bg-success-soft/60 p-2"},Ee=X({__name:"ChangeComparison",props:{comparison:{},fields:{}},setup(d){const o=d,s=$(()=>o.comparison.before===null?"created":o.comparison.after===null?"deleted":"changed"),r=$(()=>o.fields?xe(o.fields,o.comparison.before,o.comparison.after):[]),m=$(()=>{if(o.fields)return null;const g=a=>Array.isArray(a==null?void 0:a.order)?a.order:[];return{before:g(o.comparison.before),after:g(o.comparison.after)}}),p=$(()=>{if(!m.value)return new Set;const g=new Map(m.value.before.map((a,u)=>[a.slug,u]));return new Set(m.value.after.filter((a,u)=>g.get(a.slug)!==u).map(a=>a.slug))});return(g,a)=>(t(),n("div",Ce,[s.value==="created"?(t(),n("p",$e," New — publishing puts this on the site for the first time. ")):s.value==="deleted"?(t(),n("p",Ae," Publishing removes this from the site. ")):w("",!0),m.value?(t(),n("div",Se,[l("div",null,[a[0]||(a[0]=l("p",{class:"mb-1.5 font-medium text-muted"},"Before",-1)),l("ol",Pe,[(t(!0),n(x,null,S(m.value.before,u=>(t(),n("li",{key:u.slug,class:B(p.value.has(u.slug)&&"font-medium text-ink")},f(u.title),3))),128))])]),l("div",null,[a[1]||(a[1]=l("p",{class:"mb-1.5 font-medium text-muted"},"After",-1)),l("ol",Re,[(t(!0),n(x,null,S(m.value.after,u=>(t(),n("li",{key:u.slug,class:B(p.value.has(u.slug)&&"font-medium text-success")},f(u.title),3))),128))])])])):(t(),n(x,{key:3},[r.value.length===0?(t(),n("p",je," Nothing visible changed — files moved or were rewritten without a field changing its value. ")):(t(),n("dl",Te,[(t(!0),n(x,null,S(r.value,u=>(t(),n("div",{key:u.path},[l("dt",Me,[(t(!0),n(x,null,S(u.label,(v,y)=>(t(),n(x,{key:y},[y>0?(t(),n("span",Ne," › ")):w("",!0),l("span",null,f(v),1)],64))),128))]),l("dd",{class:B(["grid gap-2",s.value==="changed"?"grid-cols-2":"grid-cols-1"])},[s.value!=="created"?(t(),n("div",De,[a[2]||(a[2]=l("span",{class:"sr-only"},"Before: ",-1)),R(f(u.before),1)])):w("",!0),s.value!=="deleted"?(t(),n("div",Be,[a[3]||(a[3]=l("span",{class:"sr-only"},"After: ",-1)),R(f(u.after),1)])):w("",!0)],2)]))),128))]))],64))]))}}),Le=["disabled"],Ve={class:"mx-auto max-w-3xl space-y-5 px-4 py-6 sm:px-6"},Fe={key:0,class:"text-sm text-muted"},Oe={key:0,class:"rounded-md border border-line bg-subtle p-4 text-sm text-muted"},ze={class:"mt-1"},Ie={key:1,role:"alert",class:"rounded-md border border-warning/15 bg-warning-soft p-4"},Ye={class:"mt-1 text-xs text-muted"},qe=["disabled"],Ge={key:2,role:"alert",class:"rounded-md border border-danger/15 bg-danger-soft p-4"},He={class:"mt-1.5 space-y-1 text-xs text-danger"},Je={class:"font-medium"},Ue={key:3,class:"card p-8 text-center"},We={class:"mt-1 text-sm text-muted"},Ke={key:4,"aria-labelledby":"changes-heading"},Qe={class:"card divide-y divide-line"},Xe={class:"min-w-0 flex-1"},Ze={key:0,class:"mt-2 text-xs text-muted"},es={key:1,class:"mt-2 text-xs text-danger"},ss={key:1,class:"mt-1 space-y-0.5"},ts={class:"break-all font-mono"},ns=["onClick"],os={key:5,class:"card p-4","aria-labelledby":"publish-heading"},as={id:"publish-heading",class:"text-sm font-semibold"},is={class:"mt-1 text-xs text-muted"},ls=["disabled"],rs=["disabled"],us={key:2,class:"text-sm text-muted"},ds={key:0},cs={key:1},gs=X({__name:"ChangesView",setup(d){const o=ge(),s=he(),r=me(),m=A(!0),p=A(!1),g=A(!1),a=A(""),u=A(null),v=A(!1),y=A(null),c=s.status,C=s.edits,k=A({});function j(e){var i,b;return e.kind==="entry"?((i=o.collection(e.collection))==null?void 0:i.fields)??null:e.kind==="singleton"?((b=o.singleton(e.name))==null?void 0:b.fields)??null:null}async function I(e){if(e.target){k.value[e.key]={loading:!0,error:null,comparison:null};try{const i=await N.staging.compare(e.target);k.value[e.key]={loading:!1,error:null,comparison:i}}catch(i){k.value[e.key]={loading:!1,error:i instanceof D?i.message:"Could not load the comparison.",comparison:null}}}}le(C,e=>{for(const i of e)i.target&&!k.value[i.key]&&I(i)});const Z=$(()=>{var e;return((e=c.value)==null?void 0:e.workspace)??"draft-store"}),T=$(()=>Z.value==="working-tree"),ee=$(()=>c.value?T.value?c.value.branch?`Your working tree, on branch ${c.value.branch}`:"Your working tree":"Saved in Mica, waiting to be published":null),se=$(()=>{var e;return y.value!==null||T.value&&(((e=c.value)==null?void 0:e.ahead)??0)>0}),Y=$(()=>{var e,i,b;return(((e=c.value)==null?void 0:e.publish.enabled)??!1)&&(((i=c.value)==null?void 0:i.validation.ok)??!1)&&(((b=c.value)==null?void 0:b.changes.length)??0)>0&&!p.value}),te={create:"Added",update:"Changed",delete:"Removed"};async function q(){k.value={},await s.refresh();for(const e of C.value)e.target&&!k.value[e.key]&&I(e);m.value=!1}re(q);async function ne(){var e,i;p.value=!0;try{const b=await N.staging.publish(a.value,((e=c.value)==null?void 0:e.baseRevision)??null);b.state==="published"?(y.value=null,a.value="",r.success("Published.",b.revision?`Commit ${E(b.revision)}.`:void 0)):(y.value=b,a.value="",r.error("Committed, but the push failed.",b.pushError)),await s.refresh()}catch(b){b instanceof D?(r.error(b.message,(i=b.issues[0])==null?void 0:i.message),await s.refresh()):r.error("Could not publish.")}finally{p.value=!1}}async function oe(){g.value=!0;try{const e=await N.staging.push();e.state==="published"?(y.value=null,r.success("Pushed.",e.revision?`Commit ${E(e.revision)}.`:void 0)):(y.value=e,r.error("The push failed again.",e.pushError)),await s.refresh()}catch(e){r.error(e instanceof D?e.message:"Could not push.")}finally{g.value=!1}}async function ae(){const e=u.value;if(e){v.value=!0;try{await N.staging.discard(e.fileChanges.map(i=>i.path)),r.success(`Discarded the changes to ${e.label}.`),u.value=null,await s.refresh()}catch(i){r.error(i instanceof D?i.message:"Could not discard.")}finally{v.value=!1}}}function E(e){return/^[0-9a-f]{20,}$/i.test(e)?e.slice(0,7):e}return(e,i)=>{var b,G;return t(),n(x,null,[L(ye,{title:"Publish",subtitle:ee.value},{default:V(()=>[l("button",{type:"button",class:"btn-ghost px-2",disabled:m.value,onClick:q},[L(_(_e),{size:16,"aria-hidden":"true"}),i[3]||(i[3]=l("span",{class:"sr-only"},"Refresh the change list",-1))],8,Le)]),_:1},8,["subtitle"]),l("div",Ve,[m.value?(t(),n("p",Fe,"Loading…")):_(c)?(t(),n(x,{key:1},[_(c).publish.enabled?w("",!0):(t(),n("div",Oe,[i[4]||(i[4]=l("p",{class:"font-medium text-ink"},"Publishing is not available here",-1)),l("p",ze,f(_(c).publish.reason),1)])),se.value?(t(),n("div",Ie,[i[5]||(i[5]=l("p",{class:"text-sm font-medium text-warning"},"Committed, waiting to be pushed",-1)),l("p",Ye,f(((b=y.value)==null?void 0:b.pushError)??"This branch has commits the remote has not seen. Retrying pushes the existing commits — it never creates new ones."),1),l("button",{type:"button",class:"btn-secondary mt-2.5",disabled:g.value,onClick:oe},f(g.value?"Pushing…":"Retry push"),9,qe)])):w("",!0),_(c).validation.ok?w("",!0):(t(),n("div",Ge,[i[6]||(i[6]=l("p",{class:"text-sm font-medium text-danger"}," These changes cannot be published until they are fixed ",-1)),l("ul",He,[(t(!0),n(x,null,S(_(c).validation.problems,h=>(t(),n("li",{key:h.path},[l("span",Je,f(h.label),1),h.issues.length?(t(),n(x,{key:0},[R(" — "+f(h.issues.map(M=>M.message).join("; ")),1)],64)):w("",!0)]))),128))])])),_(C).length===0?(t(),n("div",Ue,[i[7]||(i[7]=l("p",{class:"text-sm font-medium"},"Nothing waiting to be published",-1)),l("p",We," Saved changes collect here until somebody publishes them. Right now the "+f(T.value?"working tree":"draft workspace")+" matches the repository. ",1)])):(t(),n("section",Ke,[i[8]||(i[8]=l("h2",{id:"changes-heading",class:"sr-only"},"Pending changes",-1)),l("ul",Qe,[(t(!0),n(x,null,S(_(C),h=>{var M,H,J,U;return t(),n("li",{key:h.key,class:"flex items-start gap-3 p-4"},[l("div",Xe,[(t(),W(fe(h.link?"RouterLink":"p"),pe({ref_for:!0},h.link?{to:h.link}:{},{class:["text-sm font-medium",h.link&&"hover:underline"]}),{default:V(()=>[R(f(h.label),1)]),_:2},1040,["class"])),h.target?(t(),n(x,{key:0},[(M=k.value[h.key])!=null&&M.loading?(t(),n("p",Ze," Comparing… ")):(H=k.value[h.key])!=null&&H.error?(t(),n("p",es,f((J=k.value[h.key])==null?void 0:J.error),1)):(U=k.value[h.key])!=null&&U.comparison?(t(),W(Ee,{key:2,comparison:k.value[h.key].comparison,fields:j(h.target)},null,8,["comparison","fields"])):w("",!0)],64)):(t(),n("ul",ss,[(t(!0),n(x,null,S(h.fileChanges,P=>(t(),n("li",{key:P.path,class:"flex items-baseline gap-2 text-xs text-muted"},[l("span",{class:B(["w-16 shrink-0 font-mono text-[11px]",P.kind==="delete"?"text-danger":P.kind==="create"?"text-success":""])},f(te[P.kind]),3),l("span",ts,f(P.path),1)]))),128))]))]),l("button",{type:"button",class:"btn-ghost shrink-0 text-xs",onClick:P=>u.value=h}," Discard ",8,ns)])}),128))])])),_(C).length>0&&_(c).publish.enabled?(t(),n("section",os,[l("h2",as," Publish "+f(_(C).length===1?"this edit":`these ${_(C).length} edits`),1),l("p",is,[R(f(T.value?"One commit of exactly the files listed above, pushed with your own Git configuration.":"One commit to the content repository, which is what triggers your site's build.")+" ",1),_(c).baseRevision?(t(),n(x,{key:0},[R(" Based on "+f(E(_(c).baseRevision))+".",1)],64)):w("",!0)]),l("form",{class:"mt-3 flex flex-wrap items-center gap-2",onSubmit:i[1]||(i[1]=ue(h=>Y.value&&a.value.trim()&&ne(),["prevent"]))},[de(l("input",{"onUpdate:modelValue":i[0]||(i[0]=h=>a.value=h),type:"text",class:"input min-w-0 flex-1",maxlength:"500",placeholder:"Describe this publication — it becomes the commit message","aria-label":"Commit message",disabled:p.value},null,8,ls),[[ce,a.value]]),l("button",{type:"submit",class:"btn-primary",disabled:!Y.value||!a.value.trim()},f(p.value?"Publishing…":"Publish"),9,rs)],32)])):w("",!0)],64)):(t(),n("p",us,"The change list could not be loaded. Reload to retry."))]),L(ve,{open:u.value!==null,title:`Discard the changes to “${(G=u.value)==null?void 0:G.label}”?`,"confirm-label":"Discard",destructive:"",busy:v.value,onCancel:i[2]||(i[2]=h=>u.value=null),onConfirm:ae},{default:V(()=>[T.value?(t(),n("p",ds," This restores the files in your working tree to the last commit — new files are deleted, edited ones go back. It cannot be undone from here. ")):(t(),n("p",cs," This forgets the saved changes; the repository stays exactly as it is. It cannot be undone from here. "))]),_:1},8,["open","title","busy"])],64)}}});export{gs as default};
7
- //# sourceMappingURL=ChangesView-DoLhwPxu.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChangesView-DoLhwPxu.js","sources":["../../../../common/temp/node_modules/.pnpm/@lucide+vue@1.37.0_vue@3.5.42_typescript@5.9.3_/node_modules/@lucide/vue/dist/esm/icons/refresh-cw.mjs","../../src/lib/compare.ts","../../src/components/ChangeComparison.vue","../../src/views/ChangesView.vue"],"sourcesContent":["/**\n * @license @lucide/vue v1.37.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n];\nconst RefreshCw = createLucideIcon(\"refresh-cw\", __iconNode);\n\nexport { __iconNode, RefreshCw as default };\n//# sourceMappingURL=refresh-cw.mjs.map\n","/**\n * Turns a raw before/after pair into rows an editor reads.\n *\n * The server's comparison is two documents of field data; everything friendly\n * about it happens here, where the model is at hand: fields get their labels,\n * nesting becomes a breadcrumb, unchanged values disappear, and each value is\n * written the way its field type would show it — never as JSON with quotes.\n */\n\nimport type { AnyField, FieldMap } from \"@micacms/core\";\n\nimport { humanise } from \"@/composables/useField\";\n\n/** One changed value, named and rendered for both sides. */\nexport interface CompareRow {\n /** Unique among the rows — the dotted path of the leaf. */\n path: string;\n /** Breadcrumb of labels, e.g. `[\"Extra sections\", \"2\", \"Heading\"]`. */\n label: string[];\n /** The field's kind, as a rendering hint (`richText` wants more room). */\n kind: string;\n /** Display strings; null on the side where the document does not exist. */\n before: string | null;\n after: string | null;\n}\n\n/**\n * The changed fields between two documents, in model order.\n *\n * A side that is null means the document itself is absent there (a creation\n * or a deletion); every present value on the other side becomes a row, so the\n * comparison doubles as a summary of the new or removed document.\n */\nexport function compareRows(\n fields: FieldMap,\n before: Record<string, unknown> | null,\n after: Record<string, unknown> | null,\n): CompareRow[] {\n return walk(fields, before, after, [], []);\n}\n\nfunction walk(\n fields: FieldMap,\n before: Record<string, unknown> | null,\n after: Record<string, unknown> | null,\n path: string[],\n label: string[],\n): CompareRow[] {\n const rows: CompareRow[] = [];\n\n for (const [name, field] of Object.entries(fields)) {\n if (field.hidden) continue;\n\n const a = before === null ? undefined : before[name];\n const b = after === null ? undefined : after[name];\n const at = [...path, name];\n const named = [...label, field.label ?? humanise(name)];\n\n // Null means \"this side's document does not exist\" all the way down. A\n // *value* that is merely missing inside an existing document becomes an\n // empty record instead, so its leaves read as Empty rather than vanish.\n if (field.kind === \"object\") {\n rows.push(\n ...walk(\n field.fields,\n before === null ? null : (asRecord(a) ?? {}),\n after === null ? null : (asRecord(b) ?? {}),\n at,\n named,\n ),\n );\n continue;\n }\n\n if (field.kind === \"repeater\") {\n rows.push(\n ...repeaterRows(field.fields, field.itemLabel, asList(a), asList(b), at, named, {\n before: before !== null,\n after: after !== null,\n }),\n );\n continue;\n }\n\n if (canonical(a) === canonical(b)) continue;\n\n rows.push({\n path: at.join(\".\"),\n label: named,\n kind: field.kind,\n before: before === null ? null : displayValue(field, a),\n after: after === null ? null : displayValue(field, b),\n });\n }\n\n return rows;\n}\n\n/**\n * Repeater items compared by position. Position is what the editor sees and\n * what the file stores; chasing moved items across indexes would guess.\n */\nfunction repeaterRows(\n fields: FieldMap,\n itemLabel: string | undefined,\n before: Array<Record<string, unknown>> | null,\n after: Array<Record<string, unknown>> | null,\n path: string[],\n label: string[],\n present: { before: boolean; after: boolean },\n): CompareRow[] {\n const rows: CompareRow[] = [];\n const count = Math.max(before?.length ?? 0, after?.length ?? 0);\n\n for (let index = 0; index < count; index++) {\n const a = before?.[index] ?? (present.before ? {} : null);\n const b = after?.[index] ?? (present.after ? {} : null);\n\n // Name the item by its summary field where one is set, else its number.\n const caption = (item: Record<string, unknown> | null) => {\n const value = itemLabel ? item?.[itemLabel] : undefined;\n return typeof value === \"string\" && value !== \"\" ? value : `${index + 1}`;\n };\n\n rows.push(...walk(fields, a, b, [...path, String(index)], [...label, caption(b ?? a)]));\n }\n\n return rows;\n}\n\n/**\n * A field value as the editor would say it — `displayValue` never shows JSON.\n * Null on both ends of a row is prevented by the change filter, so \"Empty\"\n * only ever appears opposite a real value.\n */\nexport function displayValue(field: AnyField, value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"Empty\";\n\n if (field.kind === \"boolean\") return value === true ? \"Yes\" : \"No\";\n\n if (field.kind === \"select\") {\n const values = Array.isArray(value) ? value : [value];\n return values\n .map((entry) => field.options.find((option) => option.value === entry)?.label ?? String(entry))\n .join(\", \");\n }\n\n if (field.kind === \"media\") {\n const values = Array.isArray(value) ? value : [value];\n if (values.length === 0) return \"Empty\";\n return values.map((entry) => String(entry).split(\"/\").at(-1) ?? String(entry)).join(\", \");\n }\n\n if (field.kind === \"coordinates\") {\n const point = asRecord(value);\n if (point && typeof point[\"lat\"] === \"number\" && typeof point[\"lng\"] === \"number\") {\n return `${point[\"lat\"].toFixed(5)}, ${point[\"lng\"].toFixed(5)}`;\n }\n }\n\n if (Array.isArray(value)) return value.map(String).join(\", \");\n if (typeof value === \"object\") return canonical(value);\n\n return String(value);\n}\n\n/* ------------------------------------------------------------------ */\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction asList(value: unknown): Array<Record<string, unknown>> | null {\n return Array.isArray(value) ? (value as Array<Record<string, unknown>>) : null;\n}\n\n/** Canonical JSON — keys sorted, so a rebuilt object compares equal. */\nfunction canonical(value: unknown): string {\n return JSON.stringify(value ?? null, (_key, entry: unknown) => {\n if (entry === null || typeof entry !== \"object\" || Array.isArray(entry)) return entry;\n const record = entry as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = record[key];\n return sorted;\n });\n}\n","<script setup lang=\"ts\">\n/**\n * What a pending change does, said as before and after.\n *\n * Not a diff: no line numbers, no `+`/`-`, no file contents. Each changed\n * field is one row with the stored value on the left and the staged one on\n * the right, worded by the field type — an editor who has never read a patch\n * can see exactly what publishing applies.\n */\n\nimport { computed } from \"vue\";\n\nimport type { FieldMap } from \"@micacms/core\";\n\nimport type { Comparison } from \"@/api\";\nimport { compareRows } from \"@/lib/compare\";\n\nconst props = defineProps<{\n comparison: Comparison;\n /** The owning document's fields; null for an order comparison. */\n fields: FieldMap | null;\n}>();\n\nconst mode = computed<\"created\" | \"deleted\" | \"changed\">(() => {\n if (props.comparison.before === null) return \"created\";\n if (props.comparison.after === null) return \"deleted\";\n return \"changed\";\n});\n\nconst rows = computed(() =>\n props.fields\n ? compareRows(props.fields, props.comparison.before, props.comparison.after)\n : [],\n);\n\n/** An order comparison — the collection's sequence on both sides. */\ninterface OrderItem {\n slug: string;\n title: string;\n}\n\nconst order = computed(() => {\n if (props.fields) return null;\n const side = (data: Record<string, unknown> | null): OrderItem[] =>\n Array.isArray(data?.[\"order\"]) ? (data[\"order\"] as OrderItem[]) : [];\n return { before: side(props.comparison.before), after: side(props.comparison.after) };\n});\n\n/** Slugs whose position changed, which is what an order change *is*. */\nconst moved = computed(() => {\n if (!order.value) return new Set<string>();\n const positions = new Map(order.value.before.map((item, index) => [item.slug, index]));\n return new Set(\n order.value.after\n .filter((item, index) => positions.get(item.slug) !== index)\n .map((item) => item.slug),\n );\n});\n</script>\n\n<template>\n <div class=\"mt-3 rounded-md border border-line bg-canvas/60 p-3 text-xs\">\n <p v-if=\"mode === 'created'\" class=\"mb-2 font-medium text-success\">\n New — publishing puts this on the site for the first time.\n </p>\n <p v-else-if=\"mode === 'deleted'\" class=\"mb-2 font-medium text-danger\">\n Publishing removes this from the site.\n </p>\n\n <!-- An order change: the sequence, before and after. -->\n <div v-if=\"order\" class=\"grid grid-cols-2 gap-3\">\n <div>\n <p class=\"mb-1.5 font-medium text-muted\">Before</p>\n <ol class=\"list-decimal space-y-0.5 pl-5\">\n <li\n v-for=\"item in order.before\"\n :key=\"item.slug\"\n :class=\"moved.has(item.slug) && 'font-medium text-ink'\"\n >\n {{ item.title }}\n </li>\n </ol>\n </div>\n <div>\n <p class=\"mb-1.5 font-medium text-muted\">After</p>\n <ol class=\"list-decimal space-y-0.5 pl-5\">\n <li\n v-for=\"item in order.after\"\n :key=\"item.slug\"\n :class=\"moved.has(item.slug) && 'font-medium text-success'\"\n >\n {{ item.title }}\n </li>\n </ol>\n </div>\n </div>\n\n <!-- Field changes. -->\n <template v-else>\n <p v-if=\"rows.length === 0\" class=\"text-muted\">\n Nothing visible changed — files moved or were rewritten without a field changing its value.\n </p>\n\n <dl v-else class=\"space-y-3\">\n <div v-for=\"row in rows\" :key=\"row.path\">\n <dt class=\"mb-1 font-medium\">\n <template v-for=\"(part, index) in row.label\" :key=\"index\">\n <span v-if=\"index > 0\" class=\"text-muted\" aria-hidden=\"true\"> › </span\n ><span>{{ part }}</span>\n </template>\n </dt>\n <dd :class=\"['grid gap-2', mode === 'changed' ? 'grid-cols-2' : 'grid-cols-1']\">\n <div\n v-if=\"mode !== 'created'\"\n class=\"max-h-48 overflow-y-auto whitespace-pre-wrap break-words rounded-sm border border-danger/15 bg-danger-soft/60 p-2\"\n >\n <span class=\"sr-only\">Before: </span>{{ row.before }}\n </div>\n <div\n v-if=\"mode !== 'deleted'\"\n class=\"max-h-48 overflow-y-auto whitespace-pre-wrap break-words rounded-sm border border-success/15 bg-success-soft/60 p-2\"\n >\n <span class=\"sr-only\">After: </span>{{ row.after }}\n </div>\n </dd>\n </div>\n </dl>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The pending change set, and Publish.\n *\n * This view is where Saved and Published stop being abstract words: everything\n * listed here is durable in the draft workspace and absent from the\n * repository's history until the button at the bottom is pressed. The list is\n * shared by the whole site — one pending set, not one per editor — so\n * everything on it is published together, whoever presses the button.\n *\n * The two workspaces speak through one API and differ only in what the words\n * mean physically: a working tree lists `git status` and publishes through the\n * developer's own Git; a draft store lists staged rows and publishes one\n * provider-side commit. The `workspace` field decides the phrasing, never the\n * behaviour.\n */\n\nimport { computed, onMounted, ref, watch } from \"vue\";\nimport { RefreshCw } from \"@lucide/vue\";\n\nimport type { FieldMap } from \"@micacms/core\";\n\nimport {\n api,\n ApiError,\n type Comparison,\n type CompareTarget,\n type FileChange,\n type PublishOutcome,\n} from \"@/api\";\nimport ChangeComparison from \"@/components/ChangeComparison.vue\";\nimport type { Edit } from \"@/lib/edits\";\nimport ConfirmDialog from \"@/components/ConfirmDialog.vue\";\nimport PageHeader from \"@/components/PageHeader.vue\";\nimport { useSchema } from \"@/stores/schema\";\nimport { useStaging } from \"@/stores/staging\";\nimport { useToast } from \"@/stores/toast\";\n\nconst schema = useSchema();\nconst staging = useStaging();\nconst toast = useToast();\n\nconst loading = ref(true);\nconst publishing = ref(false);\nconst pushing = ref(false);\nconst message = ref(\"\");\nconst discardTarget = ref<Edit | null>(null);\nconst discarding = ref(false);\n\n/** The half-finished publication, when a local push failed. */\nconst pendingPush = ref<PublishOutcome | null>(null);\n\nconst status = staging.status;\n\n/** One row per edit, never per file — see `lib/edits.ts`. */\nconst edits = staging.edits;\n\n/* ------------------------------------------------- before/after */\n\ninterface LoadedComparison {\n loading: boolean;\n error: string | null;\n comparison: Comparison | null;\n}\n\nconst comparisons = ref<Record<string, LoadedComparison>>({});\n\n/** The compared document's fields — null for an order comparison. */\nfunction fieldsFor(target: CompareTarget): FieldMap | null {\n if (target.kind === \"entry\") return schema.collection(target.collection)?.fields ?? null;\n if (target.kind === \"singleton\") return schema.singleton(target.name)?.fields ?? null;\n return null;\n}\n\nasync function loadComparison(edit: Edit): Promise<void> {\n if (!edit.target) return;\n comparisons.value[edit.key] = { loading: true, error: null, comparison: null };\n try {\n const comparison = await api.staging.compare(edit.target);\n comparisons.value[edit.key] = { loading: false, error: null, comparison };\n } catch (error) {\n comparisons.value[edit.key] = {\n loading: false,\n error: error instanceof ApiError ? error.message : \"Could not load the comparison.\",\n comparison: null,\n };\n }\n}\n\n// The comparison is the change list, so it loads with it — every edit, as\n// soon as it appears, without anything to click.\nwatch(edits, (next) => {\n for (const edit of next) {\n if (edit.target && !comparisons.value[edit.key]) void loadComparison(edit);\n }\n});\n\nconst workspace = computed(() => status.value?.workspace ?? \"draft-store\");\nconst isTree = computed(() => workspace.value === \"working-tree\");\n\nconst subtitle = computed(() => {\n if (!status.value) return null;\n if (isTree.value) {\n return status.value.branch\n ? `Your working tree, on branch ${status.value.branch}`\n : \"Your working tree\";\n }\n return \"Saved in Mica, waiting to be published\";\n});\n\n/** Commits already made and not yet pushed — visible even across a restart. */\nconst waitingToPush = computed(\n () => pendingPush.value !== null || (isTree.value && (status.value?.ahead ?? 0) > 0),\n);\n\nconst canPublish = computed(\n () =>\n (status.value?.publish.enabled ?? false) &&\n (status.value?.validation.ok ?? false) &&\n (status.value?.changes.length ?? 0) > 0 &&\n !publishing.value,\n);\n\nconst kindWord: Record<FileChange[\"kind\"], string> = {\n create: \"Added\",\n update: \"Changed\",\n delete: \"Removed\",\n};\n\nasync function refresh(): Promise<void> {\n // Forget the comparisons first, so the edits watcher reloads every one of\n // them against the refreshed change set instead of showing a stale panel.\n comparisons.value = {};\n await staging.refresh();\n for (const edit of edits.value) {\n if (edit.target && !comparisons.value[edit.key]) void loadComparison(edit);\n }\n loading.value = false;\n}\n\nonMounted(refresh);\n\nasync function publish(): Promise<void> {\n publishing.value = true;\n try {\n const outcome = await api.staging.publish(message.value, status.value?.baseRevision ?? null);\n\n if (outcome.state === \"published\") {\n pendingPush.value = null;\n message.value = \"\";\n toast.success(\"Published.\", outcome.revision ? `Commit ${short(outcome.revision)}.` : undefined);\n } else {\n // The commit is real; only the push failed. Say so, and keep the retry\n // visible — pressing Publish again must not create a second commit.\n pendingPush.value = outcome;\n message.value = \"\";\n toast.error(\"Committed, but the push failed.\", outcome.pushError);\n }\n\n await staging.refresh();\n } catch (error) {\n if (error instanceof ApiError) {\n toast.error(error.message, error.issues[0]?.message);\n // A conflict or a validation refusal means the list moved: show the truth.\n await staging.refresh();\n } else {\n toast.error(\"Could not publish.\");\n }\n } finally {\n publishing.value = false;\n }\n}\n\nasync function retryPush(): Promise<void> {\n pushing.value = true;\n try {\n const outcome = await api.staging.push();\n if (outcome.state === \"published\") {\n pendingPush.value = null;\n toast.success(\"Pushed.\", outcome.revision ? `Commit ${short(outcome.revision)}.` : undefined);\n } else {\n pendingPush.value = outcome;\n toast.error(\"The push failed again.\", outcome.pushError);\n }\n await staging.refresh();\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not push.\");\n } finally {\n pushing.value = false;\n }\n}\n\nasync function discard(): Promise<void> {\n const edit = discardTarget.value;\n if (!edit) return;\n\n discarding.value = true;\n try {\n await api.staging.discard(edit.fileChanges.map((change) => change.path));\n toast.success(`Discarded the changes to ${edit.label}.`);\n discardTarget.value = null;\n await staging.refresh();\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not discard.\");\n } finally {\n discarding.value = false;\n }\n}\n\nfunction short(revision: string): string {\n return /^[0-9a-f]{20,}$/i.test(revision) ? revision.slice(0, 7) : revision;\n}\n</script>\n\n<template>\n <PageHeader title=\"Publish\" :subtitle=\"subtitle\">\n <button type=\"button\" class=\"btn-ghost px-2\" :disabled=\"loading\" @click=\"refresh\">\n <RefreshCw :size=\"16\" aria-hidden=\"true\" />\n <span class=\"sr-only\">Refresh the change list</span>\n </button>\n </PageHeader>\n\n <div class=\"mx-auto max-w-3xl space-y-5 px-4 py-6 sm:px-6\">\n <p v-if=\"loading\" class=\"text-sm text-muted\">Loading…</p>\n\n <template v-else-if=\"status\">\n <!-- Publishing unavailable: still an honest, read-only change list. -->\n <div\n v-if=\"!status.publish.enabled\"\n class=\"rounded-md border border-line bg-subtle p-4 text-sm text-muted\"\n >\n <p class=\"font-medium text-ink\">Publishing is not available here</p>\n <p class=\"mt-1\">{{ status.publish.reason }}</p>\n </div>\n\n <!-- A commit exists that the repository's remote has not seen. -->\n <div\n v-if=\"waitingToPush\"\n role=\"alert\"\n class=\"rounded-md border border-warning/15 bg-warning-soft p-4\"\n >\n <p class=\"text-sm font-medium text-warning\">Committed, waiting to be pushed</p>\n <p class=\"mt-1 text-xs text-muted\">\n {{\n pendingPush?.pushError ??\n \"This branch has commits the remote has not seen. Retrying pushes the existing \" +\n \"commits — it never creates new ones.\"\n }}\n </p>\n <button\n type=\"button\"\n class=\"btn-secondary mt-2.5\"\n :disabled=\"pushing\"\n @click=\"retryPush\"\n >\n {{ pushing ? \"Pushing…\" : \"Retry push\" }}\n </button>\n </div>\n\n <div\n v-if=\"!status.validation.ok\"\n role=\"alert\"\n class=\"rounded-md border border-danger/15 bg-danger-soft p-4\"\n >\n <p class=\"text-sm font-medium text-danger\">\n These changes cannot be published until they are fixed\n </p>\n <ul class=\"mt-1.5 space-y-1 text-xs text-danger\">\n <li v-for=\"problem in status.validation.problems\" :key=\"problem.path\">\n <span class=\"font-medium\">{{ problem.label }}</span>\n <template v-if=\"problem.issues.length\">\n — {{ problem.issues.map((issue) => issue.message).join(\"; \") }}\n </template>\n </li>\n </ul>\n </div>\n\n <!-- Nothing pending -->\n <div v-if=\"edits.length === 0\" class=\"card p-8 text-center\">\n <p class=\"text-sm font-medium\">Nothing waiting to be published</p>\n <p class=\"mt-1 text-sm text-muted\">\n Saved changes collect here until somebody publishes them. Right now the\n {{ isTree ? \"working tree\" : \"draft workspace\" }} matches the repository.\n </p>\n </div>\n\n <!-- The pending set -->\n <section v-else aria-labelledby=\"changes-heading\">\n <h2 id=\"changes-heading\" class=\"sr-only\">Pending changes</h2>\n\n <ul class=\"card divide-y divide-line\">\n <li v-for=\"edit in edits\" :key=\"edit.key\" class=\"flex items-start gap-3 p-4\">\n <div class=\"min-w-0 flex-1\">\n <component\n :is=\"edit.link ? 'RouterLink' : 'p'\"\n v-bind=\"edit.link ? { to: edit.link } : {}\"\n :class=\"['text-sm font-medium', edit.link && 'hover:underline']\"\n >\n {{ edit.label }}\n </component>\n\n <!-- What the change does. Edits with a document get the\n before/after view and no file paths; media and everything\n else have only their files to show. -->\n <template v-if=\"edit.target\">\n <p v-if=\"comparisons[edit.key]?.loading\" class=\"mt-2 text-xs text-muted\">\n Comparing…\n </p>\n <p v-else-if=\"comparisons[edit.key]?.error\" class=\"mt-2 text-xs text-danger\">\n {{ comparisons[edit.key]?.error }}\n </p>\n <ChangeComparison\n v-else-if=\"comparisons[edit.key]?.comparison\"\n :comparison=\"comparisons[edit.key]!.comparison!\"\n :fields=\"fieldsFor(edit.target)\"\n />\n </template>\n\n <ul v-else class=\"mt-1 space-y-0.5\">\n <li\n v-for=\"change in edit.fileChanges\"\n :key=\"change.path\"\n class=\"flex items-baseline gap-2 text-xs text-muted\"\n >\n <span\n :class=\"[\n 'w-16 shrink-0 font-mono text-[11px]',\n change.kind === 'delete' ? 'text-danger' : change.kind === 'create' ? 'text-success' : '',\n ]\"\n >\n {{ kindWord[change.kind] }}\n </span>\n <span class=\"break-all font-mono\">{{ change.path }}</span>\n </li>\n </ul>\n </div>\n\n <button type=\"button\" class=\"btn-ghost shrink-0 text-xs\" @click=\"discardTarget = edit\">\n Discard\n </button>\n </li>\n </ul>\n </section>\n\n <!-- Publish -->\n <section v-if=\"edits.length > 0 && status.publish.enabled\" class=\"card p-4\" aria-labelledby=\"publish-heading\">\n <h2 id=\"publish-heading\" class=\"text-sm font-semibold\">\n Publish {{ edits.length === 1 ? \"this edit\" : `these ${edits.length} edits` }}\n </h2>\n\n <p class=\"mt-1 text-xs text-muted\">\n {{\n isTree\n ? \"One commit of exactly the files listed above, pushed with your own Git configuration.\"\n : \"One commit to the content repository, which is what triggers your site's build.\"\n }}\n <template v-if=\"status.baseRevision\"> Based on {{ short(status.baseRevision) }}.</template>\n </p>\n\n <form class=\"mt-3 flex flex-wrap items-center gap-2\" @submit.prevent=\"canPublish && message.trim() && publish()\">\n <input\n v-model=\"message\"\n type=\"text\"\n class=\"input min-w-0 flex-1\"\n maxlength=\"500\"\n placeholder=\"Describe this publication — it becomes the commit message\"\n aria-label=\"Commit message\"\n :disabled=\"publishing\"\n />\n <button type=\"submit\" class=\"btn-primary\" :disabled=\"!canPublish || !message.trim()\">\n {{ publishing ? \"Publishing…\" : \"Publish\" }}\n </button>\n </form>\n </section>\n </template>\n\n <p v-else class=\"text-sm text-muted\">The change list could not be loaded. Reload to retry.</p>\n </div>\n\n <ConfirmDialog\n :open=\"discardTarget !== null\"\n :title=\"`Discard the changes to “${discardTarget?.label}”?`\"\n confirm-label=\"Discard\"\n destructive\n :busy=\"discarding\"\n @cancel=\"discardTarget = null\"\n @confirm=\"discard\"\n >\n <p v-if=\"isTree\">\n This restores the files in your working tree to the last commit — new files are deleted,\n edited ones go back. It cannot be undone from here.\n </p>\n <p v-else>\n This forgets the saved changes; the repository stays exactly as it is. It cannot be undone\n from here.\n </p>\n </ConfirmDialog>\n</template>\n"],"names":["__iconNode","RefreshCw","createLucideIcon","compareRows","fields","before","after","walk","path","label","rows","name","field","a","b","at","named","humanise","asRecord","repeaterRows","asList","canonical","displayValue","itemLabel","present","count","index","caption","item","value","entry","_a","option","values","point","_key","record","sorted","key","props","__props","mode","computed","order","side","data","moved","positions","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_createElementVNode","_cache","_hoisted_5","_Fragment","_renderList","_toDisplayString","_hoisted_6","_hoisted_7","_hoisted_8","row","_hoisted_9","part","_hoisted_10","_hoisted_11","_createTextVNode","_hoisted_12","schema","useSchema","staging","useStaging","toast","useToast","loading","ref","publishing","pushing","message","discardTarget","discarding","pendingPush","status","edits","comparisons","fieldsFor","target","_b","loadComparison","edit","comparison","api","error","ApiError","watch","next","workspace","isTree","subtitle","waitingToPush","canPublish","_c","kindWord","refresh","onMounted","publish","outcome","short","retryPush","discard","change","revision","_createVNode","PageHeader","_unref","problem","issue","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_createBlock","_resolveDynamicComponent","_mergeProps","_hoisted_17","_hoisted_18","_d","ChangeComparison","_hoisted_19","_normalizeClass","_hoisted_20","$event","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_26","_hoisted_27","ConfirmDialog"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,2 +0,0 @@
1
- import{d as k,o as C,i as V,A as $,c as l,j as d,a as e,F as c,k as L,w as m,l as p,t as a,b as x,m as N,n as S,r as b,g as _,p as B,h as r,e as D,u as E}from"./index-Colfqb-9.js";import{_ as G}from"./PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js";const R={class:"mx-auto max-w-5xl space-y-6 px-4 py-6 sm:px-6"},T={key:0,class:"text-sm text-muted"},j={"aria-labelledby":"content-heading"},A={class:"grid grid-cols-2 gap-3 lg:grid-cols-4"},F={class:"text-sm text-muted"},M={class:"mt-1 text-[30px] font-light leading-9 tabular-nums"},H={class:"mt-1 text-xs text-muted"},O={class:"mt-1 text-[30px] font-light leading-9 tabular-nums"},q={class:"mt-1 text-xs text-muted"},z={key:0,class:"card p-4","aria-labelledby":"pending-heading"},I={class:"flex flex-wrap items-center justify-between gap-3"},J={id:"pending-heading",class:"text-sm font-semibold"},K={class:"card p-4","aria-labelledby":"repository-heading"},P={class:"mt-2 break-all font-mono text-xs text-muted"},X=k({__name:"DashboardView",setup(Q){const y=E(),u=N(),f=S(),n=b(null),h=b(!0),w=_(()=>{var o,v;const s=(v=(o=y.identity.value)==null?void 0:o.name)==null?void 0:v.split(" ")[0];if(!s)return"Overview";const t=new Date().getHours();return`${t<12?"Good morning":t<18?"Good afternoon":"Good evening"}, ${s}`}),g=_(()=>{var s;return(((s=n.value)==null?void 0:s.collections)??[]).reduce((t,i)=>t+i.total,0)});return C(async()=>{try{n.value=await V.overview()}catch(s){f.error(s instanceof $?s.message:"Could not load the overview.")}finally{h.value=!1}}),(s,t)=>{const i=B("RouterLink");return r(),l(c,null,[d(G,{title:w.value,subtitle:`${g.value} entr${g.value===1?"y":"ies"} in the content repository`},null,8,["title","subtitle"]),e("div",R,[h.value?(r(),l("p",T,"Loading…")):n.value?(r(),l(c,{key:1},[e("section",j,[t[1]||(t[1]=e("h2",{id:"content-heading",class:"sr-only"},"Content",-1)),e("ul",A,[(r(!0),l(c,null,L(n.value.collections,o=>(r(),l("li",{key:o.name},[d(i,{to:{name:"collection",params:{collection:o.name}},class:"card block p-4 transition hover:border-line-strong hover:bg-raised"},{default:m(()=>[e("p",F,a(o.label),1),e("p",M,a(o.total),1),e("p",H,a(o.total===1?"entry":"entries"),1)]),_:2},1032,["to"])]))),128)),e("li",null,[d(i,{to:{name:"media"},class:"card block p-4 transition hover:border-line-strong hover:bg-raised"},{default:m(()=>[t[0]||(t[0]=e("p",{class:"text-sm text-muted"},"Media",-1)),e("p",O,a(n.value.media.files),1),e("p",q,a(n.value.media.readable),1)]),_:1})])])]),p(u).editCount.value>0?(r(),l("section",z,[e("div",I,[e("div",null,[e("h2",J,a(p(u).editCount.value)+" edit"+a(p(u).editCount.value===1?"":"s")+" waiting to be published ",1),t[2]||(t[2]=e("p",{class:"mt-1 text-sm text-muted"}," Saved, and not yet in the repository. The whole set is published together. ",-1))]),d(i,{to:{name:"changes"},class:"btn-secondary"},{default:m(()=>[...t[3]||(t[3]=[D("Review and publish",-1)])]),_:1})])])):x("",!0),e("section",K,[t[4]||(t[4]=e("h2",{id:"repository-heading",class:"text-sm font-semibold"},"Content repository",-1)),e("p",P,a(n.value.repository),1),t[5]||(t[5]=e("p",{class:"mt-3 text-sm text-muted"}," Every entry and every uploaded file becomes a file in this repository when it is published, so the website can be rebuilt from the repository alone — with or without this server. ",-1))])],64)):x("",!0)])],64)}}});export{X as default};
2
- //# sourceMappingURL=DashboardView-JZ2Eaw1_.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DashboardView-JZ2Eaw1_.js","sources":["../../src/views/DashboardView.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Dashboard.\n *\n * Counts and where the content lives, and deliberately little else.\n *\n * One pending-changes card, because Saved and Published are different words\n * now and the difference should be visible from the front door. Still no\n * \"Rebuild website\" button: the published commit is the trigger, and what\n * follows belongs to the repository's own pipeline. No \"recently edited\" list\n * either — the honest source for that is the repository's history, which a\n * connector in front of a plain working tree cannot read, and a half-true\n * version would be worse than none.\n */\n\nimport { computed, onMounted, ref } from \"vue\";\n\nimport { api, ApiError, type Overview } from \"@/api\";\nimport PageHeader from \"@/components/PageHeader.vue\";\nimport { useSession } from \"@/stores/session\";\nimport { useStaging } from \"@/stores/staging\";\nimport { useToast } from \"@/stores/toast\";\n\nconst session = useSession();\nconst staging = useStaging();\nconst toast = useToast();\n\nconst overview = ref<Overview | null>(null);\nconst loading = ref(true);\n\n/**\n * Greeted by name only where somebody said what the name is.\n *\n * Local mode has no user, so there is nobody to greet — and \"Good morning,\n * there\" would be a greeting to an imaginary person, which is exactly the\n * synthetic local user this design does without.\n */\nconst greeting = computed(() => {\n const name = session.identity.value?.name?.split(\" \")[0];\n if (!name) return \"Overview\";\n\n const hour = new Date().getHours();\n const part = hour < 12 ? \"Good morning\" : hour < 18 ? \"Good afternoon\" : \"Good evening\";\n return `${part}, ${name}`;\n});\n\nconst entries = computed(() =>\n (overview.value?.collections ?? []).reduce((total, item) => total + item.total, 0),\n);\n\nonMounted(async () => {\n try {\n overview.value = await api.overview();\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not load the overview.\");\n } finally {\n loading.value = false;\n }\n});\n</script>\n\n<template>\n <PageHeader\n :title=\"greeting\"\n :subtitle=\"`${entries} entr${entries === 1 ? 'y' : 'ies'} in the content repository`\"\n />\n\n <div class=\"mx-auto max-w-5xl space-y-6 px-4 py-6 sm:px-6\">\n <p v-if=\"loading\" class=\"text-sm text-muted\">Loading…</p>\n\n <template v-else-if=\"overview\">\n <section aria-labelledby=\"content-heading\">\n <h2 id=\"content-heading\" class=\"sr-only\">Content</h2>\n\n <ul class=\"grid grid-cols-2 gap-3 lg:grid-cols-4\">\n <li v-for=\"collection in overview.collections\" :key=\"collection.name\">\n <RouterLink\n :to=\"{ name: 'collection', params: { collection: collection.name } }\"\n class=\"card block p-4 transition hover:border-line-strong hover:bg-raised\"\n >\n <p class=\"text-sm text-muted\">{{ collection.label }}</p>\n <p class=\"mt-1 text-[30px] font-light leading-9 tabular-nums\">{{ collection.total }}</p>\n <p class=\"mt-1 text-xs text-muted\">\n {{ collection.total === 1 ? \"entry\" : \"entries\" }}\n </p>\n </RouterLink>\n </li>\n\n <li>\n <RouterLink :to=\"{ name: 'media' }\" class=\"card block p-4 transition hover:border-line-strong hover:bg-raised\">\n <p class=\"text-sm text-muted\">Media</p>\n <p class=\"mt-1 text-[30px] font-light leading-9 tabular-nums\">{{ overview.media.files }}</p>\n <p class=\"mt-1 text-xs text-muted\">{{ overview.media.readable }}</p>\n </RouterLink>\n </li>\n </ul>\n </section>\n\n <section\n v-if=\"staging.editCount.value > 0\"\n class=\"card p-4\"\n aria-labelledby=\"pending-heading\"\n >\n <div class=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h2 id=\"pending-heading\" class=\"text-sm font-semibold\">\n {{ staging.editCount.value }} edit{{ staging.editCount.value === 1 ? \"\" : \"s\" }}\n waiting to be published\n </h2>\n <p class=\"mt-1 text-sm text-muted\">\n Saved, and not yet in the repository. The whole set is published together.\n </p>\n </div>\n <RouterLink :to=\"{ name: 'changes' }\" class=\"btn-secondary\">Review and publish</RouterLink>\n </div>\n </section>\n\n <section class=\"card p-4\" aria-labelledby=\"repository-heading\">\n <h2 id=\"repository-heading\" class=\"text-sm font-semibold\">Content repository</h2>\n\n <p class=\"mt-2 break-all font-mono text-xs text-muted\">{{ overview.repository }}</p>\n\n <p class=\"mt-3 text-sm text-muted\">\n Every entry and every uploaded file becomes a file in this repository when it is\n published, so the website can be rebuilt from the repository alone — with or without\n this server.\n </p>\n </section>\n </template>\n </div>\n</template>\n"],"names":["session","useSession","staging","useStaging","toast","useToast","overview","ref","loading","greeting","computed","name","_b","_a","hour","entries","total","item","onMounted","api","error","ApiError","_createVNode","PageHeader","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_Fragment","_hoisted_3","_hoisted_4","_openBlock","_renderList","collection","_component_RouterLink","_hoisted_5","_toDisplayString","_hoisted_6","_hoisted_7","_cache","_hoisted_8","_hoisted_9","_unref","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{d as J,o as K,A as f,c as n,j as N,w as z,a as l,F as w,b as x,t as o,k as M,z as O,B as P,n as Q,g as k,r as u,i as h,y as W,h as r,e as B,l as L,C as X,m as Z}from"./index-Colfqb-9.js";import{_ as ee}from"./ConfirmDialog.vue_vue_type_script_setup_true_lang-BhOQwoeA.js";import{u as te,d as se,_ as le}from"./useUnsavedChanges-B0WVqgI4.js";import{_ as ae}from"./PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js";import"./useField-BDSV5ZPo.js";import"./arrow-right-DJTAYrz5.js";import"./plus-D_aoCFbi.js";const ne=["disabled"],oe={class:"mx-auto max-w-3xl px-4 py-6 sm:px-6"},re={key:0,class:"text-sm text-muted"},ie={key:0,role:"alert",class:"mb-5 rounded-md border border-warning/15 bg-warning-soft p-4"},ue={key:1,role:"alert",class:"mb-5 rounded-md border border-danger/15 bg-danger-soft p-4"},ce={class:"text-sm font-medium text-danger"},de={class:"mt-1.5 space-y-0.5 text-xs text-danger"},me={key:2,class:"mt-10 border-t border-line pt-5"},ve={key:0,class:"mt-3 rounded-md border border-warning/15 bg-warning-soft p-4"},fe={class:"text-sm font-medium text-warning"},ge={class:"mt-1 list-inside list-disc text-xs"},ye={key:1,class:"p-8 text-center text-sm text-muted"},_e=J({__name:"EntryView",props:{collection:{},slug:{}},setup(g){const s=g,C=P(),T=W(),E=Z(),i=Q(),m=k(()=>T.collection(s.collection)),F=u(null),d=u({}),c=u([]),_=u(!0),y=u(!1),S=u(!1),b=u(!1),v=u([]),V=u(null),p=te(d),D=p.dirty,U=k(()=>!s.slug),A=k(()=>{const t=m.value;if(!t)return"Entry";const e=d.value[t.titleField];return typeof e=="string"&&e.trim()?e.trim():U.value?`New ${t.labelSingular.toLowerCase()}`:"Untitled"}),j=k(()=>{var t;return((t=F.value)==null?void 0:t.path)??"Not saved yet"});function R(t){F.value=t,d.value=structuredClone(t.data),V.value=t.revision,c.value=[],S.value=!1,p.markClean()}async function $(t){R(await h.entries.get(s.collection,t))}K(async()=>{const t=m.value;if(!t){_.value=!1;return}try{s.slug?await $(s.slug):(d.value=se(t.fields),V.value=null,p.markClean())}catch(e){i.error(e instanceof f?e.message:"Could not open this entry."),await C.replace({name:"collection",params:{collection:s.collection}})}finally{_.value=!1}});async function q(){y.value=!0,c.value=[];const t={data:d.value,revision:V.value};try{const e=s.slug?await h.entries.update(s.collection,s.slug,t):await h.entries.create(s.collection,t);if(p.markClean(),i.success(e.renamed?`Saved as “${e.slug}”.`:"Saved."),E.refresh(),e.slug!==s.slug){await C.replace({name:"entry",params:{collection:s.collection,slug:e.slug}});return}await $(e.slug)}catch(e){e instanceof f&&e.status===409?(S.value=!0,i.error("Someone else saved this entry while you were editing it.")):e instanceof f&&e.issues.length>0?(c.value=e.issues,i.error(e.message,`${e.issues.length} field(s) need attention.`),requestAnimationFrame(()=>{var a;(a=document.querySelector('[aria-invalid="true"], .field-error'))==null||a.scrollIntoView({behavior:"smooth",block:"center"})})):i.error(e instanceof f?e.message:"Could not save this entry.")}finally{y.value=!1}}async function I(){if(s.slug)try{await $(s.slug),i.success("Reloaded from the repository.")}catch(t){i.error(t instanceof f?t.message:"Could not reload this entry.")}}async function Y(){if(v.value=[],s.slug)try{const{references:t}=await h.entries.references(s.collection,s.slug);v.value=t.map(e=>{var a;return{collection:((a=T.collection(e.collection))==null?void 0:a.label)??e.collection,title:e.title}})}catch{}b.value=!0}async function G(){if(s.slug)try{await h.entries.remove(s.collection,s.slug),p.release(),i.success("Deleted."),E.refresh(),await C.replace({name:"collection",params:{collection:s.collection}})}catch(t){i.error(t instanceof f?t.message:"Could not delete this entry.")}finally{b.value=!1}}return(t,e)=>m.value?(r(),n(w,{key:0},[N(ae,{title:A.value,subtitle:j.value,back:{name:"collection",params:{collection:g.collection}},"back-label":m.value.label},{default:z(()=>[l("span",{class:X(["badge",L(D)?"border-accent bg-accent-soft text-accent":"text-success"])},[e[2]||(e[2]=l("span",{class:"h-1.5 w-1.5 rounded-full bg-current","aria-hidden":"true"},null,-1)),B(" "+o(L(D)?"Unsaved":"Saved"),1)],2),l("button",{type:"button",class:"btn-primary",disabled:y.value||!L(D),onClick:q},o(y.value?"Saving…":"Save changes"),9,ne)]),_:1},8,["title","subtitle","back","back-label"]),l("div",oe,[_.value?(r(),n("p",re,"Loading…")):(r(),n(w,{key:1},[S.value?(r(),n("div",ie,[e[3]||(e[3]=l("p",{class:"text-sm font-medium text-warning"},"This entry changed while you were editing",-1)),e[4]||(e[4]=l("p",{class:"mt-1 text-xs text-muted"}," Your changes are still here and have not been saved. Copy anything you need, then load the current version — or open the repository to see what changed. ",-1)),l("button",{type:"button",class:"btn-secondary mt-2.5",onClick:I}," Discard mine and reload ")])):x("",!0),c.value.length?(r(),n("div",ue,[l("p",ce,o(c.value.length)+" field"+o(c.value.length===1?"":"s")+" need attention ",1),l("ul",de,[(r(!0),n(w,null,M(c.value,a=>(r(),n("li",{key:a.path},o(a.message),1))),128))])])):x("",!0),l("form",{novalidate:"",onSubmit:O(q,["prevent"])},[N(le,{modelValue:d.value,"onUpdate:modelValue":e[0]||(e[0]=a=>d.value=a),fields:m.value.fields,issues:c.value,disabled:y.value,collection:g.collection,"entry-slug":g.slug},null,8,["modelValue","fields","issues","disabled","collection","entry-slug"]),e[5]||(e[5]=l("button",{type:"submit",class:"sr-only"},"Save",-1))],32),U.value?x("",!0):(r(),n("div",me,[l("button",{type:"button",class:"btn-danger",onClick:Y}," Delete this "+o(m.value.labelSingular.toLowerCase()),1)]))],64))]),N(ee,{open:b.value,title:`Delete “${A.value}”?`,"confirm-label":"Delete",destructive:"",onCancel:e[1]||(e[1]=a=>b.value=!1),onConfirm:G},{default:z(()=>[l("p",null,[e[6]||(e[6]=B(" This removes ",-1)),l("code",null,o(j.value),1),e[7]||(e[7]=B(". Like any edit, the removal joins the pending changes and reaches the repository when they are published. ",-1))]),v.value.length?(r(),n("div",ve,[l("p",fe,o(v.value.length)+" other entr"+o(v.value.length===1?"y":"ies")+" link to this one: ",1),l("ul",ge,[(r(!0),n(w,null,M(v.value,(a,H)=>(r(),n("li",{key:H},o(a.title)+" ("+o(a.collection)+") ",1))),128))])])):x("",!0)]),_:1},8,["open","title"])],64)):(r(),n("div",ye,' There is no collection called "'+o(g.collection)+'". ',1))}});export{_e as default};
2
- //# sourceMappingURL=EntryView-BwERaZkJ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EntryView-BwERaZkJ.js","sources":["../../src/views/EntryView.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Entry editor.\n *\n * One Save button, and Saved is not Published: a save lands in the site's\n * draft workspace and collects on the Publish page until somebody publishes\n * it. Unfinished work stays in this form and never reaches the server, which\n * is what the unsaved-changes guard is for.\n *\n * `revision` is how two editors stay out of each other's way. The form\n * remembers which version of the entry it opened and sends that token back with\n * the save. If someone else saved in the meantime the server answers 409, and\n * this view says so plainly rather than overwriting their work.\n *\n * An entry is addressed by its slug, so changing the slug field moves the entry\n * — files and all — and the route follows it.\n */\n\nimport { computed, onMounted, ref } from \"vue\";\nimport { useRouter } from \"vue-router\";\n\nimport { defaultValues, type FieldIssue } from \"@micacms/core\";\n\nimport { api, ApiError, type EntryDetail } from \"@/api\";\nimport ConfirmDialog from \"@/components/ConfirmDialog.vue\";\nimport FieldList from \"@/components/fields/FieldList.vue\";\nimport PageHeader from \"@/components/PageHeader.vue\";\nimport { useUnsavedChanges } from \"@/composables/useUnsavedChanges\";\nimport { useSchema } from \"@/stores/schema\";\nimport { useStaging } from \"@/stores/staging\";\nimport { useToast } from \"@/stores/toast\";\n\nconst props = defineProps<{ collection: string; slug?: string }>();\n\nconst router = useRouter();\nconst schema = useSchema();\nconst staging = useStaging();\nconst toast = useToast();\n\nconst definition = computed(() => schema.collection(props.collection));\n\nconst entry = ref<EntryDetail | null>(null);\nconst values = ref<Record<string, unknown>>({});\nconst issues = ref<FieldIssue[]>([]);\nconst loading = ref(true);\nconst saving = ref(false);\nconst conflict = ref(false);\nconst confirmDelete = ref(false);\nconst references = ref<Array<{ collection: string; title: string }>>([]);\n\n/**\n * The version this form was opened against.\n *\n * `null` on a new entry, which asserts to the server that nothing is there —\n * so two people creating the same slug is a conflict, not a silent overwrite.\n */\nconst revision = ref<string | null>(null);\n\nconst unsaved = useUnsavedChanges(values);\nconst dirty = unsaved.dirty;\n\nconst isNew = computed(() => !props.slug);\n\nconst title = computed(() => {\n const def = definition.value;\n if (!def) return \"Entry\";\n const value = values.value[def.titleField];\n if (typeof value === \"string\" && value.trim()) return value.trim();\n return isNew.value ? `New ${def.labelSingular.toLowerCase()}` : \"Untitled\";\n});\n\n/**\n * Where this entry lives in the repository — the path a reviewer will see.\n *\n * From the server, not assembled here: an entry with rich text or media is a\n * directory, and one without is a single `.json` file.\n */\nconst location = computed(() => entry.value?.path ?? \"Not saved yet\");\n\nfunction setBaseline(detail: EntryDetail): void {\n entry.value = detail;\n values.value = structuredClone(detail.data);\n revision.value = detail.revision;\n issues.value = [];\n conflict.value = false;\n unsaved.markClean();\n}\n\nasync function open(slug: string): Promise<void> {\n setBaseline(await api.entries.get(props.collection, slug));\n}\n\nonMounted(async () => {\n const def = definition.value;\n if (!def) {\n loading.value = false;\n return;\n }\n\n try {\n if (props.slug) {\n await open(props.slug);\n } else {\n // A fresh entry starts as a full skeleton so every input is bound. The\n // skeleton itself is not an edit, so it becomes the baseline.\n values.value = defaultValues(def.fields);\n revision.value = null;\n unsaved.markClean();\n }\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not open this entry.\");\n await router.replace({ name: \"collection\", params: { collection: props.collection } });\n } finally {\n loading.value = false;\n }\n});\n\nasync function save(): Promise<void> {\n saving.value = true;\n issues.value = [];\n\n const payload = { data: values.value, revision: revision.value };\n\n try {\n const saved = props.slug\n ? await api.entries.update(props.collection, props.slug, payload)\n : await api.entries.create(props.collection, payload);\n\n // The server owns the slug — it derives it, de-duplicates it, and may have\n // moved the entry. Re-open at whatever it decided rather than assuming.\n unsaved.markClean();\n toast.success(saved.renamed ? `Saved as “${saved.slug}”.` : \"Saved.\");\n void staging.refresh();\n\n if (saved.slug !== props.slug) {\n await router.replace({\n name: \"entry\",\n params: { collection: props.collection, slug: saved.slug },\n });\n return;\n }\n\n await open(saved.slug);\n } catch (error) {\n if (error instanceof ApiError && error.status === 409) {\n // Nothing is lost: the form still holds the editor's work, and reloading\n // is a deliberate act rather than something that happens under them.\n conflict.value = true;\n toast.error(\"Someone else saved this entry while you were editing it.\");\n } else if (error instanceof ApiError && error.issues.length > 0) {\n issues.value = error.issues;\n toast.error(error.message, `${error.issues.length} field(s) need attention.`);\n // Take the editor to the first problem rather than leaving them hunting.\n requestAnimationFrame(() => {\n document\n .querySelector('[aria-invalid=\"true\"], .field-error')\n ?.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n });\n } else {\n toast.error(error instanceof ApiError ? error.message : \"Could not save this entry.\");\n }\n } finally {\n saving.value = false;\n }\n}\n\n/** Takes the version now in the repository, discarding this form's edits. */\nasync function reload(): Promise<void> {\n if (!props.slug) return;\n try {\n await open(props.slug);\n toast.success(\"Reloaded from the repository.\");\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not reload this entry.\");\n }\n}\n\nasync function askDelete(): Promise<void> {\n references.value = [];\n if (props.slug) {\n try {\n const { references: found } = await api.entries.references(props.collection, props.slug);\n references.value = found.map((item) => ({\n collection: schema.collection(item.collection)?.label ?? item.collection,\n title: item.title,\n }));\n } catch {\n // The warning is a courtesy; a failure to fetch it must not block deletion.\n }\n }\n confirmDelete.value = true;\n}\n\nasync function remove(): Promise<void> {\n if (!props.slug) return;\n try {\n await api.entries.remove(props.collection, props.slug);\n unsaved.release();\n toast.success(\"Deleted.\");\n void staging.refresh();\n await router.replace({ name: \"collection\", params: { collection: props.collection } });\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not delete this entry.\");\n } finally {\n confirmDelete.value = false;\n }\n}\n</script>\n\n<template>\n <template v-if=\"definition\">\n <PageHeader\n :title=\"title\"\n :subtitle=\"location\"\n :back=\"{ name: 'collection', params: { collection } }\"\n :back-label=\"definition.label\"\n >\n <span :class=\"['badge', dirty ? 'border-accent bg-accent-soft text-accent' : 'text-success']\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-current\" aria-hidden=\"true\" />\n {{ dirty ? \"Unsaved\" : \"Saved\" }}\n </span>\n <button type=\"button\" class=\"btn-primary\" :disabled=\"saving || !dirty\" @click=\"save\">\n {{ saving ? \"Saving…\" : \"Save changes\" }}\n </button>\n </PageHeader>\n\n <div class=\"mx-auto max-w-3xl px-4 py-6 sm:px-6\">\n <p v-if=\"loading\" class=\"text-sm text-muted\">Loading…</p>\n\n <template v-else>\n <div\n v-if=\"conflict\"\n role=\"alert\"\n class=\"mb-5 rounded-md border border-warning/15 bg-warning-soft p-4\"\n >\n <p class=\"text-sm font-medium text-warning\">This entry changed while you were editing</p>\n <p class=\"mt-1 text-xs text-muted\">\n Your changes are still here and have not been saved. Copy anything you need, then load\n the current version — or open the repository to see what changed.\n </p>\n <button type=\"button\" class=\"btn-secondary mt-2.5\" @click=\"reload\">\n Discard mine and reload\n </button>\n </div>\n\n <div\n v-if=\"issues.length\"\n role=\"alert\"\n class=\"mb-5 rounded-md border border-danger/15 bg-danger-soft p-4\"\n >\n <p class=\"text-sm font-medium text-danger\">\n {{ issues.length }} field{{ issues.length === 1 ? \"\" : \"s\" }} need attention\n </p>\n <ul class=\"mt-1.5 space-y-0.5 text-xs text-danger\">\n <li v-for=\"issue in issues\" :key=\"issue.path\">{{ issue.message }}</li>\n </ul>\n </div>\n\n <form novalidate @submit.prevent=\"save\">\n <FieldList\n v-model=\"values\"\n :fields=\"definition.fields\"\n :issues=\"issues\"\n :disabled=\"saving\"\n :collection=\"collection\"\n :entry-slug=\"slug\"\n />\n\n <!-- Enter in a text input should save, not do nothing. -->\n <button type=\"submit\" class=\"sr-only\">Save</button>\n </form>\n\n <div v-if=\"!isNew\" class=\"mt-10 border-t border-line pt-5\">\n <button type=\"button\" class=\"btn-danger\" @click=\"askDelete\">\n Delete this {{ definition.labelSingular.toLowerCase() }}\n </button>\n </div>\n </template>\n </div>\n\n <ConfirmDialog\n :open=\"confirmDelete\"\n :title=\"`Delete “${title}”?`\"\n confirm-label=\"Delete\"\n destructive\n @cancel=\"confirmDelete = false\"\n @confirm=\"remove\"\n >\n <!-- Honest about what a delete is now: a pending change. It reaches the\n repository's history when the pending set is published, and the\n history keeps it from then on. -->\n <p>\n This removes <code>{{ location }}</code>. Like any edit, the removal joins the pending\n changes and reaches the repository when they are published.\n </p>\n\n <div v-if=\"references.length\" class=\"mt-3 rounded-md border border-warning/15 bg-warning-soft p-4\">\n <p class=\"text-sm font-medium text-warning\">\n {{ references.length }} other entr{{ references.length === 1 ? \"y\" : \"ies\" }} link to this\n one:\n </p>\n <ul class=\"mt-1 list-inside list-disc text-xs\">\n <li v-for=\"(item, index) in references\" :key=\"index\">\n {{ item.title }} ({{ item.collection }})\n </li>\n </ul>\n </div>\n </ConfirmDialog>\n </template>\n\n <div v-else class=\"p-8 text-center text-sm text-muted\">\n There is no collection called \"{{ collection }}\".\n </div>\n</template>\n"],"names":["props","__props","router","useRouter","schema","useSchema","staging","useStaging","toast","useToast","definition","computed","entry","ref","values","issues","loading","saving","conflict","confirmDelete","references","revision","unsaved","useUnsavedChanges","dirty","isNew","title","def","value","location","_a","setBaseline","detail","open","slug","api","onMounted","defaultValues","error","ApiError","save","payload","saved","reload","askDelete","found","item","remove","_createElementBlock","_Fragment","_createVNode","PageHeader","_createElementVNode","_unref","_createTextVNode","_hoisted_1","_hoisted_2","_hoisted_3","_openBlock","_hoisted_4","_cache","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","_renderList","issue","FieldList","$event","_hoisted_8","ConfirmDialog","_hoisted_9","_hoisted_10","_hoisted_11","index","_hoisted_12"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{d as D,o as U,q as $,c as a,j as N,w as z,a as s,F as _,t as l,b as w,k as A,z as E,g as F,r as i,i as T,A as p,n as L,h as n,e as M,l as h,C as j,m as q,y as G}from"./index-Colfqb-9.js";import{u as H,_ as I,w as J}from"./useUnsavedChanges-B0WVqgI4.js";import{_ as K}from"./PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js";import"./useField-BDSV5ZPo.js";import"./arrow-right-DJTAYrz5.js";import"./plus-D_aoCFbi.js";const O=["disabled"],P={class:"mx-auto max-w-3xl px-4 py-6 sm:px-6"},Q={key:0,class:"text-sm text-muted"},R={key:0,class:"mb-5 text-sm text-muted"},W={key:1,role:"alert",class:"mb-5 rounded-md border border-warning/15 bg-warning-soft p-4"},X={key:2,role:"alert",class:"mb-5 rounded-md border border-danger/15 bg-danger-soft p-4"},Y={class:"text-sm font-medium text-danger"},Z={class:"mt-1.5 space-y-0.5 text-xs text-danger"},ee={key:1,class:"p-8 text-center text-sm text-muted"},ie=D({__name:"SingletonView",props:{name:{}},setup(k){const m=k,B=G(),u=L(),r=F(()=>B.singleton(m.name)),d=i({}),o=i([]),b=i(null),y=i(!0),c=i(!1),v=i(!1),C=i(""),{dirty:g,markClean:S}=H(d);async function x(){var t;y.value=!0;try{const e=await T.singletons.get(m.name);d.value=structuredClone(J(((t=r.value)==null?void 0:t.fields)??{},e.data)),b.value=e.revision,C.value=e.path,o.value=[],v.value=!1,S()}catch(e){u.error(e instanceof p?e.message:"Could not load these settings.")}finally{y.value=!1}}U(x),$(()=>m.name,x);async function V(){c.value=!0,o.value=[];try{const t=await T.singletons.save(m.name,d.value,b.value);b.value=t.revision,v.value=!1,S(),u.success("Settings saved."),q().refresh()}catch(t){t instanceof p&&t.status===409?(v.value=!0,u.error("Someone else saved these settings while you were editing them.")):t instanceof p&&t.issues.length>0?(o.value=t.issues,u.error(t.message,`${t.issues.length} field(s) need attention.`)):u.error(t instanceof p?t.message:"Could not save these settings.")}finally{c.value=!1}}return(t,e)=>r.value?(n(),a(_,{key:0},[N(K,{title:r.value.label,subtitle:C.value},{default:z(()=>[s("span",{class:j(["badge",h(g)?"border-accent bg-accent-soft text-accent":"text-success"])},[e[1]||(e[1]=s("span",{class:"h-1.5 w-1.5 rounded-full bg-current","aria-hidden":"true"},null,-1)),M(" "+l(h(g)?"Unsaved":"Saved"),1)],2),s("button",{type:"button",class:"btn-primary",disabled:c.value||!h(g),onClick:V},l(c.value?"Saving…":h(g)?"Save changes":"Saved"),9,O)]),_:1},8,["title","subtitle"]),s("div",P,[y.value?(n(),a("p",Q,"Loading…")):(n(),a(_,{key:1},[r.value.description?(n(),a("p",R,l(r.value.description),1)):w("",!0),v.value?(n(),a("div",W,[e[2]||(e[2]=s("p",{class:"text-sm font-medium text-warning"},"These settings changed while you were editing",-1)),e[3]||(e[3]=s("p",{class:"mt-1 text-xs text-muted"}," Nothing has been saved. Copy anything you need, then load the current version. ",-1)),s("button",{type:"button",class:"btn-secondary mt-2.5",onClick:x}," Discard mine and reload ")])):w("",!0),o.value.length?(n(),a("div",X,[s("p",Y,l(o.value.length)+" field"+l(o.value.length===1?"":"s")+" need attention ",1),s("ul",Z,[(n(!0),a(_,null,A(o.value,f=>(n(),a("li",{key:f.path},l(f.message),1))),128))])])):w("",!0),s("form",{novalidate:"",onSubmit:E(V,["prevent"])},[N(I,{modelValue:d.value,"onUpdate:modelValue":e[0]||(e[0]=f=>d.value=f),fields:r.value.fields,issues:o.value,disabled:c.value},null,8,["modelValue","fields","issues","disabled"]),e[4]||(e[4]=s("button",{type:"submit",class:"sr-only"},"Save",-1))],32)],64))])],64)):(n(),a("div",ee,' There are no settings called "'+l(k.name)+'". ',1))}});export{ie as default};
2
- //# sourceMappingURL=SingletonView-BNJCcl7V.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SingletonView-BNJCcl7V.js","sources":["../../src/views/SingletonView.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Singleton editor — site configuration, navigation, theme.\n *\n * A singleton is one file in the repository, so this view is the entry editor\n * without the parts that need a slug: no rename, no delete, no list to go back\n * to. What it shares is `revision` — the version the form was opened against,\n * sent back with the save so a second editor cannot be overwritten in silence.\n */\n\nimport { computed, onMounted, ref, watch } from \"vue\";\n\nimport { withDefaults as fillDefaults, type FieldIssue } from \"@micacms/core\";\n\nimport { api, ApiError } from \"@/api\";\nimport FieldList from \"@/components/fields/FieldList.vue\";\nimport PageHeader from \"@/components/PageHeader.vue\";\nimport { useUnsavedChanges } from \"@/composables/useUnsavedChanges\";\nimport { useSchema } from \"@/stores/schema\";\nimport { useStaging } from \"@/stores/staging\";\nimport { useToast } from \"@/stores/toast\";\n\nconst props = defineProps<{ name: string }>();\n\nconst schema = useSchema();\nconst toast = useToast();\n\nconst definition = computed(() => schema.singleton(props.name));\n\nconst values = ref<Record<string, unknown>>({});\nconst issues = ref<FieldIssue[]>([]);\nconst revision = ref<string | null>(null);\nconst loading = ref(true);\nconst saving = ref(false);\nconst conflict = ref(false);\n\n/** Where these settings live, as the server reports it. */\nconst location = ref(\"\");\n\nconst { dirty, markClean } = useUnsavedChanges(values);\n\nasync function load(): Promise<void> {\n loading.value = true;\n try {\n const detail = await api.singletons.get(props.name);\n // Defaults fill in fields added to the model since the file was written.\n values.value = structuredClone(fillDefaults(definition.value?.fields ?? {}, detail.data));\n revision.value = detail.revision;\n location.value = detail.path;\n issues.value = [];\n conflict.value = false;\n markClean();\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not load these settings.\");\n } finally {\n loading.value = false;\n }\n}\n\nonMounted(load);\nwatch(() => props.name, load);\n\nasync function save(): Promise<void> {\n saving.value = true;\n issues.value = [];\n\n try {\n const saved = await api.singletons.save(props.name, values.value, revision.value);\n revision.value = saved.revision;\n conflict.value = false;\n markClean();\n toast.success(\"Settings saved.\");\n void useStaging().refresh();\n } catch (error) {\n if (error instanceof ApiError && error.status === 409) {\n conflict.value = true;\n toast.error(\"Someone else saved these settings while you were editing them.\");\n } else if (error instanceof ApiError && error.issues.length > 0) {\n issues.value = error.issues;\n toast.error(error.message, `${error.issues.length} field(s) need attention.`);\n } else {\n toast.error(error instanceof ApiError ? error.message : \"Could not save these settings.\");\n }\n } finally {\n saving.value = false;\n }\n}\n</script>\n\n<template>\n <template v-if=\"definition\">\n <PageHeader :title=\"definition.label\" :subtitle=\"location\">\n <span :class=\"['badge', dirty ? 'border-accent bg-accent-soft text-accent' : 'text-success']\">\n <span class=\"h-1.5 w-1.5 rounded-full bg-current\" aria-hidden=\"true\" />\n {{ dirty ? \"Unsaved\" : \"Saved\" }}\n </span>\n <button type=\"button\" class=\"btn-primary\" :disabled=\"saving || !dirty\" @click=\"save\">\n {{ saving ? \"Saving…\" : dirty ? \"Save changes\" : \"Saved\" }}\n </button>\n </PageHeader>\n\n <div class=\"mx-auto max-w-3xl px-4 py-6 sm:px-6\">\n <p v-if=\"loading\" class=\"text-sm text-muted\">Loading…</p>\n\n <template v-else>\n <p v-if=\"definition.description\" class=\"mb-5 text-sm text-muted\">\n {{ definition.description }}\n </p>\n\n <div\n v-if=\"conflict\"\n role=\"alert\"\n class=\"mb-5 rounded-md border border-warning/15 bg-warning-soft p-4\"\n >\n <p class=\"text-sm font-medium text-warning\">These settings changed while you were editing</p>\n <p class=\"mt-1 text-xs text-muted\">\n Nothing has been saved. Copy anything you need, then load the current version.\n </p>\n <button type=\"button\" class=\"btn-secondary mt-2.5\" @click=\"load\">\n Discard mine and reload\n </button>\n </div>\n\n <div\n v-if=\"issues.length\"\n role=\"alert\"\n class=\"mb-5 rounded-md border border-danger/15 bg-danger-soft p-4\"\n >\n <p class=\"text-sm font-medium text-danger\">\n {{ issues.length }} field{{ issues.length === 1 ? \"\" : \"s\" }} need attention\n </p>\n <ul class=\"mt-1.5 space-y-0.5 text-xs text-danger\">\n <li v-for=\"issue in issues\" :key=\"issue.path\">{{ issue.message }}</li>\n </ul>\n </div>\n\n <form novalidate @submit.prevent=\"save\">\n <FieldList\n v-model=\"values\"\n :fields=\"definition.fields\"\n :issues=\"issues\"\n :disabled=\"saving\"\n />\n <button type=\"submit\" class=\"sr-only\">Save</button>\n </form>\n </template>\n </div>\n </template>\n\n <div v-else class=\"p-8 text-center text-sm text-muted\">\n There are no settings called \"{{ name }}\".\n </div>\n</template>\n"],"names":["props","__props","schema","useSchema","toast","useToast","definition","computed","values","ref","issues","revision","loading","saving","conflict","location","dirty","markClean","useUnsavedChanges","load","detail","api","fillDefaults","_a","error","ApiError","onMounted","watch","save","saved","useStaging","_createElementBlock","_Fragment","_createVNode","PageHeader","_createElementVNode","_unref","_createTextVNode","_toDisplayString","_hoisted_1","_hoisted_2","_hoisted_3","_openBlock","_hoisted_4","_hoisted_5","_cache","_hoisted_6","_hoisted_7","_hoisted_8","_renderList","issue","FieldList","$event","_hoisted_9"],"mappings":"s8BAsBA,MAAMA,EAAQC,EAERC,EAASC,EAAA,EACTC,EAAQC,EAAA,EAERC,EAAaC,EAAS,IAAML,EAAO,UAAUF,EAAM,IAAI,CAAC,EAExDQ,EAASC,EAA6B,EAAE,EACxCC,EAASD,EAAkB,EAAE,EAC7BE,EAAWF,EAAmB,IAAI,EAClCG,EAAUH,EAAI,EAAI,EAClBI,EAASJ,EAAI,EAAK,EAClBK,EAAWL,EAAI,EAAK,EAGpBM,EAAWN,EAAI,EAAE,EAEjB,CAAE,MAAAO,EAAO,UAAAC,GAAcC,EAAkBV,CAAM,EAErD,eAAeW,GAAsB,OACnCP,EAAQ,MAAQ,GAChB,GAAI,CACF,MAAMQ,EAAS,MAAMC,EAAI,WAAW,IAAIrB,EAAM,IAAI,EAElDQ,EAAO,MAAQ,gBAAgBc,IAAaC,EAAAjB,EAAW,QAAX,YAAAiB,EAAkB,SAAU,CAAA,EAAIH,EAAO,IAAI,CAAC,EACxFT,EAAS,MAAQS,EAAO,SACxBL,EAAS,MAAQK,EAAO,KACxBV,EAAO,MAAQ,CAAA,EACfI,EAAS,MAAQ,GACjBG,EAAA,CACF,OAASO,EAAO,CACdpB,EAAM,MAAMoB,aAAiBC,EAAWD,EAAM,QAAU,gCAAgC,CAC1F,QAAA,CACEZ,EAAQ,MAAQ,EAClB,CACF,CAEAc,EAAUP,CAAI,EACdQ,EAAM,IAAM3B,EAAM,KAAMmB,CAAI,EAE5B,eAAeS,GAAsB,CACnCf,EAAO,MAAQ,GACfH,EAAO,MAAQ,CAAA,EAEf,GAAI,CACF,MAAMmB,EAAQ,MAAMR,EAAI,WAAW,KAAKrB,EAAM,KAAMQ,EAAO,MAAOG,EAAS,KAAK,EAChFA,EAAS,MAAQkB,EAAM,SACvBf,EAAS,MAAQ,GACjBG,EAAA,EACAb,EAAM,QAAQ,iBAAiB,EAC1B0B,EAAA,EAAa,QAAA,CACpB,OAASN,EAAO,CACVA,aAAiBC,GAAYD,EAAM,SAAW,KAChDV,EAAS,MAAQ,GACjBV,EAAM,MAAM,gEAAgE,GACnEoB,aAAiBC,GAAYD,EAAM,OAAO,OAAS,GAC5Dd,EAAO,MAAQc,EAAM,OACrBpB,EAAM,MAAMoB,EAAM,QAAS,GAAGA,EAAM,OAAO,MAAM,2BAA2B,GAE5EpB,EAAM,MAAMoB,aAAiBC,EAAWD,EAAM,QAAU,gCAAgC,CAE5F,QAAA,CACEX,EAAO,MAAQ,EACjB,CACF,cAIkBP,EAAA,WAAhByB,EAyDWC,EAAA,CAAA,IAAA,GAAA,CAxDTC,EAQaC,EAAA,CARA,MAAO5B,EAAA,MAAW,MAAQ,SAAUS,EAAA,KAAA,aAC/C,IAGO,CAHPoB,EAGO,OAAA,CAHA,iBAAiBC,EAAApB,CAAA,EAAK,2CAAA,cAAA,CAAA,CAAA,eAC3BmB,EAAuE,OAAA,CAAjE,MAAM,sCAAsC,cAAY,MAAA,YAASE,EAAA,MACpED,EAAApB,CAAA,EAAK,UAAA,OAAA,EAAA,CAAA,CAAA,KAEVmB,EAES,SAAA,CAFD,KAAK,SAAS,MAAM,cAAe,SAAUtB,EAAA,OAAM,CAAKuB,EAAApB,CAAA,EAAQ,QAAOY,CAAA,EAC1EU,EAAAzB,EAAA,gBAAqBuB,EAAApB,CAAA,EAAK,eAAA,OAAA,EAAA,EAAAuB,CAAA,CAAA,gCAIjCJ,EA6CM,MA7CNK,EA6CM,CA5CK5B,EAAA,WAATmB,EAAyD,IAAzDU,EAA6C,UAAQ,QAErDV,EAyCWC,EAAA,CAAA,IAAA,GAAA,CAxCA1B,EAAA,MAAW,aAApBoC,EAAA,EAAAX,EAEI,IAFJY,EAEIL,EADChC,EAAA,MAAW,WAAW,EAAA,CAAA,YAInBQ,EAAA,OADR4B,EAAA,EAAAX,EAYM,MAZNa,EAYM,CAPJC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAA6F,IAAA,CAA1F,MAAM,kCAAA,EAAmC,gDAA6C,EAAA,GACzFU,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAEI,IAAA,CAFD,MAAM,yBAAA,EAA0B,mFAEnC,EAAA,GACAA,EAES,SAAA,CAFD,KAAK,SAAS,MAAM,uBAAwB,QAAOhB,CAAA,EAAM,2BAEjE,CAAA,aAIMT,EAAA,MAAO,QADfgC,IAAAX,EAWM,MAXNe,EAWM,CANJX,EAEI,IAFJY,EAEIT,EADC5B,EAAA,MAAO,MAAM,EAAG,SAAM4B,EAAG5B,EAAA,MAAO,mBAA0B,mBAC/D,CAAA,EACAyB,EAEK,KAFLa,EAEK,QADHjB,EAAsEC,EAAA,KAAAiB,EAAlDvC,EAAA,MAATwC,QAAXnB,EAAsE,KAAA,CAAzC,IAAKmB,EAAM,IAAA,EAASZ,EAAAY,EAAM,OAAO,EAAA,CAAA,wBAIlEf,EAQO,OAAA,CARD,WAAA,GAAY,WAAgBP,EAAI,CAAA,SAAA,CAAA,CAAA,GACpCK,EAKEkB,EAAA,YAJS3C,EAAA,2CAAAA,EAAM,MAAA4C,GACd,OAAQ9C,EAAA,MAAW,OACnB,OAAQI,EAAA,MACR,SAAUG,EAAA,KAAA,kEAEbsB,EAAmD,SAAA,CAA3C,KAAK,SAAS,MAAM,SAAA,EAAU,OAAI,EAAA,EAAA,qBAMlDO,EAAA,EAAAX,EAEM,MAFNsB,GAAuD,kCACvBf,EAAGrC,EAAA,IAAI,EAAG,MAC1C,CAAA"}
@@ -1,3 +0,0 @@
1
- import{d as L,o as M,c as a,j as p,w as b,a as t,F as r,t as o,l as m,k as y,b as i,r as w,i as U,A as B,n as E,h as d,G as I,e as v,g as k,p as N,Y as O}from"./index-Colfqb-9.js";import{_ as V}from"./PageHeader.vue_vue_type_script_setup_true_lang-B-fBJAjn.js";import{a as $,b as D,f as x}from"./format-Cpnr2As6.js";import{A as F}from"./arrow-right-DJTAYrz5.js";const j=["disabled"],z=["disabled"],H={class:"mx-auto max-w-5xl space-y-6 px-4 py-5 pb-12 sm:px-6"},q={key:0,class:"text-sm text-muted"},P={"aria-labelledby":"glance-heading"},Y={class:"grid grid-cols-2 gap-3 lg:grid-cols-4"},G={class:"card p-4"},K={class:"mt-1 text-2xl font-semibold tabular-nums"},W={class:"mt-1 text-xs text-muted"},Z={class:"card p-4"},J={class:"mt-1 text-2xl font-semibold tabular-nums"},Q={class:"mt-1 text-xs text-muted"},X=["datetime"],tt={class:"card p-4"},et={class:"mt-1 text-2xl font-semibold tabular-nums"},st={class:"mt-1 text-xs text-muted"},ot={class:"card p-4"},lt={class:"mt-1 text-2xl font-semibold tabular-nums"},nt={class:"mt-1 text-xs text-muted"},at={class:"card p-4","aria-labelledby":"model-heading"},dt={class:"spec mt-3"},it={class:"tabular-nums"},rt={class:"mt-2 space-y-1.5"},ut={class:"w-28 shrink-0 truncate"},mt={class:"h-1.5 min-w-0 flex-1 rounded-full bg-canvas","aria-hidden":"true"},ct={class:"w-8 shrink-0 text-right text-xs tabular-nums text-muted"},pt={class:"card overflow-hidden","aria-labelledby":"collections-heading"},yt={class:"overflow-x-auto"},ht={class:"w-full text-sm"},bt={class:"divide-y divide-line"},vt={class:"px-4 py-2.5"},xt={class:"mono block text-muted"},ft={class:"px-4 py-2.5 text-right tabular-nums"},gt={class:"px-4 py-2.5 text-right tabular-nums"},_t={key:0,class:"block text-xs text-muted"},wt={class:"mono hidden px-4 py-2.5 text-muted sm:table-cell"},kt={class:"hidden px-4 py-2.5 text-xs text-muted sm:table-cell"},$t={key:0,class:"card p-4","aria-labelledby":"singletons-heading"},Ct={class:"spec mt-3"},Rt={class:"tabular-nums"},St={key:1,class:"card p-4","aria-labelledby":"relations-heading"},At={class:"mt-3 space-y-1.5 text-sm"},Tt={class:"font-medium"},Lt={class:"mono text-muted"},Mt={key:0,class:"badge bg-accent-soft text-accent"},Ut={class:"card p-4","aria-labelledby":"repository-heading"},Bt={class:"spec mt-3"},Et={class:"mono"},It={class:"tabular-nums"},Nt={class:"tabular-nums"},Ot={key:2,class:"card p-4","aria-labelledby":"database-heading"},Vt={class:"spec mt-3"},Dt={class:"mono"},Ft={class:"tabular-nums"},jt={class:"card p-4","aria-labelledby":"deployment-heading"},zt={key:0,class:"mt-3 rounded-md border border-warning/15 bg-warning-soft px-4 py-3 text-xs text-warning"},Ht={class:"spec mt-3"},qt={class:"mono"},Pt={class:"mono"},Yt={class:"mono"},Gt={key:0},Kt={class:"mono"},Wt={class:"tabular-nums"},Zt={class:"tabular-nums"},Jt={class:"mono"},Qt={key:1},Xt={class:"mono"},te={key:2},ee={class:"tabular-nums"},se={key:3},oe={class:"mono"},le=L({__name:"SystemView",setup(ne){const h=E(),s=w(null),c=w(!0);async function f(){c.value=!0;try{s.value=await U.system()}catch(l){h.error(l instanceof B?l.message:"Could not load the system information.")}finally{c.value=!1}}M(f);const g={url:"URL"};function C(l){if(g[l])return g[l];const e=l.replace(/([A-Z])/g," $1").toLowerCase();return e.charAt(0).toUpperCase()+e.slice(1)}const R=k(()=>{var l;return Math.max(1,...(((l=s.value)==null?void 0:l.schema.kinds)??[]).map(e=>e.count))}),_=k(()=>{var e,u;const l=new Map;for(const n of((e=s.value)==null?void 0:e.schema.collections)??[])l.set(`collection:${n.name}`,n.label);for(const n of((u=s.value)==null?void 0:u.schema.singletons)??[])l.set(`singleton:${n.name}`,n.label);return l});function S(l){return _.value.get(`collection:${l}`)??l}function A(){const l=s.value;return l?[`Mica ${l.cms.version} (${l.cms.environment})`,`Node ${l.cms.node} on ${l.cms.platform}, up ${$(l.cms.uptimeSeconds)}`,`Schema — ${l.schema.totals.collections} collections, ${l.schema.totals.singletons} singletons, ${l.schema.totals.total} fields`,`Repository ${l.repository.origin}`,`Repository holds ${l.repository.entries} entries and ${l.repository.media.files} media files (${l.repository.media.readable})`,l.database?`Database: migration ${l.database.version}, ${l.database.bytes===null?"size unknown":x(l.database.bytes)}`:"Database: none — the local editor keeps no state",`Site ${l.deployment.site}`,`Base URL ${l.deployment.baseUrl}`,`Content model ${l.deployment.schemaOrigin}`,`Content root ${l.deployment.contentRoot}`,`Authentication ${l.deployment.auth}`,`Admission ${l.deployment.admission??"none"}`].join(`
2
- `):""}async function T(){try{await navigator.clipboard.writeText(A()),h.success("Report copied to the clipboard.")}catch{h.error("Could not copy. Select the values you need instead.")}}return(l,e)=>{const u=N("RouterLink");return d(),a(r,null,[p(V,{title:"System",subtitle:s.value?`Mica ${s.value.cms.version} · ${s.value.cms.environment}`:null},{default:b(()=>[t("button",{type:"button",class:"btn-ghost",disabled:c.value,onClick:f},"Refresh",8,j),t("button",{type:"button",class:"btn-secondary",disabled:!s.value,onClick:T}," Copy report ",8,z)]),_:1},8,["subtitle"]),t("div",H,[c.value?(d(),a("p",q,"Loading…")):s.value?(d(),a(r,{key:1},[t("section",P,[e[4]||(e[4]=t("h2",{id:"glance-heading",class:"sr-only"},"At a glance",-1)),t("dl",Y,[t("div",G,[e[0]||(e[0]=t("dt",{class:"text-sm text-muted"},"Version",-1)),t("dd",K,o(s.value.cms.version),1),t("dd",W,o(s.value.cms.environment),1)]),t("div",Z,[e[1]||(e[1]=t("dt",{class:"text-sm text-muted"},"Uptime",-1)),t("dd",J,o(m($)(s.value.cms.uptimeSeconds)),1),t("dd",Q,[t("time",{datetime:s.value.cms.startedAt},o(m(D)(s.value.cms.startedAt)),9,X)])]),t("div",tt,[e[2]||(e[2]=t("dt",{class:"text-sm text-muted"},"Content model",-1)),t("dd",et,o(s.value.schema.totals.total),1),t("dd",st," fields in "+o(s.value.schema.totals.collections)+" collections, "+o(s.value.schema.totals.singletons)+" singletons ",1)]),t("div",ot,[e[3]||(e[3]=t("dt",{class:"text-sm text-muted"},"In the repository",-1)),t("dd",lt,o(s.value.repository.entries),1),t("dd",nt," entries · "+o(s.value.repository.media.files)+" media files ",1)])])]),t("section",at,[e[6]||(e[6]=t("h2",{id:"model-heading",class:"text-sm font-semibold"},"Content model",-1)),e[7]||(e[7]=t("p",{class:"mt-1 text-xs text-muted"}," The schema this server was handed at startup. The same file describes the model to the Astro build, so the editor and the website cannot disagree about it. ",-1)),t("dl",dt,[t("div",null,[e[5]||(e[5]=t("dt",null,"Required fields",-1)),t("dd",it,o(s.value.schema.totals.required)+" of "+o(s.value.schema.totals.total),1)])]),e[8]||(e[8]=t("h3",{class:"mt-5 text-xs font-semibold uppercase tracking-wider text-muted"},"Field types",-1)),t("ul",rt,[(d(!0),a(r,null,y(s.value.schema.kinds,n=>(d(),a("li",{key:n.kind,class:"flex items-center gap-3 text-sm"},[t("span",ut,o(C(n.kind)),1),t("span",mt,[t("span",{class:"block h-full rounded-full bg-accent/60",style:I({width:`${n.count/R.value*100}%`})},null,4)]),t("span",ct,o(n.count),1)]))),128))])]),t("section",pt,[e[11]||(e[11]=t("h2",{id:"collections-heading",class:"border-b border-line px-4 py-3 text-sm font-semibold"}," Collections ",-1)),t("div",yt,[t("table",ht,[e[9]||(e[9]=t("caption",{class:"sr-only"},"Collections in the content model, with their entry counts",-1)),e[10]||(e[10]=t("thead",null,[t("tr",{class:"border-b border-line text-left text-xs text-muted"},[t("th",{scope:"col",class:"px-4 py-2 font-medium"},"Collection"),t("th",{scope:"col",class:"px-4 py-2 text-right font-medium"},"Entries"),t("th",{scope:"col",class:"px-4 py-2 text-right font-medium"},"Fields"),t("th",{scope:"col",class:"hidden px-4 py-2 font-medium sm:table-cell"},"Title / slug"),t("th",{scope:"col",class:"hidden px-4 py-2 font-medium sm:table-cell"},"Ordering")])],-1)),t("tbody",bt,[(d(!0),a(r,null,y(s.value.schema.collections,n=>(d(),a("tr",{key:n.name},[t("td",vt,[p(u,{to:{name:"collection",params:{collection:n.name}},class:"font-medium hover:text-accent"},{default:b(()=>[v(o(n.label),1)]),_:2},1032,["to"]),t("span",xt,o(n.name),1)]),t("td",ft,o(n.entries),1),t("td",gt,[v(o(n.fields.top)+" ",1),n.fields.total>n.fields.top?(d(),a("span",_t,o(n.fields.total)+" with nested ",1)):i("",!0)]),t("td",wt,o(n.titleField??"—")+" / "+o(n.slugField??"—"),1),t("td",kt,o(n.sortable?"Manual":"Automatic"),1)]))),128))])])])]),s.value.schema.singletons.length?(d(),a("section",$t,[e[12]||(e[12]=t("h2",{id:"singletons-heading",class:"text-sm font-semibold"},"Singletons",-1)),t("dl",Ct,[(d(!0),a(r,null,y(s.value.schema.singletons,n=>(d(),a("div",{key:n.name},[t("dt",null,[p(u,{to:{name:"singleton",params:{name:n.name}},class:"hover:text-accent"},{default:b(()=>[v(o(n.label),1)]),_:2},1032,["to"])]),t("dd",Rt,o(n.fields.top)+" field"+o(n.fields.top===1?"":"s"),1)]))),128))])])):i("",!0),s.value.schema.relations.length?(d(),a("section",St,[e[13]||(e[13]=t("h2",{id:"relations-heading",class:"text-sm font-semibold"},"Relations",-1)),e[14]||(e[14]=t("p",{class:"mt-1 text-xs text-muted"}," Deleting an entry that is referenced here is warned about before it happens. ",-1)),t("ul",At,[(d(!0),a(r,null,y(s.value.schema.relations,n=>(d(),a("li",{key:`${n.fromType}:${n.from}.${n.path}`,class:"flex flex-wrap items-baseline gap-x-2"},[t("span",Tt,o(_.value.get(`${n.fromType}:${n.from}`)??n.from),1),t("span",Lt,o(n.path),1),p(m(F),{size:14,class:"text-muted","aria-hidden":"true"}),t("span",null,o(S(n.to)),1),n.multiple?(d(),a("span",Mt,"many")):i("",!0)]))),128))])])):i("",!0),t("section",Ut,[e[18]||(e[18]=t("h2",{id:"repository-heading",class:"text-sm font-semibold"},"Content repository",-1)),e[19]||(e[19]=t("p",{class:"mt-1 text-xs text-muted"}," The source of truth for the website. Everything here is a file under version control, so the site can be rebuilt from it without this server. ",-1)),t("dl",Bt,[t("div",null,[e[15]||(e[15]=t("dt",null,"Origin",-1)),t("dd",Et,o(s.value.repository.origin),1)]),t("div",null,[e[16]||(e[16]=t("dt",null,"Entries",-1)),t("dd",It,o(s.value.repository.entries),1)]),t("div",null,[e[17]||(e[17]=t("dt",null,"Media",-1)),t("dd",Nt,o(s.value.repository.media.files)+" files · "+o(s.value.repository.media.readable),1)])])]),s.value.database?(d(),a("section",Ot,[e[22]||(e[22]=t("h2",{id:"database-heading",class:"text-sm font-semibold"},"Operational database",-1)),e[23]||(e[23]=t("p",{class:"mt-1 text-xs text-muted"}," The pending draft where saves are staged — there are no accounts or sessions, and nothing published is only in here. ",-1)),t("dl",Vt,[t("div",null,[e[20]||(e[20]=t("dt",null,"Path",-1)),t("dd",Dt,o(s.value.database.path),1)]),t("div",null,[e[21]||(e[21]=t("dt",null,"Size",-1)),t("dd",Ft,o(s.value.database.bytes===null?"in memory":m(x)(s.value.database.bytes))+" · migration "+o(s.value.database.version),1)])])])):i("",!0),t("section",jt,[e[38]||(e[38]=t("h2",{id:"deployment-heading",class:"text-sm font-semibold"},"Deployment",-1)),e[39]||(e[39]=t("p",{class:"mt-1 text-xs text-muted"}," How this Mica is configured. Secrets are never shown — only whether they are set. ",-1)),s.value.deployment.generatedSecrets.length?(d(),a("p",zt," Running with generated development secrets ("+o(s.value.deployment.generatedSecrets.join(", "))+"). Everyone is signed out on restart — set these before this deployment is used for real. ",1)):i("",!0),t("dl",Ht,[t("div",null,[e[24]||(e[24]=t("dt",null,"Site",-1)),t("dd",qt,o(s.value.deployment.site),1)]),t("div",null,[e[25]||(e[25]=t("dt",null,"Base URL",-1)),t("dd",Pt,o(s.value.deployment.baseUrl),1)]),t("div",null,[e[26]||(e[26]=t("dt",null,"Content model",-1)),t("dd",Yt,o(s.value.deployment.schemaOrigin),1)]),t("div",null,[e[27]||(e[27]=t("dt",null,"Repository access",-1)),t("dd",null,o(s.value.deployment.repositoryMode),1)]),s.value.deployment.contentRoot?(d(),a("div",Gt,[e[28]||(e[28]=t("dt",null,"Content root",-1)),t("dd",Kt,o(s.value.deployment.contentRoot),1)])):i("",!0),t("div",null,[e[29]||(e[29]=t("dt",null,"Runtime",-1)),t("dd",null,o(s.value.cms.node)+" on "+o(s.value.cms.platform),1)]),t("div",null,[e[30]||(e[30]=t("dt",null,"Memory in use",-1)),t("dd",Wt,o(m(x)(s.value.deployment.memoryBytes)),1)]),t("div",null,[e[31]||(e[31]=t("dt",null,"Upload limit",-1)),t("dd",Zt,o(s.value.deployment.maxUploadReadable),1)]),t("div",null,[e[32]||(e[32]=t("dt",null,"Authentication",-1)),t("dd",Jt,o(s.value.deployment.auth),1)]),s.value.deployment.admission?(d(),a("div",Qt,[e[33]||(e[33]=t("dt",null,"Who may edit",-1)),t("dd",Xt,o(s.value.deployment.admission),1)])):i("",!0),s.value.deployment.sessionTtlHours!==null?(d(),a("div",te,[e[34]||(e[34]=t("dt",null,"Session lifetime",-1)),t("dd",ee,o(s.value.deployment.sessionTtlHours)+" h, idle out after "+o(s.value.deployment.sessionIdleHours)+" h ",1)])):i("",!0),t("div",null,[e[35]||(e[35]=t("dt",null,"Trust proxy headers",-1)),t("dd",null,o(s.value.deployment.trustProxy?"Yes":"No"),1)]),s.value.deployment.adminOrigins.length?(d(),a("div",se,[e[36]||(e[36]=t("dt",null,"Extra admin origins",-1)),t("dd",oe,o(s.value.deployment.adminOrigins.join(", ")),1)])):i("",!0),t("div",null,[e[37]||(e[37]=t("dt",null,"Log level",-1)),t("dd",null,o(s.value.deployment.logLevel),1)])])])],64)):i("",!0)])],64)}}}),ue=O(le,[["__scopeId","data-v-524c55f4"]]);export{ue as default};
3
- //# sourceMappingURL=SystemView-CB8CT0Pa.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SystemView-CB8CT0Pa.js","sources":["../../src/views/SystemView.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * System information.\n *\n * What is running, what content model it was handed, and how much content\n * there is — the questions that otherwise need shell access to the container.\n * Read-only except for \"Copy report\", which puts the whole thing on the\n * clipboard in the shape a bug report wants.\n *\n * Nothing here is per customer: the model section is generated from whatever\n * model the server was given, exactly like the rest of the admin.\n */\n\nimport { computed, onMounted, ref } from \"vue\";\nimport { ArrowRight } from \"@lucide/vue\";\n\nimport { api, ApiError, type SystemInfo } from \"@/api\";\nimport PageHeader from \"@/components/PageHeader.vue\";\nimport { absoluteTime, formatBytes, formatDuration } from \"@/lib/format\";\nimport { useToast } from \"@/stores/toast\";\n\nconst toast = useToast();\n\nconst info = ref<SystemInfo | null>(null);\nconst loading = ref(true);\n\nasync function load(): Promise<void> {\n loading.value = true;\n try {\n info.value = await api.system();\n } catch (error) {\n toast.error(error instanceof ApiError ? error.message : \"Could not load the system information.\");\n } finally {\n loading.value = false;\n }\n}\n\nonMounted(load);\n\n/**\n * `richText` → \"Rich text\". Derived rather than a table, so a field kind added\n * to the model reads correctly here without a second edit — the initialisms are\n * the only thing splitting on case cannot get right.\n */\nconst INITIALISMS: Record<string, string> = { url: \"URL\" };\n\nfunction kindLabel(kind: string): string {\n if (INITIALISMS[kind]) return INITIALISMS[kind];\n const words = kind.replace(/([A-Z])/g, \" $1\").toLowerCase();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\nconst busiestKind = computed(() =>\n Math.max(1, ...(info.value?.schema.kinds ?? []).map((item) => item.count)),\n);\n\nconst labels = computed(() => {\n const map = new Map<string, string>();\n for (const item of info.value?.schema.collections ?? []) map.set(`collection:${item.name}`, item.label);\n for (const item of info.value?.schema.singletons ?? []) {\n map.set(`singleton:${item.name}`, item.label);\n }\n return map;\n});\n\nfunction collectionLabel(name: string): string {\n return labels.value.get(`collection:${name}`) ?? name;\n}\n\n/** The report a support request should carry, as plain text. */\nfunction report(): string {\n const data = info.value;\n if (!data) return \"\";\n\n const lines = [\n `Mica ${data.cms.version} (${data.cms.environment})`,\n `Node ${data.cms.node} on ${data.cms.platform}, up ${formatDuration(data.cms.uptimeSeconds)}`,\n `Schema — ${data.schema.totals.collections} collections, ` +\n `${data.schema.totals.singletons} singletons, ${data.schema.totals.total} fields`,\n `Repository ${data.repository.origin}`,\n `Repository holds ${data.repository.entries} entries and ` +\n `${data.repository.media.files} media files (${data.repository.media.readable})`,\n data.database\n ? `Database: migration ${data.database.version}, ` +\n `${data.database.bytes === null ? \"size unknown\" : formatBytes(data.database.bytes)}`\n : \"Database: none — the local editor keeps no state\",\n `Site ${data.deployment.site}`,\n `Base URL ${data.deployment.baseUrl}`,\n `Content model ${data.deployment.schemaOrigin}`,\n `Content root ${data.deployment.contentRoot}`,\n `Authentication ${data.deployment.auth}`,\n `Admission ${data.deployment.admission ?? \"none\"}`,\n ];\n\n return lines.join(\"\\n\");\n}\n\nasync function copyReport(): Promise<void> {\n try {\n // Absent on an insecure origin, which a self-hosted CMS may well be.\n await navigator.clipboard.writeText(report());\n toast.success(\"Report copied to the clipboard.\");\n } catch {\n toast.error(\"Could not copy. Select the values you need instead.\");\n }\n}\n</script>\n\n<template>\n <PageHeader\n title=\"System\"\n :subtitle=\"info ? `Mica ${info.cms.version} · ${info.cms.environment}` : null\"\n >\n <button type=\"button\" class=\"btn-ghost\" :disabled=\"loading\" @click=\"load\">Refresh</button>\n <button type=\"button\" class=\"btn-secondary\" :disabled=\"!info\" @click=\"copyReport\">\n Copy report\n </button>\n </PageHeader>\n\n <div class=\"mx-auto max-w-5xl space-y-6 px-4 py-5 pb-12 sm:px-6\">\n <p v-if=\"loading\" class=\"text-sm text-muted\">Loading…</p>\n\n <template v-else-if=\"info\">\n <!-- ------------------------------------------------------ at a glance -->\n\n <section aria-labelledby=\"glance-heading\">\n <h2 id=\"glance-heading\" class=\"sr-only\">At a glance</h2>\n\n <dl class=\"grid grid-cols-2 gap-3 lg:grid-cols-4\">\n <div class=\"card p-4\">\n <dt class=\"text-sm text-muted\">Version</dt>\n <dd class=\"mt-1 text-2xl font-semibold tabular-nums\">{{ info.cms.version }}</dd>\n <dd class=\"mt-1 text-xs text-muted\">{{ info.cms.environment }}</dd>\n </div>\n\n <div class=\"card p-4\">\n <dt class=\"text-sm text-muted\">Uptime</dt>\n <dd class=\"mt-1 text-2xl font-semibold tabular-nums\">\n {{ formatDuration(info.cms.uptimeSeconds) }}\n </dd>\n <dd class=\"mt-1 text-xs text-muted\">\n <!-- Absolute, not relative: \"up 1 min, since 1 minute ago\" says\n the same thing twice, and the start time is the useful half. -->\n <time :datetime=\"info.cms.startedAt\">{{ absoluteTime(info.cms.startedAt) }}</time>\n </dd>\n </div>\n\n <div class=\"card p-4\">\n <dt class=\"text-sm text-muted\">Content model</dt>\n <dd class=\"mt-1 text-2xl font-semibold tabular-nums\">\n {{ info.schema.totals.total }}\n </dd>\n <dd class=\"mt-1 text-xs text-muted\">\n fields in {{ info.schema.totals.collections }} collections,\n {{ info.schema.totals.singletons }} singletons\n </dd>\n </div>\n\n <div class=\"card p-4\">\n <dt class=\"text-sm text-muted\">In the repository</dt>\n <dd class=\"mt-1 text-2xl font-semibold tabular-nums\">\n {{ info.repository.entries }}\n </dd>\n <dd class=\"mt-1 text-xs text-muted\">\n entries · {{ info.repository.media.files }} media files\n </dd>\n </div>\n </dl>\n </section>\n\n <!-- --------------------------------------------------- content model -->\n\n <section class=\"card p-4\" aria-labelledby=\"model-heading\">\n <h2 id=\"model-heading\" class=\"text-sm font-semibold\">Content model</h2>\n <p class=\"mt-1 text-xs text-muted\">\n The schema this server was handed at startup. The same file describes the model to the\n Astro build, so the editor and the website cannot disagree about it.\n </p>\n\n <dl class=\"spec mt-3\">\n <div>\n <dt>Required fields</dt>\n <dd class=\"tabular-nums\">\n {{ info.schema.totals.required }} of {{ info.schema.totals.total }}\n </dd>\n </div>\n </dl>\n\n <h3 class=\"mt-5 text-xs font-semibold uppercase tracking-wider text-muted\">Field types</h3>\n <ul class=\"mt-2 space-y-1.5\">\n <li v-for=\"item in info.schema.kinds\" :key=\"item.kind\" class=\"flex items-center gap-3 text-sm\">\n <span class=\"w-28 shrink-0 truncate\">{{ kindLabel(item.kind) }}</span>\n <span class=\"h-1.5 min-w-0 flex-1 rounded-full bg-canvas\" aria-hidden=\"true\">\n <span\n class=\"block h-full rounded-full bg-accent/60\"\n :style=\"{ width: `${(item.count / busiestKind) * 100}%` }\"\n />\n </span>\n <span class=\"w-8 shrink-0 text-right text-xs tabular-nums text-muted\">\n {{ item.count }}\n </span>\n </li>\n </ul>\n </section>\n\n <!-- ---------------------------------------------------- collections -->\n\n <section class=\"card overflow-hidden\" aria-labelledby=\"collections-heading\">\n <h2 id=\"collections-heading\" class=\"border-b border-line px-4 py-3 text-sm font-semibold\">\n Collections\n </h2>\n\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-sm\">\n <caption class=\"sr-only\">Collections in the content model, with their entry counts</caption>\n <thead>\n <tr class=\"border-b border-line text-left text-xs text-muted\">\n <th scope=\"col\" class=\"px-4 py-2 font-medium\">Collection</th>\n <th scope=\"col\" class=\"px-4 py-2 text-right font-medium\">Entries</th>\n <th scope=\"col\" class=\"px-4 py-2 text-right font-medium\">Fields</th>\n <th scope=\"col\" class=\"hidden px-4 py-2 font-medium sm:table-cell\">Title / slug</th>\n <th scope=\"col\" class=\"hidden px-4 py-2 font-medium sm:table-cell\">Ordering</th>\n </tr>\n </thead>\n\n <tbody class=\"divide-y divide-line\">\n <tr v-for=\"item in info.schema.collections\" :key=\"item.name\">\n <td class=\"px-4 py-2.5\">\n <RouterLink\n :to=\"{ name: 'collection', params: { collection: item.name } }\"\n class=\"font-medium hover:text-accent\"\n >\n {{ item.label }}\n </RouterLink>\n <span class=\"mono block text-muted\">{{ item.name }}</span>\n </td>\n\n <td class=\"px-4 py-2.5 text-right tabular-nums\">{{ item.entries }}</td>\n\n <td class=\"px-4 py-2.5 text-right tabular-nums\">\n {{ item.fields.top }}\n <span v-if=\"item.fields.total > item.fields.top\" class=\"block text-xs text-muted\">\n {{ item.fields.total }} with nested\n </span>\n </td>\n\n <td class=\"mono hidden px-4 py-2.5 text-muted sm:table-cell\">\n {{ item.titleField ?? \"—\" }} / {{ item.slugField ?? \"—\" }}\n </td>\n\n <td class=\"hidden px-4 py-2.5 text-xs text-muted sm:table-cell\">\n {{ item.sortable ? \"Manual\" : \"Automatic\" }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- ----------------------------------------------------- singletons -->\n\n <section\n v-if=\"info.schema.singletons.length\"\n class=\"card p-4\"\n aria-labelledby=\"singletons-heading\"\n >\n <h2 id=\"singletons-heading\" class=\"text-sm font-semibold\">Singletons</h2>\n\n <dl class=\"spec mt-3\">\n <div v-for=\"item in info.schema.singletons\" :key=\"item.name\">\n <dt>\n <RouterLink\n :to=\"{ name: 'singleton', params: { name: item.name } }\"\n class=\"hover:text-accent\"\n >\n {{ item.label }}\n </RouterLink>\n </dt>\n <dd class=\"tabular-nums\">\n {{ item.fields.top }} field{{ item.fields.top === 1 ? \"\" : \"s\" }}\n </dd>\n </div>\n </dl>\n </section>\n\n <!-- ------------------------------------------------------ relations -->\n\n <section v-if=\"info.schema.relations.length\" class=\"card p-4\" aria-labelledby=\"relations-heading\">\n <h2 id=\"relations-heading\" class=\"text-sm font-semibold\">Relations</h2>\n <p class=\"mt-1 text-xs text-muted\">\n Deleting an entry that is referenced here is warned about before it happens.\n </p>\n\n <ul class=\"mt-3 space-y-1.5 text-sm\">\n <li\n v-for=\"edge in info.schema.relations\"\n :key=\"`${edge.fromType}:${edge.from}.${edge.path}`\"\n class=\"flex flex-wrap items-baseline gap-x-2\"\n >\n <span class=\"font-medium\">\n {{ labels.get(`${edge.fromType}:${edge.from}`) ?? edge.from }}\n </span>\n <span class=\"mono text-muted\">{{ edge.path }}</span>\n <ArrowRight :size=\"14\" class=\"text-muted\" aria-hidden=\"true\" />\n <span>{{ collectionLabel(edge.to) }}</span>\n <span v-if=\"edge.multiple\" class=\"badge bg-accent-soft text-accent\">many</span>\n </li>\n </ul>\n </section>\n\n <!-- ----------------------------------------------------- repository -->\n\n <!--\n Two sections rather than one \"Storage\", because they are not the same\n kind of thing and should not be backed up the same way. The repository\n is the website. The database holds only work that is saved and not\n yet published.\n -->\n\n <section class=\"card p-4\" aria-labelledby=\"repository-heading\">\n <h2 id=\"repository-heading\" class=\"text-sm font-semibold\">Content repository</h2>\n <p class=\"mt-1 text-xs text-muted\">\n The source of truth for the website. Everything here is a file under version control, so\n the site can be rebuilt from it without this server.\n </p>\n\n <dl class=\"spec mt-3\">\n <div>\n <dt>Origin</dt>\n <dd class=\"mono\">{{ info.repository.origin }}</dd>\n </div>\n <div>\n <dt>Entries</dt>\n <dd class=\"tabular-nums\">{{ info.repository.entries }}</dd>\n </div>\n <div>\n <dt>Media</dt>\n <dd class=\"tabular-nums\">\n {{ info.repository.media.files }} files · {{ info.repository.media.readable }}\n </dd>\n </div>\n </dl>\n </section>\n\n <!-- ------------------------------------------------------- database -->\n\n <section v-if=\"info.database\" class=\"card p-4\" aria-labelledby=\"database-heading\">\n <h2 id=\"database-heading\" class=\"text-sm font-semibold\">Operational database</h2>\n <p class=\"mt-1 text-xs text-muted\">\n The pending draft where saves are staged — there are no accounts or\n sessions, and nothing published is only in here.\n </p>\n\n <dl class=\"spec mt-3\">\n <div>\n <dt>Path</dt>\n <dd class=\"mono\">{{ info.database.path }}</dd>\n </div>\n <div>\n <dt>Size</dt>\n <dd class=\"tabular-nums\">\n {{ info.database.bytes === null ? \"in memory\" : formatBytes(info.database.bytes) }}\n · migration {{ info.database.version }}\n </dd>\n </div>\n </dl>\n </section>\n\n <!-- ----------------------------------------------------- deployment -->\n\n <section class=\"card p-4\" aria-labelledby=\"deployment-heading\">\n <h2 id=\"deployment-heading\" class=\"text-sm font-semibold\">Deployment</h2>\n <p class=\"mt-1 text-xs text-muted\">\n How this Mica is configured. Secrets are never shown — only whether they are set.\n </p>\n\n <p\n v-if=\"info.deployment.generatedSecrets.length\"\n class=\"mt-3 rounded-md border border-warning/15 bg-warning-soft px-4 py-3 text-xs text-warning\"\n >\n Running with generated development secrets\n ({{ info.deployment.generatedSecrets.join(\", \") }}). Everyone is signed out on restart —\n set these before this deployment is used for real.\n </p>\n\n <dl class=\"spec mt-3\">\n <div>\n <dt>Site</dt>\n <dd class=\"mono\">{{ info.deployment.site }}</dd>\n </div>\n <div>\n <dt>Base URL</dt>\n <dd class=\"mono\">{{ info.deployment.baseUrl }}</dd>\n </div>\n <div>\n <dt>Content model</dt>\n <dd class=\"mono\">{{ info.deployment.schemaOrigin }}</dd>\n </div>\n <div>\n <dt>Repository access</dt>\n <dd>{{ info.deployment.repositoryMode }}</dd>\n </div>\n <div v-if=\"info.deployment.contentRoot\">\n <dt>Content root</dt>\n <dd class=\"mono\">{{ info.deployment.contentRoot }}</dd>\n </div>\n <div>\n <dt>Runtime</dt>\n <dd>{{ info.cms.node }} on {{ info.cms.platform }}</dd>\n </div>\n <div>\n <dt>Memory in use</dt>\n <dd class=\"tabular-nums\">{{ formatBytes(info.deployment.memoryBytes) }}</dd>\n </div>\n <div>\n <dt>Upload limit</dt>\n <dd class=\"tabular-nums\">{{ info.deployment.maxUploadReadable }}</dd>\n </div>\n <div>\n <dt>Authentication</dt>\n <dd class=\"mono\">{{ info.deployment.auth }}</dd>\n </div>\n <div v-if=\"info.deployment.admission\">\n <dt>Who may edit</dt>\n <dd class=\"mono\">{{ info.deployment.admission }}</dd>\n </div>\n <div v-if=\"info.deployment.sessionTtlHours !== null\">\n <dt>Session lifetime</dt>\n <dd class=\"tabular-nums\">\n {{ info.deployment.sessionTtlHours }} h, idle out after\n {{ info.deployment.sessionIdleHours }} h\n </dd>\n </div>\n <div>\n <dt>Trust proxy headers</dt>\n <dd>{{ info.deployment.trustProxy ? \"Yes\" : \"No\" }}</dd>\n </div>\n <div v-if=\"info.deployment.adminOrigins.length\">\n <dt>Extra admin origins</dt>\n <dd class=\"mono\">{{ info.deployment.adminOrigins.join(\", \") }}</dd>\n </div>\n <div>\n <dt>Log level</dt>\n <dd>{{ info.deployment.logLevel }}</dd>\n </div>\n </dl>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n@reference \"../style.css\";\n\n/* Term/value rows: the page is mostly these, so they are worth a class. */\n.spec {\n @apply divide-y divide-line text-sm;\n}\n\n.spec > div {\n @apply flex items-baseline justify-between gap-6 py-1.5;\n}\n\n.spec dt {\n @apply shrink-0 text-muted;\n}\n\n.spec dd {\n @apply min-w-0 text-right;\n}\n\n.mono {\n @apply font-mono text-xs break-all;\n}\n</style>\n"],"names":["toast","useToast","info","ref","loading","load","api","error","ApiError","onMounted","INITIALISMS","kindLabel","kind","words","busiestKind","computed","_a","item","labels","map","_b","collectionLabel","name","report","data","formatDuration","formatBytes","copyReport","_createVNode","PageHeader","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_createElementBlock","_hoisted_4","_Fragment","_hoisted_5","_hoisted_6","_hoisted_7","_cache","_hoisted_8","_toDisplayString","_hoisted_9","_hoisted_10","_hoisted_11","_unref","_hoisted_12","absoluteTime","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_23","_openBlock","_hoisted_24","_hoisted_25","_normalizeStyle","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_component_RouterLink","_createTextVNode","_hoisted_32","_hoisted_33","_hoisted_34","_hoisted_35","_hoisted_36","_hoisted_37","_hoisted_38","_hoisted_39","_hoisted_40","_hoisted_41","_hoisted_42","edge","_hoisted_43","_hoisted_44","ArrowRight","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_50","_hoisted_51","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_55","_hoisted_56","_hoisted_57","_hoisted_58","_hoisted_59","_hoisted_60","_hoisted_61","_hoisted_62","_hoisted_63","_hoisted_64","_hoisted_65","_hoisted_66","_hoisted_67","_hoisted_68","_hoisted_69","_hoisted_70","_hoisted_71"],"mappings":"o4FAqBA,MAAMA,EAAQC,EAAA,EAERC,EAAOC,EAAuB,IAAI,EAClCC,EAAUD,EAAI,EAAI,EAExB,eAAeE,GAAsB,CACnCD,EAAQ,MAAQ,GAChB,GAAI,CACFF,EAAK,MAAQ,MAAMI,EAAI,OAAA,CACzB,OAASC,EAAO,CACdP,EAAM,MAAMO,aAAiBC,EAAWD,EAAM,QAAU,wCAAwC,CAClG,QAAA,CACEH,EAAQ,MAAQ,EAClB,CACF,CAEAK,EAAUJ,CAAI,EAOd,MAAMK,EAAsC,CAAE,IAAK,KAAA,EAEnD,SAASC,EAAUC,EAAsB,CACvC,GAAIF,EAAYE,CAAI,EAAG,OAAOF,EAAYE,CAAI,EAC9C,MAAMC,EAAQD,EAAK,QAAQ,WAAY,KAAK,EAAE,YAAA,EAC9C,OAAOC,EAAM,OAAO,CAAC,EAAE,cAAgBA,EAAM,MAAM,CAAC,CACtD,CAEA,MAAMC,EAAcC,EAAS,IAAA,OAC3B,YAAK,IAAI,EAAG,MAAIC,EAAAd,EAAK,QAAL,YAAAc,EAAY,OAAO,QAAS,CAAA,GAAI,IAAKC,GAASA,EAAK,KAAK,CAAC,EAAA,EAGrEC,EAASH,EAAS,IAAM,SAC5B,MAAMI,MAAU,IAChB,UAAWF,MAAQD,EAAAd,EAAK,QAAL,YAAAc,EAAY,OAAO,cAAe,GAAIG,EAAI,IAAI,cAAcF,EAAK,IAAI,GAAIA,EAAK,KAAK,EACtG,UAAWA,MAAQG,EAAAlB,EAAK,QAAL,YAAAkB,EAAY,OAAO,aAAc,GAClDD,EAAI,IAAI,aAAaF,EAAK,IAAI,GAAIA,EAAK,KAAK,EAE9C,OAAOE,CACT,CAAC,EAED,SAASE,EAAgBC,EAAsB,CAC7C,OAAOJ,EAAO,MAAM,IAAI,cAAcI,CAAI,EAAE,GAAKA,CACnD,CAGA,SAASC,GAAiB,CACxB,MAAMC,EAAOtB,EAAK,MAClB,OAAKsB,EAES,CACZ,QAAQA,EAAK,IAAI,OAAO,KAAKA,EAAK,IAAI,WAAW,IACjD,QAAQA,EAAK,IAAI,IAAI,OAAOA,EAAK,IAAI,QAAQ,QAAQC,EAAeD,EAAK,IAAI,aAAa,CAAC,GAC3F,YAAYA,EAAK,OAAO,OAAO,WAAW,iBACrCA,EAAK,OAAO,OAAO,UAAU,gBAAgBA,EAAK,OAAO,OAAO,KAAK,UAC1E,cAAcA,EAAK,WAAW,MAAM,GACpC,oBAAoBA,EAAK,WAAW,OAAO,gBACtCA,EAAK,WAAW,MAAM,KAAK,iBAAiBA,EAAK,WAAW,MAAM,QAAQ,IAC/EA,EAAK,SACD,uBAAuBA,EAAK,SAAS,OAAO,KACzCA,EAAK,SAAS,QAAU,KAAO,eAAiBE,EAAYF,EAAK,SAAS,KAAK,CAAC,GACnF,mDACJ,QAAQA,EAAK,WAAW,IAAI,GAC5B,YAAYA,EAAK,WAAW,OAAO,GACnC,iBAAiBA,EAAK,WAAW,YAAY,GAC7C,gBAAgBA,EAAK,WAAW,WAAW,GAC3C,kBAAkBA,EAAK,WAAW,IAAI,GACtC,aAAaA,EAAK,WAAW,WAAa,MAAM,EAAA,EAGrC,KAAK;AAAA,CAAI,EAtBJ,EAuBpB,CAEA,eAAeG,GAA4B,CACzC,GAAI,CAEF,MAAM,UAAU,UAAU,UAAUJ,EAAA,CAAQ,EAC5CvB,EAAM,QAAQ,iCAAiC,CACjD,MAAQ,CACNA,EAAM,MAAM,qDAAqD,CACnE,CACF,4DAIE4B,EAQaC,EAAA,CAPX,MAAM,SACL,SAAU3B,EAAA,MAAI,QAAWA,EAAA,MAAK,IAAI,OAAO,MAAMA,EAAA,MAAK,IAAI,WAAW,GAAA,IAAA,aAEpE,IAA0F,CAA1F4B,EAA0F,SAAA,CAAlF,KAAK,SAAS,MAAM,YAAa,SAAU1B,EAAA,MAAU,QAAOC,CAAA,EAAM,UAAO,EAAA0B,CAAA,EACjFD,EAES,SAAA,CAFD,KAAK,SAAS,MAAM,gBAAiB,UAAW5B,EAAA,MAAO,QAAOyB,CAAA,EAAY,gBAElF,EAAAK,CAAA,CAAA,wBAGFF,EAyUM,MAzUNG,EAyUM,CAxUK7B,EAAA,WAAT8B,EAAyD,IAAzDC,EAA6C,UAAQ,GAEhCjC,EAAA,WAArBgC,EAqUWE,EAAA,CAAA,IAAA,GAAA,CAlUTN,EA2CU,UA3CVO,EA2CU,aA1CRP,EAAwD,KAAA,CAApD,GAAG,iBAAiB,MAAM,SAAA,EAAU,cAAW,EAAA,GAEnDA,EAuCK,KAvCLQ,EAuCK,CAtCHR,EAIM,MAJNS,EAIM,CAHJC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAA2C,KAAA,CAAvC,MAAM,oBAAA,EAAqB,UAAO,EAAA,GACtCA,EAAgF,KAAhFW,EAAgFC,EAAxBxC,QAAK,IAAI,OAAO,EAAA,CAAA,EACxE4B,EAAmE,KAAnEa,EAAmED,EAA5BxC,QAAK,IAAI,WAAW,EAAA,CAAA,CAAA,GAG7D4B,EAUM,MAVNc,EAUM,CATJJ,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAA0C,KAAA,CAAtC,MAAM,oBAAA,EAAqB,SAAM,EAAA,GACrCA,EAEK,KAFLe,EAEKH,EADAI,EAAArB,CAAA,EAAevB,EAAA,MAAK,IAAI,aAAa,CAAA,EAAA,CAAA,EAE1C4B,EAIK,KAJLiB,EAIK,CADHjB,EAAkF,OAAA,CAA3E,SAAU5B,EAAA,MAAK,IAAI,SAAA,EAAcwC,EAAAI,EAAAE,CAAA,EAAa9C,EAAA,MAAK,IAAI,SAAS,CAAA,EAAA,EAAA+C,CAAA,CAAA,KAI3EnB,EASM,MATNoB,GASM,CARJV,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAAiD,KAAA,CAA7C,MAAM,oBAAA,EAAqB,gBAAa,EAAA,GAC5CA,EAEK,KAFLqB,GAEKT,EADAxC,EAAA,MAAK,OAAO,OAAO,KAAK,EAAA,CAAA,EAE7B4B,EAGK,KAHLsB,GAAoC,gBACrBlD,EAAA,MAAK,OAAO,OAAO,WAAW,EAAG,iBAC9CwC,EAAGxC,EAAA,MAAK,OAAO,OAAO,UAAU,EAAG,eACrC,CAAA,CAAA,GAGF4B,EAQM,MARNuB,GAQM,CAPJb,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAAqD,KAAA,CAAjD,MAAM,oBAAA,EAAqB,oBAAiB,EAAA,GAChDA,EAEK,KAFLwB,GAEKZ,EADAxC,QAAK,WAAW,OAAO,EAAA,CAAA,EAE5B4B,EAEK,KAFLyB,GAAoC,cACxBb,EAAGxC,EAAA,MAAK,WAAW,MAAM,KAAK,EAAG,gBAC7C,CAAA,CAAA,OAON4B,EA+BU,UA/BV0B,GA+BU,aA9BR1B,EAAuE,KAAA,CAAnE,GAAG,gBAAgB,MAAM,uBAAA,EAAwB,gBAAa,EAAA,GAClEU,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAGI,IAAA,CAHD,MAAM,yBAAA,EAA0B,gKAGnC,EAAA,GAEAA,EAOK,KAPL2B,GAOK,CANH3B,EAKM,MAAA,KAAA,CAJJU,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAAwB,UAApB,kBAAe,EAAA,GACnBA,EAEK,KAFL4B,GAEKhB,EADAxC,QAAK,OAAO,OAAO,QAAQ,EAAG,SAAOA,EAAA,MAAK,OAAO,OAAO,KAAK,EAAA,CAAA,CAAA,KAKtEsC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAA2F,KAAA,CAAvF,MAAM,gEAAA,EAAiE,cAAW,EAAA,GACtFA,EAaK,KAbL6B,GAaK,EAZHC,EAAA,EAAA,EAAA1B,EAWKE,SAXclC,EAAA,MAAK,OAAO,MAApBe,QAAXiB,EAWK,KAAA,CAXkC,IAAKjB,EAAK,KAAM,MAAM,iCAAA,GAC3Da,EAAsE,OAAtE+B,GAAsEnB,EAA9B/B,EAAUM,EAAK,IAAI,CAAA,EAAA,CAAA,EAC3Da,EAKO,OALPgC,GAKO,CAJLhC,EAGE,OAAA,CAFA,MAAM,yCACL,MAAKiC,EAAA,CAAA,MAAA,GAAe9C,EAAK,MAAQH,EAAA,MAAW,GAAA,GAAA,CAAA,CAAA,YAGjDgB,EAEO,OAFPkC,GAEOtB,EADFzB,EAAK,KAAK,EAAA,CAAA,CAAA,eAQrBa,EAkDU,UAlDVmC,GAkDU,eAjDRnC,EAEK,KAAA,CAFD,GAAG,sBAAsB,MAAM,sDAAA,EAAuD,gBAE1F,EAAA,GAEAA,EA4CM,MA5CNoC,GA4CM,CA3CJpC,EA0CQ,QA1CRqC,GA0CQ,CAzCN3B,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAV,EAA4F,UAAA,CAAnF,MAAM,SAAA,EAAU,4DAAyD,EAAA,iBAClFA,EAQQ,QAAA,KAAA,CAPNA,EAMK,KAAA,CAND,MAAM,qDAAmD,CAC3DA,EAA6D,KAAA,CAAzD,MAAM,MAAM,MAAM,uBAAA,EAAwB,YAAU,EACxDA,EAAqE,KAAA,CAAjE,MAAM,MAAM,MAAM,kCAAA,EAAmC,SAAO,EAChEA,EAAoE,KAAA,CAAhE,MAAM,MAAM,MAAM,kCAAA,EAAmC,QAAM,EAC/DA,EAAoF,KAAA,CAAhF,MAAM,MAAM,MAAM,4CAAA,EAA6C,cAAY,EAC/EA,EAAgF,KAAA,CAA5E,MAAM,MAAM,MAAM,4CAAA,EAA6C,UAAQ,CAAA,SAI/EA,EA6BQ,QA7BRsC,GA6BQ,EA5BNR,EAAA,EAAA,EAAA1B,EA2BKE,SA3BclC,EAAA,MAAK,OAAO,YAApBe,QAAXiB,EA2BK,KAAA,CA3BwC,IAAKjB,EAAK,IAAA,GACrDa,EAQK,KARLuC,GAQK,CAPHzC,EAKa0C,EAAA,CAJV,GAAE,CAAA,KAAA,aAAA,OAAA,CAAA,WAA8CrD,EAAK,KAAI,EAC1D,MAAM,+BAAA,aAEN,IAAgB,CAAbsD,EAAA7B,EAAAzB,EAAK,KAAK,EAAA,CAAA,CAAA,qBAEfa,EAA0D,OAA1D0C,GAA0D9B,EAAnBzB,EAAK,IAAI,EAAA,CAAA,CAAA,GAGlDa,EAAuE,KAAvE2C,GAAuE/B,EAApBzB,EAAK,OAAO,EAAA,CAAA,EAE/Da,EAKK,KALL4C,GAKK,CAJAH,EAAA7B,EAAAzB,EAAK,OAAO,GAAG,EAAG,IACrB,CAAA,EAAYA,EAAK,OAAO,MAAQA,EAAK,OAAO,SAA5CiB,EAEO,OAFPyC,GAEOjC,EADFzB,EAAK,OAAO,KAAK,EAAG,gBACzB,CAAA,cAGFa,EAEK,KAFL8C,GAEKlC,EADAzB,EAAK,YAAU,GAAA,EAAU,MAAGyB,EAAGzB,EAAK,WAAS,GAAA,EAAA,CAAA,EAGlDa,EAEK,KAFL+C,GAEKnC,EADAzB,EAAK,SAAQ,SAAA,WAAA,EAAA,CAAA,CAAA,mBAWpBf,EAAA,MAAK,OAAO,WAAW,QAD/B0D,IAAA1B,EAsBU,UAtBV4C,GAsBU,eAjBRhD,EAAyE,KAAA,CAArE,GAAG,qBAAqB,MAAM,uBAAA,EAAwB,aAAU,EAAA,GAEpEA,EAcK,KAdLiD,GAcK,EAbHnB,EAAA,EAAA,EAAA1B,EAYME,SAZclC,EAAA,MAAK,OAAO,WAApBe,QAAZiB,EAYM,MAAA,CAZuC,IAAKjB,EAAK,IAAA,GACrDa,EAOK,KAAA,KAAA,CANHF,EAKa0C,EAAA,CAJV,GAAE,CAAA,KAAA,YAAA,OAAA,CAAA,KAAuCrD,EAAK,KAAI,EACnD,MAAM,mBAAA,aAEN,IAAgB,CAAbsD,EAAA7B,EAAAzB,EAAK,KAAK,EAAA,CAAA,CAAA,uBAGjBa,EAEK,KAFLkD,GAEKtC,EADAzB,EAAK,OAAO,GAAG,EAAG,SAAMyB,EAAGzB,EAAK,OAAO,MAAG,EAAA,GAAA,GAAA,EAAA,CAAA,CAAA,yBAQtCf,EAAA,MAAK,OAAO,UAAU,QAArC0D,IAAA1B,EAqBU,UArBV+C,GAqBU,eApBRnD,EAAuE,KAAA,CAAnE,GAAG,oBAAoB,MAAM,uBAAA,EAAwB,YAAS,EAAA,GAClEU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAEI,IAAA,CAFD,MAAM,yBAAA,EAA0B,iFAEnC,EAAA,GAEAA,EAcK,KAdLoD,GAcK,EAbHtB,EAAA,EAAA,EAAA1B,EAYKE,SAXYlC,EAAA,MAAK,OAAO,UAApBiF,QADTjD,EAYK,KAAA,CAVF,IAAG,GAAKiD,EAAK,QAAQ,IAAIA,EAAK,IAAI,IAAIA,EAAK,IAAI,GAChD,MAAM,uCAAA,GAENrD,EAEO,OAFPsD,GAEO1C,EADFxB,EAAA,MAAO,IAAG,GAAIiE,EAAK,QAAQ,IAAIA,EAAK,IAAI,EAAA,GAAOA,EAAK,IAAI,EAAA,CAAA,EAE7DrD,EAAoD,OAApDuD,GAAoD3C,EAAnByC,EAAK,IAAI,EAAA,CAAA,EAC1CvD,EAA+DkB,EAAAwC,CAAA,EAAA,CAAlD,KAAM,GAAI,MAAM,aAAa,cAAY,MAAA,GACtDxD,EAA2C,OAAA,KAAAY,EAAlCrB,EAAgB8D,EAAK,EAAE,CAAA,EAAA,CAAA,EACpBA,EAAK,cAAjBjD,EAA+E,OAA/EqD,GAAoE,MAAI,oCAc9EzD,EAuBU,UAvBV0D,GAuBU,eAtBR1D,EAAiF,KAAA,CAA7E,GAAG,qBAAqB,MAAM,uBAAA,EAAwB,qBAAkB,EAAA,GAC5EU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAGI,IAAA,CAHD,MAAM,yBAAA,EAA0B,kJAGnC,EAAA,GAEAA,EAeK,KAfL2D,GAeK,CAdH3D,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAe,UAAX,SAAM,EAAA,GACVA,EAAkD,KAAlD4D,GAAkDhD,EAA9BxC,QAAK,WAAW,MAAM,EAAA,CAAA,CAAA,GAE5C4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAgB,UAAZ,UAAO,EAAA,GACXA,EAA2D,KAA3D6D,GAA2DjD,EAA/BxC,QAAK,WAAW,OAAO,EAAA,CAAA,CAAA,GAErD4B,EAKM,MAAA,KAAA,CAJJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAc,UAAV,QAAK,EAAA,GACTA,EAEK,KAFL8D,GAEKlD,EADAxC,QAAK,WAAW,MAAM,KAAK,EAAG,cAAYA,EAAA,MAAK,WAAW,MAAM,QAAQ,EAAA,CAAA,CAAA,OAQpEA,EAAA,MAAK,UAApB0D,IAAA1B,EAoBU,UApBV2D,GAoBU,eAnBR/D,EAAiF,KAAA,CAA7E,GAAG,mBAAmB,MAAM,uBAAA,EAAwB,uBAAoB,EAAA,GAC5EU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAGI,IAAA,CAHD,MAAM,yBAAA,EAA0B,yHAGnC,EAAA,GAEAA,EAYK,KAZLgE,GAYK,CAXHhE,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAa,UAAT,OAAI,EAAA,GACRA,EAA8C,KAA9CiE,GAA8CrD,EAA1BxC,QAAK,SAAS,IAAI,EAAA,CAAA,CAAA,GAExC4B,EAMM,MAAA,KAAA,CALJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAa,UAAT,OAAI,EAAA,GACRA,EAGK,KAHLkE,GAGKtD,EAFAxC,EAAA,MAAK,SAAS,QAAK,KAAA,YAA0B4C,EAAApB,CAAA,EAAYxB,QAAK,SAAS,KAAK,CAAA,EAAI,kBACpEA,EAAA,MAAK,SAAS,OAAO,EAAA,CAAA,CAAA,iBAQ5C4B,EA4EU,UA5EVmE,GA4EU,eA3ERnE,EAAyE,KAAA,CAArE,GAAG,qBAAqB,MAAM,uBAAA,EAAwB,aAAU,EAAA,GACpEU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAEI,IAAA,CAFD,MAAM,yBAAA,EAA0B,sFAEnC,EAAA,GAGQ5B,EAAA,MAAK,WAAW,iBAAiB,QADzC0D,IAAA1B,EAOI,IAPJgE,GAGC,gDAEExD,EAAGxC,EAAA,MAAK,WAAW,iBAAiB,YAAa,6FAEpD,CAAA,YAEA4B,EA4DK,KA5DLqE,GA4DK,CA3DHrE,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAa,UAAT,OAAI,EAAA,GACRA,EAAgD,KAAhDsE,GAAgD1D,EAA5BxC,QAAK,WAAW,IAAI,EAAA,CAAA,CAAA,GAE1C4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAiB,UAAb,WAAQ,EAAA,GACZA,EAAmD,KAAnDuE,GAAmD3D,EAA/BxC,QAAK,WAAW,OAAO,EAAA,CAAA,CAAA,GAE7C4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAsB,UAAlB,gBAAa,EAAA,GACjBA,EAAwD,KAAxDwE,GAAwD5D,EAApCxC,QAAK,WAAW,YAAY,EAAA,CAAA,CAAA,GAElD4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAA0B,UAAtB,oBAAiB,EAAA,GACrBA,EAA6C,KAAA,KAAAY,EAAtCxC,EAAA,MAAK,WAAW,cAAc,EAAA,CAAA,CAAA,GAE5BA,EAAA,MAAK,WAAW,iBAA3BgC,EAGM,MAAAqE,GAAA,CAFJ/D,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAqB,UAAjB,eAAY,EAAA,GAChBA,EAAuD,KAAvD0E,GAAuD9D,EAAnCxC,QAAK,WAAW,WAAW,EAAA,CAAA,CAAA,aAEjD4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAgB,UAAZ,UAAO,EAAA,GACXA,EAAuD,KAAA,KAAAY,EAAhDxC,EAAA,MAAK,IAAI,IAAI,EAAG,OAAIwC,EAAGxC,EAAA,MAAK,IAAI,QAAQ,EAAA,CAAA,CAAA,GAEjD4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAsB,UAAlB,gBAAa,EAAA,GACjBA,EAA4E,KAA5E2E,GAA4E/D,EAAhDI,EAAApB,CAAA,EAAYxB,EAAA,MAAK,WAAW,WAAW,CAAA,EAAA,CAAA,CAAA,GAErE4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAqB,UAAjB,eAAY,EAAA,GAChBA,EAAqE,KAArE4E,GAAqEhE,EAAzCxC,QAAK,WAAW,iBAAiB,EAAA,CAAA,CAAA,GAE/D4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAuB,UAAnB,iBAAc,EAAA,GAClBA,EAAgD,KAAhD6E,GAAgDjE,EAA5BxC,QAAK,WAAW,IAAI,EAAA,CAAA,CAAA,GAE/BA,EAAA,MAAK,WAAW,eAA3BgC,EAGM,MAAA0E,GAAA,CAFJpE,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAqB,UAAjB,eAAY,EAAA,GAChBA,EAAqD,KAArD+E,GAAqDnE,EAAjCxC,QAAK,WAAW,SAAS,EAAA,CAAA,CAAA,aAEpCA,EAAA,MAAK,WAAW,kBAAe,UAA1CgC,EAMM,MAAA4E,GAAA,CALJtE,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAyB,UAArB,mBAAgB,EAAA,GACpBA,EAGK,KAHLiF,GAGKrE,EAFAxC,EAAA,MAAK,WAAW,eAAe,EAAG,wBAClCA,EAAA,MAAK,WAAW,gBAAgB,EAAG,MACxC,CAAA,CAAA,aAEF4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAA4B,UAAxB,sBAAmB,EAAA,GACvBA,EAAwD,KAAA,KAAAY,EAAjDxC,EAAA,MAAK,WAAW,WAAU,MAAA,IAAA,EAAA,CAAA,CAAA,GAExBA,EAAA,MAAK,WAAW,aAAa,YAAxCgC,EAGM,MAAA8E,GAAA,CAFJxE,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAA4B,UAAxB,sBAAmB,EAAA,GACvBA,EAAmE,KAAnEmF,GAAmEvE,EAA/CxC,EAAA,MAAK,WAAW,aAAa,KAAI,IAAA,CAAA,EAAA,CAAA,CAAA,aAEvD4B,EAGM,MAAA,KAAA,CAFJU,EAAA,EAAA,IAAAA,EAAA,EAAA,EAAAV,EAAkB,UAAd,YAAS,EAAA,GACbA,EAAuC,KAAA,KAAAY,EAAhCxC,EAAA,MAAK,WAAW,QAAQ,EAAA,CAAA,CAAA"}