@promptowl/contextnest-community 1.26.0 → 1.27.0

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 (94) hide show
  1. package/API.md +34 -1
  2. package/CONFIGURATION.md +32 -1
  3. package/dist/{chunk-TRSGPS27.js → chunk-H3W72HN3.js} +28 -0
  4. package/dist/{chunk-DGPTJXIV.js → chunk-MB52DWWP.js} +4 -4
  5. package/dist/{chunk-IEAWRHMV.js → chunk-NFFUZF2B.js} +23 -2
  6. package/dist/{chunk-PICUHQEM.js → chunk-O3JEI33N.js} +2 -2
  7. package/dist/{chunk-SWA5M5XX.js → chunk-QMQDWRHN.js} +128 -22
  8. package/dist/{chunk-I5EDEZBQ.js → chunk-RXCVXG34.js} +1 -1
  9. package/dist/{chunk-2QOJE7A5.js → chunk-SE5U4J4T.js} +4 -4
  10. package/dist/{chunk-RPGFHESR.js → chunk-VHEMGQ3I.js} +1 -1
  11. package/dist/{chunk-M6PGYMBD.js → chunk-VRLAP4HB.js} +33 -15
  12. package/dist/{engine-QNMFDIBV.js → engine-HLYQLP5T.js} +3 -3
  13. package/dist/{external-edit-service-4MEGPT4D.js → external-edit-service-3DFQ4EZZ.js} +4 -4
  14. package/dist/{grants-service-24GLUBY4.js → grants-service-WICV4Y2J.js} +2 -2
  15. package/dist/index.js +804 -304
  16. package/dist/{invited-user-AM6A3WGO.js → invited-user-XEBX6BM4.js} +3 -3
  17. package/dist/{review-service-2EWN7WWO.js → review-service-GB43UQVH.js} +7 -7
  18. package/dist/{stewardship-service-TDZUC2Q6.js → stewardship-service-KDBPWRZI.js} +4 -4
  19. package/dist/{version-service-C3JTZLJH.js → version-service-JYHFPSYP.js} +8 -4
  20. package/dist/web3/assets/{ActivityTracePage-DzwWIjjx.js → ActivityTracePage-CkRoyIc-.js} +1 -1
  21. package/dist/web3/assets/AgentDocsPage-BTRXmliv.js +1 -0
  22. package/dist/web3/assets/CollaboratorManager-CqJIkvs-.js +1 -0
  23. package/dist/web3/assets/CollaboratorsTab-JcO1P-qm.js +1 -0
  24. package/dist/web3/assets/DocumentEditor-D1GLeeEP.js +36 -0
  25. package/dist/web3/assets/DocumentsTab-BAgSxTX1.js +6 -0
  26. package/dist/web3/assets/ExternalEditsTab-DuuTXZap.js +1 -0
  27. package/dist/web3/assets/{MarkdownEditor-CKh4WSn-.js → MarkdownEditor-BELFww9q.js} +116 -126
  28. package/dist/web3/assets/{NestPageHeader-Cizo8nUi.js → NestPageHeader-Bbje2ncY.js} +1 -1
  29. package/dist/web3/assets/NestView-D4OMXPQ7.js +73 -0
  30. package/dist/web3/assets/OverviewTab-FIDGjR3Q.js +6 -0
  31. package/dist/web3/assets/{PersonCombobox-BKI7dff4.js → PersonCombobox-D52m_jhc.js} +1 -1
  32. package/dist/web3/assets/{ReviewActions-CS8JXgXF.js → ReviewActions-DYqBcWlv.js} +2 -2
  33. package/dist/web3/assets/ReviewTab-DoxfygOb.js +1 -0
  34. package/dist/web3/assets/StewardsTab-CFsYjbEn.js +1 -0
  35. package/dist/web3/assets/{SubmitForReviewModal-Biq3m79i.js → SubmitForReviewModal-AW2OLNAE.js} +1 -1
  36. package/dist/web3/assets/{alert-dialog-BvF3NFr7.js → alert-dialog-p-fBLSWx.js} +2 -2
  37. package/dist/web3/assets/{arrow-left-CWIsv-sG.js → arrow-left-CiErCCTG.js} +1 -1
  38. package/dist/web3/assets/{backlinks-Cqcn7n1J.js → backlinks-DaVSYvhV.js} +2 -2
  39. package/dist/web3/assets/{boxes-ClbgQqG2.js → boxes-VWrCCMzW.js} +1 -1
  40. package/dist/web3/assets/{chevron-left-CK_ZPFm9.js → chevron-left-CsD8gZwL.js} +1 -1
  41. package/dist/web3/assets/{circle-check-Bw_aTXiH.js → circle-check-BBCXd9LI.js} +1 -1
  42. package/dist/web3/assets/{circle-x-DkIG68H7.js → circle-x-C9LsnORQ.js} +1 -1
  43. package/dist/web3/assets/{code-xml-BlR7EN6l.js → code-xml-BaoV7HiQ.js} +1 -1
  44. package/dist/web3/assets/{corner-down-right-DSVxK3tf.js → corner-down-right-DgiTXrtw.js} +1 -1
  45. package/dist/web3/assets/{count-skeleton-DToLM74B.js → count-skeleton-CnEE4uF-.js} +1 -1
  46. package/dist/web3/assets/{earth-BXhVPvCR.js → earth-BmMbVt9k.js} +1 -1
  47. package/dist/web3/assets/{file-exclamation-point-BevGZgtj.js → file-exclamation-point-qJeca9-A.js} +1 -1
  48. package/dist/web3/assets/{folder-input-m8UBV4fA.js → folder-input-D7R93LJ6.js} +1 -1
  49. package/dist/web3/assets/index-DNmWTxN7.css +1 -0
  50. package/dist/web3/assets/index-DvuUIUP6.js +451 -0
  51. package/dist/web3/assets/{page-DzKwP5Ds.js → page-BJQuaTRW.js} +2 -2
  52. package/dist/web3/assets/{page-B6pkc9cd.js → page-Bb8xGOPQ.js} +2 -2
  53. package/dist/web3/assets/{page-Deq6IKiN.js → page-BtM-qDzr.js} +2 -2
  54. package/dist/web3/assets/{page-DPY01SOj.js → page-Bxd0EG25.js} +1 -1
  55. package/dist/web3/assets/page-C3QCO6IR.js +1 -0
  56. package/dist/web3/assets/{page-CptuAPJc.js → page-CfoR0khy.js} +2 -2
  57. package/dist/web3/assets/page-D7Zr5tAI.js +1 -0
  58. package/dist/web3/assets/{page-Dwbp4Seu.js → page-DATSlHCW.js} +2 -2
  59. package/dist/web3/assets/page-DTjPQizZ.js +45 -0
  60. package/dist/web3/assets/{page-Bgy9Ng9p.js → page-DspptlWr.js} +1 -1
  61. package/dist/web3/assets/{page-Dh57L0RG.js → page-I6vAFJOj.js} +4 -4
  62. package/dist/web3/assets/page-QxI4Ud2s.js +9 -0
  63. package/dist/web3/assets/{page-BJrFCKXB.js → page-YcNNg-dX.js} +1 -1
  64. package/dist/web3/assets/page-kM7eO5Kj.js +1 -0
  65. package/dist/web3/assets/{page-title-DVq4qvMR.js → page-title-Dn5jANiU.js} +1 -1
  66. package/dist/web3/assets/{play-CXhS6Pgq.js → play-B2k_Ix-L.js} +1 -1
  67. package/dist/web3/assets/{send-DdfwnIrj.js → send-DPNxv3As.js} +1 -1
  68. package/dist/web3/assets/{settings-DKX0Q4gO.js → settings-DZjq-OQA.js} +1 -1
  69. package/dist/web3/assets/{share-2-CxmXRt58.js → share-2-C-OnE2ru.js} +1 -1
  70. package/dist/web3/assets/{tag-DeYC_mRv.js → tag-CwJl7FdI.js} +1 -1
  71. package/dist/web3/assets/{trash-2-B0HyPTnI.js → trash-2-aljmIff4.js} +1 -1
  72. package/dist/web3/assets/{user-plus-Ckm_Isyc.js → user-plus-DPerZexX.js} +1 -1
  73. package/dist/web3/assets/{zap-D2ifcnYb.js → zap-CHZtiN7P.js} +1 -1
  74. package/dist/web3/index.html +2 -2
  75. package/package.json +6 -2
  76. package/dist/web3/assets/AgentDocsPage-ixP2UdAE.js +0 -1
  77. package/dist/web3/assets/CollaboratorManager-C9VAXZ0h.js +0 -1
  78. package/dist/web3/assets/CollaboratorsTab-tq4ZTexH.js +0 -1
  79. package/dist/web3/assets/DocumentEditor-C2CP2fiE.js +0 -36
  80. package/dist/web3/assets/DocumentsTab-Mh7KxUoB.js +0 -6
  81. package/dist/web3/assets/ExternalEditsTab-B_CWKXZ_.js +0 -1
  82. package/dist/web3/assets/NestView-EW-sraEb.js +0 -73
  83. package/dist/web3/assets/OverviewTab-CjidsMX_.js +0 -6
  84. package/dist/web3/assets/ReviewTab-CwVrXzw5.js +0 -1
  85. package/dist/web3/assets/StewardsTab-C-iP6gnh.js +0 -1
  86. package/dist/web3/assets/index-BOVYgMvj.js +0 -29
  87. package/dist/web3/assets/index-DVnaYqj9.css +0 -1
  88. package/dist/web3/assets/index-WYDmEOfO.js +0 -404
  89. package/dist/web3/assets/page-C2zoxumw.js +0 -1
  90. package/dist/web3/assets/page-CJWO06dN.js +0 -1
  91. package/dist/web3/assets/page-Dea2SblF.js +0 -9
  92. package/dist/web3/assets/page-Dfjg8p7Z.js +0 -1
  93. package/dist/web3/assets/page-YxjrE5b5.js +0 -45
  94. package/dist/web3/assets/x-mNtADYHc.js +0 -6
