1c013aa8d8
* If a Certified member deletes the final picture from their gallery page, their Certification Photo will be automatically rejected and they are instructed to begin the process again from the beginning. * Add nice Alert and Confirm modals around the website in place of the standard browser feature. Note: the inline confirm on submit buttons are still using the standard feature for now, as intercepting submit buttons named "intent" causes problems in getting the final form to submit.
892 lines
53 KiB
HTML
892 lines
53 KiB
HTML
{{define "title"}}My Dashboard{{end}}
|
|
{{define "content"}}
|
|
<div class="container">
|
|
<section class="hero is-link is-bold">
|
|
<div class="hero-body">
|
|
<div class="container">
|
|
<h1 class="title">
|
|
<span class="icon mr-4 pl-3">
|
|
<i class="fa fa-house-user"></i>
|
|
</span>
|
|
<span>My Dashboard</span>
|
|
</h1>
|
|
<h2 class="subtitle">Settings & Notifications</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>
|
|
|
|
<aside class="menu">
|
|
<ul class="menu-list">
|
|
<li>
|
|
<a href="/photo/upload?intent=profile_pic">
|
|
<div class="columns is-mobile is-gapless">
|
|
<div class="column is-narrow mr-2">
|
|
{{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-xmark has-text-danger"></i></span>
|
|
{{end}}
|
|
</div>
|
|
<div class="column">
|
|
Upload a Profile Picture to your account that shows your face
|
|
|
|
<p class="help">
|
|
Click here to upload a new profile picture
|
|
<i class="fa fa-external-link ml-1"></i>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/photo/certification">
|
|
<div class="columns is-mobile is-gapless">
|
|
<div class="column is-narrow mr-2">
|
|
{{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-xmark has-text-danger"></i></span>
|
|
{{end}}
|
|
</div>
|
|
<div class="column">
|
|
Get certified by uploading a verification selfie
|
|
|
|
<p class="help">
|
|
Click here to go to the Certification Photo upload page
|
|
<i class="fa fa-external-link ml-1"></i>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- "Very Private" Restricted Account warning for certified users -->
|
|
{{if and .CurrentUser.Certified .IsShyUser}}
|
|
<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-exclamation-triangle"></i></span>
|
|
<span>Your profile page is too private</span>
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<p class="block">
|
|
You are considered to be a <strong>Shy Account</strong> because your profile and
|
|
photos are all set to Private or Friends-only visibility, so that to other members
|
|
of {{PrettyTitle}} you appear like a blank, faceless profile.
|
|
</p>
|
|
|
|
<p class="block">
|
|
While in this restricted state, you are grouped into a cohort with other members who
|
|
are as shy as you are and have limited contact options to connect with our other,
|
|
{{PrettyTitle}} members who are sharing their nudes on public.
|
|
</p>
|
|
|
|
<p class="block">
|
|
<a href="/faq#shy-faqs">Click here to learn more</a> about your Shy Account. To
|
|
remedy this, please see the following steps:
|
|
</p>
|
|
|
|
<aside class="menu">
|
|
<ul class="menu-list">
|
|
<li>
|
|
<a href="/settings">
|
|
{{if eq .CurrentUser.Visibility "public"}}
|
|
<span class="icon"><i class="fa fa-circle-check has-text-success"></i></span>
|
|
{{else}}
|
|
<span class="icon"><i class="fa fa-circle-xmark has-text-danger"></i></span>
|
|
{{end}}
|
|
<span>
|
|
Have your profile visibility set to <strong>Public</strong>.
|
|
{{if not (eq .CurrentUser.Visibility "public")}}
|
|
<span class="icon"><i class="fa fa-external-link"></i></span>
|
|
{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="/u/{{.CurrentUser.Username}}/photos">
|
|
{{if .HasPublicPhoto}}
|
|
<span class="icon"><i class="fa fa-circle-check has-text-success"></i></span>
|
|
{{else}}
|
|
<span class="icon"><i class="fa fa-circle-xmark has-text-danger"></i></span>
|
|
{{end}}
|
|
<span>
|
|
Have at least one <strong>Public</strong> photo on your profile.
|
|
{{if not .HasPublicPhoto}}
|
|
<span class="icon"><i class="fa fa-external-link"></i></span>
|
|
{{end}}
|
|
</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- New Feature -->
|
|
{{if not (.CurrentUser.GetProfileField "website-theme-hue")}}
|
|
<div class="card block">
|
|
<header class="card-header has-background-success">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-gift mr-2"></i>
|
|
New Feature: Website Themes!
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<p class="block">
|
|
We have a mildly fun new update to the website: you can now customize how
|
|
the {{PrettyTitle}} website appears to you by adding a splash of color!
|
|
</p>
|
|
|
|
<p class="block">
|
|
Check it out on your Settings > <a href="/settings#look">Look & Feel</a>
|
|
page!
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="card block">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">Quick Links</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<aside class="menu">
|
|
<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="/u/{{.CurrentUser.Username}}/photos">
|
|
<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 Photo
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/photo/private">
|
|
<span class="icon"><i class="fa fa-eye"></i></span>
|
|
Manage Private Photos
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/settings">
|
|
<span class="icon"><i class="fa fa-gear"></i></span>
|
|
Edit Profile & Settings
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/notes/me">
|
|
<span class="icon"><i class="fa fa-pen-to-square mr-1"></i></span>
|
|
My User Notes
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/photo/certification">
|
|
<span class="icon"><i class="fa fa-certificate"></i></span>
|
|
My 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="/users/muted">
|
|
<span class="icon"><i class="fa fa-eye-slash"></i></span>
|
|
Muted 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}}
|
|
</ul>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{$Root := .}}
|
|
|
|
<div class="column">
|
|
<div class="card" id="notifications">
|
|
<header class="card-header has-background-warning">
|
|
<p class="card-header-title">Notifications</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
<!-- Notifications header row: tablets on upwards -->
|
|
<div class="is-hidden-mobile">
|
|
<form method="POST" action="{{.Request.URL.Path}}">
|
|
{{InputCSRF}}
|
|
<div class="columns mb-2">
|
|
<div class="column">
|
|
{{if gt .NavUnreadNotifications 0}}
|
|
{{.NavUnreadNotifications}} unread notification{{Pluralize64 .NavUnreadNotifications}}.
|
|
{{else}}
|
|
No unread notifications.
|
|
{{end}}
|
|
</div>
|
|
<div class="column is-narrow has-text-right">
|
|
<button type="submit" name="intent" value="clear-all"
|
|
class="button is-danger is-light is-small"
|
|
onclick="return window.confirm('Are you sure you want to REMOVE all notifications?')"
|
|
title="Remove all notifications from your feed">
|
|
<i class="fa fa-xmark mr-1"></i>
|
|
Clear all
|
|
</button>
|
|
|
|
<button type="submit" name="intent" value="read-notifications"
|
|
class="button is-link is-light is-small">
|
|
<i class="fa fa-check mr-1"></i>
|
|
Mark all as read
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Notifications header: for mobiles only version -->
|
|
<div class="is-hidden-tablet">
|
|
<p>
|
|
{{if gt .NavUnreadNotifications 0}}
|
|
{{.NavUnreadNotifications}} unread notification{{Pluralize64 .NavUnreadNotifications}}.
|
|
{{else}}
|
|
No unread notifications.
|
|
{{end}}
|
|
</p>
|
|
<form method="POST" action="{{.Request.URL.Path}}">
|
|
{{InputCSRF}}
|
|
<div class="my-2 has-text-right">
|
|
<button type="submit" name="intent" value="clear-all"
|
|
class="button is-danger is-light is-small"
|
|
onclick="return window.confirm('Are you sure you want to REMOVE all notifications?')">
|
|
<i class="fa fa-xmark mr-1"></i>
|
|
Clear all
|
|
</button>
|
|
|
|
<button type="submit" name="intent" value="read-notifications"
|
|
class="button is-link is-light is-small">
|
|
<i class="fa fa-check mr-1"></i>
|
|
Mark all as read
|
|
</button>
|
|
</div>
|
|
</form>
|
|
<hr>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="block">
|
|
<form action="{{.Request.URL.Path}}" method="GET">
|
|
|
|
<div class="card nonshy-collapsible-mobile nonshy-collapsible-always mb-5">
|
|
<header class="card-header has-background-link-light">
|
|
<p class="card-header-title has-text-dark">
|
|
<i class="fa fa-list mr-2"></i> Notification Types
|
|
</p>
|
|
<button class="card-header-icon" type="button">
|
|
<span class="icon">
|
|
<i class="fa fa-angle-up"></i>
|
|
</span>
|
|
</button>
|
|
</header>
|
|
<div class="card-content">
|
|
|
|
<p class="block">
|
|
<a href="/settings#notifications">
|
|
<i class="fa fa-gear mr-1"></i>
|
|
Manage notification settings
|
|
</a>
|
|
</p>
|
|
|
|
<div class="columns is-multiline mb-0">
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="likes"
|
|
value="true"
|
|
{{if .Filters.Likes}}checked{{end}}
|
|
>
|
|
Likes
|
|
<p class="help">
|
|
on your photos, profile or comments
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="comments"
|
|
value="true"
|
|
{{if .Filters.Comments}}checked{{end}}
|
|
>
|
|
Comments
|
|
<p class="help">
|
|
on your photos
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="photos"
|
|
value="true"
|
|
{{if .Filters.NewPhotos}}checked{{end}}
|
|
>
|
|
New Photos
|
|
<p class="help">
|
|
of your friends
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="replies"
|
|
value="true"
|
|
{{if .Filters.AlsoCommented}}checked{{end}}
|
|
>
|
|
Replies
|
|
<p class="help">
|
|
on comment threads you follow
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="private"
|
|
value="true"
|
|
{{if .Filters.PrivatePhoto}}checked{{end}}
|
|
>
|
|
Private photos
|
|
<p class="help">
|
|
unlock notifications
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column is-half">
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="misc"
|
|
value="true"
|
|
{{if .Filters.Misc}}checked{{end}}
|
|
>
|
|
Miscellaneous
|
|
<p class="help">
|
|
new friends, certification photos, etc.
|
|
</p>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="block has-text-centered">
|
|
<a href="{{.Request.URL.Path}}" class="button">
|
|
Reset
|
|
</a>
|
|
<button type="submit" class="button is-success">
|
|
Apply Filters
|
|
</button>
|
|
</div>
|
|
|
|
</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}}">
|
|
<!-- Delete button for just this notification -->
|
|
<button type="button"
|
|
class="button is-danger px-2 py-1 is-small nonshy-notif-delete-button"
|
|
data-notification-id="{{.ID}}"
|
|
title="Remove this notification from your feed">
|
|
<i class="fa fa-xmark mr"></i>
|
|
</button>
|
|
|
|
<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}}
|
|
{{template "avatar-48x48" .AboutUser}}
|
|
</div>
|
|
<div class="column">
|
|
<div class="mb-1 pr-4">
|
|
{{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 "new_photo"}}
|
|
<span class="icon">
|
|
{{if and $Body.Photo (eq $Body.Photo.Visibility "private")}}
|
|
<i class="fa fa-eye {{if $Body.Photo.Explicit}}has-text-danger{{else}}has-text-private{{end}}"></i>
|
|
{{else}}
|
|
<i class="fa fa-image {{if $Body.Photo.Explicit}}has-text-danger{{else}}has-text-link{{end}}"></i>
|
|
{{end}}
|
|
</span>
|
|
<span>
|
|
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
|
|
has uploaded a new
|
|
{{if and $Body.Photo (eq $Body.Photo.Visibility "private")}}
|
|
<span class="has-text-private">private photo!</span>
|
|
{{else}}
|
|
photo!
|
|
{{end}}
|
|
</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_secondary"}}
|
|
<span class="icon"><i class="fa fa-certificate has-text-warning"></i></span>
|
|
<span>
|
|
About your <strong>certification photo:</strong>
|
|
</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 if eq .Type "forum_moderator"}}
|
|
<span class="icon"><i class="fa fa-user-tie has-text-success"></i></span>
|
|
<span>
|
|
You have been appointed as a <strong class="has-text-success">moderator</strong>
|
|
for the forum <a href="/f/{{$Body.Forum.Fragment}}">{{$Body.Forum.Title}}</a>!
|
|
</span>
|
|
{{else if eq .Type "explicit_photo"}}
|
|
<span class="icon"><i class="fa fa-fire has-text-danger"></i></span>
|
|
<span>
|
|
Your <a href="{{.Link}}">photo</a> was marked as <span class="has-text-danger">Explicit!</span>
|
|
</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 if eq .Type "explicit_photo"}}
|
|
<div class="content pt-1" style="font-size: smaller">
|
|
<p>
|
|
A community member thinks that this photo should have been marked as 'Explicit' when
|
|
it was uploaded.
|
|
</p>
|
|
<p>
|
|
Please <a href="/tos/photos#explicit">review our Explicit Photos policy</a>
|
|
and remember to correctly mark your new uploads as 'explicit' when they contain sexually
|
|
suggestive content.
|
|
</p>
|
|
</div>
|
|
{{else}}
|
|
<em>{{or $Body.Photo.Caption "No caption."}}</em>
|
|
{{end}}
|
|
|
|
<!-- Admin action: mark this pic explicit? -->
|
|
{{if and ($Root.CurrentUser.IsAdmin) (not $Body.Photo.Explicit)}}
|
|
<div class="mt-2">
|
|
<a href="/admin/photo/mark-explicit?photo_id={{$Body.Photo.ID}}&next={{$Root.Request.URL}}"
|
|
class="has-text-danger is-size-7"
|
|
onclick="return confirm('Do you want to mark this photo as Explicit?')">
|
|
<i class="fa fa-peace mr-1"></i>
|
|
Mark photo as Explicit
|
|
</a>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<hr class="has-background-light mb-1">
|
|
<small title="{{.CreatedAt.Format "2006-01-02 15:04:05"}}">
|
|
{{SincePrettyCoarse .CreatedAt}} ago.
|
|
|
|
<!-- Contextual "Unsubscribe" buttons -->
|
|
{{if or (eq .Type "also_posted") (eq .Type "also_comment")}}
|
|
<small>
|
|
<a href="#"
|
|
data-link="/comments/subscription?table_name={{.TableName}}&table_id={{.TableID}}&next={{UrlEncode $Root.Request.URL.String}}&subscribe=false"
|
|
data-confirm="Do you want to TURN OFF notifications about this comment thread?"
|
|
class="has-text-warning is-small nonshy-mute-notification-link"
|
|
title="Turn off notifications about this thread">
|
|
<i class="fa fa-microphone-slash mr-1"></i> Mute this thread
|
|
</a>
|
|
</small>
|
|
{{else if eq .Type "new_photo"}}
|
|
<small>
|
|
<a href="#"
|
|
data-link="/comments/subscription?table_name=friend.photos&table_id={{.AboutUser.Username}}&next={{UrlEncode $Root.Request.URL.String}}&subscribe=false"
|
|
data-confirm="Do you want to TURN OFF notifications about @{{.AboutUser.Username}}'s new photo uploads?\n\nNote: to re-subscribe to their new photo notifications, see the link at the top of @{{.AboutUser.Username}}'s Photo Gallery page."
|
|
class="has-text-warning is-small nonshy-mute-notification-link"
|
|
title="Turn off notifications about @{{.AboutUser.Username}}'s new photo uploads">
|
|
<i class="fa fa-microphone-slash mr-1"></i> Mute these notifications
|
|
</a>
|
|
</small>
|
|
{{end}}
|
|
</small>
|
|
</div>
|
|
|
|
<!-- Attached photo? -->
|
|
{{if $Body.PhotoID}}
|
|
<div class="column is-one-quarter is-clipped">
|
|
<!-- GIF video? -->
|
|
{{if HasSuffix $Body.Photo.Filename ".mp4"}}
|
|
<video loop controls controlsList="nodownload" playsinline
|
|
{{if $Body.Photo.AltText}}title="{{$Body.Photo.AltText}}"{{end}}
|
|
{{if BlurExplicit $Body.Photo}}class="blurred-explicit"
|
|
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
|
|
{{end}}>
|
|
<source src="{{PhotoURL $Body.Photo.Filename}}" type="video/mp4">
|
|
</video>
|
|
<div>
|
|
<a href="/photo/view?id={{$Body.Photo.ID}}" class="is-size-7">
|
|
<i class="fa fa-arrow-right"></i> View GIF
|
|
</a>
|
|
</div>
|
|
{{else}}
|
|
<a href="/photo/view?id={{$Body.Photo.ID}}">
|
|
<img src="{{PhotoURL $Body.Photo.Filename}}" loading="lazy"
|
|
{{if BlurExplicit $Body.Photo}} class="blurred-explicit"{{end}}
|
|
{{if $Body.Photo.AltText}}title="{{$Body.Photo.AltText}}" alt="{{$Body.Photo.AltText}}"{{end}}>
|
|
</a>
|
|
{{end}}
|
|
|
|
{{if $Body.Photo.Caption}}
|
|
<small>{{$Body.Photo.Caption}}</small>
|
|
{{else}}
|
|
<small><em>No caption.</em></small>
|
|
{{end}}
|
|
|
|
<!-- Like button for the photo right here -->
|
|
{{if ne $Body.Photo.UserID $Root.CurrentUser.ID}}
|
|
<div class="mt-1">
|
|
{{$Like := $Root.PhotoLikeMap.Get $Body.PhotoID}}
|
|
<button type="button" class="button is-small nonshy-like-button"
|
|
data-table-name="photos" data-table-id="{{$Body.PhotoID}}"
|
|
title="Like">
|
|
<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>
|
|
{{end}}
|
|
</div>
|
|
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
|
|
{{if .Pager.HasNext}}
|
|
<div class="has-text-centered">
|
|
<a href="{{.Request.URL.Path}}?{{QueryPlus "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;
|
|
|
|
// For delete buttons: if they click thru the first confirm, do not ask every single time
|
|
// for the rest of the current page load.
|
|
let dontAskAgain = false;
|
|
|
|
// Bind to the notification table rows.
|
|
(document.querySelectorAll(".nonshy-notification-row") || []).forEach(node => {
|
|
let $newBadge = node.querySelector(".nonshy-notification-new"),
|
|
$deleteButton = node.querySelector(".nonshy-notif-delete-button"),
|
|
ID = node.dataset.notificationId;
|
|
|
|
// Delete buttons for individual notifications.
|
|
$deleteButton.addEventListener("click", (e) => {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
|
|
let callback = () => {
|
|
busy = true;
|
|
return fetch("/v1/notifications/delete", {
|
|
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);
|
|
|
|
// Hide the notification row immediately.
|
|
node.style.display = 'none';
|
|
}).catch(resp => {
|
|
console.error(resp);
|
|
}).finally(() => {
|
|
busy = false;
|
|
});
|
|
};
|
|
|
|
if (!dontAskAgain) {
|
|
modalConfirm({
|
|
message: "Do you want to DELETE this notification?\n\nNote: If you click Ok, you will not be asked "+
|
|
"the next time you want to delete another notification until your next page reload.",
|
|
}).then(() => {
|
|
dontAskAgain = true;
|
|
callback();
|
|
});
|
|
} else {
|
|
callback();
|
|
}
|
|
});
|
|
|
|
// 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 => {
|
|
console.error(resp);
|
|
}).finally(() => {
|
|
busy = false;
|
|
if (href !== undefined && href !== "#") {
|
|
window.location.href = href;
|
|
}
|
|
});
|
|
})
|
|
});
|
|
});
|
|
|
|
// "Mute notification" links.
|
|
// NOTE: to avoid conflict with the "mark notification as read, then follow href" code
|
|
// above, the mute buttons href is made safer and this function will get its follow-thru
|
|
// URL from a data attribute.
|
|
(document.querySelectorAll(".nonshy-mute-notification-link") || []).forEach(node => {
|
|
node.addEventListener("click", (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
const link = node.dataset.link,
|
|
prompt = node.dataset.confirm.replace(/\\n/g, "\n");
|
|
|
|
modalConfirm({message: prompt}).then(() => {
|
|
window.location = link;
|
|
});
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
{{end}}
|