f2e847922f
* Profile pictures on profile pages now link to the gallery when clicked. * Admins can no longer automatically see the default profile pic on profile pages unless they have photo moderator ability. * Photo view counts are not added when an admin with photo moderator ability should not have otherwise been able to see the photo.
555 lines
28 KiB
HTML
555 lines
28 KiB
HTML
{{define "title"}}{{.User.Username}}{{end}}
|
|
{{define "content"}}
|
|
{{template "profile-theme-style" .User}}
|
|
<div class="container">
|
|
<section class="hero {{if and .LoggedIn (not .IsPrivate)}}is-info{{else}}is-light is-bold{{end}}">
|
|
<div class="hero-body">
|
|
<div class="container">
|
|
<div class="columns">
|
|
<div class="column is-narrow has-text-centered">
|
|
<figure class="profile-photo is-inline-block">
|
|
{{if or (not .CurrentUser) .IsExternalView}}
|
|
<img src="{{.User.VisibleAvatarURL nil}}" data-photo-id="{{.User.ProfilePhoto.ID}}">
|
|
{{else}}
|
|
<a href="/u/{{.User.Username}}/photos">
|
|
<img src="{{.User.VisibleAvatarURL .CurrentUser}}" data-photo-id="{{.User.ProfilePhoto.ID}}">
|
|
</a>
|
|
{{end}}
|
|
|
|
<!-- CurrentUser can upload a new profile pic -->
|
|
{{if and .LoggedIn (eq .CurrentUser.ID .User.ID) (not .IsPrivate)}}
|
|
<span class="corner">
|
|
<button class="button is-small p-1 is-success">
|
|
<a href="/photo/upload?intent=profile_pic"
|
|
class="fa fa-camera has-text-link"
|
|
title="Upload a new Profile Picture"></a>
|
|
</button>
|
|
</span>
|
|
{{end}}
|
|
</figure>
|
|
</div>
|
|
|
|
<div class="column">
|
|
<h1 class="title">
|
|
{{.User.NameOrUsername}}
|
|
{{if eq .User.Visibility "private"}}<sup class="fa fa-mask ml-2 is-size-6" title="Private Profile"></sup>{{end}}
|
|
</h1>
|
|
{{if ne .User.Status "active"}}
|
|
<h2 class="subtitle">
|
|
({{.User.Status}})
|
|
</h2>
|
|
{{end}}
|
|
{{if or (not .LoggedIn) .IsPrivate}}
|
|
<h2 class="subtitle">is on {{PrettyTitle}}, a social network for nudists & exhibitionists.</h2>
|
|
<p>
|
|
{{PrettyTitle}} is a new social network for <strong>real</strong> nudists and exhibitionists.
|
|
Join <strong>{{.User.Username}}</strong> and the others on this site by
|
|
<a href="/signup"><ins>creating an account</ins></a> and sending them a friend request! Please
|
|
see <a href="/"><ins>the home page</ins></a> for all the details.
|
|
</p>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{if and .LoggedIn (not .IsPrivate)}}
|
|
<div class="column is-narrow">
|
|
<div class="box">
|
|
<div>
|
|
Member since:
|
|
<span title="Since {{.User.CreatedAt.Format "Jan _2 2006"}}">
|
|
{{SincePrettyCoarse .User.CreatedAt}} ago
|
|
</span>
|
|
</div>
|
|
<div>
|
|
Last logged in:
|
|
<span title="On {{.User.LastLoginAt.Format "Jan _2 2006 15:04:05 MST"}}">
|
|
{{SincePrettyCoarse .User.LastLoginAt}} ago
|
|
</span>
|
|
</div>
|
|
{{if .OnChat}}
|
|
<div class="my-1">
|
|
<span class="tag is-success is-light">
|
|
<i class="fa fa-user mr-2"></i> Currently on chat!
|
|
</span>
|
|
</div>
|
|
{{end}}
|
|
{{if .User.Certified}}
|
|
<div class="pt-1">
|
|
<div class="icon-text" title="Their certification photo was approved by a website admin.">
|
|
<span class="icon">
|
|
<i class="fa-solid fa-certificate has-text-success"></i>
|
|
</span>
|
|
<strong class="has-text-info">Certified!</strong>
|
|
|
|
{{$CertSince := .User.CertifiedSince}}
|
|
<small title="On {{$CertSince.Format "Jan _2 2006"}}" class="has-text-grey is-size-7">
|
|
{{SincePrettyCoarse $CertSince}} ago
|
|
</small>
|
|
|
|
<!-- Admin link to see it -->
|
|
{{if .CurrentUser.IsAdmin}}
|
|
<a href="/admin/photo/certification?username={{.User.Username}}"
|
|
class="fa fa-image ml-1 is-size-7"
|
|
title="Search for certification picture">
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
<div class="pt-1">
|
|
<div class="icon-text" title="This user has not certified themselves with a verification selfie.">
|
|
<span class="icon">
|
|
<i class="fa-solid fa-certificate has-text-danger"></i>
|
|
</span>
|
|
<strong class="has-text-danger">Not certified!</strong>
|
|
|
|
<!-- Admin link to see it -->
|
|
{{if .CurrentUser.IsAdmin}}
|
|
<a href="/admin/photo/certification?username={{.User.Username}}"
|
|
class="fa fa-image has-text-link ml-2 is-size-7"
|
|
title="Search for certification picture"></a>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .User.IsShy}}
|
|
<div class="pt-1">
|
|
<div class="icon-text has-text-danger">
|
|
<span class="icon">
|
|
<i class="fa fa-ghost"></i>
|
|
</span>
|
|
<strong>Shy Account</strong>
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
<div class="pt-1" title="Badge for having at least one public picture.">
|
|
{{PrettyTitleShort}}
|
|
<strong class="has-text-link ml-1">Non-shy!</strong>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .User.IsAdmin}}
|
|
<div class="pt-1">
|
|
<div class="icon-text has-text-danger">
|
|
<a href="/admin/transparency/{{.User.Username}}" class="has-text-danger">
|
|
<span class="icon">
|
|
<i class="fa fa-peace"></i>
|
|
</span>
|
|
<strong class="has-text-danger">Admin</strong>
|
|
<sup class="fa fa-info-circle ml-1 is-size-7 has-text-success"></sup>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}<!-- if .LoggedIn -->
|
|
</div>
|
|
|
|
{{if and .LoggedIn (not .IsExternalView)}}
|
|
<div class="columns is-centered is-gapless">
|
|
<div class="column is-narrow has-text-centered">
|
|
<form action="/friends/add" method="POST">
|
|
{{InputCSRF}}
|
|
<input type="hidden" name="username" value="{{.User.Username}}">
|
|
|
|
<!-- If you are already friends, the button will remove them -->
|
|
{{if eq .IsFriend "approved"}}
|
|
<input type="hidden" name="verdict" value="remove">
|
|
{{end}}
|
|
|
|
<button type="submit" class="button is-fullwidth"
|
|
{{if not (eq .IsFriend "none")}}title="Friendship {{.IsFriend}}"{{end}}
|
|
{{if eq .IsFriend "approved"}}onclick="return confirm('Do you want to remove this friendship?')"{{end}}>
|
|
<span class="icon-text">
|
|
<span class="icon">
|
|
{{if eq .IsFriend "approved"}}
|
|
<i class="fa fa-check has-text-success"></i>
|
|
{{else if eq .IsFriend "pending"}}
|
|
<i class="fa fa-paper-plane"></i>
|
|
{{else}}
|
|
<i class="fa fa-plus"></i>
|
|
{{end}}
|
|
</span>
|
|
<span>Friend{{if eq .IsFriend "approved"}}s{{end}}</span>
|
|
</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- DM button -->
|
|
{{if and (eq (.User.GetProfileField "dm_privacy") "friends") (not (eq .IsFriend "approved")) (not .CurrentUser.IsAdmin)}}
|
|
<!-- Only friends can send them a DM -->
|
|
{{else if and (eq (.User.GetProfileField "dm_privacy") "nobody") (not .CurrentUser.IsAdmin)}}
|
|
<!-- They set "Nobody" can send them a DM -->
|
|
{{else}}
|
|
<div class="column is-narrow has-text-centered">
|
|
<a href="/messages/compose?to={{.User.Username}}" class="button is-fullwidth">
|
|
<span class="icon-text">
|
|
<span class="icon">
|
|
<i class="fa fa-message"></i>
|
|
</span>
|
|
<span>Message</span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Like button -->
|
|
{{if not .IsPrivate}}
|
|
{{$Like := .LikeMap.Get .User.ID}}
|
|
<div class="column is-narrow has-text-centered">
|
|
<button type="button" class="button is-fullwidth nonshy-like-button"
|
|
data-table-name="users" data-table-id="{{.User.Username}}"
|
|
title="Like this profile">
|
|
<span class="icon{{if $Like.UserLikes}} has-text-danger{{end}}"><i class="fa fa-heart"></i></span>
|
|
<span class="nonshy-likes">
|
|
Like
|
|
{{if gt $Like.Count 0}}
|
|
({{$Like.Count}})
|
|
{{end}}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="column is-narrow has-text-centered">
|
|
<form action="/users/block" method="POST">
|
|
{{InputCSRF}}
|
|
<input type="hidden" name="username" value="{{.User.Username}}">
|
|
|
|
<button type="submit" class="button is-fullwidth"
|
|
{{if not (eq .IsFriend "none")}}title="Friendship {{.IsFriend}}"{{end}}>
|
|
<span class="icon-text">
|
|
<span class="icon">
|
|
<i class="fa fa-hand"></i>
|
|
</span>
|
|
<span>Block</span>
|
|
</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="column is-narrow has-text-centered">
|
|
<a href="/contact?intent=report&subject=report.user&id={{.User.Username}}" class="button is-fullwidth">
|
|
<span class="icon-text">
|
|
<span class="icon">
|
|
<i class="fa fa-flag"></i>
|
|
</span>
|
|
<span>Report</span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
|
|
</div><!-- columns -->
|
|
{{end}}<!-- if .LoggedIn -->
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{if or (not .LoggedIn) .IsPrivate}}
|
|
<div class="py-6"></div>
|
|
{{else if .IsPrivate}}
|
|
<div class="block p-4">
|
|
<div class="notification block is-warning">
|
|
<i class="fa fa-mask"></i> This member's profile page is <strong>private.</strong> You may send them
|
|
a friend request, and only if approved, you may then view their profile page and photo gallery.
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
<div class="block p-4">
|
|
<div class="tabs is-boxed mb-0">
|
|
<ul>
|
|
<li class="is-active">
|
|
<a>
|
|
<span class="icon is-small">
|
|
<i class="fa fa-user"></i>
|
|
</span>
|
|
<span>Profile</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/u/{{.User.Username}}/photos">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-image"></i>
|
|
</span>
|
|
<span>
|
|
Photos
|
|
{{if .PhotoCount}}<span class="tag is-link is-light ml-1">{{.PhotoCount}}</span>{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/u/{{.User.Username}}/notes">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-pen-to-square"></i>
|
|
</span>
|
|
<span>
|
|
Notes
|
|
{{if .NoteCount}}<span class="tag is-link is-light ml-1">{{.NoteCount}}</span>{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/u/{{.User.Username}}/friends">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-user-group"></i>
|
|
</span>
|
|
<span>
|
|
Friends
|
|
{{if .FriendCount}}<span class="tag is-link is-light ml-1">{{.FriendCount}}</span>{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Show who likes this user -->
|
|
{{if not .CurrentUser.IsShy}}
|
|
{{template "like-example" .}}
|
|
{{end}}
|
|
|
|
<div class="columns mt-1">
|
|
|
|
<div class="column is-two-thirds">
|
|
<div class="card block">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">
|
|
About Me
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<div class="content">
|
|
{{or (ToMarkdown (.User.GetProfileField "about_me")) "n/a"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">
|
|
My Interests
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<div class="content">
|
|
{{or (ToMarkdown (.User.GetProfileField "interests")) "n/a"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">
|
|
Music/Bands/Movies
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<div class="content">
|
|
{{or (ToMarkdown (.User.GetProfileField "music_movies")) "n/a"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column">
|
|
<div class="card block">
|
|
<header class="card-header has-background-info">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-user pr-2"></i>
|
|
About {{.User.Username}}
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<table class="table is-fullwidth" style="font-size: small">
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Age:</label>
|
|
</td>
|
|
<td>
|
|
<!-- The user's display age (or 'n/a' if don't have or they hide it) -->
|
|
{{.User.GetDisplayAge}}
|
|
|
|
<!-- Admin version always shows it -->
|
|
{{if .CurrentUser.HasAdminScope "admin.user.insights"}}
|
|
<small class="has-text-danger" title="{{.User.Birthdate.Format "2006-01-02"}}">
|
|
{{if not .User.Birthdate.IsZero}}
|
|
({{ComputeAge .User.Birthdate}})
|
|
{{else}}
|
|
(n/a)
|
|
{{end}}
|
|
</small>
|
|
{{end}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Gender:</label>
|
|
</td>
|
|
<td>
|
|
{{or (.User.GetProfileField "gender") "n/a"}}
|
|
<small class="ml-3">{{.User.GetProfileField "pronouns"}}</small>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">City:</label>
|
|
</td>
|
|
<td>
|
|
{{or (.User.GetProfileField "city") "n/a"}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Job:</label>
|
|
</td>
|
|
<td>
|
|
{{or (.User.GetProfileField "job") "n/a"}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Marital status:</label>
|
|
</td>
|
|
<td>
|
|
{{or (.User.GetProfileField "marital_status") "n/a"}}
|
|
{{if .User.GetProfileField "relationship_type"}}({{.User.GetProfileField "relationship_type"}}){{end}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Orientation:</small>
|
|
</td>
|
|
<td>
|
|
{{or (.User.GetProfileField "orientation") "n/a"}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="has-text-right">
|
|
<strong class="is-size-7">Here for:</label>
|
|
</td>
|
|
<td>
|
|
{{range Split (.User.GetProfileField "here_for") ","}}
|
|
<div class="tag">{{.}}</div>
|
|
{{end}}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-info">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-chart-line pr-2"></i>
|
|
Activity
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
|
|
<!-- Lazy load the statistics card-->
|
|
<div hx-get="/htmx/user/profile/activity?username={{.User.Username}}" hx-trigger="load">
|
|
<i class="fa fa-spinner fa-spin mr-1"></i> Loading...
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Admin Actions-->
|
|
{{if .CurrentUser.IsAdmin}}
|
|
<div class="card block">
|
|
<header class="card-header has-background-danger">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-peace pr-2"></i>
|
|
Admin
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<aside class="menu">
|
|
<ul class="menu-list">
|
|
<p class="menu-label">Profile Information</p>
|
|
<li>
|
|
<a href="/admin/user-action?intent=insights&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-search"></i></span>
|
|
<span>Admin insights <small>(block lists, etc.)</small></span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/changelog?about_user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-clipboard-list"></i></span>
|
|
<span>Change logs about this user</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/changelog?table_name=users&table_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-clipboard-list"></i></span>
|
|
<span>User account history</span>
|
|
</a>
|
|
</li>
|
|
|
|
<p class="menu-label">Admin Actions</p>
|
|
<li>
|
|
<a href="/admin/user-action?intent=chat.rules&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-gavel"></i></span>
|
|
<span>
|
|
Chat Moderation Rules
|
|
{{if .NumChatModerationRules}}
|
|
<span class="tag is-warning ml-2">{{.NumChatModerationRules}}</span>
|
|
{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=essays&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-pencil"></i></span>
|
|
<span>Edit their profile text</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=impersonate&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-ghost"></i></span>
|
|
<span>Impersonate this user</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=ban&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-ban"></i></span>
|
|
<span>Ban/unban this user</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=promote&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-peace"></i></span>
|
|
<span>Add/Remove admin rights</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=password&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-lock"></i></span>
|
|
<span>Reset Password</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/admin/user-action?intent=delete&user_id={{.User.ID}}">
|
|
<span class="icon"><i class="fa fa-trash"></i></span>
|
|
<span>Delete user account</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div><!-- /columns-->
|
|
</div>
|
|
{{end}}<!-- not IsPrivate -->
|
|
</div>
|
|
{{end}}
|