feat(ui): refresh shell, auth, and node visuals
This commit is contained in:
@@ -16,6 +16,12 @@
|
||||
<button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#addJobModal">
|
||||
<i class="ti ti-plus me-1"></i>Add Job
|
||||
</button>
|
||||
{{else if eq .CurrentPath "/uptime"}}
|
||||
<form method="post" action="/uptime/run">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<i class="ti ti-activity-heartbeat me-1"></i>Run Checks
|
||||
</button>
|
||||
</form>
|
||||
{{else if eq .CurrentPath "/groups"}}
|
||||
<button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#createGroupModal">
|
||||
<i class="ti ti-plus me-1"></i>Create Group
|
||||
@@ -39,20 +45,24 @@
|
||||
{{define "shell"}}
|
||||
<div class="app-shell d-flex min-vh-100">
|
||||
<aside class="app-sidebar border-end">
|
||||
<div class="p-3 p-lg-4 d-flex flex-column h-100">
|
||||
<a href="/dashboard" class="d-flex align-items-center justify-content-center gap-3 text-decoration-none mb-4 sidebar-brand">
|
||||
<div class="app-sidebar-inner p-3 d-flex flex-column h-100">
|
||||
<a href="/dashboard" class="d-flex align-items-center gap-3 text-decoration-none mb-4 sidebar-brand">
|
||||
<img src="/static/img/maintainarr_logo.png" alt="Maintainarr" class="sidebar-logo">
|
||||
<div class="text-center">
|
||||
<div class="fw-bold fs-5 text-body-emphasis">Maintainarr</div>
|
||||
<div class="min-w-0">
|
||||
<div class="sidebar-brand-title text-body-emphasis">Maintainarr</div>
|
||||
</div>
|
||||
</a>
|
||||
<nav class="nav flex-column gap-2 app-sidebar-nav">
|
||||
<a href="/dashboard" class="btn text-start {{if eq .CurrentPath "/dashboard"}}btn-primary{{else}}btn-outline-secondary{{end}}"><i class="ti ti-layout-grid me-2"></i>Dashboard</a>
|
||||
<a href="/groups" class="btn text-start {{if eq .CurrentPath "/groups"}}btn-primary{{else}}btn-outline-secondary{{end}}"><i class="ti ti-stack-2 me-2"></i>Groups</a>
|
||||
<a href="/automations" class="btn text-start {{if eq .CurrentPath "/automations"}}btn-primary{{else}}btn-outline-secondary{{end}}"><i class="ti ti-clock-cog me-2"></i>Jobs</a>
|
||||
<a href="/settings" class="btn text-start {{if eq .CurrentPath "/settings"}}btn-primary{{else}}btn-outline-secondary{{end}}"><i class="ti ti-settings-2 me-2"></i>Settings</a>
|
||||
|
||||
<div class="sidebar-section-label">Navigation</div>
|
||||
<nav class="nav flex-column gap-1 app-sidebar-nav">
|
||||
<a href="/dashboard" class="app-nav-link {{if eq .CurrentPath "/dashboard"}}is-active{{end}}"><i class="ti ti-layout-grid"></i><span>Dashboard</span></a>
|
||||
<a href="/groups" class="app-nav-link {{if eq .CurrentPath "/groups"}}is-active{{end}}"><i class="ti ti-stack-2"></i><span>Groups</span></a>
|
||||
<a href="/automations" class="app-nav-link {{if eq .CurrentPath "/automations"}}is-active{{end}}"><i class="ti ti-clock-cog"></i><span>Jobs</span></a>
|
||||
<a href="/uptime" class="app-nav-link {{if eq .CurrentPath "/uptime"}}is-active{{end}}"><i class="ti ti-activity-heartbeat"></i><span>Uptime</span></a>
|
||||
<a href="/settings" class="app-nav-link {{if eq .CurrentPath "/settings"}}is-active{{end}}"><i class="ti ti-settings-2"></i><span>Settings</span></a>
|
||||
</nav>
|
||||
<div class="card mt-auto border-0 sidebar-status">
|
||||
|
||||
<div class="card mt-auto border-0 sidebar-status shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-between gap-3">
|
||||
<div class="d-flex align-items-center gap-3 min-w-0">
|
||||
@@ -74,7 +84,9 @@
|
||||
<header class="app-header border-bottom">
|
||||
<div class="container-fluid px-3 px-lg-4">
|
||||
<div class="d-flex align-items-center justify-content-between gap-3 py-3">
|
||||
<div class="fw-semibold text-body-emphasis">{{.Title}}</div>
|
||||
<div>
|
||||
<div class="fw-semibold text-body-emphasis">{{.Title}}</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
{{template "contextAction" .}}
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{{define "shell"}}
|
||||
<main class="min-vh-100 d-flex align-items-center auth-shell py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
|
||||
<div class="card border-0 shadow-lg auth-card">
|
||||
<div class="auth-form-wrap p-4 p-lg-5">
|
||||
{{template "content" .}}
|
||||
</div>
|
||||
</div>
|
||||
<main class="min-vh-100 d-flex align-items-center justify-content-center auth-shell py-5">
|
||||
<div class="container-tight w-100 px-3 py-4">
|
||||
<div class="text-center mb-4">
|
||||
<img src="/static/img/maintainarr_logo.png" alt="Maintainarr" class="auth-logo">
|
||||
</div>
|
||||
<div class="card border-0 shadow-lg auth-card auth-card-tabler">
|
||||
<div class="card-body p-4 p-lg-5">
|
||||
{{template "content" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@3.44.0/dist/tabler-icons.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/dist/tabler-icons.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/font-logos@1/assets/font-logos.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/css/app.css">
|
||||
</head>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<div class="card-body p-0">
|
||||
<div class="node-tile">
|
||||
<div class="node-tile-icon">
|
||||
<div class="chip-icon">
|
||||
<div class="chip-icon chip-icon-plain node-brand-icon">
|
||||
{{if nodeIconPending .Distro .PackageManager}}
|
||||
<i class="ti ti-loader-2 node-loading-icon"></i>
|
||||
{{else}}
|
||||
{{icon (nodeIconName .Distro .PackageManager)}}
|
||||
<i class="{{nodeIconClass .Distro .PackageManager}} distro-icon"></i>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
{{define "content"}}
|
||||
<div class="mb-4">
|
||||
<h2 class="fw-bold mb-0">Sign In</h2>
|
||||
<div class="text-center mb-4">
|
||||
<h1 class="h3 fw-bold mb-0">Sign in</h1>
|
||||
</div>
|
||||
{{with .Content}}{{with .Error}}<div class="alert alert-danger">{{.}}</div>{{end}}{{end}}
|
||||
<form method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" name="email" required>
|
||||
<input type="email" class="form-control auth-input" name="email" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Password</label>
|
||||
<input type="password" class="form-control form-control-lg" name="password" required>
|
||||
<input type="password" class="form-control auth-input" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100"><i class="ti ti-login-2 me-2"></i>Continue</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100">Sign in</button>
|
||||
</form>
|
||||
<p class="mt-4 text-body-secondary mb-0"><a href="/register" class="link-primary link-offset-2">Create account</a></p>
|
||||
<div class="text-center mt-4 small text-body-secondary">
|
||||
<a href="/register" class="link-primary link-offset-2">Create account</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -17,11 +17,21 @@
|
||||
|
||||
<section class="row g-3 mb-4 node-live" data-node-id="{{$data.Node.ID}}">
|
||||
<div class="col-12 col-md-6 col-xxl-3">
|
||||
<div class="card border-0 shadow-sm stat-card kpi-card h-100" data-kpi="cpu">
|
||||
<div class="card border-0 shadow-sm stat-card kpi-card kpi-card-featured h-100" data-kpi="cpu">
|
||||
<div class="kpi-graph"></div>
|
||||
<div class="card-body position-relative">
|
||||
<div class="small text-body-secondary mb-2">CPU</div>
|
||||
<div class="display-6 fw-bold" data-kpi-value="cpu">{{printf "%.1f" $data.Node.CPUUsage}}%</div>
|
||||
<div class="d-flex align-items-start justify-content-between gap-3 mb-3">
|
||||
<div>
|
||||
<div class="kpi-card-label">CPU usage</div>
|
||||
<div class="kpi-card-subtle">Live</div>
|
||||
</div>
|
||||
<span class="kpi-card-chip">Last minute</span>
|
||||
</div>
|
||||
<div class="kpi-card-featured-value" data-kpi-value="cpu">{{printf "%.1f" $data.Node.CPUUsage}}%</div>
|
||||
<div class="kpi-card-featured-trend">
|
||||
<span class="kpi-card-trend is-flat" data-kpi-trend="cpu">0%</span>
|
||||
<span class="kpi-card-trend-copy">from previous sample</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,8 +70,8 @@
|
||||
<div class="card-body p-4">
|
||||
<div class="system-summary vstack gap-3">
|
||||
<div class="system-summary-item">
|
||||
<div class="chip-icon system-summary-icon">
|
||||
<i class="{{nodeIconClass $data.Node.Distro $data.Node.PackageManager}}"></i>
|
||||
<div class="chip-icon chip-icon-plain system-summary-icon system-summary-icon-plain">
|
||||
<i class="{{nodeIconClass $data.Node.Distro $data.Node.PackageManager}} distro-icon distro-icon-lg"></i>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<div class="system-summary-label">Distribution</div>
|
||||
@@ -69,7 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="system-summary-item">
|
||||
<div class="chip-icon system-summary-icon">
|
||||
<div class="chip-icon chip-icon-plain system-summary-icon system-summary-icon-plain">
|
||||
<i class="{{packageManagerIconClass $data.Node.PackageManager}}"></i>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
{{define "content"}}
|
||||
<div class="mb-4">
|
||||
<h2 class="fw-bold mb-0">Create Account</h2>
|
||||
<div class="text-center mb-4">
|
||||
<h1 class="h3 fw-bold mb-0">Create account</h1>
|
||||
</div>
|
||||
{{with .Content}}{{with .Error}}<div class="alert alert-danger">{{.}}</div>{{end}}{{end}}
|
||||
<form method="post">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Name</label>
|
||||
<input type="text" class="form-control form-control-lg" name="name" required>
|
||||
<input type="text" class="form-control auth-input" name="name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" name="email" required>
|
||||
<input type="email" class="form-control auth-input" name="email" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Password</label>
|
||||
<input type="password" class="form-control form-control-lg" name="password" required>
|
||||
<input type="password" class="form-control auth-input" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100"><i class="ti ti-user-plus me-2"></i>Create account</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100">Create account</button>
|
||||
</form>
|
||||
<p class="mt-4 text-body-secondary mb-0">Already registered? <a href="/login" class="link-primary link-offset-2">Sign in</a></p>
|
||||
<div class="text-center mt-4 small text-body-secondary">
|
||||
<a href="/login" class="link-primary link-offset-2">Back to sign in</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -38,7 +38,6 @@ func NewRenderer() (*Renderer, error) {
|
||||
"contains": strings.Contains,
|
||||
"distroIconClass": distroIconClass,
|
||||
"nodeIconClass": nodeIconClass,
|
||||
"nodeIconName": nodeIconName,
|
||||
"nodeIconPending": nodeIconPending,
|
||||
"packageManagerIconClass": packageManagerIconClass,
|
||||
"packageManagerLabel": packageManagerLabel,
|
||||
@@ -134,11 +133,11 @@ func distroIconClass(distro string) string {
|
||||
value := strings.ToLower(strings.TrimSpace(distro))
|
||||
switch {
|
||||
case strings.Contains(value, "ubuntu"):
|
||||
return "fa-brands fa-ubuntu"
|
||||
return "fl-ubuntu"
|
||||
case strings.Contains(value, "debian"):
|
||||
return "fa-brands fa-debian"
|
||||
return "fl-debian"
|
||||
case strings.Contains(value, "arch"), strings.Contains(value, "manjaro"), strings.Contains(value, "endeavouros"):
|
||||
return "ti ti-brand-archlinux"
|
||||
return "fl-archlinux"
|
||||
default:
|
||||
return "ti ti-server-2"
|
||||
}
|
||||
@@ -151,35 +150,14 @@ func nodeIconClass(distro, packageManager string) string {
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(packageManager)) {
|
||||
case "apt":
|
||||
return "fa-brands fa-debian"
|
||||
return "fl-debian"
|
||||
case "pacman":
|
||||
return "ti ti-brand-archlinux"
|
||||
return "fl-archlinux"
|
||||
default:
|
||||
return "ti ti-server-2"
|
||||
}
|
||||
}
|
||||
|
||||
func nodeIconName(distro, packageManager string) string {
|
||||
value := strings.ToLower(strings.TrimSpace(distro))
|
||||
switch {
|
||||
case strings.Contains(value, "ubuntu"):
|
||||
return "ubuntu"
|
||||
case strings.Contains(value, "debian"):
|
||||
return "debian"
|
||||
case strings.Contains(value, "arch"), strings.Contains(value, "manjaro"), strings.Contains(value, "endeavouros"):
|
||||
return "arch"
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(packageManager)) {
|
||||
case "apt":
|
||||
return "debian"
|
||||
case "pacman":
|
||||
return "arch"
|
||||
default:
|
||||
return "server"
|
||||
}
|
||||
}
|
||||
|
||||
func nodeIconPending(distro, packageManager string) bool {
|
||||
distroValue := strings.ToLower(strings.TrimSpace(distro))
|
||||
packageValue := strings.ToLower(strings.TrimSpace(packageManager))
|
||||
@@ -189,7 +167,7 @@ func nodeIconPending(distro, packageManager string) bool {
|
||||
func packageManagerIconClass(value string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case "apt":
|
||||
return "fa-brands fa-debian"
|
||||
return "ti ti-brand-debian"
|
||||
case "pacman":
|
||||
return "ti ti-brand-archlinux"
|
||||
case "dnf", "yum", "zypper", "apk", "nix", "emerge":
|
||||
|
||||
Reference in New Issue
Block a user