Files
docs/templates/admin_edit.html
2026-07-28 07:20:32 -05:00

185 lines
7.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
{{template "head" .}}
<title>{{if .Page}}Edit: {{.Page.Title}}{{else}}New Page{{end}} — Admin — Arcline</title>
<meta name="robots" content="noindex">
<style>
.admin-wrap { max-width:860px; margin:2.5rem auto; padding:0 1.5rem; }
.admin-header{ display:flex; align-items:center; gap:1rem; margin-bottom:1.75rem; }
.admin-header h1 { font-size:1.375rem; font-weight:800; color:var(--text-strong); margin:0; }
.form-grid { display:grid; grid-template-columns:1fr 1fr; gap:1rem; }
.form-group { display:flex; flex-direction:column; gap:.375rem; }
.form-group--full { grid-column:1/-1; }
label { font-size:.8125rem; font-weight:600; color:var(--text-strong); }
input[type=text], input[type=number], select, textarea {
font-family:var(--mono); font-size:.875rem;
padding:.5rem .75rem; border:1px solid var(--border);
border-radius:var(--radius-sm); background:var(--white);
color:var(--text-strong); width:100%; box-sizing:border-box;
transition:border-color var(--t);
}
input:focus, select:focus, textarea:focus { outline:none; border-color:var(--accent); }
textarea { font-family:var(--mono); font-size:.8125rem; min-height:420px; resize:vertical; line-height:1.6; }
.vis-row { display:flex; gap:.75rem; align-items:center; flex-wrap:wrap; }
.vis-radio { display:flex; align-items:center; gap:.375rem; font-size:.875rem; cursor:pointer; }
.form-hint { font-size:.75rem; color:var(--text-muted); margin-top:.25rem; }
.form-actions{ display:flex; gap:.75rem; margin-top:1.5rem; align-items:center; }
.error-box { background:#fef2f2; border:1px solid #fca5a5; border-left:3px solid #ef4444;
border-radius:var(--radius-sm); padding:.875rem 1.125rem; margin-bottom:1.25rem;
font-size:.9rem; color:#991b1b; }
#vis-plan-wrap, #vis-customer-wrap { display:none; }
@media(max-width:640px){ .form-grid{ grid-template-columns:1fr; } }
</style>
</head>
<body>
{{template "nav" .}}
<div class="admin-wrap">
<div class="admin-header">
<h1>{{if .Page}}Edit page{{else}}New page{{end}}</h1>
</div>
{{if .Error}}
<div class="error-box">{{.Error}}</div>
{{end}}
<form method="POST"
action="{{if .Page}}/admin/pages/{{.Page.ID}}{{else}}/admin/pages{{end}}">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<div class="form-grid">
<div class="form-group">
<label for="title">Title</label>
<input type="text" id="title" name="title" required
value="{{if .Page}}{{.Page.Title}}{{end}}"
placeholder="e.g. Server Setup Guide">
</div>
<div class="form-group">
<label for="slug">Slug</label>
<input type="text" id="slug" name="slug" required
value="{{if .Page}}{{.Page.Slug}}{{end}}"
placeholder="e.g. server-setup-guide">
<span class="form-hint">URL: /client/<em>slug</em>/</span>
</div>
<div class="form-group form-group--full">
<label for="description">Description <span style="font-weight:400;color:var(--text-muted)">(optional)</span></label>
<input type="text" id="description" name="description"
value="{{if .Page}}{{.Page.Description}}{{end}}"
placeholder="Short summary shown in listings">
</div>
<div class="form-group">
<label for="section">Section</label>
<input type="text" id="section" name="section"
value="{{if .Page}}{{.Page.Section}}{{else}}client{{end}}"
placeholder="client">
<span class="form-hint">Use "client" for customer-facing docs.</span>
</div>
<div class="form-group">
<label for="display_order">Display order</label>
<input type="number" id="display_order" name="display_order" min="0"
value="{{if .Page}}{{.Page.DisplayOrder}}{{else}}0{{end}}">
</div>
<div class="form-group form-group--full">
<label>Visibility</label>
<div class="vis-row">
<label class="vis-radio">
<input type="radio" name="vis_type" value="public"
{{if or (not .Page) (eq .Page.Visibility "public")}}checked{{end}}>
Public
</label>
<label class="vis-radio">
<input type="radio" name="vis_type" value="plan"
{{if and .Page (hasPrefix .Page.Visibility "plan:")}}checked{{end}}>
Plan
</label>
<label class="vis-radio">
<input type="radio" name="vis_type" value="customer"
{{if and .Page (hasPrefix .Page.Visibility "customer:")}}checked{{end}}>
Customer
</label>
</div>
<div id="vis-plan-wrap" style="margin-top:.5rem;">
<select name="vis_plan" id="vis_plan">
{{range .PlanOptions}}
<option value="{{.Key}}"
{{if and $.Page (eq $.Page.Visibility (print "plan:" .Key))}}selected{{end}}>
{{.Name}}
</option>
{{end}}
</select>
<span class="form-hint">Visible to all customers on this plan with an active subscription.</span>
</div>
<div id="vis-customer-wrap" style="margin-top:.5rem;">
<select name="vis_customer" id="vis_customer">
{{range .Customers}}
<option value="{{.ID}}"
{{if and $.Page (eq $.Page.Visibility (print "customer:" .ID))}}selected{{end}}>
{{.FirstName}} {{.LastName}} ({{.Email}})
</option>
{{end}}
</select>
<span class="form-hint">Visible to this customer only.</span>
</div>
</div>
<div class="form-group form-group--full">
<label for="content">Content <span style="font-weight:400;color:var(--text-muted)">(Markdown)</span></label>
<textarea id="content" name="content" placeholder="Write markdown here...">{{if .Page}}{{.Page.Content}}{{end}}</textarea>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn--primary">{{if .Page}}Save changes{{else}}Create page{{end}}</button>
<a href="/admin/" class="btn btn--ghost">Cancel</a>
{{if .Page}}
<a href="/client/{{.Page.Slug}}/" class="btn btn--ghost btn--sm" target="_blank"
style="margin-left:auto;">View page →</a>
{{end}}
</div>
</form>
</div>
{{template "footer-simple" .}}
<script>
(function() {
var radios = document.querySelectorAll('[name="vis_type"]');
var planWrap = document.getElementById('vis-plan-wrap');
var custWrap = document.getElementById('vis-customer-wrap');
function update() {
var val = document.querySelector('[name="vis_type"]:checked');
if (!val) return;
planWrap.style.display = val.value === 'plan' ? 'block' : 'none';
custWrap.style.display = val.value === 'customer' ? 'block' : 'none';
}
radios.forEach(function(r) { r.addEventListener('change', update); });
update();
var titleInput = document.getElementById('title');
var slugInput = document.getElementById('slug');
var slugTouched = slugInput.value !== '';
titleInput.addEventListener('input', function() {
if (slugTouched) return;
slugInput.value = titleInput.value
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
});
slugInput.addEventListener('input', function() { slugTouched = true; });
})();
</script>
</body>
</html>