@@ -1 +1 @@
1
- import{cY as ue,Q as pe,r as p,u as xe,l as U,d1 as K,j as t,d2 as ge,d3 as D,f as fe,C as ve,i as j,w as je,L as be,d0 as Q,B as f,ar as V,bK as Y,ag as J,d4 as ye,d5 as ke,d6 as Ne,cd as _e,ce as we,aD as Ce,aI as Re}from"./index-WYDmEOfO.js";import{P as Se}from"./page-title-DVq4qvMR.js";import{A as $e,a as qe,R as We}from"./ReviewActions-CS8JXgXF.js";import{C as Ae}from"./circle-check-Bw_aTXiH.js";import{T as De}from"./trash-2-B0HyPTnI.js";import{C as Te}from"./circle-x-DkIG68H7.js";import{C as ze}from"./chevron-left-CK_ZPFm9.js";const G=8;function Ie(h,u,b=G){return u?h:h.slice(0,b)}function X(h,u){return h.filter(b=>b.id!==u)}function Me(h){return{reviews:h.filter(u=>u.type==="review"),requests:h.filter(u=>u.type!=="review")}}function Ke(){var E,L;const{openNest:h,openReview:u}=ue(),{adminStatus:b}=pe(),H=((E=b==null?void 0:b.me)==null?void 0:E.email)??null,[n,x]=p.useState({items:[],waiting:[]}),[Z,ee]=p.useState(!0),[T,z]=p.useState(!1),[l,S]=p.useState(null),[k,I]=p.useState("delete"),[d,y]=p.useState(new Set),[v,N]=p.useState(null),[$,te]=p.useState(!1),M=xe(),w=async e=>{z(!0);try{const s=await M.fetchQuery(U.myWork({offset:e}));x(a=>({items:s.items,waiting:s.waiting,notifications:s.notifications??a.notifications,pagination:s.pagination}));const i=new Set(s.items.map(a=>`${a.nest_id}:${a.node_id}`));y(a=>new Set([...a].filter(m=>i.has(m))))}catch(s){console.error("[Dashboard] goToWorkPage failed",s)}finally{z(!1)}};p.useEffect(()=>{M.fetchQuery(U.myWork()).then(x).catch(()=>x({items:[],waiting:[],notifications:[]})).finally(()=>ee(!1))},[H]);const se=async(e,s)=>{await ye(e.nest_id,e.node_id,s),R(e)},ie=async(e,s)=>{await ke(e.nest_id,e.node_id,s),R(e)},{reviews:g,requests:q}=Me(n.items),W=e=>`${e.nest_id}:${e.node_id}`,C=(()=>{const e=new Map;for(const i of g)d.has(W(i))&&e.set(i.nest_id,(e.get(i.nest_id)??0)+1);const s=Math.max(0,...e.values());return Math.max(0,s-K)})(),ne=async(e,s)=>{var F;const i=g.filter(o=>d.has(W(o)));if(i.length===0){j.info("Nothing selected on this page"),y(new Set),N(null);return}const a=new Map;for(const o of i)a.set(o.nest_id,[...a.get(o.nest_id)??[],o.node_id]);const m=await Promise.all([...a].map(([o,r])=>Ne(o,e,r,s||void 0).then(_=>({nestId:o,..._})).catch(_=>({nestId:o,succeeded:0,failed:r.length,results:r.map(he=>({nodeId:he,ok:!1,error:(_==null?void 0:_.message)||"Request failed"}))})))),A=m.reduce((o,r)=>o+r.succeeded,0),O=m.reduce((o,r)=>o+r.failed,0),me=new Set(m.flatMap(o=>o.results.filter(r=>!r.ok).map(r=>`${o.nestId}:${r.nodeId}`))),B=e==="approve"?"approved":"rejected";if(O===0)j.success(`${A} document${A===1?"":"s"} ${B}`);else{const o=[...new Set(m.flatMap(r=>r.results).filter(r=>!r.ok).map(r=>r.error||"Unknown reason"))];j.warning(`${A} ${B}, ${O} could not be`,{description:o.join(" "),duration:1e4})}y(me),N(null),w(((F=n.pagination)==null?void 0:F.offset)??0)},c=e=>e.target_type==="nest_archive",ae=e=>e.type!=="deletion"?"Review":c(e)?"Archive":"Deletion",oe=async()=>{const e=l;await _e(e.nest_id,e.request_id),R(e)},re=async e=>{const s=l;await we(s.nest_id,s.request_id,e),R(s)},de=async e=>{await Ce(e.nest_id,e.request_id),x(s=>({...s,waiting:s.waiting.filter(i=>!(i.nest_id===e.nest_id&&i.node_id===e.node_id))}))},le=async e=>{await Re(e.nest_id,e.node_id),x(s=>({...s,waiting:s.waiting.filter(i=>!(i.nest_id===e.nest_id&&i.node_id===e.node_id))}))},P=e=>{if(e.type==="deletion"&&e.target_type&&e.target_type!=="document"){h(e.nest_id,e.nest_name,!1,!1);return}u(e.nest_id,e.nest_name,e.node_id)},ce=e=>{D([e.id]).catch(()=>{}),x(s=>({...s,notifications:X(s.notifications??[],e.id)})),e.node_id?u(e.nest_id,e.nest_name,e.node_id):h(e.nest_id,e.nest_name,!1,!1)},R=e=>{var s;x(i=>({...i,items:i.items.filter(a=>!(a.nest_id===e.nest_id&&a.node_id===e.node_id))})),y(i=>{const a=new Set(i);return a.delete(`${e.nest_id}:${e.node_id}`),a}),w(((s=n.pagination)==null?void 0:s.offset)??0)};return t.jsxs("div",{className:"space-y-4",children:[t.jsx(Se,{icon:ge,title:"My Work",description:"Reviews and requests waiting on you, and what you handed off.",className:"mb-0"}),t.jsx("div",{children:t.jsxs("div",{className:"space-y-5",children:[t.jsxs("div",{children:[(((L=n.notifications)==null?void 0:L.length)??0)>0&&t.jsxs("div",{className:"mb-3 rounded-lg border border-amber-300/50 bg-amber-500/5",children:[t.jsxs("div",{className:"px-4 py-2 flex items-center gap-2 text-sm font-medium",children:["🔔 Notifications",t.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",n.notifications.length,")"]}),t.jsx("div",{className:"flex-1"}),t.jsx("button",{type:"button",className:"text-xs text-primary hover:underline",onClick:async()=>{await D("all"),x(e=>({...e,notifications:[]}))},children:"Mark all read"})]}),t.jsx("div",{className:je("divide-y border-t",$&&"max-h-80 overflow-y-auto"),children:Ie(n.notifications,$).map(e=>t.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 text-xs hover:bg-amber-500/10",children:[t.jsxs("button",{type:"button",onClick:()=>ce(e),className:"flex-1 flex items-center gap-2 text-left",children:[t.jsx("span",{className:"flex-1",children:e.message}),t.jsx("span",{className:"text-muted-foreground shrink-0",children:fe(e.created_at)})]}),t.jsx("button",{type:"button",title:"Mark as read","aria-label":"Mark as read",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-amber-500/20 hover:text-foreground",onClick:async()=>{try{await D([e.id]),x(s=>({...s,notifications:X(s.notifications??[],e.id)}))}catch(s){j.error((s==null?void 0:s.message)||"Failed to mark as read")}},children:t.jsx(ve,{className:"h-3.5 w-3.5"})})]},e.id))}),n.notifications.length>G&&t.jsx("div",{className:"border-t px-4 py-1.5 text-center",children:t.jsx("button",{type:"button",className:"text-xs text-primary hover:underline",onClick:()=>te(e=>!e),children:$?"Show less":`Show all (${n.notifications.length})`})})]}),Z?t.jsxs("div",{className:"rounded-lg border bg-muted/20 px-4 py-6 flex items-center justify-center gap-2 text-sm text-muted-foreground",children:[t.jsx(be,{className:"h-4 w-4 animate-spin"}),"Loading your work…"]}):n.items.length===0?t.jsx("div",{className:"rounded-lg border bg-muted/20 px-4 py-6 text-center text-sm text-muted-foreground",children:"You're all caught up — nothing waiting on you."}):t.jsxs("div",{className:"rounded-lg border divide-y overflow-hidden",children:[g.length>1&&t.jsxs("div",{className:"flex flex-wrap items-center gap-2 bg-muted/40 px-4 py-2 text-sm",children:[t.jsx(Q,{checked:d.size===0?!1:d.size===g.length?!0:"indeterminate",onCheckedChange:e=>y(e===!0?new Set(g.map(W)):new Set),"aria-label":"Select every review waiting on you","data-testid":"work-select-all"}),t.jsx("span",{className:"text-muted-foreground",children:d.size>0?`${d.size} selected`:`Select all ${g.length} reviews`}),C>0&&t.jsxs("span",{className:"text-destructive",children:["Up to ",K," per nest — deselect"," ",C,"."]}),d.size>0&&t.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[t.jsxs(f,{size:"sm",disabled:C>0,onClick:()=>N("approve"),"data-testid":"work-bulk-approve",children:["Approve ",d.size]}),t.jsxs(f,{size:"sm",variant:"outline",disabled:C>0,onClick:()=>N("reject"),"data-testid":"work-bulk-reject",children:["Reject ",d.size]}),t.jsx(f,{size:"sm",variant:"ghost",onClick:()=>y(new Set),children:"Clear"})]})]}),[...g,...q].map((e,s)=>{const i=`${e.nest_id}:${e.node_id}`;return t.jsxs(p.Fragment,{children:[s===g.length&&t.jsxs("div",{className:"bg-muted/40 px-4 py-2 text-sm text-muted-foreground",children:[q.length," ",q.length===1?"request":"requests"," · approve or reject each one"]}),t.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 hover:bg-muted/40 group",children:[g.length>1&&t.jsx(Q,{checked:d.has(i),disabled:e.type!=="review",onCheckedChange:()=>y(a=>{const m=new Set(a);return m.has(i)?m.delete(i):m.add(i),m}),"aria-label":`Select ${e.title}`,className:e.type==="review"?"":"invisible"}),t.jsx("span",{className:`rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide shrink-0 ${e.type==="deletion"&&!c(e)?"bg-red-100 text-red-800 dark:bg-red-950/40 dark:text-red-300":"bg-amber-100 text-amber-800 dark:bg-amber-950/40 dark:text-amber-300"}`,children:ae(e)}),t.jsxs("button",{onClick:()=>P(e),className:"flex items-center gap-2 min-w-0 flex-1 text-left",children:[t.jsx("span",{className:"font-medium truncate",children:e.title}),t.jsxs("span",{className:"text-xs text-muted-foreground truncate",children:["in ",e.nest_name," · ",e.requested_by," · ",V(e.requested_at),e.reason?` · "${e.reason}"`:""]})]}),t.jsx("div",{className:"flex items-center gap-2 shrink-0",children:e.type==="deletion"?t.jsxs(t.Fragment,{children:[t.jsxs(f,{variant:"outline",className:c(e)?$e:"text-destructive hover:text-destructive",onClick:()=>{I("delete"),S(e)},children:[c(e)?t.jsx(Ae,{className:"h-4 w-4 mr-2"}):t.jsx(De,{className:"h-4 w-4 mr-2"}),c(e)?"Approve":"Delete"]}),t.jsxs(f,{variant:"outline",className:qe,onClick:()=>{I("decline"),S(e)},children:[t.jsx(Te,{className:"h-4 w-4 mr-2"})," Reject"]})]}):t.jsx(We,{documentTitle:e.title,version:1,onApprove:a=>se(e,a),onReject:a=>ie(e,a)})})]})]},i)})]})]}),n.waiting.length>0&&t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[t.jsx("h3",{className:"text-sm font-semibold text-muted-foreground uppercase tracking-wide",children:"Waiting on others"}),t.jsx("span",{className:"rounded-full bg-muted text-muted-foreground text-xs font-semibold px-2 py-0.5",children:n.waiting.length})]}),t.jsx("div",{className:"rounded-lg border divide-y overflow-hidden",children:n.waiting.map(e=>t.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 hover:bg-muted/40 group text-sm",children:[t.jsxs("button",{onClick:()=>P(e),className:"flex items-center gap-3 flex-1 min-w-0 text-left",children:[t.jsx("span",{className:"font-medium truncate",children:e.title}),t.jsxs("span",{className:"text-xs text-muted-foreground shrink-0",children:["in ",e.nest_name," ·"," ",e.type==="deletion"?"requested":"submitted"," ",V(e.requested_at)]}),t.jsx("span",{className:"flex-1"}),t.jsx("span",{className:"text-xs text-muted-foreground",children:e.type!=="deletion"?"Pending Review":c(e)?"Archive Requested":"Deletion Requested"})]}),e.type==="deletion"&&e.request_id&&t.jsx(f,{size:"sm",variant:"ghost",className:"shrink-0 text-muted-foreground h-7 px-2",onClick:async s=>{s.stopPropagation();try{await de(e),j.success(c(e)?"Archive request withdrawn":"Deletion request withdrawn")}catch(i){j.error((i==null?void 0:i.message)||"Failed to withdraw deletion request")}},title:"Withdraw this deletion request",children:"Withdraw"}),e.type==="review"&&t.jsx(f,{size:"sm",variant:"ghost",className:"shrink-0 text-muted-foreground h-7 px-2",onClick:async s=>{s.stopPropagation();try{await le(e),j.success("Submission withdrawn — back to Draft")}catch(i){j.error((i==null?void 0:i.message)||"Failed to withdraw submission")}},title:"Withdraw this submission and return the document to Draft",children:"Withdraw"}),t.jsx(Y,{className:"h-4 w-4 text-muted-foreground group-hover:translate-x-0.5 transition-transform shrink-0"})]},`${e.nest_id}:${e.node_id}`))})]}),n.pagination&&n.pagination.total>n.pagination.limit&&t.jsxs("div",{className:"flex items-center justify-center gap-3 pt-1 text-sm text-muted-foreground",children:[t.jsxs(f,{variant:"outline",size:"sm",disabled:T||n.pagination.offset===0,onClick:()=>w(Math.max(0,n.pagination.offset-n.pagination.limit)),children:[t.jsx(ze,{className:"h-3.5 w-3.5 mr-1"}),"Prev"]}),t.jsxs("span",{children:["Page ",Math.floor(n.pagination.offset/n.pagination.limit)+1," of"," ",Math.max(1,Math.ceil(n.pagination.total/n.pagination.limit))]}),t.jsxs(f,{variant:"outline",size:"sm",disabled:T||!n.pagination.has_more,onClick:()=>w(n.pagination.offset+n.pagination.limit),children:["Next",t.jsx(Y,{className:"h-3.5 w-3.5 ml-1"})]})]})]})}),v&&t.jsx(J,{open:!0,onOpenChange:e=>!e&&N(null),title:v==="approve"?`Approve ${d.size} document${d.size===1?"":"s"}?`:`Reject ${d.size} document${d.size===1?"":"s"}?`,description:v==="approve"?"Approving publishes each one. Anything that changed since this inbox loaded is reported back and left alone.":"Each author gets the same reason and the work goes back to them.",label:v==="reject"?"Why?":"Comment (optional)",optionalReason:v==="approve",placeholder:"Shared with every author in this batch",confirmLabel:v==="approve"?"Approve all":"Reject all",destructive:v==="reject",onConfirm:e=>ne(v,e)}),l&&t.jsx(J,{open:!0,onOpenChange:e=>!e&&S(null),title:k!=="delete"?`Reject this ${c(l)?"archive":"deletion"} request`:c(l)?`Archive "${l.title}"?`:`Delete "${l.title}"?`,description:`${l.requested_by} asked for this: "${l.reason??""}". ${k!=="delete"?c(l)?"The nest stays where it is; your note is the record, and the requester is notified.":"The document stays; your note is the record, and the requester is notified.":c(l)?"The nest goes read-only and leaves the dashboard; nothing is deleted and you can restore it.":"Deleting removes the document, its history, comments and annotations. It cannot be undone."}`,label:k==="decline"?"Why are you rejecting?":void 0,placeholder:"e.g. still referenced by onboarding",confirmLabel:k!=="delete"?"Reject":c(l)?"Archive nest":"Delete document",destructive:k==="delete"&&!c(l),onConfirm:k==="delete"?oe:re})]})}export{Ke as default};
1
+ import{dl as ue,S as pe,r as p,u as xe,l as U,dr as Q,j as t,ds as ge,dt as T,f as fe,C as ve,i as j,w as je,L as be,dq as K,B as f,av as V,bQ as H,ak as J,du as ye,dv as ke,dw as Ne,ck as _e,cl as we,aH as Ce,aM as Re}from"./index-DvuUIUP6.js";import{P as Se}from"./page-title-Dn5jANiU.js";import{A as $e,a as qe,R as We}from"./ReviewActions-DYqBcWlv.js";import{C as Ae}from"./circle-check-BBCXd9LI.js";import{T as Te}from"./trash-2-aljmIff4.js";import{C as De}from"./circle-x-C9LsnORQ.js";import{C as Me}from"./chevron-left-CsD8gZwL.js";const Y=8;function ze(h,u,b=Y){return u?h:h.slice(0,b)}function X(h,u){return h.filter(b=>b.id!==u)}function Ie(h){return{reviews:h.filter(u=>u.type==="review"),requests:h.filter(u=>u.type!=="review")}}function Qe(){var E,L;const{openNest:h,openReview:u}=ue(),{adminStatus:b}=pe(),G=((E=b==null?void 0:b.me)==null?void 0:E.email)??null,[n,x]=p.useState({items:[],waiting:[]}),[Z,ee]=p.useState(!0),[D,M]=p.useState(!1),[l,S]=p.useState(null),[k,z]=p.useState("delete"),[d,y]=p.useState(new Set),[v,N]=p.useState(null),[$,te]=p.useState(!1),I=xe(),w=async e=>{M(!0);try{const s=await I.fetchQuery(U.myWork({offset:e}));x(a=>({items:s.items,waiting:s.waiting,notifications:s.notifications??a.notifications,pagination:s.pagination}));const i=new Set(s.items.map(a=>`${a.nest_id}:${a.node_id}`));y(a=>new Set([...a].filter(m=>i.has(m))))}catch(s){console.error("[Dashboard] goToWorkPage failed",s)}finally{M(!1)}};p.useEffect(()=>{I.fetchQuery(U.myWork()).then(x).catch(()=>x({items:[],waiting:[],notifications:[]})).finally(()=>ee(!1))},[G]);const se=async(e,s)=>{await ye(e.nest_id,e.node_id,s),R(e)},ie=async(e,s)=>{await ke(e.nest_id,e.node_id,s),R(e)},{reviews:g,requests:q}=Ie(n.items),W=e=>`${e.nest_id}:${e.node_id}`,C=(()=>{const e=new Map;for(const i of g)d.has(W(i))&&e.set(i.nest_id,(e.get(i.nest_id)??0)+1);const s=Math.max(0,...e.values());return Math.max(0,s-Q)})(),ne=async(e,s)=>{var F;const i=g.filter(o=>d.has(W(o)));if(i.length===0){j.info("Nothing selected on this page"),y(new Set),N(null);return}const a=new Map;for(const o of i)a.set(o.nest_id,[...a.get(o.nest_id)??[],o.node_id]);const m=await Promise.all([...a].map(([o,r])=>Ne(o,e,r,s||void 0).then(_=>({nestId:o,..._})).catch(_=>({nestId:o,succeeded:0,failed:r.length,results:r.map(he=>({nodeId:he,ok:!1,error:(_==null?void 0:_.message)||"Request failed"}))})))),A=m.reduce((o,r)=>o+r.succeeded,0),O=m.reduce((o,r)=>o+r.failed,0),me=new Set(m.flatMap(o=>o.results.filter(r=>!r.ok).map(r=>`${o.nestId}:${r.nodeId}`))),B=e==="approve"?"approved":"rejected";if(O===0)j.success(`${A} document${A===1?"":"s"} ${B}`);else{const o=[...new Set(m.flatMap(r=>r.results).filter(r=>!r.ok).map(r=>r.error||"Unknown reason"))];j.warning(`${A} ${B}, ${O} could not be`,{description:o.join(" "),duration:1e4})}y(me),N(null),w(((F=n.pagination)==null?void 0:F.offset)??0)},c=e=>e.target_type==="nest_archive",ae=e=>e.type!=="deletion"?"Review":c(e)?"Archive":"Deletion",oe=async()=>{const e=l;await _e(e.nest_id,e.request_id),R(e)},re=async e=>{const s=l;await we(s.nest_id,s.request_id,e),R(s)},de=async e=>{await Ce(e.nest_id,e.request_id),x(s=>({...s,waiting:s.waiting.filter(i=>!(i.nest_id===e.nest_id&&i.node_id===e.node_id))}))},le=async e=>{await Re(e.nest_id,e.node_id),x(s=>({...s,waiting:s.waiting.filter(i=>!(i.nest_id===e.nest_id&&i.node_id===e.node_id))}))},P=e=>{if(e.type==="deletion"&&e.target_type&&e.target_type!=="document"){h(e.nest_id,e.nest_name,!1,!1);return}u(e.nest_id,e.nest_name,e.node_id)},ce=e=>{T([e.id]).catch(()=>{}),x(s=>({...s,notifications:X(s.notifications??[],e.id)})),e.node_id?u(e.nest_id,e.nest_name,e.node_id):h(e.nest_id,e.nest_name,!1,!1)},R=e=>{var s;x(i=>({...i,items:i.items.filter(a=>!(a.nest_id===e.nest_id&&a.node_id===e.node_id))})),y(i=>{const a=new Set(i);return a.delete(`${e.nest_id}:${e.node_id}`),a}),w(((s=n.pagination)==null?void 0:s.offset)??0)};return t.jsxs("div",{className:"space-y-4",children:[t.jsx(Se,{icon:ge,title:"My Work",description:"Reviews and requests waiting on you, and what you handed off.",className:"mb-0"}),t.jsx("div",{children:t.jsxs("div",{className:"space-y-5",children:[t.jsxs("div",{children:[(((L=n.notifications)==null?void 0:L.length)??0)>0&&t.jsxs("div",{className:"mb-3 rounded-lg border border-amber-300/50 bg-amber-500/5",children:[t.jsxs("div",{className:"px-4 py-2 flex items-center gap-2 text-sm font-medium",children:["🔔 Notifications",t.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",n.notifications.length,")"]}),t.jsx("div",{className:"flex-1"}),t.jsx("button",{type:"button",className:"text-xs text-primary hover:underline",onClick:async()=>{await T("all"),x(e=>({...e,notifications:[]}))},children:"Mark all read"})]}),t.jsx("div",{className:je("divide-y border-t",$&&"max-h-80 overflow-y-auto"),children:ze(n.notifications,$).map(e=>t.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 text-xs hover:bg-amber-500/10",children:[t.jsxs("button",{type:"button",onClick:()=>ce(e),className:"flex-1 flex items-center gap-2 text-left",children:[t.jsx("span",{className:"flex-1",children:e.message}),t.jsx("span",{className:"text-muted-foreground shrink-0",children:fe(e.created_at)})]}),t.jsx("button",{type:"button",title:"Mark as read","aria-label":"Mark as read",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-amber-500/20 hover:text-foreground",onClick:async()=>{try{await T([e.id]),x(s=>({...s,notifications:X(s.notifications??[],e.id)}))}catch(s){j.error((s==null?void 0:s.message)||"Failed to mark as read")}},children:t.jsx(ve,{className:"h-3.5 w-3.5"})})]},e.id))}),n.notifications.length>Y&&t.jsx("div",{className:"border-t px-4 py-1.5 text-center",children:t.jsx("button",{type:"button",className:"text-xs text-primary hover:underline",onClick:()=>te(e=>!e),children:$?"Show less":`Show all (${n.notifications.length})`})})]}),Z?t.jsxs("div",{className:"rounded-lg border bg-muted/20 px-4 py-6 flex items-center justify-center gap-2 text-sm text-muted-foreground",children:[t.jsx(be,{className:"h-4 w-4 animate-spin"}),"Loading your work…"]}):n.items.length===0?t.jsx("div",{className:"rounded-lg border bg-muted/20 px-4 py-6 text-center text-sm text-muted-foreground",children:"You're all caught up — nothing waiting on you."}):t.jsxs("div",{className:"rounded-lg border divide-y overflow-hidden",children:[g.length>1&&t.jsxs("div",{className:"flex flex-wrap items-center gap-2 bg-muted/40 px-4 py-2 text-sm",children:[t.jsx(K,{checked:d.size===0?!1:d.size===g.length?!0:"indeterminate",onCheckedChange:e=>y(e===!0?new Set(g.map(W)):new Set),"aria-label":"Select every review waiting on you","data-testid":"work-select-all"}),t.jsx("span",{className:"text-muted-foreground",children:d.size>0?`${d.size} selected`:`Select all ${g.length} reviews`}),C>0&&t.jsxs("span",{className:"text-destructive",children:["Up to ",Q," per nest — deselect"," ",C,"."]}),d.size>0&&t.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[t.jsxs(f,{size:"sm",disabled:C>0,onClick:()=>N("approve"),"data-testid":"work-bulk-approve",children:["Approve ",d.size]}),t.jsxs(f,{size:"sm",variant:"outline",disabled:C>0,onClick:()=>N("reject"),"data-testid":"work-bulk-reject",children:["Reject ",d.size]}),t.jsx(f,{size:"sm",variant:"ghost",onClick:()=>y(new Set),children:"Clear"})]})]}),[...g,...q].map((e,s)=>{const i=`${e.nest_id}:${e.node_id}`;return t.jsxs(p.Fragment,{children:[s===g.length&&t.jsxs("div",{className:"bg-muted/40 px-4 py-2 text-sm text-muted-foreground",children:[q.length," ",q.length===1?"request":"requests"," · approve or reject each one"]}),t.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 hover:bg-muted/40 group",children:[g.length>1&&t.jsx(K,{checked:d.has(i),disabled:e.type!=="review",onCheckedChange:()=>y(a=>{const m=new Set(a);return m.has(i)?m.delete(i):m.add(i),m}),"aria-label":`Select ${e.title}`,className:e.type==="review"?"":"invisible"}),t.jsx("span",{className:`rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide shrink-0 ${e.type==="deletion"&&!c(e)?"bg-red-100 text-red-800 dark:bg-red-950/40 dark:text-red-300":"bg-amber-100 text-amber-800 dark:bg-amber-950/40 dark:text-amber-300"}`,children:ae(e)}),t.jsxs("button",{onClick:()=>P(e),className:"flex items-center gap-2 min-w-0 flex-1 text-left",children:[t.jsx("span",{className:"font-medium truncate",children:e.title}),t.jsxs("span",{className:"text-xs text-muted-foreground truncate",children:["in ",e.nest_name," · ",e.requested_by," · ",V(e.requested_at),e.reason?` · "${e.reason}"`:""]})]}),t.jsx("div",{className:"flex items-center gap-2 shrink-0",children:e.type==="deletion"?t.jsxs(t.Fragment,{children:[t.jsxs(f,{variant:"outline",className:c(e)?$e:"text-destructive hover:text-destructive",onClick:()=>{z("delete"),S(e)},children:[c(e)?t.jsx(Ae,{className:"h-4 w-4 mr-2"}):t.jsx(Te,{className:"h-4 w-4 mr-2"}),c(e)?"Approve":"Delete"]}),t.jsxs(f,{variant:"outline",className:qe,onClick:()=>{z("decline"),S(e)},children:[t.jsx(De,{className:"h-4 w-4 mr-2"})," Reject"]})]}):t.jsx(We,{documentTitle:e.title,version:1,onApprove:a=>se(e,a),onReject:a=>ie(e,a)})})]})]},i)})]})]}),n.waiting.length>0&&t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[t.jsx("h3",{className:"text-sm font-semibold text-muted-foreground uppercase tracking-wide",children:"Waiting on others"}),t.jsx("span",{className:"rounded-full bg-muted text-muted-foreground text-xs font-semibold px-2 py-0.5",children:n.waiting.length})]}),t.jsx("div",{className:"rounded-lg border divide-y overflow-hidden",children:n.waiting.map(e=>t.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 hover:bg-muted/40 group text-sm",children:[t.jsxs("button",{onClick:()=>P(e),className:"flex items-center gap-3 flex-1 min-w-0 text-left",children:[t.jsx("span",{className:"font-medium truncate",children:e.title}),t.jsxs("span",{className:"text-xs text-muted-foreground shrink-0",children:["in ",e.nest_name," ·"," ",e.type==="deletion"?"requested":"submitted"," ",V(e.requested_at)]}),t.jsx("span",{className:"flex-1"}),t.jsx("span",{className:"text-xs text-muted-foreground",children:e.type!=="deletion"?"Pending Review":c(e)?"Archive Requested":"Deletion Requested"})]}),e.type==="deletion"&&e.request_id&&t.jsx(f,{size:"sm",variant:"ghost",className:"shrink-0 text-muted-foreground h-7 px-2",onClick:async s=>{s.stopPropagation();try{await de(e),j.success(c(e)?"Archive request withdrawn":"Deletion request withdrawn")}catch(i){j.error((i==null?void 0:i.message)||"Failed to withdraw deletion request")}},title:"Withdraw this deletion request",children:"Withdraw"}),e.type==="review"&&t.jsx(f,{size:"sm",variant:"ghost",className:"shrink-0 text-muted-foreground h-7 px-2",onClick:async s=>{s.stopPropagation();try{await le(e),j.success("Submission withdrawn — back to Draft")}catch(i){j.error((i==null?void 0:i.message)||"Failed to withdraw submission")}},title:"Withdraw this submission and return the document to Draft",children:"Withdraw"}),t.jsx(H,{className:"h-4 w-4 text-muted-foreground group-hover:translate-x-0.5 transition-transform shrink-0"})]},`${e.nest_id}:${e.node_id}`))})]}),n.pagination&&n.pagination.total>n.pagination.limit&&t.jsxs("div",{className:"flex items-center justify-center gap-3 pt-1 text-sm text-muted-foreground",children:[t.jsxs(f,{variant:"outline",size:"sm",disabled:D||n.pagination.offset===0,onClick:()=>w(Math.max(0,n.pagination.offset-n.pagination.limit)),children:[t.jsx(Me,{className:"h-3.5 w-3.5 mr-1"}),"Prev"]}),t.jsxs("span",{children:["Page ",Math.floor(n.pagination.offset/n.pagination.limit)+1," of"," ",Math.max(1,Math.ceil(n.pagination.total/n.pagination.limit))]}),t.jsxs(f,{variant:"outline",size:"sm",disabled:D||!n.pagination.has_more,onClick:()=>w(n.pagination.offset+n.pagination.limit),children:["Next",t.jsx(H,{className:"h-3.5 w-3.5 ml-1"})]})]})]})}),v&&t.jsx(J,{open:!0,onOpenChange:e=>!e&&N(null),title:v==="approve"?`Approve ${d.size} document${d.size===1?"":"s"}?`:`Reject ${d.size} document${d.size===1?"":"s"}?`,description:v==="approve"?"Approving publishes each one. Anything that changed since this inbox loaded is reported back and left alone.":"Each author gets the same reason and the work goes back to them.",label:v==="reject"?"Why?":"Comment (optional)",optionalReason:v==="approve",placeholder:"Shared with every author in this batch",confirmLabel:v==="approve"?"Approve all":"Reject all",destructive:v==="reject",onConfirm:e=>ne(v,e)}),l&&t.jsx(J,{open:!0,onOpenChange:e=>!e&&S(null),title:k!=="delete"?`Reject this ${c(l)?"archive":"deletion"} request`:c(l)?`Archive "${l.title}"?`:`Delete "${l.title}"?`,description:`${l.requested_by} asked for this: "${l.reason??""}". ${k!=="delete"?c(l)?"The nest stays where it is; your note is the record, and the requester is notified.":"The document stays; your note is the record, and the requester is notified.":c(l)?"The nest goes read-only and leaves the dashboard; nothing is deleted and you can restore it.":"Deleting removes the document, its history, comments and annotations. It cannot be undone."}`,label:k==="decline"?"Why are you rejecting?":void 0,placeholder:"e.g. still referenced by onboarding",confirmLabel:k!=="delete"?"Reject":c(l)?"Archive nest":"Delete document",destructive:k==="delete"&&!c(l),onConfirm:k==="delete"?oe:re})]})}export{Qe as default};
@@ -0,0 +1 @@
1
+ import{S as ue,u as me,r as o,aY as ge,aZ as fe,a6 as xe,l as pe,a_ as W,a$ as he,b0 as ye,b1 as je,i as b,ar as be,n as ve,b2 as x,aN as V,b3 as Ne,j as e,I as q,B as I,b4 as Ce,R as we,L as ke,b5 as De,X as Se,b6 as U,aa as Fe,b7 as Ae,F as Oe,b8 as Ee}from"./index-DvuUIUP6.js";import{N as Te}from"./NestPageHeader-Bbje2ncY.js";import{s as $e}from"./folder-target-CUSWqImF.js";import{G as Me,Z as Re,F as Be}from"./zap-CHZtiN7P.js";import"./arrow-left-CiErCCTG.js";const ee="cn.board.";function Le(n){try{const u=localStorage.getItem(ee+n);if(u){const m=JSON.parse(u),v=m.dimension==="status"||m.dimension==="tag"?m.dimension:"folder",k=typeof m.tagNamespace=="string"?m.tagNamespace:"",p=l=>Array.isArray(l)?l.filter(f=>typeof f=="string"):void 0,g={};for(const[l,f]of Object.entries(m.layouts??{}))f&&typeof f=="object"&&(g[l]=U(l,{columnOrder:p(f.columnOrder),hiddenColumns:p(f.hiddenColumns)}));const h={columnOrder:p(m.columnOrder),hiddenColumns:p(m.hiddenColumns)};if(h.columnOrder||h.hiddenColumns){const l=W({dimension:v,tagNamespace:k});g[l]??(g[l]=U(l,h))}return{dimension:v,tagNamespace:k,layouts:g}}}catch{}return{dimension:"folder",tagNamespace:"",layouts:{}}}function K(n,u){try{localStorage.setItem(ee+n,JSON.stringify(u))}catch{}}function Pe({type:n}){const u="h-3.5 w-3.5 shrink-0";return n==="skill"?e.jsx(Re,{className:`${u} text-blue-500`}):n==="agent"?e.jsx(Fe,{className:`${u} text-violet-500`}):n==="table"?e.jsx(Ae,{className:`${u} text-emerald-500`}):n==="pdf"?e.jsx(Be,{className:`${u} text-rose-500`}):e.jsx(Oe,{className:`${u} text-muted-foreground`})}function Ge({nestId:n,nestName:u,isOwner:m,isArchived:v,onBack:k,onOpenDocument:p}){var Y,J,Q;const{isAdmin:g}=ue(),h=me(),[l,f]=o.useState([]),[O,P]=o.useState(!0),[G,z]=o.useState(null),[d,Z]=o.useState(()=>Le(n)),[E,T]=o.useState(null),[_,$]=o.useState(null),[se,D]=o.useState(null),[te,H]=o.useState(!1),[S,ae]=o.useState(!1);o.useEffect(()=>{let s=!1;return ge(n).then(t=>{s||ae(fe({roles:(t==null?void 0:t.roles)??[],permission:(t==null?void 0:t.permission)??null,myStewards:(t==null?void 0:t.myStewards)??[],isOwner:m,isAdmin:g,isArchived:v||xe(t==null?void 0:t.nest)}).canEditDocs)}).catch(()=>{}),()=>{s=!0}},[n,m,g,v]);const N=o.useCallback(async()=>{P(!0),z(null);try{const{nodes:s}=await h.fetchQuery(pe.nodesMeta(n));f(s.map(t=>({id:t.id,title:t.title??t.id,type:t.type??"document",tags:Array.isArray(t.tags)?t.tags:[],status:t.status??""})))}catch(s){z((s==null?void 0:s.message)||"Failed to load nodes")}finally{P(!1)}},[n,h]);o.useEffect(()=>{N()},[N]);const X=o.useCallback(s=>{Z(t=>{const i={...t,...s};return K(n,i),i})},[n]),y=o.useCallback(s=>{Z(t=>{const i=W(t),a={...t,layouts:{...t.layouts,[i]:{...t.layouts[i],...s}}};return K(n,a),a})},[n]),r=o.useMemo(()=>he(d),[d]),{columns:C,byColumn:ne}=o.useMemo(()=>ye(l,r),[l,r]),re=o.useCallback(async s=>{const t=E,i=_;if(T(null),$(null),D(null),!t)return;const a=l.find(w=>w.id===t);if(!a)return;const c=je(a,s,r,i??void 0);if(c.kind==="unsupported"){c.reason!=="Already in this column."&&b(c.reason);return}H(!0);try{c.kind==="move-folder"?(await be(n,t,c.folder),b.success("Moved")):c.kind==="retag"&&(await ve(n,t,{tags:c.tags}),b.success("Retagged")),await N()}catch(w){b.error((w==null?void 0:w.message)||"Move failed")}finally{H(!1)}},[E,_,l,r,n,N]),F=(r.dimension==="folder"||r.dimension==="tag")&&S,[M,R]=o.useState(null),[oe,A]=o.useState(null),[B,L]=o.useState(""),j=o.useMemo(()=>C.map(s=>s.key).filter(s=>s!==x),[C]),ie=o.useCallback((s,t)=>{if(s===t)return;const i=[...j],a=i.indexOf(s),c=i.indexOf(t);a<0||c<0||(i.splice(a,1),i.splice(c,0,s),y({columnOrder:i}))},[j,y]),le=o.useCallback(s=>y({...r.explicitColumns?{columnOrder:j.filter(t=>t!==s)}:{},hiddenColumns:[...new Set([...r.hiddenColumns??[],s])]}),[j,r.explicitColumns,r.hiddenColumns,y]),de=o.useCallback(s=>{const t=r.dimension==="folder"?$e(s):s.trim().replace(/^#/,"");if(r.dimension==="folder"&&!t){s.trim()&&b("A folder name needs at least one letter or digit.");return}if(t){if(r.dimension==="folder"&&t.split("/").length>V){b(`Folders may nest at most ${V} levels deep.`);return}y({columnOrder:[...new Set([...j,t])],hiddenColumns:(r.hiddenColumns??[]).filter(i=>i!==t)}),L("")}},[j,r.dimension,r.hiddenColumns,y]),ce=o.useMemo(()=>{if(r.dimension!=="tag")return[];const s=new Set;for(const t of l)for(const i of Ne(t,r))i!==x&&s.add(i);return[...s].sort()},[l,r]);return e.jsxs("div",{className:"space-y-4",children:[e.jsx(Te,{nestName:u,onBack:k,children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{className:"text-sm text-muted-foreground",children:"Columns by"}),e.jsxs("select",{value:d.dimension,onChange:s=>{L(""),X({dimension:s.target.value})},className:"h-8 rounded-md border border-input bg-background px-2 text-sm",children:[e.jsx("option",{value:"folder",children:"Folder"}),e.jsx("option",{value:"status",children:"Status"}),e.jsx("option",{value:"tag",children:"Tag namespace"})]}),d.dimension==="tag"&&e.jsx(q,{value:d.tagNamespace??"",onChange:s=>X({tagNamespace:s.target.value}),placeholder:"all tags",className:"h-8 w-32",title:"Optional. Empty groups by every tag; a namespace like 'stage' groups by stage:<value> tags only."}),(d.dimension==="tag"||r.dimension==="folder"&&S)&&e.jsxs("form",{onSubmit:s=>{s.preventDefault(),de(B)},className:"flex items-center gap-1",children:[e.jsx(q,{value:B,onChange:s=>L(s.target.value),placeholder:d.dimension==="tag"?"add column…":"new folder…",list:d.dimension==="tag"?"board-tag-values":void 0,className:"h-8 w-32",title:d.dimension==="tag"?"Add a tag column — pick an existing tag or type a new value":"Add a folder column — drag a card into it to file the document there (nest with parent/child)"}),d.dimension==="tag"&&e.jsx("datalist",{id:"board-tag-values",children:ce.map(s=>e.jsx("option",{value:s},s))}),e.jsx(I,{type:"submit",variant:"outline",size:"sm",disabled:!B.trim(),title:d.dimension==="tag"?"Add column":"Add folder column",children:e.jsx(Ce,{className:"h-3.5 w-3.5"})})]}),e.jsx(I,{variant:"outline",size:"sm",onClick:N,disabled:O,children:e.jsx(we,{className:`h-3.5 w-3.5 ${O?"animate-spin":""}`})})]})}),e.jsx("ul",{className:"max-w-2xl list-disc space-y-1 pl-5 text-xs text-muted-foreground",children:d.dimension==="status"?e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:["Status is"," ",e.jsx("span",{className:"font-medium text-foreground",children:"read-only"})," ","here — move a doc through review in the document view."]}),e.jsxs("li",{children:["Switch to"," ",e.jsx("span",{className:"font-medium text-foreground",children:"Folder"})," for a draggable board."]}),e.jsx("li",{children:"Drag a column header to reorder."})]}):d.dimension==="tag"?e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:["Grouped by"," ",e.jsx("span",{className:"font-medium text-foreground",children:(Y=d.tagNamespace)!=null&&Y.trim()?`${d.tagNamespace.trim().split(":")[0]}:`:"tag"}),(J=d.tagNamespace)!=null&&J.trim()?" — only documents carrying one show up.":" — one column per tag, so a document with several tags appears in each."]}),e.jsx("li",{children:(Q=d.tagNamespace)!=null&&Q.trim()?"Clear the box to group by every tag.":"Type a namespace (e.g. stage) to group by stage: values only."}),e.jsx("li",{children:S?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"font-medium text-foreground",children:"Drag a card"})," ","between columns to swap its tag; drag a header to reorder."]}):e.jsxs(e.Fragment,{children:["You have"," ",e.jsx("span",{className:"font-medium text-foreground",children:"read-only"})," ","access, so cards can't be retagged. Drag a header to reorder."]})}),e.jsxs("li",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"+"})," to add a column, ",e.jsx("span",{className:"font-medium text-foreground",children:"×"})," to remove one."]})]}):S?C.length<2?e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:["Every document is in"," ",e.jsx("span",{className:"font-medium text-foreground",children:"Root"}),". Type a name in"," ",e.jsx("span",{className:"font-medium text-foreground",children:"new folder"})," ","above to add a column."]}),e.jsxs("li",{children:["Then ",e.jsx("span",{className:"font-medium text-foreground",children:"drag a card"})," ","into it — that files the document in the folder."]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"Drag a card"})," ","between columns to move it to that folder."]}),e.jsxs("li",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"Drag a column header"})," ","to reorder."]}),e.jsxs("li",{children:[e.jsx("span",{className:"font-medium text-foreground",children:"new folder"})," ","adds a column; it sticks once a card lands in it."]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("li",{children:["You have"," ",e.jsx("span",{className:"font-medium text-foreground",children:"read-only"})," ","access to this nest, so cards can't be moved."]}),e.jsx("li",{children:"Ask the nest owner for write access to rearrange the board."})]})}),O?e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground py-12 justify-center",children:[e.jsx(ke,{className:"h-4 w-4 animate-spin"})," Loading board…"]}):G?e.jsx("div",{className:"text-sm text-destructive py-8",children:G}):C.length===0?e.jsx("div",{className:"text-sm text-muted-foreground py-8",children:r.dimension==="tag"?"No tag columns yet — add one above to start sorting documents into it.":"No documents to show."}):e.jsx("div",{className:"flex gap-3 overflow-x-auto pb-4",children:C.map(s=>{const t=ne[s.key]??[],i=se===s.key;return e.jsxs("div",{onDragOver:a=>{if(M){a.preventDefault(),A(s.key);return}F&&(a.preventDefault(),D(s.key))},onDragLeave:()=>{D(a=>a===s.key?null:a),A(a=>a===s.key?null:a)},onDrop:a=>{if(a.preventDefault(),M){ie(M,s.key),R(null),A(null);return}re(s.key)},className:`flex-shrink-0 w-64 rounded-lg border bg-muted/30 flex flex-col max-h-[70vh] transition-colors ${i?"border-primary ring-1 ring-primary":"border-border"}`,children:[e.jsxs("div",{className:`flex items-center justify-between gap-1 px-3 py-2 border-b border-border sticky top-0 ${s.key!==x?"cursor-grab active:cursor-grabbing":""} ${oe===s.key?"bg-primary/10":""}`,draggable:s.key!==x,onDragStart:a=>{s.key!==x&&(R(s.key),a.dataTransfer.effectAllowed="move",a.dataTransfer.setData("text/plain",`col:${s.key}`))},onDragEnd:()=>{R(null),A(null)},title:s.title,children:[e.jsx("span",{className:`min-w-0 text-sm font-medium truncate ${De(r.dimension)?"capitalize":""} ${s.key===x?"text-muted-foreground":""}`,children:s.label}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("span",{className:"text-xs text-muted-foreground tabular-nums",children:t.length}),s.key!==x&&(r.dimension==="tag"||r.dimension==="folder"&&t.length===0)&&e.jsx("button",{type:"button",onClick:()=>le(s.key),className:"text-muted-foreground/50 hover:text-foreground",title:r.dimension==="folder"?"Remove this empty column":"Remove this column — its cards drop off the board; their tags aren't changed",children:e.jsx(Se,{className:"h-3.5 w-3.5"})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-2 space-y-2",children:[t.map(a=>e.jsxs("div",{draggable:F,onDragStart:c=>{T(a.id),$(s.key),c.dataTransfer.effectAllowed="move",c.dataTransfer.setData("text/plain",a.id)},onDragEnd:()=>{T(null),$(null),D(null)},onClick:()=>p(a.id),className:`group rounded-md border border-border bg-card px-2.5 py-2 text-sm cursor-pointer hover:border-primary/60 hover:shadow-sm transition ${E===a.id?"opacity-50":""} ${te?"pointer-events-none":""}`,children:[e.jsxs("div",{className:"flex items-start gap-1.5",children:[F&&e.jsx(Me,{className:"h-3.5 w-3.5 mt-0.5 text-muted-foreground/40 group-hover:text-muted-foreground shrink-0"}),e.jsx(Pe,{type:a.type}),e.jsx("span",{className:"min-w-0 flex-1 leading-snug break-words",children:a.title})]}),a.tags.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1 mt-1.5 pl-5",children:a.tags.slice(0,4).map(c=>e.jsx("span",{className:"text-[10px] px-1 py-0.5 rounded bg-muted text-muted-foreground",children:c},c))})]},a.id)),t.length===0&&e.jsx("div",{className:"text-xs text-muted-foreground/60 text-center py-6",children:F?"Drop here":"Empty"})]})]},s.key)})})]})}function Je(){const n=Ee();return e.jsx(Ge,{nestId:n.nestId,nestName:n.nestName,isOwner:n.isOwner,isArchived:n.isArchived,onBack:n.leaveNest,onOpenDocument:n.openDocument})}export{Je as default};
@@ -1 +1 @@
1
- import{j as e,w as l}from"./index-WYDmEOfO.js";function x({icon:s,title:r,description:t,actions:a,className:i}){return e.jsxs("div",{className:l("mb-4",i),"data-testid":"page-title",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("h1",{className:"flex items-center gap-2 text-2xl font-semibold tracking-tight",children:[s&&e.jsx(s,{className:"h-6 w-6 shrink-0 text-muted-foreground"}),r]}),a&&e.jsx("div",{className:"ml-auto flex shrink-0 items-center gap-2",children:a})]}),t&&e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:t})]})}export{x as P};
1
+ import{j as e,w as l}from"./index-DvuUIUP6.js";function x({icon:s,title:r,description:t,actions:a,className:i}){return e.jsxs("div",{className:l("mb-4",i),"data-testid":"page-title",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("h1",{className:"flex items-center gap-2 text-2xl font-semibold tracking-tight",children:[s&&e.jsx(s,{className:"h-6 w-6 shrink-0 text-muted-foreground"}),r]}),a&&e.jsx("div",{className:"ml-auto flex shrink-0 items-center gap-2",children:a})]}),t&&e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:t})]})}export{x as P};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-WYDmEOfO.js";/**
1
+ import{c as a}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-WYDmEOfO.js";/**
1
+ import{c as a}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-WYDmEOfO.js";/**
1
+ import{c}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-WYDmEOfO.js";/**
1
+ import{c}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-WYDmEOfO.js";/**
1
+ import{c}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-WYDmEOfO.js";/**
1
+ import{c as a}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-WYDmEOfO.js";/**
1
+ import{c as e}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-WYDmEOfO.js";/**
1
+ import{c}from"./index-DvuUIUP6.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ContextNest</title>
7
7
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🪺</text></svg>" />
8
- <script type="module" crossorigin src="/assets/index-WYDmEOfO.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DVnaYqj9.css">
8
+ <script type="module" crossorigin src="/assets/index-DvuUIUP6.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-DNmWTxN7.css">
10
10
  </head>
11
11
  <body class="bg-background text-foreground antialiased">
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptowl/contextnest-community",
3
- "version": "1.26.0",
3
+ "version": "1.27.0",
4
4
  "description": "ContextNest Community Edition — self-hosted context governance server for AI workflows. Commercial software by Promptowl LLC.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -58,6 +58,7 @@
58
58
  "lint:mcp-schemas": "node scripts/check-mcp-schemas.mjs",
59
59
  "test": "vitest run",
60
60
  "test:watch": "vitest",
61
+ "test:playwright": "playwright test --project=test-suite",
61
62
  "prepublishOnly": "npm run build",
62
63
  "version-packages": "changeset version && npm install --package-lock-only",
63
64
  "release": "npm run build && changeset publish"
@@ -69,6 +70,7 @@
69
70
  ]
70
71
  },
71
72
  "dependencies": {
73
+ "@anthropic-ai/sdk": "^0.127.0",
72
74
  "@aws-sdk/client-sesv2": "3.1139.0",
73
75
  "@hono/node-server": "^1.13.8",
74
76
  "@modelcontextprotocol/sdk": "^1.12.1",
@@ -90,6 +92,7 @@
90
92
  "devDependencies": {
91
93
  "@changesets/changelog-github": "^0.7.0",
92
94
  "@changesets/cli": "^2.31.0",
95
+ "@playwright/test": "^1.59.1",
93
96
  "@radix-ui/react-alert-dialog": "^1.1.11",
94
97
  "@radix-ui/react-avatar": "^1.1.0",
95
98
  "@radix-ui/react-checkbox": "^1.1.1",
@@ -163,7 +166,8 @@
163
166
  "tsx": "^4.19.4",
164
167
  "typescript": "^5.7.3",
165
168
  "vite": "6.4.3",
166
- "vitest": "3.2.6"
169
+ "vitest": "3.2.6",
170
+ "winston": "^3.19.0"
167
171
  },
168
172
  "overrides": {
169
173
  "shell-quote": "1.8.4",
@@ -1 +0,0 @@
1
- import{r as o,j as e,aP as m,x as c,aQ as x,aR as u,L as h}from"./index-WYDmEOfO.js";import{P as p}from"./page-title-DVq4qvMR.js";import{C as f}from"./code-xml-BlR7EN6l.js";import{M as g,r as j}from"./index-BOVYgMvj.js";const w=[[x,"Connect an MCP client","Claude Code, Cursor, VS Code or Claude Desktop talk to a nest directly. See “MCP” below."],[f,"Call the REST API","Every read is deterministic: same selector, same context. See “Deterministic retrieval API” below."],[u,"Use the ctx CLI","Query a hosted nest from a terminal or a script. See “From the ctx CLI” below."]];function y({onOpenGuide:n}){const[r,l]=o.useState(null),[a,i]=o.useState(null);return o.useEffect(()=>{let s=!1;return fetch("/llms.txt").then(t=>{if(!t.ok)throw new Error(`Failed to load manual (${t.status})`);return t.text()}).then(t=>!s&&l(t)).catch(t=>!s&&i((t==null?void 0:t.message)||"Failed to load")),()=>{s=!0}},[]),e.jsxs("div",{className:"w-full space-y-6",children:[e.jsx(p,{icon:m,title:"Docs",description:"How agents talk to this server: keys, endpoints, MCP tools and the CLI.",className:"mb-0",actions:e.jsxs("a",{href:"/llms.txt",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",children:["Raw llms.txt (for agents)",e.jsx(c,{className:"h-3 w-3"})]})}),e.jsxs("div",{className:"rounded-lg border-l-2 border-primary bg-muted/40 p-4 text-sm text-muted-foreground",children:["This is the manual an agent reads when you point it at"," ",e.jsx("code",{className:"rounded bg-muted px-1 py-0.5 text-xs",children:"/llms.txt"}),". It documents shapes, never data. Looking for how to use the app yourself?"," ",e.jsx("button",{type:"button",onClick:n,className:"font-medium text-foreground underline underline-offset-2",children:"Start with How it works"}),"."]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-3",children:w.map(([s,t,d])=>e.jsxs("div",{className:"rounded-lg border bg-card p-3",children:[e.jsxs("div",{className:"mb-1 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(s,{className:"h-4 w-4 text-primary"}),t]}),e.jsx("p",{className:"text-xs leading-relaxed text-muted-foreground",children:d})]},t))}),a&&e.jsx("p",{className:"text-sm text-red-500",children:a}),!r&&!a&&e.jsxs("div",{className:"flex items-center justify-center py-16 text-muted-foreground",children:[e.jsx(h,{className:"h-5 w-5 animate-spin mr-2"})," Loading docs…"]}),r&&e.jsx("article",{className:"prose prose-sm dark:prose-invert max-w-none",children:e.jsx(g,{remarkPlugins:[j],children:r})})]})}export{y as AgentDocsPage};
@@ -1 +0,0 @@
1
- import{r as n,Q as Ae,u as he,_ as Te,j as e,M as O,T as De,as as Pe,at as ke,L as $,ad as ne,ae as re,af as ce,au as Fe,av as Re,ax as Le,C as Me,ah as se,ai as ae,aj as te,ak as ie,al as B,bY as ze,ac as Oe,cf as $e,A as Be,N as Ue,a as Ve,U as oe,B as T,e as G,l as J,P as qe,i as X,bB as Qe,dP as Ye,O as _e,ef as He,eg as Ie}from"./index-WYDmEOfO.js";import{A as ue,a as xe,b as pe,c as ve,d as ge,e as fe,f as be,g as je}from"./alert-dialog-BvF3NFr7.js";import{x as We,w as de,y as Ke,S as Ee}from"./MarkdownEditor-CKh4WSn-.js";import{P as Ge}from"./PersonCombobox-BKI7dff4.js";import{U as Je}from"./user-plus-Ckm_Isyc.js";import{S as Xe}from"./share-2-CxmXRt58.js";import{T as me}from"./trash-2-B0HyPTnI.js";const Z=[{value:"private",label:"Private"},{value:"org",label:"Organization"},{value:"public",label:"Public"}];function cs({nestId:r,onChanged:b,onError:i,variant:_="card"}){var A,V,q,Q;const[x,p]=n.useState("private"),v=x==="public",f=x==="org",[C,U]=n.useState(!1),[g,j]=n.useState(null),{sharedDeployment:D}=Ae(),y={sharedDeployment:D},P=he(),[S,k]=n.useState(""),F=Te(r),w=(V=(A=F.data)==null?void 0:A.nest)==null?void 0:V.visibility,N=((Q=(q=F.data)==null?void 0:q.nest)==null?void 0:Q.description)??"";n.useEffect(()=>{w&&p(w)},[w]);const R=async(a,m)=>{const h=x;p(a),U(!0),i==null||i(null);try{const l=await $e(r,a,m);if(p(l.visibility||a),l.visibility!==a){i==null||i("Server did not accept the change. You may not have admin access to this nest.");return}b()}catch(l){p(h),i==null||i((l==null?void 0:l.message)||"Failed to change visibility")}finally{U(!1)}},L=async a=>{if(a!==x){if(a!=="private"&&Ke(a,y)){k(N),j(a);return}await R(a)}},o=async()=>{const a=g;if(!a)return;j(null);const m=S.trim();if(m&&m!==N.trim())try{await ze(r,{description:m}),P.invalidateQueries({queryKey:Oe.nest(r)})}catch(h){i==null||i((h==null?void 0:h.message)||"Failed to save the description")}await R(a,!0)},d=g?We(g,y):null,M=e.jsx(ue,{open:g!==null,onOpenChange:a=>{a||j(null)},children:e.jsxs(xe,{children:[e.jsxs(pe,{children:[e.jsx(ve,{children:d==null?void 0:d.title}),e.jsx(ge,{children:d==null?void 0:d.body})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"visibility-description",className:"text-xs",children:N.trim()?"Description readers will see":"This nest has no description — readers will only see its name. Add one? (optional)"}),e.jsx(De,{id:"visibility-description",value:S,onChange:a=>k(a.target.value),placeholder:"What this nest is for, and who it's meant for",rows:2,"data-testid":"visibility-description"})]}),e.jsxs(fe,{children:[e.jsx(be,{children:"Cancel"}),e.jsx(je,{onClick:()=>void o(),"data-testid":"visibility-confirm",children:d==null?void 0:d.confirm})]})]})});if(_==="compact"){if(!w)return null;const a=v?ne:f?re:ce,m=Z.find(l=>l.value===x)??Z[0],h=de(x,y);return e.jsxs(e.Fragment,{children:[e.jsxs(Pe,{children:[e.jsx(ke,{asChild:!0,children:e.jsxs("button",{type:"button",disabled:C,className:"inline-flex h-8 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:opacity-60",title:`${m.label} — ${h}. Click to change.`,"aria-label":`Nest visibility: ${m.label}`,"data-testid":"nest-visibility-compact",children:[C?e.jsx($,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(a,{className:`h-3.5 w-3.5 ${v?"text-green-600":f?"text-blue-600":""}`}),e.jsx("span",{className:"hidden sm:inline",children:m.label}),e.jsx(Fe,{className:"h-3 w-3 opacity-60"})]})}),e.jsx(Re,{align:"end",className:"w-64",children:Z.map(l=>e.jsxs(Le,{onClick:()=>void L(l.value),className:"flex items-start gap-2",children:[l.value===x?e.jsx(Me,{className:"mt-0.5 h-4 w-4 shrink-0"}):e.jsx("span",{className:"w-4 shrink-0"}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-sm",children:l.label}),e.jsx("span",{className:"text-xs text-muted-foreground",children:de(l.value,y)})]})]},l.value))})]}),M]})}return e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsxs(O,{className:"flex items-center gap-2 text-sm font-medium",children:[v?e.jsx(ne,{className:"h-4 w-4 text-green-600"}):f?e.jsx(re,{className:"h-4 w-4 text-blue-600"}):e.jsx(ce,{className:"h-4 w-4"}),v?"Public":f?"Organization":"Private"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v?D?"Anyone on the internet with the URL can read this nest — including every account on this server, other organizations too. Editing still requires being added below.":"Anyone on the internet with the URL can read this nest. Editing still requires being added below.":f?D?"Every account on this server can read this nest — other organizations included, not just yours. Editing still requires being added below.":"Everyone signed in to this deployment can read this nest. Editing still requires being added below.":"Only people added below (and the owner) can see this nest."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[C&&e.jsx($,{className:"h-3.5 w-3.5 animate-spin text-muted-foreground"}),e.jsxs(se,{value:x,onValueChange:a=>void L(a),disabled:C,children:[e.jsx(ae,{className:"h-8 w-[150px]","aria-label":"Nest visibility",children:e.jsx(te,{})}),e.jsxs(ie,{children:[e.jsx(B,{value:"private",children:"Private"}),e.jsx(B,{value:"org",children:"Organization"}),e.jsx(B,{value:"public",children:"Public"})]})]})]})]}),M]})}function Ze(r,b){return{title:"Remove access?",body:`Remove ${r||"this collaborator"}'s access to "${b}"? They keep their account; only their access to this nest is revoked.`,confirm:"Remove access"}}function es(r){return`${r||"Collaborator"} removed from this nest`}const ee=[{value:"read",label:"Viewer",hint:"Read only"},{value:"write",label:"Editor",hint:"Read and edit documents"},{value:"admin",label:"Admin",hint:"Full access except deleting the nest"}],Y={read:1,write:2,admin:3,owner:4};function os({nestId:r,nestName:b,onChanged:i,currentUserEmail:_,callerPermission:x="admin",showTeams:p=!1}){const v=(_||"").toLowerCase(),f=Y[x]??Y.read,C=f>=Y.admin,U=ee.filter(s=>Y[s.value]<=f),[g,j]=n.useState([]),[D,y]=n.useState(!0),P=he(),[S,k]=n.useState(""),[F,w]=n.useState("read"),[N,R]=n.useState(!1),[L,o]=n.useState(null),[d,M]=n.useState("person"),[A,V]=n.useState([]),[q,Q]=n.useState([]),[a,m]=n.useState(""),[h,l]=n.useState(!1),[z,H]=n.useState(null),I=async()=>{y(!0);try{const{collaborators:s}=await P.fetchQuery(J.collaborators(r));j(s)}catch(s){o((s==null?void 0:s.message)||"Failed to load collaborators")}finally{y(!1)}},W=async()=>{try{const[s,t]=await Promise.all([P.fetchQuery(J.nestTeams(r)),P.fetchQuery(J.teamList()).catch(()=>({teams:[]}))]);V(s.teams),Q(t.teams)}catch(s){o((s==null?void 0:s.message)||"Failed to load teams")}};n.useEffect(()=>{I(),p&&W()},[r]);const le=async()=>{const s=S.trim();if(s){if(!Qe(s)){o("Enter a valid email address.");return}R(!0),o(null);try{await Ye(r,{email:s,permission:F}),k(""),w("read"),await I(),i()}catch(t){o((t==null?void 0:t.message)||"Failed to add collaborator")}finally{R(!1)}}},ye=s=>{s.preventDefault(),le()},K=q.filter(s=>!A.some(t=>t.teamId===s.id)),we=async()=>{if(a){l(!0),o(null);try{await qe(r,a),m(""),X.success("Team shared"),await W(),i()}catch(s){o((s==null?void 0:s.message)||"Failed to share team")}finally{l(!1)}}},Ne=async(s,t)=>{if(window.confirm(`Unshare "${t}" from "${b}"? Its members lose the access this share granted.`)){l(!0),o(null);try{await _e(r,s),await W(),i()}catch(u){o((u==null?void 0:u.message)||"Failed to unshare team")}finally{l(!1)}}},Ce=async(s,t)=>{const c=g.find(u=>u.id===s);if(c&&(c.email||"").toLowerCase()===v){X.error("You can't change your own access level.");return}o(null),j(u=>u.map(E=>E.id===s?{...E,permission:t}:E));try{await He(r,s,t),i()}catch(u){o((u==null?void 0:u.message)||"Failed to update permission"),await I()}},Se=async()=>{const s=z;if(s){H(null),o(null);try{await Ie(r,s.id),j(t=>t.filter(c=>c.id!==s.id)),X.success(es(s.email)),i()}catch(t){o((t==null?void 0:t.message)||"Failed to remove collaborator")}}};return e.jsxs("div",{className:"space-y-4",children:[L&&e.jsxs(Be,{variant:"destructive",children:[e.jsx(Ue,{className:"h-4 w-4"}),e.jsx(Ve,{children:L})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx(O,{className:"flex items-center gap-2 text-sm font-medium",children:p&&d==="team"?e.jsxs(e.Fragment,{children:[e.jsx(oe,{className:"h-4 w-4"}),"Add a team"]}):e.jsxs(e.Fragment,{children:[e.jsx(Je,{className:"h-4 w-4"}),"Add a person"]})}),p&&e.jsxs("div",{className:"flex gap-1",children:[e.jsx(T,{type:"button",size:"sm",variant:d==="person"?"secondary":"ghost",className:"h-7 px-2 text-xs",onClick:()=>M("person"),children:"Person"}),e.jsx(T,{type:"button",size:"sm",variant:d==="team"?"secondary":"ghost",className:"h-7 px-2 text-xs",onClick:()=>M("team"),children:"Team"})]})]}),p&&d==="team"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx("div",{className:"flex-1",children:e.jsx(Ee,{value:a,onChange:m,options:K.map(s=>({value:s.id,label:s.name})),disabled:K.length===0,placeholder:K.length===0?"No teams available to share":"Select a team…",searchPlaceholder:"Search teams…",emptyText:"No teams match.",testId:"collab-team-select"})}),e.jsx(T,{onClick:we,disabled:h||!a,children:h?e.jsx($,{className:"h-4 w-4 animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx(Xe,{className:"h-4 w-4 mr-1"}),"Share"]})})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Every member gets the role you gave them on the Teams page. Manage members there."})]}):e.jsxs("form",{onSubmit:ye,className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(Ge,{value:S,onChange:k,onSubmit:le,placeholder:"teammate@example.com",disabled:N,className:"flex-1",exclude:g.map(s=>s.email||"").filter(Boolean),testId:"collab-person-input"}),e.jsxs(se,{value:F,onValueChange:s=>w(s),children:[e.jsx(ae,{className:"w-full sm:w-[130px]",children:e.jsx(te,{})}),e.jsx(ie,{children:U.map(s=>e.jsx(B,{value:s.value,children:s.label},s.value))})]}),e.jsx(T,{type:"submit",disabled:N||!S.trim(),children:N?e.jsx($,{className:"h-4 w-4 animate-spin"}):"Add"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"If they don't have an account yet, they'll get access when they register with this email."})]})]}),p&&A.length>0&&e.jsxs("div",{className:"rounded-lg border p-4 space-y-2",children:[e.jsxs(O,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(oe,{className:"h-4 w-4"}),"Teams with access"]}),e.jsx("div",{className:"space-y-1",children:A.map(s=>e.jsxs("div",{className:"flex items-center gap-2 py-1.5",children:[e.jsx("span",{className:"flex-1 min-w-0 truncate text-sm",children:s.teamName}),e.jsxs(G,{variant:"secondary",className:"text-[11px]",children:[s.members.length," member",s.members.length===1?"":"s"]}),e.jsx(T,{variant:"ghost",size:"sm",disabled:h,onClick:()=>Ne(s.teamId,s.teamName),title:"Unshare team",className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:e.jsx(me,{className:"h-3.5 w-3.5"})})]},s.teamId))})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-2",children:[e.jsx(O,{className:"text-sm font-medium",children:"People with access"}),D?e.jsx("div",{className:"flex items-center justify-center py-4",children:e.jsx($,{className:"h-5 w-5 animate-spin text-muted-foreground"})}):g.length===0?e.jsx("p",{className:"text-xs text-muted-foreground py-2",children:"Nobody's been added yet. The owner always has full access."}):e.jsx("div",{className:"space-y-1",children:g.map(s=>{var t;return e.jsxs("div",{className:"flex items-center gap-2 py-1.5","data-testid":`collaborator-row-${s.id}`,children:[e.jsx("span",{className:"flex-1 min-w-0 truncate text-sm",children:s.email||s.user_id}),(s.stewardRoles??[]).map(c=>e.jsx(G,{variant:"outline",className:"text-[10px] px-1.5 py-0 capitalize",title:"Steward role — manage in the Stewards tab",children:c},c)),C?e.jsxs(e.Fragment,{children:[e.jsxs(se,{value:s.permission,disabled:(s.email||"").toLowerCase()===v,onValueChange:c=>Ce(s.id,c),children:[e.jsx(ae,{className:"w-[120px] h-8",title:(s.email||"").toLowerCase()===v?"You can't change your own access level":void 0,children:e.jsx(te,{})}),e.jsx(ie,{children:ee.map(c=>e.jsx(B,{value:c.value,children:c.label},c.value))})]}),(s.email||"").toLowerCase()!==v&&e.jsx(T,{variant:"ghost",size:"sm",onClick:()=>H(s),title:"Remove access",className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:e.jsx(me,{className:"h-3.5 w-3.5"})})]}):e.jsx(G,{variant:"secondary",className:"text-[11px] capitalize",children:((t=ee.find(c=>c.value===s.permission))==null?void 0:t.label)??s.permission})]},s.id)})})]}),e.jsx(ue,{open:z!==null,onOpenChange:s=>{s||H(null)},children:e.jsx(xe,{children:(()=>{const s=Ze(z==null?void 0:z.email,b);return e.jsxs(e.Fragment,{children:[e.jsxs(pe,{children:[e.jsx(ve,{children:s.title}),e.jsx(ge,{children:s.body})]}),e.jsxs(fe,{children:[e.jsx(be,{children:"Cancel"}),e.jsx(je,{onClick:()=>void Se(),className:"bg-destructive text-destructive-foreground hover:bg-destructive/90","data-testid":"remove-collaborator-confirm",children:s.confirm})]})]})})()})})]})}export{os as C,cs as N};
@@ -1 +0,0 @@
1
- import{j as s,b_ as m,b$ as p,c1 as h,c0 as x,c2 as u,i as f}from"./index-WYDmEOfO.js";import{N as j,C as b}from"./CollaboratorManager-C9VAXZ0h.js";import"./alert-dialog-BvF3NFr7.js";import"./MarkdownEditor-CKh4WSn-.js";import"./zap-D2ifcnYb.js";import"./index-BOVYgMvj.js";import"./arrow-left-CWIsv-sG.js";import"./trash-2-B0HyPTnI.js";import"./x-mNtADYHc.js";import"./PersonCombobox-BKI7dff4.js";import"./user-plus-Ckm_Isyc.js";import"./share-2-CxmXRt58.js";function D({nestId:r,nestName:t,canManage:o,canManageGovernance:n,stewardshipEnabled:i,currentUserEmail:l,callerPermission:c,onOpenSettings:d,onChanged:e}){return s.jsxs(m,{children:[s.jsxs(p,{className:"pb-3",children:[s.jsx(h,{className:"text-lg",children:"Collaborators"}),s.jsxs(x,{className:"space-y-1",children:[s.jsxs("span",{className:"block",children:[s.jsx("strong",{className:"font-medium text-foreground",children:"Who can access this nest"})," ","— visibility and access for people and teams. Sharing grants viewer, editor or admin access."]}),s.jsxs("span",{className:"block",children:[s.jsx("strong",{className:"font-medium text-foreground",children:"Stewardship"})," — sharing does not make anyone a steward.",i?" Stewards are assigned on the Stewards tab.":n?s.jsxs(s.Fragment,{children:[" ","Turn on Stewardship & Approval Workflow in"," ",s.jsx("button",{type:"button",onClick:d,className:"font-medium text-foreground underline underline-offset-2 hover:no-underline",children:"Nest settings"})," ","to use stewards."]}):" Stewardship & Approval Workflow is off for this nest — an owner or admin can turn it on in Nest settings."]})]})]}),s.jsxs(u,{className:"space-y-4",children:[o&&s.jsx(j,{nestId:r,onChanged:e,onError:a=>a&&f.error(a)}),s.jsx(b,{nestId:r,nestName:t,onChanged:e,currentUserEmail:l,callerPermission:c,showTeams:!0})]})]})}export{D as CollaboratorsTab};