@promptowl/contextnest-community 1.24.0 → 1.26.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.
- package/API.md +177 -14
- package/CONFIGURATION.md +577 -116
- package/README.md +4 -3
- package/STEWARDSHIP.md +24 -0
- package/dist/{chunk-XUIWAWDO.js → chunk-2QOJE7A5.js} +4 -4
- package/dist/{chunk-2TPQTN4Y.js → chunk-DGPTJXIV.js} +47 -15
- package/dist/chunk-I5EDEZBQ.js +523 -0
- package/dist/{chunk-ZTT4U4NE.js → chunk-IEAWRHMV.js} +99 -12
- package/dist/{chunk-YVMSM7LS.js → chunk-LHWOJPFE.js} +7 -0
- package/dist/{chunk-5EZOPA47.js → chunk-M6PGYMBD.js} +20 -11
- package/dist/{chunk-F66VCBLA.js → chunk-PICUHQEM.js} +51 -2
- package/dist/{chunk-I3CSD6CK.js → chunk-RPGFHESR.js} +2 -2
- package/dist/{chunk-KIAAEHWL.js → chunk-SWA5M5XX.js} +88 -546
- package/dist/{chunk-LA3VTQ22.js → chunk-TRSGPS27.js} +81 -14
- package/dist/{engine-S3QBQ7LH.js → engine-QNMFDIBV.js} +4 -3
- package/dist/{external-edit-service-6FNFPOJJ.js → external-edit-service-4MEGPT4D.js} +5 -4
- package/dist/{grants-service-UT3EQ3R7.js → grants-service-24GLUBY4.js} +3 -3
- package/dist/index.js +1739 -583
- package/dist/invited-user-AM6A3WGO.js +12 -0
- package/dist/{migrations.postgres-AIQ7WSU7.js → migrations.postgres-HGSQ7IA5.js} +16 -2
- package/dist/{review-service-HHGOTO6P.js → review-service-2EWN7WWO.js} +8 -7
- package/dist/{stewardship-service-4DHNRULG.js → stewardship-service-TDZUC2Q6.js} +7 -4
- package/dist/{version-service-KIOQME6U.js → version-service-C3JTZLJH.js} +5 -4
- package/dist/web3/assets/ActivityTracePage-DzwWIjjx.js +1 -0
- package/dist/web3/assets/{AgentDocsPage-CIiaBqMy.js → AgentDocsPage-ixP2UdAE.js} +1 -1
- package/dist/web3/assets/CollaboratorManager-C9VAXZ0h.js +1 -0
- package/dist/web3/assets/CollaboratorsTab-tq4ZTexH.js +1 -0
- package/dist/web3/assets/DocumentEditor-C2CP2fiE.js +36 -0
- package/dist/web3/assets/DocumentsTab-Mh7KxUoB.js +6 -0
- package/dist/web3/assets/ExternalEditsTab-B_CWKXZ_.js +1 -0
- package/dist/web3/assets/MarkdownEditor-CKh4WSn-.js +653 -0
- package/dist/web3/assets/MarkdownEditor-ndtIx5x0.css +1 -0
- package/dist/web3/assets/NestPageHeader-Cizo8nUi.js +1 -0
- package/dist/web3/assets/NestView-EW-sraEb.js +73 -0
- package/dist/web3/assets/OverviewTab-CjidsMX_.js +6 -0
- package/dist/web3/assets/PersonCombobox-BKI7dff4.js +1 -0
- package/dist/web3/assets/{ReviewActions-OfOdqzCn.js → ReviewActions-CS8JXgXF.js} +2 -2
- package/dist/web3/assets/ReviewTab-CwVrXzw5.js +1 -0
- package/dist/web3/assets/StewardsTab-C-iP6gnh.js +1 -0
- package/dist/web3/assets/SubmitForReviewModal-Biq3m79i.js +1 -0
- package/dist/web3/assets/{alert-dialog-DTozKlmV.js → alert-dialog-BvF3NFr7.js} +2 -2
- package/dist/web3/assets/{arrow-left-BCKt4CwQ.js → arrow-left-CWIsv-sG.js} +1 -1
- package/dist/web3/assets/backlinks-Cqcn7n1J.js +19 -0
- package/dist/web3/assets/boxes-ClbgQqG2.js +6 -0
- package/dist/web3/assets/{chevron-left-BPwUT9DS.js → chevron-left-CK_ZPFm9.js} +1 -1
- package/dist/web3/assets/{circle-check-DI8IBGeo.js → circle-check-Bw_aTXiH.js} +1 -1
- package/dist/web3/assets/{circle-x-VKVhC88W.js → circle-x-DkIG68H7.js} +1 -1
- package/dist/web3/assets/client-attribution-BraarYaP.js +1 -0
- package/dist/web3/assets/{code-xml-CMabYZvH.js → code-xml-BlR7EN6l.js} +1 -1
- package/dist/web3/assets/{corner-down-right-BGxwK6wH.js → corner-down-right-DSVxK3tf.js} +1 -1
- package/dist/web3/assets/count-skeleton-DToLM74B.js +1 -0
- package/dist/web3/assets/{earth-BEp1EKTo.js → earth-BXhVPvCR.js} +1 -1
- package/dist/web3/assets/{file-exclamation-point-r8qZGIjP.js → file-exclamation-point-BevGZgtj.js} +1 -1
- package/dist/web3/assets/{folder-input-Cmtx1Jhk.js → folder-input-m8UBV4fA.js} +1 -1
- package/dist/web3/assets/{index-C1wTSjfP.js → index-BOVYgMvj.js} +1 -1
- package/dist/web3/assets/index-DVnaYqj9.css +1 -0
- package/dist/web3/assets/index-WYDmEOfO.js +404 -0
- package/dist/web3/assets/page-B6pkc9cd.js +2 -0
- package/dist/web3/assets/page-BJrFCKXB.js +1 -0
- package/dist/web3/assets/page-Bgy9Ng9p.js +1 -0
- package/dist/web3/assets/page-C2zoxumw.js +1 -0
- package/dist/web3/assets/page-CJWO06dN.js +1 -0
- package/dist/web3/assets/page-CptuAPJc.js +6 -0
- package/dist/web3/assets/page-DPY01SOj.js +1 -0
- package/dist/web3/assets/page-Dea2SblF.js +9 -0
- package/dist/web3/assets/page-Deq6IKiN.js +6 -0
- package/dist/web3/assets/page-Dfjg8p7Z.js +1 -0
- package/dist/web3/assets/{page-ByyVLDVo.js → page-Dh57L0RG.js} +5 -5
- package/dist/web3/assets/page-Dwbp4Seu.js +6 -0
- package/dist/web3/assets/{page-CHb0F5hV.js → page-DzKwP5Ds.js} +3 -3
- package/dist/web3/assets/page-YxjrE5b5.js +45 -0
- package/dist/web3/assets/{page-title-ClvvBsIo.js → page-title-DVq4qvMR.js} +1 -1
- package/dist/web3/assets/{play-C5YNKpAH.js → play-CXhS6Pgq.js} +1 -1
- package/dist/web3/assets/{send-0CHvmluT.js → send-DdfwnIrj.js} +1 -1
- package/dist/web3/assets/{settings-CeeF4LEb.js → settings-DKX0Q4gO.js} +1 -1
- package/dist/web3/assets/{share-2-CMnOlOt-.js → share-2-CxmXRt58.js} +1 -1
- package/dist/web3/assets/{tag-DQ_6J5Gv.js → tag-DeYC_mRv.js} +1 -1
- package/dist/web3/assets/{trash-2-HBi-Pslz.js → trash-2-B0HyPTnI.js} +1 -1
- package/dist/web3/assets/{user-plus-CvBNcpn4.js → user-plus-Ckm_Isyc.js} +1 -1
- package/dist/web3/assets/{x-By7piikG.js → x-mNtADYHc.js} +1 -1
- package/dist/web3/assets/zap-D2ifcnYb.js +16 -0
- package/dist/web3/index.html +2 -2
- package/package.json +3 -2
- package/dist/client-KEY4PYJH.js +0 -11
- package/dist/keys-CTOGAG3W.js +0 -20
- package/dist/web3/assets/ActivityTracePage-BOZHgJ8S.js +0 -1
- package/dist/web3/assets/CollaboratorManager-By91wrIr.js +0 -1
- package/dist/web3/assets/CollaboratorsTab-D1EE64Fs.js +0 -1
- package/dist/web3/assets/DocumentEditor-DrQfrW3d.js +0 -36
- package/dist/web3/assets/DocumentsTab-Vba-AzBv.js +0 -6
- package/dist/web3/assets/ExternalEditsTab-BSzAQIGM.js +0 -1
- package/dist/web3/assets/MarkdownEditor-74N_naNQ.css +0 -1
- package/dist/web3/assets/MarkdownEditor-C9zqZjC5.js +0 -643
- package/dist/web3/assets/NestPageHeader-CoLUV1Oz.js +0 -1
- package/dist/web3/assets/NestView-CTZ55tXD.js +0 -63
- package/dist/web3/assets/OverviewTab-Dxi-Hu-N.js +0 -1
- package/dist/web3/assets/PersonCombobox-CPOlNs6G.js +0 -1
- package/dist/web3/assets/ReasonDialog-DgLxfRWv.js +0 -1
- package/dist/web3/assets/ReviewTab-CyX8yxd3.js +0 -1
- package/dist/web3/assets/StewardsTab-DBEEfAQI.js +0 -1
- package/dist/web3/assets/SubmitForReviewModal-Ci2DdWs0.js +0 -1
- package/dist/web3/assets/backlinks-CYd4xENL.js +0 -24
- package/dist/web3/assets/card-XG2dP5Xf.js +0 -1
- package/dist/web3/assets/count-skeleton-DMbdpscX.js +0 -1
- package/dist/web3/assets/dates-BCxbm4_q.js +0 -1
- package/dist/web3/assets/index-BM-h3DwI.css +0 -1
- package/dist/web3/assets/index-EaX2yql0.js +0 -389
- package/dist/web3/assets/page-B3yvQvHy.js +0 -1
- package/dist/web3/assets/page-BExMvttJ.js +0 -1
- package/dist/web3/assets/page-BUOADv2X.js +0 -1
- package/dist/web3/assets/page-BYUFhYWZ.js +0 -1
- package/dist/web3/assets/page-Bicf02Cz.js +0 -1
- package/dist/web3/assets/page-BsPMDm5d.js +0 -45
- package/dist/web3/assets/page-CC0NJi8v.js +0 -1
- package/dist/web3/assets/page-CPjWQNKx.js +0 -11
- package/dist/web3/assets/page-CQt3ZGbf.js +0 -2
- package/dist/web3/assets/page-Cj1NetQ-.js +0 -1
- package/dist/web3/assets/page-CtaW65El.js +0 -1
- package/dist/web3/assets/page-DGOL9l8i.js +0 -6
- package/dist/web3/assets/refresh-cw-BhHzSH9m.js +0 -6
- package/dist/web3/assets/scroll-area-dRWncRqa.css +0 -1
- package/dist/web3/assets/scroll-area-hz-xtayP.js +0 -1
- package/dist/web3/assets/select-DBFTrUmI.js +0 -6
- package/dist/web3/assets/triangle-alert-CDy8-7sv.js +0 -6
- package/dist/web3/assets/zap-C2T8riBp.js +0 -11
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as n,u as G,l as z,i as l,aT as J,a2 as U,j as e,B as C,L as M,aq as W,h as V,a_ as X,b3 as Y,b4 as Z,b2 as I}from"./index-WYDmEOfO.js";import{N as ee}from"./NestPageHeader-Cizo8nUi.js";import{T as te}from"./trash-2-B0HyPTnI.js";import"./arrow-left-CWIsv-sG.js";function se({nestId:a,nestName:B,isArchived:T,onBack:H}){var K;const[h,Q]=n.useState([]),p=G(),[S,D]=n.useState(!0),[d,E]=n.useState(!1),[g,_]=n.useState(!1),[i,A]=n.useState(null),[o,b]=n.useState(""),[c,j]=n.useState(""),[L,w]=n.useState(""),x=n.useCallback(async()=>{D(!0);try{const{definitions:t}=await p.fetchQuery(z.definitions(a));Q(t)}catch(t){l.error((t==null?void 0:t.message)||"Failed to load definitions")}finally{D(!1)}},[a]);n.useEffect(()=>{let t=!1;return p.fetchQuery(z.nest(a)).then(s=>{if(t)return;const q=J({roles:(s==null?void 0:s.roles)??[],permission:(s==null?void 0:s.permission)??null,myStewards:(s==null?void 0:s.myStewards)??[],isOwner:(s==null?void 0:s.permission)==="owner",isAdmin:(s==null?void 0:s.permission)==="admin",isArchived:T||U(s==null?void 0:s.nest)});E(q.canManage||q.collabCanWrite)}).catch(()=>{t||E(!1)}),()=>{t=!0}},[a,p,T]),n.useEffect(()=>{x()},[x]);const N=()=>{A(null),b(""),j(""),w("")},y=t=>{var s;A(t.id),b(t.term),j(t.definition),w(((s=t.linked_tag)==null?void 0:s.replace(/^#/,""))??"")},P=o.trim().toLowerCase(),r=P?h.find(t=>t.term.toLowerCase()===P&&t.id!==i)??null:null,F=async()=>{if(!o.trim()||!c.trim())return l.error("Term and definition are both required."),!1;_(!0);try{const t=L.trim();return await Y(a,{term:o.trim(),definition:c.trim(),...t||i?{linked_tag:t||null}:{},...i?{editing_id:i}:{}}),l.success(i?"Definition updated":r?`Replaced the definition of "${r.term}"`:"Term defined"),N(),await x(),!0}catch(t){return l.error((t==null?void 0:t.message)||"Save failed"),!1}finally{_(!1)}},O=async t=>{try{await Z(a,t.id),l.success(`Removed "${t.term}"`),await x()}catch(s){l.error((s==null?void 0:s.message)||"Delete failed")}},[u,m]=n.useState(!1),f=i??(u?"new":null),$=()=>{N(),m(!1)},v=t=>{t.key==="Escape"?(t.preventDefault(),$()):t.key==="Enter"&&(t.ctrlKey||t.metaKey||!(t.target instanceof HTMLTextAreaElement))&&(t.preventDefault(),F().then(s=>s&&m(!1)))},k="w-full rounded-md border border-input bg-background px-2 py-1 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",R=e.jsxs(e.Fragment,{children:[e.jsx("td",{className:"align-top",children:e.jsx("input",{autoFocus:!0,value:o,onChange:t=>b(t.target.value),onKeyDown:v,placeholder:"Term","aria-label":"Term",className:k,"data-testid":"definitions-term"})}),e.jsx("td",{className:"align-top",children:e.jsx("textarea",{value:c,onChange:t=>j(t.target.value),onKeyDown:v,placeholder:"What this term means here — formula or source if quantitative. Ctrl+Enter saves.","aria-label":"Definition",rows:Math.min(8,Math.max(2,c.split(`
|
|
2
|
+
`).length+1)),className:`${k} min-h-[2.25rem] resize-y`,"data-testid":"definitions-definition"})}),e.jsx("td",{className:"align-top",children:e.jsx("input",{value:L,onChange:t=>w(t.target.value),onKeyDown:v,placeholder:"tag","aria-label":"Linked tag",className:`${k} w-28`,"data-testid":"definitions-tag"})}),e.jsx("td",{className:"align-top text-xs text-muted-foreground whitespace-nowrap pt-2",children:i?(K=h.find(t=>t.id===i))==null?void 0:K.defined_by:"you"}),e.jsx("td",{className:"align-top whitespace-nowrap text-right",children:e.jsxs("div",{className:"flex items-center justify-end gap-1",children:[e.jsx(C,{variant:"ghost",size:"sm",className:"h-7",onClick:$,disabled:g,children:"Cancel"}),e.jsx(C,{size:"sm",className:"h-7",onClick:()=>void F().then(t=>t&&m(!1)),disabled:g||!o.trim()||!c.trim(),"data-testid":"definitions-save",children:g?e.jsx(M,{className:"h-3.5 w-3.5 animate-spin"}):r&&!i?"Replace":"Save"})]})})]});return e.jsxs("div",{className:"space-y-4",children:[e.jsx(ee,{nestName:B,onBack:H,title:e.jsx("h1",{className:"min-w-0 truncate text-xl font-semibold",children:"Definitions"})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"The nest's shared vocabulary — what each term means here, written down once so everyone (and every agent reading this nest) uses it the same way. Click a row to edit it."}),e.jsx("div",{className:"border border-border rounded-lg overflow-x-auto","data-testid":"definitions-table",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-muted/50 text-muted-foreground text-xs",children:e.jsxs("tr",{className:"[&>th]:px-3 [&>th]:py-2 [&>th]:text-left [&>th]:font-medium",children:[e.jsx("th",{className:"w-[18%]",children:"Term"}),e.jsx("th",{children:"Definition"}),e.jsx("th",{className:"w-28",children:"Tag"}),e.jsx("th",{className:"w-36",children:"Defined by"}),e.jsx("th",{className:"w-28"})]})}),e.jsxs("tbody",{children:[S&&e.jsx("tr",{children:e.jsxs("td",{colSpan:5,className:"px-3 py-8 text-center text-muted-foreground",children:[e.jsx(M,{className:"h-4 w-4 animate-spin inline mr-2"}),"Loading…"]})}),!S&&h.length===0&&!u&&e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"px-3 py-8 text-center text-muted-foreground",children:d?"No terms defined yet. Add the first one below.":"No terms defined yet."})}),h.map(t=>f===t.id?e.jsx("tr",{className:"border-t border-border bg-muted/20 [&>td]:px-2 [&>td]:py-1.5","data-testid":"definitions-row-editing",children:R},t.id):e.jsxs("tr",{onClick:d&&f===null?()=>y(t):void 0,className:`group border-t border-border align-top [&>td]:px-3 [&>td]:py-2${d&&f===null?" cursor-text hover:bg-muted/30":""}`,"data-testid":"definitions-row",children:[e.jsx("td",{className:"font-medium whitespace-nowrap",children:t.term}),e.jsx("td",{className:"max-w-[520px]",children:e.jsx("span",{className:"whitespace-pre-wrap",children:t.definition})}),e.jsx("td",{className:"whitespace-nowrap",children:t.linked_tag?e.jsx("span",{className:"rounded bg-amber-50 text-amber-700 px-1.5 py-0.5 text-xs",children:t.linked_tag}):e.jsx("span",{className:"text-muted-foreground",children:"—"})}),e.jsx("td",{className:"text-xs text-muted-foreground whitespace-nowrap",children:t.defined_by}),e.jsx("td",{className:"whitespace-nowrap text-right",children:d&&e.jsxs("span",{className:"opacity-0 group-hover:opacity-100 focus-within:opacity-100",children:[e.jsx("button",{type:"button","aria-label":`Edit ${t.term}`,onClick:s=>{s.stopPropagation(),y(t)},className:"p-1 rounded hover:bg-accent mr-1",children:e.jsx(W,{className:"h-3.5 w-3.5"})}),e.jsx("button",{type:"button","aria-label":`Delete ${t.term}`,onClick:s=>{s.stopPropagation(),O(t)},className:"p-1 rounded hover:bg-accent text-red-600",children:e.jsx(te,{className:"h-3.5 w-3.5"})})]})})]},t.id)),f!==null&&r&&e.jsx("tr",{className:"bg-amber-50/60",children:e.jsx("td",{colSpan:5,className:"px-3 py-2 text-xs text-amber-800",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(V,{className:"h-3.5 w-3.5 shrink-0 mt-0.5"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("b",{children:r.term})," ",i?e.jsxs(e.Fragment,{children:["is already defined by another row (",r.defined_by,") — this rename will be rejected."]}):e.jsxs(e.Fragment,{children:["is already defined by ",r.defined_by,". Saving replaces that definition."]})]}),!i&&e.jsxs(C,{variant:"outline",size:"sm",className:"h-7 shrink-0",onClick:()=>{m(!1),y(r)},children:[e.jsx(W,{className:"h-3.5 w-3.5 mr-1"})," Edit it instead"]})]})})}),d&&u&&i===null&&e.jsx("tr",{className:"border-t border-border bg-muted/20 [&>td]:px-2 [&>td]:py-1.5","data-testid":"definitions-row-new",children:R}),d&&!u&&e.jsx("tr",{className:"border-t border-border",children:e.jsx("td",{colSpan:5,className:"p-0",children:e.jsxs("button",{type:"button",onClick:()=>{N(),m(!0)},className:"flex w-full items-center gap-1.5 px-3 py-2 text-left text-sm text-muted-foreground hover:bg-muted/40 hover:text-foreground","data-testid":"definitions-add",children:[e.jsx(X,{className:"h-3.5 w-3.5"})," New term"]})})})]})]})}),e.jsxs("details",{className:"rounded-md border bg-muted/30 px-3 py-2 text-xs",children:[e.jsx("summary",{className:"cursor-pointer font-medium text-muted-foreground",children:"For developers — fetch a definition over HTTP"}),e.jsxs("div",{className:"mt-2 space-y-1.5 text-muted-foreground",children:[e.jsx("p",{children:"Agents and analysis jobs read these live, so a definition edited here changes what they answer with on the next call."}),e.jsxs("pre",{className:"overflow-x-auto rounded border bg-background p-2 font-mono text-[10.5px] leading-relaxed",children:["GET /nests/",a,"/definitions?term=<term>"]}),e.jsx("p",{children:"Omit the query to get the whole glossary."})]})]})]})}function de(){const a=I();return e.jsx(se,{nestId:a.nestId,nestName:a.nestName,isArchived:a.isArchived,onBack:a.leaveNest})}export{de as default};
|
|
@@ -0,0 +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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r,j as e,D as P,z as D,G as A,H as T,cG as F,J as z,I as b,K as H,B as h,cH as I,E as R,cI as K,i as k,Q as B,cJ as Y,cK as G,cL as J,e as L,bE as O,cM as U}from"./index-WYDmEOfO.js";import{P as M}from"./page-title-DVq4qvMR.js";function S({shown:n,onToggle:c}){return e.jsx("button",{type:"button",onClick:c,tabIndex:-1,"aria-label":n?"Hide password":"Show password",title:n?"Hide password":"Show password",className:"absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",children:n?e.jsx(I,{className:"h-4 w-4"}):e.jsx(R,{className:"h-4 w-4"})})}function Q({open:n,onClose:c}){const[u,l]=r.useState(""),[a,m]=r.useState(""),[t,x]=r.useState(""),[d,p]=r.useState(!1),[j,i]=r.useState(null),[N,v]=r.useState(!1),[w,g]=r.useState(!1),[f,o]=r.useState(!1),C=()=>{l(""),m(""),x(""),i(null),v(!1),g(!1),o(!1)},E=async()=>{if(i(null),a.trim().length===0){i("New password cannot be empty or only whitespace.");return}if(a.length<8){i("New password must be at least 8 characters.");return}if(a!==t){i("New passwords don't match.");return}if(a===u){i("New password must be different from the current password.");return}p(!0);try{await K(u,a),k.success("Password changed. Your other sessions were signed out."),C(),c()}catch(s){i((s==null?void 0:s.message)||"Could not change password.")}finally{p(!1)}};return e.jsx(P,{open:n,onOpenChange:s=>{!s&&!d&&(C(),c())},children:e.jsxs(D,{className:"sm:max-w-[400px]",children:[e.jsxs(A,{children:[e.jsxs(T,{className:"flex items-center gap-2",children:[e.jsx(F,{className:"h-4 w-4 text-muted-foreground"}),"Change password"]}),e.jsx(z,{children:"If an admin gave you a temporary password, set your own here. This signs out your other sessions."})]}),e.jsxs("div",{className:"space-y-3 py-1",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"cp-current",className:"block text-sm font-medium",children:"Current password"}),e.jsxs("div",{className:"relative",children:[e.jsx(b,{id:"cp-current",type:N?"text":"password",placeholder:"Enter your current password",value:u,onChange:s=>l(s.target.value),autoComplete:"current-password",className:"pr-10"}),e.jsx(S,{shown:N,onToggle:()=>v(s=>!s)})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"cp-next",className:"block text-sm font-medium",children:"New password"}),e.jsxs("div",{className:"relative",children:[e.jsx(b,{id:"cp-next",type:w?"text":"password",placeholder:"At least 8 characters",value:a,onChange:s=>m(s.target.value),autoComplete:"new-password",className:"pr-10"}),e.jsx(S,{shown:w,onToggle:()=>g(s=>!s)})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"cp-confirm",className:"block text-sm font-medium",children:"Confirm new password"}),e.jsxs("div",{className:"relative",children:[e.jsx(b,{id:"cp-confirm",type:f?"text":"password",placeholder:"Re-enter your new password",value:t,onChange:s=>x(s.target.value),autoComplete:"new-password","aria-invalid":t.length>0&&t!==a,className:"pr-10"}),e.jsx(S,{shown:f,onToggle:()=>o(s=>!s)})]}),t.length>0&&t!==a&&e.jsx("p",{className:"text-sm text-destructive",children:"Passwords don't match."})]}),j&&e.jsx("p",{className:"text-sm text-destructive",children:j})]}),e.jsxs(H,{className:"gap-2",children:[e.jsx(h,{variant:"outline",onClick:()=>{C(),c()},disabled:d,children:"Cancel"}),e.jsx(h,{onClick:E,disabled:d||!u||!a||!t||a!==t,children:d?"Saving...":"Change password"})]})]})})}function V(){var g,f;const{adminStatus:n,isAdmin:c,refresh:u}=B(),l=(n==null?void 0:n.me)??null,[a,m]=r.useState(!1),[t,x]=r.useState(""),[d,p]=r.useState(!1),[j,i]=r.useState(!1);if(!l)return e.jsx("div",{className:"py-12 text-center text-muted-foreground",children:"Sign in to see your account."});const N=((g=l.name)==null?void 0:g.trim())||l.email,v=()=>{x(l.name??""),m(!0)},w=async()=>{p(!0);try{await U(t),await u(),k.success("Name updated."),m(!1)}catch(o){k.error((o==null?void 0:o.message)||"Could not update name.")}finally{p(!1)}};return e.jsxs("div",{"data-testid":"account-page",children:[e.jsx(M,{icon:Y,title:"Your Account",description:"Who you are on this server."}),e.jsx(y,{label:"Profile photo",children:e.jsx(G,{className:"h-20 w-20",children:e.jsx(J,{className:"text-3xl",children:N.charAt(0).toUpperCase()})})}),e.jsx(y,{label:"Name",action:a?null:e.jsx(h,{variant:"outline",size:"sm",onClick:v,"data-testid":"account-edit-name",children:"Edit"}),children:a?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(b,{value:t,"aria-label":"Name",maxLength:80,placeholder:"Your name",autoFocus:!0,onChange:o=>x(o.target.value),onKeyDown:o=>{o.key==="Enter"&&!d&&w(),o.key==="Escape"&&m(!1)},className:"max-w-xs","data-testid":"account-name-input"}),e.jsx(h,{size:"sm",onClick:w,disabled:d||t.trim()===(l.name??"").trim(),children:d?"Saving...":"Save"}),e.jsx(h,{size:"sm",variant:"ghost",onClick:()=>m(!1),disabled:d,children:"Cancel"})]}):e.jsx("span",{className:"text-muted-foreground",children:((f=l.name)==null?void 0:f.trim())||e.jsx("em",{children:"Not set — your email is shown instead"})})}),e.jsx(y,{label:"Email address",children:e.jsxs("span",{className:"flex items-center gap-2 text-muted-foreground",children:[l.email,c&&e.jsxs(L,{variant:"outline",className:"gap-1 border-blue-200 bg-blue-50 text-blue-700 text-[10px] px-1.5 py-0",children:[e.jsx(O,{className:"h-2.5 w-2.5"}),"Admin"]})]})}),e.jsx(y,{label:"Password",action:e.jsx(h,{variant:"outline",size:"sm",onClick:()=>i(!0),"data-testid":"account-change-password",children:"Change password"}),children:e.jsx("span",{className:"tracking-widest text-muted-foreground","aria-hidden":!0,children:"••••••••••••"})}),e.jsx(Q,{open:j,onClose:()=>i(!1)})]})}function y({label:n,action:c,children:u}){return e.jsxs("div",{className:"flex items-start justify-between gap-4 border-b border-border py-5",children:[e.jsxs("div",{className:"min-w-0 space-y-2",children:[e.jsx("div",{className:"text-sm font-medium",children:n}),e.jsx("div",{className:"text-sm",children:u})]}),c]})}export{V as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as t}from"./index-WYDmEOfO.js";import{ActivityTracePage as r}from"./ActivityTracePage-DzwWIjjx.js";import"./page-title-DVq4qvMR.js";import"./client-attribution-BraarYaP.js";import"./arrow-left-CWIsv-sG.js";import"./chevron-left-CK_ZPFm9.js";function s(){return t.jsx(r,{})}export{s as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Q as ue,u as me,r as o,aS as ge,aT as fe,a2 as xe,l as pe,aU as K,aV as he,aW as ye,aX as je,i as v,an as ve,n as be,aY as x,aJ as Y,aZ as Ne,j as e,I as U,B as q,a_ as Ce,R as we,L as ke,a$ as De,b0 as I,a6 as Se,b1 as Fe,F as Ae,b2 as Oe}from"./index-WYDmEOfO.js";import{N as Ee}from"./NestPageHeader-Cizo8nUi.js";import{s as Te}from"./folder-target-CUSWqImF.js";import{X as $e}from"./x-mNtADYHc.js";import{G as Me,Z as Re,F as Be}from"./zap-D2ifcnYb.js";import"./arrow-left-CWIsv-sG.js";const ee="cn.board.";function Le(n){try{const u=localStorage.getItem(ee+n);if(u){const m=JSON.parse(u),b=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]=I(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=K({dimension:b,tagNamespace:k});g[l]??(g[l]=I(l,h))}return{dimension:b,tagNamespace:k,layouts:g}}}catch{}return{dimension:"folder",tagNamespace:"",layouts:{}}}function W(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(Se,{className:`${u} text-violet-500`}):n==="table"?e.jsx(Fe,{className:`${u} text-emerald-500`}):n==="pdf"?e.jsx(Be,{className:`${u} text-rose-500`}):e.jsx(Ae,{className:`${u} text-muted-foreground`})}function Ge({nestId:n,nestName:u,isOwner:m,isArchived:b,onBack:k,onOpenDocument:p}){var J,Q,V;const{isAdmin:g}=ue(),h=me(),[l,f]=o.useState([]),[O,P]=o.useState(!0),[G,z]=o.useState(null),[d,X]=o.useState(()=>Le(n)),[E,T]=o.useState(null),[Z,$]=o.useState(null),[se,D]=o.useState(null),[te,_]=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:b||xe(t==null?void 0:t.nest)}).canEditDocs)}).catch(()=>{}),()=>{s=!0}},[n,m,g,b]);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 H=o.useCallback(s=>{X(t=>{const i={...t,...s};return W(n,i),i})},[n]),y=o.useCallback(s=>{X(t=>{const i=K(t),a={...t,layouts:{...t.layouts,[i]:{...t.layouts[i],...s}}};return W(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=Z;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."&&v(c.reason);return}_(!0);try{c.kind==="move-folder"?(await ve(n,t,c.folder),v.success("Moved")):c.kind==="retag"&&(await be(n,t,{tags:c.tags}),v.success("Retagged")),await N()}catch(w){v.error((w==null?void 0:w.message)||"Move failed")}finally{_(!1)}},[E,Z,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"?Te(s):s.trim().replace(/^#/,"");if(r.dimension==="folder"&&!t){s.trim()&&v("A folder name needs at least one letter or digit.");return}if(t){if(r.dimension==="folder"&&t.split("/").length>Y){v(`Folders may nest at most ${Y} 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(Ee,{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(""),H({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(U,{value:d.tagNamespace??"",onChange:s=>H({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(U,{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(q,{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(q,{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:(J=d.tagNamespace)!=null&&J.trim()?`${d.tagNamespace.trim().split(":")[0]}:`:"tag"}),(Q=d.tagNamespace)!=null&&Q.trim()?" — only documents carrying one show up.":" — one column per tag, so a document with several tags appears in each."]}),e.jsx("li",{children:(V=d.tagNamespace)!=null&&V.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($e,{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 Ve(){const n=Oe();return e.jsx(Ge,{nestId:n.nestId,nestName:n.nestName,isOwner:n.isOwner,isArchived:n.isArchived,onBack:n.leaveNest,onOpenDocument:n.openDocument})}export{Ve as default};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as z,u as D,cN as G,cO as O,r,cP as p,j as e,cG as W,I as Q,ah as U,ai as V,aj as $,ak as H,al as A,B as g,L as T,a_ as X,cQ as Y,e as F,R as J,cR as Z,ag as ee,cS as se,i as f,cT as ae,cU as te,cV as ne,cW as re,cX as oe,l as le}from"./index-WYDmEOfO.js";import{P as ie}from"./page-title-DVq4qvMR.js";import{B as _}from"./boxes-ClbgQqG2.js";import{T as ce}from"./trash-2-B0HyPTnI.js";/**
|
|
2
|
+
* @license lucide-react v0.577.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 de=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],I=z("layers",de);function P(l){if(!l)return"never";const t=oe(l);return t?t.toLocaleDateString():"never"}function ye(){const l=D(),{data:t,isLoading:q}=G(),d=(t==null?void 0:t.keys)??[],{data:m}=O(),j=(m==null?void 0:m.nests)??[],B=j.filter(s=>!s.discovered&&!s.grant_only).map(s=>({id:s.id,name:s.name??s.id})),[k,v]=r.useState(""),[N,w]=r.useState(p),[o,i]=r.useState(null),[M,b]=r.useState(null),[u,C]=r.useState(null),[h,S]=r.useState(null),x=k.trim(),y=d.some(s=>{var a;return((a=s.label)==null?void 0:a.trim().toLowerCase())===x.toLowerCase()}),K=x.length>0&&!y,L=()=>l.invalidateQueries({queryKey:le.apiKeys().queryKey});async function R(s,a,n){i(s);try{const{api_key:c}=await a();S({apiKey:c,kind:n}),s==="new"&&(v(""),w(p))}catch(c){f.error(c instanceof Error?c.message:"Something went wrong.")}finally{L(),i(null)}}async function E(s){i(s);try{await ae(s),f.success("Key revoked")}catch(a){f.error(a instanceof Error?a.message:"Couldn't revoke.")}finally{L(),i(null)}}return e.jsxs("div",{className:"space-y-4",children:[e.jsx(ie,{icon:W,title:"API keys",description:"Make one key per place you connect from — then rotating the key for one client leaves the others alone.",className:"mb-0"}),e.jsxs("div",{className:"grid gap-2 text-xs text-muted-foreground sm:grid-cols-2",children:[e.jsxs("p",{className:"rounded-md border p-2.5",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-medium text-foreground",children:[e.jsx(I,{className:"h-3.5 w-3.5"})," All your nests"]}),"Works on every nest you can see, the server-level MCP endpoint, and your account (including managing keys). Use it for your own tools."]}),e.jsxs("p",{className:"rounded-md border p-2.5",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-medium text-foreground",children:[e.jsx(_,{className:"h-3.5 w-3.5"})," One nest only"]}),"Reaches that one nest and nothing else — every other nest, your account, API keys and admin settings answer 403. Hand this one to an agent or integration."]})]}),e.jsxs("form",{className:"flex flex-col gap-2 sm:flex-row",onSubmit:s=>{s.preventDefault(),K&&R("new",()=>te(ne(x,N)),"generated")},children:[e.jsxs("div",{className:"flex-1",children:[e.jsx(Q,{value:k,onChange:s=>v(s.target.value),maxLength:60,placeholder:"What's this key for? e.g. Claude Desktop, laptop CLI","aria-label":"Key name","aria-invalid":y||void 0}),y&&e.jsx("p",{className:"mt-1 text-xs text-destructive",children:"You already have a key with this name."})]}),e.jsxs(U,{value:N,onValueChange:w,children:[e.jsx(V,{className:"w-full sm:w-[200px] shrink-0","aria-label":"What this key can reach",children:e.jsx($,{})}),e.jsxs(H,{children:[e.jsx(A,{value:p,children:"All your nests"}),B.map(s=>e.jsxs(A,{value:s.id,children:["Only ",s.name]},s.id))]})]}),e.jsxs(g,{type:"submit",disabled:o==="new"||!K,className:"shrink-0",children:[o==="new"?e.jsx(T,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(X,{className:"mr-2 h-4 w-4"}),"Generate key"]})]}),q?e.jsx("p",{className:"py-6 text-center text-sm text-muted-foreground",children:"Loading your keys…"}):d.length===0?e.jsx("p",{className:"rounded-md border border-dashed py-6 text-center text-sm text-muted-foreground",children:"No keys yet. Generate one above to connect an AI client."}):e.jsx("ul",{className:"divide-y rounded-md border",children:d.map(s=>{const a=s.label||"Unnamed key",n=Y(s,j);return e.jsxs("li",{className:"flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("p",{className:"truncate text-sm font-medium",children:a}),e.jsxs(F,{variant:"outline",className:n.kind==="nest"?"shrink-0 gap-1 border-amber-200 bg-amber-50 text-amber-800":"shrink-0 gap-1",title:n.kind==="nest"?"This key reaches this one nest only.":"This key reaches every nest you can see.",children:[n.kind==="nest"?e.jsx(_,{className:"h-3 w-3"}):e.jsx(I,{className:"h-3 w-3"}),e.jsx("span",{className:"max-w-[16rem] truncate",children:n.label})]})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[e.jsx("code",{className:"font-mono",children:s.key_prefix})," · created ",P(s.created_at)," · last used"," ",P(s.last_used_at)]})]}),e.jsxs("div",{className:"flex shrink-0 gap-2",children:[e.jsxs(g,{variant:"outline",size:"sm",disabled:o===s.id,onClick:()=>b({id:s.id,name:a}),children:[o===s.id?e.jsx(T,{className:"mr-1.5 h-3.5 w-3.5 animate-spin"}):e.jsx(J,{className:"mr-1.5 h-3.5 w-3.5"}),"Rotate"]}),e.jsx(g,{variant:"ghost",size:"sm",disabled:o===s.id,onClick:()=>C({id:s.id,name:a}),"aria-label":`Revoke ${a}`,children:e.jsx(ce,{className:"h-3.5 w-3.5"})})]})]},s.id)})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"A key is shown once, when it's created. There's no way to read it back — if you lose one, rotate that key (its client needs the new value) or revoke it and make another."}),e.jsx(Z,{target:M,onConfirm:s=>R(s,()=>re({key_id:s}),"rotated"),onClose:()=>b(null)}),u&&e.jsx(ee,{open:!0,onOpenChange:s=>!s&&C(null),title:`Revoke "${u.name}"?`,description:"Anything still using this key stops working immediately.",confirmLabel:"Revoke key",destructive:!0,onConfirm:()=>E(u.id)}),h&&e.jsx(se,{apiKey:h.apiKey,kind:h.kind,onClose:()=>S(null)})]})}export{ye as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cY as U,Q as V,r as i,u as Y,cs as G,j as e,aq as J,I as W,L as R,d0 as T,B as h,bO as X,ar as Z,bK as ee,l as te,aL as se,i as k,a9 as ae}from"./index-WYDmEOfO.js";import{P as re}from"./page-title-DVq4qvMR.js";import{S as ie}from"./SubmitForReviewModal-Biq3m79i.js";import{A as ne,a as oe,b as le,c as de,d as ce,e as me,f as ue,g as fe}from"./alert-dialog-BvF3NFr7.js";import{C as E}from"./circle-check-Bw_aTXiH.js";import{T as L}from"./trash-2-B0HyPTnI.js";import{C as he}from"./chevron-left-CK_ZPFm9.js";import"./send-DdfwnIrj.js";function De(){var A;const{openReview:M}=U(),{adminStatus:D}=V(),F=((A=D==null?void 0:D.me)==null?void 0:A.email)??null,[c,S]=i.useState([]),[a,P]=i.useState(null),[N,$]=i.useState(!0),[m,j]=i.useState(null),[C,B]=i.useState(""),[v,Q]=i.useState(""),[b,O]=i.useState("updated"),[l,x]=i.useState(new Set),[w,_]=i.useState(!1),[n,y]=i.useState(null),q=Y(),f=async t=>{$(!0);try{const s=await q.fetchQuery(te.myDrafts({offset:t,q:v||void 0,sort:b}));if(s.drafts.length===0&&t>0&&s.pagination.total>0)return void await f(0);S(s.drafts),P(s.pagination)}catch(s){console.error("[Dashboard] goToDraftsPage failed",s),S([])}finally{$(!1)}},I=async(t,s,u)=>{const r=[],d=[];for(const o of t)try{await se(o.nest_id,o.node_id,s,u),r.push(o)}catch(p){d.push(o),console.error("[Dashboard] submitForReview failed",o.node_id,p)}if(S(o=>o.filter(p=>!r.some(H=>g(H)===g(p)))),x(new Set),f((a==null?void 0:a.offset)??0),d.length){j(d);const o=r.length?`${r.length} submitted. `:"";throw new Error(`${o}Couldn't submit ${d.length}: ${d.map(p=>p.title).join(", ")}`)}r.length>1&&k.success(`${r.length} submitted for review`)},g=t=>`${t.nest_id}:${t.node_id}`;i.useEffect(()=>{const t=setTimeout(()=>Q(C.trim()),250);return()=>clearTimeout(t)},[C]),i.useEffect(()=>{f(0)},[F]);const z=G.useRef(!1);i.useEffect(()=>{if(!z.current){z.current=!0;return}x(new Set),f(0)},[v,b]);const K=async t=>{if(t.length===0)return;y(null),_(!0);let s=0,u=0;const r=[];for(const d of t)try{(await ae(d.nest_id,d.node_id)).deleted?u++:s++}catch(o){r.push(d.title),console.error("[Dashboard] discardDraft failed",d.node_id,o)}_(!1),x(new Set),(s||u)&&k.success([s?`${s} restored to the approved version`:"",u?`${u} deleted`:""].filter(Boolean).join(" · ")),r.length&&k.error(`Couldn't discard: ${r.join(", ")}`),f((a==null?void 0:a.offset)??0)};return e.jsxs("div",{className:"space-y-4",children:[e.jsx(re,{icon:J,title:"My Drafts",description:"Everything you started and never handed off.",className:"mb-0"}),e.jsx("div",{children:e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2",children:[e.jsx(W,{value:C,onChange:t=>B(t.target.value),placeholder:"Search drafts by title or nest…",className:"h-8 max-w-xs","aria-label":"Search your drafts","data-testid":"drafts-search"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:"Sort:"}),e.jsx("div",{className:"inline-flex items-center rounded-md border bg-muted/40 p-0.5",role:"group","aria-label":"Sort drafts",children:[["updated","Recently edited"],["title","Title"]].map(([t,s])=>e.jsx("button",{type:"button","aria-pressed":b===t,onClick:()=>O(t),className:`h-6 rounded px-2 text-xs transition-colors ${b===t?"bg-background font-medium text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,"data-testid":`drafts-sort-${t}`,children:s},t))})]})]}),N?e.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:[e.jsx(R,{className:"h-4 w-4 animate-spin"}),"Loading your drafts…"]}):c.length===0?e.jsx("div",{className:"rounded-lg border bg-muted/20 px-4 py-6 text-center text-sm text-muted-foreground",children:v?`No drafts match "${v}".`:"No unsubmitted drafts — everything you've written is in review or approved."}):e.jsxs("div",{className:"rounded-lg border divide-y overflow-hidden",children:[c.length>1&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2 bg-muted/40 px-4 py-2 text-sm",children:[e.jsx(T,{checked:l.size===0?!1:l.size===c.length?!0:"indeterminate",onCheckedChange:t=>x(t===!0?new Set(c.map(g)):new Set),"aria-label":"Select every draft on this page","data-testid":"drafts-select-all"}),e.jsx("span",{className:"text-muted-foreground",children:l.size>0?`${l.size} selected`:`Select all ${c.length} on this page`}),l.size>0&&e.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[e.jsxs(h,{size:"sm",variant:"outline",disabled:w,onClick:()=>j(c.filter(t=>l.has(g(t)))),"data-testid":"drafts-bulk-submit",children:[e.jsx(E,{className:"h-3.5 w-3.5 mr-1"}),"Submit ",l.size," for review"]}),e.jsxs(h,{size:"sm",variant:"outline",disabled:w,onClick:()=>y(c.filter(t=>l.has(g(t)))),"data-testid":"drafts-bulk-discard",children:[w?e.jsx(R,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(L,{className:"h-3.5 w-3.5 mr-1"}),"Discard ",l.size]}),e.jsx(h,{size:"sm",variant:"ghost",onClick:()=>x(new Set),children:"Clear"})]})]}),c.map(t=>{const s=`${t.nest_id}:${t.node_id}`;return e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 hover:bg-muted/40 group",children:[c.length>1&&e.jsx(T,{checked:l.has(s),onCheckedChange:()=>x(u=>{const r=new Set(u);return r.has(s)?r.delete(s):r.add(s),r}),"aria-label":`Select ${t.title}`}),e.jsx("span",{className:`rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide shrink-0 ${t.status==="rejected"?"bg-red-100 text-red-800 dark:bg-red-950/40 dark:text-red-300":"bg-muted text-muted-foreground"}`,children:t.status==="rejected"?"Rejected":"Draft"}),e.jsxs("button",{onClick:()=>M(t.nest_id,t.nest_name,t.node_id),className:"flex flex-col min-w-0 flex-1 text-left gap-0.5",children:[e.jsx("span",{className:"font-medium truncate",children:t.title}),e.jsxs("span",{className:"text-xs text-muted-foreground truncate",title:`${t.nest_name} / ${t.node_id}`,children:[e.jsx(X,{className:"h-3 w-3 inline mr-1 -mt-0.5"}),t.nest_name,t.folder?` / ${t.folder}`:""," · edited"," ",Z(t.updated_at)]})]}),e.jsxs(h,{size:"sm",variant:"outline",className:"shrink-0",onClick:()=>j([t]),children:[e.jsx(E,{className:"h-3.5 w-3.5 mr-1"}),"Submit for review"]}),e.jsx(h,{size:"sm",variant:"ghost",disabled:w,className:"shrink-0 text-muted-foreground hover:text-destructive",title:"Discard this draft — back to the last approved version, or delete it if there isn't one",onClick:()=>y([t]),"data-testid":"draft-discard",children:e.jsx(L,{className:"h-3.5 w-3.5"})})]},s)})]}),a&&a.total>a.limit&&e.jsxs("div",{className:"flex items-center justify-center gap-3 pt-3 text-sm text-muted-foreground",children:[e.jsxs(h,{variant:"outline",size:"sm",disabled:N||a.offset===0,onClick:()=>f(Math.max(0,a.offset-a.limit)),children:[e.jsx(he,{className:"h-3.5 w-3.5 mr-1"}),"Prev"]}),e.jsxs("span",{children:["Page ",Math.floor(a.offset/a.limit)+1," of"," ",Math.max(1,Math.ceil(a.total/a.limit))]}),e.jsxs(h,{variant:"outline",size:"sm",disabled:N||!a.has_more,onClick:()=>f(a.offset+a.limit),children:["Next",e.jsx(ee,{className:"h-3.5 w-3.5 ml-1"})]})]})]})}),m&&m.length>0&&e.jsx(ie,{isOpen:!0,onClose:()=>j(null),documentTitle:m.length===1?m[0].title:`${m.length} drafts`,currentVersion:m.length===1?m[0].version:null,onSubmit:(t,s)=>I(m,t,s)}),e.jsx(ne,{open:!!n,onOpenChange:t=>!t&&y(null),children:e.jsxs(oe,{children:[e.jsxs(le,{children:[e.jsx(de,{children:(n==null?void 0:n.length)===1?`Discard "${n[0].title}"?`:`Discard ${(n==null?void 0:n.length)??0} drafts?`}),e.jsxs(ce,{children:[(n==null?void 0:n.length)===1?"The document goes":"Each document goes"," ","back to its last approved version. A document that was never approved is deleted instead. This can't be undone."]})]}),e.jsxs(me,{children:[e.jsx(ue,{children:"Cancel"}),e.jsx(fe,{onClick:()=>void K(n??[]),"data-testid":"drafts-discard-confirm",children:"Discard"})]})]})})]})}export{De as default};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{r as l,j as e,b_ as m,b$ as u,c1 as p,c0 as x,B as b,az as se,aE as te,c2 as g,h as Fe,e as Ae,Q as Te,u as Oe,dE as He,dF as qe,l as ne,i as R,bE as X,L as O,S as We,V as Ke,W as Ve,X as P,a_ as ve,Z as _,U as Qe,cG as Ye,C as Je,c$ as Xe,aq as Ze,D as _e,z as be,G as je,H as ke,J as we,M as q,I as E,K as Ne,cH as es,E as ss,dG as Ce,dH as ts,dI as ns,dJ as as}from"./index-WYDmEOfO.js";import{P as rs}from"./page-title-DVq4qvMR.js";import{M as is,r as os}from"./index-BOVYgMvj.js";import{E as ls}from"./earth-BXhVPvCR.js";import{T as cs}from"./trash-2-B0HyPTnI.js";function Pe(n){return`${n.replace(/["'`\\$;|&<>(){}\s]/g,"").replace(/\/+$/,"")}/mcp`}function S(...n){return n.filter(i=>i!==null).join(`
|
|
2
|
+
`)}const W="<your ContextNest API key>",I="CONTEXTNEST_API_KEY";function ds(n,i,t,d){return[`**Not connectable yet.** ${t}`,"",n.openMode?`This server needs no credential at all, but ${i} still wants an OAuth client to authorize against, and this server runs no authorization server to offer it. There is no header field to fall back to either.`:`This server authenticates with API keys and does not run an OAuth authorization server, so ${i} has nothing to complete its consent flow against. There is no header field to fall back to.`,"",`The endpoint it would point at is \`${d}\`, so nothing here changes once an authorization server ships.`,"","Until then, the workable routes are:","","- Use one of the other harnesses in this panel.","- Or drive the nest through the REST API directly."].join(`
|
|
3
|
+
`)}const K=[{id:"claude-desktop",name:"Claude (claude.ai and Claude Desktop)",kind:"chat",where:"Customize → Connectors → Add custom connector",open:"https://claude.ai/customize/connectors",docs:"https://claude.com/docs/connectors/custom/remote-mcp",support:"header",body:(n,i)=>S("1. Open **Customize → Connectors** and click **Add custom connector**. On Team and Enterprise plans an Owner adds it once under **Organization settings → Connectors → Add → Custom → Web**; members then find it under **Customize → Connectors** and click **Connect**.",`2. Set the MCP server URL to \`${i}\`.`,n.openMode?"3. For **Authentication**, choose **No sign-in** — this server needs no credential.":`3. For **Authentication**, choose **No sign-in**, then open **Request headers**, pick the \`authorization\` header and enter \`Bearer ${W}\` as its value. Enter the value only — Claude adds the header name itself and sends the value exactly as typed, so the \`Bearer \` prefix and its trailing space have to be there.`,"4. Click **Add**. Authentication settings can't be changed afterwards; changing them means removing the connector and adding it again.",n.openMode?null:"",n.openMode?null:"> **Request headers are in beta, and the credential is organization-wide.** If the dialog has no **Request headers** section, your organization doesn't have access yet. Everyone on the connector shares the one credential, so on this surface they all reach this server as the key's owner and see that person's nests. Per-user visibility here needs OAuth, which this server doesn't run yet — for per-user nests today, use one of the command-line harnesses.","","> The MCP client runs on Anthropic's servers, not the user's machine, so this URL must resolve on the public internet and present a valid TLS certificate. A `localhost` or internal-DNS address will not work here.")},{id:"chatgpt",name:"ChatGPT",kind:"chat",where:"Settings → Security and login → Developer mode",docs:"https://developers.openai.com/plugins/deploy/connect-chatgpt",support:"header",body:(n,i)=>S("1. Open **Settings → Security and login** and turn on **Developer mode**.","2. Go to the **Plugins** page and click the **+** button.","3. Give it a name and description you'll recognise in the tools menu later.",`4. Under **Connection**, paste the MCP server URL \`${i}\` — including the \`/mcp\` path.`,"5. Create the connection, then add it from the **tools menu** in a new conversation.","","Developer mode is available on Plus, Pro, Business, Enterprise and Edu — not on the free tier. Public HTTPS is required.",n.openMode?null:"",n.openMode?null:"> **This surface may not connect yet.** The connection step takes a URL and discovers the server's own authentication; OpenAI documents no field for a fixed API key or `Authorization` header. If the connection fails asking you to sign in, this server has no OAuth authorization server to offer it — use one of the command-line harnesses instead.","","> ChatGPT renamed this surface in July 2026. Older guides point at **Settings → Connectors → Advanced**, which no longer exists.")},{id:"grok",name:"Grok",kind:"chat",where:"grok.com/connectors → New Connector → Custom",open:"https://grok.com/connectors",docs:"https://docs.x.ai/grok/connectors",support:"header",body:(n,i)=>S("1. Go to **grok.com/connectors** and choose **New Connector → Custom**.",`2. Enter the MCP server URL \`${i}\`.`,n.openMode?"3. Leave authentication empty.":`3. Complete any authentication the form asks for, supplying \`Bearer ${W}\` where it wants a credential.`,"4. Grok discovers the exposed tools and offers them alongside its built-in connectors.","","The server must be reachable over the public internet; Grok has no tunnel of its own.",n.openMode?null:"",n.openMode?null:"> xAI documents the connector form but not which credentials it accepts, so the authentication step isn't verified here. If it only offers OAuth, this server has none to offer yet — use a command-line harness instead.")},{id:"perplexity",name:"Perplexity",kind:"chat",where:"All settings → Connectors (perplexity.ai/account/connectors)",open:"https://www.perplexity.ai/account/connectors",docs:"https://www.perplexity.ai/help-center/en/articles/13915507-adding-custom-remote-connectors",support:"oauth-only",body:(n,i)=>ds(n,"Perplexity","Under **All settings → Connectors**, Perplexity's custom-connector form asks for an OAuth client ID under **Advanced**, over Streamable HTTP, on a Pro, Max or Enterprise plan.",i)},{id:"claude-code",name:"Claude Code",kind:"cli",where:"one command in any terminal",docs:"https://code.claude.com/docs/en/mcp-quickstart",support:"header",body:(n,i)=>S("```bash",n.openMode?`claude mcp add --transport http contextnest ${i}`:`claude mcp add --transport http contextnest ${i} \\
|
|
4
|
+
--header "Authorization: Bearer $${I}"`,"```","",n.openMode?"By default this registers at `local` scope — only you, only this project. Add `--scope user` for every project, or `--scope project` to write `.mcp.json` in the repo; that file is safe to commit.":`By default this registers at \`local\` scope — only you, only this project. Add \`--scope user\` for every project, or \`--scope project\` to write \`.mcp.json\` in the repo — that file is safe to commit because it can reference \`\${${I}}\` rather than the value.`,"","A session started before the server was added must be restarted; a fresh session picks it up automatically.")},{id:"codex",name:"OpenAI Codex CLI",kind:"cli",where:"codex mcp add, or ~/.codex/config.toml",docs:"https://learn.chatgpt.com/docs/extend/mcp?surface=cli",support:"header",body:(n,i)=>S("```bash",n.openMode?`codex mcp add contextnest --url ${i}`:`codex mcp add contextnest --url ${i} --bearer-token-env-var ${I}`,"```","","Or write it into `~/.codex/config.toml` directly:","","```toml","[mcp_servers.contextnest]",`url = "${i}"`,n.openMode?null:`bearer_token_env_var = "${I}"`,"```","",n.openMode?null:"Codex reads the token from the environment and sends it as an `Authorization: Bearer` header, so the value never lands in the config file.")},{id:"hermes",name:"Hermes (Nous Research)",kind:"cli",where:"~/.hermes/config.yaml",docs:"https://hermes-agent.nousresearch.com/docs/reference/mcp-config-reference",support:"header",body:(n,i)=>S("```yaml","mcp_servers:"," contextnest:",` url: "${i}"`,n.openMode?null:" headers:",n.openMode?null:` Authorization: "Bearer \${env:${I}}"`," enabled: true","```","",n.openMode?null:`Values support \`\${env:VAR}\` interpolation against \`~/.hermes/.env\`, so put the key in that file as \`${I}\` and keep it out of the YAML.`,n.openMode?null:"",'A `url` entry speaks Streamable HTTP — set `transport: "sse"` only if you need the older one.')},{id:"gemini-cli",name:"Gemini CLI",kind:"cli",where:"~/.gemini/settings.json",docs:"https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md",support:"header",body:(n,i)=>S("```json","{",' "mcpServers": {',' "contextnest": {',` "httpUrl": "${i}"${n.openMode?"":","}`,n.openMode?null:` "headers": { "Authorization": "Bearer ${W}" }`," }"," }","}","```","","Gemini CLI picks the transport from the property name: `httpUrl` is Streamable HTTP, `url` would be SSE, `command` would be stdio. Use `httpUrl` here.")},{id:"cursor",name:"Cursor",kind:"editor",where:"~/.cursor/mcp.json (or .cursor/mcp.json in a project)",docs:"https://cursor.com/docs/mcp",support:"header",body:(n,i)=>S("```json","{",' "mcpServers": {',' "contextnest": {',` "url": "${i}"${n.openMode?"":","}`,n.openMode?null:` "headers": { "Authorization": "Bearer ${W}" }`," }"," }","}","```","","Cursor expands variables inside `url` and `headers`, so the key can come from the environment rather than the file.")}],Se=K[0];function hs(n){return K.find(i=>i.id===n)}function Ie(n,i){const t=[n.open?`[Open the settings page](${n.open})`:null,`[${n.name} docs](${n.docs})`].filter(d=>d!==null).join(" · ");return`${n.body(i,Pe(i.serverUrl))}
|
|
5
|
+
|
|
6
|
+
${t}`}const ms=[{kind:"chat",heading:"# Chat"},{kind:"cli",heading:"# Command line"},{kind:"editor",heading:"# Editors"}];function us(n){const t=[`**Connect once.** All of these point at the same endpoint — \`${Pe(n.serverUrl)}\` — and that one connection reads across every nest the caller can see: the public ones, plus whatever private nests they have been given access to. There is no per-nest setup, and nothing to redo when someone is added to another nest.`,"","What comes back is decided by who the caller authenticates as, not by which tool they are running.","",n.openMode?"This deployment runs in open mode, so no credential is involved and every caller is the same anonymous user.":["Two things to get right about the credential:","","- **Use a user-level key, not a nest-scoped one.** A key scoped to a single nest narrows this endpoint back down to that nest, which looks exactly like the connect-once promise being broken. Mint a user-level key in the Connect dialog.","- **Each person uses their own key.** A key shared across a team makes all of them the same user to this server, so they would all see the key owner's nests instead of their own."].join(`
|
|
7
|
+
`),""];for(const{kind:d,heading:f}of ms){const c=K.filter(y=>y.kind===d);if(c.length!==0){t.push(f,"");for(const y of c)t.push(`## ${y.name}`,"",`*${y.where}*`,"",Ie(y,n),"")}}return t.join(`
|
|
8
|
+
`).trimEnd()+`
|
|
9
|
+
`}const ps={chat:"Chat",cli:"Command line",editor:"Editors"},xs=["chat","cli","editor"];function gs({publicBaseUrl:n,openMode:i}){const[t,d]=l.useState(Se.id),f=n.trim(),c=f||window.location.origin,y=l.useMemo(()=>({serverUrl:c,openMode:i}),[c,i]),v=hs(t)??Se,M=l.useMemo(()=>Ie(v,y),[v,y]);return e.jsxs(m,{children:[e.jsx(u,{children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx(p,{className:"text-base",children:"Connecting agents"}),e.jsxs(x,{children:["Setup steps for each AI tool your people are likely to use. Every one of them connects ",e.jsx("strong",{children:"once"}),", to the same server-level MCP endpoint, and that single connection reads across every nest the caller can see — the public ones plus whatever private nests they have access to. There is no per-nest setup, and nothing to redo when someone is added to another nest."]})]}),e.jsxs(b,{size:"sm",variant:"outline",onClick:()=>te(us(y),"All connection instructions copied"),children:[e.jsx(se,{className:"h-4 w-4 mr-1.5"}),"Copy all"]})]})}),e.jsxs(g,{className:"space-y-4",children:[!f&&e.jsxs("div",{role:"alert",className:"flex gap-2 rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs",children:[e.jsx(Fe,{className:"h-4 w-4 shrink-0 mt-0.5 text-amber-600"}),e.jsxs("span",{children:["No public base URL is set, so these steps use"," ",e.jsx("code",{children:c})," — the address of"," ",e.jsx("em",{children:"this browser's"})," connection. Most of these tools run the MCP client on the vendor's servers, not the user's machine, so a private or proxied address will fail for them. Set the public base URL on the ",e.jsx("strong",{children:"General"})," tab."]})]}),!i&&e.jsxs("div",{className:"space-y-1 text-xs text-muted-foreground",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Use a user-level key, not a nest-scoped one."})," A key scoped to a single nest narrows this endpoint back down to that nest, which looks exactly like the connect-once promise being broken."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Each person uses their own key."})," A key shared across a team makes all of them the same user to this server, so they would all see the key owner's nests instead of their own."]})]}),xs.map(C=>{const U=K.filter(N=>N.kind===C);return U.length===0?null:e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("div",{className:"text-xs font-medium text-muted-foreground",children:ps[C]}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:U.map(N=>e.jsxs(b,{size:"sm",variant:N.id===t?"default":"outline","aria-pressed":N.id===t,onClick:()=>d(N.id),children:[N.name,N.support==="oauth-only"&&e.jsx(Ae,{variant:"secondary",className:"ml-1.5",children:"OAuth"})]},N.id))})]},C)}),e.jsxs("div",{className:"rounded-lg border border-border bg-muted/30 p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4 mb-2",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:v.name}),e.jsx("div",{className:"text-xs text-muted-foreground",children:v.where})]}),e.jsxs(b,{size:"sm",variant:"ghost",onClick:()=>te(M,`${v.name} steps copied`),children:[e.jsx(se,{className:"h-4 w-4 mr-1.5"}),"Copy"]})]}),e.jsx("article",{className:"prose prose-sm dark:prose-invert max-w-none",children:e.jsx(is,{remarkPlugins:[os],components:{a:({...C})=>e.jsx("a",{...C,target:"_blank",rel:"noopener noreferrer"})},children:M})})]})]})]})}const fs=[{value:"open",label:"Everyone",hint:"Anyone can sign in with PromptOwl."},{value:"admin-only",label:"Admins only",hint:"Only the server admin can use PromptOwl sign-in."},{value:"disabled",label:"Off",hint:"Hide PromptOwl sign-in."}],ys=[{value:"open",label:"Everyone",hint:"Anyone can sign in and create their own account."},{value:"invite-only",label:"Invite only",hint:"Invited users sign in and set a password; no self sign-up."},{value:"disabled",label:"Off",hint:"No email & password sign-in — PromptOwl only."}],Z=[{id:"general",label:"General",keys:["promptowl_sign_in_gate","manual_sign_in","public_base_url","logo_url","anthropic_api_key","nest_creation","people_suggest_all_users","shared_deployment"]},{id:"sso",label:"Single sign-on",keys:["oidc_enabled","oidc_issuer","oidc_client_id","oidc_client_secret","oidc_allowed_domains","oidc_auto_provision","oidc_department_tagging","sso_token_exchange_enabled","mcp_signing_secret","mcp_token_ttl_seconds","ms_token_exchange_enabled","ms_client_id","ms_tenant_id","google_token_exchange_enabled","google_client_id"]},{id:"notifications",label:"Notifications",keys:["slack_webhook_url","msteams_webhook_url","email_provider","smtp_url","ses_region","ses_access_key_id","ses_secret_access_key","notify_email_from","notify_email_to"]},{id:"community-sites",label:"Community sites",keys:[]},{id:"agents",label:"Connecting agents",keys:[]},{id:"advanced",label:"Advanced",keys:["telemetry_enabled","posthog_key","posthog_host","max_body_bytes","trace_retention_days","type_artifact_enabled","type_table_enabled","workflow_plane_enabled","promptowl_teams_enabled","subagent_runs_enabled","subagent_max_depth","subagent_max_children"]}],V=n=>({autoComplete:n==="password"?"new-password":"off","data-1p-ignore":!0,"data-lpignore":"true","data-form-type":"other"});function h({value:n,placeholder:i,onChange:t,type:d="text"}){const f=d==="password",[c,y]=l.useState(!1);return e.jsxs("div",{className:"relative flex-1",children:[e.jsx(E,{value:n,type:f&&c?"text":d,placeholder:i,onChange:v=>t(v.target.value),className:f?"flex-1 pr-9":"flex-1",...V(d)}),f&&e.jsx("button",{type:"button",tabIndex:-1,onClick:()=>y(v=>!v),className:"absolute inset-y-0 right-0 flex items-center px-2.5 text-muted-foreground hover:text-foreground",title:c?"Hide":"Show","aria-label":c?"Hide value":"Show value",children:c?e.jsx(es,{className:"h-4 w-4"}):e.jsx(ss,{className:"h-4 w-4"})})]})}function vs({bytes:n,onChange:i}){const[t,d]=l.useState(String(Math.round(n/1048576)));return l.useEffect(()=>d(String(Math.round(n/(1024*1024)))),[n]),e.jsxs("div",{className:"flex items-center gap-2 max-w-xs",children:[e.jsx(E,{type:"number",value:t,onChange:f=>{d(f.target.value);const c=Number(f.target.value);Number.isFinite(c)&&c>0&&i(Math.floor(c*1024*1024))},...V("number")}),e.jsx("span",{className:"text-sm text-muted-foreground shrink-0",children:"MB"})]})}function ee({value:n,onChange:i,min:t,max:d}){const[f,c]=l.useState(String(n));return l.useEffect(()=>c(String(n)),[n]),e.jsx(E,{type:"number",min:t,max:d,value:f,className:"max-w-[7rem]",onChange:y=>{c(y.target.value);const v=Number(y.target.value);Number.isInteger(v)&&i(v)},...V("number")})}function _s({settings:n,onUpdate:i}){var ge,fe;const[t,d]=l.useState(n),[f,c]=l.useState(!1),y=Oe(),{authMode:v}=Te(),[M,C]=l.useState(null),[U,N]=l.useState("general"),[ae,re]=l.useState(!1);l.useEffect(()=>{n&&d(n)},[n]);const[Q,Ee]=l.useState(null),[ie,oe]=l.useState(null),z=async()=>{try{await y.invalidateQueries({queryKey:ne.communitySites().queryKey});const s=await y.fetchQuery(ne.communitySites());Ee(s.community_sites),oe(null)}catch(s){oe(s.message)}};l.useEffect(()=>{z()},[]);const[j,L]=l.useState(null),[k,A]=l.useState({name:"",url:"",secret:"",is_active:!0}),[le,ce]=l.useState(!1),[de,B]=l.useState(null),[T,G]=l.useState(null),[he,me]=l.useState(!1),Me=()=>{A({name:"",url:"",secret:"",is_active:!0}),B(null),L({mode:"add"})},Le=s=>{A({name:s.name,url:s.url,secret:"",is_active:s.is_active}),B(null),L({mode:"edit",site:s})},$e=async()=>{if(j){ce(!0),B(null);try{if(j.mode==="add")await ts({name:k.name.trim(),url:k.url.trim(),secret:k.secret.trim(),is_active:k.is_active});else{const s={name:k.name.trim(),url:k.url.trim(),is_active:k.is_active};k.secret.trim()&&(s.secret=k.secret.trim()),await Ce(j.site.id,s)}L(null),await z()}catch(s){B(s.message)}finally{ce(!1)}}},De=async s=>{try{await Ce(s.id,{is_active:!s.is_active}),await z()}catch(a){R.error(a.message)}},Re=async()=>{if(T){me(!0);try{await ns(T.id),G(null),await z()}catch(s){R.error(s.message)}finally{me(!1)}}},r=s=>{d(a=>a&&{...a,...s}),C(null)},$=l.useMemo(()=>{if(!t||!n)return[];const s=n;return Object.keys(t).filter(a=>{if(a==="anthropic_api_key"||a==="oidc_client_secret"||a==="mcp_signing_secret"||a==="ses_secret_access_key"){const o=t[a];return typeof o=="string"&&o.trim()!==""||o===null}return(t[a]??"")!==(s[a]??"")})},[t,n]),F=$.length>0,Ue=s=>s.some(a=>$.includes(a)),ze=async()=>{var a;if(!t||!F)return;const s={};for(const o of $)s[o]=t[o];c(!0),C(null);try{await i(s)}catch(o){C((o==null?void 0:o.message)||"Failed to save settings");const w=((a=o==null?void 0:o.body)==null?void 0:a.fieldErrors)??{},D=Object.keys(w),H=Y=>D.some(J=>Y.keys.includes(J)),ye=D.length?Z.find(H):Z.find(Y=>Y.keys.some(J=>$.includes(J)));ye&&N(ye.id)}finally{c(!1)}},Be=()=>{n&&d(n),C(null)},[ue,pe]=l.useState(null),Ge=async s=>{pe(s);try{await as(s),R.success(`Test ${s==="slack"?"Slack":"Teams"} notification sent — check the channel.`)}catch(a){R.error((a==null?void 0:a.message)||"Test notification failed.")}finally{pe(null)}},xe=(s,a)=>e.jsxs("div",{className:"mt-3 flex items-center gap-2",children:[e.jsxs(b,{type:"button",variant:"outline",size:"sm",disabled:ue===s||!(n!=null&&n[a]),onClick:()=>Ge(s),children:[ue===s&&e.jsx(O,{className:"h-3.5 w-3.5 mr-1.5 animate-spin"}),"Send test"]}),$.includes(a)&&e.jsx("span",{className:"text-xs text-muted-foreground",children:"Save first — the test uses the saved URL."})]});return e.jsxs("div",{children:[e.jsx(rs,{icon:X,title:"Server settings",description:"Server-wide options. Changes apply on Save and persist across restarts.",className:"mb-6",actions:n&&e.jsxs(e.Fragment,{children:[F&&e.jsx("span",{className:"text-xs text-muted-foreground mr-1",children:"Unsaved changes"}),e.jsx(b,{variant:"ghost",size:"sm",onClick:Be,disabled:!F||f,children:"Discard"}),e.jsxs(b,{size:"sm",onClick:ze,disabled:!F||f,children:[f&&e.jsx(O,{className:"h-4 w-4 mr-1.5 animate-spin"}),"Save changes"]})]})}),M&&e.jsxs("div",{role:"alert",className:"mb-4 rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",children:[e.jsx("div",{className:"font-medium",children:"Couldn't save settings"}),e.jsx("div",{className:"mt-0.5 text-destructive/90",children:M})]}),t?e.jsxs(We,{value:U,onValueChange:N,children:[e.jsx(Ke,{children:Z.map(s=>e.jsxs(Ve,{value:s.id,className:"gap-1.5",children:[s.label,Ue(s.keys)&&e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-primary","aria-label":"unsaved changes"})]},s.id))}),e.jsxs(P,{value:"general",className:"space-y-4",children:[e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(X,{className:"h-4 w-4 text-muted-foreground"}),"PromptOwl sign-in"]}),e.jsx(x,{children:"Who can sign in to this server using their PromptOwl account."})]}),e.jsx(g,{children:e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:fs.map(s=>{const a=t.promptowl_sign_in_gate===s.value,o=s.value==="disabled"&&t.manual_sign_in==="disabled";return e.jsxs("button",{type:"button",disabled:o,onClick:()=>!a&&!o&&r({promptowl_sign_in_gate:s.value}),className:`text-left rounded-lg border p-3 transition-colors ${a?"border-primary bg-primary/5 ring-1 ring-primary":o?"opacity-50 cursor-not-allowed":"hover:bg-muted/50"}`,"aria-pressed":a,children:[e.jsx("div",{className:"text-sm font-medium",children:s.label}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5",children:s.hint})]},s.value)})})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(X,{className:"h-4 w-4 text-muted-foreground"}),"Manual sign-in"]}),e.jsx(x,{children:"Email & password sign-in. Independent of PromptOwl — you can't turn this fully off while PromptOwl sign-in is also off."})]}),e.jsx(g,{children:e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:ys.map(s=>{const a=t.manual_sign_in===s.value,o=s.value==="disabled"&&t.promptowl_sign_in_gate==="disabled";return e.jsxs("button",{type:"button",disabled:o,onClick:()=>!a&&!o&&r({manual_sign_in:s.value}),className:`text-left rounded-lg border p-3 transition-colors ${a?"border-primary bg-primary/5 ring-1 ring-primary":o?"opacity-50 cursor-not-allowed":"hover:bg-muted/50"}`,"aria-pressed":a,children:[e.jsx("div",{className:"text-sm font-medium",children:s.label}),e.jsx("div",{className:"text-xs text-muted-foreground mt-0.5",children:s.hint})]},s.value)})})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Public base URL"}),e.jsx(x,{children:"This server's public address — used for share links and SSO redirects. Leave empty if unsure."})]}),e.jsx(g,{children:e.jsx(h,{value:t.public_base_url??"",placeholder:"https://nest.yourcompany.com",onChange:s=>r({public_base_url:s})})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Logo"}),e.jsx(x,{children:"URL of the logo shown in the header. Leave empty for the default."})]}),e.jsx(g,{children:e.jsx(h,{value:t.logo_url??"",placeholder:"https://example.com/logo.svg",onChange:s=>r({logo_url:s})})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Anthropic API key"}),e.jsx(x,{children:"The server-wide model key. Runners pick it up automatically (every nest, unless a nest overrides it in its Tool environment). No key, no LLM calls. Stored server-side; shown masked."})]}),e.jsxs(g,{children:[e.jsx("div",{className:"text-xs text-muted-foreground mb-2",children:t.anthropic_api_key===null?"Will be cleared when you save.":n!=null&&n.anthropic_api_key_masked?`Current: ${n.anthropic_api_key_masked}`:"Not set — runs can't execute until a key exists here or in a nest's Tool environment."}),e.jsx(h,{type:"password",value:typeof t.anthropic_api_key=="string"?t.anthropic_api_key:"",placeholder:"sk-ant-… (paste to set or replace)",onChange:s=>r({anthropic_api_key:s})}),(n==null?void 0:n.anthropic_api_key_masked)&&t.anthropic_api_key!==null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-destructive hover:underline",onClick:()=>r({anthropic_api_key:null}),children:"Clear key"}),t.anthropic_api_key===null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-muted-foreground hover:underline",onClick:()=>r({anthropic_api_key:void 0}),children:"Keep current key"})]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(ve,{className:"h-4 w-4 text-muted-foreground"}),"Nest creation"]}),e.jsx(x,{children:"Who can create and import nests on this server."})]}),e.jsx(g,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"pr-4",children:[e.jsx("div",{className:"text-sm font-medium",children:"Let everyone create nests"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Off, only server admins can create or import nests, and everyone else works in the nests shared with them. On, any signed-in user can create their own."})]}),e.jsx(_,{checked:t.nest_creation==="everyone",onCheckedChange:s=>r({nest_creation:s?"everyone":"admins"})})]})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(Qe,{className:"h-4 w-4 text-muted-foreground"}),"People directory"]}),e.jsx(x,{children:'What the "add a person" fields suggest when inviting someone to a nest, a team, or a stewardship role.'})]}),e.jsxs(g,{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"pr-4",children:[e.jsx("div",{className:"text-sm font-medium",children:"Suggest everyone on this server"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Off, the pickers only suggest people the inviter already shares a nest or team with. On, they suggest every registered account — right when this server is one organisation, wrong when it hosts several, because it shows them each other's email addresses. Either way anyone can still be invited by typing their address."})]}),e.jsx(_,{checked:t.people_suggest_all_users,onCheckedChange:s=>r({people_suggest_all_users:s})})]}),e.jsxs("div",{className:"flex items-start justify-between gap-4 pt-4 border-t",children:[e.jsxs("div",{className:"pr-4",children:[e.jsx("div",{className:"text-sm font-medium",children:"This server hosts several organizations"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"A nest's Organization tier is readable by every account on this server. Off, that is one company and the tier applies in one click. On — the PromptOwl-hosted service, or any install shared by unrelated customers — opening a nest to Organization asks for the same acknowledgement as Public (enforced by the server, not only the UI), and the visibility picker says who the tier really reaches."})]}),e.jsx(_,{checked:t.shared_deployment,onCheckedChange:s=>r({shared_deployment:s}),"data-testid":"settings-shared-deployment"})]})]})]})]}),e.jsxs(P,{value:"sso",className:"space-y-4",children:[e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(Ye,{className:"h-4 w-4 text-muted-foreground"}),"Single sign-on (OIDC)"]}),e.jsx(x,{children:"Let teammates sign in with your identity provider — Microsoft Entra ID, Google, or any OpenID Connect issuer. Fill in the issuer and app credentials below, then turn it on."})]}),e.jsxs(g,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-sm",children:[t.oidc_enabled?"On":"Off",!t.oidc_enabled&&!(t.oidc_issuer&&t.oidc_client_id)&&e.jsxs("span",{className:"text-muted-foreground",children:[" ","· configure the issuer and app credentials first"]})]}),e.jsx(_,{checked:t.oidc_enabled,onCheckedChange:s=>r({oidc_enabled:s})})]}),(()=>{var o,w;const s=t.oidc_client_secret===null?!1:typeof t.oidc_client_secret=="string"&&t.oidc_client_secret.trim()!==""?!0:!!(n!=null&&n.oidc_client_secret_set),a=t.oidc_enabled&&!!((o=t.oidc_issuer)!=null&&o.trim())&&!!((w=t.oidc_client_id)!=null&&w.trim())&&s;return!t.oidc_enabled||a?null:e.jsx("div",{role:"alert",className:"rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-400",children:"Enabled but not configured — the SSO sign-in button stays hidden until the issuer, client ID, and client secret are all set."})})(),(()=>{var o;const s=((o=t.oidc_issuer)==null?void 0:o.trim())??"",a=/^https:\/\/login\.microsoftonline\.com\/[^/]+\/v2\.0$/.test(s)?"entra":s==="https://accounts.google.com"?"google":null;return e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Issuer URL"}),e.jsxs("div",{className:"flex gap-2 mb-2",role:"group","aria-label":"Identity provider preset",children:[e.jsx(b,{type:"button",variant:a==="entra"?"default":"outline",size:"sm","aria-pressed":a==="entra",onClick:()=>{const w=window.prompt("Microsoft Entra tenant ID (Directory ID) — find it on your app registration's Overview page:");w&&w.trim()&&r({oidc_issuer:`https://login.microsoftonline.com/${w.trim()}/v2.0`})},children:"Microsoft Entra ID"}),e.jsx(b,{type:"button",variant:a==="google"?"default":"outline",size:"sm","aria-pressed":a==="google",onClick:()=>r({oidc_issuer:"https://accounts.google.com"}),children:"Google"}),a===null&&s!==""&&e.jsx("span",{className:"self-center text-xs text-muted-foreground",children:"Custom issuer"})]}),e.jsx(h,{value:t.oidc_issuer??"",placeholder:"https://login.microsoftonline.com/{tenant}/v2.0",onChange:w=>r({oidc_issuer:w})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"https:// only. Must serve /.well-known/openid-configuration."})]})})(),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Client ID"}),e.jsx(h,{value:t.oidc_client_id??"",placeholder:"Application (client) ID from your IdP app registration",onChange:s=>r({oidc_client_id:s})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Client secret"}),e.jsx("div",{className:"text-xs text-muted-foreground mb-2",children:t.oidc_client_secret===null?"Will be cleared when you save.":n!=null&&n.oidc_client_secret_set?"A client secret is set. Paste a new one to replace it.":"Not set."}),e.jsx(h,{type:"password",value:typeof t.oidc_client_secret=="string"?t.oidc_client_secret:"",placeholder:"Paste to set or replace",onChange:s=>r({oidc_client_secret:s})}),(n==null?void 0:n.oidc_client_secret_set)&&t.oidc_client_secret!==null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-destructive hover:underline",onClick:()=>r({oidc_client_secret:null}),children:"Clear secret"}),t.oidc_client_secret===null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-muted-foreground hover:underline",onClick:()=>r({oidc_client_secret:void 0}),children:"Keep current secret"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Redirect URI"}),(()=>{const a=`${(t.public_base_url||window.location.origin).replace(/\/$/,"")}/auth/oidc/callback`;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"flex-1 bg-muted/40 border rounded px-2 py-1.5 text-xs font-mono break-all",children:a}),e.jsxs(b,{type:"button",variant:"outline",size:"sm",onClick:async()=>{await te(a)&&(re(!0),setTimeout(()=>re(!1),1500))},children:[ae?e.jsx(Je,{className:"h-3.5 w-3.5"}):e.jsx(se,{className:"h-3.5 w-3.5"}),e.jsx("span",{className:"ml-1.5",children:ae?"Copied":"Copy"})]})]})})(),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Register this exact URI in your IdP's app registration (Entra: Authentication → Web redirect URIs; Google: Authorized redirect URIs)."})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Allowed email domains"}),e.jsx(h,{value:t.oidc_allowed_domains??"",placeholder:"acme.com, contractors.acme.com — empty allows any",onChange:s=>r({oidc_allowed_domains:s})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Only accounts whose email domain is listed may sign in. Leave empty to allow any domain your IdP asserts."})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Auto-provision new users"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Create an account on first SSO sign-in. Turn off to allow only users you've already invited."})]}),e.jsx(_,{checked:t.oidc_auto_provision,onCheckedChange:s=>r({oidc_auto_provision:s})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Department auto-tagging"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Tag new documents with the creator's directory department (requires the department claim from your IdP)."})]}),e.jsx(_,{checked:t.oidc_department_tagging,onCheckedChange:s=>r({oidc_department_tagging:s})})]}),t.oidc_enabled&&t.oidc_auto_provision&&!((ge=t.oidc_allowed_domains)!=null&&ge.trim())&&e.jsx("div",{role:"alert",className:"rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-400",children:"Anyone your issuer can authenticate will get an account on first sign-in — with a consumer or multi-tenant issuer (e.g. Google), that's any account on the internet, and it applies even when manual sign-in is invite-only. Set allowed email domains above, or turn auto-provision off."})]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{children:"Agent SSO — token exchange"}),e.jsx(x,{children:"Let an external agent, acting for a user your IdP already authenticated (Microsoft Entra / Google), exchange that IdP's ID token for a short-lived MCP bearer — no second login. Uses the domain allowlist and auto-provision settings above."})]}),e.jsxs(g,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",children:t.sso_token_exchange_enabled?"On":"Off"}),e.jsx(_,{checked:t.sso_token_exchange_enabled,onCheckedChange:s=>r({sso_token_exchange_enabled:s})})]}),(t.ms_token_exchange_enabled||t.google_token_exchange_enabled)&&t.oidc_auto_provision&&!((fe=t.oidc_allowed_domains)!=null&&fe.trim())&&e.jsx("div",{role:"alert",className:"rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-xs text-destructive",children:"Blocked: with auto-provision on and no allowed email domains, anyone with an account at that provider could sign themselves up and mint a token. Set allowed email domains above, or turn auto-provision off."}),(()=>{var w,D,H;const s=t.mcp_signing_secret===null?!1:typeof t.mcp_signing_secret=="string"&&t.mcp_signing_secret.trim()!==""?!0:!!(n!=null&&n.mcp_signing_secret_set),a=t.ms_token_exchange_enabled&&!!((w=t.ms_client_id)!=null&&w.trim())&&!!((D=t.ms_tenant_id)!=null&&D.trim()),o=t.google_token_exchange_enabled&&!!((H=t.google_client_id)!=null&&H.trim());return!t.sso_token_exchange_enabled||s&&(a||o)?null:e.jsx("div",{role:"alert",className:"rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-400",children:"Enabled but not ready — the endpoint needs a signing secret and at least one provider turned on with its client ID filled in (plus the tenant ID for Microsoft)."})})(),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"MCP signing secret"}),e.jsx("div",{className:"text-xs text-muted-foreground mb-2",children:t.mcp_signing_secret===null?"Will be cleared when you save.":n!=null&&n.mcp_signing_secret_set?"A signing secret is set. Paste a new one to replace it.":"Not set. Use a long random string — this signs the MCP tokens the exchange mints."}),e.jsx(h,{type:"password",value:typeof t.mcp_signing_secret=="string"?t.mcp_signing_secret:"",placeholder:"Paste to set or replace (16+ characters)",onChange:s=>r({mcp_signing_secret:s})}),(n==null?void 0:n.mcp_signing_secret_set)&&t.mcp_signing_secret!==null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-destructive hover:underline",onClick:()=>r({mcp_signing_secret:null}),children:"Clear secret"}),t.mcp_signing_secret===null&&e.jsx("button",{type:"button",className:"mt-2 text-xs text-muted-foreground hover:underline",onClick:()=>r({mcp_signing_secret:void 0}),children:"Keep current secret"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Token lifetime (seconds)"}),e.jsx(h,{type:"number",value:String(t.mcp_token_ttl_seconds??300),placeholder:"300",onChange:s=>r({mcp_token_ttl_seconds:s.trim()===""?300:Number(s)})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"30–3600. Short by design — a minted token expires quickly."})]}),e.jsxs("div",{className:"border-t pt-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm font-medium",children:"Microsoft Entra"}),e.jsx(_,{checked:t.ms_token_exchange_enabled,onCheckedChange:s=>r({ms_token_exchange_enabled:s})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Client (application) ID"}),e.jsx(h,{value:t.ms_client_id??"",placeholder:"Entra app (client) ID — the token audience",onChange:s=>r({ms_client_id:s})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Tenant ID"}),e.jsx(h,{value:t.ms_tenant_id??"",placeholder:"Directory (tenant) ID — builds the issuer",onChange:s=>r({ms_tenant_id:s})})]})]}),e.jsxs("div",{className:"border-t pt-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm font-medium",children:"Google"}),e.jsx(_,{checked:t.google_token_exchange_enabled,onCheckedChange:s=>r({google_token_exchange_enabled:s})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"OAuth client ID"}),e.jsx(h,{value:t.google_client_id??"",placeholder:"Google OAuth client ID — the token audience",onChange:s=>r({google_client_id:s})})]})]}),e.jsxs("div",{className:"rounded-md border bg-muted/30 px-3 py-2 text-xs text-muted-foreground",children:["Your agent calls"," ",e.jsx("code",{className:"text-[11px]",children:"POST /auth/token-exchange"})," ","with the IdP ID token and receives a short-lived MCP bearer for"," ",e.jsx("code",{className:"text-[11px]",children:"/mcp"})," and"," ",e.jsx("code",{className:"text-[11px]",children:"/index"}),". The token is verified by signature, issuer, audience (the client id above) and expiry. Security-critical — keep it off until reviewed. For a public IdP like Google, set the allowed email domains above so only your organization can exchange."]})]})]})]}),e.jsxs(P,{value:"notifications",className:"space-y-4",children:[e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Slack notifications"}),e.jsx(x,{children:"Post governance events (review requested, approved, rejected, nest shared) to a Slack channel via an incoming-webhook URL. Leave empty to turn the connector off. The URL contains a secret — treat it like a password."})]}),e.jsxs(g,{children:[e.jsx(h,{type:"password",value:t.slack_webhook_url??"",placeholder:"https://hooks.slack.com/services/…",onChange:s=>r({slack_webhook_url:s})}),xe("slack","slack_webhook_url")]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Microsoft Teams notifications"}),e.jsx(x,{children:'Post the same governance events to a Microsoft Teams channel as Adaptive Cards via an incoming-webhook URL (create one in Teams with the Workflows app: "Post to a channel when a webhook request is received"). Leave empty to turn the connector off. The URL contains a secret — treat it like a password.'})]}),e.jsxs(g,{children:[e.jsx(h,{type:"password",value:t.msteams_webhook_url??"",placeholder:"https://….logic.azure.com/workflows/…",onChange:s=>r({msteams_webhook_url:s})}),xe("teams","msteams_webhook_url")]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Email notifications"}),e.jsx(x,{children:"Invites, shares and governance events by email. Send through SMTP, or through AWS SES when this server can't use SMTP. Set a From address and one or more team recipients (comma-separated). Leave the SMTP URL or AWS region empty to turn email off."})]}),e.jsxs(g,{className:"space-y-3",children:[e.jsx("div",{role:"radiogroup",className:"flex gap-4 text-sm",children:[["smtp","SMTP"],["ses","AWS SES"]].map(([s,a])=>e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"radio",name:"email_provider",checked:(t.email_provider??"smtp")===s,onChange:()=>r({email_provider:s})}),a]},s))}),(t.email_provider??"smtp")==="smtp"?e.jsx(h,{type:"password",value:t.smtp_url??"",placeholder:"smtps://user:pass@smtp.example.com:465",onChange:s=>r({smtp_url:s})}):e.jsxs(e.Fragment,{children:[e.jsx(h,{value:t.ses_region??"",placeholder:"AWS region — us-east-1",onChange:s=>r({ses_region:s})}),e.jsx(h,{value:t.ses_access_key_id??"",placeholder:"Access key ID — leave empty to use the server's IAM role",onChange:s=>r({ses_access_key_id:s})}),e.jsx(h,{type:"password",value:typeof t.ses_secret_access_key=="string"?t.ses_secret_access_key:"",placeholder:t.ses_secret_access_key===null?"Secret access key — will be cleared when you save":n!=null&&n.ses_secret_access_key_set?"Secret access key is set — paste to replace":"Secret access key — leave empty to use the server's IAM role",onChange:s=>r({ses_secret_access_key:s})}),(n==null?void 0:n.ses_secret_access_key_set)&&t.ses_secret_access_key!==null&&e.jsx("button",{type:"button",className:"text-xs text-destructive hover:underline",onClick:()=>r({ses_secret_access_key:null,ses_access_key_id:""}),children:"Clear keys"})]}),e.jsx(h,{value:t.notify_email_from??"",placeholder:"From — nest@yourcompany.com",onChange:s=>r({notify_email_from:s})}),e.jsx(h,{value:t.notify_email_to??"",placeholder:"To — team@yourcompany.com, ops@yourcompany.com",onChange:s=>r({notify_email_to:s})})]})]})]}),e.jsxs(P,{value:"advanced",className:"space-y-4",children:[e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Usage telemetry"}),e.jsx(x,{children:"Send anonymous usage counts to PromptOwl. Turn off to keep all usage data on this server."})]}),e.jsx(g,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",children:t.telemetry_enabled?"On":"Off"}),e.jsx(_,{checked:t.telemetry_enabled,onCheckedChange:s=>r({telemetry_enabled:s})})]})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Product analytics"}),e.jsx(x,{children:"Send usage events to your own PostHog project. Leave the key empty to keep analytics off. Also off whenever usage telemetry above is off."})]}),e.jsxs(g,{className:"space-y-3",children:[e.jsx(h,{value:t.posthog_key??"",placeholder:"Project API key — phc_...",onChange:s=>r({posthog_key:s})}),e.jsx(h,{value:t.posthog_host??"",placeholder:"Host — https://us.i.posthog.com",onChange:s=>r({posthog_host:s})})]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Max upload size"}),e.jsx(x,{children:"Largest request/file accepted, in megabytes. Raise this if big HTML artifacts (decks, dashboards) get rejected."})]}),e.jsx(g,{children:e.jsx(vs,{bytes:t.max_body_bytes,onChange:s=>r({max_body_bytes:s})})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Activity trace retention"}),e.jsx(x,{children:"How many days of activity-trace rows (API requests and MCP tool calls) to keep. Older rows are pruned opportunistically. Set 0 to keep activity forever."})]}),e.jsxs(g,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ee,{value:t.trace_retention_days,min:0,max:3650,onChange:s=>r({trace_retention_days:s})}),e.jsx("span",{className:"text-sm text-muted-foreground shrink-0",children:"days"})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"0–3650 — 0 disables pruning entirely."})]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Content types"}),e.jsx(x,{children:"Which node types can be created on this server. Turning one off hides it from the editor and refuses new creations — existing nodes of that type stay readable and versioned. Runnable types (agent, skill, tool) are governed by the workflow plane below."})]}),e.jsxs(g,{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-sm",children:["Artifacts (hosted HTML) —"," ",t.type_artifact_enabled?"On":"Off"]}),e.jsx(_,{checked:t.type_artifact_enabled,onCheckedChange:s=>r({type_artifact_enabled:s})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-sm",children:["Tables (CSV fact stores) —"," ",t.type_table_enabled?"On":"Off"]}),e.jsx(_,{checked:t.type_table_enabled,onCheckedChange:s=>r({type_table_enabled:s})})]})]})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsxs(p,{className:"text-base",children:["Workflow plane ",e.jsx(Xe,{className:"ml-1 align-middle"})]}),e.jsx(x,{children:"Typed edges, an edge-type registry, and governed runs — the automation layer. Optional; off by default. Turning it on adds API surface and UI views but changes nothing until someone creates an edge."})]}),e.jsx(g,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",children:t.workflow_plane_enabled?"On":"Off"}),e.jsx(_,{checked:t.workflow_plane_enabled,onCheckedChange:s=>r({workflow_plane_enabled:s,...s?{}:{subagent_runs_enabled:!1}})})]})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Import teams from PromptOwl"}),e.jsx(x,{children:"Lets users who signed in with PromptOwl pull their PromptOwl teams in as local teams. Off by default. When off, the PromptOwl Teams panel is hidden and the import API is unavailable."})]}),e.jsx(g,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",children:t.promptowl_teams_enabled?"On":"Off"}),e.jsx(_,{checked:t.promptowl_teams_enabled,onCheckedChange:s=>r({promptowl_teams_enabled:s})})]})})]}),e.jsxs(m,{children:[e.jsxs(u,{children:[e.jsx(p,{className:"text-base",children:"Sub-agent runs (recursion)"}),e.jsx(x,{children:"Lets a run spawn nested sub-agent runs (a call tree). Bounded by depth, fan-out and re-entrancy caps so the tree stays finite. This opens a recursion surface — enable it only after reviewing the caps for your deployment. Requires the workflow plane."})]}),e.jsxs(g,{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-sm",children:[t.subagent_runs_enabled?"On":"Off",!t.workflow_plane_enabled&&e.jsxs("span",{className:"text-muted-foreground",children:[" ","· enable the workflow plane first"]})]}),e.jsx(_,{checked:t.subagent_runs_enabled,disabled:!t.workflow_plane_enabled,onCheckedChange:s=>r({subagent_runs_enabled:s})})]}),t.subagent_runs_enabled&&e.jsxs("div",{className:"mt-4 grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Max depth"}),e.jsx(ee,{value:t.subagent_max_depth,min:1,max:32,onChange:s=>r({subagent_max_depth:s})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"1–32 — how deep the sub-agent call tree may nest."})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium mb-1",children:"Max sub-agents per run"}),e.jsx(ee,{value:t.subagent_max_children,min:1,max:128,onChange:s=>r({subagent_max_children:s})}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"1–128 — fan-out a single run may spawn."})]})]})]})]})]}),e.jsx(P,{value:"community-sites",className:"space-y-4",children:e.jsxs(m,{children:[e.jsx(u,{children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsxs(p,{className:"flex items-center gap-2 text-base",children:[e.jsx(ls,{className:"h-4 w-4 text-muted-foreground"}),"Official community sites"]}),e.jsx(x,{children:"Sites trusted for one-click SSO auto-login. A visitor arriving with a ticket signed by one of these sites' secrets is signed in automatically — the ticket's audience is also checked against this server's own base URL, so a ticket minted for a different deployment can't be replayed here."})]}),e.jsxs(b,{size:"sm",onClick:Me,children:[e.jsx(ve,{className:"h-4 w-4 mr-1.5"}),"Add site"]})]})}),e.jsxs(g,{children:[ie&&e.jsx("div",{role:"alert",className:"mb-4 rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",children:ie}),Q?Q.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-6",children:"No community sites configured yet. Add one to enable SSO auto-login from it."}):e.jsx("div",{className:"divide-y",children:Q.map(s=>e.jsxs("div",{className:"flex items-center justify-between gap-3 py-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-sm truncate",children:s.name}),e.jsx(Ae,{variant:"outline",className:s.is_active?"border-emerald-200 bg-emerald-50 text-emerald-700":"border-muted-foreground/20 text-muted-foreground",children:s.is_active?"Enabled":"Disabled"})]}),e.jsxs("div",{className:"text-xs text-muted-foreground truncate",children:[s.url," · secret ",s.secret_set?"set":"not set"]})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsx(_,{checked:s.is_active,onCheckedChange:()=>De(s),"aria-label":`Enable ${s.name}`,title:"Enabled sites can sign visitors in with an SSO ticket. This is the admin switch, not a reachability check."}),e.jsx(b,{variant:"outline",size:"sm",onClick:()=>Le(s),title:"Edit this community site",children:e.jsx(Ze,{className:"h-4 w-4"})}),e.jsx(b,{variant:"outline",size:"sm",className:"text-destructive hover:text-destructive hover:bg-destructive/10",onClick:()=>G(s),title:"Remove this community site",children:e.jsx(cs,{className:"h-4 w-4"})})]})]},s.id))}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground py-6",children:[e.jsx(O,{className:"h-4 w-4 animate-spin"})," Loading community sites…"]})]})]})}),e.jsx(P,{value:"agents",className:"space-y-4",children:e.jsx(gs,{publicBaseUrl:t.public_base_url,openMode:v==="open"})})]}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground py-10",children:[e.jsx(O,{className:"h-4 w-4 animate-spin"})," Loading settings…"]}),e.jsx(_e,{open:!!j,onOpenChange:s=>!s&&L(null),children:e.jsxs(be,{children:[e.jsxs(je,{children:[e.jsx(ke,{children:(j==null?void 0:j.mode)==="edit"?"Edit community site":"Add community site"}),e.jsx(we,{children:"The secret is write-only — leave it blank when editing to keep the current one."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx(q,{htmlFor:"site-name",children:"Name"}),e.jsx(E,{id:"site-name",value:k.name,onChange:s=>A(a=>({...a,name:s.target.value})),placeholder:"Main community site"})]}),e.jsxs("div",{children:[e.jsx(q,{htmlFor:"site-url",children:"Site URL"}),e.jsx(E,{id:"site-url",value:k.url,onChange:s=>A(a=>({...a,url:s.target.value})),placeholder:"https://community.example.com"})]}),e.jsxs("div",{children:[e.jsx(q,{htmlFor:"site-secret",children:"Secret key"}),e.jsx(E,{id:"site-secret",type:"password",value:k.secret,onChange:s=>A(a=>({...a,secret:s.target.value})),placeholder:(j==null?void 0:j.mode)==="edit"?"Leave blank to keep the current secret":"Shared secret (16+ characters)",...V("password")})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(q,{htmlFor:"site-active",children:"Auto-login enabled"}),e.jsx(_,{id:"site-active",checked:k.is_active,onCheckedChange:s=>A(a=>({...a,is_active:s}))})]}),de&&e.jsx("div",{role:"alert",className:"text-sm text-destructive",children:de})]}),e.jsxs(Ne,{children:[e.jsx(b,{variant:"outline",onClick:()=>L(null),children:"Cancel"}),e.jsxs(b,{onClick:$e,disabled:le,children:[le&&e.jsx(O,{className:"h-4 w-4 mr-1.5 animate-spin"}),(j==null?void 0:j.mode)==="edit"?"Save changes":"Add site"]})]})]})}),e.jsx(_e,{open:!!T,onOpenChange:s=>!s&&G(null),children:e.jsxs(be,{children:[e.jsxs(je,{children:[e.jsxs(ke,{children:["Remove ",T==null?void 0:T.name,"?"]}),e.jsx(we,{children:"Visitors arriving from this site will no longer be auto-signed-in. This can't be undone from here — you'll need to re-add the site and its secret to restore it."})]}),e.jsxs(Ne,{children:[e.jsx(b,{variant:"outline",onClick:()=>G(null),children:"Cancel"}),e.jsxs(b,{variant:"destructive",onClick:Re,disabled:he,children:[he&&e.jsx(O,{className:"h-4 w-4 mr-1.5 animate-spin"}),"Remove"]})]})]})})]})}function Cs(){const{isAdmin:n,refreshHealth:i}=Te(),t=Oe(),[d,f]=l.useState(null);l.useEffect(()=>{n&&He().then(f).catch(()=>{})},[n]);const c=l.useCallback(async y=>{try{const v=await qe(y);f(v.settings),await i(),await t.invalidateQueries({queryKey:ne.health().queryKey}),R.success("Settings saved")}catch(v){throw v}},[i,t]);return e.jsx(_s,{settings:d,onUpdate:c})}export{Cs as default};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as Ee,Q as Ie,r as a,u as Le,j as e,U as he,B as r,A as $,N as H,a as q,b_ as xe,b$ as ue,c1 as pe,c0 as je,c2 as ge,L as v,I as Ne,cK as ve,cL as fe,e as B,bE as we,cZ as _e,dK as Re,C as V,az as be,aE as Ce,D as R,z as D,G as P,H as z,J as F,K as O,dL as De,dM as Pe,dN as ze,l as Z,cX as Fe,M as ke,dO as Oe,Y as Ge,dP as Me}from"./index-WYDmEOfO.js";import{P as Ue}from"./page-title-DVq4qvMR.js";import{U as ye}from"./user-plus-Ckm_Isyc.js";/**
|
|
2
|
+
* @license lucide-react v0.577.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:"m2 2 20 20",key:"1ooewy"}],["path",{d:"M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71",key:"1jlk70"}],["path",{d:"M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264",key:"18rp1v"}]],Qe=Ee("shield-off",Ke);function We(){var de,me;const{adminStatus:h}=Ie(),l=((me=(de=h==null?void 0:h.me)==null?void 0:de.email)==null?void 0:me.toLowerCase())??null,[g,c]=a.useState([]),i=Le(),[x,d]=a.useState(""),[u,f]=a.useState("all"),[w,m]=a.useState([]),[j,A]=a.useState(!0),[E,y]=a.useState(null),[J,t]=a.useState(!1),[N,b]=a.useState(""),[I,ee]=a.useState(null),[p,L]=a.useState(null),[Se,W]=a.useState(!1);a.useEffect(()=>W(!1),[p==null?void 0:p.password]);const[C,G]=a.useState(null),[M,se]=a.useState(!1),[k,U]=a.useState(null),[K,ae]=a.useState(!1),[te,re]=a.useState(null),[S,Q]=a.useState(null),[Y,ne]=a.useState(!1),[ie,le]=a.useState(null),[ce,Te]=a.useState({}),T=async()=>{A(!0);try{const[s,o]=await Promise.all([i.fetchQuery(Z.teammates()),i.fetchQuery(Z.superAdmins())]);c(s.teammates),m(s.pending_stewards||[]),Te(Object.fromEntries(o.super_admins.map(n=>[n.email.toLowerCase(),{source:n.source,self:n.self}]))),y(null)}catch(s){y(s.message)}finally{A(!1)}};a.useEffect(()=>{T()},[]);const X=x.trim().toLowerCase(),oe=g.filter(s=>u==="admin"&&!s.is_admin||u==="normal"&&s.is_admin?!1:X?s.email.toLowerCase().includes(X)||(s.name||"").toLowerCase().includes(X):!0),Ae=s=>{const o=Fe(s);if(!o)return"Never";const n=Date.now()-o.getTime();return n<6e4?"Just now":n<36e5?`${Math.floor(n/6e4)}m ago`:n<864e5?`${Math.floor(n/36e5)}h ago`:n<6048e5?`${Math.floor(n/864e5)}d ago`:o.toLocaleDateString()};return e.jsxs("div",{children:[e.jsx(Ue,{icon:he,title:"Teammates",description:"Add teammates and manage their access",actions:e.jsxs(r,{onClick:()=>t(!0),children:[e.jsx(ye,{className:"h-4 w-4 mr-2"}),"Invite Teammate"]})}),E&&e.jsxs($,{variant:"destructive",className:"mb-4",children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx(q,{children:E})]}),e.jsxs(xe,{children:[e.jsxs(ue,{children:[e.jsxs(pe,{className:"text-lg flex items-center gap-2",children:[e.jsx(he,{className:"h-4 w-4"}),"All Users"]}),e.jsx(je,{children:"Everyone who has access to this community server"})]}),e.jsx(ge,{children:j?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(v,{className:"h-5 w-5 animate-spin text-muted-foreground"})}):g.length===0?e.jsx("div",{className:"text-center py-8 text-sm text-muted-foreground",children:'No teammates yet. Click "Invite Teammate" to add one.'}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-3",children:[e.jsx(Ne,{value:x,onChange:s=>d(s.target.value),placeholder:"Search by name or email…",className:"h-8 max-w-xs text-sm"}),e.jsx("div",{className:"flex items-center rounded-md border p-0.5 text-xs",children:[["all","All"],["admin","Superadmins"],["normal","Members"]].map(([s,o])=>e.jsx("button",{type:"button",onClick:()=>f(s),className:`px-2.5 py-1 rounded ${u===s?"bg-primary text-primary-foreground":"text-muted-foreground hover:text-foreground"}`,children:o},s))})]}),oe.length===0?e.jsx("div",{className:"text-center py-8 text-sm text-muted-foreground",children:"No users match your filters."}):e.jsx("div",{className:"space-y-2",children:oe.map(s=>{var o,n;return e.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-lg border",children:[e.jsx(ve,{className:"h-9 w-9",children:e.jsx(fe,{children:(s.email[0]||"?").toUpperCase()})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium truncate",children:s.name||s.email}),l&&s.email.toLowerCase()===l&&e.jsx(B,{variant:"outline",className:"border-emerald-200 bg-emerald-50 text-emerald-700",children:"You"}),s.is_admin&&e.jsxs(B,{variant:"outline",className:"gap-1 border-blue-200 bg-blue-50 text-blue-700",children:[e.jsx(we,{className:"h-3 w-3"}),"Admin"]}),!!s.is_invited&&e.jsx(B,{variant:"outline",className:"border-amber-200 bg-amber-50 text-amber-700",title:"Added with a temporary password. They can sign in with their email + that password (use Reset password to re-issue one), then change it.",children:"Invited"})]}),e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center gap-3",children:[e.jsx("span",{children:s.email}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:[s.key_count," key",s.key_count!==1?"s":""]}),s.last_active&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsxs("span",{children:["last active ",Ae(s.last_active)]})]})]})]}),s.is_admin&&((o=ce[s.email.toLowerCase()])==null?void 0:o.source)==="granted"&&!((n=ce[s.email.toLowerCase()])!=null&&n.self)&&e.jsxs(r,{variant:"outline",size:"sm",className:"text-destructive hover:text-destructive hover:bg-destructive/10",onClick:()=>Q(s),title:"Revoke this user's superadmin access",children:[e.jsx(Qe,{className:"h-4 w-4 mr-2"}),"Revoke superadmin"]}),!s.is_admin&&e.jsxs(e.Fragment,{children:[!s.is_invited&&e.jsxs(r,{variant:"outline",size:"sm",onClick:()=>U(s),title:"Grant this user superadmin access",children:[e.jsx(_e,{className:"h-4 w-4 mr-2"}),"Grant superadmin"]}),e.jsx(r,{variant:"outline",size:"sm",disabled:!!p,onClick:async()=>{L({email:s.email,password:null});try{const _=await Re(s.id);L({email:s.email,password:_.temporary_password||""}),await T()}catch(_){L(null),y(_.message)}},title:"Generate a temporary password to share with this user (no email is sent)",children:"Reset password"}),e.jsx(r,{variant:"outline",size:"sm",className:"text-destructive hover:text-destructive hover:bg-destructive/10",onClick:()=>G(s),title:"Remove this user and revoke all access",children:"Remove"})]})]},s.id)})})]})})]}),w.length>0&&e.jsxs(xe,{className:"mt-4 border-amber-200 bg-amber-50/40",children:[e.jsxs(ue,{children:[e.jsxs(pe,{className:"text-lg flex items-center gap-2",children:[e.jsx(we,{className:"h-4 w-4 text-amber-700"}),"Stewards without server access"]}),e.jsx(je,{children:"These emails are assigned as stewards on one or more nests, but haven't registered to this server yet — they can't log in or approve anything until they claim an account."})]}),e.jsx(ge,{children:e.jsx("div",{className:"space-y-2",children:w.map(s=>e.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-lg border bg-background",children:[e.jsx(ve,{className:"h-9 w-9",children:e.jsx(fe,{className:"bg-amber-100 text-amber-800",children:(s[0]||"?").toUpperCase()})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"font-medium text-sm truncate",children:s}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Assigned as steward · not registered yet"})]}),e.jsxs(r,{size:"sm",onClick:()=>{b(s),t(!0)},children:[e.jsx(ye,{className:"h-3.5 w-3.5 mr-1"}),"Invite"]})]},s))})})]}),J&&e.jsx(Ye,{seedEmail:N,onClose:()=>{t(!1),b("")},onCreated:(s,o,n,_)=>{t(!1),b(""),ee({email:s,password:o,promptowl:n,emailed:_}),T()}}),I&&e.jsx($e,{email:I.email,password:I.password,promptowl:I.promptowl,emailed:I.emailed,onClose:()=>ee(null)}),p&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",onClick:()=>L(null),children:e.jsxs("div",{className:"w-full max-w-sm rounded-lg border bg-background p-5 shadow-lg",onClick:s=>s.stopPropagation(),children:[e.jsx("h3",{className:"font-semibold mb-1",children:"Temporary password"}),p.password===null?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-8 text-center",children:[e.jsx(v,{className:"h-6 w-6 animate-spin text-muted-foreground"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Generating a temporary password for",e.jsx("br",{}),e.jsx("strong",{className:"text-foreground",children:p.email})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-xs text-muted-foreground mb-3",children:["Share this with ",e.jsx("strong",{children:p.email})," directly — no email is sent. They sign in with it, then change it from their account. It won't be shown again. Their existing API keys keep working; revoke a key separately if it may be compromised."]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"flex-1 bg-muted border rounded px-2 py-1.5 text-sm font-mono break-all",children:p.password}),e.jsx(r,{variant:"outline",size:"sm",onClick:async()=>{await Ce(p.password,"Temporary password copied")&&(W(!0),setTimeout(()=>W(!1),1500))},children:Se?e.jsxs(e.Fragment,{children:[e.jsx(V,{className:"h-3.5 w-3.5 mr-1 text-green-600"}),"Copied"]}):e.jsxs(e.Fragment,{children:[e.jsx(be,{className:"h-3.5 w-3.5 mr-1"}),"Copy"]})})]}),e.jsx("div",{className:"mt-4 text-right",children:e.jsx(r,{variant:"outline",size:"sm",onClick:()=>L(null),children:"Done"})})]})]})}),e.jsx(R,{open:!!C,onOpenChange:s=>!s&&!M&&G(null),children:e.jsxs(D,{className:"sm:max-w-[420px]",children:[e.jsxs(P,{children:[e.jsxs(z,{children:["Remove ",C==null?void 0:C.email,"?"]}),e.jsx(F,{children:"This revokes all their access (API keys, sessions, steward + collaborator roles) and deletes the account. This cannot be undone."})]}),e.jsxs(O,{children:[e.jsx(r,{variant:"outline",onClick:()=>G(null),disabled:M,children:"Cancel"}),e.jsx(r,{variant:"destructive",disabled:M,onClick:async()=>{if(C){se(!0);try{await De(C.id),G(null),await T()}catch(s){y(s.message)}finally{se(!1)}}},children:M?e.jsx(v,{className:"h-4 w-4 animate-spin"}):"Remove"})]})]})}),e.jsx(R,{open:!!k,onOpenChange:s=>!s&&!K&&U(null),children:e.jsxs(D,{className:"sm:max-w-[420px]",children:[e.jsxs(P,{children:[e.jsxs(z,{children:["Grant superadmin to ",k==null?void 0:k.email,"?"]}),e.jsx(F,{children:"They immediately get server-admin access everywhere: every nest, teammate management, and the activity trace. You can revoke this later from this list."})]}),te&&e.jsxs($,{variant:"destructive",children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx(q,{children:te})]}),e.jsxs(O,{children:[e.jsx(r,{variant:"outline",onClick:()=>U(null),disabled:K,children:"Cancel"}),e.jsx(r,{disabled:K,onClick:async()=>{if(k){ae(!0),re(null);try{await Pe(k.email),U(null),await T()}catch(s){re(s.message)}finally{ae(!1)}}},children:K?e.jsx(v,{className:"h-4 w-4 animate-spin"}):"Grant"})]})]})}),e.jsx(R,{open:!!S,onOpenChange:s=>!s&&!Y&&Q(null),children:e.jsxs(D,{className:"sm:max-w-[420px]",children:[e.jsxs(P,{children:[e.jsxs(z,{children:["Revoke superadmin from ",S==null?void 0:S.email,"?"]}),e.jsx(F,{children:"They immediately lose server-admin access. They keep their account and any nest/collaborator roles granted separately. You can grant superadmin again later."})]}),ie&&e.jsxs($,{variant:"destructive",children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx(q,{children:ie})]}),e.jsxs(O,{children:[e.jsx(r,{variant:"outline",onClick:()=>Q(null),disabled:Y,children:"Cancel"}),e.jsx(r,{variant:"destructive",disabled:Y,onClick:async()=>{if(S){ne(!0),le(null);try{await ze(S.email),Q(null),await T()}catch(s){le(s.message)}finally{ne(!1)}}},children:Y?e.jsx(v,{className:"h-4 w-4 animate-spin"}):"Revoke"})]})]})})]})}function Ye({seedEmail:h,onClose:l,onCreated:g}){const[c,i]=a.useState(h||""),[x,d]=a.useState(!1),[u,f]=a.useState(null),w=async m=>{if(m.preventDefault(),!!c.trim()){d(!0),f(null);try{const j=await Oe(c);g(c,j.temporary_password,!!j.promptowl_sign_in,!!j.emailed)}catch(j){f(j.message),d(!1)}}};return e.jsx(R,{open:!0,onOpenChange:l,children:e.jsxs(D,{className:"sm:max-w-[420px]",children:[e.jsxs(P,{children:[e.jsx(z,{children:"Add Teammate"}),e.jsx(F,{children:"Create a login for a teammate. They get a temporary password to sign in with, then can change it and create their own API key."})]}),e.jsxs("form",{onSubmit:w,className:"space-y-3",children:[u&&e.jsxs($,{variant:"destructive",children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx(q,{children:u})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(ke,{children:"Email"}),e.jsx(Ne,{type:"email",placeholder:"jane@acme.com",value:c,onChange:m=>i(m.target.value),required:!0,autoFocus:!0})]}),e.jsxs(O,{children:[e.jsx(r,{variant:"outline",type:"button",onClick:l,children:"Cancel"}),e.jsx(r,{type:"submit",disabled:x||!c.trim(),children:x?e.jsx(v,{className:"h-4 w-4 animate-spin"}):"Add teammate"})]})]})]})})}function $e({email:h,password:l,promptowl:g,emailed:c,onClose:i}){const[x,d]=a.useState(!1),u=async()=>{await Ce(l)&&(d(!0),setTimeout(()=>d(!1),1500))};return e.jsx(R,{open:!0,onOpenChange:i,children:e.jsxs(D,{className:"sm:max-w-[520px]",children:[e.jsxs(P,{children:[e.jsxs(z,{children:["Teammate added: ",h]}),e.jsxs(F,{children:[c?"We've emailed them this temporary password and a sign-in link. ":"Send them this temporary password via Slack, email, or another secure channel. ",e.jsx("strong",{children:"It won't be shown again."})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(ke,{className:"text-xs text-muted-foreground",children:"Temporary password"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"min-w-0 flex-1 bg-muted px-3 py-2 rounded text-xs font-mono break-all",children:l}),e.jsx(r,{size:"sm",variant:"outline",onClick:u,children:x?e.jsx(V,{className:"h-3.5 w-3.5 text-green-600"}):e.jsx(be,{className:"h-3.5 w-3.5"})})]}),e.jsx("p",{className:"text-xs text-muted-foreground pt-2",children:"They sign in at this server with their email + this password, then can change it under their account and create their own API key for Hootie, Claude Desktop, or the CLI."}),g&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Or they can choose ",e.jsx("strong",{children:"Sign in with PromptOwl"}),", using a PromptOwl account under this same email."]})]}),e.jsx(He,{email:h}),e.jsx(O,{children:e.jsx(r,{onClick:i,children:"Done"})})]})})}function He({email:h}){const{data:l,isLoading:g}=Ge(Z.nestList()),c=((l==null?void 0:l.nests)??[]).filter(t=>["owner","admin","write"].includes(t.permission??"owner")),[i,x]=a.useState(""),[d,u]=a.useState("read"),[f,w]=a.useState(!1),[m,j]=a.useState([]),A=c.filter(t=>!m.some(N=>N.id===t.id)),[E,y]=a.useState(null),J=async()=>{var t;w(!0),y(null);try{await Me(i,{email:h,permission:d});const N=((t=c.find(b=>b.id===i))==null?void 0:t.name)??i;j(b=>[...b,{id:i,name:N,permission:d}]),x("")}catch(N){y(N.message)}finally{w(!1)}};return e.jsxs("div",{className:"rounded-md border border-amber-200 bg-amber-50/60 p-3 space-y-2",children:[m.length>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:"Shared with them"}),e.jsx("ul",{className:"space-y-1",children:m.map(t=>e.jsxs("li",{className:"flex items-center gap-2 text-sm",children:[e.jsx(V,{className:"h-3.5 w-3.5 text-green-600 shrink-0"}),e.jsx("span",{className:"truncate",children:t.name}),e.jsx(B,{variant:"outline",className:"ml-auto shrink-0",children:t.permission==="write"?"Can edit":"Can view"})]},t.id))})]}),e.jsx("p",{className:"text-sm font-medium",children:m.length?"Share another nest?":"This person has no nests yet. Share one?"}),g?e.jsx(v,{className:"h-4 w-4 animate-spin text-muted-foreground"}):A.length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:m.length?"Every nest you can share is shared with them.":"You don't have a nest you can share yet."}):e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("select",{"aria-label":"Nest to share",value:i,onChange:t=>x(t.target.value),className:"h-8 flex-1 min-w-[10rem] rounded-md border bg-background px-2 text-sm",children:[e.jsx("option",{value:"",children:"Pick a nest…"}),A.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]}),e.jsxs("select",{"aria-label":"Access level",value:d,onChange:t=>u(t.target.value),className:"h-8 rounded-md border bg-background px-2 text-sm",children:[e.jsx("option",{value:"read",children:"Can view"}),e.jsx("option",{value:"write",children:"Can edit"})]}),e.jsxs(r,{size:"sm",disabled:!i||f,onClick:J,children:[f&&e.jsx(v,{className:"h-3.5 w-3.5 mr-1 animate-spin"}),"Share"]})]}),E&&e.jsx("p",{className:"text-xs text-destructive",children:E})]})}export{We as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e,r as o,dQ as Be,dR as ze,dS as Ge,dt as ue,dT as Ue,dU as Ye,dw as k,dV as xe,dW as he,dX as Xe,dB as qe,dY as Ke,dZ as Qe,d_ as We,d$ as Ze,w as Je,u as pe,l as fe,e0 as oe,A as L,N as Z,a as I,L as A,B as C,R as je,b_ as B,c2 as z,e1 as es,D as G,z as U,G as Y,H as X,h as ss,K as q,C as ge,b$ as ve,e as M,cn as ts,af as ns,e2 as as,i as E,Q as rs,e3 as os,U as ls,a_ as is,S as cs,V as ds,W as le,X as ie,e4 as ms,aq as us,I as we,ah as ye,ai as Ne,aj as Ce,ak as be,e5 as se,al as Te,e6 as xs,e7 as Pe,bB as hs,e8 as ps,e9 as fs,ea as js}from"./index-WYDmEOfO.js";import{P as gs}from"./page-title-DVq4qvMR.js";import{P as vs}from"./PersonCombobox-BKI7dff4.js";import{T as Ee}from"./trash-2-B0HyPTnI.js";import{C as Se}from"./circle-check-Bw_aTXiH.js";import{C as Re}from"./circle-x-DkIG68H7.js";import{X as ws}from"./x-mNtADYHc.js";import{U as ys}from"./user-plus-Ckm_Isyc.js";var Ns=Symbol("radix.slottable");function Cs(s){const n=({children:t})=>e.jsx(e.Fragment,{children:t});return n.displayName=`${s}.Slottable`,n.__radixId=Ns,n}var[K]=qe("Tooltip",[xe]),Q=xe(),ke="TooltipProvider",bs=700,J="tooltip.open",[Ts,te]=K(ke),Oe=s=>{const{__scopeTooltip:n,delayDuration:t=bs,skipDelayDuration:r=300,disableHoverableContent:a=!1,children:m}=s,u=o.useRef(!0),p=o.useRef(!1),d=o.useRef(0);return o.useEffect(()=>{const f=d.current;return()=>window.clearTimeout(f)},[]),e.jsx(Ts,{scope:n,isOpenDelayedRef:u,delayDuration:t,onOpen:o.useCallback(()=>{window.clearTimeout(d.current),u.current=!1},[]),onClose:o.useCallback(()=>{window.clearTimeout(d.current),d.current=window.setTimeout(()=>u.current=!0,r)},[r]),isPointerInTransitRef:p,onPointerInTransitChange:o.useCallback(f=>{p.current=f},[]),disableHoverableContent:a,children:m})};Oe.displayName=ke;var H="Tooltip",[Ps,F]=K(H),_e=s=>{const{__scopeTooltip:n,children:t,open:r,defaultOpen:a,onOpenChange:m,disableHoverableContent:u,delayDuration:p}=s,d=te(H,s.__scopeTooltip),f=Q(n),[l,h]=o.useState(null),i=Be(),c=o.useRef(0),j=u??d.disableHoverableContent,g=p??d.delayDuration,v=o.useRef(!1),[w,y]=ze({prop:r,defaultProp:a??!1,onChange:b=>{b?(d.onOpen(),document.dispatchEvent(new CustomEvent(J))):d.onClose(),m==null||m(b)},caller:H}),T=o.useMemo(()=>w?v.current?"delayed-open":"instant-open":"closed",[w]),P=o.useCallback(()=>{window.clearTimeout(c.current),c.current=0,v.current=!1,y(!0)},[y]),x=o.useCallback(()=>{window.clearTimeout(c.current),c.current=0,y(!1)},[y]),S=o.useCallback(()=>{window.clearTimeout(c.current),c.current=window.setTimeout(()=>{v.current=!0,y(!0),c.current=0},g)},[g,y]);return o.useEffect(()=>()=>{c.current&&(window.clearTimeout(c.current),c.current=0)},[]),e.jsx(Ge,{...f,children:e.jsx(Ps,{scope:n,contentId:i,open:w,stateAttribute:T,trigger:l,onTriggerChange:h,onTriggerEnter:o.useCallback(()=>{d.isOpenDelayedRef.current?S():P()},[d.isOpenDelayedRef,S,P]),onTriggerLeave:o.useCallback(()=>{j?x():(window.clearTimeout(c.current),c.current=0)},[x,j]),onOpen:P,onClose:x,disableHoverableContent:j,children:t})})};_e.displayName=H;var ee="TooltipTrigger",Ae=o.forwardRef((s,n)=>{const{__scopeTooltip:t,...r}=s,a=F(ee,t),m=te(ee,t),u=Q(t),p=o.useRef(null),d=ue(n,p,a.onTriggerChange),f=o.useRef(!1),l=o.useRef(!1),h=o.useCallback(()=>f.current=!1,[]);return o.useEffect(()=>()=>document.removeEventListener("pointerup",h),[h]),e.jsx(Ue,{asChild:!0,...u,children:e.jsx(Ye.button,{"aria-describedby":a.open?a.contentId:void 0,"data-state":a.stateAttribute,...r,ref:d,onPointerMove:k(s.onPointerMove,i=>{i.pointerType!=="touch"&&!l.current&&!m.isPointerInTransitRef.current&&(a.onTriggerEnter(),l.current=!0)}),onPointerLeave:k(s.onPointerLeave,()=>{a.onTriggerLeave(),l.current=!1}),onPointerDown:k(s.onPointerDown,()=>{a.open&&a.onClose(),f.current=!0,document.addEventListener("pointerup",h,{once:!0})}),onFocus:k(s.onFocus,()=>{f.current||a.onOpen()}),onBlur:k(s.onBlur,a.onClose),onClick:k(s.onClick,a.onClose)})})});Ae.displayName=ee;var ne="TooltipPortal",[Es,Ss]=K(ne,{forceMount:void 0}),De=s=>{const{__scopeTooltip:n,forceMount:t,children:r,container:a}=s,m=F(ne,n);return e.jsx(Es,{scope:n,forceMount:t,children:e.jsx(he,{present:t||m.open,children:e.jsx(Xe,{asChild:!0,container:a,children:r})})})};De.displayName=ne;var D="TooltipContent",Le=o.forwardRef((s,n)=>{const t=Ss(D,s.__scopeTooltip),{forceMount:r=t.forceMount,side:a="top",...m}=s,u=F(D,s.__scopeTooltip);return e.jsx(he,{present:r||u.open,children:u.disableHoverableContent?e.jsx(Ie,{side:a,...m,ref:n}):e.jsx(Rs,{side:a,...m,ref:n})})}),Rs=o.forwardRef((s,n)=>{const t=F(D,s.__scopeTooltip),r=te(D,s.__scopeTooltip),a=o.useRef(null),m=ue(n,a),[u,p]=o.useState(null),{trigger:d,onClose:f}=t,l=a.current,{onPointerInTransitChange:h}=r,i=o.useCallback(()=>{p(null),h(!1)},[h]),c=o.useCallback((j,g)=>{const v=j.currentTarget,w={x:j.clientX,y:j.clientY},y=Ds(w,v.getBoundingClientRect()),T=Ls(w,y),P=Is(g.getBoundingClientRect()),x=Hs([...T,...P]);p(x),h(!0)},[h]);return o.useEffect(()=>()=>i(),[i]),o.useEffect(()=>{if(d&&l){const j=v=>c(v,l),g=v=>c(v,d);return d.addEventListener("pointerleave",j),l.addEventListener("pointerleave",g),()=>{d.removeEventListener("pointerleave",j),l.removeEventListener("pointerleave",g)}}},[d,l,c,i]),o.useEffect(()=>{if(u){const j=g=>{const v=g.target,w={x:g.clientX,y:g.clientY},y=(d==null?void 0:d.contains(v))||(l==null?void 0:l.contains(v)),T=!Ms(w,u);y?i():T&&(i(),f())};return document.addEventListener("pointermove",j),()=>document.removeEventListener("pointermove",j)}},[d,l,u,f,i]),e.jsx(Ie,{...s,ref:m})}),[ks,Os]=K(H,{isInside:!1}),_s=Cs("TooltipContent"),Ie=o.forwardRef((s,n)=>{const{__scopeTooltip:t,children:r,"aria-label":a,onEscapeKeyDown:m,onPointerDownOutside:u,...p}=s,d=F(D,t),f=Q(t),{onClose:l}=d;return o.useEffect(()=>(document.addEventListener(J,l),()=>document.removeEventListener(J,l)),[l]),o.useEffect(()=>{if(d.trigger){const h=i=>{const c=i.target;c!=null&&c.contains(d.trigger)&&l()};return window.addEventListener("scroll",h,{capture:!0}),()=>window.removeEventListener("scroll",h,{capture:!0})}},[d.trigger,l]),e.jsx(Ke,{asChild:!0,disableOutsidePointerEvents:!1,onEscapeKeyDown:m,onPointerDownOutside:u,onFocusOutside:h=>h.preventDefault(),onDismiss:l,children:e.jsxs(Qe,{"data-state":d.stateAttribute,...f,...p,ref:n,style:{...p.style,"--radix-tooltip-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-tooltip-content-available-width":"var(--radix-popper-available-width)","--radix-tooltip-content-available-height":"var(--radix-popper-available-height)","--radix-tooltip-trigger-width":"var(--radix-popper-anchor-width)","--radix-tooltip-trigger-height":"var(--radix-popper-anchor-height)"},children:[e.jsx(_s,{children:r}),e.jsx(ks,{scope:t,isInside:!0,children:e.jsx(We,{id:d.contentId,role:"tooltip",children:a||r})})]})})});Le.displayName=D;var Me="TooltipArrow",As=o.forwardRef((s,n)=>{const{__scopeTooltip:t,...r}=s,a=Q(t);return Os(Me,t).isInside?null:e.jsx(Ze,{...a,...r,ref:n})});As.displayName=Me;function Ds(s,n){const t=Math.abs(n.top-s.y),r=Math.abs(n.bottom-s.y),a=Math.abs(n.right-s.x),m=Math.abs(n.left-s.x);switch(Math.min(t,r,a,m)){case m:return"left";case a:return"right";case t:return"top";case r:return"bottom";default:throw new Error("unreachable")}}function Ls(s,n,t=5){const r=[];switch(n){case"top":r.push({x:s.x-t,y:s.y+t},{x:s.x+t,y:s.y+t});break;case"bottom":r.push({x:s.x-t,y:s.y-t},{x:s.x+t,y:s.y-t});break;case"left":r.push({x:s.x+t,y:s.y-t},{x:s.x+t,y:s.y+t});break;case"right":r.push({x:s.x-t,y:s.y-t},{x:s.x-t,y:s.y+t});break}return r}function Is(s){const{top:n,right:t,bottom:r,left:a}=s;return[{x:a,y:n},{x:t,y:n},{x:t,y:r},{x:a,y:r}]}function Ms(s,n){const{x:t,y:r}=s;let a=!1;for(let m=0,u=n.length-1;m<n.length;u=m++){const p=n[m],d=n[u],f=p.x,l=p.y,h=d.x,i=d.y;l>r!=i>r&&t<(h-f)*(r-l)/(i-l)+f&&(a=!a)}return a}function Hs(s){const n=s.slice();return n.sort((t,r)=>t.x<r.x?-1:t.x>r.x?1:t.y<r.y?-1:t.y>r.y?1:0),$s(n)}function $s(s){if(s.length<=1)return s.slice();const n=[];for(let r=0;r<s.length;r++){const a=s[r];for(;n.length>=2;){const m=n[n.length-1],u=n[n.length-2];if((m.x-u.x)*(a.y-u.y)>=(m.y-u.y)*(a.x-u.x))n.pop();else break}n.push(a)}n.pop();const t=[];for(let r=s.length-1;r>=0;r--){const a=s[r];for(;t.length>=2;){const m=t[t.length-1],u=t[t.length-2];if((m.x-u.x)*(a.y-u.y)>=(m.y-u.y)*(a.x-u.x))t.pop();else break}t.push(a)}return t.pop(),n.length===1&&t.length===1&&n[0].x===t[0].x&&n[0].y===t[0].y?n:n.concat(t)}var Fs=Oe,Vs=_e,Bs=Ae,zs=De,He=Le;const Gs=({children:s,delayDuration:n=0})=>e.jsx(Fs,{delayDuration:n,children:s}),O=Vs,_=Bs,R=o.forwardRef(({className:s,sideOffset:n=4,...t},r)=>e.jsx(zs,{children:e.jsx(He,{ref:r,sideOffset:n,className:Je("z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",s),...t})}));R.displayName=He.displayName;const Us={Owner:"Admin",Editor:"Editor",Viewer:"Viewer",User:"Viewer"},ce=s=>Us[s]??"Viewer";function Ys({localTeams:s,onImported:n}){const[t,r]=o.useState([]),a=pe(),[m,u]=o.useState(!0),[p,d]=o.useState(null),[f,l]=o.useState(!1),[h,i]=o.useState(null),[c,j]=o.useState(null),[g,v]=o.useState(null),w=new Map(s.filter(x=>x.source==="promptowl"&&x.external_id).map(x=>[x.external_id,x]));o.useEffect(()=>{y()},[]);const y=async()=>{u(!0),d(null);try{const x=await a.fetchQuery(fe.promptowlTeams());r(x.teams)}catch(x){oe(x)?l(!0):d((x==null?void 0:x.message)||"Could not reach PromptOwl")}finally{u(!1)}},T=async x=>{var S;i(x.id),d(null);try{const b=await as([x.id]);v(b.results[0]??null),n(),E.success((S=b.results[0])!=null&&S.created?`Imported ${x.name}`:`Synced ${x.name}`)}catch(b){oe(b)?l(!0):d((b==null?void 0:b.message)||"Sync failed")}finally{i(null),j(null)}},P=x=>{w.has(x.id)?j(x):T(x)};return f?e.jsxs(L,{children:[e.jsx(Z,{className:"h-4 w-4"}),e.jsx(I,{children:"Your PromptOwl session has ended. Sign out and sign back in with PromptOwl to import teams."})]}):m?e.jsx("div",{className:"flex justify-center py-12",children:e.jsx(A,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"space-y-4",children:[p&&e.jsxs(L,{variant:"destructive",children:[e.jsx(Z,{className:"h-4 w-4"}),e.jsx(I,{children:p})]}),e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground flex-1",children:"Your PromptOwl teams. Syncing one copies it here with its members — people without an account are invited automatically. Teams you're view-only on can't be imported, since the copy would be yours to control."}),e.jsx(C,{size:"sm",variant:"ghost",onClick:y,"aria-label":"Refresh",children:e.jsx(je,{className:"h-4 w-4"})})]}),g&&e.jsx(qs,{result:g}),t.length===0?e.jsx(B,{children:e.jsx(z,{className:"py-10 text-center text-sm text-muted-foreground",children:"You're not in any teams in PromptOwl."})}):e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:t.map(x=>e.jsx(Xs,{team:x,imported:w.has(x.id),syncing:h===x.id,canImport:es(x),onSync:()=>P(x)},x.id))}),e.jsx(G,{open:!!c,onOpenChange:x=>!x&&j(null),children:e.jsxs(U,{className:"sm:max-w-[460px]",children:[e.jsx(Y,{children:e.jsxs(X,{children:['Sync "',c==null?void 0:c.name,'" from PromptOwl?']})}),e.jsxs(L,{children:[e.jsx(ss,{className:"h-4 w-4"}),e.jsx(I,{className:"text-xs",children:"PromptOwl is the source of truth. This team's roster here will be made to match PromptOwl exactly: roles are reset, and anyone you added by hand in ContextNest is removed."})]}),e.jsxs(q,{children:[e.jsx(C,{variant:"outline",onClick:()=>j(null),children:"Cancel"}),e.jsxs(C,{disabled:!!h,onClick:()=>c&&T(c),children:[h&&e.jsx(A,{className:"h-4 w-4 mr-1 animate-spin"}),"Sync"]})]})]})})]})}function Xs({team:s,imported:n,syncing:t,canImport:r,onSync:a}){return e.jsxs(B,{className:`flex flex-col${r?"":" opacity-70"}`,children:[e.jsx(ve,{className:"space-y-1 pb-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h3",{className:"font-semibold truncate",children:s.name}),e.jsx(M,{variant:"secondary",className:"shrink-0",children:s.members.length}),n&&e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsxs(M,{variant:"outline",className:"shrink-0 gap-1",children:[e.jsx(ge,{className:"h-3 w-3"}),"Synced"]})}),e.jsx(R,{children:"Already imported. Syncing again updates it in place."})]})]}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:["You're ",s.your_role," in PromptOwl",s.enterprise?` · ${s.enterprise.name}`:""]})]}),r?e.jsxs(C,{size:"sm",variant:n?"outline":"default",className:"shrink-0",disabled:t,onClick:a,children:[t?e.jsx(A,{className:"h-3.5 w-3.5 animate-spin"}):n?e.jsx(je,{className:"h-3.5 w-3.5"}):e.jsx(ts,{className:"h-3.5 w-3.5"}),e.jsx("span",{className:"ml-1",children:n?"Sync":"Import"})]}):e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsxs("span",{className:"shrink-0 inline-flex items-center gap-1 text-xs text-muted-foreground border rounded-md px-2 py-1.5",children:[e.jsx(ns,{className:"h-3 w-3"}),"View-only"]})}),e.jsx(R,{className:"max-w-xs",children:"Importing a team makes you the owner of the copy here, which is more than you can do with this team in PromptOwl. Ask an owner or editor of it to import it."})]})]})}),e.jsx(z,{className:"space-y-1.5",children:s.members.length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:"No members."}):s.members.map(m=>e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:"flex-1 truncate",children:m.email}),e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:ce(m.role)})}),e.jsxs(R,{children:[m.role," in PromptOwl → ",ce(m.role)," here"]})]})]},m.email))})]})}function qs({result:s}){const n=!s.added.length&&!s.updated.length&&!s.removed.length;return e.jsxs(L,{children:[e.jsx(ge,{className:"h-4 w-4"}),e.jsxs(I,{className:"text-xs space-y-0.5",children:[e.jsxs("div",{className:"font-medium",children:[s.name," — ",s.created?"imported":"synced"]}),n?e.jsx("div",{children:"Already up to date."}):e.jsxs(e.Fragment,{children:[s.added.length>0&&e.jsxs("div",{children:["Added: ",s.added.join(", ")]}),s.updated.length>0&&e.jsxs("div",{children:["Role changed: ",s.updated.join(", ")]}),s.removed.length>0&&e.jsxs("div",{children:["Removed: ",s.removed.join(", ")]})]})]})]})}const de=5,W=s=>{var n;return((n=se.find(t=>t.value===s))==null?void 0:n.label)??s},$={viewer:1,editor:2,admin:3},V=4;function me(s,n,t){if(t||s.owner_email&&s.owner_email.toLowerCase()===n)return V;const r=s.members.find(a=>(a.email||"").toLowerCase()===n);return r?$[r.role]??0:0}function lt(){var ae;const{adminStatus:s,isAdmin:n,promptowlTeamsEnabled:t}=rs(),r=(((ae=s==null?void 0:s.me)==null?void 0:ae.email)||"").toLowerCase(),[a]=o.useState(()=>os()),m=t&&a,[u,p]=o.useState([]),[d,f]=o.useState(!0),l=pe(),[h,i]=o.useState(null),[c,j]=o.useState(!1),[g,v]=o.useState(null),[w,y]=o.useState(null),[T,P]=o.useState(!1),x=async()=>{i(null);try{const N=await l.fetchQuery(fe.teamList());p(N.teams),v(re=>re?N.teams.find(Ve=>Ve.id===re.id)??null:null)}catch(N){i((N==null?void 0:N.message)||"Failed to load teams")}finally{f(!1)}};o.useEffect(()=>{x()},[]);const S=async()=>{if(w){P(!0);try{await ms(w.id),E.success("Team deleted"),y(null),await x()}catch(N){E.error((N==null?void 0:N.message)||"Failed to delete team")}finally{P(!1)}}},b=d?e.jsx("div",{className:"flex justify-center py-12",children:e.jsx(A,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):u.length===0?e.jsx(B,{children:e.jsx(z,{className:"py-10 text-center text-sm text-muted-foreground",children:"No teams yet. Create one to share a nest with a whole group at once."})}):e.jsx("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:u.map(N=>e.jsx(Qs,{team:N,rank:me(N,r,n),onEdit:()=>v(N),onDelete:()=>y(N)},N.id))});return e.jsxs(Gs,{delayDuration:150,children:[e.jsxs("div",{className:"w-full mx-auto space-y-4",children:[e.jsx(gs,{icon:ls,title:"Teams",description:e.jsxs(e.Fragment,{children:["A team is a reusable group. Give each member a role, then share the team with a nest from its ",e.jsx("strong",{children:"Share"})," dialog — every member gets their role on that nest."]}),actions:e.jsxs(C,{size:"sm",onClick:()=>j(!0),children:[e.jsx(is,{className:"h-4 w-4 mr-1"}),"New Team"]})}),h&&e.jsxs(L,{variant:"destructive",children:[e.jsx(Z,{className:"h-4 w-4"}),e.jsx(I,{children:h})]}),m?e.jsxs(cs,{defaultValue:"cn",children:[e.jsxs(ds,{children:[e.jsx(le,{value:"cn",children:"ContextNest Teams"}),e.jsx(le,{value:"po",children:"PromptOwl Teams"})]}),e.jsx(ie,{value:"cn",className:"mt-4",children:b}),e.jsx(ie,{value:"po",className:"mt-4",children:e.jsx(Ys,{localTeams:u,onImported:x})})]}):b]}),c&&e.jsx(Ws,{onClose:()=>j(!1),onCreated:x}),g&&e.jsx(Zs,{team:g,rank:me(g,r,n),onClose:()=>v(null),onChanged:x}),e.jsx(G,{open:!!w,onOpenChange:N=>!N&&y(null),children:e.jsxs(U,{className:"sm:max-w-[420px]",children:[e.jsx(Y,{children:e.jsxs(X,{children:['Delete team "',w==null?void 0:w.name,'"?']})}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Members lose access to every nest this team is shared with. This can't be undone."}),e.jsxs(q,{children:[e.jsx(C,{variant:"outline",onClick:()=>y(null),children:"Cancel"}),e.jsxs(C,{variant:"destructive",disabled:T,onClick:S,children:[T&&e.jsx(A,{className:"h-4 w-4 mr-1 animate-spin"}),"Delete"]})]})]})})]})}function $e({registered:s}){return e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsx("span",{className:"shrink-0 flex items-center",children:s?e.jsx(Se,{className:"h-3.5 w-3.5 text-green-600"}):e.jsx(Re,{className:"h-3.5 w-3.5 text-red-500"})})}),e.jsx(R,{children:s?"Registered account":"Invited — hasn't signed up yet"})]})}function Ks({member:s}){return e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx($e,{registered:s.registered}),e.jsx("span",{className:"flex-1 truncate",children:s.email}),e.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:W(s.role)})]})}function Qs({team:s,rank:n,onEdit:t,onDelete:r}){const a=s.members.slice(0,de),m=s.members.slice(de),u=n>=$.editor,p=n>=V;return e.jsxs(B,{className:"flex flex-col",children:[e.jsx(ve,{className:"space-y-1 pb-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h3",{className:"font-semibold truncate",children:s.name}),e.jsx(M,{variant:"secondary",className:"shrink-0",children:s.members.length}),s.source==="promptowl"&&e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsx(M,{variant:"outline",className:"shrink-0",children:"PromptOwl"})}),e.jsx(R,{children:"Imported from PromptOwl. Re-syncing makes this roster match PromptOwl exactly."})]})]}),s.owner_email&&e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:["Created by ",s.owner_email]})]}),e.jsxs("div",{className:"flex items-center gap-0.5 shrink-0",children:[u&&e.jsx(C,{size:"icon",variant:"ghost",className:"h-7 w-7",onClick:t,"aria-label":"Edit team",children:e.jsx(us,{className:"h-3.5 w-3.5"})}),p&&e.jsx(C,{size:"icon",variant:"ghost",className:"h-7 w-7 text-destructive",onClick:r,"aria-label":"Delete team",children:e.jsx(Ee,{className:"h-3.5 w-3.5"})})]})]})}),e.jsx(z,{className:"space-y-1.5",children:s.members.length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:"No members yet."}):e.jsxs(e.Fragment,{children:[a.map(d=>e.jsx(Ks,{member:d},d.userId)),m.length>0&&e.jsxs(O,{children:[e.jsx(_,{asChild:!0,children:e.jsxs("button",{className:"text-xs text-muted-foreground hover:text-foreground text-left",children:["+",m.length," more member",m.length===1?"":"s"]})}),e.jsx(R,{className:"max-w-xs",children:e.jsx("div",{className:"space-y-1",children:m.map(d=>e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[d.registered?e.jsx(Se,{className:"h-3 w-3 text-green-600 shrink-0"}):e.jsx(Re,{className:"h-3 w-3 text-red-500 shrink-0"}),e.jsx("span",{className:"truncate",children:d.email}),e.jsxs("span",{className:"opacity-70",children:["· ",W(d.role)]})]},d.userId))})})]})]})})]})}function Fe({onAdd:s,busy:n,maxRank:t=V,members:r=[]}){var i;const a=se.filter(c=>$[c.value]<=t),[m,u]=o.useState(""),[p,d]=o.useState(((i=a[0])==null?void 0:i.value)??"viewer"),[f,l]=o.useState(null),h=()=>{const c=m.trim();if(c){if(!hs(c)){l("Enter a valid email address.");return}l(null),Promise.resolve(s(c,p)).then(()=>{var j;u(""),d(((j=a[0])==null?void 0:j.value)??"viewer")})}};return e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row items-stretch sm:items-center gap-2",children:[e.jsx(vs,{value:m,onChange:c=>{u(c),f&&l(null)},onSubmit:h,placeholder:"person@company.com",exclude:r,className:"flex-1",testId:"team-member-input"}),e.jsxs(ye,{value:p,onValueChange:c=>d(c),children:[e.jsx(Ne,{className:"w-full sm:w-[130px] h-8",children:e.jsx(Ce,{})}),e.jsx(be,{children:a.map(c=>e.jsx(Te,{value:c.value,children:c.label},c.value))})]}),e.jsxs(C,{size:"sm",onClick:h,disabled:n||!m.trim(),children:[e.jsx(ys,{className:"h-4 w-4 mr-1"}),"Add"]})]}),f&&e.jsx("p",{className:"text-xs text-destructive",children:f})]})}function Ws({onClose:s,onCreated:n}){const[t,r]=o.useState(""),[a,m]=o.useState([]),[u,p]=o.useState(!1),d=(l,h)=>{if(a.some(i=>i.email.toLowerCase()===l.toLowerCase())){E.error("Already added");return}m(i=>[...i,{email:l,role:h}])},f=async()=>{const l=t.trim();if(l){p(!0);try{const{team:h}=await xs(l);for(const i of a)try{await Pe(h.id,{email:i.email,role:i.role})}catch(c){E.error(`${i.email}: ${(c==null?void 0:c.message)||"could not add"}`)}E.success(`Team "${l}" created`),n(),s()}catch(h){E.error((h==null?void 0:h.message)||"Failed to create team")}finally{p(!1)}}};return e.jsx(G,{open:!0,onOpenChange:l=>!l&&s(),children:e.jsxs(U,{className:"sm:max-w-[480px]",children:[e.jsx(Y,{children:e.jsx(X,{children:"New team"})}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(we,{autoFocus:!0,placeholder:"Team name (e.g. Platform)",value:t,onChange:l=>r(l.target.value)}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground",children:"Members (optional)"}),a.length>0&&e.jsx("div",{className:"space-y-1.5",children:a.map(l=>e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:"flex-1 truncate",children:l.email}),e.jsx("span",{className:"text-xs text-muted-foreground",children:W(l.role)}),e.jsx(C,{size:"icon",variant:"ghost",className:"h-6 w-6",onClick:()=>m(h=>h.filter(i=>i.email!==l.email)),"aria-label":`Remove ${l.email}`,children:e.jsx(ws,{className:"h-3.5 w-3.5"})})]},l.email))}),e.jsx(Fe,{onAdd:d,members:a.map(l=>l.email)})]})]}),e.jsxs(q,{children:[e.jsx(C,{variant:"outline",onClick:s,children:"Cancel"}),e.jsxs(C,{onClick:f,disabled:u||!t.trim(),children:[u&&e.jsx(A,{className:"h-4 w-4 mr-1 animate-spin"}),"Create"]})]})]})})}function Zs({team:s,rank:n,onClose:t,onChanged:r}){const a=n>=$.admin,m=n>=$.editor,[u,p]=o.useState(s.name),[d,f]=o.useState(!1),l=async(i,c)=>{f(!0);try{await i(),c&&E.success(c),r()}catch(j){E.error((j==null?void 0:j.message)||"Something went wrong")}finally{f(!1)}},h=async()=>{if(!a)return;const i=u.trim();!i||i===s.name||await l(()=>ps(s.id,i),"Team renamed")};return e.jsx(G,{open:!0,onOpenChange:i=>!i&&t(),children:e.jsxs(U,{className:"sm:max-w-[480px]",children:[e.jsx(Y,{children:e.jsx(X,{children:"Edit team"})}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(we,{value:u,onChange:i=>p(i.target.value),onBlur:h,onKeyDown:i=>i.key==="Enter"&&h(),className:"h-9",disabled:!a})}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground",children:"Members"}),s.members.length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:"No members yet."}):e.jsx("div",{className:"space-y-2",children:s.members.map(i=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx($e,{registered:i.registered}),e.jsx("span",{className:"text-sm flex-1 truncate",children:i.email}),a?e.jsxs(ye,{value:i.role,onValueChange:c=>l(()=>fs(s.id,i.userId,c),"Role updated"),children:[e.jsx(Ne,{className:"w-[120px] h-8",children:e.jsx(Ce,{})}),e.jsx(be,{children:se.map(c=>e.jsx(Te,{value:c.value,children:c.label},c.value))})]}):e.jsx(M,{variant:"secondary",className:"text-[11px]",children:W(i.role)}),a&&e.jsx(C,{size:"icon",variant:"ghost",className:"h-8 w-8",disabled:d,onClick:()=>l(()=>js(s.id,i.userId),"Member removed"),"aria-label":`Remove ${i.email}`,children:e.jsx(Ee,{className:"h-3.5 w-3.5"})})]},i.userId))}),m&&e.jsx("div",{className:"pt-1 border-t",children:e.jsx("div",{className:"pt-2",children:e.jsx(Fe,{busy:d,maxRank:n,members:s.members.map(i=>i.email),onAdd:(i,c)=>l(()=>Pe(s.id,{email:i,role:c}),"Member added")})})})]})]}),e.jsx(q,{children:e.jsx(C,{variant:"outline",onClick:t,children:"Done"})})]})})}export{lt as default};
|