summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2024-07-11 23:20:40 -0400
committerrealtradam <[email protected]>2024-07-11 23:20:40 -0400
commitd0e45a9093b33d4e5cb5f57fabdcb807dc8e8ff0 (patch)
treec5e4457bdbc64d5ecbe72e43258d2c7af70063eb
parent40075162def7d0a4ce9d795f4cfe83264fac50b4 (diff)
downloadspring-blog-d0e45a9093b33d4e5cb5f57fabdcb807dc8e8ff0.tar.gz
spring-blog-d0e45a9093b33d4e5cb5f57fabdcb807dc8e8ff0.zip
add search functionality
-rw-r--r--src/main/java/com/blog/web/controllers/ArticleController.java25
-rw-r--r--src/main/java/com/blog/web/repository/ArticleRepository.java8
-rw-r--r--src/main/java/com/blog/web/services/ArticleService.java4
-rw-r--r--src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java11
-rw-r--r--src/main/resources/templates/articles/show.html87
-rw-r--r--src/main/resources/templates/index.html5
-rw-r--r--src/main/resources/templates/layout.html13
7 files changed, 145 insertions, 8 deletions
diff --git a/src/main/java/com/blog/web/controllers/ArticleController.java b/src/main/java/com/blog/web/controllers/ArticleController.java
index 0e58877..0cdff15 100644
--- a/src/main/java/com/blog/web/controllers/ArticleController.java
+++ b/src/main/java/com/blog/web/controllers/ArticleController.java
@@ -7,10 +7,7 @@ import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
@@ -30,6 +27,13 @@ public class ArticleController {
return "index";
}
+ @GetMapping("/articles/{articleId}")
+ public String showArticle(@PathVariable("articleId") long articleId, Model model) {
+ ArticleDto articleDto = articleService.findArticleById(articleId);
+ model.addAttribute("article", articleDto);
+ return "articles/show";
+ }
+
@GetMapping("/articles/new")
public String createArticleForm(Model model) {
Article article = new Article();
@@ -49,6 +53,12 @@ public class ArticleController {
return "redirect:/articles";
}
+ @GetMapping("/articles/delete/{articleId}")
+ public String deleteArticle(@PathVariable("articleId") Long articleId) {
+ articleService.delete(articleId);
+ return "redirect:/articles";
+ }
+
@GetMapping("/articles/edit/{articleId}")
public String editArticleForm(@PathVariable("articleId") long articleId, Model model) {
ArticleDto articleDto = articleService.findArticleById(articleId);
@@ -68,6 +78,13 @@ public class ArticleController {
return "redirect:/articles";
}
+ @GetMapping("/articles/search")
+ public String searchArticle(@RequestParam(value = "search") String search, Model model) {
+ List<ArticleDto> articles = articleService.searchArticles(search);
+ model.addAttribute("articles", articles);
+ return "index";
+ }
+
@GetMapping("/articles")
public String getArticles() {
return "redirect:/";
diff --git a/src/main/java/com/blog/web/repository/ArticleRepository.java b/src/main/java/com/blog/web/repository/ArticleRepository.java
index c7e8c04..db9edf6 100644
--- a/src/main/java/com/blog/web/repository/ArticleRepository.java
+++ b/src/main/java/com/blog/web/repository/ArticleRepository.java
@@ -2,7 +2,13 @@ package com.blog.web.repository;
import com.blog.web.models.Article;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+import java.util.Optional;
public interface ArticleRepository extends JpaRepository<Article, Long> {
-
+ Optional<Article> findByTitle(String url);
+ @Query("SELECT a from Article a WHERE a.title LIKE CONCAT('%', :search, '%')")
+ List<Article> searchArticles(String search);
}
diff --git a/src/main/java/com/blog/web/services/ArticleService.java b/src/main/java/com/blog/web/services/ArticleService.java
index e2ec309..9cab70b 100644
--- a/src/main/java/com/blog/web/services/ArticleService.java
+++ b/src/main/java/com/blog/web/services/ArticleService.java
@@ -13,4 +13,8 @@ public interface ArticleService {
ArticleDto findArticleById(long articleId);
void updateArticle(ArticleDto articleDto);
+
+ void delete(Long articleId);
+
+ List<ArticleDto> searchArticles(String search);
}
diff --git a/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java b/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java
index b9e11f6..c8e2903 100644
--- a/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java
+++ b/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java
@@ -41,6 +41,17 @@ public class ArticleServiceImpl implements ArticleService {
articleRepository.save(article);
}
+ @Override
+ public void delete(Long articleId) {
+ articleRepository.deleteById(articleId);
+ }
+
+ @Override
+ public List<ArticleDto> searchArticles(String search) {
+ List<Article> articles = articleRepository.searchArticles(search);
+ return articles.stream().map(article -> mapToArticleDto(article)).collect(Collectors.toList());
+ }
+
private Article mapToArticle(ArticleDto articleDto) {
Article article = Article.builder()
.id(articleDto.getId())
diff --git a/src/main/resources/templates/articles/show.html b/src/main/resources/templates/articles/show.html
new file mode 100644
index 0000000..206aaae
--- /dev/null
+++ b/src/main/resources/templates/articles/show.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html lang="en"
+ xmlns:th="http://www.thymeleaf.org"
+ xmlns:layout="https://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorate="~{layout}"
+>
+<body layout:fragment="content">
+
+
+
+<!--Title-->
+<div class="text-center pt-16 md:pt-32">
+ <p th:text="${article.createdOn}" class="text-sm md:text-base text-green-500 font-bold"></p>
+ <h1 th:text="${article.title}" class="font-bold break-normal text-3xl md:text-5xl">Welcome to Ghostwind CSS</h1>
+</div>
+
+<!--image-->
+<div class="container w-full max-w-6xl mx-auto bg-white bg-cover mt-8 rounded" th:style="'background:url(' + @{${article.photoUrl}} + '); height: 75vh;'"></div>
+
+<!--Container-->
+<div class="container max-w-5xl mx-auto -mt-32">
+
+ <div class="mx-0 sm:mx-6">
+
+ <div class="bg-white w-full p-8 md:p-24 text-xl md:text-2xl text-gray-800 leading-normal" style="font-family:Georgia,serif;">
+
+ <!--Post Content-->
+
+ <div th:text="${article.content}"></div>
+
+ <!--/ Post Content-->
+
+ </div>
+
+
+ <!--Subscribe-->
+ <div class="container font-sans bg-green-100 rounded mt-8 p-4 md:p-24 text-center">
+ <h2 class="font-bold break-normal text-2xl md:text-4xl">Subscribe to Ghostwind CSS</h2>
+ <h3 class="font-bold break-normal font-normal text-gray-600 text-base md:text-xl">Get the latest posts delivered right to your inbox</h3>
+ <div class="w-full text-center pt-4">
+ <form action="#">
+ <div class="max-w-sm mx-auto p-1 pr-0 flex flex-wrap items-center">
+ <input type="email" placeholder="[email protected]" class="flex-1 appearance-none rounded shadow p-3 text-gray-600 mr-2 focus:outline-none">
+ <button type="submit" class="flex-1 mt-4 md:mt-0 block md:inline-block appearance-none bg-green-500 text-white text-base font-semibold tracking-wider uppercase py-4 rounded shadow hover:bg-green-400">Subscribe</button>
+ </div>
+ </form>
+ </div>
+ </div>
+ <!-- /Subscribe-->
+
+
+ <!--Author-->
+ <div class="flex w-full items-center font-sans p-8 md:p-24">
+ <img class="w-10 h-10 rounded-full mr-4" src="http://i.pravatar.cc/300" alt="Avatar of Author">
+ <div class="flex-1">
+ <p class="text-base font-bold text-base md:text-xl leading-none">Ghostwind CSS</p>
+ <p class="text-gray-600 text-xs md:text-base">Tailwind CSS version of Ghost's Casper theme by <a class="text-gray-800 hover:text-green-500 no-underline border-b-2 border-green-500" href="https://www.tailwindtoolbox.com">TailwindToolbox.com</a></p>
+ </div>
+ <div class="justify-end">
+
+ </div>
+ <!--/Author-->
+
+ </div>
+
+
+ </div>
+
+</div>
+
+
+<!-- Scroll Top Button -->
+<button class="btn-toggle-round scroll-top js-scroll-top" type="button" title="Scroll to top">
+ <svg class="progress-circle" width="100%" height="100%" viewBox="-1 -1 102 102">
+ <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"/>
+ </svg>
+ <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-up" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="cuurentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
+ <line x1="12" y1="5" x2="12" y2="19" />
+ <line x1="18" y1="11" x2="12" y2="5" />
+ <line x1="6" y1="11" x2="12" y2="5" />
+ </svg>
+</button>
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
index ed98605..1dcef48 100644
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -103,12 +103,13 @@
<!--1/2 col -->
<div th:each="article :${articles}" class="w-full md:w-1/2 p-6 flex flex-col flex-grow flex-shrink">
<div class="flex-1 bg-white rounded-t rounded-b-none overflow-hidden shadow-lg">
- <a href="#" class="flex flex-wrap no-underline hover:no-underline">
+ <a th:href="@{/articles/{articleId}(articleId=${article.id})}" class="flex flex-wrap no-underline hover:no-underline">
<img th:src="${article.photoUrl}" class="h-full w-full rounded-t pb-6">
<div th:text="${article.title}" class="w-full font-bold text-xl text-gray-900 px-6">Lorem ipsum dolor sit amet.</div>
- <p th:text="${article.content}" class="text-gray-800 font-serif text-base px-6 mb-5"></p>
+ <p class="text-gray-800 font-serif text-base px-6 mb-5"></p>
</a>
<a th:href="@{/articles/edit/{articleId}(articleId=${article.id})}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">Edit</a>
+ <a th:href="@{/articles/delete/{articleId}(articleId=${article.id})}" class="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 ml-4 text-sm rounded">Delete</a>
</div>
<div class="flex-none mt-auto bg-white rounded-b rounded-t-none overflow-hidden shadow-lg p-6">
<div class="flex items-center justify-between">
diff --git a/src/main/resources/templates/layout.html b/src/main/resources/templates/layout.html
index 407ecd9..17d6939 100644
--- a/src/main/resources/templates/layout.html
+++ b/src/main/resources/templates/layout.html
@@ -33,7 +33,7 @@
👻 <span class="hidden w-0 md:w-auto md:block pl-1">Ghostwind CSS</span>
</a>
</div>
- <div class="flex pl-4 text-sm">
+ <div class="flex pl-4 text-sm place-content-between w-full">
<ul class="list-reset flex justify-between flex-1 md:flex-none items-center">
<li class="mr-2">
<a class="inline-block py-2 px-2 text-white no-underline" href="/">HOME</a>
@@ -48,6 +48,17 @@
<a class="inline-block text-indigo-200 no-underline hover:text-indigo-100 hover:text-underline py-2 px-2" href="#">LINK</a>
</li>
</ul>
+ <form th:action="@{/articles/search}" class="w-full max-w-md">
+ <div class="flex flex-wrap -mx-3">
+ <div class="w-full px-3">
+ <input class="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white"
+ id="search"
+ type="search"
+ name="search"
+ placeholder="Search">
+ </div>
+ </div>
+ </form>
</div>
</div>
</nav>