PageSourceSearch

https://xterns.ai/assets/TechLeadGithubIntegration-fsaOHO7l.js

js xterns.ai collected 2026-10-05 13:24:46 UTC 19,673 bytes, 1 lines download raw bytes

1import{M as w,s as x,j as e,J as y,U as O,r as L,B as k,b as z,t as $,p as F,Z as K,ae as v,a1 as B,a2 as M,a3 as Q,a5 as U,f as D,aK as J,bK as Y,bu as W,h as G,i as H,k as P,l as T,m as A,x as E,F as X}from"./index-DLd_kDlx.js";import{T as Z}from"./TechLeadHeader-eLOg3V3h.js";import{C as V}from"./ConnectGitHubButton-DLktnEM_.js";import{u as R}from"./useGitHubIdentity-DDmb0Jwt.js";import{L as C}from"./loader-circle-D2miE2xB.js";import{G as ee}from"./git-commit-horizontal-CQF5yVsh.js";import{G as te}from"./git-pull-request-__1fAqC3.js";import{E as se}from"./eye-CRDofLPH.js";import{P as ae,a as re,b as ie}from"./popover-BMD5FOmU.js";import{C as ne,a as oe,b as ce,c as le,d as de,e as ue,f as me}from"./command-BReSBG4f.js";import{G as pe}from"./globe-C057RQ73.js";import{C as he}from"./CreateRepoDialog-CS0zHZ02.js";import{u as S}from"./useMutation-CotV56Sa.js";import{U as I}from"./user-plus-CSalqUlO.js";import{G as xe}from"./git-branch-C-twpC7K.js";import{L as fe}from"./link-2-DxGcptQD.js";import{R as ge}from"./refresh-cw-CoPjtj5-.js";import"./dropdown-menu-DSd1c3Vk.js";import"./index-Deh-4PO1.js";import"./index-lTaZyIGy.js";import"./chevron-right-CD1gvy-q.js";import"./NotificationIcon-C1wwYnH5.js";import"./scroll-area-BXTuUF24.js";import"./index-BdQq_4o_.js";import"./NotificationItem-Dc2WXW-y.js";import"./formatDistanceToNow-57P64IbE.js";import"./en-US-9SRVm7yB.js";import"./differenceInCalendarMonths-BA0TPVs2.js";import"./endOfDay-DkR3ZXc8.js";import"./endOfMonth-CYn6pTOm.js";import"./message-square-CtxeCfRz.js";import"./trophy-DBX-jNOC.js";import"./triangle-alert-Chqk_WK7.js";import"./rotate-ccw-Bx1C64Ur.js";import"./external-link-D0CFvOTk.js";import"./search-DFH5eAlA.js";import"./label-D4-ENrYn.js";import"./switch-7Twrb7Os.js";import"./plus-0WhrdjYO.js";function be(){const{isConnected:a}=R();return w({queryKey:["github-repos",a],queryFn:async()=>{var f;const{data:u}=await x.auth.getSession(),b=(f=u==null?void 0:u.session)==null?void 0:f.access_token;if(!b)throw new Error("Not authenticated");const o=await fetch("https://cfcvcgojltawrodgtjnc.supabase.co/functions/v1/github-list-repos",{headers:{Authorization:`Bearer ${b}`,"Content-Type":"application/json"}});if(!o.ok){const c=await o.json().catch(()=>({}));throw new Error(c.error||"Failed to fetch repos")}return o.json()},enabled:a,staleTime:6e4})}function _e(a,u){const{startDate:b,endDate:o}=u??{};return w({queryKey:["pod-contributions",a,b,o],queryFn:async()=>{if(!a)return[];let f=x.from("github_events").select("event_type, actor_github_username, actor_user_id, event_data").eq("pod_id",a);b&&(f=f.gte("created_at",b)),o&&(f=f.lte("created_at",o));const{data:c,error:m}=await f;if(m)throw m;const l=new Map;for(const n of c||[]){if(n.actor_github_username.endsWith("[bot]"))continue;const h=n.actor_github_username;l.has(h)||l.set(h,{user_id:n.actor_user_id,username:n.actor_github_username,commits:0,prs_opened:0,prs_merged:0,reviews:0});const N=l.get(h),g=n.event_data;if(n.event_type==="push")g!=null&&g.is_merge_push||(N.commits+=(g==null?void 0:g.commits_count)||1);else if(n.event_type==="pull_request"){const r=g==null?void 0:g.action;r==="closed"&&(g!=null&&g.merged)?N.prs_merged++:r==="opened"&&N.prs_opened++}else n.event_type==="pull_request_review"&&N.reviews++}return Array.from(l.values()).sort((n,h)=>h.commits+h.prs_opened+h.prs_merged+h.reviews-(n.commits+n.prs_opened+n.prs_merged+n.reviews))},enabled:!!a})}const je=({podId:a,startDate:u,endDate:b})=>{const{data:o,isLoading:f}=_e(a,{startDate:u,endDate:b});if(f)return e.jsxs("div",{className:"flex items-center gap-2 py-3",children:[e.jsx(C,{className:"h-4 w-4 animate-spin"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"Loading contributions..."})]});if(!(o!=null&&o.length))return e.jsx("p",{className:"text-xs text-muted-foreground py-2",children:"No contributions recorded yet. Events will appear after pushes, PRs, or reviews."});const c=o.reduce((m,l)=>({commits:m.commits+l.commits,prs:m.prs+l.prs_opened+l.prs_merged,reviews:m.reviews+l.reviews}),{commits:0,prs:0,reviews:0});return e.jsxs("div",{className:"space-y-3 mt-3",children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(y,{variant:"secondary",className:"gap-1 text-xs",children:[e.jsx(ee,{className:"h-3 w-3"})," ",c.commits," commits"]}),e.jsxs(y,{variant:"secondary",className:"gap-1 text-xs",children:[e.jsx(te,{className:"h-3 w-3"})," ",c.prs," PRs"]}),e.jsxs(y,{variant:"secondary",className:"gap-1 text-xs",children:[e.jsx(se,{className:"h-3 w-3"})," ",c.reviews," reviews"]}),e.jsxs(y,{variant:"secondary",className:"gap-1 text-xs",children:[e.jsx(O,{className:"h-3 w-3"})," ",o.length," contributors"]})]}),e.jsx("div",{className:"border border-border rounded-md overflow-hidden",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-muted/50",children:[e.jsx("th",{className:"text-left px-3 py-2 font-medium text-muted-foreground",children:"Contributor"}),e.jsx("th",{className:"text-center px-2 py-2 font-medium text-muted-foreground",children:"Commits"}),e.jsx("th",{className:"text-center px-2 py-2 font-medium text-muted-foreground",children:"PRs"}),e.jsx("th",{className:"text-center px-2 py-2 font-medium text-muted-foreground",children:"Merged"}),e.jsx("th",{className:"text-center px-2 py-2 font-medium text-muted-foreground",children:"Reviews"})]})}),e.jsx("tbody",{children:o.map(m=>e.jsxs("tr",{className:"border-t border-border",children:[e.jsx("td",{className:"px-3 py-2 font-medium",children:m.username}),e.jsx("td",{className:"text-center px-2 py-2",children:m.commits}),e.jsx("td",{className:"text-center px-2 py-2",children:m.prs_opened}),e.jsx("td",{className:"text-center px-2 py-2",children:m.prs_merged}),e.jsx("td",{className:"text-center px-2 py-2",children:m.reviews})]},m.username))})]})})]})},ye=({repos:a,isLoading:u,onSelect:b,isPending:o})=>{const[f,c]=L.useState(!1),[m,l]=L.useState("");return e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(ae,{open:f,onOpenChange:c,children:[e.jsx(re,{asChild:!0,children:e.jsxs(k,{variant:"outline",role:"combobox","aria-expanded":f,className:"flex-1 justify-between text-sm font-normal",disabled:u,children:[u?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(C,{className:"h-4 w-4 animate-spin"}),"Loading repos..."]}):m||"Select a repository...",e.jsx(ne,{className:"ml-2 h-4 w-4 shrink-0 opacity-50"})]})}),e.jsx(ie,{className:"w-[400px] p-0",align:"start",children:e.jsxs(oe,{children:[e.jsx(ce,{placeholder:"Search repositories..."}),e.jsxs(le,{children:[e.jsx(de,{children:"No repositories found."}),e.jsx(ue,{children:a.map(n=>e.jsxs(me,{value:n.full_name,onSelect:h=>{l(h),c(!1)},children:[e.jsx(z,{className:$("mr-2 h-4 w-4",m===n.full_name?"opacity-100":"opacity-0")}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 min-w-0",children:[n.private?e.jsx(F,{className:"h-3 w-3 shrink-0 text-muted-foreground"}):e.jsx(pe,{className:"h-3 w-3 shrink-0 text-muted-foreground"}),e.jsx("span",{className:"truncate",children:n.full_name})]})]},n.full_name))})]})]})})]}),e.jsx(k,{size:"sm",disabled:!m||o,onClick:()=>b(m),children:o?e.jsx(C,{className:"h-4 w-4 animate-spin"}):"Link"})]})},ve=({podId:a,repoFullName:u})=>{const b=K(),{data:o}=w({queryKey:["current-user"],queryFn:async()=>{const{data:{user:r}}=await x.auth.getUser();return r}}),{data:f,isLoading:c}=w({queryKey:["pod-members-github",a],queryFn:async()=>{const{data:r,error:t}=await x.from("pod_members").select("user_id").eq("pod_id",a).in("status",["active","inactive","completed"]);if(t)throw t;if(!(r!=null&&r.length))return[];const s=r.map(d=>
1d.user_id),{data:i}=await x.from("profiles").select("id, full_name").in("id",s),{data:p}=await x.from("github_identities").select("user_id, github_username, github_avatar_url").in("user_id",s),_=new Map((p||[]).map(d=>[d.user_id,d]));return(i||[]).map(d=>{const j=_.get(d.id);return{user_id:d.id,full_name:d.full_name,github_username:(j==null?void 0:j.github_username)||null,github_avatar_url:(j==null?void 0:j.github_avatar_url)||null}})},enabled:!!a}),{data:m={},isLoading:l}=w({queryKey:["github-collaborator-status",a,u],queryFn:async()=>{var p;const{data:r}=await x.auth.getSession(),t=(p=r==null?void 0:r.session)==null?void 0:p.access_token;if(!t)throw new Error("Not authenticated");const s=await fetch("https://cfcvcgojltawrodgtjnc.supabase.co/functions/v1/github-collaborator-status",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({pod_id:a,repo_full_name:u})});if(!s.ok)throw new Error("Unable to retrieve repository access status");return(await s.json()).statuses||{}},enabled:!!a&&!!u&&!!o,staleTime:3e4}),n=S({mutationFn:async r=>{var p;const{data:t}=await x.auth.getSession(),s=(p=t==null?void 0:t.session)==null?void 0:p.access_token;if(!s)throw new Error("Not authenticated");const i=await fetch("https://cfcvcgojltawrodgtjnc.supabase.co/functions/v1/github-add-collaborator",{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({pod_id:a,repo_full_name:u,target_user_id:r.user_id,github_username:r.github_username})});if(!i.ok){const _=await i.json().catch(()=>({}));throw new Error(_.error||"Failed to invite")}return i.json()},onSuccess:(r,t)=>{b.invalidateQueries({queryKey:["github-collaborator-status",a,u]}),v({title:r.status==="already_collaborator"?"Already a collaborator":"Invitation sent",description:`${t.github_username} has been ${r.status==="already_collaborator"?"confirmed as":"invited as"} a collaborator.`})},onError:r=>{v({title:"Error",description:r.message,variant:"destructive"})}}),h=f||[];if(c)return e.jsxs("div",{className:"flex items-center gap-2 py-2",children:[e.jsx(C,{className:"h-3 w-3 animate-spin"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"Loading members..."})]});if(!h.length)return null;const N=h.filter(r=>r.github_username),g=h.filter(r=>!r.github_username);return e.jsxs("div",{className:"space-y-2 mt-3",children:[e.jsxs("h5",{className:"text-xs font-medium text-muted-foreground flex items-center gap-1",children:[e.jsx(I,{className:"h-3 w-3"}),"Pod Members — Repo Access"]}),e.jsxs("div",{className:"space-y-1",children:[N.map(r=>{const t=m[r.github_username.toLowerCase()];return e.jsxs("div",{className:"flex items-center justify-between py-1.5 px-2 rounded bg-muted/30",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(B,{className:"h-5 w-5",children:[e.jsx(M,{src:r.github_avatar_url||void 0}),e.jsx(Q,{children:e.jsx(U,{className:"h-3 w-3"})})]}),e.jsx("span",{className:"text-xs",children:r.full_name||r.github_username}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["@",r.github_username]})]}),r.user_id===(o==null?void 0:o.id)?e.jsx(y,{variant:"secondary",className:"text-[10px]",children:"You"}):l?e.jsx(C,{className:"h-3 w-3 animate-spin text-muted-foreground"}):t?e.jsx(y,{variant:t==="collaborator"?"default":"secondary",className:"text-[10px]",children:t==="collaborator"?"Collaborator":"Invited"}):e.jsx(k,{variant:"ghost",size:"sm",className:"h-6 text-xs",disabled:n.isPending,onClick:()=>n.mutate(r),children:n.isPending?e.jsx(C,{className:"h-3 w-3 animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"h-3 w-3 mr-1"}),"Invite"]})})]},r.user_id)}),g.map(r=>e.jsxs("div",{className:"flex items-center justify-between py-1.5 px-2 rounded bg-muted/30 opacity-50",children:[e.jsx("span",{className:"text-xs",children:r.full_name||"Unknown"}),e.jsx(y,{variant:"outline",className:"text-[10px]",children:"No GitHub"})]},r.user_id))]})]})},Ne=a=>a.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),lt=()=>{const{user:a}=D(),u=K(),{isConnected:b}=R(),{data:o,isLoading:f}=be(),{data:c,isLoading:m}=w({queryKey:["tech-lead-pods-github",a==null?void 0:a.id],queryFn:async()=>
1{if(!(a!=null&&a.id))return[];const{data:t}=await x.from("tech_leads").select("id").eq("user_id",a.id).maybeSingle();if(!t)return[];const{data:s,error:i}=await x.from("pods").select("id, pod_name, github_repo_url, github_connected_at, status, project_id, projects(title, description)").eq("tech_lead_id",t.id).in("status",["active","recruiting","setup"]);if(i)throw i;return s||[]},enabled:!!(a!=null&&a.id)}),{data:l}=w({queryKey:["github-pod-repos",a==null?void 0:a.id],queryFn:async()=>{if(!(c!=null&&c.length))return[];const t=c.map(p=>p.id),{data:s,error:i}=await x.from("github_pod_repos").select("*").in("pod_id",t);if(i)throw i;return s||[]},enabled:!!(c!=null&&c.length)}),{data:n}=w({queryKey:["backfill-jobs",a==null?void 0:a.id],queryFn:async()=>{if(!(l!=null&&l.length))return[];const t=l.map(p=>p.repo_full_name),{data:s,error:i}=await x.from("github_backfill_jobs").select("*").in("repo_full_name",t);if(i)throw i;return s||[]},enabled:!!(l!=null&&l.length),refetchInterval:t=>(t.state.data??[]).some(p=>p.status==="pending"||p.status==="running")?3e4:!1,refetchIntervalInBackground:!1}),h=S({mutationFn:async({podId:t,repoFullName:s})=>{var d;const{data:i}=await x.from("github_identities").select("installation_id").eq("user_id",a.id).maybeSingle(),p=(i==null?void 0:i.installation_id)||0,{error:_}=await x.from("github_pod_repos").insert({pod_id:t,repo_full_name:s,installation_id:p,linked_by:a.id});if(_)throw _;if(await x.from("pods").update({github_repo_url:`https://github.com/${s}`,github_connected_at:new Date().toISOString()}).eq("id",t),p){const{data:j}=await x.auth.getSession(),q=(d=j==null?void 0:j.session)==null?void 0:d.access_token;q&&fetch("https://cfcvcgojltawrodgtjnc.supabase.co/functions/v1/github-backfill",{method:"POST",headers:{Authorization:`Bearer ${q}`,"Content-Type":"application/json"},body:JSON.stringify({repo_full_name:s,installation_id:p})}).catch(console.error)}},onSuccess:()=>{u.invalidateQueries({queryKey:["tech-lead-pods-github"]}
1),u.invalidateQueries({queryKey:["github-pod-repos"]}),u.invalidateQueries({queryKey:["backfill-jobs"]}),v({title:"Repository linked",description:"Repo linked and backfill started."})},onError:t=>{const s=(t==null?void 0:t.message)||"";s.includes("NO_INSTALLATION")||s.includes("not found")||s.includes("reinstall")?v({title:"GitHub App not installed",description:"The GitHub App needs to be reinstalled on your organization. Use the 'Install on Organization' button above.",variant:"destructive"}):s.includes("TOKEN_EXPIRED")||s.includes("reconnect")?v({title:"GitHub connection expired",description:"Please reconnect your GitHub account using the Connect GitHub button.",variant:"destructive"}):v({title:"Error",description:s,variant:"destructive"})}}),N=S({mutationFn:async({podId:t,repoFullName:s})=>{const{error:i}=await x.from("github_pod_repos").delete().eq("pod_id",t).eq("repo_full_name",s);if(i)throw i;await x.from("pods").update({github_repo_url:null,github_connected_at:null}).eq("id",t)},onSuccess:()=>{u.invalidateQueries({queryKey:["tech-lead-pods-github"]}
1),u.invalidateQueries({queryKey:["github-pod-repos"]}),v({title:"Repository unlinked"})},onError:t=>{const s=(t==null?void 0:t.message)||"";s.includes("NO_INSTALLATION")||s.includes("reinstall")?v({title:"GitHub App not installed",description:"The GitHub App needs to be reinstalled on your organization.",variant:"destructive"}):v({title:"Error",description:s,variant:"destructive"})}}),g=t=>l==null?void 0:l.find(s=>s.pod_id===t),r=t=>{const s=(n==null?void 0:n.filter(d=>d.repo_full_name===t))||[];if(!s.length)return null;const i=s.filter(d=>d.status==="pending"||d.status==="in_progress"),p=s.filter(d=>d.status==="completed"),_=s.filter(d=>d.status==="failed");return i.length>0?"in_progress":_.length>0&&p.length===0?"failed":"completed"};return e.jsx(J,{children:e.jsxs("div",{className:"min-h-screen flex w-full bg-background",children:[e.jsx(Y,{}),e.jsxs(W,{className:"flex-1",children:[e.jsx(Z,{title:"GitHub Integration"}),e.jsxs("main",{className:"p-8 space-y-6",children:[e.jsxs(G,{children:[e.jsxs(H,{children:[e.jsxs(P,{className:"flex items-center gap-2",children:[e.jsx(xe,{className:"h-5 w-5"}),"Your GitHub Connection"]}),e.jsx(T,{children:"Connect your personal GitHub account to verify your identity and enable contribution tracking."})]}),e.jsxs(A,{children:[e.jsx(V,{}),b&&e.jsx("div",{className:"mt-4 rounded-lg border border-primary/30 bg-primary/5 p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(E,{className:"mt-0.5 h-4 w-4 shrink-0 text-primary"}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium text-foreground",children:"GitHub connected"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Repositories will be created under the ",e.jsx("strong",{children:"xterns"})," organization automatically."]})]})]})})]})]}
1),e.jsxs(G,{children:[e.jsxs(H,{children:[e.jsxs(P,{className:"flex items-center gap-2",children:[e.jsx(fe,{className:"h-5 w-5"}),"Pod Repositories"]}),e.jsx(T,{children:"Link GitHub repositories to your pods to track team contributions."})]}),e.jsx(A,{children:m?e.jsxs("div",{className:"flex items-center gap-2 py-4",children:[e.jsx(C,{className:"h-4 w-4 animate-spin"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"Loading pods..."})]}):c!=null&&c.length?e.jsx("div",{className:"space-y-4",children:c.map(t=>{var p,_;const s=g(t.id),i=s?r(s.repo_full_name):null;return e.jsxs("div",{className:"border border-border rounded-lg p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium text-sm",children:t.pod_name}),e.jsx(y,{variant:"outline",className:"text-xs mt-1",children:t.status})]}),s?e.jsxs(y,{variant:"secondary",className:"gap-1",children:[e.jsx(E,{className:"h-3 w-3"}),"Connected"]}):e.jsxs(y,{variant:"outline",className:"gap-1 text-muted-foreground",children:[e.jsx(X,{className:"h-3 w-3"}),"No repo"]})]}),s?e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"text-xs text-muted-foreground",children:[e.jsx("a",{href:`https://github.com/${s.repo_full_name}`,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:s.repo_full_name}),e.jsxs("p",{className:"mt-1",children:["Linked ",new Date(s.linked_at).toLocaleDateString()]}),i==="in_progress"&&e.jsxs("div",{className:"flex items-center gap-1 mt-1 text-primary",children:[e.jsx(ge,{className:"h-3 w-3 animate-spin"}),e.jsx("span",{children:"Syncing history..."})]}),i==="completed"&&e.jsx("p",{className:"mt-1 text-primary",children:"History sync complete"}),i==="failed"&&e.jsx("p",{className:"mt-1 text-destructive",children:"History sync failed"})]}),e.jsx(k,{variant:"ghost",size:"sm",className:"text-destructive",onClick:()=>N.mutate({podId:t.id,repoFullName:s.repo_full_name}),children:"Disconnect"}),e.jsx(ve,{podId:t.id,repoFullName:s.repo_full_name}),e.jsx(je,{podId:t.id})]}):e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"Select or create a repo:"}),e.jsx(he,{defaultRepoName:Ne(((p=t.projects)==null?void 0:p.title)||t.pod_name),defaultDescription:((_=t.projects)==null?void 0:_.description)||"",podName:t.pod_name,onCreated:d=>{u.invalidateQueries({queryKey:["github-repos"]}),h.mutate({podId:t.id,repoFullName:d})}})]}),e.jsx(ye,{repos:o||[],isLoading:f,isPending:h.isPending,onSelect:d=>h.mutate({podId:t.id,repoFullName:d})})]})]},t.id)})}):e.jsx("p",{className:"text-sm text-muted-foreground py-4",children:"No active pods found."})})]})]})]})]})})};export{lt 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.