704124157d
Instead of fighting to override Bulma CSS classes, add user-theme-* classes for simpler styling.
588 lines
30 KiB
HTML
588 lines
30 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}} {{if not .IsExternalView}}user-theme-hero{{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="{{VisibleAvatarURL .User nil}}" data-photo-id="{{.User.ProfilePhoto.ID}}">
|
|
{{else}}
|
|
<a href="/u/{{.User.Username}}/photos">
|
|
<img src="{{VisibleAvatarURL .User .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 user-theme-card-title">
|
|
<div class="card-header-title">
|
|
<div class="columns is-mobile is-gapless nonshy-fullwidth">
|
|
<div class="column">
|
|
About Me
|
|
</div>
|
|
{{if eq .CurrentUser.ID .User.ID}}
|
|
<div class="column is-narrow">
|
|
<a href="/settings#profile/about_me" class="button is-outlined is-small">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="card-content user-theme-card-body">
|
|
<div class="content">
|
|
{{or (ReSignPhotoLinks (ToMarkdown (.User.GetProfileField "about_me"))) "n/a"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-link user-theme-card-title">
|
|
<div class="card-header-title">
|
|
<div class="columns is-mobile is-gapless nonshy-fullwidth">
|
|
<div class="column">
|
|
My Interests
|
|
</div>
|
|
{{if eq .CurrentUser.ID .User.ID}}
|
|
<div class="column is-narrow">
|
|
<a href="/settings#profile/interests" class="button is-outlined is-small">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="card-content user-theme-card-body">
|
|
<div class="content">
|
|
{{or (ReSignPhotoLinks (ToMarkdown (.User.GetProfileField "interests"))) "n/a"}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-link user-theme-card-title">
|
|
<div class="card-header-title">
|
|
<div class="columns is-mobile is-gapless nonshy-fullwidth">
|
|
<div class="column">
|
|
Music/Bands/Movies
|
|
</div>
|
|
{{if eq .CurrentUser.ID .User.ID}}
|
|
<div class="column is-narrow">
|
|
<a href="/settings#profile/music_movies" class="button is-outlined is-small">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="card-content user-theme-card-body">
|
|
<div class="content">
|
|
{{or (ReSignPhotoLinks (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 user-theme-card-title">
|
|
<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 user-theme-card-body">
|
|
<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 user-theme-card-title">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-chart-line pr-2"></i>
|
|
Activity
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content user-theme-card-body">
|
|
|
|
<!-- 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}}
|