1import{j as a}from"./vendor-three-Bmn2g83e.js";import{u as T,r as i}from"./vendor-react-kRHgybFd.js";import{az as l,a4 as f,R as B,ap as C,an as m,al as D,ao as L,n as P}from"./vendor-misc-DSUDoLcJ.js";function I(){T();const[n,h]=i.useState(null),[o,k]=i.useState([]),[N,p]=i.useState(!0),[u,j]=i.useState(!1),[x,b]=i.useState(!1),[r,v]=i.useState(!1);i.useEffect(()=>{const s=localStorage.getItem("adminToken");if(!s){console.log("No token found, redirecting to admin login"),window.location.href="/admin/login";return}console.log("Token found, loading stats..."),c(s),d(s)},[]);const c=async s=>{try{p(!0),console.log("Fetching from: /api/admin/database-stats");const e=await fetch("/api/admin/database-stats",{method:"GET",headers:{Authorization:`Bearer ${s||localStorage.getItem("adminToken")}`,"Content-Type":"application/json"}});if(console.log("Response status:",e.status),e.status===401){console.log("Unauthorized - redirecting to admin login"),localStorage.removeItem("adminToken"),window.location.href="/admin/login";return}if(!e.ok)throw new Error(`HTTP ${e.status}`);const t=await e.json();console.log("Stats loaded successfully:",t),h(t)}catch(e){console.error("Error loading stats:",e),h({databaseSize:"Unknown",dbType:"PostgreSQL",lastBackup:null,tables:{}})}finally{p(!1)}},d=async s=>{try{const e=await fetch("/api/admin/backups",{method:"GET",headers:{Authorization:`Bearer ${s||localStorage.getItem("adminToken")}`,"Content-Type":"application/json"}});if(e.ok){const t=await e.json();k(t.backups||[])}}catch(e){console.error("Error loading backups:",e)}},w=async()=>{if(window.confirm("Create a database backup? This may take a moment."))try{j(!0);const s=localStorage.getItem("adminToken");if(!s){window.location.href="/admin/login";return}const e=await fetch("/api/admin/database-backup",{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"}});if(e.status===401){localStorage.removeItem("adminToken"),window.location.href="/admin/login";return}const t=await e.json();t.success?(alert(`â Backup created successfully! 2 3Filename: `+t.filename+` 4Size: `+t.size),c(s),d(s)):alert("â Backup failed: "+(t.error||t.message||"Unknown error"))}catch(s){console.error("Backup error:",s),alert("â Backup failed: "+s.message)}finally{j(!1)}},S=async()=>{if(window.confirm("Optimize the database? This will run VACUUM ANALYZE."))try{b(!0);const s=localStorage.getItem("adminToken"),e=await fetch("/api/database/optimize",{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"}});if(e.status===401){localStorage.removeItem("adminToken"),window.location.href="/admin/login";return}const t=await e.json();t.success?alert("â Database optimized successfully!"):alert("â Optimization failed: "+(t.error||"Unknown error"))}catch(s){console.error("Optimize error:",s),alert("â Optimization failed: "+s.message)}finally{b(!1)}},z=async s=>{if(window.confirm(`Delete backup: ${s}? 5 6This action cannot be undone.`))try{const e=localStorage.getItem("adminToken"),g=await(await fetch(`/api/admin/backups/${s}`,{method:"DELETE",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}})).json();g.success?(alert("â Backup deleted successfully!"),d(e),c(e)):alert("â Delete failed: "+(g.error||"Unknown error"))}catch(e){console.error("Delete error:",e),alert("â Delete failed: "+e.message)}},y=s=>{const e=localStorage.getItem("adminToken");window.open(`/api/database/download/${s}?token=${e}`,"_blank")};return N?a.jsxs("div",{className:"admin-database loading",children:[a.jsx(l,{className:"spin",size:48}),a.jsx("p",{children:"Loading database information..."})]}):a.jsxs("div",{className:"admin-database",children:[a.jsxs("div",{className:"page-header",children:[a.jsxs("h1",{children:[a.jsx(f,{size:32}),"Database Management"]}),a.jsx("p",{children:"Manage your PostgreSQL database, backups, and optimization"})]}),a.jsxs("div",{className:"database-grid",children:[a.jsxs("div",{className:"db-card stats-card",children:[a.jsxs("h2",{children:[a.jsx(B,{size:24}),"Database Statistics"]}),a.jsxs("div",{className:"stats-grid",children:[a.jsxs("div",{className:"stat-item",children:[a.jsx("span",{className:"stat-label",children:"Database Size"}),a.jsx("span",{className:"stat-value",children:n?.databaseSize||"0 MB"})]}),a.jsxs("div",{className:"stat-item",children:[a.jsx("span",{className:"stat-label",children:"Type"}),a.jsx("span",{className:"stat-value",children:n?.dbType||"PostgreSQL"})]}),a.jsxs("div",{className:"stat-item",children:[a.jsx("span",{className:"stat-label",children:"Status"}),a.jsx("span",{className:"stat-value status-active",children:n?.dbExists?"â Connected":"â Disconnected"})]}),a.jsxs("div",{className:"stat-item",children:[a.jsx("span",{className:"stat-label",children:"Total Tables"}),a.jsx("span",{className:"stat-value",children:Object.keys(n?.tables||{}).length})]})]}),a.jsxs("div",{className:"quick-actions",children:[a.jsxs("button",{className:"btn btn-small btn-secondary",onClick:()=>c(localStorage.getItem("adminToken")),children:[a.jsx(l,{size:16}),"Refresh"]}),a.jsx("button",{className:"btn btn-small btn-secondary",onClick:S,disabled:x,children:x?a.jsxs(a.Fragment,{children:[a.jsx(l,{className:"spin",size:16}),"Optimizing..."]}):a.jsxs(a.Fragment,{children:[a.jsx(C,{size:16}),"Optimize DB"]})})]})]}),a.jsxs("div",{className:"db-card backup-card",children:[a.jsxs("h2",{children:[a.jsx(m,{size:24}),"Backup Management"]}),a.jsx("p",{children:"Create and manage PostgreSQL database backups"}),a.jsxs("div",{className:"backup-actions",children:[a.jsx("button",{className:"btn btn-primary",onClick:w,disabled:u,children:u?a.jsxs(a.Fragment,{children:[a.jsx(l,{className:"spin",size:18}),"Creating..."]}):a.jsxs(a.Fragment,{children:[a.jsx(m,{size:18}),"Create Backup"]})}),a.jsxs("button",{className:"btn btn-secondary",onClick:()=>v(!r),children:[a.jsx(D,{size:18}),r?"Hide":"Manage"," Backups"]})]}),a.jsxs("div",{className:"backup-info",children:[a.jsx("p",{children:"ð¡ Backups: /opt/scholarnet-ai/backend/backups/postgres/"}),a.jsx("p",{children:"ð Format: PostgreSQL SQL dump (.sql)"}),a.jsxs("p",{children:["ð Last backup: ",n?.lastBackup||"Never"]}),a.jsxs("p",{children:["ð¦ Total backups: ",n?.backupCount||0]})]}),r&&a.jsxs("div",{className:"backup-list-container",children:[a.jsxs("h3",{children:["Available Backups (",o.length,")"]}),o.length>0?a.jsx("div",{className:"backup-list",children:o.map((s,e)=>a.jsxs("div",{className:"backup-item",children:[a.jsxs("div",{className:"backup-detail
6s",children:[a.jsx("span",{className:"backup-name",children:s.filename}),a.jsxs("span",{className:"backup-meta",children:[s.size," ⢠",new Date(s.created).toLocaleString()]})]}),a.jsxs("div",{className:"backup-item-actions",children:[a.jsx("button",{className:"btn btn-icon",onClick:()=>y(s.filename),title:"Download",children:a.jsx(m,{size:16})}),a.jsx("button",{className:"btn btn-icon btn-danger",onClick:()=>z(s.filename),title:"Delete",children:a.jsx(L,{size:16})})]})]},e))}):a.jsx("p",{className:"no-backups",children:"No backups found. Create your first backup above."})]})]}),a.jsxs("div",{className:"db-card migration-card",children:[a.jsxs("h2",{children:[a.jsx(P,{size:24}),"Database Configuration"]}),a.jsx("p",{children:"Production database status and configuration"}),a.jsx("div",{className:"migration-status",children:a.jsx("div",{className:"status-badge success",children:"â
Using PostgreSQL (Production)"})}),a.jsxs("div",{className:"migration-info",children:[a.jsx("h3",{children:"PostgreSQL Features Active:"}),a.jsxs("ul",{children:[a.jsx("li",{children:"â
High performance for large datasets"}),a.jsx("li",{children:"â
Advanced querying with indexes"}),a.jsx("li",{children:"â
Multi-user concurrent access"}),a.jsx("li",{children:"â
Production-grade reliability"}),a.jsx("li",{children:"â
ACID compliance for data integrity"}),a.jsx("li",{children:"â
Full transaction support"})]})]}),a.jsxs("div",{className:"db-config-info",children:[a.jsx("h3",{children:"Connection Details:"}),a.jsxs("div",{className:"config-item",children:[a.jsx("span",{className:"config-label",children:"Host:"}),a.jsx("span",{className:"config-value",children:"localhost"})]}),a.jsxs("div",{className:"config-item",children:[a.jsx("span",{className:"config-label",children:"Port:"}),a.jsx("span",{className:"config-value",children:"5432"})]}),a.jsxs("div",{className:"config-item",children:[a.jsx("span",{className:"config-label",children:"Database:"}),a.jsx("span",{className:"config-value",children:"scholarnet"})]})]})]}),a.jsxs("div",{className:"db-card tables-card",children:[a.jsxs("h2",{children:[a.jsx(f,{size:24}),"Database Information"]}),n?a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"db-info-list",children:[a.jsxs("div",{className:"info-item",children:[a.jsx("span",{className:"info-label",children:"Database Type:"}),a.jsx("span",{className:"info-value",children:n.dbType||"PostgreSQL"})]}),a.jsxs("div",{className:"info-item",children:[a.jsx("span",{className:"info-label",children:"Size:"}),a.jsx("span",{className:"info-value",children:n.databaseSize||"Unknown"})]}),a.jsxs("div",{className:"info-item",children:[a.jsx("span",{className:"info-label",children:"Status:"}),a.jsx("span",{className:"info-value status-active",children:n.dbExists?"â
Connected":"â Not Connected"})]}),a.jsxs("div",{className:"info-item",children:[a.jsx("span",{className:"info-label",children:"Last Backup:"}),a.jsx("span",{className:"info-value",children:n.lastBackup&&n.lastBackup!=="Never"?n.lastBackup:"Never"})]}),a.jsxs("div",{className:"info-item",children:[a.jsx("span",{className:"info-label",children:"Backup Count:"}),a.jsx("span",{className:"info-value",children:n.backupCount||0})]})]}),n.tables&&Object.keys(n.tables).length>0&&a.jsxs("div",{className:"tables-breakdown",children:[a.jsx("h3",{children:"Table Breakdown"}),a.jsx("div",{className:"table-list",children:Object.entries(n.tables).map(([s,e])=>a.jsxs("div",{className:"table-row",children:[a.jsx("span",{className:"table-name",children:s}),a.jsxs("span",{className:"table-count",children:[e.toLocaleString()," records"]})]},s))}),a.jsxs("div",{className:"table-summary",children:[a.jsx("strong",{children:"Total Records:"})," ",Object.values(n.tables).reduce((s,e)=>s+e,0).toLocaleString()]})]})]}):a.jsxs("div",{className:"loading-message",children:[a.jsx(l,{className:"spin",size:24}),a.jsx("p",{children:"Loading database information..."})]})]})]})]})}export{I 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.