Gallery page now lists common tags, added basic pagination controls

This commit is contained in:
neviyn 2021-05-10 15:42:46 +01:00
parent 03df15818e
commit 1a154f2db4
6 changed files with 115 additions and 52 deletions

View File

@ -87,6 +87,9 @@ class ImageController
} }
} }
} ?: return "gallery" } ?: return "gallery"
model.addAttribute("pageNumber", pageNumber)
val commonTags: List<Tag> = tagRepository.find20TagsOnImages(images.content.map { it.id })
model.addAttribute("commonTags", commonTags)
model.addAttribute("imagePage", images) model.addAttribute("imagePage", images)
return "gallery" return "gallery"
} }

View File

@ -32,4 +32,14 @@ interface ImageRepository : JpaRepository<Image, Long> {
interface TagRepository : CrudRepository<Tag, Long> { interface TagRepository : CrudRepository<Tag, Long> {
fun findByTagIs(tag: String): Tag? fun findByTagIs(tag: String): Tag?
fun findAllByTagIn(tags: List<String>): List<Tag> fun findAllByTagIn(tags: List<String>): List<Tag>
//SELECT * FROM booru.tag t WHERE t.id IN (SELECT DISTINCT tag_id FROM booru.tag_image ti WHERE ti.image_id IN ?1) ORDER BY t.amount DESC, t.tag LIMIT 20
//SELECT DISTINCT t.id, t.tag, t.amount FROM booru.tag t JOIN booru.tag_image ti ON ti.tag_id = t.id WHERE ti.image_id IN ?1 ORDER BY t.amount DESC, t.tag LIMIT 20
//WITH x AS (SELECT DISTINCT tag_id FROM booru.tag_image ti WHERE ti.image_id in ?1) SELECT t.* FROM booru.tag t RIGHT JOIN x ON t.id = x.tag_id ORDER BY t.AMOUNT DESC, t.tag LIMIT 20
@Suppress("SqlResolve")
@Query(
value = "SELECT * FROM booru.tag t WHERE t.id IN (SELECT DISTINCT tag_id FROM booru.tag_image ti WHERE ti.image_id IN ?1) ORDER BY t.amount DESC, t.tag LIMIT 20",
nativeQuery = true
)
fun find20TagsOnImages(imageIDs: List<Long>): List<Tag>
} }

View File

@ -38,5 +38,21 @@
</div> </div>
</nav> </nav>
</div> </div>
<div th:fragment="searchBarRow">
<form action="/gallery" class="text-center row row-cols-auto align-items-center mt-2">
<div class="col-10">
<!--suppress HtmlFormInputWithoutLabel -->
<input class="form-control" id="imageSearch"
name="tags"
pattern="[a-zA-Z0-9\s_]*"
placeholder="Ex: blue_eyes smile"
th:value="${#request.getParameter('tags')}"
type="search">
</div>
<div class="col-2 d-grid">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</form>
</div>
</body> </body>
</html> </html>

View File

@ -7,31 +7,70 @@
<body> <body>
<div th:replace="fragments :: navbar"></div> <div th:replace="fragments :: navbar"></div>
<div class="container"> <div class="container">
<form action="/gallery" class="text-center row row-cols-auto align-items-center mt-2"> <div th:replace="fragments :: searchBarRow"></div>
<div class="row mt-3" th:if="${imagePage != null}">
<div class="col-2">
<ul>
<li th:each="tag : ${commonTags}">
<a class="text-decoration-none"
th:href="${#mvc.url('IC#getGalleryPage').arg(0, 1).arg(1, tag.tag).build()}"
th:text="${tag.tag} + ' ' + ${tag.amount}">tag</a>
</li>
</ul>
</div>
<div class="col-10"> <div class="col-10">
<!--suppress HtmlFormInputWithoutLabel --> <div class="container-fluid">
<input class="form-control" id="imageSearch" <div class="row">
name="tags" <div class="col-xl-2 col-lg-4 col-md-6 col-sm-12" th:each="image : ${imagePage.content}">
pattern="[a-zA-Z0-9\s_]*" <!--suppress ThymeleafVariablesResolveInspection -->
placeholder="Ex: blue_eyes smile" <a th:href="'/view/' + ${image.id}">
th:value="${#request.getParameter('tags')}" <!--suppress ThymeleafVariablesResolveInspection -->
type="search"> <img alt="" class="img-thumbnail" th:src="'/i/thumbnail.' + ${image.filename}"/>
</a>
</div>
</div>
</div>
</div> </div>
<div class="col-2 d-grid">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</form>
</div>
<div class="row" th:if="${imagePage != null}">
<div class="col-2" th:each="image : ${imagePage.content}">
<a th:href="'/view/' + ${image.id}">
<img alt="" class="img-thumbnail" th:src="'/i/thumbnail.' + ${image.filename}"/>
</a>
</div> </div>
</div> <div class="row" th:if="${imagePage == null}">
<div class="row" th:if="${imagePage == null}"> <div class="col text-center mt-3">
<div class="col text-center mt-3"> <p class="lead">No images found with all the specified tags.</p>
<p class="lead">No images found with all the specified tags.</p> </div>
</div>
<div class="row justify-content-center mt-3" th:if="${imagePage != null}">
<div class="col d-flex justify-content-center">
<ul class="pagination">
<li class="page-item" th:classappend="${imagePage.isFirst() ? 'disabled' : ''}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber - 1},tags=${param.tags})}">Previous</a>
</li>
<li class="page-item" th:if="${pageNumber > 2}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber - 2},tags=${param.tags})}"
th:text="${pageNumber - 2}">P-2</a></li>
<li class="page-item" th:if="${pageNumber > 1}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber - 1},tags=${param.tags})}"
th:text="${pageNumber - 1}">P-1</a></li>
<li class="page-item active">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber},tags=${param.tags})}"
th:text="${pageNumber}">P</a>
</li>
<li class="page-item" th:if="${pageNumber < imagePage.getTotalPages() - 1}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber},tags=${param.tags})}"
th:text="${pageNumber}">P+1</a></li>
<li class="page-item" th:if="${pageNumber < imagePage.getTotalPages()}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber},tags=${param.tags})}"
th:text="${pageNumber}">P+2</a></li>
<li class="page-item" th:classappend="${imagePage.isLast() ? 'disabled' : ''}">
<a class="page-link"
th:href="@{/gallery/(page=${pageNumber + 1},tags=${param.tags})}">Next</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</body> </body>

