new changes
This commit is contained in:
@@ -72,6 +72,38 @@ async def site_create(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class SiteBatchRequest(BaseModel):
|
||||||
|
action: str
|
||||||
|
ids: list[int]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/batch")
|
||||||
|
async def site_batch(
|
||||||
|
body: SiteBatchRequest,
|
||||||
|
current_user: User = Depends(get_current_user),
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
):
|
||||||
|
"""Bulk enable, disable, or delete sites by id."""
|
||||||
|
if body.action not in ("enable", "disable", "delete"):
|
||||||
|
raise HTTPException(status_code=400, detail="action must be enable, disable, or delete")
|
||||||
|
if not body.ids:
|
||||||
|
raise HTTPException(status_code=400, detail="ids required")
|
||||||
|
results: list[dict] = []
|
||||||
|
for sid in body.ids:
|
||||||
|
if body.action == "delete":
|
||||||
|
r = await delete_site(db, sid)
|
||||||
|
elif body.action == "enable":
|
||||||
|
r = await set_site_status(db, sid, 1)
|
||||||
|
else:
|
||||||
|
r = await set_site_status(db, sid, 0)
|
||||||
|
results.append({
|
||||||
|
"id": sid,
|
||||||
|
"ok": bool(r.get("status")),
|
||||||
|
"msg": r.get("msg", ""),
|
||||||
|
})
|
||||||
|
return {"results": results}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{site_id}")
|
@router.get("/{site_id}")
|
||||||
async def site_get(
|
async def site_get(
|
||||||
site_id: int,
|
site_id: int,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""YakPanel - Site service"""
|
"""YakPanel - Site service"""
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from datetime import datetime, timezone
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
@@ -126,13 +127,19 @@ async def create_site(
|
|||||||
|
|
||||||
|
|
||||||
async def list_sites(db: AsyncSession) -> list[dict]:
|
async def list_sites(db: AsyncSession) -> list[dict]:
|
||||||
"""List all sites with domain count."""
|
"""List all sites with domain count, primary domain, backup count, SSL summary."""
|
||||||
|
cfg = get_runtime_config()
|
||||||
|
backup_dir = cfg.get("backup_path") or ""
|
||||||
result = await db.execute(select(Site).order_by(Site.id))
|
result = await db.execute(select(Site).order_by(Site.id))
|
||||||
sites = result.scalars().all()
|
sites = result.scalars().all()
|
||||||
out = []
|
out = []
|
||||||
for s in sites:
|
for s in sites:
|
||||||
domain_result = await db.execute(select(Domain).where(Domain.pid == s.id))
|
domain_result = await db.execute(select(Domain).where(Domain.pid == s.id).order_by(Domain.id))
|
||||||
domains = domain_result.scalars().all()
|
domain_rows = domain_result.scalars().all()
|
||||||
|
domain_list = [f"{d.name}:{d.port}" if d.port != "80" else d.name for d in domain_rows]
|
||||||
|
hostnames = [d.name for d in domain_rows]
|
||||||
|
primary = hostnames[0] if hostnames else ""
|
||||||
|
php_ver = getattr(s, "php_version", None) or "74"
|
||||||
out.append({
|
out.append({
|
||||||
"id": s.id,
|
"id": s.id,
|
||||||
"name": s.name,
|
"name": s.name,
|
||||||
@@ -140,8 +147,13 @@ async def list_sites(db: AsyncSession) -> list[dict]:
|
|||||||
"status": s.status,
|
"status": s.status,
|
||||||
"ps": s.ps,
|
"ps": s.ps,
|
||||||
"project_type": s.project_type,
|
"project_type": s.project_type,
|
||||||
"domain_count": len(domains),
|
"domain_count": len(domain_rows),
|
||||||
"addtime": s.addtime.isoformat() if s.addtime else None,
|
"addtime": s.addtime.isoformat() if s.addtime else None,
|
||||||
|
"php_version": php_ver,
|
||||||
|
"primary_domain": primary,
|
||||||
|
"domains": domain_list,
|
||||||
|
"backup_count": _backup_count(s.name, backup_dir),
|
||||||
|
"ssl": _best_ssl_for_hostnames(hostnames),
|
||||||
})
|
})
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{j as t}from"./index-CRR9sQ49.js";function o({variant:l="danger",children:r,className:a="",dismissible:e,onDismiss:s}){return t.jsxs("div",{className:`alert alert-${l} ${e?"alert-dismissible fade show":""} ${a}`.trim(),role:"alert",children:[r,e?t.jsx("button",{type:"button",className:"btn-close","aria-label":"Close",onClick:s}):null]})}export{o as A};
|
import{j as t}from"./index-Cvh4tLHo.js";function o({variant:l="danger",children:r,className:a="",dismissible:e,onDismiss:s}){return t.jsxs("div",{className:`alert alert-${l} ${e?"alert-dismissible fade show":""} ${a}`.trim(),role:"alert",children:[r,e?t.jsx("button",{type:"button",className:"btn-close","aria-label":"Close",onClick:s}):null]})}export{o as A};
|
||||||
@@ -1 +1 @@
|
|||||||
import{j as a}from"./index-CRR9sQ49.js";function i({children:n,variant:r="primary",size:t,type:o="button",disabled:m,className:s="",...u}){return a.jsx("button",{type:o,disabled:m,className:`btn btn-${r}${t?` btn-${t}`:""} ${s}`.trim(),...u,children:n})}export{i as A};
|
import{j as a}from"./index-Cvh4tLHo.js";function i({children:n,variant:r="primary",size:t,type:o="button",disabled:m,className:s="",...u}){return a.jsx("button",{type:o,disabled:m,className:`btn btn-${r}${t?` btn-${t}`:""} ${s}`.trim(),...u,children:n})}export{i as A};
|
||||||
@@ -1 +1 @@
|
|||||||
import{j as e}from"./index-CRR9sQ49.js";function c({title:s,iconClass:a,children:i,headerExtra:r,className:d="",bodyClassName:l=""}){return e.jsxs("div",{className:`card flex-fill ${d}`.trim(),children:[(s||r)&&e.jsxs("div",{className:"card-header border-0 pb-0 d-flex align-items-center justify-content-between flex-wrap gap-2",children:[e.jsxs("h4",{className:"mb-0 d-flex align-items-center gap-2",children:[a?e.jsx("i",{className:a,"aria-hidden":!0}):null,s]}),r]}),e.jsx("div",{className:`card-body ${l}`.trim(),children:i})]})}export{c as A};
|
import{j as e}from"./index-Cvh4tLHo.js";function c({title:s,iconClass:a,children:i,headerExtra:r,className:d="",bodyClassName:l=""}){return e.jsxs("div",{className:`card flex-fill ${d}`.trim(),children:[(s||r)&&e.jsxs("div",{className:"card-header border-0 pb-0 d-flex align-items-center justify-content-between flex-wrap gap-2",children:[e.jsxs("h4",{className:"mb-0 d-flex align-items-center gap-2",children:[a?e.jsx("i",{className:a,"aria-hidden":!0}):null,s]}),r]}),e.jsx("div",{className:`card-body ${l}`.trim(),children:i})]})}export{c as A};
|
||||||
@@ -1 +1 @@
|
|||||||
import{j as t}from"./index-CRR9sQ49.js";function l({children:r,className:s="",responsive:a=!0}){const e=t.jsx("table",{className:`table table-hover ${s}`.trim(),children:r});return a?t.jsx("div",{className:"table-responsive",children:e}):e}export{l as A};
|
import{j as t}from"./index-Cvh4tLHo.js";function l({children:r,className:s="",responsive:a=!0}){const e=t.jsx("table",{className:`table table-hover ${s}`.trim(),children:r});return a?t.jsx("div",{className:"table-responsive",children:e}):e}export{l as A};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
YakPanel-server/frontend/dist/assets/ConfigPage-t5KRejpn.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/ConfigPage-t5KRejpn.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as i,g as m,j as s}from"./index-CRR9sQ49.js";import{A as n}from"./AdminAlert-DW1IRWce.js";import{A as o}from"./AdminCard-DNA70pGd.js";import{P as d}from"./PageHeader-BcjNf7GG.js";function p(){const[e,r]=i.useState(null),[a,l]=i.useState("");return i.useEffect(()=>{m().then(r).catch(c=>l(c.message))},[]),a?s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsx(n,{variant:"danger",children:a})]}):e?s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsxs("div",{className:"row g-3 mb-4",children:[s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-world",title:"Websites",value:e.site_count})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-folder-share",title:"FTP Accounts",value:e.ftp_count})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-database",title:"Databases",value:e.database_count})})]}),s.jsxs("div",{className:"row g-3",children:[s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-cpu",title:"CPU",value:`${e.system.cpu_percent}%`})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-device-desktop",title:"Memory",value:`${e.system.memory_percent}%`,subtitle:`${e.system.memory_used_mb} / ${e.system.memory_total_mb} MB`})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-database-export",title:"Disk",value:`${e.system.disk_percent}%`,subtitle:`${e.system.disk_used_gb} / ${e.system.disk_total_gb} GB`})})]})]}):s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsx("div",{className:"placeholder-glow",children:s.jsx("span",{className:"placeholder col-12 rounded",style:{height:"8rem"}})})]})}function t({iconClass:e,title:r,value:a,subtitle:l}){return s.jsxs(o,{className:"border-0 shadow-sm",bodyClassName:"d-flex align-items-center gap-3",children:[s.jsx("span",{className:"avatar avatar-md bg-primary-transparent text-primary rounded-circle d-flex align-items-center justify-content-center flex-shrink-0",children:s.jsx("i",{className:`${e} fs-4`,"aria-hidden":!0})}),s.jsxs("div",{children:[s.jsx("p",{className:"text-muted mb-0 small",children:r}),s.jsx("p",{className:"fs-4 fw-semibold mb-0",children:a}),l?s.jsx("p",{className:"text-muted small mb-0",children:l}):null]})]})}export{p as DashboardPage};
|
import{r as i,g as m,j as s}from"./index-Cvh4tLHo.js";import{A as n}from"./AdminAlert-Bt3L8_zJ.js";import{A as o}from"./AdminCard-BYkisaPa.js";import{P as d}from"./PageHeader-D6k34vvM.js";function p(){const[e,r]=i.useState(null),[a,l]=i.useState("");return i.useEffect(()=>{m().then(r).catch(c=>l(c.message))},[]),a?s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsx(n,{variant:"danger",children:a})]}):e?s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsxs("div",{className:"row g-3 mb-4",children:[s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-world",title:"Websites",value:e.site_count})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-folder-share",title:"FTP Accounts",value:e.ftp_count})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-database",title:"Databases",value:e.database_count})})]}),s.jsxs("div",{className:"row g-3",children:[s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-cpu",title:"CPU",value:`${e.system.cpu_percent}%`})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-device-desktop",title:"Memory",value:`${e.system.memory_percent}%`,subtitle:`${e.system.memory_used_mb} / ${e.system.memory_total_mb} MB`})}),s.jsx("div",{className:"col-md-4 d-flex",children:s.jsx(t,{iconClass:"ti ti-database-export",title:"Disk",value:`${e.system.disk_percent}%`,subtitle:`${e.system.disk_used_gb} / ${e.system.disk_total_gb} GB`})})]})]}):s.jsxs(s.Fragment,{children:[s.jsx(d,{}),s.jsx("div",{className:"placeholder-glow",children:s.jsx("span",{className:"placeholder col-12 rounded",style:{height:"8rem"}})})]})}function t({iconClass:e,title:r,value:a,subtitle:l}){return s.jsxs(o,{className:"border-0 shadow-sm",bodyClassName:"d-flex align-items-center gap-3",children:[s.jsx("span",{className:"avatar avatar-md bg-primary-transparent text-primary rounded-circle d-flex align-items-center justify-content-center flex-shrink-0",children:s.jsx("i",{className:`${e} fs-4`,"aria-hidden":!0})}),s.jsxs("div",{children:[s.jsx("p",{className:"text-muted mb-0 small",children:r}),s.jsx("p",{className:"fs-4 fw-semibold mb-0",children:a}),l?s.jsx("p",{className:"text-muted small mb-0",children:l}):null]})]})}export{p as DashboardPage};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
YakPanel-server/frontend/dist/assets/DockerPage-DyZ77ivO.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/DockerPage-DyZ77ivO.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as t,j as e,a as o}from"./index-CRR9sQ49.js";import{M as l}from"./Modal-B7V4w_St.js";import{A as R}from"./AdminAlert-DW1IRWce.js";import{A as m}from"./AdminButton-Bd2cLTu3.js";import{P as N}from"./PageHeader-BcjNf7GG.js";function k(){const[d,y]=t.useState([]),[c,b]=t.useState([]),[v,u]=t.useState(!0),[x,h]=t.useState(""),[i,p]=t.useState(null),[a,n]=t.useState(null),[j,f]=t.useState(""),g=()=>{u(!0),Promise.all([o("/ssl/domains"),o("/ssl/certificates")]).then(([s,r])=>{y(s),b(r.certificates||[])}).catch(s=>h(s.message)).finally(()=>u(!1))};t.useEffect(()=>{g()},[]);const S=s=>{s.preventDefault(),a&&(p(a.name),o("/ssl/request",{method:"POST",body:JSON.stringify({domain:a.name,webroot:a.site_path,email:j})}).then(()=>{n(null),g()}).catch(r=>h(r.message)).finally(()=>p(null)))},q=s=>c.some(r=>r.name===s||r.name.startsWith(s+" "));return v?e.jsxs(e.Fragment,{children:[e.jsx(N,{title:"Domains & SSL"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(N,{title:"Domains & SSL"}),x?e.jsx(R,{className:"mb-3",children:x}):null,e.jsx("div",{className:"alert alert-warning small mb-4",children:"Request Let's Encrypt certificates for your site domains. Requires certbot and nginx configured for the domain."}),e.jsxs("div",{className:"row g-4",children:[e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header",children:"Domains (from sites)"}),e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:"20rem"},children:d.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"No domains. Add a site first."}):d.map(s=>e.jsxs("div",{className:"list-group-item d-flex align-items-center justify-content-between gap-2 flex-wrap",children:[e.jsxs("div",{className:"small",children:[e.jsx("span",{className:"font-monospace",children:s.name}),s.port!=="80"?e.jsxs("span",{className:"text-secondary ms-1",children:[":",s.port]}):null,e.jsxs("span",{className:"text-secondary ms-2",children:["(",s.site_name,")"]})]}),e.jsx("div",{children:q(s.name)?e.jsxs("span",{className:"text-success small",children:[e.jsx("i",{className:"ti ti-shield-check me-1","aria-hidden":!0}),"Cert"]}):e.jsx(m,{variant:"outline-primary",size:"sm",disabled:!!i,onClick:()=>{n(s),f("")},children:i===s.name?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):"Request SSL"})})]},s.id))})]})}),e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header",children:"Certificates"}),e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:"20rem"},children:c.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"No certificates yet"}):c.map(s=>e.jsxs("div",{className:"list-group-item d-flex align-items-center gap-2",children:[e.jsx("i",{className:"ti ti-shield-check text-success flex-shrink-0","aria-hidden":!0}),e.jsx("span",{className:"font-monospace small text-break",children:s.name})]},s.name))})]})})]}),e.jsxs(l,{show:!!a,onHide:()=>n(null),centered:!0,children:[e.jsx(l.Header,{closeButton:!0,children:e.jsxs(l.Title,{children:["Request SSL for ",a==null?void 0:a.name]})}),a?e.jsxs("form",{onSubmit:S,children:[e.jsxs(l.Body,{children:[e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Domain"}),e.jsx("input",{type:"text",value:a.name,readOnly:!0,className:"form-control-plaintext border rounded px-3 py-2 bg-body-secondary"})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Webroot (site path)"}),e.jsx("input",{type:"text",value:a.site_path,readOnly:!0,className:"form-control-plaintext border rounded px-3 py-2 bg-body-secondary"})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Email (for Let's Encrypt)"}),e.jsx("input",{type:"email",value:j,onChange:s=>f(s.target.value),placeholder:"admin@example.com",className:"form-control",required:!0})]})]}),e.jsxs(l.Footer,{children:[e.jsx(m,{type:"button",variant:"secondary",onClick:()=>n(null),children:"Cancel"}),e.jsx(m,{type:"submit",variant:"primary",disabled:!!i,children:i?"Requesting…":"Request"})]})]}):null]})]})}export{k as DomainsPage};
|
import{r as t,j as e,M as o}from"./index-Cvh4tLHo.js";import{M as l}from"./Modal-CCihVZTY.js";import{A as R}from"./AdminAlert-Bt3L8_zJ.js";import{A as m}from"./AdminButton-BKglG8kI.js";import{P as N}from"./PageHeader-D6k34vvM.js";function k(){const[d,y]=t.useState([]),[c,b]=t.useState([]),[v,u]=t.useState(!0),[x,h]=t.useState(""),[i,p]=t.useState(null),[a,n]=t.useState(null),[j,f]=t.useState(""),g=()=>{u(!0),Promise.all([o("/ssl/domains"),o("/ssl/certificates")]).then(([s,r])=>{y(s),b(r.certificates||[])}).catch(s=>h(s.message)).finally(()=>u(!1))};t.useEffect(()=>{g()},[]);const S=s=>{s.preventDefault(),a&&(p(a.name),o("/ssl/request",{method:"POST",body:JSON.stringify({domain:a.name,webroot:a.site_path,email:j})}).then(()=>{n(null),g()}).catch(r=>h(r.message)).finally(()=>p(null)))},q=s=>c.some(r=>r.name===s||r.name.startsWith(s+" "));return v?e.jsxs(e.Fragment,{children:[e.jsx(N,{title:"Domains & SSL"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(N,{title:"Domains & SSL"}),x?e.jsx(R,{className:"mb-3",children:x}):null,e.jsx("div",{className:"alert alert-warning small mb-4",children:"Request Let's Encrypt certificates for your site domains. Requires certbot and nginx configured for the domain."}),e.jsxs("div",{className:"row g-4",children:[e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header",children:"Domains (from sites)"}),e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:"20rem"},children:d.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"No domains. Add a site first."}):d.map(s=>e.jsxs("div",{className:"list-group-item d-flex align-items-center justify-content-between gap-2 flex-wrap",children:[e.jsxs("div",{className:"small",children:[e.jsx("span",{className:"font-monospace",children:s.name}),s.port!=="80"?e.jsxs("span",{className:"text-secondary ms-1",children:[":",s.port]}):null,e.jsxs("span",{className:"text-secondary ms-2",children:["(",s.site_name,")"]})]}),e.jsx("div",{children:q(s.name)?e.jsxs("span",{className:"text-success small",children:[e.jsx("i",{className:"ti ti-shield-check me-1","aria-hidden":!0}),"Cert"]}):e.jsx(m,{variant:"outline-primary",size:"sm",disabled:!!i,onClick:()=>{n(s),f("")},children:i===s.name?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):"Request SSL"})})]},s.id))})]})}),e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header",children:"Certificates"}),e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:"20rem"},children:c.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"No certificates yet"}):c.map(s=>e.jsxs("div",{className:"list-group-item d-flex align-items-center gap-2",children:[e.jsx("i",{className:"ti ti-shield-check text-success flex-shrink-0","aria-hidden":!0}),e.jsx("span",{className:"font-monospace small text-break",children:s.name})]},s.name))})]})})]}),e.jsxs(l,{show:!!a,onHide:()=>n(null),centered:!0,children:[e.jsx(l.Header,{closeButton:!0,children:e.jsxs(l.Title,{children:["Request SSL for ",a==null?void 0:a.name]})}),a?e.jsxs("form",{onSubmit:S,children:[e.jsxs(l.Body,{children:[e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Domain"}),e.jsx("input",{type:"text",value:a.name,readOnly:!0,className:"form-control-plaintext border rounded px-3 py-2 bg-body-secondary"})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Webroot (site path)"}),e.jsx("input",{type:"text",value:a.site_path,readOnly:!0,className:"form-control-plaintext border rounded px-3 py-2 bg-body-secondary"})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Email (for Let's Encrypt)"}),e.jsx("input",{type:"email",value:j,onChange:s=>f(s.target.value),placeholder:"admin@example.com",className:"form-control",required:!0})]})]}),e.jsxs(l.Footer,{children:[e.jsx(m,{type:"button",variant:"secondary",onClick:()=>n(null),children:"Cancel"}),e.jsx(m,{type:"submit",variant:"primary",disabled:!!i,children:i?"Requesting…":"Request"})]})]}):null]})]})}export{k as DomainsPage};
|
||||||
@@ -1 +1 @@
|
|||||||
import{j as t}from"./index-CRR9sQ49.js";function m({iconClass:s="ti ti-inbox",title:a,description:e,action:i}){return t.jsxs("div",{className:"text-center py-5 text-muted",children:[t.jsx("i",{className:`${s} display-4 d-block mb-3`,"aria-hidden":!0}),t.jsx("h5",{className:"text-body",children:a}),e?t.jsx("p",{className:"mb-3",children:e}):null,i]})}export{m as E};
|
import{j as t}from"./index-Cvh4tLHo.js";function m({iconClass:s="ti ti-inbox",title:a,description:e,action:i}){return t.jsxs("div",{className:"text-center py-5 text-muted",children:[t.jsx("i",{className:`${s} display-4 d-block mb-3`,"aria-hidden":!0}),t.jsx("h5",{className:"text-body",children:a}),e?t.jsx("p",{className:"mb-3",children:e}):null,i]})}export{m as E};
|
||||||
File diff suppressed because one or more lines are too long
1
YakPanel-server/frontend/dist/assets/FilesPage-oDxR4Lhi.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/FilesPage-oDxR4Lhi.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as t,j as e,a as p,V as k}from"./index-CRR9sQ49.js";import{M as r}from"./Modal-B7V4w_St.js";import{A as y}from"./AdminAlert-DW1IRWce.js";import{A as c}from"./AdminButton-Bd2cLTu3.js";import{A as D}from"./AdminTable-BLiLxfnS.js";import{E as H}from"./EmptyState-C61VdEFl.js";import{P as g}from"./PageHeader-BcjNf7GG.js";function W(){const[o,v]=t.useState([]),[A,x]=t.useState(!0),[u,d]=t.useState(""),[w,a]=t.useState(!1),[j,f]=t.useState(!1),[N,m]=t.useState(""),[h,b]=t.useState(!1),n=()=>{x(!0),p("/firewall/list").then(v).catch(s=>d(s.message)).finally(()=>x(!1))};t.useEffect(()=>{n()},[]);const S=s=>{s.preventDefault();const l=s.currentTarget,i=l.elements.namedItem("port").value.trim(),E=l.elements.namedItem("protocol").value,F=l.elements.namedItem("action").value,R=l.elements.namedItem("ps").value.trim();if(!i){m("Port is required");return}f(!0),m(""),p("/firewall/create",{method:"POST",body:JSON.stringify({port:i,protocol:E,action:F,ps:R})}).then(()=>{a(!1),l.reset(),n()}).catch(T=>m(T.message)).finally(()=>f(!1))},C=(s,l)=>{confirm(`Delete rule for port ${l}?`)&&p(`/firewall/${s}`,{method:"DELETE"}).then(n).catch(i=>d(i.message))},P=()=>{b(!0),k().then(()=>n()).catch(s=>d(s.message)).finally(()=>b(!1))};return A?e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Security / Firewall"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Security / Firewall",actions:e.jsxs("div",{className:"d-flex flex-wrap gap-2",children:[e.jsxs(c,{variant:"success",disabled:h||o.length===0,onClick:P,children:[h?e.jsx("span",{className:"spinner-border spinner-border-sm me-1",role:"status"}):e.jsx("i",{className:"ti ti-bolt me-1","aria-hidden":!0}),h?"Applying…":"Apply to UFW"]}),e.jsxs(c,{variant:"primary",onClick:()=>a(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add Rule"]})]})}),u?e.jsx(y,{className:"mb-3",children:u}):null,e.jsxs("div",{className:"alert alert-warning small mb-3",children:['Rules are stored in the panel. Click "Apply to UFW" to run ',e.jsx("code",{className:"font-monospace",children:"ufw allow/deny"})," for each rule."]}),e.jsxs(r,{show:w,onHide:()=>a(!1),centered:!0,children:[e.jsx(r.Header,{closeButton:!0,children:e.jsx(r.Title,{children:"Add Firewall Rule"})}),e.jsxs("form",{onSubmit:S,children:[e.jsxs(r.Body,{children:[N?e.jsx(y,{className:"mb-3",children:N}):null,e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Port"}),e.jsx("input",{name:"port",type:"text",placeholder:"80 or 80-90 or 80,443",className:"form-control",required:!0})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Protocol"}),e.jsxs("select",{name:"protocol",className:"form-select",children:[e.jsx("option",{value:"tcp",children:"TCP"}),e.jsx("option",{value:"udp",children:"UDP"})]})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Action"}),e.jsxs("select",{name:"action",className:"form-select",children:[e.jsx("option",{value:"accept",children:"Accept"}),e.jsx("option",{value:"drop",children:"Drop"}),e.jsx("option",{value:"reject",children:"Reject"})]})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Note (optional)"}),e.jsx("input",{name:"ps",type:"text",placeholder:"HTTP",className:"form-control"})]})]}),e.jsxs(r.Footer,{children:[e.jsx(c,{type:"button",variant:"secondary",onClick:()=>a(!1),children:"Cancel"}),e.jsx(c,{type:"submit",variant:"primary",disabled:j,children:j?"Adding…":"Add"})]})]})]}),e.jsx("div",{className:"card",children:e.jsxs(D,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Port"}),e.jsx("th",{children:"Protocol"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Note"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:o.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"p-0",children:e.jsx(H,{title:"No rules",description:'Click "Add Rule" to create one.'})})}):o.map(s=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-monospace",children:s.port}),e.jsx("td",{children:s.protocol}),e.jsx("td",{children:s.action}),e.jsx("td",{children:s.ps||"—"}),e.jsx("td",{className:"text-end",children:e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Delete",onClick:()=>C(s.id,s.port),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})})]},s.id))})]})})]})}export{W as FirewallPage};
|
import{r as t,j as e,M as p,_ as k}from"./index-Cvh4tLHo.js";import{M as r}from"./Modal-CCihVZTY.js";import{A as y}from"./AdminAlert-Bt3L8_zJ.js";import{A as c}from"./AdminButton-BKglG8kI.js";import{A as D}from"./AdminTable-BQ5Lf7EC.js";import{E as H}from"./EmptyState-D6lCh4WN.js";import{P as g}from"./PageHeader-D6k34vvM.js";function W(){const[o,v]=t.useState([]),[A,x]=t.useState(!0),[u,d]=t.useState(""),[w,a]=t.useState(!1),[j,f]=t.useState(!1),[N,m]=t.useState(""),[h,b]=t.useState(!1),n=()=>{x(!0),p("/firewall/list").then(v).catch(s=>d(s.message)).finally(()=>x(!1))};t.useEffect(()=>{n()},[]);const S=s=>{s.preventDefault();const l=s.currentTarget,i=l.elements.namedItem("port").value.trim(),E=l.elements.namedItem("protocol").value,F=l.elements.namedItem("action").value,R=l.elements.namedItem("ps").value.trim();if(!i){m("Port is required");return}f(!0),m(""),p("/firewall/create",{method:"POST",body:JSON.stringify({port:i,protocol:E,action:F,ps:R})}).then(()=>{a(!1),l.reset(),n()}).catch(T=>m(T.message)).finally(()=>f(!1))},C=(s,l)=>{confirm(`Delete rule for port ${l}?`)&&p(`/firewall/${s}`,{method:"DELETE"}).then(n).catch(i=>d(i.message))},P=()=>{b(!0),k().then(()=>n()).catch(s=>d(s.message)).finally(()=>b(!1))};return A?e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Security / Firewall"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Security / Firewall",actions:e.jsxs("div",{className:"d-flex flex-wrap gap-2",children:[e.jsxs(c,{variant:"success",disabled:h||o.length===0,onClick:P,children:[h?e.jsx("span",{className:"spinner-border spinner-border-sm me-1",role:"status"}):e.jsx("i",{className:"ti ti-bolt me-1","aria-hidden":!0}),h?"Applying…":"Apply to UFW"]}),e.jsxs(c,{variant:"primary",onClick:()=>a(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add Rule"]})]})}),u?e.jsx(y,{className:"mb-3",children:u}):null,e.jsxs("div",{className:"alert alert-warning small mb-3",children:['Rules are stored in the panel. Click "Apply to UFW" to run ',e.jsx("code",{className:"font-monospace",children:"ufw allow/deny"})," for each rule."]}),e.jsxs(r,{show:w,onHide:()=>a(!1),centered:!0,children:[e.jsx(r.Header,{closeButton:!0,children:e.jsx(r.Title,{children:"Add Firewall Rule"})}),e.jsxs("form",{onSubmit:S,children:[e.jsxs(r.Body,{children:[N?e.jsx(y,{className:"mb-3",children:N}):null,e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Port"}),e.jsx("input",{name:"port",type:"text",placeholder:"80 or 80-90 or 80,443",className:"form-control",required:!0})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Protocol"}),e.jsxs("select",{name:"protocol",className:"form-select",children:[e.jsx("option",{value:"tcp",children:"TCP"}),e.jsx("option",{value:"udp",children:"UDP"})]})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Action"}),e.jsxs("select",{name:"action",className:"form-select",children:[e.jsx("option",{value:"accept",children:"Accept"}),e.jsx("option",{value:"drop",children:"Drop"}),e.jsx("option",{value:"reject",children:"Reject"})]})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Note (optional)"}),e.jsx("input",{name:"ps",type:"text",placeholder:"HTTP",className:"form-control"})]})]}),e.jsxs(r.Footer,{children:[e.jsx(c,{type:"button",variant:"secondary",onClick:()=>a(!1),children:"Cancel"}),e.jsx(c,{type:"submit",variant:"primary",disabled:j,children:j?"Adding…":"Add"})]})]})]}),e.jsx("div",{className:"card",children:e.jsxs(D,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Port"}),e.jsx("th",{children:"Protocol"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Note"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:o.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:5,className:"p-0",children:e.jsx(H,{title:"No rules",description:'Click "Add Rule" to create one.'})})}):o.map(s=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-monospace",children:s.port}),e.jsx("td",{children:s.protocol}),e.jsx("td",{children:s.action}),e.jsx("td",{children:s.ps||"—"}),e.jsx("td",{className:"text-end",children:e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Delete",onClick:()=>C(s.id,s.port),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})})]},s.id))})]})})]})}export{W as FirewallPage};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as t,T as p,j as e,U as C}from"./index-CRR9sQ49.js";import{A as P}from"./AdminAlert-DW1IRWce.js";import{A as g}from"./AdminButton-Bd2cLTu3.js";import{P as E}from"./PageHeader-BcjNf7GG.js";function _(a){return a<1024?a+" B":a<1024*1024?(a/1024).toFixed(1)+" KB":(a/1024/1024).toFixed(1)+" MB"}function $(){const[a,j]=t.useState("/"),[m,N]=t.useState([]),[v,x]=t.useState(!0),[h,i]=t.useState(""),[l,y]=t.useState(null),[b,u]=t.useState(""),[o,r]=t.useState(!1),[c,w]=t.useState(500),d=s=>{x(!0),i(""),C(s).then(n=>{j(n.path),N(n.items.sort((f,F)=>f.is_dir===F.is_dir?0:f.is_dir?-1:1))}).catch(n=>i(n.message)).finally(()=>x(!1))};t.useEffect(()=>{d(a)},[]),t.useEffect(()=>{l&&(r(!0),p(l,c).then(s=>u(s.content)).catch(s=>i(s.message)).finally(()=>r(!1)))},[l,c]);const k=s=>{if(s.is_dir){const n=a==="/"?"/"+s.name:a+"/"+s.name;d(n)}else y(a==="/"?s.name:a+"/"+s.name)},L=()=>{const s=a.replace(/\/$/,"").split("/").filter(Boolean);if(s.length<=1)return;s.pop();const n=s.length===0?"/":"/"+s.join("/");d(n)},S=()=>{l&&(r(!0),p(l,c).then(s=>u(s.content)).catch(s=>i(s.message)).finally(()=>r(!1)))},B=a.split("/").filter(Boolean).length>0;return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:"Logs"}),e.jsxs("div",{className:"d-flex flex-wrap align-items-center gap-2 mb-3",children:[e.jsxs(g,{variant:"secondary",size:"sm",onClick:L,disabled:!B,children:[e.jsx("i",{className:"ti ti-arrow-left me-1","aria-hidden":!0}),"Back"]}),e.jsxs("code",{className:"small bg-body-secondary px-2 py-1 rounded text-break",children:["Path: ",a||"/"]})]}),h?e.jsx(P,{className:"mb-3",children:h}):null,e.jsxs("div",{className:"row g-3",children:[e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header small fw-medium",children:"Log files"}),v?e.jsx("div",{className:"card-body text-center py-5",children:e.jsx("span",{className:"spinner-border text-secondary",role:"status"})}):e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:500},children:m.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"Empty directory"}):m.map(s=>e.jsxs("button",{type:"button",className:"list-group-item list-group-item-action d-flex gap-2 align-items-center",onClick:()=>k(s),children:[e.jsx("i",{className:`ti flex-shrink-0 ${s.is_dir?"ti-folder text-warning":"ti-file text-secondary"}`,"aria-hidden":!0}),e.jsx("span",{className:"text-truncate",children:s.name}),s.is_dir?null:e.jsx("span",{className:"small text-secondary ms-auto flex-shrink-0",children:_(s.size)})]},s.name))})]})}),e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100 d-flex flex-column",style:{minHeight:400},children:[e.jsxs("div",{className:"card-header d-flex align-items-center justify-content-between gap-2 flex-wrap",children:[e.jsx("span",{className:"small fw-medium text-truncate",children:l||"Select a log file"}),l?e.jsxs("div",{className:"d-flex align-items-center gap-2 flex-shrink-0",children:[e.jsx("label",{className:"small text-secondary mb-0",children:"Lines:"}),e.jsxs("select",{value:c,onChange:s=>w(Number(s.target.value)),className:"form-select form-select-sm",style:{width:"auto"},children:[e.jsx("option",{value:100,children:"100"}),e.jsx("option",{value:500,children:"500"}),e.jsx("option",{value:1e3,children:"1000"}),e.jsx("option",{value:5e3,children:"5000"}),e.jsx("option",{value:1e4,children:"10000"})]}),e.jsx(g,{variant:"light",size:"sm",onClick:S,disabled:o,title:"Refresh",children:o?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):e.jsx("i",{className:"ti ti-refresh","aria-hidden":!0})})]}):null]}),e.jsx("div",{className:"card-body flex-grow-1 overflow-auto",children:l?o?e.jsx("div",{className:"text-center py-5",children:e.jsx("span",{className:"spinner-border text-secondary",role:"status"})}):e.jsx("pre",{className:"font-monospace small mb-0 text-break",style:{whiteSpace:"pre-wrap"},children:b||"(empty)"}):e.jsx("p",{className:"text-secondary small mb-0",children:"Click a log file to view"})})]})})]})]})}export{$ as LogsPage};
|
import{r as t,Y as p,j as e,Z as C}from"./index-Cvh4tLHo.js";import{A as P}from"./AdminAlert-Bt3L8_zJ.js";import{A as g}from"./AdminButton-BKglG8kI.js";import{P as E}from"./PageHeader-D6k34vvM.js";function _(a){return a<1024?a+" B":a<1024*1024?(a/1024).toFixed(1)+" KB":(a/1024/1024).toFixed(1)+" MB"}function D(){const[a,j]=t.useState("/"),[m,N]=t.useState([]),[v,x]=t.useState(!0),[h,i]=t.useState(""),[l,y]=t.useState(null),[b,u]=t.useState(""),[o,r]=t.useState(!1),[c,w]=t.useState(500),d=s=>{x(!0),i(""),C(s).then(n=>{j(n.path),N(n.items.sort((f,F)=>f.is_dir===F.is_dir?0:f.is_dir?-1:1))}).catch(n=>i(n.message)).finally(()=>x(!1))};t.useEffect(()=>{d(a)},[]),t.useEffect(()=>{l&&(r(!0),p(l,c).then(s=>u(s.content)).catch(s=>i(s.message)).finally(()=>r(!1)))},[l,c]);const k=s=>{if(s.is_dir){const n=a==="/"?"/"+s.name:a+"/"+s.name;d(n)}else y(a==="/"?s.name:a+"/"+s.name)},L=()=>{const s=a.replace(/\/$/,"").split("/").filter(Boolean);if(s.length<=1)return;s.pop();const n=s.length===0?"/":"/"+s.join("/");d(n)},S=()=>{l&&(r(!0),p(l,c).then(s=>u(s.content)).catch(s=>i(s.message)).finally(()=>r(!1)))},B=a.split("/").filter(Boolean).length>0;return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:"Logs"}),e.jsxs("div",{className:"d-flex flex-wrap align-items-center gap-2 mb-3",children:[e.jsxs(g,{variant:"secondary",size:"sm",onClick:L,disabled:!B,children:[e.jsx("i",{className:"ti ti-arrow-left me-1","aria-hidden":!0}),"Back"]}),e.jsxs("code",{className:"small bg-body-secondary px-2 py-1 rounded text-break",children:["Path: ",a||"/"]})]}),h?e.jsx(P,{className:"mb-3",children:h}):null,e.jsxs("div",{className:"row g-3",children:[e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100",children:[e.jsx("div",{className:"card-header small fw-medium",children:"Log files"}),v?e.jsx("div",{className:"card-body text-center py-5",children:e.jsx("span",{className:"spinner-border text-secondary",role:"status"})}):e.jsx("div",{className:"list-group list-group-flush overflow-auto",style:{maxHeight:500},children:m.length===0?e.jsx("div",{className:"list-group-item text-secondary text-center py-4",children:"Empty directory"}):m.map(s=>e.jsxs("button",{type:"button",className:"list-group-item list-group-item-action d-flex gap-2 align-items-center",onClick:()=>k(s),children:[e.jsx("i",{className:`ti flex-shrink-0 ${s.is_dir?"ti-folder text-warning":"ti-file text-secondary"}`,"aria-hidden":!0}),e.jsx("span",{className:"text-truncate",children:s.name}),s.is_dir?null:e.jsx("span",{className:"small text-secondary ms-auto flex-shrink-0",children:_(s.size)})]},s.name))})]})}),e.jsx("div",{className:"col-lg-6",children:e.jsxs("div",{className:"card h-100 d-flex flex-column",style:{minHeight:400},children:[e.jsxs("div",{className:"card-header d-flex align-items-center justify-content-between gap-2 flex-wrap",children:[e.jsx("span",{className:"small fw-medium text-truncate",children:l||"Select a log file"}),l?e.jsxs("div",{className:"d-flex align-items-center gap-2 flex-shrink-0",children:[e.jsx("label",{className:"small text-secondary mb-0",children:"Lines:"}),e.jsxs("select",{value:c,onChange:s=>w(Number(s.target.value)),className:"form-select form-select-sm",style:{width:"auto"},children:[e.jsx("option",{value:100,children:"100"}),e.jsx("option",{value:500,children:"500"}),e.jsx("option",{value:1e3,children:"1000"}),e.jsx("option",{value:5e3,children:"5000"}),e.jsx("option",{value:1e4,children:"10000"})]}),e.jsx(g,{variant:"light",size:"sm",onClick:S,disabled:o,title:"Refresh",children:o?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):e.jsx("i",{className:"ti ti-refresh","aria-hidden":!0})})]}):null]}),e.jsx("div",{className:"card-body flex-grow-1 overflow-auto",children:l?o?e.jsx("div",{className:"text-center py-5",children:e.jsx("span",{className:"spinner-border text-secondary",role:"status"})}):e.jsx("pre",{className:"font-monospace small mb-0 text-break",style:{whiteSpace:"pre-wrap"},children:b||"(empty)"}):e.jsx("p",{className:"text-secondary small mb-0",children:"Click a log file to view"})})]})})]})]})}export{D as LogsPage};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r,j as s,a as b,O as g,P as v}from"./index-CRR9sQ49.js";import{A as N}from"./AdminAlert-DW1IRWce.js";import{A as y}from"./AdminTable-BLiLxfnS.js";import{P as o}from"./PageHeader-BcjNf7GG.js";function M(){const[e,d]=r.useState(null),[c,l]=r.useState([]),[t,n]=r.useState(null),[i,p]=r.useState("");return r.useEffect(()=>{const a=()=>{b("/monitor/system").then(d).catch(m=>p(m.message))},h=()=>{g(50).then(m=>l(m.processes)).catch(()=>l([]))},j=()=>{v().then(n).catch(()=>n(null))};a(),h(),j();const u=setInterval(()=>{a(),h(),j()},3e3);return()=>clearInterval(u)},[]),i&&!e?s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),s.jsx(N,{children:i})]}):e?s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),i?s.jsx(N,{className:"mb-3",children:i}):null,s.jsx("p",{className:"small text-secondary mb-3",children:"Refreshes every 3 seconds"}),s.jsxs("div",{className:"row g-3 mb-3",children:[s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-cpu",title:"CPU",value:`${e.cpu_percent}%`,subtitle:"Usage",percent:e.cpu_percent})}),s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-device-sd-card",title:"Memory",value:`${e.memory_used_mb} / ${e.memory_total_mb} MB`,subtitle:`${e.memory_percent}% used`,percent:e.memory_percent})}),s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-database",title:"Disk",value:`${e.disk_used_gb} / ${e.disk_total_gb} GB`,subtitle:`${e.disk_percent}% used`,percent:e.disk_percent})})]}),t?s.jsx("div",{className:"card mb-3",children:s.jsxs("div",{className:"card-body",children:[s.jsxs("div",{className:"d-flex align-items-center gap-2 mb-3",children:[s.jsx("i",{className:"ti ti-network fs-5","aria-hidden":!0}),s.jsx("span",{className:"fw-medium",children:"Network I/O"})]}),s.jsxs("div",{className:"row g-3 small",children:[s.jsxs("div",{className:"col-6",children:[s.jsx("span",{className:"text-secondary d-block",children:"Sent"}),s.jsxs("span",{className:"font-monospace fw-medium",children:[t.bytes_sent_mb," MB"]})]}),s.jsxs("div",{className:"col-6",children:[s.jsx("span",{className:"text-secondary d-block",children:"Received"}),s.jsxs("span",{className:"font-monospace fw-medium",children:[t.bytes_recv_mb," MB"]})]})]})]})}):null,s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"card-header d-flex align-items-center gap-2",children:[s.jsx("i",{className:"ti ti-cpu","aria-hidden":!0}),s.jsx("span",{className:"fw-medium",children:"Top Processes (by CPU)"})]}),s.jsx("div",{className:"table-responsive",style:{maxHeight:"20rem"},children:s.jsxs(y,{responsive:!1,children:[s.jsx("thead",{className:"sticky-top bg-body-secondary",children:s.jsxs("tr",{children:[s.jsx("th",{className:"small",children:"PID"}),s.jsx("th",{className:"small",children:"Name"}),s.jsx("th",{className:"small",children:"User"}),s.jsx("th",{className:"small text-end",children:"CPU %"}),s.jsx("th",{className:"small text-end",children:"Mem %"}),s.jsx("th",{className:"small",children:"Status"})]})}),s.jsx("tbody",{children:c.length===0?s.jsx("tr",{children:s.jsx("td",{colSpan:6,className:"text-center text-secondary small py-3",children:"No process data"})}):c.map(a=>s.jsxs("tr",{className:"small",children:[s.jsx("td",{className:"font-monospace",children:a.pid}),s.jsx("td",{className:"text-truncate",style:{maxWidth:120},title:a.name,children:a.name}),s.jsx("td",{children:a.username}),s.jsxs("td",{className:"text-end font-monospace",children:[a.cpu_percent,"%"]}),s.jsxs("td",{className:"text-end font-monospace",children:[a.memory_percent,"%"]}),s.jsx("td",{className:"text-secondary",children:a.status})]},a.pid))})]})})]}),s.jsxs("div",{className:"alert alert-warning small mt-3 mb-0",children:[s.jsxs("div",{className:"d-flex align-items-center gap-2 fw-medium mb-1",children:[s.jsx("i",{className:"ti ti-activity","aria-hidden":!0}),"Live monitoring"]}),"System metrics, processes, and network stats are polled every 3 seconds."]})]}):s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),s.jsx("p",{className:"text-secondary",children:"Loading…"})]})}function x({iconClass:e,title:d,value:c,subtitle:l,percent:t}){const n=t>90?"bg-danger":t>70?"bg-warning":"bg-primary";return s.jsx("div",{className:"card h-100",children:s.jsxs("div",{className:"card-body",children:[s.jsxs("div",{className:"d-flex align-items-center gap-3 mb-3",children:[s.jsx("div",{className:"p-3 rounded bg-primary-subtle text-primary",children:s.jsx("i",{className:`${e} fs-2`,"aria-hidden":!0})}),s.jsxs("div",{children:[s.jsx("p",{className:"small text-secondary mb-0",children:d}),s.jsx("p",{className:"h5 mb-0",children:c}),s.jsx("p",{className:"small text-secondary mb-0",children:l})]})]}),s.jsx("div",{className:"progress",style:{height:6},children:s.jsx("div",{className:`progress-bar ${n}`,role:"progressbar",style:{width:`${Math.min(t,100)}%`}})})]})})}export{M as MonitorPage};
|
import{r,j as s,M as b,T as g,U as v}from"./index-Cvh4tLHo.js";import{A as N}from"./AdminAlert-Bt3L8_zJ.js";import{A as y}from"./AdminTable-BQ5Lf7EC.js";import{P as o}from"./PageHeader-D6k34vvM.js";function M(){const[e,d]=r.useState(null),[c,l]=r.useState([]),[t,n]=r.useState(null),[i,p]=r.useState("");return r.useEffect(()=>{const a=()=>{b("/monitor/system").then(d).catch(m=>p(m.message))},h=()=>{g(50).then(m=>l(m.processes)).catch(()=>l([]))},j=()=>{v().then(n).catch(()=>n(null))};a(),h(),j();const u=setInterval(()=>{a(),h(),j()},3e3);return()=>clearInterval(u)},[]),i&&!e?s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),s.jsx(N,{children:i})]}):e?s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),i?s.jsx(N,{className:"mb-3",children:i}):null,s.jsx("p",{className:"small text-secondary mb-3",children:"Refreshes every 3 seconds"}),s.jsxs("div",{className:"row g-3 mb-3",children:[s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-cpu",title:"CPU",value:`${e.cpu_percent}%`,subtitle:"Usage",percent:e.cpu_percent})}),s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-device-sd-card",title:"Memory",value:`${e.memory_used_mb} / ${e.memory_total_mb} MB`,subtitle:`${e.memory_percent}% used`,percent:e.memory_percent})}),s.jsx("div",{className:"col-md-4",children:s.jsx(x,{iconClass:"ti ti-database",title:"Disk",value:`${e.disk_used_gb} / ${e.disk_total_gb} GB`,subtitle:`${e.disk_percent}% used`,percent:e.disk_percent})})]}),t?s.jsx("div",{className:"card mb-3",children:s.jsxs("div",{className:"card-body",children:[s.jsxs("div",{className:"d-flex align-items-center gap-2 mb-3",children:[s.jsx("i",{className:"ti ti-network fs-5","aria-hidden":!0}),s.jsx("span",{className:"fw-medium",children:"Network I/O"})]}),s.jsxs("div",{className:"row g-3 small",children:[s.jsxs("div",{className:"col-6",children:[s.jsx("span",{className:"text-secondary d-block",children:"Sent"}),s.jsxs("span",{className:"font-monospace fw-medium",children:[t.bytes_sent_mb," MB"]})]}),s.jsxs("div",{className:"col-6",children:[s.jsx("span",{className:"text-secondary d-block",children:"Received"}),s.jsxs("span",{className:"font-monospace fw-medium",children:[t.bytes_recv_mb," MB"]})]})]})]})}):null,s.jsxs("div",{className:"card",children:[s.jsxs("div",{className:"card-header d-flex align-items-center gap-2",children:[s.jsx("i",{className:"ti ti-cpu","aria-hidden":!0}),s.jsx("span",{className:"fw-medium",children:"Top Processes (by CPU)"})]}),s.jsx("div",{className:"table-responsive",style:{maxHeight:"20rem"},children:s.jsxs(y,{responsive:!1,children:[s.jsx("thead",{className:"sticky-top bg-body-secondary",children:s.jsxs("tr",{children:[s.jsx("th",{className:"small",children:"PID"}),s.jsx("th",{className:"small",children:"Name"}),s.jsx("th",{className:"small",children:"User"}),s.jsx("th",{className:"small text-end",children:"CPU %"}),s.jsx("th",{className:"small text-end",children:"Mem %"}),s.jsx("th",{className:"small",children:"Status"})]})}),s.jsx("tbody",{children:c.length===0?s.jsx("tr",{children:s.jsx("td",{colSpan:6,className:"text-center text-secondary small py-3",children:"No process data"})}):c.map(a=>s.jsxs("tr",{className:"small",children:[s.jsx("td",{className:"font-monospace",children:a.pid}),s.jsx("td",{className:"text-truncate",style:{maxWidth:120},title:a.name,children:a.name}),s.jsx("td",{children:a.username}),s.jsxs("td",{className:"text-end font-monospace",children:[a.cpu_percent,"%"]}),s.jsxs("td",{className:"text-end font-monospace",children:[a.memory_percent,"%"]}),s.jsx("td",{className:"text-secondary",children:a.status})]},a.pid))})]})})]}),s.jsxs("div",{className:"alert alert-warning small mt-3 mb-0",children:[s.jsxs("div",{className:"d-flex align-items-center gap-2 fw-medium mb-1",children:[s.jsx("i",{className:"ti ti-activity","aria-hidden":!0}),"Live monitoring"]}),"System metrics, processes, and network stats are polled every 3 seconds."]})]}):s.jsxs(s.Fragment,{children:[s.jsx(o,{title:"Monitor"}),s.jsx("p",{className:"text-secondary",children:"Loading…"})]})}function x({iconClass:e,title:d,value:c,subtitle:l,percent:t}){const n=t>90?"bg-danger":t>70?"bg-warning":"bg-primary";return s.jsx("div",{className:"card h-100",children:s.jsxs("div",{className:"card-body",children:[s.jsxs("div",{className:"d-flex align-items-center gap-3 mb-3",children:[s.jsx("div",{className:"p-3 rounded bg-primary-subtle text-primary",children:s.jsx("i",{className:`${e} fs-2`,"aria-hidden":!0})}),s.jsxs("div",{children:[s.jsx("p",{className:"small text-secondary mb-0",children:d}),s.jsx("p",{className:"h5 mb-0",children:c}),s.jsx("p",{className:"small text-secondary mb-0",children:l})]})]}),s.jsx("div",{className:"progress",style:{height:6},children:s.jsx("div",{className:`progress-bar ${n}`,role:"progressbar",style:{width:`${Math.min(t,100)}%`}})})]})})}export{M as MonitorPage};
|
||||||
File diff suppressed because one or more lines are too long
1
YakPanel-server/frontend/dist/assets/NodePage-DOIEhdrc.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/NodePage-DOIEhdrc.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{av as c,j as e,aw as m}from"./index-CRR9sQ49.js";const d={"/":"Dashboard","/site":"Website","/ftp":"FTP","/database":"Databases","/docker":"Docker","/control":"Monitor","/firewall":"Security","/files":"Files","/node":"Node","/logs":"Logs","/ssl_domain":"Domains","/xterm":"Terminal","/crontab":"Cron","/soft":"App Store","/config":"Settings","/services":"Services","/plugins":"Plugins","/backup-plans":"Backup Plans","/users":"Users","/login":"Login","/install":"Remote install"};function b(t){return d[t]||"YakPanel"}function p({title:t,breadcrumbs:i,actions:n}){const{pathname:o}=c(),r=t??b(o),s=i??[{label:"Home",path:"/"},{label:r}];return e.jsx("div",{className:"page-header mb-4",children:e.jsxs("div",{className:"row align-items-center",children:[e.jsxs("div",{className:"col-md-6",children:[e.jsx("h3",{className:"page-title",children:r}),e.jsx("nav",{"aria-label":"breadcrumb",children:e.jsx("ol",{className:"breadcrumb mb-0",children:s.map((a,l)=>e.jsx("li",{className:`breadcrumb-item${l===s.length-1?" active":""}`,...l===s.length-1?{"aria-current":"page"}:{},children:a.path&&l<s.length-1?e.jsx(m,{to:a.path,children:a.label}):a.label},`${a.label}-${l}`))})})]}),n?e.jsx("div",{className:"col-md-6 d-flex justify-content-md-end mt-2 mt-md-0",children:n}):null]})})}export{p as P};
|
|
||||||
1
YakPanel-server/frontend/dist/assets/PageHeader-D6k34vvM.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/PageHeader-D6k34vvM.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{aA as c,j as e,L as m}from"./index-Cvh4tLHo.js";const d={"/":"Dashboard","/site":"Website","/ftp":"FTP","/database":"Databases","/docker":"Docker","/control":"Monitor","/firewall":"Security","/files":"Files","/node":"Node","/logs":"Logs","/ssl_domain":"Domains","/xterm":"Terminal","/crontab":"Cron","/soft":"App Store","/config":"Settings","/services":"Services","/plugins":"Plugins","/backup-plans":"Backup Plans","/users":"Users","/login":"Login","/install":"Remote install"};function b(t){return d[t]||"YakPanel"}function p({title:t,breadcrumbs:i,actions:n}){const{pathname:o}=c(),r=t??b(o),s=i??[{label:"Home",path:"/"},{label:r}];return e.jsx("div",{className:"page-header mb-4",children:e.jsxs("div",{className:"row align-items-center",children:[e.jsxs("div",{className:"col-md-6",children:[e.jsx("h3",{className:"page-title",children:r}),e.jsx("nav",{"aria-label":"breadcrumb",children:e.jsx("ol",{className:"breadcrumb mb-0",children:s.map((a,l)=>e.jsx("li",{className:`breadcrumb-item${l===s.length-1?" active":""}`,...l===s.length-1?{"aria-current":"page"}:{},children:a.path&&l<s.length-1?e.jsx(m,{to:a.path,children:a.label}):a.label},`${a.label}-${l}`))})})]}),n?e.jsx("div",{className:"col-md-6 d-flex justify-content-md-end mt-2 mt-md-0",children:n}):null]})})}export{p as P};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{r as a,j as e,a as R,$ as U,a0 as w}from"./index-CRR9sQ49.js";import{M as t}from"./Modal-B7V4w_St.js";import{A as f}from"./AdminAlert-DW1IRWce.js";import{A as r}from"./AdminButton-Bd2cLTu3.js";import{P as p}from"./PageHeader-BcjNf7GG.js";function F(){const[b,N]=a.useState([]),[v,c]=a.useState(!0),[o,m]=a.useState(""),[y,l]=a.useState(!1),[u,h]=a.useState(""),[x,j]=a.useState(!1),[g,i]=a.useState(""),d=()=>R("/plugin/list").then(s=>N(s.plugins||[])).catch(s=>m(s.message));a.useEffect(()=>{c(!0),d().finally(()=>c(!1))},[]);const A=s=>{s.preventDefault();const n=u.trim();n&&(j(!0),i(""),U(n).then(()=>{l(!1),h(""),d()}).catch(S=>i(S.message)).finally(()=>j(!1)))},P=s=>{confirm("Remove this plugin?")&&w(s).then(d).catch(n=>m(n.message))};return v?e.jsxs(e.Fragment,{children:[e.jsx(p,{title:"Plugins",actions:e.jsxs(r,{variant:"primary",disabled:!0,children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add from URL"]})}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(p,{title:"Plugins",actions:e.jsxs(r,{variant:"primary",onClick:()=>l(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add from URL"]})}),o?e.jsx(f,{className:"mb-3",children:o}):null,e.jsxs("div",{className:"alert alert-secondary small mb-4",children:["Built-in extensions and third-party plugins. Add plugins from a JSON manifest URL (must include ",e.jsx("code",{children:"id"}),","," ",e.jsx("code",{children:"name"}),", and optionally ",e.jsx("code",{children:"version"}),", ",e.jsx("code",{children:"desc"}),")."]}),e.jsxs(t,{show:y,onHide:()=>{l(!1),i("")},centered:!0,children:[e.jsx(t.Header,{closeButton:!0,children:e.jsx(t.Title,{children:"Add Plugin from URL"})}),e.jsxs("form",{onSubmit:A,children:[e.jsxs(t.Body,{children:[g?e.jsx(f,{className:"mb-3",children:g}):null,e.jsx("label",{className:"form-label",children:"Manifest URL"}),e.jsx("input",{value:u,onChange:s=>h(s.target.value),placeholder:"https://example.com/plugin.json",className:"form-control",required:!0})]}),e.jsxs(t.Footer,{children:[e.jsx(r,{type:"button",variant:"secondary",onClick:()=>{l(!1),i("")},children:"Cancel"}),e.jsx(r,{type:"submit",variant:"primary",disabled:x,children:x?"Adding…":"Add"})]})]})]}),e.jsx("div",{className:"row g-3",children:b.map(s=>e.jsx("div",{className:"col-md-6 col-xl-4",children:e.jsx("div",{className:"card h-100",children:e.jsxs("div",{className:"card-body d-flex gap-3",children:[e.jsx("i",{className:"ti ti-puzzle text-primary fs-2 flex-shrink-0","aria-hidden":!0}),e.jsxs("div",{className:"min-w-0 flex-grow-1",children:[e.jsxs("div",{className:"d-flex flex-wrap align-items-center gap-2 mb-1",children:[e.jsx("h3",{className:"h6 mb-0",children:s.name}),s.enabled?e.jsxs("span",{className:"badge bg-success-subtle text-success small",children:[e.jsx("i",{className:"ti ti-check me-1","aria-hidden":!0}),"Enabled"]}):null,s.builtin?null:e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-0 ms-auto",title:"Remove",onClick:()=>P(s.id),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})]}),e.jsx("p",{className:"small text-secondary mb-1",children:s.desc}),e.jsxs("p",{className:"small text-muted mb-0",children:["v",s.version,s.builtin?" (built-in)":""]})]})]})})},s.id))})]})}export{F as PluginsPage};
|
|
||||||
1
YakPanel-server/frontend/dist/assets/PluginsPage-D1KZQdzk.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/PluginsPage-D1KZQdzk.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{r as a,j as e,M as R,a4 as U,a5 as w}from"./index-Cvh4tLHo.js";import{M as t}from"./Modal-CCihVZTY.js";import{A as f}from"./AdminAlert-Bt3L8_zJ.js";import{A as r}from"./AdminButton-BKglG8kI.js";import{P as p}from"./PageHeader-D6k34vvM.js";function F(){const[b,N]=a.useState([]),[v,c]=a.useState(!0),[o,m]=a.useState(""),[y,l]=a.useState(!1),[u,h]=a.useState(""),[x,j]=a.useState(!1),[g,i]=a.useState(""),d=()=>R("/plugin/list").then(s=>N(s.plugins||[])).catch(s=>m(s.message));a.useEffect(()=>{c(!0),d().finally(()=>c(!1))},[]);const A=s=>{s.preventDefault();const n=u.trim();n&&(j(!0),i(""),U(n).then(()=>{l(!1),h(""),d()}).catch(S=>i(S.message)).finally(()=>j(!1)))},P=s=>{confirm("Remove this plugin?")&&w(s).then(d).catch(n=>m(n.message))};return v?e.jsxs(e.Fragment,{children:[e.jsx(p,{title:"Plugins",actions:e.jsxs(r,{variant:"primary",disabled:!0,children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add from URL"]})}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(p,{title:"Plugins",actions:e.jsxs(r,{variant:"primary",onClick:()=>l(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add from URL"]})}),o?e.jsx(f,{className:"mb-3",children:o}):null,e.jsxs("div",{className:"alert alert-secondary small mb-4",children:["Built-in extensions and third-party plugins. Add plugins from a JSON manifest URL (must include ",e.jsx("code",{children:"id"}),","," ",e.jsx("code",{children:"name"}),", and optionally ",e.jsx("code",{children:"version"}),", ",e.jsx("code",{children:"desc"}),")."]}),e.jsxs(t,{show:y,onHide:()=>{l(!1),i("")},centered:!0,children:[e.jsx(t.Header,{closeButton:!0,children:e.jsx(t.Title,{children:"Add Plugin from URL"})}),e.jsxs("form",{onSubmit:A,children:[e.jsxs(t.Body,{children:[g?e.jsx(f,{className:"mb-3",children:g}):null,e.jsx("label",{className:"form-label",children:"Manifest URL"}),e.jsx("input",{value:u,onChange:s=>h(s.target.value),placeholder:"https://example.com/plugin.json",className:"form-control",required:!0})]}),e.jsxs(t.Footer,{children:[e.jsx(r,{type:"button",variant:"secondary",onClick:()=>{l(!1),i("")},children:"Cancel"}),e.jsx(r,{type:"submit",variant:"primary",disabled:x,children:x?"Adding…":"Add"})]})]})]}),e.jsx("div",{className:"row g-3",children:b.map(s=>e.jsx("div",{className:"col-md-6 col-xl-4",children:e.jsx("div",{className:"card h-100",children:e.jsxs("div",{className:"card-body d-flex gap-3",children:[e.jsx("i",{className:"ti ti-puzzle text-primary fs-2 flex-shrink-0","aria-hidden":!0}),e.jsxs("div",{className:"min-w-0 flex-grow-1",children:[e.jsxs("div",{className:"d-flex flex-wrap align-items-center gap-2 mb-1",children:[e.jsx("h3",{className:"h6 mb-0",children:s.name}),s.enabled?e.jsxs("span",{className:"badge bg-success-subtle text-success small",children:[e.jsx("i",{className:"ti ti-check me-1","aria-hidden":!0}),"Enabled"]}):null,s.builtin?null:e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-0 ms-auto",title:"Remove",onClick:()=>P(s.id),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})]}),e.jsx("p",{className:"small text-secondary mb-1",children:s.desc}),e.jsxs("p",{className:"small text-muted mb-0",children:["v",s.version,s.builtin?" (built-in)":""]})]})]})})},s.id))})]})}export{F as PluginsPage};
|
||||||
2
YakPanel-server/frontend/dist/assets/RemoteInstallPage-19-_F3Xw.js
vendored
Normal file
2
YakPanel-server/frontend/dist/assets/RemoteInstallPage-19-_F3Xw.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r,j as e,a as l}from"./index-CRR9sQ49.js";import{A as S}from"./AdminAlert-DW1IRWce.js";import{A as g}from"./AdminButton-Bd2cLTu3.js";import{A as y}from"./AdminTable-BLiLxfnS.js";import{P as x}from"./PageHeader-BcjNf7GG.js";function u({show:d}){return d?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null}function R(){const[d,j]=r.useState([]),[p,o]=r.useState(!0),[m,c]=r.useState(""),[n,s]=r.useState(null),i=()=>{o(!0),l("/service/list").then(t=>j(t.services||[])).catch(t=>c(t.message)).finally(()=>o(!1))};r.useEffect(()=>{i()},[]);const b=t=>{s(t),l(`/service/${t}/start`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},f=t=>{s(t),l(`/service/${t}/stop`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},v=t=>{s(t),l(`/service/${t}/restart`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},h=t=>t==="active"||t==="activating";return p?e.jsxs(e.Fragment,{children:[e.jsx(x,{title:"Services"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(x,{title:"Services",actions:e.jsxs(g,{variant:"secondary",size:"sm",onClick:i,children:[e.jsx("i",{className:"ti ti-rotate-clockwise me-1","aria-hidden":!0}),"Refresh"]})}),m?e.jsx(S,{className:"mb-3",children:m}):null,e.jsx("div",{className:"alert alert-secondary small mb-3",children:"Control system services via systemctl. Requires panel to run with sufficient privileges."}),e.jsx("div",{className:"card",children:e.jsxs(y,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Service"}),e.jsx("th",{children:"Unit"}),e.jsx("th",{children:"Status"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:d.map(t=>e.jsxs("tr",{children:[e.jsx("td",{children:t.name}),e.jsx("td",{className:"font-monospace small",children:t.unit}),e.jsx("td",{children:e.jsx("span",{className:h(t.status)?"text-success":"text-secondary",children:t.status})}),e.jsx("td",{className:"text-end",children:e.jsx("span",{className:"d-inline-flex gap-1 justify-content-end",children:h(t.status)?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-warning p-1",title:"Restart",disabled:!!n,onClick:()=>v(t.id),children:n===t.id?e.jsx(u,{show:!0}):e.jsx("i",{className:"ti ti-rotate-clockwise","aria-hidden":!0})}),e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Stop",disabled:!!n,onClick:()=>f(t.id),children:e.jsx("i",{className:"ti ti-square","aria-hidden":!0})})]}):e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-success p-1",title:"Start",disabled:!!n,onClick:()=>b(t.id),children:n===t.id?e.jsx(u,{show:!0}):e.jsx("i",{className:"ti ti-player-play","aria-hidden":!0})})})})]},t.id))})]})})]})}export{R as ServicesPage};
|
import{r,j as e,M as l}from"./index-Cvh4tLHo.js";import{A as S}from"./AdminAlert-Bt3L8_zJ.js";import{A as g}from"./AdminButton-BKglG8kI.js";import{A as y}from"./AdminTable-BQ5Lf7EC.js";import{P as x}from"./PageHeader-D6k34vvM.js";function u({show:d}){return d?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null}function R(){const[d,j]=r.useState([]),[p,o]=r.useState(!0),[m,c]=r.useState(""),[n,s]=r.useState(null),i=()=>{o(!0),l("/service/list").then(t=>j(t.services||[])).catch(t=>c(t.message)).finally(()=>o(!1))};r.useEffect(()=>{i()},[]);const b=t=>{s(t),l(`/service/${t}/start`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},f=t=>{s(t),l(`/service/${t}/stop`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},v=t=>{s(t),l(`/service/${t}/restart`,{method:"POST"}).then(i).catch(a=>c(a.message)).finally(()=>s(null))},h=t=>t==="active"||t==="activating";return p?e.jsxs(e.Fragment,{children:[e.jsx(x,{title:"Services"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(x,{title:"Services",actions:e.jsxs(g,{variant:"secondary",size:"sm",onClick:i,children:[e.jsx("i",{className:"ti ti-rotate-clockwise me-1","aria-hidden":!0}),"Refresh"]})}),m?e.jsx(S,{className:"mb-3",children:m}):null,e.jsx("div",{className:"alert alert-secondary small mb-3",children:"Control system services via systemctl. Requires panel to run with sufficient privileges."}),e.jsx("div",{className:"card",children:e.jsxs(y,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Service"}),e.jsx("th",{children:"Unit"}),e.jsx("th",{children:"Status"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:d.map(t=>e.jsxs("tr",{children:[e.jsx("td",{children:t.name}),e.jsx("td",{className:"font-monospace small",children:t.unit}),e.jsx("td",{children:e.jsx("span",{className:h(t.status)?"text-success":"text-secondary",children:t.status})}),e.jsx("td",{className:"text-end",children:e.jsx("span",{className:"d-inline-flex gap-1 justify-content-end",children:h(t.status)?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-warning p-1",title:"Restart",disabled:!!n,onClick:()=>v(t.id),children:n===t.id?e.jsx(u,{show:!0}):e.jsx("i",{className:"ti ti-rotate-clockwise","aria-hidden":!0})}),e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Stop",disabled:!!n,onClick:()=>f(t.id),children:e.jsx("i",{className:"ti ti-square","aria-hidden":!0})})]}):e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-success p-1",title:"Start",disabled:!!n,onClick:()=>b(t.id),children:n===t.id?e.jsx(u,{show:!0}):e.jsx("i",{className:"ti ti-player-play","aria-hidden":!0})})})})]},t.id))})]})})]})}export{R as ServicesPage};
|
||||||
File diff suppressed because one or more lines are too long
1
YakPanel-server/frontend/dist/assets/SitePage-D5AOBBFP.js
vendored
Normal file
1
YakPanel-server/frontend/dist/assets/SitePage-D5AOBBFP.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as t,j as e,a as c}from"./index-CRR9sQ49.js";import{A as b}from"./AdminAlert-DW1IRWce.js";import{A as v}from"./AdminButton-Bd2cLTu3.js";import{P as m}from"./PageHeader-BcjNf7GG.js";function A(){const[x,u]=t.useState([]),[p,d]=t.useState(!0),[o,a]=t.useState(""),[n,l]=t.useState(null),[f,h]=t.useState(""),r=()=>{d(!0),c("/soft/list").then(s=>{u(s.software||[]),h(s.package_manager||"")}).catch(s=>a(s.message)).finally(()=>d(!1))};t.useEffect(()=>{r()},[]);const j=s=>{l(s),a(""),c(`/soft/install/${s}`,{method:"POST"}).then(()=>r()).catch(i=>a(i.message)).finally(()=>l(null))},g=(s,i)=>{confirm(`Uninstall ${i}?`)&&(l(s),a(""),c(`/soft/uninstall/${s}`,{method:"POST"}).then(()=>r()).catch(N=>a(N.message)).finally(()=>l(null)))};return p?e.jsxs(e.Fragment,{children:[e.jsx(m,{title:"App Store"}),e.jsx("div",{className:"d-flex justify-content-center py-5",children:e.jsx("div",{className:"spinner-border text-primary",role:"status",children:e.jsx("span",{className:"visually-hidden",children:"Loading…"})})})]}):e.jsxs(e.Fragment,{children:[e.jsx(m,{title:"App Store",actions:e.jsxs(v,{variant:"secondary",onClick:r,children:[e.jsx("i",{className:"ti ti-refresh me-1"}),"Refresh"]})}),o?e.jsx(b,{variant:"danger",children:o}):null,e.jsxs("div",{className:"alert alert-warning",role:"note",children:["Installs use your server package manager (",f||"unknown","). Panel must run as root (or equivalent). Supported: apt, dnf/yum/microdnf, apk."]}),e.jsx("div",{className:"row g-3",children:x.map(s=>e.jsx("div",{className:"col-md-6 col-xl-4 d-flex",children:e.jsx("div",{className:"card flex-fill shadow-sm",children:e.jsxs("div",{className:"card-body d-flex flex-column",children:[e.jsxs("div",{className:"d-flex align-items-start justify-content-between gap-2 mb-2",children:[e.jsxs("div",{className:"d-flex align-items-start gap-2",children:[e.jsx("span",{className:"avatar avatar-md bg-primary-transparent text-primary rounded flex-shrink-0",children:e.jsx("i",{className:"ti ti-package fs-5","aria-hidden":!0})}),e.jsxs("div",{children:[e.jsx("h5",{className:"card-title mb-1",children:s.name}),e.jsx("p",{className:"text-muted small mb-0",children:s.desc})]})]}),s.installed?e.jsxs("span",{className:"text-success small text-nowrap",children:[e.jsx("i",{className:"ti ti-circle-check me-1"}),s.version||"Installed"]}):e.jsxs("span",{className:"text-muted small text-nowrap",children:[e.jsx("i",{className:"ti ti-x me-1"}),"Not installed"]})]}),e.jsx("div",{className:"mt-auto pt-3",children:s.installed?e.jsxs("button",{type:"button",onClick:()=>g(s.id,s.name),disabled:n===s.id,className:"btn btn-outline-danger btn-sm w-100 d-inline-flex align-items-center justify-content-center gap-2",children:[n===s.id?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null,"Uninstall"]}):e.jsxs("button",{type:"button",onClick:()=>j(s.id),disabled:n===s.id,className:"btn btn-primary btn-sm w-100 d-inline-flex align-items-center justify-content-center gap-2",children:[n===s.id?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null,"Install"]})})]})})},s.id))})]})}export{A as SoftPage};
|
import{r as t,j as e,M as c}from"./index-Cvh4tLHo.js";import{A as b}from"./AdminAlert-Bt3L8_zJ.js";import{A as v}from"./AdminButton-BKglG8kI.js";import{P as m}from"./PageHeader-D6k34vvM.js";function A(){const[x,u]=t.useState([]),[p,d]=t.useState(!0),[o,a]=t.useState(""),[n,l]=t.useState(null),[f,h]=t.useState(""),r=()=>{d(!0),c("/soft/list").then(s=>{u(s.software||[]),h(s.package_manager||"")}).catch(s=>a(s.message)).finally(()=>d(!1))};t.useEffect(()=>{r()},[]);const j=s=>{l(s),a(""),c(`/soft/install/${s}`,{method:"POST"}).then(()=>r()).catch(i=>a(i.message)).finally(()=>l(null))},g=(s,i)=>{confirm(`Uninstall ${i}?`)&&(l(s),a(""),c(`/soft/uninstall/${s}`,{method:"POST"}).then(()=>r()).catch(N=>a(N.message)).finally(()=>l(null)))};return p?e.jsxs(e.Fragment,{children:[e.jsx(m,{title:"App Store"}),e.jsx("div",{className:"d-flex justify-content-center py-5",children:e.jsx("div",{className:"spinner-border text-primary",role:"status",children:e.jsx("span",{className:"visually-hidden",children:"Loading…"})})})]}):e.jsxs(e.Fragment,{children:[e.jsx(m,{title:"App Store",actions:e.jsxs(v,{variant:"secondary",onClick:r,children:[e.jsx("i",{className:"ti ti-refresh me-1"}),"Refresh"]})}),o?e.jsx(b,{variant:"danger",children:o}):null,e.jsxs("div",{className:"alert alert-warning",role:"note",children:["Installs use your server package manager (",f||"unknown","). Panel must run as root (or equivalent). Supported: apt, dnf/yum/microdnf, apk."]}),e.jsx("div",{className:"row g-3",children:x.map(s=>e.jsx("div",{className:"col-md-6 col-xl-4 d-flex",children:e.jsx("div",{className:"card flex-fill shadow-sm",children:e.jsxs("div",{className:"card-body d-flex flex-column",children:[e.jsxs("div",{className:"d-flex align-items-start justify-content-between gap-2 mb-2",children:[e.jsxs("div",{className:"d-flex align-items-start gap-2",children:[e.jsx("span",{className:"avatar avatar-md bg-primary-transparent text-primary rounded flex-shrink-0",children:e.jsx("i",{className:"ti ti-package fs-5","aria-hidden":!0})}),e.jsxs("div",{children:[e.jsx("h5",{className:"card-title mb-1",children:s.name}),e.jsx("p",{className:"text-muted small mb-0",children:s.desc})]})]}),s.installed?e.jsxs("span",{className:"text-success small text-nowrap",children:[e.jsx("i",{className:"ti ti-circle-check me-1"}),s.version||"Installed"]}):e.jsxs("span",{className:"text-muted small text-nowrap",children:[e.jsx("i",{className:"ti ti-x me-1"}),"Not installed"]})]}),e.jsx("div",{className:"mt-auto pt-3",children:s.installed?e.jsxs("button",{type:"button",onClick:()=>g(s.id,s.name),disabled:n===s.id,className:"btn btn-outline-danger btn-sm w-100 d-inline-flex align-items-center justify-content-center gap-2",children:[n===s.id?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null,"Uninstall"]}):e.jsxs("button",{type:"button",onClick:()=>j(s.id),disabled:n===s.id,className:"btn btn-primary btn-sm w-100 d-inline-flex align-items-center justify-content-center gap-2",children:[n===s.id?e.jsx("span",{className:"spinner-border spinner-border-sm",role:"status"}):null,"Install"]})})]})})},s.id))})]})}export{A as SoftPage};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as a,j as e,a6 as I,a as _,a7 as D,a8 as P,a9 as L}from"./index-CRR9sQ49.js";import{M as n}from"./Modal-B7V4w_St.js";import{A as b}from"./AdminAlert-DW1IRWce.js";import{A as o}from"./AdminButton-Bd2cLTu3.js";import{A as T}from"./AdminTable-BLiLxfnS.js";import{P as g}from"./PageHeader-BcjNf7GG.js";function $(){const[h,v]=a.useState([]),[N,x]=a.useState(!0),[u,d]=a.useState(""),[y,l]=a.useState(!1),[j,p]=a.useState(!1),[f,i]=a.useState(""),[U,A]=a.useState(null),c=()=>{x(!0),I().then(s=>{v(s),_("/auth/me").then(t=>A(t.id))}).catch(s=>d(s.message)).finally(()=>x(!1))};a.useEffect(()=>{c()},[]);const C=s=>{s.preventDefault();const t=s.currentTarget,r=t.elements.namedItem("username").value.trim(),m=t.elements.namedItem("password").value,E=t.elements.namedItem("email").value.trim();if(!r||r.length<2){i("Username must be at least 2 characters");return}if(!m||m.length<6){i("Password must be at least 6 characters");return}p(!0),i(""),L({username:r,password:m,email:E}).then(()=>{l(!1),t.reset(),c()}).catch(k=>i(k.message)).finally(()=>p(!1))},w=(s,t)=>{confirm(`Delete user "${t}"?`)&&P(s).then(c).catch(r=>d(r.message))},S=s=>{D(s).then(c).catch(t=>d(t.message))};return N&&h.length===0?e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Users"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Users",actions:e.jsxs(o,{variant:"primary",onClick:()=>l(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add User"]})}),u?e.jsx(b,{className:"mb-3",children:u}):null,e.jsx("div",{className:"card",children:e.jsxs(T,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Username"}),e.jsx("th",{children:"Email"}),e.jsx("th",{children:"Status"}),e.jsx("th",{children:"Role"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:h.map(s=>e.jsxs("tr",{children:[e.jsx("td",{children:s.username}),e.jsx("td",{children:s.email||"—"}),e.jsx("td",{children:e.jsx("span",{className:s.is_active?"text-success":"text-secondary",children:s.is_active?"Active":"Inactive"})}),e.jsx("td",{children:s.is_superuser?"Admin":"User"}),e.jsx("td",{className:"text-end",children:s.id!==U?e.jsxs("span",{className:"d-inline-flex gap-1 justify-content-end",children:[e.jsx("button",{type:"button",className:`btn btn-link btn-sm p-1 ${s.is_active?"text-warning":"text-success"}`,title:s.is_active?"Deactivate":"Activate",onClick:()=>S(s.id),children:e.jsx("i",{className:s.is_active?"ti ti-user-x":"ti ti-user-check","aria-hidden":!0})}),e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Delete",onClick:()=>w(s.id,s.username),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})]}):null})]},s.id))})]})}),e.jsxs(n,{show:y,onHide:()=>l(!1),centered:!0,children:[e.jsx(n.Header,{closeButton:!0,children:e.jsx(n.Title,{children:"Add User"})}),e.jsxs("form",{onSubmit:C,children:[e.jsxs(n.Body,{children:[f?e.jsx(b,{className:"mb-3",children:f}):null,e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Username"}),e.jsx("input",{name:"username",type:"text",placeholder:"newuser",className:"form-control",required:!0,minLength:2})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Password"}),e.jsx("input",{name:"password",type:"password",placeholder:"••••••••",className:"form-control",required:!0,minLength:6})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Email (optional)"}),e.jsx("input",{name:"email",type:"email",placeholder:"user@example.com",className:"form-control"})]})]}),e.jsxs(n.Footer,{children:[e.jsx(o,{type:"button",variant:"secondary",onClick:()=>l(!1),children:"Cancel"}),e.jsx(o,{type:"submit",variant:"primary",disabled:j,children:j?"Creating…":"Create"})]})]})]})]})}export{$ as UsersPage};
|
import{r as a,j as e,ab as I,M as _,ac as D,ad as P,ae as L}from"./index-Cvh4tLHo.js";import{M as n}from"./Modal-CCihVZTY.js";import{A as b}from"./AdminAlert-Bt3L8_zJ.js";import{A as o}from"./AdminButton-BKglG8kI.js";import{A as T}from"./AdminTable-BQ5Lf7EC.js";import{P as g}from"./PageHeader-D6k34vvM.js";function $(){const[h,v]=a.useState([]),[N,x]=a.useState(!0),[u,d]=a.useState(""),[y,l]=a.useState(!1),[j,p]=a.useState(!1),[f,i]=a.useState(""),[U,A]=a.useState(null),c=()=>{x(!0),I().then(s=>{v(s),_("/auth/me").then(t=>A(t.id))}).catch(s=>d(s.message)).finally(()=>x(!1))};a.useEffect(()=>{c()},[]);const C=s=>{s.preventDefault();const t=s.currentTarget,r=t.elements.namedItem("username").value.trim(),m=t.elements.namedItem("password").value,E=t.elements.namedItem("email").value.trim();if(!r||r.length<2){i("Username must be at least 2 characters");return}if(!m||m.length<6){i("Password must be at least 6 characters");return}p(!0),i(""),L({username:r,password:m,email:E}).then(()=>{l(!1),t.reset(),c()}).catch(k=>i(k.message)).finally(()=>p(!1))},w=(s,t)=>{confirm(`Delete user "${t}"?`)&&P(s).then(c).catch(r=>d(r.message))},S=s=>{D(s).then(c).catch(t=>d(t.message))};return N&&h.length===0?e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Users"}),e.jsx("p",{className:"text-secondary",children:"Loading…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(g,{title:"Users",actions:e.jsxs(o,{variant:"primary",onClick:()=>l(!0),children:[e.jsx("i",{className:"ti ti-plus me-1","aria-hidden":!0}),"Add User"]})}),u?e.jsx(b,{className:"mb-3",children:u}):null,e.jsx("div",{className:"card",children:e.jsxs(T,{children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Username"}),e.jsx("th",{children:"Email"}),e.jsx("th",{children:"Status"}),e.jsx("th",{children:"Role"}),e.jsx("th",{className:"text-end",children:"Actions"})]})}),e.jsx("tbody",{children:h.map(s=>e.jsxs("tr",{children:[e.jsx("td",{children:s.username}),e.jsx("td",{children:s.email||"—"}),e.jsx("td",{children:e.jsx("span",{className:s.is_active?"text-success":"text-secondary",children:s.is_active?"Active":"Inactive"})}),e.jsx("td",{children:s.is_superuser?"Admin":"User"}),e.jsx("td",{className:"text-end",children:s.id!==U?e.jsxs("span",{className:"d-inline-flex gap-1 justify-content-end",children:[e.jsx("button",{type:"button",className:`btn btn-link btn-sm p-1 ${s.is_active?"text-warning":"text-success"}`,title:s.is_active?"Deactivate":"Activate",onClick:()=>S(s.id),children:e.jsx("i",{className:s.is_active?"ti ti-user-x":"ti ti-user-check","aria-hidden":!0})}),e.jsx("button",{type:"button",className:"btn btn-link btn-sm text-danger p-1",title:"Delete",onClick:()=>w(s.id,s.username),children:e.jsx("i",{className:"ti ti-trash","aria-hidden":!0})})]}):null})]},s.id))})]})}),e.jsxs(n,{show:y,onHide:()=>l(!1),centered:!0,children:[e.jsx(n.Header,{closeButton:!0,children:e.jsx(n.Title,{children:"Add User"})}),e.jsxs("form",{onSubmit:C,children:[e.jsxs(n.Body,{children:[f?e.jsx(b,{className:"mb-3",children:f}):null,e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Username"}),e.jsx("input",{name:"username",type:"text",placeholder:"newuser",className:"form-control",required:!0,minLength:2})]}),e.jsxs("div",{className:"mb-3",children:[e.jsx("label",{className:"form-label",children:"Password"}),e.jsx("input",{name:"password",type:"password",placeholder:"••••••••",className:"form-control",required:!0,minLength:6})]}),e.jsxs("div",{className:"mb-0",children:[e.jsx("label",{className:"form-label",children:"Email (optional)"}),e.jsx("input",{name:"email",type:"email",placeholder:"user@example.com",className:"form-control"})]})]}),e.jsxs(n.Footer,{children:[e.jsx(o,{type:"button",variant:"secondary",onClick:()=>l(!1),children:"Cancel"}),e.jsx(o,{type:"submit",variant:"primary",disabled:j,children:j?"Creating…":"Create"})]})]})]})]})}export{$ as UsersPage};
|
||||||
File diff suppressed because one or more lines are too long
2
YakPanel-server/frontend/dist/index.html
vendored
2
YakPanel-server/frontend/dist/index.html
vendored
@@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>YakPanel</title>
|
<title>YakPanel</title>
|
||||||
<script type="module" crossorigin src="/assets/index-CRR9sQ49.js"></script>
|
<script type="module" crossorigin src="/assets/index-Cvh4tLHo.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BHS5Y1YN.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BHS5Y1YN.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -74,6 +74,39 @@ export async function createSite(data: { name: string; domains: string[]; path?:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SiteSslInfo = {
|
||||||
|
status: 'none' | 'active' | 'expiring' | 'expired'
|
||||||
|
days_left: number | null
|
||||||
|
cert_name: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SiteListItem = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
status: number
|
||||||
|
ps: string
|
||||||
|
project_type: string
|
||||||
|
domain_count: number
|
||||||
|
addtime: string | null
|
||||||
|
php_version: string
|
||||||
|
primary_domain: string
|
||||||
|
domains: string[]
|
||||||
|
backup_count: number
|
||||||
|
ssl: SiteSslInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function listSites() {
|
||||||
|
return apiRequest<SiteListItem[]>('/site/list')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function siteBatch(action: 'enable' | 'disable' | 'delete', ids: number[]) {
|
||||||
|
return apiRequest<{ results: { id: number; ok: boolean; msg: string }[] }>('/site/batch', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ action, ids }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSite(siteId: number) {
|
export async function getSite(siteId: number) {
|
||||||
return apiRequest<{ id: number; name: string; path: string; status: number; ps: string; project_type: string; php_version: string; force_https: number; domains: string[] }>(
|
return apiRequest<{ id: number; name: string; path: string; status: number; ps: string; project_type: string; php_version: string; force_https: number; domains: string[] }>(
|
||||||
`/site/${siteId}`
|
`/site/${siteId}`
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import Modal from 'react-bootstrap/Modal'
|
import Modal from 'react-bootstrap/Modal'
|
||||||
import Dropdown from 'react-bootstrap/Dropdown'
|
import Dropdown from 'react-bootstrap/Dropdown'
|
||||||
import {
|
import {
|
||||||
@@ -44,6 +45,7 @@ const TEXT_EXT = ['.txt', '.html', '.htm', '.css', '.js', '.json', '.xml', '.md'
|
|||||||
type Clip = { op: 'copy' | 'cut'; entries: { parent: string; name: string }[] }
|
type Clip = { op: 'copy' | 'cut'; entries: { parent: string; name: string }[] }
|
||||||
|
|
||||||
export function FilesPage() {
|
export function FilesPage() {
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
const [path, setPath] = useState('/')
|
const [path, setPath] = useState('/')
|
||||||
const [pathInput, setPathInput] = useState('/')
|
const [pathInput, setPathInput] = useState('/')
|
||||||
const [items, setItems] = useState<FileListItem[]>([])
|
const [items, setItems] = useState<FileListItem[]>([])
|
||||||
@@ -92,8 +94,17 @@ export function FilesPage() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadDir(path)
|
const raw = searchParams.get('path')
|
||||||
}, [])
|
let p = '/'
|
||||||
|
if (raw && raw.trim()) {
|
||||||
|
try {
|
||||||
|
p = decodeURIComponent(raw.trim())
|
||||||
|
} catch {
|
||||||
|
p = raw.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadDir(p)
|
||||||
|
}, [searchParams, loadDir])
|
||||||
|
|
||||||
const filteredItems = useMemo(() => {
|
const filteredItems = useMemo(() => {
|
||||||
const q = filter.trim().toLowerCase()
|
const q = filter.trim().toLowerCase()
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
import Modal from 'react-bootstrap/Modal'
|
import Modal from 'react-bootstrap/Modal'
|
||||||
|
import Dropdown from 'react-bootstrap/Dropdown'
|
||||||
import {
|
import {
|
||||||
apiRequest,
|
listSites,
|
||||||
|
siteBatch,
|
||||||
createSite,
|
createSite,
|
||||||
getSite,
|
getSite,
|
||||||
updateSite,
|
updateSite,
|
||||||
@@ -16,22 +19,18 @@ import {
|
|||||||
deleteSiteRedirect,
|
deleteSiteRedirect,
|
||||||
siteGitClone,
|
siteGitClone,
|
||||||
siteGitPull,
|
siteGitPull,
|
||||||
|
listServices,
|
||||||
|
type SiteListItem,
|
||||||
} from '../api/client'
|
} from '../api/client'
|
||||||
import { PageHeader, AdminButton, AdminAlert, AdminTable, EmptyState } from '../components/admin'
|
import { PageHeader, AdminButton, AdminAlert, AdminTable, EmptyState } from '../components/admin'
|
||||||
|
|
||||||
interface Site {
|
function formatPhpVersion(code: string): string {
|
||||||
id: number
|
const m: Record<string, string> = { '74': '7.4', '80': '8.0', '81': '8.1', '82': '8.2' }
|
||||||
name: string
|
return m[code] || code
|
||||||
path: string
|
|
||||||
status: number
|
|
||||||
ps: string
|
|
||||||
project_type: string
|
|
||||||
domain_count: number
|
|
||||||
addtime: string | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SitePage() {
|
export function SitePage() {
|
||||||
const [sites, setSites] = useState<Site[]>([])
|
const [sites, setSites] = useState<SiteListItem[]>([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const [showCreate, setShowCreate] = useState(false)
|
const [showCreate, setShowCreate] = useState(false)
|
||||||
@@ -62,10 +61,17 @@ export function SitePage() {
|
|||||||
const [gitBranch, setGitBranch] = useState('main')
|
const [gitBranch, setGitBranch] = useState('main')
|
||||||
const [gitAction, setGitAction] = useState<'clone' | 'pull' | null>(null)
|
const [gitAction, setGitAction] = useState<'clone' | 'pull' | null>(null)
|
||||||
const [gitLoading, setGitLoading] = useState(false)
|
const [gitLoading, setGitLoading] = useState(false)
|
||||||
|
const [search, setSearch] = useState('')
|
||||||
|
const [selectedIds, setSelectedIds] = useState<Set<number>>(() => new Set())
|
||||||
|
const [page, setPage] = useState(1)
|
||||||
|
const [pageSize, setPageSize] = useState(25)
|
||||||
|
const [nginxStatus, setNginxStatus] = useState<string | null>(null)
|
||||||
|
const [batchLoading, setBatchLoading] = useState(false)
|
||||||
|
const [rowBackupId, setRowBackupId] = useState<number | null>(null)
|
||||||
|
|
||||||
const loadSites = () => {
|
const loadSites = () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
apiRequest<Site[]>('/site/list')
|
listSites()
|
||||||
.then(setSites)
|
.then(setSites)
|
||||||
.catch((err) => setError(err.message))
|
.catch((err) => setError(err.message))
|
||||||
.finally(() => setLoading(false))
|
.finally(() => setLoading(false))
|
||||||
@@ -75,6 +81,90 @@ export function SitePage() {
|
|||||||
loadSites()
|
loadSites()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
listServices()
|
||||||
|
.then((data) => {
|
||||||
|
const n = data.services.find((s) => s.id === 'nginx')
|
||||||
|
setNginxStatus(n?.status ?? null)
|
||||||
|
})
|
||||||
|
.catch(() => setNginxStatus(null))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const filteredSites = useMemo(() => {
|
||||||
|
const q = search.trim().toLowerCase()
|
||||||
|
if (!q) return sites
|
||||||
|
return sites.filter((s) => {
|
||||||
|
const blob = [s.name, s.path, s.ps, s.primary_domain, ...(s.domains || [])].join(' ').toLowerCase()
|
||||||
|
return blob.includes(q)
|
||||||
|
})
|
||||||
|
}, [sites, search])
|
||||||
|
|
||||||
|
useEffect(() => setPage(1), [search, pageSize])
|
||||||
|
|
||||||
|
const totalPages = Math.max(1, Math.ceil(filteredSites.length / pageSize))
|
||||||
|
const paginatedSites = useMemo(() => {
|
||||||
|
const start = (page - 1) * pageSize
|
||||||
|
return filteredSites.slice(start, start + pageSize)
|
||||||
|
}, [filteredSites, page, pageSize])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (page > totalPages) setPage(totalPages)
|
||||||
|
}, [page, totalPages])
|
||||||
|
|
||||||
|
const toggleSelect = (id: number) => {
|
||||||
|
setSelectedIds((prev) => {
|
||||||
|
const n = new Set(prev)
|
||||||
|
if (n.has(id)) n.delete(id)
|
||||||
|
else n.add(id)
|
||||||
|
return n
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectAllOnPage = () => {
|
||||||
|
const onPage = new Set(paginatedSites.map((s) => s.id))
|
||||||
|
const allSelected = paginatedSites.length > 0 && paginatedSites.every((s) => selectedIds.has(s.id))
|
||||||
|
if (allSelected) {
|
||||||
|
setSelectedIds((prev) => {
|
||||||
|
const n = new Set(prev)
|
||||||
|
paginatedSites.forEach((s) => n.delete(s.id))
|
||||||
|
return n
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setSelectedIds((prev) => new Set([...prev, ...onPage]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runBatch = async (action: 'enable' | 'disable' | 'delete') => {
|
||||||
|
const ids = [...selectedIds]
|
||||||
|
if (ids.length === 0) return
|
||||||
|
const msg =
|
||||||
|
action === 'delete'
|
||||||
|
? `Delete ${ids.length} site(s)? This cannot be undone.`
|
||||||
|
: `${action === 'enable' ? 'Enable' : 'Disable'} ${ids.length} site(s)?`
|
||||||
|
if (!confirm(msg)) return
|
||||||
|
setBatchLoading(true)
|
||||||
|
try {
|
||||||
|
const r = await siteBatch(action, ids)
|
||||||
|
const failed = r.results.filter((x) => !x.ok)
|
||||||
|
if (failed.length) setError(failed.map((f) => `${f.id}: ${f.msg}`).join('; '))
|
||||||
|
else setError('')
|
||||||
|
setSelectedIds(new Set())
|
||||||
|
loadSites()
|
||||||
|
} catch (e) {
|
||||||
|
setError(e instanceof Error ? e.message : 'Batch failed')
|
||||||
|
} finally {
|
||||||
|
setBatchLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuickBackup = (siteId: number) => {
|
||||||
|
setRowBackupId(siteId)
|
||||||
|
createSiteBackup(siteId)
|
||||||
|
.then(() => loadSites())
|
||||||
|
.catch((err) => setError(err.message))
|
||||||
|
.finally(() => setRowBackupId(null))
|
||||||
|
}
|
||||||
|
|
||||||
const handleCreate = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleCreate = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const form = e.currentTarget
|
const form = e.currentTarget
|
||||||
@@ -341,99 +431,237 @@ export function SitePage() {
|
|||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<div className="card shadow-sm border-0 mb-3">
|
||||||
|
<div className="card-body py-3">
|
||||||
|
<div className="row g-2 align-items-center">
|
||||||
|
<div className="col-md-4">
|
||||||
|
<div className="input-group input-group-sm">
|
||||||
|
<span className="input-group-text">
|
||||||
|
<i className="ti ti-search" aria-hidden />
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Site name, domain, path, or note…"
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
|
aria-label="Search sites"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-5">
|
||||||
|
<div className="d-flex flex-wrap gap-2 align-items-center">
|
||||||
|
<AdminButton variant="secondary" size="sm" onClick={() => runBatch('enable')} disabled={batchLoading || selectedIds.size === 0}>
|
||||||
|
Enable
|
||||||
|
</AdminButton>
|
||||||
|
<AdminButton variant="secondary" size="sm" onClick={() => runBatch('disable')} disabled={batchLoading || selectedIds.size === 0}>
|
||||||
|
Disable
|
||||||
|
</AdminButton>
|
||||||
|
<AdminButton variant="danger" size="sm" onClick={() => runBatch('delete')} disabled={batchLoading || selectedIds.size === 0}>
|
||||||
|
Delete
|
||||||
|
</AdminButton>
|
||||||
|
<span className="text-secondary small ms-md-2">
|
||||||
|
{selectedIds.size > 0 ? `${selectedIds.size} selected` : ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-3 text-md-end">
|
||||||
|
<span
|
||||||
|
className={`badge ${nginxStatus === 'active' ? 'bg-success' : 'bg-secondary'} me-2`}
|
||||||
|
title="Nginx (systemd)"
|
||||||
|
>
|
||||||
|
Nginx {nginxStatus ?? '—'}
|
||||||
|
</span>
|
||||||
|
<select
|
||||||
|
className="form-select form-select-sm d-inline-block w-auto"
|
||||||
|
value={pageSize}
|
||||||
|
onChange={(e) => setPageSize(Number(e.target.value))}
|
||||||
|
aria-label="Rows per page"
|
||||||
|
>
|
||||||
|
<option value={10}>10 / page</option>
|
||||||
|
<option value={25}>25 / page</option>
|
||||||
|
<option value={50}>50 / page</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="card shadow-sm border-0">
|
<div className="card shadow-sm border-0">
|
||||||
<div className="card-body p-0">
|
<div className="card-body p-0">
|
||||||
<AdminTable>
|
<AdminTable>
|
||||||
<thead className="table-light">
|
<thead className="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th style={{ width: 40 }}>
|
||||||
<th>Path</th>
|
<input
|
||||||
<th>Domains</th>
|
type="checkbox"
|
||||||
<th>Type</th>
|
className="form-check-input"
|
||||||
<th className="text-end">Actions</th>
|
checked={paginatedSites.length > 0 && paginatedSites.every((s) => selectedIds.has(s.id))}
|
||||||
|
onChange={selectAllOnPage}
|
||||||
|
aria-label="Select all on page"
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
<th>Site</th>
|
||||||
|
<th className="text-center">Status</th>
|
||||||
|
<th>Backup</th>
|
||||||
|
<th className="text-center">Quick</th>
|
||||||
|
<th className="text-center">PHP</th>
|
||||||
|
<th>SSL</th>
|
||||||
|
<th className="d-none d-xl-table-cell">Note</th>
|
||||||
|
<th className="text-end">Operate</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{sites.length === 0 ? (
|
{sites.length === 0 ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={5} className="p-0">
|
<td colSpan={9} className="p-0">
|
||||||
<EmptyState title="No sites yet" description='Click "Add Site" to create one.' />
|
<EmptyState title="No sites yet" description='Click "Add Site" to create one.' />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
) : filteredSites.length === 0 ? (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={9} className="p-0">
|
||||||
|
<EmptyState title="No matches" description="Try a different search." />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
) : (
|
) : (
|
||||||
sites.map((s) => (
|
paginatedSites.map((s) => (
|
||||||
<tr key={s.id}>
|
<tr key={s.id}>
|
||||||
<td className="align-middle">{s.name}</td>
|
<td className="align-middle" onClick={(e) => e.stopPropagation()}>
|
||||||
<td className="align-middle text-muted">{s.path}</td>
|
<input
|
||||||
<td className="align-middle">{s.domain_count}</td>
|
type="checkbox"
|
||||||
<td className="align-middle">{s.project_type}</td>
|
className="form-check-input"
|
||||||
<td className="align-middle text-end text-nowrap">
|
checked={selectedIds.has(s.id)}
|
||||||
|
onChange={() => toggleSelect(s.id)}
|
||||||
|
aria-label={`Select ${s.name}`}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td className="align-middle">
|
||||||
|
<div className="d-flex align-items-start gap-2">
|
||||||
|
{s.primary_domain ? (
|
||||||
|
<a
|
||||||
|
href={`https://${s.primary_domain.split(':')[0]}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="text-decoration-none"
|
||||||
|
title="Open site"
|
||||||
|
>
|
||||||
|
<i className="ti ti-external-link text-muted" aria-hidden />
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
<div className="small">
|
||||||
|
<div className="fw-medium">{s.primary_domain || s.name}</div>
|
||||||
|
<div className="text-muted text-truncate" style={{ maxWidth: 220 }} title={s.path}>
|
||||||
|
{s.project_type} · {s.path}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="align-middle text-center">
|
||||||
{s.status === 1 ? (
|
{s.status === 1 ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleSetStatus(s.id, false)}
|
onClick={() => handleSetStatus(s.id, false)}
|
||||||
disabled={statusLoading === s.id}
|
disabled={statusLoading === s.id}
|
||||||
className="btn btn-sm btn-outline-warning me-1"
|
className="btn btn-sm btn-link text-success p-0"
|
||||||
title="Stop"
|
title="Running — click to stop"
|
||||||
>
|
>
|
||||||
<i className="ti ti-player-stop" />
|
<i className="ti ti-player-play" />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleSetStatus(s.id, true)}
|
onClick={() => handleSetStatus(s.id, true)}
|
||||||
disabled={statusLoading === s.id}
|
disabled={statusLoading === s.id}
|
||||||
className="btn btn-sm btn-outline-success me-1"
|
className="btn btn-sm btn-link text-secondary p-0"
|
||||||
title="Start"
|
title="Stopped — click to start"
|
||||||
>
|
>
|
||||||
<i className="ti ti-player-play" />
|
<i className="ti ti-player-stop" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="align-middle small">
|
||||||
|
<span className="me-2">{s.backup_count}</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
className="btn btn-link btn-sm text-danger p-0 text-decoration-none"
|
||||||
|
onClick={() => handleQuickBackup(s.id)}
|
||||||
|
disabled={rowBackupId === s.id}
|
||||||
|
>
|
||||||
|
{rowBackupId === s.id ? '…' : 'Backup now'}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td className="align-middle text-center text-nowrap">
|
||||||
|
<Link
|
||||||
|
to={`/files?path=${encodeURIComponent(s.path)}`}
|
||||||
|
className="btn btn-sm btn-light border"
|
||||||
|
title="Site directory"
|
||||||
|
>
|
||||||
|
<i className="ti ti-folder" />
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
<td className="align-middle text-center small">
|
||||||
|
<span className="badge bg-light text-dark border">{formatPhpVersion(s.php_version || '74')}</span>
|
||||||
|
</td>
|
||||||
|
<td className="align-middle small">
|
||||||
|
{(s.ssl?.status ?? 'none') === 'none' ? (
|
||||||
|
<span className="text-warning">Not set</span>
|
||||||
|
) : s.ssl?.status === 'expired' ? (
|
||||||
|
<span className="text-danger">Expired</span>
|
||||||
|
) : s.ssl?.status === 'expiring' ? (
|
||||||
|
<span className="text-warning">{s.ssl?.days_left ?? 0}d left</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-success">{s.ssl?.days_left ?? 0} days</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="align-middle small text-muted d-none d-xl-table-cell text-truncate" style={{ maxWidth: 140 }} title={s.ps}>
|
||||||
|
{s.ps || '—'}
|
||||||
|
</td>
|
||||||
|
<td className="align-middle text-end">
|
||||||
|
<Dropdown align="end">
|
||||||
|
<Dropdown.Toggle variant="light" size="sm" className="py-0 border">
|
||||||
|
More
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
<Dropdown.Menu>
|
||||||
|
<Dropdown.Item onClick={() => openEditModal(s.id)}>
|
||||||
|
<i className="ti ti-settings me-2" />
|
||||||
|
Config
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item as={Link} to="/logs">
|
||||||
|
<i className="ti ti-file-text me-2" />
|
||||||
|
Logs
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item as={Link} to="/ssl_domain">
|
||||||
|
<i className="ti ti-shield-lock me-2" />
|
||||||
|
SSL / Domains
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Divider />
|
||||||
|
<Dropdown.Item
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setGitSiteId(s.id)
|
setGitSiteId(s.id)
|
||||||
setGitAction('clone')
|
setGitAction('clone')
|
||||||
setGitUrl('')
|
setGitUrl('')
|
||||||
setGitBranch('main')
|
setGitBranch('main')
|
||||||
}}
|
}}
|
||||||
className="btn btn-sm btn-outline-success me-1"
|
|
||||||
title="Git Deploy"
|
|
||||||
>
|
>
|
||||||
<i className="ti ti-git-branch" />
|
<i className="ti ti-git-branch me-2" />
|
||||||
</button>
|
Git
|
||||||
<button
|
</Dropdown.Item>
|
||||||
type="button"
|
<Dropdown.Item onClick={() => openRedirectModal(s.id)}>
|
||||||
onClick={() => openRedirectModal(s.id)}
|
<i className="ti ti-arrows-right-left me-2" />
|
||||||
className="btn btn-sm btn-outline-secondary me-1"
|
Redirects
|
||||||
title="Redirects"
|
</Dropdown.Item>
|
||||||
>
|
<Dropdown.Item onClick={() => openBackupModal(s.id)}>
|
||||||
<i className="ti ti-arrows-right-left" />
|
<i className="ti ti-archive me-2" />
|
||||||
</button>
|
Backups
|
||||||
<button
|
</Dropdown.Item>
|
||||||
type="button"
|
<Dropdown.Divider />
|
||||||
onClick={() => openEditModal(s.id)}
|
<Dropdown.Item className="text-danger" onClick={() => handleDelete(s.id, s.name)}>
|
||||||
className="btn btn-sm btn-outline-primary me-1"
|
<i className="ti ti-trash me-2" />
|
||||||
title="Edit"
|
Delete
|
||||||
>
|
</Dropdown.Item>
|
||||||
<i className="ti ti-pencil" />
|
</Dropdown.Menu>
|
||||||
</button>
|
</Dropdown>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => openBackupModal(s.id)}
|
|
||||||
className="btn btn-sm btn-outline-primary me-1"
|
|
||||||
title="Backup"
|
|
||||||
>
|
|
||||||
<i className="ti ti-archive" />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleDelete(s.id, s.name)}
|
|
||||||
className="btn btn-sm btn-outline-danger"
|
|
||||||
title="Delete"
|
|
||||||
>
|
|
||||||
<i className="ti ti-trash" />
|
|
||||||
</button>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
@@ -441,6 +669,35 @@ export function SitePage() {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</AdminTable>
|
</AdminTable>
|
||||||
</div>
|
</div>
|
||||||
|
{sites.length > 0 && filteredSites.length > 0 ? (
|
||||||
|
<div className="card-footer py-2 d-flex flex-wrap align-items-center justify-content-between gap-2 small text-secondary">
|
||||||
|
<span>
|
||||||
|
Total <strong>{filteredSites.length}</strong> site(s)
|
||||||
|
{search.trim() ? ` (filtered from ${sites.length})` : ''}
|
||||||
|
</span>
|
||||||
|
<div className="d-flex align-items-center gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm btn-outline-secondary"
|
||||||
|
disabled={page <= 1}
|
||||||
|
onClick={() => setPage((p) => Math.max(1, p - 1))}
|
||||||
|
>
|
||||||
|
Prev
|
||||||
|
</button>
|
||||||
|
<span>
|
||||||
|
Page {page} / {totalPages}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm btn-outline-secondary"
|
||||||
|
disabled={page >= totalPages}
|
||||||
|
onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Modal show={!!gitSiteId && !!gitAction} onHide={() => { setGitSiteId(null); setGitAction(null) }} centered>
|
<Modal show={!!gitSiteId && !!gitAction} onHide={() => { setGitSiteId(null); setGitAction(null) }} centered>
|
||||||
|
|||||||
Reference in New Issue
Block a user