Files
Maintainarr/internal/views/layouts/app.gohtml

211 lines
9.8 KiB
Plaintext

{{define "contextAction"}}
{{if and .User (ne .User.Role "viewer")}}
{{if eq .CurrentPath "/automations"}}
<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 "/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
</button>
{{else if eq .CurrentPath "/settings"}}
<a class="btn btn-primary" href="#theme-presets">
<i class="ti ti-plus me-1"></i>Themes
</a>
{{else}}
<button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#addVmModal">
<i class="ti ti-plus me-1"></i>Add VM
</button>
{{end}}
{{end}}
{{end}}
{{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">
<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>
</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>
</nav>
<div class="card mt-auto border-0 sidebar-status">
<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">
<img src="/static/img/maintainarr_logo.png" alt="" class="sidebar-logo">
<div class="min-w-0">
<div class="fw-semibold text-truncate">{{with .User}}{{.Name}}{{end}}</div>
<div class="text-body-secondary small text-truncate">{{with .User}}{{.Role}}{{end}}</div>
</div>
</div>
<a class="btn btn-outline-secondary btn-sm" href="/logout"><i class="fa-solid fa-right-from-bracket"></i></a>
</div>
</div>
</div>
</div>
</aside>
<div class="d-flex flex-column flex-grow-1 min-w-0">
{{if not (contains .CurrentPath "/console")}}
<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 class="d-flex align-items-center gap-2">
{{template "contextAction" .}}
</div>
</div>
</div>
</header>
{{end}}
<main class="content flex-grow-1">
<div class="container-fluid {{if contains .CurrentPath "/console"}}p-0{{else}}px-3 px-lg-4 py-4{{end}}">
{{template "content" .}}
</div>
</main>
{{if not (contains .CurrentPath "/console")}}
<footer class="app-footer border-top">
<div class="container-fluid px-3 px-lg-4 py-3 d-flex flex-column flex-md-row justify-content-between gap-2 small text-body-secondary">
<span>{{with .Organization}}{{.Name}}{{end}}</span>
<span>{{with .User}}{{.Name}} · {{.Role}}{{end}}</span>
</div>
</footer>
{{end}}
</div>
</div>
{{if and .User (ne .User.Role "viewer")}}
<div class="modal fade" id="createGroupModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 shadow-lg">
<form method="post" action="/groups">
<div class="modal-header">
<h2 class="modal-title fs-5">Create Group</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div>
<label class="form-label">Description</label>
<textarea class="form-control" name="description" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary"><i class="ti ti-plus me-1"></i>Create Group</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="addVmModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content border-0 shadow-lg">
<form method="post" action="/nodes" enctype="multipart/form-data">
<div class="modal-header">
<h2 class="modal-title fs-5">Add VM</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-4 p-lg-5">
<div class="add-vm-form">
<section class="add-vm-panel">
<div class="add-vm-panel-title">Node</div>
<div class="row g-3">
<div class="col-12 col-lg-6">
<label class="form-label">IP address</label>
<input type="text" class="form-control" name="ip_address" placeholder="10.0.20.24" required>
</div>
<div class="col-12 col-lg-6">
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name" placeholder="Optional display name">
</div>
<div class="col-12 col-lg-6">
<label class="form-label">Group</label>
<select class="form-select" name="group_id">
<option value="">None</option>
{{range .AvailableGroups}}<option value="{{.ID}}">{{.Name}}</option>{{end}}
</select>
</div>
<div class="col-12 col-lg-6">
<label class="form-label">Tag</label>
<input type="text" class="form-control" name="tag" list="vm-tag-options" placeholder="prod, edge, lab">
<datalist id="vm-tag-options">
{{range .AvailableTags}}<option value="{{.}}"></option>{{end}}
</datalist>
</div>
</div>
</section>
<section class="add-vm-panel">
<div class="add-vm-panel-title">Access</div>
<div class="mb-3">
<label class="form-label">Username</label>
<input type="text" class="form-control" name="ssh_username" placeholder="root" required>
</div>
<div class="auth-toggle mb-3" data-auth-toggle>
<input type="radio" class="btn-check" name="auth_mode" id="authModePassword" value="password" autocomplete="off" checked>
<label class="auth-toggle-option" for="authModePassword">
<span class="auth-toggle-label">Password</span>
</label>
<input type="radio" class="btn-check" name="auth_mode" id="authModeKey" value="key" autocomplete="off">
<label class="auth-toggle-option" for="authModeKey">
<span class="auth-toggle-label">Key File</span>
</label>
</div>
<div class="auth-mode-panel" data-auth-panel="password">
<label class="form-label">Password</label>
<input type="password" class="form-control" name="ssh_password" placeholder="Password" data-auth-input="password">
</div>
<div class="auth-mode-panel d-none" data-auth-panel="key">
<label class="form-label">SSH key</label>
<input type="file" class="form-control" name="ssh_key" data-auth-input="key">
</div>
</section>
<section class="add-vm-panel add-vm-panel-wide">
<div class="add-vm-panel-title">Options</div>
<div class="row g-3 align-items-start">
<div class="col-12 col-lg-8">
<label class="form-label">Notes</label>
<textarea class="form-control" name="notes" rows="4" placeholder="Optional notes"></textarea>
</div>
<div class="col-12 col-lg-4">
<label class="form-label d-block">Behavior</label>
<label class="option-check">
<input class="form-check-input" type="checkbox" value="on" id="autoUpdatesEnabled" name="auto_updates_enabled">
<span>Enable auto updates</span>
</label>
</div>
</div>
</section>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary"><i class="ti ti-plus me-1"></i>Create VM</button>
</div>
</form>
</div>
</div>
</div>
{{end}}
{{end}}