PageSourceSearch

https://slatedata.ai/assets/page-5ZPn3No2.js

js slatedata.ai collected 2026-10-05 15:05:08 UTC 11,159 bytes, 1 lines download raw bytes

1import{r as o,a5 as D,p as ee,K as re,q as se,j as e,E as V,G as f,v as F,a6 as U,A as E,T as z,S as M,D as q,m as ae,g as te,B as H,V as J,o as A,e as ie,x as N}from"./index-CB1LRsvg.js";import{I as ne}from"./IconInfoCircle-CGxJ5qpI.js";import{I as P}from"./IconTrash-B56plgcD.js";import{I as K}from"./IconUsers-D7UWYmlL.js";import{b as le,u as oe}from"./useGroups-BxyqH8s2.js";import{u as ce}from"./usePageTitle-PP7G01cs.js";import{u as de}from"./useConfirm-B_NA31aX.js";import{S as B}from"./StatusText-gwUfW1V-.js";import{u as me}from"./use-form-CaiTdMy3.js";import{B as j}from"./Badge-CvorhVBt.js";import{C as Q}from"./Card-DwzWyE8m.js";import{T as s}from"./Table-D4aHVX52.js";import{A as he}from"./Avatar-BsrwxVRy.js";import"./index-C148XJoK.js";function ue(a){const[v,b]=o.useState(null),[$,y]=o.useState(null),[W,i]=o.useState(!1),[R,l]=o.useState(null),[G,T]=o.useState(""),c=o.useCallback(async()=>{if(!a){b(null);return}i(!0),l(null);try{const t=await fetch(`/v2/workspaces/${a}/members`,{credentials:"include"});if(!t.ok){b([]),l(new Error(`Member fetch error: ${t.status}`));return}const n=await t.json();b(n)}catch(t){l(t),b([])}finally{i(!1)}},[a]),d=o.useCallback(async()=>{if(!a){y(null);return}try{const t=await fetch(`/v2/workspaces/${a}/invites`,{credentials:"include"});y(t.ok?await t.json():[])}catch{y([])}},[a]);o.useEffect(()=>{c(),d()},[c,d]);const m=o.useCallback(async(t,n="viewer")=>{var u;if(!a)return{ok:!1,error:"Missing workspace."};try{i(!0);const x=await fetch(`/v2/workspaces/${a}/members`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t,role:n})});if(!x.ok){const S=await x.json().catch(()=>({})),p=typeof S.detail=="string"?S.detail:"Failed to add member, please try again.";return l(new Error(p)),i(!1),{ok:!1,error:p}}const w=await x.json();return T(""),D(a),await c(),await d(),{ok:!0,status:w.status==="invited"?"invited":"added",email:((u=w.invite)==null?void 0:u.email)??t,emailSent:w.email_sent!==!1}}catch(x){return l(x),i(!1),{ok:!1,error:"Network error, please try again."}}},[a,c,d]),k=o.useCallback(async t=>{if(!a)return!1;try{return i(!0),(await fetch(`/v2/workspaces/${a}/invites/${t}`,{method:"DELETE",credentials:"include"})).ok?(await d(),i(!1),!0):(l(new Error("Failed to revoke invitation, please try again.")),i(!1),!1)}catch(n){return l(n),i(!1),!1}},[a,d]),_=o.useCallback(async t=>{if(!a)return!1;try{return i(!0),(await fetch(`/v2/workspaces/${a}/members/${t}`,{method:"DELETE",credentials:"include"})).ok?(D(a),await c(),!0):(l(new Error("Failed to remove member, please try again.")),i(!1),!1)}catch(n){return l(n),i(!1),!1}},[a,c]),h=o.useCallback(async(t,n)=>{if(!a)return!1;try{return i(!0),(await fetch(`/v2/workspaces/${a}/members/${t}`,{method:"PUT",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({role:n})})).ok?(D(a),await c(),!0):(l(new Error("Failed to update member role, please try again.")),i(!1),!1)}catch(u){return l(u),i(!1),!1}},[a,c]);return{members:v,invites:$,loading:W,error:R,email:G,setEmail:T,addMember:m,removeMember:_,revokeInvite:k,changeMemberRole:h,refresh:c}}const L={owner:{color:"blue",description:"Workspace owner — can manage members and delete the workspace, regardless of team role."},member:{color:"gray",description:"Has access to the workspace. What they can do (read / edit / manage) depends on their team role."}};function X({name:a}){return e.jsxs(f,{gap:"xs",wrap:"nowrap",children:[e.jsx(he,{name:a,size:"sm",radius:"xl"}),e.jsx("span",{children:a})]})}function ze(){ce("Workspace Members");const{workspace:a}=ee(),{user:v}=re(),{members:b,invites:$,loading:y,addMember:W,removeMember:i,revokeInvite:R}=ue(a),{workspaceGroups:l,addGroup:G,removeGroup:T}=le(a),{groups:c}=oe(),{capability:d}=se(a),m=d==="manage",{confirm:k,confirmDialog:_}=de(),h=me({mode:"controlled",initialValues:{email:""}}),t=h.values.email,[n,u]=o.useState(null),x=r=>N.show({title:"Error",message:r,color:"red"}),w=async()=>{if(!t.trim())return;h.clearErrors();const r=await W(t.trim(),"member");if(!r.ok){h.setFieldError("email",r.error);return}h.reset(),r.status==="invited"?N.show(r.emailSent?{title:"Invitation sent",message:`${r.email} will get access as soon as they create their account.`,color:"green"}:{title:"Invitation saved, email not sent",message:`We couldn't send the invitation email, so tell ${r.email}
1 yourself: signing up at SlateData with that address gives them this workspace.`,color:"yellow"}):N.show(r.emailSent?{title:"Member added",message:`We emailed ${r.email} a link to this workspace.`,color:"green"}:{title:"Member added, email not sent",message:`${r.email} has access now, but we couldn't email them about it — send them the workspace link yourself.`,color:"yellow"})},S=async()=>{if(!n)return;await G(n,"member")?u(null):x("Failed to add group.")},p=(b||[]).find(r=>r.role==="owner"),O=(b||[]).filter(r=>r.role!=="owner"),I=$||[],C=(c||[]).filter(r=>!(l||[]).some(g=>g.group_id===r.id));return e.jsxs(V,{children:[_,e.jsxs(f,{gap:"xs",align:"center",mb:"xl",children:[e.jsx(F,{order:2,children:"Members"}),e.jsxs(U,{width:340,position:"bottom-start",withArrow:!0,shadow:"lg",radius:"md",children:[e.jsx(U.Target,{children:e.jsx(E,{variant:"subtle",color:"blue","aria-label":"Role descriptions",children:e.jsx(ne,{size:16,"aria-hidden":!0})})}),e.jsxs(U.Dropdown,{p:"md",children:[e.jsx(z,{size:"sm",fw:700,mb:"sm",children:"Workspace roles"}),e.jsx(M,{gap:"sm",children:Object.entries(L).map(([r,g],Y,Z)=>e.jsxs(V,{children:[e.jsx(f,{gap:"xs",mb:4,children:e.jsx(j,{color:g.color,variant:"filled",size:"sm",children:r.charAt(0).toUpperCase()+r.slice(1)})}),e.jsx(z,{size:"xs",c:"dimmed",children:g.description}),Y<Z.length-1&&e.jsx(q,{mt:"sm"})]},r))}),e.jsxs(z,{size:"xs",c:"dimmed",mt:"md",pt:"sm",style:{borderTop:"1px solid var(--mantine-color-default-border)"},children:["What a member can ",e.jsx("em",{children:"do"})," inside the workspace is determined by their team role (viewer / creator / admin / owner)."]})]})]})]}),e.jsxs(M,{gap:0,children:[e.jsxs(M,{gap:"sm",children:[e.jsxs(f,{gap:"xs",children:[e.jsx(ae,{size:20,"aria-hidden":!0}),e.jsx(F,{order:3,children:"Users"})]}),m&&e.jsx("form",{onSubmit:h.onSubmit(()=>void w()),children:e.jsxs(f,{align:"flex-end",gap:"sm",children:[e.jsx(te,{label:"Add user by email",placeholder:"[email protected]",type:"email",required:!0,...h.getInputProps("email"),flex:1,maw:280}),e.jsx(H,{type:"submit",variant:"default",loading:y,disabled:!t.trim(),children:"Add"})]})}),m&&e.jsx(z,{size:"xs",c:"dimmed",mt:-4,children:"No SlateData account yet? We'll email them an invitation — they get access to this workspace as soon as they sign up."}),e.jsx(Q,{withBorder:!0,p:0,children:e.jsx(s.ScrollContainer,{minWidth:520,children:e.jsxs(s,{"aria-label":"Users",children:[e.jsx(s.Thead,{children:e.jsxs(s.Tr,{children:[e.jsx(s.Th,{w:140,children:"Workspace role"}),e.jsx(s.Th,{children:"User"}),e.jsx(s.Th,{children:"Team role"}),e.jsx(s.Th,{children:e.jsx(J,{children:"Actions"})})]})}),e.jsxs(s.Tbody,{children:[p&&e.jsxs(s.Tr,{children:[e.jsx(s.Td,{children:e.jsx(A,{label:L.owner.description,withArrow:!0,multiline:!0,w:240,children:e.jsx(j,{color:"blue",variant:"filled",tabIndex:0,style:{cursor:"default"},children:"Owner"})})}),e.jsx(s.Td,{children:e.jsx(X,{name:p.username||p.user_id})}),e.jsx(s.Td,{children:e.jsx(j,{size:"sm",variant:"light",color:"blue",styles:{root:{height:"auto"},label:{whiteSpace:"normal",overflow:"visible",overflowWrap:"anywhere"}},children:p.team_role})}),e.jsx(s.Td,{})]}),O.map(r=>{const g=r.user_id===(v==null?void 0:v.id);return e.jsxs(s.Tr,{children:[e.jsx(s.Td,{children:e.jsx(A,{label:L.member.description,withArrow:!0,multiline:!0,w:240,children:e.jsx(j,{color:"blue",variant:"light",tabIndex:0,style:{cursor:"default"},children:"Member"})})}),e.jsx(s.Td,{children:e.jsx(X,{name:r.username||r.user_id})}),e.jsx(s.Td,{children:e.jsx(j,{size:"sm",variant:"light",color:"blue",styles:{root:{height:"auto"},label:{whiteSpace:"normal",overflow:"visible",overflowWrap:"anywhere"}},children:r.team_role})}),e.jsx(s.Td,{align:"right",children:m&&!g&&e.jsx(E,{"aria-label":`Remove ${r.username}`,color:"red",variant:"subtle",size:"sm",onClick:async()=>{await k({title:"Remove member",message:`Remove ${r.username} from this workspace?`,confirmLabel:"Remove"})&&i(r.id)},children:e.jsx(P,{size:14,"aria-hidden":!0})})})]},r.id)}),I.map(r=>e.jsxs(s.Tr,{children:[e.jsx(s.Td,{children:e.jsx(A,{label:"Invited — they get access as soon as they create their SlateData account.",withArrow:!0,multiline:!0,w:240,children:e.jsx(j,{color:"orange",variant:"light",tabIndex:0,style:{cursor:"default"},children:"Invited"})})}),e.jsx(s.Td,{children:r.email}),e.jsx(s.Td,{children:e.jsx(B,{size:"xs",c:"dimmed",children:"Pending sign-up"})}),e.jsx(s.Td,{align:"right",children:m&&e.jsx(A,{label:"Revoke",children:e.jsx(E,{"aria-label":`Revoke invitation for ${r.email}`,color:"red",variant:"subtle",size:"sm",onClick:async()=>{await R(r.id)||x("Failed to revoke invitation.")},children:e.jsx(P,{size:14,"aria-hidden":!0})})})})]},r.id)),!p&&O.length===0&&I.length===0&&e.jsx(s.Tr,{children:e.jsx(s.Td,{colSpan:4,children:e.jsx(B,{size:"sm",c:"dimmed",py:"xs",children:"No individual members yet."})})})]})]})})})]}),e.jsx(q,{my:"xl"}),e.jsxs(M,{gap:"sm",children:[e.jsxs(f,{gap:"xs",children:[e.jsx(K,{size:20,"aria-hidden":!0}),e.jsx(F,{order:3,children:"Groups"})]}),m&&e.jsx("form",{onSubmit:r=>{r.preventDefault(),S()},children:e.jsxs(f,{align:"flex-end",gap:"sm",children:[e.jsx(ie,{label:"Add a group",placeholder:C.length?"Pick a group":"No more groups to add",description:C.length?void 0:"Every team group already has access to this workspace.",data:C.map(r=>
1({value:r.id,label:r.name})),value:n,onChange:u,disabled:!C.length,searchable:!0,flex:1,maw:280}),e.jsx(H,{type:"submit",variant:"default",disabled:!n,children:"Add"})]})}),(l||[]).length===0?e.jsx(B,{size:"sm",c:"dimmed",children:"No groups have access to this workspace yet."}):e.jsx(Q,{withBorder:!0,p:0,children:e.jsx(s.ScrollContainer,{minWidth:480,children:e.jsxs(s,{"aria-label":"Groups",children:[e.jsx(s.Thead,{children:e.jsxs(s.Tr,{children:[e.jsx(s.Th,{w:140,children:"Workspace role"}),e.jsx(s.Th,{children:"Group"}),e.jsx(s.Th,{children:"Members"}),e.jsx(s.Th,{children:e.jsx(J,{children:"Actions"})})]})}),e.jsx(s.Tbody,{children:(l||[]).map(r=>e.jsxs(s.Tr,{children:[e.jsx(s.Td,{children:e.jsx(j,{color:"blue",variant:"light",style:{cursor:"default"},children:r.role.charAt(0).toUpperCase()+r.role.slice(1)})}),e.jsx(s.Td,{children:e.jsxs(f,{gap:"xs",children:[e.jsx(K,{size:16,"aria-hidden":!0}),r.group_name]})}),e.jsx(s.Td,{children:e.jsx(j,{size:"sm",variant:"light",color:"blue",children:r.member_count})}),e.jsx(s.Td,{align:"right",children:m&&e.jsx(E,{"aria-label":`Remove group ${r.group_name}`,color:"red",variant:"subtle",size:"sm",onClick:async()=>{await k({title:"Remove group",message:`Remove group "${r.group_name}" from workspace?`,confirmLabel:"Remove"})&&T(r.group_id)},children:e.jsx(P,{size:14,"aria-hidden":!0})})})]},r.id))})]})})})]})]})]})}export{ze as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.