PageSourceSearch

https://convolyze.io/assets/SuperAdminPage-CSC6jNeo.js

js convolyze.io collected 2026-10-02 01:57:25 UTC 7,074 bytes, 1 lines download raw bytes

1import{m as z,a6 as P,r as n,j as e,N,S as L,s as d}from"./index-Bbgev6vg.js";import{P as B}from"./plus-OvzM0vUk.js";const U=()=>{var _;const{user:w,loading:S,isAdmin:m,adminChecked:T}=z(),{toast:i}=P(),[p,C]=n.useState([]),[h,M]=n.useState([]),[u,b]=n.useState(""),[x,f]=n.useState(""),[g,o]=n.useState(!1),[r,k]=n.useState(null),[c,j]=n.useState(""),[v,A]=n.useState("subdomain_admin"),l=async()=>{const{data:t}=await d.from("tenants").select("*").order("created_at",{ascending:!1});C(t??[]);const{data:s}=await d.rpc("all_tenant_memberships_with_email");M(s??[])};if(n.useEffect(()=>{m&&l()},[m]),S||!T)return e.jsx("div",{className:"p-8 text-muted-foreground",children:"Loading…"});if(!w)return e.jsx(N,{to:"/auth",replace:!0});if(!m)return e.jsx(N,{to:"/",replace:!0});const E=async t=>{if(t.preventDefault(),!u||!x)return;o(!0);const s=u.trim().toLowerCase().replace(/[^a-z0-9-]/g,""),{error:a}=await d.from("tenants").insert({subdomain:s,name:x});if(o(!1),a){i({title:"Failed",description:a.message,variant:"destructive"});return}i({title:"Tenant registered",description:`${s}.convolyze.io`}),b(""),f(""),l()},F=async t=>{if(t.preventDefault(),!r||!c)return;o(!0);const{error:s}=await d.rpc("assign_tenant_member_by_email",{_tenant_id:r,_email:c.trim(),_role:v});if(o(!1),s){i({title:"Failed",description:s.message,variant:"destructive"});return}i({title:"Assigned",description:c}),j(""),l()},R=async(t,s,a)=>{const{error:y}=await d.rpc("set_tenant_member_role",{_tenant_id:s,_user_id:t,_role:a});y&&i({title:"Failed",description:y.message,variant:"destructive"}),l()},D=async(t,s)=>{if(!confirm("Archive this member? They will lose feed access."))return;const{error:a}=await d.rpc("archive_tenant_member",{_tenant_id:s,_user_id:t});a&&i({title:"Failed",description:a.message,variant:"destructive"}),l()},q=async(t,s)=>{const{error:a}=await d.rpc("unarchive_tenant_member",{_tenant_id:s,_user_id:t});a&&i({title:"Failed",description:a.message,variant:"destructive"}),l()};return e.jsxs("div",{className:"max-w-5xl mx-auto px-4 md:px-6 py-6 md:py-8 space-y-8",children:[e.jsx(L,{title:"Tenants",description:"Tenant management.",path:"/superadmin",noindex:!0}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",style:{fontFamily:"'Space Grotesk', sans-serif"},children:"Tenants"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Register subdomains and manage their members."})]}),e.jsxs("section",{className:"rounded-xl border border-border bg-card p-4 space-y-3",children:[e.jsx("h2",{className:"font-semibold",children:"Register new tenant"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"The subdomain DNS record must be added separately. This only records it in the app."}),e.jsxs("form",{onSubmit:E,className:"flex flex-col md:flex-row gap-2",children:[e.jsx("input",{value:u,onChange:t=>b(t.target.value),placeholder:"subdomain (e.g. pitt)",className:"flex-1 px-3 py-2 rounded-md border border-input bg-background text-sm",required:!0}),e.jsx("input",{value:x,onChange:t=>f(t.target.value),placeholder:"Display name",className:"flex-1 px-3 py-2 rounded-md border border-input bg-background text-sm",required:!0}),e.jsxs("button",{disabled:g,className:"px-4 py-2 rounded-md bg-primary text-primary-foreground text-sm font-medium flex items-center gap-1.5",children:[e.jsx(B,{className:"w-4 h-4"})," Register"]})]})]}),e.jsxs("section",{className:"space-y-3",children:[e.jsx("h2",{className:"font-semibold",children:"All tenants"}),e.jsx("div",{className:"rounded-xl border border-border bg-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-muted/50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Subdomain"}),e.jsx("th",{className:"text-left px-4 py-2 font-medium",children:"Name"}),e.jsx("th",{className:"text-right px-4 py-2 font-medium",children:"Members"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:p.map(t=>e.jsxs("tr",{className:"border-t border-border",children:[e.jsxs("td",{className:"px-4 py-2 font-mono text-xs",children:[t.subdomain,".convolyze.io"]}),e.jsx("td",{className:"px-4 py-2",children:t.name}),e.jsx("td",{className:"px-4 py-2 text-right",children:h.filter(s=>s.tenant_id===t.id&&!s.archived_at).length}),e.jsx("td",{className:"px-4 py-2 text-right",children:e.jsx("button",{className:"text-primary text-xs hover:underline",onClick:()=>k(r===t.id?null:t.id),children:r===t.id?"Close":"Manage"})})]},t.id))})]})})]}),r&&e.jsxs("section",{className:"rounded-xl border border-border bg-card p-4 space-y-4",children:[e.jsxs("h2",{className:"font-semibold",children:["Members of ",(_=p.find(t=>
1t.id===r))==null?void 0:_.subdomain]}),e.jsxs("form",{onSubmit:F,className:"flex flex-col md:flex-row gap-2",children:[e.jsx("input",{value:c,onChange:t=>j(t.target.value),type:"email",placeholder:"[email protected]",className:"flex-1 px-3 py-2 rounded-md border border-input bg-background text-sm",required:!0}),e.jsxs("select",{value:v,onChange:t=>A(t.target.value),className:"px-3 py-2 rounded-md border border-input bg-background text-sm",children:[e.jsx("option",{value:"feed_user",children:"Feed user"}),e.jsx("option",{value:"subdomain_admin",children:"Subdomain admin"}),e.jsx("option",{value:"feed_admin",children:"Feed admin"})]}),e.jsx("button",{disabled:g,className:"px-4 py-2 rounded-md bg-primary text-primary-foreground text-sm font-medium",children:"Assign"})]}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Enter the user's email. They must already have signed up. Assigning moves an existing member to this tenant."}),e.jsx("div",{className:"rounded-lg border border-border overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-muted/50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-3 py-1.5 font-medium",children:"Email"}),e.jsx("th",{className:"text-left px-3 py-1.5 font-medium",children:"Role"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:h.filter(t=>t.tenant_id===r).map(t=>e.jsxs("tr",{className:"border-t border-border "+(t.archived_at?"text-muted-foreground line-through":""),children:[e.jsx("td",{className:"px-3 py-1.5",title:t.user_id,children:t.email??"—"}),e.jsx("td",{className:"px-3 py-1.5 no-underline",children:e.jsxs("select",{value:t.role,onChange:s=>R(t.user_id,r,s.target.value),className:"px-2 py-1 rounded-md border border-input bg-background text-xs",disabled:!!t.archived_at,children:[e.jsx("option",{value:"feed_user",children:"feed_user"}),e.jsx("option",{value:"subdomain_admin",children:"subdomain_admin"}),e.jsx("option",{value:"feed_admin",children:"feed_admin"})]})}),e.jsx("td",{className:"px-3 py-1.5 text-right no-underline",children:t.archived_at?e.jsx("button",{className:"text-primary text-xs hover:underline",onClick:()=>q(t.user_id,r),children:"Unarchive"}):e.jsx("button",{className:"text-destructive text-xs hover:underline",onClick:()=>D(t.user_id,r),children:"Archive"})})]},t.user_id))})]})})]})]})};export{U 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.