View File

@ -14,18 +14,20 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<p class="text-center"> <p class="text-center">
<a th:href="${#mvc.url('IC#getGalleryPage').build()}" class="text-decoration-none">Browse All</a> <a class="text-decoration-none" th:href="${#mvc.url('IC#getGalleryPage').arg(0, 1).build()}">Browse All</a>
<span class="text-secondary"> |</span> <span class="text-secondary"> |</span>
<a th:href="${#mvc.url('UC#showUploadPage').build()}" class="text-decoration-none">Upload New</a> <a class="text-decoration-none" th:href="${#mvc.url('UC#showUploadPage').build()}">Upload New</a>
<span class="text-secondary"> |</span> <span class="text-secondary"> |</span>
<a th:href="${#mvc.url('MC#memberDetails').build()}" class="text-decoration-none">My Account</a> <a class="text-decoration-none" th:href="${#mvc.url('MC#memberDetails').build()}">My Account</a>
</p> </p>
</div> </div>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-center">
<form class="col-xs-12 col-sm-9 col-md-6 text-center" action="/gallery"> <form action="/gallery" class="col-xs-12 col-sm-9 col-md-6 text-center">
<!--suppress HtmlFormInputWithoutLabel --> <!--suppress HtmlFormInputWithoutLabel -->
<input class="form-control" id="imageSearch" pattern="[a-zA-Z0-9\s_]*" placeholder="Ex: blue_eyes smile" type="search" name="tags"> <input name="page" type="hidden" value="1">
<!--suppress HtmlFormInputWithoutLabel -->
<input class="form-control" id="imageSearch" name="tags" pattern="[a-zA-Z0-9\s_]*" placeholder="Ex: blue_eyes smile" type="search">
<button class="btn btn-primary mt-1 w-25" type="submit">Search</button> <button class="btn btn-primary mt-1 w-25" type="submit">Search</button>
</form> </form>
</div> </div>

View File

@ -7,34 +7,27 @@
<body> <body>
<div th:replace="fragments :: navbar"></div> <div th:replace="fragments :: navbar"></div>
<div class="container"> <div class="container">
<form action="/gallery" class="text-center row row-cols-auto align-items-center mt-2"> <div th:replace="fragments :: searchBarRow"></div>
<div class="col-10"> <div class="row mt-2">
<!--suppress HtmlFormInputWithoutLabel --> <div class="col-2">
<input class="form-control" id="imageSearch" <ul>
name="tags" <li th:each="tag : ${tags}">
pattern="[a-zA-Z0-9\s_]*" <a class="text-decoration-none"
placeholder="Ex: blue_eyes smile" th:href="${#mvc.url('IC#getGalleryPage').arg(1, tag.tag).build()}"
th:value="${#request.getParameter('tags')}" th:text="${tag.tag} + ' ' + ${tag.amount}">tag</a></li>
type="search"> </ul>
<form th:action="'/upload/d/' + ${image.id}"
th:if="${isUploader}"
th:method="delete">
<button type="submit">Delete</button>
</form>
</div> </div>
<div class="col-2 d-grid"> <div class="col-8">
<button class="btn btn-primary" type="submit">Search</button> <!--suppress HtmlRequiredAltAttribute -->
<img class="w-100" th:alt="${image.filename}" th:src="'/i/' + ${image.filename}">
</div> </div>
</form> <div class="col-2"></div>
</div>
<div class="row mt-2">
<div class="col-2">
<ul>
<li th:each="tag : ${tags}"><a class="text-decoration-none" th:href="${#mvc.url('IC#getGalleryPage').arg(1, tag.tag).build()}" th:text="${tag.tag} + ' ' + ${tag.amount}">tag</a></li>
</ul>
<form th:if="${isUploader}" th:action="'/upload/d/' + ${image.id}" th:method="delete">
<button type="submit">Delete</button>
</form>
</div> </div>
<div class="col-8">
<img th:src="'/i/' + ${image.filename}" th:alt="${image.filename}" class="w-100">
</div>
<div class="col-2"></div>
</div> </div>
</body> </body>
</html> </html>