feat: upload dentro de la plantilla SamShell (sin sidenav propio)
This commit is contained in:
1 parent
70df8e95a9
commit
3d9685adeb
1 file changed
+185
-209
+185
-209
@@ -1,9 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import SamShell from "@/components/SamShell";
|
||||
import { useModules } from "@/lib/store";
|
||||
import { itMenu } from "@/lib/sam";
|
||||
|
||||
export default function UploadPage() {
|
||||
const { data } = useModules();
|
||||
const [form, setForm] = useState({
|
||||
name: "",
|
||||
repoUrl: "",
|
||||
@@ -59,222 +62,195 @@ export default function UploadPage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sidenav">
|
||||
<div className="row text-light login-main-text">
|
||||
<div className="col-12 text-center">
|
||||
<div
|
||||
className="mx-auto d-flex align-items-center justify-content-center bg-white rounded-3"
|
||||
style={{ width: 80, height: 80 }}
|
||||
>
|
||||
<i className="bx bx-upload text-primary" style={{ fontSize: 48 }} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 text-center mt-3">
|
||||
<h1 className="fw-bold fs-2">Sistema SAM</h1>
|
||||
</div>
|
||||
<div className="col-12 text-center">
|
||||
<h4 className="fw-semibold opacity-75">Subir Proyecto</h4>
|
||||
</div>
|
||||
<div className="col-12 text-center mt-4">
|
||||
<Link href="/" className="btn btn-outline-light btn-sm px-4">
|
||||
<i className="bx bx-arrow-back me-1" /> Volver
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<SamShell
|
||||
brand="IT"
|
||||
subtitle="Agregar módulo"
|
||||
menu={itMenu(data?.modules ?? [])}
|
||||
activeHref="/upload"
|
||||
topUser="SAM"
|
||||
backHref="/"
|
||||
>
|
||||
<div className="alert alert-light section-header mb-3 py-2 px-3">
|
||||
<i className="bx bx-cloud-upload me-1" /> Integrar Nuevo Módulo
|
||||
</div>
|
||||
|
||||
<div className="main">
|
||||
<div className="row">
|
||||
<div className="col-lg-1" />
|
||||
<div className="col-lg-10 mt-4">
|
||||
<div className="alert alert-light section-header mb-3 py-2 px-3">
|
||||
<i className="bx bx-cloud-upload me-1" /> Integrar Nuevo Módulo
|
||||
<div className="app-card p-4">
|
||||
<p className="text-muted mb-4">
|
||||
Registra un proyecto <strong>Next.js 15 + Bootstrap</strong> desde un repositorio
|
||||
Gitea. Se clonará, desplegará automáticamente y quedará disponible en{" "}
|
||||
<code>https://{"{subdominio}"}.devops.norteamericano.cl</code>. Cada push futuro
|
||||
actualiza el módulo vía webhook.
|
||||
</p>
|
||||
|
||||
{result && (
|
||||
<div className={`alert ${result.ok ? "alert-success" : "alert-danger"}`}>
|
||||
<i className={`bx ${result.ok ? "bx-check-circle" : "bx-error-circle"} me-2`} />
|
||||
{result.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row g-3">
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Nombre del módulo <span className="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
name="name"
|
||||
value={form.name}
|
||||
onChange={handleChange}
|
||||
placeholder="ej: ventas"
|
||||
pattern="^[a-z][a-z0-9-]+$"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Minúsculas, guiones, empieza con letra.</div>
|
||||
</div>
|
||||
|
||||
<div className="app-card p-4">
|
||||
<p className="text-muted mb-4">
|
||||
Registra un proyecto <strong>Next.js 15 + Bootstrap</strong> desde un repositorio
|
||||
Gitea. Se clonará, desplegará automáticamente y quedará disponible en{" "}
|
||||
<code>https://{"{subdominio}"}.devops.norteamericano.cl</code>. Cada push futuro
|
||||
actualiza el módulo vía webhook.
|
||||
</p>
|
||||
|
||||
{result && (
|
||||
<div className={`alert ${result.ok ? "alert-success" : "alert-danger"}`}>
|
||||
<i className={`bx ${result.ok ? "bx-check-circle" : "bx-error-circle"} me-2`} />
|
||||
{result.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row g-3">
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Nombre del módulo <span className="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
name="name"
|
||||
value={form.name}
|
||||
onChange={handleChange}
|
||||
placeholder="ej: ventas"
|
||||
pattern="^[a-z][a-z0-9-]+$"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Minúsculas, guiones, empieza con letra.</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<label className="form-label fw-semibold">
|
||||
URL del repositorio Gitea <span className="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
name="repoUrl"
|
||||
value={form.repoUrl}
|
||||
onChange={handleChange}
|
||||
placeholder="https://git.norteamericano.cl/user/mi-proyecto.git"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Debe ser accesible desde el deployer (https://git.norteamericano.cl).</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<div className="alert alert-light border py-2 small">
|
||||
<i className="bx bx-cog me-1" />
|
||||
<strong>Configuración automática:</strong> puerto y subdominio se asignan automáticamente
|
||||
{form.name && (
|
||||
<span>
|
||||
{" "}
|
||||
→ <code>https://{form.subdomain || form.name}.devops.norteamericano.cl</code>
|
||||
{form.port ? ` :${form.port}` : " (puerto auto)"}
|
||||
</span>
|
||||
)}
|
||||
. Se crean los registros en Caddy y DNS.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details className="col-12">
|
||||
<summary className="small text-muted" style={{ cursor: "pointer" }}>
|
||||
Opciones avanzadas (puerto / subdominio manual)
|
||||
</summary>
|
||||
<div className="row g-3 mt-1">
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Subdominio <small className="text-muted">(opcional)</small>
|
||||
</label>
|
||||
<input
|
||||
name="subdomain"
|
||||
value={form.subdomain}
|
||||
onChange={handleChange}
|
||||
placeholder="ej: ventas (default: nombre)"
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">https://{form.subdomain || form.name || "subdominio"}.devops.norteamericano.cl</div>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Puerto <small className="text-muted">(opcional)</small>
|
||||
</label>
|
||||
<input
|
||||
name="port"
|
||||
type="number"
|
||||
value={form.port}
|
||||
onChange={handleChange}
|
||||
placeholder="auto (3011+)"
|
||||
min={3000}
|
||||
max={4000}
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Se asigna automáticamente si se deja vacío.</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
¿A qué corresponde? <span className="text-danger">*</span>
|
||||
</label>
|
||||
<select
|
||||
name="category"
|
||||
value={form.category}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="form-select"
|
||||
>
|
||||
<option value="pagina-web">Página Web</option>
|
||||
<option value="sam">SAM</option>
|
||||
<option value="profesores">Profesores</option>
|
||||
<option value="otras-apps">Otras Aplicaciones</option>
|
||||
</select>
|
||||
<div className="form-text">
|
||||
Define en qué sección del índice SAM aparece el módulo.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">Rama</label>
|
||||
<input
|
||||
name="branch"
|
||||
value={form.branch}
|
||||
onChange={handleChange}
|
||||
placeholder="main"
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">
|
||||
main = producción, otra rama = desarrollo.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 mt-2">
|
||||
<div className="alert alert-info py-2 small mb-0">
|
||||
<i className="bx bx-info-circle me-1" />
|
||||
El repositorio debe ser un proyecto <strong>Next.js 15</strong> (con{" "}
|
||||
<code>package.json</code> en raíz o en <code>frontend/</code>) y usar{" "}
|
||||
<strong>Bootstrap</strong>. Si no trae <code>Dockerfile</code>, se genera uno automáticamente.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 mt-3 d-flex gap-2">
|
||||
<button type="submit" disabled={loading} className="btn btn-primary px-4">
|
||||
{loading ? (
|
||||
<>
|
||||
<span className="spinner-border spinner-border-sm me-2" /> Desplegando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="bx bx-rocket me-1" /> Registrar y Desplegar
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<Link href="/" className="btn btn-outline-secondary">
|
||||
Cancelar
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div className="col-12">
|
||||
<label className="form-label fw-semibold">
|
||||
URL del repositorio Gitea <span className="text-danger">*</span>
|
||||
</label>
|
||||
<input
|
||||
name="repoUrl"
|
||||
value={form.repoUrl}
|
||||
onChange={handleChange}
|
||||
placeholder="https://git.norteamericano.cl/user/mi-proyecto.git"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Debe ser accesible desde el deployer (https://git.norteamericano.cl).</div>
|
||||
</div>
|
||||
|
||||
<div className="app-card p-3 mt-3">
|
||||
<h6 className="fw-semibold mb-2">
|
||||
<i className="bx bx-book-open me-1" /> Requisitos del repositorio
|
||||
</h6>
|
||||
<ul className="small text-muted mb-0">
|
||||
<li>
|
||||
Proyecto Next.js 15 con <code>next build</code> / <code>next start</code>
|
||||
</li>
|
||||
<li>Bootstrap 5 (via CDN o npm) + Boxicons opcional</li>
|
||||
<li>
|
||||
Variable <code>NEXT_PUBLIC_API_URL=https://api.devops.norteamericano.cl</code>{" "}
|
||||
para consumir el backend
|
||||
</li>
|
||||
<li>Branch por defecto: main (configurable)</li>
|
||||
</ul>
|
||||
<div className="col-12">
|
||||
<div className="alert alert-light border py-2 small">
|
||||
<i className="bx bx-cog me-1" />
|
||||
<strong>Configuración automática:</strong> puerto y subdominio se asignan automáticamente
|
||||
{form.name && (
|
||||
<span>
|
||||
{" "}
|
||||
→ <code>https://{form.subdomain || form.name}.devops.norteamericano.cl</code>
|
||||
{form.port ? ` :${form.port}` : " (puerto auto)"}
|
||||
</span>
|
||||
)}
|
||||
. Se crean los registros en Caddy y DNS.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details className="col-12">
|
||||
<summary className="small text-muted" style={{ cursor: "pointer" }}>
|
||||
Opciones avanzadas (puerto / subdominio manual)
|
||||
</summary>
|
||||
<div className="row g-3 mt-1">
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Subdominio <small className="text-muted">(opcional)</small>
|
||||
</label>
|
||||
<input
|
||||
name="subdomain"
|
||||
value={form.subdomain}
|
||||
onChange={handleChange}
|
||||
placeholder="ej: ventas (default: nombre)"
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">https://{form.subdomain || form.name || "subdominio"}.devops.norteamericano.cl</div>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
Puerto <small className="text-muted">(opcional)</small>
|
||||
</label>
|
||||
<input
|
||||
name="port"
|
||||
type="number"
|
||||
value={form.port}
|
||||
onChange={handleChange}
|
||||
placeholder="auto (3011+)"
|
||||
min={3000}
|
||||
max={4000}
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">Se asigna automáticamente si se deja vacío.</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">
|
||||
¿A qué corresponde? <span className="text-danger">*</span>
|
||||
</label>
|
||||
<select
|
||||
name="category"
|
||||
value={form.category}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="form-select"
|
||||
>
|
||||
<option value="pagina-web">Página Web</option>
|
||||
<option value="sam">SAM</option>
|
||||
<option value="profesores">Profesores</option>
|
||||
<option value="otras-apps">Otras Aplicaciones</option>
|
||||
</select>
|
||||
<div className="form-text">
|
||||
Define en qué sección del índice SAM aparece el módulo.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
<label className="form-label fw-semibold">Rama</label>
|
||||
<input
|
||||
name="branch"
|
||||
value={form.branch}
|
||||
onChange={handleChange}
|
||||
placeholder="main"
|
||||
className="form-control"
|
||||
/>
|
||||
<div className="form-text">
|
||||
main = producción, otra rama = desarrollo.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 mt-2">
|
||||
<div className="alert alert-info py-2 small mb-0">
|
||||
<i className="bx bx-info-circle me-1" />
|
||||
El repositorio debe ser un proyecto <strong>Next.js 15</strong> (con{" "}
|
||||
<code>package.json</code> en raíz o en <code>frontend/</code>) y usar{" "}
|
||||
<strong>Bootstrap</strong>. Si no trae <code>Dockerfile</code>, se genera uno automáticamente.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 mt-3 d-flex gap-2">
|
||||
<button type="submit" disabled={loading} className="btn btn-primary px-4">
|
||||
{loading ? (
|
||||
<>
|
||||
<span className="spinner-border spinner-border-sm me-2" /> Desplegando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="bx bx-rocket me-1" /> Registrar y Desplegar
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<div className="app-card p-3 mt-3">
|
||||
<h6 className="fw-semibold mb-2">
|
||||
<i className="bx bx-book-open me-1" /> Requisitos del repositorio
|
||||
</h6>
|
||||
<ul className="small text-muted mb-0">
|
||||
<li>
|
||||
Proyecto Next.js 15 con <code>next build</code> / <code>next start</code>
|
||||
</li>
|
||||
<li>Bootstrap 5 (via CDN o npm) + Boxicons opcional</li>
|
||||
<li>
|
||||
Variable <code>NEXT_PUBLIC_API_URL=https://api.devops.norteamericano.cl</code>{" "}
|
||||
para consumir el backend
|
||||
</li>
|
||||
<li>Branch por defecto: main (configurable)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</SamShell>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user