| 1 |
{% extends "base.html" %} |
| 2 |
{% import "settings_tabs.html" as t %} |
| 3 |
{% block title %}Profile{% endblock %} |
| 4 |
{% block tabs %}{% call t::tabs("profile") %}{% endblock %} |
| 5 |
{% block content %} |
| 6 |
<div class="head"><h1>Profile <small>{{ me.username }}</small></h1></div> |
| 7 |
{% if let Some(n) = notice %}<p class="note">{{ n }}</p>{% endif %} |
| 8 |
{% if let Some(e) = error %}<p class="error">{{ e }}</p>{% endif %} |
| 9 |
<div class="sectioned"> |
| 10 |
<nav class="section-nav" aria-label="Sections"> |
| 11 |
<a href="#profile">Profile</a> |
| 12 |
<a href="#picture">Picture</a> |
| 13 |
<a href="#appearance">Appearance</a> |
| 14 |
<a href="#password">Password</a> |
| 15 |
</nav> |
| 16 |
<div class="sections"> |
| 17 |
<form id="verify-email" method="post" action="/settings/email/verify" hidden><input type="hidden" name="_csrf" value="{{ shell.csrf }}"></form> |
| 18 |
<form class="card" id="profile" method="post" action="/settings"> |
| 19 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 20 |
<label for="display_name">Display name</label><input type="text" id="display_name" name="display_name" value="{{ me.display_name }}"> |
| 21 |
<label for="email">Email</label><input type="email" id="email" name="email" value="{{ me.email }}"> |
| 22 |
<p class="small mute">Your email is never shown on your profile. {% if me.email.is_empty() %}Add one to receive notification email and reset your password by email.{% else if me.email_verified %}<span class="sig sig-valid">✔</span> Verified.{% else %}<span class="sig sig-unsigned">○</span> Not verified yet{% if mail %}: use the link we sent, or <button type="submit" form="verify-email" class="linkish">send a new one</button>{% endif %}.{% endif %}</p> |
| 23 |
<label for="bio">Bio</label><textarea id="bio" name="bio" rows="3" maxlength="280">{{ me.bio }}</textarea> |
| 24 |
<label for="website">Website</label><input type="url" id="website" name="website" value="{{ me.website }}" placeholder="https://"> |
| 25 |
<label for="location">Location</label><input type="text" id="location" name="location" value="{{ me.location }}" maxlength="80"> |
| 26 |
<label for="bluesky">Bluesky</label><input type="text" id="bluesky" name="bluesky" value="{{ me.bluesky }}" placeholder="andy.bsky.social"> |
| 27 |
<label for="mastodon">Mastodon</label><input type="text" id="mastodon" name="mastodon" value="{% if !me.mastodon.is_empty() %}@{{ me.mastodon }}{% endif %}" placeholder="@[email protected]"> |
| 28 |
<label for="github">GitHub</label><input type="text" id="github" name="github" value="{{ me.github }}" placeholder="andymccall"> |
| 29 |
<p class="small mute">Shown on <a href="/{{ me.username }}">your profile</a>, with a picture drawn from your username.</p> |
| 30 |
<button type="submit">SAVE</button> |
| 31 |
</form> |
| 32 |
<form class="card picture-card" id="picture" method="post" action="/settings/avatar" enctype="multipart/form-data"> |
| 33 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 34 |
<h2>Picture</h2> |
| 35 |
<div class="picture-row"> |
| 36 |
<img class="avatar xl" src="/avatar/{{ me.username }}?v={{ me.avatar }}" alt="Your picture" width="96" height="96"> |
| 37 |
<div> |
| 38 |
<label for="picture-file">Upload a photo</label> |
| 39 |
<input type="file" id="picture-file" name="picture" accept="image/png,image/jpeg,image/webp"> |
| 40 |
<p class="small mute">PNG, JPEG or WebP, up to 5 MiB. It is cropped to the middle square and resized to 400×400.{% if me.avatar.is_empty() %} Until then you have a picture drawn from your username.{% endif %}</p> |
| 41 |
<button type="submit" name="action" value="upload">UPLOAD</button> |
| 42 |
{% if !me.avatar.is_empty() %}<button type="submit" name="action" value="remove" class="danger-btn">REMOVE</button>{% endif %} |
| 43 |
</div> |
| 44 |
</div> |
| 45 |
</form> |
| 46 |
<form class="card" id="appearance" method="post" action="/settings/appearance"> |
| 47 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 48 |
<h2>Appearance</h2> |
| 49 |
<fieldset class="choices"> |
| 50 |
<legend class="small mute">Theme, remembered in this browser</legend> |
| 51 |
{% for (value, label) in themes %} |
| 52 |
<label class="choice"><input type="radio" name="theme" value="{{ value }}"{% if theme == *value %} checked{% endif %}> {{ label }}</label> |
| 53 |
{% endfor %} |
| 54 |
</fieldset> |
| 55 |
<button type="submit">SAVE</button> |
| 56 |
</form> |
| 57 |
<form class="card" id="password" method="post" action="/settings/password"> |
| 58 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 59 |
<h2>Change password</h2> |
| 60 |
<label for="current">Current password</label><input type="password" id="current" name="current" autocomplete="current-password" required> |
| 61 |
<label for="password">New password</label><input type="password" id="password" name="password" autocomplete="new-password" required minlength="10"> |
| 62 |
<p class="small mute">Changing it signs out every other session.</p> |
| 63 |
<button type="submit">CHANGE PASSWORD</button> |
| 64 |
</form> |
| 65 |
</div> |
| 66 |
</div> |
| 67 |
{% endblock %} |