All checks were successful
check / check (push) Successful in 4s
Unifies user-visible copy on "Webhook" (routes and URLs unchanged), drops the placeholder Profile settings section, and adds a copy-to-clipboard affordance for the entrypoint URL as progressive enhancement — the button stays hidden unless both the target element and the Clipboard API resolve, so no dead control appears without JavaScript and the URL stays selectable. Retention copy now matches what the code does: deletion is permanent, 0 retains forever, and a blank field means the default on create or the current value on edit. The permanent-deletion sentence is suppressed for a retain-forever webhook, which the reaper exempts before computing a cutoff. Template tests gained a render-completed assertion. Without it, a page that aborted mid-render still satisfied assertions matching the already-flushed prefix, because renderTemplate streams to the ResponseWriter (#123).
101 lines
3.5 KiB
HTML
101 lines
3.5 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}Profile - Webhooker{{end}}
|
|
|
|
{{define "content"}}
|
|
<div class="max-w-4xl mx-auto px-6 py-12">
|
|
<h1 class="text-2xl font-medium text-gray-900 mb-6">User Profile</h1>
|
|
|
|
{{if .SuccessMessage}}
|
|
<div class="alert-success">
|
|
<span>{{.SuccessMessage}}</span>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .ErrorMessage}}
|
|
<div class="alert-error">
|
|
<span>{{.ErrorMessage}}</span>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="card p-6">
|
|
<div class="flex items-center mb-6">
|
|
<div class="mr-4">
|
|
<svg class="w-16 h-16 text-primary-500" fill="currentColor" viewBox="0 0 16 16">
|
|
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
|
|
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<h2 class="text-xl font-medium text-gray-900">{{.User.Username}}</h2>
|
|
<p class="text-sm text-gray-500">User ID: {{.User.ID}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="border-gray-200 mb-6">
|
|
|
|
<div>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-3">Account Information</h3>
|
|
<dl class="space-y-3">
|
|
<div class="flex">
|
|
<dt class="w-32 text-sm font-medium text-gray-500">Username</dt>
|
|
<dd class="text-sm text-gray-900">{{.User.Username}}</dd>
|
|
</div>
|
|
<div class="flex">
|
|
<dt class="w-32 text-sm font-medium text-gray-500">Account Type</dt>
|
|
<dd class="text-sm text-gray-900">Standard User</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card p-6 mt-6">
|
|
<h3 class="text-lg font-medium text-gray-900 mb-3">Change Password</h3>
|
|
<form method="POST" action="/user/{{.User.Username}}/password" class="space-y-6">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
<div class="form-group">
|
|
<label for="current_password" class="label">Current Password</label>
|
|
<input
|
|
type="password"
|
|
id="current_password"
|
|
name="current_password"
|
|
required
|
|
autocomplete="current-password"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="new_password" class="label">New Password</label>
|
|
<input
|
|
type="password"
|
|
id="new_password"
|
|
name="new_password"
|
|
required
|
|
autocomplete="new-password"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="confirm_password" class="label">Confirm New Password</label>
|
|
<input
|
|
type="password"
|
|
id="confirm_password"
|
|
name="confirm_password"
|
|
required
|
|
autocomplete="new-password"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-primary">Change Password</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="mt-6">
|
|
<a href="/" class="btn-secondary">Back to Home</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|