website/web/templates/account/dashboard.html
Noah 6c91c67c97 More Private User Avatars
* Users who set their Profile Picture to "friends only" or "private" can have
  their avatar be private all over the website to users who are not their
  friends or not granted access.
* Users who are not your friends see a yellow placeholder avatar, and users
  not granted access to a private Profile Pic sees a purple avatar.
* Admin users see these same placeholder avatars most places too (on search,
  forums, comments, etc.) if the user did not friend or grant the admin. But
  admins ALWAYS see it on their Profile Page directly, for ability to moderate.
* Fix marking Notifications as read: clicking the link in an unread notification
  now will wait on the ajax request to finish before allowing the redirect.
* Update the FAQ
2022-09-08 21:42:20 -07:00

407 lines
23 KiB
HTML

{{define "title"}}My Dashboard{{end}}
{{define "content"}}
<div class="container">
<section class="hero is-info is-bold">
<div class="hero-body">
<div class="container">
<h1 class="title">User Dashboard</h1>
<h2 class="subtitle">to your account</h2>
</div>
</div>
</section>
<div class="block p-4">
<div class="columns">
<div class="column">
<!-- Onboarding Checklist -->
{{if or (not .CurrentUser.Certified) (not .CurrentUser.ProfilePhoto.ID)}}
<div class="card block">
<header class="card-header has-background-danger">
<p class="card-header-title has-text-light">
<span class="icon"><i class="fa fa-check"></i></span>
<span>Onboarding Checklist</span>
</p>
</header>
<div class="card-content">
<p class="block">
You're almost there! Please review the following checklist items to gain
full access to this website. Members are expected to have a face picture
as their default Profile Pic and upload a Verification Photo to become
certified as being a real person.
</p>
<ul class="menu-list block">
<li>
<a href="/photo/upload?intent=profile_pic">
{{if .CurrentUser.ProfilePhoto.ID}}
<span class="icon"><i class="fa fa-circle-check has-text-success"></i></span>
{{else}}
<span class="icon"><i class="fa fa-circle has-text-danger"></i></span>
{{end}}
<span>
Add a Profile Picture
{{if not .CurrentUser.ProfilePhoto.ID}}
<span class="icon"><i class="fa fa-external-link"></i></span>
{{end}}
</span>
</a>
</li>
<li>
<a href="/photo/certification">
{{if .CurrentUser.Certified}}
<span class="icon"><i class="fa fa-circle-check has-text-success"></i></span>
{{else}}
<span class="icon"><i class="fa fa-circle has-text-danger"></i></span>
{{end}}
<span>
Get certified by uploading a verification selfie
{{if not .CurrentUser.Certified}}
<span class="icon"><i class="fa fa-external-link"></i></span>
{{end}}
</span>
</a>
</li>
</ul>
</div>
</div>
{{end}}
<div class="card block">
<header class="card-header has-background-link">
<p class="card-header-title has-text-light">My Account</p>
</header>
<div class="card-content">
<ul class="menu-list">
<li>
<a href="/u/{{.CurrentUser.Username}}">
<span class="icon"><i class="fa fa-user"></i></span>
My Profile
</a>
</li>
<li>
<a href="/photo/u/{{.CurrentUser.Username}}">
<span class="icon"><i class="fa fa-image"></i></span>
My Photos
</a>
</li>
<li>
<a href="/photo/upload">
<span class="icon"><i class="fa fa-upload"></i></span>
Upload Photos
</a>
</li>
<li>
<a href="/photo/private">
<span class="icon"><i class="fa fa-eye"></i></span>
Manage Private Photos
<span class="tag is-success ml-1">NEW!</span>
</a>
</li>
<li>
<a href="/settings">
<span class="icon"><i class="fa fa-edit"></i></span>
Edit Profile &amp; Settings
</a>
</li>
<li>
<a href="/photo/certification">
<span class="icon"><i class="fa fa-certificate"></i></span>
Certification Photo
</a>
</li>
<li>
<a href="/users/blocked">
<span class="icon"><i class="fa fa-hand"></i></span>
Blocked Users
</a>
</li>
<li>
<a href="/logout">
<span class="icon"><i class="fa fa-arrow-right-from-bracket"></i></span>
Log out
</a>
</li>
{{if .SessionImpersonated}}
<li>
<a href="/admin/unimpersonate" class="has-text-danger">
<span class="icon"><i class="fa fa-ghost"></i></span>
<span>Unimpersonate</span>
</a>
</li>
{{end}}
<li>
<a href="/account/delete">
<span class="icon"><i class="fa fa-trash"></i></span>
Delete account
</a>
</li>
</ul>
</div>
</div>
</div>
{{$Root := .}}
<div class="column">
<div class="card" id="notifications">
<header class="card-header has-background-warning">
<p class="card-header-title has-text-dark-dark">Notifications</p>
</header>
<div class="card-content">
<div class="columns">
<div class="column">
{{if gt .NavUnreadNotifications 0}}
{{.NavUnreadNotifications}} unread notification{{Pluralize64 .NavUnreadNotifications}}.
{{else}}
No unread notifications.
{{end}}
</div>
<div class="column is-narrow">
<a href="/me?intent=read-notifications" class="button is-link is-light is-small">
<span class="icon-text">
<span class="icon"><i class="fa fa-check"></i></span>
<span>Mark all as read</span>
</span>
</a>
</div>
</div>
<table class="table is-striped is-fullwidth is-hoverable">
<tbody>
{{range .Notifications}}
{{$Body := $Root.NotifMap.Get .ID}}
<tr>
<td class="nonshy-notification-row" data-notification-id="{{.ID}}">
<div class="columns">
<div class="column is-narrow has-text-centered">
{{if not .Read}}
<div class="mb-2 nonshy-notification-new">
<strong class="tag is-success">NEW!</strong>
</div>
{{end}}
<a href="/u/{{.AboutUser.Username}}">
{{template "avatar-48x48" .AboutUser}}
</a>
</div>
<div class="column">
<div class="mb-1">
{{if eq .Type "like"}}
<span class="icon"><i class="fa fa-heart has-text-danger"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
liked your
{{if eq .TableName "photos"}}
{{if $Body.Photo}}
<a href="/photo/view?id={{$Body.Photo.ID}}">photo</a>.
{{else}}
photo.
{{end}}
{{else if eq .TableName "users"}}
profile page.
{{else if eq .TableName "comments"}}
{{if .Link}}
<a href="{{.Link}}">comment</a>:
{{else}}
comment.
{{end}}
{{else}}
{{.TableName}}.
{{end}}
</span>
{{else if eq .Type "comment"}}
<span class="icon"><i class="fa fa-comment has-text-success"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
commented on your
<a href="{{.Link}}">
{{if eq .TableName "photos"}}
photo:
{{else}}
{{.TableName}}:
{{end}}
</a>
</span>
{{else if eq .Type "also_comment"}}
<span class="icon"><i class="fa fa-comment has-text-success"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
also commented on a
<a href="{{.Link}}">
{{if eq .TableName "photos"}}
photo
{{else}}
{{.TableName}}
{{end}}
</a>
that you replied to:
</span>
{{else if eq .Type "also_posted"}}
<span class="icon"><i class="fa fa-comments has-text-success"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
replied to <a href="{{.Link}}">a forum thread</a> that you follow:
</span>
{{else if eq .Type "friendship_approved"}}
<span class="icon"><i class="fa fa-user-group has-text-success"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
accepted your friend request!
</span>
{{else if eq .Type "private_photo"}}
<span class="icon"><i class="fa fa-unlock has-text-private"></i></span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
has granted you access to see their
<a href="{{.Link}}" class="has-text-private">private photos</a>!
</span>
{{else if eq .Type "cert_approved"}}
<span class="icon"><i class="fa fa-certificate has-text-success"></i></span>
<span>
Your <strong>certification photo</strong> was approved!
</span>
{{else if eq .Type "cert_rejected"}}
<span class="icon"><i class="fa fa-certificate has-text-danger"></i></span>
<span>
Your <strong>certification photo</strong> was rejected!
</span>
{{else}}
{{.AboutUser.Username}} {{.Type}} {{.TableName}} {{.TableID}}
{{end}}
</div>
<!-- Attached message? -->
{{if .Message}}
<div class="block content mb-1">
<blockquote class="p-2 pl-4">{{ToMarkdown (TrimEllipses .Message 256)}}</blockquote>
</div>
{{end}}
<!-- Attached forum thread? -->
{{if $Body.Thread}}
<div>
On thread: <a href="{{.Link}}">{{$Body.Thread.Title}}</a>
</div>
{{end}}
<!-- Photo caption? -->
{{if $Body.Photo}}
<div class="block">
<!-- If it's a comment, have a link to view it -->
{{if eq .Type "comment"}}
<div class="is-size-7 pt-1">
<span class="icon"><i class="fa fa-arrow-right"></i></span>
<a href="{{.Link}}">See all comments</a>
</div>
{{else}}
<em>{{or $Body.Photo.Caption "No caption."}}</em>
{{end}}
</div>
{{end}}
<hr class="has-background-light mb-1">
<small title="{{.CreatedAt.Format "2006-01-02 15:04:05"}}">
{{SincePrettyCoarse .CreatedAt}} ago
</small>
</div>
<!-- Attached photo? -->
{{if $Body.PhotoID}}
<div class="column is-one-quarter">
<a href="/photo/view?id={{$Body.Photo.ID}}">
<img src="{{PhotoURL $Body.Photo.Filename}}">
</a>
{{if $Body.Photo.Caption}}
<small>{{$Body.Photo.Caption}}</small>
{{else}}
<small><em>No caption.</em></small>
{{end}}
</div>
{{end}}
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
{{if .Pager.HasNext}}
<div class="has-text-centered">
<a href="{{.Request.URL.Path}}?page={{.Pager.Next}}" class="button">View older notifications</a>
</div>
{{end}}
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// Notifications helper.
document.addEventListener('DOMContentLoaded', () => {
let busy = false;
// Bind to the notification table rows.
(document.querySelectorAll(".nonshy-notification-row") || []).forEach(node => {
let $newBadge = node.querySelector(".nonshy-notification-new"),
ID = node.dataset.notificationId;
// If the notification doesn't have a "NEW!" badge, no action needed.
if ($newBadge === null) return;
// Collect any hyperlinks in this row.
let links = Array.from(node.querySelectorAll("a"));
links.push(node);
// Apply a "click" handler to the notification row as a whole, and to all of the hyperlinks in it.
// For the hyperlinks: prevent the browser following the link UNTIL the successful ajax request to
// mark the notification "read" has run.
links.forEach(link => {
link.addEventListener("click", (e) => {
if (busy) return;
// In case it's a hyperlink, grab the href.
let href = link.attributes.href;
if (href !== undefined) {
e.preventDefault();
href = href.textContent;
}
$newBadge.style.display = "none";
busy = true;
return fetch("/v1/notifications/read", {
method: "POST",
mode: "same-origin",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"id": parseInt(ID),
}),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
}).catch(resp => {
window.alert(resp);
}).finally(() => {
busy = false;
if (href !== undefined) {
window.location.href = href;
}
});
})
})
});
});
</script>
{{end}}