{{define "title"}}{{.Thread.Title}} - {{.Forum.Title}}{{end}} {{define "content"}} <div class="block"> <section class="hero is-light is-success"> <div class="hero-body"> <div class="container"> <h1 class="title"> <a href="/f/{{.Forum.Fragment}}" class="has-text-light"> <span class="icon mr-4"><i class="fa fa-comments"></i></span> <span>{{.Forum.Title}}</span> </a> </h1> </div> </div> </section> </div> {{$Root := .}} <div class="block px-4"> <div class="columns"> <div class="column"> <nav class="breadcrumb" aria-label="breadcrumbs"> <ul> <li><a href="/forum">Forums</a></li> <li><a href="/f/{{.Forum.Fragment}}">{{.Forum.Title}}</a></Li> <li class="is-active"> <a href="{{.Request.URL.Path}}" aria-current="page">{{or .Thread.Title "Untitled Thread"}}</a> </li> </ul> </nav> </div> <div class="column is-narrow"> {{if not .Thread.NoReply}} <a href="/forum/post?to={{.Forum.Fragment}}&thread={{.Thread.ID}}" class="button is-link"> <span class="icon"><i class="fa fa-reply"></i></span> <span>Add Reply</span> </a> {{end}} </div> </div> </div> <h1 class="title px-4"> {{if .Thread.Pinned}}<sup class="fa fa-thumbtack has-text-success mr-2 is-size-5" title="Pinned"></sup>{{end}} {{or .Thread.Title "Untitled Thread"}} </h1> <div class="px-4"> {{if .Thread.Pinned}} <span class="tag is-success is-light mr-2"> <span class="icon"><i class="fa fa-thumbtack"></i></span> <span>Pinned</span> </span> {{end}} {{if .Thread.Explicit}} <span class="tag is-danger is-light mr-2"> <span class="icon"><i class="fa fa-fire"></i></span> <span>NSFW</span> </span> {{end}} {{if .Thread.NoReply}} <span class="tag is-warning is-light mr-2" title="This thread can not be replied to."> <span class="icon"><i class="fa fa-ban"></i></span> <span>No Reply</span> </span> {{end}} <span class="tag is-grey is-light mr-2" title="This thread can not be replied to."> <span class="icon"><i class="fa fa-eye"></i></span> <span>{{.Thread.Views}} View{{PluralizeU64 .Thread.Views}}</span> </span> <em title="{{.Thread.UpdatedAt.Format "2006-01-02 15:04:05"}}"> Updated {{SincePrettyCoarse .Thread.UpdatedAt}} ago </em> </div> <p class="block p-4 mb-0"> Found <strong>{{.Pager.Total}}</strong> post{{Pluralize64 .Pager.Total}} on this thread (page {{.Pager.Page}} of {{.Pager.Pages}}). </p> <p class="block px-4 mb-4"> <a href="/comments/subscription?table_name=threads&table_id={{.Thread.ID}}&next={{UrlEncode .Request.URL.String}}&subscribe={{if not .IsSubscribed}}true{{else}}false{{end}}"> <span class="icon"><i class="fa fa-bell{{if not .IsSubscribed}}-slash{{end}}"></i></span> <span> {{if .IsSubscribed}} Disable notifications about this thread {{else}} Enable notifications about this thread {{end}} </span> </a> </p> <div class="block p-2"> <nav class="pagination" role="navigation" aria-label="pagination"> <a class="pagination-previous{{if not .Pager.HasPrevious}} is-disabled{{end}}" title="Previous" href="{{.Request.URL.Path}}?{{QueryPlus "page" .Pager.Previous}}">Previous</a> <a class="pagination-next{{if not .Pager.HasNext}} is-disabled{{end}}" title="Next" href="{{.Request.URL.Path}}?{{QueryPlus "page" .Pager.Next}}">Next page</a> <ul class="pagination-list"> {{$Root := .}} {{range .Pager.Iter}} <li> <a class="pagination-link{{if .IsCurrent}} is-current{{end}}" aria-label="Page {{.Page}}" href="{{$Root.Request.URL.Path}}?{{QueryPlus "page" .Page}}"> {{.Page}} </a> </li> {{end}} </ul> </nav> </div> {{$Root := .}} <div class="block p-2"> {{range $i, $c := .Comments}} <div class="box has-background-link-light"> <div class="columns"> <div class="column is-2 has-text-centered"> <div> <a href="/u/{{$c.User.Username}}"> {{template "avatar-96x96" $c.User}} </a> </div> <a href="/u/{{$c.User.Username}}">{{$c.User.Username}}</a> {{if $c.User.IsAdmin}} <div class="is-size-7 mt-1"> <span class="tag is-danger is-light"> <span class="icon"><i class="fa fa-gavel"></i></span> <span>Admin</span> </span> </div> {{end}} </div> <div class="column content"> {{ToMarkdown $c.Message}} {{if $c.IsEdited}} <div class="mt-4"> <em title="{{$c.UpdatedAt.Format "2006-01-02 15:04:05"}}"> <small>Edited {{SincePrettyCoarse $c.UpdatedAt}} ago</small> </em> </div> {{end}} <!-- Poll attachment? --> {{if and (eq $i 0) $Root.Thread.PollID}} <h2>Poll</h2> <!-- Get the results --> {{$Poll := $Root.Thread.Poll}} {{$PollResult := $Poll.Result $Root.CurrentUser}} <form name="ballot" action="/poll/vote" method="POST"> {{InputCSRF}} <input type="hidden" name="poll_id" value="{{$Root.Thread.PollID}}"> <input type="hidden" name="from_thread_id" value="{{$Root.Thread.ID}}"> <!-- Poll is open? --> {{if $PollResult.AcceptingVotes}} {{range $Poll.Options}} <div class="control"> <label class="{{$Poll.InputType}} box nonshy-fullwidth p-3 mb-3"> <input type="{{$Poll.InputType}}" name="answer" value="{{.}}"> {{.}} </label> </div> {{end}} {{if $Poll.MultipleChoice}} <div class="mt-2 mb-4"> <strong>Multiple choice:</strong> select all the answers you want before casting your vote! </div> {{end}} <div class="mb-4"> {{if and ($Poll.Expires) (not $Poll.IsExpired)}} Poll expires in about <span title="{{$Poll.ExpiresAt.Format "2006-01-02 15:04:05"}}">{{SincePrettyCoarse $Root.Thread.Poll.ExpiresAt}}</span>. Vote or wait to see the responses. {{else}} Poll doesn't expire. Vote to see the responses. {{end}} </div> <button type="submit" class="button is-primary is-outline"> Submit response </button> {{else}} {{range $Poll.Options}} <div class="columns mb-0"> <div class="column is-one-quarter"> {{.}} </div> <div class="column"> <progress class="{{$PollResult.GetClass .}}" value="{{$PollResult.GetPercent .}}" max="100">{{$PollResult.GetPercent .}}%</progress> </div> <div class="column is-1"> {{$PollResult.GetPercent .}}% </div> </div> {{end}} <em> {{$PollResult.TotalVotes}} vote{{Pluralize $PollResult.TotalVotes}}. {{if $Poll.IsExpired}} Poll ended <span title="{{$Poll.ExpiresAt.Format "2006-01-02 15:04:05"}}">{{SincePrettyCoarse $Root.Thread.Poll.ExpiresAt}} ago</span>. {{end}} </em> {{end}} </form> {{end}} <!-- Photo attachments? --> {{$Photos := $Root.PhotoMap.Get $c.ID}} {{if $Photos}} {{range $Photos}} {{if not .ExpiredAt.IsZero}} <div class="mt-4"> <span class="tag is-dark">photo expired on {{.ExpiredAt.Format "2006-01-02"}}</span> </div> {{else}} <div class="image mt-4"> <img src="{{PhotoURL .Filename}}"> </div> {{end}} {{end}} {{end}} <hr class="has-background-grey mb-2"> <div class="columns is-mobile is-multiline is-size-7 mb-0"> <div class="column is-narrow"> <span title="{{.CreatedAt.Format "2006-01-02 15:04:05"}}"> {{SincePrettyCoarse .CreatedAt}} ago </span> </div> <div class="column is-narrow"> {{$Like := $Root.LikeMap.Get .ID}} <a href="#" class="has-text-dark nonshy-like-button" data-table-name="comments" data-table-id="{{.ID}}" 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> </a> </div> <div class="column is-narrow"> <a href="/contact?intent=report&subject=report.comment&id={{.ID}}" class="has-text-dark"> <span class="icon"><i class="fa fa-flag"></i></span> <span>Report</span> </a> </div> {{if not $Root.Thread.NoReply}} <div class="column is-narrow"> <a href="/forum/post?to={{$Root.Forum.Fragment}}&thread={{$Root.Thread.ID}}"e={{.ID}}" class="has-text-dark nonshy-quote-button" data-quote-body="{{.Message}}"> <span class="icon"><i class="fa fa-quote-right"></i></span> <span>Quote</span> </a> </div> <div class="column is-narrow"> <a href="/forum/post?to={{$Root.Forum.Fragment}}&thread={{$Root.Thread.ID}}" class="has-text-dark nonshy-reply-button" data-reply-to="{{.User.Username}}"> <span class="icon"><i class="fa fa-reply"></i></span> <span>Reply</span> </a> </div> {{end}} {{if or $Root.CurrentUser.IsAdmin (eq $Root.CurrentUser.ID .User.ID)}} <div class="column is-narrow"> <a href="/forum/post?to={{$Root.Forum.Fragment}}&thread={{$Root.Thread.ID}}&edit={{.ID}}" class="has-text-dark"> <span class="icon"><i class="fa fa-edit"></i></span> <span>Edit</span> </a> </div> <div class="column is-narrow"> <a href="/forum/post?to={{$Root.Forum.Fragment}}&thread={{$Root.Thread.ID}}&edit={{.ID}}&delete=true" onclick="return confirm('Are you sure you want to delete this comment?')" class="has-text-dark"> <span class="icon"><i class="fa fa-trash"></i></span> <span>Delete</span> </a> </div> {{end}} </div> {{if $Root.CurrentUser.IsAdmin}} <div> <span class="tag is-primary is-light"> <span class="icon"><i class="fa fa-database"></i></span> <span>ID: {{.ID}}</span> </span> </div> {{end}} </div> </div> </div> {{end}} </div> {{if .Thread.NoReply}} <div class="block notification is-warning is-light"> <i class="fa fa-ban pr-2"></i> This thread is not accepting any new replies. </div> {{else}} <div class="block p-2" id="reply"> <div class="card"> <header class="card-header has-background-link"> <p class="card-header-title has-text-light"> <i class="fa fa-comment mr-2"></i> Reply to Thread </p> </header> <div class="card-content"> <form action="/forum/post?to={{.Forum.Fragment}}&thread={{.Thread.ID}}" method="POST" enctype="multipart/form-data"> {{InputCSRF}} <div class="field block"> <label for="message" class="label">Message</label> <textarea class="textarea" cols="80" rows="6" name="message" id="message" {{if not .Forum.PermitPhotos}}required{{end}} placeholder="Message"></textarea> <p class="help"> <a href="/markdown" target="_blank">Markdown formatting</a> supported. </p> </div> <!-- Photo board that allows attachments? --> {{if .Forum.PermitPhotos}} <div class="field block mb-4"> <input type="hidden" name="photo_intent" id="photoIntent"> <!-- Drag/Drop Modal --> <div class="modal" id="drop-modal"> <div class="modal-background"></div> <div class="modal-content"> <div class="box content has-text-centered"> <h1><i class="fa fa-upload mr-2"></i> Drop image to select it for upload</h1> </div> </div> </div> <label class="label">Photo Attachment</label> <div class="file has-name is-fullwidth"> <label class="file-label"> <input class="file-input" type="file" name="file" id="file" accept=".jpg,.jpeg,.jpe,.png"> <span class="file-cta"> <span class="file-icon"> <i class="fas fa-upload"></i> </span> <span class="file-label"> Choose a fileā¦ </span> </span> <span class="file-name" id="fileName"> Select a file </span> </label> </div> </div> {{end}} <div class="field has-text-centered"> <button type="submit" name="intent" value="preview" class="button is-link"> Preview </button> <button type="submit" name="intent" value="submit" class="button is-success"> Post Message </button> </div> </form> </div> </div> </div> {{end}} <script type="text/javascript"> document.addEventListener('DOMContentLoaded', function() { const $message = document.querySelector("#message"); // Enhance the in-post Quote and Reply buttons to activate the reply field // at the page footer instead of going to the dedicated comment page. (document.querySelectorAll(".nonshy-quote-button") || []).forEach(node => { const message = node.dataset.quoteBody; node.addEventListener("click", (e) => { e.preventDefault(); // Prepare the quoted message. var lines = []; for (let line of message.split("\n")) { lines.push("> " + line); } $message.value += lines.join("\n") + "\n\n"; $message.scrollIntoView(); $message.focus(); }); }); (document.querySelectorAll(".nonshy-reply-button") || []).forEach(node => { const replyTo = node.dataset.replyTo; node.addEventListener("click", (e) => { e.preventDefault(); $message.value += "@" + replyTo + "\n\n"; $message.scrollIntoView(); $message.focus(); }); }); }); </script> <!-- Script for photo upload on photo boards --> {{if .Forum.PermitPhotos}} <script type="text/javascript"> window.addEventListener("DOMContentLoaded", (event) => { let $file = document.querySelector("#file"), $fileName = document.querySelector("#fileName"), $dropArea = document.querySelector("#drop-modal"), $photoIntent = document.querySelector("#photoIntent"), $body = document.querySelector("body"); // Common handler for file selection (file input or drag/drop) let onFile = (file) => { $photoIntent.value = "upload"; $fileName.innerHTML = file.name; }; // Set up drag/drop file upload events. $body.addEventListener("dragenter", function(e) { e.preventDefault(); e.stopPropagation(); $dropArea.classList.add("is-active"); }); $body.addEventListener("dragover", function(e) { e.preventDefault(); e.stopPropagation(); $dropArea.classList.add("is-active"); }); $body.addEventListener("dragleave", function(e) { e.preventDefault(); e.stopPropagation(); $dropArea.classList.remove("is-active"); }); $body.addEventListener("drop", function(e) { e.preventDefault(); e.stopPropagation(); $dropArea.classList.remove("is-active"); // Grab the file. let dt = e.dataTransfer; let file = dt.files[0]; // Set the file on the input field too. $file.files = dt.files; onFile(file); }); // File input handler. $file.addEventListener("change", function() { let file = this.files[0]; onFile(file); }); }); </script> {{end}}<!-- .Forum.PermitPhotos --> {{end}}