185 lines
7.4 KiB
HTML
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>
|